permachine 0.4.1 → 0.5.1
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/dist/cli.js +316 -177
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -6458,6 +6458,142 @@ async function isFileTrackedByGit(filePath, cwd) {
|
|
|
6458
6458
|
}
|
|
6459
6459
|
}
|
|
6460
6460
|
|
|
6461
|
+
// src/core/git-hooks.ts
|
|
6462
|
+
import fs3 from "node:fs/promises";
|
|
6463
|
+
import path6 from "node:path";
|
|
6464
|
+
import { exec as exec2 } from "node:child_process";
|
|
6465
|
+
import { promisify as promisify2 } from "node:util";
|
|
6466
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
6467
|
+
var execAsync2 = promisify2(exec2);
|
|
6468
|
+
var __filename2 = fileURLToPath3(import.meta.url);
|
|
6469
|
+
var __dirname2 = path6.dirname(__filename2);
|
|
6470
|
+
var HOOK_NAMES = ["post-checkout", "post-merge", "post-commit"];
|
|
6471
|
+
var HOOKS_DIR = ".permachine/hooks";
|
|
6472
|
+
async function installHooks(options = {}) {
|
|
6473
|
+
const warnings = [];
|
|
6474
|
+
if (!await isGitRepository()) {
|
|
6475
|
+
throw new Error('Not a git repository. Run "git init" first.');
|
|
6476
|
+
}
|
|
6477
|
+
const cwd = process.cwd();
|
|
6478
|
+
const existingHooksPath = await getGitConfig("core.hooksPath");
|
|
6479
|
+
if (existingHooksPath && existingHooksPath !== HOOKS_DIR && !options.legacy) {
|
|
6480
|
+
warnings.push(`Git core.hooksPath is already set to: ${existingHooksPath}`, "Use --legacy flag to install hooks in .git/hooks instead");
|
|
6481
|
+
}
|
|
6482
|
+
const useLegacy = options.legacy || existingHooksPath && existingHooksPath !== HOOKS_DIR;
|
|
6483
|
+
if (useLegacy) {
|
|
6484
|
+
return await installLegacyHooks(warnings);
|
|
6485
|
+
} else {
|
|
6486
|
+
return await installHooksPathMethod(warnings);
|
|
6487
|
+
}
|
|
6488
|
+
}
|
|
6489
|
+
async function installHooksPathMethod(warnings) {
|
|
6490
|
+
const cwd = process.cwd();
|
|
6491
|
+
const hooksDir = path6.join(cwd, HOOKS_DIR);
|
|
6492
|
+
await fs3.mkdir(hooksDir, { recursive: true });
|
|
6493
|
+
let templatesDir = path6.join(__dirname2, "../../templates/hooks");
|
|
6494
|
+
if (!await fileExists2(path6.join(templatesDir, "post-checkout"))) {
|
|
6495
|
+
templatesDir = path6.join(__dirname2, "../templates/hooks");
|
|
6496
|
+
}
|
|
6497
|
+
const installedHooks = [];
|
|
6498
|
+
for (const hookName of HOOK_NAMES) {
|
|
6499
|
+
const templatePath = path6.join(templatesDir, hookName);
|
|
6500
|
+
const hookPath = path6.join(hooksDir, hookName);
|
|
6501
|
+
const content = await fs3.readFile(templatePath, "utf-8");
|
|
6502
|
+
await fs3.writeFile(hookPath, content, { mode: 493 });
|
|
6503
|
+
installedHooks.push(hookName);
|
|
6504
|
+
}
|
|
6505
|
+
await setGitConfig("core.hooksPath", HOOKS_DIR);
|
|
6506
|
+
logger.success(`Installed git hooks via core.hooksPath`);
|
|
6507
|
+
return {
|
|
6508
|
+
method: "hooksPath",
|
|
6509
|
+
hooksInstalled: installedHooks,
|
|
6510
|
+
warnings
|
|
6511
|
+
};
|
|
6512
|
+
}
|
|
6513
|
+
async function installLegacyHooks(warnings) {
|
|
6514
|
+
const cwd = process.cwd();
|
|
6515
|
+
const gitHooksDir = path6.join(cwd, ".git/hooks");
|
|
6516
|
+
const installedHooks = [];
|
|
6517
|
+
for (const hookName of HOOK_NAMES) {
|
|
6518
|
+
const hookPath = path6.join(gitHooksDir, hookName);
|
|
6519
|
+
const backupPath = path6.join(gitHooksDir, `${hookName}.pre-mcs`);
|
|
6520
|
+
const hookExists = await fileExists2(hookPath);
|
|
6521
|
+
if (hookExists) {
|
|
6522
|
+
await fs3.rename(hookPath, backupPath);
|
|
6523
|
+
}
|
|
6524
|
+
const hookContent = `#!/bin/sh
|
|
6525
|
+
# Auto-generated by permachine (legacy mode)
|
|
6526
|
+
|
|
6527
|
+
permachine merge --silent
|
|
6528
|
+
|
|
6529
|
+
# Call original hook if it existed
|
|
6530
|
+
if [ -f "${backupPath}" ]; then
|
|
6531
|
+
"${backupPath}" "$@"
|
|
6532
|
+
fi
|
|
6533
|
+
|
|
6534
|
+
exit 0
|
|
6535
|
+
`;
|
|
6536
|
+
await fs3.writeFile(hookPath, hookContent, { mode: 493 });
|
|
6537
|
+
installedHooks.push(hookName);
|
|
6538
|
+
}
|
|
6539
|
+
logger.success("Installed git hooks via legacy .git/hooks wrapping");
|
|
6540
|
+
return {
|
|
6541
|
+
method: "legacy",
|
|
6542
|
+
hooksInstalled: installedHooks,
|
|
6543
|
+
warnings
|
|
6544
|
+
};
|
|
6545
|
+
}
|
|
6546
|
+
async function uninstallHooks() {
|
|
6547
|
+
const cwd = process.cwd();
|
|
6548
|
+
const hooksPath = await getGitConfig("core.hooksPath");
|
|
6549
|
+
if (hooksPath === HOOKS_DIR) {
|
|
6550
|
+
await execAsync2("git config --unset core.hooksPath");
|
|
6551
|
+
const hooksDir = path6.join(cwd, HOOKS_DIR);
|
|
6552
|
+
await fs3.rm(hooksDir, { recursive: true, force: true });
|
|
6553
|
+
logger.success("Uninstalled git hooks (removed core.hooksPath)");
|
|
6554
|
+
} else {
|
|
6555
|
+
const gitHooksDir = path6.join(cwd, ".git/hooks");
|
|
6556
|
+
for (const hookName of HOOK_NAMES) {
|
|
6557
|
+
const hookPath = path6.join(gitHooksDir, hookName);
|
|
6558
|
+
const backupPath = path6.join(gitHooksDir, `${hookName}.pre-mcs`);
|
|
6559
|
+
if (await fileExists2(hookPath)) {
|
|
6560
|
+
await fs3.unlink(hookPath);
|
|
6561
|
+
}
|
|
6562
|
+
if (await fileExists2(backupPath)) {
|
|
6563
|
+
await fs3.rename(backupPath, hookPath);
|
|
6564
|
+
}
|
|
6565
|
+
}
|
|
6566
|
+
logger.success("Uninstalled git hooks (restored original hooks)");
|
|
6567
|
+
}
|
|
6568
|
+
}
|
|
6569
|
+
async function isGitRepository() {
|
|
6570
|
+
try {
|
|
6571
|
+
await execAsync2("git rev-parse --git-dir");
|
|
6572
|
+
return true;
|
|
6573
|
+
} catch {
|
|
6574
|
+
return false;
|
|
6575
|
+
}
|
|
6576
|
+
}
|
|
6577
|
+
async function getGitConfig(key) {
|
|
6578
|
+
try {
|
|
6579
|
+
const { stdout } = await execAsync2(`git config --get ${key}`);
|
|
6580
|
+
return stdout.trim() || null;
|
|
6581
|
+
} catch {
|
|
6582
|
+
return null;
|
|
6583
|
+
}
|
|
6584
|
+
}
|
|
6585
|
+
async function setGitConfig(key, value) {
|
|
6586
|
+
await execAsync2(`git config ${key} "${value}"`);
|
|
6587
|
+
}
|
|
6588
|
+
async function fileExists2(filePath) {
|
|
6589
|
+
try {
|
|
6590
|
+
await fs3.access(filePath);
|
|
6591
|
+
return true;
|
|
6592
|
+
} catch {
|
|
6593
|
+
return false;
|
|
6594
|
+
}
|
|
6595
|
+
}
|
|
6596
|
+
|
|
6461
6597
|
// node_modules/chokidar/index.js
|
|
6462
6598
|
import { EventEmitter as EventEmitter2 } from "node:events";
|
|
6463
6599
|
import { stat as statcb, Stats } from "node:fs";
|
|
@@ -6549,7 +6685,7 @@ class ReaddirpStream extends Readable {
|
|
|
6549
6685
|
this._directoryFilter = normalizeFilter(opts.directoryFilter);
|
|
6550
6686
|
const statMethod = opts.lstat ? lstat2 : stat;
|
|
6551
6687
|
if (wantBigintFsStats) {
|
|
6552
|
-
this._stat = (
|
|
6688
|
+
this._stat = (path7) => statMethod(path7, { bigint: true });
|
|
6553
6689
|
} else {
|
|
6554
6690
|
this._stat = statMethod;
|
|
6555
6691
|
}
|
|
@@ -6574,8 +6710,8 @@ class ReaddirpStream extends Readable {
|
|
|
6574
6710
|
const par = this.parent;
|
|
6575
6711
|
const fil = par && par.files;
|
|
6576
6712
|
if (fil && fil.length > 0) {
|
|
6577
|
-
const { path:
|
|
6578
|
-
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent,
|
|
6713
|
+
const { path: path7, depth } = par;
|
|
6714
|
+
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path7));
|
|
6579
6715
|
const awaited = await Promise.all(slice);
|
|
6580
6716
|
for (const entry of awaited) {
|
|
6581
6717
|
if (!entry)
|
|
@@ -6615,20 +6751,20 @@ class ReaddirpStream extends Readable {
|
|
|
6615
6751
|
this.reading = false;
|
|
6616
6752
|
}
|
|
6617
6753
|
}
|
|
6618
|
-
async _exploreDir(
|
|
6754
|
+
async _exploreDir(path7, depth) {
|
|
6619
6755
|
let files;
|
|
6620
6756
|
try {
|
|
6621
|
-
files = await readdir2(
|
|
6757
|
+
files = await readdir2(path7, this._rdOptions);
|
|
6622
6758
|
} catch (error) {
|
|
6623
6759
|
this._onError(error);
|
|
6624
6760
|
}
|
|
6625
|
-
return { files, depth, path:
|
|
6761
|
+
return { files, depth, path: path7 };
|
|
6626
6762
|
}
|
|
6627
|
-
async _formatEntry(dirent,
|
|
6763
|
+
async _formatEntry(dirent, path7) {
|
|
6628
6764
|
let entry;
|
|
6629
6765
|
const basename = this._isDirent ? dirent.name : dirent;
|
|
6630
6766
|
try {
|
|
6631
|
-
const fullPath = presolve(pjoin(
|
|
6767
|
+
const fullPath = presolve(pjoin(path7, basename));
|
|
6632
6768
|
entry = { path: prelative(this._root, fullPath), fullPath, basename };
|
|
6633
6769
|
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
|
|
6634
6770
|
} catch (err) {
|
|
@@ -7027,16 +7163,16 @@ var delFromSet = (main, prop, item) => {
|
|
|
7027
7163
|
};
|
|
7028
7164
|
var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
|
|
7029
7165
|
var FsWatchInstances = new Map;
|
|
7030
|
-
function createFsWatchInstance(
|
|
7166
|
+
function createFsWatchInstance(path7, options, listener, errHandler, emitRaw) {
|
|
7031
7167
|
const handleEvent = (rawEvent, evPath) => {
|
|
7032
|
-
listener(
|
|
7033
|
-
emitRaw(rawEvent, evPath, { watchedPath:
|
|
7034
|
-
if (evPath &&
|
|
7035
|
-
fsWatchBroadcast(sp.resolve(
|
|
7168
|
+
listener(path7);
|
|
7169
|
+
emitRaw(rawEvent, evPath, { watchedPath: path7 });
|
|
7170
|
+
if (evPath && path7 !== evPath) {
|
|
7171
|
+
fsWatchBroadcast(sp.resolve(path7, evPath), KEY_LISTENERS, sp.join(path7, evPath));
|
|
7036
7172
|
}
|
|
7037
7173
|
};
|
|
7038
7174
|
try {
|
|
7039
|
-
return fs_watch(
|
|
7175
|
+
return fs_watch(path7, {
|
|
7040
7176
|
persistent: options.persistent
|
|
7041
7177
|
}, handleEvent);
|
|
7042
7178
|
} catch (error) {
|
|
@@ -7052,12 +7188,12 @@ var fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
|
|
|
7052
7188
|
listener(val1, val2, val3);
|
|
7053
7189
|
});
|
|
7054
7190
|
};
|
|
7055
|
-
var setFsWatchListener = (
|
|
7191
|
+
var setFsWatchListener = (path7, fullPath, options, handlers) => {
|
|
7056
7192
|
const { listener, errHandler, rawEmitter } = handlers;
|
|
7057
7193
|
let cont = FsWatchInstances.get(fullPath);
|
|
7058
7194
|
let watcher;
|
|
7059
7195
|
if (!options.persistent) {
|
|
7060
|
-
watcher = createFsWatchInstance(
|
|
7196
|
+
watcher = createFsWatchInstance(path7, options, listener, errHandler, rawEmitter);
|
|
7061
7197
|
if (!watcher)
|
|
7062
7198
|
return;
|
|
7063
7199
|
return watcher.close.bind(watcher);
|
|
@@ -7067,7 +7203,7 @@ var setFsWatchListener = (path6, fullPath, options, handlers) => {
|
|
|
7067
7203
|
addAndConvert(cont, KEY_ERR, errHandler);
|
|
7068
7204
|
addAndConvert(cont, KEY_RAW, rawEmitter);
|
|
7069
7205
|
} else {
|
|
7070
|
-
watcher = createFsWatchInstance(
|
|
7206
|
+
watcher = createFsWatchInstance(path7, options, fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS), errHandler, fsWatchBroadcast.bind(null, fullPath, KEY_RAW));
|
|
7071
7207
|
if (!watcher)
|
|
7072
7208
|
return;
|
|
7073
7209
|
watcher.on(EV.ERROR, async (error) => {
|
|
@@ -7076,7 +7212,7 @@ var setFsWatchListener = (path6, fullPath, options, handlers) => {
|
|
|
7076
7212
|
cont.watcherUnusable = true;
|
|
7077
7213
|
if (isWindows && error.code === "EPERM") {
|
|
7078
7214
|
try {
|
|
7079
|
-
const fd = await open(
|
|
7215
|
+
const fd = await open(path7, "r");
|
|
7080
7216
|
await fd.close();
|
|
7081
7217
|
broadcastErr(error);
|
|
7082
7218
|
} catch (err) {}
|
|
@@ -7106,7 +7242,7 @@ var setFsWatchListener = (path6, fullPath, options, handlers) => {
|
|
|
7106
7242
|
};
|
|
7107
7243
|
};
|
|
7108
7244
|
var FsWatchFileInstances = new Map;
|
|
7109
|
-
var setFsWatchFileListener = (
|
|
7245
|
+
var setFsWatchFileListener = (path7, fullPath, options, handlers) => {
|
|
7110
7246
|
const { listener, rawEmitter } = handlers;
|
|
7111
7247
|
let cont = FsWatchFileInstances.get(fullPath);
|
|
7112
7248
|
const copts = cont && cont.options;
|
|
@@ -7128,7 +7264,7 @@ var setFsWatchFileListener = (path6, fullPath, options, handlers) => {
|
|
|
7128
7264
|
});
|
|
7129
7265
|
const currmtime = curr.mtimeMs;
|
|
7130
7266
|
if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
|
|
7131
|
-
foreach(cont.listeners, (listener2) => listener2(
|
|
7267
|
+
foreach(cont.listeners, (listener2) => listener2(path7, curr));
|
|
7132
7268
|
}
|
|
7133
7269
|
})
|
|
7134
7270
|
};
|
|
@@ -7153,13 +7289,13 @@ class NodeFsHandler {
|
|
|
7153
7289
|
this.fsw = fsW;
|
|
7154
7290
|
this._boundHandleError = (error) => fsW._handleError(error);
|
|
7155
7291
|
}
|
|
7156
|
-
_watchWithNodeFs(
|
|
7292
|
+
_watchWithNodeFs(path7, listener) {
|
|
7157
7293
|
const opts = this.fsw.options;
|
|
7158
|
-
const directory = sp.dirname(
|
|
7159
|
-
const basename2 = sp.basename(
|
|
7294
|
+
const directory = sp.dirname(path7);
|
|
7295
|
+
const basename2 = sp.basename(path7);
|
|
7160
7296
|
const parent = this.fsw._getWatchedDir(directory);
|
|
7161
7297
|
parent.add(basename2);
|
|
7162
|
-
const absolutePath = sp.resolve(
|
|
7298
|
+
const absolutePath = sp.resolve(path7);
|
|
7163
7299
|
const options = {
|
|
7164
7300
|
persistent: opts.persistent
|
|
7165
7301
|
};
|
|
@@ -7169,12 +7305,12 @@ class NodeFsHandler {
|
|
|
7169
7305
|
if (opts.usePolling) {
|
|
7170
7306
|
const enableBin = opts.interval !== opts.binaryInterval;
|
|
7171
7307
|
options.interval = enableBin && isBinaryPath(basename2) ? opts.binaryInterval : opts.interval;
|
|
7172
|
-
closer = setFsWatchFileListener(
|
|
7308
|
+
closer = setFsWatchFileListener(path7, absolutePath, options, {
|
|
7173
7309
|
listener,
|
|
7174
7310
|
rawEmitter: this.fsw._emitRaw
|
|
7175
7311
|
});
|
|
7176
7312
|
} else {
|
|
7177
|
-
closer = setFsWatchListener(
|
|
7313
|
+
closer = setFsWatchListener(path7, absolutePath, options, {
|
|
7178
7314
|
listener,
|
|
7179
7315
|
errHandler: this._boundHandleError,
|
|
7180
7316
|
rawEmitter: this.fsw._emitRaw
|
|
@@ -7192,7 +7328,7 @@ class NodeFsHandler {
|
|
|
7192
7328
|
let prevStats = stats;
|
|
7193
7329
|
if (parent.has(basename2))
|
|
7194
7330
|
return;
|
|
7195
|
-
const listener = async (
|
|
7331
|
+
const listener = async (path7, newStats) => {
|
|
7196
7332
|
if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
|
|
7197
7333
|
return;
|
|
7198
7334
|
if (!newStats || newStats.mtimeMs === 0) {
|
|
@@ -7206,11 +7342,11 @@ class NodeFsHandler {
|
|
|
7206
7342
|
this.fsw._emit(EV.CHANGE, file, newStats2);
|
|
7207
7343
|
}
|
|
7208
7344
|
if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
|
|
7209
|
-
this.fsw._closeFile(
|
|
7345
|
+
this.fsw._closeFile(path7);
|
|
7210
7346
|
prevStats = newStats2;
|
|
7211
7347
|
const closer2 = this._watchWithNodeFs(file, listener);
|
|
7212
7348
|
if (closer2)
|
|
7213
|
-
this.fsw._addPathCloser(
|
|
7349
|
+
this.fsw._addPathCloser(path7, closer2);
|
|
7214
7350
|
} else {
|
|
7215
7351
|
prevStats = newStats2;
|
|
7216
7352
|
}
|
|
@@ -7234,7 +7370,7 @@ class NodeFsHandler {
|
|
|
7234
7370
|
}
|
|
7235
7371
|
return closer;
|
|
7236
7372
|
}
|
|
7237
|
-
async _handleSymlink(entry, directory,
|
|
7373
|
+
async _handleSymlink(entry, directory, path7, item) {
|
|
7238
7374
|
if (this.fsw.closed) {
|
|
7239
7375
|
return;
|
|
7240
7376
|
}
|
|
@@ -7244,7 +7380,7 @@ class NodeFsHandler {
|
|
|
7244
7380
|
this.fsw._incrReadyCount();
|
|
7245
7381
|
let linkPath;
|
|
7246
7382
|
try {
|
|
7247
|
-
linkPath = await fsrealpath(
|
|
7383
|
+
linkPath = await fsrealpath(path7);
|
|
7248
7384
|
} catch (e) {
|
|
7249
7385
|
this.fsw._emitReady();
|
|
7250
7386
|
return true;
|
|
@@ -7254,12 +7390,12 @@ class NodeFsHandler {
|
|
|
7254
7390
|
if (dir.has(item)) {
|
|
7255
7391
|
if (this.fsw._symlinkPaths.get(full) !== linkPath) {
|
|
7256
7392
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
7257
|
-
this.fsw._emit(EV.CHANGE,
|
|
7393
|
+
this.fsw._emit(EV.CHANGE, path7, entry.stats);
|
|
7258
7394
|
}
|
|
7259
7395
|
} else {
|
|
7260
7396
|
dir.add(item);
|
|
7261
7397
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
7262
|
-
this.fsw._emit(EV.ADD,
|
|
7398
|
+
this.fsw._emit(EV.ADD, path7, entry.stats);
|
|
7263
7399
|
}
|
|
7264
7400
|
this.fsw._emitReady();
|
|
7265
7401
|
return true;
|
|
@@ -7289,9 +7425,9 @@ class NodeFsHandler {
|
|
|
7289
7425
|
return;
|
|
7290
7426
|
}
|
|
7291
7427
|
const item = entry.path;
|
|
7292
|
-
let
|
|
7428
|
+
let path7 = sp.join(directory, item);
|
|
7293
7429
|
current.add(item);
|
|
7294
|
-
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory,
|
|
7430
|
+
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path7, item)) {
|
|
7295
7431
|
return;
|
|
7296
7432
|
}
|
|
7297
7433
|
if (this.fsw.closed) {
|
|
@@ -7300,8 +7436,8 @@ class NodeFsHandler {
|
|
|
7300
7436
|
}
|
|
7301
7437
|
if (item === target || !target && !previous.has(item)) {
|
|
7302
7438
|
this.fsw._incrReadyCount();
|
|
7303
|
-
|
|
7304
|
-
this._addToNodeFs(
|
|
7439
|
+
path7 = sp.join(dir, sp.relative(dir, path7));
|
|
7440
|
+
this._addToNodeFs(path7, initialAdd, wh, depth + 1);
|
|
7305
7441
|
}
|
|
7306
7442
|
}).on(EV.ERROR, this._boundHandleError);
|
|
7307
7443
|
return new Promise((resolve2, reject) => {
|
|
@@ -7350,13 +7486,13 @@ class NodeFsHandler {
|
|
|
7350
7486
|
}
|
|
7351
7487
|
return closer;
|
|
7352
7488
|
}
|
|
7353
|
-
async _addToNodeFs(
|
|
7489
|
+
async _addToNodeFs(path7, initialAdd, priorWh, depth, target) {
|
|
7354
7490
|
const ready = this.fsw._emitReady;
|
|
7355
|
-
if (this.fsw._isIgnored(
|
|
7491
|
+
if (this.fsw._isIgnored(path7) || this.fsw.closed) {
|
|
7356
7492
|
ready();
|
|
7357
7493
|
return false;
|
|
7358
7494
|
}
|
|
7359
|
-
const wh = this.fsw._getWatchHelpers(
|
|
7495
|
+
const wh = this.fsw._getWatchHelpers(path7);
|
|
7360
7496
|
if (priorWh) {
|
|
7361
7497
|
wh.filterPath = (entry) => priorWh.filterPath(entry);
|
|
7362
7498
|
wh.filterDir = (entry) => priorWh.filterDir(entry);
|
|
@@ -7372,8 +7508,8 @@ class NodeFsHandler {
|
|
|
7372
7508
|
const follow = this.fsw.options.followSymlinks;
|
|
7373
7509
|
let closer;
|
|
7374
7510
|
if (stats.isDirectory()) {
|
|
7375
|
-
const absPath = sp.resolve(
|
|
7376
|
-
const targetPath = follow ? await fsrealpath(
|
|
7511
|
+
const absPath = sp.resolve(path7);
|
|
7512
|
+
const targetPath = follow ? await fsrealpath(path7) : path7;
|
|
7377
7513
|
if (this.fsw.closed)
|
|
7378
7514
|
return;
|
|
7379
7515
|
closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
|
|
@@ -7383,29 +7519,29 @@ class NodeFsHandler {
|
|
|
7383
7519
|
this.fsw._symlinkPaths.set(absPath, targetPath);
|
|
7384
7520
|
}
|
|
7385
7521
|
} else if (stats.isSymbolicLink()) {
|
|
7386
|
-
const targetPath = follow ? await fsrealpath(
|
|
7522
|
+
const targetPath = follow ? await fsrealpath(path7) : path7;
|
|
7387
7523
|
if (this.fsw.closed)
|
|
7388
7524
|
return;
|
|
7389
7525
|
const parent = sp.dirname(wh.watchPath);
|
|
7390
7526
|
this.fsw._getWatchedDir(parent).add(wh.watchPath);
|
|
7391
7527
|
this.fsw._emit(EV.ADD, wh.watchPath, stats);
|
|
7392
|
-
closer = await this._handleDir(parent, stats, initialAdd, depth,
|
|
7528
|
+
closer = await this._handleDir(parent, stats, initialAdd, depth, path7, wh, targetPath);
|
|
7393
7529
|
if (this.fsw.closed)
|
|
7394
7530
|
return;
|
|
7395
7531
|
if (targetPath !== undefined) {
|
|
7396
|
-
this.fsw._symlinkPaths.set(sp.resolve(
|
|
7532
|
+
this.fsw._symlinkPaths.set(sp.resolve(path7), targetPath);
|
|
7397
7533
|
}
|
|
7398
7534
|
} else {
|
|
7399
7535
|
closer = this._handleFile(wh.watchPath, stats, initialAdd);
|
|
7400
7536
|
}
|
|
7401
7537
|
ready();
|
|
7402
7538
|
if (closer)
|
|
7403
|
-
this.fsw._addPathCloser(
|
|
7539
|
+
this.fsw._addPathCloser(path7, closer);
|
|
7404
7540
|
return false;
|
|
7405
7541
|
} catch (error) {
|
|
7406
7542
|
if (this.fsw._handleError(error)) {
|
|
7407
7543
|
ready();
|
|
7408
|
-
return
|
|
7544
|
+
return path7;
|
|
7409
7545
|
}
|
|
7410
7546
|
}
|
|
7411
7547
|
}
|
|
@@ -7449,24 +7585,24 @@ function createPattern(matcher) {
|
|
|
7449
7585
|
}
|
|
7450
7586
|
return () => false;
|
|
7451
7587
|
}
|
|
7452
|
-
function normalizePath(
|
|
7453
|
-
if (typeof
|
|
7588
|
+
function normalizePath(path7) {
|
|
7589
|
+
if (typeof path7 !== "string")
|
|
7454
7590
|
throw new Error("string expected");
|
|
7455
|
-
|
|
7456
|
-
|
|
7591
|
+
path7 = sp2.normalize(path7);
|
|
7592
|
+
path7 = path7.replace(/\\/g, "/");
|
|
7457
7593
|
let prepend = false;
|
|
7458
|
-
if (
|
|
7594
|
+
if (path7.startsWith("//"))
|
|
7459
7595
|
prepend = true;
|
|
7460
|
-
|
|
7596
|
+
path7 = path7.replace(DOUBLE_SLASH_RE, "/");
|
|
7461
7597
|
if (prepend)
|
|
7462
|
-
|
|
7463
|
-
return
|
|
7598
|
+
path7 = "/" + path7;
|
|
7599
|
+
return path7;
|
|
7464
7600
|
}
|
|
7465
7601
|
function matchPatterns(patterns, testString, stats) {
|
|
7466
|
-
const
|
|
7602
|
+
const path7 = normalizePath(testString);
|
|
7467
7603
|
for (let index = 0;index < patterns.length; index++) {
|
|
7468
7604
|
const pattern = patterns[index];
|
|
7469
|
-
if (pattern(
|
|
7605
|
+
if (pattern(path7, stats)) {
|
|
7470
7606
|
return true;
|
|
7471
7607
|
}
|
|
7472
7608
|
}
|
|
@@ -7504,19 +7640,19 @@ var toUnix = (string) => {
|
|
|
7504
7640
|
}
|
|
7505
7641
|
return str;
|
|
7506
7642
|
};
|
|
7507
|
-
var normalizePathToUnix = (
|
|
7508
|
-
var normalizeIgnored = (cwd = "") => (
|
|
7509
|
-
if (typeof
|
|
7510
|
-
return normalizePathToUnix(sp2.isAbsolute(
|
|
7643
|
+
var normalizePathToUnix = (path7) => toUnix(sp2.normalize(toUnix(path7)));
|
|
7644
|
+
var normalizeIgnored = (cwd = "") => (path7) => {
|
|
7645
|
+
if (typeof path7 === "string") {
|
|
7646
|
+
return normalizePathToUnix(sp2.isAbsolute(path7) ? path7 : sp2.join(cwd, path7));
|
|
7511
7647
|
} else {
|
|
7512
|
-
return
|
|
7648
|
+
return path7;
|
|
7513
7649
|
}
|
|
7514
7650
|
};
|
|
7515
|
-
var getAbsolutePath = (
|
|
7516
|
-
if (sp2.isAbsolute(
|
|
7517
|
-
return
|
|
7651
|
+
var getAbsolutePath = (path7, cwd) => {
|
|
7652
|
+
if (sp2.isAbsolute(path7)) {
|
|
7653
|
+
return path7;
|
|
7518
7654
|
}
|
|
7519
|
-
return sp2.join(cwd,
|
|
7655
|
+
return sp2.join(cwd, path7);
|
|
7520
7656
|
};
|
|
7521
7657
|
var EMPTY_SET = Object.freeze(new Set);
|
|
7522
7658
|
|
|
@@ -7583,10 +7719,10 @@ class WatchHelper {
|
|
|
7583
7719
|
dirParts;
|
|
7584
7720
|
followSymlinks;
|
|
7585
7721
|
statMethod;
|
|
7586
|
-
constructor(
|
|
7722
|
+
constructor(path7, follow, fsw) {
|
|
7587
7723
|
this.fsw = fsw;
|
|
7588
|
-
const watchPath =
|
|
7589
|
-
this.path =
|
|
7724
|
+
const watchPath = path7;
|
|
7725
|
+
this.path = path7 = path7.replace(REPLACER_RE, "");
|
|
7590
7726
|
this.watchPath = watchPath;
|
|
7591
7727
|
this.fullWatchPath = sp2.resolve(watchPath);
|
|
7592
7728
|
this.dirParts = [];
|
|
@@ -7717,20 +7853,20 @@ class FSWatcher extends EventEmitter2 {
|
|
|
7717
7853
|
this._closePromise = undefined;
|
|
7718
7854
|
let paths = unifyPaths(paths_);
|
|
7719
7855
|
if (cwd) {
|
|
7720
|
-
paths = paths.map((
|
|
7721
|
-
const absPath = getAbsolutePath(
|
|
7856
|
+
paths = paths.map((path7) => {
|
|
7857
|
+
const absPath = getAbsolutePath(path7, cwd);
|
|
7722
7858
|
return absPath;
|
|
7723
7859
|
});
|
|
7724
7860
|
}
|
|
7725
|
-
paths.forEach((
|
|
7726
|
-
this._removeIgnoredPath(
|
|
7861
|
+
paths.forEach((path7) => {
|
|
7862
|
+
this._removeIgnoredPath(path7);
|
|
7727
7863
|
});
|
|
7728
7864
|
this._userIgnored = undefined;
|
|
7729
7865
|
if (!this._readyCount)
|
|
7730
7866
|
this._readyCount = 0;
|
|
7731
7867
|
this._readyCount += paths.length;
|
|
7732
|
-
Promise.all(paths.map(async (
|
|
7733
|
-
const res = await this._nodeFsHandler._addToNodeFs(
|
|
7868
|
+
Promise.all(paths.map(async (path7) => {
|
|
7869
|
+
const res = await this._nodeFsHandler._addToNodeFs(path7, !_internal, undefined, 0, _origAdd);
|
|
7734
7870
|
if (res)
|
|
7735
7871
|
this._emitReady();
|
|
7736
7872
|
return res;
|
|
@@ -7749,17 +7885,17 @@ class FSWatcher extends EventEmitter2 {
|
|
|
7749
7885
|
return this;
|
|
7750
7886
|
const paths = unifyPaths(paths_);
|
|
7751
7887
|
const { cwd } = this.options;
|
|
7752
|
-
paths.forEach((
|
|
7753
|
-
if (!sp2.isAbsolute(
|
|
7888
|
+
paths.forEach((path7) => {
|
|
7889
|
+
if (!sp2.isAbsolute(path7) && !this._closers.has(path7)) {
|
|
7754
7890
|
if (cwd)
|
|
7755
|
-
|
|
7756
|
-
|
|
7891
|
+
path7 = sp2.join(cwd, path7);
|
|
7892
|
+
path7 = sp2.resolve(path7);
|
|
7757
7893
|
}
|
|
7758
|
-
this._closePath(
|
|
7759
|
-
this._addIgnoredPath(
|
|
7760
|
-
if (this._watched.has(
|
|
7894
|
+
this._closePath(path7);
|
|
7895
|
+
this._addIgnoredPath(path7);
|
|
7896
|
+
if (this._watched.has(path7)) {
|
|
7761
7897
|
this._addIgnoredPath({
|
|
7762
|
-
path:
|
|
7898
|
+
path: path7,
|
|
7763
7899
|
recursive: true
|
|
7764
7900
|
});
|
|
7765
7901
|
}
|
|
@@ -7808,38 +7944,38 @@ class FSWatcher extends EventEmitter2 {
|
|
|
7808
7944
|
if (event !== EVENTS.ERROR)
|
|
7809
7945
|
this.emit(EVENTS.ALL, event, ...args);
|
|
7810
7946
|
}
|
|
7811
|
-
async _emit(event,
|
|
7947
|
+
async _emit(event, path7, stats) {
|
|
7812
7948
|
if (this.closed)
|
|
7813
7949
|
return;
|
|
7814
7950
|
const opts = this.options;
|
|
7815
7951
|
if (isWindows)
|
|
7816
|
-
|
|
7952
|
+
path7 = sp2.normalize(path7);
|
|
7817
7953
|
if (opts.cwd)
|
|
7818
|
-
|
|
7819
|
-
const args = [
|
|
7954
|
+
path7 = sp2.relative(opts.cwd, path7);
|
|
7955
|
+
const args = [path7];
|
|
7820
7956
|
if (stats != null)
|
|
7821
7957
|
args.push(stats);
|
|
7822
7958
|
const awf = opts.awaitWriteFinish;
|
|
7823
7959
|
let pw;
|
|
7824
|
-
if (awf && (pw = this._pendingWrites.get(
|
|
7960
|
+
if (awf && (pw = this._pendingWrites.get(path7))) {
|
|
7825
7961
|
pw.lastChange = new Date;
|
|
7826
7962
|
return this;
|
|
7827
7963
|
}
|
|
7828
7964
|
if (opts.atomic) {
|
|
7829
7965
|
if (event === EVENTS.UNLINK) {
|
|
7830
|
-
this._pendingUnlinks.set(
|
|
7966
|
+
this._pendingUnlinks.set(path7, [event, ...args]);
|
|
7831
7967
|
setTimeout(() => {
|
|
7832
|
-
this._pendingUnlinks.forEach((entry,
|
|
7968
|
+
this._pendingUnlinks.forEach((entry, path8) => {
|
|
7833
7969
|
this.emit(...entry);
|
|
7834
7970
|
this.emit(EVENTS.ALL, ...entry);
|
|
7835
|
-
this._pendingUnlinks.delete(
|
|
7971
|
+
this._pendingUnlinks.delete(path8);
|
|
7836
7972
|
});
|
|
7837
7973
|
}, typeof opts.atomic === "number" ? opts.atomic : 100);
|
|
7838
7974
|
return this;
|
|
7839
7975
|
}
|
|
7840
|
-
if (event === EVENTS.ADD && this._pendingUnlinks.has(
|
|
7976
|
+
if (event === EVENTS.ADD && this._pendingUnlinks.has(path7)) {
|
|
7841
7977
|
event = EVENTS.CHANGE;
|
|
7842
|
-
this._pendingUnlinks.delete(
|
|
7978
|
+
this._pendingUnlinks.delete(path7);
|
|
7843
7979
|
}
|
|
7844
7980
|
}
|
|
7845
7981
|
if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
|
|
@@ -7857,16 +7993,16 @@ class FSWatcher extends EventEmitter2 {
|
|
|
7857
7993
|
this.emitWithAll(event, args);
|
|
7858
7994
|
}
|
|
7859
7995
|
};
|
|
7860
|
-
this._awaitWriteFinish(
|
|
7996
|
+
this._awaitWriteFinish(path7, awf.stabilityThreshold, event, awfEmit);
|
|
7861
7997
|
return this;
|
|
7862
7998
|
}
|
|
7863
7999
|
if (event === EVENTS.CHANGE) {
|
|
7864
|
-
const isThrottled = !this._throttle(EVENTS.CHANGE,
|
|
8000
|
+
const isThrottled = !this._throttle(EVENTS.CHANGE, path7, 50);
|
|
7865
8001
|
if (isThrottled)
|
|
7866
8002
|
return this;
|
|
7867
8003
|
}
|
|
7868
8004
|
if (opts.alwaysStat && stats === undefined && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
|
|
7869
|
-
const fullPath = opts.cwd ? sp2.join(opts.cwd,
|
|
8005
|
+
const fullPath = opts.cwd ? sp2.join(opts.cwd, path7) : path7;
|
|
7870
8006
|
let stats2;
|
|
7871
8007
|
try {
|
|
7872
8008
|
stats2 = await stat3(fullPath);
|
|
@@ -7885,23 +8021,23 @@ class FSWatcher extends EventEmitter2 {
|
|
|
7885
8021
|
}
|
|
7886
8022
|
return error || this.closed;
|
|
7887
8023
|
}
|
|
7888
|
-
_throttle(actionType,
|
|
8024
|
+
_throttle(actionType, path7, timeout) {
|
|
7889
8025
|
if (!this._throttled.has(actionType)) {
|
|
7890
8026
|
this._throttled.set(actionType, new Map);
|
|
7891
8027
|
}
|
|
7892
8028
|
const action = this._throttled.get(actionType);
|
|
7893
8029
|
if (!action)
|
|
7894
8030
|
throw new Error("invalid throttle");
|
|
7895
|
-
const actionPath = action.get(
|
|
8031
|
+
const actionPath = action.get(path7);
|
|
7896
8032
|
if (actionPath) {
|
|
7897
8033
|
actionPath.count++;
|
|
7898
8034
|
return false;
|
|
7899
8035
|
}
|
|
7900
8036
|
let timeoutObject;
|
|
7901
8037
|
const clear = () => {
|
|
7902
|
-
const item = action.get(
|
|
8038
|
+
const item = action.get(path7);
|
|
7903
8039
|
const count = item ? item.count : 0;
|
|
7904
|
-
action.delete(
|
|
8040
|
+
action.delete(path7);
|
|
7905
8041
|
clearTimeout(timeoutObject);
|
|
7906
8042
|
if (item)
|
|
7907
8043
|
clearTimeout(item.timeoutObject);
|
|
@@ -7909,50 +8045,50 @@ class FSWatcher extends EventEmitter2 {
|
|
|
7909
8045
|
};
|
|
7910
8046
|
timeoutObject = setTimeout(clear, timeout);
|
|
7911
8047
|
const thr = { timeoutObject, clear, count: 0 };
|
|
7912
|
-
action.set(
|
|
8048
|
+
action.set(path7, thr);
|
|
7913
8049
|
return thr;
|
|
7914
8050
|
}
|
|
7915
8051
|
_incrReadyCount() {
|
|
7916
8052
|
return this._readyCount++;
|
|
7917
8053
|
}
|
|
7918
|
-
_awaitWriteFinish(
|
|
8054
|
+
_awaitWriteFinish(path7, threshold, event, awfEmit) {
|
|
7919
8055
|
const awf = this.options.awaitWriteFinish;
|
|
7920
8056
|
if (typeof awf !== "object")
|
|
7921
8057
|
return;
|
|
7922
8058
|
const pollInterval = awf.pollInterval;
|
|
7923
8059
|
let timeoutHandler;
|
|
7924
|
-
let fullPath =
|
|
7925
|
-
if (this.options.cwd && !sp2.isAbsolute(
|
|
7926
|
-
fullPath = sp2.join(this.options.cwd,
|
|
8060
|
+
let fullPath = path7;
|
|
8061
|
+
if (this.options.cwd && !sp2.isAbsolute(path7)) {
|
|
8062
|
+
fullPath = sp2.join(this.options.cwd, path7);
|
|
7927
8063
|
}
|
|
7928
8064
|
const now = new Date;
|
|
7929
8065
|
const writes = this._pendingWrites;
|
|
7930
8066
|
function awaitWriteFinishFn(prevStat) {
|
|
7931
8067
|
statcb(fullPath, (err, curStat) => {
|
|
7932
|
-
if (err || !writes.has(
|
|
8068
|
+
if (err || !writes.has(path7)) {
|
|
7933
8069
|
if (err && err.code !== "ENOENT")
|
|
7934
8070
|
awfEmit(err);
|
|
7935
8071
|
return;
|
|
7936
8072
|
}
|
|
7937
8073
|
const now2 = Number(new Date);
|
|
7938
8074
|
if (prevStat && curStat.size !== prevStat.size) {
|
|
7939
|
-
writes.get(
|
|
8075
|
+
writes.get(path7).lastChange = now2;
|
|
7940
8076
|
}
|
|
7941
|
-
const pw = writes.get(
|
|
8077
|
+
const pw = writes.get(path7);
|
|
7942
8078
|
const df = now2 - pw.lastChange;
|
|
7943
8079
|
if (df >= threshold) {
|
|
7944
|
-
writes.delete(
|
|
8080
|
+
writes.delete(path7);
|
|
7945
8081
|
awfEmit(undefined, curStat);
|
|
7946
8082
|
} else {
|
|
7947
8083
|
timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
|
|
7948
8084
|
}
|
|
7949
8085
|
});
|
|
7950
8086
|
}
|
|
7951
|
-
if (!writes.has(
|
|
7952
|
-
writes.set(
|
|
8087
|
+
if (!writes.has(path7)) {
|
|
8088
|
+
writes.set(path7, {
|
|
7953
8089
|
lastChange: now,
|
|
7954
8090
|
cancelWait: () => {
|
|
7955
|
-
writes.delete(
|
|
8091
|
+
writes.delete(path7);
|
|
7956
8092
|
clearTimeout(timeoutHandler);
|
|
7957
8093
|
return event;
|
|
7958
8094
|
}
|
|
@@ -7960,8 +8096,8 @@ class FSWatcher extends EventEmitter2 {
|
|
|
7960
8096
|
timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval);
|
|
7961
8097
|
}
|
|
7962
8098
|
}
|
|
7963
|
-
_isIgnored(
|
|
7964
|
-
if (this.options.atomic && DOT_RE.test(
|
|
8099
|
+
_isIgnored(path7, stats) {
|
|
8100
|
+
if (this.options.atomic && DOT_RE.test(path7))
|
|
7965
8101
|
return true;
|
|
7966
8102
|
if (!this._userIgnored) {
|
|
7967
8103
|
const { cwd } = this.options;
|
|
@@ -7971,13 +8107,13 @@ class FSWatcher extends EventEmitter2 {
|
|
|
7971
8107
|
const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
|
|
7972
8108
|
this._userIgnored = anymatch(list, undefined);
|
|
7973
8109
|
}
|
|
7974
|
-
return this._userIgnored(
|
|
8110
|
+
return this._userIgnored(path7, stats);
|
|
7975
8111
|
}
|
|
7976
|
-
_isntIgnored(
|
|
7977
|
-
return !this._isIgnored(
|
|
8112
|
+
_isntIgnored(path7, stat4) {
|
|
8113
|
+
return !this._isIgnored(path7, stat4);
|
|
7978
8114
|
}
|
|
7979
|
-
_getWatchHelpers(
|
|
7980
|
-
return new WatchHelper(
|
|
8115
|
+
_getWatchHelpers(path7) {
|
|
8116
|
+
return new WatchHelper(path7, this.options.followSymlinks, this);
|
|
7981
8117
|
}
|
|
7982
8118
|
_getWatchedDir(directory) {
|
|
7983
8119
|
const dir = sp2.resolve(directory);
|
|
@@ -7991,57 +8127,57 @@ class FSWatcher extends EventEmitter2 {
|
|
|
7991
8127
|
return Boolean(Number(stats.mode) & 256);
|
|
7992
8128
|
}
|
|
7993
8129
|
_remove(directory, item, isDirectory) {
|
|
7994
|
-
const
|
|
7995
|
-
const fullPath = sp2.resolve(
|
|
7996
|
-
isDirectory = isDirectory != null ? isDirectory : this._watched.has(
|
|
7997
|
-
if (!this._throttle("remove",
|
|
8130
|
+
const path7 = sp2.join(directory, item);
|
|
8131
|
+
const fullPath = sp2.resolve(path7);
|
|
8132
|
+
isDirectory = isDirectory != null ? isDirectory : this._watched.has(path7) || this._watched.has(fullPath);
|
|
8133
|
+
if (!this._throttle("remove", path7, 100))
|
|
7998
8134
|
return;
|
|
7999
8135
|
if (!isDirectory && this._watched.size === 1) {
|
|
8000
8136
|
this.add(directory, item, true);
|
|
8001
8137
|
}
|
|
8002
|
-
const wp = this._getWatchedDir(
|
|
8138
|
+
const wp = this._getWatchedDir(path7);
|
|
8003
8139
|
const nestedDirectoryChildren = wp.getChildren();
|
|
8004
|
-
nestedDirectoryChildren.forEach((nested) => this._remove(
|
|
8140
|
+
nestedDirectoryChildren.forEach((nested) => this._remove(path7, nested));
|
|
8005
8141
|
const parent = this._getWatchedDir(directory);
|
|
8006
8142
|
const wasTracked = parent.has(item);
|
|
8007
8143
|
parent.remove(item);
|
|
8008
8144
|
if (this._symlinkPaths.has(fullPath)) {
|
|
8009
8145
|
this._symlinkPaths.delete(fullPath);
|
|
8010
8146
|
}
|
|
8011
|
-
let relPath =
|
|
8147
|
+
let relPath = path7;
|
|
8012
8148
|
if (this.options.cwd)
|
|
8013
|
-
relPath = sp2.relative(this.options.cwd,
|
|
8149
|
+
relPath = sp2.relative(this.options.cwd, path7);
|
|
8014
8150
|
if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
|
|
8015
8151
|
const event = this._pendingWrites.get(relPath).cancelWait();
|
|
8016
8152
|
if (event === EVENTS.ADD)
|
|
8017
8153
|
return;
|
|
8018
8154
|
}
|
|
8019
|
-
this._watched.delete(
|
|
8155
|
+
this._watched.delete(path7);
|
|
8020
8156
|
this._watched.delete(fullPath);
|
|
8021
8157
|
const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
|
|
8022
|
-
if (wasTracked && !this._isIgnored(
|
|
8023
|
-
this._emit(eventName,
|
|
8024
|
-
this._closePath(
|
|
8158
|
+
if (wasTracked && !this._isIgnored(path7))
|
|
8159
|
+
this._emit(eventName, path7);
|
|
8160
|
+
this._closePath(path7);
|
|
8025
8161
|
}
|
|
8026
|
-
_closePath(
|
|
8027
|
-
this._closeFile(
|
|
8028
|
-
const dir = sp2.dirname(
|
|
8029
|
-
this._getWatchedDir(dir).remove(sp2.basename(
|
|
8162
|
+
_closePath(path7) {
|
|
8163
|
+
this._closeFile(path7);
|
|
8164
|
+
const dir = sp2.dirname(path7);
|
|
8165
|
+
this._getWatchedDir(dir).remove(sp2.basename(path7));
|
|
8030
8166
|
}
|
|
8031
|
-
_closeFile(
|
|
8032
|
-
const closers = this._closers.get(
|
|
8167
|
+
_closeFile(path7) {
|
|
8168
|
+
const closers = this._closers.get(path7);
|
|
8033
8169
|
if (!closers)
|
|
8034
8170
|
return;
|
|
8035
8171
|
closers.forEach((closer) => closer());
|
|
8036
|
-
this._closers.delete(
|
|
8172
|
+
this._closers.delete(path7);
|
|
8037
8173
|
}
|
|
8038
|
-
_addPathCloser(
|
|
8174
|
+
_addPathCloser(path7, closer) {
|
|
8039
8175
|
if (!closer)
|
|
8040
8176
|
return;
|
|
8041
|
-
let list = this._closers.get(
|
|
8177
|
+
let list = this._closers.get(path7);
|
|
8042
8178
|
if (!list) {
|
|
8043
8179
|
list = [];
|
|
8044
|
-
this._closers.set(
|
|
8180
|
+
this._closers.set(path7, list);
|
|
8045
8181
|
}
|
|
8046
8182
|
list.push(closer);
|
|
8047
8183
|
}
|
|
@@ -8071,7 +8207,7 @@ function watch(paths, options = {}) {
|
|
|
8071
8207
|
var chokidar_default = { watch, FSWatcher };
|
|
8072
8208
|
|
|
8073
8209
|
// src/core/watcher.ts
|
|
8074
|
-
import
|
|
8210
|
+
import path7 from "node:path";
|
|
8075
8211
|
function formatTime() {
|
|
8076
8212
|
const now = new Date;
|
|
8077
8213
|
const hours = String(now.getHours()).padStart(2, "0");
|
|
@@ -8104,7 +8240,7 @@ function getWatchPaths(operations) {
|
|
|
8104
8240
|
return Array.from(paths);
|
|
8105
8241
|
}
|
|
8106
8242
|
async function handleFileChange(changedPath, state, options) {
|
|
8107
|
-
const relPath =
|
|
8243
|
+
const relPath = path7.relative(options.cwd || process.cwd(), changedPath);
|
|
8108
8244
|
if (!logger.isSilent() && !options.verbose) {
|
|
8109
8245
|
console.log(`[${formatTime()}] Changed: ${relPath}`);
|
|
8110
8246
|
}
|
|
@@ -8118,9 +8254,9 @@ async function handleFileChange(changedPath, state, options) {
|
|
|
8118
8254
|
for (const op of affectedOps) {
|
|
8119
8255
|
const result = await performMerge(op);
|
|
8120
8256
|
if (result.success && result.changed) {
|
|
8121
|
-
const baseFile = op.basePath ?
|
|
8122
|
-
const machineFile =
|
|
8123
|
-
const outputFile =
|
|
8257
|
+
const baseFile = op.basePath ? path7.basename(op.basePath) : "";
|
|
8258
|
+
const machineFile = path7.basename(op.machinePath);
|
|
8259
|
+
const outputFile = path7.basename(op.outputPath);
|
|
8124
8260
|
if (!logger.isSilent()) {
|
|
8125
8261
|
if (baseFile) {
|
|
8126
8262
|
console.log(`[${formatTime()}] Merged ${baseFile} + ${machineFile} → ${outputFile}`);
|
|
@@ -8131,7 +8267,7 @@ async function handleFileChange(changedPath, state, options) {
|
|
|
8131
8267
|
} else if (!result.success && result.error) {
|
|
8132
8268
|
logger.error(`Failed to merge: ${result.error.message}`);
|
|
8133
8269
|
} else if (options.verbose && !result.changed) {
|
|
8134
|
-
logger.info(`No changes needed for ${
|
|
8270
|
+
logger.info(`No changes needed for ${path7.basename(op.outputPath)}`);
|
|
8135
8271
|
}
|
|
8136
8272
|
}
|
|
8137
8273
|
if (!logger.isSilent() && !options.verbose) {
|
|
@@ -8162,7 +8298,7 @@ async function startWatcher(machineName, options = {}) {
|
|
|
8162
8298
|
if (!logger.isSilent()) {
|
|
8163
8299
|
console.log(`✓ Watching ${watchPaths.length} file(s) for changes...`);
|
|
8164
8300
|
for (const watchPath of watchPaths) {
|
|
8165
|
-
console.log(` - ${
|
|
8301
|
+
console.log(` - ${path7.relative(cwd, watchPath)}`);
|
|
8166
8302
|
}
|
|
8167
8303
|
console.log("");
|
|
8168
8304
|
}
|
|
@@ -8175,9 +8311,9 @@ async function startWatcher(machineName, options = {}) {
|
|
|
8175
8311
|
}
|
|
8176
8312
|
});
|
|
8177
8313
|
watcher.on("change", (changedPath) => {
|
|
8178
|
-
const absolutePath =
|
|
8314
|
+
const absolutePath = path7.resolve(cwd, changedPath);
|
|
8179
8315
|
if (options.verbose) {
|
|
8180
|
-
logger.info(`File changed: ${
|
|
8316
|
+
logger.info(`File changed: ${path7.relative(cwd, absolutePath)}`);
|
|
8181
8317
|
}
|
|
8182
8318
|
const existingTimer = state.debounceTimers.get(absolutePath);
|
|
8183
8319
|
if (existingTimer) {
|
|
@@ -8190,9 +8326,9 @@ async function startWatcher(machineName, options = {}) {
|
|
|
8190
8326
|
state.debounceTimers.set(absolutePath, timer);
|
|
8191
8327
|
});
|
|
8192
8328
|
watcher.on("add", async (addedPath) => {
|
|
8193
|
-
const absolutePath =
|
|
8329
|
+
const absolutePath = path7.resolve(cwd, addedPath);
|
|
8194
8330
|
if (options.verbose) {
|
|
8195
|
-
logger.info(`File added: ${
|
|
8331
|
+
logger.info(`File added: ${path7.relative(cwd, absolutePath)}`);
|
|
8196
8332
|
}
|
|
8197
8333
|
const newOperations = await scanForMergeOperations(machineName, cwd);
|
|
8198
8334
|
state.operations = newOperations;
|
|
@@ -8201,7 +8337,7 @@ async function startWatcher(machineName, options = {}) {
|
|
|
8201
8337
|
});
|
|
8202
8338
|
watcher.on("unlink", (deletedPath) => {
|
|
8203
8339
|
if (options.verbose) {
|
|
8204
|
-
const relPath =
|
|
8340
|
+
const relPath = path7.relative(cwd, deletedPath);
|
|
8205
8341
|
logger.warn(`File deleted: ${relPath}`);
|
|
8206
8342
|
logger.info("Run merge manually or restart watch to update operations");
|
|
8207
8343
|
}
|
|
@@ -8222,17 +8358,17 @@ async function startWatcher(machineName, options = {}) {
|
|
|
8222
8358
|
}
|
|
8223
8359
|
|
|
8224
8360
|
// src/cli.ts
|
|
8225
|
-
import
|
|
8226
|
-
import
|
|
8227
|
-
import { fileURLToPath as
|
|
8361
|
+
import fs4 from "node:fs/promises";
|
|
8362
|
+
import path8 from "node:path";
|
|
8363
|
+
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
8228
8364
|
import { createInterface } from "node:readline";
|
|
8229
|
-
var
|
|
8230
|
-
var
|
|
8365
|
+
var __filename3 = fileURLToPath4(import.meta.url);
|
|
8366
|
+
var __dirname3 = path8.dirname(__filename3);
|
|
8231
8367
|
async function checkExistingOutputFiles(operations) {
|
|
8232
8368
|
const existing = [];
|
|
8233
8369
|
for (const op of operations) {
|
|
8234
8370
|
try {
|
|
8235
|
-
await
|
|
8371
|
+
await fs4.access(op.outputPath);
|
|
8236
8372
|
existing.push(op.outputPath);
|
|
8237
8373
|
} catch {}
|
|
8238
8374
|
}
|
|
@@ -8243,8 +8379,8 @@ async function checkTrackedOutputFiles(operations) {
|
|
|
8243
8379
|
const cwd = process.cwd();
|
|
8244
8380
|
for (const op of operations) {
|
|
8245
8381
|
try {
|
|
8246
|
-
await
|
|
8247
|
-
const relativePath =
|
|
8382
|
+
await fs4.access(op.outputPath);
|
|
8383
|
+
const relativePath = path8.relative(cwd, op.outputPath);
|
|
8248
8384
|
const isTracked = await isFileTrackedByGit(relativePath, cwd);
|
|
8249
8385
|
if (isTracked) {
|
|
8250
8386
|
tracked.push(op.outputPath);
|
|
@@ -8267,12 +8403,13 @@ async function promptConfirmation(message) {
|
|
|
8267
8403
|
}
|
|
8268
8404
|
async function main() {
|
|
8269
8405
|
const argv = import_minimist.default(process.argv.slice(2), {
|
|
8270
|
-
boolean: ["help", "version", "silent", "legacy", "auto", "with-package-json", "no-gitignore", "verbose"],
|
|
8406
|
+
boolean: ["help", "version", "silent", "legacy", "auto", "with-package-json", "no-gitignore", "verbose", "yes"],
|
|
8271
8407
|
string: ["debounce"],
|
|
8272
8408
|
alias: {
|
|
8273
8409
|
h: "help",
|
|
8274
8410
|
v: "version",
|
|
8275
|
-
s: "silent"
|
|
8411
|
+
s: "silent",
|
|
8412
|
+
y: "yes"
|
|
8276
8413
|
}
|
|
8277
8414
|
});
|
|
8278
8415
|
const command = argv._[0];
|
|
@@ -8323,10 +8460,10 @@ async function handleInit(argv) {
|
|
|
8323
8460
|
if (trackedFiles.length > 0 && !argv["no-gitignore"]) {
|
|
8324
8461
|
logger.warn("⚠️ Warning: The following files will be overwritten and untracked from git:");
|
|
8325
8462
|
for (const file of trackedFiles) {
|
|
8326
|
-
logger.warn(` - ${
|
|
8463
|
+
logger.warn(` - ${path8.relative(process.cwd(), file)}`);
|
|
8327
8464
|
}
|
|
8328
8465
|
logger.info("");
|
|
8329
|
-
const confirmed = await promptConfirmation("Do you want to continue?");
|
|
8466
|
+
const confirmed = argv.yes || await promptConfirmation("Do you want to continue?");
|
|
8330
8467
|
if (!confirmed) {
|
|
8331
8468
|
logger.info("Aborted.");
|
|
8332
8469
|
process.exit(0);
|
|
@@ -8391,10 +8528,10 @@ async function handleMerge(argv) {
|
|
|
8391
8528
|
if (trackedFiles.length > 0) {
|
|
8392
8529
|
logger.warn("⚠️ Warning: The following files will be overwritten and untracked from git:");
|
|
8393
8530
|
for (const file of trackedFiles) {
|
|
8394
|
-
logger.warn(` - ${
|
|
8531
|
+
logger.warn(` - ${path8.relative(process.cwd(), file)}`);
|
|
8395
8532
|
}
|
|
8396
8533
|
logger.info("");
|
|
8397
|
-
const confirmed = await promptConfirmation("Do you want to continue?");
|
|
8534
|
+
const confirmed = argv.yes || await promptConfirmation("Do you want to continue?");
|
|
8398
8535
|
if (!confirmed) {
|
|
8399
8536
|
logger.info("Aborted.");
|
|
8400
8537
|
process.exit(0);
|
|
@@ -8429,11 +8566,11 @@ async function handleInfo(argv) {
|
|
|
8429
8566
|
const operations = await scanForMergeOperations(machineName);
|
|
8430
8567
|
console.log(`Machine name: ${machineName}`);
|
|
8431
8568
|
console.log(`Repository: ${process.cwd()}`);
|
|
8432
|
-
const { exec:
|
|
8433
|
-
const { promisify:
|
|
8434
|
-
const
|
|
8569
|
+
const { exec: exec3 } = await import("node:child_process");
|
|
8570
|
+
const { promisify: promisify3 } = await import("node:util");
|
|
8571
|
+
const execAsync3 = promisify3(exec3);
|
|
8435
8572
|
try {
|
|
8436
|
-
const { stdout } = await
|
|
8573
|
+
const { stdout } = await execAsync3("git config --get core.hooksPath");
|
|
8437
8574
|
const hooksPath = stdout.trim();
|
|
8438
8575
|
if (hooksPath) {
|
|
8439
8576
|
console.log(`Hooks method: core.hooksPath`);
|
|
@@ -8446,9 +8583,9 @@ async function handleInfo(argv) {
|
|
|
8446
8583
|
}
|
|
8447
8584
|
console.log(`Tracked patterns: ${operations.length}`);
|
|
8448
8585
|
for (const op of operations) {
|
|
8449
|
-
const baseName = op.basePath ?
|
|
8450
|
-
const machineName2 =
|
|
8451
|
-
const outputName =
|
|
8586
|
+
const baseName = op.basePath ? path8.basename(op.basePath) : "(none)";
|
|
8587
|
+
const machineName2 = path8.basename(op.machinePath);
|
|
8588
|
+
const outputName = path8.basename(op.outputPath);
|
|
8452
8589
|
console.log(` - ${baseName} + ${machineName2} → ${outputName}`);
|
|
8453
8590
|
}
|
|
8454
8591
|
if (operations.length > 0) {
|
|
@@ -8458,7 +8595,7 @@ async function handleInfo(argv) {
|
|
|
8458
8595
|
if (existingFiles.length > 0) {
|
|
8459
8596
|
console.log("Existing output files:");
|
|
8460
8597
|
for (const file of existingFiles) {
|
|
8461
|
-
console.log(` - ${
|
|
8598
|
+
console.log(` - ${path8.relative(process.cwd(), file)}`);
|
|
8462
8599
|
}
|
|
8463
8600
|
}
|
|
8464
8601
|
}
|
|
@@ -8519,6 +8656,7 @@ OPTIONS:
|
|
|
8519
8656
|
--help, -h Show this help message
|
|
8520
8657
|
--version, -v Show version number
|
|
8521
8658
|
--silent, -s Suppress all output except errors (for merge command)
|
|
8659
|
+
--yes, -y Skip confirmation prompts (for init/merge commands)
|
|
8522
8660
|
--legacy Use legacy .git/hooks wrapping (for init command)
|
|
8523
8661
|
--auto Auto-detect best installation method (for init command)
|
|
8524
8662
|
--no-gitignore Don't manage .gitignore or git tracking (for init/merge commands)
|
|
@@ -8528,6 +8666,7 @@ OPTIONS:
|
|
|
8528
8666
|
EXAMPLES:
|
|
8529
8667
|
permachine init
|
|
8530
8668
|
permachine merge --silent
|
|
8669
|
+
permachine merge --yes
|
|
8531
8670
|
permachine info
|
|
8532
8671
|
permachine uninstall
|
|
8533
8672
|
permachine watch
|
|
@@ -8539,8 +8678,8 @@ DOCUMENTATION:
|
|
|
8539
8678
|
}
|
|
8540
8679
|
async function showVersion() {
|
|
8541
8680
|
try {
|
|
8542
|
-
const packageJsonPath =
|
|
8543
|
-
const packageJson = JSON.parse(await
|
|
8681
|
+
const packageJsonPath = path8.join(__dirname3, "../package.json");
|
|
8682
|
+
const packageJson = JSON.parse(await fs4.readFile(packageJsonPath, "utf-8"));
|
|
8544
8683
|
console.log(packageJson.version);
|
|
8545
8684
|
} catch {
|
|
8546
8685
|
console.log("unknown");
|