@solaqua/gji 0.12.4 → 0.13.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} +46 -44
- package/dist/application/worktree/read-models.d.ts +31 -0
- package/dist/application/worktree/sources.d.ts +7 -0
- package/dist/{worktree-sources.js → application/worktree/sources.js} +12 -24
- 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} +4 -2
- package/dist/{clean.js → cli/commands/clean.js} +32 -24
- 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} +6 -1
- package/dist/{go.js → cli/commands/go.js} +57 -41
- 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} +23 -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} +20 -10
- 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 +15 -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 +7100 -6265
- 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} +1 -51
- 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} +7 -11
- package/dist/{worktree-picker.js → presentation/worktree/picker.js} +36 -191
- 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/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-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
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { mapWithConcurrency } from "../../domain/shared/concurrency.js";
|
|
2
|
+
import { readWorktreeHealth } from "../git/health.js";
|
|
3
|
+
import { readBranchLastCommitTimestamp } from "../git/refs.js";
|
|
4
|
+
import { getWorktreeSlot } from "../persistence/slots.js";
|
|
5
|
+
import { readTask } from "../persistence/task.js";
|
|
6
|
+
const MAX_WORKTREE_INFO_READ_CONCURRENCY = 8;
|
|
7
|
+
export async function readWorktreeInfos(worktrees) {
|
|
8
|
+
return mapWithConcurrency(worktrees, MAX_WORKTREE_INFO_READ_CONCURRENCY, readWorktreeInfo);
|
|
9
|
+
}
|
|
10
|
+
export async function readWorktreeInfo(worktree) {
|
|
11
|
+
const [healthResult, lastCommitResult, slotResult, taskResult] = await Promise.allSettled([
|
|
12
|
+
readWorktreeHealth(worktree.path),
|
|
13
|
+
worktree.branch === null
|
|
14
|
+
? null
|
|
15
|
+
: readBranchLastCommitTimestamp(worktree.path, worktree.branch),
|
|
16
|
+
getWorktreeSlot(worktree.path),
|
|
17
|
+
readTask(worktree.path),
|
|
18
|
+
]);
|
|
19
|
+
const health = healthResult.status === "fulfilled" ? healthResult.value : null;
|
|
20
|
+
const lastCommitTimestamp = lastCommitResult.status === "fulfilled" ? lastCommitResult.value : null;
|
|
21
|
+
const slot = slotResult.status === "fulfilled" ? slotResult.value : null;
|
|
22
|
+
const task = taskResult.status === "fulfilled" ? (taskResult.value?.task ?? null) : null;
|
|
23
|
+
return {
|
|
24
|
+
...worktree,
|
|
25
|
+
lastCommitTimestamp,
|
|
26
|
+
slot,
|
|
27
|
+
status: health?.status ?? "unknown",
|
|
28
|
+
task,
|
|
29
|
+
upstream: buildUpstreamState(worktree.branch, health),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function buildUpstreamState(branch, health) {
|
|
33
|
+
if (branch === null) {
|
|
34
|
+
return { kind: "detached" };
|
|
35
|
+
}
|
|
36
|
+
if (health === null) {
|
|
37
|
+
return { kind: "unknown" };
|
|
38
|
+
}
|
|
39
|
+
if (!health.hasUpstream) {
|
|
40
|
+
return { kind: "no-upstream" };
|
|
41
|
+
}
|
|
42
|
+
if (health.upstreamGone) {
|
|
43
|
+
return { kind: "stale" };
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
ahead: health.ahead,
|
|
47
|
+
behind: health.behind,
|
|
48
|
+
kind: "tracked",
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
export function serializeWorktreeInfo(info) {
|
|
52
|
+
return {
|
|
53
|
+
branch: info.branch,
|
|
54
|
+
lastCommitTimestamp: info.lastCommitTimestamp,
|
|
55
|
+
path: info.path,
|
|
56
|
+
slot: info.slot,
|
|
57
|
+
status: info.status,
|
|
58
|
+
task: info.task,
|
|
59
|
+
upstream: info.upstream,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
import { type RepositoryContext, type WorktreeEntry } from "./repo.js";
|
|
2
|
-
export interface LinkedWorktreeContext {
|
|
3
|
-
linkedWorktrees: WorktreeEntry[];
|
|
4
|
-
repository: RepositoryContext;
|
|
5
|
-
}
|
|
6
|
-
export declare function loadLinkedWorktrees(cwd: string): Promise<LinkedWorktreeContext>;
|
|
7
1
|
export declare function removeWorktree(repoRoot: string, worktreePath: string): Promise<void>;
|
|
8
2
|
export declare function forceRemoveWorktree(repoRoot: string, worktreePath: string): Promise<void>;
|
|
9
3
|
export declare function deleteBranch(repoRoot: string, branch: string): Promise<void>;
|
|
@@ -1,18 +1,10 @@
|
|
|
1
1
|
import { execFile } from "node:child_process";
|
|
2
2
|
import { rm } from "node:fs/promises";
|
|
3
3
|
import { promisify } from "node:util";
|
|
4
|
-
import {
|
|
4
|
+
import { listWorktrees } from "../repository/worktrees.js";
|
|
5
5
|
const execFileAsync = promisify(execFile);
|
|
6
6
|
// Force English output so error message string matching is locale-independent.
|
|
7
7
|
const GIT_ENV = { ...process.env, LC_ALL: "C" };
|
|
8
|
-
export async function loadLinkedWorktrees(cwd) {
|
|
9
|
-
const repository = await detectRepository(cwd);
|
|
10
|
-
const linkedWorktrees = (await listWorktrees(cwd)).filter((worktree) => worktree.path !== repository.repoRoot);
|
|
11
|
-
return {
|
|
12
|
-
linkedWorktrees,
|
|
13
|
-
repository,
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
8
|
export async function removeWorktree(repoRoot, worktreePath) {
|
|
17
9
|
await execFileAsync("git", ["worktree", "remove", worktreePath], {
|
|
18
10
|
cwd: repoRoot,
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { EffectiveGjiConfig } from "./config.js";
|
|
2
|
+
import type { CommandRunner } from "./process.js";
|
|
3
|
+
export type BootstrapKind = "dependency" | "build-cache" | "sync-file";
|
|
4
|
+
export type BootstrapState = "installed" | "failed";
|
|
5
|
+
export type DependencyBootstrapMode = "off" | "install";
|
|
6
|
+
export interface BootstrapEvent {
|
|
7
|
+
adapter: string;
|
|
8
|
+
kind: BootstrapKind;
|
|
9
|
+
reason?: string;
|
|
10
|
+
state: BootstrapState;
|
|
11
|
+
target: string;
|
|
12
|
+
message: string;
|
|
13
|
+
}
|
|
14
|
+
export interface DependencyBootstrapReporter {
|
|
15
|
+
dependency(event: BootstrapEvent): void;
|
|
16
|
+
}
|
|
17
|
+
export interface DependencyBootstrapReport {
|
|
18
|
+
mode: DependencyBootstrapMode;
|
|
19
|
+
ready: boolean;
|
|
20
|
+
events: readonly BootstrapEvent[];
|
|
21
|
+
}
|
|
22
|
+
export interface DependencyBootstrapPreview {
|
|
23
|
+
mode: DependencyBootstrapMode;
|
|
24
|
+
targets: readonly {
|
|
25
|
+
adapter: string;
|
|
26
|
+
kind: BootstrapKind;
|
|
27
|
+
target: string;
|
|
28
|
+
command: string;
|
|
29
|
+
}[];
|
|
30
|
+
}
|
|
31
|
+
export interface DependencyBootstrapPreviewContext {
|
|
32
|
+
repoRoot: string;
|
|
33
|
+
currentRoot?: string;
|
|
34
|
+
worktreePath: string;
|
|
35
|
+
cargoBuildCommand?: string;
|
|
36
|
+
}
|
|
37
|
+
export interface DependencyBootstrapPort {
|
|
38
|
+
resolveMode(dependencyBootstrap: "off" | undefined, noInstall?: boolean): DependencyBootstrapMode;
|
|
39
|
+
preview(mode: DependencyBootstrapMode, context: DependencyBootstrapPreviewContext): Promise<DependencyBootstrapPreview>;
|
|
40
|
+
}
|
|
41
|
+
export interface WorktreeBootstrapOptions {
|
|
42
|
+
branch: string;
|
|
43
|
+
config: EffectiveGjiConfig;
|
|
44
|
+
currentRoot?: string;
|
|
45
|
+
dependencyDetectionRoot?: string;
|
|
46
|
+
dependencyMode: DependencyBootstrapMode;
|
|
47
|
+
runCommand?: CommandRunner;
|
|
48
|
+
commandStdout?: (chunk: string) => void;
|
|
49
|
+
commandStderr?: (chunk: string) => void;
|
|
50
|
+
repoRoot: string;
|
|
51
|
+
reporter: DependencyBootstrapReporter;
|
|
52
|
+
worktreePath: string;
|
|
53
|
+
}
|
|
54
|
+
export interface WorktreeBootstrapResult {
|
|
55
|
+
dependencyBootstrap: DependencyBootstrapReport;
|
|
56
|
+
ready: boolean;
|
|
57
|
+
syncFileFailures: readonly BootstrapEvent[];
|
|
58
|
+
}
|
|
59
|
+
export interface WorktreeBootstrapPort {
|
|
60
|
+
bootstrapWorktree(options: WorktreeBootstrapOptions): Promise<WorktreeBootstrapResult>;
|
|
61
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export type GjiConfig = Record<string, unknown>;
|
|
2
|
+
export type DependencyBootstrapSetting = "off";
|
|
3
|
+
export declare const KNOWN_CONFIG_KEYS: ReadonlySet<string>;
|
|
4
|
+
export declare const KNOWN_GLOBAL_CONFIG_KEYS: ReadonlySet<string>;
|
|
5
|
+
export interface EffectiveGjiConfig extends GjiConfig {
|
|
6
|
+
branchPrefix?: string;
|
|
7
|
+
dependencyBuildCommand?: string;
|
|
8
|
+
dependencyBootstrap?: DependencyBootstrapSetting;
|
|
9
|
+
editor?: string;
|
|
10
|
+
hooks?: Record<string, unknown>;
|
|
11
|
+
installSaveTarget?: string;
|
|
12
|
+
shellIntegration?: string;
|
|
13
|
+
syncFiles?: readonly string[];
|
|
14
|
+
syncDefaultBranch?: string;
|
|
15
|
+
syncRemote?: string;
|
|
16
|
+
worktreePath?: string;
|
|
17
|
+
}
|
|
18
|
+
export interface ConfigPort {
|
|
19
|
+
loadEffectiveConfig(root: string, home?: string, onWarning?: (message: string) => void): Promise<EffectiveGjiConfig>;
|
|
20
|
+
resolveConfigString(config: GjiConfig, key: string): string | undefined;
|
|
21
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export const KNOWN_CONFIG_KEYS = new Set([
|
|
2
|
+
"branchPrefix",
|
|
3
|
+
"dependencyBuildCommand",
|
|
4
|
+
"dependencyBootstrap",
|
|
5
|
+
"editor",
|
|
6
|
+
"hooks",
|
|
7
|
+
"installSaveTarget",
|
|
8
|
+
"shellIntegration",
|
|
9
|
+
"syncDefaultBranch",
|
|
10
|
+
"syncFiles",
|
|
11
|
+
"syncRemote",
|
|
12
|
+
"worktreePath",
|
|
13
|
+
]);
|
|
14
|
+
export const KNOWN_GLOBAL_CONFIG_KEYS = new Set([
|
|
15
|
+
...KNOWN_CONFIG_KEYS,
|
|
16
|
+
"repos",
|
|
17
|
+
]);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type GjiHookCommand = string | string[];
|
|
2
|
+
export interface GjiHooks {
|
|
3
|
+
"after-create"?: GjiHookCommand;
|
|
4
|
+
"after-enter"?: GjiHookCommand;
|
|
5
|
+
"before-remove"?: GjiHookCommand;
|
|
6
|
+
}
|
|
7
|
+
export interface HookContext {
|
|
8
|
+
branch?: string;
|
|
9
|
+
path: string;
|
|
10
|
+
repo: string;
|
|
11
|
+
slot?: number | null;
|
|
12
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface PullRequestInfo {
|
|
2
|
+
number: number;
|
|
3
|
+
sourceBranch: string;
|
|
4
|
+
title?: string;
|
|
5
|
+
url: string;
|
|
6
|
+
}
|
|
7
|
+
export interface PullRequestPort {
|
|
8
|
+
findOpenPullRequest(repoRoot: string, number: number): Promise<PullRequestInfo | null>;
|
|
9
|
+
listOpenPullRequests(repoRoot: string, sourceBranch: string): Promise<PullRequestInfo[]>;
|
|
10
|
+
listOpenPullRequestsForRepository(repoRoot: string): Promise<PullRequestInfo[]>;
|
|
11
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { RepositoryContext } from "../domain/repository/context.js";
|
|
2
|
+
import type { RepoRegistryEntry } from "../domain/repository/registry.js";
|
|
3
|
+
import type { WorktreeEntry } from "../domain/worktree/types.js";
|
|
4
|
+
export interface RepositoryContextPort {
|
|
5
|
+
detectRepository(cwd: string): Promise<RepositoryContext>;
|
|
6
|
+
}
|
|
7
|
+
export interface WorktreePort {
|
|
8
|
+
listWorktrees(cwd: string): Promise<WorktreeEntry[]>;
|
|
9
|
+
}
|
|
10
|
+
export interface RepositoryRefPort {
|
|
11
|
+
getRepositoryRemoteUrl(repoRoot: string, remote: string): Promise<string | null>;
|
|
12
|
+
hasLocalBranch(repoRoot: string, branch: string): Promise<boolean>;
|
|
13
|
+
hasRemoteBranch(repoRoot: string, remote: string, branch: string): Promise<boolean>;
|
|
14
|
+
}
|
|
15
|
+
export interface RepositoryRegistryPort {
|
|
16
|
+
loadRegistry(): Promise<RepoRegistryEntry[]>;
|
|
17
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { DependencyBootstrapReporter } from "
|
|
1
|
+
import type { DependencyBootstrapReporter } from "../../ports/bootstrap.js";
|
|
2
2
|
export declare function createBootstrapReporter(write: (chunk: string) => void, json: boolean): DependencyBootstrapReporter & {
|
|
3
3
|
write: (chunk: string) => void;
|
|
4
4
|
};
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
import { prepareDependencyBootstrap, previewDependencyBootstrap, } from "./dependency-bootstrap.js";
|
|
2
|
-
export async function createDependencyBootstrapPreview(mode, context) {
|
|
3
|
-
return previewDependencyBootstrap(await prepareDependencyBootstrap(mode, context));
|
|
4
|
-
}
|
|
5
1
|
export function formatDependencyBootstrapPreview(preview) {
|
|
6
2
|
if (!preview)
|
|
7
3
|
return "";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { KNOWN_GLOBAL_CONFIG_KEYS } from "
|
|
1
|
+
import { KNOWN_GLOBAL_CONFIG_KEYS } from "../../ports/config.js";
|
|
2
2
|
const TOP_LEVEL_COMMANDS = [
|
|
3
3
|
{
|
|
4
4
|
name: "new",
|
|
5
|
-
description: "create a
|
|
5
|
+
description: "create a branch with an optional linked worktree",
|
|
6
6
|
},
|
|
7
7
|
{
|
|
8
8
|
name: "done",
|
|
@@ -149,7 +149,7 @@ _gji_completion() {
|
|
|
149
149
|
|
|
150
150
|
case "$command_name" in
|
|
151
151
|
new)
|
|
152
|
-
COMPREPLY=( $(compgen -W "--detached --from-current --no-fetch --take --copy --task --force --open --editor --dry-run --no-install --json --help" -- "$cur") )
|
|
152
|
+
COMPREPLY=( $(compgen -W "--branch-only --detached --from-current --no-fetch --take --copy --task --force --open --editor --dry-run --no-install --json --help" -- "$cur") )
|
|
153
153
|
;;
|
|
154
154
|
done)
|
|
155
155
|
COMPREPLY=( $(compgen -W "--force --keep-branch --json --help" -- "$cur") )
|
|
@@ -387,6 +387,7 @@ complete -c gji -n '__fish_seen_subcommand_from undo' -l json -d 'emit JSON on s
|
|
|
387
387
|
${commandLines}
|
|
388
388
|
|
|
389
389
|
complete -c gji -n '__fish_seen_subcommand_from new' -l detached -d 'create a detached worktree without a branch'
|
|
390
|
+
complete -c gji -n '__fish_seen_subcommand_from new' -l branch-only -d 'update the default branch and create the new branch in the current worktree'
|
|
390
391
|
complete -c gji -n '__fish_seen_subcommand_from new' -l from-current -d 'base the new branch on the current worktree instead of the main worktree'
|
|
391
392
|
complete -c gji -n '__fish_seen_subcommand_from new' -l take -d 'move current uncommitted changes into the new worktree'
|
|
392
393
|
complete -c gji -n '__fish_seen_subcommand_from new' -l copy -d 'copy current uncommitted changes instead of moving them (requires --take)'
|
|
@@ -553,7 +554,7 @@ fi
|
|
|
553
554
|
|
|
554
555
|
case "\${words[2]}" in
|
|
555
556
|
new)
|
|
556
|
-
_arguments '--detached[create a detached worktree without a branch]' '--from-current[base the new branch on the current worktree instead of the main worktree]' '--no-fetch[skip refreshing the remote default branch before creating the new branch]' '--take[move current uncommitted changes into the new worktree]' '--copy[copy current uncommitted changes instead of moving them (requires --take)]' '--task[record the purpose of the new worktree]:description:' '--force[remove and recreate the worktree if the target path already exists]' '--open[open the new worktree in an editor after creation]' '--editor[editor CLI to use with --open (code, cursor, zed, …)]:editor:' '--dry-run[show what would be created without executing any git commands or writing files]' '--no-install[skip automatic dependency setup in the new worktree]' '--json[emit JSON on success or error instead of human-readable output]' '2:branch: '
|
|
557
|
+
_arguments '--branch-only[update the default branch and create the new branch in the current worktree]' '--detached[create a detached worktree without a branch]' '--from-current[base the new branch on the current worktree instead of the main worktree]' '--no-fetch[skip refreshing the remote default branch before creating the new branch]' '--take[move current uncommitted changes into the new worktree]' '--copy[copy current uncommitted changes instead of moving them (requires --take)]' '--task[record the purpose of the new worktree]:description:' '--force[remove and recreate the worktree if the target path already exists]' '--open[open the new worktree in an editor after creation]' '--editor[editor CLI to use with --open (code, cursor, zed, …)]:editor:' '--dry-run[show what would be created without executing any git commands or writing files]' '--no-install[skip automatic dependency setup in the new worktree]' '--json[emit JSON on success or error instead of human-readable output]' '2:branch: '
|
|
557
558
|
;;
|
|
558
559
|
done)
|
|
559
560
|
_arguments '--force[remove dirty or unmerged worktrees without prompting]' '--keep-branch[remove the worktree but preserve its branch]' '--json[emit JSON on success or error instead of human-readable output]' '2:branch: '
|
|
@@ -1,16 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import { readWorktreeInfo } from "./worktree-info.js";
|
|
4
|
-
export async function renderContextCard(worktreePath) {
|
|
5
|
-
const worktree = (await listWorktrees(worktreePath)).find((entry) => entry.path === worktreePath);
|
|
6
|
-
if (!worktree)
|
|
7
|
-
return null;
|
|
8
|
-
const info = await readWorktreeInfo(worktree);
|
|
9
|
-
const task = await readTask(worktreePath);
|
|
10
|
-
if (!task)
|
|
11
|
-
return null;
|
|
1
|
+
export function renderContextCard(model) {
|
|
2
|
+
const { info, task } = model;
|
|
12
3
|
const rows = [`┌ ${info.branch ?? "(detached)"}`];
|
|
13
|
-
rows.push(`│ task ${task
|
|
4
|
+
rows.push(`│ task ${task}`);
|
|
14
5
|
rows.push(`│ state ${formatState(info)}`);
|
|
15
6
|
if (info.lastCommitTimestamp !== null)
|
|
16
7
|
rows.push(`│ last ${formatLastCommit(info)}`);
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { UpstreamState } from "../../application/worktree/read-models.js";
|
|
2
|
+
export declare function formatUpstreamState(upstream: UpstreamState): string;
|
|
3
|
+
export declare function formatLastCommit(timestampSeconds: number | null): string;
|
|
4
|
+
export declare function formatRelativeAge(timestampSeconds: number, nowSeconds?: number): string;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export function formatUpstreamState(upstream) {
|
|
2
|
+
if (upstream.kind === "detached")
|
|
3
|
+
return "n/a";
|
|
4
|
+
if (upstream.kind === "no-upstream")
|
|
5
|
+
return "no-upstream";
|
|
6
|
+
if (upstream.kind === "stale")
|
|
7
|
+
return "gone";
|
|
8
|
+
if (upstream.kind === "unknown")
|
|
9
|
+
return "unknown";
|
|
10
|
+
return formatAheadBehind(upstream.ahead, upstream.behind);
|
|
11
|
+
}
|
|
12
|
+
function formatAheadBehind(ahead, behind) {
|
|
13
|
+
if (ahead === 0 && behind === 0)
|
|
14
|
+
return "up to date";
|
|
15
|
+
if (ahead === 0)
|
|
16
|
+
return `behind ${behind}`;
|
|
17
|
+
if (behind === 0)
|
|
18
|
+
return `ahead ${ahead}`;
|
|
19
|
+
return `ahead ${ahead}, behind ${behind}`;
|
|
20
|
+
}
|
|
21
|
+
export function formatLastCommit(timestampSeconds) {
|
|
22
|
+
return timestampSeconds === null
|
|
23
|
+
? "n/a"
|
|
24
|
+
: formatRelativeAge(timestampSeconds);
|
|
25
|
+
}
|
|
26
|
+
export function formatRelativeAge(timestampSeconds, nowSeconds = Math.floor(Date.now() / 1000)) {
|
|
27
|
+
const ageSeconds = Math.max(0, nowSeconds - timestampSeconds);
|
|
28
|
+
const units = [
|
|
29
|
+
{ label: "y", seconds: 365 * 24 * 60 * 60 },
|
|
30
|
+
{ label: "mo", seconds: 30 * 24 * 60 * 60 },
|
|
31
|
+
{ label: "d", seconds: 24 * 60 * 60 },
|
|
32
|
+
{ label: "h", seconds: 60 * 60 },
|
|
33
|
+
{ label: "m", seconds: 60 },
|
|
34
|
+
];
|
|
35
|
+
for (const unit of units) {
|
|
36
|
+
const value = Math.floor(ageSeconds / unit.seconds);
|
|
37
|
+
if (value > 0)
|
|
38
|
+
return `${value}${unit.label} ago`;
|
|
39
|
+
}
|
|
40
|
+
return "just now";
|
|
41
|
+
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { Readable, Writable } from "node:stream";
|
|
2
|
-
import { type
|
|
3
|
-
import type {
|
|
4
|
-
import type {
|
|
2
|
+
import { type WorktreeCatalogDependencies, type WorktreeMetadataMode } from "../../application/worktree/catalog.js";
|
|
3
|
+
import type { WorktreeSource } from "../../domain/worktree/source.js";
|
|
4
|
+
import type { WorktreeEntry } from "../../domain/worktree/types.js";
|
|
5
|
+
import type { PullRequestInfo, PullRequestPort } from "../../ports/pull-requests.js";
|
|
5
6
|
export type WorktreePromptSource = WorktreeSource;
|
|
6
7
|
export interface WorktreePromptEntry extends WorktreeEntry {
|
|
7
8
|
group: "recent" | "other";
|
|
@@ -11,14 +12,12 @@ export interface WorktreePromptEntry extends WorktreeEntry {
|
|
|
11
12
|
repoName: string;
|
|
12
13
|
task?: string | null;
|
|
13
14
|
}
|
|
14
|
-
export type QueryWorktreePullRequests =
|
|
15
|
-
export type QueryRepositoryPullRequests =
|
|
15
|
+
export type QueryWorktreePullRequests = PullRequestPort["listOpenPullRequests"];
|
|
16
|
+
export type QueryRepositoryPullRequests = PullRequestPort["listOpenPullRequestsForRepository"];
|
|
16
17
|
export interface BuildWorktreePromptEntriesDependencies {
|
|
17
18
|
metadata?: WorktreeMetadataMode;
|
|
18
|
-
|
|
19
|
-
queryRepositoryPullRequests?: QueryRepositoryPullRequests;
|
|
19
|
+
catalog?: WorktreeCatalogDependencies;
|
|
20
20
|
}
|
|
21
|
-
export type WorktreeMetadataMode = "full" | "fast";
|
|
22
21
|
export interface WorktreePickerIO {
|
|
23
22
|
input?: Readable & {
|
|
24
23
|
isTTY?: boolean;
|
|
@@ -40,9 +39,6 @@ export interface WorktreePromptScopeResult {
|
|
|
40
39
|
toggleLabel: string;
|
|
41
40
|
}
|
|
42
41
|
export declare function buildWorktreePromptEntries(sources: WorktreeSource[], dependencies?: BuildWorktreePromptEntriesDependencies): Promise<WorktreePromptEntry[]>;
|
|
43
|
-
export declare function resolveWorktreeQuery(sources: WorktreeSource[], query: string): WorktreeSource | null;
|
|
44
|
-
export declare function resolveWorktreeQueryMatches(sources: WorktreeSource[], query: string): WorktreeSource[];
|
|
45
|
-
export declare function resolveExactWorktreeQueryMatches(sources: WorktreeSource[], query: string): WorktreeSource[];
|
|
46
42
|
export declare function promptForSingleWorktree(message: string, worktrees: WorktreePromptEntry[], io?: WorktreePickerIO & {
|
|
47
43
|
scope?: WorktreePromptScope;
|
|
48
44
|
}): Promise<string | null>;
|