Chris Estreich 6 месяцев назад
Родитель
Сommit
483d951723
2 измененных файлов с 38 добавлено и 8 удалено
  1. 35 7
      packages/build/src/esbuild.ts
  2. 3 1
      src/esbuild.mjs

+ 35 - 7
packages/build/src/esbuild.ts

@@ -1,5 +1,6 @@
 import * as fs from "fs"
 import * as path from "path"
+import { execSync } from "child_process"
 
 import { ViewsContainer, Views, Menus, Configuration, contributesSchema } from "./types.js"
 
@@ -22,7 +23,7 @@ function copyDir(srcDir: string, dstDir: string, count: number): number {
 	return count
 }
 
-function rmDir(dirPath: string, maxRetries: number = 3): void {
+function rmDir(dirPath: string, maxRetries: number = 5): void {
 	for (let attempt = 1; attempt <= maxRetries; attempt++) {
 		try {
 			fs.rmSync(dirPath, { recursive: true, force: true })
@@ -30,15 +31,42 @@ function rmDir(dirPath: string, maxRetries: number = 3): void {
 		} catch (error) {
 			const isLastAttempt = attempt === maxRetries
 
-			const isEnotemptyError =
-				error instanceof Error && "code" in error && (error.code === "ENOTEMPTY" || error.code === "EBUSY")
+			const isRetryableError =
+				error instanceof Error &&
+				"code" in error &&
+				(error.code === "ENOTEMPTY" ||
+					error.code === "EBUSY" ||
+					error.code === "EPERM" ||
+					error.code === "EACCES")
+
+			if (isLastAttempt) {
+				// On the last attempt, try alternative cleanup methods.
+				try {
+					console.warn(`[rmDir] Final attempt using alternative cleanup for ${dirPath}`)
+
+					// Try to clear readonly flags on Windows.
+					if (process.platform === "win32") {
+						try {
+							execSync(`attrib -R "${dirPath}\\*.*" /S /D`, { stdio: "ignore" })
+						} catch {
+							// Ignore attrib errors.
+						}
+					}
+					fs.rmSync(dirPath, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 })
+					return
+				} catch (finalError) {
+					console.error(`[rmDir] Failed to remove ${dirPath} after ${maxRetries} attempts:`, finalError)
+					throw finalError
+				}
+			}
 
-			if (isLastAttempt || !isEnotemptyError) {
-				throw error // Re-throw if it's the last attempt or not a locking error.
+			if (!isRetryableError) {
+				throw error // Re-throw if it's not a retryable error.
 			}
 
-			// Wait with exponential backoff before retrying.
-			const delay = Math.min(100 * Math.pow(2, attempt - 1), 1000) // Cap at 1s.
+			// Wait with exponential backoff before retrying, with longer delays for Windows.
+			const baseDelay = process.platform === "win32" ? 200 : 100
+			const delay = Math.min(baseDelay * Math.pow(2, attempt - 1), 2000) // Cap at 2s
 			console.warn(`[rmDir] Attempt ${attempt} failed for ${dirPath}, retrying in ${delay}ms...`)
 
 			// Synchronous sleep for simplicity in build scripts.

+ 3 - 1
src/esbuild.mjs

@@ -81,7 +81,9 @@ async function main() {
 				build.onEnd((result) => {
 					result.errors.forEach(({ text, location }) => {
 						console.error(`✘ [ERROR] ${text}`)
-						console.error(`    ${location.file}:${location.line}:${location.column}:`)
+						if (location && location.file) {
+							console.error(`    ${location.file}:${location.line}:${location.column}:`)
+						}
 					})
 
 					console.log("[esbuild-problem-matcher#onEnd]")