@karmaniverous/jeeves-watcher 0.18.3 → 0.18.4
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.
|
@@ -934,17 +934,32 @@ class CommitMessageGenerator {
|
|
|
934
934
|
*/
|
|
935
935
|
/** Promisified execFile for git commands. */
|
|
936
936
|
const execFileAsync = promisify(execFile);
|
|
937
|
+
/**
|
|
938
|
+
* Normalize a path for case-insensitive comparison on Windows.
|
|
939
|
+
* On Windows, lowercases the entire path; on other platforms, returns as-is.
|
|
940
|
+
*
|
|
941
|
+
* @param p - The path string to normalize.
|
|
942
|
+
* @param platform - The platform to check against (default: `process.platform`).
|
|
943
|
+
* @returns The normalized path.
|
|
944
|
+
*/
|
|
945
|
+
function normalizePathCase(p, platform = process.platform) {
|
|
946
|
+
return platform === 'win32' ? p.toLowerCase() : p;
|
|
947
|
+
}
|
|
937
948
|
/**
|
|
938
949
|
* Find the longest-prefix-match root for a normalized path.
|
|
939
950
|
* Roots must be sorted longest-first for correct nested matching.
|
|
940
951
|
*
|
|
941
952
|
* @param roots - Root paths sorted longest-first.
|
|
942
953
|
* @param normalizedPath - Normalized absolute path (forward slashes).
|
|
954
|
+
* @param platform - The platform to check against (default: `process.platform`).
|
|
943
955
|
* @returns The matching root, or undefined.
|
|
944
956
|
*/
|
|
945
|
-
function findRootForPath(roots, normalizedPath) {
|
|
957
|
+
function findRootForPath(roots, normalizedPath, platform = process.platform) {
|
|
958
|
+
const comparePath = normalizePathCase(normalizedPath, platform);
|
|
946
959
|
for (const root of roots) {
|
|
947
|
-
|
|
960
|
+
const compareRoot = normalizePathCase(root, platform);
|
|
961
|
+
if (comparePath === compareRoot ||
|
|
962
|
+
comparePath.startsWith(compareRoot + '/')) {
|
|
948
963
|
return root;
|
|
949
964
|
}
|
|
950
965
|
}
|
|
@@ -1303,6 +1318,7 @@ class VcsManager {
|
|
|
1303
1318
|
debounceTimer;
|
|
1304
1319
|
commitInFlight = Promise.resolve();
|
|
1305
1320
|
started = false;
|
|
1321
|
+
isBaseline = false;
|
|
1306
1322
|
_lastPushTime = null;
|
|
1307
1323
|
constructor(rootPath, config, logger, commitMessageGenerator, remoteUrl, accessToken) {
|
|
1308
1324
|
this.rootPath = rootPath;
|
|
@@ -1323,11 +1339,47 @@ class VcsManager {
|
|
|
1323
1339
|
}
|
|
1324
1340
|
/**
|
|
1325
1341
|
* Begin accepting file changes. Sets up the debounce mechanism.
|
|
1342
|
+
* Enqueues a baseline commit for pre-existing files if the repo has no commits.
|
|
1326
1343
|
*/
|
|
1327
|
-
start() {
|
|
1344
|
+
async start() {
|
|
1328
1345
|
this.started = true;
|
|
1329
1346
|
this.squashManager?.start();
|
|
1330
1347
|
this.logger.info({ root: this.rootPath }, 'VcsManager started');
|
|
1348
|
+
await this.enqueueBaselineIfNeeded();
|
|
1349
|
+
}
|
|
1350
|
+
/**
|
|
1351
|
+
* If the repo has no commits, enumerate untracked files and feed them
|
|
1352
|
+
* through fileChanged() to create a baseline commit.
|
|
1353
|
+
*/
|
|
1354
|
+
async enqueueBaselineIfNeeded() {
|
|
1355
|
+
try {
|
|
1356
|
+
await execFileAsync('git', ['rev-parse', 'HEAD'], {
|
|
1357
|
+
cwd: this.rootPath,
|
|
1358
|
+
});
|
|
1359
|
+
// HEAD exists — repo already has commits
|
|
1360
|
+
return;
|
|
1361
|
+
}
|
|
1362
|
+
catch {
|
|
1363
|
+
// No commits yet — proceed with baseline
|
|
1364
|
+
}
|
|
1365
|
+
try {
|
|
1366
|
+
const { stdout } = await execFileAsync('git', ['ls-files', '--others', '--exclude-standard', '-z'], { cwd: this.rootPath });
|
|
1367
|
+
const files = stdout
|
|
1368
|
+
.split('\0')
|
|
1369
|
+
.map((line) => line.trim())
|
|
1370
|
+
.filter((line) => line.length > 0);
|
|
1371
|
+
if (files.length === 0)
|
|
1372
|
+
return;
|
|
1373
|
+
this.logger.info({ root: this.rootPath, fileCount: files.length }, 'Enqueuing baseline commit for pre-existing files');
|
|
1374
|
+
this.isBaseline = true;
|
|
1375
|
+
const absolutePaths = files.map((f) => this.rootPath + '/' + f);
|
|
1376
|
+
for (const filePath of absolutePaths) {
|
|
1377
|
+
this.fileChanged(filePath);
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
catch (error) {
|
|
1381
|
+
this.logger.warn({ root: this.rootPath, err: normalizeError(error) }, 'Failed to enumerate untracked files for baseline commit');
|
|
1382
|
+
}
|
|
1331
1383
|
}
|
|
1332
1384
|
/**
|
|
1333
1385
|
* Add a file to the pending set and reset the debounce timer.
|
|
@@ -1442,6 +1494,9 @@ class VcsManager {
|
|
|
1442
1494
|
*/
|
|
1443
1495
|
buildTemplateMessage(fileCount) {
|
|
1444
1496
|
if (this.pendingReversions.length === 0) {
|
|
1497
|
+
if (this.isBaseline) {
|
|
1498
|
+
return `baseline: batch (${String(fileCount)} files)`;
|
|
1499
|
+
}
|
|
1445
1500
|
const timestamp = new Date().toISOString();
|
|
1446
1501
|
return `watcher: batch ${timestamp} (${String(fileCount)} files)`;
|
|
1447
1502
|
}
|
|
@@ -1499,10 +1554,15 @@ class VcsManager {
|
|
|
1499
1554
|
cwd: this.rootPath,
|
|
1500
1555
|
});
|
|
1501
1556
|
// Build message after staging so getStagedDiff can see the changes
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1557
|
+
// Skip AI for baselines and retries — use template directly
|
|
1558
|
+
const message = this.isBaseline || attempt > 1
|
|
1559
|
+
? this.buildTemplateMessage(files.length)
|
|
1560
|
+
: await this.buildCommitMessage(files);
|
|
1505
1561
|
this.pendingReversions.length = 0;
|
|
1562
|
+
// Only clear baseline flag when all baseline files have been committed
|
|
1563
|
+
if (this.pending.size === 0) {
|
|
1564
|
+
this.isBaseline = false;
|
|
1565
|
+
}
|
|
1506
1566
|
await execFileAsync('git', ['commit', '-m', message], {
|
|
1507
1567
|
cwd: this.rootPath,
|
|
1508
1568
|
});
|
|
@@ -1579,8 +1639,9 @@ class VcsCoordinator {
|
|
|
1579
1639
|
if (!rootVcs)
|
|
1580
1640
|
continue;
|
|
1581
1641
|
const resolvedRoot = normalizeSlashes(resolve(globRoot(entry.path)));
|
|
1642
|
+
const rootKey = normalizePathCase(resolvedRoot);
|
|
1582
1643
|
// Deduplicate: skip if another glob already resolved to this root.
|
|
1583
|
-
if (this.managers.has(
|
|
1644
|
+
if (this.managers.has(rootKey))
|
|
1584
1645
|
continue;
|
|
1585
1646
|
const mergedConfig = {
|
|
1586
1647
|
...config.vcs,
|
|
@@ -1600,7 +1661,7 @@ class VcsCoordinator {
|
|
|
1600
1661
|
const remoteUrl = entry.vcs?.remote;
|
|
1601
1662
|
const accessToken = entry.vcs?.accessToken ?? config.vcs.defaultAccessToken;
|
|
1602
1663
|
const manager = new VcsManager(resolvedRoot, mergedConfig, logger.child({ vcsRoot: resolvedRoot }), generator, remoteUrl, accessToken);
|
|
1603
|
-
this.managers.set(
|
|
1664
|
+
this.managers.set(rootKey, manager);
|
|
1604
1665
|
this.roots.push(resolvedRoot);
|
|
1605
1666
|
}
|
|
1606
1667
|
// Sort roots longest-first so nested paths match before parents.
|
|
@@ -1609,10 +1670,12 @@ class VcsCoordinator {
|
|
|
1609
1670
|
/**
|
|
1610
1671
|
* Start all VcsManager instances.
|
|
1611
1672
|
*/
|
|
1612
|
-
start() {
|
|
1673
|
+
async start() {
|
|
1674
|
+
const startPromises = [];
|
|
1613
1675
|
this.managers.forEach((manager) => {
|
|
1614
|
-
manager.start();
|
|
1676
|
+
startPromises.push(manager.start());
|
|
1615
1677
|
});
|
|
1678
|
+
await Promise.all(startPromises);
|
|
1616
1679
|
this.logger.info({ rootCount: this.managers.size }, 'VcsCoordinator started');
|
|
1617
1680
|
}
|
|
1618
1681
|
/**
|
|
@@ -1654,7 +1717,7 @@ class VcsCoordinator {
|
|
|
1654
1717
|
* Get the VcsManager for a specific root path.
|
|
1655
1718
|
*/
|
|
1656
1719
|
getManager(root) {
|
|
1657
|
-
return this.managers.get(root);
|
|
1720
|
+
return this.managers.get(normalizePathCase(root));
|
|
1658
1721
|
}
|
|
1659
1722
|
/**
|
|
1660
1723
|
* Get all managers as [root, manager] pairs.
|
|
@@ -1671,7 +1734,7 @@ class VcsCoordinator {
|
|
|
1671
1734
|
*/
|
|
1672
1735
|
findManagerForPath(normalizedPath) {
|
|
1673
1736
|
const root = findRootForPath(this.roots, normalizedPath);
|
|
1674
|
-
return root ? this.managers.get(root) : undefined;
|
|
1737
|
+
return root ? this.managers.get(normalizePathCase(root)) : undefined;
|
|
1675
1738
|
}
|
|
1676
1739
|
}
|
|
1677
1740
|
|
|
@@ -2892,15 +2955,18 @@ function resolveWatchRootsForGlob(coordinator, glob) {
|
|
|
2892
2955
|
const normalizedGlob = normalizeSlashes(glob);
|
|
2893
2956
|
const roots = coordinator.getRoots();
|
|
2894
2957
|
const results = [];
|
|
2958
|
+
const compareGlob = normalizePathCase(normalizedGlob);
|
|
2895
2959
|
for (const root of roots) {
|
|
2896
|
-
|
|
2960
|
+
const compareRoot = normalizePathCase(root);
|
|
2961
|
+
if (compareGlob.startsWith(compareRoot + '/') ||
|
|
2962
|
+
compareGlob === compareRoot) {
|
|
2897
2963
|
// Glob is under this root
|
|
2898
2964
|
results.push({
|
|
2899
2965
|
root,
|
|
2900
2966
|
relativePath: normalizeSlashes(relative(root, normalizedGlob)),
|
|
2901
2967
|
});
|
|
2902
2968
|
}
|
|
2903
|
-
else if (
|
|
2969
|
+
else if (compareRoot.startsWith(compareGlob.replace(/[*?[\]{}]/g, ''))) {
|
|
2904
2970
|
// Root is under the glob's base path — include with root-relative glob
|
|
2905
2971
|
results.push({
|
|
2906
2972
|
root,
|
|
@@ -7694,7 +7760,7 @@ class JeevesWatcher {
|
|
|
7694
7760
|
this.watcher = watcher;
|
|
7695
7761
|
this.gitignoreFilter = gitignoreFilter;
|
|
7696
7762
|
this.server = await this.startApiServer();
|
|
7697
|
-
vcsCoordinator.start();
|
|
7763
|
+
await vcsCoordinator.start();
|
|
7698
7764
|
this.watcher.start();
|
|
7699
7765
|
this.startConfigWatch();
|
|
7700
7766
|
logger.info('jeeves-watcher started');
|
|
@@ -224,7 +224,7 @@ async function startFromConfig(configPath, descriptor) {
|
|
|
224
224
|
const config = await loadConfig(resolvedPath);
|
|
225
225
|
// Dynamic import breaks the circular dependency between this module
|
|
226
226
|
// and app/index.ts (which defines JeevesWatcher and re-exports startFromConfig).
|
|
227
|
-
const { JeevesWatcher } = await import('./index-
|
|
227
|
+
const { JeevesWatcher } = await import('./index-ChYxOGtD.js');
|
|
228
228
|
const app = new JeevesWatcher(config, resolvedPath, descriptor);
|
|
229
229
|
installShutdownHandlers(() => app.stop());
|
|
230
230
|
await app.start();
|
package/dist/index.d.ts
CHANGED
|
@@ -1291,14 +1291,21 @@ declare class VcsManager {
|
|
|
1291
1291
|
private debounceTimer;
|
|
1292
1292
|
private commitInFlight;
|
|
1293
1293
|
private started;
|
|
1294
|
+
private isBaseline;
|
|
1294
1295
|
private _lastPushTime;
|
|
1295
1296
|
constructor(rootPath: string, config: VcsConfig, logger: pino.Logger, commitMessageGenerator?: CommitMessageGenerator, remoteUrl?: string, accessToken?: string);
|
|
1296
1297
|
get lastPushTime(): string | null;
|
|
1297
1298
|
get pushErrors(): readonly PushError[];
|
|
1298
1299
|
/**
|
|
1299
1300
|
* Begin accepting file changes. Sets up the debounce mechanism.
|
|
1301
|
+
* Enqueues a baseline commit for pre-existing files if the repo has no commits.
|
|
1300
1302
|
*/
|
|
1301
|
-
start(): void
|
|
1303
|
+
start(): Promise<void>;
|
|
1304
|
+
/**
|
|
1305
|
+
* If the repo has no commits, enumerate untracked files and feed them
|
|
1306
|
+
* through fileChanged() to create a baseline commit.
|
|
1307
|
+
*/
|
|
1308
|
+
private enqueueBaselineIfNeeded;
|
|
1302
1309
|
/**
|
|
1303
1310
|
* Add a file to the pending set and reset the debounce timer.
|
|
1304
1311
|
* If the pending set exceeds maxBatchSize, flush immediately.
|
|
@@ -1379,7 +1386,7 @@ declare class VcsCoordinator {
|
|
|
1379
1386
|
/**
|
|
1380
1387
|
* Start all VcsManager instances.
|
|
1381
1388
|
*/
|
|
1382
|
-
start(): void
|
|
1389
|
+
start(): Promise<void>;
|
|
1383
1390
|
/**
|
|
1384
1391
|
* Route a file event to the correct root's VcsManager.
|
|
1385
1392
|
*
|
package/dist/index.js
CHANGED
|
@@ -3375,17 +3375,32 @@ function createSearchHandler(deps) {
|
|
|
3375
3375
|
*/
|
|
3376
3376
|
/** Promisified execFile for git commands. */
|
|
3377
3377
|
const execFileAsync = promisify(execFile);
|
|
3378
|
+
/**
|
|
3379
|
+
* Normalize a path for case-insensitive comparison on Windows.
|
|
3380
|
+
* On Windows, lowercases the entire path; on other platforms, returns as-is.
|
|
3381
|
+
*
|
|
3382
|
+
* @param p - The path string to normalize.
|
|
3383
|
+
* @param platform - The platform to check against (default: `process.platform`).
|
|
3384
|
+
* @returns The normalized path.
|
|
3385
|
+
*/
|
|
3386
|
+
function normalizePathCase(p, platform = process.platform) {
|
|
3387
|
+
return platform === 'win32' ? p.toLowerCase() : p;
|
|
3388
|
+
}
|
|
3378
3389
|
/**
|
|
3379
3390
|
* Find the longest-prefix-match root for a normalized path.
|
|
3380
3391
|
* Roots must be sorted longest-first for correct nested matching.
|
|
3381
3392
|
*
|
|
3382
3393
|
* @param roots - Root paths sorted longest-first.
|
|
3383
3394
|
* @param normalizedPath - Normalized absolute path (forward slashes).
|
|
3395
|
+
* @param platform - The platform to check against (default: `process.platform`).
|
|
3384
3396
|
* @returns The matching root, or undefined.
|
|
3385
3397
|
*/
|
|
3386
|
-
function findRootForPath(roots, normalizedPath) {
|
|
3398
|
+
function findRootForPath(roots, normalizedPath, platform = process.platform) {
|
|
3399
|
+
const comparePath = normalizePathCase(normalizedPath, platform);
|
|
3387
3400
|
for (const root of roots) {
|
|
3388
|
-
|
|
3401
|
+
const compareRoot = normalizePathCase(root, platform);
|
|
3402
|
+
if (comparePath === compareRoot ||
|
|
3403
|
+
comparePath.startsWith(compareRoot + '/')) {
|
|
3389
3404
|
return root;
|
|
3390
3405
|
}
|
|
3391
3406
|
}
|
|
@@ -3425,15 +3440,18 @@ function resolveWatchRootsForGlob(coordinator, glob) {
|
|
|
3425
3440
|
const normalizedGlob = normalizeSlashes(glob);
|
|
3426
3441
|
const roots = coordinator.getRoots();
|
|
3427
3442
|
const results = [];
|
|
3443
|
+
const compareGlob = normalizePathCase(normalizedGlob);
|
|
3428
3444
|
for (const root of roots) {
|
|
3429
|
-
|
|
3445
|
+
const compareRoot = normalizePathCase(root);
|
|
3446
|
+
if (compareGlob.startsWith(compareRoot + '/') ||
|
|
3447
|
+
compareGlob === compareRoot) {
|
|
3430
3448
|
// Glob is under this root
|
|
3431
3449
|
results.push({
|
|
3432
3450
|
root,
|
|
3433
3451
|
relativePath: normalizeSlashes(relative(root, normalizedGlob)),
|
|
3434
3452
|
});
|
|
3435
3453
|
}
|
|
3436
|
-
else if (
|
|
3454
|
+
else if (compareRoot.startsWith(compareGlob.replace(/[*?[\]{}]/g, ''))) {
|
|
3437
3455
|
// Root is under the glob's base path — include with root-relative glob
|
|
3438
3456
|
results.push({
|
|
3439
3457
|
root,
|
|
@@ -4780,6 +4798,7 @@ class VcsManager {
|
|
|
4780
4798
|
debounceTimer;
|
|
4781
4799
|
commitInFlight = Promise.resolve();
|
|
4782
4800
|
started = false;
|
|
4801
|
+
isBaseline = false;
|
|
4783
4802
|
_lastPushTime = null;
|
|
4784
4803
|
constructor(rootPath, config, logger, commitMessageGenerator, remoteUrl, accessToken) {
|
|
4785
4804
|
this.rootPath = rootPath;
|
|
@@ -4800,11 +4819,47 @@ class VcsManager {
|
|
|
4800
4819
|
}
|
|
4801
4820
|
/**
|
|
4802
4821
|
* Begin accepting file changes. Sets up the debounce mechanism.
|
|
4822
|
+
* Enqueues a baseline commit for pre-existing files if the repo has no commits.
|
|
4803
4823
|
*/
|
|
4804
|
-
start() {
|
|
4824
|
+
async start() {
|
|
4805
4825
|
this.started = true;
|
|
4806
4826
|
this.squashManager?.start();
|
|
4807
4827
|
this.logger.info({ root: this.rootPath }, 'VcsManager started');
|
|
4828
|
+
await this.enqueueBaselineIfNeeded();
|
|
4829
|
+
}
|
|
4830
|
+
/**
|
|
4831
|
+
* If the repo has no commits, enumerate untracked files and feed them
|
|
4832
|
+
* through fileChanged() to create a baseline commit.
|
|
4833
|
+
*/
|
|
4834
|
+
async enqueueBaselineIfNeeded() {
|
|
4835
|
+
try {
|
|
4836
|
+
await execFileAsync('git', ['rev-parse', 'HEAD'], {
|
|
4837
|
+
cwd: this.rootPath,
|
|
4838
|
+
});
|
|
4839
|
+
// HEAD exists — repo already has commits
|
|
4840
|
+
return;
|
|
4841
|
+
}
|
|
4842
|
+
catch {
|
|
4843
|
+
// No commits yet — proceed with baseline
|
|
4844
|
+
}
|
|
4845
|
+
try {
|
|
4846
|
+
const { stdout } = await execFileAsync('git', ['ls-files', '--others', '--exclude-standard', '-z'], { cwd: this.rootPath });
|
|
4847
|
+
const files = stdout
|
|
4848
|
+
.split('\0')
|
|
4849
|
+
.map((line) => line.trim())
|
|
4850
|
+
.filter((line) => line.length > 0);
|
|
4851
|
+
if (files.length === 0)
|
|
4852
|
+
return;
|
|
4853
|
+
this.logger.info({ root: this.rootPath, fileCount: files.length }, 'Enqueuing baseline commit for pre-existing files');
|
|
4854
|
+
this.isBaseline = true;
|
|
4855
|
+
const absolutePaths = files.map((f) => this.rootPath + '/' + f);
|
|
4856
|
+
for (const filePath of absolutePaths) {
|
|
4857
|
+
this.fileChanged(filePath);
|
|
4858
|
+
}
|
|
4859
|
+
}
|
|
4860
|
+
catch (error) {
|
|
4861
|
+
this.logger.warn({ root: this.rootPath, err: normalizeError(error) }, 'Failed to enumerate untracked files for baseline commit');
|
|
4862
|
+
}
|
|
4808
4863
|
}
|
|
4809
4864
|
/**
|
|
4810
4865
|
* Add a file to the pending set and reset the debounce timer.
|
|
@@ -4919,6 +4974,9 @@ class VcsManager {
|
|
|
4919
4974
|
*/
|
|
4920
4975
|
buildTemplateMessage(fileCount) {
|
|
4921
4976
|
if (this.pendingReversions.length === 0) {
|
|
4977
|
+
if (this.isBaseline) {
|
|
4978
|
+
return `baseline: batch (${String(fileCount)} files)`;
|
|
4979
|
+
}
|
|
4922
4980
|
const timestamp = new Date().toISOString();
|
|
4923
4981
|
return `watcher: batch ${timestamp} (${String(fileCount)} files)`;
|
|
4924
4982
|
}
|
|
@@ -4976,10 +5034,15 @@ class VcsManager {
|
|
|
4976
5034
|
cwd: this.rootPath,
|
|
4977
5035
|
});
|
|
4978
5036
|
// Build message after staging so getStagedDiff can see the changes
|
|
4979
|
-
|
|
4980
|
-
|
|
4981
|
-
|
|
5037
|
+
// Skip AI for baselines and retries — use template directly
|
|
5038
|
+
const message = this.isBaseline || attempt > 1
|
|
5039
|
+
? this.buildTemplateMessage(files.length)
|
|
5040
|
+
: await this.buildCommitMessage(files);
|
|
4982
5041
|
this.pendingReversions.length = 0;
|
|
5042
|
+
// Only clear baseline flag when all baseline files have been committed
|
|
5043
|
+
if (this.pending.size === 0) {
|
|
5044
|
+
this.isBaseline = false;
|
|
5045
|
+
}
|
|
4983
5046
|
await execFileAsync('git', ['commit', '-m', message], {
|
|
4984
5047
|
cwd: this.rootPath,
|
|
4985
5048
|
});
|
|
@@ -5056,8 +5119,9 @@ class VcsCoordinator {
|
|
|
5056
5119
|
if (!rootVcs)
|
|
5057
5120
|
continue;
|
|
5058
5121
|
const resolvedRoot = normalizeSlashes(resolve(globRoot(entry.path)));
|
|
5122
|
+
const rootKey = normalizePathCase(resolvedRoot);
|
|
5059
5123
|
// Deduplicate: skip if another glob already resolved to this root.
|
|
5060
|
-
if (this.managers.has(
|
|
5124
|
+
if (this.managers.has(rootKey))
|
|
5061
5125
|
continue;
|
|
5062
5126
|
const mergedConfig = {
|
|
5063
5127
|
...config.vcs,
|
|
@@ -5077,7 +5141,7 @@ class VcsCoordinator {
|
|
|
5077
5141
|
const remoteUrl = entry.vcs?.remote;
|
|
5078
5142
|
const accessToken = entry.vcs?.accessToken ?? config.vcs.defaultAccessToken;
|
|
5079
5143
|
const manager = new VcsManager(resolvedRoot, mergedConfig, logger.child({ vcsRoot: resolvedRoot }), generator, remoteUrl, accessToken);
|
|
5080
|
-
this.managers.set(
|
|
5144
|
+
this.managers.set(rootKey, manager);
|
|
5081
5145
|
this.roots.push(resolvedRoot);
|
|
5082
5146
|
}
|
|
5083
5147
|
// Sort roots longest-first so nested paths match before parents.
|
|
@@ -5086,10 +5150,12 @@ class VcsCoordinator {
|
|
|
5086
5150
|
/**
|
|
5087
5151
|
* Start all VcsManager instances.
|
|
5088
5152
|
*/
|
|
5089
|
-
start() {
|
|
5153
|
+
async start() {
|
|
5154
|
+
const startPromises = [];
|
|
5090
5155
|
this.managers.forEach((manager) => {
|
|
5091
|
-
manager.start();
|
|
5156
|
+
startPromises.push(manager.start());
|
|
5092
5157
|
});
|
|
5158
|
+
await Promise.all(startPromises);
|
|
5093
5159
|
this.logger.info({ rootCount: this.managers.size }, 'VcsCoordinator started');
|
|
5094
5160
|
}
|
|
5095
5161
|
/**
|
|
@@ -5131,7 +5197,7 @@ class VcsCoordinator {
|
|
|
5131
5197
|
* Get the VcsManager for a specific root path.
|
|
5132
5198
|
*/
|
|
5133
5199
|
getManager(root) {
|
|
5134
|
-
return this.managers.get(root);
|
|
5200
|
+
return this.managers.get(normalizePathCase(root));
|
|
5135
5201
|
}
|
|
5136
5202
|
/**
|
|
5137
5203
|
* Get all managers as [root, manager] pairs.
|
|
@@ -5148,7 +5214,7 @@ class VcsCoordinator {
|
|
|
5148
5214
|
*/
|
|
5149
5215
|
findManagerForPath(normalizedPath) {
|
|
5150
5216
|
const root = findRootForPath(this.roots, normalizedPath);
|
|
5151
|
-
return root ? this.managers.get(root) : undefined;
|
|
5217
|
+
return root ? this.managers.get(normalizePathCase(root)) : undefined;
|
|
5152
5218
|
}
|
|
5153
5219
|
}
|
|
5154
5220
|
|
|
@@ -8845,7 +8911,7 @@ class JeevesWatcher {
|
|
|
8845
8911
|
this.watcher = watcher;
|
|
8846
8912
|
this.gitignoreFilter = gitignoreFilter;
|
|
8847
8913
|
this.server = await this.startApiServer();
|
|
8848
|
-
vcsCoordinator.start();
|
|
8914
|
+
await vcsCoordinator.start();
|
|
8849
8915
|
this.watcher.start();
|
|
8850
8916
|
this.startConfigWatch();
|
|
8851
8917
|
logger.info('jeeves-watcher started');
|
package/package.json
CHANGED