@@ -42,6 +42,25 @@ if (process.env.S3_FORCE_PATH_STYLE === 'true') config.forcePathStyle = true;
4242const client = new S3Client ( config ) ;
4343const prefix = `${ Org } /.da-versions/` ;
4444
45+ /** Cache repo existence checks (Promise<boolean>) so each repo is checked only once. */
46+ const repoExistsCache = new Map ( ) ;
47+
48+ async function repoExistsInStorage ( repo ) {
49+ const resp = await client . send ( new ListObjectsV2Command ( {
50+ Bucket,
51+ Prefix : `${ Org } /${ repo } /` ,
52+ MaxKeys : 1 ,
53+ } ) ) ;
54+ return ( resp . KeyCount ?? 0 ) > 0 ;
55+ }
56+
57+ function checkRepoExists ( repo ) {
58+ if ( ! repoExistsCache . has ( repo ) ) {
59+ repoExistsCache . set ( repo , repoExistsInStorage ( repo ) ) ;
60+ }
61+ return repoExistsCache . get ( repo ) ;
62+ }
63+
4564/** Process N file IDs in parallel. */
4665const CONCURRENCY = parseInt ( process . env . MIGRATE_RUN_CONCURRENCY || '15' , 10 ) ;
4766
@@ -285,6 +304,16 @@ async function migrateFileId(fileId) {
285304 repo = firstRepo ;
286305 } else if ( repoSet . size > 1 ) repo = 'unknown' ;
287306
307+ if ( repo && repo !== 'unknown' ) {
308+ const exists = await checkRepoExists ( repo ) ;
309+ if ( ! exists ) {
310+ console . log ( ` ${ fileId } : repo "${ repo } " no longer exists, skipping.` ) ;
311+ return {
312+ fileId, skipped : true , repo, snapshots : 0 , audit : 0 , auditLines : 0 ,
313+ } ;
314+ }
315+ }
316+
288317 const allLegacyAudit = [ ...auditEntries , ...snapshotAuditEntries ] ;
289318 let auditLines = 0 ;
290319 if ( allLegacyAudit . length && repo ) {
@@ -375,7 +404,8 @@ async function main() {
375404 } ) ;
376405
377406 const errors = results . filter ( ( r ) => r . error ) ;
378- const ok = results . filter ( ( r ) => ! r . error ) ;
407+ const skipped = results . filter ( ( r ) => r . skipped ) ;
408+ const ok = results . filter ( ( r ) => ! r . error && ! r . skipped ) ;
379409 const elapsedSec = ( Date . now ( ) - startMs ) / 1000 ;
380410
381411 if ( DRY_RUN && ok . length > 0 ) {
@@ -385,21 +415,22 @@ async function main() {
385415 console . log ( '' ) ;
386416 console . log ( '--- DRY RUN summary (no changes were made) ---' ) ;
387417 console . log ( ` File IDs processed: ${ ok . length } ${ errors . length > 0 ? ` (${ errors . length } error(s))` : '' } ` ) ;
418+ console . log ( ` Repos not found: ${ skipped . length } file ID(s) skipped` ) ;
388419 console . log ( ` Snapshots would copy: ${ totalSnapshots } ` ) ;
389420 console . log ( ` audit.txt would write: ${ filesWithAudit } file(s), ${ totalAuditLines } total lines (after dedup + merge)` ) ;
390421 const idsPerSec = ok . length / elapsedSec ;
391422 console . log ( ` Timing: ${ elapsedSec . toFixed ( 1 ) } s total | ${ idsPerSec . toFixed ( 1 ) } file IDs/s` ) ;
392423 console . log ( ' Compare with Analyse: "With content" ≈ snapshots above; run without DRY_RUN to apply.' ) ;
393- } else if ( errors . length > 0 ) {
424+ } else if ( errors . length > 0 || skipped . length > 0 ) {
394425 console . log ( '' ) ;
395- console . log ( `Done. ${ results . length } processed, ${ errors . length } error(s).` ) ;
426+ console . log ( `Done. ${ results . length } processed, ${ skipped . length } skipped (repo gone), ${ errors . length } error(s).` ) ;
396427 }
397428
398429 if ( ok . length > 0 && ! DRY_RUN ) {
399430 const totalSnapshots = ok . reduce ( ( sum , r ) => sum + r . snapshots , 0 ) ;
400431 const totalAuditLines = ok . reduce ( ( sum , r ) => sum + ( r . auditLines || 0 ) , 0 ) ;
401432 console . log ( '' ) ;
402- console . log ( `Completed in ${ elapsedSec . toFixed ( 1 ) } s | ${ ( ok . length / elapsedSec ) . toFixed ( 1 ) } file IDs/s | ${ totalSnapshots } snapshots copied, ${ totalAuditLines } audit lines written` ) ;
433+ console . log ( `Completed in ${ elapsedSec . toFixed ( 1 ) } s | ${ ( ok . length / elapsedSec ) . toFixed ( 1 ) } file IDs/s | ${ totalSnapshots } snapshots copied, ${ totalAuditLines } audit lines written${ skipped . length > 0 ? ` | ${ skipped . length } skipped (repo gone)` : '' } ` ) ;
403434 }
404435}
405436
0 commit comments