@openclaw/fs-safe 0.13.1 → 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 +14 -1
- 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 +6 -0
- package/dist/native-binding.d.ts.map +1 -1
- package/dist/native-pinned-write.d.ts.map +1 -1
- package/dist/native-pinned-write.js +195 -161
- 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/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/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.md +8 -0
- package/docs/writing.md +6 -0
- package/package.json +8 -8
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { FsSafeError } from "./errors.js";
|
|
3
|
+
import { getFsSafeNativeConfig } from "./native-config.js";
|
|
4
|
+
export class NativePolicyDirectoryMismatch extends FsSafeError {
|
|
5
|
+
constructor(cause) {
|
|
6
|
+
super("path-mismatch", "staging directory pathname changed", { cause });
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
/** Fresh name/metadata/canonical facts from a caller-owned POSIX descriptor. */
|
|
10
|
+
export function nativePolicyDirectoryObserver(binding, fd, pathname) {
|
|
11
|
+
if (!binding || process.platform === "win32" || process.versions.bun)
|
|
12
|
+
return undefined;
|
|
13
|
+
const observe = binding.observeDirectoryFd;
|
|
14
|
+
if (typeof observe !== "function")
|
|
15
|
+
return undefined;
|
|
16
|
+
const mode = getFsSafeNativeConfig().mode;
|
|
17
|
+
let disposed = false;
|
|
18
|
+
const inspect = () => {
|
|
19
|
+
if (disposed)
|
|
20
|
+
throw new NativePolicyDirectoryMismatch();
|
|
21
|
+
if (getFsSafeNativeConfig().mode !== mode)
|
|
22
|
+
return undefined;
|
|
23
|
+
let observed;
|
|
24
|
+
try {
|
|
25
|
+
observed = observe.call(binding, fd, pathname);
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
if (error?.code === "OBSERVATION_UNAVAILABLE")
|
|
29
|
+
return undefined;
|
|
30
|
+
if (error?.code === "OBSERVATION_REDIRECTED") {
|
|
31
|
+
// A contained redirect requires ordinary selected-object admission;
|
|
32
|
+
// it has not yet supplied inconsistent descriptor/name evidence.
|
|
33
|
+
throw new FsSafeError("path-mismatch", "staging directory pathname redirected");
|
|
34
|
+
}
|
|
35
|
+
if (error?.code === "path-mismatch") {
|
|
36
|
+
throw new NativePolicyDirectoryMismatch(error instanceof Error ? error : undefined);
|
|
37
|
+
}
|
|
38
|
+
throw error;
|
|
39
|
+
}
|
|
40
|
+
if (getFsSafeNativeConfig().mode !== mode)
|
|
41
|
+
return undefined;
|
|
42
|
+
if (!observed || typeof observed.dev !== "bigint" || observed.dev < 0n || observed.dev > 0xffffffffffffffffn ||
|
|
43
|
+
typeof observed.ino !== "bigint" || observed.ino < 0n || observed.ino > 0xffffffffffffffffn ||
|
|
44
|
+
typeof observed.mode !== "bigint" || observed.mode < 0n || observed.mode > 0xffffffffn ||
|
|
45
|
+
typeof observed.nlink !== "bigint" || observed.nlink < 0n || observed.nlink > 0xffffffffffffffffn ||
|
|
46
|
+
typeof observed.realPath !== "string" || observed.realPath.includes("\0") ||
|
|
47
|
+
!path.isAbsolute(observed.realPath))
|
|
48
|
+
return undefined;
|
|
49
|
+
if ((observed.mode & 61440n) !== 16384n || observed.nlink === 0n ||
|
|
50
|
+
observed.realPath !== pathname) {
|
|
51
|
+
throw new NativePolicyDirectoryMismatch();
|
|
52
|
+
}
|
|
53
|
+
return Object.freeze({
|
|
54
|
+
canonicalPath: observed.realPath,
|
|
55
|
+
identity: Object.freeze({
|
|
56
|
+
dev: observed.dev, ino: observed.ino, mode: observed.mode, nlink: observed.nlink,
|
|
57
|
+
}),
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
return Object.assign(inspect, { dispose() { disposed = true; } });
|
|
61
|
+
}
|
|
@@ -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":"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"}
|
|
@@ -1,74 +1,23 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import { FsSafeError } from "./errors.js";
|
|
4
|
-
import { isNotFoundPathError } from "./path.js";
|
|
5
|
-
import { admitPathInsideRoot } from "./root-boundary.js";
|
|
6
1
|
import { withPinnedWriteRenameIdentityLock } from "./pinned-write.js";
|
|
7
|
-
import {
|
|
2
|
+
import { createRootWriteLockBinding } from "./root-write-lock-binding.js";
|
|
8
3
|
import { serializePathWrite } from "./write-queue.js";
|
|
9
|
-
function
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
//
|
|
16
|
-
function effectiveDestination(rootPath, targetPath, rootIdentity) {
|
|
17
|
-
let effective;
|
|
4
|
+
export async function withRootFallbackCompatibilityLock(params, run) {
|
|
5
|
+
const binding = createRootWriteLockBinding(params);
|
|
6
|
+
const callerAssertion = params.assertBeforeMutation;
|
|
7
|
+
const assertBeforeMutation = callerAssertion === undefined
|
|
8
|
+
? binding.assertCurrent
|
|
9
|
+
: () => { callerAssertion.call(params); binding.assertCurrent(); };
|
|
10
|
+
// Keep the alias queue and historical lock hash before admitting the writer.
|
|
18
11
|
try {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
for (;;) {
|
|
27
|
-
try {
|
|
28
|
-
fs.lstatSync(cursor);
|
|
29
|
-
break;
|
|
30
|
-
}
|
|
31
|
-
catch (error) {
|
|
32
|
-
if (!isNotFoundPathError(error) || cursor === rootPath)
|
|
33
|
-
throw error;
|
|
34
|
-
const parent = path.dirname(cursor);
|
|
35
|
-
if (parent === cursor)
|
|
36
|
-
throw error;
|
|
37
|
-
missing.unshift(path.basename(cursor));
|
|
38
|
-
cursor = parent;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
// An existing dangling link must fail resolution, not become a missing
|
|
42
|
-
// lexical component. Keep the fallback bounded by the retained Root.
|
|
43
|
-
effective = path.join(realpathSync.native(cursor), ...missing);
|
|
12
|
+
return await serializePathWrite(binding.targetPath, async () => await withPinnedWriteRenameIdentityLock({
|
|
13
|
+
rootPath: params.rootPath, targetPath: binding.targetPath, relativeTargetPath: binding.relativeLockPath,
|
|
14
|
+
}, async () => await run({
|
|
15
|
+
targetPath: binding.targetPath,
|
|
16
|
+
relativePath: binding.relativePath,
|
|
17
|
+
assertBeforeMutation,
|
|
18
|
+
})));
|
|
44
19
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
throw unsupportedSpelling();
|
|
48
|
-
const relative = admitted.relativePath;
|
|
49
|
-
if (!relative || !relative.split(path.sep).every(component => /^[a-z0-9._-]+$/.test(component) && !component.endsWith(".")))
|
|
50
|
-
throw unsupportedSpelling();
|
|
51
|
-
return admitted.path;
|
|
52
|
-
}
|
|
53
|
-
export function assertRootFallbackWritePath(expected, actual) {
|
|
54
|
-
if (expected !== undefined && actual !== expected) {
|
|
55
|
-
throw new FsSafeError("path-mismatch", "compatibility write destination changed after lock selection");
|
|
20
|
+
finally {
|
|
21
|
+
binding.dispose();
|
|
56
22
|
}
|
|
57
23
|
}
|
|
58
|
-
export async function withRootFallbackCompatibilityLock(params, run) {
|
|
59
|
-
const targetPath = effectiveDestination(params.rootPath, params.targetPath, params.rootIdentity);
|
|
60
|
-
const relativePath = path.relative(params.rootPath, targetPath).split(path.sep).join("/");
|
|
61
|
-
const assertCurrent = () => assertRootFallbackWritePath(targetPath, effectiveDestination(params.rootPath, targetPath, params.rootIdentity));
|
|
62
|
-
// Sidecars are reentrant within one manager; aliases also need the same local
|
|
63
|
-
// queue before acquisition. The outer Root queue uses the caller's spelling.
|
|
64
|
-
return await serializePathWrite(targetPath, async () => await withPinnedWriteRenameIdentityLock({
|
|
65
|
-
rootPath: params.rootPath, targetPath, relativeTargetPath: relativePath,
|
|
66
|
-
}, async () => {
|
|
67
|
-
// The guarded open resolves again under the lock; each mutation rechecks
|
|
68
|
-
// below. Lock selection is never reused as post-lock filesystem authority.
|
|
69
|
-
return await run({
|
|
70
|
-
targetPath, relativePath,
|
|
71
|
-
assertBeforeMutation: () => { params.assertBeforeMutation?.(); assertCurrent(); },
|
|
72
|
-
});
|
|
73
|
-
}));
|
|
74
|
-
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"root-write-complete-parent.d.ts","sourceRoot":"","sources":["../src/root-write-complete-parent.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE3C,OAAO,EAIL,KAAK,mBAAmB,EACzB,MAAM,sBAAsB,CAAC;AAO9B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"root-write-complete-parent.d.ts","sourceRoot":"","sources":["../src/root-write-complete-parent.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE3C,OAAO,EAIL,KAAK,mBAAmB,EACzB,MAAM,sBAAsB,CAAC;AAO9B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AAMxE,KAAK,8BAA8B,GAAG,QAAQ,CAC1C;IAAE,MAAM,EAAE,KAAK,CAAA;CAAE,GACjB;IAAE,MAAM,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,WAAW,CAAA;CAAE,CACtC,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,uBAAuB,GAAG,QAAQ,CAAC;IAC7C,mBAAmB,EAAE,MAAM,CAAC;IAC5B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,WAAW,EAAE,mBAAmB,CAAC,WAAW,CAAC,CAAC;IAC9C,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,QAAQ,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACrD,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,8BAA8B,CAAC;CACxC,CAAC,CAAC;AAEH,KAAK,2BAA2B,GAAG,QAAQ,CAAC;IAC1C,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,sBAAsB,CAAC;IACtC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,oBAAoB,CAAC,EAAE,MAAM,IAAI,CAAC;CACnC,CAAC,CAAC;AAEH,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC;IAC3C,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,sBAAsB,CAAC,mBAAmB,CAAC,CAAC;IAC/D,cAAc,CAAC,EAAE,uBAAuB,CAAC;CAC1C,CAAC,CAAC;AA2GH,wBAAgB,oCAAoC,CAClD,QAAQ,EAAE,uBAAuB,EACjC,YAAY,UAAQ,GACnB,IAAI,CAqBN;AAwCD,wBAAsB,4BAA4B,CAChD,IAAI,EAAE,WAAW,EACjB,MAAM,EAAE,2BAA2B,GAClC,OAAO,CAAC,qBAAqB,CAAC,CAsBhC"}
|
|
@@ -8,6 +8,7 @@ import { hasNodeErrorCode } from "./path.js";
|
|
|
8
8
|
import { realpathSync } from "./realpath.js";
|
|
9
9
|
import { admitPathInsideRoot } from "./root-boundary.js";
|
|
10
10
|
import { prepareRootWriteTarget } from "./root-directory-creation.js";
|
|
11
|
+
import { canReuseParentWithMutationAssertion } from "./root-write-lock-binding.js";
|
|
11
12
|
import { isSafePathSegment } from "./safe-path-segment.js";
|
|
12
13
|
import { inspectFileIdentitySync } from "./strict-file-identity.js";
|
|
13
14
|
import { getFsSafeTestHooks } from "./test-hooks.js";
|
|
@@ -185,7 +186,8 @@ export async function prepareSharedRootWriteTarget(root, params) {
|
|
|
185
186
|
if (mutationAdmission)
|
|
186
187
|
await beforeParentAdmission?.(resolvedPath);
|
|
187
188
|
const preparedParent = params.mkdir !== false &&
|
|
188
|
-
params.assertBeforeMutation
|
|
189
|
+
canReuseParentWithMutationAssertion(params.assertBeforeMutation, root.rootReal, guardedTarget.targetPath) &&
|
|
190
|
+
beforeParentAdmission === undefined
|
|
189
191
|
? await prepareCompleteRootWriteParent(root, guardedTarget, params.relativePath)
|
|
190
192
|
: undefined;
|
|
191
193
|
const targetPath = params.mkdir === false
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type RootBoundaryIdentity } from "./root-boundary.js";
|
|
2
|
+
export declare function canReuseParentWithMutationAssertion(assertion: (() => void) | undefined, rootPath: string, targetPath: string): boolean;
|
|
3
|
+
export declare function assertRootFallbackWritePath(expected: string | undefined, actual: string): void;
|
|
4
|
+
export declare function createRootWriteLockBinding(params: Readonly<{
|
|
5
|
+
rootPath: string;
|
|
6
|
+
targetPath: string;
|
|
7
|
+
rootIdentity?: RootBoundaryIdentity;
|
|
8
|
+
}>): Readonly<{
|
|
9
|
+
targetPath: string;
|
|
10
|
+
relativePath: string;
|
|
11
|
+
relativeLockPath: string;
|
|
12
|
+
assertCurrent: () => void;
|
|
13
|
+
dispose(): void;
|
|
14
|
+
}>;
|
|
15
|
+
//# sourceMappingURL=root-write-lock-binding.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"root-write-lock-binding.d.ts","sourceRoot":"","sources":["../src/root-write-lock-binding.ts"],"names":[],"mappings":"AAKA,OAAO,EAAuB,KAAK,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAKpF,wBAAgB,mCAAmC,CACjD,SAAS,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,EACnC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACjB,OAAO,CAIT;AA6GD,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAI9F;AAED,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,QAAQ,CAAC;IAC1D,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,oBAAoB,CAAC;CACrC,CAAC;;;;;;GAqCD"}
|