Browse Source

Sorts branches & tags by date desc in Git commands

main
Eric Amodio 4 years ago
parent
commit
732b47a2bc
8 changed files with 77 additions and 55 deletions
  1. +1
    -1
      src/commands/git/cherry-pick.ts
  2. +2
    -0
      src/commands/git/switch.ts
  3. +33
    -21
      src/commands/quickCommand.steps.ts
  4. +17
    -13
      src/git/gitService.ts
  5. +7
    -9
      src/git/models/branch.ts
  6. +13
    -6
      src/git/models/repository.ts
  7. +3
    -3
      src/git/models/tag.ts
  8. +1
    -2
      src/quickpicks/referencePicker.ts

+ 1
- 1
src/commands/git/cherry-pick.ts View File

@ -131,7 +131,7 @@ export class CherryPickGitCommand extends QuickCommand {
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,

+ 2
- 0
src/commands/git/switch.ts View File

@ -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 {
@ -143,6 +144,7 @@ export class SwitchGitCommand extends QuickCommand {
const branches = await Container.git.getBranches(state.reference.repoPath, {
filter: b => b.tracking === state.reference!.name,
sort: { orderBy: BranchSorting.DateDesc },
});
if (branches.length === 0) {

+ 33
- 21
src/commands/quickCommand.steps.ts View File

@ -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 {
@ -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;
@ -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,
]);
@ -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;
@ -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();
@ -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;
@ -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();

+ 17
- 13
src/git/gitService.ts View File

@ -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';
@ -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 [];
@ -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,
]);
@ -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 [];
@ -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;

+ 7
- 9
src/git/models/branch.ts View File

@ -34,16 +34,14 @@ 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()),
@ -51,7 +49,7 @@ export class GitBranch implements GitBranchReference {
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()),
@ -59,7 +57,7 @@ export class GitBranch implements GitBranchReference {
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) ||
@ -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) ||

+ 13
- 6
src/git/models/repository.ts View File

@ -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';
@ -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);
@ -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);
}

+ 3
- 3
src/git/models/tag.ts View File

@ -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:

+ 1
- 2
src/quickpicks/referencePicker.ts View File

@ -150,8 +150,7 @@ export namespace ReferencePicker {
? ['tags']
: [],
{
filterBranches: filterBranches,
filterTags: filterTags,
filter: { branches: filterBranches, tags: filterTags },
picked: picked,
},
);

Loading…
Cancel
Save