Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions contributions.json
Original file line number Diff line number Diff line change
Expand Up @@ -5056,6 +5056,44 @@
]
}
},
"gitlens.views.branches.setShowRemoteBranchesOff": {
"label": "Hide Remote Branches",
"menus": {
"gitlens/views/grouped/more": [
{
"when": "view == gitlens.views.scm.grouped && gitlens:views:scm:grouped:view == branches && config.gitlens.views.branches.showRemoteBranches && !gitlens:hasVirtualFolders",
"group": "5_gitlens",
"order": 11
}
],
"view/title": [
{
"when": "view == gitlens.views.branches && config.gitlens.views.branches.showRemoteBranches && !gitlens:hasVirtualFolders",
"group": "5_gitlens",
"order": 11
}
]
}
},
"gitlens.views.branches.setShowRemoteBranchesOn": {
"label": "Show Remote Branches",
"menus": {
"gitlens/views/grouped/more": [
{
"when": "view == gitlens.views.scm.grouped && gitlens:views:scm:grouped:view == branches && !config.gitlens.views.branches.showRemoteBranches && !gitlens:hasVirtualFolders",
"group": "5_gitlens",
"order": 11
}
],
"view/title": [
{
"when": "view == gitlens.views.branches && !config.gitlens.views.branches.showRemoteBranches && !gitlens:hasVirtualFolders",
"group": "5_gitlens",
"order": 11
}
]
}
},
"gitlens.views.branches.setShowStashesOff": {
"label": "Hide Stashes",
"menus": {
Expand Down
43 changes: 43 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2369,6 +2369,13 @@
"title": "Branches View",
"order": 170,
"properties": {
"gitlens.views.branches.showRemoteBranches": {
"type": "boolean",
"default": false,
"markdownDescription": "Specifies whether to show remote branches for the default remote in the _Branches_ view",
"scope": "window",
"order": 8
},
"gitlens.views.branches.showStashes": {
"type": "boolean",
"default": false,
Expand Down Expand Up @@ -7612,6 +7619,14 @@
"command": "gitlens.views.branches.setShowBranchPullRequestOn",
"title": "Show Branch Pull Requests"
},
{
"command": "gitlens.views.branches.setShowRemoteBranchesOff",
"title": "Hide Remote Branches"
},
{
"command": "gitlens.views.branches.setShowRemoteBranchesOn",
"title": "Show Remote Branches"
},
{
"command": "gitlens.views.branches.setShowStashesOff",
"title": "Hide Stashes"
Expand Down Expand Up @@ -11239,6 +11254,14 @@
"command": "gitlens.views.branches.setShowBranchPullRequestOn",
"when": "false"
},
{
"command": "gitlens.views.branches.setShowRemoteBranchesOff",
"when": "false"
},
{
"command": "gitlens.views.branches.setShowRemoteBranchesOn",
"when": "false"
},
{
"command": "gitlens.views.branches.setShowStashesOff",
"when": "false"
Expand Down Expand Up @@ -14556,6 +14579,16 @@
"when": "view == gitlens.views.scm.grouped && gitlens:views:scm:grouped:view =~ /(branches|commits|contributors|remotes|repositories|tags|worktrees)/ && !config.gitlens.views.showRelativeDateMarkers",
"group": "5_gitlens@10"
},
{
"command": "gitlens.views.branches.setShowRemoteBranchesOff",
"when": "view == gitlens.views.scm.grouped && gitlens:views:scm:grouped:view == branches && config.gitlens.views.branches.showRemoteBranches && !gitlens:hasVirtualFolders",
"group": "5_gitlens@11"
},
{
"command": "gitlens.views.branches.setShowRemoteBranchesOn",
"when": "view == gitlens.views.scm.grouped && gitlens:views:scm:grouped:view == branches && !config.gitlens.views.branches.showRemoteBranches && !gitlens:hasVirtualFolders",
"group": "5_gitlens@11"
},
{
"command": "gitlens.views.branches.setShowStashesOff",
"when": "view == gitlens.views.scm.grouped && gitlens:views:scm:grouped:view == branches && config.gitlens.views.branches.showStashes && !gitlens:hasVirtualFolders",
Expand Down Expand Up @@ -16799,6 +16832,16 @@
"when": "view =~ /^gitlens\\.views\\.(branches|commits|contributors|fileHistory|lineHistory|remotes|repositories|tags|worktrees)/ && !config.gitlens.views.showRelativeDateMarkers",
"group": "5_gitlens@10"
},
{
"command": "gitlens.views.branches.setShowRemoteBranchesOff",
"when": "view == gitlens.views.branches && config.gitlens.views.branches.showRemoteBranches && !gitlens:hasVirtualFolders",
"group": "5_gitlens@11"
},
{
"command": "gitlens.views.branches.setShowRemoteBranchesOn",
"when": "view == gitlens.views.branches && !config.gitlens.views.branches.showRemoteBranches && !gitlens:hasVirtualFolders",
"group": "5_gitlens@11"
},
{
"command": "gitlens.views.branches.setShowStashesOff",
"when": "view == gitlens.views.branches && config.gitlens.views.branches.showStashes && !gitlens:hasVirtualFolders",
Expand Down
1 change: 1 addition & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -745,6 +745,7 @@ export interface BranchesViewConfig {
};
readonly reveal: boolean;
readonly showBranchComparison: false | Extract<ViewShowBranchComparison, 'branch'>;
readonly showRemoteBranches: boolean;
readonly showStashes: boolean;
}

Expand Down
1 change: 1 addition & 0 deletions src/constants.commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,7 @@ export type TreeViewCommands = `gitlens.views.${
| `setShowAvatars${'On' | 'Off'}`
| `setShowBranchComparison${'On' | 'Off'}`
| `setShowBranchPullRequest${'On' | 'Off'}`
| `setShowRemoteBranches${'On' | 'Off'}`
| `setShowStashes${'On' | 'Off'}`}`
| `commits.${
| 'copy'
Expand Down
8 changes: 7 additions & 1 deletion src/git/gitProviderService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ import type { GitBranchReference, GitReference, GitRevisionRange } from './model
import { createRevisionRange, isSha, isUncommitted, isUncommittedParent } from './models/reference';
import type { GitReflog } from './models/reflog';
import type { GitRemote } from './models/remote';
import { getRemoteThemeIconString, getVisibilityCacheKey } from './models/remote';
import { getDefaultRemoteOrHighlander, getRemoteThemeIconString, getVisibilityCacheKey } from './models/remote';
import type { RepositoryChangeEvent } from './models/repository';
import { Repository, RepositoryChange, RepositoryChangeComparisonMode } from './models/repository';
import type { GitStash } from './models/stash';
Expand Down Expand Up @@ -2319,6 +2319,12 @@ export class GitProviderService implements Disposable {
return undefined;
}

@log()
async getDefaultRemote(repoPath: string | Uri, _cancellation?: CancellationToken): Promise<GitRemote | undefined> {
const remotes = await this.getRemotes(repoPath, undefined, _cancellation);
return getDefaultRemoteOrHighlander(remotes);
}

@log()
async getRemote(
repoPath: string | Uri,
Expand Down
23 changes: 18 additions & 5 deletions src/git/models/branch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export type GitBranchStatus =

export interface BranchSortOptions {
current?: boolean;
groupByType?: boolean;
missingUpstream?: boolean;
orderBy?: BranchSorting;
openedWorktreesByBranch?: Set<string>;
Expand Down Expand Up @@ -311,7 +312,7 @@ export function isOfBranchRefType(branch: GitReference | undefined) {
}

export function sortBranches(branches: GitBranch[], options?: BranchSortOptions) {
options = { current: true, orderBy: configuration.get('sortBranchesBy'), ...options };
options = { current: true, groupByType: true, orderBy: configuration.get('sortBranchesBy'), ...options };

switch (options.orderBy) {
case 'date:asc':
Expand All @@ -324,7 +325,7 @@ export function sortBranches(branches: GitBranch[], options?: BranchSortOptions)
(options.openedWorktreesByBranch.has(b.id) ? -1 : 1)
: 0) ||
(a.starred ? -1 : 1) - (b.starred ? -1 : 1) ||
(b.remote ? -1 : 1) - (a.remote ? -1 : 1) ||
(options.groupByType ? (b.remote ? -1 : 1) - (a.remote ? -1 : 1) : 0) ||
(a.date == null ? -1 : a.date.getTime()) - (b.date == null ? -1 : b.date.getTime()) ||
sortCompare(a.name, b.name),
);
Expand All @@ -341,7 +342,7 @@ export function sortBranches(branches: GitBranch[], options?: BranchSortOptions)
(a.name === 'main' ? -1 : 1) - (b.name === 'main' ? -1 : 1) ||
(a.name === 'master' ? -1 : 1) - (b.name === 'master' ? -1 : 1) ||
(a.name === 'develop' ? -1 : 1) - (b.name === 'develop' ? -1 : 1) ||
(b.remote ? -1 : 1) - (a.remote ? -1 : 1) ||
(options.groupByType ? (b.remote ? -1 : 1) - (a.remote ? -1 : 1) : 0) ||
sortCompare(a.name, b.name),
);
case 'name:desc':
Expand All @@ -357,7 +358,7 @@ export function sortBranches(branches: GitBranch[], options?: BranchSortOptions)
(a.name === 'main' ? -1 : 1) - (b.name === 'main' ? -1 : 1) ||
(a.name === 'master' ? -1 : 1) - (b.name === 'master' ? -1 : 1) ||
(a.name === 'develop' ? -1 : 1) - (b.name === 'develop' ? -1 : 1) ||
(b.remote ? -1 : 1) - (a.remote ? -1 : 1) ||
(options.groupByType ? (b.remote ? -1 : 1) - (a.remote ? -1 : 1) : 0) ||
sortCompare(b.name, a.name),
);
case 'date:desc':
Expand All @@ -371,7 +372,7 @@ export function sortBranches(branches: GitBranch[], options?: BranchSortOptions)
(options.openedWorktreesByBranch.has(b.id) ? -1 : 1)
: 0) ||
(a.starred ? -1 : 1) - (b.starred ? -1 : 1) ||
(b.remote ? -1 : 1) - (a.remote ? -1 : 1) ||
(options.groupByType ? (b.remote ? -1 : 1) - (a.remote ? -1 : 1) : 0) ||
(b.date == null ? -1 : b.date.getTime()) - (a.date == null ? -1 : a.date.getTime()) ||
sortCompare(b.name, a.name),
);
Expand Down Expand Up @@ -414,3 +415,15 @@ export async function getLocalBranchByUpstream(

return undefined;
}

export async function getLocalBranchUpstreamNames(branches: PageableResult<GitBranch>): Promise<Set<string>> {
const remoteBranches = new Set<string>();

for await (const branch of branches.values()) {
if (!branch.remote && branch.upstream?.name != null) {
remoteBranches.add(branch.upstream.name);
}
}

return remoteBranches;
}
14 changes: 9 additions & 5 deletions src/git/models/remote.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { ColorTheme } from 'vscode';
import { Uri, window } from 'vscode';
import { GlyphChars } from '../../constants';
import { Container } from '../../container';
import type { Container } from '../../container';
import type { HostingIntegration } from '../../plus/integrations/integration';
import { memoize } from '../../system/decorators/memoize';
import { equalsIgnoreCase, sortCompare } from '../../system/string';
Expand All @@ -25,7 +25,7 @@ export class GitRemote<TProvider extends RemoteProvider | undefined = RemoteProv
) {}

get default() {
const defaultRemote = Container.instance.storage.getWorkspace('remote:default');
const defaultRemote = this.container.storage.getWorkspace('remote:default');
// Check for `this.remoteKey` matches to handle previously saved data
return this.name === defaultRemote || this.remoteKey === defaultRemote;
}
Expand Down Expand Up @@ -90,15 +90,19 @@ export class GitRemote<TProvider extends RemoteProvider | undefined = RemoteProv
}

async setAsDefault(value: boolean = true) {
const repository = Container.instance.git.getRepository(this.repoPath);
const repository = this.container.git.getRepository(this.repoPath);
await repository?.setRemoteAsDefault(this, value);
}
}

export function getDefaultRemoteOrHighlander<T extends GitRemote>(remotes: T[]): T | undefined {
return remotes.length === 1 ? remotes[0] : remotes.find(r => r.default);
}

export function getHighlanderProviders(remotes: GitRemote<RemoteProvider>[]) {
if (remotes.length === 0) return undefined;

const remote = remotes.length === 1 ? remotes[0] : remotes.find(r => r.default);
const remote = getDefaultRemoteOrHighlander(remotes);
if (remote != null) return [remote.provider];

const providerName = remotes[0].provider.name;
Expand All @@ -110,7 +114,7 @@ export function getHighlanderProviders(remotes: GitRemote<RemoteProvider>[]) {
export function getHighlanderProviderName(remotes: GitRemote<RemoteProvider>[]) {
if (remotes.length === 0) return undefined;

const remote = remotes.length === 1 ? remotes[0] : remotes.find(r => r.default);
const remote = getDefaultRemoteOrHighlander(remotes);
if (remote != null) return remote.provider.name;

const providerName = remotes[0].provider.name;
Expand Down
1 change: 1 addition & 0 deletions src/git/models/repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export type RepoGitProviderService = Pick<
| 'getBestRemotesWithProviders'
| 'getBestRemoteWithIntegration'
| 'getBranch'
| 'getDefaultRemote'
| 'getRemote'
| 'getTag'
| 'getWorktree'
Expand Down
18 changes: 18 additions & 0 deletions src/git/utils/remote-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { ThemeIcon } from 'vscode';
import type { IconPath } from '../../@types/vscode.iconpath';
import type { Container } from '../../container';
import { getIconPathUris } from '../../system/vscode/vscode';
import type { GitRemote } from '../models/remote';
import { getRemoteThemeIconString } from '../models/remote';

export function getRemoteIconPath(
container: Container,
remote: GitRemote | undefined,
options?: { avatars?: boolean },
): IconPath {
if (options?.avatars && remote?.provider?.icon != null) {
return getIconPathUris(container, `icon-${remote.provider.icon}.svg`);
}

return new ThemeIcon(getRemoteThemeIconString(remote));
}
7 changes: 6 additions & 1 deletion src/system/paging.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@ import type { PagedResult } from '../git/gitProvider';
export class PageableResult<T> {
private cached: Mutable<PagedResult<T>> | undefined;

constructor(private readonly fetch: (paging: PagedResult<T>['paging']) => Promise<PagedResult<T>>) {}
constructor(
private readonly fetch: (paging: PagedResult<T>['paging']) => Promise<PagedResult<T>>,
seed?: PagedResult<T>,
) {
this.cached = seed;
}

async *values(): AsyncIterable<NonNullable<T>> {
if (this.cached != null) {
Expand Down
22 changes: 21 additions & 1 deletion src/views/branchesView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,13 @@ export class BranchesViewNode extends RepositoriesSubscribeableNode<BranchesView
if (this.children.length === 1) {
const [child] = this.children;

const branches = await child.repo.git.getBranches({ filter: b => !b.remote });
const { showRemoteBranches } = this.view.config;
const defaultRemote = showRemoteBranches ? (await child.repo.git.getDefaultRemote())?.name : undefined;

const branches = await child.repo.git.getBranches({
filter: b =>
!b.remote || (showRemoteBranches && defaultRemote != null && b.getRemoteName() === defaultRemote),
});
if (branches.values.length === 0) {
this.view.message = 'No branches could be found.';
void child.ensureSubscription();
Expand Down Expand Up @@ -178,6 +184,16 @@ export class BranchesView extends ViewBase<'branches', BranchesViewNode, Branche
() => this.setShowBranchPullRequest(false),
this,
),
registerViewCommand(
this.getQualifiedCommand('setShowRemoteBranchesOn'),
() => this.setShowRemoteBranches(true),
this,
),
registerViewCommand(
this.getQualifiedCommand('setShowRemoteBranchesOff'),
() => this.setShowRemoteBranches(false),
this,
),
registerViewCommand(this.getQualifiedCommand('setShowStashesOn'), () => this.setShowStashes(true), this),
registerViewCommand(this.getQualifiedCommand('setShowStashesOff'), () => this.setShowStashes(false), this),
];
Expand Down Expand Up @@ -356,6 +372,10 @@ export class BranchesView extends ViewBase<'branches', BranchesViewNode, Branche
await configuration.updateEffective(`views.${this.configKey}.pullRequests.enabled` as const, enabled);
}

private setShowRemoteBranches(enabled: boolean) {
return configuration.updateEffective(`views.${this.configKey}.showRemoteBranches` as const, enabled);
}

private setShowStashes(enabled: boolean) {
return configuration.updateEffective(`views.${this.configKey}.showStashes` as const, enabled);
}
Expand Down
Loading
Loading