|
|
- import {
- CancellationToken,
- commands,
- ConfigurationChangeEvent,
- Disposable,
- ProgressLocation,
- TreeItem,
- TreeItemCollapsibleState,
- window,
- } from 'vscode';
- import {
- BranchesViewConfig,
- configuration,
- ViewBranchesLayout,
- ViewFilesLayout,
- ViewShowBranchComparison,
- } from '../configuration';
- import { Commands } from '../constants';
- import { Container } from '../container';
- import { GitUri } from '../git/gitUri';
- import {
- GitBranchReference,
- GitCommit,
- GitReference,
- GitRevisionReference,
- RepositoryChange,
- RepositoryChangeComparisonMode,
- RepositoryChangeEvent,
- } from '../git/models';
- import { executeCommand } from '../system/command';
- import { gate } from '../system/decorators/gate';
- import {
- BranchesNode,
- BranchNode,
- BranchOrTagFolderNode,
- RepositoriesSubscribeableNode,
- RepositoryFolderNode,
- RepositoryNode,
- ViewNode,
- } from './nodes';
- import { ViewBase } from './viewBase';
-
- export class BranchesRepositoryNode extends RepositoryFolderNode<BranchesView, BranchesNode> {
- async getChildren(): Promise<ViewNode[]> {
- if (this.child == null) {
- this.child = new BranchesNode(this.uri, this.view, this, this.repo);
- }
-
- return this.child.getChildren();
- }
-
- protected changed(e: RepositoryChangeEvent) {
- return e.changed(
- RepositoryChange.Config,
- RepositoryChange.Heads,
- RepositoryChange.Index,
- RepositoryChange.Remotes,
- RepositoryChange.RemoteProviders,
- RepositoryChange.Status,
- RepositoryChange.Unknown,
- RepositoryChangeComparisonMode.Any,
- );
- }
- }
-
- export class BranchesViewNode extends RepositoriesSubscribeableNode<BranchesView, BranchesRepositoryNode> {
- async getChildren(): Promise<ViewNode[]> {
- if (this.children == null) {
- const repositories = this.view.container.git.openRepositories;
- if (repositories.length === 0) {
- this.view.message = 'No branches could be found.';
-
- return [];
- }
-
- this.view.message = undefined;
-
- const splat = repositories.length === 1;
- this.children = repositories.map(
- r => new BranchesRepositoryNode(GitUri.fromRepoPath(r.path), this.view, this, r, splat),
- );
- }
-
- if (this.children.length === 1) {
- const [child] = this.children;
-
- const branches = await child.repo.getBranches({ filter: b => !b.remote });
- if (branches.values.length === 0) {
- this.view.message = 'No branches could be found.';
- this.view.title = 'Branches';
-
- void child.ensureSubscription();
-
- return [];
- }
-
- this.view.message = undefined;
- this.view.title = `Branches (${branches.values.length})`;
-
- return child.getChildren();
- }
-
- return this.children;
- }
-
- getTreeItem(): TreeItem {
- const item = new TreeItem('Branches', TreeItemCollapsibleState.Expanded);
- return item;
- }
- }
-
- export class BranchesView extends ViewBase<BranchesViewNode, BranchesViewConfig> {
- protected readonly configKey = 'branches';
-
- constructor(container: Container) {
- super('gitlens.views.branches', 'Branches', container);
- }
-
- override get canReveal(): boolean {
- return this.config.reveal || !configuration.get('views.repositories.showBranches');
- }
-
- protected getRoot() {
- return new BranchesViewNode(this);
- }
-
- protected registerCommands(): Disposable[] {
- void this.container.viewCommands;
-
- return [
- commands.registerCommand(
- this.getQualifiedCommand('copy'),
- () => executeCommand(Commands.ViewsCopy, this.selection),
- this,
- ),
- commands.registerCommand(
- this.getQualifiedCommand('refresh'),
- () => {
- this.container.git.resetCaches('branches');
- return this.refresh(true);
- },
- this,
- ),
- commands.registerCommand(
- this.getQualifiedCommand('setLayoutToList'),
- () => this.setLayout(ViewBranchesLayout.List),
- this,
- ),
- commands.registerCommand(
- this.getQualifiedCommand('setLayoutToTree'),
- () => this.setLayout(ViewBranchesLayout.Tree),
- this,
- ),
- commands.registerCommand(
- this.getQualifiedCommand('setFilesLayoutToAuto'),
- () => this.setFilesLayout(ViewFilesLayout.Auto),
- this,
- ),
- commands.registerCommand(
- this.getQualifiedCommand('setFilesLayoutToList'),
- () => this.setFilesLayout(ViewFilesLayout.List),
- this,
- ),
- commands.registerCommand(
- this.getQualifiedCommand('setFilesLayoutToTree'),
- () => this.setFilesLayout(ViewFilesLayout.Tree),
- this,
- ),
- commands.registerCommand(
- this.getQualifiedCommand('setShowAvatarsOn'),
- () => this.setShowAvatars(true),
- this,
- ),
- commands.registerCommand(
- this.getQualifiedCommand('setShowAvatarsOff'),
- () => this.setShowAvatars(false),
- this,
- ),
- commands.registerCommand(
- this.getQualifiedCommand('setShowBranchComparisonOn'),
- () => this.setShowBranchComparison(true),
- this,
- ),
- commands.registerCommand(
- this.getQualifiedCommand('setShowBranchComparisonOff'),
- () => this.setShowBranchComparison(false),
- this,
- ),
- commands.registerCommand(
- this.getQualifiedCommand('setShowBranchPullRequestOn'),
- () => this.setShowBranchPullRequest(true),
- this,
- ),
- commands.registerCommand(
- this.getQualifiedCommand('setShowBranchPullRequestOff'),
- () => this.setShowBranchPullRequest(false),
- this,
- ),
- ];
- }
-
- protected override filterConfigurationChanged(e: ConfigurationChangeEvent) {
- const changed = super.filterConfigurationChanged(e);
- if (
- !changed &&
- !configuration.changed(e, 'defaultDateFormat') &&
- !configuration.changed(e, 'defaultDateShortFormat') &&
- !configuration.changed(e, 'defaultDateSource') &&
- !configuration.changed(e, 'defaultDateStyle') &&
- !configuration.changed(e, 'defaultGravatarsStyle') &&
- !configuration.changed(e, 'defaultTimeFormat') &&
- !configuration.changed(e, 'sortBranchesBy')
- ) {
- return false;
- }
-
- return true;
- }
-
- findBranch(branch: GitBranchReference, token?: CancellationToken) {
- if (branch.remote) return undefined;
-
- const repoNodeId = RepositoryNode.getId(branch.repoPath);
-
- return this.findNode((n: any) => n.branch?.ref === branch.ref, {
- allowPaging: true,
- maxDepth: 4,
- canTraverse: n => {
- if (n instanceof BranchesViewNode) return true;
-
- if (n instanceof BranchesRepositoryNode || n instanceof BranchOrTagFolderNode) {
- return n.id.startsWith(repoNodeId);
- }
-
- return false;
- },
- token: token,
- });
- }
-
- async findCommit(commit: GitCommit | { repoPath: string; ref: string }, token?: CancellationToken) {
- const repoNodeId = RepositoryNode.getId(commit.repoPath);
-
- // Get all the branches the commit is on
- const branches = await this.container.git.getCommitBranches(
- commit.repoPath,
- commit.ref,
- GitCommit.is(commit) ? { commitDate: commit.committer.date } : undefined,
- );
- if (branches.length === 0) return undefined;
-
- return this.findNode((n: any) => n.commit?.ref === commit.ref, {
- allowPaging: true,
- maxDepth: 5,
- canTraverse: async n => {
- if (n instanceof BranchesViewNode) return true;
-
- if (n instanceof BranchesRepositoryNode || n instanceof BranchOrTagFolderNode) {
- return n.id.startsWith(repoNodeId);
- }
-
- if (n instanceof BranchNode && branches.includes(n.branch.name)) {
- await n.loadMore({ until: commit.ref });
- return true;
- }
-
- return false;
- },
- token: token,
- });
- }
-
- @gate(() => '')
- revealBranch(
- branch: GitBranchReference,
- options?: {
- select?: boolean;
- focus?: boolean;
- expand?: boolean | number;
- },
- ) {
- return window.withProgress(
- {
- location: ProgressLocation.Notification,
- title: `Revealing ${GitReference.toString(branch, { icon: false, quoted: true })} in the side bar...`,
- cancellable: true,
- },
- async (progress, token) => {
- const node = await this.findBranch(branch, token);
- if (node == null) return undefined;
-
- await this.ensureRevealNode(node, options);
-
- return node;
- },
- );
- }
-
- @gate(() => '')
- async revealCommit(
- commit: GitRevisionReference,
- options?: {
- select?: boolean;
- focus?: boolean;
- expand?: boolean | number;
- },
- ) {
- return window.withProgress(
- {
- location: ProgressLocation.Notification,
- title: `Revealing ${GitReference.toString(commit, { icon: false, quoted: true })} in the side bar...`,
- cancellable: true,
- },
- async (progress, token) => {
- const node = await this.findCommit(commit, token);
- if (node == null) return undefined;
-
- await this.ensureRevealNode(node, options);
-
- return node;
- },
- );
- }
-
- @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);
- }
-
- private setFilesLayout(layout: ViewFilesLayout) {
- return configuration.updateEffective(`views.${this.configKey}.files.layout` as const, layout);
- }
-
- private setShowAvatars(enabled: boolean) {
- return configuration.updateEffective(`views.${this.configKey}.avatars` as const, enabled);
- }
-
- private setShowBranchComparison(enabled: boolean) {
- return configuration.updateEffective(
- `views.${this.configKey}.showBranchComparison` as const,
- enabled ? ViewShowBranchComparison.Branch : false,
- );
- }
-
- private async setShowBranchPullRequest(enabled: boolean) {
- await configuration.updateEffective(`views.${this.configKey}.pullRequests.showForBranches` as const, enabled);
- await configuration.updateEffective(`views.${this.configKey}.pullRequests.enabled` as const, enabled);
- }
- }
|