diff --git a/src/annotations/blameAnnotationProvider.ts b/src/annotations/blameAnnotationProvider.ts index 53fb45d..98866ee 100644 --- a/src/annotations/blameAnnotationProvider.ts +++ b/src/annotations/blameAnnotationProvider.ts @@ -114,7 +114,7 @@ export abstract class BlameAnnotationProviderBase extends AnnotationProviderBase // Get the full commit message -- since blame only returns the summary let logCommit: GitCommit | undefined = undefined; if (!commit.isUncommitted) { - logCommit = await Container.git.getLogCommit(commit.repoPath, commit.uri.fsPath, commit.sha); + logCommit = await Container.git.getLogCommitForFile(commit.repoPath, commit.uri.fsPath, { ref: commit.sha }); if (logCommit !== undefined) { // Preserve the previous commit from the blame commit logCommit.previousFileName = commit.previousFileName; diff --git a/src/annotations/recentChangesAnnotationProvider.ts b/src/annotations/recentChangesAnnotationProvider.ts index f296bbc..b771e5e 100644 --- a/src/annotations/recentChangesAnnotationProvider.ts +++ b/src/annotations/recentChangesAnnotationProvider.ts @@ -25,7 +25,7 @@ export class RecentChangesAnnotationProvider extends AnnotationProviderBase { async onProvideAnnotation(shaOrLine?: string | number): Promise { this.annotationType = FileAnnotationType.RecentChanges; - const commit = await Container.git.getLogCommit(this._uri.repoPath, this._uri.fsPath, { previous: true }); + const commit = await Container.git.getRecentLogCommitForFile(this._uri.repoPath, this._uri.fsPath); if (commit === undefined) return false; const diff = await Container.git.getDiffForFile(this._uri, commit.previousSha); diff --git a/src/commands/copyMessageToClipboard.ts b/src/commands/copyMessageToClipboard.ts index 6fcee6a..40ecf7d 100644 --- a/src/commands/copyMessageToClipboard.ts +++ b/src/commands/copyMessageToClipboard.ts @@ -39,7 +39,7 @@ export class CopyMessageToClipboardCommand extends ActiveEditorCommand { const repoPath = await Container.git.getActiveRepoPath(editor); if (!repoPath) return undefined; - const log = await Container.git.getLogForRepo(repoPath, { maxCount: 1 }); + const log = await Container.git.getLog(repoPath, { maxCount: 1 }); if (!log) return undefined; args.message = Iterables.first(log.commits.values()).message; @@ -74,7 +74,7 @@ export class CopyMessageToClipboardCommand extends ActiveEditorCommand { } // Get the full commit message -- since blame only returns the summary - const commit = await Container.git.getLogCommit(gitUri.repoPath, gitUri.fsPath, args.sha); + const commit = await Container.git.getLogCommit(gitUri.repoPath!, args.sha); if (commit === undefined) return undefined; args.message = commit.message; diff --git a/src/commands/copyShaToClipboard.ts b/src/commands/copyShaToClipboard.ts index 5de5127..cb730f2 100644 --- a/src/commands/copyShaToClipboard.ts +++ b/src/commands/copyShaToClipboard.ts @@ -38,7 +38,7 @@ export class CopyShaToClipboardCommand extends ActiveEditorCommand { const repoPath = await Container.git.getActiveRepoPath(editor); if (!repoPath) return undefined; - const log = await Container.git.getLogForRepo(repoPath, { maxCount: 1 }); + const log = await Container.git.getLog(repoPath, { maxCount: 1 }); if (!log) return undefined; args.sha = Iterables.first(log.commits.values()).sha; diff --git a/src/commands/diffWithWorking.ts b/src/commands/diffWithWorking.ts index 013662f..1e48bb5 100644 --- a/src/commands/diffWithWorking.ts +++ b/src/commands/diffWithWorking.ts @@ -60,7 +60,7 @@ export class DiffWithWorkingCommand extends ActiveEditorCommand { } try { - args.commit = await Container.git.getLogCommit(gitUri.repoPath, gitUri.fsPath, gitUri.sha, { firstIfMissing: true }); + args.commit = await Container.git.getLogCommitForFile(gitUri.repoPath, gitUri.fsPath, { ref: gitUri.sha, firstIfNotFound: true }); if (args.commit === undefined) return Messages.showFileNotUnderSourceControlWarningMessage('Unable to open compare'); } catch (ex) { diff --git a/src/commands/showCommitSearch.ts b/src/commands/showCommitSearch.ts index 5a88a72..b93cd53 100644 --- a/src/commands/showCommitSearch.ts +++ b/src/commands/showCommitSearch.ts @@ -114,7 +114,7 @@ export class ShowCommitSearchCommand extends ActiveEditorCachedCommand { const progressCancellation = CommitsQuickPick.showProgress(searchLabel!); try { - const log = await Container.git.getLogForRepoSearch(repoPath, args.search, args.searchBy, { maxCount: args.maxCount }); + const log = await Container.git.getLogForSearch(repoPath, args.search, args.searchBy, { maxCount: args.maxCount }); if (progressCancellation.token.isCancellationRequested) return undefined; diff --git a/src/commands/showQuickBranchHistory.ts b/src/commands/showQuickBranchHistory.ts index f7fcfe9..659e565 100644 --- a/src/commands/showQuickBranchHistory.ts +++ b/src/commands/showQuickBranchHistory.ts @@ -52,7 +52,7 @@ export class ShowQuickBranchHistoryCommand extends ActiveEditorCachedCommand { } if (args.log === undefined) { - args.log = await Container.git.getLogForRepo(repoPath, { maxCount: args.maxCount, ref: (gitUri && gitUri.sha) || args.branch }); + args.log = await Container.git.getLog(repoPath, { maxCount: args.maxCount, ref: (gitUri && gitUri.sha) || args.branch }); if (args.log === undefined) return window.showWarningMessage(`Unable to show branch history`); } diff --git a/src/commands/showQuickCommitDetails.ts b/src/commands/showQuickCommitDetails.ts index cb38deb..080e372 100644 --- a/src/commands/showQuickCommitDetails.ts +++ b/src/commands/showQuickCommitDetails.ts @@ -92,7 +92,7 @@ export class ShowQuickCommitDetailsCommand extends ActiveEditorCachedCommand { } if (args.repoLog === undefined) { - const log = await Container.git.getLogForRepo(repoPath!, { maxCount: 2, ref: args.sha }); + const log = await Container.git.getLog(repoPath!, { maxCount: 2, ref: args.sha }); if (log === undefined) return Messages.showCommitNotFoundWarningMessage(`Unable to show commit details`); args.commit = log.commits.get(args.sha!); diff --git a/src/commands/showQuickCommitFileDetails.ts b/src/commands/showQuickCommitFileDetails.ts index fdc834f..2482f65 100644 --- a/src/commands/showQuickCommitFileDetails.ts +++ b/src/commands/showQuickCommitFileDetails.ts @@ -94,7 +94,7 @@ export class ShowQuickCommitFileDetailsCommand extends ActiveEditorCachedCommand } if (args.fileLog === undefined) { - args.commit = await Container.git.getLogCommit(args.commit === undefined ? gitUri.repoPath : args.commit.repoPath, gitUri.fsPath, args.sha, { previous: true }); + args.commit = await Container.git.getLogCommitForFile(args.commit === undefined ? gitUri.repoPath : args.commit.repoPath, gitUri.fsPath, { ref: args.sha }); if (args.commit === undefined) return Messages.showCommitNotFoundWarningMessage(`Unable to show commit file details`); } } diff --git a/src/currentLineController.ts b/src/currentLineController.ts index 8024244..02779fd 100644 --- a/src/currentLineController.ts +++ b/src/currentLineController.ts @@ -257,7 +257,7 @@ export class CurrentLineController extends Disposable { // Get the full commit message -- since blame only returns the summary let logCommit = this._lineTracker.state !== undefined ? this._lineTracker.state.logCommit : undefined; if (logCommit === undefined && !commit.isUncommitted) { - logCommit = await Container.git.getLogCommit(commit.repoPath, commit.uri.fsPath, commit.sha); + logCommit = await Container.git.getLogCommitForFile(commit.repoPath, commit.uri.fsPath, { ref: commit.sha }); if (logCommit !== undefined) { // Preserve the previous commit from the blame commit logCommit.previousSha = commit.previousSha; diff --git a/src/gitRevisionCodeLensProvider.ts b/src/gitRevisionCodeLensProvider.ts index dfaa4e2..96b451e 100644 --- a/src/gitRevisionCodeLensProvider.ts +++ b/src/gitRevisionCodeLensProvider.ts @@ -36,7 +36,7 @@ export class GitRevisionCodeLensProvider implements CodeLensProvider { const lenses: CodeLens[] = []; - const commit = await Container.git.getLogCommit(gitUri.repoPath, gitUri.fsPath, gitUri.sha, { firstIfMissing: true, previous: true }); + const commit = await Container.git.getLogCommitForFile(gitUri.repoPath, gitUri.fsPath, { ref: gitUri.sha, firstIfNotFound: true }); if (commit === undefined) return lenses; if (commit.previousSha) { diff --git a/src/gitService.ts b/src/gitService.ts index 23b9602..76002de 100644 --- a/src/gitService.ts +++ b/src/gitService.ts @@ -337,14 +337,14 @@ export class GitService extends Disposable { private async findNextFileNameCore(repoPath: string, fileName: string, sha?: string): Promise { if (sha === undefined) { // Get the most recent commit for this file name - const c = await this.getLogCommit(repoPath, fileName); + const c = await this.getRecentLogCommitForFile(repoPath, fileName); if (c === undefined) return undefined; sha = c.sha; } // Get the full commit (so we can see if there are any matching renames in the file statuses) - const log = await this.getLogForRepo(repoPath, { maxCount: 1, ref: sha }); + const log = await this.getLog(repoPath, { maxCount: 1, ref: sha }); if (log === undefined) return undefined; const c = Iterables.first(log.commits.values()); @@ -819,37 +819,38 @@ export class GitService extends Disposable { } } - async getLogCommit(repoPath: string | undefined, fileName: string, options?: { firstIfMissing?: boolean, previous?: boolean }): Promise; - async getLogCommit(repoPath: string | undefined, fileName: string, sha: string | undefined, options?: { firstIfMissing?: boolean, previous?: boolean }): Promise; - async getLogCommit(repoPath: string | undefined, fileName: string, shaOrOptions?: string | undefined | { firstIfMissing?: boolean, previous?: boolean }, options?: { firstIfMissing?: boolean, previous?: boolean }): Promise { - let sha: string | undefined = undefined; - if (typeof shaOrOptions === 'string') { - sha = shaOrOptions; - } - else if (options === undefined) { - options = shaOrOptions; - } + async getRecentLogCommitForFile(repoPath: string | undefined, fileName: string): Promise { + return this.getLogCommitForFile(repoPath, fileName, undefined); + } + + async getLogCommit(repoPath: string, ref: string): Promise { + Logger.log(`getLogCommit('${repoPath}', '${ref}'`); - options = options || {}; + const log = await this.getLog(repoPath, { maxCount: 2, ref: ref }); + if (log === undefined) return undefined; + + return log.commits.get(ref); + } - Logger.log(`getLogCommit('${repoPath}', '${fileName}', '${sha}', ${options.firstIfMissing}, ${options.previous})`); + async getLogCommitForFile(repoPath: string | undefined, fileName: string, options: { ref?: string, firstIfNotFound?: boolean } = {}): Promise { + Logger.log(`getFileLogCommit('${repoPath}', '${fileName}', '${options.ref}', ${options.firstIfNotFound})`); - const log = await this.getLogForFile(repoPath, fileName, { maxCount: options.previous ? 2 : 1, ref: sha }); + const log = await this.getLogForFile(repoPath, fileName, { maxCount: 2, ref: options.ref }); if (log === undefined) return undefined; - const commit = sha && log.commits.get(sha); - if (commit === undefined && sha && !options.firstIfMissing) { - // If the sha isn't resolved we will never find it, so don't kick out - if (!Git.isResolveRequired(sha)) return undefined; + const commit = options.ref && log.commits.get(options.ref); + if (commit === undefined && !options.firstIfNotFound && options.ref) { + // If the sha isn't resolved we will never find it, so let it fall through so we return the first + if (!Git.isResolveRequired(options.ref)) return undefined; } return commit || Iterables.first(log.commits.values()); } - async getLogForRepo(repoPath: string, options: { maxCount?: number, ref?: string, reverse?: boolean } = {}): Promise { + async getLog(repoPath: string, options: { maxCount?: number, ref?: string, reverse?: boolean } = {}): Promise { options = { reverse: false, ...options }; - Logger.log(`getLogForRepo('${repoPath}', '${options.ref}', ${options.maxCount}, ${options.reverse})`); + Logger.log(`getLog('${repoPath}', '${options.ref}', ${options.maxCount}, ${options.reverse})`); const maxCount = options.maxCount == null ? Container.config.advanced.maxListItems || 0 @@ -861,7 +862,7 @@ export class GitService extends Disposable { if (log !== undefined) { const opts = { ...options }; - log.query = (maxCount: number | undefined) => this.getLogForRepo(repoPath, { ...opts, maxCount: maxCount }); + log.query = (maxCount: number | undefined) => this.getLog(repoPath, { ...opts, maxCount: maxCount }); } return log; @@ -871,8 +872,8 @@ export class GitService extends Disposable { } } - async getLogForRepoSearch(repoPath: string, search: string, searchBy: GitRepoSearchBy, options: { maxCount?: number } = {}): Promise { - Logger.log(`getLogForRepoSearch('${repoPath}', '${search}', '${searchBy}', ${options.maxCount})`); + async getLogForSearch(repoPath: string, search: string, searchBy: GitRepoSearchBy, options: { maxCount?: number } = {}): Promise { + Logger.log(`getLogForSearch('${repoPath}', '${search}', '${searchBy}', ${options.maxCount})`); let maxCount = options.maxCount == null ? Container.config.advanced.maxListItems || 0 @@ -907,7 +908,7 @@ export class GitService extends Disposable { if (log !== undefined) { const opts = { ...options }; - log.query = (maxCount: number | undefined) => this.getLogForRepoSearch(repoPath, search, searchBy, { ...opts, maxCount: maxCount }); + log.query = (maxCount: number | undefined) => this.getLogForSearch(repoPath, search, searchBy, { ...opts, maxCount: maxCount }); } return log; @@ -918,6 +919,8 @@ export class GitService extends Disposable { } async getLogForFile(repoPath: string | undefined, fileName: string, options: { maxCount?: number, range?: Range, ref?: string, reverse?: boolean, skipMerges?: boolean } = {}): Promise { + if (repoPath !== undefined && repoPath === Strings.normalizePath(fileName)) throw new Error(`File name cannot match the repository path; fileName=${fileName}`); + options = { reverse: false, skipMerges: false, ...options }; let key = 'log'; diff --git a/src/quickPicks/commitDetails.ts b/src/quickPicks/commitDetails.ts index 63f2fca..27422ee 100644 --- a/src/quickPicks/commitDetails.ts +++ b/src/quickPicks/commitDetails.ts @@ -241,7 +241,7 @@ export class CommitDetailsQuickPick { // If we can't find the commit or the previous commit isn't available (since it isn't trustworthy) if (c === undefined || c.previousSha === undefined) { - log = await Container.git.getLogForRepo(commit.repoPath, { maxCount: Container.config.advanced.maxListItems, ref: commit.sha }); + log = await Container.git.getLog(commit.repoPath, { maxCount: Container.config.advanced.maxListItems, ref: commit.sha }); c = log && log.commits.get(commit.sha); if (c) { @@ -272,7 +272,7 @@ export class CommitDetailsQuickPick { c = undefined; // Try to find the next commit - const nextLog = await Container.git.getLogForRepo(commit.repoPath, { maxCount: 1, reverse: true, ref: commit.sha }); + const nextLog = await Container.git.getLog(commit.repoPath, { maxCount: 1, reverse: true, ref: commit.sha }); const next = nextLog && Iterables.first(nextLog.commits.values()); if (next !== undefined && next.sha !== commit.sha) { c = commit; diff --git a/src/quickPicks/commitFileDetails.ts b/src/quickPicks/commitFileDetails.ts index d0aca29..2003069 100644 --- a/src/quickPicks/commitFileDetails.ts +++ b/src/quickPicks/commitFileDetails.ts @@ -77,7 +77,7 @@ export class CommitFileDetailsQuickPick { const isUncommitted = commit.isUncommitted; if (isUncommitted) { // Since we can't trust the previous sha on an uncommitted commit, find the last commit for this file - const c = await Container.git.getLogCommit(undefined, commit.uri.fsPath, { previous: true }); + const c = await Container.git.getRecentLogCommitForFile(undefined, commit.uri.fsPath); if (c === undefined) return undefined; commit = c; diff --git a/src/views/branchNode.ts b/src/views/branchNode.ts index fda892a..1b113e0 100644 --- a/src/views/branchNode.ts +++ b/src/views/branchNode.ts @@ -24,7 +24,7 @@ export class BranchNode extends ExplorerRefNode { } async getChildren(): Promise { - const log = await Container.git.getLogForRepo(this.uri.repoPath!, { maxCount: this.maxCount, ref: this.branch.name }); + const log = await Container.git.getLog(this.uri.repoPath!, { maxCount: this.maxCount, ref: this.branch.name }); if (log === undefined) return [new MessageNode('No commits yet')]; const children: (CommitNode | ShowAllNode)[] = [...Iterables.map(log.commits.values(), c => new CommitNode(c, this.explorer, this.branch))]; diff --git a/src/views/comparisionResultsNode.ts b/src/views/comparisionResultsNode.ts index b3377d6..6da4e0f 100644 --- a/src/views/comparisionResultsNode.ts +++ b/src/views/comparisionResultsNode.ts @@ -22,7 +22,7 @@ export class ComparisionResultsNode extends ExplorerNode { async getChildren(): Promise { this.resetChildren(); - const commitsQueryFn = (maxCount: number | undefined) => Container.git.getLogForRepo(this.uri.repoPath!, { maxCount: maxCount, ref: `${this.ref1}...${this.ref2 || 'HEAD'}` }); + const commitsQueryFn = (maxCount: number | undefined) => Container.git.getLog(this.uri.repoPath!, { maxCount: maxCount, ref: `${this.ref1}...${this.ref2 || 'HEAD'}` }); const commitsLabelFn = (log: GitLog | undefined) => { const count = log !== undefined ? log.count : 0; const truncated = log !== undefined ? log.truncated : false; diff --git a/src/views/stashNode.ts b/src/views/stashNode.ts index 4e3c286..19a39a5 100644 --- a/src/views/stashNode.ts +++ b/src/views/stashNode.ts @@ -23,7 +23,7 @@ export class StashNode extends ExplorerRefNode { const statuses = (this.commit as GitStashCommit).fileStatuses; // Check for any untracked files -- since git doesn't return them via `git stash list` :( - const log = await Container.git.getLogForRepo(this.commit.repoPath, { maxCount: 1, ref: `${(this.commit as GitStashCommit).stashName}^3` }); + const log = await Container.git.getLog(this.commit.repoPath, { maxCount: 1, ref: `${(this.commit as GitStashCommit).stashName}^3` }); if (log !== undefined) { const commit = Iterables.first(log.commits.values()); if (commit !== undefined && commit.fileStatuses.length !== 0) { diff --git a/src/views/statusFilesNode.ts b/src/views/statusFilesNode.ts index 6e4bcd5..6223b38 100644 --- a/src/views/statusFilesNode.ts +++ b/src/views/statusFilesNode.ts @@ -31,7 +31,7 @@ export class StatusFilesNode extends ExplorerNode { let log: GitLog | undefined; if (this.range !== undefined) { - log = await Container.git.getLogForRepo(repoPath, { maxCount: this.maxCount, ref: this.range }); + log = await Container.git.getLog(repoPath, { maxCount: this.maxCount, ref: this.range }); if (log !== undefined) { statuses = Array.from(Iterables.flatMap(log.commits.values(), c => { return c.fileStatuses.map(s => { diff --git a/src/views/statusUpstreamNode.ts b/src/views/statusUpstreamNode.ts index cac90f5..d620329 100644 --- a/src/views/statusUpstreamNode.ts +++ b/src/views/statusUpstreamNode.ts @@ -21,7 +21,7 @@ export class StatusUpstreamNode extends ExplorerNode { ? `${this.status.upstream}..${this.status.branch}` : `${this.status.branch}..${this.status.upstream}`; - let log = await Container.git.getLogForRepo(this.uri.repoPath!, { maxCount: 0, ref: range }); + let log = await Container.git.getLog(this.uri.repoPath!, { maxCount: 0, ref: range }); if (log === undefined) return []; if (this.direction !== 'ahead') return [...Iterables.map(log.commits.values(), c => new CommitNode(c, this.explorer))]; @@ -30,7 +30,7 @@ export class StatusUpstreamNode extends ExplorerNode { const commits = Array.from(log.commits.values()); const commit = commits[commits.length - 1]; if (commit.previousSha === undefined) { - log = await Container.git.getLogForRepo(this.uri.repoPath!, { maxCount: 2, ref: commit.sha }); + log = await Container.git.getLog(this.uri.repoPath!, { maxCount: 2, ref: commit.sha }); if (log !== undefined) { commits[commits.length - 1] = Iterables.first(log.commits.values()); } diff --git a/src/views/tagNode.ts b/src/views/tagNode.ts index 85faefc..e0081f1 100644 --- a/src/views/tagNode.ts +++ b/src/views/tagNode.ts @@ -23,7 +23,7 @@ export class TagNode extends ExplorerRefNode { } async getChildren(): Promise { - const log = await Container.git.getLogForRepo(this.uri.repoPath!, { maxCount: this.maxCount, ref: this.tag.name }); + const log = await Container.git.getLog(this.uri.repoPath!, { maxCount: this.maxCount, ref: this.tag.name }); if (log === undefined) return [new MessageNode('No commits yet')]; const children: (CommitNode | ShowAllNode)[] = [...Iterables.map(log.commits.values(), c => new CommitNode(c, this.explorer))];