Skip to content

Commit

Permalink
Sorts branches & tags by date desc in Git commands
Browse files Browse the repository at this point in the history
  • Loading branch information
eamodio committed Sep 26, 2020
1 parent 7c268fc commit 732b47a
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 55 deletions.
2 changes: 1 addition & 1 deletion src/commands/git/cherry-pick.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ export class CherryPickGitCommand extends QuickCommand<State> {
state as CherryPickStepState,
context,
{
filterBranches: b => b.id !== context.destination.id,
filter: { branches: b => b.id !== context.destination.id },
placeholder: context =>
`Choose a branch${context.showTags ? ' or tag' : ''} to cherry-pick from`,
picked: context.selectedBranchOrTag?.ref,
Expand Down
2 changes: 2 additions & 0 deletions src/commands/git/switch.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
'use strict';
import { ProgressLocation, QuickPickItem, window } from 'vscode';
import { BranchSorting } from '../../config';
import { Container } from '../../container';
import { GitReference, Repository } from '../../git/git';
import {
Expand Down Expand Up @@ -143,6 +144,7 @@ export class SwitchGitCommand extends QuickCommand<State> {

const branches = await Container.git.getBranches(state.reference.repoPath, {
filter: b => b.tracking === state.reference!.name,
sort: { orderBy: BranchSorting.DateDesc },
});

if (branches.length === 0) {
Expand Down
54 changes: 33 additions & 21 deletions src/commands/quickCommand.steps.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict';
import { QuickInputButton, QuickPick } from 'vscode';
import { Commands } from './common';
import { configuration } from '../configuration';
import { BranchSorting, configuration, TagSorting } from '../configuration';
import { Container } from '../container';
import { GlyphChars, quickPickTitleMaxChars } from '../constants';
import {
Expand Down Expand Up @@ -122,13 +122,13 @@ export async function getBranchesAndOrTags(
repos: Repository | Repository[],
include: ('tags' | 'branches')[],
{
filterBranches,
filterTags,
filter,
picked,
sort,
}: {
filterBranches?: (b: GitBranch) => boolean;
filterTags?: (t: GitTag) => boolean;
filter?: { branches?: (b: GitBranch) => boolean; tags?: (t: GitTag) => boolean };
picked?: string | string[];
sort?: boolean | { branches?: { current?: boolean; orderBy?: BranchSorting }; tags?: { orderBy?: TagSorting } };
} = {},
): Promise<(BranchQuickPickItem | TagQuickPickItem)[]> {
let branches: GitBranch[] | undefined;
Expand All @@ -140,16 +140,32 @@ export async function getBranchesAndOrTags(
const repo = repos instanceof Repository ? repos : repos[0];

[branches, tags] = await Promise.all<GitBranch[] | undefined, GitTag[] | undefined>([
include.includes('branches') ? repo.getBranches({ filter: filterBranches, sort: true }) : undefined,
include.includes('tags') ? repo.getTags({ filter: filterTags, sort: true }) : undefined,
include.includes('branches')
? repo.getBranches({
filter: filter?.branches,
sort: typeof sort === 'boolean' ? sort : sort?.branches,
})
: undefined,
include.includes('tags') ? repo.getTags({ filter: filter?.tags, sort: true }) : undefined,
]);
} else {
const [branchesByRepo, tagsByRepo] = await Promise.all<GitBranch[][] | undefined, GitTag[][] | undefined>([
include.includes('branches')
? Promise.all(repos.map(r => r.getBranches({ filter: filterBranches, sort: true })))
? Promise.all(
repos.map(r =>
r.getBranches({
filter: filter?.branches,
sort: typeof sort === 'boolean' ? sort : sort?.branches,
}),
),
)
: undefined,
include.includes('tags')
? Promise.all(repos.map(r => r.getTags({ filter: filterTags, sort: true })))
? Promise.all(
repos.map(r =>
r.getTags({ filter: filter?.tags, sort: typeof sort === 'boolean' ? sort : sort?.tags }),
),
)
: undefined,
]);

Expand Down Expand Up @@ -479,16 +495,14 @@ export async function* pickBranchOrTagStep<
state: State,
context: Context,
{
filterBranches,
filterTags,
filter,
picked,
placeholder,
titleContext,
value,
additionalButtons,
}: {
filterBranches?: (b: GitBranch) => boolean;
filterTags?: (t: GitTag) => boolean;
filter?: { branches?: (b: GitBranch) => boolean; tags?: (t: GitTag) => boolean };
picked: string | string[] | undefined;
placeholder: string | ((context: Context) => string);
titleContext?: string;
Expand All @@ -502,9 +516,9 @@ export async function* pickBranchOrTagStep<

const getBranchesAndOrTagsFn = async () => {
return getBranchesAndOrTags(state.repo, context.showTags ? ['branches', 'tags'] : ['branches'], {
filterBranches: filterBranches,
filterTags: filterTags,
filter: filter,
picked: picked,
sort: { branches: { orderBy: BranchSorting.DateDesc }, tags: { orderBy: TagSorting.DateDesc } },
});
};
const branchesAndOrTags = await getBranchesAndOrTagsFn();
Expand Down Expand Up @@ -596,15 +610,13 @@ export async function* pickBranchOrTagStepMultiRepo<
state: State,
context: Context,
{
filterBranches,
filterTags,
filter,
picked,
placeholder,
titleContext,
value,
}: {
filterBranches?: (b: GitBranch) => boolean;
filterTags?: (t: GitTag) => boolean;
filter?: { branches?: (b: GitBranch) => boolean; tags?: (t: GitTag) => boolean };
picked?: string | string[];
placeholder: string | ((context: Context) => string);
titleContext?: string;
Expand All @@ -618,9 +630,9 @@ export async function* pickBranchOrTagStepMultiRepo<
const getBranchesAndOrTagsFn = () => {
return getBranchesAndOrTags(state.repos, context.showTags ? ['branches', 'tags'] : ['branches'], {
// Filter out remote branches if we are going to affect multiple repos
filterBranches: filterBranches ?? (state.repos.length === 1 ? undefined : b => !b.remote),
filterTags: filterTags,
filter: { branches: state.repos.length === 1 ? undefined : b => !b.remote, ...filter },
picked: picked ?? state.reference?.ref,
sort: { branches: { orderBy: BranchSorting.DateDesc }, tags: { orderBy: TagSorting.DateDesc } },
});
};
const branchesAndOrTags = await getBranchesAndOrTagsFn();
Expand Down
30 changes: 17 additions & 13 deletions src/git/gitService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {
WorkspaceFoldersChangeEvent,
} from 'vscode';
import { API as BuiltInGitApi, Repository as BuiltInGitRepository, GitExtension } from '../@types/git';
import { configuration } from '../configuration';
import { BranchSorting, configuration, TagSorting } from '../configuration';
import { CommandContext, DocumentSchemes, setCommandContext } from '../constants';
import { Container } from '../container';
import { LogCorrelationContext, Logger } from '../logger';
Expand Down Expand Up @@ -1103,7 +1103,10 @@ export class GitService implements Disposable {
@log()
async getBranches(
repoPath: string | undefined,
options: { filter?: (b: GitBranch) => boolean; sort?: boolean | { current: boolean } } = {},
options: {
filter?: (b: GitBranch) => boolean;
sort?: boolean | { current?: boolean; orderBy?: BranchSorting };
} = {},
): Promise<GitBranch[]> {
if (repoPath == null) return [];

Expand Down Expand Up @@ -1159,31 +1162,31 @@ export class GitService implements Disposable {
async getBranchesAndOrTags(
repoPath: string | undefined,
{
filterBranches,
filterTags,
filter,
include,
sort,
...options
}: {
filterBranches?: (b: GitBranch) => boolean;
filterTags?: (t: GitTag) => boolean;
filter?: { branches?: (b: GitBranch) => boolean; tags?: (t: GitTag) => boolean };
include?: 'all' | 'branches' | 'tags';
sort?: boolean | { current: boolean };
sort?:
| boolean
| { branches?: { current?: boolean; orderBy?: BranchSorting }; tags?: { orderBy?: TagSorting } };
} = {},
) {
const [branches, tags] = await Promise.all<GitBranch[] | undefined, GitTag[] | undefined>([
include === 'all' || include === 'branches'
? this.getBranches(repoPath, {
...options,
filter: filterBranches,
sort: sort,
filter: filter?.branches,
sort: typeof sort === 'boolean' ? undefined : sort?.branches,
})
: undefined,
include === 'all' || include === 'tags'
? this.getTags(repoPath, {
...options,
filter: filterTags,
sort: Boolean(sort),
filter: filter?.tags,
sort: typeof sort === 'boolean' ? undefined : sort?.tags,
})
: undefined,
]);
Expand Down Expand Up @@ -3063,7 +3066,7 @@ export class GitService implements Disposable {
@log()
async getTags(
repoPath: string | undefined,
options: { filter?: (t: GitTag) => boolean; sort?: boolean } = {},
options: { filter?: (t: GitTag) => boolean; sort?: boolean | { orderBy?: TagSorting } } = {},
): Promise<GitTag[]> {
if (repoPath == null) return [];

Expand All @@ -3082,8 +3085,9 @@ export class GitService implements Disposable {
tags = tags.filter(options.filter);
}

// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
if (options.sort) {
GitTag.sort(tags);
GitTag.sort(tags, typeof options.sort === 'boolean' ? undefined : options.sort);
}

return tags;
Expand Down
16 changes: 7 additions & 9 deletions src/git/models/branch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,32 +34,30 @@ export class GitBranch implements GitBranchReference {
return branch?.refType === 'branch';
}

static sort(branches: GitBranch[], options?: { current: boolean }) {
const order = configuration.get('sortBranchesBy');
static sort(branches: GitBranch[], options?: { current?: boolean; orderBy?: BranchSorting }) {
options = { current: true, orderBy: configuration.get('sortBranchesBy'), ...options };

const opts = { current: true, ...options };

switch (order) {
switch (options.orderBy) {
case BranchSorting.DateAsc:
return branches.sort(
(a, b) =>
(opts.current ? (a.current ? -1 : 1) - (b.current ? -1 : 1) : 0) ||
(options!.current ? (a.current ? -1 : 1) - (b.current ? -1 : 1) : 0) ||
(a.starred ? -1 : 1) - (b.starred ? -1 : 1) ||
(b.remote ? -1 : 1) - (a.remote ? -1 : 1) ||
(a.date == null ? -1 : a.date.getTime()) - (b.date == null ? -1 : b.date.getTime()),
);
case BranchSorting.DateDesc:
return branches.sort(
(a, b) =>
(opts.current ? (a.current ? -1 : 1) - (b.current ? -1 : 1) : 0) ||
(options!.current ? (a.current ? -1 : 1) - (b.current ? -1 : 1) : 0) ||
(a.starred ? -1 : 1) - (b.starred ? -1 : 1) ||
(b.remote ? -1 : 1) - (a.remote ? -1 : 1) ||
(b.date == null ? -1 : b.date.getTime()) - (a.date == null ? -1 : a.date.getTime()),
);
case BranchSorting.NameAsc:
return branches.sort(
(a, b) =>
(opts.current ? (a.current ? -1 : 1) - (b.current ? -1 : 1) : 0) ||
(options!.current ? (a.current ? -1 : 1) - (b.current ? -1 : 1) : 0) ||
(a.starred ? -1 : 1) - (b.starred ? -1 : 1) ||
(a.name === 'main' ? -1 : 1) - (b.name === 'main' ? -1 : 1) ||
(a.name === 'master' ? -1 : 1) - (b.name === 'master' ? -1 : 1) ||
Expand All @@ -70,7 +68,7 @@ export class GitBranch implements GitBranchReference {
default:
return branches.sort(
(a, b) =>
(opts.current ? (a.current ? -1 : 1) - (b.current ? -1 : 1) : 0) ||
(options!.current ? (a.current ? -1 : 1) - (b.current ? -1 : 1) : 0) ||
(a.starred ? -1 : 1) - (b.starred ? -1 : 1) ||
(a.name === 'main' ? -1 : 1) - (b.name === 'main' ? -1 : 1) ||
(a.name === 'master' ? -1 : 1) - (b.name === 'master' ? -1 : 1) ||
Expand Down
19 changes: 13 additions & 6 deletions src/git/models/repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
workspace,
WorkspaceFolder,
} from 'vscode';
import { configuration } from '../../configuration';
import { BranchSorting, configuration, TagSorting } from '../../configuration';
import { StarredRepositories, WorkspaceState } from '../../constants';
import { Container } from '../../container';
import { GitBranch, GitContributor, GitDiffShortStat, GitRemote, GitStash, GitStatus, GitTag } from '../git';
Expand Down Expand Up @@ -388,17 +388,21 @@ export class Repository implements Disposable {
}

getBranches(
options: { filter?: (b: GitBranch) => boolean; sort?: boolean | { current: boolean } } = {},
options: {
filter?: (b: GitBranch) => boolean;
sort?: boolean | { current?: boolean; orderBy?: BranchSorting };
} = {},
): Promise<GitBranch[]> {
return Container.git.getBranches(this.path, options);
}

getBranchesAndOrTags(
options: {
filterBranches?: (b: GitBranch) => boolean;
filterTags?: (t: GitTag) => boolean;
filter?: { branches?: (b: GitBranch) => boolean; tags?: (t: GitTag) => boolean };
include?: 'all' | 'branches' | 'tags';
sort?: boolean | { current: boolean };
sort?:
| boolean
| { branches?: { current?: boolean; orderBy?: BranchSorting }; tags?: { orderBy?: TagSorting } };
} = {},
) {
return Container.git.getBranchesAndOrTags(this.path, options);
Expand Down Expand Up @@ -466,7 +470,10 @@ export class Repository implements Disposable {
return Container.git.getStatusForRepo(this.path);
}

getTags(options?: { filter?: (t: GitTag) => boolean; sort?: boolean }): Promise<GitTag[]> {
getTags(options?: {
filter?: (t: GitTag) => boolean;
sort?: boolean | { orderBy?: TagSorting };
}): Promise<GitTag[]> {
return Container.git.getTags(this.path, options);
}

Expand Down
6 changes: 3 additions & 3 deletions src/git/models/tag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ export class GitTag implements GitTagReference {
return tag?.refType === 'tag';
}

static sort(tags: GitTag[]) {
const order = configuration.get('sortTagsBy');
static sort(tags: GitTag[], options?: { orderBy?: TagSorting }) {
options = { orderBy: configuration.get('sortTagsBy'), ...options };

switch (order) {
switch (options.orderBy) {
case TagSorting.DateAsc:
return tags.sort((a, b) => a.date.getTime() - b.date.getTime());
case TagSorting.DateDesc:
Expand Down
3 changes: 1 addition & 2 deletions src/quickpicks/referencePicker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,7 @@ export namespace ReferencePicker {
? ['tags']
: [],
{
filterBranches: filterBranches,
filterTags: filterTags,
filter: { branches: filterBranches, tags: filterTags },
picked: picked,
},
);
Expand Down

0 comments on commit 732b47a

Please sign in to comment.