@relayfile/local-mount 0.7.23 → 0.7.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/dist/auto-sync.js +3 -3
- package/dist/mount.d.ts +2 -0
- package/dist/mount.js +21 -10
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -21,6 +21,8 @@ const handle = await createMount(projectDir, mountDir, options);
|
|
|
21
21
|
|
|
22
22
|
interface MountHandle {
|
|
23
23
|
mountDir: string;
|
|
24
|
+
initialFileCount?: number;
|
|
25
|
+
initialMountDurationMs?: number;
|
|
24
26
|
syncBack(opts?: { signal?: AbortSignal; paths?: Iterable<string> }): Promise<number>;
|
|
25
27
|
startAutoSync(opts?: AutoSyncOptions): AutoSyncHandle;
|
|
26
28
|
cleanup(): void;
|
|
@@ -28,6 +30,7 @@ interface MountHandle {
|
|
|
28
30
|
```
|
|
29
31
|
|
|
30
32
|
`createMount` returns `Promise<MountHandle>`. The walker yields the event loop between directory entries so consumer-side timers (e.g. an `ora` spinner driven by `setInterval`) keep firing while the mount is being built.
|
|
33
|
+
The returned handle includes initial mount timing and copied-file count metadata so callers can report setup performance.
|
|
31
34
|
|
|
32
35
|
Behavior:
|
|
33
36
|
- Copies regular files into the mount, requesting a filesystem reflink clone when the source and mount are on a compatible same-volume filesystem and falling back to a byte copy otherwise
|
package/dist/auto-sync.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { chmodSync, copyFileSync, existsSync, lstatSync, mkdirSync, readdirSync, readFileSync, realpathSync, rmSync, statSync, } from 'node:fs';
|
|
1
|
+
import { chmodSync, constants as fsConstants, copyFileSync, existsSync, lstatSync, mkdirSync, readdirSync, readFileSync, realpathSync, rmSync, statSync, } from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import watcher from '@parcel/watcher';
|
|
4
4
|
const STOP_EVENT_SETTLE_MS = 250;
|
|
@@ -504,7 +504,7 @@ function doMountToProject(relPosix, state, ctx, mountAbs, projectAbs) {
|
|
|
504
504
|
updateState(state, relPosix, mountAbs, target);
|
|
505
505
|
return false;
|
|
506
506
|
}
|
|
507
|
-
copyFileSync(mountAbs, target);
|
|
507
|
+
copyFileSync(mountAbs, target, fsConstants.COPYFILE_FICLONE);
|
|
508
508
|
updateState(state, relPosix, mountAbs, target);
|
|
509
509
|
return true;
|
|
510
510
|
}
|
|
@@ -526,7 +526,7 @@ function doProjectToMount(relPosix, state, ctx, projectAbs, mountAbs, readonly)
|
|
|
526
526
|
}
|
|
527
527
|
catch { /* best effort */ }
|
|
528
528
|
}
|
|
529
|
-
copyFileSync(projectAbs, target);
|
|
529
|
+
copyFileSync(projectAbs, target, fsConstants.COPYFILE_FICLONE);
|
|
530
530
|
if (readonly) {
|
|
531
531
|
try {
|
|
532
532
|
chmodSync(target, 0o444);
|
package/dist/mount.d.ts
CHANGED
package/dist/mount.js
CHANGED
|
@@ -60,7 +60,9 @@ export async function createMount(projectDir, mountDir, options) {
|
|
|
60
60
|
mkdirSync(resolvedMountDir, { recursive: true });
|
|
61
61
|
const realMountDir = realpathSync(resolvedMountDir);
|
|
62
62
|
writeFileSync(path.join(realMountDir, MOUNT_MARKER_FILENAME), MOUNT_MARKER_CONTENT, 'utf8');
|
|
63
|
-
|
|
63
|
+
const initialMountStartedAt = Date.now();
|
|
64
|
+
const initialFileCount = await walkProjectTree(resolvedProjectDir, resolvedProjectDir, realMountDir, realMountDir, excludeRules, readonlyMatcher, ignoredMatcher);
|
|
65
|
+
const initialMountDurationMs = Date.now() - initialMountStartedAt;
|
|
64
66
|
const readmePath = resolveSafeCopyTarget(realMountDir, path.join(realMountDir, MOUNT_README_FILENAME));
|
|
65
67
|
if (!readmePath) {
|
|
66
68
|
throw new Error('Failed to create mount readme inside mountDir');
|
|
@@ -79,6 +81,8 @@ export async function createMount(projectDir, mountDir, options) {
|
|
|
79
81
|
};
|
|
80
82
|
return {
|
|
81
83
|
mountDir: resolvedMountDir,
|
|
84
|
+
initialFileCount,
|
|
85
|
+
initialMountDurationMs,
|
|
82
86
|
async syncBack(opts) {
|
|
83
87
|
let synced = 0;
|
|
84
88
|
const realProjectDir = realpathSync(resolvedProjectDir);
|
|
@@ -160,6 +164,7 @@ async function walkProjectTree(projectDir, currentDir, mountDir, currentMountDir
|
|
|
160
164
|
await yieldToEventLoop();
|
|
161
165
|
const entries = readdirSync(currentDir, { withFileTypes: true });
|
|
162
166
|
let processed = 0;
|
|
167
|
+
let copiedFiles = 0;
|
|
163
168
|
for (const entry of entries) {
|
|
164
169
|
if (processed > 0 && processed % WALK_YIELD_EVERY === 0) {
|
|
165
170
|
await yieldToEventLoop();
|
|
@@ -185,18 +190,23 @@ async function walkProjectTree(projectDir, currentDir, mountDir, currentMountDir
|
|
|
185
190
|
if (!safeMountDir) {
|
|
186
191
|
continue;
|
|
187
192
|
}
|
|
188
|
-
await walkProjectTree(projectDir, absolutePath, mountDir, safeMountDir, excludeRules, readonlyMatcher, ignoredMatcher);
|
|
193
|
+
copiedFiles += await walkProjectTree(projectDir, absolutePath, mountDir, safeMountDir, excludeRules, readonlyMatcher, ignoredMatcher);
|
|
189
194
|
continue;
|
|
190
195
|
}
|
|
191
196
|
if (entry.isSymbolicLink()) {
|
|
192
|
-
copySymlinkedFile(projectDir, mountDir, absolutePath, mountPath, relativePath, readonlyMatcher)
|
|
197
|
+
if (copySymlinkedFile(projectDir, mountDir, absolutePath, mountPath, relativePath, readonlyMatcher)) {
|
|
198
|
+
copiedFiles += 1;
|
|
199
|
+
}
|
|
193
200
|
continue;
|
|
194
201
|
}
|
|
195
202
|
if (!entry.isFile()) {
|
|
196
203
|
continue;
|
|
197
204
|
}
|
|
198
|
-
copyMountedFile(projectDir, mountDir, absolutePath, mountPath, relativePath, readonlyMatcher)
|
|
205
|
+
if (copyMountedFile(projectDir, mountDir, absolutePath, mountPath, relativePath, readonlyMatcher)) {
|
|
206
|
+
copiedFiles += 1;
|
|
207
|
+
}
|
|
199
208
|
}
|
|
209
|
+
return copiedFiles;
|
|
200
210
|
}
|
|
201
211
|
function yieldToEventLoop() {
|
|
202
212
|
return new Promise((resolve) => setImmediate(resolve));
|
|
@@ -209,29 +219,30 @@ function copySymlinkedFile(projectDir, mountDir, sourcePath, mountPath, relative
|
|
|
209
219
|
resolvedStat = statSync(sourcePath);
|
|
210
220
|
}
|
|
211
221
|
catch {
|
|
212
|
-
return;
|
|
222
|
+
return false;
|
|
213
223
|
}
|
|
214
224
|
if (!isPathWithinRoot(realSource, projectDir) || !resolvedStat.isFile()) {
|
|
215
|
-
return;
|
|
225
|
+
return false;
|
|
216
226
|
}
|
|
217
|
-
copyMountedFile(projectDir, mountDir, realSource, mountPath, relativePath, readonlyMatcher, resolvedStat.mode);
|
|
227
|
+
return copyMountedFile(projectDir, mountDir, realSource, mountPath, relativePath, readonlyMatcher, resolvedStat.mode);
|
|
218
228
|
}
|
|
219
229
|
function copyMountedFile(sourceRoot, mountDir, sourcePath, mountPath, relativePath, readonlyMatcher, sourceMode) {
|
|
220
230
|
const safeMountPath = resolveSafeCopyTarget(mountDir, mountPath);
|
|
221
231
|
if (!safeMountPath) {
|
|
222
|
-
return;
|
|
232
|
+
return false;
|
|
223
233
|
}
|
|
224
234
|
const safeSourcePath = resolveVerifiedFilePath(sourceRoot, sourcePath);
|
|
225
235
|
if (!safeSourcePath) {
|
|
226
|
-
return;
|
|
236
|
+
return false;
|
|
227
237
|
}
|
|
228
238
|
copyFileSync(safeSourcePath, safeMountPath, fsConstants.COPYFILE_FICLONE);
|
|
229
239
|
if (isPathMatched(relativePath, readonlyMatcher)) {
|
|
230
240
|
chmodSync(safeMountPath, 0o444);
|
|
231
|
-
return;
|
|
241
|
+
return true;
|
|
232
242
|
}
|
|
233
243
|
const mode = sourceMode ?? statSync(safeSourcePath).mode;
|
|
234
244
|
chmodSync(safeMountPath, mode & 0o777);
|
|
245
|
+
return true;
|
|
235
246
|
}
|
|
236
247
|
function ensureDirectory(pathValue) {
|
|
237
248
|
mkdirSync(pathValue, { recursive: true });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@relayfile/local-mount",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.25",
|
|
4
4
|
"description": "Create a symlink/copy mount of a project directory with .agentignore/.agentreadonly semantics, then launch a CLI inside it and sync writable changes back on exit",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|