@ricsam/r5d-worker 0.0.76 → 0.0.78

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.
@@ -2,6 +2,7 @@ import { createHash } from "node:crypto";
2
2
  import fs from "node:fs";
3
3
  import os from "node:os";
4
4
  import path from "node:path";
5
+ import { gitCredentialUsernameConfigKey, gitTransportSecurityArgs, workerGitProcessEnvironment } from "./git-process-environment.mjs";
5
6
  import { validateManagedBranchName } from "./managed-paths.mjs";
6
7
  import { mirrorWorkingTree } from "./working-tree-mirror.mjs";
7
8
  const PROJECT_WORKTREE_SNAPSHOT_PREFIX = "r5d-project-worktrees-";
@@ -33,25 +34,15 @@ const NON_RECURSIVE_GIT_CONFIG = [
33
34
  "-c",
34
35
  "push.recurseSubmodules=false"
35
36
  ];
36
- function normalizedHttpOrigin(value) {
37
- try {
38
- const url = new URL(value);
39
- return `${url.protocol}//${url.host}`;
40
- } catch {
41
- return value.replace(/\/+$/, "");
42
- }
43
- }
44
- function authArgs(auth) {
45
- if (!auth) return [];
46
- const key = `http.${normalizedHttpOrigin(auth.extraHeaderUrl)}/.extraHeader`;
47
- return ["-c", "http.extraHeader=", "-c", `${key}=`, "-c", `${key}=${auth.header}`];
37
+ function gitCommandArgs(args) {
38
+ return ["git", ...NON_RECURSIVE_GIT_CONFIG, ...args];
48
39
  }
49
- function gitResult(cwd, args, auth) {
50
- const result = Bun.spawnSync(["git", ...NON_RECURSIVE_GIT_CONFIG, ...authArgs(auth), ...args], {
40
+ function gitResult(cwd, args) {
41
+ const result = Bun.spawnSync(gitCommandArgs(args), {
51
42
  cwd,
52
43
  stdout: "pipe",
53
44
  stderr: "pipe",
54
- env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }
45
+ env: workerGitProcessEnvironment()
55
46
  });
56
47
  return {
57
48
  exitCode: result.exitCode,
@@ -59,13 +50,13 @@ function gitResult(cwd, args, auth) {
59
50
  stderr: result.stderr.toString().trim()
60
51
  };
61
52
  }
62
- function git(cwd, args, action, auth) {
63
- const result = gitResult(cwd, args, auth);
53
+ function git(cwd, args, action) {
54
+ const result = gitResult(cwd, args);
64
55
  if (result.exitCode !== 0) throw new Error(`${action}: ${result.stderr || result.stdout || `git exited ${result.exitCode}`}`);
65
56
  return result.stdout;
66
57
  }
67
- function tryGit(cwd, args, auth) {
68
- return gitResult(cwd, args, auth).exitCode === 0;
58
+ function tryGit(cwd, args) {
59
+ return gitResult(cwd, args).exitCode === 0;
69
60
  }
70
61
  function branchPath(projectRoot, branchName) {
71
62
  validateManagedBranchName(branchName);
@@ -192,7 +183,16 @@ function configureRepository(input) {
192
183
  } else {
193
184
  git(input.primaryPath, ["remote", "add", "origin", input.originUrl], "configure project origin");
194
185
  }
186
+ tryGit(input.primaryPath, ["config", "--local", "--unset-all", "remote.origin.pushurl"]);
195
187
  git(input.primaryPath, ["config", "--local", "--replace-all", "credential.helper", ""], "reset project credential helpers");
188
+ git(input.primaryPath, ["config", "--local", "credential.useHttpPath", "false"], "configure project credential path matching");
189
+ if (input.originCredentialUsername) {
190
+ git(
191
+ input.primaryPath,
192
+ ["config", "--local", "--replace-all", gitCredentialUsernameConfigKey(input.originUrl), input.originCredentialUsername],
193
+ "configure project credential username"
194
+ );
195
+ }
196
196
  if (input.credentialHelper) {
197
197
  git(
198
198
  input.primaryPath,
@@ -209,19 +209,25 @@ function configureRepository(input) {
209
209
  }
210
210
  }
211
211
  function fetchProjectHeads(input) {
212
- const originFetch = gitResult(
213
- input.primaryPath,
214
- ["fetch", "--no-recurse-submodules", "--prune", "origin", "+refs/heads/*:refs/remotes/origin/*"],
215
- input.originAuth
216
- );
212
+ const originFetch = gitResult(input.primaryPath, [
213
+ ...gitTransportSecurityArgs(input.originUrl, input.credentialHelper, input.originCredentialUsername),
214
+ "fetch",
215
+ "--no-recurse-submodules",
216
+ "--prune",
217
+ "origin",
218
+ "+refs/heads/*:refs/remotes/origin/*"
219
+ ]);
217
220
  if (originFetch.exitCode !== 0) {
218
221
  throw new Error(`Fetch project origin: ${originFetch.stderr || originFetch.stdout || `git exited ${originFetch.exitCode}`}`);
219
222
  }
220
- const mirrorFetch = gitResult(
221
- input.primaryPath,
222
- ["fetch", "--no-recurse-submodules", "--prune", input.mirrorUrl, "+refs/heads/*:refs/r5d/mirror/*"],
223
- input.mirrorAuth
224
- );
223
+ const mirrorFetch = gitResult(input.primaryPath, [
224
+ ...gitTransportSecurityArgs(input.mirrorUrl, input.credentialHelper, input.mirrorCredentialUsername),
225
+ "fetch",
226
+ "--no-recurse-submodules",
227
+ "--prune",
228
+ input.mirrorUrl,
229
+ "+refs/heads/*:refs/r5d/mirror/*"
230
+ ]);
225
231
  if (mirrorFetch.exitCode !== 0 && !/(couldn't find remote ref|does not have any commits|remote repository is empty|no such ref)/i.test(
226
232
  `${mirrorFetch.stderr}
227
233
  ${mirrorFetch.stdout}`
@@ -231,11 +237,19 @@ ${mirrorFetch.stdout}`
231
237
  }
232
238
  function ensureCommitAvailable(input) {
233
239
  if (tryGit(input.primaryPath, ["cat-file", "-e", `${input.commitHash}^{commit}`])) return;
234
- for (const [url, auth] of [
235
- [input.mirrorUrl, input.mirrorAuth],
236
- [input.originUrl, input.originAuth]
240
+ for (const [url, username] of [
241
+ [input.mirrorUrl, input.mirrorCredentialUsername],
242
+ [input.originUrl, input.originCredentialUsername]
237
243
  ]) {
238
- if (tryGit(input.primaryPath, ["fetch", "--no-recurse-submodules", "--no-tags", url, input.commitHash], auth)) return;
244
+ if (tryGit(input.primaryPath, [
245
+ ...gitTransportSecurityArgs(url, input.credentialHelper, username),
246
+ "fetch",
247
+ "--no-recurse-submodules",
248
+ "--no-tags",
249
+ url,
250
+ input.commitHash
251
+ ]))
252
+ return;
239
253
  }
240
254
  throw new Error(`Project base commit ${input.commitHash} is unavailable from origin and the canonical mirror`);
241
255
  }
@@ -439,11 +453,13 @@ function removeProjectWorktrees(input) {
439
453
  }
440
454
  function deleteProjectMirrorBranch(input) {
441
455
  validateManagedBranchName(input.branchName);
442
- const deleted = gitResult(
443
- input.gitDirectory,
444
- ["push", "--no-recurse-submodules", input.mirrorUrl, `:refs/heads/${input.branchName}`],
445
- input.mirrorAuth
446
- );
456
+ const deleted = gitResult(input.gitDirectory, [
457
+ ...gitTransportSecurityArgs(input.mirrorUrl, input.credentialHelper, input.credentialUsername),
458
+ "push",
459
+ "--no-recurse-submodules",
460
+ input.mirrorUrl,
461
+ `:refs/heads/${input.branchName}`
462
+ ]);
447
463
  if (deleted.exitCode !== 0 && !/(remote ref does not exist|unable to delete|no such ref)/i.test(`${deleted.stderr}
448
464
  ${deleted.stdout}`)) {
449
465
  throw new Error(
@@ -463,9 +479,14 @@ function pushProjectMirrorHeads(input) {
463
479
  }
464
480
  git(
465
481
  checkoutPath,
466
- ["push", "--no-recurse-submodules", input.mirrorUrl, `+HEAD:refs/heads/${branchName}`],
467
- `push hidden project mirror for ${branchName}`,
468
- input.mirrorAuth
482
+ [
483
+ ...gitTransportSecurityArgs(input.mirrorUrl, input.credentialHelper, input.credentialUsername),
484
+ "push",
485
+ "--no-recurse-submodules",
486
+ input.mirrorUrl,
487
+ `+HEAD:refs/heads/${branchName}`
488
+ ],
489
+ `push hidden project mirror for ${branchName}`
469
490
  );
470
491
  results.push({ branchName, head, pushed: true });
471
492
  }
@@ -473,11 +494,14 @@ function pushProjectMirrorHeads(input) {
473
494
  }
474
495
  function fastForwardProjectHeadsFromMirror(input) {
475
496
  const primaryPath = branchPath(input.projectRoot, input.primaryBranchName);
476
- const fetch = gitResult(
477
- primaryPath,
478
- ["fetch", "--no-recurse-submodules", "--prune", input.mirrorUrl, "+refs/heads/*:refs/r5d/mirror/*"],
479
- input.mirrorAuth
480
- );
497
+ const fetch = gitResult(primaryPath, [
498
+ ...gitTransportSecurityArgs(input.mirrorUrl, input.credentialHelper, input.credentialUsername),
499
+ "fetch",
500
+ "--no-recurse-submodules",
501
+ "--prune",
502
+ input.mirrorUrl,
503
+ "+refs/heads/*:refs/r5d/mirror/*"
504
+ ]);
481
505
  if (fetch.exitCode !== 0)
482
506
  throw new Error(`Refresh project head mirror: ${fetch.stderr || fetch.stdout || `git exited ${fetch.exitCode}`}`);
483
507
  return [...input.branchNames].sort().map((branchName) => {
@@ -494,7 +518,8 @@ function fastForwardProjectHeadsFromMirror(input) {
494
518
  });
495
519
  }
496
520
  const projectWorktreesTestHarness = {
497
- commandArgs: (args, auth) => ["git", ...NON_RECURSIVE_GIT_CONFIG, ...authArgs(auth), ...args]
521
+ commandArgs: gitCommandArgs,
522
+ configureRepository
498
523
  };
499
524
  export {
500
525
  PROJECT_WORKTREE_SNAPSHOT_PREFIX,
@@ -1,5 +1,6 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
+ import { workerGitProcessEnvironment } from "./git-process-environment.mjs";
3
4
  function isGitMetadataPath(relativePath) {
4
5
  return relativePath.split("/").includes(".git");
5
6
  }
@@ -36,7 +37,7 @@ function gitEligibleRoots(root) {
36
37
  cwd: root,
37
38
  stdout: "pipe",
38
39
  stderr: "pipe",
39
- env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }
40
+ env: workerGitProcessEnvironment()
40
41
  }
41
42
  );
42
43
  if (result.exitCode !== 0) {
@@ -1,5 +1,6 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
+ import { gitCredentialUsernameConfigKey, gitTransportSecurityArgs, workerGitProcessEnvironment } from "./git-process-environment.mjs";
3
4
  import { mirrorWorkingTree } from "./working-tree-mirror.mjs";
4
5
  const WORKSPACE_GIT_BRANCH = "main";
5
6
  const MAX_WORKSPACE_GIT_DIFF_BYTES = 5 * 1024 * 1024;
@@ -13,25 +14,18 @@ const NON_RECURSIVE_GIT_CONFIG = [
13
14
  "-c",
14
15
  "push.recurseSubmodules=false"
15
16
  ];
16
- function normalizedHttpOrigin(value) {
17
- try {
18
- const url = new URL(value);
19
- return `${url.protocol}//${url.host}`;
20
- } catch {
21
- return value.replace(/\/+$/, "");
22
- }
17
+ function gitCommandArgs(args) {
18
+ return ["git", ...NON_RECURSIVE_GIT_CONFIG, ...args];
23
19
  }
24
- function authArgs(auth) {
25
- if (!auth) return [];
26
- const key = `http.${normalizedHttpOrigin(auth.extraHeaderUrl)}/.extraHeader`;
27
- return ["-c", "http.extraHeader=", "-c", `${key}=`, "-c", `${key}=${auth.header}`];
20
+ function workspaceCloneCommandArgs(args, remoteUrl, credentialHelper, credentialUsername) {
21
+ return gitCommandArgs([...gitTransportSecurityArgs(remoteUrl, credentialHelper, credentialUsername), ...args]);
28
22
  }
29
- function gitResult(cwd, args, auth) {
30
- const result = Bun.spawnSync(["git", ...NON_RECURSIVE_GIT_CONFIG, ...authArgs(auth), ...args], {
23
+ function gitResult(cwd, args) {
24
+ const result = Bun.spawnSync(gitCommandArgs(args), {
31
25
  cwd,
32
26
  stdout: "pipe",
33
27
  stderr: "pipe",
34
- env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }
28
+ env: workerGitProcessEnvironment()
35
29
  });
36
30
  return {
37
31
  exitCode: result.exitCode,
@@ -39,13 +33,13 @@ function gitResult(cwd, args, auth) {
39
33
  stderr: result.stderr.toString().trim()
40
34
  };
41
35
  }
42
- function git(cwd, args, action, auth) {
43
- const result = gitResult(cwd, args, auth);
36
+ function git(cwd, args, action) {
37
+ const result = gitResult(cwd, args);
44
38
  if (result.exitCode !== 0) throw new Error(`${action}: ${result.stderr || result.stdout || `git exited ${result.exitCode}`}`);
45
39
  return result.stdout;
46
40
  }
47
- function tryGit(cwd, args, auth) {
48
- return gitResult(cwd, args, auth).exitCode === 0;
41
+ function tryGit(cwd, args) {
42
+ return gitResult(cwd, args).exitCode === 0;
49
43
  }
50
44
  function revParse(workspacePath, revision) {
51
45
  const result = gitResult(workspacePath, ["rev-parse", "--verify", revision]);
@@ -91,9 +85,22 @@ function configureWorkspaceRepository(input) {
91
85
  } else {
92
86
  git(input.workspacePath, ["remote", "add", "origin", input.remoteUrl], "configure workspace origin");
93
87
  }
88
+ tryGit(input.workspacePath, ["config", "--local", "--unset-all", "remote.origin.pushurl"]);
94
89
  git(input.workspacePath, ["config", "--local", "--replace-all", "credential.helper", ""], "reset workspace credential helpers");
90
+ git(input.workspacePath, ["config", "--local", "credential.useHttpPath", "false"], "configure workspace credential path matching");
91
+ if (input.credentialUsername) {
92
+ git(
93
+ input.workspacePath,
94
+ ["config", "--local", "--replace-all", gitCredentialUsernameConfigKey(input.remoteUrl), input.credentialUsername],
95
+ "configure workspace credential username"
96
+ );
97
+ }
95
98
  if (input.credentialHelper) {
96
- git(input.workspacePath, ["config", "--local", "--add", "credential.helper", input.credentialHelper], "configure workspace credential helper");
99
+ git(
100
+ input.workspacePath,
101
+ ["config", "--local", "--add", "credential.helper", input.credentialHelper],
102
+ "configure workspace credential helper"
103
+ );
97
104
  }
98
105
  const name = input.gitIdentity.name.trim();
99
106
  const email = input.gitIdentity.email.trim();
@@ -101,19 +108,16 @@ function configureWorkspaceRepository(input) {
101
108
  git(input.workspacePath, ["config", "--local", "user.name", name], "configure workspace Git user name");
102
109
  git(input.workspacePath, ["config", "--local", "user.email", email], "configure workspace Git user email");
103
110
  }
104
- function fetchWorkspaceHead(workspacePath, remoteAuth) {
105
- const result = gitResult(
106
- workspacePath,
107
- [
108
- "fetch",
109
- "--no-recurse-submodules",
110
- "--prune",
111
- "--update-shallow",
112
- "origin",
113
- `+refs/heads/${WORKSPACE_GIT_BRANCH}:refs/remotes/origin/${WORKSPACE_GIT_BRANCH}`
114
- ],
115
- remoteAuth
116
- );
111
+ function fetchWorkspaceHead(workspacePath, remoteUrl, credentialHelper, credentialUsername) {
112
+ const result = gitResult(workspacePath, [
113
+ ...gitTransportSecurityArgs(remoteUrl, credentialHelper, credentialUsername),
114
+ "fetch",
115
+ "--no-recurse-submodules",
116
+ "--prune",
117
+ "--update-shallow",
118
+ "origin",
119
+ `+refs/heads/${WORKSPACE_GIT_BRANCH}:refs/remotes/origin/${WORKSPACE_GIT_BRANCH}`
120
+ ]);
117
121
  if (result.exitCode !== 0) {
118
122
  const detail = `${result.stderr}
119
123
  ${result.stdout}`;
@@ -130,11 +134,17 @@ function ensureWorkspaceGitClone(input) {
130
134
  if (!fs.existsSync(gitPath)) {
131
135
  fs.rmSync(workspacePath, { recursive: true, force: true });
132
136
  fs.mkdirSync(path.dirname(workspacePath), { recursive: true });
133
- const clone = gitResult(
134
- void 0,
137
+ const cloneCommand = workspaceCloneCommandArgs(
135
138
  ["clone", "--no-recurse-submodules", "--branch", WORKSPACE_GIT_BRANCH, input.remoteUrl, workspacePath],
136
- input.remoteAuth
139
+ input.remoteUrl,
140
+ input.credentialHelper,
141
+ input.credentialUsername
137
142
  );
143
+ const clone = Bun.spawnSync(cloneCommand, {
144
+ stdout: "pipe",
145
+ stderr: "pipe",
146
+ env: workerGitProcessEnvironment()
147
+ });
138
148
  if (clone.exitCode !== 0) {
139
149
  fs.rmSync(workspacePath, { recursive: true, force: true });
140
150
  fs.mkdirSync(workspacePath, { recursive: true });
@@ -147,7 +157,7 @@ function ensureWorkspaceGitClone(input) {
147
157
  if (!revParse(workspacePath, WORKSPACE_GIT_INTEGRATED_REF) && previousRemoteHead && localHeadBeforeFetch && tryGit(workspacePath, ["merge-base", "--is-ancestor", previousRemoteHead, localHeadBeforeFetch])) {
148
158
  updateIntegratedWorkspaceHead(workspacePath, previousRemoteHead);
149
159
  }
150
- const remoteHead = fetchWorkspaceHead(workspacePath, input.remoteAuth);
160
+ const remoteHead = fetchWorkspaceHead(workspacePath, input.remoteUrl, input.credentialHelper, input.credentialUsername);
151
161
  let localHead = revParse(workspacePath, "HEAD");
152
162
  if (!localHead && remoteHead) {
153
163
  git(
@@ -233,7 +243,7 @@ function resetWorkspaceGit(input) {
233
243
  const initial = ensureWorkspaceGitClone({ ...input, workspacePath });
234
244
  const status = gitResult(workspacePath, ["status", "--porcelain=v1", "-z"]);
235
245
  const discardedPaths = status.exitCode === 0 ? status.stdout.split("\0").filter(Boolean).map((entry) => entry.slice(3)).sort() : [];
236
- const remoteHead = fetchWorkspaceHead(workspacePath, input.remoteAuth);
246
+ const remoteHead = fetchWorkspaceHead(workspacePath, input.remoteUrl, input.credentialHelper, input.credentialUsername);
237
247
  if (remoteHead) {
238
248
  git(workspacePath, ["checkout", "--no-recurse-submodules", "-B", WORKSPACE_GIT_BRANCH, remoteHead], "reset workspace main");
239
249
  git(workspacePath, ["clean", "-fd", "--", "."], "remove untracked workspace changes");
@@ -259,9 +269,10 @@ function emptyTreeHash(workspacePath) {
259
269
  stdin: Buffer.alloc(0),
260
270
  stdout: "pipe",
261
271
  stderr: "pipe",
262
- env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }
272
+ env: workerGitProcessEnvironment()
263
273
  });
264
- if (result.exitCode !== 0) throw new Error(`Create empty workspace tree: ${result.stderr.toString().trim() || `git exited ${result.exitCode}`}`);
274
+ if (result.exitCode !== 0)
275
+ throw new Error(`Create empty workspace tree: ${result.stderr.toString().trim() || `git exited ${result.exitCode}`}`);
265
276
  return result.stdout.toString().trim();
266
277
  }
267
278
  function changedPaths(workspacePath, baseRevision, headRevision) {
@@ -270,15 +281,12 @@ function changedPaths(workspacePath, baseRevision, headRevision) {
270
281
  }
271
282
  async function diffSizeBytes(workspacePath, baseRevision, headRevision, limit) {
272
283
  const base = baseRevision ?? emptyTreeHash(workspacePath);
273
- const subprocess = Bun.spawn(
274
- ["git", ...NON_RECURSIVE_GIT_CONFIG, "diff", "--binary", "--no-ext-diff", base, headRevision],
275
- {
276
- cwd: workspacePath,
277
- stdout: "pipe",
278
- stderr: "pipe",
279
- env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }
280
- }
281
- );
284
+ const subprocess = Bun.spawn(["git", ...NON_RECURSIVE_GIT_CONFIG, "diff", "--binary", "--no-ext-diff", base, headRevision], {
285
+ cwd: workspacePath,
286
+ stdout: "pipe",
287
+ stderr: "pipe",
288
+ env: workerGitProcessEnvironment()
289
+ });
282
290
  const stderrPromise = new Response(subprocess.stderr).text();
283
291
  const reader = subprocess.stdout.getReader();
284
292
  let total = 0;
@@ -399,7 +407,7 @@ async function synchronizeWorkspaceGit(input) {
399
407
  "commit workspace working trees"
400
408
  );
401
409
  }
402
- let remoteHead = fetchWorkspaceHead(workspacePath, input.remoteAuth);
410
+ let remoteHead = fetchWorkspaceHead(workspacePath, input.remoteUrl, input.credentialHelper, input.credentialUsername);
403
411
  let rebaseCount = 0;
404
412
  let updated = false;
405
413
  for (let pushAttempt = 0; pushAttempt < maxPushAttempts; pushAttempt += 1) {
@@ -475,10 +483,14 @@ async function synchronizeWorkspaceGit(input) {
475
483
  skippedMountIds: selected.skipped.map(({ id }) => id).sort()
476
484
  };
477
485
  }
478
- const pushArgs = ["push", "--no-recurse-submodules"];
486
+ const pushArgs = [
487
+ ...gitTransportSecurityArgs(input.remoteUrl, input.credentialHelper, input.credentialUsername),
488
+ "push",
489
+ "--no-recurse-submodules"
490
+ ];
479
491
  if (input.allowLargeDiff) pushArgs.push(`--push-option=${WORKSPACE_GIT_CONFIRMED_LARGE_DIFF_PUSH_OPTION}`);
480
492
  pushArgs.push("origin", `HEAD:refs/heads/${WORKSPACE_GIT_BRANCH}`);
481
- const push = gitResult(workspacePath, pushArgs, input.remoteAuth);
493
+ const push = gitResult(workspacePath, pushArgs);
482
494
  if (push.exitCode === 0) {
483
495
  updateIntegratedWorkspaceHead(workspacePath, localHead);
484
496
  await input.afterWorkspacePublished?.({
@@ -503,12 +515,14 @@ async function synchronizeWorkspaceGit(input) {
503
515
  ${push.stdout}`)) {
504
516
  throw new Error(`Push workspace main: ${push.stderr || push.stdout || `git exited ${push.exitCode}`}`);
505
517
  }
506
- remoteHead = fetchWorkspaceHead(workspacePath, input.remoteAuth);
518
+ remoteHead = fetchWorkspaceHead(workspacePath, input.remoteUrl, input.credentialHelper, input.credentialUsername);
507
519
  }
508
520
  throw new Error(`Workspace push did not converge after ${maxPushAttempts} attempts`);
509
521
  }
510
522
  const workspaceGitSyncTestHarness = {
511
- commandArgs: (args, auth) => ["git", ...NON_RECURSIVE_GIT_CONFIG, ...authArgs(auth), ...args],
523
+ commandArgs: gitCommandArgs,
524
+ workspaceCloneCommandArgs,
525
+ configureWorkspaceRepository,
512
526
  mirrorMountsToWorkspace,
513
527
  hydrateMountsFromWorkspace: hydrateWorkspaceGitMounts
514
528
  };
@@ -0,0 +1,9 @@
1
+ /** Build the complete environment for a worker-owned Git child process. */
2
+ export declare function workerGitProcessEnvironment(source?: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
3
+ /** Clear inherited and repository-local HTTP authorization headers for one transport URL. */
4
+ export declare function gitHttpAuthorizationClearArgs(remoteUrl: string): string[];
5
+ /** Select only the app-owned credential store, regardless of repository-local helpers. */
6
+ export declare function gitCredentialHelperConfigArgs(credentialHelper?: string | null): string[];
7
+ export declare function gitCredentialUsernameConfigKey(remoteUrl: string): string;
8
+ /** Non-secret command configuration required for an authenticated HTTP transport. */
9
+ export declare function gitTransportSecurityArgs(remoteUrl: string, credentialHelper?: string | null, credentialUsername?: string | null): string[];
@@ -130,6 +130,30 @@ type ResolvedWorkerFilePath = {
130
130
  virtualRootPath: string;
131
131
  };
132
132
  export declare function resolveWorkerFilePath(branchPath: string, inputPath: string, builtInPaths?: WorkerBuiltInToolPaths): ResolvedWorkerFilePath;
133
+ declare function readOnlyCredentialStoreHelper(storePath: string): string;
134
+ declare function legacySharedCredentialStorePath(): string;
135
+ declare function credentialStorePathForProject(projectId: string): string;
136
+ declare function credentialStorePathForWorkspace(remoteUrl: string): string;
137
+ declare function removeLegacySharedCredentialStore(storePath?: string): void;
138
+ declare function resetCredentialStoreDirectory(directoryPath?: string): void;
139
+ declare function pruneCredentialStoreFiles(requiredStorePaths: ReadonlySet<string>, directoryPath?: string): string[];
140
+ declare function replaceCredentialStoreFile(storePath: string, content: string): void;
141
+ declare function credentialHelperForRemotes(remotes: readonly {
142
+ remoteUrl: string;
143
+ authHeader: string | null | undefined;
144
+ }[], storePath: string): string | null;
145
+ export declare const workerGitSecurityTestHarness: {
146
+ commandArgs: (args: string[]) => string[];
147
+ credentialHelperForRemotes: typeof credentialHelperForRemotes;
148
+ credentialStorePathForProject: typeof credentialStorePathForProject;
149
+ credentialStorePathForWorkspace: typeof credentialStorePathForWorkspace;
150
+ legacySharedCredentialStorePath: typeof legacySharedCredentialStorePath;
151
+ removeLegacySharedCredentialStore: typeof removeLegacySharedCredentialStore;
152
+ pruneCredentialStoreFiles: typeof pruneCredentialStoreFiles;
153
+ readOnlyCredentialStoreHelper: typeof readOnlyCredentialStoreHelper;
154
+ resetCredentialStoreDirectory: typeof resetCredentialStoreDirectory;
155
+ replaceCredentialStoreFile: typeof replaceCredentialStoreFile;
156
+ };
133
157
  export declare function githubCliEnv(token: string | null | undefined): Record<string, string>;
134
158
  type ResolvedWorkerSessionTarget = {
135
159
  target: WorkerSessionTarget;
@@ -1,8 +1,4 @@
1
1
  export declare const PROJECT_WORKTREE_SNAPSHOT_PREFIX = "r5d-project-worktrees-";
2
- export type GitHttpAuth = {
3
- extraHeaderUrl: string;
4
- header: string;
5
- };
6
2
  export type ProjectWorktreeBranch = {
7
3
  branchName: string;
8
4
  baseCommitHash: string;
@@ -28,6 +24,7 @@ export declare function projectWorktreeConfigurationFingerprint(input: {
28
24
  email: string;
29
25
  } | null;
30
26
  }): string;
27
+ declare function gitCommandArgs(args: string[]): string[];
31
28
  export declare function hasLinkedProjectWorktreeLayout(input: {
32
29
  projectRoot: string;
33
30
  primaryBranchName: string;
@@ -43,15 +40,25 @@ export declare function cleanupStaleProjectWorktreeSnapshots(input?: {
43
40
  error: string;
44
41
  }>;
45
42
  };
43
+ declare function configureRepository(input: {
44
+ primaryPath: string;
45
+ originUrl: string;
46
+ credentialHelper?: string | null;
47
+ originCredentialUsername?: string | null;
48
+ gitIdentity?: {
49
+ name: string;
50
+ email: string;
51
+ } | null;
52
+ }): void;
46
53
  export declare function ensureProjectWorktrees(input: {
47
54
  projectRoot: string;
48
55
  primaryBranchName: string;
49
56
  branches: readonly ProjectWorktreeBranch[];
50
57
  originUrl: string;
51
- originAuth?: GitHttpAuth;
52
58
  mirrorUrl: string;
53
- mirrorAuth?: GitHttpAuth;
54
59
  credentialHelper?: string | null;
60
+ originCredentialUsername?: string | null;
61
+ mirrorCredentialUsername?: string | null;
55
62
  gitIdentity?: {
56
63
  name: string;
57
64
  email: string;
@@ -81,13 +88,15 @@ export declare function deleteProjectMirrorBranch(input: {
81
88
  gitDirectory: string;
82
89
  branchName: string;
83
90
  mirrorUrl: string;
84
- mirrorAuth?: GitHttpAuth;
91
+ credentialHelper?: string | null;
92
+ credentialUsername?: string | null;
85
93
  }): void;
86
94
  export declare function pushProjectMirrorHeads(input: {
87
95
  projectRoot: string;
88
96
  branchNames: readonly string[];
89
97
  mirrorUrl: string;
90
- mirrorAuth?: GitHttpAuth;
98
+ credentialHelper?: string | null;
99
+ credentialUsername?: string | null;
91
100
  onlyBranches?: ReadonlySet<string>;
92
101
  }): Array<{
93
102
  branchName: string;
@@ -100,7 +109,8 @@ export declare function fastForwardProjectHeadsFromMirror(input: {
100
109
  primaryBranchName: string;
101
110
  branchNames: readonly string[];
102
111
  mirrorUrl: string;
103
- mirrorAuth?: GitHttpAuth;
112
+ credentialHelper?: string | null;
113
+ credentialUsername?: string | null;
104
114
  }): Array<{
105
115
  branchName: string;
106
116
  previousHead: string;
@@ -108,5 +118,7 @@ export declare function fastForwardProjectHeadsFromMirror(input: {
108
118
  fastForwarded: boolean;
109
119
  }>;
110
120
  export declare const projectWorktreesTestHarness: {
111
- commandArgs: (args: string[], auth?: GitHttpAuth) => string[];
121
+ commandArgs: typeof gitCommandArgs;
122
+ configureRepository: typeof configureRepository;
112
123
  };
124
+ export {};
@@ -1,5 +1,4 @@
1
1
  import { type WorkingTreeSourceMode } from "./working-tree-mirror";
2
- import type { GitHttpAuth } from "./project-worktrees";
3
2
  export declare const WORKSPACE_GIT_BRANCH = "main";
4
3
  export declare const MAX_WORKSPACE_GIT_DIFF_BYTES: number;
5
4
  export declare const WORKSPACE_GIT_CONFIRMED_LARGE_DIFF_PUSH_OPTION = "r5d-confirm-large-diff-v1";
@@ -33,11 +32,23 @@ export type WorkspaceGitSyncResult = {
33
32
  };
34
33
  error?: string;
35
34
  };
35
+ declare function gitCommandArgs(args: string[]): string[];
36
+ declare function workspaceCloneCommandArgs(args: string[], remoteUrl: string, credentialHelper?: string | null, credentialUsername?: string | null): string[];
37
+ declare function configureWorkspaceRepository(input: {
38
+ workspacePath: string;
39
+ remoteUrl: string;
40
+ credentialHelper?: string | null;
41
+ credentialUsername?: string | null;
42
+ gitIdentity: {
43
+ name: string;
44
+ email: string;
45
+ };
46
+ }): void;
36
47
  export declare function ensureWorkspaceGitClone(input: {
37
48
  workspacePath: string;
38
49
  remoteUrl: string;
39
- remoteAuth?: GitHttpAuth;
40
50
  credentialHelper?: string | null;
51
+ credentialUsername?: string | null;
41
52
  gitIdentity: {
42
53
  name: string;
43
54
  email: string;
@@ -51,8 +62,8 @@ export declare function hydrateWorkspaceGitMounts(workspacePath: string, mounts:
51
62
  export declare function resetWorkspaceGit(input: {
52
63
  workspacePath: string;
53
64
  remoteUrl: string;
54
- remoteAuth?: GitHttpAuth;
55
65
  credentialHelper?: string | null;
66
+ credentialUsername?: string | null;
56
67
  gitIdentity: {
57
68
  name: string;
58
69
  email: string;
@@ -69,8 +80,8 @@ export declare function synchronizeWorkspaceGit(input: {
69
80
  workerLabel: string;
70
81
  workspacePath: string;
71
82
  remoteUrl: string;
72
- remoteAuth?: GitHttpAuth;
73
83
  credentialHelper?: string | null;
84
+ credentialUsername?: string | null;
74
85
  gitIdentity: {
75
86
  name: string;
76
87
  email: string;
@@ -90,7 +101,9 @@ export declare function synchronizeWorkspaceGit(input: {
90
101
  }) => void | Promise<void>;
91
102
  }): Promise<WorkspaceGitSyncResult>;
92
103
  export declare const workspaceGitSyncTestHarness: {
93
- commandArgs: (args: string[], auth?: GitHttpAuth) => string[];
104
+ commandArgs: typeof gitCommandArgs;
105
+ workspaceCloneCommandArgs: typeof workspaceCloneCommandArgs;
106
+ configureWorkspaceRepository: typeof configureWorkspaceRepository;
94
107
  mirrorMountsToWorkspace: typeof mirrorMountsToWorkspace;
95
108
  hydrateMountsFromWorkspace: typeof hydrateWorkspaceGitMounts;
96
109
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ricsam/r5d-worker",
3
- "version": "0.0.76",
3
+ "version": "0.0.78",
4
4
  "type": "module",
5
5
  "main": "./dist/cjs/main.cjs",
6
6
  "module": "./dist/mjs/main.mjs",