Skip to content

Commit 3ec65a4

Browse files
committed
Improves repo picker for quick wizards
- Adds option to exclude worktrees
1 parent de11195 commit 3ec65a4

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';
@@ -1576,43 +1584,49 @@ export function* pickRemotesStep<
15761584
export async function* pickRepositoryStep<
15771585
State extends PartialStepState & { repo?: string | Repository },
15781586
Context extends { repos: Repository[]; title: string; associatedView: ViewsWithRepositoryFolders },
1579-
>(state: State, context: Context, placeholder: string = 'Choose a repository'): AsyncStepResultGenerator<Repository> {
1587+
>(
1588+
state: State,
1589+
context: Context,
1590+
options?: { excludeWorktrees?: boolean; placeholder?: string },
1591+
): AsyncStepResultGenerator<Repository> {
15801592
if (typeof state.repo === 'string') {
15811593
state.repo = Container.instance.git.getRepository(state.repo);
15821594
if (state.repo != null) return state.repo;
15831595
}
1584-
let active;
1585-
try {
1586-
active = state.repo ?? (await Container.instance.git.getOrOpenRepositoryForEditor());
1587-
} catch (ex) {
1588-
Logger.log(
1589-
'pickRepositoryStep: failed to get active repository. Normally it happens when the currently open file does not belong to a repository',
1590-
ex,
1591-
);
1592-
active = undefined;
1596+
1597+
const active = state.repo ?? (await Container.instance.git.getOrOpenRepositoryForEditor());
1598+
1599+
let repos = context.repos;
1600+
const grouped = await groupRepositories(repos);
1601+
if (options?.excludeWorktrees) {
1602+
repos = sortRepositories([...grouped.keys()]);
1603+
} else {
1604+
repos = sortRepositoriesGrouped(grouped);
15931605
}
15941606

1607+
const placeholder = options?.placeholder ?? 'Choose a repository';
1608+
15951609
const step = createPickStep<RepositoryQuickPickItem>({
15961610
title: context.title,
1597-
placeholder: context.repos.length === 0 ? `${placeholder} — no opened repositories found` : placeholder,
1598-
items:
1599-
context.repos.length === 0
1600-
? [
1601-
createDirectiveQuickPickItem(Directive.Cancel, true, {
1602-
label: 'Cancel',
1603-
detail: 'No opened repositories found',
1611+
placeholder: !repos.length ? `${placeholder} — no opened repositories found` : placeholder,
1612+
items: !repos.length
1613+
? [
1614+
createDirectiveQuickPickItem(Directive.Cancel, true, {
1615+
label: 'Cancel',
1616+
detail: 'No opened repositories found',
1617+
}),
1618+
]
1619+
: Promise.all(
1620+
repos.map(r =>
1621+
createRepositoryQuickPickItem(r, r.id === active?.id, {
1622+
branch: true,
1623+
buttons: [RevealInSideBarQuickInputButton],
1624+
fetched: true,
1625+
indent: !grouped.has(r),
1626+
status: true,
16041627
}),
1605-
]
1606-
: Promise.all(
1607-
context.repos.map(r =>
1608-
createRepositoryQuickPickItem(r, r.id === active?.id, {
1609-
branch: true,
1610-
buttons: [RevealInSideBarQuickInputButton],
1611-
fetched: true,
1612-
status: true,
1613-
}),
1614-
),
16151628
),
1629+
),
16161630
onDidClickItemButton: (_quickpick, button, { item }) => {
16171631
if (button === RevealInSideBarQuickInputButton) {
16181632
void revealRepository(item.path, context.associatedView, { select: true, focus: false, expand: true });
@@ -1634,15 +1648,13 @@ export async function* pickRepositoriesStep<
16341648
>(
16351649
state: State,
16361650
context: Context,
1637-
options?: { placeholder?: string; skipIfPossible?: boolean },
1651+
options?: { excludeWorktrees?: boolean; placeholder?: string; skipIfPossible?: boolean },
16381652
): AsyncStepResultGenerator<Repository[]> {
1639-
options = { placeholder: 'Choose repositories', skipIfPossible: false, ...options };
1640-
16411653
let actives: Repository[];
16421654
if (state.repos != null) {
16431655
if (isStringArray(state.repos)) {
16441656
actives = filterMap(state.repos, path => context.repos.find(r => r.path === path));
1645-
if (options.skipIfPossible && actives.length !== 0 && state.repos.length === actives.length) {
1657+
if (options?.skipIfPossible && actives.length && state.repos.length === actives.length) {
16461658
return actives;
16471659
}
16481660
} else {
@@ -1653,33 +1665,42 @@ export async function* pickRepositoriesStep<
16531665
actives = active != null ? [active] : [];
16541666
}
16551667

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

0 commit comments

Comments
 (0)