From e12ec7093c53aa768e27c8ba3b909831b707bec0 Mon Sep 17 00:00:00 2001 From: Eric Amodio Date: Fri, 10 Feb 2017 04:09:00 -0500 Subject: [PATCH] Adds new command to show quick commit info --- package.json | 10 +++ src/commands/quickPickItems.ts | 2 + src/commands/showQuickCommitDetails.ts | 112 +++++++++++++++++++++++++++++++++ src/commands/showQuickRepoHistory.ts | 5 +- src/constants.ts | 3 +- src/extension.ts | 2 + src/git/git.ts | 9 ++- src/gitProvider.ts | 4 +- 8 files changed, 139 insertions(+), 8 deletions(-) create mode 100644 src/commands/showQuickCommitDetails.ts diff --git a/package.json b/package.json index cf7a3f1..19da56b 100644 --- a/package.json +++ b/package.json @@ -342,6 +342,11 @@ "category": "GitLens" }, { + "command": "gitlens.showQuickCommitDetails", + "title": "Show Commit Details", + "category": "GitLens" + }, + { "command": "gitlens.showQuickFileHistory", "title": "Show File History", "category": "GitLens" @@ -451,6 +456,11 @@ "mac": "shift+alt+h" }, { + "command": "gitlens.showQuickCommitDetails", + "key": "alt+c", + "mac": "alt+c" + }, + { "command": "gitlens.diffLineWithPrevious", "key": "alt+p", "mac": "alt+p", diff --git a/src/commands/quickPickItems.ts b/src/commands/quickPickItems.ts index c13b77f..2e4027e 100644 --- a/src/commands/quickPickItems.ts +++ b/src/commands/quickPickItems.ts @@ -31,10 +31,12 @@ export class FileQuickPickItem implements QuickPickItem { label: string; description: string; detail: string; + sha: string; uri: GitUri; constructor(commit: GitCommit, public fileName: string) { this.label = fileName; + this.sha = commit.sha; this.uri = GitUri.fromUri(Uri.file(path.resolve(commit.repoPath, fileName))); } } diff --git a/src/commands/showQuickCommitDetails.ts b/src/commands/showQuickCommitDetails.ts new file mode 100644 index 0000000..2bef041 --- /dev/null +++ b/src/commands/showQuickCommitDetails.ts @@ -0,0 +1,112 @@ +'use strict'; +import { Iterables } from '../system'; +import { commands, QuickPickOptions, TextEditor, TextEditorEdit, Uri, window } from 'vscode'; +import { EditorCommand } from './commands'; +import { Commands } from '../constants'; +import GitProvider, { GitUri } from '../gitProvider'; +import { Logger } from '../logger'; +import { BackQuickPickItem, CommitQuickPickItem, CompareQuickPickItem, FileQuickPickItem } from './quickPickItems'; +import * as moment from 'moment'; + +export default class ShowQuickCommitDetailsCommand extends EditorCommand { + + constructor(private git: GitProvider) { + super(Commands.ShowQuickCommitDetails); + } + + async execute(editor: TextEditor, edit: TextEditorEdit, uri?: Uri, sha?: string) { + if (!(uri instanceof Uri)) { + if (!editor.document) return undefined; + uri = editor.document.uri; + } + + const gitUri = GitUri.fromUri(uri, this.git); + + let repoPath = gitUri.repoPath; + + let line = editor.selection.active.line; + if (!sha) { + const blameline = line - gitUri.offset; + if (blameline < 0) return undefined; + + try { + const blame = await this.git.getBlameForLine(gitUri.fsPath, blameline, gitUri.sha, gitUri.repoPath); + if (!blame) return window.showWarningMessage(`Unable to show commit details. File is probably not under source control`); + + sha = blame.commit.isUncommitted ? blame.commit.previousSha : blame.commit.sha; + repoPath = blame.commit.repoPath; + } + catch (ex) { + Logger.error('[GitLens.ShowQuickCommitDetails]', `getBlameForLine(${blameline})`, ex); + return window.showErrorMessage(`Unable to show commit details. See output channel for more details`); + } + } + + try { + const log = await this.git.getLogForRepo(repoPath, sha, 0); + if (!log) return window.showWarningMessage(`Unable to show commit details`); + + const commit = Iterables.first(log.commits.values()); + const commitPick = new CommitQuickPickItem(commit, ` \u2014 ${commit.fileName}`); + const files = commitPick.commit.fileName + .split(', ') + .filter(_ => !!_) + .map(f => new FileQuickPickItem(commitPick.commit, f)); + + const filePick = await window.showQuickPick(files, { + matchOnDescription: true, + matchOnDetail: true, + placeHolder: `${commitPick.commit.sha} \u2022 ${commitPick.commit.author}, ${moment(commitPick.commit.date).fromNow()}` + } as QuickPickOptions); + + if (filePick) { + // TODO need to make log for file -- go from commit to HEAD so we can get the current filename + const log = await this.git.getLogForFile(filePick.uri.fsPath, filePick.sha); + if (!log) return window.showWarningMessage(`Unable to open diff`); + + const commit = Iterables.find(log.commits.values(), c => c.sha === commitPick.commit.sha); + + let command: Commands | undefined = Commands.DiffWithWorking; + const items: CompareQuickPickItem[] = [ + { + label: `Compare with Working Tree`, + description: `\u2022 ${commit.sha} $(git-compare) ${commit.fileName}`, + command: Commands.DiffWithWorking + } + ]; + + if (commit.previousSha) { + items.push({ + label: `Compare with Previous Commit`, + description: `\u2022 ${commit.previousSha} $(git-compare) ${commit.sha}`, + command: Commands.DiffWithPrevious + }); + } + + items.push({ + label: `go back \u21A9`, + description: null, + command: Commands.ShowQuickCommitDetails + } as BackQuickPickItem); + + const comparePick = await window.showQuickPick(items, { + matchOnDescription: true, + placeHolder: `${commit.fileName} \u2022 ${commit.sha} \u2022 ${commit.author}, ${moment(commit.date).fromNow()}` + } as QuickPickOptions); + + command = comparePick ? comparePick.command : undefined; + + if (command) { + if (command === Commands.ShowQuickCommitDetails) return commands.executeCommand(command, uri), sha; + return commands.executeCommand(command, commit.uri, commit); + } + } + + return undefined; + } + catch (ex) { + Logger.error('[GitLens.ShowQuickCommitDetailsCommand]', ex); + return window.showErrorMessage(`Unable to show commit details. See output channel for more details`); + } + } +} \ No newline at end of file diff --git a/src/commands/showQuickRepoHistory.ts b/src/commands/showQuickRepoHistory.ts index ddcc750..a3cec8c 100644 --- a/src/commands/showQuickRepoHistory.ts +++ b/src/commands/showQuickRepoHistory.ts @@ -43,7 +43,7 @@ export default class ShowQuickRepoHistoryCommand extends Command { if (!repoPath) return window.showWarningMessage(`Unable to show repository history`); - const log = await this.git.getLogForRepo(repoPath, maxCount); + const log = await this.git.getLogForRepo(repoPath, undefined, maxCount); if (!log) return window.showWarningMessage(`Unable to show repository history`); const commits = Array.from(Iterables.map(log.commits.values(), c => new CommitQuickPickItem(c, ` \u2014 ${c.fileName}`))) as QuickPickItem[]; @@ -93,7 +93,8 @@ export default class ShowQuickRepoHistoryCommand extends Command { const filePick = pick as FileQuickPickItem; if (filePick) { - const log = await this.git.getLogForFile(filePick.uri.fsPath); + // TODO need to make log for file -- go from commit to HEAD so we can get the current filename + const log = await this.git.getLogForFile(filePick.uri.fsPath, filePick.sha); if (!log) return window.showWarningMessage(`Unable to open diff`); const commit = Iterables.find(log.commits.values(), c => c.sha === commitPick.commit.sha); diff --git a/src/constants.ts b/src/constants.ts index d5208fa..52eeb51 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -14,7 +14,7 @@ export const BuiltInCommands = { ToggleRenderWhitespace: 'editor.action.toggleRenderWhitespace' as BuiltInCommands }; -export type Commands = 'gitlens.diffWithPrevious' | 'gitlens.diffLineWithPrevious' | 'gitlens.diffWithWorking' | 'gitlens.diffLineWithWorking' | 'gitlens.showBlame' | 'gitlens.showBlameHistory' | 'gitlens.showFileHistory' | 'gitlens.showQuickFileHistory' | 'gitlens.showQuickRepoHistory' | 'gitlens.toggleBlame' | 'gitlens.toggleCodeLens'; +export type Commands = 'gitlens.diffWithPrevious' | 'gitlens.diffLineWithPrevious' | 'gitlens.diffWithWorking' | 'gitlens.diffLineWithWorking' | 'gitlens.showBlame' | 'gitlens.showBlameHistory' | 'gitlens.showFileHistory' | 'gitlens.showQuickCommitDetails' | 'gitlens.showQuickFileHistory' | 'gitlens.showQuickRepoHistory' | 'gitlens.toggleBlame' | 'gitlens.toggleCodeLens'; export const Commands = { DiffWithPrevious: 'gitlens.diffWithPrevious' as Commands, DiffLineWithPrevious: 'gitlens.diffLineWithPrevious' as Commands, @@ -23,6 +23,7 @@ export const Commands = { ShowBlame: 'gitlens.showBlame' as Commands, ShowBlameHistory: 'gitlens.showBlameHistory' as Commands, ShowFileHistory: 'gitlens.showFileHistory' as Commands, + ShowQuickCommitDetails: 'gitlens.showQuickCommitDetails' as Commands, ShowQuickFileHistory: 'gitlens.showQuickFileHistory' as Commands, ShowQuickRepoHistory: 'gitlens.showQuickRepoHistory' as Commands, ToggleBlame: 'gitlens.toggleBlame' as Commands, diff --git a/src/extension.ts b/src/extension.ts index 86abe6c..09250a4 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -10,6 +10,7 @@ import DiffWithWorkingCommand from './commands/diffWithWorking'; import ShowBlameCommand from './commands/showBlame'; import ShowBlameHistoryCommand from './commands/showBlameHistory'; import ShowFileHistoryCommand from './commands/showFileHistory'; +import ShowQuickCommitDetailsCommand from './commands/showQuickCommitDetails'; import ShowQuickFileHistoryCommand from './commands/showQuickFileHistory'; import ShowQuickRepoHistoryCommand from './commands/showQuickRepoHistory'; import ToggleBlameCommand from './commands/toggleBlame'; @@ -73,6 +74,7 @@ export async function activate(context: ExtensionContext) { context.subscriptions.push(new ToggleBlameCommand(annotationController)); context.subscriptions.push(new ShowBlameHistoryCommand(git)); context.subscriptions.push(new ShowFileHistoryCommand(git)); + context.subscriptions.push(new ShowQuickCommitDetailsCommand(git)); context.subscriptions.push(new ShowQuickFileHistoryCommand(git)); context.subscriptions.push(new ShowQuickRepoHistoryCommand(git, repoPath)); context.subscriptions.push(new ToggleCodeLensCommand(git)); diff --git a/src/git/git.ts b/src/git/git.ts index 90d9007..334c771 100644 --- a/src/git/git.ts +++ b/src/git/git.ts @@ -95,7 +95,7 @@ export default class Git { params.push(`-n${maxCount}`); } if (sha) { - params.push(`origin..${sha}`); + params.push(sha); params.push(`--`); } @@ -111,18 +111,21 @@ export default class Git { } if (sha) { params.push(`--follow`); - params.push(`origin..${sha}`); + params.push(sha); } params.push(`-L ${start},${end}:${file}`); return gitCommand(root, ...params); } - static logRepo(repoPath: string, maxCount?: number) { + static logRepo(repoPath: string, sha?: string, maxCount?: number) { const params = [...DefaultLogParams]; if (maxCount) { params.push(`-n${maxCount}`); } + if (sha) { + params.push(`${sha}^!`); + } return gitCommand(repoPath, ...params); } diff --git a/src/gitProvider.ts b/src/gitProvider.ts index e2ea2b0..40a5aac 100644 --- a/src/gitProvider.ts +++ b/src/gitProvider.ts @@ -421,7 +421,7 @@ export default class GitProvider extends Disposable { return locations; } - async getLogForRepo(repoPath: string, maxCount?: number): Promise { + async getLogForRepo(repoPath: string, sha?: string, maxCount?: number): Promise { Logger.log(`getLogForRepo('${repoPath}', ${maxCount})`); if (maxCount == null) { @@ -429,7 +429,7 @@ export default class GitProvider extends Disposable { } try { - const data = await Git.logRepo(repoPath, maxCount); + const data = await Git.logRepo(repoPath, sha, maxCount); return new GitLogParserEnricher().enrich(data, repoPath, true); } catch (ex) {