@solaqua/gji 0.12.2 → 0.12.4

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.
Files changed (55) hide show
  1. package/dist/bootstrap-output.d.ts +3 -2
  2. package/dist/bootstrap-output.js +1 -16
  3. package/dist/bootstrap-preview.d.ts +2 -3
  4. package/dist/bootstrap-preview.js +1 -11
  5. package/dist/cli.js +5 -1
  6. package/dist/config.d.ts +3 -13
  7. package/dist/config.js +12 -59
  8. package/dist/dependency-bootstrap.d.ts +11 -45
  9. package/dist/dependency-bootstrap.js +142 -608
  10. package/dist/gji-bundle.mjs +580 -2360
  11. package/dist/new.d.ts +4 -5
  12. package/dist/new.js +10 -45
  13. package/dist/pr.d.ts +4 -5
  14. package/dist/pr.js +9 -69
  15. package/dist/shell-completion.js +7 -5
  16. package/dist/uv-validation.d.ts +4 -0
  17. package/dist/uv-validation.js +232 -0
  18. package/dist/worktree-bootstrap.d.ts +5 -16
  19. package/dist/worktree-bootstrap.js +1 -24
  20. package/man/man1/gji-back.1 +1 -1
  21. package/man/man1/gji-clean.1 +1 -1
  22. package/man/man1/gji-completion.1 +1 -1
  23. package/man/man1/gji-config.1 +1 -1
  24. package/man/man1/gji-doctor.1 +1 -1
  25. package/man/man1/gji-done.1 +1 -1
  26. package/man/man1/gji-go.1 +1 -1
  27. package/man/man1/gji-history.1 +1 -1
  28. package/man/man1/gji-init.1 +1 -1
  29. package/man/man1/gji-ls.1 +1 -1
  30. package/man/man1/gji-new.1 +8 -5
  31. package/man/man1/gji-open.1 +1 -1
  32. package/man/man1/gji-pr.1 +6 -3
  33. package/man/man1/gji-remove.1 +1 -1
  34. package/man/man1/gji-root.1 +1 -1
  35. package/man/man1/gji-run-hook.1 +1 -1
  36. package/man/man1/gji-status.1 +1 -1
  37. package/man/man1/gji-sync-files.1 +1 -1
  38. package/man/man1/gji-sync.1 +1 -1
  39. package/man/man1/gji-task.1 +1 -1
  40. package/man/man1/gji-undo.1 +1 -1
  41. package/man/man1/gji-warp.1 +1 -1
  42. package/man/man1/gji.1 +2 -2
  43. package/package.json +1 -1
  44. package/dist/dependency-bootstrap-prompt.d.ts +0 -24
  45. package/dist/dependency-bootstrap-prompt.js +0 -103
  46. package/dist/dir-clone.d.ts +0 -32
  47. package/dist/dir-clone.js +0 -641
  48. package/dist/install-prompt.d.ts +0 -12
  49. package/dist/install-prompt.js +0 -127
  50. package/dist/package-manager.d.ts +0 -5
  51. package/dist/package-manager.js +0 -159
  52. package/dist/sync-directories.d.ts +0 -29
  53. package/dist/sync-directories.js +0 -77
  54. package/dist/sync-plan.d.ts +0 -16
  55. package/dist/sync-plan.js +0 -128
@@ -1,35 +1,24 @@
1
1
  import type { EffectiveGjiConfig } from "./config.js";
