


























@@ -1,14 +1,63 @@
11import "./fs-safe-defaults.js";
2+import fs from "node:fs/promises";
3+import path from "node:path";
4+import {
5+movePathWithCopyFallback as movePathWithCopyFallbackBase,
6+replaceDirectoryAtomic,
7+replaceFileAtomic,
8+replaceFileAtomicSync,
9+type MovePathWithCopyFallbackOptions as BaseMovePathWithCopyFallbackOptions,
10+} from "@openclaw/fs-safe/atomic";
11+212export {
3-movePathWithCopyFallback,
413replaceDirectoryAtomic,
514replaceFileAtomic,
615replaceFileAtomicSync,
7-type MovePathWithCopyFallbackOptions,
816type ReplaceDirectoryAtomicOptions,
917type ReplaceFileAtomicFileSystem,
1018type ReplaceFileAtomicOptions,
1119type ReplaceFileAtomicResult,
1220type ReplaceFileAtomicSyncFileSystem,
1321type ReplaceFileAtomicSyncOptions,
1422} from "@openclaw/fs-safe/atomic";
23+24+export type MovePathWithCopyFallbackOptions = BaseMovePathWithCopyFallbackOptions & {
25+sourceHardlinks?: "allow" | "reject";
26+};
27+28+export async function movePathWithCopyFallback(
29+options: MovePathWithCopyFallbackOptions,
30+): Promise<void> {
31+if (options.sourceHardlinks === "reject") {
32+await assertNoHardlinkedSourceFiles(options.from);
33+}
34+await movePathWithCopyFallbackBase({ from: options.from, to: options.to });
35+}
36+37+async function assertNoHardlinkedSourceFiles(sourcePath: string): Promise<void> {
38+const sourceStat = await fs.lstat(sourcePath);
39+if (sourceStat.isFile() && sourceStat.nlink > 1) {
40+throw new Error(`Hardlinked source file is not allowed: ${sourcePath}`);
41+}
42+if (!sourceStat.isDirectory()) {
43+return;
44+}
45+46+const entries = await fs.readdir(sourcePath, { withFileTypes: true });
47+await Promise.all(
48+entries.map(async (entry) => {
49+const entryPath = path.join(sourcePath, entry.name);
50+if (entry.isDirectory()) {
51+await assertNoHardlinkedSourceFiles(entryPath);
52+return;
53+}
54+if (!entry.isFile()) {
55+return;
56+}
57+const entryStat = await fs.lstat(entryPath);
58+if (entryStat.nlink > 1) {
59+throw new Error(`Hardlinked source file is not allowed: ${entryPath}`);
60+}
61+}),
62+);
63+}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。