@solaqua/gji 0.12.5 → 0.14.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/README.md +12 -0
- package/dist/application/worktree/catalog.d.ts +31 -0
- package/dist/application/worktree/catalog.js +88 -0
- package/dist/application/worktree/context-card.d.ts +14 -0
- package/dist/application/worktree/context-card.js +12 -0
- package/dist/{go-resolver.d.ts → application/worktree/go-resolution.d.ts} +12 -4
- package/dist/{go-resolver.js → application/worktree/go-resolution.js} +50 -46
- package/dist/application/worktree/read-models.d.ts +31 -0
- package/dist/application/worktree/sources.d.ts +16 -0
- package/dist/application/worktree/sources.js +86 -0
- package/dist/{back.d.ts → cli/commands/back.d.ts} +3 -1
- package/dist/{back.js → cli/commands/back.js} +8 -6
- package/dist/{clean.d.ts → cli/commands/clean.d.ts} +6 -3
- package/dist/cli/commands/clean.js +555 -0
- package/dist/{completion.js → cli/commands/completion.js} +2 -2
- package/dist/{config-command.d.ts → cli/commands/config-command.d.ts} +2 -0
- package/dist/{config-command.js → cli/commands/config-command.js} +7 -5
- package/dist/{doctor.d.ts → cli/commands/doctor.d.ts} +2 -0
- package/dist/{doctor.js → cli/commands/doctor.js} +23 -25
- package/dist/{done.d.ts → cli/commands/done.d.ts} +2 -0
- package/dist/{done.js → cli/commands/done.js} +26 -23
- package/dist/{go.d.ts → cli/commands/go.d.ts} +8 -2
- package/dist/{go.js → cli/commands/go.js} +68 -48
- package/dist/{history-command.d.ts → cli/commands/history-command.d.ts} +2 -0
- package/dist/{history-command.js → cli/commands/history-command.js} +3 -1
- package/dist/{hub.d.ts → cli/commands/hub.d.ts} +7 -3
- package/dist/{hub.js → cli/commands/hub.js} +26 -33
- package/dist/{init.d.ts → cli/commands/init.d.ts} +3 -1
- package/dist/{init.js → cli/commands/init.js} +37 -34
- package/dist/{ls.d.ts → cli/commands/ls.d.ts} +4 -2
- package/dist/{ls.js → cli/commands/ls.js} +8 -5
- package/dist/{new.d.ts → cli/commands/new.d.ts} +6 -2
- package/dist/{new.js → cli/commands/new.js} +237 -109
- package/dist/{open.d.ts → cli/commands/open.d.ts} +4 -2
- package/dist/{open.js → cli/commands/open.js} +19 -12
- package/dist/{pr-open.d.ts → cli/commands/pr-open.d.ts} +4 -2
- package/dist/{pr-open.js → cli/commands/pr-open.js} +20 -18
- package/dist/{pr.d.ts → cli/commands/pr.d.ts} +5 -3
- package/dist/{pr.js → cli/commands/pr.js} +34 -41
- package/dist/{remove.d.ts → cli/commands/remove.d.ts} +4 -2
- package/dist/{remove.js → cli/commands/remove.js} +23 -17
- package/dist/{root.d.ts → cli/commands/root.d.ts} +2 -0
- package/dist/{root.js → cli/commands/root.js} +4 -2
- package/dist/{run-hook.d.ts → cli/commands/run-hook.d.ts} +2 -0
- package/dist/{run-hook.js → cli/commands/run-hook.js} +7 -4
- package/dist/{status.d.ts → cli/commands/status.d.ts} +2 -0
- package/dist/{status.js → cli/commands/status.js} +10 -7
- package/dist/{sync-files-command.d.ts → cli/commands/sync-files-command.d.ts} +2 -0
- package/dist/{sync-files-command.js → cli/commands/sync-files-command.js} +11 -9
- package/dist/{sync.d.ts → cli/commands/sync.d.ts} +2 -0
- package/dist/{sync.js → cli/commands/sync.js} +7 -4
- package/dist/{task-command.d.ts → cli/commands/task-command.d.ts} +2 -0
- package/dist/{task-command.js → cli/commands/task-command.js} +4 -2
- package/dist/{undo.d.ts → cli/commands/undo.d.ts} +8 -6
- package/dist/{undo.js → cli/commands/undo.js} +44 -34
- package/dist/{warp.d.ts → cli/commands/warp.d.ts} +5 -2
- package/dist/{warp.js → cli/commands/warp.js} +25 -13
- package/dist/cli/dependencies.d.ts +114 -0
- package/dist/cli/dependencies.js +118 -0
- package/dist/{cli.d.ts → cli/program.d.ts} +4 -2
- package/dist/{cli.js → cli/program.js} +108 -124
- package/dist/domain/repository/context.d.ts +6 -0
- package/dist/domain/repository/context.js +1 -0
- package/dist/domain/repository/registry.d.ts +5 -0
- package/dist/domain/repository/registry.js +1 -0
- package/dist/domain/shared/concurrency.d.ts +1 -0
- package/dist/domain/shared/concurrency.js +20 -0
- package/dist/domain/worktree/matching.d.ts +4 -0
- package/dist/domain/worktree/matching.js +79 -0
- package/dist/domain/worktree/policy.d.ts +2 -0
- package/dist/domain/worktree/policy.js +58 -0
- package/dist/domain/worktree/pr-reference.d.ts +1 -0
- package/dist/domain/worktree/pr-reference.js +9 -0
- package/dist/{worktree-source.d.ts → domain/worktree/source.d.ts} +1 -1
- package/dist/domain/worktree/source.js +1 -0
- package/dist/domain/worktree/types.d.ts +5 -0
- package/dist/domain/worktree/types.js +1 -0
- package/dist/gji-bundle.mjs +8756 -7666
- package/dist/index.js +3 -3
- package/dist/{dependency-bootstrap.d.ts → infrastructure/bootstrap/dependency-bootstrap.d.ts} +3 -30
- package/dist/{dependency-bootstrap.js → infrastructure/bootstrap/dependency-bootstrap.js} +4 -4
- package/dist/infrastructure/git/health.d.ts +9 -0
- package/dist/infrastructure/git/health.js +44 -0
- package/dist/infrastructure/git/refs.d.ts +6 -0
- package/dist/{git.js → infrastructure/git/refs.js} +4 -62
- package/dist/infrastructure/git/runner.d.ts +2 -0
- package/dist/infrastructure/git/runner.js +16 -0
- package/dist/{editor.d.ts → infrastructure/integrations/editor.d.ts} +2 -6
- package/dist/{pull-requests.d.ts → infrastructure/integrations/pull-requests.d.ts} +3 -11
- package/dist/{config.d.ts → infrastructure/persistence/config.d.ts} +3 -17
- package/dist/{config.js → infrastructure/persistence/config.js} +2 -17
- package/dist/{history.d.ts → infrastructure/persistence/history.d.ts} +2 -5
- package/dist/{task.js → infrastructure/persistence/task.js} +1 -1
- package/dist/infrastructure/process/command-runner.d.ts +3 -0
- package/dist/{hooks.d.ts → infrastructure/process/hooks.d.ts} +2 -12
- package/dist/infrastructure/repository/adapters.d.ts +7 -0
- package/dist/infrastructure/repository/adapters.js +23 -0
- package/dist/infrastructure/repository/context.d.ts +3 -0
- package/dist/infrastructure/repository/context.js +20 -0
- package/dist/infrastructure/repository/refs.d.ts +3 -0
- package/dist/infrastructure/repository/refs.js +37 -0
- package/dist/{repo-registry.d.ts → infrastructure/repository/registry.d.ts} +1 -5
- package/dist/{repo-registry.js → infrastructure/repository/registry.js} +1 -1
- package/dist/infrastructure/repository/worktrees.d.ts +2 -0
- package/dist/infrastructure/repository/worktrees.js +48 -0
- package/dist/{uv-validation.d.ts → infrastructure/validation/uv.d.ts} +1 -1
- package/dist/{uv-validation.js → infrastructure/validation/uv.js} +1 -1
- package/dist/infrastructure/worktree/bootstrap.d.ts +3 -0
- package/dist/{worktree-bootstrap.js → infrastructure/worktree/bootstrap.js} +7 -10
- package/dist/infrastructure/worktree/info.d.ts +6 -0
- package/dist/infrastructure/worktree/info.js +61 -0
- package/dist/{worktree-management.d.ts → infrastructure/worktree/lifecycle.d.ts} +0 -6
- package/dist/{worktree-management.js → infrastructure/worktree/lifecycle.js} +1 -9
- package/dist/ports/bootstrap.d.ts +61 -0
- package/dist/ports/bootstrap.js +1 -0
- package/dist/ports/config.d.ts +21 -0
- package/dist/ports/config.js +17 -0
- package/dist/ports/editor.d.ts +6 -0
- package/dist/ports/editor.js +1 -0
- package/dist/ports/git.d.ts +8 -0
- package/dist/ports/git.js +1 -0
- package/dist/ports/history.d.ts +5 -0
- package/dist/ports/history.js +1 -0
- package/dist/ports/hooks.d.ts +12 -0
- package/dist/ports/hooks.js +1 -0
- package/dist/{command-runner.d.ts → ports/process.d.ts} +0 -1
- package/dist/ports/process.js +1 -0
- package/dist/ports/pull-requests.d.ts +11 -0
- package/dist/ports/pull-requests.js +1 -0
- package/dist/ports/repository.d.ts +17 -0
- package/dist/ports/repository.js +1 -0
- package/dist/{bootstrap-output.d.ts → presentation/bootstrap/output.d.ts} +1 -1
- package/dist/presentation/bootstrap/preview.d.ts +2 -0
- package/dist/{bootstrap-preview.js → presentation/bootstrap/preview.js} +0 -4
- package/dist/{shell-completion.js → presentation/shell/completion.js} +5 -4
- package/dist/presentation/terminal/context-card.d.ts +2 -0
- package/dist/{context-card.js → presentation/terminal/context-card.js} +3 -12
- package/dist/presentation/worktree/format.d.ts +4 -0
- package/dist/presentation/worktree/format.js +41 -0
- package/dist/{worktree-picker.d.ts → presentation/worktree/picker.d.ts} +16 -17
- package/dist/{worktree-picker.js → presentation/worktree/picker.js} +30 -184
- package/man/man1/gji-back.1 +1 -1
- package/man/man1/gji-clean.1 +1 -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 +6 -3
- 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 +2 -2
- package/package.json +1 -1
- package/dist/bootstrap-preview.d.ts +0 -9
- package/dist/clean.js +0 -313
- package/dist/context-card.d.ts +0 -1
- package/dist/format-bytes.d.ts +0 -1
- package/dist/format-bytes.js +0 -14
- package/dist/git.d.ts +0 -18
- package/dist/repo.d.ts +0 -20
- package/dist/repo.js +0 -161
- package/dist/worktree-bootstrap.d.ts +0 -24
- package/dist/worktree-info.d.ts +0 -37
- package/dist/worktree-info.js +0 -123
- package/dist/worktree-sources.d.ts +0 -4
- package/dist/worktree-sources.js +0 -77
- /package/dist/{worktree-source.js → application/worktree/read-models.js} +0 -0
- /package/dist/{completion.d.ts → cli/commands/completion.d.ts} +0 -0
- /package/dist/{headless.d.ts → cli/runtime/headless.d.ts} +0 -0
- /package/dist/{headless.js → cli/runtime/headless.js} +0 -0
- /package/dist/{paths.d.ts → domain/shared/paths.d.ts} +0 -0
- /package/dist/{paths.js → domain/shared/paths.js} +0 -0
- /package/dist/{file-sync.d.ts → infrastructure/filesystem/file-sync.d.ts} +0 -0
- /package/dist/{file-sync.js → infrastructure/filesystem/file-sync.js} +0 -0
- /package/dist/{fs-utils.d.ts → infrastructure/filesystem/fs-utils.d.ts} +0 -0
- /package/dist/{fs-utils.js → infrastructure/filesystem/fs-utils.js} +0 -0
- /package/dist/{safe-destination.d.ts → infrastructure/filesystem/safe-destination.d.ts} +0 -0
- /package/dist/{safe-destination.js → infrastructure/filesystem/safe-destination.js} +0 -0
- /package/dist/{browser.d.ts → infrastructure/integrations/browser.d.ts} +0 -0
- /package/dist/{browser.js → infrastructure/integrations/browser.js} +0 -0
- /package/dist/{editor.js → infrastructure/integrations/editor.js} +0 -0
- /package/dist/{pull-requests.js → infrastructure/integrations/pull-requests.js} +0 -0
- /package/dist/{history.js → infrastructure/persistence/history.js} +0 -0
- /package/dist/{slots.d.ts → infrastructure/persistence/slots.d.ts} +0 -0
- /package/dist/{slots.js → infrastructure/persistence/slots.js} +0 -0
- /package/dist/{task.d.ts → infrastructure/persistence/task.d.ts} +0 -0
- /package/dist/{command-runner.js → infrastructure/process/command-runner.js} +0 -0
- /package/dist/{hooks.js → infrastructure/process/hooks.js} +0 -0
- /package/dist/{bootstrap-output.js → presentation/bootstrap/output.js} +0 -0
- /package/dist/{conflict.d.ts → presentation/prompts/path-conflict.d.ts} +0 -0
- /package/dist/{conflict.js → presentation/prompts/path-conflict.js} +0 -0
- /package/dist/{shell-completion.d.ts → presentation/shell/completion.d.ts} +0 -0
- /package/dist/{shell-handoff.d.ts → presentation/shell/handoff.d.ts} +0 -0
- /package/dist/{shell-handoff.js → presentation/shell/handoff.js} +0 -0
- /package/dist/{shell-setup.d.ts → presentation/shell/setup.d.ts} +0 -0
- /package/dist/{shell-setup.js → presentation/shell/setup.js} +0 -0
- /package/dist/{shell.d.ts → presentation/shell/shell.d.ts} +0 -0
- /package/dist/{shell.js → presentation/shell/shell.js} +0 -0
- /package/dist/{navigation-output.d.ts → presentation/terminal/navigation.d.ts} +0 -0
- /package/dist/{navigation-output.js → presentation/terminal/navigation.js} +0 -0
- /package/dist/{terminal-text.d.ts → presentation/terminal/text.d.ts} +0 -0
- /package/dist/{terminal-text.js → presentation/terminal/text.js} +0 -0
- /package/dist/{worktree-prompts.d.ts → presentation/worktree/prompts.d.ts} +0 -0
- /package/dist/{worktree-prompts.js → presentation/worktree/prompts.js} +0 -0
|
@@ -1,23 +1,27 @@
|
|
|
1
1
|
import { basename } from "node:path";
|
|
2
2
|
import { stdin, stdout } from "node:process";
|
|
3
3
|
import { spinner } from "@clack/prompts";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { middleEllipsize, sanitizeTerminalText, terminalWidth, } from "
|
|
8
|
-
import { formatRelativeAge, formatUpstreamState,
|
|
9
|
-
import {
|
|
4
|
+
import { loadWorktreeCatalog } from "../../application/worktree/catalog.js";
|
|
5
|
+
import { listDiscoverableWorktreeSources } from "../../application/worktree/sources.js";
|
|
6
|
+
import { mapWithConcurrency } from "../../domain/shared/concurrency.js";
|
|
7
|
+
import { middleEllipsize, sanitizeTerminalText, terminalWidth, } from "../../presentation/terminal/text.js";
|
|
8
|
+
import { formatRelativeAge, formatUpstreamState, } from "../../presentation/worktree/format.js";
|
|
9
|
+
import { defaultCliDependencies } from "../dependencies.js";
|
|
10
10
|
const MAX_HUB_REPOSITORY_CONCURRENCY = 4;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
export async function buildHubData(cwd, dependencies = {}, runtime = defaultCliDependencies) {
|
|
12
|
+
const { detectRepository } = runtime.repositoryContext;
|
|
13
|
+
const sourceDependencies = {
|
|
14
|
+
...runtime.repositoryContext,
|
|
15
|
+
...runtime.repositoryRegistry,
|
|
16
|
+
...runtime.worktrees,
|
|
17
|
+
};
|
|
15
18
|
const queryRepositoryPullRequests = dependencies.queryRepositoryPullRequests ??
|
|
16
|
-
|
|
19
|
+
runtime.pullRequests.listOpenPullRequestsForRepository;
|
|
17
20
|
const currentRepository = await detectRepository(cwd).catch(() => null);
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
+
const { sources } = await listDiscoverableWorktreeSources({
|
|
22
|
+
cwd,
|
|
23
|
+
repositoryPort: sourceDependencies,
|
|
24
|
+
});
|
|
21
25
|
const groups = new Map();
|
|
22
26
|
for (const source of sources) {
|
|
23
27
|
if (!source.repoRoot)
|
|
@@ -35,7 +39,6 @@ export async function buildHubData(cwd, dependencies = {}) {
|
|
|
35
39
|
}
|
|
36
40
|
}
|
|
37
41
|
const repositories = await mapWithConcurrency([...groups.entries()], MAX_HUB_REPOSITORY_CONCURRENCY, async ([root, group]) => {
|
|
38
|
-
const infos = await readWorktreeInfos(group.sources.map((source) => source.worktree));
|
|
39
42
|
let pullRequests = [];
|
|
40
43
|
try {
|
|
41
44
|
pullRequests = await queryRepositoryPullRequests(root);
|
|
@@ -43,10 +46,14 @@ export async function buildHubData(cwd, dependencies = {}) {
|
|
|
43
46
|
catch {
|
|
44
47
|
// PR metadata is optional. The hub remains useful when a provider is unavailable.
|
|
45
48
|
}
|
|
46
|
-
const
|
|
49
|
+
const hydrated = await loadWorktreeCatalog(group.sources, "full", {
|
|
50
|
+
...runtime.worktreeCatalog,
|
|
51
|
+
queryRepositoryPullRequests: async () => pullRequests,
|
|
52
|
+
});
|
|
53
|
+
const worktrees = hydrated.map(({ info, lastUsedTimestamp, pullRequests }) => ({
|
|
47
54
|
...info,
|
|
48
|
-
lastUsedTimestamp
|
|
49
|
-
pullRequests
|
|
55
|
+
lastUsedTimestamp,
|
|
56
|
+
pullRequests,
|
|
50
57
|
}));
|
|
51
58
|
return {
|
|
52
59
|
current: currentRepository?.repoRoot === root,
|
|
@@ -73,7 +80,7 @@ export async function runHubCommand(options, dependencies = {}) {
|
|
|
73
80
|
loading?.start("Loading worktrees");
|
|
74
81
|
let data;
|
|
75
82
|
try {
|
|
76
|
-
data = await buildHubData(options.cwd, dependencies);
|
|
83
|
+
data = await buildHubData(options.cwd, dependencies, options.runtime);
|
|
77
84
|
}
|
|
78
85
|
finally {
|
|
79
86
|
loading?.stop();
|
|
@@ -283,17 +290,3 @@ function formatHumanText(value, maxLength) {
|
|
|
283
290
|
? sanitized
|
|
284
291
|
: `${sanitized.slice(0, Math.max(0, maxLength - 1))}…`;
|
|
285
292
|
}
|
|
286
|
-
async function mapWithConcurrency(items, limit, mapper) {
|
|
287
|
-
const results = new Array(items.length);
|
|
288
|
-
let nextIndex = 0;
|
|
289
|
-
async function readNext() {
|
|
290
|
-
for (;;) {
|
|
291
|
-
const index = nextIndex++;
|
|
292
|
-
if (index >= items.length)
|
|
293
|
-
return;
|
|
294
|
-
results[index] = await mapper(items[index]);
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
await Promise.all(Array.from({ length: Math.min(limit, items.length) }, () => readNext()));
|
|
298
|
-
return results;
|
|
299
|
-
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { type SupportedShell } from "
|
|
1
|
+
import { type SupportedShell } from "../../presentation/shell/shell.js";
|
|
2
|
+
import { type CliRuntime } from "../dependencies.js";
|
|
2
3
|
export type InstallSaveTarget = "local" | "global";
|
|
3
4
|
export type ShellIntegrationChoice = "existing" | "install" | "skip";
|
|
4
5
|
export interface SetupWizardResult {
|
|
@@ -29,6 +30,7 @@ export interface InitCommandOptions {
|
|
|
29
30
|
promptForOnboarding?: (context: InitOnboardingContext) => Promise<InitOnboardingResult | null>;
|
|
30
31
|
promptForSetup?: () => Promise<SetupWizardResult | null>;
|
|
31
32
|
shell?: string;
|
|
33
|
+
runtime?: CliRuntime<"integrations" | "configStore">;
|
|
32
34
|
stderr?: (chunk: string) => void;
|
|
33
35
|
stdout: (chunk: string) => void;
|
|
34
36
|
write?: boolean;
|
|
@@ -3,12 +3,11 @@ import { access, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
4
|
import { dirname } from "node:path";
|
|
5
5
|
import { confirm, intro, isCancel, log, outro, select, text, } from "@clack/prompts";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import { SHELL_INTEGRATION_END_MARKER as END_MARKER, executableExists, hasShellIntegration, ONBOARDING_SHELL_INTEGRATION_END_MARKER as ONBOARDING_END_MARKER, ONBOARDING_SHELL_INTEGRATION_START_MARKER as ONBOARDING_START_MARKER, resolveCompletionPath, resolveShellConfigPath, SHELL_INTEGRATION_START_MARKER as START_MARKER, } from "./shell-setup.js";
|
|
6
|
+
import { renderShellCompletion } from "../../presentation/shell/completion.js";
|
|
7
|
+
import { SHELL_INTEGRATION_END_MARKER as END_MARKER, executableExists, hasShellIntegration, ONBOARDING_SHELL_INTEGRATION_END_MARKER as ONBOARDING_END_MARKER, ONBOARDING_SHELL_INTEGRATION_START_MARKER as ONBOARDING_START_MARKER, resolveCompletionPath, resolveShellConfigPath, SHELL_INTEGRATION_START_MARKER as START_MARKER, } from "../../presentation/shell/setup.js";
|
|
8
|
+
import { resolveSupportedShell, } from "../../presentation/shell/shell.js";
|
|
9
|
+
import { defaultCliDependencies, } from "../dependencies.js";
|
|
10
|
+
import { isHeadless } from "../runtime/headless.js";
|
|
12
11
|
const ZSH_COMPLETION_PATH_LINE = "fpath=(~/.zsh/completions $fpath)";
|
|
13
12
|
const SHELL_WRAPPED_COMMANDS = [
|
|
14
13
|
{
|
|
@@ -69,12 +68,13 @@ const SHELL_WRAPPED_COMMANDS = [
|
|
|
69
68
|
},
|
|
70
69
|
];
|
|
71
70
|
export async function runInitCommand(options) {
|
|
71
|
+
const runtime = options.runtime ?? defaultCliDependencies;
|
|
72
72
|
if (options.shell === undefined) {
|
|
73
|
-
return runOnboardingInitCommand(options);
|
|
73
|
+
return runOnboardingInitCommand(options, runtime);
|
|
74
74
|
}
|
|
75
|
-
return runLegacyInitCommand(options);
|
|
75
|
+
return runLegacyInitCommand(options, runtime);
|
|
76
76
|
}
|
|
77
|
-
async function runOnboardingInitCommand(options) {
|
|
77
|
+
async function runOnboardingInitCommand(options, runtime) {
|
|
78
78
|
if (options.json || isHeadless() || !canRunOnboarding(options)) {
|
|
79
79
|
return writeNonInteractiveInitError(options);
|
|
80
80
|
}
|
|
@@ -84,14 +84,14 @@ async function runOnboardingInitCommand(options) {
|
|
|
84
84
|
home,
|
|
85
85
|
};
|
|
86
86
|
if (options.promptForOnboarding === undefined) {
|
|
87
|
-
return runDefaultOnboarding(context);
|
|
87
|
+
return runDefaultOnboarding(context, runtime);
|
|
88
88
|
}
|
|
89
89
|
const result = await options.promptForOnboarding(context);
|
|
90
90
|
if (!result) {
|
|
91
91
|
options.stderr?.("Aborted.\n");
|
|
92
92
|
return 1;
|
|
93
93
|
}
|
|
94
|
-
await applyOnboardingResult(result, home);
|
|
94
|
+
await applyOnboardingResult(result, home, runtime);
|
|
95
95
|
return 0;
|
|
96
96
|
}
|
|
97
97
|
function canRunOnboarding(options) {
|
|
@@ -104,7 +104,7 @@ function writeNonInteractiveInitError(options) {
|
|
|
104
104
|
options.stderr?.(options.json ? `${JSON.stringify({ error })}\n` : `${error}\n`);
|
|
105
105
|
return 1;
|
|
106
106
|
}
|
|
107
|
-
async function runDefaultOnboarding(context) {
|
|
107
|
+
async function runDefaultOnboarding(context, runtime) {
|
|
108
108
|
intro("gji init");
|
|
109
109
|
const shell = await select({
|
|
110
110
|
message: "Which shell should gji configure?",
|
|
@@ -124,7 +124,7 @@ async function runDefaultOnboarding(context) {
|
|
|
124
124
|
return abortDefaultOnboarding();
|
|
125
125
|
const completionPath = resolveCompletionPath(shell, context.home);
|
|
126
126
|
const completionAlreadyInstalled = await fileExists(completionPath);
|
|
127
|
-
await applyShellIntegration(shell, shellIntegration, context.home);
|
|
127
|
+
await applyShellIntegration(shell, shellIntegration, context.home, runtime);
|
|
128
128
|
const installCompletion = await promptForCompletion(shell, completionPath);
|
|
129
129
|
if (installCompletion === null)
|
|
130
130
|
return abortDefaultOnboarding();
|
|
@@ -135,21 +135,21 @@ async function runDefaultOnboarding(context) {
|
|
|
135
135
|
if (shell === "zsh" && (completionAlreadyInstalled || installCompletion)) {
|
|
136
136
|
await ensureZshCompletionPath(rcPath);
|
|
137
137
|
}
|
|
138
|
-
const editor = await promptForEditor();
|
|
138
|
+
const editor = await promptForEditor(runtime.integrations.EDITORS);
|
|
139
139
|
if (editor === null)
|
|
140
140
|
return abortDefaultOnboarding();
|
|
141
141
|
if (editor) {
|
|
142
|
-
await updateGlobalConfigKey("editor", editor, context.home);
|
|
142
|
+
await runtime.configStore.updateGlobalConfigKey("editor", editor, context.home);
|
|
143
143
|
}
|
|
144
144
|
outro(`Setup complete. Restart your shell or run: source ${rcPath}\nVerify with: gji doctor`);
|
|
145
145
|
return 0;
|
|
146
146
|
}
|
|
147
|
-
async function applyShellIntegration(shell, choice, home) {
|
|
147
|
+
async function applyShellIntegration(shell, choice, home, runtime) {
|
|
148
148
|
if (choice === "install") {
|
|
149
149
|
await installOnboardingShellIntegration(shell, home);
|
|
150
150
|
}
|
|
151
151
|
if (choice !== "skip") {
|
|
152
|
-
await updateGlobalConfigKey("shellIntegration", true, home);
|
|
152
|
+
await runtime.configStore.updateGlobalConfigKey("shellIntegration", true, home);
|
|
153
153
|
}
|
|
154
154
|
}
|
|
155
155
|
function abortDefaultOnboarding() {
|
|
@@ -187,8 +187,8 @@ async function promptForCompletion(shell, completionPath) {
|
|
|
187
187
|
return null;
|
|
188
188
|
return confirmed;
|
|
189
189
|
}
|
|
190
|
-
async function promptForEditor() {
|
|
191
|
-
const availableEditors = await findAvailableEditors();
|
|
190
|
+
async function promptForEditor(editors) {
|
|
191
|
+
const availableEditors = await findAvailableEditors(editors);
|
|
192
192
|
if (availableEditors.length === 0) {
|
|
193
193
|
log.info("No supported editor CLIs found on PATH; skipping editor setup.");
|
|
194
194
|
return undefined;
|
|
@@ -209,20 +209,20 @@ async function promptForEditor() {
|
|
|
209
209
|
return null;
|
|
210
210
|
return selected === skipValue ? undefined : selected;
|
|
211
211
|
}
|
|
212
|
-
async function findAvailableEditors() {
|
|
212
|
+
async function findAvailableEditors(editors) {
|
|
213
213
|
const availableEditors = [];
|
|
214
|
-
for (const editor of
|
|
214
|
+
for (const editor of editors) {
|
|
215
215
|
if (await executableExists(editor.cli)) {
|
|
216
216
|
availableEditors.push(editor);
|
|
217
217
|
}
|
|
218
218
|
}
|
|
219
219
|
return availableEditors;
|
|
220
220
|
}
|
|
221
|
-
async function applyOnboardingResult(result, home) {
|
|
221
|
+
async function applyOnboardingResult(result, home, runtime) {
|
|
222
222
|
const rcPath = resolveShellConfigPath(result.shell, home);
|
|
223
223
|
const completionPath = resolveCompletionPath(result.shell, home);
|
|
224
224
|
const completionAlreadyInstalled = await fileExists(completionPath);
|
|
225
|
-
await applyShellIntegration(result.shell, result.shellIntegration, home);
|
|
225
|
+
await applyShellIntegration(result.shell, result.shellIntegration, home, runtime);
|
|
226
226
|
if (result.installCompletion) {
|
|
227
227
|
await mkdir(dirname(completionPath), { recursive: true });
|
|
228
228
|
await writeFile(completionPath, renderShellCompletion(result.shell), "utf8");
|
|
@@ -232,7 +232,7 @@ async function applyOnboardingResult(result, home) {
|
|
|
232
232
|
await ensureZshCompletionPath(rcPath);
|
|
233
233
|
}
|
|
234
234
|
if (result.editor) {
|
|
235
|
-
await updateGlobalConfigKey("editor", result.editor, home);
|
|
235
|
+
await runtime.configStore.updateGlobalConfigKey("editor", result.editor, home);
|
|
236
236
|
}
|
|
237
237
|
}
|
|
238
238
|
async function installOnboardingShellIntegration(shell, home) {
|
|
@@ -290,7 +290,7 @@ async function fileExists(path) {
|
|
|
290
290
|
return false;
|
|
291
291
|
}
|
|
292
292
|
}
|
|
293
|
-
async function runLegacyInitCommand(options) {
|
|
293
|
+
async function runLegacyInitCommand(options, runtime) {
|
|
294
294
|
const shell = resolveSupportedShell(options.shell, process.env.SHELL);
|
|
295
295
|
const home = options.home ?? homedir();
|
|
296
296
|
if (!shell) {
|
|
@@ -309,7 +309,7 @@ async function runLegacyInitCommand(options) {
|
|
|
309
309
|
await writeFile(rcPath, next, "utf8");
|
|
310
310
|
options.stdout(`${rcPath}\n`);
|
|
311
311
|
// Run the setup wizard on the first-ever init (not on subsequent re-runs).
|
|
312
|
-
const { config: globalConfig } = await loadGlobalConfig(home);
|
|
312
|
+
const { config: globalConfig } = await runtime.configStore.loadGlobalConfig(home);
|
|
313
313
|
const alreadyConfigured = "shellIntegration" in globalConfig || "installSaveTarget" in globalConfig;
|
|
314
314
|
const hasCustomPrompt = options.promptForSetup !== undefined;
|
|
315
315
|
const canPrompt = !isHeadless() && (hasCustomPrompt || process.stdout.isTTY === true);
|
|
@@ -317,12 +317,12 @@ async function runLegacyInitCommand(options) {
|
|
|
317
317
|
const prompt = options.promptForSetup ?? defaultPromptForSetup;
|
|
318
318
|
const result = await prompt();
|
|
319
319
|
if (result) {
|
|
320
|
-
await updateGlobalConfigKey("installSaveTarget", result.installSaveTarget, home);
|
|
321
|
-
await saveWizardConfig(result, options.cwd, home);
|
|
320
|
+
await runtime.configStore.updateGlobalConfigKey("installSaveTarget", result.installSaveTarget, home);
|
|
321
|
+
await saveWizardConfig(result, options.cwd, home, runtime);
|
|
322
322
|
}
|
|
323
323
|
}
|
|
324
324
|
// Mark shell integration as installed so the first-run nudge is suppressed.
|
|
325
|
-
await updateGlobalConfigKey("shellIntegration", true, home);
|
|
325
|
+
await runtime.configStore.updateGlobalConfigKey("shellIntegration", true, home);
|
|
326
326
|
return 0;
|
|
327
327
|
}
|
|
328
328
|
export function renderShellIntegration(shell) {
|
|
@@ -361,7 +361,7 @@ export function upsertShellIntegration(existingConfig, script) {
|
|
|
361
361
|
}
|
|
362
362
|
return ensureTrailingNewline(`${prefix}\n\n${trimmedScript}`);
|
|
363
363
|
}
|
|
364
|
-
async function saveWizardConfig(result, cwd, home) {
|
|
364
|
+
async function saveWizardConfig(result, cwd, home, runtime) {
|
|
365
365
|
const values = {};
|
|
366
366
|
if (result.branchPrefix)
|
|
367
367
|
values.branchPrefix = result.branchPrefix;
|
|
@@ -379,12 +379,15 @@ async function saveWizardConfig(result, cwd, home) {
|
|
|
379
379
|
if (Object.keys(values).length === 0)
|
|
380
380
|
return;
|
|
381
381
|
if (result.installSaveTarget === "local") {
|
|
382
|
-
const loaded = await loadConfig(cwd);
|
|
383
|
-
await saveLocalConfig(cwd, {
|
|
382
|
+
const loaded = await runtime.configStore.loadConfig(cwd);
|
|
383
|
+
await runtime.configStore.saveLocalConfig(cwd, {
|
|
384
|
+
...loaded.config,
|
|
385
|
+
...values,
|
|
386
|
+
});
|
|
384
387
|
}
|
|
385
388
|
else {
|
|
386
|
-
const { config: existing } = await loadGlobalConfig(home);
|
|
387
|
-
await saveGlobalConfig({ ...existing, ...values }, home);
|
|
389
|
+
const { config: existing } = await runtime.configStore.loadGlobalConfig(home);
|
|
390
|
+
await runtime.configStore.saveGlobalConfig({ ...existing, ...values }, home);
|
|
388
391
|
}
|
|
389
392
|
}
|
|
390
393
|
async function readExistingConfig(path) {
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import type { WorktreeInfo } from "../../application/worktree/read-models.js";
|
|
2
|
+
import type { WorktreeEntry } from "../../domain/worktree/types.js";
|
|
3
|
+
import { type CliRuntime } from "../dependencies.js";
|
|
3
4
|
export interface LsCommandOptions {
|
|
4
5
|
compact?: boolean;
|
|
5
6
|
cwd: string;
|
|
6
7
|
json?: boolean;
|
|
8
|
+
runtime?: CliRuntime<"worktrees" | "worktreeInfo">;
|
|
7
9
|
stdout: (chunk: string) => void;
|
|
8
10
|
}
|
|
9
11
|
export declare function runLsCommand(options: LsCommandOptions): Promise<number>;
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import { comparePaths } from "
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { comparePaths } from "../../domain/shared/paths.js";
|
|
2
|
+
import { formatLastCommit, formatUpstreamState, } from "../../presentation/worktree/format.js";
|
|
3
|
+
import { defaultCliDependencies } from "../dependencies.js";
|
|
4
4
|
export async function runLsCommand(options) {
|
|
5
|
+
const runtime = options.runtime ?? defaultCliDependencies;
|
|
6
|
+
const { listWorktrees } = runtime.worktrees;
|
|
7
|
+
const { readWorktreeInfos } = runtime.worktreeInfo;
|
|
5
8
|
const worktrees = sortWorktrees(await listWorktrees(options.cwd));
|
|
6
9
|
if (options.compact) {
|
|
7
10
|
if (options.json) {
|
|
@@ -44,7 +47,7 @@ export function formatDetailedWorktreeTable(worktrees) {
|
|
|
44
47
|
"UPSTREAM".padEnd(upstreamWidth, " ") +
|
|
45
48
|
" " +
|
|
46
49
|
"LAST".padEnd(lastCommitWidth, " ") +
|
|
47
|
-
(hasTasks ?
|
|
50
|
+
(hasTasks ? ` ${"TASK".padEnd(taskWidth, " ")}` : "") +
|
|
48
51
|
" PATH",
|
|
49
52
|
];
|
|
50
53
|
for (const row of rows) {
|
|
@@ -68,7 +71,7 @@ export function formatWorktreeTable(worktrees) {
|
|
|
68
71
|
path: worktree.path,
|
|
69
72
|
}));
|
|
70
73
|
const branchWidth = Math.max("BRANCH".length, ...rows.map((row) => row.branch.length));
|
|
71
|
-
const lines = [
|
|
74
|
+
const lines = [` ${"BRANCH".padEnd(branchWidth, " ")} PATH`];
|
|
72
75
|
for (const row of rows) {
|
|
73
76
|
lines.push(`${row.isCurrent ? "*" : " "} ${row.branch.padEnd(branchWidth, " ")} ${row.path}`);
|
|
74
77
|
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { type
|
|
1
|
+
import type { CommandRunner as BootstrapCommandRunner } from "../../ports/process.js";
|
|
2
|
+
import { type PathConflictChoice } from "../../presentation/prompts/path-conflict.js";
|
|
3
|
+
import { type CliRuntime } from "../dependencies.js";
|
|
3
4
|
export type { PathConflictChoice };
|
|
4
5
|
export type NewWorktreeMode = "create" | "checkout" | "track";
|
|
5
6
|
export interface NewCommandOptions {
|
|
6
7
|
branch?: string;
|
|
8
|
+
branchOnly?: boolean;
|
|
7
9
|
copy?: boolean;
|
|
8
10
|
cwd: string;
|
|
9
11
|
detached?: boolean;
|
|
@@ -22,7 +24,9 @@ export interface NewCommandOptions {
|
|
|
22
24
|
stderr: (chunk: string) => void;
|
|
23
25
|
stdout: (chunk: string) => void;
|
|
24
26
|
task?: string;
|
|
27
|
+
runtime?: NewRuntime;
|
|
25
28
|
}
|
|
29
|
+
type NewRuntime = CliRuntime<"bootstrap" | "config" | "git" | "history" | "integrations" | "repositoryContext" | "tasks">;
|
|
26
30
|
export interface NewCommandDependencies {
|
|
27
31
|
createBranchPlaceholder: () => string;
|
|
28
32
|
promptForBranch: (placeholder: string) => Promise<string | null>;
|