Skip to content

Commit

Permalink
Adds favoriting to repos & branches
Browse files Browse the repository at this point in the history
  • Loading branch information
eamodio committed Jan 2, 2019
1 parent fbe0c7c commit 2b0673b
Show file tree
Hide file tree
Showing 15 changed files with 228 additions and 17 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p

### Added

- Adds favoriting of repositories and branches in the _Repositories_ view to allow for better (user-customized) sorting
- Adds the ability to turn on file annotations (blame, heatmap, and recent changes) via user-defined modes — closes [#542](https://github.com/eamodio/vscode-gitlens/issues/542)

## [9.2.4] - 2018-12-26
Expand Down
4 changes: 4 additions & 0 deletions images/dark/icon-star-filled.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions images/dark/icon-star.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions images/light/icon-star-filled.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions images/light/icon-star.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
66 changes: 66 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2265,6 +2265,24 @@
"light": "images/light/icon-minus.svg"
}
},
{
"command": "gitlens.views.star",
"title": "Add to Favorites",
"category": "GitLens",
"icon": {
"dark": "images/dark/icon-star.svg",
"light": "images/light/icon-star.svg"
}
},
{
"command": "gitlens.views.unstar",
"title": "Remove from Favorites",
"category": "GitLens",
"icon": {
"dark": "images/dark/icon-star-filled.svg",
"light": "images/light/icon-star-filled.svg"
}
},
{
"command": "gitlens.views.openDirectoryDiff",
"title": "Open Directory Compare",
Expand Down Expand Up @@ -3023,6 +3041,14 @@
"command": "gitlens.views.unstageFile",
"when": "false"
},
{
"command": "gitlens.views.star",
"when": "false"
},
{
"command": "gitlens.views.unstar",
"when": "false"
},
{
"command": "gitlens.views.openChanges",
"when": "false"
Expand Down Expand Up @@ -3797,6 +3823,16 @@
"when": "viewItem =~ /gitlens:branches\\b.*?\\+remotes\\b.*?/",
"group": "1_gitlens@1"
},
{
"command": "gitlens.views.star",
"when": "viewItem =~ /gitlens:branch\\b(?!.*?\\+starred\\b.*?)/",
"group": "inline@1"
},
{
"command": "gitlens.views.unstar",
"when": "viewItem =~ /gitlens:branch\\b.*?\\+starred\\b.*?/",
"group": "inline@2"
},
{
"command": "gitlens.views.checkout",
"when": "!gitlens:readonly && viewItem =~ /gitlens:branch\\b(?!.*?\\+current\\b.*?)/",
Expand Down Expand Up @@ -3833,6 +3869,16 @@
"when": "viewItem =~ /gitlens:branch\\b.*?\\+(tracking|remote)\\b.*?/",
"group": "2_gitlens@1"
},
{
"command": "gitlens.views.star",
"when": "viewItem =~ /gitlens:branch\\b(?!.*?\\+starred\\b.*?)/",
"group": "3_gitlens@1"
},
{
"command": "gitlens.views.unstar",
"when": "viewItem =~ /gitlens:branch\\b.*?\\+starred\\b.*?/",
"group": "3_gitlens@1"
},
{
"command": "gitlens.views.compareWithRemote",
"when": "viewItem =~ /gitlens:branch\\b.*?\\+tracking\\b.*?/",
Expand Down Expand Up @@ -4153,8 +4199,18 @@
{
"command": "gitlens.showCommitSearch",
"when": "viewItem =~ /gitlens:repository\\b/",
"group": "inline@10"
},
{
"command": "gitlens.views.star",
"when": "viewItem =~ /gitlens:repository\\b(?!.*?\\+starred\\b.*?)/",
"group": "inline@1"
},
{
"command": "gitlens.views.unstar",
"when": "viewItem =~ /gitlens:repository\\b.*?\\+starred\\b.*?/",
"group": "inline@2"
},
{
"command": "gitlens.views.push",
"when": "gitlens:hasRemotes && !gitlens:readonly && viewItem =~ /gitlens:repository\\b/",
Expand Down Expand Up @@ -4191,6 +4247,16 @@
"when": "gitlens:hasRemotes && !gitlens:readonly && viewItem =~ /gitlens:repository\\b/",
"group": "1_gitlens@2"
},
{
"command": "gitlens.views.star",
"when": "viewItem =~ /gitlens:repository\\b(?!.*?\\+starred\\b.*?)/",
"group": "2_gitlens@1"
},
{
"command": "gitlens.views.unstar",
"when": "viewItem =~ /gitlens:repository\\b.*?\\+starred\\b.*?/",
"group": "2_gitlens@1"
},
{
"command": "gitlens.views.pull",
"when": "gitlens:hasRemotes && !gitlens:readonly && viewItem == gitlens:status:upstream:behind",
Expand Down
10 changes: 10 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,17 @@ export const ImageMimetypes: { [key: string]: string } = {
'.bmp': 'image/bmp'
};

export interface StarredBranches {
[id: string]: boolean;
}

export interface StarredRepositories {
[id: string]: boolean;
}

export enum WorkspaceState {
StarredBranches = 'gitlens:starred:branches',
StarredRepositories = 'gitlens:starred:repositories',
ViewsCompareKeepResults = 'gitlens:views:compare:keepResults',
ViewsRepositoriesAutoRefresh = 'gitlens:views:repositories:autoRefresh',
ViewsSearchKeepResults = 'gitlens:views:search:keepResults'
Expand Down
2 changes: 1 addition & 1 deletion src/git/gitService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1771,7 +1771,7 @@ export class GitService implements Disposable {
const repositories = [...(await this.getRepositories())];
if (repositories.length === 0) return repositories;

return repositories.sort((a, b) => a.index - b.index);
return repositories.sort((a, b) => (a.starred ? -1 : 1) - (b.starred ? -1 : 1) || a.index - b.index);
}

private async getRepositoryTree(): Promise<TernarySearchTree<Repository>> {
Expand Down
34 changes: 34 additions & 0 deletions src/git/models/branch.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
'use strict';
import { StarredBranches, WorkspaceState } from '../../constants';
import { Container } from '../../container';
import { Git } from '../git';
import { GitStatus } from './status';

Expand All @@ -9,6 +11,7 @@ export interface GitTrackingState {

export class GitBranch {
readonly detached: boolean;
readonly id: string;
readonly name: string;
readonly remote: boolean;
readonly tracking?: string;
Expand All @@ -24,6 +27,8 @@ export class GitBranch {
behind: number = 0,
detached: boolean = false
) {
this.id = `${repoPath}|${name}`;

if (name.startsWith('remotes/')) {
name = name.substring(8);
this.remote = true;
Expand Down Expand Up @@ -88,6 +93,35 @@ export class GitBranch {
return GitStatus.getUpstreamStatus(this.tracking, this.state, options);
}

get starred() {
const starred = Container.context.workspaceState.get<StarredBranches>(WorkspaceState.StarredBranches);
return starred !== undefined && starred[this.id] === true;
}

star() {
return this.updateStarred(true);
}

unstar() {
return this.updateStarred(false);
}

private async updateStarred(star: boolean) {
let starred = Container.context.workspaceState.get<StarredBranches>(WorkspaceState.StarredBranches);
if (starred === undefined) {
starred = Object.create(null);
}

if (star) {
starred![this.id] = true;
}
else {
const { [this.id]: _, ...rest } = starred!;
starred = rest;
}
await Container.context.workspaceState.update(WorkspaceState.StarredBranches, starred);
}

static getRemote(branch: string): string {
return branch.substring(0, branch.indexOf('/'));
}
Expand Down
32 changes: 32 additions & 0 deletions src/git/models/repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
WorkspaceFolder
} from 'vscode';
import { configuration, RemotesConfig } from '../../configuration';
import { StarredRepositories, WorkspaceState } from '../../constants';
import { Container } from '../../container';
import { Functions, gate, log } from '../../system';
import { GitBranch, GitDiffShortStat, GitRemote, GitStash, GitStatus, GitTag } from '../git';
Expand Down Expand Up @@ -71,6 +72,7 @@ export class Repository implements Disposable {
}

readonly formattedName: string;
readonly id: string;
readonly index: number;
readonly name: string;
readonly normalizedPath: string;
Expand Down Expand Up @@ -115,6 +117,7 @@ export class Repository implements Disposable {
this.index = folder.index;

this.normalizedPath = (path.endsWith('/') ? path : `${path}/`).toLowerCase();
this.id = this.normalizedPath;

this._suspended = suspended;
this._closed = closed;
Expand Down Expand Up @@ -378,6 +381,35 @@ export class Repository implements Disposable {
}
}

get starred() {
const starred = Container.context.workspaceState.get<StarredRepositories>(WorkspaceState.StarredRepositories);
return starred !== undefined && starred[this.id] === true;
}

star() {
return this.updateStarred(true);
}

unstar() {
return this.updateStarred(false);
}

private async updateStarred(star: boolean) {
let starred = Container.context.workspaceState.get<StarredRepositories>(WorkspaceState.StarredRepositories);
if (starred === undefined) {
starred = Object.create(null);
}

if (star) {
starred![this.id] = true;
}
else {
const { [this.id]: _, ...rest } = starred!;
starred = rest;
}
await Container.context.workspaceState.update(WorkspaceState.StarredRepositories, starred);
}

startWatchingFileSystem() {
this._fsWatchCounter++;
if (this._fsWatcherDisposable !== undefined) return;
Expand Down
34 changes: 25 additions & 9 deletions src/views/nodes/branchNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { ViewBranchesLayout } from '../../configuration';
import { GlyphChars } from '../../constants';
import { Container } from '../../container';
import { GitBranch, GitUri } from '../../git/gitService';
import { debug, gate, Iterables } from '../../system';
import { debug, gate, Iterables, log } from '../../system';
import { RepositoriesView } from '../repositoriesView';
import { BranchTrackingStatusNode } from './branchTrackingStatusNode';
import { CommitNode } from './commitNode';
Expand All @@ -30,9 +30,9 @@ export class BranchNode extends ViewRefNode<RepositoriesView> implements Pageabl
}

get id(): string {
return `gitlens:repository(${this.branch.repoPath}):${this._root ? 'root:' : ''}branch(${this.branch.name})${
this.branch.remote ? ':remote' : ''
}`;
return `gitlens:repository(${this.branch.repoPath})${this._root ? ':root:' : ''}:branch(${this.branch.name})${
this.branch.current ? '+current:' : ''
}${this.branch.remote ? '+remote' : ''}${this.branch.starred ? '+starred:' : ''}`;
}

get current(): boolean {
Expand All @@ -43,13 +43,19 @@ export class BranchNode extends ViewRefNode<RepositoriesView> implements Pageabl
const branchName = this.branch.getName();
if (this.view.config.branches.layout === ViewBranchesLayout.List) return branchName;

return this.current || GitBranch.isDetached(branchName) ? branchName : this.branch.getBasename();
return (this._root && this.current) || this.branch.detached || this.branch.starred
? branchName
: this.branch.getBasename();
}

get ref(): string {
return this.branch.ref;
}

get treeHierarchy(): string[] {
return this.branch.detached || this.branch.starred ? [this.branch.name] : this.branch.getName().split('/');
}

async getChildren(): Promise<ViewNode[]> {
if (this._children === undefined) {
const children = [];
Expand Down Expand Up @@ -136,10 +142,8 @@ export class BranchNode extends ViewRefNode<RepositoriesView> implements Pageabl
if (this.branch.remote) {
item.contextValue += '+remote';
}
else if (this.current) {
item.contextValue = this.branch.tracking
? ResourceType.CurrentBranchWithTracking
: ResourceType.CurrentBranch;
if (this.branch.starred) {
item.contextValue += '+starred';
}
if (this.branch.tracking) {
item.contextValue += '+tracking';
Expand All @@ -156,6 +160,18 @@ export class BranchNode extends ViewRefNode<RepositoriesView> implements Pageabl
return item;
}

@log()
async star() {
await this.branch.star();
void this.parent!.triggerChange();
}

@log()
async unstar() {
await this.branch.unstar();
void this.parent!.triggerChange();
}

@gate()
@debug()
refresh() {
Expand Down
8 changes: 6 additions & 2 deletions src/views/nodes/branchesNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@ export class BranchesNode extends ViewNode<RepositoriesView> {
const branches = await this.repo.getBranches();
if (branches === undefined) return [];

branches.sort((a, b) => a.name.localeCompare(b.name, undefined, { numeric: true, sensitivity: 'base' }));
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 = [
Expand All @@ -42,7 +46,7 @@ export class BranchesNode extends ViewNode<RepositoriesView> {

const hierarchy = Arrays.makeHierarchical(
branchNodes,
n => (n.branch.detached ? [n.branch.name] : n.branch.getName().split('/')),
n => n.treeHierarchy,
(...paths: string[]) => paths.join('/'),
this.view.config.files.compact
);
Expand Down

0 comments on commit 2b0673b

Please sign in to comment.