mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-13 21:54:42 +00:00
Merge #11106
11106: internal: Remove network access from Code extension r=lnicola a=lnicola Co-authored-by: Laurențiu Nicola <lnicola@dend.ro>
This commit is contained in:
commit
cb0e270c02
8 changed files with 54 additions and 667 deletions
|
@ -1 +1 @@
|
|||
See the [Privacy](https://rust-analyzer.github.io/manual.html#security) section of the user manual.
|
||||
See the [Privacy](https://rust-analyzer.github.io/manual.html#privacy) section of the user manual.
|
||||
|
|
|
@ -653,10 +653,12 @@ Here is a **non-exhaustive** list of ways to make rust-analyzer execute arbitrar
|
|||
The LSP server performs no network access in itself, but runs `cargo metadata` which will update or download the crate registry and the source code of the project dependencies.
|
||||
If enabled (the default), build scripts and procedural macros can do anything.
|
||||
|
||||
The Code extension automatically connects to GitHub to download updated LSP binaries and, if the nightly channel is selected, to perform update checks using the GitHub API. For `rust-analyzer` developers, using `cargo xtask release` uses the same API to put together the release notes.
|
||||
The Code extension does not access the network.
|
||||
|
||||
Any other editor plugins are not under the control of the `rust-analyzer` developers. For any privacy concerns, you should check with their respective developers.
|
||||
|
||||
For `rust-analyzer` developers, `cargo xtask release` uses the GitHub API to put together the release notes.
|
||||
|
||||
== Features
|
||||
|
||||
include::./generated_features.adoc[]
|
||||
|
|
115
editors/code/package-lock.json
generated
115
editors/code/package-lock.json
generated
|
@ -11,8 +11,6 @@
|
|||
"dependencies": {
|
||||
"d3": "^7.2.0",
|
||||
"d3-graphviz": "^4.0.0",
|
||||
"https-proxy-agent": "^5.0.0",
|
||||
"node-fetch": "^3.0.3",
|
||||
"vscode-languageclient": "8.0.0-next.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -345,6 +343,7 @@
|
|||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
|
||||
"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"debug": "4"
|
||||
},
|
||||
|
@ -1274,18 +1273,11 @@
|
|||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/data-uri-to-buffer": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz",
|
||||
"integrity": "sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==",
|
||||
"engines": {
|
||||
"node": ">= 12"
|
||||
}
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.3.3",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
|
||||
"integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ms": "2.1.2"
|
||||
},
|
||||
|
@ -2059,27 +2051,6 @@
|
|||
"pend": "~1.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fetch-blob": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.1.3.tgz",
|
||||
"integrity": "sha512-ax1Y5I9w+9+JiM+wdHkhBoxew+zG4AJ2SvAD1v1szpddUIiPERVGBxrMcB2ZqW0Y3PP8bOWYv2zqQq1Jp2kqUQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/jimmywarting"
|
||||
},
|
||||
{
|
||||
"type": "paypal",
|
||||
"url": "https://paypal.me/jimmywarting"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"web-streams-polyfill": "^3.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.20 || >= 14.13"
|
||||
}
|
||||
},
|
||||
"node_modules/file-entry-cache": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
|
||||
|
@ -2123,17 +2094,6 @@
|
|||
"integrity": "sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/formdata-polyfill": {
|
||||
"version": "4.0.10",
|
||||
"resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
|
||||
"integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
|
||||
"dependencies": {
|
||||
"fetch-blob": "^3.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.20.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fs-constants": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
|
||||
|
@ -2403,6 +2363,7 @@
|
|||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz",
|
||||
"integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"agent-base": "6",
|
||||
"debug": "4"
|
||||
|
@ -2770,7 +2731,8 @@
|
|||
"node_modules/ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/mute-stream": {
|
||||
"version": "0.0.8",
|
||||
|
@ -2814,23 +2776,6 @@
|
|||
"integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/node-fetch": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.1.0.tgz",
|
||||
"integrity": "sha512-QU0WbIfMUjd5+MUzQOYhenAazakV7Irh1SGkWCsRzBwvm4fAhzEUaHMJ6QLP7gWT6WO9/oH2zhKMMGMuIrDyKw==",
|
||||
"dependencies": {
|
||||
"data-uri-to-buffer": "^4.0.0",
|
||||
"fetch-blob": "^3.1.2",
|
||||
"formdata-polyfill": "^4.0.10"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/node-fetch"
|
||||
}
|
||||
},
|
||||
"node_modules/npmlog": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
|
||||
|
@ -3866,14 +3811,6 @@
|
|||
"resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.0-next.3.tgz",
|
||||
"integrity": "sha512-VQcXnhKYxUW6OiRMhG++SzmZYMJwusXknJGd+FfdOnS1yHAo734OHyR0e2eEHDlv0/oWc8RZPgx/VKSKyondVg=="
|
||||
},
|
||||
"node_modules/web-streams-polyfill": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.0.tgz",
|
||||
"integrity": "sha512-EqPmREeOzttaLRm5HS7io98goBgZ7IVz79aDvqjD0kYXLtFZTc0T/U6wHTPKyIjb+MdN7DFIIX6hgdBEpWmfPA==",
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
|
@ -4170,6 +4107,7 @@
|
|||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
|
||||
"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"debug": "4"
|
||||
}
|
||||
|
@ -4874,15 +4812,11 @@
|
|||
"d3-transition": "2 - 3"
|
||||
}
|
||||
},
|
||||
"data-uri-to-buffer": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz",
|
||||
"integrity": "sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA=="
|
||||
},
|
||||
"debug": {
|
||||
"version": "4.3.3",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
|
||||
"integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ms": "2.1.2"
|
||||
}
|
||||
|
@ -5434,14 +5368,6 @@
|
|||
"pend": "~1.2.0"
|
||||
}
|
||||
},
|
||||
"fetch-blob": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.1.3.tgz",
|
||||
"integrity": "sha512-ax1Y5I9w+9+JiM+wdHkhBoxew+zG4AJ2SvAD1v1szpddUIiPERVGBxrMcB2ZqW0Y3PP8bOWYv2zqQq1Jp2kqUQ==",
|
||||
"requires": {
|
||||
"web-streams-polyfill": "^3.0.3"
|
||||
}
|
||||
},
|
||||
"file-entry-cache": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
|
||||
|
@ -5476,14 +5402,6 @@
|
|||
"integrity": "sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==",
|
||||
"dev": true
|
||||
},
|
||||
"formdata-polyfill": {
|
||||
"version": "4.0.10",
|
||||
"resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
|
||||
"integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
|
||||
"requires": {
|
||||
"fetch-blob": "^3.1.2"
|
||||
}
|
||||
},
|
||||
"fs-constants": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
|
||||
|
@ -5696,6 +5614,7 @@
|
|||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz",
|
||||
"integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"agent-base": "6",
|
||||
"debug": "4"
|
||||
|
@ -5978,7 +5897,8 @@
|
|||
"ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||
"dev": true
|
||||
},
|
||||
"mute-stream": {
|
||||
"version": "0.0.8",
|
||||
|
@ -6021,16 +5941,6 @@
|
|||
"integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==",
|
||||
"dev": true
|
||||
},
|
||||
"node-fetch": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.1.0.tgz",
|
||||
"integrity": "sha512-QU0WbIfMUjd5+MUzQOYhenAazakV7Irh1SGkWCsRzBwvm4fAhzEUaHMJ6QLP7gWT6WO9/oH2zhKMMGMuIrDyKw==",
|
||||
"requires": {
|
||||
"data-uri-to-buffer": "^4.0.0",
|
||||
"fetch-blob": "^3.1.2",
|
||||
"formdata-polyfill": "^4.0.10"
|
||||
}
|
||||
},
|
||||
"npmlog": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
|
||||
|
@ -6827,11 +6737,6 @@
|
|||
"resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.0-next.3.tgz",
|
||||
"integrity": "sha512-VQcXnhKYxUW6OiRMhG++SzmZYMJwusXknJGd+FfdOnS1yHAo734OHyR0e2eEHDlv0/oWc8RZPgx/VKSKyondVg=="
|
||||
},
|
||||
"web-streams-polyfill": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.0.tgz",
|
||||
"integrity": "sha512-EqPmREeOzttaLRm5HS7io98goBgZ7IVz79aDvqjD0kYXLtFZTc0T/U6wHTPKyIjb+MdN7DFIIX6hgdBEpWmfPA=="
|
||||
},
|
||||
"which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
|
|
|
@ -36,8 +36,6 @@
|
|||
"test": "node ./out/tests/runTests.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"https-proxy-agent": "^5.0.0",
|
||||
"node-fetch": "^3.0.3",
|
||||
"vscode-languageclient": "8.0.0-next.2",
|
||||
"d3": "^7.2.0",
|
||||
"d3-graphviz": "^4.0.0"
|
||||
|
@ -305,24 +303,6 @@
|
|||
"default": true,
|
||||
"description": "Whether inlay hints font size should be smaller than editor's font size."
|
||||
},
|
||||
"rust-analyzer.updates.channel": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"stable",
|
||||
"nightly"
|
||||
],
|
||||
"default": "stable",
|
||||
"markdownEnumDescriptions": [
|
||||
"`stable` updates are shipped weekly, they don't contain cutting-edge features from VSCode proposed APIs but have less bugs in general.",
|
||||
"`nightly` updates are shipped daily (extension updates automatically by downloading artifacts directly from GitHub), they contain cutting-edge features and latest bug fixes. These releases help us get your feedback very quickly and speed up rust-analyzer development **drastically**."
|
||||
],
|
||||
"markdownDescription": "Choose `nightly` updates to get the latest features and bug fixes every day. While `stable` releases occur weekly and don't contain cutting-edge features from VSCode proposed APIs."
|
||||
},
|
||||
"rust-analyzer.updates.askBeforeDownload": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Whether to ask for permission before downloading any files from the Internet."
|
||||
},
|
||||
"rust-analyzer.server.path": {
|
||||
"type": [
|
||||
"null",
|
||||
|
|
|
@ -8,11 +8,6 @@ const NIGHTLY_TAG = "nightly";
|
|||
|
||||
export type RunnableEnvCfg = undefined | Record<string, string> | { mask?: string; env: Record<string, string> }[];
|
||||
|
||||
export class ProxySettings {
|
||||
proxy?: string = undefined;
|
||||
strictSSL: boolean = true;
|
||||
}
|
||||
|
||||
export class Config {
|
||||
readonly extensionId = "matklad.rust-analyzer";
|
||||
|
||||
|
@ -24,7 +19,6 @@ export class Config {
|
|||
"procMacro",
|
||||
"files",
|
||||
"highlighting",
|
||||
"updates.channel",
|
||||
"lens", // works as lens.*
|
||||
]
|
||||
.map(opt => `${this.rootSection}.${opt}`);
|
||||
|
@ -36,11 +30,9 @@ export class Config {
|
|||
} = vscode.extensions.getExtension(this.extensionId)!.packageJSON;
|
||||
|
||||
readonly globalStorageUri: vscode.Uri;
|
||||
readonly installUri: vscode.Uri;
|
||||
|
||||
constructor(ctx: vscode.ExtensionContext) {
|
||||
this.globalStorageUri = ctx.globalStorageUri;
|
||||
this.installUri = ctx.extensionUri;
|
||||
vscode.workspace.onDidChangeConfiguration(this.onDidChangeConfiguration, this, ctx.subscriptions);
|
||||
this.refreshLogging();
|
||||
}
|
||||
|
@ -103,21 +95,7 @@ export class Config {
|
|||
return this.get<null | string>("server.path") ?? this.get<null | string>("serverPath");
|
||||
}
|
||||
get serverExtraEnv() { return this.get<Env | null>("server.extraEnv") ?? {}; }
|
||||
get channel() { return this.get<UpdatesChannel>("updates.channel"); }
|
||||
get askBeforeDownload() { return this.get<boolean>("updates.askBeforeDownload"); }
|
||||
get traceExtension() { return this.get<boolean>("trace.extension"); }
|
||||
get proxySettings(): ProxySettings {
|
||||
const proxy = vscode
|
||||
.workspace
|
||||
.getConfiguration('http')
|
||||
.get<null | string>("proxy")! || process.env["https_proxy"] || process.env["HTTPS_PROXY"];
|
||||
const strictSSL = vscode.workspace.getConfiguration("http").get<boolean>("proxyStrictSSL") ?? true;
|
||||
|
||||
return {
|
||||
proxy: proxy,
|
||||
strictSSL: strictSSL,
|
||||
};
|
||||
}
|
||||
|
||||
get inlayHints() {
|
||||
return {
|
||||
|
|
|
@ -5,12 +5,11 @@ import * as commands from './commands';
|
|||
import { activateInlayHints } from './inlay_hints';
|
||||
import { Ctx } from './ctx';
|
||||
import { Config } from './config';
|
||||
import { log, assert, isValidExecutable, isRustDocument } from './util';
|
||||
import { log, isValidExecutable, isRustDocument } from './util';
|
||||
import { PersistentState } from './persistent_state';
|
||||
import { fetchRelease, download } from './net';
|
||||
import { activateTaskProvider } from './tasks';
|
||||
import { setContextValue } from './util';
|
||||
import { exec, spawnSync } from 'child_process';
|
||||
import { exec } from 'child_process';
|
||||
|
||||
let ctx: Ctx | undefined;
|
||||
|
||||
|
@ -28,14 +27,9 @@ export async function activate(context: vscode.ExtensionContext) {
|
|||
async function tryActivate(context: vscode.ExtensionContext) {
|
||||
const config = new Config(context);
|
||||
const state = new PersistentState(context.globalState);
|
||||
const serverPath = await bootstrap(config, state).catch(err => {
|
||||
const serverPath = await bootstrap(context, config, state).catch(err => {
|
||||
let message = "bootstrap error. ";
|
||||
|
||||
if (err.code === "EBUSY" || err.code === "ETXTBSY" || err.code === "EPERM") {
|
||||
message += "Other vscode windows might be using rust-analyzer, ";
|
||||
message += "you should close them and reload this window to retry. ";
|
||||
}
|
||||
|
||||
message += 'See the logs in "OUTPUT > Rust Analyzer Client" (should open automatically). ';
|
||||
message += 'To enable verbose logs use { "rust-analyzer.trace.extension": true }';
|
||||
|
||||
|
@ -111,10 +105,6 @@ async function initCommonContext(context: vscode.ExtensionContext, ctx: Ctx) {
|
|||
await activate(context).catch(log.error);
|
||||
});
|
||||
|
||||
ctx.registerCommand('updateGithubToken', ctx => async () => {
|
||||
await queryForGithubToken(new PersistentState(ctx.globalState));
|
||||
});
|
||||
|
||||
ctx.registerCommand('analyzerStatus', commands.analyzerStatus);
|
||||
ctx.registerCommand('memoryUsage', commands.memoryUsage);
|
||||
ctx.registerCommand('shuffleCrateGraph', commands.shuffleCrateGraph);
|
||||
|
@ -161,99 +151,8 @@ export async function deactivate() {
|
|||
ctx = undefined;
|
||||
}
|
||||
|
||||
async function bootstrap(config: Config, state: PersistentState): Promise<string> {
|
||||
await vscode.workspace.fs.createDirectory(config.globalStorageUri).then();
|
||||
|
||||
if (!config.currentExtensionIsNightly) {
|
||||
await state.updateNightlyReleaseId(undefined);
|
||||
}
|
||||
await bootstrapExtension(config, state);
|
||||
const path = await bootstrapServer(config, state);
|
||||
return path;
|
||||
}
|
||||
|
||||
async function bootstrapExtension(config: Config, state: PersistentState): Promise<void> {
|
||||
if (config.package.releaseTag === null) return;
|
||||
if (config.channel === "stable") {
|
||||
if (config.currentExtensionIsNightly) {
|
||||
void vscode.window.showWarningMessage(
|
||||
`You are running a nightly version of rust-analyzer extension. ` +
|
||||
`To switch to stable, uninstall the extension and re-install it from the marketplace`
|
||||
);
|
||||
}
|
||||
return;
|
||||
};
|
||||
if (serverPath(config)) return;
|
||||
|
||||
const now = Date.now();
|
||||
const isInitialNightlyDownload = state.nightlyReleaseId === undefined;
|
||||
if (config.currentExtensionIsNightly) {
|
||||
// Check if we should poll github api for the new nightly version
|
||||
// if we haven't done it during the past hour
|
||||
const lastCheck = state.lastCheck;
|
||||
|
||||
const anHour = 60 * 60 * 1000;
|
||||
const shouldCheckForNewNightly = isInitialNightlyDownload || (now - (lastCheck ?? 0)) > anHour;
|
||||
|
||||
if (!shouldCheckForNewNightly) return;
|
||||
}
|
||||
|
||||
const latestNightlyRelease = await downloadWithRetryDialog(state, async () => {
|
||||
return await fetchRelease("nightly", state.githubToken, config.proxySettings);
|
||||
}).catch(async (e) => {
|
||||
log.error(e);
|
||||
if (isInitialNightlyDownload) {
|
||||
await vscode.window.showErrorMessage(`Failed to download rust-analyzer nightly: ${e}`);
|
||||
}
|
||||
return;
|
||||
});
|
||||
if (latestNightlyRelease === undefined) {
|
||||
if (isInitialNightlyDownload) {
|
||||
await vscode.window.showErrorMessage("Failed to download rust-analyzer nightly: empty release contents returned");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (config.currentExtensionIsNightly && latestNightlyRelease.id === state.nightlyReleaseId) return;
|
||||
|
||||
const userResponse = await vscode.window.showInformationMessage(
|
||||
"New version of rust-analyzer (nightly) is available (requires reload).",
|
||||
"Update"
|
||||
);
|
||||
if (userResponse !== "Update") return;
|
||||
|
||||
let arch = process.arch;
|
||||
if (arch === "ia32") {
|
||||
arch = "x64";
|
||||
}
|
||||
let platform = process.platform as string;
|
||||
if (platform === "linux" && isMusl()) {
|
||||
platform = "alpine";
|
||||
}
|
||||
const artifactName = `rust-analyzer-${platform}-${arch}.vsix`;
|
||||
|
||||
const artifact = latestNightlyRelease.assets.find(artifact => artifact.name === artifactName);
|
||||
assert(!!artifact, `Bad release: ${JSON.stringify(latestNightlyRelease)}`);
|
||||
const dest = vscode.Uri.joinPath(config.globalStorageUri, "rust-analyzer.vsix");
|
||||
|
||||
await downloadWithRetryDialog(state, async () => {
|
||||
await download({
|
||||
url: artifact.browser_download_url,
|
||||
dest,
|
||||
progressTitle: "Downloading rust-analyzer extension",
|
||||
proxySettings: config.proxySettings,
|
||||
});
|
||||
});
|
||||
|
||||
await vscode.commands.executeCommand("workbench.extensions.installExtension", dest);
|
||||
await vscode.workspace.fs.delete(dest);
|
||||
|
||||
await state.updateNightlyReleaseId(latestNightlyRelease.id);
|
||||
await state.updateLastCheck(now);
|
||||
await vscode.commands.executeCommand("workbench.action.reloadWindow");
|
||||
}
|
||||
|
||||
async function bootstrapServer(config: Config, state: PersistentState): Promise<string> {
|
||||
const path = await getServer(config, state);
|
||||
async function bootstrap(context: vscode.ExtensionContext, config: Config, state: PersistentState): Promise<string> {
|
||||
const path = await getServer(context, config, state);
|
||||
if (!path) {
|
||||
throw new Error(
|
||||
"Rust Analyzer Language Server is not available. " +
|
||||
|
@ -318,7 +217,7 @@ async function patchelf(dest: vscode.Uri): Promise<void> {
|
|||
);
|
||||
}
|
||||
|
||||
async function getServer(config: Config, state: PersistentState): Promise<string | undefined> {
|
||||
async function getServer(context: vscode.ExtensionContext, config: Config, state: PersistentState): Promise<string | undefined> {
|
||||
const explicitPath = serverPath(config);
|
||||
if (explicitPath) {
|
||||
if (explicitPath.startsWith("~/")) {
|
||||
|
@ -328,85 +227,39 @@ async function getServer(config: Config, state: PersistentState): Promise<string
|
|||
};
|
||||
if (config.package.releaseTag === null) return "rust-analyzer";
|
||||
|
||||
const platforms: { [key: string]: string } = {
|
||||
"ia32 win32": "x86_64-pc-windows-msvc",
|
||||
"x64 win32": "x86_64-pc-windows-msvc",
|
||||
"x64 linux": "x86_64-unknown-linux-gnu",
|
||||
"x64 darwin": "x86_64-apple-darwin",
|
||||
"arm64 win32": "aarch64-pc-windows-msvc",
|
||||
"arm64 linux": "aarch64-unknown-linux-gnu",
|
||||
"arm64 darwin": "aarch64-apple-darwin",
|
||||
};
|
||||
let platform = platforms[`${process.arch} ${process.platform}`];
|
||||
if (platform === undefined) {
|
||||
await vscode.window.showErrorMessage(
|
||||
"Unfortunately we don't ship binaries for your platform yet. " +
|
||||
"You need to manually clone rust-analyzer repository and " +
|
||||
"run `cargo xtask install --server` to build the language server from sources. " +
|
||||
"If you feel that your platform should be supported, please create an issue " +
|
||||
"about that [here](https://github.com/rust-analyzer/rust-analyzer/issues) and we " +
|
||||
"will consider it."
|
||||
);
|
||||
return undefined;
|
||||
}
|
||||
if (platform === "x86_64-unknown-linux-gnu" && isMusl()) {
|
||||
platform = "x86_64-unknown-linux-musl";
|
||||
}
|
||||
const ext = platform.indexOf("-windows-") !== -1 ? ".exe" : "";
|
||||
const dest = vscode.Uri.joinPath(config.globalStorageUri, `rust-analyzer-${platform}${ext}`);
|
||||
const bundled = vscode.Uri.joinPath(config.installUri, "server", `rust-analyzer${ext}`);
|
||||
const ext = process.platform === "win32" ? ".exe" : "";
|
||||
const bundled = vscode.Uri.joinPath(context.extensionUri, "server", `rust-analyzer${ext}`);
|
||||
const bundledExists = await vscode.workspace.fs.stat(bundled).then(() => true, () => false);
|
||||
let exists = await vscode.workspace.fs.stat(dest).then(() => true, () => false);
|
||||
if (bundledExists) {
|
||||
let server = bundled;
|
||||
if (await isNixOs()) {
|
||||
await vscode.workspace.fs.createDirectory(config.globalStorageUri).then();
|
||||
const dest = vscode.Uri.joinPath(config.globalStorageUri, `rust-analyzer${ext}`);
|
||||
let exists = await vscode.workspace.fs.stat(dest).then(() => true, () => false);
|
||||
if (exists && config.package.version !== state.serverVersion) {
|
||||
await vscode.workspace.fs.delete(dest);
|
||||
exists = false;
|
||||
}
|
||||
if (!exists) {
|
||||
await vscode.workspace.fs.copy(bundled, dest);
|
||||
await patchelf(dest);
|
||||
server = dest;
|
||||
}
|
||||
}
|
||||
await state.updateServerVersion(config.package.version);
|
||||
if (!await isNixOs()) {
|
||||
return bundled.fsPath;
|
||||
}
|
||||
if (!exists) {
|
||||
await vscode.workspace.fs.copy(bundled, dest);
|
||||
await patchelf(dest);
|
||||
exists = true;
|
||||
}
|
||||
}
|
||||
if (!exists) {
|
||||
await state.updateServerVersion(undefined);
|
||||
return server.fsPath;
|
||||
}
|
||||
|
||||
if (state.serverVersion === config.package.version) return dest.fsPath;
|
||||
|
||||
if (config.askBeforeDownload) {
|
||||
const userResponse = await vscode.window.showInformationMessage(
|
||||
`Language server version ${config.package.version} for rust-analyzer is not installed.`,
|
||||
"Download now"
|
||||
);
|
||||
if (userResponse !== "Download now") return dest.fsPath;
|
||||
}
|
||||
|
||||
const releaseTag = config.package.releaseTag;
|
||||
const release = await downloadWithRetryDialog(state, async () => {
|
||||
return await fetchRelease(releaseTag, state.githubToken, config.proxySettings);
|
||||
});
|
||||
const artifact = release.assets.find(artifact => artifact.name === `rust-analyzer-${platform}.gz`);
|
||||
assert(!!artifact, `Bad release: ${JSON.stringify(release)}`);
|
||||
|
||||
await downloadWithRetryDialog(state, async () => {
|
||||
await download({
|
||||
url: artifact.browser_download_url,
|
||||
dest,
|
||||
progressTitle: "Downloading rust-analyzer server",
|
||||
gunzip: true,
|
||||
mode: 0o755,
|
||||
proxySettings: config.proxySettings,
|
||||
});
|
||||
});
|
||||
|
||||
// Patching executable if that's NixOS.
|
||||
if (await isNixOs()) {
|
||||
await patchelf(dest);
|
||||
}
|
||||
|
||||
await state.updateServerVersion(config.package.version);
|
||||
return dest.fsPath;
|
||||
await state.updateServerVersion(undefined);
|
||||
await vscode.window.showErrorMessage(
|
||||
"Unfortunately we don't ship binaries for your platform yet. " +
|
||||
"You need to manually clone the rust-analyzer repository and " +
|
||||
"run `cargo xtask install --server` to build the language server from sources. " +
|
||||
"If you feel that your platform should be supported, please create an issue " +
|
||||
"about that [here](https://github.com/rust-analyzer/rust-analyzer/issues) and we " +
|
||||
"will consider it."
|
||||
);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function serverPath(config: Config): string | null {
|
||||
|
@ -422,85 +275,14 @@ async function isNixOs(): Promise<boolean> {
|
|||
}
|
||||
}
|
||||
|
||||
function isMusl(): boolean {
|
||||
// We can detect Alpine by checking `/etc/os-release` but not Void Linux musl.
|
||||
// Instead, we run `ldd` since it advertises the libc which it belongs to.
|
||||
const res = spawnSync("ldd", ["--version"]);
|
||||
return res.stderr != null && res.stderr.indexOf("musl libc") >= 0;
|
||||
}
|
||||
|
||||
async function downloadWithRetryDialog<T>(state: PersistentState, downloadFunc: () => Promise<T>): Promise<T> {
|
||||
while (true) {
|
||||
try {
|
||||
return await downloadFunc();
|
||||
} catch (e) {
|
||||
const selected = await vscode.window.showErrorMessage("Failed to download: " + e.message, {}, {
|
||||
title: "Update Github Auth Token",
|
||||
updateToken: true,
|
||||
}, {
|
||||
title: "Retry download",
|
||||
retry: true,
|
||||
}, {
|
||||
title: "Dismiss",
|
||||
});
|
||||
|
||||
if (selected?.updateToken) {
|
||||
await queryForGithubToken(state);
|
||||
continue;
|
||||
} else if (selected?.retry) {
|
||||
continue;
|
||||
}
|
||||
throw e;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async function queryForGithubToken(state: PersistentState): Promise<void> {
|
||||
const githubTokenOptions: vscode.InputBoxOptions = {
|
||||
value: state.githubToken,
|
||||
password: true,
|
||||
prompt: `
|
||||
This dialog allows to store a Github authorization token.
|
||||
The usage of an authorization token will increase the rate
|
||||
limit on the use of Github APIs and can thereby prevent getting
|
||||
throttled.
|
||||
Auth tokens can be created at https://github.com/settings/tokens`,
|
||||
};
|
||||
|
||||
const newToken = await vscode.window.showInputBox(githubTokenOptions);
|
||||
if (newToken === undefined) {
|
||||
// The user aborted the dialog => Do not update the stored token
|
||||
return;
|
||||
}
|
||||
|
||||
if (newToken === "") {
|
||||
log.info("Clearing github token");
|
||||
await state.updateGithubToken(undefined);
|
||||
} else {
|
||||
log.info("Storing new github token");
|
||||
await state.updateGithubToken(newToken);
|
||||
}
|
||||
}
|
||||
|
||||
function warnAboutExtensionConflicts() {
|
||||
const conflicting = [
|
||||
["rust-analyzer", "matklad.rust-analyzer"],
|
||||
["Rust", "rust-lang.rust"],
|
||||
["Rust", "kalitaalexey.vscode-rust"],
|
||||
];
|
||||
|
||||
const found = conflicting.filter(
|
||||
nameId => vscode.extensions.getExtension(nameId[1]) !== undefined);
|
||||
|
||||
if (found.length > 1) {
|
||||
const fst = found[0];
|
||||
const sec = found[1];
|
||||
if (vscode.extensions.getExtension("rust-lang.rust")) {
|
||||
vscode.window.showWarningMessage(
|
||||
`You have both the ${fst[0]} (${fst[1]}) and ${sec[0]} (${sec[1]}) ` +
|
||||
`You have both the rust-analyzer (matklad.rust-analyzer) and Rust (rust-lang.rust) ` +
|
||||
"plugins enabled. These are known to conflict and cause various functions of " +
|
||||
"both plugins to not work correctly. You should disable one of them.", "Got it")
|
||||
.then(() => { }, console.error);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,228 +0,0 @@
|
|||
import fetch from "node-fetch";
|
||||
var HttpsProxyAgent = require('https-proxy-agent');
|
||||
|
||||
import * as vscode from "vscode";
|
||||
import * as stream from "stream";
|
||||
import * as crypto from "crypto";
|
||||
import * as fs from "fs";
|
||||
import * as zlib from "zlib";
|
||||
import * as util from "util";
|
||||
import * as path from "path";
|
||||
import { log, assert } from "./util";
|
||||
import * as https from "https";
|
||||
import { ProxySettings } from "./config";
|
||||
|
||||
const pipeline = util.promisify(stream.pipeline);
|
||||
|
||||
const GITHUB_API_ENDPOINT_URL = "https://api.github.com";
|
||||
const OWNER = "rust-analyzer";
|
||||
const REPO = "rust-analyzer";
|
||||
|
||||
function makeHttpAgent(proxy: string | null | undefined, options?: https.AgentOptions) {
|
||||
if (proxy) {
|
||||
return new HttpsProxyAgent({ ...options, ...new URL(proxy) });
|
||||
} else {
|
||||
return new https.Agent(options);
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchRelease(
|
||||
releaseTag: string,
|
||||
githubToken: string | null | undefined,
|
||||
proxySettings: ProxySettings,
|
||||
): Promise<GithubRelease> {
|
||||
|
||||
const apiEndpointPath = `/repos/${OWNER}/${REPO}/releases/tags/${releaseTag}`;
|
||||
|
||||
const requestUrl = GITHUB_API_ENDPOINT_URL + apiEndpointPath;
|
||||
|
||||
log.debug("Issuing request for released artifacts metadata to", requestUrl);
|
||||
|
||||
const headers: Record<string, string> = { Accept: "application/vnd.github.v3+json" };
|
||||
if (githubToken != null) {
|
||||
headers.Authorization = "token " + githubToken;
|
||||
}
|
||||
|
||||
const response = await (() => {
|
||||
if (proxySettings.proxy) {
|
||||
log.debug(`Fetching release metadata via proxy: ${proxySettings.proxy}`);
|
||||
}
|
||||
const options: any = {};
|
||||
if (proxySettings.strictSSL) {
|
||||
options["rejectUnauthorized"] = false;
|
||||
}
|
||||
const agent = makeHttpAgent(proxySettings.proxy, options);
|
||||
return fetch(requestUrl, { headers: headers, agent: agent });
|
||||
})();
|
||||
|
||||
if (!response.ok) {
|
||||
log.error("Error fetching artifact release info", {
|
||||
requestUrl,
|
||||
releaseTag,
|
||||
response: {
|
||||
headers: response.headers,
|
||||
status: response.status,
|
||||
body: await response.text(),
|
||||
}
|
||||
});
|
||||
|
||||
throw new Error(
|
||||
`Got response ${response.status} when trying to fetch ` +
|
||||
`release info for ${releaseTag} release`
|
||||
);
|
||||
}
|
||||
|
||||
// We skip runtime type checks for simplicity (here we cast from `unknown` to `GithubRelease`)
|
||||
const release = await response.json() as GithubRelease;
|
||||
return release;
|
||||
}
|
||||
|
||||
// We omit declaration of tremendous amount of fields that we are not using here
|
||||
export interface GithubRelease {
|
||||
name: string;
|
||||
id: number;
|
||||
// eslint-disable-next-line camelcase
|
||||
published_at: string;
|
||||
assets: Array<{
|
||||
name: string;
|
||||
// eslint-disable-next-line camelcase
|
||||
browser_download_url: vscode.Uri;
|
||||
}>;
|
||||
}
|
||||
|
||||
interface DownloadOpts {
|
||||
progressTitle: string;
|
||||
url: vscode.Uri;
|
||||
dest: vscode.Uri;
|
||||
mode?: number;
|
||||
gunzip?: boolean;
|
||||
proxySettings: ProxySettings;
|
||||
}
|
||||
|
||||
export async function download(opts: DownloadOpts) {
|
||||
// Put artifact into a temporary file (in the same dir for simplicity)
|
||||
// to prevent partially downloaded files when user kills vscode
|
||||
// This also avoids overwriting running executables
|
||||
const randomHex = crypto.randomBytes(5).toString("hex");
|
||||
const rawDest = path.parse(opts.dest.fsPath);
|
||||
const oldServerPath = vscode.Uri.joinPath(vscode.Uri.file(rawDest.dir), `${rawDest.name}-stale-${randomHex}${rawDest.ext}`);
|
||||
const tempFilePath = vscode.Uri.joinPath(vscode.Uri.file(rawDest.dir), `${rawDest.name}${randomHex}`);
|
||||
|
||||
await vscode.window.withProgress(
|
||||
{
|
||||
location: vscode.ProgressLocation.Notification,
|
||||
cancellable: false,
|
||||
title: opts.progressTitle
|
||||
},
|
||||
async (progress, _cancellationToken) => {
|
||||
let lastPercentage = 0;
|
||||
await downloadFile(opts.url, tempFilePath, opts.mode, !!opts.gunzip, opts.proxySettings, (readBytes, totalBytes) => {
|
||||
const newPercentage = Math.round((readBytes / totalBytes) * 100);
|
||||
if (newPercentage !== lastPercentage) {
|
||||
progress.report({
|
||||
message: `${newPercentage.toFixed(0)}%`,
|
||||
increment: newPercentage - lastPercentage
|
||||
});
|
||||
|
||||
lastPercentage = newPercentage;
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
// Try to rename a running server to avoid EPERM on Windows
|
||||
// NB: this can lead to issues if a running Code instance tries to restart the server.
|
||||
try {
|
||||
await vscode.workspace.fs.rename(opts.dest, oldServerPath, { overwrite: true });
|
||||
log.info(`Renamed old server binary ${opts.dest.fsPath} to ${oldServerPath.fsPath}`);
|
||||
} catch (err) {
|
||||
const fsErr = err as vscode.FileSystemError;
|
||||
|
||||
// This is supposed to return `FileNotFound` (spelled as `EntryNotFound`)
|
||||
// but instead `code` is `Unknown` and `name` is `EntryNotFound (FileSystemError) (FileSystemError)`.
|
||||
// https://github.com/rust-analyzer/rust-analyzer/pull/10222
|
||||
if (!fsErr.code || fsErr.code !== "EntryNotFound" && fsErr.name.indexOf("EntryNotFound") === -1) {
|
||||
log.error(`Cannot rename existing server instance: ${err}"`);
|
||||
}
|
||||
}
|
||||
try {
|
||||
await vscode.workspace.fs.rename(tempFilePath, opts.dest, { overwrite: true });
|
||||
} catch (err) {
|
||||
log.error(`Cannot update server binary: ${err}`);
|
||||
}
|
||||
|
||||
// Now try to remove any stale server binaries
|
||||
const serverDir = vscode.Uri.file(rawDest.dir);
|
||||
try {
|
||||
const entries = await vscode.workspace.fs.readDirectory(serverDir);
|
||||
for (const [entry, _] of entries) {
|
||||
try {
|
||||
if (entry.includes(`${rawDest.name}-stale-`)) {
|
||||
const uri = vscode.Uri.joinPath(serverDir, entry);
|
||||
try {
|
||||
await vscode.workspace.fs.delete(uri);
|
||||
log.info(`Removed old server binary ${uri.fsPath}`);
|
||||
} catch (err) {
|
||||
log.error(`Unable to remove old server binary ${uri.fsPath}`);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
log.error(`Unable to parse ${entry}`);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
log.error(`Unable to enumerate contents of ${serverDir.fsPath}`);
|
||||
}
|
||||
}
|
||||
|
||||
async function downloadFile(
|
||||
url: vscode.Uri,
|
||||
destFilePath: vscode.Uri,
|
||||
mode: number | undefined,
|
||||
gunzip: boolean,
|
||||
proxySettings: ProxySettings,
|
||||
onProgress: (readBytes: number, totalBytes: number) => void
|
||||
): Promise<void> {
|
||||
const urlString = url.toString();
|
||||
|
||||
const res = await (() => {
|
||||
if (proxySettings.proxy) {
|
||||
log.debug(`Downloading ${urlString} via proxy: ${proxySettings.proxy}`);
|
||||
}
|
||||
const options: any = {};
|
||||
if (proxySettings.strictSSL) {
|
||||
options["rejectUnauthorized"] = false;
|
||||
}
|
||||
const agent = makeHttpAgent(proxySettings.proxy, options);
|
||||
return fetch(urlString, { agent: agent });
|
||||
})();
|
||||
|
||||
if (!res.ok) {
|
||||
log.error("Error", res.status, "while downloading file from", urlString);
|
||||
log.error({ body: await res.text(), headers: res.headers });
|
||||
|
||||
throw new Error(`Got response ${res.status} when trying to download a file.`);
|
||||
}
|
||||
|
||||
if (!res.body) {
|
||||
log.error("Empty body while downloading file from", urlString);
|
||||
log.error({ headers: res.headers });
|
||||
throw new Error(`Got empty body when trying to download a file.`);
|
||||
}
|
||||
|
||||
const totalBytes = Number(res.headers.get('content-length'));
|
||||
assert(!Number.isNaN(totalBytes), "Sanity check of content-length protocol");
|
||||
|
||||
log.debug("Downloading file of", totalBytes, "bytes size from", urlString, "to", destFilePath.fsPath);
|
||||
|
||||
let readBytes = 0;
|
||||
res.body.on("data", (chunk: Buffer) => {
|
||||
readBytes += chunk.length;
|
||||
onProgress(readBytes, totalBytes);
|
||||
});
|
||||
|
||||
const destFileStream = fs.createWriteStream(destFilePath.fsPath, { mode });
|
||||
const srcStream = gunzip ? res.body.pipe(zlib.createGunzip()) : res.body;
|
||||
|
||||
await pipeline(srcStream, destFileStream);
|
||||
}
|
|
@ -3,34 +3,13 @@ import { log } from './util';
|
|||
|
||||
export class PersistentState {
|
||||
constructor(private readonly globalState: vscode.Memento) {
|
||||
const { lastCheck, nightlyReleaseId, serverVersion } = this;
|
||||
log.info("PersistentState:", { lastCheck, nightlyReleaseId, serverVersion });
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to check for *nightly* updates once an hour.
|
||||
*/
|
||||
get lastCheck(): number | undefined {
|
||||
return this.globalState.get("lastCheck");
|
||||
}
|
||||
async updateLastCheck(value: number) {
|
||||
await this.globalState.update("lastCheck", value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Release id of the *nightly* extension.
|
||||
* Used to check if we should update.
|
||||
*/
|
||||
get nightlyReleaseId(): number | undefined {
|
||||
return this.globalState.get("releaseId");
|
||||
}
|
||||
async updateNightlyReleaseId(value: number | undefined) {
|
||||
await this.globalState.update("releaseId", value);
|
||||
const { serverVersion } = this;
|
||||
log.info("PersistentState:", { serverVersion });
|
||||
}
|
||||
|
||||
/**
|
||||
* Version of the extension that installed the server.
|
||||
* Used to check if we need to update the server.
|
||||
* Used to check if we need to run patchelf again on NixOS.
|
||||
*/
|
||||
get serverVersion(): string | undefined {
|
||||
return this.globalState.get("serverVersion");
|
||||
|
@ -38,15 +17,4 @@ export class PersistentState {
|
|||
async updateServerVersion(value: string | undefined) {
|
||||
await this.globalState.update("serverVersion", value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Github authorization token.
|
||||
* This is used for API requests against the Github API.
|
||||
*/
|
||||
get githubToken(): string | undefined {
|
||||
return this.globalState.get("githubToken");
|
||||
}
|
||||
async updateGithubToken(value: string | undefined) {
|
||||
await this.globalState.update("githubToken", value);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue