@ricsam/r5d-worker 0.0.93 → 0.0.95

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
@@ -81,6 +81,7 @@ var import_repository_transition_policy = require("./repository-transition-polic
81
81
  var import_supervisor = require("./supervisor.cjs");
82
82
  var import_managed_paths = require("./managed-paths.cjs");
83
83
  var import_project_worktrees = require("./project-worktrees.cjs");
84
+ var import_project_mirror_fetch_policy = require("./project-mirror-fetch-policy.cjs");
84
85
  var import_project_snapshot_recovery_runner = require("./project-snapshot-recovery-runner.cjs");
85
86
  var import_project_workspace_state = require("./project-workspace-state.cjs");
86
87
  var import_workspace_git_sync = require("./workspace-git-sync.cjs");
@@ -113,6 +114,7 @@ const DEFAULT_READ_MAX_BYTES = 5e4;
113
114
  const MAX_LINE_LENGTH = 2e3;
114
115
  const WORKSPACE_GIT_QUIET_MS = 5e3;
115
116
  const WORKSPACE_GIT_PERIODIC_MS = 6e4;
117
+ const PROJECT_MIRROR_OBSERVE_CONCURRENCY = 6;
116
118
  const WORKSPACE_INCIDENT_CONFIG_REFRESH_TIMEOUT_MS = 6e4;
117
119
  const PTY_INPUT_BUSY_GRACE_MS = 3e3;
118
120
  const PTY_FOREGROUND_POLL_MS = 1e3;
@@ -1003,6 +1005,21 @@ function resolveWorkerFilePath(branchPath, inputPath, builtInPaths) {
1003
1005
  function canonicalProjectRemoteUrl(baseUrl, projectId) {
1004
1006
  return new URL(`/git/${projectId}.git`, baseUrl).toString();
1005
1007
  }
1008
+ async function mapWithConcurrencyLimit(items, limit, task) {
1009
+ const results = new Array(items.length);
1010
+ let nextIndex = 0;
1011
+ await Promise.all(
1012
+ Array.from({ length: Math.max(1, Math.min(limit, items.length)) }, async () => {
1013
+ while (true) {
1014
+ const index = nextIndex;
1015
+ nextIndex += 1;
1016
+ if (index >= items.length) return;
1017
+ results[index] = await task(items[index], index);
1018
+ }
1019
+ })
1020
+ );
1021
+ return results;
1022
+ }
1006
1023
  function shellQuote(value) {
1007
1024
  return `'${value.replace(/'/g, "'\\''")}'`;
1008
1025
  }
@@ -3462,6 +3479,10 @@ async function startWorker(options) {
3462
3479
  const readyProjectIds = /* @__PURE__ */ new Set();
3463
3480
  const reconciledProjectConfigFingerprints = /* @__PURE__ */ new Map();
3464
3481
  const lastObservedProjectHeads = /* @__PURE__ */ new Map();
3482
+ const advertisedProjectMirrorRefsTokens = /* @__PURE__ */ new Map();
3483
+ const fetchedProjectMirrorRefsTokens = /* @__PURE__ */ new Map();
3484
+ const lastProjectMirrorFetchAtMs = /* @__PURE__ */ new Map();
3485
+ const projectMirrorFetchSkippingEnabled = process.env.R5D_PROJECT_MIRROR_FETCH_SKIP !== "0";
3465
3486
  const pendingMirrorDeletes = /* @__PURE__ */ new Map();
3466
3487
  let workspaceRemoteUrl = null;
3467
3488
  let workspaceCredentialHelper = null;
@@ -3479,6 +3500,7 @@ async function startWorker(options) {
3479
3500
  let automaticSyncInFlight = false;
3480
3501
  let terminalReplayTimer;
3481
3502
  let workspaceSyncRequestsInFlight = 0;
3503
+ let lastWorkspaceSyncMirrorObservationMs = 0;
3482
3504
  let sessionArtifactSyncRequestsInFlight = 0;
3483
3505
  let cliUpdateInProgress = false;
3484
3506
  let reloadAfterClose = false;
@@ -4067,7 +4089,7 @@ async function startWorker(options) {
4067
4089
  }
4068
4090
  return heads;
4069
4091
  };
4070
- const pushChangedProjectHeads = async (activeMountIds, publishedHead, publicationHeads, suppressedMountIds = /* @__PURE__ */ new Set()) => {
4092
+ const pushChangedProjectHeads = async (activeMountIds, publishedHead, publicationHeads, expectedMirrorHeads, suppressedMountIds = /* @__PURE__ */ new Set()) => {
4071
4093
  const active = new Set(activeMountIds);
4072
4094
  for (const project of projectConfigById.values()) {
4073
4095
  if (!readyProjectIds.has(project.projectId) || !(0, import_repository_transition_policy.repositoryMirrorWritesAllowed)(project)) continue;
@@ -4082,6 +4104,12 @@ async function startWorker(options) {
4082
4104
  }
4083
4105
  }
4084
4106
  if (changed.size === 0) continue;
4107
+ const branchLeases = /* @__PURE__ */ new Map();
4108
+ for (const branchName of changed.keys()) {
4109
+ const mountId = projectMountId(project.projectId, branchName);
4110
+ if (!expectedMirrorHeads.has(mountId)) throw new Error(`Missing observed hidden-mirror lease for active project mount ${mountId}`);
4111
+ branchLeases.set(branchName, expectedMirrorHeads.get(mountId) ?? null);
4112
+ }
4085
4113
  const connection = projectConnection(project);
4086
4114
  const results = await (0, import_project_worktrees.pushProjectMirrorHeads)({
4087
4115
  projectRoot: configuredProjectRoot(projectsRoot, project),
@@ -4090,12 +4118,25 @@ async function startWorker(options) {
4090
4118
  credentialHelper: connection.credentialHelper,
4091
4119
  credentialUsername: connection.mirrorCredentialUsername,
4092
4120
  onlyBranches: new Set(changed.keys()),
4093
- publicationHeads: changed
4121
+ publicationHeads: changed,
4122
+ expectedMirrorHeads: branchLeases,
4123
+ branchIds: new Map(project.branches.map(({ branchId, branchName }) => [branchName, branchId]))
4094
4124
  });
4095
4125
  (0, import_project_worktrees.assertProjectMirrorHeadsPushed)(results);
4096
4126
  for (const result of results) {
4097
4127
  lastObservedProjectHeads.set(projectBranchKey(project.projectId, result.branchName), result.head);
4098
4128
  }
4129
+ try {
4130
+ fetchedProjectMirrorRefsTokens.set(
4131
+ project.projectId,
4132
+ await (0, import_project_worktrees.computeLocalProjectMirrorRefsToken)({
4133
+ projectRoot: configuredProjectRoot(projectsRoot, project),
4134
+ primaryBranchName: primaryProjectBranch(project)
4135
+ })
4136
+ );
4137
+ } catch {
4138
+ fetchedProjectMirrorRefsTokens.delete(project.projectId);
4139
+ }
4099
4140
  }
4100
4141
  const publishedTombstoneIds = [
4101
4142
  ...new Set(
@@ -4121,6 +4162,7 @@ async function startWorker(options) {
4121
4162
  credentialHelper: deletion.credentialHelper,
4122
4163
  credentialUsername: deletion.credentialUsername
4123
4164
  });
4165
+ fetchedProjectMirrorRefsTokens.delete(deletion.projectId);
4124
4166
  }
4125
4167
  if (deletion.tombstoneId && !deletion.projectDeleted) {
4126
4168
  projectWorkspaceState = projectWorkspaceStateStore.recordMirrorRefDeletion({
@@ -4131,43 +4173,103 @@ async function startWorker(options) {
4131
4173
  pendingMirrorDeletes.delete(key);
4132
4174
  if (deletion.projectDeleted && !projectConfigById.has(deletion.projectId) && ![...pendingMirrorDeletes.values()].some((pending) => pending.projectId === deletion.projectId)) {
4133
4175
  removeProjectCredentialStore(deletion.projectId);
4176
+ advertisedProjectMirrorRefsTokens.delete(deletion.projectId);
4177
+ fetchedProjectMirrorRefsTokens.delete(deletion.projectId);
4178
+ lastProjectMirrorFetchAtMs.delete(deletion.projectId);
4134
4179
  }
4135
4180
  lastObservedProjectHeads.delete(key);
4136
4181
  }
4137
4182
  };
4183
+ const observeSingleProjectMirrorBundle = async (project, options2) => {
4184
+ const connection = projectConnection(project);
4185
+ const projectRoot = configuredProjectRoot(projectsRoot, project);
4186
+ const primaryBranchName = primaryProjectBranch(project);
4187
+ if (options2.refreshRemote) {
4188
+ const advertisedBeforeFetch = advertisedProjectMirrorRefsTokens.get(project.projectId);
4189
+ const observations = await (0, import_project_worktrees.observeProjectMirrorHeads)({
4190
+ projectRoot,
4191
+ primaryBranchName,
4192
+ branchNames: project.branches.map(({ branchName }) => branchName),
4193
+ mirrorUrl: connection.mirrorUrl,
4194
+ credentialHelper: connection.credentialHelper,
4195
+ credentialUsername: connection.mirrorCredentialUsername,
4196
+ allowNonFastForward: options2.allowNonFastForward,
4197
+ branchIds: new Map(project.branches.map(({ branchId, branchName }) => [branchName, branchId]))
4198
+ });
4199
+ if (advertisedBeforeFetch === void 0) fetchedProjectMirrorRefsTokens.delete(project.projectId);
4200
+ else fetchedProjectMirrorRefsTokens.set(project.projectId, advertisedBeforeFetch);
4201
+ lastProjectMirrorFetchAtMs.set(project.projectId, Date.now());
4202
+ return { projectId: project.projectId, projectRoot, primaryBranchName, observations };
4203
+ }
4204
+ return {
4205
+ projectId: project.projectId,
4206
+ projectRoot,
4207
+ primaryBranchName,
4208
+ observations: await (0, import_project_worktrees.observeProjectMirrorHeads)({
4209
+ projectRoot,
4210
+ primaryBranchName,
4211
+ branchNames: project.branches.map(({ branchName }) => branchName),
4212
+ mirrorUrl: connection.mirrorUrl,
4213
+ credentialHelper: connection.credentialHelper,
4214
+ credentialUsername: connection.mirrorCredentialUsername,
4215
+ allowNonFastForward: options2.allowNonFastForward,
4216
+ branchIds: new Map(project.branches.map(({ branchId, branchName }) => [branchName, branchId])),
4217
+ refreshRemote: false
4218
+ })
4219
+ };
4220
+ };
4138
4221
  const observeProjectHeadsBeforeOuterWorkspace = async (input) => {
4139
- const bundles = [];
4140
- for (const project of projectConfigById.values()) {
4141
- if (project.executionDisabled || !readyProjectIds.has(project.projectId) || project.branches.length === 0) continue;
4142
- try {
4143
- const connection = projectConnection(project);
4144
- const projectRoot = configuredProjectRoot(projectsRoot, project);
4145
- const primaryBranchName = primaryProjectBranch(project);
4146
- bundles.push({
4147
- projectId: project.projectId,
4148
- projectRoot,
4149
- primaryBranchName,
4150
- observations: await (0, import_project_worktrees.observeProjectMirrorHeads)({
4151
- projectRoot,
4152
- primaryBranchName,
4153
- branchNames: project.branches.map(({ branchName }) => branchName),
4154
- mirrorUrl: connection.mirrorUrl,
4155
- credentialHelper: connection.credentialHelper,
4156
- credentialUsername: connection.mirrorCredentialUsername,
4157
- allowNonFastForward: input.allowNonFastForward
4158
- })
4159
- });
4160
- } catch (error) {
4161
- if (input.failClosed) throw error;
4222
+ const observationStartedAt = Date.now();
4223
+ const eligibleProjects = [...projectConfigById.values()].filter(
4224
+ (project) => !project.executionDisabled && readyProjectIds.has(project.projectId) && project.branches.length > 0
4225
+ );
4226
+ try {
4227
+ if (input.failClosed) {
4228
+ const bundles2 = [];
4229
+ for (const project of eligibleProjects) {
4230
+ bundles2.push(await observeSingleProjectMirrorBundle(project, { allowNonFastForward: input.allowNonFastForward, refreshRemote: true }));
4231
+ }
4232
+ return bundles2;
4233
+ }
4234
+ let fetchedCount = 0;
4235
+ const bundles = await mapWithConcurrencyLimit(
4236
+ eligibleProjects,
4237
+ PROJECT_MIRROR_OBSERVE_CONCURRENCY,
4238
+ async (project) => {
4239
+ try {
4240
+ const decision = (0, import_project_mirror_fetch_policy.projectMirrorFetchDecision)({
4241
+ advertisedToken: advertisedProjectMirrorRefsTokens.get(project.projectId),
4242
+ fetchedToken: fetchedProjectMirrorRefsTokens.get(project.projectId),
4243
+ lastFetchAtMs: lastProjectMirrorFetchAtMs.get(project.projectId),
4244
+ nowMs: Date.now(),
4245
+ skippingEnabled: projectMirrorFetchSkippingEnabled
4246
+ });
4247
+ if (decision.fetch) fetchedCount += 1;
4248
+ return await observeSingleProjectMirrorBundle(project, {
4249
+ allowNonFastForward: input.allowNonFastForward,
4250
+ refreshRemote: decision.fetch
4251
+ });
4252
+ } catch (error) {
4253
+ process.stderr.write(
4254
+ `[r5d-worker] failed to observe project mirror heads before workspace update: ${error instanceof Error ? error.message : String(error)}
4255
+ `
4256
+ );
4257
+ return null;
4258
+ }
4259
+ }
4260
+ );
4261
+ if (fetchedCount > 0) {
4162
4262
  process.stderr.write(
4163
- `[r5d-worker] failed to observe project mirror heads before workspace update: ${error instanceof Error ? error.message : String(error)}
4263
+ `[r5d-worker] project mirror observation fetched ${fetchedCount} of ${eligibleProjects.length} mirror(s)
4164
4264
  `
4165
4265
  );
4166
4266
  }
4267
+ return bundles.filter((bundle) => bundle !== null);
4268
+ } finally {
4269
+ lastWorkspaceSyncMirrorObservationMs = Date.now() - observationStartedAt;
4167
4270
  }
4168
- return bundles;
4169
4271
  };
4170
- const applyObservedProjectHeadsAfterInboundWorkspace = async (bundles, activeMountIds, requireObservedHeads) => {
4272
+ const applyObservedProjectHeadsAfterInboundWorkspace = async (bundles, activeMountIds, requireObservedHeads, integratedWorkspaceHead) => {
4171
4273
  const active = new Set(activeMountIds);
4172
4274
  for (const bundle of bundles) {
4173
4275
  const project = projectConfigById.get(bundle.projectId);
@@ -4179,7 +4281,16 @@ async function startWorker(options) {
4179
4281
  projectRoot: bundle.projectRoot,
4180
4282
  primaryBranchName: bundle.primaryBranchName,
4181
4283
  observations,
4182
- branchMutationAllowed: (branchName, checkoutPath) => !projectBranchMountBusy(project.projectId, branchName, checkoutPath)
4284
+ branchMutationAllowed: (branchName, checkoutPath) => !projectBranchMountBusy(project.projectId, branchName, checkoutPath),
4285
+ serverSyncedWorkspaceCovered: async (observation) => {
4286
+ if (!integratedWorkspaceHead) return false;
4287
+ for (const workspaceHead of observation.serverSyncedWorkspaceHeads) {
4288
+ if (await tryGitAsync(["merge-base", "--is-ancestor", workspaceHead, integratedWorkspaceHead], { cwd: workspaceShadowRoot })) {
4289
+ return true;
4290
+ }
4291
+ }
4292
+ return false;
4293
+ }
4183
4294
  });
4184
4295
  if (requireObservedHeads) {
4185
4296
  for (const observation of observations) {
@@ -4304,6 +4415,12 @@ async function startWorker(options) {
4304
4415
  const outerRemediation = input.trigger.type === "remediation" || input.trigger.type === "remediation_confirm";
4305
4416
  const mounts = outerRemediation ? (0, import_workspace_git_sync.workspaceGitMountsForRemediation)(configuredMounts) : configuredMounts;
4306
4417
  const observedProjectHeads = outerRemediation ? [] : await observeProjectHeadsBeforeOuterWorkspace({ allowNonFastForward: false, failClosed: false });
4418
+ const expectedMirrorHeads = /* @__PURE__ */ new Map();
4419
+ for (const bundle of observedProjectHeads) {
4420
+ for (const observation of bundle.observations) {
4421
+ expectedMirrorHeads.set(projectMountId(bundle.projectId, observation.branchName), observation.mirrorHead);
4422
+ }
4423
+ }
4307
4424
  const inboundMoveMountIds = new Set(
4308
4425
  observedProjectHeads.flatMap(
4309
4426
  ({ projectId, observations }) => observations.filter(({ shouldMove }) => shouldMove).map(({ branchName }) => projectMountId(projectId, branchName))
@@ -4325,12 +4442,17 @@ async function startWorker(options) {
4325
4442
  requiredAncestorHeads: input.requiredAncestorHeads,
4326
4443
  assertStillAdmitted: input.assertStillAdmitted,
4327
4444
  afterWorkspacePublished: outerRemediation ? void 0 : async ({ activeMountIds, publishedHead }) => {
4328
- await pushChangedProjectHeads(activeMountIds, publishedHead, publicationHeads, inboundMoveMountIds);
4445
+ await pushChangedProjectHeads(activeMountIds, publishedHead, publicationHeads, expectedMirrorHeads, inboundMoveMountIds);
4329
4446
  }
4330
4447
  });
4331
4448
  input.assertStillAdmitted?.();
4332
4449
  if (["no_change", "updated", "pushed"].includes(result.outcome) && !outerRemediation) {
4333
- await applyObservedProjectHeadsAfterInboundWorkspace(observedProjectHeads, result.activeMountIds, false);
4450
+ await applyObservedProjectHeadsAfterInboundWorkspace(
4451
+ observedProjectHeads,
4452
+ result.activeMountIds,
4453
+ false,
4454
+ result.localHead ?? result.remoteHead
4455
+ );
4334
4456
  }
4335
4457
  return mapWorkspaceGitResult(input.attemptId, input.trigger, result);
4336
4458
  };
@@ -4414,6 +4536,7 @@ async function startWorker(options) {
4414
4536
  result = await workspaceSyncSingleFlight.runExclusive(async () => {
4415
4537
  queueEnteredAt = Date.now();
4416
4538
  syncStartedAt = Date.now();
4539
+ lastWorkspaceSyncMirrorObservationMs = 0;
4417
4540
  if (!deferredWorkspaceSyncTriggerIsAllowed(deferredWorkspaceConfiguration, activeWorkspaceIncidentId, input.trigger)) {
4418
4541
  return await failedWorkspaceSyncResult(
4419
4542
  attemptId,
@@ -4498,7 +4621,9 @@ async function startWorker(options) {
4498
4621
  telemetry: {
4499
4622
  totalMs: finishedAt - requestedAt,
4500
4623
  queueMs: queueEnteredAt - requestedAt,
4501
- prepareMs: 0,
4624
+ // Duration of the pre-outer mirror-head observation phase; near zero
4625
+ // on a cycle whose token-gated observation skipped every fetch.
4626
+ prepareMs: lastWorkspaceSyncMirrorObservationMs,
4502
4627
  synchronizeMs: finishedAt - syncStartedAt
4503
4628
  }
4504
4629
  };
@@ -5215,7 +5340,9 @@ async function startWorker(options) {
5215
5340
  workspaceRemediationAncestorGuardV1: true,
5216
5341
  workspaceIncidentConfigDeferralV1: true,
5217
5342
  workspaceConfigResetToCanonicalV1: true,
5218
- projectBranchDeletionFastAckV1: true
5343
+ projectBranchDeletionFastAckV1: true,
5344
+ projectMirrorLeaseV1: true,
5345
+ projectMirrorRefsTokensV1: true
5219
5346
  },
5220
5347
  projectRoot: projectsRoot,
5221
5348
  artifactRoot,
@@ -5253,6 +5380,17 @@ async function startWorker(options) {
5253
5380
  if (message.type === "connected") {
5254
5381
  return;
5255
5382
  }
5383
+ if (message.type === "project_mirror_refs_tokens") {
5384
+ advertisedProjectMirrorRefsTokens.clear();
5385
+ if (message.tokens && typeof message.tokens === "object") {
5386
+ for (const [projectId, token2] of Object.entries(message.tokens)) {
5387
+ if (typeof token2 === "string" && /^[0-9a-f]{64}$/.test(token2)) {
5388
+ advertisedProjectMirrorRefsTokens.set(projectId, token2);
5389
+ }
5390
+ }
5391
+ }
5392
+ return;
5393
+ }
5256
5394
  if (message.type === "workspace_config") {
5257
5395
  const receiptGeneration = ++workspaceConfigurationReceiptGeneration;
5258
5396
  const refreshesDeferredConfiguration = deferredWorkspaceConfiguration !== null && activeWorkspaceIncidentId === null && message.deferWorkspaceSyncForIncidentId === void 0;
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@ricsam/r5d-worker",
3
- "version": "0.0.93",
3
+ "version": "0.0.95",
4
4
  "type": "commonjs"
5
5
  }
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var project_mirror_fetch_policy_exports = {};
20
+ __export(project_mirror_fetch_policy_exports, {
21
+ PROJECT_MIRROR_FETCH_BACKSTOP_MS: () => PROJECT_MIRROR_FETCH_BACKSTOP_MS,
22
+ projectMirrorFetchDecision: () => projectMirrorFetchDecision
23
+ });
24
+ module.exports = __toCommonJS(project_mirror_fetch_policy_exports);
25
+ const PROJECT_MIRROR_FETCH_BACKSTOP_MS = 10 * 6e4;
26
+ function projectMirrorFetchDecision(input) {
27
+ if (!input.skippingEnabled) return { fetch: true, reason: "skipping_disabled" };
28
+ if (input.advertisedToken === void 0) return { fetch: true, reason: "no_advertised_token" };
29
+ if (input.fetchedToken === void 0) return { fetch: true, reason: "never_fetched" };
30
+ if (input.advertisedToken !== input.fetchedToken) return { fetch: true, reason: "token_changed" };
31
+ const backstopMs = input.backstopMs ?? PROJECT_MIRROR_FETCH_BACKSTOP_MS;
32
+ if (input.lastFetchAtMs === void 0 || input.nowMs - input.lastFetchAtMs >= backstopMs) {
33
+ return { fetch: true, reason: "backstop_elapsed" };
34
+ }
35
+ return { fetch: false, reason: "token_match" };
36
+ }
37
+ // Annotate the CommonJS export names for ESM import in node:
38
+ 0 && (module.exports = {
39
+ PROJECT_MIRROR_FETCH_BACKSTOP_MS,
40
+ projectMirrorFetchDecision
41
+ });
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var project_mirror_refs_token_exports = {};
20
+ __export(project_mirror_refs_token_exports, {
21
+ PROJECT_MIRROR_REF_PREFIX: () => PROJECT_MIRROR_REF_PREFIX,
22
+ PROJECT_SERVER_SYNCED_REF_PREFIX: () => PROJECT_SERVER_SYNCED_REF_PREFIX,
23
+ canonicalizeLocalProjectMirrorRefs: () => canonicalizeLocalProjectMirrorRefs,
24
+ hashProjectMirrorRefs: () => hashProjectMirrorRefs
25
+ });
26
+ module.exports = __toCommonJS(project_mirror_refs_token_exports);
27
+ var import_node_crypto = require("node:crypto");
28
+ const PROJECT_MIRROR_REF_PREFIX = "refs/r5d/mirror/";
29
+ const PROJECT_SERVER_SYNCED_REF_PREFIX = "refs/r5d/server-synced/";
30
+ function hashProjectMirrorRefs(refs) {
31
+ const lines = refs.map(({ objectName, refname }) => `${objectName} ${refname}`).sort((left, right) => left < right ? -1 : left > right ? 1 : 0);
32
+ return (0, import_node_crypto.createHash)("sha256").update(lines.join("\n")).digest("hex");
33
+ }
34
+ function canonicalizeLocalProjectMirrorRefs(refs) {
35
+ const canonical = [];
36
+ for (const { refname, objectName } of refs) {
37
+ if (refname.startsWith(PROJECT_MIRROR_REF_PREFIX)) {
38
+ canonical.push({ refname: `refs/heads/${refname.slice(PROJECT_MIRROR_REF_PREFIX.length)}`, objectName });
39
+ } else if (refname.startsWith(PROJECT_SERVER_SYNCED_REF_PREFIX)) {
40
+ canonical.push({ refname, objectName });
41
+ }
42
+ }
43
+ return canonical;
44
+ }
45
+ // Annotate the CommonJS export names for ESM import in node:
46
+ 0 && (module.exports = {
47
+ PROJECT_MIRROR_REF_PREFIX,
48
+ PROJECT_SERVER_SYNCED_REF_PREFIX,
49
+ canonicalizeLocalProjectMirrorRefs,
50
+ hashProjectMirrorRefs
51
+ });