Skip to content

Commit ee6e478

Browse files
committed
Fix 'cabal clean' on Windows for 'build-type: Custom'.
Fixes #1863.
1 parent 3c1728c commit ee6e478

File tree

4 files changed

+76
-10
lines changed

4 files changed

+76
-10
lines changed

cabal-install/Distribution/Client/Configure.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ configure verbosity packageDBs repos comp platform conf
127127
(configDistPref configFlags),
128128
useLoggingHandle = Nothing,
129129
useWorkingDir = Nothing,
130+
useWin32CleanHack = False,
130131
forceExternalSetupMethod = False,
131132
setupCacheLock = Nothing
132133
}

cabal-install/Distribution/Client/Install.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1028,6 +1028,7 @@ performInstallations verbosity
10281028
useLoggingHandle = Nothing,
10291029
useWorkingDir = Nothing,
10301030
forceExternalSetupMethod = parallelInstall,
1031+
useWin32CleanHack = False,
10311032
setupCacheLock = Just lock
10321033
}
10331034
reportingLevel = fromFlag (installBuildReports installFlags)

cabal-install/Distribution/Client/SetupWrapper.hs

Lines changed: 60 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
{-# LANGUAGE CPP #-}
12
-----------------------------------------------------------------------------
23
-- |
34
-- Module : Distribution.Client.SetupWrapper
@@ -97,6 +98,16 @@ import Data.Maybe ( fromMaybe, isJust )
9798
import Data.Monoid ( mempty )
9899
import Data.Char ( isSpace )
99100

101+
#ifdef mingw32_HOST_OS
102+
import Distribution.Simple.Utils
103+
( withTempDirectory )
104+
105+
import Control.Exception ( bracket )
106+
import System.FilePath ( equalFilePath, takeDirectory )
107+
import System.Directory ( doesDirectoryExist )
108+
import qualified System.Win32 as Win32
109+
#endif
110+
100111
data SetupScriptOptions = SetupScriptOptions {
101112
useCabalVersion :: VersionRange,
102113
useCompiler :: Maybe Compiler,
@@ -109,6 +120,12 @@ data SetupScriptOptions = SetupScriptOptions {
109120
useWorkingDir :: Maybe FilePath,
110121
forceExternalSetupMethod :: Bool,
111122

123+
-- On Windows, running './dist/setup/setup clean' doesn't work because the
124+
-- setup script will try to delete itself. So we have to move the setup exe
125+
-- out of the way first and then delete it manually. This applies only to
126+
-- the external setup method.
127+
useWin32CleanHack :: Bool,
128+
112129
-- Used only when calling setupWrapper from parallel code to serialise
113130
-- access to the setup cache; should be Nothing otherwise.
114131
--
@@ -135,6 +152,7 @@ defaultSetupScriptOptions = SetupScriptOptions {
135152
useDistPref = defaultDistPref,
136153
useLoggingHandle = Nothing,
137154
useWorkingDir = Nothing,
155+
useWin32CleanHack = False,
138156
forceExternalSetupMethod = False,
139157
setupCacheLock = Nothing
140158
}
@@ -491,12 +509,46 @@ externalSetupMethod verbosity options pkg bt mkargs = do
491509
-- working directory.
492510
path' <- tryCanonicalizePath path
493511

494-
searchpath <- programSearchPathAsPATHVar
495-
(getProgramSearchPath (useProgramConfig options'))
496-
env <- getEffectiveEnvironment [("PATH", Just searchpath)]
512+
#if mingw32_HOST_OS
513+
setupProgFile' <- tryCanonicalizePath setupProgFile
514+
let win32CleanHackNeeded = (useWin32CleanHack options')
515+
-- Skip when a cached setup script is used.
516+
&& setupProgFile' `equalFilePath` path'
517+
if win32CleanHackNeeded then doWin32CleanHack path' else doInvoke path'
518+
#else
519+
doInvoke path'
520+
#endif
497521

498-
process <- runProcess path' args
499-
(useWorkingDir options') env
500-
Nothing (useLoggingHandle options') (useLoggingHandle options')
501-
exitCode <- waitForProcess process
502-
unless (exitCode == ExitSuccess) $ exitWith exitCode
522+
where
523+
doInvoke path' = do
524+
searchpath <- programSearchPathAsPATHVar
525+
(getProgramSearchPath (useProgramConfig options'))
526+
env <- getEffectiveEnvironment [("PATH", Just searchpath)]
527+
528+
process <- runProcess path' args
529+
(useWorkingDir options') env Nothing
530+
(useLoggingHandle options') (useLoggingHandle options')
531+
exitCode <- waitForProcess process
532+
unless (exitCode == ExitSuccess) $ exitWith exitCode
533+
534+
#if mingw32_HOST_OS
535+
doWin32CleanHack path' = do
536+
info verbosity $ "Using the Win32 clean hack."
537+
-- Recursively removes the temp dir on exit.
538+
withTempDirectory verbosity workingDir "cabal-tmp" $ \tmpDir ->
539+
bracket (moveOutOfTheWay tmpDir path')
540+
(maybeRestore path')
541+
doInvoke
542+
543+
moveOutOfTheWay tmpDir path' = do
544+
let newPath = tmpDir </> "setup" <.> exeExtension
545+
Win32.moveFile path' newPath
546+
return newPath
547+
548+
maybeRestore oldPath path' = do
549+
let oldPathDir = takeDirectory oldPath
550+
oldPathDirExists <- doesDirectoryExist oldPathDir
551+
-- 'setup clean' didn't complete, 'dist/setup' still exists.
552+
when oldPathDirExists $
553+
Win32.moveFile path' oldPath
554+
#endif

cabal-install/Main.hs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -236,10 +236,9 @@ mainWorker args = topHandler $
236236
,haddockCommand `commandAddAction` haddockAction
237237
,execCommand `commandAddAction` execAction
238238
,userConfigCommand `commandAddAction` userConfigAction
239+
,cleanCommand `commandAddAction` cleanAction
239240
,wrapperAction copyCommand
240241
copyVerbosity copyDistPref
241-
,wrapperAction cleanCommand
242-
cleanVerbosity cleanDistPref
243242
,wrapperAction hscolourCommand
244243
hscolourVerbosity hscolourDistPref
245244
,wrapperAction registerCommand
@@ -804,6 +803,19 @@ haddockAction haddockFlags extraArgs globalFlags = do
804803
setupWrapper verbosity setupScriptOptions Nothing
805804
haddockCommand (const haddockFlags') extraArgs
806805

806+
cleanAction :: CleanFlags -> [String] -> GlobalFlags -> IO ()
807+
cleanAction cleanFlags extraArgs _globalFlags =
808+
setupWrapper verbosity setupScriptOptions Nothing
809+
cleanCommand (const cleanFlags) extraArgs
810+
where
811+
verbosity = fromFlagOrDefault normal (cleanVerbosity cleanFlags)
812+
setupScriptOptions = defaultSetupScriptOptions {
813+
useDistPref = fromFlagOrDefault
814+
(useDistPref defaultSetupScriptOptions)
815+
(cleanDistPref cleanFlags),
816+
useWin32CleanHack = True
817+
}
818+
807819
listAction :: ListFlags -> [String] -> GlobalFlags -> IO ()
808820
listAction listFlags extraArgs globalFlags = do
809821
let verbosity = fromFlag (listVerbosity listFlags)

0 commit comments

Comments
 (0)