diff --git a/package.json b/package.json index 653af2d..ee91877 100644 --- a/package.json +++ b/package.json @@ -161,6 +161,8 @@ "enum": [ "gitlens.toggleFileBlame", "gitlens.diffWithPrevious", + "gitlens.revealCommitInView", + "gitlens.showCommitsInView", "gitlens.showQuickCommitDetails", "gitlens.showQuickCommitFileDetails", "gitlens.showQuickFileHistory", @@ -169,6 +171,8 @@ "enumDescriptions": [ "Toggles file blame annotations", "Compares the current committed file with the previous commit", + "Reveals the commit in the Repositories view", + "Shows the commits within the range in the Search Commits view", "Shows a commit details quick pick", "Shows a commit file details quick pick", "Shows a file history quick pick", @@ -201,6 +205,8 @@ "enum": [ "gitlens.toggleFileBlame", "gitlens.diffWithPrevious", + "gitlens.revealCommitInView", + "gitlens.showCommitsInView", "gitlens.showQuickCommitDetails", "gitlens.showQuickCommitFileDetails", "gitlens.showQuickFileHistory", @@ -209,6 +215,8 @@ "enumDescriptions": [ "Toggles file blame annotations", "Compares the current committed file with the previous commit", + "Reveals the commit in the Repositories view", + "Shows the commit in the Search Commits view", "Shows a commit details quick pick", "Shows a commit file details quick pick", "Shows a file history quick pick", @@ -2237,6 +2245,16 @@ "category": "GitLens" }, { + "command": "gitlens.showCommitInView", + "title": "Show Commit in Search Commits View", + "category": "GitLens" + }, + { + "command": "gitlens.showCommitsInView", + "title": "Show Commits within Selection in Search Commits View", + "category": "GitLens" + }, + { "command": "gitlens.showFileHistoryInView", "title": "Show in File History View", "category": "GitLens" @@ -3422,6 +3440,10 @@ "when": "gitlens:activeFileStatus =~ /blameable/" }, { + "command": "gitlens.showCommitsInView", + "when": "gitlens:activeFileStatus =~ /blameable/" + }, + { "command": "gitlens.showFileHistoryInView", "when": "gitlens:activeFileStatus =~ /tracked/" }, diff --git a/src/codelens/codeLensProvider.ts b/src/codelens/codeLensProvider.ts index 8ea4c2d..5ed0fa1 100644 --- a/src/codelens/codeLensProvider.ts +++ b/src/codelens/codeLensProvider.ts @@ -20,6 +20,7 @@ import { import { Commands, DiffWithPreviousCommandArgs, + ShowCommitsInViewCommandArgs, ShowQuickCommitDetailsCommandArgs, ShowQuickCommitFileDetailsCommandArgs, ShowQuickFileHistoryCommandArgs @@ -476,6 +477,7 @@ export class GitCodeLensProvider implements CodeLensProvider { if (blame === undefined) return lens; const recentCommit = Iterables.first(blame.commits.values()); + let title = `${recentCommit.author}, ${recentCommit.formattedDate}`; if (Container.config.debug) { title += ` [${lens.languageId}: ${SymbolKind[lens.symbol.kind]}(${lens.range.start.character}-${ @@ -491,32 +493,21 @@ export class GitCodeLensProvider implements CodeLensProvider { switch (lens.desiredCommand) { case CodeLensCommand.DiffWithPrevious: - return this.applyDiffWithPreviousCommand(title, lens, blame, recentCommit); + return this.applyDiffWithPreviousCommand(title, lens, recentCommit); + case CodeLensCommand.RevealCommitInView: + return this.applyRevealCommitInViewCommand(title, lens, recentCommit); + case CodeLensCommand.ShowCommitsInView: + return this.applyShowCommitsInViewCommand(title, lens, blame, recentCommit); case CodeLensCommand.ShowQuickCommitDetails: - return this.applyShowQuickCommitDetailsCommand( - title, - lens, - blame, - recentCommit - ); + return this.applyShowQuickCommitDetailsCommand(title, lens, recentCommit); case CodeLensCommand.ShowQuickCommitFileDetails: - return this.applyShowQuickCommitFileDetailsCommand( - title, - lens, - blame, - recentCommit - ); + return this.applyShowQuickCommitFileDetailsCommand(title, lens, recentCommit); case CodeLensCommand.ShowQuickCurrentBranchHistory: - return this.applyShowQuickCurrentBranchHistoryCommand( - title, - lens, - blame, - recentCommit - ); + return this.applyShowQuickCurrentBranchHistoryCommand(title, lens); case CodeLensCommand.ShowQuickFileHistory: - return this.applyShowQuickFileHistoryCommand(title, lens, blame, recentCommit); + return this.applyShowQuickFileHistoryCommand(title, lens); case CodeLensCommand.ToggleFileBlame: - return this.applyToggleFileBlameCommand(title, lens, blame); + return this.applyToggleFileBlameCommand(title, lens); default: return lens; } @@ -527,9 +518,10 @@ export class GitCodeLensProvider implements CodeLensProvider { if (blame === undefined) return lens; const count = blame.authors.size; - let title = `${count} ${count > 1 ? 'authors' : 'author'} (${Iterables.first(blame.authors.values()).name}${ - count > 1 ? ' and others' : '' - })`; + + const author = Iterables.first(blame.authors.values()).name; + + let title = `${count} ${count > 1 ? 'authors' : 'author'} (${author}${count > 1 ? ' and others' : ''})`; if (Container.config.debug) { title += ` [${lens.languageId}: ${SymbolKind[lens.symbol.kind]}(${lens.range.start.character}-${ lens.range.end.character @@ -543,19 +535,26 @@ export class GitCodeLensProvider implements CodeLensProvider { )})]`; } + const commit = + Iterables.find(blame.commits.values(), c => c.author === author) || Iterables.first(blame.commits.values()); + switch (lens.desiredCommand) { case CodeLensCommand.DiffWithPrevious: - return this.applyDiffWithPreviousCommand(title, lens, blame); + return this.applyDiffWithPreviousCommand(title, lens, commit); + case CodeLensCommand.RevealCommitInView: + return this.applyRevealCommitInViewCommand(title, lens, commit); + case CodeLensCommand.ShowCommitsInView: + return this.applyShowCommitsInViewCommand(title, lens, blame); case CodeLensCommand.ShowQuickCommitDetails: - return this.applyShowQuickCommitDetailsCommand(title, lens, blame); + return this.applyShowQuickCommitDetailsCommand(title, lens, commit); case CodeLensCommand.ShowQuickCommitFileDetails: - return this.applyShowQuickCommitFileDetailsCommand(title, lens, blame); + return this.applyShowQuickCommitFileDetailsCommand(title, lens, commit); case CodeLensCommand.ShowQuickCurrentBranchHistory: - return this.applyShowQuickCurrentBranchHistoryCommand(title, lens, blame); + return this.applyShowQuickCurrentBranchHistoryCommand(title, lens); case CodeLensCommand.ShowQuickFileHistory: - return this.applyShowQuickFileHistoryCommand(title, lens, blame); + return this.applyShowQuickFileHistoryCommand(title, lens); case CodeLensCommand.ToggleFileBlame: - return this.applyToggleFileBlameCommand(title, lens, blame); + return this.applyToggleFileBlameCommand(title, lens); default: return lens; } @@ -564,14 +563,8 @@ export class GitCodeLensProvider implements CodeLensProvider { private applyDiffWithPreviousCommand( title: string, lens: T, - blame: GitBlameLines, - commit?: GitBlameCommit + commit: GitBlameCommit | undefined ): T { - if (commit === undefined) { - const blameLine = blame.allLines[lens.range.start.line]; - commit = blame.commits.get(blameLine.sha); - } - const commandArgs: DiffWithPreviousCommandArgs = { commit: commit }; @@ -583,12 +576,53 @@ export class GitCodeLensProvider implements CodeLensProvider { return lens; } - private applyShowQuickCommitDetailsCommand( + private applyRevealCommitInViewCommand( + title: string, + lens: T, + commit: GitBlameCommit | undefined + ): T { + const commandArgs: ShowQuickCommitDetailsCommandArgs = { + commit: commit, + sha: commit === undefined ? undefined : commit.sha + }; + lens.command = { + title: title, + command: commit !== undefined && commit.isUncommitted ? '' : CodeLensCommand.RevealCommitInView, + arguments: [lens.uri!.toFileUri(), commandArgs] + }; + return lens; + } + + private applyShowCommitsInViewCommand( title: string, lens: T, blame: GitBlameLines, commit?: GitBlameCommit ): T { + let refs; + if (commit === undefined) { + refs = [...Iterables.filterMap(blame.commits.values(), c => (c.isUncommitted ? undefined : c.ref))]; + } else { + refs = [commit.ref]; + } + + const commandArgs: ShowCommitsInViewCommandArgs = { + repoPath: blame.repoPath, + refs: refs + }; + lens.command = { + title: title, + command: Commands.ShowCommitsInView, + arguments: [commandArgs] + }; + return lens; + } + + private applyShowQuickCommitDetailsCommand( + title: string, + lens: T, + commit: GitBlameCommit | undefined + ): T { const commandArgs: ShowQuickCommitDetailsCommandArgs = { commit: commit, sha: commit === undefined ? undefined : commit.sha @@ -604,8 +638,7 @@ export class GitCodeLensProvider implements CodeLensProvider { private applyShowQuickCommitFileDetailsCommand( title: string, lens: T, - blame: GitBlameLines, - commit?: GitBlameCommit + commit: GitBlameCommit | undefined ): T { const commandArgs: ShowQuickCommitFileDetailsCommandArgs = { commit: commit, @@ -621,9 +654,7 @@ export class GitCodeLensProvider implements CodeLensProvider { private applyShowQuickCurrentBranchHistoryCommand( title: string, - lens: T, - blame: GitBlameLines, - commit?: GitBlameCommit + lens: T ): T { lens.command = { title: title, @@ -635,9 +666,7 @@ export class GitCodeLensProvider implements CodeLensProvider { private applyShowQuickFileHistoryCommand( title: string, - lens: T, - blame: GitBlameLines, - commit?: GitBlameCommit + lens: T ): T { const commandArgs: ShowQuickFileHistoryCommandArgs = { range: lens.isFullRange ? undefined : lens.blameRange @@ -652,8 +681,7 @@ export class GitCodeLensProvider implements CodeLensProvider { private applyToggleFileBlameCommand( title: string, - lens: T, - blame: GitBlameLines + lens: T ): T { lens.command = { title: title, diff --git a/src/commands.ts b/src/commands.ts index d62aa43..93cd56b 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -34,6 +34,7 @@ export * from './commands/gitCommands'; export * from './commands/repositories'; export * from './commands/resetSuppressedWarnings'; export * from './commands/searchCommits'; +export * from './commands/showCommitsInView'; export * from './commands/showLastQuickPick'; export * from './commands/showQuickBranchHistory'; export * from './commands/showQuickCommitDetails'; diff --git a/src/commands/common.ts b/src/commands/common.ts index fe00cc6..7a52dd5 100644 --- a/src/commands/common.ts +++ b/src/commands/common.ts @@ -72,9 +72,10 @@ export enum Commands { GitCommands = 'gitlens.gitCommands', ResetSuppressedWarnings = 'gitlens.resetSuppressedWarnings', RevealCommitInView = 'gitlens.revealCommitInView', - ShowCommitInView = 'gitlens.showCommitInView', SearchCommits = 'gitlens.showCommitSearch', SearchCommitsInView = 'gitlens.views.search.searchCommits', + ShowCommitInView = 'gitlens.showCommitInView', + ShowCommitsInView = 'gitlens.showCommitsInView', ShowCompareView = 'gitlens.showCompareView', ShowFileHistoryView = 'gitlens.showFileHistoryView', ShowFileHistoryInView = 'gitlens.showFileHistoryInView', diff --git a/src/commands/showCommitsInView.ts b/src/commands/showCommitsInView.ts new file mode 100644 index 0000000..9c6d3a7 --- /dev/null +++ b/src/commands/showCommitsInView.ts @@ -0,0 +1,70 @@ +'use strict'; +import { commands, TextEditor, Uri } from 'vscode'; +import { Container } from '../container'; +import { ActiveEditorCommand, command, Commands, getCommandUri } from './common'; +import { GitUri, SearchPattern } from '../git/gitService'; +import { GitCommandsCommandArgs } from '../commands'; +import { Messages } from '../messages'; +import { Iterables } from '../system'; +import { Logger } from '../logger'; + +export interface ShowCommitsInViewCommandArgs { + refs?: string[]; + repoPath?: string; +} + +@command() +export class ShowCommitsInViewCommand extends ActiveEditorCommand { + constructor() { + super([Commands.ShowCommitInView, Commands.ShowCommitsInView]); + } + + async execute(editor?: TextEditor, uri?: Uri, args?: ShowCommitsInViewCommandArgs) { + args = { ...args }; + + if (args.refs === undefined) { + if (editor == null) return undefined; + + uri = getCommandUri(uri, editor); + if (uri == null) return undefined; + + const gitUri = await GitUri.fromUri(uri); + + args.repoPath = gitUri.repoPath; + + try { + // Check for any uncommitted changes in the range + const blame = editor.document.isDirty + ? await Container.git.getBlameForRangeContents(gitUri, editor.selection, editor.document.getText()) + : await Container.git.getBlameForRange(gitUri, editor.selection); + if (blame === undefined) { + return Messages.showFileNotUnderSourceControlWarningMessage( + 'Unable to show commits in Search Commits view' + ); + } + + args.refs = [ + ...Iterables.filterMap(blame.commits.values(), c => (c.isUncommitted ? undefined : c.ref)) + ]; + } catch (ex) { + Logger.error(ex, 'ShowCommitsInViewCommand', 'getBlameForRange'); + return Messages.showGenericErrorMessage('Unable to show commits in Search Commits view'); + } + } + + let repo; + if (args.repoPath !== undefined) { + repo = await Container.git.getRepository(args.repoPath); + } + + const gitCommandArgs: GitCommandsCommandArgs = { + command: 'search', + state: { + repo: repo, + pattern: SearchPattern.fromCommits(args.refs), + showResultsInView: true + } + }; + return commands.executeCommand(Commands.GitCommands, gitCommandArgs); + } +} diff --git a/src/commands/showQuickCommitDetails.ts b/src/commands/showQuickCommitDetails.ts index 130bc5d..7d9ba50 100644 --- a/src/commands/showQuickCommitDetails.ts +++ b/src/commands/showQuickCommitDetails.ts @@ -2,7 +2,7 @@ import { commands, TextEditor, Uri } from 'vscode'; import { GlyphChars } from '../constants'; import { Container } from '../container'; -import { GitCommit, GitLog, GitLogCommit, GitUri, SearchPattern } from '../git/gitService'; +import { GitCommit, GitLog, GitLogCommit, GitUri } from '../git/gitService'; import { Logger } from '../logger'; import { Messages } from '../messages'; import { CommandQuickPickItem, CommitQuickPick, CommitWithFileStatusQuickPickItem } from '../quickpicks'; @@ -20,7 +20,7 @@ export interface ShowQuickCommitDetailsCommandArgs { sha?: string; commit?: GitCommit | GitLogCommit; repoLog?: GitLog; - showInView?: 'reveal' | 'show'; + revealInView?: boolean; goBackCommand?: CommandQuickPickItem; } @@ -38,16 +38,13 @@ export class ShowQuickCommitDetailsCommand extends ActiveEditorCachedCommand { } constructor() { - super([Commands.RevealCommitInView, Commands.ShowCommitInView, Commands.ShowQuickCommitDetails]); + super([Commands.RevealCommitInView, Commands.ShowQuickCommitDetails]); } protected preExecute(context: CommandContext, args?: ShowQuickCommitDetailsCommandArgs) { if (context.command === Commands.RevealCommitInView) { args = { ...args }; - args.showInView = 'reveal'; - } else if (context.command === Commands.ShowCommitInView) { - args = { ...args }; - args.showInView = 'show'; + args.revealInView = true; } if (context.type === 'viewItem') { @@ -122,22 +119,12 @@ export class ShowQuickCommitDetailsCommand extends ActiveEditorCachedCommand { return Messages.showCommitNotFoundWarningMessage('Unable to show commit details'); } - if (args.showInView) { - if (args.showInView === 'reveal') { - void (await Container.repositoriesView.revealCommit(args.commit, { - select: true, - focus: true, - expand: true - })); - } else { - void (await Container.searchView.search( - repoPath!, - { pattern: SearchPattern.fromCommit(args.commit) }, - { - label: { label: `for commit id ${args.commit.shortSha}` } - } - )); - } + if (args.revealInView) { + void (await Container.repositoriesView.revealCommit(args.commit, { + select: true, + focus: true, + expand: true + })); return undefined; } diff --git a/src/config.ts b/src/config.ts index fb5a894..752a1fd 100644 --- a/src/config.ts +++ b/src/config.ts @@ -126,6 +126,8 @@ export enum BranchSorting { export enum CodeLensCommand { DiffWithPrevious = 'gitlens.diffWithPrevious', + RevealCommitInView = 'gitlens.revealCommitInView', + ShowCommitsInView = 'gitlens.showCommitsInView', ShowQuickCommitDetails = 'gitlens.showQuickCommitDetails', ShowQuickCommitFileDetails = 'gitlens.showQuickCommitFileDetails', ShowQuickCurrentBranchHistory = 'gitlens.showQuickRepoHistory', diff --git a/src/git/gitService.ts b/src/git/gitService.ts index 5e0f6c6..e39eb5a 100644 --- a/src/git/gitService.ts +++ b/src/git/gitService.ts @@ -133,7 +133,13 @@ export namespace SearchPattern { export function fromCommit(ref: string): string; export function fromCommit(commit: GitCommit): string; export function fromCommit(refOrCommit: string | GitCommit) { - return `commit:${GitService.shortenSha(typeof refOrCommit === 'string' ? refOrCommit : refOrCommit.sha)}`; + return `#:${GitService.shortenSha(typeof refOrCommit === 'string' ? refOrCommit : refOrCommit.sha)}`; + } + + export function fromCommits(refs: string[]): string; + export function fromCommits(commits: GitCommit[]): string; + export function fromCommits(refsOrCommits: (string | GitCommit)[]) { + return refsOrCommits.map(r => `#:${GitService.shortenSha(typeof r === 'string' ? r : r.sha)}`).join(' '); } export function toKey(search: SearchPattern) { diff --git a/src/webviews/apps/settings/index.html b/src/webviews/apps/settings/index.html index 8fff4ef..9f75735 100644 --- a/src/webviews/apps/settings/index.html +++ b/src/webviews/apps/settings/index.html @@ -349,6 +349,12 @@ + + @@ -403,6 +409,13 @@ + +