@openclaw/fs-safe 0.5.6 → 0.7.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 +89 -0
- package/README.md +23 -10
- package/dist/advanced.d.ts +2 -1
- package/dist/advanced.d.ts.map +1 -1
- package/dist/advanced.js +1 -0
- package/dist/archive-crc32.d.ts +2 -0
- package/dist/archive-crc32.d.ts.map +1 -0
- package/dist/archive-crc32.js +14 -0
- package/dist/archive-deadline.d.ts +3 -0
- package/dist/archive-deadline.d.ts.map +1 -1
- package/dist/archive-deadline.js +44 -8
- package/dist/archive-entry.d.ts.map +1 -1
- package/dist/archive-entry.js +1 -0
- package/dist/archive-errors.d.ts +1 -0
- package/dist/archive-errors.d.ts.map +1 -1
- package/dist/archive-errors.js +3 -0
- package/dist/archive-input.d.ts.map +1 -1
- package/dist/archive-input.js +26 -16
- package/dist/archive-kind.js +2 -2
- package/dist/archive-limits.d.ts +11 -3
- package/dist/archive-limits.d.ts.map +1 -1
- package/dist/archive-limits.js +24 -0
- package/dist/archive-native.d.ts +3 -2
- package/dist/archive-native.d.ts.map +1 -1
- package/dist/archive-native.js +31 -9
- package/dist/archive-policy.d.ts +2 -0
- package/dist/archive-policy.d.ts.map +1 -1
- package/dist/archive-policy.js +9 -1
- package/dist/archive-read.d.ts.map +1 -1
- package/dist/archive-read.js +88 -41
- package/dist/archive-staging.d.ts +3 -0
- package/dist/archive-staging.d.ts.map +1 -1
- package/dist/archive-staging.js +91 -43
- package/dist/archive-tar-admission.d.ts +7 -0
- package/dist/archive-tar-admission.d.ts.map +1 -0
- package/dist/archive-tar-admission.js +43 -0
- package/dist/archive-tar-gnu.d.ts +2 -0
- package/dist/archive-tar-gnu.d.ts.map +1 -0
- package/dist/archive-tar-gnu.js +20 -0
- package/dist/archive-tar-header.d.ts +8 -0
- package/dist/archive-tar-header.d.ts.map +1 -0
- package/dist/archive-tar-header.js +47 -0
- package/dist/archive-tar-meta.d.ts +29 -1
- package/dist/archive-tar-meta.d.ts.map +1 -1
- package/dist/archive-tar-meta.js +135 -19
- package/dist/archive-tar-pax.d.ts +8 -0
- package/dist/archive-tar-pax.d.ts.map +1 -0
- package/dist/archive-tar-pax.js +100 -0
- package/dist/archive-tar-runtime.d.ts +4 -0
- package/dist/archive-tar-runtime.d.ts.map +1 -1
- package/dist/archive-tar-runtime.js +3 -0
- package/dist/archive-tar.d.ts.map +1 -1
- package/dist/archive-tar.js +8 -2
- package/dist/archive-zip-admission.d.ts +7 -0
- package/dist/archive-zip-admission.d.ts.map +1 -0
- package/dist/archive-zip-admission.js +60 -0
- package/dist/archive-zip-count.d.ts +2 -0
- package/dist/archive-zip-count.d.ts.map +1 -0
- package/dist/archive-zip-count.js +140 -0
- package/dist/archive-zip-directory.d.ts +8 -0
- package/dist/archive-zip-directory.d.ts.map +1 -0
- package/dist/archive-zip-directory.js +224 -0
- package/dist/archive-zip-integrity.d.ts.map +1 -1
- package/dist/archive-zip-integrity.js +1 -14
- package/dist/archive-zip-names.d.ts +12 -0
- package/dist/archive-zip-names.d.ts.map +1 -0
- package/dist/archive-zip-names.js +99 -0
- package/dist/archive-zip-preflight.d.ts +1 -1
- package/dist/archive-zip-preflight.d.ts.map +1 -1
- package/dist/archive-zip-preflight.js +8 -145
- package/dist/archive.d.ts.map +1 -1
- package/dist/archive.js +63 -42
- package/dist/atomic.d.ts +1 -1
- package/dist/atomic.d.ts.map +1 -1
- package/dist/bounded-read-stream.d.ts.map +1 -1
- package/dist/bounded-read-stream.js +2 -4
- package/dist/bounded-read.d.ts.map +1 -1
- package/dist/bounded-read.js +3 -10
- package/dist/byte-budget.d.ts +5 -0
- package/dist/byte-budget.d.ts.map +1 -0
- package/dist/byte-budget.js +9 -0
- package/dist/file-hash.d.ts.map +1 -1
- package/dist/file-hash.js +25 -19
- package/dist/file-lock-sync.d.ts.map +1 -1
- package/dist/file-lock-sync.js +26 -9
- package/dist/file-store-boundary.d.ts.map +1 -1
- package/dist/file-store-boundary.js +9 -5
- package/dist/file-store-limit.d.ts +2 -0
- package/dist/file-store-limit.d.ts.map +1 -0
- package/dist/file-store-limit.js +8 -0
- package/dist/file-store-sync-write.d.ts.map +1 -1
- package/dist/file-store-sync-write.js +38 -8
- package/dist/file-store.d.ts.map +1 -1
- package/dist/file-store.js +26 -26
- package/dist/json-durable-queue-directory.d.ts +2 -0
- package/dist/json-durable-queue-directory.d.ts.map +1 -0
- package/dist/json-durable-queue-directory.js +20 -0
- package/dist/json-durable-queue-ownership.d.ts +14 -0
- package/dist/json-durable-queue-ownership.d.ts.map +1 -0
- package/dist/json-durable-queue-ownership.js +168 -0
- package/dist/json-durable-queue-retirement.d.ts +9 -0
- package/dist/json-durable-queue-retirement.d.ts.map +1 -0
- package/dist/json-durable-queue-retirement.js +126 -0
- package/dist/json-durable-queue-transfer-lock.d.ts +2 -0
- package/dist/json-durable-queue-transfer-lock.d.ts.map +1 -0
- package/dist/json-durable-queue-transfer-lock.js +19 -0
- package/dist/json-durable-queue.d.ts +1 -0
- package/dist/json-durable-queue.d.ts.map +1 -1
- package/dist/json-durable-queue.js +90 -57
- package/dist/json.d.ts.map +1 -1
- package/dist/json.js +27 -8
- package/dist/local-roots.d.ts.map +1 -1
- package/dist/local-roots.js +4 -2
- package/dist/native-binding.d.ts +15 -3
- package/dist/native-binding.d.ts.map +1 -1
- package/dist/native-operations.d.ts +4 -1
- package/dist/native-operations.d.ts.map +1 -1
- package/dist/native-operations.js +22 -6
- package/dist/native-pinned-write-windows.d.ts +8 -0
- package/dist/native-pinned-write-windows.d.ts.map +1 -0
- package/dist/native-pinned-write-windows.js +92 -0
- package/dist/native-pinned-write.d.ts.map +1 -1
- package/dist/native-pinned-write.js +136 -127
- package/dist/native-staged-file.d.ts +24 -0
- package/dist/native-staged-file.d.ts.map +1 -0
- package/dist/native-staged-file.js +337 -0
- package/dist/native.d.ts.map +1 -1
- package/dist/native.js +4 -4
- package/dist/opened-realpath.d.ts +2 -0
- package/dist/opened-realpath.d.ts.map +1 -1
- package/dist/opened-realpath.js +12 -7
- package/dist/output-sibling.d.ts.map +1 -1
- package/dist/output-sibling.js +11 -110
- package/dist/output.d.ts.map +1 -1
- package/dist/output.js +4 -2
- package/dist/owner-dacl.d.ts.map +1 -1
- package/dist/owner-dacl.js +2 -1
- package/dist/permission-exec.d.ts +19 -0
- package/dist/permission-exec.d.ts.map +1 -1
- package/dist/permission-exec.js +57 -11
- package/dist/permissions-public.d.ts +1 -1
- package/dist/permissions-public.d.ts.map +1 -1
- package/dist/permissions-windows.d.ts +3 -0
- package/dist/permissions-windows.d.ts.map +1 -1
- package/dist/permissions-windows.js +16 -5
- package/dist/permissions.d.ts +5 -0
- package/dist/permissions.d.ts.map +1 -1
- package/dist/pinned-open.d.ts.map +1 -1
- package/dist/pinned-open.js +27 -48
- package/dist/pinned-write.d.ts +6 -0
- package/dist/pinned-write.d.ts.map +1 -1
- package/dist/pinned-write.js +26 -37
- package/dist/private-directory.d.ts.map +1 -1
- package/dist/private-directory.js +3 -2
- package/dist/private-temp-workspace.d.ts +3 -1
- package/dist/private-temp-workspace.d.ts.map +1 -1
- package/dist/private-temp-workspace.js +81 -56
- package/dist/publish-file.d.ts.map +1 -1
- package/dist/publish-file.js +2 -4
- package/dist/read-opened-file.d.ts.map +1 -1
- package/dist/read-opened-file.js +6 -4
- package/dist/regular-file.d.ts.map +1 -1
- package/dist/regular-file.js +136 -82
- package/dist/replace-file-copy-fallback.d.ts +3 -1
- package/dist/replace-file-copy-fallback.d.ts.map +1 -1
- package/dist/replace-file-copy-fallback.js +21 -36
- package/dist/replace-file-copy-source.d.ts +21 -0
- package/dist/replace-file-copy-source.d.ts.map +1 -0
- package/dist/replace-file-copy-source.js +112 -0
- package/dist/replace-file-descriptor.d.ts +13 -3
- package/dist/replace-file-descriptor.d.ts.map +1 -1
- package/dist/replace-file-descriptor.js +32 -7
- package/dist/replace-file-rename-policy.d.ts +7 -0
- package/dist/replace-file-rename-policy.d.ts.map +1 -0
- package/dist/replace-file-rename-policy.js +30 -0
- package/dist/replace-file-temp-owner.d.ts +46 -0
- package/dist/replace-file-temp-owner.d.ts.map +1 -0
- package/dist/replace-file-temp-owner.js +346 -0
- package/dist/replace-file.d.ts +6 -1
- package/dist/replace-file.d.ts.map +1 -1
- package/dist/replace-file.js +72 -58
- package/dist/root-impl.d.ts.map +1 -1
- package/dist/root-impl.js +118 -98
- package/dist/root-paths.d.ts +11 -14
- package/dist/root-paths.d.ts.map +1 -1
- package/dist/root-paths.js +36 -27
- package/dist/root-write-verification.d.ts +11 -0
- package/dist/root-write-verification.d.ts.map +1 -0
- package/dist/root-write-verification.js +91 -0
- package/dist/secret-file.d.ts +1 -6
- package/dist/secret-file.d.ts.map +1 -1
- package/dist/secret-file.js +49 -120
- package/dist/secret-read-async.d.ts +1 -1
- package/dist/secret-read-async.d.ts.map +1 -1
- package/dist/secret-read-async.js +51 -72
- package/dist/secret-read-policy.d.ts +13 -0
- package/dist/secret-read-policy.d.ts.map +1 -0
- package/dist/secret-read-policy.js +28 -0
- package/dist/secret.d.ts +2 -1
- package/dist/secret.d.ts.map +1 -1
- package/dist/secret.js +2 -1
- package/dist/secure-file.d.ts.map +1 -1
- package/dist/secure-file.js +42 -29
- package/dist/sibling-staged-file.d.ts +15 -0
- package/dist/sibling-staged-file.d.ts.map +1 -0
- package/dist/sibling-staged-file.js +148 -0
- package/dist/sibling-temp.d.ts +3 -0
- package/dist/sibling-temp.d.ts.map +1 -1
- package/dist/sibling-temp.js +30 -74
- package/dist/sidecar-lock-acquire.d.ts.map +1 -1
- package/dist/sidecar-lock-acquire.js +48 -27
- package/dist/sidecar-lock-handle.d.ts +6 -2
- package/dist/sidecar-lock-handle.d.ts.map +1 -1
- package/dist/sidecar-lock-handle.js +17 -3
- package/dist/sidecar-lock-policy.d.ts +2 -0
- package/dist/sidecar-lock-policy.d.ts.map +1 -1
- package/dist/sidecar-lock-policy.js +29 -0
- package/dist/sidecar-lock-reclaim.d.ts.map +1 -1
- package/dist/sidecar-lock-reclaim.js +29 -7
- package/dist/sidecar-lock.d.ts.map +1 -1
- package/dist/sidecar-lock.js +28 -16
- package/dist/staged-directory.d.ts +16 -0
- package/dist/staged-directory.d.ts.map +1 -0
- package/dist/staged-directory.js +60 -0
- package/dist/staged-file-types.d.ts +56 -0
- package/dist/staged-file-types.d.ts.map +1 -0
- package/dist/staged-file-types.js +1 -0
- package/dist/staged-file.d.ts +10 -0
- package/dist/staged-file.d.ts.map +1 -0
- package/dist/staged-file.js +15 -0
- package/dist/strict-file-identity.d.ts +6 -0
- package/dist/strict-file-identity.d.ts.map +1 -0
- package/dist/strict-file-identity.js +48 -0
- package/dist/suppressed-error.d.ts +6 -0
- package/dist/suppressed-error.d.ts.map +1 -0
- package/dist/suppressed-error.js +15 -0
- package/dist/temp-cleanup.d.ts +2 -0
- package/dist/temp-cleanup.d.ts.map +1 -1
- package/dist/temp-cleanup.js +25 -10
- package/dist/temp-workspace-owner.d.ts +23 -0
- package/dist/temp-workspace-owner.d.ts.map +1 -0
- package/dist/temp-workspace-owner.js +320 -0
- package/dist/temp.d.ts +1 -1
- package/dist/temp.d.ts.map +1 -1
- package/dist/test-hooks.d.ts +5 -0
- package/dist/test-hooks.d.ts.map +1 -1
- package/dist/windows-owner.d.ts +3 -0
- package/dist/windows-owner.d.ts.map +1 -1
- package/dist/windows-owner.js +10 -2
- package/docs/advanced.md +19 -2
- package/docs/archive.md +250 -35
- package/docs/atomic.md +11 -2
- package/docs/config.md +7 -0
- package/docs/contributing.md +45 -7
- package/docs/durability.md +18 -5
- package/docs/errors.md +16 -1
- package/docs/file-store.md +2 -0
- package/docs/index.md +3 -1
- package/docs/install.md +20 -8
- package/docs/json.md +8 -4
- package/docs/migrating-to-0.5.md +7 -7
- package/docs/migrating-to-0.6.md +43 -0
- package/docs/native-helper.md +30 -8
- package/docs/native.md +73 -17
- package/docs/output.md +10 -0
- package/docs/path-scope.md +28 -2
- package/docs/permissions.md +13 -2
- package/docs/public-api.md +6 -3
- package/docs/quickstart.md +1 -1
- package/docs/reading.md +1 -1
- package/docs/regular-file.md +9 -2
- package/docs/root.md +3 -1
- package/docs/secret-file.md +12 -0
- package/docs/secure-file.md +21 -3
- package/docs/security-model.md +33 -1
- package/docs/sidecar-lock.md +15 -1
- package/docs/staged-file.md +178 -0
- package/docs/store.md +13 -0
- package/docs/temp.md +128 -14
- package/docs/testing.md +1 -1
- package/docs/writing.md +19 -0
- package/package.json +16 -9
- package/dist/native/darwin-arm64/fs-safe-native.node +0 -0
- package/dist/native/darwin-x64/fs-safe-native.node +0 -0
- package/dist/native/linux-arm64-gnu/fs-safe-native.node +0 -0
- package/dist/native/linux-arm64-musl/fs-safe-native.node +0 -0
- package/dist/native/linux-x64-gnu/fs-safe-native.node +0 -0
- package/dist/native/linux-x64-musl/fs-safe-native.node +0 -0
- package/dist/native/win32-x64-msvc/fs-safe-native.node +0 -0
package/dist/replace-file.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
|
-
import syncFs from "node:fs";
|
|
2
|
+
import syncFs, {} from "node:fs";
|
|
3
3
|
import fs from "node:fs/promises";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { assertDestinationHardlinkPolicy, assertDestinationHardlinkPolicySync, copyFallbackReplace, copyFallbackReplaceSync, } from "./replace-file-copy-fallback.js";
|
|
6
6
|
import { applyDirectoryMode, applyDirectoryModeSync, writeTempFile, writeTempFileSync, } from "./replace-file-descriptor.js";
|
|
7
|
+
import { atomicExpectedContentHash, validateRenameIdentity, withAtomicRenameIdentityLock, withAtomicRenameIdentityLockSync, } from "./replace-file-rename-policy.js";
|
|
8
|
+
import { AsyncAtomicTempOwner, SyncAtomicTempOwner } from "./replace-file-temp-owner.js";
|
|
7
9
|
import { assertSafePathPrefix } from "./safe-path-segment.js";
|
|
8
|
-
import { registerTempPathForExit } from "./temp-cleanup.js";
|
|
9
10
|
import { sleep, sleepSync } from "./timing.js";
|
|
10
11
|
import { serializePathWrite } from "./write-queue.js";
|
|
11
12
|
function isRetryableRenameError(error) {
|
|
@@ -17,6 +18,7 @@ function isPermissionRenameError(error) {
|
|
|
17
18
|
}
|
|
18
19
|
async function renameWithRetry(params) {
|
|
19
20
|
for (let attempt = 0; attempt <= params.maxRetries; attempt++) {
|
|
21
|
+
await params.assertSourceCurrent();
|
|
20
22
|
try {
|
|
21
23
|
await params.fsModule.rename(params.src, params.dest);
|
|
22
24
|
return { method: "rename" };
|
|
@@ -34,6 +36,7 @@ async function renameWithRetry(params) {
|
|
|
34
36
|
destinationHardlinks: params.destinationHardlinks,
|
|
35
37
|
restore: params.copyFallbackRestore,
|
|
36
38
|
maxRestoreBytes: params.maxRestoreBytes,
|
|
39
|
+
expectedSourceIdentity: params.sourceIdentity,
|
|
37
40
|
sync: params.syncFallback,
|
|
38
41
|
});
|
|
39
42
|
return { method: "copy-fallback" };
|
|
@@ -45,6 +48,7 @@ async function renameWithRetry(params) {
|
|
|
45
48
|
}
|
|
46
49
|
function renameWithRetrySync(params) {
|
|
47
50
|
for (let attempt = 0; attempt <= params.maxRetries; attempt++) {
|
|
51
|
+
params.assertSourceCurrent();
|
|
48
52
|
try {
|
|
49
53
|
params.fsModule.renameSync(params.src, params.dest);
|
|
50
54
|
return { method: "rename" };
|
|
@@ -62,6 +66,7 @@ function renameWithRetrySync(params) {
|
|
|
62
66
|
destinationHardlinks: params.destinationHardlinks,
|
|
63
67
|
restore: params.copyFallbackRestore,
|
|
64
68
|
maxRestoreBytes: params.maxRestoreBytes,
|
|
69
|
+
expectedSourceIdentity: params.sourceIdentity,
|
|
65
70
|
fchmodSync: params.fchmodSync,
|
|
66
71
|
sync: params.syncFallback,
|
|
67
72
|
});
|
|
@@ -158,26 +163,20 @@ function syncDirectoryBestEffortSync(fsModule, dirPath) {
|
|
|
158
163
|
}
|
|
159
164
|
}
|
|
160
165
|
}
|
|
161
|
-
async function cleanupTempFile(params) {
|
|
162
|
-
const cleanupError = await params.fsModule
|
|
163
|
-
.rm(params.tempPath, { force: true })
|
|
164
|
-
.catch((error) => error);
|
|
165
|
-
if (!cleanupError)
|
|
166
|
-
return true;
|
|
167
|
-
if (params.throwOnCleanupError) {
|
|
168
|
-
if (params.originalError !== undefined) {
|
|
169
|
-
throw new Error(`Atomic file replace failed (${String(params.originalError)}); cleanup also failed (${String(cleanupError)})`, { cause: params.originalError });
|
|
170
|
-
}
|
|
171
|
-
throw cleanupError;
|
|
172
|
-
}
|
|
173
|
-
return false;
|
|
174
|
-
}
|
|
175
166
|
export async function replaceFileAtomic(options) {
|
|
176
167
|
const filePath = options.filePath;
|
|
177
168
|
validateReplaceFilePath(filePath);
|
|
178
169
|
validateRestoreOptions(options);
|
|
170
|
+
validateRenameIdentity(options.renameIdentity);
|
|
179
171
|
return await serializePathWrite(path.resolve(filePath), async () => {
|
|
180
|
-
|
|
172
|
+
if (options.renameIdentity !== "verify-content-with-lock") {
|
|
173
|
+
return await replaceFileAtomicUnserialized(options);
|
|
174
|
+
}
|
|
175
|
+
await (options.fileSystem?.promises ?? fs).mkdir(path.dirname(filePath), {
|
|
176
|
+
recursive: true,
|
|
177
|
+
mode: options.dirMode ?? 0o700,
|
|
178
|
+
});
|
|
179
|
+
return await withAtomicRenameIdentityLock(filePath, async () => await replaceFileAtomicUnserialized(options));
|
|
181
180
|
});
|
|
182
181
|
}
|
|
183
182
|
async function replaceFileAtomicUnserialized(options) {
|
|
@@ -186,24 +185,27 @@ async function replaceFileAtomicUnserialized(options) {
|
|
|
186
185
|
const dir = path.dirname(filePath);
|
|
187
186
|
const dirMode = options.dirMode ?? 0o700;
|
|
188
187
|
const mode = await resolveMode(options);
|
|
188
|
+
const expectedHash = atomicExpectedContentHash(options.renameIdentity, options.content);
|
|
189
189
|
const tempPath = buildReplaceTempPath(filePath, options.tempPrefix);
|
|
190
|
-
const
|
|
191
|
-
let tempExists = false;
|
|
190
|
+
const tempOwner = new AsyncAtomicTempOwner(tempPath);
|
|
192
191
|
let originalError;
|
|
193
192
|
try {
|
|
194
193
|
await fsModule.mkdir(dir, { recursive: true, mode: dirMode });
|
|
195
194
|
await applyDirectoryMode({ fsModule, dirPath: dir, mode: dirMode });
|
|
196
|
-
|
|
197
|
-
|
|
195
|
+
tempOwner.start();
|
|
196
|
+
tempOwner.adopt(await writeTempFile({
|
|
198
197
|
fsModule,
|
|
199
198
|
tempPath,
|
|
200
199
|
content: options.content,
|
|
201
200
|
mode,
|
|
202
201
|
sync: options.syncTempFile === true,
|
|
202
|
+
onIdentity: tempOwner.onIdentity,
|
|
203
203
|
}));
|
|
204
|
+
await tempOwner.assertCurrent(fsModule);
|
|
204
205
|
if (options.beforeRename) {
|
|
205
206
|
await options.beforeRename({ filePath, tempPath });
|
|
206
207
|
}
|
|
208
|
+
await tempOwner.assertCurrent(fsModule);
|
|
207
209
|
await assertDestinationHardlinkPolicy(fsModule, filePath, options.destinationHardlinks);
|
|
208
210
|
const result = await renameWithRetry({
|
|
209
211
|
fsModule,
|
|
@@ -215,15 +217,23 @@ async function replaceFileAtomicUnserialized(options) {
|
|
|
215
217
|
copyFallbackRestore: options.copyFallbackRestore ?? "none",
|
|
216
218
|
maxRestoreBytes: options.maxRestoreBytes,
|
|
217
219
|
destinationHardlinks: options.destinationHardlinks,
|
|
220
|
+
sourceIdentity: tempOwner.identity,
|
|
221
|
+
assertSourceCurrent: () => tempOwner.assertCurrent(fsModule),
|
|
218
222
|
syncFallback: options.syncTempFile === true,
|
|
219
223
|
});
|
|
220
224
|
if (result.method === "rename") {
|
|
221
|
-
|
|
222
|
-
|
|
225
|
+
tempOwner.markRenamed();
|
|
226
|
+
await tempOwner.assertPublished(fsModule, filePath, expectedHash);
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
await tempOwner.assertCurrent(fsModule);
|
|
223
230
|
}
|
|
224
231
|
if (options.syncParentDir) {
|
|
225
232
|
await syncDirectoryBestEffort(fsModule, dir);
|
|
226
233
|
}
|
|
234
|
+
if (result.method === "rename") {
|
|
235
|
+
await tempOwner.assertPublished(fsModule, filePath, expectedHash);
|
|
236
|
+
}
|
|
227
237
|
return result;
|
|
228
238
|
}
|
|
229
239
|
catch (error) {
|
|
@@ -231,27 +241,34 @@ async function replaceFileAtomicUnserialized(options) {
|
|
|
231
241
|
throw error;
|
|
232
242
|
}
|
|
233
243
|
finally {
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
originalError,
|
|
240
|
-
throwOnCleanupError: options.throwOnCleanupError === true,
|
|
241
|
-
});
|
|
242
|
-
}
|
|
243
|
-
if (tempRemoved)
|
|
244
|
-
unregisterTempPath();
|
|
244
|
+
await tempOwner.finish({
|
|
245
|
+
fsModule,
|
|
246
|
+
originalError,
|
|
247
|
+
throwOnCleanupError: options.throwOnCleanupError === true,
|
|
248
|
+
});
|
|
245
249
|
}
|
|
246
250
|
}
|
|
247
251
|
export function replaceFileAtomicSync(options) {
|
|
248
252
|
const filePath = options.filePath;
|
|
249
253
|
validateReplaceFilePath(filePath);
|
|
250
254
|
validateRestoreOptions(options);
|
|
255
|
+
validateRenameIdentity(options.renameIdentity);
|
|
256
|
+
if (options.renameIdentity !== "verify-content-with-lock") {
|
|
257
|
+
return replaceFileAtomicSyncUnserialized(options);
|
|
258
|
+
}
|
|
259
|
+
(options.fileSystem ?? syncFs).mkdirSync(path.dirname(filePath), {
|
|
260
|
+
recursive: true,
|
|
261
|
+
mode: options.dirMode ?? 0o700,
|
|
262
|
+
});
|
|
263
|
+
return withAtomicRenameIdentityLockSync(filePath, () => replaceFileAtomicSyncUnserialized(options));
|
|
264
|
+
}
|
|
265
|
+
function replaceFileAtomicSyncUnserialized(options) {
|
|
266
|
+
const filePath = options.filePath;
|
|
251
267
|
const fsModule = options.fileSystem ?? syncFs;
|
|
252
268
|
const dir = path.dirname(filePath);
|
|
253
269
|
const dirMode = options.dirMode ?? 0o700;
|
|
254
270
|
const mode = resolveModeSync(options);
|
|
271
|
+
const expectedHash = atomicExpectedContentHash(options.renameIdentity, options.content);
|
|
255
272
|
const fchmodSync = options.fileSystem?.fchmodSync ?? (options.fileSystem === undefined ? syncFs.fchmodSync : undefined);
|
|
256
273
|
if (!fchmodSync &&
|
|
257
274
|
(options.mode !== undefined ||
|
|
@@ -260,24 +277,26 @@ export function replaceFileAtomicSync(options) {
|
|
|
260
277
|
throw missingFchmodSyncError();
|
|
261
278
|
}
|
|
262
279
|
const tempPath = buildReplaceTempPath(filePath, options.tempPrefix);
|
|
263
|
-
const
|
|
264
|
-
let tempExists = false;
|
|
280
|
+
const tempOwner = new SyncAtomicTempOwner(tempPath);
|
|
265
281
|
let originalError;
|
|
266
282
|
try {
|
|
267
283
|
fsModule.mkdirSync(dir, { recursive: true, mode: dirMode });
|
|
268
284
|
applyDirectoryModeSync({ fsModule, dirPath: dir, mode: dirMode, fchmodSync });
|
|
269
|
-
|
|
270
|
-
|
|
285
|
+
tempOwner.start();
|
|
286
|
+
tempOwner.adopt(writeTempFileSync({
|
|
271
287
|
fsModule,
|
|
272
288
|
tempPath,
|
|
273
289
|
content: options.content,
|
|
274
290
|
mode,
|
|
275
291
|
fchmodSync,
|
|
276
292
|
sync: options.syncTempFile === true,
|
|
293
|
+
onIdentity: tempOwner.onIdentity,
|
|
277
294
|
}));
|
|
295
|
+
tempOwner.assertCurrent(fsModule);
|
|
278
296
|
if (options.beforeRename) {
|
|
279
297
|
options.beforeRename({ filePath, tempPath });
|
|
280
298
|
}
|
|
299
|
+
tempOwner.assertCurrent(fsModule);
|
|
281
300
|
assertDestinationHardlinkPolicySync(fsModule, filePath, options.destinationHardlinks);
|
|
282
301
|
const result = renameWithRetrySync({
|
|
283
302
|
fsModule,
|
|
@@ -289,16 +308,24 @@ export function replaceFileAtomicSync(options) {
|
|
|
289
308
|
copyFallbackRestore: options.copyFallbackRestore ?? "none",
|
|
290
309
|
maxRestoreBytes: options.maxRestoreBytes,
|
|
291
310
|
destinationHardlinks: options.destinationHardlinks,
|
|
311
|
+
sourceIdentity: tempOwner.identity,
|
|
312
|
+
assertSourceCurrent: () => tempOwner.assertCurrent(fsModule),
|
|
292
313
|
fchmodSync,
|
|
293
314
|
syncFallback: options.syncTempFile === true,
|
|
294
315
|
});
|
|
295
316
|
if (result.method === "rename") {
|
|
296
|
-
|
|
297
|
-
|
|
317
|
+
tempOwner.markRenamed();
|
|
318
|
+
tempOwner.assertPublished(fsModule, filePath, expectedHash);
|
|
319
|
+
}
|
|
320
|
+
else {
|
|
321
|
+
tempOwner.assertCurrent(fsModule);
|
|
298
322
|
}
|
|
299
323
|
if (options.syncParentDir) {
|
|
300
324
|
syncDirectoryBestEffortSync(fsModule, dir);
|
|
301
325
|
}
|
|
326
|
+
if (result.method === "rename") {
|
|
327
|
+
tempOwner.assertPublished(fsModule, filePath, expectedHash);
|
|
328
|
+
}
|
|
302
329
|
return result;
|
|
303
330
|
}
|
|
304
331
|
catch (error) {
|
|
@@ -306,23 +333,10 @@ export function replaceFileAtomicSync(options) {
|
|
|
306
333
|
throw error;
|
|
307
334
|
}
|
|
308
335
|
finally {
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
}
|
|
315
|
-
catch (cleanupError) {
|
|
316
|
-
if (options.throwOnCleanupError) {
|
|
317
|
-
if (originalError !== undefined) {
|
|
318
|
-
throw new Error(`Atomic file replace failed (${String(originalError)}); cleanup also failed (${String(cleanupError)})`, { cause: originalError });
|
|
319
|
-
}
|
|
320
|
-
throw cleanupError;
|
|
321
|
-
}
|
|
322
|
-
// The temp file is best-effort cleanup after write failure.
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
if (tempRemoved)
|
|
326
|
-
unregisterTempPath();
|
|
336
|
+
tempOwner.finish({
|
|
337
|
+
fsModule,
|
|
338
|
+
originalError,
|
|
339
|
+
throwOnCleanupError: options.throwOnCleanupError === true,
|
|
340
|
+
});
|
|
327
341
|
}
|
|
328
342
|
}
|
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,KAAK,EAAE,MAAM,SAAS,CAAC;AAElD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"root-impl.d.ts","sourceRoot":"","sources":["../src/root-impl.ts"],"names":[],"mappings":"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"}
|