@@ -12,21 +12,26 @@ Types and functions related to Stack's @clean@ and @purge@ commands.
1212
1313module Stack.Clean
1414 ( CleanOpts (.. )
15+ , CleanDepth (.. )
1516 , CleanCommand (.. )
1617 , cleanCmd
1718 , clean
1819 ) where
1920
21+ import Control.Monad.Extra ( concatMapM )
2022import Data.List ( (\\) )
2123import qualified Data.Map.Strict as Map
22- import Path.IO ( ignoringAbsence , removeDirRecur )
23- import Stack.Config ( withBuildConfig )
24- import Stack.Constants.Config ( rootDistDirFromDir , workDirFromDir )
24+ import Path ( (</>) , isProperPrefixOf )
25+ import Path.IO ( ignoringAbsence , listDirRecur , removeDirRecur )
26+ import Stack.Constants.Config
27+ ( distRelativeDir , rootDistDirFromDir , workDirFromDir )
2528import Stack.Prelude
26- import Stack.Runners ( ShouldReexec (.. ), withConfig )
29+ import Stack.Runners
30+ ( ShouldReexec (.. ), withConfig , withDefaultEnvConfig )
2731import Stack.Types.BuildConfig
2832 ( BuildConfig (.. ), HasBuildConfig (.. ), getWorkDir )
2933import Stack.Types.Config ( Config )
34+ import Stack.Types.EnvConfig ( EnvConfig )
3035import Stack.Types.Runner ( Runner )
3136import Stack.Types.SourceMap ( SMWanted (.. ), ppRoot )
3237
@@ -64,7 +69,13 @@ instance Pretty CleanPrettyException where
6469instance Exception CleanPrettyException
6570
6671-- | Type representing command line options for the @stack clean@ command.
67- data CleanOpts
72+ data CleanOpts = CleanOpts
73+ { depth :: ! CleanDepth
74+ , omitThis :: ! Bool
75+ }
76+
77+ -- | Type representing depths of cleaning for the @stack clean@ command.
78+ data CleanDepth
6879 = CleanShallow [PackageName ]
6980 -- ^ Delete the "dist directories" as defined in
7081 -- 'Stack.Constants.Config.distRelativeDir' for the given project packages.
@@ -84,7 +95,7 @@ cleanCmd = withConfig NoReexec . clean
8495-- | Deletes build artifacts in the current project.
8596clean :: CleanOpts -> RIO Config ()
8697clean cleanOpts = do
87- toDelete <- withBuildConfig $ dirsToDelete cleanOpts
98+ toDelete <- withDefaultEnvConfig $ dirsToDelete cleanOpts
8899 logDebug $ " Need to delete: " <> fromString (show (map toFilePath toDelete))
89100 failures <- catMaybes <$> mapM cleanDir toDelete
90101 case failures of
@@ -97,20 +108,50 @@ cleanDir dir = do
97108 liftIO (ignoringAbsence (removeDirRecur dir) >> pure Nothing ) `catchAny` \ ex ->
98109 pure $ Just (dir, ex)
99110
100- dirsToDelete :: CleanOpts -> RIO BuildConfig [Path Abs Dir ]
111+ dirsToDelete :: CleanOpts -> RIO EnvConfig [Path Abs Dir ]
101112dirsToDelete cleanOpts = do
102113 packages <- view $ buildConfigL . to (. smWanted. project)
103114 case cleanOpts of
104- CleanShallow [] ->
115+ ( CleanOpts ( CleanShallow [] ) omitThis) -> do
105116 -- Filter out packages listed as extra-deps
106- mapM (rootDistDirFromDir . ppRoot) $ Map. elems packages
107- CleanShallow targets -> do
117+ let pkgNames = Map. elems packages
118+ if omitThis
119+ then
120+ concatMapM (unusedRootDistDirsFromDir . ppRoot) pkgNames
121+ else
122+ mapM (rootDistDirFromDir . ppRoot) pkgNames
123+ (CleanOpts (CleanShallow targets) omitThis) -> do
108124 let localPkgNames = Map. keys packages
109125 getPkgDir pkgName' = fmap ppRoot (Map. lookup pkgName' packages)
126+ pkgNames = mapMaybe getPkgDir targets
110127 case targets \\ localPkgNames of
111- [] -> mapM rootDistDirFromDir (mapMaybe getPkgDir targets)
128+ [] -> if omitThis
129+ then
130+ concatMapM unusedRootDistDirsFromDir pkgNames
131+ else
132+ mapM rootDistDirFromDir pkgNames
112133 xs -> prettyThrowM (NonLocalPackages xs)
113- CleanFull -> do
134+ ( CleanOpts CleanFull _) -> do
114135 pkgWorkDirs <- mapM (workDirFromDir . ppRoot) $ Map. elems packages
115136 projectWorkDir <- getWorkDir
116137 pure (projectWorkDir : pkgWorkDirs)
138+
139+ unusedRootDistDirsFromDir :: Path Abs Dir -> RIO EnvConfig [Path Abs Dir ]
140+ unusedRootDistDirsFromDir pkgDir = do
141+ rootDistDir <- rootDistDirFromDir pkgDir
142+ omitDir <- fmap (pkgDir </> ) distRelativeDir
143+ allDirsOmittingDirs rootDistDir omitDir
144+
145+ allDirsOmittingDirs ::
146+ MonadIO m
147+ => Path Abs Dir
148+ -> Path Abs Dir
149+ -> m [Path Abs Dir ]
150+ allDirsOmittingDirs topDir subDir = do
151+ allDirs <- (topDir : ) <$> fst <$> listDirRecur topDir
152+ let isNotInSubDir dir = not
153+ ( isProperPrefixOf dir subDir
154+ || subDir == dir
155+ || isProperPrefixOf subDir dir
156+ )
157+ pure $ filter isNotInSubDir allDirs
0 commit comments