@@ -16,13 +16,14 @@ module.exports = async function renameOverwrite (oldPath, newPath, retry = 0) {
1616 case 'EEXIST' :
1717 case 'ENOTDIR' :
1818 try {
19+ // Swap-rename avoids leaving a window where the target doesn't exist,
20+ // which is important when parallel processes read from the target.
21+ await swapRename ( oldPath , newPath )
22+ } catch {
23+ // If swap-rename failed (e.g. target was already moved by another
24+ // process), fall back to rimraf + rename.
1925 await rimraf ( newPath )
2026 await fs . promises . rename ( oldPath , newPath )
21- } catch {
22- // If rimraf + rename failed (e.g. parallel process race), fall back
23- // to swap-rename which avoids leaving a window where target is missing.
24- // This was added to solve concurrency issues with pnpm global virtual store
25- await swapRename ( oldPath , newPath )
2627 }
2728 break
2829 // Windows Antivirus issues
@@ -111,12 +112,14 @@ module.exports.sync = function renameOverwriteSync (oldPath, newPath, retry = 0)
111112 case 'EEXIST' :
112113 case 'ENOTDIR' :
113114 try {
115+ // Swap-rename avoids leaving a window where the target doesn't exist,
116+ // which is important when parallel processes read from the target.
117+ swapRenameSync ( oldPath , newPath )
118+ } catch {
119+ // If swap-rename failed (e.g. target was already moved by another
120+ // process), fall back to rimraf + rename.
114121 rimraf . sync ( newPath )
115122 fs . renameSync ( oldPath , newPath )
116- } catch {
117- // If rimraf + rename failed (e.g. parallel process race), fall back
118- // to swap-rename which avoids leaving a window where target is missing.
119- swapRenameSync ( oldPath , newPath )
120123 }
121124 break
122125 case 'ENOENT' :
0 commit comments