moluoxixi-ai-rules 0.2.0 → 0.2.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.
|
@@ -412,6 +412,54 @@ function rollbackManagedEntries(entries) {
|
|
|
412
412
|
}
|
|
413
413
|
return rollbackErrors;
|
|
414
414
|
}
|
|
415
|
+
function managedChildNames(currentRoot, nextRoot) {
|
|
416
|
+
const names = new Map();
|
|
417
|
+
for (const root of [currentRoot, nextRoot]) {
|
|
418
|
+
if (!fs.existsSync(root))
|
|
419
|
+
continue;
|
|
420
|
+
requirePlainDirectoryOrMissing(root, 'Managed vendor skills root');
|
|
421
|
+
for (const entry of fs.readdirSync(root, { withFileTypes: true })) {
|
|
422
|
+
if (!entry.isDirectory() && !entry.isFile())
|
|
423
|
+
throw new Error(`Managed vendor skill has unsupported filesystem type: ${path.join(root, entry.name)}`);
|
|
424
|
+
const key = entry.name.toLowerCase();
|
|
425
|
+
const previous = names.get(key);
|
|
426
|
+
if (previous !== undefined && previous !== entry.name)
|
|
427
|
+
throw new Error(`Managed vendor skill names differ only by case: ${previous}, ${entry.name}`);
|
|
428
|
+
names.set(key, entry.name);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
return [...names.values()].sort(compareStable);
|
|
432
|
+
}
|
|
433
|
+
function commitManagedChildren(spec, committedEntries, createdRoots) {
|
|
434
|
+
requirePlainDirectoryOrMissing(spec.current, 'Managed vendor skills root');
|
|
435
|
+
requirePlainDirectoryOrMissing(spec.next, 'Staged vendor skills root');
|
|
436
|
+
const childNames = managedChildNames(spec.current, spec.next);
|
|
437
|
+
if (!fs.existsSync(spec.current)) {
|
|
438
|
+
if (!fs.existsSync(spec.next))
|
|
439
|
+
return;
|
|
440
|
+
fs.mkdirSync(spec.current, { recursive: true });
|
|
441
|
+
createdRoots.push(spec.current);
|
|
442
|
+
}
|
|
443
|
+
for (const name of childNames) {
|
|
444
|
+
const entry = {
|
|
445
|
+
current: path.join(spec.current, name),
|
|
446
|
+
backup: path.join(spec.backup, name),
|
|
447
|
+
movedCurrent: false,
|
|
448
|
+
installedNext: false,
|
|
449
|
+
};
|
|
450
|
+
committedEntries.push(entry);
|
|
451
|
+
if (fs.existsSync(entry.current)) {
|
|
452
|
+
fs.mkdirSync(path.dirname(entry.backup), { recursive: true });
|
|
453
|
+
fs.renameSync(entry.current, entry.backup);
|
|
454
|
+
entry.movedCurrent = true;
|
|
455
|
+
}
|
|
456
|
+
const nextChild = path.join(spec.next, name);
|
|
457
|
+
if (fs.existsSync(nextChild)) {
|
|
458
|
+
fs.renameSync(nextChild, entry.current);
|
|
459
|
+
entry.installedNext = true;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
}
|
|
415
463
|
async function commitManagedEntries(stagingRoot, roleStagingRoot, homeDir, role) {
|
|
416
464
|
const resolvedHome = path.resolve(homeDir);
|
|
417
465
|
const vendorRoot = path.join(resolvedHome, 'vendor');
|
|
@@ -429,6 +477,7 @@ async function commitManagedEntries(stagingRoot, roleStagingRoot, homeDir, role)
|
|
|
429
477
|
const nextRoot = path.join(nextWorkspace, 'vendor');
|
|
430
478
|
const backupRoot = fs.mkdtempSync(path.join(resolvedHome, '.airules-vendor-backup-'));
|
|
431
479
|
const committedEntries = [];
|
|
480
|
+
const createdRoots = [];
|
|
432
481
|
try {
|
|
433
482
|
fs.mkdirSync(nextRoot);
|
|
434
483
|
fs.cpSync(stagingRoot, nextRoot, { recursive: true, dereference: true });
|
|
@@ -436,6 +485,7 @@ async function commitManagedEntries(stagingRoot, roleStagingRoot, homeDir, role)
|
|
|
436
485
|
current: path.join(vendorRoot, name),
|
|
437
486
|
next: path.join(nextRoot, name),
|
|
438
487
|
backup: path.join(backupRoot, 'vendor', name),
|
|
488
|
+
preserveRoot: name === 'skills',
|
|
439
489
|
}));
|
|
440
490
|
if (roleStagingRoot !== undefined) {
|
|
441
491
|
const nextRole = path.join(nextWorkspace, 'roles', role);
|
|
@@ -448,6 +498,10 @@ async function commitManagedEntries(stagingRoot, roleStagingRoot, homeDir, role)
|
|
|
448
498
|
});
|
|
449
499
|
}
|
|
450
500
|
for (const spec of specs) {
|
|
501
|
+
if (spec.preserveRoot) {
|
|
502
|
+
commitManagedChildren(spec, committedEntries, createdRoots);
|
|
503
|
+
continue;
|
|
504
|
+
}
|
|
451
505
|
const entry = {
|
|
452
506
|
current: spec.current,
|
|
453
507
|
backup: spec.backup,
|
|
@@ -469,6 +523,14 @@ async function commitManagedEntries(stagingRoot, roleStagingRoot, homeDir, role)
|
|
|
469
523
|
}
|
|
470
524
|
catch (error) {
|
|
471
525
|
const rollbackErrors = rollbackManagedEntries(committedEntries);
|
|
526
|
+
for (const root of [...createdRoots].reverse()) {
|
|
527
|
+
try {
|
|
528
|
+
fs.rmdirSync(root);
|
|
529
|
+
}
|
|
530
|
+
catch (rollbackError) {
|
|
531
|
+
rollbackErrors.push(rollbackError instanceof Error ? rollbackError : new Error(String(rollbackError)));
|
|
532
|
+
}
|
|
533
|
+
}
|
|
472
534
|
removeBestEffort(nextWorkspace);
|
|
473
535
|
if (rollbackErrors.length > 0) {
|
|
474
536
|
throw new AggregateError([error, ...rollbackErrors], `Role and vendor staging commit failed and rollback did not restore every managed asset: ${String(error)}`);
|
package/package.json
CHANGED