diff --git a/Cabal-tests/lib/Test/Utils/TempTestDir.hs b/Cabal-tests/lib/Test/Utils/TempTestDir.hs index af565ff5154..8718440c9fb 100644 --- a/Cabal-tests/lib/Test/Utils/TempTestDir.hs +++ b/Cabal-tests/lib/Test/Utils/TempTestDir.hs @@ -60,7 +60,7 @@ removeDirectoryRecursiveHack :: Verbosity -> FilePath -> IO () removeDirectoryRecursiveHack verbosity dir | isWindows = go 1 where isWindows = System.Info.os == "mingw32" - limit = 3 + limit = 5 go :: Int -> IO () go n = do diff --git a/cabal-install/src/Distribution/Client/CmdClean.hs b/cabal-install/src/Distribution/Client/CmdClean.hs index 21d4b2c9480..e1261f9dacb 100644 --- a/cabal-install/src/Distribution/Client/CmdClean.hs +++ b/cabal-install/src/Distribution/Client/CmdClean.hs @@ -81,6 +81,7 @@ import Control.Monad , mapM ) import qualified Data.Set as Set +import qualified GHC.IO.Exception as GHC import System.Directory ( canonicalizePath , doesDirectoryExist @@ -92,7 +93,8 @@ import System.FilePath ( () ) import System.IO.Error - ( isPermissionError + ( ioeGetErrorType + , isPermissionError ) import qualified System.Process as Process @@ -193,7 +195,14 @@ cleanAction (ProjectFlags{..}, CleanFlags{..}) extraArgs _ = do "attrib -s -h -r " <> distRoot <> "\\*.* /s /d" catch (removePathForcibly distRoot) - (\e -> if isPermissionError e then threadDelay 1000 >> removePathForcibly distRoot else throw e) + ( \e -> + -- Permission error is usually when some files are (temporarily) locked. + -- Unsatisfied constraints (directory is non empty) error happens + -- when some files inside the directory were not removed (perhaps because they are locked). + if isPermissionError e || ioeGetErrorType e == GHC.UnsatisfiedConstraints + then threadDelay 1000 >> removePathForcibly distRoot + else throw e + ) removeEnvFiles $ distProjectRootDirectory distLayout diff --git a/changelog.d/pr-11604.md b/changelog.d/pr-11604.md index 9c05ce1d910..4348c02c892 100644 --- a/changelog.d/pr-11604.md +++ b/changelog.d/pr-11604.md @@ -1,7 +1,7 @@ --- synopsis: Replace removeDirectoryRecursive with removePathForcibly packages: [Cabal, cabal-install] -prs: 11604 +prs: 11604 11938 --- We replace `System.Directory.removeDirectoryRecursive` calls with a more robust `System.Directory.removePathForcibly`. Additionally, some functions (most notably the one responsible for `cabal clean`) now run `removeDirectoryRecursive` twice on all platforms if the first time was not successful (previously only on Windows) and include a small delay in between.