permachine 0.3.0 → 0.4.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 +207 -322
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -5845,9 +5845,12 @@ function createCustomContext(overrides) {
|
|
|
5845
5845
|
return { ...base, ...overrides };
|
|
5846
5846
|
}
|
|
5847
5847
|
var FILTER_REGEX = /\{([a-zA-Z0-9_-]+)(=|!=|~|\^)([a-zA-Z0-9_*.,\-]+)\}/g;
|
|
5848
|
+
var BASE_PLACEHOLDER_REGEX = /\{base\}/gi;
|
|
5848
5849
|
function parseFilters(filename) {
|
|
5849
5850
|
const filters = [];
|
|
5850
5851
|
let match2;
|
|
5852
|
+
BASE_PLACEHOLDER_REGEX.lastIndex = 0;
|
|
5853
|
+
const hasBasePlaceholder = BASE_PLACEHOLDER_REGEX.test(filename);
|
|
5851
5854
|
FILTER_REGEX.lastIndex = 0;
|
|
5852
5855
|
while ((match2 = FILTER_REGEX.exec(filename)) !== null) {
|
|
5853
5856
|
const [raw, key, operator, value] = match2;
|
|
@@ -5860,11 +5863,14 @@ function parseFilters(filename) {
|
|
|
5860
5863
|
}
|
|
5861
5864
|
let baseFilename = filename.replace(/\.?\{[^}]+\}/g, "");
|
|
5862
5865
|
baseFilename = baseFilename.replace(/\.{2,}/g, ".");
|
|
5863
|
-
return { filters, baseFilename };
|
|
5866
|
+
return { filters, baseFilename, hasBasePlaceholder };
|
|
5864
5867
|
}
|
|
5865
5868
|
function hasFilters(filename) {
|
|
5866
5869
|
FILTER_REGEX.lastIndex = 0;
|
|
5867
|
-
|
|
5870
|
+
const hasFilterSyntax = FILTER_REGEX.test(filename);
|
|
5871
|
+
BASE_PLACEHOLDER_REGEX.lastIndex = 0;
|
|
5872
|
+
const hasBasePlaceholder = BASE_PLACEHOLDER_REGEX.test(filename);
|
|
5873
|
+
return hasFilterSyntax || hasBasePlaceholder;
|
|
5868
5874
|
}
|
|
5869
5875
|
function evaluateFilter(filter2, context) {
|
|
5870
5876
|
const contextValue = context[filter2.key];
|
|
@@ -6370,148 +6376,12 @@ async function performAllMerges(operations) {
|
|
|
6370
6376
|
return results;
|
|
6371
6377
|
}
|
|
6372
6378
|
|
|
6373
|
-
// src/core/
|
|
6379
|
+
// src/core/gitignore-manager.ts
|
|
6374
6380
|
import fs2 from "node:fs/promises";
|
|
6375
6381
|
import path5 from "node:path";
|
|
6376
6382
|
import { exec } from "node:child_process";
|
|
6377
6383
|
import { promisify } from "node:util";
|
|
6378
|
-
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
6379
6384
|
var execAsync = promisify(exec);
|
|
6380
|
-
var __filename2 = fileURLToPath3(import.meta.url);
|
|
6381
|
-
var __dirname2 = path5.dirname(__filename2);
|
|
6382
|
-
var HOOK_NAMES = ["post-checkout", "post-merge", "post-commit"];
|
|
6383
|
-
var HOOKS_DIR = ".permachine/hooks";
|
|
6384
|
-
async function installHooks(options = {}) {
|
|
6385
|
-
const warnings = [];
|
|
6386
|
-
if (!await isGitRepository()) {
|
|
6387
|
-
throw new Error('Not a git repository. Run "git init" first.');
|
|
6388
|
-
}
|
|
6389
|
-
const cwd = process.cwd();
|
|
6390
|
-
const existingHooksPath = await getGitConfig("core.hooksPath");
|
|
6391
|
-
if (existingHooksPath && existingHooksPath !== HOOKS_DIR && !options.legacy) {
|
|
6392
|
-
warnings.push(`Git core.hooksPath is already set to: ${existingHooksPath}`, "Use --legacy flag to install hooks in .git/hooks instead");
|
|
6393
|
-
}
|
|
6394
|
-
const useLegacy = options.legacy || existingHooksPath && existingHooksPath !== HOOKS_DIR;
|
|
6395
|
-
if (useLegacy) {
|
|
6396
|
-
return await installLegacyHooks(warnings);
|
|
6397
|
-
} else {
|
|
6398
|
-
return await installHooksPathMethod(warnings);
|
|
6399
|
-
}
|
|
6400
|
-
}
|
|
6401
|
-
async function installHooksPathMethod(warnings) {
|
|
6402
|
-
const cwd = process.cwd();
|
|
6403
|
-
const hooksDir = path5.join(cwd, HOOKS_DIR);
|
|
6404
|
-
await fs2.mkdir(hooksDir, { recursive: true });
|
|
6405
|
-
let templatesDir = path5.join(__dirname2, "../../templates/hooks");
|
|
6406
|
-
if (!await fileExists2(path5.join(templatesDir, "post-checkout"))) {
|
|
6407
|
-
templatesDir = path5.join(__dirname2, "../templates/hooks");
|
|
6408
|
-
}
|
|
6409
|
-
const installedHooks = [];
|
|
6410
|
-
for (const hookName of HOOK_NAMES) {
|
|
6411
|
-
const templatePath = path5.join(templatesDir, hookName);
|
|
6412
|
-
const hookPath = path5.join(hooksDir, hookName);
|
|
6413
|
-
const content = await fs2.readFile(templatePath, "utf-8");
|
|
6414
|
-
await fs2.writeFile(hookPath, content, { mode: 493 });
|
|
6415
|
-
installedHooks.push(hookName);
|
|
6416
|
-
}
|
|
6417
|
-
await setGitConfig("core.hooksPath", HOOKS_DIR);
|
|
6418
|
-
logger.success(`Installed git hooks via core.hooksPath`);
|
|
6419
|
-
return {
|
|
6420
|
-
method: "hooksPath",
|
|
6421
|
-
hooksInstalled: installedHooks,
|
|
6422
|
-
warnings
|
|
6423
|
-
};
|
|
6424
|
-
}
|
|
6425
|
-
async function installLegacyHooks(warnings) {
|
|
6426
|
-
const cwd = process.cwd();
|
|
6427
|
-
const gitHooksDir = path5.join(cwd, ".git/hooks");
|
|
6428
|
-
const installedHooks = [];
|
|
6429
|
-
for (const hookName of HOOK_NAMES) {
|
|
6430
|
-
const hookPath = path5.join(gitHooksDir, hookName);
|
|
6431
|
-
const backupPath = path5.join(gitHooksDir, `${hookName}.pre-mcs`);
|
|
6432
|
-
const hookExists = await fileExists2(hookPath);
|
|
6433
|
-
if (hookExists) {
|
|
6434
|
-
await fs2.rename(hookPath, backupPath);
|
|
6435
|
-
}
|
|
6436
|
-
const hookContent = `#!/bin/sh
|
|
6437
|
-
# Auto-generated by permachine (legacy mode)
|
|
6438
|
-
|
|
6439
|
-
permachine merge --silent
|
|
6440
|
-
|
|
6441
|
-
# Call original hook if it existed
|
|
6442
|
-
if [ -f "${backupPath}" ]; then
|
|
6443
|
-
"${backupPath}" "$@"
|
|
6444
|
-
fi
|
|
6445
|
-
|
|
6446
|
-
exit 0
|
|
6447
|
-
`;
|
|
6448
|
-
await fs2.writeFile(hookPath, hookContent, { mode: 493 });
|
|
6449
|
-
installedHooks.push(hookName);
|
|
6450
|
-
}
|
|
6451
|
-
logger.success("Installed git hooks via legacy .git/hooks wrapping");
|
|
6452
|
-
return {
|
|
6453
|
-
method: "legacy",
|
|
6454
|
-
hooksInstalled: installedHooks,
|
|
6455
|
-
warnings
|
|
6456
|
-
};
|
|
6457
|
-
}
|
|
6458
|
-
async function uninstallHooks() {
|
|
6459
|
-
const cwd = process.cwd();
|
|
6460
|
-
const hooksPath = await getGitConfig("core.hooksPath");
|
|
6461
|
-
if (hooksPath === HOOKS_DIR) {
|
|
6462
|
-
await execAsync("git config --unset core.hooksPath");
|
|
6463
|
-
const hooksDir = path5.join(cwd, HOOKS_DIR);
|
|
6464
|
-
await fs2.rm(hooksDir, { recursive: true, force: true });
|
|
6465
|
-
logger.success("Uninstalled git hooks (removed core.hooksPath)");
|
|
6466
|
-
} else {
|
|
6467
|
-
const gitHooksDir = path5.join(cwd, ".git/hooks");
|
|
6468
|
-
for (const hookName of HOOK_NAMES) {
|
|
6469
|
-
const hookPath = path5.join(gitHooksDir, hookName);
|
|
6470
|
-
const backupPath = path5.join(gitHooksDir, `${hookName}.pre-mcs`);
|
|
6471
|
-
if (await fileExists2(hookPath)) {
|
|
6472
|
-
await fs2.unlink(hookPath);
|
|
6473
|
-
}
|
|
6474
|
-
if (await fileExists2(backupPath)) {
|
|
6475
|
-
await fs2.rename(backupPath, hookPath);
|
|
6476
|
-
}
|
|
6477
|
-
}
|
|
6478
|
-
logger.success("Uninstalled git hooks (restored original hooks)");
|
|
6479
|
-
}
|
|
6480
|
-
}
|
|
6481
|
-
async function isGitRepository() {
|
|
6482
|
-
try {
|
|
6483
|
-
await execAsync("git rev-parse --git-dir");
|
|
6484
|
-
return true;
|
|
6485
|
-
} catch {
|
|
6486
|
-
return false;
|
|
6487
|
-
}
|
|
6488
|
-
}
|
|
6489
|
-
async function getGitConfig(key) {
|
|
6490
|
-
try {
|
|
6491
|
-
const { stdout } = await execAsync(`git config --get ${key}`);
|
|
6492
|
-
return stdout.trim() || null;
|
|
6493
|
-
} catch {
|
|
6494
|
-
return null;
|
|
6495
|
-
}
|
|
6496
|
-
}
|
|
6497
|
-
async function setGitConfig(key, value) {
|
|
6498
|
-
await execAsync(`git config ${key} "${value}"`);
|
|
6499
|
-
}
|
|
6500
|
-
async function fileExists2(filePath) {
|
|
6501
|
-
try {
|
|
6502
|
-
await fs2.access(filePath);
|
|
6503
|
-
return true;
|
|
6504
|
-
} catch {
|
|
6505
|
-
return false;
|
|
6506
|
-
}
|
|
6507
|
-
}
|
|
6508
|
-
|
|
6509
|
-
// src/core/gitignore-manager.ts
|
|
6510
|
-
import fs3 from "node:fs/promises";
|
|
6511
|
-
import path6 from "node:path";
|
|
6512
|
-
import { exec as exec2 } from "node:child_process";
|
|
6513
|
-
import { promisify as promisify2 } from "node:util";
|
|
6514
|
-
var execAsync2 = promisify2(exec2);
|
|
6515
6385
|
async function manageGitignore(outputPaths, options = {}) {
|
|
6516
6386
|
const result = {
|
|
6517
6387
|
added: [],
|
|
@@ -6522,13 +6392,13 @@ async function manageGitignore(outputPaths, options = {}) {
|
|
|
6522
6392
|
return result;
|
|
6523
6393
|
}
|
|
6524
6394
|
const cwd = options.cwd || process.cwd();
|
|
6525
|
-
const gitignorePath =
|
|
6395
|
+
const gitignorePath = path5.join(cwd, ".gitignore");
|
|
6526
6396
|
try {
|
|
6527
|
-
const relativePaths = outputPaths.map((p) =>
|
|
6397
|
+
const relativePaths = outputPaths.map((p) => path5.relative(cwd, p).replace(/\\/g, "/"));
|
|
6528
6398
|
let gitignoreContent = "";
|
|
6529
6399
|
let gitignoreExists = false;
|
|
6530
6400
|
try {
|
|
6531
|
-
gitignoreContent = await
|
|
6401
|
+
gitignoreContent = await fs2.readFile(gitignorePath, "utf-8");
|
|
6532
6402
|
gitignoreExists = true;
|
|
6533
6403
|
} catch (error) {
|
|
6534
6404
|
if (error.code !== "ENOENT") {
|
|
@@ -6555,7 +6425,7 @@ async function manageGitignore(outputPaths, options = {}) {
|
|
|
6555
6425
|
` : newEntries.join(`
|
|
6556
6426
|
`) + `
|
|
6557
6427
|
`;
|
|
6558
|
-
await
|
|
6428
|
+
await fs2.writeFile(gitignorePath, updatedContent, "utf-8");
|
|
6559
6429
|
if (!gitignoreExists) {
|
|
6560
6430
|
logger.info("Created .gitignore");
|
|
6561
6431
|
}
|
|
@@ -6564,7 +6434,7 @@ async function manageGitignore(outputPaths, options = {}) {
|
|
|
6564
6434
|
try {
|
|
6565
6435
|
const isTracked = await isFileTrackedByGit(relPath, cwd);
|
|
6566
6436
|
if (isTracked) {
|
|
6567
|
-
await
|
|
6437
|
+
await execAsync(`git rm --cached "${relPath}"`, { cwd });
|
|
6568
6438
|
result.removed.push(relPath);
|
|
6569
6439
|
logger.info(`Removed ${relPath} from git tracking`);
|
|
6570
6440
|
}
|
|
@@ -6581,7 +6451,7 @@ async function manageGitignore(outputPaths, options = {}) {
|
|
|
6581
6451
|
}
|
|
6582
6452
|
async function isFileTrackedByGit(filePath, cwd) {
|
|
6583
6453
|
try {
|
|
6584
|
-
await
|
|
6454
|
+
await execAsync(`git ls-files --error-unmatch "${filePath}"`, { cwd });
|
|
6585
6455
|
return true;
|
|
6586
6456
|
} catch {
|
|
6587
6457
|
return false;
|
|
@@ -6679,7 +6549,7 @@ class ReaddirpStream extends Readable {
|
|
|
6679
6549
|
this._directoryFilter = normalizeFilter(opts.directoryFilter);
|
|
6680
6550
|
const statMethod = opts.lstat ? lstat2 : stat;
|
|
6681
6551
|
if (wantBigintFsStats) {
|
|
6682
|
-
this._stat = (
|
|
6552
|
+
this._stat = (path6) => statMethod(path6, { bigint: true });
|
|
6683
6553
|
} else {
|
|
6684
6554
|
this._stat = statMethod;
|
|
6685
6555
|
}
|
|
@@ -6704,8 +6574,8 @@ class ReaddirpStream extends Readable {
|
|
|
6704
6574
|
const par = this.parent;
|
|
6705
6575
|
const fil = par && par.files;
|
|
6706
6576
|
if (fil && fil.length > 0) {
|
|
6707
|
-
const { path:
|
|
6708
|
-
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent,
|
|
6577
|
+
const { path: path6, depth } = par;
|
|
6578
|
+
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path6));
|
|
6709
6579
|
const awaited = await Promise.all(slice);
|
|
6710
6580
|
for (const entry of awaited) {
|
|
6711
6581
|
if (!entry)
|
|
@@ -6745,20 +6615,20 @@ class ReaddirpStream extends Readable {
|
|
|
6745
6615
|
this.reading = false;
|
|
6746
6616
|
}
|
|
6747
6617
|
}
|
|
6748
|
-
async _exploreDir(
|
|
6618
|
+
async _exploreDir(path6, depth) {
|
|
6749
6619
|
let files;
|
|
6750
6620
|
try {
|
|
6751
|
-
files = await readdir2(
|
|
6621
|
+
files = await readdir2(path6, this._rdOptions);
|
|
6752
6622
|
} catch (error) {
|
|
6753
6623
|
this._onError(error);
|
|
6754
6624
|
}
|
|
6755
|
-
return { files, depth, path:
|
|
6625
|
+
return { files, depth, path: path6 };
|
|
6756
6626
|
}
|
|
6757
|
-
async _formatEntry(dirent,
|
|
6627
|
+
async _formatEntry(dirent, path6) {
|
|
6758
6628
|
let entry;
|
|
6759
6629
|
const basename = this._isDirent ? dirent.name : dirent;
|
|
6760
6630
|
try {
|
|
6761
|
-
const fullPath = presolve(pjoin(
|
|
6631
|
+
const fullPath = presolve(pjoin(path6, basename));
|
|
6762
6632
|
entry = { path: prelative(this._root, fullPath), fullPath, basename };
|
|
6763
6633
|
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
|
|
6764
6634
|
} catch (err) {
|
|
@@ -7157,16 +7027,16 @@ var delFromSet = (main, prop, item) => {
|
|
|
7157
7027
|
};
|
|
7158
7028
|
var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
|
|
7159
7029
|
var FsWatchInstances = new Map;
|
|
7160
|
-
function createFsWatchInstance(
|
|
7030
|
+
function createFsWatchInstance(path6, options, listener, errHandler, emitRaw) {
|
|
7161
7031
|
const handleEvent = (rawEvent, evPath) => {
|
|
7162
|
-
listener(
|
|
7163
|
-
emitRaw(rawEvent, evPath, { watchedPath:
|
|
7164
|
-
if (evPath &&
|
|
7165
|
-
fsWatchBroadcast(sp.resolve(
|
|
7032
|
+
listener(path6);
|
|
7033
|
+
emitRaw(rawEvent, evPath, { watchedPath: path6 });
|
|
7034
|
+
if (evPath && path6 !== evPath) {
|
|
7035
|
+
fsWatchBroadcast(sp.resolve(path6, evPath), KEY_LISTENERS, sp.join(path6, evPath));
|
|
7166
7036
|
}
|
|
7167
7037
|
};
|
|
7168
7038
|
try {
|
|
7169
|
-
return fs_watch(
|
|
7039
|
+
return fs_watch(path6, {
|
|
7170
7040
|
persistent: options.persistent
|
|
7171
7041
|
}, handleEvent);
|
|
7172
7042
|
} catch (error) {
|
|
@@ -7182,12 +7052,12 @@ var fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
|
|
|
7182
7052
|
listener(val1, val2, val3);
|
|
7183
7053
|
});
|
|
7184
7054
|
};
|
|
7185
|
-
var setFsWatchListener = (
|
|
7055
|
+
var setFsWatchListener = (path6, fullPath, options, handlers) => {
|
|
7186
7056
|
const { listener, errHandler, rawEmitter } = handlers;
|
|
7187
7057
|
let cont = FsWatchInstances.get(fullPath);
|
|
7188
7058
|
let watcher;
|
|
7189
7059
|
if (!options.persistent) {
|
|
7190
|
-
watcher = createFsWatchInstance(
|
|
7060
|
+
watcher = createFsWatchInstance(path6, options, listener, errHandler, rawEmitter);
|
|
7191
7061
|
if (!watcher)
|
|
7192
7062
|
return;
|
|
7193
7063
|
return watcher.close.bind(watcher);
|
|
@@ -7197,7 +7067,7 @@ var setFsWatchListener = (path7, fullPath, options, handlers) => {
|
|
|
7197
7067
|
addAndConvert(cont, KEY_ERR, errHandler);
|
|
7198
7068
|
addAndConvert(cont, KEY_RAW, rawEmitter);
|
|
7199
7069
|
} else {
|
|
7200
|
-
watcher = createFsWatchInstance(
|
|
7070
|
+
watcher = createFsWatchInstance(path6, options, fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS), errHandler, fsWatchBroadcast.bind(null, fullPath, KEY_RAW));
|
|
7201
7071
|
if (!watcher)
|
|
7202
7072
|
return;
|
|
7203
7073
|
watcher.on(EV.ERROR, async (error) => {
|
|
@@ -7206,7 +7076,7 @@ var setFsWatchListener = (path7, fullPath, options, handlers) => {
|
|
|
7206
7076
|
cont.watcherUnusable = true;
|
|
7207
7077
|
if (isWindows && error.code === "EPERM") {
|
|
7208
7078
|
try {
|
|
7209
|
-
const fd = await open(
|
|
7079
|
+
const fd = await open(path6, "r");
|
|
7210
7080
|
await fd.close();
|
|
7211
7081
|
broadcastErr(error);
|
|
7212
7082
|
} catch (err) {}
|
|
@@ -7236,7 +7106,7 @@ var setFsWatchListener = (path7, fullPath, options, handlers) => {
|
|
|
7236
7106
|
};
|
|
7237
7107
|
};
|
|
7238
7108
|
var FsWatchFileInstances = new Map;
|
|
7239
|
-
var setFsWatchFileListener = (
|
|
7109
|
+
var setFsWatchFileListener = (path6, fullPath, options, handlers) => {
|
|
7240
7110
|
const { listener, rawEmitter } = handlers;
|
|
7241
7111
|
let cont = FsWatchFileInstances.get(fullPath);
|
|
7242
7112
|
const copts = cont && cont.options;
|
|
@@ -7258,7 +7128,7 @@ var setFsWatchFileListener = (path7, fullPath, options, handlers) => {
|
|
|
7258
7128
|
});
|
|
7259
7129
|
const currmtime = curr.mtimeMs;
|
|
7260
7130
|
if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
|
|
7261
|
-
foreach(cont.listeners, (listener2) => listener2(
|
|
7131
|
+
foreach(cont.listeners, (listener2) => listener2(path6, curr));
|
|
7262
7132
|
}
|
|
7263
7133
|
})
|
|
7264
7134
|
};
|
|
@@ -7283,13 +7153,13 @@ class NodeFsHandler {
|
|
|
7283
7153
|
this.fsw = fsW;
|
|
7284
7154
|
this._boundHandleError = (error) => fsW._handleError(error);
|
|
7285
7155
|
}
|
|
7286
|
-
_watchWithNodeFs(
|
|
7156
|
+
_watchWithNodeFs(path6, listener) {
|
|
7287
7157
|
const opts = this.fsw.options;
|
|
7288
|
-
const directory = sp.dirname(
|
|
7289
|
-
const basename2 = sp.basename(
|
|
7158
|
+
const directory = sp.dirname(path6);
|
|
7159
|
+
const basename2 = sp.basename(path6);
|
|
7290
7160
|
const parent = this.fsw._getWatchedDir(directory);
|
|
7291
7161
|
parent.add(basename2);
|
|
7292
|
-
const absolutePath = sp.resolve(
|
|
7162
|
+
const absolutePath = sp.resolve(path6);
|
|
7293
7163
|
const options = {
|
|
7294
7164
|
persistent: opts.persistent
|
|
7295
7165
|
};
|
|
@@ -7299,12 +7169,12 @@ class NodeFsHandler {
|
|
|
7299
7169
|
if (opts.usePolling) {
|
|
7300
7170
|
const enableBin = opts.interval !== opts.binaryInterval;
|
|
7301
7171
|
options.interval = enableBin && isBinaryPath(basename2) ? opts.binaryInterval : opts.interval;
|
|
7302
|
-
closer = setFsWatchFileListener(
|
|
7172
|
+
closer = setFsWatchFileListener(path6, absolutePath, options, {
|
|
7303
7173
|
listener,
|
|
7304
7174
|
rawEmitter: this.fsw._emitRaw
|
|
7305
7175
|
});
|
|
7306
7176
|
} else {
|
|
7307
|
-
closer = setFsWatchListener(
|
|
7177
|
+
closer = setFsWatchListener(path6, absolutePath, options, {
|
|
7308
7178
|
listener,
|
|
7309
7179
|
errHandler: this._boundHandleError,
|
|
7310
7180
|
rawEmitter: this.fsw._emitRaw
|
|
@@ -7322,7 +7192,7 @@ class NodeFsHandler {
|
|
|
7322
7192
|
let prevStats = stats;
|
|
7323
7193
|
if (parent.has(basename2))
|
|
7324
7194
|
return;
|
|
7325
|
-
const listener = async (
|
|
7195
|
+
const listener = async (path6, newStats) => {
|
|
7326
7196
|
if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
|
|
7327
7197
|
return;
|
|
7328
7198
|
if (!newStats || newStats.mtimeMs === 0) {
|
|
@@ -7336,11 +7206,11 @@ class NodeFsHandler {
|
|
|
7336
7206
|
this.fsw._emit(EV.CHANGE, file, newStats2);
|
|
7337
7207
|
}
|
|
7338
7208
|
if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
|
|
7339
|
-
this.fsw._closeFile(
|
|
7209
|
+
this.fsw._closeFile(path6);
|
|
7340
7210
|
prevStats = newStats2;
|
|
7341
7211
|
const closer2 = this._watchWithNodeFs(file, listener);
|
|
7342
7212
|
if (closer2)
|
|
7343
|
-
this.fsw._addPathCloser(
|
|
7213
|
+
this.fsw._addPathCloser(path6, closer2);
|
|
7344
7214
|
} else {
|
|
7345
7215
|
prevStats = newStats2;
|
|
7346
7216
|
}
|
|
@@ -7364,7 +7234,7 @@ class NodeFsHandler {
|
|
|
7364
7234
|
}
|
|
7365
7235
|
return closer;
|
|
7366
7236
|
}
|
|
7367
|
-
async _handleSymlink(entry, directory,
|
|
7237
|
+
async _handleSymlink(entry, directory, path6, item) {
|
|
7368
7238
|
if (this.fsw.closed) {
|
|
7369
7239
|
return;
|
|
7370
7240
|
}
|
|
@@ -7374,7 +7244,7 @@ class NodeFsHandler {
|
|
|
7374
7244
|
this.fsw._incrReadyCount();
|
|
7375
7245
|
let linkPath;
|
|
7376
7246
|
try {
|
|
7377
|
-
linkPath = await fsrealpath(
|
|
7247
|
+
linkPath = await fsrealpath(path6);
|
|
7378
7248
|
} catch (e) {
|
|
7379
7249
|
this.fsw._emitReady();
|
|
7380
7250
|
return true;
|
|
@@ -7384,12 +7254,12 @@ class NodeFsHandler {
|
|
|
7384
7254
|
if (dir.has(item)) {
|
|
7385
7255
|
if (this.fsw._symlinkPaths.get(full) !== linkPath) {
|
|
7386
7256
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
7387
|
-
this.fsw._emit(EV.CHANGE,
|
|
7257
|
+
this.fsw._emit(EV.CHANGE, path6, entry.stats);
|
|
7388
7258
|
}
|
|
7389
7259
|
} else {
|
|
7390
7260
|
dir.add(item);
|
|
7391
7261
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
7392
|
-
this.fsw._emit(EV.ADD,
|
|
7262
|
+
this.fsw._emit(EV.ADD, path6, entry.stats);
|
|
7393
7263
|
}
|
|
7394
7264
|
this.fsw._emitReady();
|
|
7395
7265
|
return true;
|
|
@@ -7419,9 +7289,9 @@ class NodeFsHandler {
|
|
|
7419
7289
|
return;
|
|
7420
7290
|
}
|
|
7421
7291
|
const item = entry.path;
|
|
7422
|
-
let
|
|
7292
|
+
let path6 = sp.join(directory, item);
|
|
7423
7293
|
current.add(item);
|
|
7424
|
-
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory,
|
|
7294
|
+
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path6, item)) {
|
|
7425
7295
|
return;
|
|
7426
7296
|
}
|
|
7427
7297
|
if (this.fsw.closed) {
|
|
@@ -7430,8 +7300,8 @@ class NodeFsHandler {
|
|
|
7430
7300
|
}
|
|
7431
7301
|
if (item === target || !target && !previous.has(item)) {
|
|
7432
7302
|
this.fsw._incrReadyCount();
|
|
7433
|
-
|
|
7434
|
-
this._addToNodeFs(
|
|
7303
|
+
path6 = sp.join(dir, sp.relative(dir, path6));
|
|
7304
|
+
this._addToNodeFs(path6, initialAdd, wh, depth + 1);
|
|
7435
7305
|
}
|
|
7436
7306
|
}).on(EV.ERROR, this._boundHandleError);
|
|
7437
7307
|
return new Promise((resolve2, reject) => {
|
|
@@ -7480,13 +7350,13 @@ class NodeFsHandler {
|
|
|
7480
7350
|
}
|
|
7481
7351
|
return closer;
|
|
7482
7352
|
}
|
|
7483
|
-
async _addToNodeFs(
|
|
7353
|
+
async _addToNodeFs(path6, initialAdd, priorWh, depth, target) {
|
|
7484
7354
|
const ready = this.fsw._emitReady;
|
|
7485
|
-
if (this.fsw._isIgnored(
|
|
7355
|
+
if (this.fsw._isIgnored(path6) || this.fsw.closed) {
|
|
7486
7356
|
ready();
|
|
7487
7357
|
return false;
|
|
7488
7358
|
}
|
|
7489
|
-
const wh = this.fsw._getWatchHelpers(
|
|
7359
|
+
const wh = this.fsw._getWatchHelpers(path6);
|
|
7490
7360
|
if (priorWh) {
|
|
7491
7361
|
wh.filterPath = (entry) => priorWh.filterPath(entry);
|
|
7492
7362
|
wh.filterDir = (entry) => priorWh.filterDir(entry);
|
|
@@ -7502,8 +7372,8 @@ class NodeFsHandler {
|
|
|
7502
7372
|
const follow = this.fsw.options.followSymlinks;
|
|
7503
7373
|
let closer;
|
|
7504
7374
|
if (stats.isDirectory()) {
|
|
7505
|
-
const absPath = sp.resolve(
|
|
7506
|
-
const targetPath = follow ? await fsrealpath(
|
|
7375
|
+
const absPath = sp.resolve(path6);
|
|
7376
|
+
const targetPath = follow ? await fsrealpath(path6) : path6;
|
|
7507
7377
|
if (this.fsw.closed)
|
|
7508
7378
|
return;
|
|
7509
7379
|
closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
|
|
@@ -7513,29 +7383,29 @@ class NodeFsHandler {
|
|
|
7513
7383
|
this.fsw._symlinkPaths.set(absPath, targetPath);
|
|
7514
7384
|
}
|
|
7515
7385
|
} else if (stats.isSymbolicLink()) {
|
|
7516
|
-
const targetPath = follow ? await fsrealpath(
|
|
7386
|
+
const targetPath = follow ? await fsrealpath(path6) : path6;
|
|
7517
7387
|
if (this.fsw.closed)
|
|
7518
7388
|
return;
|
|
7519
7389
|
const parent = sp.dirname(wh.watchPath);
|
|
7520
7390
|
this.fsw._getWatchedDir(parent).add(wh.watchPath);
|
|
7521
7391
|
this.fsw._emit(EV.ADD, wh.watchPath, stats);
|
|
7522
|
-
closer = await this._handleDir(parent, stats, initialAdd, depth,
|
|
7392
|
+
closer = await this._handleDir(parent, stats, initialAdd, depth, path6, wh, targetPath);
|
|
7523
7393
|
if (this.fsw.closed)
|
|
7524
7394
|
return;
|
|
7525
7395
|
if (targetPath !== undefined) {
|
|
7526
|
-
this.fsw._symlinkPaths.set(sp.resolve(
|
|
7396
|
+
this.fsw._symlinkPaths.set(sp.resolve(path6), targetPath);
|
|
7527
7397
|
}
|
|
7528
7398
|
} else {
|
|
7529
7399
|
closer = this._handleFile(wh.watchPath, stats, initialAdd);
|
|
7530
7400
|
}
|
|
7531
7401
|
ready();
|
|
7532
7402
|
if (closer)
|
|
7533
|
-
this.fsw._addPathCloser(
|
|
7403
|
+
this.fsw._addPathCloser(path6, closer);
|
|
7534
7404
|
return false;
|
|
7535
7405
|
} catch (error) {
|
|
7536
7406
|
if (this.fsw._handleError(error)) {
|
|
7537
7407
|
ready();
|
|
7538
|
-
return
|
|
7408
|
+
return path6;
|
|
7539
7409
|
}
|
|
7540
7410
|
}
|
|
7541
7411
|
}
|
|
@@ -7579,24 +7449,24 @@ function createPattern(matcher) {
|
|
|
7579
7449
|
}
|
|
7580
7450
|
return () => false;
|
|
7581
7451
|
}
|
|
7582
|
-
function normalizePath(
|
|
7583
|
-
if (typeof
|
|
7452
|
+
function normalizePath(path6) {
|
|
7453
|
+
if (typeof path6 !== "string")
|
|
7584
7454
|
throw new Error("string expected");
|
|
7585
|
-
|
|
7586
|
-
|
|
7455
|
+
path6 = sp2.normalize(path6);
|
|
7456
|
+
path6 = path6.replace(/\\/g, "/");
|
|
7587
7457
|
let prepend = false;
|
|
7588
|
-
if (
|
|
7458
|
+
if (path6.startsWith("//"))
|
|
7589
7459
|
prepend = true;
|
|
7590
|
-
|
|
7460
|
+
path6 = path6.replace(DOUBLE_SLASH_RE, "/");
|
|
7591
7461
|
if (prepend)
|
|
7592
|
-
|
|
7593
|
-
return
|
|
7462
|
+
path6 = "/" + path6;
|
|
7463
|
+
return path6;
|
|
7594
7464
|
}
|
|
7595
7465
|
function matchPatterns(patterns, testString, stats) {
|
|
7596
|
-
const
|
|
7466
|
+
const path6 = normalizePath(testString);
|
|
7597
7467
|
for (let index = 0;index < patterns.length; index++) {
|
|
7598
7468
|
const pattern = patterns[index];
|
|
7599
|
-
if (pattern(
|
|
7469
|
+
if (pattern(path6, stats)) {
|
|
7600
7470
|
return true;
|
|
7601
7471
|
}
|
|
7602
7472
|
}
|
|
@@ -7634,19 +7504,19 @@ var toUnix = (string) => {
|
|
|
7634
7504
|
}
|
|
7635
7505
|
return str;
|
|
7636
7506
|
};
|
|
7637
|
-
var normalizePathToUnix = (
|
|
7638
|
-
var normalizeIgnored = (cwd = "") => (
|
|
7639
|
-
if (typeof
|
|
7640
|
-
return normalizePathToUnix(sp2.isAbsolute(
|
|
7507
|
+
var normalizePathToUnix = (path6) => toUnix(sp2.normalize(toUnix(path6)));
|
|
7508
|
+
var normalizeIgnored = (cwd = "") => (path6) => {
|
|
7509
|
+
if (typeof path6 === "string") {
|
|
7510
|
+
return normalizePathToUnix(sp2.isAbsolute(path6) ? path6 : sp2.join(cwd, path6));
|
|
7641
7511
|
} else {
|
|
7642
|
-
return
|
|
7512
|
+
return path6;
|
|
7643
7513
|
}
|
|
7644
7514
|
};
|
|
7645
|
-
var getAbsolutePath = (
|
|
7646
|
-
if (sp2.isAbsolute(
|
|
7647
|
-
return
|
|
7515
|
+
var getAbsolutePath = (path6, cwd) => {
|
|
7516
|
+
if (sp2.isAbsolute(path6)) {
|
|
7517
|
+
return path6;
|
|
7648
7518
|
}
|
|
7649
|
-
return sp2.join(cwd,
|
|
7519
|
+
return sp2.join(cwd, path6);
|
|
7650
7520
|
};
|
|
7651
7521
|
var EMPTY_SET = Object.freeze(new Set);
|
|
7652
7522
|
|
|
@@ -7713,10 +7583,10 @@ class WatchHelper {
|
|
|
7713
7583
|
dirParts;
|
|
7714
7584
|
followSymlinks;
|
|
7715
7585
|
statMethod;
|
|
7716
|
-
constructor(
|
|
7586
|
+
constructor(path6, follow, fsw) {
|
|
7717
7587
|
this.fsw = fsw;
|
|
7718
|
-
const watchPath =
|
|
7719
|
-
this.path =
|
|
7588
|
+
const watchPath = path6;
|
|
7589
|
+
this.path = path6 = path6.replace(REPLACER_RE, "");
|
|
7720
7590
|
this.watchPath = watchPath;
|
|
7721
7591
|
this.fullWatchPath = sp2.resolve(watchPath);
|
|
7722
7592
|
this.dirParts = [];
|
|
@@ -7847,20 +7717,20 @@ class FSWatcher extends EventEmitter2 {
|
|
|
7847
7717
|
this._closePromise = undefined;
|
|
7848
7718
|
let paths = unifyPaths(paths_);
|
|
7849
7719
|
if (cwd) {
|
|
7850
|
-
paths = paths.map((
|
|
7851
|
-
const absPath = getAbsolutePath(
|
|
7720
|
+
paths = paths.map((path6) => {
|
|
7721
|
+
const absPath = getAbsolutePath(path6, cwd);
|
|
7852
7722
|
return absPath;
|
|
7853
7723
|
});
|
|
7854
7724
|
}
|
|
7855
|
-
paths.forEach((
|
|
7856
|
-
this._removeIgnoredPath(
|
|
7725
|
+
paths.forEach((path6) => {
|
|
7726
|
+
this._removeIgnoredPath(path6);
|
|
7857
7727
|
});
|
|
7858
7728
|
this._userIgnored = undefined;
|
|
7859
7729
|
if (!this._readyCount)
|
|
7860
7730
|
this._readyCount = 0;
|
|
7861
7731
|
this._readyCount += paths.length;
|
|
7862
|
-
Promise.all(paths.map(async (
|
|
7863
|
-
const res = await this._nodeFsHandler._addToNodeFs(
|
|
7732
|
+
Promise.all(paths.map(async (path6) => {
|
|
7733
|
+
const res = await this._nodeFsHandler._addToNodeFs(path6, !_internal, undefined, 0, _origAdd);
|
|
7864
7734
|
if (res)
|
|
7865
7735
|
this._emitReady();
|
|
7866
7736
|
return res;
|
|
@@ -7879,17 +7749,17 @@ class FSWatcher extends EventEmitter2 {
|
|
|
7879
7749
|
return this;
|
|
7880
7750
|
const paths = unifyPaths(paths_);
|
|
7881
7751
|
const { cwd } = this.options;
|
|
7882
|
-
paths.forEach((
|
|
7883
|
-
if (!sp2.isAbsolute(
|
|
7752
|
+
paths.forEach((path6) => {
|
|
7753
|
+
if (!sp2.isAbsolute(path6) && !this._closers.has(path6)) {
|
|
7884
7754
|
if (cwd)
|
|
7885
|
-
|
|
7886
|
-
|
|
7755
|
+
path6 = sp2.join(cwd, path6);
|
|
7756
|
+
path6 = sp2.resolve(path6);
|
|
7887
7757
|
}
|
|
7888
|
-
this._closePath(
|
|
7889
|
-
this._addIgnoredPath(
|
|
7890
|
-
if (this._watched.has(
|
|
7758
|
+
this._closePath(path6);
|
|
7759
|
+
this._addIgnoredPath(path6);
|
|
7760
|
+
if (this._watched.has(path6)) {
|
|
7891
7761
|
this._addIgnoredPath({
|
|
7892
|
-
path:
|
|
7762
|
+
path: path6,
|
|
7893
7763
|
recursive: true
|
|
7894
7764
|
});
|
|
7895
7765
|
}
|
|
@@ -7938,38 +7808,38 @@ class FSWatcher extends EventEmitter2 {
|
|
|
7938
7808
|
if (event !== EVENTS.ERROR)
|
|
7939
7809
|
this.emit(EVENTS.ALL, event, ...args);
|
|
7940
7810
|
}
|
|
7941
|
-
async _emit(event,
|
|
7811
|
+
async _emit(event, path6, stats) {
|
|
7942
7812
|
if (this.closed)
|
|
7943
7813
|
return;
|
|
7944
7814
|
const opts = this.options;
|
|
7945
7815
|
if (isWindows)
|
|
7946
|
-
|
|
7816
|
+
path6 = sp2.normalize(path6);
|
|
7947
7817
|
if (opts.cwd)
|
|
7948
|
-
|
|
7949
|
-
const args = [
|
|
7818
|
+
path6 = sp2.relative(opts.cwd, path6);
|
|
7819
|
+
const args = [path6];
|
|
7950
7820
|
if (stats != null)
|
|
7951
7821
|
args.push(stats);
|
|
7952
7822
|
const awf = opts.awaitWriteFinish;
|
|
7953
7823
|
let pw;
|
|
7954
|
-
if (awf && (pw = this._pendingWrites.get(
|
|
7824
|
+
if (awf && (pw = this._pendingWrites.get(path6))) {
|
|
7955
7825
|
pw.lastChange = new Date;
|
|
7956
7826
|
return this;
|
|
7957
7827
|
}
|
|
7958
7828
|
if (opts.atomic) {
|
|
7959
7829
|
if (event === EVENTS.UNLINK) {
|
|
7960
|
-
this._pendingUnlinks.set(
|
|
7830
|
+
this._pendingUnlinks.set(path6, [event, ...args]);
|
|
7961
7831
|
setTimeout(() => {
|
|
7962
|
-
this._pendingUnlinks.forEach((entry,
|
|
7832
|
+
this._pendingUnlinks.forEach((entry, path7) => {
|
|
7963
7833
|
this.emit(...entry);
|
|
7964
7834
|
this.emit(EVENTS.ALL, ...entry);
|
|
7965
|
-
this._pendingUnlinks.delete(
|
|
7835
|
+
this._pendingUnlinks.delete(path7);
|
|
7966
7836
|
});
|
|
7967
7837
|
}, typeof opts.atomic === "number" ? opts.atomic : 100);
|
|
7968
7838
|
return this;
|
|
7969
7839
|
}
|
|
7970
|
-
if (event === EVENTS.ADD && this._pendingUnlinks.has(
|
|
7840
|
+
if (event === EVENTS.ADD && this._pendingUnlinks.has(path6)) {
|
|
7971
7841
|
event = EVENTS.CHANGE;
|
|
7972
|
-
this._pendingUnlinks.delete(
|
|
7842
|
+
this._pendingUnlinks.delete(path6);
|
|
7973
7843
|
}
|
|
7974
7844
|
}
|
|
7975
7845
|
if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
|
|
@@ -7987,16 +7857,16 @@ class FSWatcher extends EventEmitter2 {
|
|
|
7987
7857
|
this.emitWithAll(event, args);
|
|
7988
7858
|
}
|
|
7989
7859
|
};
|
|
7990
|
-
this._awaitWriteFinish(
|
|
7860
|
+
this._awaitWriteFinish(path6, awf.stabilityThreshold, event, awfEmit);
|
|
7991
7861
|
return this;
|
|
7992
7862
|
}
|
|
7993
7863
|
if (event === EVENTS.CHANGE) {
|
|
7994
|
-
const isThrottled = !this._throttle(EVENTS.CHANGE,
|
|
7864
|
+
const isThrottled = !this._throttle(EVENTS.CHANGE, path6, 50);
|
|
7995
7865
|
if (isThrottled)
|
|
7996
7866
|
return this;
|
|
7997
7867
|
}
|
|
7998
7868
|
if (opts.alwaysStat && stats === undefined && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
|
|
7999
|
-
const fullPath = opts.cwd ? sp2.join(opts.cwd,
|
|
7869
|
+
const fullPath = opts.cwd ? sp2.join(opts.cwd, path6) : path6;
|
|
8000
7870
|
let stats2;
|
|
8001
7871
|
try {
|
|
8002
7872
|
stats2 = await stat3(fullPath);
|
|
@@ -8015,23 +7885,23 @@ class FSWatcher extends EventEmitter2 {
|
|
|
8015
7885
|
}
|
|
8016
7886
|
return error || this.closed;
|
|
8017
7887
|
}
|
|
8018
|
-
_throttle(actionType,
|
|
7888
|
+
_throttle(actionType, path6, timeout) {
|
|
8019
7889
|
if (!this._throttled.has(actionType)) {
|
|
8020
7890
|
this._throttled.set(actionType, new Map);
|
|
8021
7891
|
}
|
|
8022
7892
|
const action = this._throttled.get(actionType);
|
|
8023
7893
|
if (!action)
|
|
8024
7894
|
throw new Error("invalid throttle");
|
|
8025
|
-
const actionPath = action.get(
|
|
7895
|
+
const actionPath = action.get(path6);
|
|
8026
7896
|
if (actionPath) {
|
|
8027
7897
|
actionPath.count++;
|
|
8028
7898
|
return false;
|
|
8029
7899
|
}
|
|
8030
7900
|
let timeoutObject;
|
|
8031
7901
|
const clear = () => {
|
|
8032
|
-
const item = action.get(
|
|
7902
|
+
const item = action.get(path6);
|
|
8033
7903
|
const count = item ? item.count : 0;
|
|
8034
|
-
action.delete(
|
|
7904
|
+
action.delete(path6);
|
|
8035
7905
|
clearTimeout(timeoutObject);
|
|
8036
7906
|
if (item)
|
|
8037
7907
|
clearTimeout(item.timeoutObject);
|
|
@@ -8039,50 +7909,50 @@ class FSWatcher extends EventEmitter2 {
|
|
|
8039
7909
|
};
|
|
8040
7910
|
timeoutObject = setTimeout(clear, timeout);
|
|
8041
7911
|
const thr = { timeoutObject, clear, count: 0 };
|
|
8042
|
-
action.set(
|
|
7912
|
+
action.set(path6, thr);
|
|
8043
7913
|
return thr;
|
|
8044
7914
|
}
|
|
8045
7915
|
_incrReadyCount() {
|
|
8046
7916
|
return this._readyCount++;
|
|
8047
7917
|
}
|
|
8048
|
-
_awaitWriteFinish(
|
|
7918
|
+
_awaitWriteFinish(path6, threshold, event, awfEmit) {
|
|
8049
7919
|
const awf = this.options.awaitWriteFinish;
|
|
8050
7920
|
if (typeof awf !== "object")
|
|
8051
7921
|
return;
|
|
8052
7922
|
const pollInterval = awf.pollInterval;
|
|
8053
7923
|
let timeoutHandler;
|
|
8054
|
-
let fullPath =
|
|
8055
|
-
if (this.options.cwd && !sp2.isAbsolute(
|
|
8056
|
-
fullPath = sp2.join(this.options.cwd,
|
|
7924
|
+
let fullPath = path6;
|
|
7925
|
+
if (this.options.cwd && !sp2.isAbsolute(path6)) {
|
|
7926
|
+
fullPath = sp2.join(this.options.cwd, path6);
|
|
8057
7927
|
}
|
|
8058
7928
|
const now = new Date;
|
|
8059
7929
|
const writes = this._pendingWrites;
|
|
8060
7930
|
function awaitWriteFinishFn(prevStat) {
|
|
8061
7931
|
statcb(fullPath, (err, curStat) => {
|
|
8062
|
-
if (err || !writes.has(
|
|
7932
|
+
if (err || !writes.has(path6)) {
|
|
8063
7933
|
if (err && err.code !== "ENOENT")
|
|
8064
7934
|
awfEmit(err);
|
|
8065
7935
|
return;
|
|
8066
7936
|
}
|
|
8067
7937
|
const now2 = Number(new Date);
|
|
8068
7938
|
if (prevStat && curStat.size !== prevStat.size) {
|
|
8069
|
-
writes.get(
|
|
7939
|
+
writes.get(path6).lastChange = now2;
|
|
8070
7940
|
}
|
|
8071
|
-
const pw = writes.get(
|
|
7941
|
+
const pw = writes.get(path6);
|
|
8072
7942
|
const df = now2 - pw.lastChange;
|
|
8073
7943
|
if (df >= threshold) {
|
|
8074
|
-
writes.delete(
|
|
7944
|
+
writes.delete(path6);
|
|
8075
7945
|
awfEmit(undefined, curStat);
|
|
8076
7946
|
} else {
|
|
8077
7947
|
timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
|
|
8078
7948
|
}
|
|
8079
7949
|
});
|
|
8080
7950
|
}
|
|
8081
|
-
if (!writes.has(
|
|
8082
|
-
writes.set(
|
|
7951
|
+
if (!writes.has(path6)) {
|
|
7952
|
+
writes.set(path6, {
|
|
8083
7953
|
lastChange: now,
|
|
8084
7954
|
cancelWait: () => {
|
|
8085
|
-
writes.delete(
|
|
7955
|
+
writes.delete(path6);
|
|
8086
7956
|
clearTimeout(timeoutHandler);
|
|
8087
7957
|
return event;
|
|
8088
7958
|
}
|
|
@@ -8090,8 +7960,8 @@ class FSWatcher extends EventEmitter2 {
|
|
|
8090
7960
|
timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval);
|
|
8091
7961
|
}
|
|
8092
7962
|
}
|
|
8093
|
-
_isIgnored(
|
|
8094
|
-
if (this.options.atomic && DOT_RE.test(
|
|
7963
|
+
_isIgnored(path6, stats) {
|
|
7964
|
+
if (this.options.atomic && DOT_RE.test(path6))
|
|
8095
7965
|
return true;
|
|
8096
7966
|
if (!this._userIgnored) {
|
|
8097
7967
|
const { cwd } = this.options;
|
|
@@ -8101,13 +7971,13 @@ class FSWatcher extends EventEmitter2 {
|
|
|
8101
7971
|
const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
|
|
8102
7972
|
this._userIgnored = anymatch(list, undefined);
|
|
8103
7973
|
}
|
|
8104
|
-
return this._userIgnored(
|
|
7974
|
+
return this._userIgnored(path6, stats);
|
|
8105
7975
|
}
|
|
8106
|
-
_isntIgnored(
|
|
8107
|
-
return !this._isIgnored(
|
|
7976
|
+
_isntIgnored(path6, stat4) {
|
|
7977
|
+
return !this._isIgnored(path6, stat4);
|
|
8108
7978
|
}
|
|
8109
|
-
_getWatchHelpers(
|
|
8110
|
-
return new WatchHelper(
|
|
7979
|
+
_getWatchHelpers(path6) {
|
|
7980
|
+
return new WatchHelper(path6, this.options.followSymlinks, this);
|
|
8111
7981
|
}
|
|
8112
7982
|
_getWatchedDir(directory) {
|
|
8113
7983
|
const dir = sp2.resolve(directory);
|
|
@@ -8121,57 +7991,57 @@ class FSWatcher extends EventEmitter2 {
|
|
|
8121
7991
|
return Boolean(Number(stats.mode) & 256);
|
|
8122
7992
|
}
|
|
8123
7993
|
_remove(directory, item, isDirectory) {
|
|
8124
|
-
const
|
|
8125
|
-
const fullPath = sp2.resolve(
|
|
8126
|
-
isDirectory = isDirectory != null ? isDirectory : this._watched.has(
|
|
8127
|
-
if (!this._throttle("remove",
|
|
7994
|
+
const path6 = sp2.join(directory, item);
|
|
7995
|
+
const fullPath = sp2.resolve(path6);
|
|
7996
|
+
isDirectory = isDirectory != null ? isDirectory : this._watched.has(path6) || this._watched.has(fullPath);
|
|
7997
|
+
if (!this._throttle("remove", path6, 100))
|
|
8128
7998
|
return;
|
|
8129
7999
|
if (!isDirectory && this._watched.size === 1) {
|
|
8130
8000
|
this.add(directory, item, true);
|
|
8131
8001
|
}
|
|
8132
|
-
const wp = this._getWatchedDir(
|
|
8002
|
+
const wp = this._getWatchedDir(path6);
|
|
8133
8003
|
const nestedDirectoryChildren = wp.getChildren();
|
|
8134
|
-
nestedDirectoryChildren.forEach((nested) => this._remove(
|
|
8004
|
+
nestedDirectoryChildren.forEach((nested) => this._remove(path6, nested));
|
|
8135
8005
|
const parent = this._getWatchedDir(directory);
|
|
8136
8006
|
const wasTracked = parent.has(item);
|
|
8137
8007
|
parent.remove(item);
|
|
8138
8008
|
if (this._symlinkPaths.has(fullPath)) {
|
|
8139
8009
|
this._symlinkPaths.delete(fullPath);
|
|
8140
8010
|
}
|
|
8141
|
-
let relPath =
|
|
8011
|
+
let relPath = path6;
|
|
8142
8012
|
if (this.options.cwd)
|
|
8143
|
-
relPath = sp2.relative(this.options.cwd,
|
|
8013
|
+
relPath = sp2.relative(this.options.cwd, path6);
|
|
8144
8014
|
if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
|
|
8145
8015
|
const event = this._pendingWrites.get(relPath).cancelWait();
|
|
8146
8016
|
if (event === EVENTS.ADD)
|
|
8147
8017
|
return;
|
|
8148
8018
|
}
|
|
8149
|
-
this._watched.delete(
|
|
8019
|
+
this._watched.delete(path6);
|
|
8150
8020
|
this._watched.delete(fullPath);
|
|
8151
8021
|
const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
|
|
8152
|
-
if (wasTracked && !this._isIgnored(
|
|
8153
|
-
this._emit(eventName,
|
|
8154
|
-
this._closePath(
|
|
8022
|
+
if (wasTracked && !this._isIgnored(path6))
|
|
8023
|
+
this._emit(eventName, path6);
|
|
8024
|
+
this._closePath(path6);
|
|
8155
8025
|
}
|
|
8156
|
-
_closePath(
|
|
8157
|
-
this._closeFile(
|
|
8158
|
-
const dir = sp2.dirname(
|
|
8159
|
-
this._getWatchedDir(dir).remove(sp2.basename(
|
|
8026
|
+
_closePath(path6) {
|
|
8027
|
+
this._closeFile(path6);
|
|
8028
|
+
const dir = sp2.dirname(path6);
|
|
8029
|
+
this._getWatchedDir(dir).remove(sp2.basename(path6));
|
|
8160
8030
|
}
|
|
8161
|
-
_closeFile(
|
|
8162
|
-
const closers = this._closers.get(
|
|
8031
|
+
_closeFile(path6) {
|
|
8032
|
+
const closers = this._closers.get(path6);
|
|
8163
8033
|
if (!closers)
|
|
8164
8034
|
return;
|
|
8165
8035
|
closers.forEach((closer) => closer());
|
|
8166
|
-
this._closers.delete(
|
|
8036
|
+
this._closers.delete(path6);
|
|
8167
8037
|
}
|
|
8168
|
-
_addPathCloser(
|
|
8038
|
+
_addPathCloser(path6, closer) {
|
|
8169
8039
|
if (!closer)
|
|
8170
8040
|
return;
|
|
8171
|
-
let list = this._closers.get(
|
|
8041
|
+
let list = this._closers.get(path6);
|
|
8172
8042
|
if (!list) {
|
|
8173
8043
|
list = [];
|
|
8174
|
-
this._closers.set(
|
|
8044
|
+
this._closers.set(path6, list);
|
|
8175
8045
|
}
|
|
8176
8046
|
list.push(closer);
|
|
8177
8047
|
}
|
|
@@ -8201,7 +8071,7 @@ function watch(paths, options = {}) {
|
|
|
8201
8071
|
var chokidar_default = { watch, FSWatcher };
|
|
8202
8072
|
|
|
8203
8073
|
// src/core/watcher.ts
|
|
8204
|
-
import
|
|
8074
|
+
import path6 from "node:path";
|
|
8205
8075
|
function formatTime() {
|
|
8206
8076
|
const now = new Date;
|
|
8207
8077
|
const hours = String(now.getHours()).padStart(2, "0");
|
|
@@ -8234,7 +8104,7 @@ function getWatchPaths(operations) {
|
|
|
8234
8104
|
return Array.from(paths);
|
|
8235
8105
|
}
|
|
8236
8106
|
async function handleFileChange(changedPath, state, options) {
|
|
8237
|
-
const relPath =
|
|
8107
|
+
const relPath = path6.relative(options.cwd || process.cwd(), changedPath);
|
|
8238
8108
|
if (!logger.isSilent() && !options.verbose) {
|
|
8239
8109
|
console.log(`[${formatTime()}] Changed: ${relPath}`);
|
|
8240
8110
|
}
|
|
@@ -8248,9 +8118,9 @@ async function handleFileChange(changedPath, state, options) {
|
|
|
8248
8118
|
for (const op of affectedOps) {
|
|
8249
8119
|
const result = await performMerge(op);
|
|
8250
8120
|
if (result.success && result.changed) {
|
|
8251
|
-
const baseFile = op.basePath ?
|
|
8252
|
-
const machineFile =
|
|
8253
|
-
const outputFile =
|
|
8121
|
+
const baseFile = op.basePath ? path6.basename(op.basePath) : "";
|
|
8122
|
+
const machineFile = path6.basename(op.machinePath);
|
|
8123
|
+
const outputFile = path6.basename(op.outputPath);
|
|
8254
8124
|
if (!logger.isSilent()) {
|
|
8255
8125
|
if (baseFile) {
|
|
8256
8126
|
console.log(`[${formatTime()}] Merged ${baseFile} + ${machineFile} → ${outputFile}`);
|
|
@@ -8261,7 +8131,7 @@ async function handleFileChange(changedPath, state, options) {
|
|
|
8261
8131
|
} else if (!result.success && result.error) {
|
|
8262
8132
|
logger.error(`Failed to merge: ${result.error.message}`);
|
|
8263
8133
|
} else if (options.verbose && !result.changed) {
|
|
8264
|
-
logger.info(`No changes needed for ${
|
|
8134
|
+
logger.info(`No changes needed for ${path6.basename(op.outputPath)}`);
|
|
8265
8135
|
}
|
|
8266
8136
|
}
|
|
8267
8137
|
if (!logger.isSilent() && !options.verbose) {
|
|
@@ -8292,7 +8162,7 @@ async function startWatcher(machineName, options = {}) {
|
|
|
8292
8162
|
if (!logger.isSilent()) {
|
|
8293
8163
|
console.log(`✓ Watching ${watchPaths.length} file(s) for changes...`);
|
|
8294
8164
|
for (const watchPath of watchPaths) {
|
|
8295
|
-
console.log(` - ${
|
|
8165
|
+
console.log(` - ${path6.relative(cwd, watchPath)}`);
|
|
8296
8166
|
}
|
|
8297
8167
|
console.log("");
|
|
8298
8168
|
}
|
|
@@ -8305,9 +8175,9 @@ async function startWatcher(machineName, options = {}) {
|
|
|
8305
8175
|
}
|
|
8306
8176
|
});
|
|
8307
8177
|
watcher.on("change", (changedPath) => {
|
|
8308
|
-
const absolutePath =
|
|
8178
|
+
const absolutePath = path6.resolve(cwd, changedPath);
|
|
8309
8179
|
if (options.verbose) {
|
|
8310
|
-
logger.info(`File changed: ${
|
|
8180
|
+
logger.info(`File changed: ${path6.relative(cwd, absolutePath)}`);
|
|
8311
8181
|
}
|
|
8312
8182
|
const existingTimer = state.debounceTimers.get(absolutePath);
|
|
8313
8183
|
if (existingTimer) {
|
|
@@ -8320,9 +8190,9 @@ async function startWatcher(machineName, options = {}) {
|
|
|
8320
8190
|
state.debounceTimers.set(absolutePath, timer);
|
|
8321
8191
|
});
|
|
8322
8192
|
watcher.on("add", async (addedPath) => {
|
|
8323
|
-
const absolutePath =
|
|
8193
|
+
const absolutePath = path6.resolve(cwd, addedPath);
|
|
8324
8194
|
if (options.verbose) {
|
|
8325
|
-
logger.info(`File added: ${
|
|
8195
|
+
logger.info(`File added: ${path6.relative(cwd, absolutePath)}`);
|
|
8326
8196
|
}
|
|
8327
8197
|
const newOperations = await scanForMergeOperations(machineName, cwd);
|
|
8328
8198
|
state.operations = newOperations;
|
|
@@ -8331,7 +8201,7 @@ async function startWatcher(machineName, options = {}) {
|
|
|
8331
8201
|
});
|
|
8332
8202
|
watcher.on("unlink", (deletedPath) => {
|
|
8333
8203
|
if (options.verbose) {
|
|
8334
|
-
const relPath =
|
|
8204
|
+
const relPath = path6.relative(cwd, deletedPath);
|
|
8335
8205
|
logger.warn(`File deleted: ${relPath}`);
|
|
8336
8206
|
logger.info("Run merge manually or restart watch to update operations");
|
|
8337
8207
|
}
|
|
@@ -8352,22 +8222,37 @@ async function startWatcher(machineName, options = {}) {
|
|
|
8352
8222
|
}
|
|
8353
8223
|
|
|
8354
8224
|
// src/cli.ts
|
|
8355
|
-
import
|
|
8356
|
-
import
|
|
8357
|
-
import { fileURLToPath as
|
|
8225
|
+
import fs3 from "node:fs/promises";
|
|
8226
|
+
import path7 from "node:path";
|
|
8227
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
8358
8228
|
import { createInterface } from "node:readline";
|
|
8359
|
-
var
|
|
8360
|
-
var
|
|
8229
|
+
var __filename2 = fileURLToPath3(import.meta.url);
|
|
8230
|
+
var __dirname2 = path7.dirname(__filename2);
|
|
8361
8231
|
async function checkExistingOutputFiles(operations) {
|
|
8362
8232
|
const existing = [];
|
|
8363
8233
|
for (const op of operations) {
|
|
8364
8234
|
try {
|
|
8365
|
-
await
|
|
8235
|
+
await fs3.access(op.outputPath);
|
|
8366
8236
|
existing.push(op.outputPath);
|
|
8367
8237
|
} catch {}
|
|
8368
8238
|
}
|
|
8369
8239
|
return existing;
|
|
8370
8240
|
}
|
|
8241
|
+
async function checkTrackedOutputFiles(operations) {
|
|
8242
|
+
const tracked = [];
|
|
8243
|
+
const cwd = process.cwd();
|
|
8244
|
+
for (const op of operations) {
|
|
8245
|
+
try {
|
|
8246
|
+
await fs3.access(op.outputPath);
|
|
8247
|
+
const relativePath = path7.relative(cwd, op.outputPath);
|
|
8248
|
+
const isTracked = await isFileTrackedByGit(relativePath, cwd);
|
|
8249
|
+
if (isTracked) {
|
|
8250
|
+
tracked.push(op.outputPath);
|
|
8251
|
+
}
|
|
8252
|
+
} catch {}
|
|
8253
|
+
}
|
|
8254
|
+
return tracked;
|
|
8255
|
+
}
|
|
8371
8256
|
async function promptConfirmation(message) {
|
|
8372
8257
|
const rl = createInterface({
|
|
8373
8258
|
input: process.stdin,
|
|
@@ -8434,11 +8319,11 @@ async function handleInit(argv) {
|
|
|
8434
8319
|
const operations = await scanForMergeOperations(machineName);
|
|
8435
8320
|
if (operations.length > 0) {
|
|
8436
8321
|
logger.info(`Found ${operations.length} machine-specific file(s)`);
|
|
8437
|
-
const
|
|
8438
|
-
if (
|
|
8322
|
+
const trackedFiles = await checkTrackedOutputFiles(operations);
|
|
8323
|
+
if (trackedFiles.length > 0 && !argv["no-gitignore"]) {
|
|
8439
8324
|
logger.warn("⚠️ Warning: The following files will be overwritten and untracked from git:");
|
|
8440
|
-
for (const file of
|
|
8441
|
-
logger.warn(` - ${
|
|
8325
|
+
for (const file of trackedFiles) {
|
|
8326
|
+
logger.warn(` - ${path7.relative(process.cwd(), file)}`);
|
|
8442
8327
|
}
|
|
8443
8328
|
logger.info("");
|
|
8444
8329
|
const confirmed = await promptConfirmation("Do you want to continue?");
|
|
@@ -8502,11 +8387,11 @@ async function handleMerge(argv) {
|
|
|
8502
8387
|
return;
|
|
8503
8388
|
}
|
|
8504
8389
|
if (!argv.silent && !argv["no-gitignore"]) {
|
|
8505
|
-
const
|
|
8506
|
-
if (
|
|
8390
|
+
const trackedFiles = await checkTrackedOutputFiles(operations);
|
|
8391
|
+
if (trackedFiles.length > 0) {
|
|
8507
8392
|
logger.warn("⚠️ Warning: The following files will be overwritten and untracked from git:");
|
|
8508
|
-
for (const file of
|
|
8509
|
-
logger.warn(` - ${
|
|
8393
|
+
for (const file of trackedFiles) {
|
|
8394
|
+
logger.warn(` - ${path7.relative(process.cwd(), file)}`);
|
|
8510
8395
|
}
|
|
8511
8396
|
logger.info("");
|
|
8512
8397
|
const confirmed = await promptConfirmation("Do you want to continue?");
|
|
@@ -8544,11 +8429,11 @@ async function handleInfo(argv) {
|
|
|
8544
8429
|
const operations = await scanForMergeOperations(machineName);
|
|
8545
8430
|
console.log(`Machine name: ${machineName}`);
|
|
8546
8431
|
console.log(`Repository: ${process.cwd()}`);
|
|
8547
|
-
const { exec:
|
|
8548
|
-
const { promisify:
|
|
8549
|
-
const
|
|
8432
|
+
const { exec: exec2 } = await import("node:child_process");
|
|
8433
|
+
const { promisify: promisify2 } = await import("node:util");
|
|
8434
|
+
const execAsync2 = promisify2(exec2);
|
|
8550
8435
|
try {
|
|
8551
|
-
const { stdout } = await
|
|
8436
|
+
const { stdout } = await execAsync2("git config --get core.hooksPath");
|
|
8552
8437
|
const hooksPath = stdout.trim();
|
|
8553
8438
|
if (hooksPath) {
|
|
8554
8439
|
console.log(`Hooks method: core.hooksPath`);
|
|
@@ -8561,9 +8446,9 @@ async function handleInfo(argv) {
|
|
|
8561
8446
|
}
|
|
8562
8447
|
console.log(`Tracked patterns: ${operations.length}`);
|
|
8563
8448
|
for (const op of operations) {
|
|
8564
|
-
const baseName = op.basePath ?
|
|
8565
|
-
const machineName2 =
|
|
8566
|
-
const outputName =
|
|
8449
|
+
const baseName = op.basePath ? path7.basename(op.basePath) : "(none)";
|
|
8450
|
+
const machineName2 = path7.basename(op.machinePath);
|
|
8451
|
+
const outputName = path7.basename(op.outputPath);
|
|
8567
8452
|
console.log(` - ${baseName} + ${machineName2} → ${outputName}`);
|
|
8568
8453
|
}
|
|
8569
8454
|
if (operations.length > 0) {
|
|
@@ -8573,7 +8458,7 @@ async function handleInfo(argv) {
|
|
|
8573
8458
|
if (existingFiles.length > 0) {
|
|
8574
8459
|
console.log("Existing output files:");
|
|
8575
8460
|
for (const file of existingFiles) {
|
|
8576
|
-
console.log(` - ${
|
|
8461
|
+
console.log(` - ${path7.relative(process.cwd(), file)}`);
|
|
8577
8462
|
}
|
|
8578
8463
|
}
|
|
8579
8464
|
}
|
|
@@ -8654,8 +8539,8 @@ DOCUMENTATION:
|
|
|
8654
8539
|
}
|
|
8655
8540
|
async function showVersion() {
|
|
8656
8541
|
try {
|
|
8657
|
-
const packageJsonPath =
|
|
8658
|
-
const packageJson = JSON.parse(await
|
|
8542
|
+
const packageJsonPath = path7.join(__dirname2, "../package.json");
|
|
8543
|
+
const packageJson = JSON.parse(await fs3.readFile(packageJsonPath, "utf-8"));
|
|
8659
8544
|
console.log(packageJson.version);
|
|
8660
8545
|
} catch {
|
|
8661
8546
|
console.log("unknown");
|