From 2892a465d839fca8613e04ec67186206ddf70b9f Mon Sep 17 00:00:00 2001 From: Eric Amodio Date: Sat, 15 Jun 2019 00:44:56 -0400 Subject: [PATCH] Adds sorting/filtering to branch/tag methods Consolidates more reusable logic into GitService --- src/annotations/annotations.ts | 2 +- src/commands/openBranchInRemote.ts | 4 +- src/commands/openFileInRemote.ts | 4 +- src/git/formatters/commitFormatter.ts | 6 - src/git/gitService.ts | 207 ++++++++++++++++++----- src/git/models/repository.ts | 11 +- src/quickpicks/branchHistoryQuickPick.ts | 2 +- src/quickpicks/commitFileQuickPick.ts | 2 +- src/quickpicks/commitQuickPick.ts | 2 +- src/quickpicks/fileHistoryQuickPick.ts | 2 +- src/quickpicks/referencesQuickPick.ts | 104 ++++-------- src/views/nodes/branchNode.ts | 7 +- src/views/nodes/branchesNode.ts | 25 +-- src/views/nodes/contributorNode.ts | 4 +- src/views/nodes/helpers.ts | 21 --- src/views/nodes/remoteNode.ts | 23 +-- src/views/nodes/remotesNode.ts | 10 +- src/views/nodes/resultsCommitsNode.ts | 4 +- src/views/nodes/tagNode.ts | 4 +- src/views/nodes/tagsNode.ts | 3 +- 20 files changed, 241 insertions(+), 206 deletions(-) diff --git a/src/annotations/annotations.ts b/src/annotations/annotations.ts index 161153ae8982c..9b17ec0c343b3 100644 --- a/src/annotations/annotations.ts +++ b/src/annotations/annotations.ts @@ -195,7 +195,7 @@ export class Annotations { const [presence, previousLineDiffUris, remotes] = await Promise.all([ Container.vsls.getContactPresence(commit.email), commit.isUncommitted ? commit.getPreviousLineDiffUris(uri, editorLine, uri.sha) : undefined, - Container.git.getRemotes(commit.repoPath) + Container.git.getRemotes(commit.repoPath, { sort: true }) ]); const markdown = new MarkdownString( diff --git a/src/commands/openBranchInRemote.ts b/src/commands/openBranchInRemote.ts index 8c9527269f134..c5121657ffa50 100644 --- a/src/commands/openBranchInRemote.ts +++ b/src/commands/openBranchInRemote.ts @@ -58,9 +58,7 @@ export class OpenBranchInRemoteCommand extends ActiveEditorCommand { { autoPick: true, checkmarks: false, - filters: { - branches: b => b.tracking !== undefined - }, + filterBranches: b => b.tracking !== undefined, include: 'branches' } ); diff --git a/src/commands/openFileInRemote.ts b/src/commands/openFileInRemote.ts index 2cb61b619ebbe..3a3a9f8caddc4 100644 --- a/src/commands/openFileInRemote.ts +++ b/src/commands/openFileInRemote.ts @@ -87,9 +87,7 @@ export class OpenFileInRemoteCommand extends ActiveEditorCommand { { autoPick: true, checkmarks: false, - filters: { - branches: b => b.tracking !== undefined - }, + filterBranches: b => b.tracking !== undefined, include: 'branches' } ); diff --git a/src/git/formatters/commitFormatter.ts b/src/git/formatters/commitFormatter.ts index 0b24c5475a738..5805b51d0b96a 100644 --- a/src/git/formatters/commitFormatter.ts +++ b/src/git/formatters/commitFormatter.ts @@ -306,12 +306,6 @@ export class CommitFormatter extends Formatter { } if (this._options.remotes !== undefined) { - this._options.remotes.sort( - (a, b) => - (a.default ? -1 : 1) - (b.default ? -1 : 1) || - a.name.localeCompare(b.name, undefined, { numeric: true, sensitivity: 'base' }) - ); - for (const r of this._options.remotes) { if (r.provider === undefined) continue; diff --git a/src/git/gitService.ts b/src/git/gitService.ts index b9d72311edb8c..4846e794ad58c 100644 --- a/src/git/gitService.ts +++ b/src/git/gitService.ts @@ -25,7 +25,7 @@ import { CommandContext, DocumentSchemes, setCommandContext } from '../constants import { Container } from '../container'; import { LogCorrelationContext, Logger } from '../logger'; import { Messages } from '../messages'; -import { gate, Iterables, log, Objects, Strings, TernarySearchTree, Versions } from '../system'; +import { Arrays, gate, Iterables, log, Objects, Strings, TernarySearchTree, Versions } from '../system'; import { CachedBlame, CachedDiff, CachedLog, GitDocumentState, TrackedDocument } from '../trackers/gitDocumentTracker'; import { vslsUriPrefixRegex } from '../vsls/vsls'; import { @@ -972,32 +972,118 @@ export class GitService implements Disposable { } @log() - async getBranches(repoPath: string | undefined): Promise { + async getBranches( + repoPath: string | undefined, + options: { filter?: (b: GitBranch) => boolean; sort?: boolean } = {} + ): Promise { if (repoPath === undefined) return []; - let branches; - if (this.useCaching) { - branches = this._branchesCache.get(repoPath); - if (branches !== undefined) return branches; + let branches: GitBranch[] | undefined; + try { + if (this.useCaching) { + branches = this._branchesCache.get(repoPath); + if (branches !== undefined) return branches; + } + + const data = await Git.for_each_ref__branch(repoPath, { all: true }); + // If we don't get any data, assume the repo doesn't have any commits yet so check if we have a current branch + if (data == null || data.length === 0) { + const current = await this.getBranch(repoPath); + branches = current !== undefined ? [current] : []; + } + else { + branches = GitBranchParser.parse(data, repoPath); + } + + if (this.useCaching) { + const repo = await this.getRepository(repoPath); + if (repo !== undefined && repo.supportsChangeEvents) { + this._branchesCache.set(repoPath, branches); + } + } + + return branches; } + finally { + if (options.filter !== undefined) { + branches = branches!.filter(options.filter); + } - const data = await Git.for_each_ref__branch(repoPath, { all: true }); - // If we don't get any data, assume the repo doesn't have any commits yet so check if we have a current branch - if (data == null || data.length === 0) { - const current = await this.getBranch(repoPath); - branches = current !== undefined ? [current] : []; + if (options.sort) { + branches!.sort( + (a, b) => + (a.starred ? -1 : 1) - (b.starred ? -1 : 1) || + (b.remote ? -1 : 1) - (a.remote ? -1 : 1) || + a.name.localeCompare(b.name, undefined, { numeric: true, sensitivity: 'base' }) + ); + } + + if (options.filter !== undefined) { + // eslint-disable-next-line no-unsafe-finally + return branches!; + } } - else { - branches = GitBranchParser.parse(data, repoPath); + } + + @log() + async getBranchesAndOrTags( + repoPath: string | undefined, + { + filterBranches, + filterTags, + include, + ...options + }: { + filterBranches?: (b: GitBranch) => boolean; + filterTags?: (t: GitTag) => boolean; + include?: 'all' | 'branches' | 'tags'; + sort?: boolean; + } = {} + ) { + const [branches, tags] = await Promise.all([ + include === 'all' || include === 'branches' + ? Container.git.getBranches(repoPath, { + ...options, + filter: filterBranches && filterBranches + }) + : undefined, + include === 'all' || include === 'tags' + ? Container.git.getTags(repoPath, { + ...options, + filter: filterTags && filterTags + }) + : undefined + ]); + + if (branches !== undefined && tags !== undefined) { + return [...branches.filter(b => !b.remote), ...tags, ...branches.filter(b => b.remote)]; } - if (this.useCaching) { - const repo = await this.getRepository(repoPath); - if (repo !== undefined && repo.supportsChangeEvents) { - this._branchesCache.set(repoPath, branches); - } + if (branches !== undefined) { + return branches; } - return branches; + + return tags; + } + + @log() + async getBranchesAndTagsTipsFn(repoPath: string | undefined, currentName?: string) { + const [branches, tags] = await Promise.all([ + Container.git.getBranches(repoPath), + Container.git.getTags(repoPath, { includeRefs: true }) + ]); + + const branchesAndTagsBySha = Arrays.groupByFilterMap( + (branches as { name: string; sha: string }[]).concat(tags as { name: string; sha: string }[]), + bt => bt.sha!, + bt => (bt.name === currentName ? undefined : bt.name) + ); + + return (sha: string) => { + const branchesAndTags = branchesAndTagsBySha.get(sha); + if (branchesAndTags === undefined || branchesAndTags.length === 0) return undefined; + return branchesAndTags.join(', '); + }; } @log() @@ -1981,18 +2067,27 @@ export class GitService implements Disposable { } @log() - async getRemotes(repoPath: string | undefined, options: { includeAll?: boolean } = {}): Promise { + async getRemotes( + repoPath: string | undefined, + options: { includeAll?: boolean; sort?: boolean } = {} + ): Promise { if (repoPath === undefined) return []; const repository = await this.getRepository(repoPath); - const remotes = repository !== undefined ? repository.getRemotes() : this.getRemotesCore(repoPath); + const remotes = await (repository !== undefined + ? repository.getRemotes({ sort: options.sort }) + : this.getRemotesCore(repoPath, undefined, { sort: options.sort })); if (options.includeAll) return remotes; - return (await remotes).filter(r => r.provider !== undefined); + return remotes.filter(r => r.provider !== undefined); } - async getRemotesCore(repoPath: string | undefined, providers?: RemoteProviders): Promise { + async getRemotesCore( + repoPath: string | undefined, + providers?: RemoteProviders, + options: { sort?: boolean } = {} + ): Promise { if (repoPath === undefined) return []; providers = @@ -2003,7 +2098,18 @@ export class GitService implements Disposable { try { const data = await Git.remote(repoPath); - return GitRemoteParser.parse(data, repoPath, RemoteProviderFactory.factory(providers)) || []; + const remotes = GitRemoteParser.parse(data, repoPath, RemoteProviderFactory.factory(providers)); + if (remotes === undefined) return []; + + if (options.sort) { + remotes.sort( + (a, b) => + (a.default ? -1 : 1) - (b.default ? -1 : 1) || + a.name.localeCompare(b.name, undefined, { numeric: true, sensitivity: 'base' }) + ); + } + + return remotes; } catch (ex) { Logger.error(ex); @@ -2236,37 +2342,56 @@ export class GitService implements Disposable { } @log() - async getTags(repoPath: string | undefined, options: { includeRefs?: boolean } = {}): Promise { + async getTags( + repoPath: string | undefined, + options: { filter?: (t: GitTag) => boolean; includeRefs?: boolean; sort?: boolean } = {} + ): Promise { if (repoPath === undefined) return []; - let tags; - if (options.includeRefs) { - tags = this._tagsWithRefsCache.get(repoPath); + let tags: GitTag[] | undefined; + try { + if (options.includeRefs) { + tags = this._tagsWithRefsCache.get(repoPath); + if (tags !== undefined) return tags; + + const data = await Git.show_ref__tags(repoPath); + tags = GitTagParser.parseWithRef(data, repoPath) || []; + + const repo = await this.getRepository(repoPath); + if (repo !== undefined && repo.supportsChangeEvents) { + this._tagsWithRefsCache.set(repoPath, tags); + } + + return tags; + } + + tags = this._tagsCache.get(repoPath); if (tags !== undefined) return tags; - const data = await Git.show_ref__tags(repoPath); - tags = GitTagParser.parseWithRef(data, repoPath) || []; + const data = await Git.tag(repoPath); + tags = GitTagParser.parse(data, repoPath) || []; const repo = await this.getRepository(repoPath); if (repo !== undefined && repo.supportsChangeEvents) { - this._tagsWithRefsCache.set(repoPath, tags); + this._tagsCache.set(repoPath, tags); } return tags; } + finally { + if (options.filter !== undefined) { + tags = tags!.filter(options.filter); + } - tags = this._tagsCache.get(repoPath); - if (tags !== undefined) return tags; - - const data = await Git.tag(repoPath); - tags = GitTagParser.parse(data, repoPath) || []; + if (options.sort) { + tags!.sort((a, b) => a.name.localeCompare(b.name, undefined, { numeric: true, sensitivity: 'base' })); + } - const repo = await this.getRepository(repoPath); - if (repo !== undefined && repo.supportsChangeEvents) { - this._tagsCache.set(repoPath, tags); + if (options.filter !== undefined) { + // eslint-disable-next-line no-unsafe-finally + return tags!; + } } - - return tags; } @log() diff --git a/src/git/models/repository.ts b/src/git/models/repository.ts index 464d1539a5fe5..39afff40d5d62 100644 --- a/src/git/models/repository.ts +++ b/src/git/models/repository.ts @@ -263,8 +263,8 @@ export class Repository implements Disposable { return this._branch; } - getBranches(): Promise { - return Container.git.getBranches(this.path); + getBranches(options: { filter?: (b: GitBranch) => boolean; sort?: boolean } = {}): Promise { + return Container.git.getBranches(this.path, options); } getChangedFilesCount(sha?: string): Promise { @@ -284,7 +284,7 @@ export class Repository implements Disposable { ); } - getRemotes(): Promise { + getRemotes(options: { sort?: boolean } = {}): Promise { if (this._remotes === undefined || !this.supportsChangeEvents) { if (this._providers === undefined) { const remotesCfg = configuration.get( @@ -294,7 +294,8 @@ export class Repository implements Disposable { this._providers = RemoteProviderFactory.loadProviders(remotesCfg); } - this._remotes = Container.git.getRemotesCore(this.path, this._providers); + // Since we are caching the results, always sort + this._remotes = Container.git.getRemotesCore(this.path, this._providers, { sort: true }); } return this._remotes; @@ -308,7 +309,7 @@ export class Repository implements Disposable { return Container.git.getStatusForRepo(this.path); } - getTags(options?: { includeRefs?: boolean }): Promise { + getTags(options?: { filter?: (t: GitTag) => boolean; includeRefs?: boolean; sort?: boolean }): Promise { return Container.git.getTags(this.path, options); } diff --git a/src/quickpicks/branchHistoryQuickPick.ts b/src/quickpicks/branchHistoryQuickPick.ts index d6c17eac69e58..691a62dd890ed 100644 --- a/src/quickpicks/branchHistoryQuickPick.ts +++ b/src/quickpicks/branchHistoryQuickPick.ts @@ -55,7 +55,7 @@ export class BranchHistoryQuickPick { [uri, currentCommandArgs] ); - const remotes = await Container.git.getRemotes((uri && uri.repoPath) || log.repoPath); + const remotes = await Container.git.getRemotes((uri && uri.repoPath) || log.repoPath, { sort: true }); if (remotes.length) { items.splice( 0, diff --git a/src/quickpicks/commitFileQuickPick.ts b/src/quickpicks/commitFileQuickPick.ts index 46d9e661aba24..974794fce1fe3 100644 --- a/src/quickpicks/commitFileQuickPick.ts +++ b/src/quickpicks/commitFileQuickPick.ts @@ -191,7 +191,7 @@ export class CommitFileQuickPick { } items.push(new OpenCommitFileRevisionCommandQuickPickItem(commit)); - const remotes = await Container.git.getRemotes(commit.repoPath); + const remotes = await Container.git.getRemotes(commit.repoPath, { sort: true }); if (remotes.length) { if (workingUri && commit.status !== 'D') { const branch = await Container.git.getBranch(commit.repoPath); diff --git a/src/quickpicks/commitQuickPick.ts b/src/quickpicks/commitQuickPick.ts index 092aa03848703..e5cc0a432ab02 100644 --- a/src/quickpicks/commitQuickPick.ts +++ b/src/quickpicks/commitQuickPick.ts @@ -293,7 +293,7 @@ export class CommitQuickPick { else { items.splice(index++, 0, new ShowCommitInViewQuickPickItem(commit)); - remotes = await Container.git.getRemotes(commit.repoPath); + remotes = await Container.git.getRemotes(commit.repoPath, { sort: true }); if (remotes.length) { items.splice( index++, diff --git a/src/quickpicks/fileHistoryQuickPick.ts b/src/quickpicks/fileHistoryQuickPick.ts index 66c41dbad1dfa..4f8f8b003e95a 100644 --- a/src/quickpicks/fileHistoryQuickPick.ts +++ b/src/quickpicks/fileHistoryQuickPick.ts @@ -159,7 +159,7 @@ export class FileHistoryQuickPick { ); } - const remotes = await Container.git.getRemotes(uri.repoPath!); + const remotes = await Container.git.getRemotes(uri.repoPath!, { sort: true }); if (remotes.length) { const resource: RemoteResource = uri.sha !== undefined diff --git a/src/quickpicks/referencesQuickPick.ts b/src/quickpicks/referencesQuickPick.ts index 36c1c292563bc..d01fee053d105 100644 --- a/src/quickpicks/referencesQuickPick.ts +++ b/src/quickpicks/referencesQuickPick.ts @@ -37,7 +37,7 @@ export class BranchQuickPickItem implements QuickPickItem { description: string; detail: string | undefined; - constructor(public readonly branch: GitBranch, showCheckmarks: boolean, checked: boolean | undefined) { + constructor(public readonly branch: GitBranch, showCheckmarks: boolean, checked?: boolean) { checked = showCheckmarks && (checked || (checked === undefined && branch.current)); this.label = `${ checked ? `$(check)${GlyphChars.Space.repeat(2)}` : showCheckmarks ? GlyphChars.Space.repeat(6) : '' @@ -71,7 +71,7 @@ export class TagQuickPickItem implements QuickPickItem { description: string; detail: string | undefined; - constructor(public readonly tag: GitTag, showCheckmarks: boolean, checked: boolean) { + constructor(public readonly tag: GitTag, showCheckmarks: boolean, checked?: boolean) { checked = showCheckmarks && checked; this.label = `${ checked ? `$(check)${GlyphChars.Space.repeat(2)}` : showCheckmarks ? GlyphChars.Space.repeat(6) : '' @@ -103,10 +103,8 @@ export interface ReferencesQuickPickOptions { autoPick?: boolean; checked?: string; checkmarks: boolean; - filters?: { - branches?(branch: GitBranch): boolean; - tags?(tag: GitTag): boolean; - }; + filterBranches?(branch: GitBranch): boolean; + filterTags?(tag: GitTag): boolean; goBack?: CommandQuickPickItem; include?: 'branches' | 'tags' | 'all'; } @@ -216,75 +214,39 @@ export class ReferencesQuickPick { } } - private async getItems(options: ReferencesQuickPickOptions, token: CancellationToken) { - const { checked, checkmarks, filters, goBack, include } = { include: 'all', ...options }; - - let branches; - let tags; - switch (include) { - case 'branches': { - const result = await Functions.cancellable(Container.git.getBranches(this.repoPath), token); - if (result === undefined || token.isCancellationRequested) return []; - - branches = result; - break; - } - case 'tags': { - const result = await Functions.cancellable(Container.git.getTags(this.repoPath), token); - if (result === undefined || token.isCancellationRequested) return []; - - tags = result; - break; - } - default: { - const result = await Functions.cancellable( - Promise.all([Container.git.getBranches(this.repoPath), Container.git.getTags(this.repoPath)]), - token - ); - if (result === undefined || token.isCancellationRequested) return []; - - [branches, tags] = result; - break; - } - } + private async getItems( + { checked, checkmarks, goBack, ...options }: ReferencesQuickPickOptions, + token: CancellationToken + ) { + const branchesAndOrTags = await Functions.cancellable( + Container.git.getBranchesAndOrTags(this.repoPath, { + include: options.include || 'all', + filterBranches: options.filterBranches, + filterTags: options.filterTags, + sort: true + }), + token + ); + if (branchesAndOrTags === undefined || token.isCancellationRequested) return []; const items: (BranchQuickPickItem | TagQuickPickItem | CommandQuickPickItem)[] = []; - if (branches !== undefined) { - const filter = - filters !== undefined && typeof filters.branches === 'function' ? filters.branches : undefined; - - branches.sort( - (a, b) => - (a.starred ? -1 : 1) - (b.starred ? -1 : 1) || - (b.remote ? -1 : 1) - (a.remote ? -1 : 1) || - a.name.localeCompare(b.name, undefined, { numeric: true, sensitivity: 'base' }) - ); - for (const b of branches) { - if (filter !== undefined && !filter(b)) continue; - - if (checkmarks && checked !== undefined && b.name === checked) { - items.splice(0, 0, new BranchQuickPickItem(b, checkmarks, true)); - } - else { - items.push(new BranchQuickPickItem(b, checkmarks, checked === undefined ? undefined : false)); - } + for (const bt of branchesAndOrTags) { + if (checkmarks && checked === bt.name) { + items.splice( + 0, + 0, + new (GitBranch.is(bt) ? BranchQuickPickItem : TagQuickPickItem)(bt as any, checkmarks, true) + ); } - } - - if (tags !== undefined) { - const filter = filters !== undefined && typeof filters.tags === 'function' ? filters.tags : undefined; - - tags.sort((a, b) => a.name.localeCompare(b.name, undefined, { numeric: true, sensitivity: 'base' })); - for (const t of tags) { - if (filter !== undefined && !filter(t)) continue; - - if (checkmarks && checked !== undefined && t.name === checked) { - items.splice(0, 0, new TagQuickPickItem(t, checkmarks, true)); - } - else { - items.push(new TagQuickPickItem(t, checkmarks, false)); - } + else { + items.push( + new (GitBranch.is(bt) ? BranchQuickPickItem : TagQuickPickItem)( + bt as any, + checkmarks, + checked === undefined ? undefined : false + ) + ); } } diff --git a/src/views/nodes/branchNode.ts b/src/views/nodes/branchNode.ts index dd03d52f68b47..d6bcdaec19fb6 100644 --- a/src/views/nodes/branchNode.ts +++ b/src/views/nodes/branchNode.ts @@ -9,7 +9,7 @@ import { RepositoriesView } from '../repositoriesView'; import { BranchTrackingStatusNode } from './branchTrackingStatusNode'; import { CommitNode } from './commitNode'; import { MessageNode, ShowMoreNode } from './common'; -import { getBranchesAndTagTipsFn, insertDateMarkers } from './helpers'; +import { insertDateMarkers } from './helpers'; import { PageableViewNode, ResourceType, ViewNode, ViewRefNode } from './viewNode'; export class BranchNode extends ViewRefNode implements PageableViewNode { @@ -83,7 +83,10 @@ export class BranchNode extends ViewRefNode implements Pageabl }); if (log === undefined) return [new MessageNode(this.view, this, 'No commits could be found.')]; - const getBranchAndTagTips = await getBranchesAndTagTipsFn(this.uri.repoPath, this.branch.name); + const getBranchAndTagTips = await Container.git.getBranchesAndTagsTipsFn( + this.uri.repoPath, + this.branch.name + ); children.push( ...insertDateMarkers( Iterables.map( diff --git a/src/views/nodes/branchesNode.ts b/src/views/nodes/branchesNode.ts index 56d5e0bc98685..e5e3023bbce90 100644 --- a/src/views/nodes/branchesNode.ts +++ b/src/views/nodes/branchesNode.ts @@ -3,7 +3,7 @@ import { TreeItem, TreeItemCollapsibleState } from 'vscode'; import { ViewBranchesLayout } from '../../configuration'; import { Container } from '../../container'; import { GitUri, Repository } from '../../git/gitService'; -import { Arrays, debug, gate, Iterables } from '../../system'; +import { Arrays, debug, gate } from '../../system'; import { RepositoriesView } from '../repositoriesView'; import { BranchNode } from './branchNode'; import { BranchOrTagFolderNode } from './branchOrTagFolderNode'; @@ -22,21 +22,14 @@ export class BranchesNode extends ViewNode { async getChildren(): Promise { if (this._children === undefined) { - const branches = await this.repo.getBranches(); + const branches = await this.repo.getBranches({ + // only show local branches + filter: b => !b.remote, + sort: true + }); if (branches === undefined) return []; - branches.sort( - (a, b) => - (a.starred ? -1 : 1) - (b.starred ? -1 : 1) || - a.name.localeCompare(b.name, undefined, { numeric: true, sensitivity: 'base' }) - ); - - // filter local branches - const branchNodes = [ - ...Iterables.filterMap(branches, b => - b.remote ? undefined : new BranchNode(this.uri, this.view, this, b) - ) - ]; + const branchNodes = branches.map(b => new BranchNode(this.uri, this.view, this, b)); if (this.view.config.branches.layout === ViewBranchesLayout.List) return branchNodes; const hierarchy = Arrays.makeHierarchical( @@ -62,11 +55,9 @@ export class BranchesNode extends ViewNode { } async getTreeItem(): Promise { - const remotes = await this.repo.getRemotes(); - const item = new TreeItem('Branches', TreeItemCollapsibleState.Collapsed); item.contextValue = ResourceType.Branches; - if (remotes !== undefined && remotes.length > 0) { + if (await this.repo.hasRemotes()) { item.contextValue += '+remotes'; } item.iconPath = { diff --git a/src/views/nodes/contributorNode.ts b/src/views/nodes/contributorNode.ts index 9aa9fff9f5f2a..710c7ddfb76f7 100644 --- a/src/views/nodes/contributorNode.ts +++ b/src/views/nodes/contributorNode.ts @@ -6,7 +6,7 @@ import { RepositoriesView } from '../repositoriesView'; import { PageableViewNode, ResourceType, ViewNode } from './viewNode'; import { Container } from '../../container'; import { MessageNode, ShowMoreNode } from './common'; -import { getBranchesAndTagTipsFn, insertDateMarkers } from './helpers'; +import { insertDateMarkers } from './helpers'; import { CommitNode } from './commitNode'; import { GlyphChars } from '../../constants'; @@ -30,7 +30,7 @@ export class ContributorNode extends ViewNode implements Pagea }); if (log === undefined) return [new MessageNode(this.view, this, 'No commits could be found.')]; - const getBranchAndTagTips = await getBranchesAndTagTipsFn(this.uri.repoPath); + const getBranchAndTagTips = await Container.git.getBranchesAndTagsTipsFn(this.uri.repoPath); const children = [ ...insertDateMarkers( Iterables.map( diff --git a/src/views/nodes/helpers.ts b/src/views/nodes/helpers.ts index b7ded3c08d00f..4e7484b4d6556 100644 --- a/src/views/nodes/helpers.ts +++ b/src/views/nodes/helpers.ts @@ -1,29 +1,8 @@ 'use strict'; -import { Container } from '../../container'; import { GitLogCommit } from '../../git/gitService'; -import { Arrays } from '../../system'; import { MessageNode } from './common'; import { ViewNode } from './viewNode'; -export async function getBranchesAndTagTipsFn(repoPath: string | undefined, currentName?: string) { - const [branches, tags] = await Promise.all([ - Container.git.getBranches(repoPath), - Container.git.getTags(repoPath, { includeRefs: true }) - ]); - - const branchesAndTagsBySha = Arrays.groupByFilterMap( - (branches as { name: string; sha: string }[]).concat(tags as { name: string; sha: string }[]), - bt => bt.sha!, - bt => (bt.name === currentName ? undefined : bt.name) - ); - - return (sha: string) => { - const branchesAndTags = branchesAndTagsBySha.get(sha); - if (branchesAndTags === undefined || branchesAndTags.length === 0) return undefined; - return branchesAndTags.join(', '); - }; -} - const markers: [number, string][] = [ [0, 'Less than a week ago'], [7, 'Over a week ago'], diff --git a/src/views/nodes/remoteNode.ts b/src/views/nodes/remoteNode.ts index ff2744fa3fbc1..434c6118c2f93 100644 --- a/src/views/nodes/remoteNode.ts +++ b/src/views/nodes/remoteNode.ts @@ -4,7 +4,7 @@ import { ViewBranchesLayout } from '../../configuration'; import { GlyphChars } from '../../constants'; import { Container } from '../../container'; import { GitRemote, GitRemoteType, GitUri, Repository } from '../../git/gitService'; -import { Arrays, Iterables, log } from '../../system'; +import { Arrays, log } from '../../system'; import { RepositoriesView } from '../repositoriesView'; import { BranchNode } from './branchNode'; import { BranchOrTagFolderNode } from './branchOrTagFolderNode'; @@ -26,23 +26,14 @@ export class RemoteNode extends ViewNode { } async getChildren(): Promise { - const branches = await this.repo.getBranches(); + const branches = await this.repo.getBranches({ + // only show remote branchs for this remote + filter: b => b.remote && b.name.startsWith(this.remote.name), + sort: true + }); if (branches === undefined) return []; - branches.sort( - (a, b) => - (a.starred ? -1 : 1) - (b.starred ? -1 : 1) || - a.name.localeCompare(b.name, undefined, { numeric: true, sensitivity: 'base' }) - ); - - // filter remote branches - const branchNodes = [ - ...Iterables.filterMap(branches, b => - !b.remote || !b.name.startsWith(this.remote.name) - ? undefined - : new BranchNode(this.uri, this.view, this, b) - ) - ]; + const branchNodes = branches.map(b => new BranchNode(this.uri, this.view, this, b)); if (this.view.config.branches.layout === ViewBranchesLayout.List) return branchNodes; const hierarchy = Arrays.makeHierarchical( diff --git a/src/views/nodes/remotesNode.ts b/src/views/nodes/remotesNode.ts index 2106fb1ea30a0..4460a83a7b05e 100644 --- a/src/views/nodes/remotesNode.ts +++ b/src/views/nodes/remotesNode.ts @@ -2,7 +2,6 @@ import { TreeItem, TreeItemCollapsibleState } from 'vscode'; import { Container } from '../../container'; import { GitUri, Repository } from '../../git/gitService'; -import { Iterables } from '../../system'; import { RepositoriesView } from '../repositoriesView'; import { MessageNode } from './common'; import { RemoteNode } from './remoteNode'; @@ -18,17 +17,12 @@ export class RemotesNode extends ViewNode { } async getChildren(): Promise { - const remotes = await this.repo.getRemotes(); + const remotes = await this.repo.getRemotes({ sort: true }); if (remotes === undefined || remotes.length === 0) { return [new MessageNode(this.view, this, 'No remotes could be found')]; } - remotes.sort( - (a, b) => - (a.default ? -1 : 1) - (b.default ? -1 : 1) || - a.name.localeCompare(b.name, undefined, { numeric: true, sensitivity: 'base' }) - ); - return [...Iterables.map(remotes, r => new RemoteNode(this.uri, this.view, this, r, this.repo))]; + return remotes.map(r => new RemoteNode(this.uri, this.view, this, r, this.repo)); } getTreeItem(): TreeItem { diff --git a/src/views/nodes/resultsCommitsNode.ts b/src/views/nodes/resultsCommitsNode.ts index a4d97e2be6651..0e746667c3627 100644 --- a/src/views/nodes/resultsCommitsNode.ts +++ b/src/views/nodes/resultsCommitsNode.ts @@ -6,7 +6,7 @@ import { debug, gate, Iterables } from '../../system'; import { ViewWithFiles } from '../viewBase'; import { CommitNode } from './commitNode'; import { ShowMoreNode } from './common'; -import { getBranchesAndTagTipsFn, insertDateMarkers } from './helpers'; +import { insertDateMarkers } from './helpers'; import { PageableViewNode, ResourceType, ViewNode } from './viewNode'; export interface CommitsQueryResults { @@ -44,7 +44,7 @@ export class ResultsCommitsNode extends ViewNode implements Pagea const { log } = await this.getCommitsQueryResults(); if (log === undefined) return []; - const getBranchAndTagTips = await getBranchesAndTagTipsFn(this.uri.repoPath); + const getBranchAndTagTips = await Container.git.getBranchesAndTagsTipsFn(this.uri.repoPath); const children = [ ...insertDateMarkers( Iterables.map( diff --git a/src/views/nodes/tagNode.ts b/src/views/nodes/tagNode.ts index 16280e94a3492..97f55a9359771 100644 --- a/src/views/nodes/tagNode.ts +++ b/src/views/nodes/tagNode.ts @@ -7,7 +7,7 @@ import { Iterables } from '../../system'; import { RepositoriesView } from '../repositoriesView'; import { CommitNode } from './commitNode'; import { MessageNode, ShowMoreNode } from './common'; -import { getBranchesAndTagTipsFn, insertDateMarkers } from './helpers'; +import { insertDateMarkers } from './helpers'; import { PageableViewNode, ResourceType, ViewNode, ViewRefNode } from './viewNode'; import { emojify } from '../../emojis'; @@ -39,7 +39,7 @@ export class TagNode extends ViewRefNode implements PageableVi }); if (log === undefined) return [new MessageNode(this.view, this, 'No commits could be found.')]; - const getBranchAndTagTips = await getBranchesAndTagTipsFn(this.uri.repoPath, this.tag.name); + const getBranchAndTagTips = await Container.git.getBranchesAndTagsTipsFn(this.uri.repoPath, this.tag.name); const children = [ ...insertDateMarkers( Iterables.map( diff --git a/src/views/nodes/tagsNode.ts b/src/views/nodes/tagsNode.ts index 032d28fa8519f..c60eece58db01 100644 --- a/src/views/nodes/tagsNode.ts +++ b/src/views/nodes/tagsNode.ts @@ -20,10 +20,9 @@ export class TagsNode extends ViewNode { } async getChildren(): Promise { - const tags = await this.repo.getTags(); + const tags = await this.repo.getTags({ sort: true }); if (tags.length === 0) return [new MessageNode(this.view, this, 'No tags could be found.')]; - tags.sort((a, b) => a.name.localeCompare(b.name, undefined, { numeric: true, sensitivity: 'base' })); const tagNodes = tags.map(t => new TagNode(this.uri, this.view, this, t)); if (this.view.config.branches.layout === ViewBranchesLayout.List) return tagNodes;