fix: EPERM error on Windows when processing dependencies (#8235) · vitejs/vite@dfe4307

2 files changed

lines changed

Original file line numberDiff line numberDiff line change

@@ -15,6 +15,7 @@ import {

1515

lookupFile,

1616

normalizeId,

1717

normalizePath,

18+

removeDir,

1819

removeDirSync,

1920

renameDir,

2021

writeFile

@@ -539,7 +540,7 @@ export async function runOptimizeDeps(

539540

async function commitProcessingDepsCacheSync() {

540541

// Processing is done, we can now replace the depsCacheDir with processingCacheDir

541542

// Rewire the file paths from the temporal processing dir to the final deps cache dir

542-

removeDirSync(depsCacheDir)

543+

await removeDir(depsCacheDir)

543544

await renameDir(processingCacheDir, depsCacheDir)

544545

}

545546
Original file line numberDiff line numberDiff line change

@@ -530,6 +530,9 @@ export function removeDirSync(dir: string) {

530530

}

531531

}

532532
533+

export const removeDir = isWindows

534+

? promisify(gracefulRemoveDir)

535+

: removeDirSync

533536

export const renameDir = isWindows ? promisify(gracefulRename) : fs.renameSync

534537
535538

export function ensureWatchedFile(

@@ -804,6 +807,38 @@ function gracefulRename(

804807

})

805808

}

806809
810+

const GRACEFUL_REMOVE_DIR_TIMEOUT = 5000

811+

function gracefulRemoveDir(

812+

dir: string,

813+

cb: (error: NodeJS.ErrnoException | null) => void

814+

) {

815+

const rmdir = fs.rm ?? fs.rmdir // TODO: Remove after support for Node 12 is dropped

816+

const start = Date.now()

817+

let backoff = 0

818+

rmdir(dir, { recursive: true }, function CB(er) {

819+

if (er) {

820+

if (

821+

(er.code === 'ENOTEMPTY' ||

822+

er.code === 'EACCES' ||

823+

er.code === 'EPERM') &&

824+

Date.now() - start < GRACEFUL_REMOVE_DIR_TIMEOUT

825+

) {

826+

setTimeout(function () {

827+

rmdir(dir, { recursive: true }, CB)

828+

}, backoff)

829+

if (backoff < 100) backoff += 10

830+

return

831+

}

832+
833+

if (er.code === 'ENOENT') {

834+

er = null

835+

}

836+

}

837+
838+

if (cb) cb(er)

839+

})

840+

}

841+
807842

export function emptyCssComments(raw: string) {

808843

return raw.replace(multilineCommentsRE, (s) => ' '.repeat(s.length))

809844

}