Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/markdown-language-features/src/languageFeatures/copyFiles/newFilePathGenerator.ts
3294 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import * as picomatch from 'picomatch';
7
import * as vscode from 'vscode';
8
import { Utils } from 'vscode-uri';
9
import { getParentDocumentUri } from '../../util/document';
10
import { CopyFileConfiguration, getCopyFileConfiguration, parseGlob, resolveCopyDestination } from './copyFiles';
11
12
13
export class NewFilePathGenerator {
14
15
private readonly _usedPaths = new Set<string>();
16
17
async getNewFilePath(
18
document: vscode.TextDocument,
19
file: vscode.DataTransferFile,
20
token: vscode.CancellationToken
21
): Promise<{ readonly uri: vscode.Uri; readonly overwrite: boolean } | undefined> {
22
const config = getCopyFileConfiguration(document);
23
const desiredPath = getDesiredNewFilePath(config, document, file);
24
25
const root = Utils.dirname(desiredPath);
26
const ext = Utils.extname(desiredPath);
27
let baseName = Utils.basename(desiredPath);
28
baseName = baseName.slice(0, baseName.length - ext.length);
29
for (let i = 0; ; ++i) {
30
if (token.isCancellationRequested) {
31
return undefined;
32
}
33
34
const name = i === 0 ? baseName : `${baseName}-${i}`;
35
const uri = vscode.Uri.joinPath(root, name + ext);
36
if (this._wasPathAlreadyUsed(uri)) {
37
continue;
38
}
39
40
// Try overwriting if it already exists
41
if (config.overwriteBehavior === 'overwrite') {
42
this._usedPaths.add(uri.toString());
43
return { uri, overwrite: true };
44
}
45
46
// Otherwise we need to check the fs to see if it exists
47
try {
48
await vscode.workspace.fs.stat(uri);
49
} catch {
50
if (!this._wasPathAlreadyUsed(uri)) {
51
// Does not exist
52
this._usedPaths.add(uri.toString());
53
return { uri, overwrite: false };
54
}
55
}
56
}
57
}
58
59
private _wasPathAlreadyUsed(uri: vscode.Uri) {
60
return this._usedPaths.has(uri.toString());
61
}
62
}
63
64
export function getDesiredNewFilePath(config: CopyFileConfiguration, document: vscode.TextDocument, file: vscode.DataTransferFile): vscode.Uri {
65
const docUri = getParentDocumentUri(document.uri);
66
for (const [rawGlob, rawDest] of Object.entries(config.destination)) {
67
for (const glob of parseGlob(rawGlob)) {
68
if (picomatch.isMatch(docUri.path, glob, { dot: true })) {
69
return resolveCopyDestination(docUri, file.name, rawDest, uri => vscode.workspace.getWorkspaceFolder(uri)?.uri);
70
}
71
}
72
}
73
74
// Default to next to current file
75
return vscode.Uri.joinPath(Utils.dirname(docUri), file.name);
76
}
77
78
79