@bivy/bivy 0.17.3-staging.31 → 0.17.3-staging.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/worktree.js +40 -3
- package/package.json +1 -1
package/dist/worktree.js
CHANGED
|
@@ -4,6 +4,7 @@ import { execFile } from "node:child_process";
|
|
|
4
4
|
import { promisify } from "node:util";
|
|
5
5
|
import fs from "node:fs";
|
|
6
6
|
import path from "node:path";
|
|
7
|
+
import { gitNonInteractiveEnv } from "./git-auth.js";
|
|
7
8
|
import { cowProvisionDeps, provisionDepsByInstall } from "./worktree-provision.js";
|
|
8
9
|
const exec = promisify(execFile);
|
|
9
10
|
/** Slugify arbitrary text into a safe git branch / directory segment. */
|
|
@@ -86,7 +87,7 @@ export async function createWorktree(opts) {
|
|
|
86
87
|
const localExists = await refExists(repoRoot, `refs/heads/${branch}`);
|
|
87
88
|
const remoteExists = !localExists && await refExists(repoRoot, `refs/remotes/origin/${branch}`);
|
|
88
89
|
if (localExists) {
|
|
89
|
-
await
|
|
90
|
+
await worktreeAdd(repoRoot, [wtPath, branch]);
|
|
90
91
|
}
|
|
91
92
|
else {
|
|
92
93
|
if (remoteExists)
|
|
@@ -98,10 +99,10 @@ export async function createWorktree(opts) {
|
|
|
98
99
|
// Empty repo (e.g. a freshly created GitHub repo with no commits): HEAD is
|
|
99
100
|
// unborn, so it can't seed a worktree. Start the branch as an orphan —
|
|
100
101
|
// the session's first commit becomes the repo's root commit.
|
|
101
|
-
await
|
|
102
|
+
await worktreeAdd(repoRoot, ["--orphan", "-b", branch, wtPath]);
|
|
102
103
|
}
|
|
103
104
|
else {
|
|
104
|
-
await
|
|
105
|
+
await worktreeAdd(repoRoot, ["-b", branch, wtPath, base]);
|
|
105
106
|
}
|
|
106
107
|
}
|
|
107
108
|
// Opportunistically reuse a sibling worktree's installed deps (node_modules,
|
|
@@ -120,6 +121,42 @@ export async function createWorktree(opts) {
|
|
|
120
121
|
}
|
|
121
122
|
return { path: wtPath, branch, repoRoot };
|
|
122
123
|
}
|
|
124
|
+
/**
|
|
125
|
+
* `git worktree add`, non-interactively. Managed repos are partial clones
|
|
126
|
+
* (`--filter=blob:none`), so the checkout lazily fetches blobs from origin and
|
|
127
|
+
* needs credentials. The daemon has no TTY: without GIT_TERMINAL_PROMPT=0 a
|
|
128
|
+
* credential miss falls through to git's terminal prompt, which fails with the
|
|
129
|
+
* cryptic "could not read Username …: Device not configured" (macOS ENXIO).
|
|
130
|
+
*/
|
|
131
|
+
async function worktreeAdd(repoRoot, args) {
|
|
132
|
+
try {
|
|
133
|
+
await exec("git", ["-C", repoRoot, "worktree", "add", ...args], { env: gitNonInteractiveEnv() });
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
const stderr = String(error.stderr ?? "");
|
|
137
|
+
const friendly = describeWorktreeAddError(stderr);
|
|
138
|
+
if (friendly)
|
|
139
|
+
throw new Error(friendly, { cause: error });
|
|
140
|
+
throw error;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Turn a `git worktree add` failure caused by the lazy blob fetch into a message
|
|
145
|
+
* a person can act on, with git's output kept below as details. Returns
|
|
146
|
+
* undefined for any other failure (the raw error is already specific).
|
|
147
|
+
*/
|
|
148
|
+
export function describeWorktreeAddError(stderr) {
|
|
149
|
+
const detail = stderr.trim();
|
|
150
|
+
const auth = /could not read (Username|Password)|terminal prompts disabled|Authentication failed|Invalid username or (password|token)|Permission to .* denied/i.test(detail);
|
|
151
|
+
const promisor = /from promisor remote/i.test(detail);
|
|
152
|
+
if (auth) {
|
|
153
|
+
return `Couldn't create the session's worktree: git had to download repository files from GitHub, but no GitHub credentials were available on this machine. Reconnect GitHub for this machine in Bivy, then start the session again.\n\n${detail}`;
|
|
154
|
+
}
|
|
155
|
+
if (promisor) {
|
|
156
|
+
return `Couldn't create the session's worktree: git had to download repository files from the remote and the download failed. Check this machine's network connection, then start the session again.\n\n${detail}`;
|
|
157
|
+
}
|
|
158
|
+
return undefined;
|
|
159
|
+
}
|
|
123
160
|
/** True if `ref` (a fully-qualified ref) resolves in the repo. */
|
|
124
161
|
async function refExists(repoRoot, ref) {
|
|
125
162
|
try {
|
package/package.json
CHANGED