Browse Source

Adds new branch history node under status

main
Eric Amodio 6 years ago
parent
commit
de83305095
5 changed files with 101 additions and 65 deletions
  1. +1
    -0
      CHANGELOG.md
  2. +2
    -0
      README.md
  3. +6
    -2
      src/views/branchNode.ts
  4. +46
    -47
      src/views/branchesNode.ts
  5. +46
    -16
      src/views/statusNode.ts

+ 1
- 0
CHANGELOG.md View File

@ -6,6 +6,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
## [Unreleased]
### Added
- Adds new branch history node under the **Repository Status** node in the *GitLens* explorer
- Adds GitLab and Visual Studio Team Services icons to the remote nodes in the *GitLens* explorer — thanks to [PR #421](https://github.com/eamodio/vscode-gitlens/pull/421) by Maxim Pekurin ([@pmaxim25](https://github.com/pmaxim25))
### Fixed

+ 2
- 0
README.md View File

@ -185,6 +185,8 @@ The repository view provides a full Git repository explorer, which has the follo
- A context menu provides *Open Repository in Remote*, and *Refresh* commands
- **Changed Files** — lists all the "working" changes
- Expands to a file-based view of all changed files in the working tree ([optionally](#gitlens-explorer-settings "Jump to the GitLens explorer settings")) and/or all files in all commits ahead of the upstream
- **History (current-branch)** — lists the revision (commit) history of the current branch
- See the *Branches expand* section under **Branches** below for more details
- **Branches** — lists the local branches
- Indicates which branch is the current branch and [optionally](#gitlens-explorer-settings "Jump to the GitLens explorer settings") shows the remote tracking branch

+ 6
- 2
src/views/branchNode.ts View File

@ -16,7 +16,7 @@ export class BranchNode extends ExplorerRefNode {
constructor(
public readonly branch: GitBranch,
uri: GitUri,
private readonly explorer: GitExplorer
protected readonly explorer: GitExplorer
) {
super(uri);
}
@ -32,6 +32,10 @@ export class BranchNode extends ExplorerRefNode {
return GitBranch.isValid(branchName) && !this.current ? this.branch.getBasename() : branchName;
}
get markCurrent(): boolean {
return true;
}
get ref(): string {
return this.branch.name;
}
@ -79,7 +83,7 @@ export class BranchNode extends ExplorerRefNode {
}
}
const item = new TreeItem(`${this.current ? `${GlyphChars.Check} ${GlyphChars.Space}` : ''}${name}`, TreeItemCollapsibleState.Collapsed);
const item = new TreeItem(`${this.markCurrent && this.current ? `${GlyphChars.Check} ${GlyphChars.Space}` : ''}${name}`, TreeItemCollapsibleState.Collapsed);
item.tooltip = tooltip;
if (this.branch.remote) {

+ 46
- 47
src/views/branchesNode.ts View File

@ -11,64 +11,63 @@ import { GitUri, Repository } from '../gitService';
export class BranchesNode extends ExplorerNode {
constructor(
uri: GitUri,
private readonly repo: Repository,
private readonly explorer: GitExplorer,
private readonly active: boolean = false
) {
super(uri);
}
get id(): string {
return `gitlens:repository(${this.repo.path})${this.active ? ':active' : ''}:branches`;
}
constructor(
uri: GitUri,
private readonly repo: Repository,
private readonly explorer: GitExplorer,
private readonly active: boolean = false
) {
super(uri);
}
async getChildren(): Promise<ExplorerNode[]> {
const branches = await this.repo.getBranches();
if (branches === undefined) return [];
get id(): string {
return `gitlens:repository(${this.repo.path})${this.active ? ':active' : ''}:branches`;
}
branches.sort((a, b) => (a.current ? -1 : 1) - (b.current ? -1 : 1) || a.name.localeCompare(b.name));
async getChildren(): Promise<ExplorerNode[]> {
const branches = await this.repo.getBranches();
if (branches === undefined) return [];
// filter local branches
const branchNodes = [...Iterables.filterMap(branches, b => b.remote ? undefined : new BranchNode(b, this.uri, this.explorer))];
if (this.explorer.config.branches.layout === ExplorerBranchesLayout.List) return branchNodes;
branches.sort((a, b) => (a.current ? -1 : 1) - (b.current ? -1 : 1) || a.name.localeCompare(b.name));
// Take out the current branch, since that should always be first and un-nested
const current = (branchNodes.length > 0 && branchNodes[0].current)
? branchNodes.splice(0, 1)[0]
: undefined;
// filter local branches
const branchNodes = [...Iterables.filterMap(branches, b => b.remote ? undefined : new BranchNode(b, this.uri, this.explorer))];
if (this.explorer.config.branches.layout === ExplorerBranchesLayout.List) return branchNodes;
const hierarchy = Arrays.makeHierarchical(branchNodes,
n => n.branch.isValid() ? n.branch.getName().split('/') : [n.branch.name],
(...paths: string[]) => paths.join('/'),
this.explorer.config.files.compact);
// Take out the current branch, since that should always be first and un-nested
const current = (branchNodes.length > 0 && branchNodes[0].current)
? branchNodes.splice(0, 1)[0]
: undefined;
const root = new BranchOrTagFolderNode(this.repo.path, '', undefined, hierarchy, this.explorer);
const children = await root.getChildren() as (BranchOrTagFolderNode | BranchNode)[];
const hierarchy = Arrays.makeHierarchical(branchNodes,
n => n.branch.isValid() ? n.branch.getName().split('/') : [n.branch.name],
(...paths: string[]) => paths.join('/'),
this.explorer.config.files.compact);
// If we found a current branch, insert it at the start
if (current !== undefined) {
children.splice(0, 0, current);
}
const root = new BranchOrTagFolderNode(this.repo.path, '', undefined, hierarchy, this.explorer);
const children = await root.getChildren() as (BranchOrTagFolderNode | BranchNode)[];
return children;
// If we found a current branch, insert it at the start
if (current !== undefined) {
children.splice(0, 0, current);
}
async getTreeItem(): Promise<TreeItem> {
// HACK: Until https://github.com/Microsoft/vscode/issues/30918 is fixed
const item = new TreeItem(`Branches`, this.active ? TreeItemCollapsibleState.Expanded : TreeItemCollapsibleState.Collapsed);
return children;
}
async getTreeItem(): Promise<TreeItem> {
const item = new TreeItem(`Branches`, TreeItemCollapsibleState.Collapsed);
const remotes = await this.repo.getRemotes();
item.contextValue = (remotes !== undefined && remotes.length > 0)
? ResourceType.BranchesWithRemotes
: ResourceType.Branches;
const remotes = await this.repo.getRemotes();
item.contextValue = (remotes !== undefined && remotes.length > 0)
? ResourceType.BranchesWithRemotes
: ResourceType.Branches;
item.iconPath = {
dark: Container.context.asAbsolutePath('images/dark/icon-branch.svg'),
light: Container.context.asAbsolutePath('images/light/icon-branch.svg')
};
item.iconPath = {
dark: Container.context.asAbsolutePath('images/dark/icon-branch.svg'),
light: Container.context.asAbsolutePath('images/light/icon-branch.svg')
};
return item;
}
return item;
}
}

+ 46
- 16
src/views/statusNode.ts View File

@ -1,9 +1,10 @@
import { Disposable, TreeItem, TreeItemCollapsibleState } from 'vscode';
import { BranchNode } from './branchNode';
import { GlyphChars } from '../constants';
import { Container } from '../container';
import { ExplorerNode, ResourceType } from './explorerNode';
import { GitExplorer } from './gitExplorer';
import { GitUri, Repository, RepositoryFileSystemChangeEvent } from '../gitService';
import { GitBranch, GitUri, Repository, RepositoryFileSystemChangeEvent } from '../gitService';
import { StatusFilesNode } from './statusFilesNode';
import { StatusUpstreamNode } from './statusUpstreamNode';
@ -25,24 +26,33 @@ export class StatusNode extends ExplorerNode {
async getChildren(): Promise<ExplorerNode[]> {
this.resetChildren();
this.children = [];
const status = await this.repo.getStatus();
if (status === undefined) return [];
if (status !== undefined) {
if (status.state.behind) {
this.children.push(new StatusUpstreamNode(status, 'behind', this.explorer, this.active));
}
this.children = [];
if (status.state.ahead) {
this.children.push(new StatusUpstreamNode(status, 'ahead', this.explorer, this.active));
}
if (status.state.behind) {
this.children.push(new StatusUpstreamNode(status, 'behind', this.explorer, this.active));
if (status.state.ahead || (status.files.length !== 0 && this.includeWorkingTree)) {
const range = status.upstream
? `${status.upstream}..${status.branch}`
: undefined;
this.children.push(new StatusFilesNode(status, range, this.explorer, this.active));
}
}
if (status.state.ahead) {
this.children.push(new StatusUpstreamNode(status, 'ahead', this.explorer, this.active));
}
let branch = await this.repo.getBranch();
if (branch !== undefined) {
if (status !== undefined) {
branch = new GitBranch(branch.repoPath, branch.name, branch.current, branch.sha, branch.tracking, status.state.ahead, status.state.behind);
}
if (status.state.ahead || (status.files.length !== 0 && this.includeWorkingTree)) {
const range = status.upstream
? `${status.upstream}..${status.branch}`
: undefined;
this.children.push(new StatusFilesNode(status, range, this.explorer, this.active));
this.children.push(new StatusBranchNode(branch, this.uri, this.explorer));
}
return this.children;
@ -91,7 +101,6 @@ export class StatusNode extends ExplorerNode {
}
}
label = `${status.branch}${label === '' ? '' : ` ${GlyphChars.Space}${status.upstream ? GlyphChars.ArrowLeftRightLong : GlyphChars.Dash}${label}`}`;
if (hasWorkingChanges) {
tooltip += `\n\nHas uncommitted changes${status.getDiffStatus({ expand: true, prefix: `\n`, separator: '\n' })}`;
}
@ -102,7 +111,7 @@ export class StatusNode extends ExplorerNode {
state = this.active ? TreeItemCollapsibleState.Expanded : TreeItemCollapsibleState.Collapsed;
}
else {
state = TreeItemCollapsibleState.None;
state = TreeItemCollapsibleState.Collapsed;
}
const item = new TreeItem(`${status.branch}${label}`, state);
@ -133,4 +142,25 @@ export class StatusNode extends ExplorerNode {
private async onFileSystemChanged(e: RepositoryFileSystemChangeEvent) {
this.explorer.refreshNode(this);
}
}
}
export class StatusBranchNode extends BranchNode {
constructor(
branch: GitBranch,
uri: GitUri,
explorer: GitExplorer
) {
super(branch, uri, explorer);
}
get markCurrent() {
return false;
}
async getTreeItem(): Promise<TreeItem> {
const item = await super.getTreeItem();
item.label = `History (${item.label})`;
return item;
}
}

Loading…
Cancel
Save