diff --git a/src/commands/diffWithWorking.ts b/src/commands/diffWithWorking.ts index 1e48bb5..4ea7e66 100644 --- a/src/commands/diffWithWorking.ts +++ b/src/commands/diffWithWorking.ts @@ -69,7 +69,7 @@ export class DiffWithWorkingCommand extends ActiveEditorCommand { } } - const workingFileName = await Container.git.findWorkingFileName(gitUri.repoPath, gitUri.fsPath); + const [workingFileName] = await Container.git.findWorkingFileName(gitUri.fsPath, gitUri.repoPath); if (workingFileName === undefined) return undefined; const diffArgs: DiffWithCommandArgs = { diff --git a/src/commands/showQuickCommitFileDetails.ts b/src/commands/showQuickCommitFileDetails.ts index 2482f65..3df0385 100644 --- a/src/commands/showQuickCommitFileDetails.ts +++ b/src/commands/showQuickCommitFileDetails.ts @@ -103,7 +103,7 @@ export class ShowQuickCommitFileDetailsCommand extends ActiveEditorCachedCommand // Attempt to the most recent commit -- so that we can find the real working filename if there was a rename args.commit.workingFileName = workingFileName; - args.commit.workingFileName = await Container.git.findWorkingFileName(args.commit); + [args.commit.workingFileName] = await Container.git.findWorkingFileName(args.commit); const shortSha = GitService.shortenSha(args.sha!); diff --git a/src/git/git.ts b/src/git/git.ts index 8ab5796..138871a 100644 --- a/src/git/git.ts +++ b/src/git/git.ts @@ -407,6 +407,16 @@ export class Git { return gitCommand({ cwd: root }, ...params); } + static async log_recent(repoPath: string, fileName: string) { + try { + const data = await gitCommandCore({ cwd: repoPath }, 'log', '--full-history', '-M', '-n1', '--format=%H', '--', fileName); + return data.trim(); + } + catch { + return undefined; + } + } + static async log_resolve(repoPath: string, fileName: string, ref: string) { try { const data = await gitCommandCore({ cwd: repoPath }, 'log', '--full-history', '-M', '-n1', '--format=%H', ref, '--', fileName); diff --git a/src/gitService.ts b/src/gitService.ts index 004c88b..9abd8c8 100644 --- a/src/gitService.ts +++ b/src/gitService.ts @@ -334,17 +334,15 @@ export class GitService extends Disposable { : await this.findNextFileNameCore(repoPath, fileName, ref); } - private async findNextFileNameCore(repoPath: string, fileName: string, sha?: string): Promise { - if (sha === undefined) { + private async findNextFileNameCore(repoPath: string, fileName: string, ref?: string): Promise { + if (ref === undefined) { // Get the most recent commit for this file name - const c = await this.getRecentLogCommitForFile(repoPath, fileName); - if (c === undefined) return undefined; - - sha = c.sha; + ref = await this.getRecentShaForFile(repoPath, fileName); + if (ref === undefined) return undefined; } // Get the full commit (so we can see if there are any matching renames in the file statuses) - const log = await this.getLog(repoPath, { maxCount: 1, ref: sha }); + const log = await this.getLog(repoPath, { maxCount: 1, ref: ref }); if (log === undefined) return undefined; const c = Iterables.first(log.commits.values()); @@ -354,28 +352,31 @@ export class GitService extends Disposable { return status.fileName; } - async findWorkingFileName(commit: GitCommit): Promise; - async findWorkingFileName(repoPath: string | undefined, fileName: string): Promise; - async findWorkingFileName(commitOrRepoPath: GitCommit | string | undefined, fileName?: string): Promise { - let repoPath: string | undefined; - if (commitOrRepoPath === undefined || typeof commitOrRepoPath === 'string') { - repoPath = commitOrRepoPath; - if (fileName === undefined) throw new Error('Invalid fileName'); + async findWorkingFileName(commit: GitCommit): Promise<[string | undefined, string | undefined]>; + async findWorkingFileName(fileName: string, repoPath?: string, ref?: string): Promise<[string | undefined, string | undefined]>; + async findWorkingFileName(commitOrFileName: GitCommit | string, repoPath?: string, ref?: string): Promise<[string | undefined, string | undefined]> { + let fileName; + if (typeof commitOrFileName === 'string') { + fileName = commitOrFileName; + if (repoPath === undefined) { + repoPath = await this.getRepoPath(fileName, { ref: ref }); + [fileName, repoPath] = Git.splitPath(fileName, repoPath); + } - [fileName] = Git.splitPath(fileName, repoPath); } else { - const c = commitOrRepoPath; + const c = commitOrFileName; repoPath = c.repoPath; - if (c.workingFileName && await this.fileExists(repoPath, c.workingFileName)) return c.workingFileName; + if (c.workingFileName && await this.fileExists(repoPath, c.workingFileName)) return [c.workingFileName, repoPath]; fileName = c.fileName; } + // Keep walking up to the most recent commit for a given filename, until it exists on disk while (true) { - if (await this.fileExists(repoPath!, fileName)) return fileName; + if (await this.fileExists(repoPath, fileName)) return [fileName, repoPath]; - fileName = await this.findNextFileNameCore(repoPath!, fileName); - if (fileName === undefined) return undefined; + fileName = await this.findNextFileNameCore(repoPath, fileName); + if (fileName === undefined) return [undefined, undefined]; } } @@ -823,6 +824,10 @@ export class GitService extends Disposable { return this.getLogCommitForFile(repoPath, fileName, undefined); } + async getRecentShaForFile(repoPath: string, fileName: string) { + return await Git.log_recent(repoPath, fileName); + } + async getLogCommit(repoPath: string, ref: string): Promise { Logger.log(`getLogCommit('${repoPath}', '${ref}'`); diff --git a/src/quickPicks/fileHistory.ts b/src/quickPicks/fileHistory.ts index 941b737..98104aa 100644 --- a/src/quickPicks/fileHistory.ts +++ b/src/quickPicks/fileHistory.ts @@ -44,7 +44,7 @@ export class FileHistoryQuickPick { items.splice(0, 0, options.showAllCommand); } else if (!options.pickerOnly) { - const workingFileName = await Container.git.findWorkingFileName(log.repoPath, path.relative(log.repoPath, uri.fsPath)); + const [workingFileName] = await Container.git.findWorkingFileName(path.relative(log.repoPath, uri.fsPath), log.repoPath); if (workingFileName) { index++; items.splice(0, 0, new CommandQuickPickItem({