2
- import { type BootstrapCommandRunner, type BootstrapEvent, type DependencyBootstrapReport, type DependencyBootstrapReporter } from "./dependency-bootstrap.js";
3
- import type { DependencyBootstrapPolicyResolution } from "./dependency-bootstrap-prompt.js";
4
- import { type CloneDirectory } from "./dir-clone.js";
5
- import { type InstallPromptDependencies } from "./install-prompt.js";
6
- import { type ClonedDirectory, type SyncDirectoryReporter } from "./sync-directories.js";
7
- export type { ClonedDirectory as ClonedDir } from "./sync-directories.js";
2
+ import { type BootstrapCommandRunner, type BootstrapEvent, type DependencyBootstrapMode, type DependencyBootstrapReport, type DependencyBootstrapReporter } from "./dependency-bootstrap.js";
8
3
  export interface WorktreeBootstrapOptions {
9
4
  branch: string;
10
- cloneDirectory?: CloneDirectory;
11
5
  config: EffectiveGjiConfig;
12
6
  currentRoot?: string;
13
7
  dependencyDetectionRoot?: string;
14
- installDependencies?: InstallPromptDependencies;
8
+ dependencyMode: DependencyBootstrapMode;
15
9
  runCommand?: BootstrapCommandRunner;
16
10
  commandStdout?: (chunk: string) => void;
17
11
  commandStderr?: (chunk: string) => void;
18
- dependencyBootstrapPolicy?: DependencyBootstrapPolicyResolution;
19
12
  json?: boolean;
20
- nonInteractive: boolean;
21
13
  repoRoot: string;
22
- reporter: SyncDirectoryReporter & DependencyBootstrapReporter;
14
+ reporter: DependencyBootstrapReporter & {
15
+ write: (chunk: string) => void;
16
+ };
23
17
  worktreePath: string;
24
18
  }
25
19
  export interface WorktreeBootstrapResult {
26
- clonedDirs: readonly ClonedDirectory[];
27
20
  dependencyBootstrap: DependencyBootstrapReport;
28
21
  ready: boolean;
29
22
  syncFileFailures: readonly BootstrapEvent[];
30
- skippedDirs: readonly {
31
- dir: string;
32
- reason: string;
33
- }[];
34
23
  }
35
24
  export declare function bootstrapWorktree(options: WorktreeBootstrapOptions): Promise<WorktreeBootstrapResult>;
@@ -1,14 +1,10 @@
1
1
  import { basename } from "node:path";
2
2
  import { executeDependencyBootstrap, prepareDependencyBootstrap, } from "./dependency-bootstrap.js";
3
- import { cloneDir } from "./dir-clone.js";
4
3
  import { syncFiles } from "./file-sync.js";
5
4
  import { extractHooks, runHook } from "./hooks.js";
6
- import { maybeRunInstallPrompt, } from "./install-prompt.js";
7
5
  import { assignWorktreeSlot } from "./slots.js";
