diff options
Diffstat (limited to 'editors/code/src/net.ts')
-rw-r--r-- | editors/code/src/net.ts | 39 |
1 files changed, 24 insertions, 15 deletions
diff --git a/editors/code/src/net.ts b/editors/code/src/net.ts index 492213937..866092882 100644 --- a/editors/code/src/net.ts +++ b/editors/code/src/net.ts | |||
@@ -1,8 +1,10 @@ | |||
1 | import fetch from "node-fetch"; | 1 | import fetch from "node-fetch"; |
2 | import * as vscode from "vscode"; | 2 | import * as vscode from "vscode"; |
3 | import * as fs from "fs"; | ||
4 | import * as stream from "stream"; | 3 | import * as stream from "stream"; |
4 | import * as crypto from "crypto"; | ||
5 | import * as fs from "fs"; | ||
5 | import * as util from "util"; | 6 | import * as util from "util"; |
7 | import * as path from "path"; | ||
6 | import { log, assert } from "./util"; | 8 | import { log, assert } from "./util"; |
7 | 9 | ||
8 | const pipeline = util.promisify(stream.pipeline); | 10 | const pipeline = util.promisify(stream.pipeline); |
@@ -58,22 +60,29 @@ export interface GithubRelease { | |||
58 | }>; | 60 | }>; |
59 | } | 61 | } |
60 | 62 | ||
63 | interface DownloadOpts { | ||
64 | progressTitle: string; | ||
65 | url: string; | ||
66 | dest: string; | ||
67 | mode?: number; | ||
68 | } | ||
69 | |||
70 | export async function download(opts: DownloadOpts) { | ||
71 | // Put artifact into a temporary file (in the same dir for simplicity) | ||
72 | // to prevent partially downloaded files when user kills vscode | ||
73 | const dest = path.parse(opts.dest); | ||
74 | const randomHex = crypto.randomBytes(5).toString("hex"); | ||
75 | const tempFile = path.join(dest.dir, `${dest.name}${randomHex}`); | ||
61 | 76 | ||
62 | export async function download( | ||
63 | downloadUrl: string, | ||
64 | destinationPath: string, | ||
65 | progressTitle: string, | ||
66 | { mode }: { mode?: number } = {}, | ||
67 | ) { | ||
68 | await vscode.window.withProgress( | 77 | await vscode.window.withProgress( |
69 | { | 78 | { |
70 | location: vscode.ProgressLocation.Notification, | 79 | location: vscode.ProgressLocation.Notification, |
71 | cancellable: false, | 80 | cancellable: false, |
72 | title: progressTitle | 81 | title: opts.progressTitle |
73 | }, | 82 | }, |
74 | async (progress, _cancellationToken) => { | 83 | async (progress, _cancellationToken) => { |
75 | let lastPercentage = 0; | 84 | let lastPercentage = 0; |
76 | await downloadFile(downloadUrl, destinationPath, mode, (readBytes, totalBytes) => { | 85 | await downloadFile(opts.url, tempFile, opts.mode, (readBytes, totalBytes) => { |
77 | const newPercentage = (readBytes / totalBytes) * 100; | 86 | const newPercentage = (readBytes / totalBytes) * 100; |
78 | progress.report({ | 87 | progress.report({ |
79 | message: newPercentage.toFixed(0) + "%", | 88 | message: newPercentage.toFixed(0) + "%", |
@@ -84,10 +93,12 @@ export async function download( | |||
84 | }); | 93 | }); |
85 | } | 94 | } |
86 | ); | 95 | ); |
96 | |||
97 | await fs.promises.rename(tempFile, opts.dest); | ||
87 | } | 98 | } |
88 | 99 | ||
89 | /** | 100 | /** |
90 | * Downloads file from `url` and stores it at `destFilePath` with `destFilePermissions`. | 101 | * Downloads file from `url` and stores it at `destFilePath` with `mode` (unix permissions). |
91 | * `onProgress` callback is called on recieveing each chunk of bytes | 102 | * `onProgress` callback is called on recieveing each chunk of bytes |
92 | * to track the progress of downloading, it gets the already read and total | 103 | * to track the progress of downloading, it gets the already read and total |
93 | * amount of bytes to read as its parameters. | 104 | * amount of bytes to read as its parameters. |
@@ -119,13 +130,11 @@ async function downloadFile( | |||
119 | }); | 130 | }); |
120 | 131 | ||
121 | const destFileStream = fs.createWriteStream(destFilePath, { mode }); | 132 | const destFileStream = fs.createWriteStream(destFilePath, { mode }); |
122 | |||
123 | await pipeline(res.body, destFileStream); | 133 | await pipeline(res.body, destFileStream); |
124 | return new Promise<void>(resolve => { | 134 | await new Promise<void>(resolve => { |
125 | destFileStream.on("close", resolve); | 135 | destFileStream.on("close", resolve); |
126 | destFileStream.destroy(); | 136 | destFileStream.destroy(); |
127 | 137 | // This workaround is awaiting to be removed when vscode moves to newer nodejs version: | |
128 | // Details on workaround: https://github.com/rust-analyzer/rust-analyzer/pull/3092#discussion_r378191131 | 138 | // https://github.com/rust-analyzer/rust-analyzer/issues/3167 |
129 | // Issue at nodejs repo: https://github.com/nodejs/node/issues/31776 | ||
130 | }); | 139 | }); |
131 | } | 140 | } |