@wipcomputer/wip-ldm-os 0.4.31 → 0.4.33
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/SKILL.md +1 -1
- package/bin/ldm.js +174 -3
- package/package.json +1 -1
package/SKILL.md
CHANGED
package/bin/ldm.js
CHANGED
|
@@ -895,9 +895,11 @@ async function cmdInstallCatalog() {
|
|
|
895
895
|
// Check parent packages for toolbox-style repos (#132)
|
|
896
896
|
// If sub-tools are installed but the parent npm package has a newer version,
|
|
897
897
|
// report the parent as needing an update (not the individual sub-tool).
|
|
898
|
-
|
|
898
|
+
// Don't skip packages already found by the extension loop. The parent check
|
|
899
|
+
// REPLACES sub-tool entries with the parent name.
|
|
900
|
+
const checkedParentNpm = new Set();
|
|
899
901
|
for (const comp of components) {
|
|
900
|
-
if (!comp.npm ||
|
|
902
|
+
if (!comp.npm || checkedParentNpm.has(comp.npm)) continue;
|
|
901
903
|
if (!comp.registryMatches || comp.registryMatches.length === 0) continue;
|
|
902
904
|
|
|
903
905
|
// If any registryMatch is installed, check the parent package
|
|
@@ -929,7 +931,7 @@ async function cmdInstallCatalog() {
|
|
|
929
931
|
});
|
|
930
932
|
}
|
|
931
933
|
} catch {}
|
|
932
|
-
|
|
934
|
+
checkedParentNpm.add(comp.npm);
|
|
933
935
|
}
|
|
934
936
|
|
|
935
937
|
const totalUpdates = npmUpdates.length;
|
|
@@ -1113,6 +1115,9 @@ async function cmdInstallCatalog() {
|
|
|
1113
1115
|
|
|
1114
1116
|
// Update from npm via catalog repos (#55) and CLIs (#81)
|
|
1115
1117
|
for (const entry of npmUpdates) {
|
|
1118
|
+
// CLI self-update is handled by the self-update block at the top of cmdInstallCatalog()
|
|
1119
|
+
if (entry.isCLI) continue;
|
|
1120
|
+
|
|
1116
1121
|
// CLI-only entries: install directly from npm (#81)
|
|
1117
1122
|
if (entry.cliOnly) {
|
|
1118
1123
|
console.log(` Updating CLI ${entry.name} v${entry.currentVersion} -> v${entry.latestVersion}...`);
|
|
@@ -1133,6 +1138,21 @@ async function cmdInstallCatalog() {
|
|
|
1133
1138
|
try {
|
|
1134
1139
|
execSync(`ldm install ${entry.catalogRepo}`, { stdio: 'inherit' });
|
|
1135
1140
|
updated++;
|
|
1141
|
+
|
|
1142
|
+
// For parent packages, update registry version for all sub-tools (#139)
|
|
1143
|
+
if (entry.isParent && entry.registryMatches) {
|
|
1144
|
+
const registry = readJSON(REGISTRY_PATH);
|
|
1145
|
+
if (registry?.extensions) {
|
|
1146
|
+
for (const subTool of entry.registryMatches) {
|
|
1147
|
+
if (registry.extensions[subTool]) {
|
|
1148
|
+
registry.extensions[subTool].version = entry.latestVersion;
|
|
1149
|
+
registry.extensions[subTool].updatedAt = new Date().toISOString();
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
writeFileSync(REGISTRY_PATH, JSON.stringify(registry, null, 2));
|
|
1153
|
+
console.log(` + Updated registry for ${entry.registryMatches.length} sub-tools`);
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1136
1156
|
} catch (e) {
|
|
1137
1157
|
console.error(` x Failed to update ${entry.name}: ${e.message}`);
|
|
1138
1158
|
}
|
|
@@ -2366,6 +2386,154 @@ async function main() {
|
|
|
2366
2386
|
console.log('');
|
|
2367
2387
|
}
|
|
2368
2388
|
|
|
2389
|
+
// ── ldm worktree ──
|
|
2390
|
+
|
|
2391
|
+
async function cmdWorktree() {
|
|
2392
|
+
const sub = args[1] || 'list';
|
|
2393
|
+
|
|
2394
|
+
if (sub === '--help' || sub === '-h') {
|
|
2395
|
+
console.log(`
|
|
2396
|
+
ldm worktree add <branch> Create worktree in _worktrees/ (auto-detects repo)
|
|
2397
|
+
ldm worktree list List all worktrees across repos
|
|
2398
|
+
ldm worktree clean Prune worktrees for merged branches
|
|
2399
|
+
ldm worktree remove <path> Remove a specific worktree
|
|
2400
|
+
`);
|
|
2401
|
+
process.exit(0);
|
|
2402
|
+
}
|
|
2403
|
+
|
|
2404
|
+
if (sub === 'add') {
|
|
2405
|
+
const branchName = args[2];
|
|
2406
|
+
if (!branchName) {
|
|
2407
|
+
console.error(' Usage: ldm worktree add <branch-name>');
|
|
2408
|
+
console.error(' Example: ldm worktree add cc-mini/fix-bug');
|
|
2409
|
+
process.exit(1);
|
|
2410
|
+
}
|
|
2411
|
+
|
|
2412
|
+
// Auto-detect repo from CWD
|
|
2413
|
+
let repoRoot;
|
|
2414
|
+
try {
|
|
2415
|
+
repoRoot = execSync('git rev-parse --show-toplevel 2>/dev/null', {
|
|
2416
|
+
encoding: 'utf8', timeout: 3000
|
|
2417
|
+
}).trim();
|
|
2418
|
+
} catch {
|
|
2419
|
+
console.error(' Not inside a git repo. cd into a repo first.');
|
|
2420
|
+
process.exit(1);
|
|
2421
|
+
}
|
|
2422
|
+
|
|
2423
|
+
const repoName = basename(repoRoot);
|
|
2424
|
+
const branchSuffix = branchName.replace(/\//g, '--');
|
|
2425
|
+
const worktreesDir = join(dirname(repoRoot), '_worktrees');
|
|
2426
|
+
const worktreePath = join(worktreesDir, `${repoName}--${branchSuffix}`);
|
|
2427
|
+
|
|
2428
|
+
mkdirSync(worktreesDir, { recursive: true });
|
|
2429
|
+
|
|
2430
|
+
console.log(` Creating worktree for ${repoName}...`);
|
|
2431
|
+
console.log(` Branch: ${branchName}`);
|
|
2432
|
+
console.log(` Path: ${worktreePath}`);
|
|
2433
|
+
|
|
2434
|
+
try {
|
|
2435
|
+
execSync(`git worktree add "${worktreePath}" -b "${branchName}"`, {
|
|
2436
|
+
cwd: repoRoot, stdio: 'inherit'
|
|
2437
|
+
});
|
|
2438
|
+
console.log('');
|
|
2439
|
+
console.log(` Done. Work in: ${worktreePath}`);
|
|
2440
|
+
console.log(` When done: ldm worktree remove "${worktreePath}"`);
|
|
2441
|
+
} catch (e) {
|
|
2442
|
+
console.error(` Failed: ${e.message}`);
|
|
2443
|
+
process.exit(1);
|
|
2444
|
+
}
|
|
2445
|
+
return;
|
|
2446
|
+
}
|
|
2447
|
+
|
|
2448
|
+
if (sub === 'list') {
|
|
2449
|
+
// Find all repos and list their worktrees
|
|
2450
|
+
const reposBase = process.env.LDM_REPOS || process.cwd();
|
|
2451
|
+
let found = 0;
|
|
2452
|
+
|
|
2453
|
+
// Check CWD repo
|
|
2454
|
+
try {
|
|
2455
|
+
const root = execSync('git rev-parse --show-toplevel 2>/dev/null', {
|
|
2456
|
+
encoding: 'utf8', timeout: 3000
|
|
2457
|
+
}).trim();
|
|
2458
|
+
const result = execSync('git worktree list', {
|
|
2459
|
+
cwd: root, encoding: 'utf8', timeout: 5000
|
|
2460
|
+
}).trim();
|
|
2461
|
+
if (result.split('\n').length > 1) {
|
|
2462
|
+
console.log(` ${basename(root)}:`);
|
|
2463
|
+
for (const line of result.split('\n')) {
|
|
2464
|
+
console.log(` ${line}`);
|
|
2465
|
+
}
|
|
2466
|
+
found++;
|
|
2467
|
+
}
|
|
2468
|
+
} catch {}
|
|
2469
|
+
|
|
2470
|
+
// Also check _worktrees/ dir
|
|
2471
|
+
const worktreesDir = join(dirname(process.cwd()), '_worktrees');
|
|
2472
|
+
if (existsSync(worktreesDir)) {
|
|
2473
|
+
try {
|
|
2474
|
+
const entries = readdirSync(worktreesDir, { withFileTypes: true })
|
|
2475
|
+
.filter(d => d.isDirectory());
|
|
2476
|
+
if (entries.length > 0) {
|
|
2477
|
+
console.log(` _worktrees/:`);
|
|
2478
|
+
for (const d of entries) {
|
|
2479
|
+
console.log(` ${d.name}`);
|
|
2480
|
+
}
|
|
2481
|
+
found++;
|
|
2482
|
+
}
|
|
2483
|
+
} catch {}
|
|
2484
|
+
}
|
|
2485
|
+
|
|
2486
|
+
if (found === 0) {
|
|
2487
|
+
console.log(' No active worktrees found.');
|
|
2488
|
+
}
|
|
2489
|
+
return;
|
|
2490
|
+
}
|
|
2491
|
+
|
|
2492
|
+
if (sub === 'remove') {
|
|
2493
|
+
const wtPath = args[2];
|
|
2494
|
+
if (!wtPath) {
|
|
2495
|
+
console.error(' Usage: ldm worktree remove <path>');
|
|
2496
|
+
process.exit(1);
|
|
2497
|
+
}
|
|
2498
|
+
try {
|
|
2499
|
+
// Find the repo root for this worktree
|
|
2500
|
+
const root = execSync('git rev-parse --show-toplevel 2>/dev/null', {
|
|
2501
|
+
cwd: resolve(wtPath), encoding: 'utf8', timeout: 3000
|
|
2502
|
+
}).trim();
|
|
2503
|
+
const mainRoot = execSync('git -C "' + root + '" worktree list --porcelain 2>/dev/null', {
|
|
2504
|
+
encoding: 'utf8', timeout: 5000
|
|
2505
|
+
}).split('\n').find(l => l.startsWith('worktree '))?.replace('worktree ', '');
|
|
2506
|
+
|
|
2507
|
+
execSync(`git worktree remove "${resolve(wtPath)}"`, {
|
|
2508
|
+
cwd: mainRoot || root, stdio: 'inherit'
|
|
2509
|
+
});
|
|
2510
|
+
console.log(` Removed worktree: ${wtPath}`);
|
|
2511
|
+
} catch (e) {
|
|
2512
|
+
console.error(` Failed: ${e.message}`);
|
|
2513
|
+
process.exit(1);
|
|
2514
|
+
}
|
|
2515
|
+
return;
|
|
2516
|
+
}
|
|
2517
|
+
|
|
2518
|
+
if (sub === 'clean') {
|
|
2519
|
+
console.log(' Pruning stale worktrees...');
|
|
2520
|
+
try {
|
|
2521
|
+
const root = execSync('git rev-parse --show-toplevel 2>/dev/null', {
|
|
2522
|
+
encoding: 'utf8', timeout: 3000
|
|
2523
|
+
}).trim();
|
|
2524
|
+
execSync('git worktree prune', { cwd: root, stdio: 'inherit' });
|
|
2525
|
+
console.log(' Done.');
|
|
2526
|
+
} catch (e) {
|
|
2527
|
+
console.error(` Failed: ${e.message}`);
|
|
2528
|
+
}
|
|
2529
|
+
return;
|
|
2530
|
+
}
|
|
2531
|
+
|
|
2532
|
+
console.error(` Unknown subcommand: ${sub}`);
|
|
2533
|
+
console.error(' Run: ldm worktree --help');
|
|
2534
|
+
process.exit(1);
|
|
2535
|
+
}
|
|
2536
|
+
|
|
2369
2537
|
if (command === '--version' || command === '-v') {
|
|
2370
2538
|
console.log(PKG_VERSION);
|
|
2371
2539
|
process.exit(0);
|
|
@@ -2412,6 +2580,9 @@ async function main() {
|
|
|
2412
2580
|
case 'uninstall':
|
|
2413
2581
|
await cmdUninstall();
|
|
2414
2582
|
break;
|
|
2583
|
+
case 'worktree':
|
|
2584
|
+
await cmdWorktree();
|
|
2585
|
+
break;
|
|
2415
2586
|
default:
|
|
2416
2587
|
console.error(` Unknown command: ${command}`);
|
|
2417
2588
|
console.error(` Run: ldm --help`);
|