@indigoai-us/hq-cloud 6.18.45-alpha.0 → 6.18.45
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/bin/sync-runner-company.d.ts.map +1 -1
- package/dist/bin/sync-runner-company.js +0 -11
- package/dist/bin/sync-runner-company.js.map +1 -1
- package/dist/bin/sync-runner.d.ts +0 -5
- package/dist/bin/sync-runner.d.ts.map +1 -1
- package/dist/bin/sync-runner.js.map +1 -1
- package/dist/cli/share.d.ts +2 -16
- package/dist/cli/share.d.ts.map +1 -1
- package/dist/cli/share.js +16 -192
- package/dist/cli/share.js.map +1 -1
- package/dist/cli/sync.d.ts +0 -6
- package/dist/cli/sync.d.ts.map +1 -1
- package/dist/cli/sync.js +0 -21
- package/dist/cli/sync.js.map +1 -1
- package/dist/cognito-auth.d.ts.map +1 -1
- package/dist/cognito-auth.js +109 -8
- package/dist/cognito-auth.js.map +1 -1
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +4 -0
- package/dist/context.js.map +1 -1
- package/dist/journal-row-store.d.ts +0 -3
- package/dist/journal-row-store.d.ts.map +1 -1
- package/dist/journal-row-store.js +0 -14
- package/dist/journal-row-store.js.map +1 -1
- package/dist/journal-snapshot-decoder.js +0 -2
- package/dist/journal-snapshot-decoder.js.map +1 -1
- package/dist/journal-snapshot-v4.d.ts +2 -2
- package/dist/journal-snapshot-v4.d.ts.map +1 -1
- package/dist/journal-snapshot-v4.js +3 -8
- package/dist/journal-snapshot-v4.js.map +1 -1
- package/dist/journal.d.ts +0 -1
- package/dist/journal.d.ts.map +1 -1
- package/dist/journal.js +1 -3
- package/dist/journal.js.map +1 -1
- package/dist/s3.d.ts +5 -22
- package/dist/s3.d.ts.map +1 -1
- package/dist/s3.js +10 -55
- package/dist/s3.js.map +1 -1
- package/dist/sync/durable-apply.d.ts +0 -16
- package/dist/sync/durable-apply.d.ts.map +1 -1
- package/dist/sync/durable-apply.js +0 -53
- package/dist/sync/durable-apply.js.map +1 -1
- package/dist/sync-progress.d.ts.map +1 -1
- package/dist/sync-progress.js +0 -2
- package/dist/sync-progress.js.map +1 -1
- package/dist/types.d.ts +0 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/vault-client.d.ts +2 -0
- package/dist/vault-client.d.ts.map +1 -1
- package/dist/vault-client.js +1 -1
- package/dist/vault-client.js.map +1 -1
- package/package.json +1 -1
- package/dist/symlink-target-policy.d.ts +0 -32
- package/dist/symlink-target-policy.d.ts.map +0 -1
- package/dist/symlink-target-policy.js +0 -124
- package/dist/symlink-target-policy.js.map +0 -1
- package/dist/sync/symlink-target-refusal-flag.d.ts +0 -13
- package/dist/sync/symlink-target-refusal-flag.d.ts.map +0 -1
- package/dist/sync/symlink-target-refusal-flag.js +0 -51
- package/dist/sync/symlink-target-refusal-flag.js.map +0 -1
package/dist/cli/share.js
CHANGED
|
@@ -7,8 +7,6 @@
|
|
|
7
7
|
import * as fs from "fs";
|
|
8
8
|
import * as os from "os";
|
|
9
9
|
import * as path from "path";
|
|
10
|
-
import { resolveSymlinkTargetRefusalFlag } from "../sync/symlink-target-refusal-flag.js";
|
|
11
|
-
import { inspectSymlinkTarget, materializedTargetMatchesWire } from "../symlink-target-policy.js";
|
|
12
10
|
import { resolveEntityContext, isExpiringSoon, refreshEntityContext } from "../context.js";
|
|
13
11
|
import { ensureCompanyVaultTransport } from "../company-vault-transport.js";
|
|
14
12
|
import { createSyncProgressRecorder } from "../sync-progress.js";
|
|
@@ -65,7 +63,7 @@ import { directoryFoldsCase, findCaseFoldedLocalKey, foldVaultKey, } from "./cas
|
|
|
65
63
|
* outcome. The name is derived from the relative path so concurrent probes
|
|
66
64
|
* for distinct files never collide on disk.
|
|
67
65
|
*/
|
|
68
|
-
async function remoteContentDiffers(ctx, relativePath, localHash, hqRoot
|
|
66
|
+
async function remoteContentDiffers(ctx, relativePath, localHash, hqRoot) {
|
|
69
67
|
const probeKey = crypto
|
|
70
68
|
.createHash("sha256")
|
|
71
69
|
.update(relativePath)
|
|
@@ -73,7 +71,7 @@ async function remoteContentDiffers(ctx, relativePath, localHash, hqRoot, symlin
|
|
|
73
71
|
.slice(0, 16);
|
|
74
72
|
const probePath = path.join(os.tmpdir(), `hq-conflict-probe-${readShortMachineId(hqRoot)}-${probeKey}.tmp`);
|
|
75
73
|
try {
|
|
76
|
-
await downloadFile(ctx, relativePath, probePath
|
|
74
|
+
await downloadFile(ctx, relativePath, probePath);
|
|
77
75
|
const remoteHash = fs.lstatSync(probePath).isSymbolicLink()
|
|
78
76
|
? hashSymlinkTarget(fs.readlinkSync(probePath))
|
|
79
77
|
: hashFile(probePath);
|
|
@@ -275,7 +273,6 @@ export const _testing = {
|
|
|
275
273
|
cooperativeRowVisits: snapshotCooperativeRowVisits,
|
|
276
274
|
computePushPlan,
|
|
277
275
|
computePushPlanCooperatively,
|
|
278
|
-
normalizeWindowsSymlinkTarget,
|
|
279
276
|
};
|
|
280
277
|
/** Snapshot of `absolutePath`, or null when it is missing or not a plain file. */
|
|
281
278
|
function statSnapshot(absolutePath) {
|
|
@@ -449,7 +446,7 @@ function refusesServerOwnedPush(relativePath, ontologyEntityPush, absolutePath,
|
|
|
449
446
|
}
|
|
450
447
|
return isCloudAuthoritative(relativePath);
|
|
451
448
|
}
|
|
452
|
-
function computePushPlan(filesToShare, journal, skipUnchanged, onHeartbeat, ontologyEntityPush = false
|
|
449
|
+
function computePushPlan(filesToShare, journal, skipUnchanged, onHeartbeat, ontologyEntityPush = false) {
|
|
453
450
|
const items = [];
|
|
454
451
|
let omittedSkips = 0;
|
|
455
452
|
let plannedRows = 0;
|
|
@@ -476,18 +473,6 @@ function computePushPlan(filesToShare, journal, skipUnchanged, onHeartbeat, onto
|
|
|
476
473
|
// itself "looks" identical.
|
|
477
474
|
if (entry.kind === "symlink") {
|
|
478
475
|
const localHash = hashSymlinkTarget(entry.target);
|
|
479
|
-
const journalEntry = journalRows(journal).get(relativePath);
|
|
480
|
-
const portable = portablePushSymlinkTarget(absolutePath, relativePath, entry.target, journalEntry?.wireSymlinkTarget, symlinkContext);
|
|
481
|
-
if (portable.refused) {
|
|
482
|
-
items.push({
|
|
483
|
-
action: "refuse-unsafe-symlink",
|
|
484
|
-
absolutePath,
|
|
485
|
-
relativePath,
|
|
486
|
-
classification: portable.classification,
|
|
487
|
-
shape: portable.shape,
|
|
488
|
-
});
|
|
489
|
-
continue;
|
|
490
|
-
}
|
|
491
476
|
if (skipUnchanged) {
|
|
492
477
|
const existing = skipFingerprint(journal, relativePath);
|
|
493
478
|
// `!localDiverges`: see the regular-file gate below — a divergent entry
|
|
@@ -503,7 +488,7 @@ function computePushPlan(filesToShare, journal, skipUnchanged, onHeartbeat, onto
|
|
|
503
488
|
kind: "symlink",
|
|
504
489
|
absolutePath,
|
|
505
490
|
relativePath,
|
|
506
|
-
target:
|
|
491
|
+
target: entry.target,
|
|
507
492
|
localHash,
|
|
508
493
|
size: 0,
|
|
509
494
|
});
|
|
@@ -623,107 +608,12 @@ function computePushPlan(filesToShare, journal, skipUnchanged, onHeartbeat, onto
|
|
|
623
608
|
filesToSkip += omittedSkips;
|
|
624
609
|
return { items, filesToUpload, bytesToUpload, filesToSkip, preplannedFilesSkipped: omittedSkips };
|
|
625
610
|
}
|
|
626
|
-
function portablePushSymlinkTarget(absolutePath, relativePath, localTarget, wireTarget, context) {
|
|
627
|
-
const pathApi = process.platform === "win32" ? path.win32 : path;
|
|
628
|
-
let scope;
|
|
629
|
-
let scopeRoot;
|
|
630
|
-
let linkPath = relativePath;
|
|
631
|
-
if (context) {
|
|
632
|
-
const skillFarmRoot = pathApi.resolve(context.hqRoot, ".claude", "skills");
|
|
633
|
-
const skillFarmRelative = pathApi.relative(skillFarmRoot, pathApi.resolve(absolutePath));
|
|
634
|
-
const isSkillFarmPath = skillFarmRelative !== ".." &&
|
|
635
|
-
!skillFarmRelative.startsWith(`..${pathApi.sep}`) && !pathApi.isAbsolute(skillFarmRelative);
|
|
636
|
-
if (isSkillFarmPath) {
|
|
637
|
-
scope = { kind: "personal" };
|
|
638
|
-
scopeRoot = context.hqRoot;
|
|
639
|
-
linkPath = `.claude/skills/${skillFarmRelative.split(pathApi.sep).join("/")}`;
|
|
640
|
-
}
|
|
641
|
-
else if (context.personalMode) {
|
|
642
|
-
scope = { kind: "personal" };
|
|
643
|
-
scopeRoot = context.syncRoot;
|
|
644
|
-
linkPath = `personal/${relativePath}`;
|
|
645
|
-
}
|
|
646
|
-
else {
|
|
647
|
-
scope = { kind: "company", companySlug: context.companySlug };
|
|
648
|
-
scopeRoot = context.syncRoot;
|
|
649
|
-
linkPath = `companies/${context.companySlug}/${relativePath}`;
|
|
650
|
-
}
|
|
651
|
-
}
|
|
652
|
-
if (wireTarget !== undefined && scope) {
|
|
653
|
-
let wireReport;
|
|
654
|
-
const wireInspection = inspectSymlinkTarget({
|
|
655
|
-
linkPath,
|
|
656
|
-
target: wireTarget,
|
|
657
|
-
scope,
|
|
658
|
-
refuse: true,
|
|
659
|
-
emit: (event) => { wireReport = event; },
|
|
660
|
-
});
|
|
661
|
-
if (wireInspection.refused) {
|
|
662
|
-
const event = wireReport ?? { classification: "escapes-scope", shape: "relative-path" };
|
|
663
|
-
process.stderr.write(`hq-cloud symlink target ${event.classification} ${event.shape}\n`);
|
|
664
|
-
return { target: "", refused: true, ...event };
|
|
665
|
-
}
|
|
666
|
-
if (materializedTargetMatchesWire(absolutePath, localTarget, wireTarget)) {
|
|
667
|
-
return { target: wireTarget, refused: false };
|
|
668
|
-
}
|
|
669
|
-
}
|
|
670
|
-
let candidate = localTarget;
|
|
671
|
-
if (path.isAbsolute(localTarget) || path.win32.isAbsolute(localTarget)) {
|
|
672
|
-
if (!scope || !scopeRoot) {
|
|
673
|
-
const event = { classification: "windows-absolute", shape: "absolute-rooted" };
|
|
674
|
-
process.stderr.write(`hq-cloud symlink target ${event.classification} ${event.shape}\n`);
|
|
675
|
-
return { target: "", refused: true, ...event };
|
|
676
|
-
}
|
|
677
|
-
const absoluteTarget = pathApi.resolve(localTarget);
|
|
678
|
-
if (scope?.kind === "company" &&
|
|
679
|
-
relativePath === "knowledge" &&
|
|
680
|
-
absoluteTarget === pathApi.resolve(scopeRoot, `../../repos/private/knowledge-${scope.companySlug}`)) {
|
|
681
|
-
return { target: `../../repos/private/knowledge-${scope.companySlug}`, refused: false };
|
|
682
|
-
}
|
|
683
|
-
const relativeToScope = pathApi.relative(scopeRoot, absoluteTarget);
|
|
684
|
-
if (relativeToScope === ".." || relativeToScope.startsWith(`..${pathApi.sep}`) || pathApi.isAbsolute(relativeToScope)) {
|
|
685
|
-
const event = { classification: "escapes-scope", shape: "absolute-outside-scope" };
|
|
686
|
-
process.stderr.write(`hq-cloud symlink target ${event.classification} ${event.shape}\n`);
|
|
687
|
-
return { target: "", refused: true, ...event };
|
|
688
|
-
}
|
|
689
|
-
candidate = pathApi.relative(pathApi.dirname(absolutePath), absoluteTarget).replaceAll("\\", "/");
|
|
690
|
-
}
|
|
691
|
-
else if (process.platform === "win32") {
|
|
692
|
-
// fs.readlink on Windows returns native separators for a relative link.
|
|
693
|
-
// The wire target is portable and must keep POSIX separators.
|
|
694
|
-
candidate = normalizeWindowsSymlinkTarget(candidate);
|
|
695
|
-
}
|
|
696
|
-
if (!scope && (path.isAbsolute(candidate) || path.win32.isAbsolute(candidate))) {
|
|
697
|
-
const event = { classification: "escapes-scope", shape: "absolute-outside-scope" };
|
|
698
|
-
process.stderr.write(`hq-cloud symlink target ${event.classification} ${event.shape}\n`);
|
|
699
|
-
return { target: "", refused: true, ...event };
|
|
700
|
-
}
|
|
701
|
-
if (!scope)
|
|
702
|
-
return { target: candidate, refused: false };
|
|
703
|
-
let report;
|
|
704
|
-
const inspection = inspectSymlinkTarget({
|
|
705
|
-
linkPath,
|
|
706
|
-
target: candidate,
|
|
707
|
-
scope,
|
|
708
|
-
refuse: true,
|
|
709
|
-
emit: (event) => { report = event; },
|
|
710
|
-
});
|
|
711
|
-
if (inspection.refused) {
|
|
712
|
-
const event = report ?? { classification: "escapes-scope", shape: "relative-path" };
|
|
713
|
-
process.stderr.write(`hq-cloud symlink target ${event.classification} ${event.shape}\n`);
|
|
714
|
-
return { target: "", refused: true, ...event };
|
|
715
|
-
}
|
|
716
|
-
return { target: candidate, refused: false };
|
|
717
|
-
}
|
|
718
|
-
function normalizeWindowsSymlinkTarget(target) {
|
|
719
|
-
return target.replaceAll("\\", "/");
|
|
720
|
-
}
|
|
721
611
|
/**
|
|
722
612
|
* Build a full-pass plan in bounded row batches. A scoped replan deliberately
|
|
723
613
|
* uses the synchronous single-row planner above, so it does not add an await
|
|
724
614
|
* boundary between upload admissions and collapse the transfer pool.
|
|
725
615
|
*/
|
|
726
|
-
async function computePushPlanCooperatively(filesToShare, journal, skipUnchanged, onHeartbeat, cooperativeCheckpoint, ontologyEntityPush = false
|
|
616
|
+
async function computePushPlanCooperatively(filesToShare, journal, skipUnchanged, onHeartbeat, cooperativeCheckpoint, ontologyEntityPush = false) {
|
|
727
617
|
// Keep each synchronous hash/stat slice small enough that a large backlog
|
|
728
618
|
// cannot starve protocol heartbeats or watcher admission for tens of seconds.
|
|
729
619
|
// This changes only scheduling granularity; plan decisions are unchanged.
|
|
@@ -736,7 +626,7 @@ async function computePushPlanCooperatively(filesToShare, journal, skipUnchanged
|
|
|
736
626
|
const cooperativeWork = { rowsSinceYield: 0, lastYieldAt: 0 };
|
|
737
627
|
for (let start = 0; start < filesToShare.length; start += rowsPerPlanningYield) {
|
|
738
628
|
const slice = filesToShare.slice(start, start + rowsPerPlanningYield);
|
|
739
|
-
const plan = computePushPlan(slice, journal, skipUnchanged, onHeartbeat, ontologyEntityPush
|
|
629
|
+
const plan = computePushPlan(slice, journal, skipUnchanged, onHeartbeat, ontologyEntityPush);
|
|
740
630
|
items.push(...plan.items);
|
|
741
631
|
filesToUpload += plan.filesToUpload;
|
|
742
632
|
bytesToUpload += plan.bytesToUpload;
|
|
@@ -787,11 +677,11 @@ function recollectPushEntry(item, reuseKnownHash = true) {
|
|
|
787
677
|
* classified from the bytes and journal state that exist immediately before a
|
|
788
678
|
* worker starts, so callers never upload with a hash captured near pass entry.
|
|
789
679
|
*/
|
|
790
|
-
function replanPushItemAtExecution(item, journal, skipUnchanged, onHeartbeat, ontologyEntityPush = false, forceRehash = false
|
|
680
|
+
function replanPushItemAtExecution(item, journal, skipUnchanged, onHeartbeat, ontologyEntityPush = false, forceRehash = false) {
|
|
791
681
|
const current = recollectPushEntry(item, !forceRehash);
|
|
792
682
|
if (current === null)
|
|
793
683
|
return null;
|
|
794
|
-
return computePushPlan([current], journal, skipUnchanged, onHeartbeat, ontologyEntityPush
|
|
684
|
+
return computePushPlan([current], journal, skipUnchanged, onHeartbeat, ontologyEntityPush).items[0] ?? null;
|
|
795
685
|
}
|
|
796
686
|
function uploadBodyMatchesPlan(planned, current) {
|
|
797
687
|
if (planned.kind !== current.kind || planned.localHash !== current.localHash) {
|
|
@@ -1242,14 +1132,6 @@ async function createPushRunContext(options) {
|
|
|
1242
1132
|
? wrapFilterWithScope(transferFilter, syncRoot, options.prefixSet, onScopeExcluded)
|
|
1243
1133
|
: transferFilter;
|
|
1244
1134
|
const journalSlug = options.journalSlug ?? ctx.slug;
|
|
1245
|
-
const flagConfig = vaultConfig ?? privateFolderVaultConfig;
|
|
1246
|
-
const symlinkTargetRefusal = flagConfig
|
|
1247
|
-
? await resolveSymlinkTargetRefusalFlag({
|
|
1248
|
-
config: flagConfig,
|
|
1249
|
-
companyUid: ctx.uid,
|
|
1250
|
-
companySlug: ctx.slug,
|
|
1251
|
-
})
|
|
1252
|
-
: false;
|
|
1253
1135
|
if (journalSlug === PERSONAL_VAULT_JOURNAL_SLUG)
|
|
1254
1136
|
migratePersonalVaultJournal();
|
|
1255
1137
|
// The scoped runner has not completed its narrow filesystem walk yet, so
|
|
@@ -1262,7 +1144,6 @@ async function createPushRunContext(options) {
|
|
|
1262
1144
|
ontologyEntityPush: false,
|
|
1263
1145
|
skillRegisterLandedBytes: false,
|
|
1264
1146
|
personalConnectorSettingsSync,
|
|
1265
|
-
symlinkTargetRefusal,
|
|
1266
1147
|
skillRegistrationFallbacks: 0,
|
|
1267
1148
|
paths,
|
|
1268
1149
|
message,
|
|
@@ -1694,11 +1575,7 @@ async function reconcileOnePendingCompanySkill(run, entry) {
|
|
|
1694
1575
|
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "hq-skill-metadata-"));
|
|
1695
1576
|
const tempFile = path.join(tempDir, "SKILL.md");
|
|
1696
1577
|
try {
|
|
1697
|
-
await downloadFile(run.ctx, entry.relativePath, tempFile
|
|
1698
|
-
refuseUnsafeSymlinkTargets: run.symlinkTargetRefusal,
|
|
1699
|
-
symlinkTargetScope: { kind: "company", companySlug: run.ctx.slug },
|
|
1700
|
-
symlinkTargetLinkPath: `companies/${run.ctx.slug}/${entry.relativePath}`,
|
|
1701
|
-
});
|
|
1578
|
+
await downloadFile(run.ctx, entry.relativePath, tempFile);
|
|
1702
1579
|
// The reconciled bytes are the REMOTE object (a peer replaced the one
|
|
1703
1580
|
// this marker described), not the local file, so pass no absolutePath:
|
|
1704
1581
|
// a 409 here is recorded, not forked (see reconcileLandedCompanySkill).
|
|
@@ -2051,7 +1928,7 @@ async function buildSharePlans(run) {
|
|
|
2051
1928
|
if (pushEntries.some((entry) => isOntologyEntityKey(entry.relativePath))) {
|
|
2052
1929
|
run.ontologyEntityPush = await resolveRunOntologyEntityPush(run);
|
|
2053
1930
|
}
|
|
2054
|
-
const pushPlan = await computePushPlanCooperatively(pushEntries, run.journal, run.skipUnchanged === true, run.options.onHeartbeat, run.options.cooperativeCheckpoint, run.ontologyEntityPush
|
|
1931
|
+
const pushPlan = await computePushPlanCooperatively(pushEntries, run.journal, run.skipUnchanged === true, run.options.onHeartbeat, run.options.cooperativeCheckpoint, run.ontologyEntityPush);
|
|
2055
1932
|
const deletePlan = run.propagateDeletes === true
|
|
2056
1933
|
? await computeDeletePlan(run.journal, run.syncRoot, deleteScopeRoots, run.shouldSync, run.propagateDeletePolicy, run.ctx, run.options.personalMode !== true, run.skipSecretPaths)
|
|
2057
1934
|
: { toDelete: [], toTombstone: [], refusedStale: [] };
|
|
@@ -2280,7 +2157,7 @@ async function executeUploads(run, pushPlan, counters, conflictPaths) {
|
|
|
2280
2157
|
for (const previewItem of pushPlan.items) {
|
|
2281
2158
|
if (previewItem.action !== "upload")
|
|
2282
2159
|
continue;
|
|
2283
|
-
const item = replanPushItemAtExecution(previewItem, run.journal, run.skipUnchanged === true, run.options.onHeartbeat, run.ontologyEntityPush
|
|
2160
|
+
const item = replanPushItemAtExecution(previewItem, run.journal, run.skipUnchanged === true, run.options.onHeartbeat, run.ontologyEntityPush);
|
|
2284
2161
|
if (item?.action === "upload" && !isUploadSuppressedByTombstone(item)) {
|
|
2285
2162
|
plannedUploadCandidates.push(item);
|
|
2286
2163
|
}
|
|
@@ -2375,14 +2252,6 @@ async function executeUploads(run, pushPlan, counters, conflictPaths) {
|
|
|
2375
2252
|
emitServerOwnedRefusal(run, item.relativePath);
|
|
2376
2253
|
}
|
|
2377
2254
|
}
|
|
2378
|
-
else if (item.action === "refuse-unsafe-symlink") {
|
|
2379
|
-
run.emit({
|
|
2380
|
-
type: "skip-unsafe-symlink-target",
|
|
2381
|
-
path: item.relativePath,
|
|
2382
|
-
classification: item.classification,
|
|
2383
|
-
shape: item.shape,
|
|
2384
|
-
});
|
|
2385
|
-
}
|
|
2386
2255
|
else if (item.action === "skip-size-limit") {
|
|
2387
2256
|
// A file over the size cap is a permanent, benign skip — NOT an error.
|
|
2388
2257
|
let bytes = 0;
|
|
@@ -2430,7 +2299,7 @@ async function executeUploads(run, pushPlan, counters, conflictPaths) {
|
|
|
2430
2299
|
return;
|
|
2431
2300
|
const { absolutePath, relativePath, localHash } = item;
|
|
2432
2301
|
const refreshUploadItem = () => {
|
|
2433
|
-
const refreshed = replanPushItemAtExecution(item, run.journal, run.skipUnchanged === true, run.options.onHeartbeat, run.ontologyEntityPush, true
|
|
2302
|
+
const refreshed = replanPushItemAtExecution(item, run.journal, run.skipUnchanged === true, run.options.onHeartbeat, run.ontologyEntityPush, true);
|
|
2434
2303
|
if (refreshed === null) {
|
|
2435
2304
|
counters.filesSkipped++;
|
|
2436
2305
|
return null;
|
|
@@ -2645,33 +2514,10 @@ async function executeUploads(run, pushPlan, counters, conflictPaths) {
|
|
|
2645
2514
|
let isFreshCollision = false;
|
|
2646
2515
|
let freshContentConverged = false;
|
|
2647
2516
|
if (!journalEntry && item.kind === "symlink") {
|
|
2648
|
-
const remoteTarget = await readVerifiedRemoteSymlinkTarget(run.ctx, relativePath);
|
|
2649
|
-
const localTarget = fs.readlinkSync(absolutePath);
|
|
2650
|
-
if (remoteTarget !== null && materializedTargetMatchesWire(absolutePath, localTarget, remoteTarget)) {
|
|
2651
|
-
const localStat = fs.lstatSync(absolutePath);
|
|
2652
|
-
updateEntry(run.journal, relativePath, hashSymlinkTarget(localTarget), 0, "down", absolutePath, {
|
|
2653
|
-
remoteEtag: remoteMeta.etag,
|
|
2654
|
-
mtimeMs: localStat.mtimeMs,
|
|
2655
|
-
ctimeMs: localStat.ctimeMs,
|
|
2656
|
-
kind: "symlink",
|
|
2657
|
-
wireSymlinkTarget: remoteTarget,
|
|
2658
|
-
});
|
|
2659
|
-
flushShareJournal(run);
|
|
2660
|
-
counters.filesSkipped++;
|
|
2661
|
-
return;
|
|
2662
|
-
}
|
|
2663
2517
|
isFreshCollision = true;
|
|
2664
2518
|
}
|
|
2665
2519
|
else if (!journalEntry && item.kind === "file") {
|
|
2666
|
-
const remoteDiffers = await remoteContentDiffers(run.ctx, relativePath, localHash, run.hqRoot
|
|
2667
|
-
refuseUnsafeSymlinkTargets: run.symlinkTargetRefusal,
|
|
2668
|
-
symlinkTargetScope: run.options.personalMode === true
|
|
2669
|
-
? { kind: "personal" }
|
|
2670
|
-
: { kind: "company", companySlug: run.ctx.slug },
|
|
2671
|
-
symlinkTargetLinkPath: run.options.personalMode === true
|
|
2672
|
-
? `personal/${relativePath}`
|
|
2673
|
-
: `companies/${run.ctx.slug}/${relativePath}`,
|
|
2674
|
-
});
|
|
2520
|
+
const remoteDiffers = await remoteContentDiffers(run.ctx, relativePath, localHash, run.hqRoot);
|
|
2675
2521
|
if (remoteDiffers) {
|
|
2676
2522
|
isFreshCollision = true;
|
|
2677
2523
|
}
|
|
@@ -2985,7 +2831,6 @@ async function executeUploads(run, pushPlan, counters, conflictPaths) {
|
|
|
2985
2831
|
mtimeMs,
|
|
2986
2832
|
ctimeMs,
|
|
2987
2833
|
kind: item.kind,
|
|
2988
|
-
...(item.kind === "symlink" ? { wireSymlinkTarget: item.target } : {}),
|
|
2989
2834
|
skillMetadataPending: skillContentAtPut !== undefined &&
|
|
2990
2835
|
skillRegistrarForRun(run) !== undefined,
|
|
2991
2836
|
});
|
|
@@ -3308,7 +3153,7 @@ async function executeUploads(run, pushPlan, counters, conflictPaths) {
|
|
|
3308
3153
|
continue;
|
|
3309
3154
|
}
|
|
3310
3155
|
const previewItem = queue[0];
|
|
3311
|
-
const item = replanPushItemAtExecution(previewItem, run.journal, run.skipUnchanged === true, run.options.onHeartbeat, run.ontologyEntityPush
|
|
3156
|
+
const item = replanPushItemAtExecution(previewItem, run.journal, run.skipUnchanged === true, run.options.onHeartbeat, run.ontologyEntityPush);
|
|
3312
3157
|
if (item === null) {
|
|
3313
3158
|
queue.shift();
|
|
3314
3159
|
counters.filesSkipped++;
|
|
@@ -3485,16 +3330,7 @@ async function probeRemoteForWinner(run, item, remoteMtime) {
|
|
|
3485
3330
|
let decision;
|
|
3486
3331
|
try {
|
|
3487
3332
|
fs.mkdirSync(path.dirname(probeAbs), { recursive: true });
|
|
3488
|
-
const downloaded = await downloadFile(run.ctx, item.relativePath, probeAbs, {
|
|
3489
|
-
...(run.options.transferPriority === "realtime" ? { bypassBandwidthGovernor: true } : {}),
|
|
3490
|
-
refuseUnsafeSymlinkTargets: run.symlinkTargetRefusal,
|
|
3491
|
-
symlinkTargetScope: run.options.personalMode === true
|
|
3492
|
-
? { kind: "personal" }
|
|
3493
|
-
: { kind: "company", companySlug: run.ctx.slug },
|
|
3494
|
-
symlinkTargetLinkPath: run.options.personalMode === true
|
|
3495
|
-
? `personal/${item.relativePath}`
|
|
3496
|
-
: `companies/${run.ctx.slug}/${item.relativePath}`,
|
|
3497
|
-
});
|
|
3333
|
+
const downloaded = await downloadFile(run.ctx, item.relativePath, probeAbs, run.options.transferPriority === "realtime" ? { bypassBandwidthGovernor: true } : {});
|
|
3498
3334
|
fetched = { abs: probeAbs, downloaded };
|
|
3499
3335
|
if (item.kind === "file" && !fs.lstatSync(probeAbs).isSymbolicLink()) {
|
|
3500
3336
|
const localStat = fs.lstatSync(item.absolutePath);
|
|
@@ -3615,16 +3451,7 @@ async function adoptRemoteOnPush(run, item, remoteHash, decision, probe) {
|
|
|
3615
3451
|
downloaded = probeBody.downloaded;
|
|
3616
3452
|
}
|
|
3617
3453
|
else {
|
|
3618
|
-
downloaded = await downloadFile(run.ctx, item.relativePath, item.absolutePath, {
|
|
3619
|
-
...(run.options.transferPriority === "realtime" ? { bypassBandwidthGovernor: true } : {}),
|
|
3620
|
-
refuseUnsafeSymlinkTargets: run.symlinkTargetRefusal,
|
|
3621
|
-
symlinkTargetScope: run.options.personalMode === true
|
|
3622
|
-
? { kind: "personal" }
|
|
3623
|
-
: { kind: "company", companySlug: run.ctx.slug },
|
|
3624
|
-
symlinkTargetLinkPath: run.options.personalMode === true
|
|
3625
|
-
? `personal/${item.relativePath}`
|
|
3626
|
-
: `companies/${run.ctx.slug}/${item.relativePath}`,
|
|
3627
|
-
});
|
|
3454
|
+
downloaded = await downloadFile(run.ctx, item.relativePath, item.absolutePath, run.options.transferPriority === "realtime" ? { bypassBandwidthGovernor: true } : {});
|
|
3628
3455
|
}
|
|
3629
3456
|
remoteAdopted = true;
|
|
3630
3457
|
const localLstat = fs.lstatSync(item.absolutePath);
|
|
@@ -3642,9 +3469,6 @@ async function adoptRemoteOnPush(run, item, remoteHash, decision, probe) {
|
|
|
3642
3469
|
ctimeMs: localLstat.ctimeMs,
|
|
3643
3470
|
...(createdBySub !== undefined ? { createdBySub } : {}),
|
|
3644
3471
|
kind: isLocalSymlink ? "symlink" : "file",
|
|
3645
|
-
...(isLocalSymlink && downloaded?.symlinkTarget !== undefined
|
|
3646
|
-
? { wireSymlinkTarget: downloaded.symlinkTarget }
|
|
3647
|
-
: {}),
|
|
3648
3472
|
});
|
|
3649
3473
|
recordPushConflict(run, item, {
|
|
3650
3474
|
detectedAt,
|