From 0d3a6dc7ee03a44777ae39343d41a5a7abf6ce66 Mon Sep 17 00:00:00 2001 From: Eric Amodio Date: Fri, 17 Dec 2021 19:19:34 -0500 Subject: [PATCH] Fixes view item revealing Adds proper reveal to repo folders Adds reveal to contributors git commands --- package.json | 7 ++ src/commands/git/branch.ts | 3 + src/commands/git/cherry-pick.ts | 3 + src/commands/git/coauthors.ts | 3 + src/commands/git/fetch.ts | 3 + src/commands/git/log.ts | 3 + src/commands/git/merge.ts | 3 + src/commands/git/pull.ts | 3 + src/commands/git/push.ts | 3 + src/commands/git/rebase.ts | 3 + src/commands/git/reset.ts | 3 + src/commands/git/revert.ts | 3 + src/commands/git/search.ts | 3 + src/commands/git/show.ts | 3 + src/commands/git/stash.ts | 3 + src/commands/git/status.ts | 3 + src/commands/git/switch.ts | 3 + src/commands/git/tag.ts | 3 + src/commands/gitCommands.actions.ts | 165 +++++++++++++++------------- src/commands/quickCommand.steps.ts | 57 ++++++---- src/config.ts | 1 + src/git/models/models.ts | 20 ++-- src/quickpicks/gitQuickPickItems.ts | 9 +- src/views/branchesView.ts | 27 ++++- src/views/commitsView.ts | 25 ++++- src/views/contributorsView.ts | 91 ++++++++++++++- src/views/lineHistoryView.ts | 2 +- src/views/remotesView.ts | 29 ++++- src/views/repositoriesView.ts | 123 ++++++++++++++++++--- src/views/searchAndCompareView.ts | 20 +++- src/views/stashesView.ts | 25 ++++- src/views/tagsView.ts | 25 ++++- src/views/viewBase.ts | 9 +- 33 files changed, 535 insertions(+), 151 deletions(-) diff --git a/package.json b/package.json index 827b8e5477391..de04884e75808 100644 --- a/package.json +++ b/package.json @@ -1614,6 +1614,13 @@ "markdownDescription": "Specifies whether to show avatar images instead of commit (or status) icons in the _Contributors_ view", "scope": "window", "order": 60 + }, + "gitlens.views.contributors.reveal": { + "type": "boolean", + "default": true, + "markdownDescription": "Specifies whether to reveal contributors in the _Contributors_ view, otherwise they revealed in the _Repositories_ view", + "scope": "window", + "order": 20 } } }, diff --git a/src/commands/git/branch.ts b/src/commands/git/branch.ts index 24712386574db..5993114f33806 100644 --- a/src/commands/git/branch.ts +++ b/src/commands/git/branch.ts @@ -4,6 +4,7 @@ import { Container } from '../../container'; import { GitBranchReference, GitReference, Repository } from '../../git/git'; import { FlagsQuickPickItem, QuickPickItemOfT } from '../../quickpicks'; import { Strings } from '../../system'; +import { ViewsWithRepositoryFolders } from '../../views/viewBase'; import { appendReposToTitle, AsyncStepResultGenerator, @@ -24,6 +25,7 @@ import { interface Context { repos: Repository[]; + associatedView: ViewsWithRepositoryFolders; showTags: boolean; title: string; } @@ -148,6 +150,7 @@ export class BranchGitCommand extends QuickCommand { protected async *steps(state: PartialStepState): StepGenerator { const context: Context = { + associatedView: Container.instance.branchesView, repos: Container.instance.git.openRepositories, showTags: false, title: this.title, diff --git a/src/commands/git/cherry-pick.ts b/src/commands/git/cherry-pick.ts index 7d392bc1f2303..f99ac7af9d824 100644 --- a/src/commands/git/cherry-pick.ts +++ b/src/commands/git/cherry-pick.ts @@ -2,6 +2,7 @@ import { Container } from '../../container'; import { GitBranch, GitLog, GitReference, GitRevision, Repository } from '../../git/git'; import { FlagsQuickPickItem } from '../../quickpicks'; +import { ViewsWithRepositoryFolders } from '../../views/viewBase'; import { appendReposToTitle, PartialStepState, @@ -19,6 +20,7 @@ import { interface Context { repos: Repository[]; + associatedView: ViewsWithRepositoryFolders; cache: Map>; destination: GitBranch; selectedBranchOrTag: GitReference | undefined; @@ -81,6 +83,7 @@ export class CherryPickGitCommand extends QuickCommand { protected async *steps(state: PartialStepState): StepGenerator { const context: Context = { repos: Container.instance.git.openRepositories, + associatedView: Container.instance.commitsView, cache: new Map>(), destination: undefined!, selectedBranchOrTag: undefined, diff --git a/src/commands/git/coauthors.ts b/src/commands/git/coauthors.ts index eb9f72e25a0d2..c5bbaeab7e5a5 100644 --- a/src/commands/git/coauthors.ts +++ b/src/commands/git/coauthors.ts @@ -3,6 +3,7 @@ import { commands } from 'vscode'; import { Container } from '../../container'; import { GitContributor, Repository } from '../../git/git'; import { Strings } from '../../system'; +import { ViewsWithRepositoryFolders } from '../../views/viewBase'; import { PartialStepState, pickContributorsStep, @@ -16,6 +17,7 @@ import { interface Context { repos: Repository[]; activeRepo: Repository | undefined; + associatedView: ViewsWithRepositoryFolders; title: string; } @@ -94,6 +96,7 @@ export class CoAuthorsGitCommand extends QuickCommand { const context: Context = { repos: Container.instance.git.openRepositories, activeRepo: undefined, + associatedView: Container.instance.contributorsView, title: this.title, }; diff --git a/src/commands/git/fetch.ts b/src/commands/git/fetch.ts index 3fc16a359c753..d4b080623db1d 100644 --- a/src/commands/git/fetch.ts +++ b/src/commands/git/fetch.ts @@ -4,6 +4,7 @@ import { Container } from '../../container'; import { GitBranchReference, GitReference, Repository } from '../../git/git'; import { FlagsQuickPickItem } from '../../quickpicks'; import { Arrays, Dates, Strings } from '../../system'; +import { ViewsWithRepositoryFolders } from '../../views/viewBase'; import { appendReposToTitle, AsyncStepResultGenerator, @@ -19,6 +20,7 @@ import { interface Context { repos: Repository[]; + associatedView: ViewsWithRepositoryFolders; title: string; } @@ -68,6 +70,7 @@ export class FetchGitCommand extends QuickCommand { protected async *steps(state: PartialStepState): StepGenerator { const context: Context = { repos: Container.instance.git.openRepositories, + associatedView: Container.instance.commitsView, title: this.title, }; diff --git a/src/commands/git/log.ts b/src/commands/git/log.ts index acc8e8eb0959e..e76200b46afa6 100644 --- a/src/commands/git/log.ts +++ b/src/commands/git/log.ts @@ -4,6 +4,7 @@ import { Container } from '../../container'; import { GitLog, GitLogCommit, GitReference, Repository } from '../../git/git'; import { GitUri } from '../../git/gitUri'; import { Strings } from '../../system'; +import { ViewsWithRepositoryFolders } from '../../views/viewBase'; import { GitCommandsCommand } from '../gitCommands'; import { PartialStepState, @@ -18,6 +19,7 @@ import { interface Context { repos: Repository[]; + associatedView: ViewsWithRepositoryFolders; cache: Map>; selectedBranchOrTag: GitReference | undefined; title: string; @@ -77,6 +79,7 @@ export class LogGitCommand extends QuickCommand { protected async *steps(state: PartialStepState): StepGenerator { const context: Context = { repos: Container.instance.git.openRepositories, + associatedView: Container.instance.commitsView, cache: new Map>(), selectedBranchOrTag: undefined, title: this.title, diff --git a/src/commands/git/merge.ts b/src/commands/git/merge.ts index 80336543983ab..d4dabcac1835d 100644 --- a/src/commands/git/merge.ts +++ b/src/commands/git/merge.ts @@ -3,6 +3,7 @@ import { Container } from '../../container'; import { GitBranch, GitLog, GitReference, GitRevision, Repository } from '../../git/git'; import { Directive, DirectiveQuickPickItem, FlagsQuickPickItem } from '../../quickpicks'; import { Strings } from '../../system'; +import { ViewsWithRepositoryFolders } from '../../views/viewBase'; import { appendReposToTitle, AsyncStepResultGenerator, @@ -21,6 +22,7 @@ import { interface Context { repos: Repository[]; + associatedView: ViewsWithRepositoryFolders; cache: Map>; destination: GitBranch; pickCommit: boolean; @@ -78,6 +80,7 @@ export class MergeGitCommand extends QuickCommand { protected async *steps(state: PartialStepState): StepGenerator { const context: Context = { repos: Container.instance.git.openRepositories, + associatedView: Container.instance.commitsView, cache: new Map>(), destination: undefined!, pickCommit: false, diff --git a/src/commands/git/pull.ts b/src/commands/git/pull.ts index 4700b3074fedb..010da08373fc5 100644 --- a/src/commands/git/pull.ts +++ b/src/commands/git/pull.ts @@ -4,6 +4,7 @@ import { Container } from '../../container'; import { GitBranch, GitBranchReference, GitReference, Repository } from '../../git/git'; import { Directive, DirectiveQuickPickItem, FlagsQuickPickItem } from '../../quickpicks'; import { Arrays, Dates, Strings } from '../../system'; +import { ViewsWithRepositoryFolders } from '../../views/viewBase'; import { appendReposToTitle, AsyncStepResultGenerator, @@ -20,6 +21,7 @@ import { interface Context { repos: Repository[]; + associatedView: ViewsWithRepositoryFolders; title: string; } @@ -74,6 +76,7 @@ export class PullGitCommand extends QuickCommand { protected async *steps(state: PartialStepState): StepGenerator { const context: Context = { repos: Container.instance.git.openRepositories, + associatedView: Container.instance.commitsView, title: this.title, }; diff --git a/src/commands/git/push.ts b/src/commands/git/push.ts index 404d89dbe6445..7b3f3d55dcadf 100644 --- a/src/commands/git/push.ts +++ b/src/commands/git/push.ts @@ -5,6 +5,7 @@ import { Container } from '../../container'; import { GitBranch, GitBranchReference, GitReference, Repository } from '../../git/git'; import { Directive, DirectiveQuickPickItem, FlagsQuickPickItem } from '../../quickpicks'; import { Arrays, Dates, Strings } from '../../system'; +import { ViewsWithRepositoryFolders } from '../../views/viewBase'; import { appendReposToTitle, AsyncStepResultGenerator, @@ -22,6 +23,7 @@ import { interface Context { repos: Repository[]; + associatedView: ViewsWithRepositoryFolders; title: string; } @@ -80,6 +82,7 @@ export class PushGitCommand extends QuickCommand { protected async *steps(state: PartialStepState): StepGenerator { const context: Context = { repos: Container.instance.git.openRepositories, + associatedView: Container.instance.commitsView, title: this.title, }; diff --git a/src/commands/git/rebase.ts b/src/commands/git/rebase.ts index 77ac61b7a6a2a..f046ccfc6f211 100644 --- a/src/commands/git/rebase.ts +++ b/src/commands/git/rebase.ts @@ -4,6 +4,7 @@ import { Container } from '../../container'; import { GitBranch, GitLog, GitReference, GitRevision, Repository } from '../../git/git'; import { Directive, DirectiveQuickPickItem, FlagsQuickPickItem } from '../../quickpicks'; import { Strings } from '../../system'; +import { ViewsWithRepositoryFolders } from '../../views/viewBase'; import { appendReposToTitle, AsyncStepResultGenerator, @@ -22,6 +23,7 @@ import { interface Context { repos: Repository[]; + associatedView: ViewsWithRepositoryFolders; cache: Map>; destination: GitBranch; pickCommit: boolean; @@ -99,6 +101,7 @@ export class RebaseGitCommand extends QuickCommand { protected async *steps(state: PartialStepState): StepGenerator { const context: Context = { repos: Container.instance.git.openRepositories, + associatedView: Container.instance.commitsView, cache: new Map>(), destination: undefined!, pickCommit: false, diff --git a/src/commands/git/reset.ts b/src/commands/git/reset.ts index 5a7c77f7f1e45..9c78b8ea8722d 100644 --- a/src/commands/git/reset.ts +++ b/src/commands/git/reset.ts @@ -2,6 +2,7 @@ import { Container } from '../../container'; import { GitBranch, GitLog, GitReference, GitRevisionReference, Repository } from '../../git/git'; import { FlagsQuickPickItem } from '../../quickpicks'; +import { ViewsWithRepositoryFolders } from '../../views/viewBase'; import { appendReposToTitle, PartialStepState, @@ -18,6 +19,7 @@ import { interface Context { repos: Repository[]; + associatedView: ViewsWithRepositoryFolders; cache: Map>; destination: GitBranch; title: string; @@ -72,6 +74,7 @@ export class ResetGitCommand extends QuickCommand { protected async *steps(state: PartialStepState): StepGenerator { const context: Context = { repos: Container.instance.git.openRepositories, + associatedView: Container.instance.commitsView, cache: new Map>(), destination: undefined!, title: this.title, diff --git a/src/commands/git/revert.ts b/src/commands/git/revert.ts index 7e544389f38ac..90950b367a977 100644 --- a/src/commands/git/revert.ts +++ b/src/commands/git/revert.ts @@ -2,6 +2,7 @@ import { Container } from '../../container'; import { GitBranch, GitLog, GitReference, GitRevisionReference, Repository } from '../../git/git'; import { FlagsQuickPickItem } from '../../quickpicks'; +import { ViewsWithRepositoryFolders } from '../../views/viewBase'; import { appendReposToTitle, PartialStepState, @@ -18,6 +19,7 @@ import { interface Context { repos: Repository[]; + associatedView: ViewsWithRepositoryFolders; cache: Map>; destination: GitBranch; title: string; @@ -74,6 +76,7 @@ export class RevertGitCommand extends QuickCommand { protected async *steps(state: PartialStepState): StepGenerator { const context: Context = { repos: Container.instance.git.openRepositories, + associatedView: Container.instance.commitsView, cache: new Map>(), destination: undefined!, title: this.title, diff --git a/src/commands/git/search.ts b/src/commands/git/search.ts index 730f5d2e603c2..d6bc67f7769f3 100644 --- a/src/commands/git/search.ts +++ b/src/commands/git/search.ts @@ -5,6 +5,7 @@ import { GitLog, GitLogCommit, Repository, SearchOperators, searchOperators, Sea import { ActionQuickPickItem, QuickPickItemOfT } from '../../quickpicks'; import { Strings } from '../../system'; import { SearchResultsNode } from '../../views/nodes'; +import { ViewsWithRepositoryFolders } from '../../views/viewBase'; import { GitCommandsCommand } from '../gitCommands'; import { appendReposToTitle, @@ -22,6 +23,7 @@ import { interface Context { repos: Repository[]; + associatedView: ViewsWithRepositoryFolders; commit: GitLogCommit | undefined; resultsKey: string | undefined; resultsPromise: Promise | undefined; @@ -92,6 +94,7 @@ export class SearchGitCommand extends QuickCommand { protected async *steps(state: PartialStepState): StepGenerator { const context: Context = { repos: Container.instance.git.openRepositories, + associatedView: Container.instance.searchAndCompareView, commit: undefined, resultsKey: undefined, resultsPromise: undefined, diff --git a/src/commands/git/show.ts b/src/commands/git/show.ts index 0f48fb8de6f30..2526f5ca38c6d 100644 --- a/src/commands/git/show.ts +++ b/src/commands/git/show.ts @@ -2,6 +2,7 @@ import { Container } from '../../container'; import { GitAuthor, GitLogCommit, GitRevisionReference, GitStashCommit, Repository } from '../../git/git'; import { CommandQuickPickItem, CommitFilesQuickPickItem, GitCommandQuickPickItem } from '../../quickpicks'; +import { ViewsWithRepositoryFolders } from '../../views/viewBase'; import { PartialStepState, pickCommitStep, @@ -17,6 +18,7 @@ import { interface Context { repos: Repository[]; + associatedView: ViewsWithRepositoryFolders; title: string; } @@ -77,6 +79,7 @@ export class ShowGitCommand extends QuickCommand { protected async *steps(state: PartialStepState): StepGenerator { const context: Context = { repos: Container.instance.git.openRepositories, + associatedView: Container.instance.commitsView, title: this.title, }; diff --git a/src/commands/git/stash.ts b/src/commands/git/stash.ts index 75dcf1d51c6f6..0b26b56c6a92d 100644 --- a/src/commands/git/stash.ts +++ b/src/commands/git/stash.ts @@ -8,6 +8,7 @@ import { Logger } from '../../logger'; import { Messages } from '../../messages'; import { FlagsQuickPickItem, QuickPickItemOfT } from '../../quickpicks'; import { Strings } from '../../system'; +import { ViewsWithRepositoryFolders } from '../../views/viewBase'; import { GitActions, GitCommandsCommand } from '../gitCommands'; import { appendReposToTitle, @@ -27,6 +28,7 @@ import { interface Context { repos: Repository[]; + associatedView: ViewsWithRepositoryFolders; title: string; } @@ -145,6 +147,7 @@ export class StashGitCommand extends QuickCommand { protected async *steps(state: PartialStepState): StepGenerator { const context: Context = { repos: Container.instance.git.openRepositories, + associatedView: Container.instance.stashesView, title: this.title, }; diff --git a/src/commands/git/status.ts b/src/commands/git/status.ts index 60cab0aa77cd5..c985e714b2d6a 100644 --- a/src/commands/git/status.ts +++ b/src/commands/git/status.ts @@ -4,6 +4,7 @@ import { Container } from '../../container'; import { GitReference, GitStatus, Repository } from '../../git/git'; import { CommandQuickPickItem, GitCommandQuickPickItem } from '../../quickpicks'; import { Strings } from '../../system'; +import { ViewsWithRepositoryFolders } from '../../views/viewBase'; import { PartialStepState, pickRepositoryStep, @@ -16,6 +17,7 @@ import { interface Context { repos: Repository[]; + associatedView: ViewsWithRepositoryFolders; status: GitStatus; title: string; } @@ -56,6 +58,7 @@ export class StatusGitCommand extends QuickCommand { protected async *steps(state: PartialStepState): StepGenerator { const context: Context = { repos: Container.instance.git.openRepositories, + associatedView: Container.instance.commitsView, status: undefined!, title: this.title, }; diff --git a/src/commands/git/switch.ts b/src/commands/git/switch.ts index 609da7923ff9a..fa4a930c4de6e 100644 --- a/src/commands/git/switch.ts +++ b/src/commands/git/switch.ts @@ -4,6 +4,7 @@ import { BranchSorting } from '../../config'; import { Container } from '../../container'; import { GitReference, Repository } from '../../git/git'; import { Arrays } from '../../system'; +import { ViewsWithRepositoryFolders } from '../../views/viewBase'; import { appendReposToTitle, inputBranchNameStep, @@ -21,6 +22,7 @@ import { interface Context { repos: Repository[]; + associatedView: ViewsWithRepositoryFolders; showTags: boolean; title: string; } @@ -89,6 +91,7 @@ export class SwitchGitCommand extends QuickCommand { protected async *steps(state: PartialStepState): StepGenerator { const context: Context = { repos: Container.instance.git.openRepositories, + associatedView: Container.instance.commitsView, showTags: false, title: this.title, }; diff --git a/src/commands/git/tag.ts b/src/commands/git/tag.ts index 2544c57344501..2566bd8896cd7 100644 --- a/src/commands/git/tag.ts +++ b/src/commands/git/tag.ts @@ -4,6 +4,7 @@ import { Container } from '../../container'; import { GitReference, GitTagReference, Repository } from '../../git/git'; import { FlagsQuickPickItem, QuickPickItemOfT } from '../../quickpicks'; import { Strings } from '../../system'; +import { ViewsWithRepositoryFolders } from '../../views/viewBase'; import { appendReposToTitle, AsyncStepResultGenerator, @@ -23,6 +24,7 @@ import { interface Context { repos: Repository[]; + associatedView: ViewsWithRepositoryFolders; showTags: boolean; title: string; } @@ -128,6 +130,7 @@ export class TagGitCommand extends QuickCommand { protected async *steps(state: PartialStepState): StepGenerator { const context: Context = { repos: Container.instance.git.openRepositories, + associatedView: Container.instance.tagsView, showTags: false, title: this.title, }; diff --git a/src/commands/gitCommands.actions.ts b/src/commands/gitCommands.actions.ts index af7e11df68f61..5430c9765619d 100644 --- a/src/commands/gitCommands.actions.ts +++ b/src/commands/gitCommands.actions.ts @@ -11,7 +11,7 @@ import { GitCommandsCommandArgs, OpenWorkingFileCommandArgs, } from '../commands'; -import { configuration, FileAnnotationType } from '../configuration'; +import { FileAnnotationType } from '../configuration'; import { Container } from '../container'; import { GitBranchReference, @@ -28,6 +28,7 @@ import { } from '../git/git'; import { GitUri } from '../git/gitUri'; import { RepositoryPicker } from '../quickpicks'; +import { ViewsWithRepositoryFolders } from '../views/viewBase'; import { ResetGitCommandArgs } from './git/reset'; export async function executeGitCommand(args: GitCommandsCommandArgs): Promise { @@ -150,21 +151,10 @@ export namespace GitActions { expand?: boolean | number; }, ) { - if ( - !configuration.get(`views.${branch.remote ? 'remotes' : 'branches'}.reveal` as const) || - (Container.instance.repositoriesView.visible && - !(branch.remote ? Container.instance.remotesView.visible : Container.instance.branchesView.visible)) - ) { - return Container.instance.repositoriesView.revealBranch(branch, options); - } - - let node; - if (branch.remote) { - node = await Container.instance.remotesView.revealBranch(branch, options); - } else { - node = await Container.instance.branchesView.revealBranch(branch, options); - } - + const view = branch.remote ? Container.instance.remotesView : Container.instance.branchesView; + const node = view.canReveal + ? await view.revealBranch(branch, options) + : await Container.instance.repositoriesView.revealBranch(branch, options); return node; } } @@ -650,23 +640,20 @@ export namespace GitActions { expand?: boolean | number; }, ) { - if ( - !configuration.get('views.commits.reveal') || - (Container.instance.repositoriesView.visible && !Container.instance.commitsView.visible) - ) { - return Container.instance.repositoriesView.revealCommit(commit, options); - } + const views = [ + Container.instance.commitsView, + Container.instance.branchesView, + Container.instance.remotesView, + ]; // TODO@eamodio stop duplicate notifications - let node = await Container.instance.commitsView.revealCommit(commit, options); - if (node != null) return node; - - node = await Container.instance.branchesView.revealCommit(commit, options); - if (node != null) return node; - - node = await Container.instance.remotesView.revealCommit(commit, options); - if (node != null) return node; + for (const view of views) { + const node = view.canReveal + ? await view.revealCommit(commit, options) + : await Container.instance.repositoriesView.revealCommit(commit, options); + if (node != null) return node; + } return undefined; } @@ -679,48 +666,19 @@ export namespace GitActions { state: { repo: repo, contributors: contributors }, }); } - } - - export namespace Tag { - export function create(repo?: string | Repository, ref?: GitReference, name?: string) { - return executeGitCommand({ - command: 'tag', - state: { - subcommand: 'create', - repo: repo, - reference: ref, - name: name, - }, - }); - } - - export function remove(repo?: string | Repository, refs?: GitTagReference | GitTagReference[]) { - return executeGitCommand({ - command: 'tag', - state: { - subcommand: 'delete', - repo: repo, - references: refs, - }, - }); - } export async function reveal( - tag: GitTagReference, + contributor: GitContributor, options?: { select?: boolean; focus?: boolean; expand?: boolean | number; }, ) { - if ( - !configuration.get('views.tags.reveal') || - (Container.instance.repositoriesView.visible && !Container.instance.tagsView.visible) - ) { - return Container.instance.repositoriesView.revealTag(tag, options); - } - - const node = await Container.instance.tagsView.revealTag(tag, options); + const view = Container.instance.contributorsView; + const node = view.canReveal + ? await view.revealContributor(contributor, options) + : await Container.instance.repositoriesView.revealContributor(contributor, options); return node; } } @@ -783,14 +741,27 @@ export namespace GitActions { expand?: boolean | number; }, ) { - // if ( - // configuration.get('views.repositories.enabled') && - // (Container.instance.repositoriesView.visible || !Container.instance.remotesView.visible) - // ) { - // return Container.instance.repositoriesView.revealRemote(remote, options); - // } - - const node = await Container.instance.remotesView.revealRemote(remote, options); + const view = Container.instance.remotesView; + const node = view.canReveal + ? await view.revealRemote(remote, options) + : await Container.instance.repositoriesView.revealRemote(remote, options); + return node; + } + } + + export namespace Repository { + export async function reveal( + repoPath: string, + view?: ViewsWithRepositoryFolders, + options?: { + select?: boolean; + focus?: boolean; + expand?: boolean | number; + }, + ) { + const node = view?.canReveal + ? await view.revealRepository(repoPath, options) + : await Container.instance.repositoriesView.revealRepository(repoPath, options); return node; } } @@ -838,14 +809,50 @@ export namespace GitActions { expand?: boolean | number; }, ) { - if ( - !configuration.get('views.stashes.reveal') || - (Container.instance.repositoriesView.visible && !Container.instance.stashesView.visible) - ) { - return Container.instance.repositoriesView.revealStash(stash, options); - } + const view = Container.instance.stashesView; + const node = view.canReveal + ? await view.revealStash(stash, options) + : await Container.instance.repositoriesView.revealStash(stash, options); + return node; + } + } + + export namespace Tag { + export function create(repo?: string | Repository, ref?: GitReference, name?: string) { + return executeGitCommand({ + command: 'tag', + state: { + subcommand: 'create', + repo: repo, + reference: ref, + name: name, + }, + }); + } - const node = await Container.instance.stashesView.revealStash(stash, options); + export function remove(repo?: string | Repository, refs?: GitTagReference | GitTagReference[]) { + return executeGitCommand({ + command: 'tag', + state: { + subcommand: 'delete', + repo: repo, + references: refs, + }, + }); + } + + export async function reveal( + tag: GitTagReference, + options?: { + select?: boolean; + focus?: boolean; + expand?: boolean | number; + }, + ) { + const view = Container.instance.tagsView; + const node = view.canReveal + ? await view.revealTag(tag, options) + : await Container.instance.repositoriesView.revealTag(tag, options); return node; } } diff --git a/src/commands/quickCommand.steps.ts b/src/commands/quickCommand.steps.ts index c474bdbc7e7db..118dfd030b201 100644 --- a/src/commands/quickCommand.steps.ts +++ b/src/commands/quickCommand.steps.ts @@ -67,6 +67,7 @@ import { TagQuickPickItem, } from '../quickpicks'; import { Arrays, Iterables, Strings } from '../system'; +import { ViewsWithRepositoryFolders } from '../views/viewBase'; import { Commands } from './common'; import { GitActions } from './gitCommands.actions'; import { @@ -499,10 +500,7 @@ export async function* pickBranchStep< : branches, onDidClickItemButton: (quickpick, button, { item }) => { if (button === QuickCommandButtons.RevealInSideBar) { - void GitActions.Branch.reveal(item, { - select: true, - expand: true, - }); + void GitActions.Branch.reveal(item, { select: true, focus: false, expand: true }); } }, keys: ['right', 'alt+right', 'ctrl+right'], @@ -558,10 +556,7 @@ export async function* pickBranchesStep< : branches, onDidClickItemButton: (quickpick, button, { item }) => { if (button === QuickCommandButtons.RevealInSideBar) { - void GitActions.Branch.reveal(item, { - select: true, - expand: true, - }); + void GitActions.Branch.reveal(item, { select: true, focus: false, expand: true }); } }, keys: ['right', 'alt+right', 'ctrl+right'], @@ -644,11 +639,11 @@ export async function* pickBranchOrTagStep< if (button === QuickCommandButtons.RevealInSideBar) { if (GitReference.isBranch(item)) { - void GitActions.Branch.reveal(item, { select: true, expand: true }); + void GitActions.Branch.reveal(item, { select: true, focus: false, expand: true }); } else if (GitReference.isTag(item)) { - void GitActions.Tag.reveal(item, { select: true, expand: true }); + void GitActions.Tag.reveal(item, { select: true, focus: false, expand: true }); } else if (GitReference.isRevision(item)) { - void GitActions.Commit.reveal(item, { select: true, expand: true }); + void GitActions.Commit.reveal(item, { select: true, focus: false, expand: true }); } } return false; @@ -753,11 +748,11 @@ export async function* pickBranchOrTagStepMultiRepo< onDidClickItemButton: (quickpick, button, { item }) => { if (button === QuickCommandButtons.RevealInSideBar) { if (GitReference.isBranch(item)) { - void GitActions.Branch.reveal(item, { select: true, expand: true }); + void GitActions.Branch.reveal(item, { select: true, focus: false, expand: true }); } else if (GitReference.isTag(item)) { - void GitActions.Tag.reveal(item, { select: true, expand: true }); + void GitActions.Tag.reveal(item, { select: true, focus: false, expand: true }); } else if (GitReference.isRevision(item)) { - void GitActions.Commit.reveal(item, { select: true, expand: true }); + void GitActions.Commit.reveal(item, { select: true, focus: false, expand: true }); } } }, @@ -1102,8 +1097,25 @@ export async function* pickContributorsStep< placeholder: placeholder, matchOnDescription: true, items: (await Container.instance.git.getContributors(state.repo.path)).map(c => - ContributorQuickPickItem.create(c, message?.includes(c.toCoauthor())), + ContributorQuickPickItem.create(c, message?.includes(c.toCoauthor()), { + buttons: [QuickCommandButtons.RevealInSideBar], + }), ), + onDidClickItemButton: (quickpick, button, { item }) => { + if (button === QuickCommandButtons.RevealInSideBar) { + void GitActions.Contributor.reveal(item, { select: true, focus: false, expand: true }); + } + }, + keys: ['right', 'alt+right', 'ctrl+right'], + onDidPressKey: quickpick => { + if (quickpick.activeItems.length === 0) return; + + void GitActions.Contributor.reveal(quickpick.activeItems[0].item, { + select: true, + focus: false, + expand: true, + }); + }, }); const selection: StepSelection = yield step; return QuickCommand.canPickStepContinue(step, state, selection) ? selection.map(i => i.item) : StepResult.Break; @@ -1111,7 +1123,7 @@ export async function* pickContributorsStep< export async function* pickRepositoryStep< State extends PartialStepState & { repo?: string | Repository }, - Context extends { repos: Repository[]; title: string }, + Context extends { repos: Repository[]; title: string; associatedView: ViewsWithRepositoryFolders }, >(state: State, context: Context, placeholder: string = 'Choose a repository'): AsyncStepResultGenerator { if (typeof state.repo === 'string') { state.repo = await Container.instance.git.getRepository(state.repo); @@ -1137,8 +1149,9 @@ export async function* pickRepositoryStep< ), onDidClickItemButton: (quickpick, button, { item }) => { if (button === QuickCommandButtons.RevealInSideBar) { - void Container.instance.repositoriesView.revealRepository(item.path, { + void GitActions.Repository.reveal(item.path, context.associatedView, { select: true, + focus: false, expand: true, }); } @@ -1147,7 +1160,7 @@ export async function* pickRepositoryStep< onDidPressKey: quickpick => { if (quickpick.activeItems.length === 0) return; - void Container.instance.repositoriesView.revealRepository(quickpick.activeItems[0].item.path, { + void GitActions.Repository.reveal(quickpick.activeItems[0].item.path, context.associatedView, { select: true, focus: false, expand: true, @@ -1160,7 +1173,7 @@ export async function* pickRepositoryStep< export async function* pickRepositoriesStep< State extends PartialStepState & { repos?: string[] | Repository[] }, - Context extends { repos: Repository[]; title: string }, + Context extends { repos: Repository[]; title: string; associatedView: ViewsWithRepositoryFolders }, >( state: State, context: Context, @@ -1206,8 +1219,9 @@ export async function* pickRepositoriesStep< ), onDidClickItemButton: (quickpick, button, { item }) => { if (button === QuickCommandButtons.RevealInSideBar) { - void Container.instance.repositoriesView.revealRepository(item.path, { + void GitActions.Repository.reveal(item.path, context.associatedView, { select: true, + focus: false, expand: true, }); } @@ -1216,7 +1230,7 @@ export async function* pickRepositoriesStep< onDidPressKey: quickpick => { if (quickpick.activeItems.length === 0) return; - void Container.instance.repositoriesView.revealRepository(quickpick.activeItems[0].item.path, { + void GitActions.Repository.reveal(quickpick.activeItems[0].item.path, context.associatedView, { select: true, focus: false, expand: true, @@ -1331,6 +1345,7 @@ export async function* pickTagsStep< if (button === QuickCommandButtons.RevealInSideBar) { void GitActions.Tag.reveal(item, { select: true, + focus: false, expand: true, }); } diff --git a/src/config.ts b/src/config.ts index 4667644a446af..bb9215977f4e9 100644 --- a/src/config.ts +++ b/src/config.ts @@ -565,6 +565,7 @@ export interface ContributorsViewConfig { enabled: boolean; showForCommits: boolean; }; + reveal: boolean; showAllBranches: boolean; showStatistics: boolean; } diff --git a/src/git/models/models.ts b/src/git/models/models.ts index a69dcf1a8b943..30008cad7d25f 100644 --- a/src/git/models/models.ts +++ b/src/git/models/models.ts @@ -251,7 +251,7 @@ export namespace GitReference { export function toString( refs: GitReference | GitReference[] | undefined, - options?: { capitalize?: boolean; expand?: boolean; icon?: boolean; label?: boolean } | false, + options?: { capitalize?: boolean; expand?: boolean; icon?: boolean; label?: boolean; quoted?: boolean } | false, ) { if (refs == null) return ''; @@ -263,15 +263,16 @@ export namespace GitReference { let result; if (!Array.isArray(refs) || refs.length === 1) { const ref = Array.isArray(refs) ? refs[0] : refs; + let refName = options?.quoted ? `'${ref.name}'` : ref.name; switch (ref.refType) { case 'branch': result = `${options.label ? `${ref.remote ? 'remote ' : ''}branch ` : ''}${ - options.icon ? `$(git-branch)${GlyphChars.Space}${ref.name}${GlyphChars.Space}` : ref.name + options.icon ? `$(git-branch)${GlyphChars.Space}${refName}${GlyphChars.Space}` : refName }`; break; case 'tag': result = `${options.label ? 'tag ' : ''}${ - options.icon ? `$(tag)${GlyphChars.Space}${ref.name}${GlyphChars.Space}` : ref.name + options.icon ? `$(tag)${GlyphChars.Space}${refName}${GlyphChars.Space}` : refName }`; break; default: { @@ -291,7 +292,7 @@ export namespace GitReference { : `${message ?? ref.number ?? ref.name}` }`; } else if (GitRevision.isRange(ref.ref)) { - result = ref.name; + result = refName; } else { let message; if (options.expand && ref.message) { @@ -301,20 +302,21 @@ export namespace GitReference { : ` (${ref.message})`; } - let name; let prefix; if (options.expand && options.label && GitRevision.isShaParent(ref.ref)) { - name = ref.name.endsWith('^') ? ref.name.substr(0, ref.name.length - 1) : ref.name; + refName = ref.name.endsWith('^') ? ref.name.substr(0, ref.name.length - 1) : ref.name; + if (options?.quoted) { + refName = `'${refName}'`; + } prefix = 'before '; } else { - name = ref.name; prefix = ''; } result = `${options.label ? `${prefix}commit ` : ''}${ options.icon - ? `$(git-commit)${GlyphChars.Space}${name}${message ?? ''}${GlyphChars.Space}` - : `${name}${message ?? ''}` + ? `$(git-commit)${GlyphChars.Space}${refName}${message ?? ''}${GlyphChars.Space}` + : `${refName}${message ?? ''}` }`; } break; diff --git a/src/quickpicks/gitQuickPickItems.ts b/src/quickpicks/gitQuickPickItems.ts index 87872ba775f5b..d479c8607d66d 100644 --- a/src/quickpicks/gitQuickPickItems.ts +++ b/src/quickpicks/gitQuickPickItems.ts @@ -42,8 +42,8 @@ export namespace BranchQuickPickItem { options: { alwaysShow?: boolean; buttons?: QuickInputButton[]; - current?: boolean | 'checkmark'; checked?: boolean; + current?: boolean | 'checkmark'; ref?: boolean; status?: boolean; type?: boolean | 'remote'; @@ -225,12 +225,13 @@ export namespace ContributorQuickPickItem { export function create( contributor: GitContributor, picked?: boolean, - options: { alwaysShow?: boolean } = {}, + options: { alwaysShow?: boolean; buttons?: QuickInputButton[] } = {}, ): ContributorQuickPickItem { const item: ContributorQuickPickItem = { label: contributor.name, description: contributor.email, alwaysShow: options.alwaysShow, + buttons: options.buttons, picked: picked, item: contributor, }; @@ -249,7 +250,7 @@ export namespace RefQuickPickItem { ref: string | GitReference, repoPath: string, picked?: boolean, - options: { alwaysShow?: boolean; buttons?: QuickInputButton[]; ref?: boolean; icon?: boolean } = {}, + options: { alwaysShow?: boolean; buttons?: QuickInputButton[]; icon?: boolean; ref?: boolean } = {}, ): RefQuickPickItem { if (ref === '') { return { @@ -399,8 +400,8 @@ export namespace TagQuickPickItem { options: { alwaysShow?: boolean; buttons?: QuickInputButton[]; - message?: boolean; checked?: boolean; + message?: boolean; ref?: boolean; type?: boolean; } = {}, diff --git a/src/views/branchesView.ts b/src/views/branchesView.ts index ef5e5e09477df..f6acbc4baa2c7 100644 --- a/src/views/branchesView.ts +++ b/src/views/branchesView.ts @@ -120,7 +120,11 @@ export class BranchesView extends ViewBase super('gitlens.views.branches', 'Branches', container); } - getRoot() { + override get canReveal(): boolean { + return this.config.reveal || !configuration.get('views.repositories.showBranches'); + } + + protected getRoot() { return new BranchesViewNode(this); } @@ -278,7 +282,7 @@ export class BranchesView extends ViewBase return window.withProgress( { location: ProgressLocation.Notification, - title: `Revealing ${GitReference.toString(branch, { icon: false })} in the side bar...`, + title: `Revealing ${GitReference.toString(branch, { icon: false, quoted: true })} in the side bar...`, cancellable: true, }, async (progress, token) => { @@ -304,7 +308,7 @@ export class BranchesView extends ViewBase return window.withProgress( { location: ProgressLocation.Notification, - title: `Revealing ${GitReference.toString(commit, { icon: false })} in the side bar...`, + title: `Revealing ${GitReference.toString(commit, { icon: false, quoted: true })} in the side bar...`, cancellable: true, }, async (progress, token) => { @@ -318,6 +322,23 @@ export class BranchesView extends ViewBase ); } + @gate(() => '') + async revealRepository( + repoPath: string, + options?: { select?: boolean; focus?: boolean; expand?: boolean | number }, + ) { + const node = await this.findNode(RepositoryFolderNode.getId(repoPath), { + maxDepth: 1, + canTraverse: n => n instanceof BranchesViewNode || n instanceof RepositoryFolderNode, + }); + + if (node !== undefined) { + await this.reveal(node, options); + } + + return node; + } + private setLayout(layout: ViewBranchesLayout) { return configuration.updateEffective(`views.${this.configKey}.branches.layout` as const, layout); } diff --git a/src/views/commitsView.ts b/src/views/commitsView.ts index b0101c04b8dd5..5f53077f5d2da 100644 --- a/src/views/commitsView.ts +++ b/src/views/commitsView.ts @@ -183,12 +183,16 @@ export class CommitsView extends ViewBase { super('gitlens.views.commits', 'Commits', container); } + override get canReveal(): boolean { + return this.config.reveal || !configuration.get('views.repositories.showCommits'); + } + private readonly _state: CommitsViewState = {}; get state(): CommitsViewState { return this._state; } - getRoot() { + protected getRoot() { return new CommitsViewNode(this); } @@ -343,7 +347,7 @@ export class CommitsView extends ViewBase { return window.withProgress( { location: ProgressLocation.Notification, - title: `Revealing ${GitReference.toString(commit, { icon: false })} in the side bar...`, + title: `Revealing ${GitReference.toString(commit, { icon: false, quoted: true })} in the side bar...`, cancellable: true, }, async (progress, token) => { @@ -357,6 +361,23 @@ export class CommitsView extends ViewBase { ); } + @gate(() => '') + async revealRepository( + repoPath: string, + options?: { select?: boolean; focus?: boolean; expand?: boolean | number }, + ) { + const node = await this.findNode(RepositoryFolderNode.getId(repoPath), { + maxDepth: 1, + canTraverse: n => n instanceof CommitsViewNode || n instanceof RepositoryFolderNode, + }); + + if (node !== undefined) { + await this.reveal(node, options); + } + + return node; + } + private setFilesLayout(layout: ViewFilesLayout) { return configuration.updateEffective(`views.${this.configKey}.files.layout` as const, layout); } diff --git a/src/views/contributorsView.ts b/src/views/contributorsView.ts index a3eea707443a7..bd5df7cef1e8a 100644 --- a/src/views/contributorsView.ts +++ b/src/views/contributorsView.ts @@ -1,13 +1,29 @@ 'use strict'; -import { commands, ConfigurationChangeEvent, Disposable, TreeItem, TreeItemCollapsibleState } from 'vscode'; +import { + CancellationToken, + commands, + ConfigurationChangeEvent, + Disposable, + ProgressLocation, + TreeItem, + TreeItemCollapsibleState, + window, +} from 'vscode'; import { Avatars } from '../avatars'; import { configuration, ContributorsViewConfig, ViewFilesLayout } from '../configuration'; import { GlyphChars } from '../constants'; import { Container } from '../container'; -import { RepositoryChange, RepositoryChangeComparisonMode, RepositoryChangeEvent } from '../git/git'; +import { GitContributor, RepositoryChange, RepositoryChangeComparisonMode, RepositoryChangeEvent } from '../git/git'; import { GitUri } from '../git/gitUri'; -import { debug, Strings } from '../system'; -import { ContributorsNode, RepositoriesSubscribeableNode, RepositoryFolderNode, ViewNode } from './nodes'; +import { debug, gate, Strings } from '../system'; +import { + ContributorNode, + ContributorsNode, + RepositoriesSubscribeableNode, + RepositoryFolderNode, + RepositoryNode, + ViewNode, +} from './nodes'; import { ViewBase } from './viewBase'; export class ContributorsRepositoryNode extends RepositoryFolderNode { @@ -110,7 +126,11 @@ export class ContributorsView extends ViewBase { + if (n instanceof ContributorsViewNode) return true; + + if (n instanceof ContributorsRepositoryNode) { + return n.id.startsWith(repoNodeId); + } + + return false; + }, + token: token, + }); + } + + @gate(() => '') + async revealRepository( + repoPath: string, + options?: { select?: boolean; focus?: boolean; expand?: boolean | number }, + ) { + const node = await this.findNode(RepositoryFolderNode.getId(repoPath), { + maxDepth: 1, + canTraverse: n => n instanceof ContributorsViewNode || n instanceof RepositoryFolderNode, + }); + + if (node !== undefined) { + await this.reveal(node, options); + } + + return node; + } + + @gate(() => '') + async revealContributor( + contributor: GitContributor, + options?: { + select?: boolean; + focus?: boolean; + expand?: boolean | number; + }, + ) { + return window.withProgress( + { + location: ProgressLocation.Notification, + title: `Revealing contributor '${contributor.name}' in the side bar...`, + cancellable: true, + }, + async (progress, token) => { + const node = await this.findContributor(contributor, token); + if (node == null) return undefined; + + await this.ensureRevealNode(node, options); + + return node; + }, + ); + } + private setFilesLayout(layout: ViewFilesLayout) { return configuration.updateEffective(`views.${this.configKey}.files.layout` as const, layout); } diff --git a/src/views/lineHistoryView.ts b/src/views/lineHistoryView.ts index 8f48f5dfac98c..de50b241524cd 100644 --- a/src/views/lineHistoryView.ts +++ b/src/views/lineHistoryView.ts @@ -21,7 +21,7 @@ export class LineHistoryView extends ViewBase { super('gitlens.views.remotes', 'Remotes', container); } - getRoot() { + override get canReveal(): boolean { + return this.config.reveal || !configuration.get('views.repositories.showRemotes'); + } + + protected getRoot() { return new RemotesViewNode(this); } @@ -297,7 +301,7 @@ export class RemotesView extends ViewBase { return window.withProgress( { location: ProgressLocation.Notification, - title: `Revealing ${GitReference.toString(branch, { icon: false })} in the side bar...`, + title: `Revealing ${GitReference.toString(branch, { icon: false, quoted: true })} in the side bar...`, cancellable: true, }, async (progress, token) => { @@ -323,7 +327,7 @@ export class RemotesView extends ViewBase { return window.withProgress( { location: ProgressLocation.Notification, - title: `Revealing ${GitReference.toString(commit, { icon: false })} in the side bar...`, + title: `Revealing ${GitReference.toString(commit, { icon: false, quoted: true })} in the side bar...`, cancellable: true, }, async (progress, token) => { @@ -349,7 +353,7 @@ export class RemotesView extends ViewBase { return window.withProgress( { location: ProgressLocation.Notification, - title: `Revealing remote ${remote.name} in the side bar...`, + title: `Revealing remote '${remote.name}' in the side bar...`, cancellable: true, }, async (progress, token) => { @@ -363,6 +367,23 @@ export class RemotesView extends ViewBase { ); } + @gate(() => '') + async revealRepository( + repoPath: string, + options?: { select?: boolean; focus?: boolean; expand?: boolean | number }, + ) { + const node = await this.findNode(RepositoryFolderNode.getId(repoPath), { + maxDepth: 1, + canTraverse: n => n instanceof RemotesViewNode || n instanceof RepositoryFolderNode, + }); + + if (node !== undefined) { + await this.reveal(node, options); + } + + return node; + } + private setLayout(layout: ViewBranchesLayout) { return configuration.updateEffective(`views.${this.configKey}.branches.layout` as const, layout); } diff --git a/src/views/repositoriesView.ts b/src/views/repositoriesView.ts index 69a4e1085850d..811b7cb0a9bd7 100644 --- a/src/views/repositoriesView.ts +++ b/src/views/repositoriesView.ts @@ -21,8 +21,10 @@ import { Container } from '../container'; import { GitBranch, GitBranchReference, + GitContributor, GitLogCommit, GitReference, + GitRemote, GitRevisionReference, GitStashReference, GitTagReference, @@ -34,6 +36,7 @@ import { BranchOrTagFolderNode, BranchTrackingStatusNode, CompareBranchNode, + ContributorNode, ContributorsNode, ReflogNode, RemoteNode, @@ -58,7 +61,7 @@ export class RepositoriesView extends ViewBase { - // Only search for commit nodes in the same repo within BranchNodes + // Only search for commit nodes in the same repo within BranchNode/RemoteNode if (n instanceof RepositoriesNode) return true; if (n instanceof RemoteNode) { @@ -389,6 +392,45 @@ export class RepositoriesView extends ViewBase { + // Only search for contributor nodes in the same repo within a ContributorsNode + if (n instanceof RepositoriesNode) return true; + + if (n instanceof RepositoryNode || n instanceof ContributorsNode) { + return n.id.startsWith(repoNodeId); + } + + return false; + }, + token: token, + }); + } + + findRemote(remote: GitRemote, token?: CancellationToken) { + const repoNodeId = RepositoryNode.getId(remote.repoPath); + + return this.findNode((n: any) => n.remote?.name === remote.name, { + allowPaging: true, + maxDepth: 2, + canTraverse: n => { + // Only search for remote nodes in the same repo within a RemotesNode + if (n instanceof RepositoriesNode) return true; + + if (n instanceof RepositoryNode || n instanceof RemotesNode) { + return n.id.startsWith(repoNodeId); + } + + return false; + }, + token: token, + }); + } + findStash(stash: GitStashReference, token?: CancellationToken) { const repoNodeId = RepositoryNode.getId(stash.repoPath); @@ -440,7 +482,10 @@ export class RepositoriesView extends ViewBase { @@ -498,7 +543,10 @@ export class RepositoriesView extends ViewBase { @@ -512,6 +560,58 @@ export class RepositoriesView extends ViewBase '') + async revealContributor( + contributor: GitContributor, + options?: { + select?: boolean; + focus?: boolean; + expand?: boolean | number; + }, + ) { + return window.withProgress( + { + location: ProgressLocation.Notification, + title: `Revealing contributor '${contributor.name} in the Repositories view...`, + cancellable: true, + }, + async (progress, token) => { + const node = await this.findContributor(contributor, token); + if (node == null) return undefined; + + await this.ensureRevealNode(node, options); + + return node; + }, + ); + } + + @gate(() => '') + revealRemote( + remote: GitRemote, + options?: { + select?: boolean; + focus?: boolean; + expand?: boolean | number; + }, + ) { + return window.withProgress( + { + location: ProgressLocation.Notification, + title: `Revealing remote '${remote.name}' in the side bar...`, + cancellable: true, + }, + async (progress, token) => { + const node = await this.findRemote(remote, token); + if (node == null) return undefined; + + await this.ensureRevealNode(node, options); + + return node; + }, + ); + } + @gate(() => '') async revealRepository( repoPath: string, @@ -525,16 +625,7 @@ export class RepositoriesView extends ViewBase { - // Only search for branches nodes in the same repo - if (n instanceof RepositoriesNode) return true; - - // if (n instanceof RepositoryNode) { - // return n.id.startsWith(repoNodeId); - // } - - return false; - }, + canTraverse: n => n instanceof RepositoriesNode, }); if (node !== undefined) { @@ -556,7 +647,7 @@ export class RepositoriesView extends ViewBase { @@ -614,7 +705,7 @@ export class RepositoriesView extends ViewBase { diff --git a/src/views/searchAndCompareView.ts b/src/views/searchAndCompareView.ts index 0ab4853a94e43..3637c642af5d0 100644 --- a/src/views/searchAndCompareView.ts +++ b/src/views/searchAndCompareView.ts @@ -10,6 +10,7 @@ import { debug, gate, Iterables, log, Promises } from '../system'; import { CompareResultsNode, ContextValues, + RepositoryFolderNode, ResultsFilesNode, SearchResultsNode, unknownGitUri, @@ -258,7 +259,7 @@ export class SearchAndCompareView extends ViewBase '') + async revealRepository( + repoPath: string, + options?: { select?: boolean; focus?: boolean; expand?: boolean | number }, + ) { + const node = await this.findNode(RepositoryFolderNode.getId(repoPath), { + maxDepth: 1, + canTraverse: n => n instanceof SearchAndCompareViewNode || n instanceof RepositoryFolderNode, + }); + + if (node !== undefined) { + await this.reveal(node, options); + } + + return node; + } + private async addResults( results: CompareResultsNode | SearchResultsNode, options: { diff --git a/src/views/stashesView.ts b/src/views/stashesView.ts index c950aa7b67ee3..9613f5208db7a 100644 --- a/src/views/stashesView.ts +++ b/src/views/stashesView.ts @@ -102,7 +102,11 @@ export class StashesView extends ViewBase { super('gitlens.views.stashes', 'Stashes', container); } - getRoot() { + override get canReveal(): boolean { + return this.config.reveal || !configuration.get('views.repositories.showStashes'); + } + + protected getRoot() { return new StashesViewNode(this); } @@ -176,6 +180,23 @@ export class StashesView extends ViewBase { }); } + @gate(() => '') + async revealRepository( + repoPath: string, + options?: { select?: boolean; focus?: boolean; expand?: boolean | number }, + ) { + const node = await this.findNode(RepositoryFolderNode.getId(repoPath), { + maxDepth: 1, + canTraverse: n => n instanceof StashesViewNode || n instanceof RepositoryFolderNode, + }); + + if (node !== undefined) { + await this.reveal(node, options); + } + + return node; + } + @gate(() => '') async revealStash( stash: GitStashReference, @@ -188,7 +209,7 @@ export class StashesView extends ViewBase { return window.withProgress( { location: ProgressLocation.Notification, - title: `Revealing ${GitReference.toString(stash, { icon: false })} in the side bar...`, + title: `Revealing ${GitReference.toString(stash, { icon: false, quoted: true })} in the side bar...`, cancellable: true, }, async (progress, token) => { diff --git a/src/views/tagsView.ts b/src/views/tagsView.ts index a27db50f2b58b..b98b356eec676 100644 --- a/src/views/tagsView.ts +++ b/src/views/tagsView.ts @@ -102,7 +102,11 @@ export class TagsView extends ViewBase { super('gitlens.views.tags', 'Tags', container); } - getRoot() { + override get canReveal(): boolean { + return this.config.reveal || !configuration.get('views.repositories.showTags'); + } + + protected getRoot() { return new TagsViewNode(this); } @@ -198,6 +202,23 @@ export class TagsView extends ViewBase { }); } + @gate(() => '') + async revealRepository( + repoPath: string, + options?: { select?: boolean; focus?: boolean; expand?: boolean | number }, + ) { + const node = await this.findNode(RepositoryFolderNode.getId(repoPath), { + maxDepth: 1, + canTraverse: n => n instanceof TagsViewNode || n instanceof RepositoryFolderNode, + }); + + if (node !== undefined) { + await this.reveal(node, options); + } + + return node; + } + @gate(() => '') revealTag( tag: GitTagReference, @@ -210,7 +231,7 @@ export class TagsView extends ViewBase { return window.withProgress( { location: ProgressLocation.Notification, - title: `Revealing ${GitReference.toString(tag, { icon: false })} in the side bar...`, + title: `Revealing ${GitReference.toString(tag, { icon: false, quoted: true })} in the side bar...`, cancellable: true, }, async (progress, token) => { diff --git a/src/views/viewBase.ts b/src/views/viewBase.ts index 8a2ef517dfa6c..60d2207954180 100644 --- a/src/views/viewBase.ts +++ b/src/views/viewBase.ts @@ -59,6 +59,7 @@ export type View = | StashesView | TagsView; export type ViewsWithCommits = Exclude; +export type ViewsWithRepositoryFolders = Exclude; export interface TreeViewNodeCollapsibleStateChangeEvent extends TreeViewExpansionEvent { state: TreeItemCollapsibleState; @@ -163,6 +164,10 @@ export abstract class ViewBase< queueMicrotask(() => this.onConfigurationChanged()); } + get canReveal(): boolean { + return true; + } + protected get showCollapseAll(): boolean { return true; } @@ -353,8 +358,8 @@ export abstract class ViewBase< // If we have no root (e.g. never been initialized) force it so the tree will load properly await this.show({ preserveFocus: true }); - // Since we have to show the view, let the callstack unwind before we try to find the node - return new Promise(resolve => queueMicrotask(() => resolve(find.call(this)))); + // Since we have to show the view, give the view time to load and let the callstack unwind before we try to find the node + return new Promise(resolve => setTimeout(() => resolve(find.call(this)), 100)); } private async findNodeCoreBFS(