From 89784cd42a923f2c5468a6ed7cc6655528ab8a41 Mon Sep 17 00:00:00 2001 From: Eric Amodio Date: Wed, 30 Sep 2020 03:33:13 -0400 Subject: [PATCH] Adds branch/tag option to open/diff revision cmds Changes default sort of branch/tag pickers to be by date desc --- src/commands/diffWithRevision.ts | 37 ++++++++++++++-------------- src/commands/openBranchOnRemote.ts | 14 +++++++---- src/commands/openFileAtRevision.ts | 23 +++++++++--------- src/commands/openFileAtRevisionFrom.ts | 2 +- src/commands/openFileOnRemote.ts | 6 ++++- src/git/gitService.ts | 4 ++-- src/quickpicks/commitPicker.ts | 40 +++++++++++++++++++++++-------- src/quickpicks/quickPicksItems.ts | 12 ++++++---- src/quickpicks/referencePicker.ts | 13 ++++++---- src/terminal/linkProvider.ts | 2 +- src/views/nodes/compareBranchNode.ts | 12 ++++++++-- src/views/nodes/compareNode.ts | 9 +++++++ src/views/nodes/fileHistoryTrackerNode.ts | 5 ++++ src/views/nodes/lineHistoryTrackerNode.ts | 5 ++++ 14 files changed, 125 insertions(+), 59 deletions(-) diff --git a/src/commands/diffWithRevision.ts b/src/commands/diffWithRevision.ts index 78c3f72..d95c359 100644 --- a/src/commands/diffWithRevision.ts +++ b/src/commands/diffWithRevision.ts @@ -8,7 +8,7 @@ import { GitRevision } from '../git/git'; import { GitUri } from '../git/gitUri'; import { Logger } from '../logger'; import { Messages } from '../messages'; -import { CommitPicker, DirectiveQuickPickItem } from '../quickpicks'; +import { CommandQuickPickItem, CommitPicker } from '../quickpicks'; import { Strings } from '../system'; export interface DiffWithRevisionCommandArgs { @@ -55,24 +55,25 @@ export class DiffWithRevisionCommand extends ActiveEditorCommand { { picked: gitUri.sha, keys: ['right', 'alt+right', 'ctrl+right'], - onDidPressKey: async (key, quickpick) => { - const [item] = quickpick.activeItems; - if (item != null && !DirectiveQuickPickItem.is(item)) { - void (await executeCommand(Commands.DiffWith, { - repoPath: gitUri.repoPath, - lhs: { - sha: item.item.ref, - uri: gitUri, - }, - rhs: { - sha: '', - uri: gitUri, - }, - line: args!.line, - showOptions: args!.showOptions, - })); - } + onDidPressKey: async (key, item) => { + void (await executeCommand(Commands.DiffWith, { + repoPath: gitUri.repoPath, + lhs: { + sha: item.item.ref, + uri: gitUri, + }, + rhs: { + sha: '', + uri: gitUri, + }, + line: args!.line, + showOptions: args!.showOptions, + })); }, + showOtherReferences: CommandQuickPickItem.fromCommand( + 'Choose a branch or tag...', + Commands.DiffWithRevisionFrom, + ), }, ); if (pick == null) return; diff --git a/src/commands/openBranchOnRemote.ts b/src/commands/openBranchOnRemote.ts index 2ca4f84..848fe28 100644 --- a/src/commands/openBranchOnRemote.ts +++ b/src/commands/openBranchOnRemote.ts @@ -1,9 +1,5 @@ 'use strict'; import { TextEditor, Uri, window } from 'vscode'; -import { RemoteResourceType } from '../git/git'; -import { GitUri } from '../git/gitUri'; -import { Logger } from '../logger'; -import { CommandQuickPickItem, ReferencePicker, ReferencesQuickPickIncludes } from '../quickpicks'; import { ActiveEditorCommand, command, @@ -14,7 +10,12 @@ import { getRepoPathOrActiveOrPrompt, isCommandViewContextWithBranch, } from './common'; +import { BranchSorting } from '../configuration'; +import { RemoteResourceType } from '../git/git'; +import { GitUri } from '../git/gitUri'; +import { Logger } from '../logger'; import { OpenOnRemoteCommandArgs } from './openOnRemote'; +import { CommandQuickPickItem, ReferencePicker, ReferencesQuickPickIncludes } from '../quickpicks'; export interface OpenBranchOnRemoteCommandArgs { branch?: string; @@ -67,8 +68,11 @@ export class OpenBranchOnRemoteCommand extends ActiveEditorCommand { { autoPick: true, // checkmarks: false, - filterBranches: b => b.tracking != null, + filter: { branches: b => b.tracking != null }, include: ReferencesQuickPickIncludes.Branches, + sort: { + branches: { current: true, orderBy: BranchSorting.DateDesc }, + }, }, ); if (pick == null || pick instanceof CommandQuickPickItem) return; diff --git a/src/commands/openFileAtRevision.ts b/src/commands/openFileAtRevision.ts index 4e6da21..6bfe06e 100644 --- a/src/commands/openFileAtRevision.ts +++ b/src/commands/openFileAtRevision.ts @@ -9,7 +9,7 @@ import { GitUri } from '../git/gitUri'; import { GitActions } from './gitCommands'; import { Logger } from '../logger'; import { Messages } from '../messages'; -import { CommitPicker, DirectiveQuickPickItem } from '../quickpicks'; +import { CommandQuickPickItem, CommitPicker } from '../quickpicks'; import { Strings } from '../system'; export interface OpenFileAtRevisionCommandArgs { @@ -83,17 +83,18 @@ export class OpenFileAtRevisionCommand extends ActiveEditorCommand { { picked: gitUri.sha, keys: ['right', 'alt+right', 'ctrl+right'], - onDidPressKey: async (key, quickpick) => { - const [item] = quickpick.activeItems; - if (item != null && !DirectiveQuickPickItem.is(item)) { - void (await GitActions.Commit.openFileAtRevision(item.item.uri.fsPath, item.item, { - annotationType: args!.annotationType, - line: args!.line, - preserveFocus: true, - preview: false, - })); - } + onDidPressKey: async (key, item) => { + void (await GitActions.Commit.openFileAtRevision(item.item.uri.fsPath, item.item, { + annotationType: args!.annotationType, + line: args!.line, + preserveFocus: true, + preview: false, + })); }, + showOtherReferences: CommandQuickPickItem.fromCommand( + 'Choose a branch or tag...', + Commands.OpenFileAtRevisionFrom, + ), }, ); if (pick == null) return; diff --git a/src/commands/openFileAtRevisionFrom.ts b/src/commands/openFileAtRevisionFrom.ts index 0024c8c..65f06ac 100644 --- a/src/commands/openFileAtRevisionFrom.ts +++ b/src/commands/openFileAtRevisionFrom.ts @@ -40,7 +40,7 @@ export class OpenFileAtRevisionFromCommand extends ActiveEditorCommand { } if (args.reference == null) { - const title = `Open File at Revision${Strings.pad(GlyphChars.Dot, 2, 2)}`; + const title = `Open File at Branch or Tag${Strings.pad(GlyphChars.Dot, 2, 2)}`; const pick = await ReferencePicker.show( gitUri.repoPath, `${title}${gitUri.getFormattedFilename({ truncateTo: quickPickTitleMaxChars - title.length })}`, diff --git a/src/commands/openFileOnRemote.ts b/src/commands/openFileOnRemote.ts index 46ff16e..cd70be4 100644 --- a/src/commands/openFileOnRemote.ts +++ b/src/commands/openFileOnRemote.ts @@ -11,6 +11,7 @@ import { isCommandViewContextWithCommit, } from './common'; import { UriComparer } from '../comparers'; +import { BranchSorting } from '../configuration'; import { GlyphChars } from '../constants'; import { Container } from '../container'; import { GitRevision, RemoteResourceType } from '../git/git'; @@ -124,8 +125,11 @@ export class OpenFileOnRemoteCommand extends ActiveEditorCommand { { autoPick: true, // checkmarks: false, - filterBranches: b => b.tracking != null, + filter: { branches: b => b.tracking != null }, include: ReferencesQuickPickIncludes.Branches, + sort: { + branches: { current: true, orderBy: BranchSorting.DateDesc }, + }, }, ); if (pick == null) return; diff --git a/src/git/gitService.ts b/src/git/gitService.ts index da6f41d..1baf6bb 100644 --- a/src/git/gitService.ts +++ b/src/git/gitService.ts @@ -1176,14 +1176,14 @@ export class GitService implements Disposable { } = {}, ) { const [branches, tags] = await Promise.all([ - include === 'all' || include === 'branches' + include == null || include === 'all' || include === 'branches' ? this.getBranches(repoPath, { ...options, filter: filter?.branches, sort: typeof sort === 'boolean' ? undefined : sort?.branches, }) : undefined, - include === 'all' || include === 'tags' + include == null || include === 'all' || include === 'tags' ? this.getTags(repoPath, { ...options, filter: filter?.tags, diff --git a/src/quickpicks/commitPicker.ts b/src/quickpicks/commitPicker.ts index 53d56a7..a80a872 100644 --- a/src/quickpicks/commitPicker.ts +++ b/src/quickpicks/commitPicker.ts @@ -1,10 +1,16 @@ 'use strict'; -import { Disposable, QuickPick, window } from 'vscode'; +import { Disposable, window } from 'vscode'; import { configuration } from '../configuration'; import { Container } from '../container'; import { GitLog, GitLogCommit } from '../git/git'; import { KeyboardScope, Keys } from '../keyboard'; -import { CommitQuickPickItem, Directive, DirectiveQuickPickItem, getQuickPickIgnoreFocusOut } from '../quickpicks'; +import { + CommandQuickPickItem, + CommitQuickPickItem, + Directive, + DirectiveQuickPickItem, + getQuickPickIgnoreFocusOut, +} from '../quickpicks'; import { Iterables, Promises } from '../system'; export namespace CommitPicker { @@ -15,13 +21,11 @@ export namespace CommitPicker { options?: { picked?: string; keys?: Keys[]; - onDidPressKey?( - key: Keys, - quickpick: QuickPick, - ): void | Promise; + onDidPressKey?(key: Keys, item: CommitQuickPickItem): void | Promise; + showOtherReferences?: CommandQuickPickItem; }, ): Promise { - const quickpick = window.createQuickPick(); + const quickpick = window.createQuickPick(); quickpick.ignoreFocusOut = getQuickPickIgnoreFocusOut(); quickpick.title = title; @@ -44,13 +48,14 @@ export namespace CommitPicker { quickpick.items = getItems(log); if (options?.picked) { - quickpick.activeItems = quickpick.items.filter(i => i.picked); + quickpick.activeItems = quickpick.items.filter(i => (CommandQuickPickItem.is(i) ? false : i.picked)); } function getItems(log: GitLog | undefined) { return log == null ? [DirectiveQuickPickItem.create(Directive.Cancel)] : [ + ...(options?.showOtherReferences != null ? [options?.showOtherReferences] : []), ...Iterables.map(log.commits.values(), commit => CommitQuickPickItem.create(commit, options?.picked === commit.ref, { compact: true, @@ -102,7 +107,14 @@ export namespace CommitPicker { { onDidPressKey: key => { if (quickpick.activeItems.length !== 0) { - void options.onDidPressKey!(key, quickpick); + const [item] = quickpick.activeItems; + if ( + item != null && + !DirectiveQuickPickItem.is(item) && + !CommandQuickPickItem.is(item) + ) { + void options.onDidPressKey!(key, item); + } } }, }, @@ -114,7 +126,9 @@ export namespace CommitPicker { } try { - const pick = await new Promise(resolve => { + const pick = await new Promise< + CommandQuickPickItem | CommitQuickPickItem | DirectiveQuickPickItem | undefined + >(resolve => { disposables.push( quickpick.onDidHide(() => resolve()), quickpick.onDidAccept(() => { @@ -154,6 +168,12 @@ export namespace CommitPicker { }); if (pick == null || DirectiveQuickPickItem.is(pick)) return undefined; + if (pick instanceof CommandQuickPickItem) { + void (await pick.execute()); + + return undefined; + } + return pick.item; } finally { quickpick.dispose(); diff --git a/src/quickpicks/quickPicksItems.ts b/src/quickpicks/quickPicksItems.ts index b664dfd..5e2e8db 100644 --- a/src/quickpicks/quickPicksItems.ts +++ b/src/quickpicks/quickPicksItems.ts @@ -75,16 +75,20 @@ export namespace DirectiveQuickPickItem { } export class CommandQuickPickItem implements QuickPickItem { - static fromCommand(label: string, command: Commands, args: T): CommandQuickPickItem; - static fromCommand(item: QuickPickItem, command: Commands, args: T): CommandQuickPickItem; - static fromCommand(labelOrItem: string | QuickPickItem, command: Commands, args: T): CommandQuickPickItem { + static fromCommand(label: string, command: Commands, args?: T): CommandQuickPickItem; + static fromCommand(item: QuickPickItem, command: Commands, args?: T): CommandQuickPickItem; + static fromCommand(labelOrItem: string | QuickPickItem, command: Commands, args?: T): CommandQuickPickItem { return new CommandQuickPickItem( typeof labelOrItem === 'string' ? { label: labelOrItem } : labelOrItem, command, - [args], + args == null ? [] : [args], ); } + static is(item: QuickPickItem): item is CommandQuickPickItem { + return item instanceof CommandQuickPickItem; + } + label!: string; description?: string; detail?: string | undefined; diff --git a/src/quickpicks/referencePicker.ts b/src/quickpicks/referencePicker.ts index 54d0cef..06f4abf 100644 --- a/src/quickpicks/referencePicker.ts +++ b/src/quickpicks/referencePicker.ts @@ -6,6 +6,7 @@ import { GitBranch, GitReference, GitTag } from '../git/git'; import { KeyboardScope, Keys } from '../keyboard'; import { BranchQuickPickItem, getQuickPickIgnoreFocusOut, RefQuickPickItem, TagQuickPickItem } from '../quickpicks'; import { getBranchesAndOrTags, getValidateGitReferenceFn } from '../commands/quickCommand'; +import { BranchSorting, TagSorting } from '../configuration'; export type ReferencesQuickPickItem = BranchQuickPickItem | TagQuickPickItem | RefQuickPickItem; @@ -22,11 +23,11 @@ export interface ReferencesQuickPickOptions { allowEnteringRefs?: boolean; autoPick?: boolean; picked?: string; - filterBranches?(branch: GitBranch): boolean; - filterTags?(tag: GitTag): boolean; + filter?: { branches?(b: GitBranch): boolean; tags?(t: GitTag): boolean }; include?: ReferencesQuickPickIncludes; keys?: Keys[]; onDidPressKey?(key: Keys, quickpick: QuickPick): void | Promise; + sort?: boolean | { branches?: { current?: boolean; orderBy?: BranchSorting }; tags?: { orderBy?: TagSorting } }; } export namespace ReferencePicker { @@ -135,7 +136,7 @@ export namespace ReferencePicker { async function getItems( repoPath: string, - { picked, filterBranches, filterTags, include }: ReferencesQuickPickOptions, + { picked, filter, include, sort }: ReferencesQuickPickOptions, ): Promise { include = include ?? ReferencesQuickPickIncludes.BranchesAndTags; @@ -149,8 +150,12 @@ export namespace ReferencePicker { ? ['tags'] : [], { - filter: { branches: filterBranches, tags: filterTags }, + filter: filter, picked: picked, + sort: sort ?? { + branches: { current: false, orderBy: BranchSorting.DateDesc }, + tags: { orderBy: TagSorting.DateDesc }, + }, }, ); diff --git a/src/terminal/linkProvider.ts b/src/terminal/linkProvider.ts index 6c91747..abd2d3a 100644 --- a/src/terminal/linkProvider.ts +++ b/src/terminal/linkProvider.ts @@ -32,7 +32,7 @@ export class GitTerminalLinkProvider implements Disposable, TerminalLinkProvider const links: GitTerminalLink[] = []; - const branchesAndTags = await Container.git.getBranchesAndOrTags(repoPath, { include: 'all' }); + const branchesAndTags = await Container.git.getBranchesAndOrTags(repoPath); // Don't use the shared regex instance directly, because we can be called reentrantly (because of the awaits below) const regex = new RegExp(refRegex, 'gi'); diff --git a/src/views/nodes/compareBranchNode.ts b/src/views/nodes/compareBranchNode.ts index 3391bf0..d115bfe 100644 --- a/src/views/nodes/compareBranchNode.ts +++ b/src/views/nodes/compareBranchNode.ts @@ -2,7 +2,7 @@ import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from 'vscode'; import { CommitsView } from '../commitsView'; import { BranchComparison, BranchComparisons, GlyphChars, WorkspaceState } from '../../constants'; -import { ViewShowBranchComparison } from '../../config'; +import { BranchSorting, TagSorting, ViewShowBranchComparison } from '../../configuration'; import { Container } from '../../container'; import { GitBranch, GitRevision } from '../../git/git'; import { GitUri } from '../../git/gitUri'; @@ -189,7 +189,15 @@ export class CompareBranchNode extends ViewNode this.branch.repoPath, `Compare ${this.branch.name}${this.compareWithWorkingTree ? ' (working)' : ''} with`, 'Choose a reference to compare with', - { allowEnteringRefs: true, picked: this.branch.ref /*checkmarks: true*/ }, + { + allowEnteringRefs: true, + picked: this.branch.ref, + // checkmarks: true, + sort: { + branches: { current: true, orderBy: BranchSorting.DateDesc }, + tags: { orderBy: TagSorting.DateDesc }, + }, + }, ); if (pick === undefined || pick instanceof CommandQuickPickItem) return; diff --git a/src/views/nodes/compareNode.ts b/src/views/nodes/compareNode.ts index 619d730..354c489 100644 --- a/src/views/nodes/compareNode.ts +++ b/src/views/nodes/compareNode.ts @@ -1,6 +1,7 @@ 'use strict'; import { TreeItem, TreeItemCollapsibleState } from 'vscode'; import { getRepoPathOrPrompt } from '../../commands'; +import { BranchSorting, TagSorting } from '../../configuration'; import { CommandContext, NamedRef, setCommandContext } from '../../constants'; import { GitRevision } from '../../git/git'; import { ReferencePicker, ReferencesQuickPickIncludes } from '../../quickpicks'; @@ -150,6 +151,10 @@ export class CompareNode extends ViewNode { ReferencesQuickPickIncludes.BranchesAndTags | ReferencesQuickPickIncludes.HEAD | ReferencesQuickPickIncludes.WorkingTree, + sort: { + branches: { current: true, orderBy: BranchSorting.DateDesc }, + tags: { orderBy: TagSorting.DateDesc }, + }, }, ); if (pick === undefined) { @@ -190,6 +195,10 @@ export class CompareNode extends ViewNode { ReferencesQuickPickIncludes.BranchesAndTags | ReferencesQuickPickIncludes.HEAD | ReferencesQuickPickIncludes.WorkingTree, + sort: { + branches: { current: true, orderBy: BranchSorting.DateDesc }, + tags: { orderBy: TagSorting.DateDesc }, + }, }); if (pick == null) { await this.view.show(); diff --git a/src/views/nodes/fileHistoryTrackerNode.ts b/src/views/nodes/fileHistoryTrackerNode.ts index 6f0a162..d6e0657 100644 --- a/src/views/nodes/fileHistoryTrackerNode.ts +++ b/src/views/nodes/fileHistoryTrackerNode.ts @@ -2,6 +2,7 @@ import { Disposable, TextEditor, TreeItem, TreeItemCollapsibleState, window } from 'vscode'; import { MessageNode } from './common'; import { UriComparer } from '../../comparers'; +import { BranchSorting, TagSorting } from '../../configuration'; import { Container } from '../../container'; import { FileHistoryView } from '../fileHistoryView'; import { FileHistoryNode } from './fileHistoryNode'; @@ -83,6 +84,10 @@ export class FileHistoryTrackerNode extends SubscribeableViewNode