diff --git a/src/blameActiveLineController.ts b/src/blameActiveLineController.ts index 54feebc..dc6e9b4 100644 --- a/src/blameActiveLineController.ts +++ b/src/blameActiveLineController.ts @@ -298,8 +298,7 @@ export class BlameActiveLineController extends Disposable { // Get the full commit message -- since blame only returns the summary let logCommit: GitCommit; if (!commit.isUncommitted) { - const log = await this.git.getLogForFile(this._uri.repoPath, this._uri.fsPath, commit.sha, undefined, 1); - logCommit = log && log.commits.get(commit.sha); + logCommit = await this.git.getLogCommit(this._uri.repoPath, this._uri.fsPath, commit.sha); } // I have no idea why I need this protection -- but it happens diff --git a/src/commands/copyMessageToClipboard.ts b/src/commands/copyMessageToClipboard.ts index 8b06e2a..df97761 100644 --- a/src/commands/copyMessageToClipboard.ts +++ b/src/commands/copyMessageToClipboard.ts @@ -56,10 +56,7 @@ export class CopyMessageToClipboardCommand extends ActiveEditorCommand { } // Get the full commit message -- since blame only returns the summary - const log = await this.git.getLogForFile(gitUri.repoPath, gitUri.fsPath, sha, undefined, 1); - if (!log) return undefined; - - const commit = log.commits.get(sha); + const commit = await this.git.getLogCommit(gitUri.repoPath, gitUri.fsPath, sha); if (!commit) return undefined; message = commit.message; diff --git a/src/commands/diffWithWorking.ts b/src/commands/diffWithWorking.ts index 84e3ff0..4269343 100644 --- a/src/commands/diffWithWorking.ts +++ b/src/commands/diffWithWorking.ts @@ -1,5 +1,5 @@ 'use strict'; -import { Iterables } from '../system'; +// import { Iterables } from '../system'; import { commands, TextEditor, Uri, window } from 'vscode'; import { ActiveEditorCommand, Commands } from './commands'; import { BuiltInCommands } from '../constants'; @@ -27,13 +27,11 @@ export class DiffWithWorkingCommand extends ActiveEditorCommand { const gitUri = await GitUri.fromUri(uri, this.git); try { - const log = await this.git.getLogForFile(gitUri.repoPath, gitUri.fsPath, gitUri.sha, undefined, gitUri.sha ? undefined : 1); - if (!log) return window.showWarningMessage(`Unable to open diff. File is probably not under source control`); - - commit = (gitUri.sha && log.commits.get(gitUri.sha)) || Iterables.first(log.commits.values()); + commit = await this.git.getLogCommit(gitUri.repoPath, gitUri.fsPath, gitUri.sha, { firstIfMissing: true }); + if (!commit) return window.showWarningMessage(`Unable to open diff. File is probably not under source control`); } catch (ex) { - Logger.error('[GitLens.DiffWithWorkingCommand]', `getLogForFile(${gitUri.repoPath}, ${gitUri.fsPath})`, ex); + Logger.error('[GitLens.DiffWithWorkingCommand]', `getLogCommit(${gitUri.repoPath}, ${gitUri.fsPath}, ${gitUri.sha})`, ex); return window.showErrorMessage(`Unable to open diff. See output channel for more details`); } } diff --git a/src/commands/showQuickCommitFileDetails.ts b/src/commands/showQuickCommitFileDetails.ts index 4aef886..d30bfcf 100644 --- a/src/commands/showQuickCommitFileDetails.ts +++ b/src/commands/showQuickCommitFileDetails.ts @@ -54,10 +54,8 @@ export class ShowQuickCommitFileDetailsCommand extends ActiveEditorCachedCommand } if (!fileLog) { - const log = await this.git.getLogForFile(commit ? commit.repoPath : gitUri.repoPath, commit ? commit.uri.fsPath : gitUri.fsPath, sha, undefined, 2); - if (!log) return window.showWarningMessage(`Unable to show commit file details`); - - commit = log.commits.get(sha); + commit = await this.git.getLogCommit(commit ? commit.repoPath : gitUri.repoPath, commit ? commit.uri.fsPath : gitUri.fsPath, sha, { previous: true }); + if (!commit) return window.showWarningMessage(`Unable to show commit file details`); } } diff --git a/src/git/gitUri.ts b/src/git/gitUri.ts index 9a5929d..903c245 100644 --- a/src/git/gitUri.ts +++ b/src/git/gitUri.ts @@ -1,5 +1,4 @@ 'use strict'; -import { Iterables } from '../system'; import { Uri } from 'vscode'; import { DocumentSchemes } from '../constants'; import { Git, GitService } from '../gitService'; @@ -83,8 +82,7 @@ export class GitUri extends Uri { // If this is a git uri, assume it is showing the most recent commit if (uri.scheme === 'git' && uri.query === '~') { - const log = await git.getLogForFile(undefined, uri.fsPath, undefined, undefined, 1); - const commit = log && Iterables.first(log.commits.values()); + const commit = await git.getLogCommit(undefined, uri.fsPath); if (commit) return new GitUri(uri, commit); } diff --git a/src/gitRevisionCodeLensProvider.ts b/src/gitRevisionCodeLensProvider.ts index 7decb99..5989c6e 100644 --- a/src/gitRevisionCodeLensProvider.ts +++ b/src/gitRevisionCodeLensProvider.ts @@ -1,5 +1,5 @@ 'use strict'; -import { Iterables } from './system'; +// import { Iterables } from './system'; import { CancellationToken, CodeLens, CodeLensProvider, DocumentSelector, ExtensionContext, Range, TextDocument, Uri } from 'vscode'; import { Commands } from './commands'; import { DocumentSchemes } from './constants'; @@ -31,10 +31,7 @@ export class GitRevisionCodeLensProvider implements CodeLensProvider { const lenses: CodeLens[] = []; - const log = await this.git.getLogForFile(gitUri.repoPath, gitUri.fsPath, gitUri.sha, undefined, 2); - if (!log) return lenses; - - const commit = (gitUri.sha && log.commits.get(gitUri.sha)) || Iterables.first(log.commits.values()); + const commit = await this.git.getLogCommit(gitUri.repoPath, gitUri.fsPath, gitUri.sha, { firstIfMissing: true, previous: true }); if (!commit) return lenses; lenses.push(new GitDiffWithWorkingCodeLens(this.git, commit.uri.fsPath, commit, new Range(0, 0, 0, 1))); diff --git a/src/gitService.ts b/src/gitService.ts index 72840ae..43a2748 100644 --- a/src/gitService.ts +++ b/src/gitService.ts @@ -4,7 +4,7 @@ import { Disposable, Event, EventEmitter, ExtensionContext, FileSystemWatcher, l import { CommandContext, setCommandContext } from './commands'; import { CodeLensVisibility, IConfig } from './configuration'; import { DocumentSchemes, WorkspaceState } from './constants'; -import { Git, GitBlameParser, GitBranch, GitCommit, GitLogParser, GitRemote, GitStatusFile, GitStatusParser, IGitAuthor, IGitBlame, IGitBlameLine, IGitBlameLines, IGitLog, IGitStatus } from './git/git'; +import { Git, GitBlameParser, GitBranch, GitCommit, GitLogCommit, GitLogParser, GitRemote, GitStatusFile, GitStatusParser, IGitAuthor, IGitBlame, IGitBlameLine, IGitBlameLines, IGitLog, IGitStatus } from './git/git'; import { IGitUriData, GitUri } from './git/gitUri'; import { GitCodeLensProvider } from './gitCodeLensProvider'; import { Logger } from './logger'; @@ -243,13 +243,11 @@ export class GitService extends Disposable { if (await this._fileExists(repoPath, fileName)) return fileName; // Get the most recent commit for this file name - let log = await this.getLogForFile(repoPath, fileName, undefined, undefined, 1); - if (!log) return undefined; - - let c = Iterables.first(log.commits.values()); + let c = await this.getLogCommit(repoPath, fileName); + if (!c) return undefined; // Get the full commit (so we can see if there are any matching renames in the file statuses) - log = await this.getLogForRepo(repoPath, c.sha, 1); + let log = await this.getLogForRepo(repoPath, c.sha, 1); if (!log) return undefined; c = Iterables.first(log.commits.values()); @@ -500,6 +498,28 @@ export class GitService extends Disposable { } } + async getLogCommit(repoPath: string, fileName: string, options?: { firstIfMissing?: boolean, previous?: boolean }): Promise; + async getLogCommit(repoPath: string, fileName: string, sha: string, options?: { firstIfMissing?: boolean, previous?: boolean }): Promise; + async getLogCommit(repoPath: string, fileName: string, shaOrOptions?: string | { firstIfMissing?: boolean, previous?: boolean }, options?: { firstIfMissing?: boolean, previous?: boolean }): Promise { + let sha: string; + if (typeof shaOrOptions === 'string') { + sha = shaOrOptions; + } + else if (!options) { + options = shaOrOptions; + } + + options = options || {}; + + const log = await this.getLogForFile(repoPath, fileName, sha, undefined, options.previous ? 2 : 1); + if (!log) return undefined; + + const commit = sha && log.commits.get(sha); + if (!commit && !options.firstIfMissing) return undefined; + + return commit || Iterables.first(log.commits.values()); + } + getLogForFile(repoPath: string, fileName: string, sha?: string, range?: Range, maxCount?: number, reverse: boolean = false): Promise { Logger.log(`getLogForFile('${repoPath}', '${fileName}', ${sha}, ${range && `[${range.start.line}, ${range.end.line}]`}, ${maxCount}, ${reverse})`); diff --git a/src/quickPicks/commitFileDetails.ts b/src/quickPicks/commitFileDetails.ts index 543e514..c6b64ac 100644 --- a/src/quickPicks/commitFileDetails.ts +++ b/src/quickPicks/commitFileDetails.ts @@ -39,10 +39,8 @@ 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 log = await git.getLogForFile(undefined, commit.uri.fsPath, undefined, undefined, 2); - if (!log) return undefined; - - commit = Iterables.first(log.commits.values()); + commit = await git.getLogCommit(undefined, commit.uri.fsPath, { previous: true }); + if (!commit) return undefined; } items.push(new CommandQuickPickItem({ @@ -141,7 +139,7 @@ export class CommitFileDetailsQuickPick { c = undefined; // Try to find the next commit - const nextLog = await git.getLogForFile(commit.repoPath, uri.fsPath, commit.sha, undefined, 1, true); + const nextLog = await git.getLogForFile(commit.repoPath, uri.fsPath, commit.sha, undefined, 1, true, true); const next = nextLog && Iterables.first(nextLog.commits.values()); if (next && next.sha !== commit.sha) { c = commit;