diff --git a/gitnexus/scripts/materialize-vendor-grammars.cjs b/gitnexus/scripts/materialize-vendor-grammars.cjs index b94df815d..fc9a15919 100644 --- a/gitnexus/scripts/materialize-vendor-grammars.cjs +++ b/gitnexus/scripts/materialize-vendor-grammars.cjs @@ -63,20 +63,31 @@ for (const name of VENDORED_GRAMMARS) { fs.renameSync(partial, dest); } catch (renameErr) { // Best-effort rollback: restore the previous dest from backup. + let restored = false; if (fs.existsSync(backup)) { try { fs.renameSync(backup, dest); + restored = true; } catch { - // If rollback also fails, the prior backup directory still exists on - // disk — the catch block below surfaces both errors via the warning. + // Rollback also failed — dest is now missing. Leave the backup in + // place (the catch below will NOT remove it) and surface where it is. } } + if (!restored && fs.existsSync(backup)) { + console.warn( + `[gitnexus] CRITICAL: could not materialize vendor/${name} AND could not restore the ` + + `previous node_modules/${name}. A recoverable copy remains at ${backup} — ` + + `restore it (e.g. \`mv ${backup} ${dest}\`) or reinstall to recover ${name}.`, + ); + } throw renameErr; } fs.rmSync(backup, { recursive: true, force: true }); } catch (err) { // Fail-soft: a single locked/inaccessible file (common on Windows) must not // abort the whole gitnexus install. Matches build-tree-sitter-*.cjs pattern. + // Only remove the scratch `partial`; never the `backup` (it may be the sole + // recoverable copy after a failed rollback above). fs.rmSync(partial, { recursive: true, force: true }); console.warn(`[gitnexus] Could not materialize vendor/${name}: ${err.message}`); console.warn(