@@ -456,53 +456,63 @@ function formatMode(mode: number): string {
456456 * @param issues - Permission issues to repair
457457 * @returns Separate lists of human-readable repair successes and failures
458458 */
459- async function repairPermissions ( issues : PermissionIssue [ ] ) : Promise < {
460- fixed : string [ ] ;
461- failed : string [ ] ;
462- } > {
463- const fixed : string [ ] = [ ] ;
464- const failed : string [ ] = [ ] ;
465-
466- // Repair directories first so child file chmod calls don't fail with EACCES
467- const dirIssues = issues . filter ( ( i ) => i . kind === "directory" ) ;
468- const fileIssues = issues . filter ( ( i ) => i . kind !== "directory" ) ;
459+ /**
460+ * Repair permissions, returning outcomes aligned by index with input.
461+ *
462+ * Repairs directories before files to avoid EACCES on child chmod calls.
463+ */
464+ async function repairPermissions (
465+ issues : PermissionIssue [ ]
466+ ) : Promise < RepairOutcome [ ] > {
467+ const outcomes = new Array < RepairOutcome > ( issues . length ) ;
468+
469+ // Build index maps for dirs and files
470+ const dirEntries : Array < { idx : number ; issue : PermissionIssue } > = [ ] ;
471+ const fileEntries : Array < { idx : number ; issue : PermissionIssue } > = [ ] ;
472+ for ( let i = 0 ; i < issues . length ; i ++ ) {
473+ const issue = issues [ i ] as PermissionIssue ;
474+ if ( issue . kind === "directory" ) {
475+ dirEntries . push ( { idx : i , issue } ) ;
476+ } else {
477+ fileEntries . push ( { idx : i , issue } ) ;
478+ }
479+ }
469480
470- await collectResults ( dirIssues , fixed , failed ) ;
471- await collectResults ( fileIssues , fixed , failed ) ;
481+ // Repair directories first, then files
482+ await collectPermResults ( dirEntries , outcomes ) ;
483+ await collectPermResults ( fileEntries , outcomes ) ;
472484
473- return { fixed , failed } ;
485+ return outcomes ;
474486}
475487
476488/**
477- * Run chmod for each issue in parallel, collecting successes and failures.
478- *
479- * @param issues - Permission issues to repair
480- * @param fixed - Accumulator for successful repair messages
481- * @param failed - Accumulator for failed repair messages
489+ * Run chmod for each entry in parallel, writing outcomes by original index.
482490 */
483- async function collectResults (
484- issues : PermissionIssue [ ] ,
485- fixed : string [ ] ,
486- failed : string [ ]
491+ async function collectPermResults (
492+ entries : Array < { idx : number ; issue : PermissionIssue } > ,
493+ outcomes : RepairOutcome [ ]
487494) : Promise < void > {
488495 const results = await Promise . allSettled (
489- issues . map ( async ( issue ) => {
496+ entries . map ( async ( { issue } ) => {
490497 await chmod ( issue . path , issue . expectedMode ) ;
491498 return `${ issue . kind } ${ issue . path } : ${ formatMode ( issue . currentMode ) } -> ${ formatMode ( issue . expectedMode ) } ` ;
492499 } )
493500 ) ;
494501
495502 for ( let i = 0 ; i < results . length ; i ++ ) {
496503 const result = results [ i ] as PromiseSettledResult < string > ;
504+ const entry = entries [ i ] as { idx : number ; issue : PermissionIssue } ;
497505 if ( result . status === "fulfilled" ) {
498- fixed . push ( result . value ) ;
506+ outcomes [ entry . idx ] = { success : true , message : result . value } ;
499507 } else {
500- const issue = issues [ i ] as PermissionIssue ;
501508 const reason =
502509 result . reason instanceof Error
503510 ? result . reason . message
504- : "permission denied" ;
505- failed . push ( `${ issue . kind } ${ issue . path } : ${ reason } ` ) ;
511+ : "unknown error" ;
512+ outcomes [ entry . idx ] = {
513+ success : false ,
514+ message : `${ entry . issue . kind } ${ entry . issue . path } : ${ reason } ` ,
515+ } ;
506516 }
507517 }
508518}
@@ -533,38 +543,26 @@ async function handlePermissionIssues(
533543 return { issues : fixIssues , repairFailed : false } ;
534544 }
535545
536- const { fixed, failed } = await repairPermissions ( permIssues ) ;
537-
538- // Map repair results back to issues
539- const repairedIssues : FixIssue [ ] = [ ] ;
540-
541- for ( const f of fixed ) {
542- repairedIssues . push ( {
543- category : "permission" ,
544- description : f ,
545- repaired : true ,
546- repairMessage : f ,
547- } ) ;
548- }
546+ const outcomes = await repairPermissions ( permIssues ) ;
549547
550- if ( failed . length > 0 ) {
551- for ( const f of failed ) {
552- repairedIssues . push ( {
553- category : "permission" ,
554- description : f ,
555- repaired : false ,
556- repairMessage : f ,
557- } ) ;
548+ // Mark each issue with its repair outcome (aligned by index)
549+ let anyFailed = false ;
550+ for ( let i = 0 ; i < fixIssues . length ; i ++ ) {
551+ const issue = fixIssues [ i ] as FixIssue ;
552+ const outcome = outcomes [ i ] as RepairOutcome ;
553+ issue . repaired = outcome . success ;
554+ issue . repairMessage = outcome . message ;
555+ if ( ! outcome . success ) {
556+ anyFailed = true ;
558557 }
559558 }
560559
561560 return {
562- issues : repairedIssues . length > 0 ? repairedIssues : fixIssues ,
563- instructions :
564- failed . length > 0
565- ? `You may need to fix permissions manually:\n chmod 700 "${ getConfigDir ( ) } "\n chmod 600 "${ dbPath } "`
566- : undefined ,
567- repairFailed : failed . length > 0 ,
561+ issues : fixIssues ,
562+ instructions : anyFailed
563+ ? `You may need to fix permissions manually:\n chmod 700 "${ getConfigDir ( ) } "\n chmod 600 "${ dbPath } "`
564+ : undefined ,
565+ repairFailed : anyFailed ,
568566 } ;
569567}
570568
@@ -593,37 +591,24 @@ function handleSchemaIssues(dbPath: string, dryRun: boolean): HandlerResult {
593591 }
594592
595593 const { fixed, failed } = repairSchema ( db ) ;
596-
597- // Map repair results back to issues
598- const repairedIssues : FixIssue [ ] = [ ] ;
599-
600- for ( const f of fixed ) {
601- repairedIssues . push ( {
602- category : "schema" ,
603- description : f ,
604- repaired : true ,
605- repairMessage : f ,
606- } ) ;
607- }
608-
609- if ( failed . length > 0 ) {
610- for ( const f of failed ) {
611- repairedIssues . push ( {
612- category : "schema" ,
613- description : f ,
614- repaired : false ,
615- repairMessage : f ,
616- } ) ;
617- }
594+ const anyFailed = failed . length > 0 ;
595+
596+ // Mark original issues with repair outcomes.
597+ // Schema repair runs independently of detection — mark all issues based
598+ // on overall success/failure. Attach repair messages for diagnostics.
599+ for ( const issue of fixIssues ) {
600+ issue . repaired = ! anyFailed ;
601+ issue . repairMessage = anyFailed
602+ ? failed . join ( "; " )
603+ : fixed . join ( "; " ) || "Schema repaired" ;
618604 }
619605
620606 return {
621- issues : repairedIssues . length > 0 ? repairedIssues : fixIssues ,
622- instructions :
623- failed . length > 0
624- ? `Try deleting the database and restarting: rm "${ dbPath } "`
625- : undefined ,
626- repairFailed : failed . length > 0 ,
607+ issues : fixIssues ,
608+ instructions : anyFailed
609+ ? `Try deleting the database and restarting: rm "${ dbPath } "`
610+ : undefined ,
611+ repairFailed : anyFailed ,
627612 } ;
628613}
629614
0 commit comments