atris 3.15.12 → 3.15.13
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/commands/pull.js +26 -2
- package/commands/push.js +32 -2
- package/package.json +1 -1
package/commands/pull.js
CHANGED
|
@@ -566,11 +566,35 @@ async function pullBusiness(slug) {
|
|
|
566
566
|
// Compute local file hashes
|
|
567
567
|
const localFiles = localFilesBeforePull;
|
|
568
568
|
|
|
569
|
+
function isPullPathInScope(filePath) {
|
|
570
|
+
if (!onlyPrefixes) return true;
|
|
571
|
+
const rel = filePath.replace(/^\//, '');
|
|
572
|
+
return onlyPrefixes.some((pref) => rel.startsWith(pref));
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
function filterFilesToPullScope(filesMap = {}) {
|
|
576
|
+
if (!onlyPrefixes) return filesMap;
|
|
577
|
+
return Object.fromEntries(
|
|
578
|
+
Object.entries(filesMap).filter(([p]) => isPullPathInScope(p))
|
|
579
|
+
);
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
function filterManifestToPullScope(existingManifest) {
|
|
583
|
+
if (!onlyPrefixes || !existingManifest || !existingManifest.files) return existingManifest;
|
|
584
|
+
return {
|
|
585
|
+
...existingManifest,
|
|
586
|
+
files: filterFilesToPullScope(existingManifest.files),
|
|
587
|
+
};
|
|
588
|
+
}
|
|
589
|
+
|
|
569
590
|
// If output dir is empty (fresh clone) or --force, treat as first sync — pull everything
|
|
570
|
-
const
|
|
591
|
+
const scopedLocalFiles = filterFilesToPullScope(localFiles);
|
|
592
|
+
const scopedRemoteFiles = filterFilesToPullScope(remoteFiles);
|
|
593
|
+
const scopedManifest = filterManifestToPullScope(manifest);
|
|
594
|
+
const effectiveManifest = (Object.keys(scopedLocalFiles).length === 0 || force) ? null : scopedManifest;
|
|
571
595
|
|
|
572
596
|
// Three-way compare
|
|
573
|
-
const diff = threeWayCompare(
|
|
597
|
+
const diff = threeWayCompare(scopedLocalFiles, scopedRemoteFiles, effectiveManifest);
|
|
574
598
|
|
|
575
599
|
if (dryRun) {
|
|
576
600
|
console.log('');
|
package/commands/push.js
CHANGED
|
@@ -95,6 +95,15 @@ function shouldRetrySyncIndividually(result, filesToPush) {
|
|
|
95
95
|
return result.status !== 403 && result.status !== 409;
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
+
function isMassDeletePlan({ deletedPaths = [], filesToPush = [], unchangedCount = 0 } = {}) {
|
|
99
|
+
const deleteCount = deletedPaths.length;
|
|
100
|
+
if (deleteCount === 0) return false;
|
|
101
|
+
const survivingCount = filesToPush.length + unchangedCount;
|
|
102
|
+
if (deleteCount >= 10 && survivingCount === 0) return true;
|
|
103
|
+
if (deleteCount >= 25) return true;
|
|
104
|
+
return deleteCount >= 10 && deleteCount > survivingCount;
|
|
105
|
+
}
|
|
106
|
+
|
|
98
107
|
async function pushAtris() {
|
|
99
108
|
const elapsedMs = startTimer();
|
|
100
109
|
let slug = process.argv[3];
|
|
@@ -113,7 +122,7 @@ async function pushAtris() {
|
|
|
113
122
|
}
|
|
114
123
|
|
|
115
124
|
if (!slug || slug === '--help') {
|
|
116
|
-
console.log('Usage: atris push [business] [--from <path>] [--only <prefix>] [--force] [--delete]');
|
|
125
|
+
console.log('Usage: atris push [business] [--from <path>] [--only <prefix>] [--force] [--delete] [--delete-all]');
|
|
117
126
|
console.log('');
|
|
118
127
|
console.log(' Push requires a fresh pull. If cloud has changed since your last pull,');
|
|
119
128
|
console.log(' the push will be blocked until you run `atris pull`. Use --force to override.');
|
|
@@ -122,13 +131,15 @@ async function pushAtris() {
|
|
|
122
131
|
console.log(' atris push pallet Push pallet/ or atris/pallet/');
|
|
123
132
|
console.log(' atris push pallet --only team/nate Only push files in team/nate/');
|
|
124
133
|
console.log(' atris push --force Bypass freshness check (force-push, may overwrite cloud changes)');
|
|
125
|
-
console.log(' atris push --delete Allow cloud deletes shown by --dry-run');
|
|
134
|
+
console.log(' atris push --delete Allow small cloud deletes shown by --dry-run');
|
|
135
|
+
console.log(' atris push --delete-all Extra confirmation for mass-delete recovery');
|
|
126
136
|
process.exit(0);
|
|
127
137
|
}
|
|
128
138
|
|
|
129
139
|
const force = process.argv.includes('--force');
|
|
130
140
|
const dryRun = process.argv.includes('--dry-run');
|
|
131
141
|
const allowDelete = process.argv.includes('--delete');
|
|
142
|
+
const allowMassDelete = process.argv.includes('--delete-all');
|
|
132
143
|
const allowCrossRootManifest = process.argv.includes('--allow-cross-root-manifest');
|
|
133
144
|
|
|
134
145
|
// Parse --only
|
|
@@ -390,6 +401,24 @@ async function pushAtris() {
|
|
|
390
401
|
process.exit(1);
|
|
391
402
|
}
|
|
392
403
|
|
|
404
|
+
if (deletedPaths.length > 0 && allowDelete && !allowMassDelete && isMassDeletePlan({ deletedPaths, filesToPush, unchangedCount })) {
|
|
405
|
+
console.log('');
|
|
406
|
+
console.log(` ✗ Refusing mass delete of ${deletedPaths.length} cloud files with --delete alone.`);
|
|
407
|
+
console.log('');
|
|
408
|
+
console.log(' This looks like a missing local folder or wrong source root.');
|
|
409
|
+
console.log(' No cloud files were deleted.');
|
|
410
|
+
console.log('');
|
|
411
|
+
console.log(' First inspect the plan:');
|
|
412
|
+
console.log(` atris push ${resolvedSlug || slug} --dry-run`);
|
|
413
|
+
console.log('');
|
|
414
|
+
console.log(' If this is truly an intentional full cleanup, rerun with both flags:');
|
|
415
|
+
console.log(` atris push ${resolvedSlug || slug} --delete --delete-all`);
|
|
416
|
+
console.log('');
|
|
417
|
+
console.log(' If this is surprising, pull cloud truth first:');
|
|
418
|
+
console.log(` atris pull ${resolvedSlug || slug} --keep-local --timeout 120`);
|
|
419
|
+
process.exit(1);
|
|
420
|
+
}
|
|
421
|
+
|
|
393
422
|
let pushed = 0;
|
|
394
423
|
let deleted = 0;
|
|
395
424
|
let skipped = [];
|
|
@@ -682,4 +711,5 @@ module.exports = {
|
|
|
682
711
|
canonicalWorkspaceRoot,
|
|
683
712
|
basenameOfManifestPath,
|
|
684
713
|
isBusinessWorkspaceRoot,
|
|
714
|
+
isMassDeletePlan,
|
|
685
715
|
};
|