Skip to content

Commit

Permalink
Adds more status nodes for upstream state
Browse files Browse the repository at this point in the history
  • Loading branch information
eamodio committed Sep 11, 2020
1 parent 58c1549 commit 3fd02e9
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 53 deletions.
18 changes: 14 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6493,12 +6493,12 @@
{
"command": "gitlens.views.pull",
"when": "gitlens:hasRemotes && !gitlens:readonly && viewItem == gitlens:status:upstream:behind",
"group": "inline@2"
"group": "inline@1"
},
{
"command": "gitlens.views.pull",
"when": "gitlens:hasRemotes && !gitlens:readonly && viewItem == gitlens:status:upstream:behind",
"group": "1_gitlens_actions@1"
"command": "gitlens.views.fetch",
"when": "gitlens:hasRemotes && !gitlens:readonly && viewItem =~ /gitlens:status:upstream:(?!none)/",
"group": "inline@2"
},
{
"command": "gitlens.views.push",
Expand All @@ -6510,6 +6510,16 @@
"when": "gitlens:hasRemotes && !gitlens:readonly && viewItem == gitlens:status:upstream:ahead",
"group": "1_gitlens_actions@2"
},
{
"command": "gitlens.views.pull",
"when": "gitlens:hasRemotes && !gitlens:readonly && viewItem == gitlens:status:upstream:behind",
"group": "1_gitlens_actions@1"
},
{
"command": "gitlens.views.fetch",
"when": "gitlens:hasRemotes && !gitlens:readonly && viewItem =~ /gitlens:status:upstream:(?!none)/",
"group": "1_gitlens_actions@3"
},
{
"command": "gitlens.views.dismissNode",
"when": "viewItem =~ /gitlens:(compare:picker:ref|compare:results\\b(?!.*?\\b\\+pinned\\b)|search)\\b(?!:(commits|files))/",
Expand Down
28 changes: 20 additions & 8 deletions src/views/nodes/branchNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,23 +100,35 @@ export class BranchNode
async getChildren(): Promise<ViewNode[]> {
if (this._children == null) {
const children = [];
if (this.options.showTracking && this.branch.tracking) {
if (this.options.showTracking) {
const status = {
ref: this.branch.ref,
repoPath: this.branch.repoPath,
state: this.branch.state,
upstream: this.branch.tracking,
};

if (this.branch.state.behind) {
children.push(
new BranchTrackingStatusNode(this.view, this, this.branch, status, 'behind', this.root),
);
}
if (this.branch.tracking) {
if (this.root && !status.state.behind && !status.state.ahead) {
children.push(
new BranchTrackingStatusNode(this.view, this, this.branch, status, 'same', this.root),
);
}

if (this.branch.state.ahead) {
if (status.state.ahead) {
children.push(
new BranchTrackingStatusNode(this.view, this, this.branch, status, 'ahead', this.root),
);
}

if (status.state.behind) {
children.push(
new BranchTrackingStatusNode(this.view, this, this.branch, status, 'behind', this.root),
);
}
} else if (this.root) {
children.push(
new BranchTrackingStatusNode(this.view, this, this.branch, status, 'ahead', this.root),
new BranchTrackingStatusNode(this.view, this, this.branch, status, 'none', this.root),
);
}
}
Expand Down
138 changes: 98 additions & 40 deletions src/views/nodes/branchTrackingStatusNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { GitBranch, GitLog, GitRevision, GitTrackingState } from '../../git/git'
import { GitUri } from '../../git/gitUri';
import { insertDateMarkers } from './helpers';
import { RepositoriesView } from '../repositoriesView';
import { debug, gate, Iterables, memoize, Strings } from '../../system';
import { Dates, debug, gate, Iterables, memoize, Strings } from '../../system';
import { ViewsWithFiles } from '../viewBase';
import { ContextValues, PageableViewNode, ViewNode } from './viewNode';

Expand All @@ -22,37 +22,35 @@ export interface BranchTrackingStatus {

export class BranchTrackingStatusNode extends ViewNode<ViewsWithFiles> implements PageableViewNode {
static key = ':status-branch:upstream';
static getId(repoPath: string, name: string, root: boolean, upstream: string, direction: string): string {
return `${BranchNode.getId(repoPath, name, root)}${this.key}(${upstream}|${direction})`;
static getId(
repoPath: string,
name: string,
root: boolean,
upstream: string | undefined,
upstreamType: string,
): string {
return `${BranchNode.getId(repoPath, name, root)}${this.key}(${upstream ?? ''}|${upstreamType})`;
}

constructor(
view: ViewsWithFiles,
parent: ViewNode,
public readonly branch: GitBranch,
public readonly status: BranchTrackingStatus,
public readonly direction: 'ahead' | 'behind',
public readonly upstreamType: 'ahead' | 'behind' | 'same' | 'none',
// Specifies that the node is shown as a root under the repository node
private readonly root: boolean = false,
) {
super(GitUri.fromRepoPath(status.repoPath), view, parent);
}

get ahead(): boolean {
return this.direction === 'ahead';
}

get behind(): boolean {
return this.direction === 'behind';
}

get id(): string {
return BranchTrackingStatusNode.getId(
this.status.repoPath,
this.status.ref,
this.root,
this.status.upstream!,
this.direction,
this.status.upstream,
this.upstreamType,
);
}

Expand All @@ -61,11 +59,13 @@ export class BranchTrackingStatusNode extends ViewNode<ViewsWithFiles> implement
}

async getChildren(): Promise<ViewNode[]> {
if (this.upstreamType === 'same' || this.upstreamType === 'none') return [];

const log = await this.getLog();
if (log == null) return [];

let children;
if (this.ahead) {
if (this.upstreamType === 'ahead') {
// Since the last commit when we are looking 'ahead' can have no previous (because of the range given) -- look it up
const commits = [...log.commits.values()];
const commit = commits[commits.length - 1];
Expand Down Expand Up @@ -97,14 +97,14 @@ export class BranchTrackingStatusNode extends ViewNode<ViewsWithFiles> implement
children.push(new ShowMoreNode(this.view, this, children[children.length - 1]));
}

if (!this.isReposView && this.status.upstream && this.ahead && this.status.state.ahead > 0) {
if (!this.isReposView && this.status.upstream && this.upstreamType === 'ahead' && this.status.state.ahead > 0) {
children.push(
new BranchTrackingStatusFilesNode(
this.view,
this,
this.branch,
this.status as Required<BranchTrackingStatus>,
this.direction,
this.upstreamType,
this.root,
),
);
Expand All @@ -113,29 +113,84 @@ export class BranchTrackingStatusNode extends ViewNode<ViewsWithFiles> implement
return children;
}

getTreeItem(): TreeItem {
const ahead = this.ahead;
let label = ahead
? `${Strings.pluralize('commit', this.status.state.ahead)} ahead`
: `${Strings.pluralize('commit', this.status.state.behind)} behind`;
if (!this.isReposView) {
label += `${ahead ? ' of ' : ' '}${this.status.upstream}`;
async getTreeItem(): Promise<TreeItem> {
let lastFetched = 0;

if (this.root && !this.isReposView && this.upstreamType !== 'none') {
const repo = await Container.git.getRepository(this.repoPath);
lastFetched = (await repo?.getLastFetched()) ?? 0;
}

const item = new TreeItem(
label,
ahead && !this.isReposView ? TreeItemCollapsibleState.Expanded : TreeItemCollapsibleState.Collapsed,
);
item.id = this.id;
if (this.root) {
item.contextValue = ahead ? ContextValues.StatusAheadOfUpstream : ContextValues.StatusBehindUpstream;
} else {
item.contextValue = ahead
? ContextValues.BranchStatusAheadOfUpstream
: ContextValues.BranchStatusBehindUpstream;
let label;
let collapsibleState;
let contextValue;
let icon;
let tooltip;
switch (this.upstreamType) {
case 'ahead':
label = `${Strings.pluralize('commit', this.status.state.ahead)} ahead`;
if (!this.isReposView) {
label = `${this.root ? `${this.branch.name} is ` : ''}${label} ${this.status.upstream}`;
}
tooltip = `${label} of ${this.status.upstream}`;

collapsibleState = !this.isReposView
? TreeItemCollapsibleState.Expanded
: TreeItemCollapsibleState.Collapsed;
contextValue = this.root
? ContextValues.StatusAheadOfUpstream
: ContextValues.BranchStatusAheadOfUpstream;
icon = 'cloud-upload';

break;

case 'behind':
label = `${Strings.pluralize('commit', this.status.state.behind)} behind`;
if (!this.isReposView) {
label = `${this.root ? `${this.branch.name} is ` : ''}${label} ${this.status.upstream}`;
}
tooltip = `${label} ${this.status.upstream}`;

collapsibleState = TreeItemCollapsibleState.Collapsed;
contextValue = this.root
? ContextValues.StatusBehindUpstream
: ContextValues.BranchStatusBehindUpstream;
icon = 'cloud-download';

break;

case 'same':
label = `${this.branch.name} is up to date`;
if (!this.isReposView) {
label += ` with ${this.status.upstream}`;
}
tooltip = `${label} with ${this.status.upstream}`;

collapsibleState = TreeItemCollapsibleState.None;
contextValue = this.root ? ContextValues.StatusSameAsUpstream : undefined;
icon = 'cloud';

break;
case 'none':
label = `${this.branch.name} hasn't yet been published`;
tooltip = label;

collapsibleState = TreeItemCollapsibleState.None;
contextValue = this.root ? ContextValues.StatusNoUpstream : undefined;
icon = 'cloud-upload';

break;
}
item.iconPath = new ThemeIcon(ahead ? 'cloud-upload' : 'cloud-download');
item.tooltip = `${label}${ahead ? ' of ' : ' '}${this.status.upstream}`;

const item = new TreeItem(label, collapsibleState);
item.id = this.id;
item.contextValue = contextValue;
item.description = lastFetched
? `Last fetched ${Dates.getFormatter(new Date(lastFetched)).fromNow()}`
: undefined;
item.iconPath = new ThemeIcon(icon);
item.tooltip = tooltip;

return item;
}

Expand All @@ -154,10 +209,13 @@ export class BranchTrackingStatusNode extends ViewNode<ViewsWithFiles> implement

private _log: GitLog | undefined;
private async getLog() {
if (this.upstreamType === 'same' || this.upstreamType === 'none') return undefined;

if (this._log == null) {
const range = this.ahead
? GitRevision.createRange(this.status.upstream, this.status.ref)
: GitRevision.createRange(this.status.ref, this.status.upstream);
const range =
this.upstreamType === 'ahead'
? GitRevision.createRange(this.status.upstream, this.status.ref)
: GitRevision.createRange(this.status.ref, this.status.upstream);

this._log = await Container.git.getLog(this.uri.repoPath!, {
limit: this.limit ?? this.view.config.defaultItemLimit,
Expand Down
2 changes: 2 additions & 0 deletions src/views/nodes/viewNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ export enum ContextValues {
StatusFiles = 'gitlens:status:files',
StatusAheadOfUpstream = 'gitlens:status:upstream:ahead',
StatusBehindUpstream = 'gitlens:status:upstream:behind',
StatusNoUpstream = 'gitlens:status:upstream:none',
StatusSameAsUpstream = 'gitlens:status:upstream:same',
Tag = 'gitlens:tag',
Tags = 'gitlens:tags',
}
Expand Down
3 changes: 2 additions & 1 deletion src/views/viewCommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -288,9 +288,10 @@ export class ViewCommands {
}

@debug()
private fetch(node: RemoteNode | RepositoryNode) {
private fetch(node: RemoteNode | RepositoryNode | BranchTrackingStatusNode) {
if (node instanceof RepositoryNode) return GitActions.fetch(node.repo);
if (node instanceof RemoteNode) return GitActions.Remote.fetch(node.remote.repoPath, node.remote.name);
if (node instanceof BranchTrackingStatusNode) return GitActions.fetch(node.repoPath);

return Promise.resolve();
}
Expand Down

0 comments on commit 3fd02e9

Please sign in to comment.