diff --git a/extensions/git/src/git.ts b/extensions/git/src/git.ts index f30eed26adc44d03f938716f526ba6cbaa372f3f..6f40f62e4a261563be33e021d04bdc1b950874e7 100644 --- a/extensions/git/src/git.ts +++ b/extensions/git/src/git.ts @@ -18,9 +18,11 @@ import { detectEncoding } from './encoding'; import { Ref, RefType, Branch, Remote, GitErrorCodes, LogOptions, Change, Status, CommitOptions } from './api/git'; import * as byline from 'byline'; import { StringDecoder } from 'string_decoder'; +import { promisify } from 'util'; // https://github.com/microsoft/vscode/issues/65693 const MAX_CLI_LENGTH = 30000; +const isWindows = process.platform === 'win32'; export interface IGit { path: string; @@ -419,8 +421,37 @@ export class Git { async getRepositoryRoot(repositoryPath: string): Promise { const result = await this.exec(repositoryPath, ['rev-parse', '--show-toplevel']); + // Keep trailing spaces which are part of the directory name - return path.normalize(result.stdout.trimLeft().replace(/(\r\n|\r|\n)+$/, '')); + const repoPath = path.normalize(result.stdout.trimLeft().replace(/(\r\n|\r|\n)+$/, '')); + + if (isWindows) { + // On Git 2.25+ if you call `rev-parse --show-toplevel` on a mapped drive, instead of getting the mapped drive path back, you get the UNC path for the mapped drive. + // So we will try to normalize it back to the mapped drive path, if possible + const repoUri = Uri.file(repoPath); + const pathUri = Uri.file(repositoryPath); + if (repoUri.authority.length !== 0 && pathUri.authority.length === 0) { + let match = /(?<=^\/?)([a-zA-Z])(?=:\/)/.exec(pathUri.path); + if (match !== null) { + const [, letter] = match; + + try { + const result = await promisify(cp.exec)(`wmic logicaldisk where 'drivetype=4 and deviceid="${letter}:"' get deviceid,providername`); + match = /([A-Z]):\s+(.*?)\s*$/m.exec(result?.stdout.toString() ?? ''); + if (match !== null) { + const [, , networkPath] = match; + return path.normalize( + repoUri.fsPath.replace(networkPath, `${letter.toLowerCase()}:`), + ); + } + } catch { } + } + + return path.normalize(pathUri.fsPath); + } + } + + return repoPath; } async getRepositoryDotGit(repositoryPath: string): Promise {