From b9a219156351c4f017085bd1a23b0c7e18e8203f Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 17 Dec 2021 11:08:17 +0100 Subject: [PATCH] files - add a method to generate a random path name (#139364) --- extensions/emmet/src/test/testUtils.ts | 9 +++- .../src/test/testUtils.ts | 9 +++- .../src/test/utils.ts | 13 +++++- extensions/vscode-notebook-tests/src/utils.ts | 7 +++- src/vs/base/common/extpath.ts | 22 ++++++++++ src/vs/base/node/pfs.ts | 5 +-- src/vs/base/test/common/extpath.test.ts | 19 +++++++++ src/vs/base/test/common/map.test.ts | 3 +- src/vs/base/test/node/pfs/pfs.test.ts | 41 +++++++------------ src/vs/base/test/node/testUtils.ts | 4 +- src/vs/code/electron-main/app.ts | 7 ++-- src/vs/code/node/cli.ts | 11 ++--- src/vs/platform/environment/node/stdin.ts | 14 +++---- src/vs/platform/environment/node/wait.ts | 8 ++-- .../node/watcher/parcel/parcelWatcher.ts | 5 +-- .../electron-sandbox/elevatedFileService.ts | 4 +- 16 files changed, 113 insertions(+), 68 deletions(-) diff --git a/extensions/emmet/src/test/testUtils.ts b/extensions/emmet/src/test/testUtils.ts index 30e11ee794b..01e1e098fea 100644 --- a/extensions/emmet/src/test/testUtils.ts +++ b/extensions/emmet/src/test/testUtils.ts @@ -8,8 +8,13 @@ import * as fs from 'fs'; import * as os from 'os'; import { join } from 'path'; -function rndName() { - return Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 10); +export function rndName() { + let name = ''; + const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + for (let i = 0; i < 10; i++) { + name += possible.charAt(Math.floor(Math.random() * possible.length)); + } + return name; } export function createRandomFile(contents = '', fileExtension = 'txt'): Thenable { diff --git a/extensions/typescript-language-features/src/test/testUtils.ts b/extensions/typescript-language-features/src/test/testUtils.ts index 28f3dfc7d92..883a196bf14 100644 --- a/extensions/typescript-language-features/src/test/testUtils.ts +++ b/extensions/typescript-language-features/src/test/testUtils.ts @@ -9,8 +9,13 @@ import * as os from 'os'; import { join } from 'path'; import * as vscode from 'vscode'; -function rndName() { - return Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 10); +export function rndName() { + let name = ''; + const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + for (let i = 0; i < 10; i++) { + name += possible.charAt(Math.floor(Math.random() * possible.length)); + } + return name; } export function createRandomFile(contents = '', fileExtension = 'txt'): Thenable { diff --git a/extensions/vscode-custom-editor-tests/src/test/utils.ts b/extensions/vscode-custom-editor-tests/src/test/utils.ts index 5edd53b27cc..7ed2afcaca3 100644 --- a/extensions/vscode-custom-editor-tests/src/test/utils.ts +++ b/extensions/vscode-custom-editor-tests/src/test/utils.ts @@ -6,8 +6,17 @@ import * as vscode from 'vscode'; export function randomFilePath(args: { root: vscode.Uri, ext: string }): vscode.Uri { - const fileName = Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 10); - return (vscode.Uri as any).joinPath(args.root, fileName + args.ext); + const fileName = rndName(); + return vscode.Uri.joinPath(args.root, fileName + args.ext); +} + +export function rndName() { + let name = ''; + const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + for (let i = 0; i < 10; i++) { + name += possible.charAt(Math.floor(Math.random() * possible.length)); + } + return name; } export function closeAllEditors(): Thenable { diff --git a/extensions/vscode-notebook-tests/src/utils.ts b/extensions/vscode-notebook-tests/src/utils.ts index 0a8f20a1942..0adaf940ea9 100644 --- a/extensions/vscode-notebook-tests/src/utils.ts +++ b/extensions/vscode-notebook-tests/src/utils.ts @@ -242,7 +242,12 @@ export class TestFS implements vscode.FileSystemProvider { } export function rndName() { - return Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 10); + let name = ''; + const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + for (let i = 0; i < 10; i++) { + name += possible.charAt(Math.floor(Math.random() * possible.length)); + } + return name; } export const testFs = new TestFS('fake-fs', true); diff --git a/src/vs/base/common/extpath.ts b/src/vs/base/common/extpath.ts index 48cb9522cd6..25b60a9608c 100644 --- a/src/vs/base/common/extpath.ts +++ b/src/vs/base/common/extpath.ts @@ -364,3 +364,25 @@ export function parseLineAndColumnAware(rawPath: string): IPathWithLineAndColumn column: column !== undefined ? column : line !== undefined ? 1 : undefined // if we have a line, make sure column is also set }; } + +const pathChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + +export function randomPath(parent?: string, prefix?: string, randomLength = 8): string { + let suffix = ''; + for (let i = 0; i < randomLength; i++) { + suffix += pathChars.charAt(Math.floor(Math.random() * pathChars.length)); + } + + let randomFileName: string; + if (prefix) { + randomFileName = `${prefix}-${suffix}`; + } else { + randomFileName = suffix; + } + + if (parent) { + return join(parent, randomFileName); + } + + return randomFileName; +} diff --git a/src/vs/base/node/pfs.ts b/src/vs/base/node/pfs.ts index 3876e2a9b3f..3804f5d2271 100644 --- a/src/vs/base/node/pfs.ts +++ b/src/vs/base/node/pfs.ts @@ -7,13 +7,12 @@ import * as fs from 'fs'; import { tmpdir } from 'os'; import { promisify } from 'util'; import { ResourceQueue } from 'vs/base/common/async'; -import { isEqualOrParent, isRootOrDriveLetter } from 'vs/base/common/extpath'; +import { isEqualOrParent, isRootOrDriveLetter, randomPath } from 'vs/base/common/extpath'; import { normalizeNFC } from 'vs/base/common/normalization'; import { join } from 'vs/base/common/path'; import { isLinux, isMacintosh, isWindows } from 'vs/base/common/platform'; import { extUriBiasedIgnorePathCase } from 'vs/base/common/resources'; import { URI } from 'vs/base/common/uri'; -import { generateUuid } from 'vs/base/common/uuid'; //#region rimraf @@ -55,7 +54,7 @@ async function rimraf(path: string, mode = RimRafMode.UNLINK): Promise { async function rimrafMove(path: string): Promise { try { - const pathInTemp = join(tmpdir(), generateUuid()); + const pathInTemp = randomPath(tmpdir()); try { await Promises.rename(path, pathInTemp); } catch (error) { diff --git a/src/vs/base/test/common/extpath.test.ts b/src/vs/base/test/common/extpath.test.ts index b2301b9392b..1c37ca687b6 100644 --- a/src/vs/base/test/common/extpath.test.ts +++ b/src/vs/base/test/common/extpath.test.ts @@ -200,4 +200,23 @@ suite('Paths', () => { assert.strictEqual(res.line, undefined); assert.strictEqual(res.column, undefined); }); + + test('randomPath', () => { + let res = extpath.randomPath('/foo/bar'); + assert.ok(res); + + res = extpath.randomPath('/foo/bar', 'prefix-'); + assert.ok(res.indexOf('prefix-')); + + const r1 = extpath.randomPath('/foo/bar'); + const r2 = extpath.randomPath('/foo/bar'); + + assert.notStrictEqual(r1, r2); + + const r3 = extpath.randomPath('', '', 3); + assert.strictEqual(r3.length, 3); + + const r4 = extpath.randomPath(); + assert.ok(r4); + }); }); diff --git a/src/vs/base/test/common/map.test.ts b/src/vs/base/test/common/map.test.ts index d19e30d9953..c681cf92396 100644 --- a/src/vs/base/test/common/map.test.ts +++ b/src/vs/base/test/common/map.test.ts @@ -5,6 +5,7 @@ import * as assert from 'assert'; import { shuffle } from 'vs/base/common/arrays'; +import { randomPath } from 'vs/base/common/extpath'; import { ConfigKeysIterator, LinkedMap, LRUCache, PathIterator, ResourceMap, StringIterator, TernarySearchTree, Touch, UriIterator } from 'vs/base/common/map'; import { extUriIgnorePathCase } from 'vs/base/common/resources'; import { StopWatch } from 'vs/base/common/stopwatch'; @@ -793,7 +794,7 @@ suite('Map', () => { for (let round = 10; round >= 0; round--) { const keys: URI[] = []; for (let i = 0; i < 100; i++) { - keys.push(URI.from({ scheme: 'fake-fs', path: Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10) })); + keys.push(URI.from({ scheme: 'fake-fs', path: randomPath(undefined, undefined, 10) })); } const tst = TernarySearchTree.forUris(); diff --git a/src/vs/base/test/node/pfs/pfs.test.ts b/src/vs/base/test/node/pfs/pfs.test.ts index 66c8f3221a6..09bc57bf432 100644 --- a/src/vs/base/test/node/pfs/pfs.test.ts +++ b/src/vs/base/test/node/pfs/pfs.test.ts @@ -8,9 +8,9 @@ import * as fs from 'fs'; import { tmpdir } from 'os'; import { timeout } from 'vs/base/common/async'; import { VSBuffer } from 'vs/base/common/buffer'; +import { randomPath } from 'vs/base/common/extpath'; import { join, sep } from 'vs/base/common/path'; import { isWindows } from 'vs/base/common/platform'; -import { generateUuid } from 'vs/base/common/uuid'; import { Promises, RimRafMode, rimrafSync, SymlinkSupport, writeFileSync } from 'vs/base/node/pfs'; import { flakySuite, getPathFromAmdModule, getRandomTestPath } from 'vs/base/test/node/testUtils'; @@ -153,12 +153,10 @@ flakySuite('PFS', function () { }); test('copy, move and delete', async () => { - const id = generateUuid(); - const id2 = generateUuid(); const sourceDir = getPathFromAmdModule(require, './fixtures'); const parentDir = join(tmpdir(), 'vsctests', 'pfs'); - const targetDir = join(parentDir, id); - const targetDir2 = join(parentDir, id2); + const targetDir = randomPath(parentDir); + const targetDir2 = randomPath(parentDir); await Promises.copy(sourceDir, targetDir, { preserveSymlinks: true }); @@ -190,14 +188,9 @@ flakySuite('PFS', function () { }); test('copy handles symbolic links', async () => { - const id1 = generateUuid(); - const symbolicLinkTarget = join(testDir, id1); - - const id2 = generateUuid(); - const symLink = join(testDir, id2); - - const id3 = generateUuid(); - const copyTarget = join(testDir, id3); + const symbolicLinkTarget = randomPath(testDir); + const symLink = randomPath(testDir); + const copyTarget = randomPath(testDir); await Promises.mkdir(symbolicLinkTarget, { recursive: true }); @@ -248,7 +241,7 @@ flakySuite('PFS', function () { test('copy handles symbolic links when the reference is inside source', async () => { // Source Folder - const sourceFolder = join(testDir, generateUuid(), 'copy-test'); // copy-test + const sourceFolder = join(randomPath(testDir), 'copy-test'); // copy-test const sourceLinkTestFolder = join(sourceFolder, 'link-test'); // copy-test/link-test const sourceLinkMD5JSFolder = join(sourceLinkTestFolder, 'md5'); // copy-test/link-test/md5 const sourceLinkMD5JSFile = join(sourceLinkMD5JSFolder, 'md5.js'); // copy-test/link-test/md5/md5.js @@ -308,11 +301,8 @@ flakySuite('PFS', function () { }); test('stat link', async () => { - const id1 = generateUuid(); - const directory = join(testDir, id1); - - const id2 = generateUuid(); - const symbolicLink = join(testDir, id2); + const directory = randomPath(testDir); + const symbolicLink = randomPath(testDir); await Promises.mkdir(directory, { recursive: true }); @@ -327,11 +317,8 @@ flakySuite('PFS', function () { }); test('stat link (non existing target)', async () => { - const id1 = generateUuid(); - const directory = join(testDir, id1); - - const id2 = generateUuid(); - const symbolicLink = join(testDir, id2); + const directory = randomPath(testDir); + const symbolicLink = randomPath(testDir); await Promises.mkdir(directory, { recursive: true }); @@ -346,14 +333,14 @@ flakySuite('PFS', function () { test('readdir', async () => { if (typeof process.versions['electron'] !== 'undefined' /* needs electron */) { - const id = generateUuid(); - const newDir = join(testDir, 'pfs', id, 'öäü'); + const parent = randomPath(join(testDir, 'pfs')); + const newDir = join(parent, 'öäü'); await Promises.mkdir(newDir, { recursive: true }); assert.ok(fs.existsSync(newDir)); - const children = await Promises.readdir(join(testDir, 'pfs', id)); + const children = await Promises.readdir(parent); assert.strictEqual(children.some(n => n === 'öäü'), true); // Mac always converts to NFD, so } }); diff --git a/src/vs/base/test/node/testUtils.ts b/src/vs/base/test/node/testUtils.ts index fb2bc77ad9c..2d67f88b343 100644 --- a/src/vs/base/test/node/testUtils.ts +++ b/src/vs/base/test/node/testUtils.ts @@ -3,13 +3,13 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { randomPath } from 'vs/base/common/extpath'; import { join } from 'vs/base/common/path'; import { URI } from 'vs/base/common/uri'; -import { generateUuid } from 'vs/base/common/uuid'; import * as testUtils from 'vs/base/test/common/testUtils'; export function getRandomTestPath(tmpdir: string, ...segments: string[]): string { - return join(tmpdir, ...segments, generateUuid()); + return randomPath(join(tmpdir, ...segments)); } export function getPathFromAmdModule(requirefn: typeof require, relativePath: string): string { diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 8982da34914..2d6a2224857 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -9,7 +9,7 @@ import { hostname, release } from 'os'; import { VSBuffer } from 'vs/base/common/buffer'; import { toErrorMessage } from 'vs/base/common/errorMessage'; import { onUnexpectedError, setUnexpectedErrorHandler } from 'vs/base/common/errors'; -import { isEqualOrParent } from 'vs/base/common/extpath'; +import { isEqualOrParent, randomPath } from 'vs/base/common/extpath'; import { once } from 'vs/base/common/functional'; import { stripComments } from 'vs/base/common/json'; import { getPathLabel, mnemonicButtonLabel } from 'vs/base/common/labels'; @@ -17,7 +17,6 @@ import { Disposable } from 'vs/base/common/lifecycle'; import { Schemas } from 'vs/base/common/network'; import { isAbsolute, join, posix } from 'vs/base/common/path'; import { IProcessEnvironment, isLinux, isLinuxSnap, isMacintosh, isWindows } from 'vs/base/common/platform'; -import { joinPath } from 'vs/base/common/resources'; import { assertType, withNullAsUndefined } from 'vs/base/common/types'; import { URI } from 'vs/base/common/uri'; import { generateUuid } from 'vs/base/common/uuid'; @@ -1043,7 +1042,7 @@ export class CodeApplication extends Disposable { } private stopTracingEventually(accessor: ServicesAccessor, windows: ICodeWindow[]): void { - this.logService.info(`Tracing: waiting for windows to get ready...`); + this.logService.info('Tracing: waiting for windows to get ready...'); const dialogMainService = accessor.get(IDialogMainService); @@ -1055,7 +1054,7 @@ export class CodeApplication extends Disposable { recordingStopped = true; // only once - const path = await contentTracing.stopRecording(joinPath(this.environmentMainService.userHome, `${this.productService.applicationName}-${Math.random().toString(16).slice(-4)}.trace.txt`).fsPath); + const path = await contentTracing.stopRecording(`${randomPath(this.environmentMainService.userHome.fsPath, this.productService.applicationName)}.trace.txt`); if (!timeout) { dialogMainService.showMessageBox({ diff --git a/src/vs/code/node/cli.ts b/src/vs/code/node/cli.ts index 6ece06fd6e3..aa53f3f2dd2 100644 --- a/src/vs/code/node/cli.ts +++ b/src/vs/code/node/cli.ts @@ -8,7 +8,7 @@ import { chmodSync, existsSync, readFileSync, statSync, truncateSync, unlinkSync import { homedir, release, tmpdir } from 'os'; import type { ProfilingSession, Target } from 'v8-inspect-profiler'; import { Event } from 'vs/base/common/event'; -import { isAbsolute, join, resolve } from 'vs/base/common/path'; +import { isAbsolute, resolve } from 'vs/base/common/path'; import { IProcessEnvironment, isMacintosh, isWindows } from 'vs/base/common/platform'; import { randomPort } from 'vs/base/common/ports'; import { isString } from 'vs/base/common/types'; @@ -22,6 +22,7 @@ import { getStdinFilePath, hasStdinWithoutTty, readFromStdin, stdinDataListener import { createWaitMarkerFile } from 'vs/platform/environment/node/wait'; import product from 'vs/platform/product/common/product'; import { CancellationTokenSource } from 'vs/base/common/cancellation'; +import { randomPath } from 'vs/base/common/extpath'; function shouldSpawnCliProcess(argv: NativeParsedArgs): boolean { return !!argv['install-source'] @@ -32,10 +33,6 @@ function shouldSpawnCliProcess(argv: NativeParsedArgs): boolean { || !!argv['telemetry']; } -function createFileName(dir: string, prefix: string): string { - return join(dir, `${prefix}-${Math.random().toString(16).slice(-4)}`); -} - interface IMainCli { main: (argv: NativeParsedArgs) => Promise; } @@ -259,7 +256,7 @@ export async function main(argv: string[]): Promise { throw new Error('Failed to find free ports for profiler. Make sure to shutdown all instances of the editor first.'); } - const filenamePrefix = createFileName(homedir(), 'prof'); + const filenamePrefix = randomPath(homedir(), 'prof'); addArg(argv, `--inspect-brk=${portMain}`); addArg(argv, `--remote-debugging-port=${portRenderer}`); @@ -393,7 +390,7 @@ export async function main(argv: string[]): Promise { for (const outputType of ['stdout', 'stderr']) { // Tmp file to target output to - const tmpName = createFileName(tmpdir(), `code-${outputType}`); + const tmpName = randomPath(tmpdir(), `code-${outputType}`); writeFileSync(tmpName, ''); spawnArgs.push(`--${outputType}`, tmpName); diff --git a/src/vs/platform/environment/node/stdin.ts b/src/vs/platform/environment/node/stdin.ts index 93c08e1d0b9..e1958f9bae0 100644 --- a/src/vs/platform/environment/node/stdin.ts +++ b/src/vs/platform/environment/node/stdin.ts @@ -2,12 +2,10 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -/** - * This code is also used by standalone cli's. Avoid adding dependencies to keep the size of the cli small. - */ -import * as fs from 'fs'; -import * as os from 'os'; -import * as paths from 'vs/base/common/path'; + +import { createWriteStream } from 'fs'; +import { tmpdir } from 'os'; +import { randomPath } from 'vs/base/common/extpath'; import { resolveTerminalEncoding } from 'vs/base/node/terminalEncoding'; export function hasStdinWithoutTty() { @@ -36,13 +34,13 @@ export function stdinDataListener(durationinMs: number): Promise { } export function getStdinFilePath(): string { - return paths.join(os.tmpdir(), `code-stdin-${Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 3)}`); + return randomPath(tmpdir(), 'code-stdin', 3); } export async function readFromStdin(targetPath: string, verbose: boolean): Promise { // open tmp file for writing - const stdinFileStream = fs.createWriteStream(targetPath); + const stdinFileStream = createWriteStream(targetPath); let encoding = await resolveTerminalEncoding(verbose); diff --git a/src/vs/platform/environment/node/wait.ts b/src/vs/platform/environment/node/wait.ts index 9441f808590..0be07ad2266 100644 --- a/src/vs/platform/environment/node/wait.ts +++ b/src/vs/platform/environment/node/wait.ts @@ -3,15 +3,15 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as fs from 'fs'; +import { writeFileSync } from 'fs'; import { tmpdir } from 'os'; -import { join } from 'vs/base/common/path'; +import { randomPath } from 'vs/base/common/extpath'; export function createWaitMarkerFile(verbose?: boolean): string | undefined { - const randomWaitMarkerPath = join(tmpdir(), Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 10)); + const randomWaitMarkerPath = randomPath(tmpdir()); try { - fs.writeFileSync(randomWaitMarkerPath, ''); // use built-in fs to avoid dragging in more dependencies + writeFileSync(randomWaitMarkerPath, ''); // use built-in fs to avoid dragging in more dependencies if (verbose) { console.log(`Marker file for --wait created: ${randomWaitMarkerPath}`); } diff --git a/src/vs/platform/files/node/watcher/parcel/parcelWatcher.ts b/src/vs/platform/files/node/watcher/parcel/parcelWatcher.ts index 7fe7d63be31..12a871c8662 100644 --- a/src/vs/platform/files/node/watcher/parcel/parcelWatcher.ts +++ b/src/vs/platform/files/node/watcher/parcel/parcelWatcher.ts @@ -10,7 +10,7 @@ import { DeferredPromise, RunOnceScheduler } from 'vs/base/common/async'; import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; import { toErrorMessage } from 'vs/base/common/errorMessage'; import { Emitter } from 'vs/base/common/event'; -import { isEqualOrParent } from 'vs/base/common/extpath'; +import { isEqualOrParent, randomPath } from 'vs/base/common/extpath'; import { parse, ParsedPattern } from 'vs/base/common/glob'; import { Disposable } from 'vs/base/common/lifecycle'; import { TernarySearchTree } from 'vs/base/common/map'; @@ -18,7 +18,6 @@ import { normalizeNFC } from 'vs/base/common/normalization'; import { dirname, isAbsolute, join, normalize, sep } from 'vs/base/common/path'; import { isLinux, isMacintosh, isWindows } from 'vs/base/common/platform'; import { rtrim } from 'vs/base/common/strings'; -import { generateUuid } from 'vs/base/common/uuid'; import { realcaseSync, realpathSync } from 'vs/base/node/extpath'; import { watchFolder } from 'vs/base/node/watcher'; import { FileChangeType } from 'vs/platform/files/common/files'; @@ -246,7 +245,7 @@ export class ParcelWatcher extends Disposable implements IRecursiveWatcher { const instance = new DeferredPromise(); - const snapshotFile = join(tmpdir(), `vscode-watcher-snapshot-${generateUuid()}`); + const snapshotFile = randomPath(tmpdir(), 'vscode-watcher-snapshot'); // Remember as watcher instance const watcher: IParcelWatcherInstance = { diff --git a/src/vs/workbench/services/files/electron-sandbox/elevatedFileService.ts b/src/vs/workbench/services/files/electron-sandbox/elevatedFileService.ts index e47aa8eae0f..f33ec87d21e 100644 --- a/src/vs/workbench/services/files/electron-sandbox/elevatedFileService.ts +++ b/src/vs/workbench/services/files/electron-sandbox/elevatedFileService.ts @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import { VSBuffer, VSBufferReadable, VSBufferReadableStream } from 'vs/base/common/buffer'; +import { randomPath } from 'vs/base/common/extpath'; import { Schemas } from 'vs/base/common/network'; -import { join } from 'vs/base/common/path'; import { URI } from 'vs/base/common/uri'; import { IFileService, IFileStatWithMetadata, IWriteFileOptions } from 'vs/platform/files/common/files'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; @@ -32,7 +32,7 @@ export class NativeElevatedFileService implements IElevatedFileService { } async writeFileElevated(resource: URI, value: VSBuffer | VSBufferReadable | VSBufferReadableStream, options?: IWriteFileOptions): Promise { - const source = URI.file(join(this.environmentService.userDataPath, `code-elevated-${Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 6)}`)); + const source = URI.file(randomPath(this.environmentService.userDataPath, 'code-elevated')); try { // write into a tmp file first await this.fileService.writeFile(source, value, options);