@ai-ecoverse/slicc-kernel 1.143.4 → 1.143.6
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/README.md +11 -4
- package/dist/index.js.map +1 -1
- package/dist/kernel-worker.js +193 -26
- package/dist/kernel-worker.js.map +4 -4
- package/dist/meta.js +1 -1
- package/dist/meta.js.map +2 -2
- package/dist/node-process-worker.js +218 -36
- package/dist/node-process-worker.js.map +3 -3
- package/dist/node.js +192 -25
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +218 -36
- package/dist/process-worker.js.map +3 -3
- package/dist/types/fs/changes.d.ts +4 -0
- package/dist/types/fs/meta.d.ts +4 -0
- package/dist/types/fs/opfs.d.ts +10 -0
- package/dist/types/fs/remote.d.ts +4 -0
- package/dist/types/fs/types.d.ts +4 -0
- package/dist/types/kernel/host.d.ts +5 -0
- package/dist/types/kernel/rename-log.d.ts +14 -0
- package/dist/types/kernel/vfs-file.d.ts +1 -0
- package/dist/types/launcher.d.ts +2 -0
- package/dist/types/process/wasi/wasi-fds.d.ts +4 -1
- package/dist/types/process/wasi/wasi-files.d.ts +2 -0
- package/dist/types/process/wasi/wasi-host.d.ts +1 -0
- package/dist/types/realm/live-vfs-fs.d.ts +8 -0
- package/dist/types/realm/sync-fs-token-registry.d.ts +5 -0
- package/dist/types/realm/sync-fs-wire.d.ts +7 -2
- package/package.json +10 -10
package/dist/node.js
CHANGED
|
@@ -3632,7 +3632,8 @@ var SLOT = 2;
|
|
|
3632
3632
|
var SHARED_TTL_MS = 100;
|
|
3633
3633
|
var DIRTY = RING + RING_SIZE * SLOT;
|
|
3634
3634
|
var FOREIGN = DIRTY + 1;
|
|
3635
|
-
var
|
|
3635
|
+
var RENAMES = FOREIGN + 1;
|
|
3636
|
+
var CHANGES_BYTES = (RENAMES + 1) * 4;
|
|
3636
3637
|
function changeHash(path) {
|
|
3637
3638
|
let h = 2166136261;
|
|
3638
3639
|
for (let i = 0; i < path.length; i++) {
|
|
@@ -3666,6 +3667,11 @@ var FileChanges = class {
|
|
|
3666
3667
|
flush() {
|
|
3667
3668
|
Atomics.add(this.view, GEN, RING_SIZE + 1);
|
|
3668
3669
|
}
|
|
3670
|
+
renamed() {
|
|
3671
|
+
const seq2 = Atomics.add(this.view, RENAMES, 1) + 1 | 0;
|
|
3672
|
+
Atomics.notify(this.view, RENAMES);
|
|
3673
|
+
return seq2;
|
|
3674
|
+
}
|
|
3669
3675
|
publish(...paths) {
|
|
3670
3676
|
for (const path of paths) {
|
|
3671
3677
|
const g = Atomics.add(this.view, GEN, 1) + 1 | 0;
|
|
@@ -3690,6 +3696,13 @@ var ChangeView = class {
|
|
|
3690
3696
|
foreign() {
|
|
3691
3697
|
return this.view.length > FOREIGN && Atomics.load(this.view, FOREIGN) === 1;
|
|
3692
3698
|
}
|
|
3699
|
+
renames() {
|
|
3700
|
+
return this.view.length > RENAMES ? Atomics.load(this.view, RENAMES) : 0;
|
|
3701
|
+
}
|
|
3702
|
+
awaitRename(seen, ms) {
|
|
3703
|
+
if (this.view.length > RENAMES) Atomics.wait(this.view, RENAMES, seen, ms);
|
|
3704
|
+
return this.renames();
|
|
3705
|
+
}
|
|
3693
3706
|
changedSince(seen, path) {
|
|
3694
3707
|
const now = Atomics.load(this.view, GEN);
|
|
3695
3708
|
const distance = now - seen >>> 0;
|
|
@@ -4546,7 +4559,7 @@ var STALE = /* @__PURE__ */ new Set(["NotFoundError", "TypeMismatchError"]);
|
|
|
4546
4559
|
var REPLACED_ATTEMPTS = 4;
|
|
4547
4560
|
var RECONCILE_LISTINGS = 8;
|
|
4548
4561
|
var EXECUTABLE = /\/node_modules\/(?:@[^/]+\/)?[^/]+\/bin\//;
|
|
4549
|
-
var
|
|
4562
|
+
var RENAMES2 = "/.slicc-renames";
|
|
4550
4563
|
var RENAME_LOCK = "slicc-rename:";
|
|
4551
4564
|
var RENAME_ADMIT = "slicc-rename-admit:";
|
|
4552
4565
|
var escapeRoot = (name2) => name2.replace(/[%:]/g, (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`);
|
|
@@ -4741,7 +4754,8 @@ var OpfsFs = class {
|
|
|
4741
4754
|
const remote = this.remote;
|
|
4742
4755
|
meta.listen?.((c) => {
|
|
4743
4756
|
for (const path of [...c.paths ?? [], ...c.trees ?? []]) this.forget(path);
|
|
4744
|
-
|
|
4757
|
+
const moved2 = movedOf(c.moved);
|
|
4758
|
+
remote?.emit({ paths: c.paths ?? [], trees: c.trees ?? [], ...moved2 ? { moved: moved2 } : {} });
|
|
4745
4759
|
});
|
|
4746
4760
|
remote?.listen((c) => {
|
|
4747
4761
|
for (const path of [...c.paths, ...c.trees]) this.forget(path);
|
|
@@ -5463,31 +5477,38 @@ var OpfsFs = class {
|
|
|
5463
5477
|
});
|
|
5464
5478
|
}
|
|
5465
5479
|
async pwrite(path, offset, bytes) {
|
|
5466
|
-
const
|
|
5467
|
-
|
|
5468
|
-
|
|
5469
|
-
|
|
5470
|
-
|
|
5471
|
-
|
|
5472
|
-
|
|
5473
|
-
|
|
5480
|
+
const at = normalizePath(path);
|
|
5481
|
+
const movedAway = this.renamesInFlight() ? await this.writeWaits(at) : false;
|
|
5482
|
+
this.fileWrites.set(at, (this.fileWrites.get(at) ?? 0) + 1);
|
|
5483
|
+
try {
|
|
5484
|
+
const [kept, target, existed] = await this.keptFor(path);
|
|
5485
|
+
if (kept) {
|
|
5486
|
+
try {
|
|
5487
|
+
await this.writeAt(kept, target, path, offset, bytes);
|
|
5488
|
+
return;
|
|
5489
|
+
} catch (err) {
|
|
5490
|
+
if (err.code !== "ENOENT") throw err;
|
|
5491
|
+
this.files.delete(target);
|
|
5492
|
+
}
|
|
5474
5493
|
}
|
|
5494
|
+
const [handle] = await this.fileFor(path, !existed && !movedAway);
|
|
5495
|
+
await this.writeAt(handle, target, path, offset, bytes);
|
|
5496
|
+
} finally {
|
|
5497
|
+
this.writeEnded(at);
|
|
5475
5498
|
}
|
|
5476
|
-
const [handle] = await this.fileFor(path);
|
|
5477
|
-
await this.writeAt(handle, target, path, offset, bytes);
|
|
5478
5499
|
}
|
|
5479
5500
|
async keptFor(path) {
|
|
5480
5501
|
const at = normalizePath(path);
|
|
5481
5502
|
const cached = this.files.get(at);
|
|
5482
5503
|
const fresh2 = cached && performance.now() - (this.found.get(cached) ?? -CHECK_MS) < CHECK_MS;
|
|
5483
5504
|
const [target, existed] = fresh2 ? [at, true] : await this.writeTarget(path);
|
|
5484
|
-
if (!existed) return [void 0, target];
|
|
5505
|
+
if (!existed) return [void 0, target, false];
|
|
5485
5506
|
this.refuse(target);
|
|
5486
5507
|
const [entry] = await this.meta.get([target]);
|
|
5487
5508
|
if (entry?.fifo || entry?.socket) throw fsError("ENXIO", path);
|
|
5488
5509
|
const kept = fresh2 ? cached : this.files.get(target);
|
|
5489
5510
|
const usable2 = kept && performance.now() - (this.found.get(kept) ?? -CHECK_MS) < CHECK_MS;
|
|
5490
|
-
return [usable2 ? kept : void 0, target];
|
|
5511
|
+
return [usable2 ? kept : void 0, target, true];
|
|
5491
5512
|
}
|
|
5492
5513
|
async writeAt(handle, target, path, offset, bytes) {
|
|
5493
5514
|
await this.counting(target);
|
|
@@ -5504,7 +5525,67 @@ var OpfsFs = class {
|
|
|
5504
5525
|
}
|
|
5505
5526
|
this.written(target);
|
|
5506
5527
|
}
|
|
5528
|
+
fileWrites = /* @__PURE__ */ new Map();
|
|
5529
|
+
movingFiles = /* @__PURE__ */ new Map();
|
|
5530
|
+
writesIdle;
|
|
5531
|
+
writeBlocked(at) {
|
|
5532
|
+
const file = this.movingFiles.get(at);
|
|
5533
|
+
if (file !== void 0) return { done: file, away: true };
|
|
5534
|
+
for (const m of this.renamingDirs) {
|
|
5535
|
+
if (within3(at, m.from)) return { done: m.done, away: true };
|
|
5536
|
+
if (within3(at, m.to)) return { done: m.done, away: false };
|
|
5537
|
+
}
|
|
5538
|
+
return void 0;
|
|
5539
|
+
}
|
|
5540
|
+
renamesInFlight() {
|
|
5541
|
+
return this.movingFiles.size > 0 || this.renamingDirs.size > 0;
|
|
5542
|
+
}
|
|
5543
|
+
async writeWaits(at) {
|
|
5544
|
+
let away = false;
|
|
5545
|
+
for (let busy = this.writeBlocked(at); busy !== void 0; busy = this.writeBlocked(at)) {
|
|
5546
|
+
away ||= busy.away;
|
|
5547
|
+
await busy.done;
|
|
5548
|
+
}
|
|
5549
|
+
return away;
|
|
5550
|
+
}
|
|
5551
|
+
writeEnded(at) {
|
|
5552
|
+
const left = (this.fileWrites.get(at) ?? 1) - 1;
|
|
5553
|
+
if (left > 0) this.fileWrites.set(at, left);
|
|
5554
|
+
else this.fileWrites.delete(at);
|
|
5555
|
+
const idle2 = this.writesIdle;
|
|
5556
|
+
if (idle2 === void 0) return;
|
|
5557
|
+
this.writesIdle = void 0;
|
|
5558
|
+
idle2.resolve();
|
|
5559
|
+
}
|
|
5560
|
+
async writesDrained(tree2) {
|
|
5561
|
+
while ([...this.fileWrites.keys()].some((at) => within3(at, tree2))) {
|
|
5562
|
+
this.writesIdle ??= Promise.withResolvers();
|
|
5563
|
+
await this.writesIdle.promise;
|
|
5564
|
+
}
|
|
5565
|
+
}
|
|
5566
|
+
async movingFile(path, op) {
|
|
5567
|
+
const { promise, resolve: resolve2 } = Promise.withResolvers();
|
|
5568
|
+
while (this.movingFiles.has(path)) await this.movingFiles.get(path);
|
|
5569
|
+
this.movingFiles.set(path, promise);
|
|
5570
|
+
try {
|
|
5571
|
+
await this.writesDrained(path);
|
|
5572
|
+
return await op();
|
|
5573
|
+
} finally {
|
|
5574
|
+
this.movingFiles.delete(path);
|
|
5575
|
+
resolve2();
|
|
5576
|
+
}
|
|
5577
|
+
}
|
|
5507
5578
|
async truncate(path, size) {
|
|
5579
|
+
const at = normalizePath(path);
|
|
5580
|
+
if (this.renamesInFlight()) await this.writeWaits(at);
|
|
5581
|
+
this.fileWrites.set(at, (this.fileWrites.get(at) ?? 0) + 1);
|
|
5582
|
+
try {
|
|
5583
|
+
await this.truncated(path, size);
|
|
5584
|
+
} finally {
|
|
5585
|
+
this.writeEnded(at);
|
|
5586
|
+
}
|
|
5587
|
+
}
|
|
5588
|
+
async truncated(path, size) {
|
|
5508
5589
|
const handle = await this.existing(path, true);
|
|
5509
5590
|
await this.refuseNode(path, (await this.io(handle.getFile())).size === 0);
|
|
5510
5591
|
const resolve2 = this.ranged || this.remote?.watched();
|
|
@@ -5562,8 +5643,9 @@ var OpfsFs = class {
|
|
|
5562
5643
|
const wanted = entry?.link === void 0 ? path : resolvePath(parentOf4(path), entry.link);
|
|
5563
5644
|
return [resolvePath((await this.locate(parentOf4(wanted), true)).path, baseOf(wanted)), false];
|
|
5564
5645
|
}
|
|
5565
|
-
async fileFor(path) {
|
|
5646
|
+
async fileFor(path, create = true) {
|
|
5566
5647
|
const [target, existed] = await this.writeTarget(path);
|
|
5648
|
+
if (!existed && !create) throw fsError("ENOENT", path);
|
|
5567
5649
|
if (existed) {
|
|
5568
5650
|
const [entry] = await this.meta.get([target]);
|
|
5569
5651
|
if (entry?.fifo || entry?.socket) throw fsError("ENXIO", path);
|
|
@@ -5572,7 +5654,7 @@ var OpfsFs = class {
|
|
|
5572
5654
|
try {
|
|
5573
5655
|
const handle = await this.inDir(
|
|
5574
5656
|
dir,
|
|
5575
|
-
(parent) => this.io(parent.getFileHandle(name2, { create
|
|
5657
|
+
(parent) => this.io(parent.getFileHandle(name2, { create }))
|
|
5576
5658
|
);
|
|
5577
5659
|
if (!existed) this.touch(Date.now(), parentOf4(target));
|
|
5578
5660
|
return [handle, existed, target];
|
|
@@ -5878,11 +5960,12 @@ var OpfsFs = class {
|
|
|
5878
5960
|
this.changed(source.path, destination);
|
|
5879
5961
|
this.touch(Date.now(), parentOf4(source.path), parent.path);
|
|
5880
5962
|
};
|
|
5881
|
-
if (!copying) return place();
|
|
5963
|
+
if (!copying) return sourceStat.isDirectory ? place() : this.movingFile(source.path, place);
|
|
5882
5964
|
const { promise, resolve: resolve2 } = Promise.withResolvers();
|
|
5883
5965
|
const entry = { from: source.path, to: destination, done: promise };
|
|
5884
5966
|
this.renamingDirs.add(entry);
|
|
5885
5967
|
try {
|
|
5968
|
+
await this.writesDrained(source.path);
|
|
5886
5969
|
const locks = this.locks;
|
|
5887
5970
|
if (locks) {
|
|
5888
5971
|
lock = `${this.renameLocks()}${crypto.randomUUID()}`;
|
|
@@ -5985,7 +6068,7 @@ var OpfsFs = class {
|
|
|
5985
6068
|
return name2.startsWith(this.renameLocks()) || LEGACY_RENAME_LOCK.test(name2);
|
|
5986
6069
|
}
|
|
5987
6070
|
async learnRenames() {
|
|
5988
|
-
for (const { rename } of await this.meta.under(
|
|
6071
|
+
for (const { rename } of await this.meta.under(RENAMES2)) {
|
|
5989
6072
|
if (rename?.lock === void 0 || this.ownLocks.has(rename.lock)) continue;
|
|
5990
6073
|
this.notePeer(rename.lock, [rename.from, rename.to]);
|
|
5991
6074
|
}
|
|
@@ -6074,7 +6157,7 @@ var OpfsFs = class {
|
|
|
6074
6157
|
if (!move.done)
|
|
6075
6158
|
await locks.request(move.lock, async () => {
|
|
6076
6159
|
if (move.done) return;
|
|
6077
|
-
const left = (await this.meta.under(
|
|
6160
|
+
const left = (await this.meta.under(RENAMES2)).filter((entry) => entry.rename?.lock === move.lock).sort(byIntent);
|
|
6078
6161
|
for (const entry of left) await this.finishRename(entry);
|
|
6079
6162
|
});
|
|
6080
6163
|
this.peerMoves.delete(move.lock);
|
|
@@ -6153,7 +6236,7 @@ var OpfsFs = class {
|
|
|
6153
6236
|
}
|
|
6154
6237
|
renamingDirs = /* @__PURE__ */ new Set();
|
|
6155
6238
|
intents = 0;
|
|
6156
|
-
async intend(rename, at = `${
|
|
6239
|
+
async intend(rename, at = `${RENAMES2}/${crypto.randomUUID()}`) {
|
|
6157
6240
|
const record2 = { ...rename, at: Date.now() * 1e3 + this.intents++ % 1e3 };
|
|
6158
6241
|
await this.meta.update(at, () => ({ path: at, rename: record2 }));
|
|
6159
6242
|
return at;
|
|
@@ -6189,7 +6272,7 @@ var OpfsFs = class {
|
|
|
6189
6272
|
const { held: h = [], pending = [] } = await locks.query();
|
|
6190
6273
|
for (const lock of [...h, ...pending]) held.add(lock.name);
|
|
6191
6274
|
}
|
|
6192
|
-
const intents = (await this.meta.under(
|
|
6275
|
+
const intents = (await this.meta.under(RENAMES2)).filter(
|
|
6193
6276
|
(entry) => entry.rename !== void 0 && (!orphaned || locks !== void 0 && entry.rename.lock !== void 0 && !held.has(entry.rename.lock))
|
|
6194
6277
|
).sort(
|
|
6195
6278
|
(a, b) => a.rename.at - b.rename.at
|
|
@@ -6241,6 +6324,7 @@ var OpfsFs = class {
|
|
|
6241
6324
|
);
|
|
6242
6325
|
}
|
|
6243
6326
|
await this.meta.update(entry.path, () => void 0);
|
|
6327
|
+
this.remote?.emit({ paths: [], trees: [], moved: { from, to } });
|
|
6244
6328
|
} finally {
|
|
6245
6329
|
this.renamingDirs.delete(barrier);
|
|
6246
6330
|
resolve2();
|
|
@@ -6558,6 +6642,10 @@ var OpfsFs = class {
|
|
|
6558
6642
|
return removed;
|
|
6559
6643
|
}
|
|
6560
6644
|
};
|
|
6645
|
+
function movedOf(moved2) {
|
|
6646
|
+
const m = moved2;
|
|
6647
|
+
return typeof m?.from === "string" && typeof m.to === "string" ? { from: m.from, to: m.to } : void 0;
|
|
6648
|
+
}
|
|
6561
6649
|
function nothing() {
|
|
6562
6650
|
return void 0;
|
|
6563
6651
|
}
|
|
@@ -7982,7 +8070,7 @@ function satisfies(version, range2) {
|
|
|
7982
8070
|
}
|
|
7983
8071
|
|
|
7984
8072
|
// src/version.ts
|
|
7985
|
-
var KERNEL_VERSION = true ? "1.143.
|
|
8073
|
+
var KERNEL_VERSION = true ? "1.143.6" : "0.0.0-dev";
|
|
7986
8074
|
var OS_RELEASE = "6.0.0-slicc";
|
|
7987
8075
|
function procVersion() {
|
|
7988
8076
|
return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
|
|
@@ -13039,7 +13127,8 @@ var SYNC_FS_OPS = [
|
|
|
13039
13127
|
"truncate",
|
|
13040
13128
|
"chown",
|
|
13041
13129
|
"lchown",
|
|
13042
|
-
"access"
|
|
13130
|
+
"access",
|
|
13131
|
+
"renames"
|
|
13043
13132
|
];
|
|
13044
13133
|
var HOLD_READ = 4;
|
|
13045
13134
|
var HOLD_WRITE = 8;
|
|
@@ -13087,6 +13176,30 @@ async function readdirStat(fs, dir, g) {
|
|
|
13087
13176
|
const shown = async (name2, stat) => stat && statJson(await callerStat(g, joinName(dir, name2), stat));
|
|
13088
13177
|
return Promise.all(listed.map(async ([name2, stat]) => [name2, await shown(name2, stat)]));
|
|
13089
13178
|
}
|
|
13179
|
+
async function visibleRenames(entry, req) {
|
|
13180
|
+
const answer2 = entry.renames?.(req.offset ?? 0, heldPaths(req.arg2)) ?? { now: 0, renames: [] };
|
|
13181
|
+
const g = guardOf(entry);
|
|
13182
|
+
if (!g?.dac.enforcing) return answer2;
|
|
13183
|
+
const searchable2 = async (path) => {
|
|
13184
|
+
const dir = path.slice(0, Math.max(1, path.lastIndexOf("/")));
|
|
13185
|
+
const w = await walk(g.fs, g.cred, dir, true, g.links).catch(nothing2);
|
|
13186
|
+
if (w === false || w.denied || w.perm === void 0 || !permits(g.cred, w.perm, X_OK))
|
|
13187
|
+
return false;
|
|
13188
|
+
return g.fs.stat(w.path).then((st) => st.isDirectory, nothing2);
|
|
13189
|
+
};
|
|
13190
|
+
const shown = [];
|
|
13191
|
+
for (const [from, to] of answer2.renames) {
|
|
13192
|
+
if (await searchable2(from) && await searchable2(to)) shown.push([from, to]);
|
|
13193
|
+
}
|
|
13194
|
+
return { now: answer2.now, renames: shown };
|
|
13195
|
+
}
|
|
13196
|
+
function nothing2() {
|
|
13197
|
+
return false;
|
|
13198
|
+
}
|
|
13199
|
+
function heldPaths(arg) {
|
|
13200
|
+
const held = JSON.parse(arg ?? "[]");
|
|
13201
|
+
return Array.isArray(held) ? held.filter((path) => typeof path === "string") : [];
|
|
13202
|
+
}
|
|
13090
13203
|
async function usageAt(entry, path) {
|
|
13091
13204
|
if (!entry.statfs) return void 0;
|
|
13092
13205
|
const real = await realTarget(entry.fs, path).catch(() => path);
|
|
@@ -13204,7 +13317,8 @@ async function run(entry, path, req) {
|
|
|
13204
13317
|
const to = fs.resolvePath(cwd, req.arg2 ?? "");
|
|
13205
13318
|
await fs.rename(path, to);
|
|
13206
13319
|
entry.renamed?.(path, to);
|
|
13207
|
-
|
|
13320
|
+
const seq2 = entry.renameSeq?.(path, to);
|
|
13321
|
+
return seq2 === void 0 ? done : json2({ seq: seq2 });
|
|
13208
13322
|
}
|
|
13209
13323
|
case "link":
|
|
13210
13324
|
await fs.link(path, fs.resolvePath(cwd, req.arg2 ?? ""), req.mode === 1);
|
|
@@ -13676,6 +13790,7 @@ async function linkFree(fs, path) {
|
|
|
13676
13790
|
}
|
|
13677
13791
|
}
|
|
13678
13792
|
async function dispatchOne(entry, req) {
|
|
13793
|
+
if (req.op === "renames") return json2(await visibleRenames(entry, req));
|
|
13679
13794
|
const result = await dispatchPath(entry, req);
|
|
13680
13795
|
if (result.ok || result.errno !== "ENOENT" || !req.direct || !MISS_OPS.has(req.op) || req.handle !== void 0) {
|
|
13681
13796
|
return result;
|
|
@@ -21717,6 +21832,7 @@ var VfsNodes = class {
|
|
|
21717
21832
|
byId = /* @__PURE__ */ new Map();
|
|
21718
21833
|
keepsOnDisk = false;
|
|
21719
21834
|
changed;
|
|
21835
|
+
movedAway;
|
|
21720
21836
|
dirtied;
|
|
21721
21837
|
fs;
|
|
21722
21838
|
entries;
|
|
@@ -22146,6 +22262,7 @@ function keepingOpen(fs, nodes, changed = () => {
|
|
|
22146
22262
|
await nodes.unlinking(b);
|
|
22147
22263
|
await fs.rename(from, to);
|
|
22148
22264
|
nodes.renamed(a, b);
|
|
22265
|
+
nodes.movedAway?.(a, b);
|
|
22149
22266
|
});
|
|
22150
22267
|
},
|
|
22151
22268
|
writeFile: async (path, content, owner) => {
|
|
@@ -24369,6 +24486,8 @@ function holdingToken(opts, holds2, caller) {
|
|
|
24369
24486
|
noLinks: opts.noLinks,
|
|
24370
24487
|
cwd: opts.cwd,
|
|
24371
24488
|
...opts.statfs ? { statfs: opts.statfs } : {},
|
|
24489
|
+
...opts.renames ? { renames: opts.renames } : {},
|
|
24490
|
+
...opts.renameSeq ? { renameSeq: opts.renameSeq } : {},
|
|
24372
24491
|
hold: (path, on, open, real, handle) => holds2.hold(path, on, open, real, handle),
|
|
24373
24492
|
keptFor: (handle) => holds2.keptFor(handle),
|
|
24374
24493
|
unlinked: (path) => holds2.keptAt(path),
|
|
@@ -25738,6 +25857,43 @@ function replayingHops(inner, heldMs = HELD_MS) {
|
|
|
25738
25857
|
};
|
|
25739
25858
|
}
|
|
25740
25859
|
|
|
25860
|
+
// src/kernel/rename-log.ts
|
|
25861
|
+
var RENAME_LOG_SIZE = 4096;
|
|
25862
|
+
function within9(path, root) {
|
|
25863
|
+
return path === root || path.startsWith(root === "/" ? "/" : `${root}/`);
|
|
25864
|
+
}
|
|
25865
|
+
var RenameLog = class {
|
|
25866
|
+
changes;
|
|
25867
|
+
entries = [];
|
|
25868
|
+
constructor(changes) {
|
|
25869
|
+
this.changes = changes;
|
|
25870
|
+
}
|
|
25871
|
+
add(from, to) {
|
|
25872
|
+
const seq2 = this.changes.renamed();
|
|
25873
|
+
this.entries.push({ seq: seq2, from, to });
|
|
25874
|
+
if (this.entries.length > RENAME_LOG_SIZE) this.entries.shift();
|
|
25875
|
+
return seq2;
|
|
25876
|
+
}
|
|
25877
|
+
seqOf(from, to) {
|
|
25878
|
+
for (let i = this.entries.length - 1; i >= 0; i--) {
|
|
25879
|
+
const entry = this.entries[i];
|
|
25880
|
+
if (entry.from === from && entry.to === to) return entry.seq;
|
|
25881
|
+
}
|
|
25882
|
+
return void 0;
|
|
25883
|
+
}
|
|
25884
|
+
since(seen, held) {
|
|
25885
|
+
const now = this.entries.at(-1)?.seq ?? seen;
|
|
25886
|
+
const renames = [];
|
|
25887
|
+
let paths = [...held];
|
|
25888
|
+
for (const { seq: seq2, from, to } of this.entries) {
|
|
25889
|
+
if (seq2 <= seen || !paths.some((path) => within9(path, from))) continue;
|
|
25890
|
+
renames.push([from, to]);
|
|
25891
|
+
paths = paths.map((path) => within9(path, from) ? to + path.slice(from.length) : path);
|
|
25892
|
+
}
|
|
25893
|
+
return { now, renames };
|
|
25894
|
+
}
|
|
25895
|
+
};
|
|
25896
|
+
|
|
25741
25897
|
// src/kernel/net/sealed-scrubs.ts
|
|
25742
25898
|
function addTo(tree2, host, secrets) {
|
|
25743
25899
|
const entry = tree2.get(host) ?? { secrets: [], version: 0, scrubber: void 0 };
|
|
@@ -28563,6 +28719,7 @@ var Launcher = class {
|
|
|
28563
28719
|
hostname;
|
|
28564
28720
|
watchers = new FsWatchers();
|
|
28565
28721
|
changes = new FileChanges();
|
|
28722
|
+
renameLog = new RenameLog(this.changes);
|
|
28566
28723
|
cwds = new CwdTable(async (path) => {
|
|
28567
28724
|
const { dev, ino } = await this.base.stat(path);
|
|
28568
28725
|
return `${dev ?? 0}:${ino}`;
|
|
@@ -28701,6 +28858,7 @@ var Launcher = class {
|
|
|
28701
28858
|
this.openFiles.add(this.nodes);
|
|
28702
28859
|
options.fs.onPeer?.(() => this.flushOpen());
|
|
28703
28860
|
options.fs.remoteChanges?.((change) => {
|
|
28861
|
+
if (change.moved) this.moved(change.moved.from, change.moved.to);
|
|
28704
28862
|
this.changes.flush();
|
|
28705
28863
|
this.cwds.touched(change.paths, change.trees);
|
|
28706
28864
|
this.rewritten(change.paths, change.trees);
|
|
@@ -29717,6 +29875,8 @@ var Launcher = class {
|
|
|
29717
29875
|
unlinkGate: stack.unlinked.gate,
|
|
29718
29876
|
replacements: stack.unlinked,
|
|
29719
29877
|
statfs: (path) => this.mounts.statfs(path),
|
|
29878
|
+
renames: (since2, held) => this.renameLog.since(since2, held),
|
|
29879
|
+
renameSeq: (from, to) => this.renameLog.seqOf(from, to),
|
|
29720
29880
|
mounts: () => this.mounts.list(),
|
|
29721
29881
|
mount: (call, signal) => this.processMount(pid, call, signal),
|
|
29722
29882
|
umount: (target, flags2) => this.processUmount(pid, target, flags2),
|
|
@@ -30664,8 +30824,15 @@ var Launcher = class {
|
|
|
30664
30824
|
const target = command && (command.shows ?? command.script ?? command.wasm);
|
|
30665
30825
|
return target === void 0 ? void 0 : { path: target, ...owner ? { owner } : {} };
|
|
30666
30826
|
}
|
|
30827
|
+
moved(from, to, source) {
|
|
30828
|
+
this.renameLog.add(from, to);
|
|
30829
|
+
if (source) return;
|
|
30830
|
+
for (const nodes of this.openFiles) nodes.renamed(from, to);
|
|
30831
|
+
this.watchers.moved(from, to);
|
|
30832
|
+
}
|
|
30667
30833
|
processChain(fs, nodes, unlinked) {
|
|
30668
30834
|
nodes.changed = (path) => this.changes.publish(path);
|
|
30835
|
+
nodes.movedAway = (from, to) => this.moved(from, to, nodes);
|
|
30669
30836
|
nodes.dirtied = (delta) => this.changes.dirtied(delta);
|
|
30670
30837
|
return unlinked.wrap(keepingOpen(fs, nodes, (path) => this.changes.publish(path)));
|
|
30671
30838
|
}
|