@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
|
@@ -64,17 +64,9 @@ async function resolveCachedRemoteDefaultBranch(cwd, remote) {
|
|
|
64
64
|
return ref.startsWith(prefix) ? ref.slice(prefix.length) : undefined;
|
|
65
65
|
}
|
|
66
66
|
catch {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
"--format=%(refname:strip=3)",
|
|
71
|
-
`refs/remotes/${remote}`,
|
|
72
|
-
]);
|
|
73
|
-
return refs.split("\n").find((ref) => ref !== "HEAD");
|
|
74
|
-
}
|
|
75
|
-
catch {
|
|
76
|
-
return undefined;
|
|
77
|
-
}
|
|
67
|
+
// A remote branch list does not identify which branch is the default.
|
|
68
|
+
// Refuse to guess when the symbolic remote HEAD is unavailable.
|
|
69
|
+
return undefined;
|
|
78
70
|
}
|
|
79
71
|
}
|
|
80
72
|
export async function readBranchLastCommitTimestamp(cwd, branch) {
|
|
@@ -221,7 +221,11 @@ _gji_completion() {
|
|
|
221
221
|
COMPREPLY=( $(compgen -W "--compact --json --help" -- "$cur") )
|
|
222
222
|
;;
|
|
223
223
|
clean)
|
|
224
|
-
|
|
224
|
+
if [ "\${COMP_WORDS[COMP_CWORD-1]}" = "--path" ]; then
|
|
225
|
+
COMPREPLY=( $(compgen -d -- "$cur") )
|
|
226
|
+
else
|
|
227
|
+
COMPREPLY=( $(compgen -W "-f --force --stale --path --dry-run --json --help" -- "$cur") )
|
|
228
|
+
fi
|
|
225
229
|
;;
|
|
226
230
|
remove|rm)
|
|
227
231
|
COMPREPLY=( $(compgen -W "$(__gji_worktree_branches) -f --force --dry-run --json --help" -- "$cur") )
|
|
@@ -454,6 +458,7 @@ complete -c gji -n '__fish_seen_subcommand_from ls' -l json -d 'print active wor
|
|
|
454
458
|
|
|
455
459
|
complete -c gji -n '__fish_seen_subcommand_from clean' -s f -l force -d 'bypass prompts, force-remove dirty worktrees, and force-delete unmerged branches'
|
|
456
460
|
complete -c gji -n '__fish_seen_subcommand_from clean' -l stale -d 'only target clean worktrees whose upstream is gone and branch is merged into the default branch'
|
|
461
|
+
complete -c gji -n '__fish_seen_subcommand_from clean' -l path -r -F -d 'only target worktrees under a directory or matching a path glob (repeatable)'
|
|
457
462
|
complete -c gji -n '__fish_seen_subcommand_from clean' -l dry-run -d 'show what would be deleted without removing anything'
|
|
458
463
|
complete -c gji -n '__fish_seen_subcommand_from clean' -l json -d 'emit JSON on success or error instead of human-readable output'
|
|
459
464
|
|
|
@@ -612,7 +617,7 @@ case "\${words[2]}" in
|
|
|
612
617
|
_arguments '--compact[show only branch and path columns]' '--json[print active worktrees as JSON]'
|
|
613
618
|
;;
|
|
614
619
|
clean)
|
|
615
|
-
_arguments '(-f --force)'{-f,--force}'[bypass prompts, force-remove dirty worktrees, and force-delete unmerged branches]' '--stale[only target clean worktrees whose upstream is gone and branch is merged into the default branch]' '--dry-run[show what would be deleted without removing anything]' '--json[emit JSON on success or error instead of human-readable output]'
|
|
620
|
+
_arguments '(-f --force)'{-f,--force}'[bypass prompts, force-remove dirty worktrees, and force-delete unmerged branches]' '--stale[only target clean worktrees whose upstream is gone and branch is merged into the default branch]' '*--path[only target worktrees under a directory or matching a path glob]:pattern:_files' '--dry-run[show what would be deleted without removing anything]' '--json[emit JSON on success or error instead of human-readable output]'
|
|
616
621
|
;;
|
|
617
622
|
remove|rm)
|
|
618
623
|
_arguments '(-f --force)'{-f,--force}'[bypass prompts, force-remove a dirty worktree, and force-delete an unmerged branch]' '--dry-run[show what would be deleted without removing anything]' '--json[emit JSON on success or error instead of human-readable output]' '2:branch:->worktrees'
|
|
@@ -30,17 +30,20 @@ export interface WorktreePickerIO {
|
|
|
30
30
|
}
|
|
31
31
|
export interface WorktreePromptScope {
|
|
32
32
|
label: string;
|
|
33
|
-
toggle: () => Promise<WorktreePromptScopeResult>;
|
|
33
|
+
toggle: (signal?: AbortSignal) => Promise<WorktreePromptScopeResult>;
|
|
34
34
|
toggleLabel: string;
|
|
35
35
|
}
|
|
36
36
|
export interface WorktreePromptScopeResult {
|
|
37
|
-
entries: WorktreePromptEntry[];
|
|
38
37
|
label: string;
|
|
38
|
+
metadata?: WorktreeMetadataMode;
|
|
39
|
+
sources: WorktreeSource[];
|
|
39
40
|
toggleLabel: string;
|
|
40
41
|
}
|
|
41
|
-
export
|
|
42
|
-
|
|
42
|
+
export interface WorktreePickerOptions extends WorktreePickerIO {
|
|
43
|
+
catalog?: WorktreeCatalogDependencies;
|
|
43
44
|
scope?: WorktreePromptScope;
|
|
44
|
-
}
|
|
45
|
-
export declare function
|
|
45
|
+
}
|
|
46
|
+
export declare function buildWorktreePromptEntries(sources: WorktreeSource[], dependencies?: BuildWorktreePromptEntriesDependencies): Promise<WorktreePromptEntry[]>;
|
|
47
|
+
export declare function promptForSingleWorktree(message: string, worktrees: WorktreePromptEntry[], io?: WorktreePickerOptions): Promise<string | null>;
|
|
48
|
+
export declare function promptForMultipleWorktrees(message: string, worktrees: WorktreePromptEntry[], io?: WorktreePickerOptions): Promise<string[] | null>;
|
|
46
49
|
export declare function formatWorktreeBranchLabel(branch: string | null, pullRequests?: PullRequestInfo[]): string;
|
|
@@ -33,6 +33,7 @@ export async function promptForSingleWorktree(message, worktrees, io = {}) {
|
|
|
33
33
|
message,
|
|
34
34
|
multiple: false,
|
|
35
35
|
output: io.output,
|
|
36
|
+
catalog: io.catalog,
|
|
36
37
|
scope: io.scope,
|
|
37
38
|
});
|
|
38
39
|
return typeof choice === "string" ? choice : null;
|
|
@@ -44,6 +45,8 @@ export async function promptForMultipleWorktrees(message, worktrees, io = {}) {
|
|
|
44
45
|
message,
|
|
45
46
|
multiple: true,
|
|
46
47
|
output: io.output,
|
|
48
|
+
catalog: io.catalog,
|
|
49
|
+
scope: io.scope,
|
|
47
50
|
});
|
|
48
51
|
return Array.isArray(choice) ? choice : null;
|
|
49
52
|
}
|
|
@@ -121,6 +124,7 @@ class SearchablePrompt {
|
|
|
121
124
|
scope;
|
|
122
125
|
scopeTogglePending = false;
|
|
123
126
|
promptClosed = false;
|
|
127
|
+
cancellation = new AbortController();
|
|
124
128
|
prompt;
|
|
125
129
|
constructor(options, input, output) {
|
|
126
130
|
this.options = options;
|
|
@@ -189,10 +193,15 @@ class SearchablePrompt {
|
|
|
189
193
|
this.scopeTogglePending = true;
|
|
190
194
|
renderPrompt(prompt);
|
|
191
195
|
try {
|
|
192
|
-
const nextScope = await currentScope.toggle();
|
|
196
|
+
const nextScope = await currentScope.toggle(this.cancellation.signal);
|
|
193
197
|
if (this.promptClosed)
|
|
194
198
|
return;
|
|
195
|
-
|
|
199
|
+
const nextEntries = await buildWorktreePromptEntries(nextScope.sources, {
|
|
200
|
+
catalog: this.options.catalog,
|
|
201
|
+
metadata: nextScope.metadata,
|
|
202
|
+
});
|
|
203
|
+
this.entries = nextEntries.map(buildSearchableWorktreeEntry);
|
|
204
|
+
this.pruneHiddenSelections();
|
|
196
205
|
this.scope = {
|
|
197
206
|
label: nextScope.label,
|
|
198
207
|
toggle: currentScope.toggle,
|
|
@@ -228,6 +237,7 @@ class SearchablePrompt {
|
|
|
228
237
|
}
|
|
229
238
|
cancel(prompt) {
|
|
230
239
|
this.promptClosed = true;
|
|
240
|
+
this.cancellation.abort();
|
|
231
241
|
prompt.state = "cancel";
|
|
232
242
|
renderPrompt(prompt);
|
|
233
243
|
closePrompt(prompt);
|
|
@@ -321,6 +331,13 @@ class SearchablePrompt {
|
|
|
321
331
|
}
|
|
322
332
|
this.selected.add(entry.value);
|
|
323
333
|
}
|
|
334
|
+
pruneHiddenSelections() {
|
|
335
|
+
const visibleValues = new Set(this.entries.filter(isSelectableEntry).map((entry) => entry.value));
|
|
336
|
+
for (const value of this.selected) {
|
|
337
|
+
if (!visibleValues.has(value))
|
|
338
|
+
this.selected.delete(value);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
324
341
|
render(state, error) {
|
|
325
342
|
const entries = this.visibleEntries();
|
|
326
343
|
const visibleEntries = windowPromptEntries(entries, this.cursor, this.maxItems());
|
package/man/man1/gji-back.1
CHANGED
package/man/man1/gji-clean.1
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
.TH GJI\-CLEAN 1 "
|
|
1
|
+
.TH GJI\-CLEAN 1 "October 2026" "gji 0.15.0" "User Commands"
|
|
2
2
|
.SH NAME
|
|
3
3
|
gji\-clean \- interactively prune linked worktrees
|
|
4
4
|
.SH SYNOPSIS
|
|
@@ -13,6 +13,9 @@ bypass prompts, force\-remove dirty worktrees, and force\-delete unmerged branch
|
|
|
13
13
|
.B \-\-stale
|
|
14
14
|
only target clean worktrees whose upstream is gone and branch is merged into the default branch
|
|
15
15
|
.TP
|
|
16
|
+
.B \-\-path <pattern>
|
|
17
|
+
only target worktrees under a directory or matching a path glob (repeatable)
|
|
18
|
+
.TP
|
|
16
19
|
.B \-\-dry\-run
|
|
17
20
|
show what would be deleted without removing anything
|
|
18
21
|
.TP
|
package/man/man1/gji-config.1
CHANGED
package/man/man1/gji-doctor.1
CHANGED
package/man/man1/gji-done.1
CHANGED
package/man/man1/gji-go.1
CHANGED
package/man/man1/gji-history.1
CHANGED
package/man/man1/gji-init.1
CHANGED
package/man/man1/gji-ls.1
CHANGED
package/man/man1/gji-new.1
CHANGED
package/man/man1/gji-open.1
CHANGED
package/man/man1/gji-pr.1
CHANGED
package/man/man1/gji-remove.1
CHANGED
package/man/man1/gji-root.1
CHANGED
package/man/man1/gji-run-hook.1
CHANGED
package/man/man1/gji-status.1
CHANGED
package/man/man1/gji-sync.1
CHANGED
package/man/man1/gji-task.1
CHANGED
package/man/man1/gji-undo.1
CHANGED
package/man/man1/gji-warp.1
CHANGED
package/man/man1/gji.1
CHANGED