@openclaw/fs-safe 0.13.0 → 0.14.0
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/CHANGELOG.md +26 -1
- package/dist/copy-file-input.d.ts +1 -1
- package/dist/copy-file-input.d.ts.map +1 -1
- package/dist/copy-file-input.js +2 -0
- package/dist/file-store-sync-directory.d.ts.map +1 -1
- package/dist/file-store-sync-directory.js +14 -7
- package/dist/guest-dispatch-python.js +1 -1
- package/dist/native-binding.d.ts +9 -0
- package/dist/native-binding.d.ts.map +1 -1
- package/dist/native-binding.js +8 -1
- package/dist/native-operations.d.ts.map +1 -1
- package/dist/native-operations.js +6 -4
- package/dist/native-parent-admission.d.ts +1 -0
- package/dist/native-parent-admission.d.ts.map +1 -1
- package/dist/native-parent-admission.js +6 -3
- package/dist/native-pinned-write-windows.d.ts.map +1 -1
- package/dist/native-pinned-write-windows.js +8 -6
- package/dist/native-pinned-write.d.ts.map +1 -1
- package/dist/native-pinned-write.js +200 -163
- package/dist/native-policy-directory-observation.d.ts +12 -0
- package/dist/native-policy-directory-observation.d.ts.map +1 -0
- package/dist/native-policy-directory-observation.js +61 -0
- package/dist/native-staged-file.d.ts +4 -4
- package/dist/native-staged-file.d.ts.map +1 -1
- package/dist/native-staged-file.js +20 -10
- package/dist/native.d.ts +1 -1
- package/dist/native.d.ts.map +1 -1
- package/dist/native.js +7 -2
- package/dist/pinned-mutation-admission.d.ts.map +1 -1
- package/dist/pinned-mutation-admission.js +13 -24
- package/dist/pinned-mutation-observation.d.ts +7 -1
- package/dist/pinned-mutation-observation.d.ts.map +1 -1
- package/dist/pinned-mutation-observation.js +87 -5
- package/dist/publish-file.d.ts.map +1 -1
- package/dist/publish-file.js +5 -3
- package/dist/root-directory-creation.d.ts.map +1 -1
- package/dist/root-directory-creation.js +5 -4
- package/dist/root-impl.d.ts.map +1 -1
- package/dist/root-impl.js +2 -1
- package/dist/root-path-existing.d.ts.map +1 -1
- package/dist/root-path-existing.js +1 -2
- package/dist/root-write-compatibility.d.ts +1 -2
- package/dist/root-write-compatibility.d.ts.map +1 -1
- package/dist/root-write-compatibility.js +17 -68
- package/dist/root-write-complete-parent.d.ts.map +1 -1
- package/dist/root-write-complete-parent.js +3 -1
- package/dist/root-write-lock-binding.d.ts +15 -0
- package/dist/root-write-lock-binding.d.ts.map +1 -0
- package/dist/root-write-lock-binding.js +162 -0
- package/dist/staged-directory.d.ts +5 -2
- package/dist/staged-directory.d.ts.map +1 -1
- package/dist/staged-directory.js +37 -1
- package/dist/temp-workspace-admission.d.ts.map +1 -1
- package/dist/temp-workspace-admission.js +28 -4
- package/docs/guest.md +1 -1
- package/docs/native-helper.md +14 -1
- package/docs/native.md +8 -0
- package/docs/writing.md +6 -0
- package/package.json +8 -8
|
@@ -57,12 +57,14 @@ import fs from "node:fs";
|
|
|
57
57
|
import path from "node:path";
|
|
58
58
|
import { FsSafeError } from "./errors.js";
|
|
59
59
|
import { MutationAuthorityError } from "./mutation-authority.js";
|
|
60
|
+
import { captureNativeFdClose } from "./native-binding.js";
|
|
60
61
|
import { writeNativeInput } from "./native-operations.js";
|
|
61
62
|
import { assertNativeCopyCompleted, createNativeCopyFile } from "./copy-file-input.js";
|
|
62
63
|
import { assertStagedDirectoryCurrent, openStagedDirectory } from "./staged-directory.js";
|
|
63
64
|
import { assertFinalSymlinkRejected } from "./root-symlink-policy.js";
|
|
64
65
|
export function assertNativeStaging(binding) {
|
|
65
66
|
if ([
|
|
67
|
+
binding.closeOwnedFd,
|
|
66
68
|
binding.createStagedFile,
|
|
67
69
|
binding.stagedFileMatches,
|
|
68
70
|
binding.removeStagedFile,
|
|
@@ -92,7 +94,9 @@ function failure(error, details) {
|
|
|
92
94
|
}
|
|
93
95
|
class NativeStagedFile {
|
|
94
96
|
#binding;
|
|
97
|
+
#closeFd;
|
|
95
98
|
#parentFd;
|
|
99
|
+
#closeParentFd;
|
|
96
100
|
#directory;
|
|
97
101
|
#portableNames;
|
|
98
102
|
#publishedMode;
|
|
@@ -102,26 +106,29 @@ class NativeStagedFile {
|
|
|
102
106
|
#state = { status: "open", publication: NOT_PUBLISHED };
|
|
103
107
|
#receipt;
|
|
104
108
|
#rejectFinalSymlink = false;
|
|
105
|
-
constructor(binding, parentFd, directory, portableNames, publishedMode, sync, assertBeforeMutation) {
|
|
109
|
+
constructor(binding, parentFd, closeParentFd, directory, portableNames, publishedMode, sync, assertBeforeMutation) {
|
|
110
|
+
this.#closeFd = captureNativeFdClose(binding);
|
|
106
111
|
this.#binding = binding;
|
|
107
112
|
this.#parentFd = parentFd;
|
|
113
|
+
this.#closeParentFd = closeParentFd;
|
|
108
114
|
this.#directory = directory;
|
|
109
115
|
this.#portableNames = portableNames;
|
|
110
116
|
this.#publishedMode = publishedMode;
|
|
111
117
|
this.#sync = sync;
|
|
112
118
|
this.#assertBeforeMutation = assertBeforeMutation;
|
|
113
119
|
}
|
|
114
|
-
//
|
|
115
|
-
|
|
120
|
+
// Public staging supplies a Node parent; pinned writes supply a native parent.
|
|
121
|
+
// The supplied closer owns parentFd even on construction or preparation failure.
|
|
122
|
+
static async create(binding, parentFd, closeParentFd, directory, input, mode, maxBytes,
|
|
116
123
|
// Public staging uses portable names; existing POSIX writes accept literal names.
|
|
117
124
|
portableNames = true, sync = true, assertBeforeMutation) {
|
|
118
125
|
let staged;
|
|
119
126
|
try {
|
|
120
|
-
staged = new NativeStagedFile(binding, parentFd, directory, portableNames, mode, sync, assertBeforeMutation);
|
|
127
|
+
staged = new NativeStagedFile(binding, parentFd, closeParentFd, directory, portableNames, mode, sync, assertBeforeMutation);
|
|
121
128
|
}
|
|
122
129
|
catch (error) {
|
|
123
130
|
try {
|
|
124
|
-
|
|
131
|
+
closeParentFd(parentFd);
|
|
125
132
|
}
|
|
126
133
|
catch (closeError) {
|
|
127
134
|
throw new AggregateError([error, closeError], "staged owner construction and close failed");
|
|
@@ -131,12 +138,12 @@ class NativeStagedFile {
|
|
|
131
138
|
await staged.#prepare(input, maxBytes);
|
|
132
139
|
return staged;
|
|
133
140
|
}
|
|
134
|
-
static async write(binding, parentFd, directory, params, parentGuard) {
|
|
141
|
+
static async write(binding, parentFd, closeParentFd, directory, params, parentGuard) {
|
|
135
142
|
const env_1 = { stack: [], error: void 0, hasError: false };
|
|
136
143
|
try {
|
|
137
144
|
// This owner never escapes. Only the internal verifier borrows its fd;
|
|
138
145
|
// public descriptor methods remain await-free and cannot race disposal.
|
|
139
|
-
const staged = __addDisposableResource(env_1, await NativeStagedFile.create(binding, parentFd, directory, params.input, params.mode, params.maxBytes, false, params.sync, params.assertBeforeMutation), true);
|
|
146
|
+
const staged = __addDisposableResource(env_1, await NativeStagedFile.create(binding, parentFd, closeParentFd, directory, params.input, params.mode, params.maxBytes, false, params.sync, params.assertBeforeMutation), true);
|
|
140
147
|
staged.#rejectFinalSymlink = params.rejectFinalSymlink === true;
|
|
141
148
|
if (params.input.kind === "file")
|
|
142
149
|
await params.input.verifySource();
|
|
@@ -336,12 +343,15 @@ class NativeStagedFile {
|
|
|
336
343
|
}
|
|
337
344
|
}
|
|
338
345
|
let resources = "closed";
|
|
339
|
-
for (const fd of [
|
|
346
|
+
for (const [fd, closeFd] of [
|
|
347
|
+
[state.fileFd, this.#closeFd],
|
|
348
|
+
[this.#parentFd, this.#closeParentFd],
|
|
349
|
+
]) {
|
|
340
350
|
if (fd === undefined) {
|
|
341
351
|
continue;
|
|
342
352
|
}
|
|
343
353
|
try {
|
|
344
|
-
|
|
354
|
+
closeFd(fd);
|
|
345
355
|
}
|
|
346
356
|
catch (error) {
|
|
347
357
|
resources = "close-failed";
|
|
@@ -385,5 +395,5 @@ export async function stageFileInDirectory(options) {
|
|
|
385
395
|
const input = { kind: "buffer", data: Buffer.from(options.content) };
|
|
386
396
|
const mode = options.mode ?? 0o600;
|
|
387
397
|
const parent = openStagedDirectory(options.directory);
|
|
388
|
-
return await createNativeStage(binding, parent.fd, parent.receipt, input, mode);
|
|
398
|
+
return await createNativeStage(binding, parent.fd, fs.closeSync, parent.receipt, input, mode);
|
|
389
399
|
}
|
package/dist/native.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type NativeBinding } from "./native-binding.js";
|
|
2
2
|
export type { NativeBinding } from "./native-binding.js";
|
|
3
3
|
export declare function __loadBundledNativeForTest(): NativeBinding;
|
|
4
4
|
export declare function __nativeLoaderDetectorsForTest(): {
|
package/dist/native.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"native.d.ts","sourceRoot":"","sources":["../src/native.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"native.d.ts","sourceRoot":"","sources":["../src/native.ts"],"names":[],"mappings":"AAQA,OAAO,EAAwB,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAG/E,YAAY,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAwKzD,wBAAgB,0BAA0B,IAAI,aAAa,CAE1D;AAED,wBAAgB,8BAA8B,IAAI;IAChD,MAAM,EAAE,OAAO,GAAG,SAAS,CAAC;IAC5B,UAAU,EAAE,OAAO,GAAG,SAAS,CAAC;IAChC,cAAc,EAAE,OAAO,GAAG,SAAS,CAAC;CACrC,CAMA;AAED,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,CAAC,QAAQ,EACzB,IAAI,EAAE,MAAM,EACZ,IAAI,UAAQ,GACX,MAAM,GAAG,SAAS,CAEpB;AAED,wBAAgB,gBAAgB,IAAI,aAAa,GAAG,SAAS,CAoB5D;AAED,wBAAgB,oBAAoB,IAAI,aAAa,CAQpD;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,aAAa,GAAG,IAAI,CAK1E;AAED,wBAAgB,0BAA0B,IAAI,IAAI,CAKjD"}
|
package/dist/native.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { closeSync, openSync, readSync, readdirSync, } from "node:fs";
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
import { FsSafeError } from "./errors.js";
|
|
4
|
+
import { captureNativeFdClose } from "./native-binding.js";
|
|
4
5
|
import { getFsSafeNativeConfig } from "./native-config.js";
|
|
5
6
|
const require = createRequire(import.meta.url);
|
|
6
7
|
let binding;
|
|
@@ -144,7 +145,9 @@ function loadBundledBinding() {
|
|
|
144
145
|
if (!target) {
|
|
145
146
|
throw new Error(`Unsupported OS or architecture: ${process.platform}-${process.arch}`);
|
|
146
147
|
}
|
|
147
|
-
|
|
148
|
+
const loaded = require(nativePackageForTarget(target));
|
|
149
|
+
captureNativeFdClose(loaded);
|
|
150
|
+
return loaded;
|
|
148
151
|
}
|
|
149
152
|
export function __loadBundledNativeForTest() {
|
|
150
153
|
return loadBundledBinding();
|
|
@@ -166,7 +169,9 @@ export function getNativeBinding() {
|
|
|
166
169
|
if (!attempted) {
|
|
167
170
|
attempted = true;
|
|
168
171
|
try {
|
|
169
|
-
|
|
172
|
+
const loaded = loadBinding();
|
|
173
|
+
captureNativeFdClose(loaded);
|
|
174
|
+
binding = loaded;
|
|
170
175
|
}
|
|
171
176
|
catch (error) {
|
|
172
177
|
loadError = error;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pinned-mutation-admission.d.ts","sourceRoot":"","sources":["../src/pinned-mutation-admission.ts"],"names":[],"mappings":"AACA,OAAO,EAA2B,KAAK,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAGvF,OAAO,EAAuB,KAAK,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AACpF,OAAO,KAAK,EAKV,4BAA4B,EAC7B,MAAM,mBAAmB,CAAC;AAQ3B,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAgCtE,MAAM,MAAM,4BAA4B,GAAG,QAAQ,CAAC;IAClD,aAAa,CAAC,EAAE,kBAAkB,CAAC;IACnC,gBAAgB,CAAC,EAAE,qBAAqB,CAAC;CAC1C,CAAC,CAAC;AAEH,wBAAgB,4BAA4B,CAC1C,aAAa,EAAE,kBAAkB,GAAG,SAAS,EAC7C,gBAAgB,EAAE,qBAAqB,GAAG,SAAS,GAClD,4BAA4B,GAAG,SAAS,CAO1C;AAuJD,wBAAsB,mCAAmC,CAAC,MAAM,EAAE;IAChE,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,oBAAoB,CAAC;IACpC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,yBAAyB,EAAE,MAAM,CAAC;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,4BAA4B,GAAG,SAAS,CAAC;IACjD,cAAc,IAAI,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACjD,GAAG,OAAO,CAAC;IACV,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,CAAC,EAAE,4BAA4B,CAAC;CAClD,CAAC,
|
|
1
|
+
{"version":3,"file":"pinned-mutation-admission.d.ts","sourceRoot":"","sources":["../src/pinned-mutation-admission.ts"],"names":[],"mappings":"AACA,OAAO,EAA2B,KAAK,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAGvF,OAAO,EAAuB,KAAK,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AACpF,OAAO,KAAK,EAKV,4BAA4B,EAC7B,MAAM,mBAAmB,CAAC;AAQ3B,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAgCtE,MAAM,MAAM,4BAA4B,GAAG,QAAQ,CAAC;IAClD,aAAa,CAAC,EAAE,kBAAkB,CAAC;IACnC,gBAAgB,CAAC,EAAE,qBAAqB,CAAC;CAC1C,CAAC,CAAC;AAEH,wBAAgB,4BAA4B,CAC1C,aAAa,EAAE,kBAAkB,GAAG,SAAS,EAC7C,gBAAgB,EAAE,qBAAqB,GAAG,SAAS,GAClD,4BAA4B,GAAG,SAAS,CAO1C;AAuJD,wBAAsB,mCAAmC,CAAC,MAAM,EAAE;IAChE,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,oBAAoB,CAAC;IACpC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,yBAAyB,EAAE,MAAM,CAAC;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,4BAA4B,GAAG,SAAS,CAAC;IACjD,cAAc,IAAI,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACjD,GAAG,OAAO,CAAC;IACV,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,CAAC,EAAE,4BAA4B,CAAC;CAClD,CAAC,CA2PD"}
|
|
@@ -7,7 +7,7 @@ import { ordinarySharedAbsoluteInsideRoot, simpleSharedRoute, } from "./pinned-m
|
|
|
7
7
|
import { resolvePathViaExistingAncestor } from "./root-path-existing.js";
|
|
8
8
|
import { outsideWorkspaceError } from "./root-errors.js";
|
|
9
9
|
import { getFsSafeNativeConfig } from "./native-config.js";
|
|
10
|
-
import { advanceMutationObservation, mutationObservationCurrent, observeMutationPath,
|
|
10
|
+
import { advanceMutationObservation, mutationObservationCurrent, observeMutationPath, mutationObservationsCurrent, mutationObservationUsesDirectory, missingMutationSegments, nextMissingMutationPath, } from "./pinned-mutation-observation.js";
|
|
11
11
|
export function snapshotPinnedMutationPolicy(denyMutations, mutationSymlinks) {
|
|
12
12
|
if (denyMutations === undefined && mutationSymlinks === undefined)
|
|
13
13
|
return undefined;
|
|
@@ -92,10 +92,12 @@ function captureEpoch(rootReal, target, policy, session) {
|
|
|
92
92
|
return undefined;
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
|
-
function epochCurrent(epoch) {
|
|
95
|
+
function epochCurrent(epoch, directories) {
|
|
96
96
|
return !process.versions.bun && epoch.mode === epoch.session.nativeMode &&
|
|
97
97
|
getFsSafeNativeConfig().mode === epoch.mode &&
|
|
98
|
-
epoch.observations
|
|
98
|
+
(directories ? mutationObservationsCurrent(epoch.observations, directories) :
|
|
99
|
+
epoch.observations.every(mutationObservationCurrent)) &&
|
|
100
|
+
getFsSafeNativeConfig().mode === epoch.mode;
|
|
99
101
|
}
|
|
100
102
|
function assertCachedNotDenied(target, epoch) {
|
|
101
103
|
if (epoch.paths.some((paths) => paths.some((denied) => isPathInside(denied, target) && isPathInside(target, denied))) ||
|
|
@@ -143,10 +145,8 @@ function advanceAuthorizedDirectory(admittedEpoch, admitted, receipt) {
|
|
|
143
145
|
target,
|
|
144
146
|
observations: Object.freeze(complete),
|
|
145
147
|
});
|
|
146
|
-
if (!
|
|
147
|
-
!
|
|
148
|
-
!mutationObservationUsesDirectory(target, receipt.child) ||
|
|
149
|
-
!epochCurrent(next))
|
|
148
|
+
if (!mutationObservationUsesDirectory(target, receipt.child) ||
|
|
149
|
+
!epochCurrent(next, [receipt.parent, receipt.child]))
|
|
150
150
|
return undefined;
|
|
151
151
|
assertCachedNotDenied(target.path, next);
|
|
152
152
|
assertCachedNotDenied(receipt.child.path, next);
|
|
@@ -232,20 +232,14 @@ export async function preparePinnedWriteMutationAdmission(params) {
|
|
|
232
232
|
if (!reusable || reusable.session !== session ||
|
|
233
233
|
!reusableSharedCreateRequest(request, reusable) ||
|
|
234
234
|
!mutationObservationUsesDirectory(reusable.target, parent) ||
|
|
235
|
-
!epochCurrent(reusable)) {
|
|
235
|
+
!nonzeroDirectoryObservation(parent) || !epochCurrent(reusable, [parent])) {
|
|
236
236
|
disable();
|
|
237
237
|
return undefined;
|
|
238
238
|
}
|
|
239
239
|
assertCachedNotDenied(request.targetPath, reusable);
|
|
240
240
|
assertCachedNotDenied(request.mutationPath, reusable);
|
|
241
|
-
//
|
|
242
|
-
//
|
|
243
|
-
// still match the observation captured by this walk.
|
|
244
|
-
if (!nonzeroDirectoryObservation(parent) ||
|
|
245
|
-
!mutationDirectoryObservationCurrent(parent)) {
|
|
246
|
-
disable();
|
|
247
|
-
return undefined;
|
|
248
|
-
}
|
|
241
|
+
// The epoch check ends with the exact parent fence. The receipt is
|
|
242
|
+
// consumed synchronously before any intervening authority callback.
|
|
249
243
|
sharedPending = Object.freeze({
|
|
250
244
|
epoch: reusable,
|
|
251
245
|
childPath: request.mutationPath,
|
|
@@ -342,19 +336,14 @@ export async function preparePinnedWriteMutationAdmission(params) {
|
|
|
342
336
|
if (!reusable || reusable.session !== pinnedSession ||
|
|
343
337
|
!reusableRequest(request, reusable) ||
|
|
344
338
|
!mutationObservationUsesDirectory(reusable.target, parent) ||
|
|
345
|
-
!epochCurrent(reusable)) {
|
|
339
|
+
!epochCurrent(reusable, [parent])) {
|
|
346
340
|
epoch = undefined;
|
|
347
341
|
return undefined;
|
|
348
342
|
}
|
|
349
343
|
assertCachedNotDenied(request.targetPath, reusable);
|
|
350
344
|
assertCachedNotDenied(request.mutationPath, reusable);
|
|
351
|
-
//
|
|
352
|
-
//
|
|
353
|
-
// spelling, descriptor identity, type, mode, and link count still match.
|
|
354
|
-
if (!mutationDirectoryObservationCurrent(parent)) {
|
|
355
|
-
epoch = undefined;
|
|
356
|
-
return undefined;
|
|
357
|
-
}
|
|
345
|
+
// The epoch check ends at the exact parent pathname, canonical spelling,
|
|
346
|
+
// identity, type, mode and link-count fence, with no intervening await.
|
|
358
347
|
if (request.phase === "parent-create") {
|
|
359
348
|
pending = Object.freeze({
|
|
360
349
|
epoch: reusable,
|
|
@@ -6,6 +6,11 @@ export type MutationIdentity = Readonly<{
|
|
|
6
6
|
nlink: bigint;
|
|
7
7
|
}>;
|
|
8
8
|
declare const checkedDirectoryObservation: unique symbol;
|
|
9
|
+
export type MutationDirectoryCurrent = Readonly<{
|
|
10
|
+
canonicalPath: string;
|
|
11
|
+
identity: MutationIdentity;
|
|
12
|
+
}>;
|
|
13
|
+
export type MutationDirectoryObserver = () => MutationDirectoryCurrent | undefined;
|
|
9
14
|
export type MutationDirectoryObservation = Readonly<{
|
|
10
15
|
path: string;
|
|
11
16
|
canonicalPath: string;
|
|
@@ -24,11 +29,12 @@ export type MutationPathObservation = Readonly<{
|
|
|
24
29
|
}>;
|
|
25
30
|
export declare function missingMutationSegments(observation: MutationPathObservation): number;
|
|
26
31
|
export declare function nextMissingMutationPath(observation: MutationPathObservation): string | undefined;
|
|
27
|
-
export declare function checkedMutationDirectory(pathname: string, canonicalPath: string, stat: BigIntStats): MutationDirectoryObservation;
|
|
32
|
+
export declare function checkedMutationDirectory(pathname: string, canonicalPath: string, stat: Pick<BigIntStats, "dev" | "ino" | "mode" | "nlink">, observeCurrent?: MutationDirectoryObserver): MutationDirectoryObservation;
|
|
28
33
|
export declare function mutationDirectoryObservationCurrent(observation: MutationDirectoryObservation): boolean;
|
|
29
34
|
export declare function mutationObservationUsesDirectory(observation: MutationPathObservation, directory: MutationDirectoryObservation): boolean;
|
|
30
35
|
export declare function observeMutationPath(pathname: string): MutationPathObservation | undefined;
|
|
31
36
|
export declare function mutationObservationCurrent(observation: MutationPathObservation): boolean;
|
|
37
|
+
export declare function mutationObservationsCurrent(observations: readonly MutationPathObservation[], directories: readonly MutationDirectoryObservation[]): boolean;
|
|
32
38
|
export declare function advanceMutationObservation(observation: MutationPathObservation, parent: MutationDirectoryObservation, child: MutationDirectoryObservation): MutationPathObservation | undefined;
|
|
33
39
|
export {};
|
|
34
40
|
//# sourceMappingURL=pinned-mutation-observation.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pinned-mutation-observation.d.ts","sourceRoot":"","sources":["../src/pinned-mutation-observation.ts"],"names":[],"mappings":"AAAA,OAAW,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;AAM/C,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC;IACtC,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf,CAAC,CAAC;AAEH,QAAA,MAAM,2BAA2B,eAAmD,CAAC;
|
|
1
|
+
{"version":3,"file":"pinned-mutation-observation.d.ts","sourceRoot":"","sources":["../src/pinned-mutation-observation.ts"],"names":[],"mappings":"AAAA,OAAW,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;AAM/C,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC;IACtC,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf,CAAC,CAAC;AAEH,QAAA,MAAM,2BAA2B,eAAmD,CAAC;AAGrF,MAAM,MAAM,wBAAwB,GAAG,QAAQ,CAAC;IAC9C,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,gBAAgB,CAAC;CAC5B,CAAC,CAAC;AACH,MAAM,MAAM,yBAAyB,GAAG,MAAM,wBAAwB,GAAG,SAAS,CAAC;AAEnF,MAAM,MAAM,4BAA4B,GAAG,QAAQ,CAAC;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,CAAC,2BAA2B,CAAC,EAAE,IAAI,CAAC;CACrC,CAAC,CAAC;AAEH,MAAM,MAAM,uBAAuB,GAAG,QAAQ,CAAC;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,gBAAgB,CAAC;IACxB,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC,CAAC;AA6BH,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,uBAAuB,GAAG,MAAM,CAEpF;AAED,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,uBAAuB,GAAG,MAAM,GAAG,SAAS,CAGhG;AAKD,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC,EACzD,cAAc,CAAC,EAAE,yBAAyB,GACzC,4BAA4B,CAY9B;AAQD,wBAAgB,mCAAmC,CACjD,WAAW,EAAE,4BAA4B,GACxC,OAAO,CAgBT;AAED,wBAAgB,gCAAgC,CAC9C,WAAW,EAAE,uBAAuB,EACpC,SAAS,EAAE,4BAA4B,GACtC,OAAO,CAMT;AAGD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,uBAAuB,GAAG,SAAS,CA0BzF;AAED,wBAAgB,0BAA0B,CAAC,WAAW,EAAE,uBAAuB,GAAG,OAAO,CAaxF;AAKD,wBAAgB,2BAA2B,CACzC,YAAY,EAAE,SAAS,uBAAuB,EAAE,EAChD,WAAW,EAAE,SAAS,4BAA4B,EAAE,GACnD,OAAO,CAiET;AAID,wBAAgB,0BAA0B,CACxC,WAAW,EAAE,uBAAuB,EACpC,MAAM,EAAE,4BAA4B,EACpC,KAAK,EAAE,4BAA4B,GAClC,uBAAuB,GAAG,SAAS,CAiBrC"}
|
|
@@ -4,6 +4,7 @@ import { isNotFoundPathError } from "./path.js";
|
|
|
4
4
|
import { realpathSync } from "./realpath.js";
|
|
5
5
|
import { inspectFileIdentitySync } from "./strict-file-identity.js";
|
|
6
6
|
const checkedDirectoryObservation = Symbol("checked mutation directory observation");
|
|
7
|
+
const directoryObservers = new WeakMap();
|
|
7
8
|
function identity(stat) {
|
|
8
9
|
return Object.freeze({ dev: stat.dev, ino: stat.ino, mode: stat.mode, nlink: stat.nlink });
|
|
9
10
|
}
|
|
@@ -17,8 +18,7 @@ function directoryMode(mode) {
|
|
|
17
18
|
}
|
|
18
19
|
function absent(pathname) {
|
|
19
20
|
try {
|
|
20
|
-
fs.lstatSync(pathname);
|
|
21
|
-
return false;
|
|
21
|
+
return fs.lstatSync(pathname, { throwIfNoEntry: false }) === undefined;
|
|
22
22
|
}
|
|
23
23
|
catch (error) {
|
|
24
24
|
// ENOTDIR is incomplete evidence, not a missing child of a directory.
|
|
@@ -35,16 +35,19 @@ export function nextMissingMutationPath(observation) {
|
|
|
35
35
|
// Callers may construct this only from their just-completed exact pathname and
|
|
36
36
|
// canonical fences. The private brand prevents unverified structural objects
|
|
37
37
|
// from advancing an admission epoch.
|
|
38
|
-
export function checkedMutationDirectory(pathname, canonicalPath, stat) {
|
|
39
|
-
if (!
|
|
38
|
+
export function checkedMutationDirectory(pathname, canonicalPath, stat, observeCurrent) {
|
|
39
|
+
if (!directoryMode(stat.mode)) {
|
|
40
40
|
throw new TypeError("mutation directory evidence must describe a real directory");
|
|
41
41
|
}
|
|
42
|
-
|
|
42
|
+
const observation = Object.freeze({
|
|
43
43
|
path: pathname,
|
|
44
44
|
canonicalPath,
|
|
45
45
|
identity: identity(stat),
|
|
46
46
|
[checkedDirectoryObservation]: true,
|
|
47
47
|
});
|
|
48
|
+
if (observeCurrent)
|
|
49
|
+
directoryObservers.set(observation, observeCurrent);
|
|
50
|
+
return observation;
|
|
48
51
|
}
|
|
49
52
|
function checkedDirectory(observation) {
|
|
50
53
|
return observation[checkedDirectoryObservation] === true &&
|
|
@@ -55,6 +58,12 @@ export function mutationDirectoryObservationCurrent(observation) {
|
|
|
55
58
|
if (!checkedDirectory(observation))
|
|
56
59
|
return false;
|
|
57
60
|
try {
|
|
61
|
+
const observed = directoryObservers.get(observation)?.();
|
|
62
|
+
if (observed) {
|
|
63
|
+
return directoryMode(observed.identity.mode) &&
|
|
64
|
+
sameIdentity(observation.identity, observed.identity) &&
|
|
65
|
+
observed.canonicalPath === observation.canonicalPath;
|
|
66
|
+
}
|
|
58
67
|
const stat = inspectFileIdentitySync(() => fs.lstatSync(observation.path, { bigint: true }));
|
|
59
68
|
return stat.isDirectory() && !stat.isSymbolicLink() &&
|
|
60
69
|
sameIdentity(observation.identity, stat) &&
|
|
@@ -118,6 +127,79 @@ export function mutationObservationCurrent(observation) {
|
|
|
118
127
|
return false;
|
|
119
128
|
}
|
|
120
129
|
}
|
|
130
|
+
// Share only ordinary spelling observations collected in this synchronous
|
|
131
|
+
// phase. Aliases retain their independent raw/canonical binding checks, and no
|
|
132
|
+
// fact escapes this call or crosses an authority callback or mutation.
|
|
133
|
+
export function mutationObservationsCurrent(observations, directories) {
|
|
134
|
+
const groups = new Map();
|
|
135
|
+
const groupFor = (pathname) => {
|
|
136
|
+
let group = groups.get(pathname);
|
|
137
|
+
if (!group) {
|
|
138
|
+
group = { observations: [], directories: [] };
|
|
139
|
+
groups.set(pathname, group);
|
|
140
|
+
}
|
|
141
|
+
return group;
|
|
142
|
+
};
|
|
143
|
+
try {
|
|
144
|
+
for (const observation of observations) {
|
|
145
|
+
if (observation.ancestor !== observation.canonicalAncestor) {
|
|
146
|
+
if (!mutationObservationCurrent(observation))
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
groupFor(observation.ancestor).observations.push(observation);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
for (const directory of directories) {
|
|
154
|
+
if (!checkedDirectory(directory))
|
|
155
|
+
return false;
|
|
156
|
+
groupFor(directory.path).directories.push(directory);
|
|
157
|
+
}
|
|
158
|
+
const current = (pathname, group) => {
|
|
159
|
+
const missing = new Set(group.observations.flatMap((observation) => {
|
|
160
|
+
const next = nextMissingMutationPath(observation);
|
|
161
|
+
return next === undefined ? [] : [next];
|
|
162
|
+
}));
|
|
163
|
+
// Exact directory roles are the end fence. Observe missing children
|
|
164
|
+
// before refreshing that parent, matching the ordered admission fence.
|
|
165
|
+
if (group.directories.length && ![...missing].every(absent))
|
|
166
|
+
return false;
|
|
167
|
+
const observed = group.directories.length
|
|
168
|
+
? directoryObservers.get(group.directories[0])?.() : undefined;
|
|
169
|
+
const stat = observed?.identity ??
|
|
170
|
+
inspectFileIdentitySync(() => fs.lstatSync(pathname, { bigint: true }));
|
|
171
|
+
const canonical = observed?.canonicalPath ?? realpathSync.native(pathname);
|
|
172
|
+
const isDirectory = directoryMode(stat.mode);
|
|
173
|
+
if (!group.observations.every((observation) => canonical === observation.canonicalAncestor &&
|
|
174
|
+
sameIdentity(observation.entry, stat, isDirectory) &&
|
|
175
|
+
sameIdentity(observation.identity, stat, isDirectory) &&
|
|
176
|
+
(missingMutationSegments(observation) === 0 || isDirectory)))
|
|
177
|
+
return false;
|
|
178
|
+
if (!group.directories.every((directory) => isDirectory &&
|
|
179
|
+
sameIdentity(directory.identity, stat) && canonical === directory.canonicalPath))
|
|
180
|
+
return false;
|
|
181
|
+
return group.directories.length > 0 || [...missing].every(absent);
|
|
182
|
+
};
|
|
183
|
+
for (const [pathname, group] of groups) {
|
|
184
|
+
if (!group.directories.length && !current(pathname, group))
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
// Preserve the supplied parent/child order, even when a directory also
|
|
188
|
+
// appeared earlier as the Root or a denied path's nearest ancestor.
|
|
189
|
+
const checked = new Set();
|
|
190
|
+
for (const directory of directories) {
|
|
191
|
+
if (checked.has(directory.path))
|
|
192
|
+
continue;
|
|
193
|
+
if (!current(directory.path, groups.get(directory.path)))
|
|
194
|
+
return false;
|
|
195
|
+
checked.add(directory.path);
|
|
196
|
+
}
|
|
197
|
+
return true;
|
|
198
|
+
}
|
|
199
|
+
catch {
|
|
200
|
+
return false;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
121
203
|
// This is deliberately a pure tentative update. The immediately following
|
|
122
204
|
// parent authorization validates the complete epoch once before reusing it.
|
|
123
205
|
export function advanceMutationObservation(observation, parent, child) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"publish-file.d.ts","sourceRoot":"","sources":["../src/publish-file.ts"],"names":[],"mappings":"AACA,OAAe,EAAoB,KAAK,KAAK,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"publish-file.d.ts","sourceRoot":"","sources":["../src/publish-file.ts"],"names":[],"mappings":"AACA,OAAe,EAAoB,KAAK,KAAK,EAAE,MAAM,SAAS,CAAC;AAG/D,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EAC1B,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,oBAAoB,CAAC;AAK5B,OAAO,EAML,KAAK,qCAAqC,EAC3C,MAAM,2BAA2B,CAAC;AAKnC,YAAY,EACV,2BAA2B,EAC3B,wCAAwC,EACxC,kCAAkC,EAClC,gCAAgC,EAChC,qCAAqC,GACtC,MAAM,2BAA2B,CAAC;AAEnC,MAAM,MAAM,4BAA4B,GAAG,cAAc,GAAG,eAAe,GAAG,kBAAkB,CAAC;AAEjG,MAAM,MAAM,0BAA0B,GAAG;IACvC,MAAM,EAAE,UAAU,GAAG,gBAAgB,GAAG,kBAAkB,CAAC;IAC3D,QAAQ,EAAE,KAAK,CAAC;IAChB,aAAa,EAAE,oBAAoB,CAAC;CACrC,CAAC;AAIF,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAE/D;AA0ND,wBAAsB,oBAAoB,CAAC,MAAM,EAAE;IACjD,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,sBAAsB,CAAC,EAAE,gBAAgB,CAAC;IAC1C,QAAQ,EAAE,4BAA4B,CAAC;IACvC,aAAa,CAAC,EAAE,qCAAqC,CAAC;IACtD,aAAa,CAAC,EAAE,gBAAgB,CAAC;CAClC,GAAG,OAAO,CAAC,0BAA0B,CAAC,CA6NtC"}
|
package/dist/publish-file.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import fsSync, {} from "node:fs";
|
|
3
|
-
import fs from "node:fs/promises";
|
|
3
|
+
import fs, {} from "node:fs/promises";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { pinDirectory, } from "./directory-durability.js";
|
|
6
6
|
import { FsSafeError } from "./errors.js";
|
|
@@ -8,6 +8,7 @@ import { hashFileHandle } from "./file-hash.js";
|
|
|
8
8
|
import { sameFileIdentity, sameFileIdentityForCleanup, } from "./file-identity.js";
|
|
9
9
|
import { syncFileBestEffortSync } from "./file-sync.js";
|
|
10
10
|
import { getNativeBinding, requireNativeBinding } from "./native.js";
|
|
11
|
+
import { captureNativeFdClose } from "./native-binding.js";
|
|
11
12
|
import { resolveReadOpenFlags } from "./read-open-flags.js";
|
|
12
13
|
import { directorySyncFailure, publicationFailure, rememberCreatedTarget, } from "./publish-file-failure.js";
|
|
13
14
|
import { admitStandalonePublicationPath } from "./standalone-publication-path.js";
|
|
@@ -54,6 +55,7 @@ async function assertPinnedSourceCurrent(params) {
|
|
|
54
55
|
}
|
|
55
56
|
async function copyPinnedSource(params) {
|
|
56
57
|
if (params.native && params.targetNativeParent) {
|
|
58
|
+
const closeFd = captureNativeFdClose(params.native);
|
|
57
59
|
for (const method of ["clone", "copy-file-range"]) {
|
|
58
60
|
let nativeFd;
|
|
59
61
|
try {
|
|
@@ -95,7 +97,7 @@ async function copyPinnedSource(params) {
|
|
|
95
97
|
const hashed = await hashFileHandle(target, params.native);
|
|
96
98
|
const completedFd = nativeFd;
|
|
97
99
|
nativeFd = undefined;
|
|
98
|
-
|
|
100
|
+
closeFd(completedFd);
|
|
99
101
|
return {
|
|
100
102
|
handle: target,
|
|
101
103
|
exactIdentity: opened,
|
|
@@ -109,7 +111,7 @@ async function copyPinnedSource(params) {
|
|
|
109
111
|
}
|
|
110
112
|
finally {
|
|
111
113
|
if (nativeFd !== undefined)
|
|
112
|
-
|
|
114
|
+
closeFd(nativeFd);
|
|
113
115
|
}
|
|
114
116
|
}
|
|
115
117
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"root-directory-creation.d.ts","sourceRoot":"","sources":["../src/root-directory-creation.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,mBAAmB,CAAC;AAEtE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"root-directory-creation.d.ts","sourceRoot":"","sources":["../src/root-directory-creation.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,mBAAmB,CAAC;AAEtE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAuDrD;;;GAGG;AACH,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,WAAW,EACjB,UAAU,EAAE,MAAM,EAClB,iBAAiB,EAAE,4BAA4B,GAC9C,OAAO,CAAC,OAAO,CAAC,CAoGlB;AAED,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,WAAW,EACjB,UAAU,EAAE,MAAM,EAClB,oBAAoB,CAAC,EAAE,MAAM,IAAI,EACjC,iBAAiB,CAAC,EAAE,4BAA4B,GAC/C,OAAO,CAAC,MAAM,CAAC,CA6BjB;AAED,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,WAAW,EACjB,QAAQ,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,EAChD,oBAAoB,CAAC,EAAE,MAAM,IAAI,EACjC,cAAc,UAAQ,EACtB,iBAAiB,CAAC,EAAE,4BAA4B,GAC/C,OAAO,CAAC,IAAI,CAAC,CAyBf"}
|
|
@@ -8,9 +8,10 @@ import { hasNodeErrorCode } from "./path.js";
|
|
|
8
8
|
import { checkedMutationDirectory, } from "./pinned-mutation-observation.js";
|
|
9
9
|
import { admitPathInsideRoot } from "./root-boundary.js";
|
|
10
10
|
import { assertFinalSymlinkRejected } from "./root-symlink-policy.js";
|
|
11
|
+
import { canReuseParentWithMutationAssertion } from "./root-write-lock-binding.js";
|
|
11
12
|
import { getFsSafeTestHooks } from "./test-hooks.js";
|
|
12
|
-
function mutationWalkOptions(mutationAdmission, operationTarget, assertBeforeMutation) {
|
|
13
|
-
const session = assertBeforeMutation
|
|
13
|
+
function mutationWalkOptions(mutationAdmission, operationTarget, assertBeforeMutation, rootPath, targetPath) {
|
|
14
|
+
const session = canReuseParentWithMutationAssertion(assertBeforeMutation, rootPath, targetPath)
|
|
14
15
|
? mutationAdmission.beginSharedParentWalk?.()
|
|
15
16
|
: undefined;
|
|
16
17
|
return {
|
|
@@ -173,7 +174,7 @@ export async function prepareRootWriteTarget(root, targetPath, assertBeforeMutat
|
|
|
173
174
|
assertBeforeMutation,
|
|
174
175
|
};
|
|
175
176
|
const mutationWalk = mutationAdmission
|
|
176
|
-
? mutationWalkOptions(mutationAdmission, (prospectiveParent) => path.join(prospectiveParent, basename), assertBeforeMutation)
|
|
177
|
+
? mutationWalkOptions(mutationAdmission, (prospectiveParent) => path.join(prospectiveParent, basename), assertBeforeMutation, root.rootReal, targetPath)
|
|
177
178
|
: undefined;
|
|
178
179
|
let parentPath;
|
|
179
180
|
try {
|
|
@@ -197,7 +198,7 @@ export async function mkdirPathFallback(root, resolved, assertBeforeMutation, re
|
|
|
197
198
|
beforeComponent: async (componentPath) => await getFsSafeTestHooks()?.beforeRootFallbackMutation?.("mkdir", componentPath),
|
|
198
199
|
};
|
|
199
200
|
const mutationWalk = mutationAdmission
|
|
200
|
-
? mutationWalkOptions(mutationAdmission, (prospectiveDirectory) => prospectiveDirectory, assertBeforeMutation)
|
|
201
|
+
? mutationWalkOptions(mutationAdmission, (prospectiveDirectory) => prospectiveDirectory, assertBeforeMutation, root.rootReal, resolved.resolved)
|
|
201
202
|
: undefined;
|
|
202
203
|
try {
|
|
203
204
|
await mkdirPathComponentsWithGuards(mutationWalk ? {
|
package/dist/root-impl.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"root-impl.d.ts","sourceRoot":"","sources":["../src/root-impl.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAElD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAKnD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAqB7D,OAAO,EAAwB,KAAK,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAU9E,OAAO,EAAiB,KAAK,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAE3E,OAAO,EASL,KAAK,WAAW,EACjB,MAAM,mBAAmB,CAAC;AAW3B,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAY,KAAK,aAAa,EAAE,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"root-impl.d.ts","sourceRoot":"","sources":["../src/root-impl.ts"],"names":[],"mappings":"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"}
|
package/dist/root-impl.js
CHANGED
|
@@ -94,7 +94,8 @@ import { verifyAtomicWriteResult } from "./root-write-verification.js";
|
|
|
94
94
|
import { assertRootWritePathSelectionSync, assertRootWriteSelectionSync, createRootWriteSelectionForFd, prepareGuardedRootWritePathSelection, resolveGuardedWritePathInRoot, resolveGuardedWriteTargetInRoot, resolvePinnedWriteTargetInRoot, refreshRetainedRootWriteAdmission, refreshRootWritePathSelection, retainRootWriteSelection, takeRootWriteSelection, } from "./root-write-admission.js";
|
|
95
95
|
import { prepareSharedRootWriteTarget } from "./root-write-complete-parent.js";
|
|
96
96
|
import { finishRootFallbackWrite } from "./root-write-publication.js";
|
|
97
|
-
import {
|
|
97
|
+
import { withRootFallbackCompatibilityLock } from "./root-write-compatibility.js";
|
|
98
|
+
import { assertRootFallbackWritePath } from "./root-write-lock-binding.js";
|
|
98
99
|
import { inspectFileIdentity, inspectFileIdentitySync } from "./strict-file-identity.js";
|
|
99
100
|
import { movePathNoReplaceNative } from "./root-move-noreplace.js";
|
|
100
101
|
import { admitRootReadHandle, inspectOpenedPathIdentitySync } from "./root-read-admission.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"root-path-existing.d.ts","sourceRoot":"","sources":["../src/root-path-existing.ts"],"names":[],"mappings":"AAWA,OAAO,EAAuB,KAAK,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAEpF,wBAAgB,2BAA2B,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAarE;AAED,wBAAgB,8BAA8B,CAC5C,SAAS,EAAE,MAAM,EACjB,iBAAiB,EAAE,MAAM,EACzB,OAAO,GAAE;IACP,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,YAAY,CAAC,EAAE,oBAAoB,CAAC;CAChC,GACL,MAAM,GAAG,SAAS,CAqDpB;
|
|
1
|
+
{"version":3,"file":"root-path-existing.d.ts","sourceRoot":"","sources":["../src/root-path-existing.ts"],"names":[],"mappings":"AAWA,OAAO,EAAuB,KAAK,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAEpF,wBAAgB,2BAA2B,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAarE;AAED,wBAAgB,8BAA8B,CAC5C,SAAS,EAAE,MAAM,EACjB,iBAAiB,EAAE,MAAM,EACzB,OAAO,GAAE;IACP,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,YAAY,CAAC,EAAE,oBAAoB,CAAC;CAChC,GACL,MAAM,GAAG,SAAS,CAqDpB;AAiBD,wBAAsB,8BAA8B,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAkCxF;AAED,wBAAgB,kCAAkC,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAqC7E"}
|
|
@@ -86,8 +86,7 @@ function isFilesystemRoot(candidate) {
|
|
|
86
86
|
}
|
|
87
87
|
async function pathExists(targetPath) {
|
|
88
88
|
try {
|
|
89
|
-
fs.lstatSync(pathForWindowsFilesystem(targetPath));
|
|
90
|
-
return true;
|
|
89
|
+
return fs.lstatSync(pathForWindowsFilesystem(targetPath), { throwIfNoEntry: false }) !== undefined;
|
|
91
90
|
}
|
|
92
91
|
catch (error) {
|
|
93
92
|
if (isNotFoundPathError(error)) {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare function assertRootFallbackWritePath(expected: string | undefined, actual: string): void;
|
|
1
|
+
import type { RootBoundaryIdentity } from "./root-boundary.js";
|
|
3
2
|
export declare function withRootFallbackCompatibilityLock<T>(params: {
|
|
4
3
|
rootPath: string;
|
|
5
4
|
targetPath: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"root-write-compatibility.d.ts","sourceRoot":"","sources":["../src/root-write-compatibility.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"root-write-compatibility.d.ts","sourceRoot":"","sources":["../src/root-write-compatibility.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAK/D,wBAAsB,iCAAiC,CAAC,CAAC,EACvD,MAAM,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,oBAAoB,CAAC;IAAC,oBAAoB,CAAC,EAAE,MAAM,IAAI,CAAA;CAAE,EACxH,GAAG,EAAE,CAAC,OAAO,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,oBAAoB,EAAE,MAAM,IAAI,CAAA;CAAE,KAAK,OAAO,CAAC,CAAC,CAAC,GAC3G,OAAO,CAAC,CAAC,CAAC,CAkBZ"}
|