@solaqua/gji 0.13.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/application/worktree/go-resolution.js +5 -3
- package/dist/application/worktree/sources.d.ts +13 -4
- package/dist/application/worktree/sources.js +34 -13
- package/dist/cli/commands/clean.d.ts +4 -2
- package/dist/cli/commands/clean.js +338 -65
- package/dist/cli/commands/go.d.ts +2 -1
- package/dist/cli/commands/go.js +17 -13
- package/dist/cli/commands/hub.js +4 -1
- package/dist/cli/commands/warp.js +6 -4
- package/dist/cli/program.js +5 -0
- package/dist/domain/shared/concurrency.d.ts +1 -1
- package/dist/domain/shared/concurrency.js +6 -1
- package/dist/domain/worktree/path-filter.d.ts +13 -0
- package/dist/domain/worktree/path-filter.js +72 -0
- package/dist/domain/worktree/policy.d.ts +1 -0
- package/dist/domain/worktree/policy.js +1 -1
- package/dist/gji-bundle.mjs +746 -368
- package/dist/infrastructure/git/refs.js +3 -11
- package/dist/presentation/shell/completion.js +7 -2
- package/dist/presentation/worktree/picker.d.ts +9 -6
- package/dist/presentation/worktree/picker.js +19 -2
- package/man/man1/gji-back.1 +1 -1
- package/man/man1/gji-clean.1 +4 -1
- package/man/man1/gji-completion.1 +1 -1
- package/man/man1/gji-config.1 +1 -1
- package/man/man1/gji-doctor.1 +1 -1
- package/man/man1/gji-done.1 +1 -1
- package/man/man1/gji-go.1 +1 -1
- package/man/man1/gji-history.1 +1 -1
- package/man/man1/gji-init.1 +1 -1
- package/man/man1/gji-ls.1 +1 -1
- package/man/man1/gji-new.1 +1 -1
- package/man/man1/gji-open.1 +1 -1
- package/man/man1/gji-pr.1 +1 -1
- package/man/man1/gji-remove.1 +1 -1
- package/man/man1/gji-root.1 +1 -1
- package/man/man1/gji-run-hook.1 +1 -1
- package/man/man1/gji-status.1 +1 -1
- package/man/man1/gji-sync-files.1 +1 -1
- package/man/man1/gji-sync.1 +1 -1
- package/man/man1/gji-task.1 +1 -1
- package/man/man1/gji-undo.1 +1 -1
- package/man/man1/gji-warp.1 +1 -1
- package/man/man1/gji.1 +1 -1
- package/package.json +1 -1
|
@@ -46,10 +46,12 @@ export async function resolveGoBranch(options) {
|
|
|
46
46
|
return finish({ kind: "existing", source: pullRequestMatches[0] }, false);
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
const registered = await listRegisteredWorktreeSources({
|
|
50
|
+
cwd,
|
|
51
|
+
repositoryPort: sourceDependencies,
|
|
52
52
|
});
|
|
53
|
+
const registeredSources = registered.sources;
|
|
54
|
+
const skippedRegisteredRepos = registered.skipped.length;
|
|
53
55
|
const crossRepoSources = registeredSources.filter((source) => source.repoRoot !== repository?.repoRoot);
|
|
54
56
|
const crossMatches = await resolveExistingWorktreeMatches(crossRepoSources, branch, (!localBranch && !remoteBranch) || isPullRequestUrl(branch), repositoryPort);
|
|
55
57
|
if (crossMatches.length === 1) {
|
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
import type { RepoRegistryEntry } from "../../domain/repository/registry.js";
|
|
2
2
|
import type { WorktreeSource } from "../../domain/worktree/source.js";
|
|
3
3
|
import type { RepositoryContextPort, RepositoryRegistryPort, WorktreePort } from "../../ports/repository.js";
|
|
4
|
-
type WorktreeSourceDependencies = RepositoryContextPort & RepositoryRegistryPort & WorktreePort;
|
|
5
|
-
export
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
export type WorktreeSourceDependencies = RepositoryContextPort & RepositoryRegistryPort & WorktreePort;
|
|
5
|
+
export interface WorktreeSourceDiscovery {
|
|
6
|
+
skipped: RepoRegistryEntry[];
|
|
7
|
+
sources: WorktreeSource[];
|
|
8
|
+
}
|
|
9
|
+
export interface ListWorktreeSourcesOptions {
|
|
10
|
+
cwd: string;
|
|
11
|
+
repositoryPort: WorktreeSourceDependencies;
|
|
12
|
+
signal?: AbortSignal;
|
|
13
|
+
}
|
|
14
|
+
export declare function listRegisteredWorktreeSources(options: ListWorktreeSourcesOptions): Promise<WorktreeSourceDiscovery>;
|
|
15
|
+
export declare function listDiscoverableWorktreeSources(options: ListWorktreeSourcesOptions): Promise<WorktreeSourceDiscovery>;
|
|
16
|
+
export declare function deduplicateWorktreeSources(sources: WorktreeSource[]): WorktreeSource[];
|
|
@@ -1,25 +1,31 @@
|
|
|
1
1
|
import { mapWithConcurrency } from "../../domain/shared/concurrency.js";
|
|
2
2
|
const MAX_REPOSITORY_DISCOVERY_CONCURRENCY = 4;
|
|
3
|
-
export async function listRegisteredWorktreeSources(
|
|
3
|
+
export async function listRegisteredWorktreeSources(options) {
|
|
4
|
+
const { cwd, repositoryPort, signal } = options;
|
|
5
|
+
throwIfAborted(signal);
|
|
4
6
|
const registry = await repositoryPort.loadRegistry();
|
|
5
7
|
const currentRoot = await repositoryPort
|
|
6
8
|
.detectRepository(cwd)
|
|
7
9
|
.then((repository) => repository.currentRoot)
|
|
8
10
|
.catch(() => null);
|
|
11
|
+
throwIfAborted(signal);
|
|
9
12
|
const results = await mapWithConcurrency(registry, MAX_REPOSITORY_DISCOVERY_CONCURRENCY, async (entry) => {
|
|
13
|
+
throwIfAborted(signal);
|
|
10
14
|
try {
|
|
11
15
|
const worktrees = await repositoryPort.listWorktrees(entry.path);
|
|
12
|
-
return { entry, worktrees };
|
|
16
|
+
return { entry, skipped: false, worktrees };
|
|
13
17
|
}
|
|
14
18
|
catch {
|
|
15
|
-
|
|
16
|
-
return null;
|
|
19
|
+
return { entry, skipped: true, worktrees: [] };
|
|
17
20
|
}
|
|
18
|
-
});
|
|
21
|
+
}, signal);
|
|
19
22
|
const allItems = [];
|
|
23
|
+
const skipped = [];
|
|
20
24
|
for (const result of results) {
|
|
21
|
-
if (result
|
|
25
|
+
if (result.skipped) {
|
|
26
|
+
skipped.push(result.entry);
|
|
22
27
|
continue;
|
|
28
|
+
}
|
|
23
29
|
const { entry, worktrees } = result;
|
|
24
30
|
for (const worktree of worktrees) {
|
|
25
31
|
allItems.push({
|
|
@@ -32,15 +38,20 @@ export async function listRegisteredWorktreeSources(cwd, repositoryPort, onSkipp
|
|
|
32
38
|
});
|
|
33
39
|
}
|
|
34
40
|
}
|
|
35
|
-
return allItems;
|
|
41
|
+
return { skipped, sources: allItems };
|
|
36
42
|
}
|
|
37
|
-
export async function listDiscoverableWorktreeSources(
|
|
43
|
+
export async function listDiscoverableWorktreeSources(options) {
|
|
44
|
+
const { cwd, repositoryPort } = options;
|
|
38
45
|
const currentRepository = await repositoryPort
|
|
39
46
|
.detectRepository(cwd)
|
|
40
47
|
.catch(() => null);
|
|
41
|
-
const
|
|
42
|
-
if (currentRepository === null)
|
|
43
|
-
return
|
|
48
|
+
const registered = await listRegisteredWorktreeSources(options);
|
|
49
|
+
if (currentRepository === null) {
|
|
50
|
+
return {
|
|
51
|
+
skipped: registered.skipped,
|
|
52
|
+
sources: deduplicateWorktreeSources(registered.sources),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
44
55
|
let currentSources = [];
|
|
45
56
|
try {
|
|
46
57
|
currentSources = (await repositoryPort.listWorktrees(cwd)).map((worktree) => ({
|
|
@@ -52,9 +63,15 @@ export async function listDiscoverableWorktreeSources(cwd, repositoryPort, onSki
|
|
|
52
63
|
catch {
|
|
53
64
|
// Registered repositories remain discoverable when the current checkout is transiently unavailable.
|
|
54
65
|
}
|
|
55
|
-
return
|
|
66
|
+
return {
|
|
67
|
+
skipped: registered.skipped,
|
|
68
|
+
sources: deduplicateWorktreeSources([
|
|
69
|
+
...currentSources,
|
|
70
|
+
...registered.sources,
|
|
71
|
+
]),
|
|
72
|
+
};
|
|
56
73
|
}
|
|
57
|
-
function
|
|
74
|
+
export function deduplicateWorktreeSources(sources) {
|
|
58
75
|
const seen = new Set();
|
|
59
76
|
return sources.filter((source) => {
|
|
60
77
|
if (seen.has(source.worktree.path))
|
|
@@ -63,3 +80,7 @@ function dedupeSources(sources) {
|
|
|
63
80
|
return true;
|
|
64
81
|
});
|
|
65
82
|
}
|
|
83
|
+
function throwIfAborted(signal) {
|
|
84
|
+
if (signal?.aborted)
|
|
85
|
+
throw new Error("Operation cancelled");
|
|
86
|
+
}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
+
import { type WorktreeCatalogDependencies } from "../../application/worktree/catalog.js";
|
|
1
2
|
import type { WorktreeEntry } from "../../domain/worktree/types.js";
|
|
2
|
-
import { type WorktreePromptEntry } from "../../presentation/worktree/picker.js";
|
|
3
|
+
import { type WorktreePromptEntry, type WorktreePromptScope } from "../../presentation/worktree/picker.js";
|
|
3
4
|
import { type CliRuntime } from "../dependencies.js";
|
|
4
5
|
export interface CleanCommandOptions {
|
|
5
6
|
cwd: string;
|
|
6
7
|
dryRun?: boolean;
|
|
7
8
|
force?: boolean;
|
|
8
9
|
json?: boolean;
|
|
10
|
+
paths?: string[];
|
|
9
11
|
stale?: boolean;
|
|
10
12
|
runtime?: CliRuntime<"git" | "config" | "configStore" | "slots" | "repositoryContext" | "repositoryRegistry" | "worktrees" | "worktreeInfo" | "worktreeLifecycle" | "worktreeCatalog">;
|
|
11
13
|
stderr: (chunk: string) => void;
|
|
@@ -15,7 +17,7 @@ export interface CleanCommandDependencies {
|
|
|
15
17
|
confirmForceDeleteBranch: (branch: string) => Promise<boolean>;
|
|
16
18
|
confirmForceRemoveWorktree: (worktreePath: string) => Promise<boolean>;
|
|
17
19
|
confirmRemoval: (worktrees: WorktreeEntry[]) => Promise<boolean>;
|
|
18
|
-
promptForWorktrees: (worktrees: WorktreePromptEntry[]) => Promise<string[] | null>;
|
|
20
|
+
promptForWorktrees: (worktrees: WorktreePromptEntry[], scope?: WorktreePromptScope, catalog?: WorktreeCatalogDependencies) => Promise<string[] | null>;
|
|
19
21
|
}
|
|
20
22
|
export declare function createCleanCommand(dependencies?: Partial<CleanCommandDependencies>): (options: CleanCommandOptions) => Promise<number>;
|
|
21
23
|
export declare const runCleanCommand: (options: CleanCommandOptions) => Promise<number>;
|