Path: blob/main/extensions/markdown-language-features/src/languageFeatures/copyFiles/newFilePathGenerator.ts
3294 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import * as picomatch from 'picomatch';6import * as vscode from 'vscode';7import { Utils } from 'vscode-uri';8import { getParentDocumentUri } from '../../util/document';9import { CopyFileConfiguration, getCopyFileConfiguration, parseGlob, resolveCopyDestination } from './copyFiles';101112export class NewFilePathGenerator {1314private readonly _usedPaths = new Set<string>();1516async getNewFilePath(17document: vscode.TextDocument,18file: vscode.DataTransferFile,19token: vscode.CancellationToken20): Promise<{ readonly uri: vscode.Uri; readonly overwrite: boolean } | undefined> {21const config = getCopyFileConfiguration(document);22const desiredPath = getDesiredNewFilePath(config, document, file);2324const root = Utils.dirname(desiredPath);25const ext = Utils.extname(desiredPath);26let baseName = Utils.basename(desiredPath);27baseName = baseName.slice(0, baseName.length - ext.length);28for (let i = 0; ; ++i) {29if (token.isCancellationRequested) {30return undefined;31}3233const name = i === 0 ? baseName : `${baseName}-${i}`;34const uri = vscode.Uri.joinPath(root, name + ext);35if (this._wasPathAlreadyUsed(uri)) {36continue;37}3839// Try overwriting if it already exists40if (config.overwriteBehavior === 'overwrite') {41this._usedPaths.add(uri.toString());42return { uri, overwrite: true };43}4445// Otherwise we need to check the fs to see if it exists46try {47await vscode.workspace.fs.stat(uri);48} catch {49if (!this._wasPathAlreadyUsed(uri)) {50// Does not exist51this._usedPaths.add(uri.toString());52return { uri, overwrite: false };53}54}55}56}5758private _wasPathAlreadyUsed(uri: vscode.Uri) {59return this._usedPaths.has(uri.toString());60}61}6263export function getDesiredNewFilePath(config: CopyFileConfiguration, document: vscode.TextDocument, file: vscode.DataTransferFile): vscode.Uri {64const docUri = getParentDocumentUri(document.uri);65for (const [rawGlob, rawDest] of Object.entries(config.destination)) {66for (const glob of parseGlob(rawGlob)) {67if (picomatch.isMatch(docUri.path, glob, { dot: true })) {68return resolveCopyDestination(docUri, file.name, rawDest, uri => vscode.workspace.getWorkspaceFolder(uri)?.uri);69}70}71}7273// Default to next to current file74return vscode.Uri.joinPath(Utils.dirname(docUri), file.name);75}76777879