Skip to content

vscode: askBeforeDownload option #3514

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Mar 9, 2020
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion docs/user/readme.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@
:toc: preamble
:sectanchors:
:page-layout: post
// https://gist.github.com/dcode/0cfbf2699a1fe9b46ff04c41721dda74#admonitions
:tip-caption: :bulb:
:note-caption: :information_source:
:important-caption: :heavy_exclamation_mark:
:caution-caption: :fire:
:warning-caption: :warning:



// Master copy of this document lives in the https://github.com/rust-analyzer/rust-analyzer repository
Expand Down Expand Up @@ -30,7 +37,7 @@ $ rustup component add rust-src

=== VS Code

This the best supported editor at the moment.
This is the best supported editor at the moment.
rust-analyzer plugin for VS Code is maintained
https://github.com/rust-analyzer/rust-analyzer/tree/master/editors/code[in tree].

Expand All @@ -40,6 +47,16 @@ By default, the plugin will prompt you to download the matching version of the s

image::https://user-images.githubusercontent.com/9021944/75067008-17502500-54ba-11ea-835a-f92aac50e866.png[]

[NOTE]
====
To disable this notification put the following to `settings.json`

[source,json]
----
{ "rust-analyzer.askBeforeDownload": false }
----
====

The server binary is stored in `~/.config/Code/User/globalStorage/matklad.rust-analyzer`.

Note that we only support the latest version of VS Code.
Expand Down
5 changes: 5 additions & 0 deletions editors/code/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,11 @@
}
}
},
"rust-analyzer.askBeforeDownload": {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's group this into rust-analyzer.updates, as we might want to add .chanel soon as well? We should refactor old options to use the same grouping at some point, but it makes sense to design new options with more up-front planing that we use to have.

"type": "boolean",
"default": true,
"description": "Whether to ask for permission before downloading any files from the Internet"
},
"rust-analyzer.serverPath": {
"type": [
"null",
Expand Down
11 changes: 6 additions & 5 deletions editors/code/src/config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as os from "os";
import * as vscode from 'vscode';
import { BinarySource } from "./installation/interfaces";
import { ArtifactSource } from "./installation/interfaces";
import { log } from "./util";

const RA_LSP_DEBUG = process.env.__RA_LSP_SERVER_DEBUG;
Expand Down Expand Up @@ -114,12 +114,12 @@ export class Config {
}
}

get serverSource(): null | BinarySource {
get serverSource(): null | ArtifactSource {
const serverPath = RA_LSP_DEBUG ?? this.cfg.get<null | string>("serverPath");

if (serverPath) {
return {
type: BinarySource.Type.ExplicitPath,
type: ArtifactSource.Type.ExplicitPath,
path: Config.replaceTildeWithHomeDir(serverPath)
};
}
Expand All @@ -129,11 +129,12 @@ export class Config {
if (!prebuiltBinaryName) return null;

return {
type: BinarySource.Type.GithubRelease,
type: ArtifactSource.Type.GithubRelease,
dir: this.ctx.globalStoragePath,
file: prebuiltBinaryName,
storage: this.ctx.globalState,
version: Config.extensionVersion,
tag: Config.extensionVersion,
askBeforeDownload: this.cfg.get("askBeforeDownload") as boolean,
repo: {
name: "rust-analyzer",
owner: "rust-analyzer",
Expand Down
15 changes: 10 additions & 5 deletions editors/code/src/installation/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ export interface ArtifactReleaseInfo {
}

/**
* Represents the source of a binary artifact which is either specified by the user
* Represents the source of a an artifact which is either specified by the user
* explicitly, or bundled by this extension from GitHub releases.
*/
export type BinarySource = BinarySource.ExplicitPath | BinarySource.GithubRelease;
export type ArtifactSource = ArtifactSource.ExplicitPath | ArtifactSource.GithubRelease;

export namespace BinarySource {
export namespace ArtifactSource {
/**
* Type tag for `BinarySource` discriminated union.
* Type tag for `ArtifactSource` discriminated union.
*/
export const enum Type { ExplicitPath, GithubRelease }

Expand Down Expand Up @@ -56,13 +56,18 @@ export namespace BinarySource {
/**
* Tag of github release that denotes a version required by this extension.
*/
version: string;
tag: string;

/**
* Object that provides `get()/update()` operations to store metadata
* about the actual binary, e.g. its actual version.
*/
storage: vscode.Memento;

/**
* Ask for the user permission before downloading the artifact.
*/
askBeforeDownload: boolean;
}

}
28 changes: 15 additions & 13 deletions editors/code/src/installation/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import * as path from "path";
import { promises as dns } from "dns";
import { spawnSync } from "child_process";

import { BinarySource } from "./interfaces";
import { ArtifactSource } from "./interfaces";
import { fetchArtifactReleaseInfo } from "./fetch_artifact_release_info";
import { downloadArtifact } from "./download_artifact";
import { log, assert } from "../util";

export async function ensureServerBinary(source: null | BinarySource): Promise<null | string> {
export async function ensureServerBinary(source: null | ArtifactSource): Promise<null | string> {
if (!source) {
vscode.window.showErrorMessage(
"Unfortunately we don't ship binaries for your platform yet. " +
Expand All @@ -22,7 +22,7 @@ export async function ensureServerBinary(source: null | BinarySource): Promise<n
}

switch (source.type) {
case BinarySource.Type.ExplicitPath: {
case ArtifactSource.Type.ExplicitPath: {
if (isBinaryAvailable(source.path)) {
return source.path;
}
Expand All @@ -34,24 +34,26 @@ export async function ensureServerBinary(source: null | BinarySource): Promise<n
);
return null;
}
case BinarySource.Type.GithubRelease: {
case ArtifactSource.Type.GithubRelease: {
const prebuiltBinaryPath = path.join(source.dir, source.file);

const installedVersion: null | string = getServerVersion(source.storage);
const requiredVersion: string = source.version;
const requiredVersion: string = source.tag;

log.debug("Installed version:", installedVersion, "required:", requiredVersion);

if (isBinaryAvailable(prebuiltBinaryPath) && installedVersion === requiredVersion) {
return prebuiltBinaryPath;
}

const userResponse = await vscode.window.showInformationMessage(
`Language server version ${source.version} for rust-analyzer is not installed. ` +
"Do you want to download it now?",
"Download now", "Cancel"
);
if (userResponse !== "Download now") return null;
if (source.askBeforeDownload) {
const userResponse = await vscode.window.showInformationMessage(
`Language server version ${source.tag} for rust-analyzer is not installed. ` +
"Do you want to download it now?",
"Download now", "Cancel"
);
if (userResponse !== "Download now") return null;
}

if (!await downloadServer(source)) return null;

Expand All @@ -60,9 +62,9 @@ export async function ensureServerBinary(source: null | BinarySource): Promise<n
}
}

async function downloadServer(source: BinarySource.GithubRelease): Promise<boolean> {
async function downloadServer(source: ArtifactSource.GithubRelease): Promise<boolean> {
try {
const releaseInfo = await fetchArtifactReleaseInfo(source.repo, source.file, source.version);
const releaseInfo = await fetchArtifactReleaseInfo(source.repo, source.file, source.tag);

await downloadArtifact(releaseInfo, source.file, source.dir, "language server");
await setServerVersion(source.storage, releaseInfo.releaseName);
Expand Down