@ricsam/r5d-worker 0.0.63 → 0.0.65

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/cjs/main.cjs CHANGED
@@ -807,6 +807,19 @@ function fallbackInternalRemoteUrl(baseUrl, projectId) {
807
807
  }
808
808
  function visibleCheckoutRemoteFor(input) {
809
809
  const canonicalCheckout = input.manifest?.canonicalCheckouts?.find((checkout) => checkout.branchName === input.branchName);
810
+ if (!canonicalCheckout && input.manifest) {
811
+ if (!input.manifest.repoHttpUrl) {
812
+ throw new Error(`Project ${input.projectId} has no connected repository; connect one before opening its checkouts`);
813
+ }
814
+ return {
815
+ remoteUrl: input.manifest.repoHttpUrl,
816
+ authHeader: input.manifest.repoAuthHeader ?? null,
817
+ persistAuth: true,
818
+ reconcileExistingOrigin: true,
819
+ requireRemoteBranch: false,
820
+ requiredBaseCommit: null
821
+ };
822
+ }
810
823
  return {
811
824
  remoteUrl: fallbackInternalRemoteUrl(input.baseUrl, input.projectId),
812
825
  authHeader: `Authorization: Bearer ${input.token}`,
@@ -1149,6 +1162,9 @@ function ensureVisibleGitCheckout(input) {
1149
1162
  if (input.reconcileExistingOrigin) {
1150
1163
  ensureOriginRemote(branchPath, input.remoteUrl);
1151
1164
  }
1165
+ if (!input.requireRemoteBranch) {
1166
+ tryGit(visibleCheckoutFetchArgs("origin", "--prune"), { cwd: branchPath, auth: input.remoteAuth });
1167
+ }
1152
1168
  if (input.requireRemoteBranch && !tryGit(["show-ref", "--verify", "--quiet", `refs/remotes/origin/${input.branchName}`], { cwd: branchPath })) {
1153
1169
  throw new Error(`Existing checkout for ${input.branchName} does not contain its canonical remote branch`);
1154
1170
  }
@@ -2905,7 +2921,6 @@ async function startWorker(options) {
2905
2921
  configureGitHubAuth(message.githubCredential);
2906
2922
  visibleGitIdentity = message.gitIdentity;
2907
2923
  workspaceRemoteUrl = message.workspaceRemoteUrl;
2908
- const migratedProjectIds = (0, import_managed_paths.migrateLegacyProjectRoots)(projectsRoot, message.projects);
2909
2924
  manifestByProjectId.clear();
2910
2925
  for (const project of message.projects) manifestByProjectId.set(project.projectId, project);
2911
2926
  const currentCheckouts = allManifestCheckouts();
@@ -2921,7 +2936,7 @@ async function startWorker(options) {
2921
2936
  if (!hasNormalVisibleGitDir(branchPath)) pendingManifestCheckouts.set(key, checkout);
2922
2937
  }
2923
2938
  if (!workspaceManifestRevision.isCurrent(revisionToken)) return false;
2924
- const created = firstBootstrap || migratedProjectIds.length > 0 ? ensureVisibleWorktrees(currentCheckouts, { strictCanonicalRevalidation: true }) : [];
2939
+ const created = firstBootstrap ? ensureVisibleWorktrees(currentCheckouts, { strictCanonicalRevalidation: true }) : [];
2925
2940
  if (!workspaceManifestRevision.isCurrent(revisionToken)) return false;
2926
2941
  const bootstrapped = await (0, import_workspace_sync.convergeWorkspaceHead)(workspaceSyncInput({ type: "connect" }, { newVisibleCheckouts: created }), {
2927
2942
  // An existing checkout becomes routable after a fetch. Its
@@ -2950,10 +2965,8 @@ async function startWorker(options) {
2950
2965
  pendingManifestCheckouts.delete(manifestCheckoutKey(checkout.projectId, checkout.branchName));
2951
2966
  }
2952
2967
  }
2953
- process.stdout.write(
2954
- `[r5d-worker] workspace manifest: ${message.projects.length} projects${migratedProjectIds.length > 0 ? `; migrated ${migratedProjectIds.length} project checkout root(s)` : ""}
2955
- `
2956
- );
2968
+ process.stdout.write(`[r5d-worker] workspace manifest: ${message.projects.length} projects
2969
+ `);
2957
2970
  return true;
2958
2971
  });
2959
2972
  if (!completed || !workspaceManifestRevision.complete(revisionToken)) return;
@@ -31,10 +31,8 @@ __export(managed_paths_exports, {
31
31
  BRANCH_NAME_MAX_LENGTH: () => BRANCH_NAME_MAX_LENGTH,
32
32
  BRANCH_NAME_PATTERN: () => BRANCH_NAME_PATTERN,
33
33
  assertPathInside: () => assertPathInside,
34
- legacyProjectSlug: () => legacyProjectSlug,
35
34
  managedBranchPath: () => managedBranchPath,
36
35
  managedProjectRoot: () => managedProjectRoot,
37
- migrateLegacyProjectRoots: () => migrateLegacyProjectRoots,
38
36
  validateCheckoutPathSegments: () => validateCheckoutPathSegments,
39
37
  validateManagedBranchName: () => validateManagedBranchName
40
38
  });
@@ -105,54 +103,13 @@ function managedBranchPath(projectsRoot, checkoutPathSegments, branchName) {
105
103
  assertNoSymlinkComponents(projectRoot, result);
106
104
  return result;
107
105
  }
108
- function legacyProjectSlug(projectPath, projectId) {
109
- return (projectPath || projectId).trim().toLowerCase().replace(/[^a-z0-9_.-]+/g, "-").replace(/^-+|-+$/g, "") || projectId;
110
- }
111
- function migrateLegacyProjectRoots(projectsRoot, projects) {
112
- const resolvedRoot = import_node_path.default.resolve(projectsRoot);
113
- const legacyOwners = /* @__PURE__ */ new Map();
114
- const nestedOwners = /* @__PURE__ */ new Map();
115
- const moves = [];
116
- for (const project of projects) {
117
- const nestedRoot = managedProjectRoot(resolvedRoot, project.checkoutPathSegments);
118
- const legacySlug = legacyProjectSlug(project.projectPath, project.projectId);
119
- const legacyRoot = import_node_path.default.join(resolvedRoot, legacySlug);
120
- assertNoSymlinkComponents(resolvedRoot, legacyRoot);
121
- const existingLegacyOwner = legacyOwners.get(legacyRoot);
122
- if (existingLegacyOwner) {
123
- throw new Error(`Projects ${existingLegacyOwner} and ${project.projectId} collide at legacy checkout path '${legacyRoot}'`);
124
- }
125
- legacyOwners.set(legacyRoot, project.projectId);
126
- const existingNestedOwner = nestedOwners.get(nestedRoot);
127
- if (existingNestedOwner) {
128
- throw new Error(`Projects ${existingNestedOwner} and ${project.projectId} collide at checkout path '${nestedRoot}'`);
129
- }
130
- nestedOwners.set(nestedRoot, project.projectId);
131
- const legacyExists = import_node_fs.default.existsSync(legacyRoot);
132
- const nestedExists = import_node_fs.default.existsSync(nestedRoot);
133
- if (legacyExists && nestedExists) {
134
- throw new Error(
135
- `Checkout migration is ambiguous for ${project.projectPath}: both '${legacyRoot}' and '${nestedRoot}' exist. Preserve the desired checkout and remove or relocate the other path before reconnecting the worker.`
136
- );
137
- }
138
- if (legacyExists) moves.push({ projectId: project.projectId, legacyRoot, nestedRoot });
139
- }
140
- for (const move of moves) {
141
- import_node_fs.default.mkdirSync(import_node_path.default.dirname(move.nestedRoot), { recursive: true });
142
- assertNoSymlinkComponents(resolvedRoot, import_node_path.default.dirname(move.nestedRoot));
143
- import_node_fs.default.renameSync(move.legacyRoot, move.nestedRoot);
144
- }
145
- return moves.map((move) => move.projectId);
146
- }
147
106
  // Annotate the CommonJS export names for ESM import in node:
148
107
  0 && (module.exports = {
149
108
  BRANCH_NAME_MAX_LENGTH,
150
109
  BRANCH_NAME_PATTERN,
151
110
  assertPathInside,
152
- legacyProjectSlug,
153
111
  managedBranchPath,
154
112
  managedProjectRoot,
155
- migrateLegacyProjectRoots,
156
113
  validateCheckoutPathSegments,
157
114
  validateManagedBranchName
158
115
  });
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@ricsam/r5d-worker",
3
- "version": "0.0.63",
3
+ "version": "0.0.65",
4
4
  "type": "commonjs"
5
5
  }
@@ -41,11 +41,8 @@ function hasNormalGitDirectory(checkoutPath) {
41
41
  function inspectWorkspaceManifestFilesystem(input) {
42
42
  const firstBootstrap = !hasNormalGitDirectory(input.workspaceShadowRoot);
43
43
  const missingCheckouts = [];
44
- const migratedProjectIds = [];
45
44
  for (const project of input.projects) {
46
45
  const projectRoot = (0, import_managed_paths.managedProjectRoot)(input.projectsRoot, project.checkoutPathSegments);
47
- const legacyRoot = import_node_path.default.join(input.projectsRoot, (0, import_managed_paths.legacyProjectSlug)(project.projectPath, project.projectId));
48
- if (import_node_fs.default.existsSync(legacyRoot)) migratedProjectIds.push(project.projectId);
49
46
  for (const branchName of project.branches) {
50
47
  if (!hasNormalGitDirectory(import_node_path.default.join(projectRoot, branchName))) {
51
48
  missingCheckouts.push({ projectId: project.projectId, branchName });
@@ -54,8 +51,7 @@ function inspectWorkspaceManifestFilesystem(input) {
54
51
  }
55
52
  return {
56
53
  firstBootstrap,
57
- missingCheckouts,
58
- migratedProjectIds
54
+ missingCheckouts
59
55
  };
60
56
  }
61
57
  // Annotate the CommonJS export names for ESM import in node:
package/dist/mjs/main.mjs CHANGED
@@ -35,7 +35,7 @@ import {
35
35
  WORKER_RELOAD_EXIT_CODE,
36
36
  WORKER_RUNTIME_ENV
37
37
  } from "./supervisor.mjs";
38
- import { managedProjectRoot, migrateLegacyProjectRoots, validateManagedBranchName } from "./managed-paths.mjs";
38
+ import { managedProjectRoot, validateManagedBranchName } from "./managed-paths.mjs";
39
39
  import {
40
40
  WorkspaceSyncSingleFlight,
41
41
  convergeWorkspaceHead,
@@ -778,6 +778,19 @@ function fallbackInternalRemoteUrl(baseUrl, projectId) {
778
778
  }
779
779
  function visibleCheckoutRemoteFor(input) {
780
780
  const canonicalCheckout = input.manifest?.canonicalCheckouts?.find((checkout) => checkout.branchName === input.branchName);
781
+ if (!canonicalCheckout && input.manifest) {
782
+ if (!input.manifest.repoHttpUrl) {
783
+ throw new Error(`Project ${input.projectId} has no connected repository; connect one before opening its checkouts`);
784
+ }
785
+ return {
786
+ remoteUrl: input.manifest.repoHttpUrl,
787
+ authHeader: input.manifest.repoAuthHeader ?? null,
788
+ persistAuth: true,
789
+ reconcileExistingOrigin: true,
790
+ requireRemoteBranch: false,
791
+ requiredBaseCommit: null
792
+ };
793
+ }
781
794
  return {
782
795
  remoteUrl: fallbackInternalRemoteUrl(input.baseUrl, input.projectId),
783
796
  authHeader: `Authorization: Bearer ${input.token}`,
@@ -1120,6 +1133,9 @@ function ensureVisibleGitCheckout(input) {
1120
1133
  if (input.reconcileExistingOrigin) {
1121
1134
  ensureOriginRemote(branchPath, input.remoteUrl);
1122
1135
  }
1136
+ if (!input.requireRemoteBranch) {
1137
+ tryGit(visibleCheckoutFetchArgs("origin", "--prune"), { cwd: branchPath, auth: input.remoteAuth });
1138
+ }
1123
1139
  if (input.requireRemoteBranch && !tryGit(["show-ref", "--verify", "--quiet", `refs/remotes/origin/${input.branchName}`], { cwd: branchPath })) {
1124
1140
  throw new Error(`Existing checkout for ${input.branchName} does not contain its canonical remote branch`);
1125
1141
  }
@@ -2876,7 +2892,6 @@ async function startWorker(options) {
2876
2892
  configureGitHubAuth(message.githubCredential);
2877
2893
  visibleGitIdentity = message.gitIdentity;
2878
2894
  workspaceRemoteUrl = message.workspaceRemoteUrl;
2879
- const migratedProjectIds = migrateLegacyProjectRoots(projectsRoot, message.projects);
2880
2895
  manifestByProjectId.clear();
2881
2896
  for (const project of message.projects) manifestByProjectId.set(project.projectId, project);
2882
2897
  const currentCheckouts = allManifestCheckouts();
@@ -2892,7 +2907,7 @@ async function startWorker(options) {
2892
2907
  if (!hasNormalVisibleGitDir(branchPath)) pendingManifestCheckouts.set(key, checkout);
2893
2908
  }
2894
2909
  if (!workspaceManifestRevision.isCurrent(revisionToken)) return false;
2895
- const created = firstBootstrap || migratedProjectIds.length > 0 ? ensureVisibleWorktrees(currentCheckouts, { strictCanonicalRevalidation: true }) : [];
2910
+ const created = firstBootstrap ? ensureVisibleWorktrees(currentCheckouts, { strictCanonicalRevalidation: true }) : [];
2896
2911
  if (!workspaceManifestRevision.isCurrent(revisionToken)) return false;
2897
2912
  const bootstrapped = await convergeWorkspaceHead(workspaceSyncInput({ type: "connect" }, { newVisibleCheckouts: created }), {
2898
2913
  // An existing checkout becomes routable after a fetch. Its
@@ -2921,10 +2936,8 @@ async function startWorker(options) {
2921
2936
  pendingManifestCheckouts.delete(manifestCheckoutKey(checkout.projectId, checkout.branchName));
2922
2937
  }
2923
2938
  }
2924
- process.stdout.write(
2925
- `[r5d-worker] workspace manifest: ${message.projects.length} projects${migratedProjectIds.length > 0 ? `; migrated ${migratedProjectIds.length} project checkout root(s)` : ""}
2926
- `
2927
- );
2939
+ process.stdout.write(`[r5d-worker] workspace manifest: ${message.projects.length} projects
2940
+ `);
2928
2941
  return true;
2929
2942
  });
2930
2943
  if (!completed || !workspaceManifestRevision.complete(revisionToken)) return;
@@ -64,53 +64,12 @@ function managedBranchPath(projectsRoot, checkoutPathSegments, branchName) {
64
64
  assertNoSymlinkComponents(projectRoot, result);
65
65
  return result;
66
66
  }
67
- function legacyProjectSlug(projectPath, projectId) {
68
- return (projectPath || projectId).trim().toLowerCase().replace(/[^a-z0-9_.-]+/g, "-").replace(/^-+|-+$/g, "") || projectId;
69
- }
70
- function migrateLegacyProjectRoots(projectsRoot, projects) {
71
- const resolvedRoot = path.resolve(projectsRoot);
72
- const legacyOwners = /* @__PURE__ */ new Map();
73
- const nestedOwners = /* @__PURE__ */ new Map();
74
- const moves = [];
75
- for (const project of projects) {
76
- const nestedRoot = managedProjectRoot(resolvedRoot, project.checkoutPathSegments);
77
- const legacySlug = legacyProjectSlug(project.projectPath, project.projectId);
78
- const legacyRoot = path.join(resolvedRoot, legacySlug);
79
- assertNoSymlinkComponents(resolvedRoot, legacyRoot);
80
- const existingLegacyOwner = legacyOwners.get(legacyRoot);
81
- if (existingLegacyOwner) {
82
- throw new Error(`Projects ${existingLegacyOwner} and ${project.projectId} collide at legacy checkout path '${legacyRoot}'`);
83
- }
84
- legacyOwners.set(legacyRoot, project.projectId);
85
- const existingNestedOwner = nestedOwners.get(nestedRoot);
86
- if (existingNestedOwner) {
87
- throw new Error(`Projects ${existingNestedOwner} and ${project.projectId} collide at checkout path '${nestedRoot}'`);
88
- }
89
- nestedOwners.set(nestedRoot, project.projectId);
90
- const legacyExists = fs.existsSync(legacyRoot);
91
- const nestedExists = fs.existsSync(nestedRoot);
92
- if (legacyExists && nestedExists) {
93
- throw new Error(
94
- `Checkout migration is ambiguous for ${project.projectPath}: both '${legacyRoot}' and '${nestedRoot}' exist. Preserve the desired checkout and remove or relocate the other path before reconnecting the worker.`
95
- );
96
- }
97
- if (legacyExists) moves.push({ projectId: project.projectId, legacyRoot, nestedRoot });
98
- }
99
- for (const move of moves) {
100
- fs.mkdirSync(path.dirname(move.nestedRoot), { recursive: true });
101
- assertNoSymlinkComponents(resolvedRoot, path.dirname(move.nestedRoot));
102
- fs.renameSync(move.legacyRoot, move.nestedRoot);
103
- }
104
- return moves.map((move) => move.projectId);
105
- }
106
67
  export {
107
68
  BRANCH_NAME_MAX_LENGTH,
108
69
  BRANCH_NAME_PATTERN,
109
70
  assertPathInside,
110
- legacyProjectSlug,
111
71
  managedBranchPath,
112
72
  managedProjectRoot,
113
- migrateLegacyProjectRoots,
114
73
  validateCheckoutPathSegments,
115
74
  validateManagedBranchName
116
75
  };
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@ricsam/r5d-worker",
3
- "version": "0.0.63",
3
+ "version": "0.0.65",
4
4
  "type": "module"
5
5
  }
@@ -1,6 +1,6 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
- import { legacyProjectSlug, managedProjectRoot } from "./managed-paths.mjs";
3
+ import { managedProjectRoot } from "./managed-paths.mjs";
4
4
  function hasNormalGitDirectory(checkoutPath) {
5
5
  const gitPath = path.join(checkoutPath, ".git");
6
6
  return fs.existsSync(gitPath) && fs.statSync(gitPath).isDirectory();
@@ -8,11 +8,8 @@ function hasNormalGitDirectory(checkoutPath) {
8
8
  function inspectWorkspaceManifestFilesystem(input) {
9
9
  const firstBootstrap = !hasNormalGitDirectory(input.workspaceShadowRoot);
10
10
  const missingCheckouts = [];
11
- const migratedProjectIds = [];
12
11
  for (const project of input.projects) {
13
12
  const projectRoot = managedProjectRoot(input.projectsRoot, project.checkoutPathSegments);
14
- const legacyRoot = path.join(input.projectsRoot, legacyProjectSlug(project.projectPath, project.projectId));
15
- if (fs.existsSync(legacyRoot)) migratedProjectIds.push(project.projectId);
16
13
  for (const branchName of project.branches) {
17
14
  if (!hasNormalGitDirectory(path.join(projectRoot, branchName))) {
18
15
  missingCheckouts.push({ projectId: project.projectId, branchName });
@@ -21,8 +18,7 @@ function inspectWorkspaceManifestFilesystem(input) {
21
18
  }
22
19
  return {
23
20
  firstBootstrap,
24
- missingCheckouts,
25
- migratedProjectIds
21
+ missingCheckouts
26
22
  };
27
23
  }
28
24
  export {
@@ -1,15 +1,8 @@
1
1
  export declare const BRANCH_NAME_MAX_LENGTH = 45;
2
2
  export declare const BRANCH_NAME_PATTERN: RegExp;
3
3
  export type CheckoutPathSegments = [namespace: string, project: string];
4
- export type ManagedProjectManifestPath = {
5
- projectId: string;
6
- projectPath: string;
7
- checkoutPathSegments: CheckoutPathSegments;
8
- };
9
4
  export declare function validateManagedBranchName(branchName: string): void;
10
5
  export declare function validateCheckoutPathSegments(value: unknown): CheckoutPathSegments;
11
6
  export declare function assertPathInside(root: string, candidate: string, label: string): void;
12
7
  export declare function managedProjectRoot(projectsRoot: string, checkoutPathSegments: unknown): string;
13
8
  export declare function managedBranchPath(projectsRoot: string, checkoutPathSegments: unknown, branchName: string): string;
14
- export declare function legacyProjectSlug(projectPath: string, projectId: string): string;
15
- export declare function migrateLegacyProjectRoots(projectsRoot: string, projects: ManagedProjectManifestPath[]): string[];
@@ -1,6 +1,5 @@
1
1
  export type WorkspaceManifestCheckout = {
2
2
  projectId: string;
3
- projectPath: string;
4
3
  checkoutPathSegments: [namespace: string, project: string];
5
4
  branches: string[];
6
5
  };
@@ -10,7 +9,6 @@ export type WorkspaceManifestFilesystemState = {
10
9
  projectId: string;
11
10
  branchName: string;
12
11
  }>;
13
- migratedProjectIds: string[];
14
12
  };
15
13
  /**
16
14
  * Inspects manifest-related filesystem state without reserving visible paths.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ricsam/r5d-worker",
3
- "version": "0.0.63",
3
+ "version": "0.0.65",
4
4
  "type": "module",
5
5
  "main": "./dist/cjs/main.cjs",
6
6
  "module": "./dist/mjs/main.mjs",