Skip to content

Commit 441f3f3

Browse files
committed
Improves repo picker for quick wizards
- Adds option to exclude worktrees
1 parent fb2a602 commit 441f3f3

File tree

6 files changed

+186
-149
lines changed

6 files changed

+186
-149
lines changed

src/commands/git/remote.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ export class RemoteGitCommand extends QuickCommand<State> {
216216

217217
state.repo = context.repos[0];
218218
} else {
219-
const result = yield* pickRepositoryStep(state, context);
219+
const result = yield* pickRepositoryStep(state, context, { excludeWorktrees: true });
220220
if (result === StepResultBreak) continue;
221221

222222
state.repo = result;

src/commands/git/tag.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ export class TagGitCommand extends QuickCommand<State> {
183183

184184
state.repo = context.repos[0];
185185
} else {
186-
const result = yield* pickRepositoryStep(state, context);
186+
const result = yield* pickRepositoryStep(state, context, { excludeWorktrees: true });
187187
if (result === StepResultBreak) continue;
188188

189189
state.repo = result;

src/commands/git/worktree.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ export class WorktreeGitCommand extends QuickCommand<State> {
298298

299299
state.repo = context.repos[0];
300300
} else {
301-
const result = yield* pickRepositoryStep(state, context);
301+
const result = yield* pickRepositoryStep(state, context, { excludeWorktrees: true });
302302
if (result === StepResultBreak) continue;
303303

304304
state.repo = result;

src/commands/quickCommand.steps.ts

Lines changed: 75 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,16 @@ import type { GitWorktree } from '../git/models/worktree';
2828
import { remoteUrlRegex } from '../git/parsers/remoteParser';
2929
import type { ContributorQuickPickItem } from '../git/utils/-webview/contributor.quickpick';
3030
import { createContributorQuickPickItem } from '../git/utils/-webview/contributor.quickpick';
31+
import { groupRepositories } from '../git/utils/-webview/repository.utils';
3132
import type { BranchSortOptions, TagSortOptions } from '../git/utils/-webview/sorting';
32-
import { sortBranches, sortContributors, sortTags, sortWorktrees } from '../git/utils/-webview/sorting';
33+
import {
34+
sortBranches,
35+
sortContributors,
36+
sortRepositories,
37+
sortRepositoriesGrouped,
38+
sortTags,
39+
sortWorktrees,
40+
} from '../git/utils/-webview/sorting';
3341
import type { WorktreeQuickPickItem } from '../git/utils/-webview/worktree.quickpick';
3442
import { createWorktreeQuickPickItem } from '../git/utils/-webview/worktree.quickpick';
3543
import { getWorktreesByBranch } from '../git/utils/-webview/worktree.utils';
@@ -1577,43 +1585,49 @@ export function* pickRemotesStep<
15771585
export async function* pickRepositoryStep<
15781586
State extends PartialStepState & { repo?: string | Repository },
15791587
Context extends { repos: Repository[]; title: string; associatedView: ViewsWithRepositoryFolders },
1580-
>(state: State, context: Context, placeholder: string = 'Choose a repository'): AsyncStepResultGenerator<Repository> {
1588+
>(
1589+
state: State,
1590+
context: Context,
1591+
options?: { excludeWorktrees?: boolean; placeholder?: string },
1592+
): AsyncStepResultGenerator<Repository> {
15811593
if (typeof state.repo === 'string') {
15821594
state.repo = Container.instance.git.getRepository(state.repo);
15831595
if (state.repo != null) return state.repo;
15841596
}
1585-
let active;
1586-
try {
1587-
active = state.repo ?? (await Container.instance.git.getOrOpenRepositoryForEditor());
1588-
} catch (ex) {
1589-
Logger.log(
1590-
'pickRepositoryStep: failed to get active repository. Normally it happens when the currently open file does not belong to a repository',
1591-
ex,
1592-
);
1593-
active = undefined;
1597+
1598+
const active = state.repo ?? (await Container.instance.git.getOrOpenRepositoryForEditor());
1599+
1600+
let repos = context.repos;
1601+
const grouped = await groupRepositories(repos);
1602+
if (options?.excludeWorktrees) {
1603+
repos = sortRepositories([...grouped.keys()]);
1604+
} else {
1605+
repos = sortRepositoriesGrouped(grouped);
15941606
}
15951607

1608+
const placeholder = options?.placeholder ?? 'Choose a repository';
1609+
15961610
const step = createPickStep<RepositoryQuickPickItem>({
15971611
title: context.title,
1598-
placeholder: context.repos.length === 0 ? `${placeholder} — no opened repositories found` : placeholder,
1599-
items:
1600-
context.repos.length === 0
1601-
? [
1602-
createDirectiveQuickPickItem(Directive.Cancel, true, {
1603-
label: 'Cancel',
1604-
detail: 'No opened repositories found',
1612+
placeholder: !repos.length ? `${placeholder} — no opened repositories found` : placeholder,
1613+
items: !repos.length
1614+
? [
1615+
createDirectiveQuickPickItem(Directive.Cancel, true, {
1616+
label: 'Cancel',
1617+
detail: 'No opened repositories found',
1618+
}),
1619+
]
1620+
: Promise.all(
1621+
repos.map(r =>
1622+
createRepositoryQuickPickItem(r, r.id === active?.id, {
1623+
branch: true,
1624+
buttons: [RevealInSideBarQuickInputButton],
1625+
fetched: true,
1626+
indent: !grouped.has(r),
1627+
status: true,
16051628
}),
1606-
]
1607-
: Promise.all(
1608-
context.repos.map(r =>
1609-
createRepositoryQuickPickItem(r, r.id === active?.id, {
1610-
branch: true,
1611-
buttons: [RevealInSideBarQuickInputButton],
1612-
fetched: true,
1613-
status: true,
1614-
}),
1615-
),
16161629
),
1630+
),
16171631
onDidClickItemButton: (_quickpick, button, { item }) => {
16181632
if (button === RevealInSideBarQuickInputButton) {
16191633
void revealRepository(item.path, context.associatedView, { select: true, focus: false, expand: true });
@@ -1635,15 +1649,13 @@ export async function* pickRepositoriesStep<
16351649
>(
16361650
state: State,
16371651
context: Context,
1638-
options?: { placeholder?: string; skipIfPossible?: boolean },
1652+
options?: { excludeWorktrees?: boolean; placeholder?: string; skipIfPossible?: boolean },
16391653
): AsyncStepResultGenerator<Repository[]> {
1640-
options = { placeholder: 'Choose repositories', skipIfPossible: false, ...options };
1641-
16421654
let actives: Repository[];
16431655
if (state.repos != null) {
16441656
if (isStringArray(state.repos)) {
16451657
actives = filterMap(state.repos, path => context.repos.find(r => r.path === path));
1646-
if (options.skipIfPossible && actives.length !== 0 && state.repos.length === actives.length) {
1658+
if (options?.skipIfPossible && actives.length && state.repos.length === actives.length) {
16471659
return actives;
16481660
}
16491661
} else {
@@ -1654,33 +1666,42 @@ export async function* pickRepositoriesStep<
16541666
actives = active != null ? [active] : [];
16551667
}
16561668

1669+
let repos = context.repos;
1670+
const grouped = await groupRepositories(repos);
1671+
if (options?.excludeWorktrees) {
1672+
repos = sortRepositories([...grouped.keys()]);
1673+
} else {
1674+
repos = sortRepositoriesGrouped(grouped);
1675+
}
1676+
1677+
const placeholder = options?.placeholder ?? 'Choose a repository';
1678+
16571679
const step = createPickStep<RepositoryQuickPickItem>({
16581680
multiselect: true,
16591681
title: context.title,
1660-
placeholder:
1661-
context.repos.length === 0 ? `${options.placeholder} — no opened repositories found` : options.placeholder,
1662-
items:
1663-
context.repos.length === 0
1664-
? [
1665-
createDirectiveQuickPickItem(Directive.Cancel, true, {
1666-
label: 'Cancel',
1667-
detail: 'No opened repositories found',
1668-
}),
1669-
]
1670-
: Promise.all(
1671-
context.repos.map(repo =>
1672-
createRepositoryQuickPickItem(
1673-
repo,
1674-
actives.some(r => r.id === repo.id),
1675-
{
1676-
branch: true,
1677-
buttons: [RevealInSideBarQuickInputButton],
1678-
fetched: true,
1679-
status: true,
1680-
},
1681-
),
1682+
placeholder: !repos.length ? `${placeholder} — no opened repositories found` : placeholder,
1683+
items: !repos.length
1684+
? [
1685+
createDirectiveQuickPickItem(Directive.Cancel, true, {
1686+
label: 'Cancel',
1687+
detail: 'No opened repositories found',
1688+
}),
1689+
]
1690+
: Promise.all(
1691+
repos.map(repo =>
1692+
createRepositoryQuickPickItem(
1693+
repo,
1694+
actives.some(r => r.id === repo.id),
1695+
{
1696+
branch: true,
1697+
buttons: [RevealInSideBarQuickInputButton],
1698+
fetched: true,
1699+
indent: !grouped.has(repo),
1700+
status: true,
1701+
},
16821702
),
16831703
),
1704+
),
16841705
onDidClickItemButton: (_quickpick, button, { item }) => {
16851706
if (button === RevealInSideBarQuickInputButton) {
16861707
void revealRepository(item.path, context.associatedView, { select: true, focus: false, expand: true });

0 commit comments

Comments
 (0)