aboutsummaryrefslogtreecommitdiff
path: root/editors/code/src/installation/download_file.ts
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-02-09 15:21:12 +0000
committerGitHub <[email protected]>2020-02-09 15:21:12 +0000
commit360890fcec3af854c4848ba7ed3511b4bae2ff5e (patch)
tree5820313364f04233fe6a36794bc370ff25407cc5 /editors/code/src/installation/download_file.ts
parent0db5525c445fb86a7fb7441267ffab2604d78a41 (diff)
parentdfb81a8cd4b9a2efd8151b4ac36105c51df7d683 (diff)
Merge #3053
3053: Feature: downloading lsp server from GitHub r=matklad a=Veetaha This is currently very WIP, I may need to change this and that, add "download language server command", logging stuff (for future bug reports), etc., but it already works. Also didn't test this on windows yet and mac (don't have the latter) The quirks: * Downloaded binary doesn't have executable permissions by default, that's why we ~~`chmod 111`~~ (**[UPD]** `chmod 755` as per @lnicola [suggestion](https://github.com/rust-analyzer/rust-analyzer/pull/3053#discussion_r376694456)) for it. * To remove installed binary run `rm /${HOME}/.config/Code/User/globalStorage/matklad.rust-analyzer/ra_lsp_server-linux`, ~~note that `-f` flag is necessary, because of `111` permissions (I think this should be changed)~~ (**[UPD]** --force is no longer needed due to 755 permissions). I also tried to keep things simple and not to use too many dependencies, all the ones added have 0 dependencies, (`ts-not-nil` is my personal npm package, that imitates `unwrap()` in TypeScript) **[UPD]** I reduced throttle latency of progress indicator to 200ms for smoother UX // TODO: - [x] ~~Add `Rust Analyzer: Download latest language server` vscode command.~~ **[UPD]**: having reviewed the code and estimated available options I concluded that this feature requires too many code changes, I'd like to extract this into a separate PR after we merge this one. - [x] Add some logging for future debugging - [x] ~~Gracefully handle the case when language server is not available (e.g. no internet connection, user explicitly rejected the download, etc.)~~ **[UPD]** Decided to postpone better implementation of graceful degradation logic as per [conversation](https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Fwg-rls-2.2E0/topic/Deployment.20and.20installation/near/187758550). Demo (**[UPD]** this is a bit outdated, but still mainly reflects the feature): ![ra-github-release-download-mvp](https://user-images.githubusercontent.com/36276403/74077961-4f248a80-4a2d-11ea-962f-27c650fd6c4c.gif) Related issue: #2988 #3007 Co-authored-by: Veetaha <[email protected]> Co-authored-by: Veetaha <[email protected]>
Diffstat (limited to 'editors/code/src/installation/download_file.ts')
-rw-r--r--editors/code/src/installation/download_file.ts34
1 files changed, 34 insertions, 0 deletions
diff --git a/editors/code/src/installation/download_file.ts b/editors/code/src/installation/download_file.ts
new file mode 100644
index 000000000..b51602ef9
--- /dev/null
+++ b/editors/code/src/installation/download_file.ts
@@ -0,0 +1,34 @@
1import fetch from "node-fetch";
2import * as fs from "fs";
3import { strict as assert } from "assert";
4
5/**
6 * Downloads file from `url` and stores it at `destFilePath`.
7 * `onProgress` callback is called on recieveing each chunk of bytes
8 * to track the progress of downloading, it gets the already read and total
9 * amount of bytes to read as its parameters.
10 */
11export async function downloadFile(
12 url: string,
13 destFilePath: fs.PathLike,
14 onProgress: (readBytes: number, totalBytes: number) => void
15): Promise<void> {
16 const response = await fetch(url);
17
18 const totalBytes = Number(response.headers.get('content-length'));
19 assert(!Number.isNaN(totalBytes), "Sanity check of content-length protocol");
20
21 let readBytes = 0;
22
23 console.log("Downloading file of", totalBytes, "bytes size from", url, "to", destFilePath);
24
25 return new Promise<void>((resolve, reject) => response.body
26 .on("data", (chunk: Buffer) => {
27 readBytes += chunk.length;
28 onProgress(readBytes, totalBytes);
29 })
30 .on("end", resolve)
31 .on("error", reject)
32 .pipe(fs.createWriteStream(destFilePath))
33 );
34}