Skip to content
This repository was archived by the owner on Nov 18, 2022. It is now read-only.

Commit d320276

Browse files
bors[bot]Veetaha
andauthored
Merge #5025
5025: Don't mess with messy temp dir and just download into extension dir r=matklad a=Veetaha Temp dirs are messy. Dealing with them requires handling quite a bunch of edge cases. As proposed by lnicola this seems better to just put the temp files in the extension dir and not care much about suddenly leaving garbage. Instead we get shorter and less platform-caveat-y code. We will also assume users don't try to issue a download in different vscode windows simultaneously. Fixes #5019 Co-authored-by: Veetaha <[email protected]>
2 parents ebbe487 + 0a6b65e commit d320276

File tree

1 file changed

+27
-57
lines changed
  • rust-analyzer/editors/code/src

1 file changed

+27
-57
lines changed

rust-analyzer/editors/code/src/net.ts

Lines changed: 27 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import fetch from "node-fetch";
22
import * as vscode from "vscode";
33
import * as stream from "stream";
4+
import * as crypto from "crypto";
45
import * as fs from "fs";
5-
import * as os from "os";
6-
import * as path from "path";
76
import * as util from "util";
7+
import * as path from "path";
88
import { log, assert } from "./util";
99

1010
const pipeline = util.promisify(stream.pipeline);
@@ -68,32 +68,33 @@ interface DownloadOpts {
6868
}
6969

7070
export async function download(opts: DownloadOpts) {
71-
// Put the artifact into a temporary folder to prevent partially downloaded files when user kills vscode
72-
await withTempDir(async tempDir => {
73-
const tempFile = path.join(tempDir, path.basename(opts.dest));
74-
75-
await vscode.window.withProgress(
76-
{
77-
location: vscode.ProgressLocation.Notification,
78-
cancellable: false,
79-
title: opts.progressTitle
80-
},
81-
async (progress, _cancellationToken) => {
82-
let lastPercentage = 0;
83-
await downloadFile(opts.url, tempFile, opts.mode, (readBytes, totalBytes) => {
84-
const newPercentage = (readBytes / totalBytes) * 100;
85-
progress.report({
86-
message: newPercentage.toFixed(0) + "%",
87-
increment: newPercentage - lastPercentage
88-
});
89-
90-
lastPercentage = newPercentage;
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}`);
76+
77+
await vscode.window.withProgress(
78+
{
79+
location: vscode.ProgressLocation.Notification,
80+
cancellable: false,
81+
title: opts.progressTitle
82+
},
83+
async (progress, _cancellationToken) => {
84+
let lastPercentage = 0;
85+
await downloadFile(opts.url, tempFile, opts.mode, (readBytes, totalBytes) => {
86+
const newPercentage = (readBytes / totalBytes) * 100;
87+
progress.report({
88+
message: newPercentage.toFixed(0) + "%",
89+
increment: newPercentage - lastPercentage
9190
});
92-
}
93-
);
9491

95-
await moveFile(tempFile, opts.dest);
96-
});
92+
lastPercentage = newPercentage;
93+
});
94+
}
95+
);
96+
97+
await fs.promises.rename(tempFile, opts.dest);
9798
}
9899

99100
/**
@@ -137,34 +138,3 @@ async function downloadFile(
137138
// https://github.com/rust-analyzer/rust-analyzer/issues/3167
138139
});
139140
}
140-
141-
async function withTempDir(scope: (tempDirPath: string) => Promise<void>) {
142-
// Based on the great article: https://advancedweb.hu/secure-tempfiles-in-nodejs-without-dependencies/
143-
144-
// `.realpath()` should handle the cases where os.tmpdir() contains symlinks
145-
const osTempDir = await fs.promises.realpath(os.tmpdir());
146-
147-
const tempDir = await fs.promises.mkdtemp(path.join(osTempDir, "rust-analyzer"));
148-
149-
try {
150-
return await scope(tempDir);
151-
} finally {
152-
// We are good citizens :D
153-
void fs.promises.rmdir(tempDir, { recursive: true }).catch(log.error);
154-
}
155-
};
156-
157-
async function moveFile(src: fs.PathLike, dest: fs.PathLike) {
158-
try {
159-
await fs.promises.rename(src, dest);
160-
} catch (err) {
161-
if (err.code === 'EXDEV') {
162-
// We are probably moving the file across partitions/devices
163-
await fs.promises.copyFile(src, dest);
164-
await fs.promises.unlink(src);
165-
} else {
166-
log.error(`Failed to rename the file ${src} -> ${dest}`, err);
167-
throw err;
168-
}
169-
}
170-
}

0 commit comments

Comments
 (0)