8
- import { executeSyncDirectoryPlan, } from "./sync-directories.js";
9
- import { prepareSyncDirectoryPlan } from "./sync-plan.js";
10
6
  export async function bootstrapWorktree(options) {
11
- const dependencyMode = options.config.dependencyBootstrap ?? "off";
7
+ const dependencyMode = options.dependencyMode;
12
8
  const dependencyPlan = await prepareDependencyBootstrap(dependencyMode, {
13
9
  currentRoot: options.currentRoot,
14
10
  detectionRoot: options.dependencyDetectionRoot,
@@ -16,15 +12,6 @@ export async function bootstrapWorktree(options) {
16
12
  cargoBuildCommand: options.config.dependencyBuildCommand,
17
13
  worktreePath: options.worktreePath,
18
14
  });
19
- const syncPlan = await prepareSyncDirectoryPlan(options.repoRoot, options.worktreePath, options.config.syncDirs ?? []);
20
- const outcomes = await executeSyncDirectoryPlan(syncPlan, {
21
- cloneDirectory: options.cloneDirectory ?? cloneDir,
22
- reporter: options.reporter,
23
- });
24
- const clonedDirs = outcomes.flatMap((outcome) => outcome.kind === "cloned" ? [outcome.directory] : []);
25
- const skippedDirs = outcomes.flatMap((outcome) => outcome.kind === "skipped"
26
- ? [{ dir: outcome.dir, reason: outcome.reason }]
27
- : []);
28
15
  const syncFileFailures = [];
29
16
  for (const pattern of options.config.syncFiles ?? []) {
30
17
  try {
@@ -51,26 +38,18 @@ export async function bootstrapWorktree(options) {
51
38
  const dependencyBootstrap = syncFileFailures.length > 0
52
39
  ? { mode: dependencyMode, ready: false, events: [] }
53
40
  : await executeDependencyBootstrap(dependencyPlan, {
54
- cloneDirectory: options.cloneDirectory,
55
41
  reporter: options.reporter,
56
42
  stderr: options.commandStderr ?? options.reporter.write,
57
43
  stdout: options.commandStdout,
58
- seededDirectories: clonedDirs.map(({ dir }) => dir),
59
44
  runCommand: options.runCommand,
60
45
  });
61
46
  if (!dependencyBootstrap.ready) {
62
47
  return {
63
- clonedDirs,
64
48
  dependencyBootstrap,
65
49
  ready: false,
66
50
  syncFileFailures,
67
- skippedDirs,
68
51
  };
69
52
  }
70
- if (dependencyMode === "off" &&
71
- ["default", "legacy"].includes(options.dependencyBootstrapPolicy?.source ?? "default")) {
72
- await maybeRunInstallPrompt(options.worktreePath, options.repoRoot, options.config, options.reporter.write, options.installDependencies, options.nonInteractive);
73
- }
74
53
  const hooks = extractHooks(options.config);
75
54
  const slot = await assignWorktreeSlot(options.repoRoot, options.worktreePath);
76
55
  await runHook(hooks["after-create"], options.worktreePath, {
@@ -82,11 +61,9 @@ export async function bootstrapWorktree(options) {
82
61
  ? () => undefined
83
62
  : (options.commandStdout ?? ((chunk) => process.stdout.write(chunk))));
84
63
  return {
85
- clonedDirs,
86
64
  dependencyBootstrap,
87
65
  ready: true,
88
66
  syncFileFailures: [],
89
- skippedDirs,
90
67
  };
91
68
  }
92
69
  function toErrorMessage(error) {
@@ -1,4 +1,4 @@
1
- .TH GJI\-BACK 1 "August 2026" "gji 0.12.2" "User Commands"
1
+ .TH GJI\-BACK 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji\-back \- navigate to the previously visited worktree, optionally N steps back
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-CLEAN 1 "August 2026" "gji 0.12.2" "User Commands"
1
+ .TH GJI\-CLEAN 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji\-clean \- interactively prune linked worktrees
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-COMPLETION 1 "August 2026" "gji 0.12.2" "User Commands"
1
+ .TH GJI\-COMPLETION 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji\-completion \- print shell completion definitions
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-CONFIG 1 "August 2026" "gji 0.12.2" "User Commands"
1
+ .TH GJI\-CONFIG 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji\-config \- manage global config defaults
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-DOCTOR 1 "August 2026" "gji 0.12.2" "User Commands"
1
+ .TH GJI\-DOCTOR 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji\-doctor \- check gji installation and configuration health
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-DONE 1 "August 2026" "gji 0.12.2" "User Commands"
1
+ .TH GJI\-DONE 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji\-done \- finish the current linked worktree and return safely
4
4
  .SH SYNOPSIS
package/man/man1/gji-go.1 CHANGED
@@ -1,4 +1,4 @@
1
- .TH GJI\-GO 1 "August 2026" "gji 0.12.2" "User Commands"
1
+ .TH GJI\-GO 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji\-go \- resolve and jump to a worktree path
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-HISTORY 1 "August 2026" "gji 0.12.2" "User Commands"
1
+ .TH GJI\-HISTORY 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji\-history \- show navigation history
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-INIT 1 "August 2026" "gji 0.12.2" "User Commands"
1
+ .TH GJI\-INIT 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji\-init \- set up shell integration interactively or print a shell wrapper
4
4
  .SH SYNOPSIS
package/man/man1/gji-ls.1 CHANGED
@@ -1,4 +1,4 @@
1
- .TH GJI\-LS 1 "August 2026" "gji 0.12.2" "User Commands"
1
+ .TH GJI\-LS 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji\-ls \- list active worktrees
4
4
  .SH SYNOPSIS
@@ -1,15 +1,15 @@
1
- .TH GJI\-NEW 1 "August 2026" "gji 0.12.2" "User Commands"
1
+ .TH GJI\-NEW 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
- gji\-new \- create a new branch or detached linked worktree and CoW\-bootstrap configured directories
3
+ gji\-new \- create a new branch or detached linked worktree
4
4
  .SH SYNOPSIS
5
5
  .B gji new [\fIoptions\fR] [options] [branch]
6
6
  .SH DESCRIPTION
7
- create a new branch or detached linked worktree and CoW\-bootstrap configured directories
7
+ create a new branch or detached linked worktree
8
8
  .SH BOOTSTRAP_POLICY
9
- dependencyBuildCommand overrides Cargo's default cargo check. Supported lockfiles trigger an interactive dependencyBootstrap choice when no explicit policy exists; the choice is saved according to installSaveTarget. JSON and headless modes never prompt and keep off. npm is always install\-only, and sync\-file failures stop dependency repair, install prompts, and after\-create hooks. JSON bootstrap events include structured reasons, and failed setup reports the created worktree path.
9
+ dependencyBuildCommand overrides Cargo's default cargo check. Supported lockfiles are installed automatically in new worktrees; set dependencyBootstrap to off or pass \-\-no\-install to skip setup. Sync\-file failures stop dependency installation and after\-create hooks. JSON bootstrap events include structured reasons, and failed setup reports the created worktree path.
10
10
 
11
11
  .SH BOOTSTRAP
12
- syncDirs performs generic copy\-on\-write directory seeding before syncFiles. It never falls back to ordinary copying and never suppresses installation or repair. Set dependencyBootstrap to off, cow\-then\-repair, or install\-only to enable deterministic project\-local package\-manager or build\-cache repair. The lifecycle is CoW seed, syncFiles, repair or install, then after\-create. CoW failures fall back to repair from an empty target; partial clones are removed and existing targets are never deleted. Bundler uses vendor/bundle only; global gem stores and caches are not cloned.
12
+ Dependency bootstrap never copies dependency trees or build caches. pnpm, Yarn, Bun, and npm install JavaScript dependencies; uv, Poetry, and Pipenv install Python environments; Bundler uses vendor/bundle; Composer uses vendor; Go runs go mod download; and Cargo runs cargo check. Failed setup is reported directly without an ordinary\-copy fallback or automatic retry.
13
13
 
14
14
  .SH OPTIONS
15
15
  .TP
@@ -43,6 +43,9 @@ editor CLI to use with \-\-open (code, cursor, zed, …)
43
43
  .B \-\-dry\-run
44
44
  show what would be created without executing any git commands or writing files
45
45
  .TP
46
+ .B \-\-no\-install
47
+ skip automatic dependency setup in the new worktree
48
+ .TP
46
49
  .B \-\-json
47
50
  emit JSON on success or error instead of human\-readable output
48
51
  .SH "SEE ALSO"
@@ -1,4 +1,4 @@
1
- .TH GJI\-OPEN 1 "August 2026" "gji 0.12.2" "User Commands"
1
+ .TH GJI\-OPEN 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji\-open \- open the worktree in an editor
4
4
  .SH SYNOPSIS
package/man/man1/gji-pr.1 CHANGED
@@ -1,4 +1,4 @@
1
- .TH GJI\-PR 1 "August 2026" "gji 0.12.2" "User Commands"
1
+ .TH GJI\-PR 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji\-pr \- fetch a pull request by number, #number, or URL into a linked worktree
4
4
  .SH SYNOPSIS
@@ -6,16 +6,19 @@ gji\-pr \- fetch a pull request by number, #number, or URL into a linked worktre
6
6
  .SH DESCRIPTION
7
7
  fetch a pull request by number, #number, or URL into a linked worktree
8
8
  .SH BOOTSTRAP_POLICY
9
- dependencyBuildCommand overrides Cargo's default cargo check. Supported lockfiles trigger an interactive dependencyBootstrap choice when no explicit policy exists; the choice is saved according to installSaveTarget. JSON and headless modes never prompt and keep off. npm is always install\-only, and sync\-file failures stop dependency repair, install prompts, and after\-create hooks. JSON bootstrap events include structured reasons, and failed setup reports the created worktree path.
9
+ dependencyBuildCommand overrides Cargo's default cargo check. Supported lockfiles are installed automatically in new worktrees; set dependencyBootstrap to off or pass \-\-no\-install to skip setup. Sync\-file failures stop dependency installation and after\-create hooks. JSON bootstrap events include structured reasons, and failed setup reports the created worktree path.
10
10
 
11
11
  .SH BOOTSTRAP
12
- syncDirs performs generic copy\-on\-write directory seeding before syncFiles. It never falls back to ordinary copying and never suppresses installation or repair. Set dependencyBootstrap to off, cow\-then\-repair, or install\-only to enable deterministic project\-local package\-manager or build\-cache repair. The lifecycle is CoW seed, syncFiles, repair or install, then after\-create. CoW failures fall back to repair from an empty target; partial clones are removed and existing targets are never deleted. Bundler uses vendor/bundle only; global gem stores and caches are not cloned.
12
+ Dependency bootstrap never copies dependency trees or build caches. pnpm, Yarn, Bun, and npm install JavaScript dependencies; uv, Poetry, and Pipenv install Python environments; Bundler uses vendor/bundle; Composer uses vendor; Go runs go mod download; and Cargo runs cargo check. Failed setup is reported directly without an ordinary\-copy fallback or automatic retry.
13
13
 
14
14
  .SH OPTIONS
15
15
  .TP
16
16
  .B \-\-dry\-run
17
17
  show what would be created without executing any git commands or writing files
18
18
  .TP
19
+ .B \-\-no\-install
20
+ skip automatic dependency setup in the PR worktree
21
+ .TP
19
22
  .B \-\-json
20
23
  emit JSON on success or error instead of human\-readable output
21
24
  .SH SUBCOMMANDS
@@ -1,4 +1,4 @@
1
- .TH GJI\-REMOVE 1 "August 2026" "gji 0.12.2" "User Commands"
1
+ .TH GJI\-REMOVE 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji\-remove \- deprecated: use gji done for one worktree or gji clean for bulk cleanup
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-ROOT 1 "August 2026" "gji 0.12.2" "User Commands"
1
+ .TH GJI\-ROOT 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji\-root \- print the main repository root path
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-RUN\-HOOK 1 "August 2026" "gji 0.12.2" "User Commands"
1
+ .TH GJI\-RUN\-HOOK 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji\-run\-hook \- run a named hook (after\-create, after\-enter, before\-remove) in the current worktree
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-STATUS 1 "August 2026" "gji 0.12.2" "User Commands"
1
+ .TH GJI\-STATUS 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji\-status \- summarize repository and worktree health
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-SYNC\-FILES 1 "August 2026" "gji 0.12.2" "User Commands"
1
+ .TH GJI\-SYNC\-FILES 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji\-sync\-files \- manage local files copied into new worktrees
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-SYNC 1 "August 2026" "gji 0.12.2" "User Commands"
1
+ .TH GJI\-SYNC 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji\-sync \- fetch and update one or all worktrees
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-TASK 1 "August 2026" "gji 0.12.2" "User Commands"
1
+ .TH GJI\-TASK 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji\-task \- show or update the current worktree task
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-UNDO 1 "August 2026" "gji 0.12.2" "User Commands"
1
+ .TH GJI\-UNDO 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji\-undo \- restore the most recent destructive worktree operation
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-WARP 1 "August 2026" "gji 0.12.2" "User Commands"
1
+ .TH GJI\-WARP 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji\-warp \- deprecated: use gji go (press Tab for all known repos)
4
4
  .SH SYNOPSIS
package/man/man1/gji.1 CHANGED
@@ -1,4 +1,4 @@
1
- .TH GJI 1 "August 2026" "gji 0.12.2" "User Commands"
1
+ .TH GJI 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji \- Context switching without the mess.
4
4
  .SH SYNOPSIS
@@ -12,7 +12,7 @@ eliminating the need for \fBgit stash\fR when switching contexts.
12
12
  .SH COMMANDS
13
13
  .TP
14
14
  .B new [options] [branch]
15
- create a new branch or detached linked worktree and CoW\-bootstrap configured directories
15
+ create a new branch or detached linked worktree
16
16
  .TP
17
17
  .B done [options] [branch]
18
18
  finish the current linked worktree and return safely
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solaqua/gji",
3
- "version": "0.12.2",
3
+ "version": "0.12.4",
4
4
  "description": "Git worktree CLI for fast context switching.",
5
5
  "license": "MIT",
6
6
  "author": "sjquant",
@@ -1,24 +0,0 @@
1
- import { type DependencyBootstrapMode, type EffectiveGjiConfig } from "./config.js";
2
- import { type DependencyBootstrapCandidate } from "./dependency-bootstrap.js";
3
- export interface DependencyBootstrapPromptDependencies {
4
- promptForDependencyBootstrap?: (candidate: DependencyBootstrapCandidate) => Promise<DependencyBootstrapMode | null>;
5
- writeConfigKey?: (root: string, key: string, value: unknown) => Promise<void>;
6
- writeGlobalRepoConfigKey?: (repoRoot: string, key: string, value: unknown) => Promise<void>;
7
- }
8
- export interface DependencyBootstrapPolicyResolution {
9
- mode: DependencyBootstrapMode;
10
- prompted: boolean;
11
- source: "explicit" | "prompted" | "default" | "legacy";
12
- }
13
- export declare function resolveDependencyBootstrapPolicy(context: {
14
- repoRoot: string;
15
- currentRoot?: string;
16
- detectionRoot?: string;
17
- worktreePath: string;
18
- }, config: EffectiveGjiConfig, dependencyBootstrapExplicit: boolean, options: {
19
- dryRun?: boolean;
20
- legacyInstallPromptConfigured?: boolean;
21
- nonInteractive?: boolean;
22
- stderr: (chunk: string) => void;
23
- dependencies?: DependencyBootstrapPromptDependencies;
24
- }): Promise<DependencyBootstrapPolicyResolution>;
@@ -1,103 +0,0 @@
1
- import { isCancel, select } from "@clack/prompts";
2
- import { updateGlobalRepoConfigKey, updateLocalConfigKey, } from "./config.js";
3
- import { detectDependencyBootstrapCandidate, } from "./dependency-bootstrap.js";
4
- import { isHeadless } from "./headless.js";
5
- export async function resolveDependencyBootstrapPolicy(context, config, dependencyBootstrapExplicit, options) {
6
- if (dependencyBootstrapExplicit) {
7
- return {
8
- mode: config.dependencyBootstrap ?? "off",
9
- prompted: false,
10
- source: "explicit",
11
- };
12
- }
13
- if (options.dryRun || options.nonInteractive || isHeadless()) {
14
- return { mode: "off", prompted: false, source: "default" };
15
- }
16
- if (options.legacyInstallPromptConfigured &&
17
- !options.dependencies?.promptForDependencyBootstrap) {
18
- return { mode: "off", prompted: false, source: "legacy" };
19
- }
20
- let candidate;
21
- try {
22
- candidate = await detectDependencyBootstrapCandidate(context);
23
- }
24
- catch (error) {
25
- options.stderr(`gji: dependency setup detection failed: ${toErrorMessage(error)}\n`);
26
- return { mode: "off", prompted: false, source: "default" };
27
- }
28
- if (!candidate)
29
- return { mode: "off", prompted: false, source: "default" };
30
- const prompt = options.dependencies?.promptForDependencyBootstrap ??
31
- defaultPromptForDependencyBootstrap;
32
- const choice = await prompt(candidate);
33
- if (choice === null)
34
- return { mode: "off", prompted: true, source: "prompted" };
35
- const mode = choice;
36
- await persistDependencyBootstrapPolicy(context.repoRoot, config, mode, options.dependencies, options.stderr);
37
- return { mode, prompted: true, source: "prompted" };
38
- }
39
- async function persistDependencyBootstrapPolicy(repoRoot, config, mode, dependencies, stderr) {
40
- const writeLocal = dependencies?.writeConfigKey ??
41
- (async (root, key, value) => {
42
- await updateLocalConfigKey(root, key, value);
43
- });
44
- const writeGlobal = dependencies?.writeGlobalRepoConfigKey ??
45
- (async (root, key, value) => {
46
- await updateGlobalRepoConfigKey(root, key, value);
47
- });
48
- try {
49
- if (config.installSaveTarget === "global") {
50
- await writeGlobal(repoRoot, "dependencyBootstrap", mode);
51
- }
52
- else {
53
- await writeLocal(repoRoot, "dependencyBootstrap", mode);
54
- }
55
- }
56
- catch (error) {
57
- stderr(`gji: failed to save dependencyBootstrap: ${toErrorMessage(error)}\n`);
58
- }
59
- }
60
- async function defaultPromptForDependencyBootstrap(candidate) {
61
- const reuseHint = formatReuseHint(candidate);
62
- const subject = candidate.kind === "build-cache"
63
- ? "dependencies and build state"
64
- : "dependencies";
65
- const choice = await select({
66
- message: `Set up ${candidate.adapter} ${subject} for new worktrees? (${candidate.lockfile})`,
67
- options: [
68
- {
69
- value: "cow-then-repair",
70
- label: "Reuse and repair (recommended)",
71
- hint: reuseHint,
72
- },
73
- {
74
- value: "install-only",
75
- label: "Install fresh each time",
76
- hint: candidate.repairCommand,
77
- },
78
- {
79
- value: "off",
80
- label: "Skip dependency setup",
81
- hint: "leave dependencies to project hooks or manual setup",
82
- },
83
- ],
84
- });
85
- if (isCancel(choice))
86
- return null;
87
- return choice;
88
- }
89
- function formatReuseHint(candidate) {
90
- if (candidate.adapter === "pnpm") {
91
- return "reuse local node_modules through CoW, then run pnpm install --frozen-lockfile";
92
- }
93
- if (candidate.adapter === "npm") {
94
- return "npm uses a clean install because node_modules is not seeded";
95
- }
96
- if (!candidate.seedable) {
97
- return `repair ${candidate.target} with ${candidate.repairCommand}`;
98
- }
99
- return `reuse ${candidate.target} through CoW, then run ${candidate.repairCommand}`;
100
- }
101
- function toErrorMessage(error) {
102
- return error instanceof Error ? error.message : String(error);
103
- }
@@ -1,32 +0,0 @@
1
- export interface CloneDirResult {
2
- bytes?: number;
3
- ms: number;
4
- }
5
- export interface CloneRequestOptions {
6
- destinationRoot?: string;
7
- measureBytes?: boolean;
8
- }
9
- export interface CloneDirOptions extends CloneRequestOptions {
10
- platform?: NodeJS.Platform;
11
- runLinuxCommand?: (command: string, args: string[]) => Promise<void>;
12
- copyDirectory?: (source: string, destination: string) => Promise<void>;
13
- copyFile?: (source: string, destination: string) => Promise<void>;
14
- }
15
- export type CloneDirectory = (source: string, destination: string, options?: CloneRequestOptions) => Promise<CloneDirResult>;
16
- export declare function cloneDir(source: string, destination: string, options?: CloneDirOptions): Promise<CloneDirResult>;
17
- export declare class CloneDestinationExistsError extends Error {
18
- readonly code = "GJI_CLONE_DESTINATION_EXISTS";
19
- constructor(destination: string);
20
- }
21
- export declare class CloneUnsupportedError extends Error {
22
- readonly code = "GJI_CLONE_UNSUPPORTED";
23
- constructor(reason: string);
24
- }
25
- export declare class CloneInProgressError extends Error {
26
- readonly code = "GJI_CLONE_IN_PROGRESS";
27
- constructor(destination: string);
28
- }
29
- export declare function isCloneDestinationExistsError(error: unknown): error is CloneDestinationExistsError;
30
- export declare function isCloneUnsupportedError(error: unknown): boolean;
31
- export declare function isCloneInProgressError(error: unknown): error is CloneInProgressError;
32
- export declare function directorySize(path: string): Promise<number>;