ghcup-0.2.6.0: lib/GHCup/Command/GC.hs
{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-|
Module : GHCup.Command.GC
Description : GHCup gc
Copyright : (c) Julian Ospald, 2020
License : LGPL-3.0
Maintainer : hasufell@hasufell.de
Stability : experimental
Portability : portable
-}
module GHCup.Command.GC where
import GHCup.Command.List
import GHCup.Command.Rm
import GHCup.Errors
import GHCup.Legacy.HLS
import GHCup.Legacy.Utils
import GHCup.Prelude
import GHCup.Prelude.String.QQ
import GHCup.Query.DB
import GHCup.Query.GHCupDirs
import GHCup.Query.Metadata
import GHCup.System.Directory
import GHCup.Types
import GHCup.Types.Optics
import Control.Applicative
import Control.Exception.Safe
import Control.Monad
#if !MIN_VERSION_base(4,13,0)
import Control.Monad.Fail ( MonadFail )
#endif
import Control.Monad.Reader
import Control.Monad.Trans.Resource hiding ( throwM )
import Data.ByteString ( ByteString )
import Data.Foldable.WithIndex
import Data.List
import Data.Maybe
import Data.Variant.Excepts
import Optics
import Prelude hiding ( abs, writeFile )
import System.FilePath
import Text.Regex.Posix
import qualified Data.Text as T
--------------------------
--[ Garbage collection ]--
--------------------------
rmOldGHC :: ( MonadReader env m
, HasGHCupInfo env
, HasPlatformReq env
, HasDirs env
, HasLog env
, MonadIOish m
)
=> Excepts '[NotInstalled, UninstallFailed, ParseError, MalformedInstallInfo] m ()
rmOldGHC = do
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
let oldGHCs = toListOf (_GHCupDownloads % ix ghc % toolVersions % getTaggedL Old % to fst) dls
ghcs <- lift $ getInstalledVersions' ghc
forM_ (_tvrTargetVer <$> ghcs) $ \ghcVer -> when (ghcVer `elem` oldGHCs) $ rmToolVersion ghc ghcVer
rmUnsetTools :: ( MonadReader env m
, HasGHCupInfo env
, HasPlatformReq env
, HasDirs env
, HasLog env
, MonadIO m
, MonadFail m
, MonadMask m
, MonadUnliftIO m
)
=> Excepts '[NotInstalled, UninstallFailed, ParseError, MalformedInstallInfo] m ()
rmUnsetTools = do
vers <- liftE $ listVersions Nothing [ListInstalled True, ListSet False] ShowUpdates False NShowAll (Nothing, Nothing)
iforM_ vers $ \tool (_, ls) -> forM_ ls $ \ListResult{..} -> liftE $ rmToolVersion tool (TargetVersion lCross lVer)
rmProfilingLibs :: ( MonadReader env m
, HasDirs env
, HasLog env
, MonadIO m
, MonadFail m
, MonadMask m
, MonadUnliftIO m
)
=> m ()
rmProfilingLibs = do
ghcs <- getInstalledVersions' ghc
let regexes :: [ByteString]
regexes = [[s|.*_p\.a$|], [s|.*\.p_hi$|]]
forM_ regexes $ \regex ->
forM_ (_tvrTargetVer <$> ghcs) $ \ghc' -> do
d <- ghcupGHCDir ghc'
-- TODO: audit findFilesDeep
matches <- liftIO $ handleIO (\_ -> pure []) $ findFilesDeep
d
(makeRegexOpts compExtended
execBlank
regex
)
forM_ matches $ \m -> do
let p = fromGHCupPath d </> m
logDebug $ "rm " <> T.pack p
rmFile p
rmShareDir :: ( MonadReader env m
, HasDirs env
, HasLog env
, MonadIO m
, MonadFail m
, MonadMask m
, MonadUnliftIO m
)
=> m ()
rmShareDir = do
ghcs <- getInstalledVersions' ghc
forM_ (_tvrTargetVer <$> ghcs) $ \ghc' -> do
d <- ghcupGHCDir ghc'
let p = d `appendGHCupPath` "share"
logDebug $ "rm -rf " <> T.pack (fromGHCupPath p)
rmPathForcibly p
rmHLSNoGHC :: ( MonadReader env m
, HasDirs env
, HasLog env
, MonadIO m
, MonadMask m
, MonadFail m
, MonadUnliftIO m
)
=> Excepts '[NotInstalled, UninstallFailed] m ()
rmHLSNoGHC = do
Dirs {..} <- getDirs
ghcs <- lift $ getInstalledVersions' ghc
hlses <- lift $ getInstalledVersions hls Nothing -- TODO: we don't support cross HLS
forM_ (_vrVersion <$> hlses) $ \hls' -> do
hlsGHCs <- fmap mkTVer <$> hlsGHCVersions' hls'
let candidates = filter (`notElem` (_tvrTargetVer <$> ghcs)) hlsGHCs
if (length hlsGHCs - length candidates) <= 0
then rmHLSVer hls'
else
-- TODO: uff
forM_ candidates $ \ghc' -> do
bins1 <- fmap (binDir </>) <$> hlsServerBinaries hls' (Just $ _tvVersion ghc')
bins2 <- ifM (isLegacyHLS hls') (pure []) $ do
shs <- hlsInternalServerScripts hls' (Just $ _tvVersion ghc')
bins <- hlsInternalServerBinaries hls' (Just $ _tvVersion ghc')
libs <- hlsInternalServerLibs hls' (_tvVersion ghc')
pure (shs ++ bins ++ libs)
forM_ (bins1 ++ bins2) $ \f -> do
logDebug $ "rm " <> T.pack f
rmFile f
pure ()
rmCache :: ( MonadReader env m
, HasDirs env
, HasLog env
, MonadIO m
, MonadMask m
)
=> m ()
rmCache = do
Dirs {..} <- getDirs
contents <- liftIO $ listDirectory (fromGHCupPath cacheDir)
forM_ contents $ \f -> do
let p = fromGHCupPath cacheDir </> f
logDebug $ "rm " <> T.pack p
rmFile p
rmTmp :: ( MonadReader env m
, HasDirs env
, HasLog env
, MonadIO m
, MonadMask m
)
=> m ()
rmTmp = do
ghcup_dirs <- liftIO getGHCupTmpDirs
forM_ ghcup_dirs $ \f -> do
logDebug $ "rm -rf " <> T.pack (fromGHCupPath f)
rmPathForcibly f