233 lines
5.8 KiB
Haskell
233 lines
5.8 KiB
Haskell
{-# LANGUAGE CPP #-}
|
|
{-# LANGUAGE DataKinds #-}
|
|
{-# LANGUAGE TypeApplications #-}
|
|
{-# LANGUAGE FlexibleContexts #-}
|
|
{-# LANGUAGE OverloadedStrings #-}
|
|
{-# LANGUAGE TemplateHaskell #-}
|
|
{-# LANGUAGE QuasiQuotes #-}
|
|
{-# LANGUAGE DuplicateRecordFields #-}
|
|
{-# LANGUAGE RankNTypes #-}
|
|
|
|
module GHCup.OptParse.Rm where
|
|
|
|
|
|
|
|
|
|
import GHCup
|
|
import GHCup.Errors
|
|
import GHCup.Types
|
|
import GHCup.Types.Optics
|
|
import GHCup.Utils
|
|
import GHCup.Prelude.Logger
|
|
import GHCup.Prelude.String.QQ
|
|
import GHCup.OptParse.Common
|
|
|
|
#if !MIN_VERSION_base(4,13,0)
|
|
import Control.Monad.Fail ( MonadFail )
|
|
#endif
|
|
import Control.Monad.Reader
|
|
import Control.Monad.Trans.Resource
|
|
import Data.Functor
|
|
import Data.Maybe
|
|
import Data.Versions
|
|
import Haskus.Utils.Variant.Excepts
|
|
import Options.Applicative hiding ( style )
|
|
import Prelude hiding ( appendFile )
|
|
import System.Exit
|
|
|
|
import qualified Data.Text as T
|
|
import Control.Exception.Safe (MonadMask)
|
|
|
|
|
|
|
|
|
|
----------------
|
|
--[ Commands ]--
|
|
----------------
|
|
|
|
|
|
data RmCommand = RmGHC RmOptions
|
|
| RmCabal Version
|
|
| RmHLS Version
|
|
| RmStack Version
|
|
deriving (Eq, Show)
|
|
|
|
|
|
|
|
|
|
---------------
|
|
--[ Options ]--
|
|
---------------
|
|
|
|
|
|
data RmOptions = RmOptions
|
|
{ ghcVer :: GHCTargetVersion
|
|
} deriving (Eq, Show)
|
|
|
|
|
|
|
|
|
|
---------------
|
|
--[ Parsers ]--
|
|
---------------
|
|
|
|
|
|
rmParser :: Parser (Either RmCommand RmOptions)
|
|
rmParser =
|
|
(Left <$> subparser
|
|
( command
|
|
"ghc"
|
|
(RmGHC <$> info (rmOpts (Just GHC) <**> helper) (progDesc "Remove GHC version"))
|
|
<> command
|
|
"cabal"
|
|
( RmCabal
|
|
<$> info (versionParser' [ListInstalled True] (Just Cabal) <**> helper)
|
|
(progDesc "Remove Cabal version")
|
|
)
|
|
<> command
|
|
"hls"
|
|
( RmHLS
|
|
<$> info (versionParser' [ListInstalled True] (Just HLS) <**> helper)
|
|
(progDesc "Remove haskell-language-server version")
|
|
)
|
|
<> command
|
|
"stack"
|
|
( RmStack
|
|
<$> info (versionParser' [ListInstalled True] (Just Stack) <**> helper)
|
|
(progDesc "Remove stack version")
|
|
)
|
|
)
|
|
)
|
|
<|> (Right <$> rmOpts Nothing)
|
|
|
|
|
|
|
|
rmOpts :: Maybe Tool -> Parser RmOptions
|
|
rmOpts tool = RmOptions <$> ghcVersionArgument [ListInstalled True] tool
|
|
|
|
|
|
|
|
|
|
--------------
|
|
--[ Footer ]--
|
|
--------------
|
|
|
|
|
|
rmFooter :: String
|
|
rmFooter = [s|Discussion:
|
|
Remove the given GHC or cabal version. When no command is given,
|
|
defaults to removing GHC with the specified version.
|
|
It is recommended to always specify a subcommand (ghc/cabal/hls/stack).|]
|
|
|
|
|
|
|
|
|
|
---------------------------
|
|
--[ Effect interpreters ]--
|
|
---------------------------
|
|
|
|
|
|
type RmEffects = '[ NotInstalled, UninstallFailed ]
|
|
|
|
|
|
runRm :: (ReaderT env m (VEither RmEffects a) -> m (VEither RmEffects a))
|
|
-> Excepts RmEffects (ReaderT env m) a
|
|
-> m (VEither RmEffects a)
|
|
runRm runAppState =
|
|
runAppState
|
|
. runE
|
|
@RmEffects
|
|
|
|
|
|
|
|
------------------
|
|
--[ Entrypoint ]--
|
|
------------------
|
|
|
|
|
|
|
|
rm :: ( Monad m
|
|
, MonadMask m
|
|
, MonadUnliftIO m
|
|
, MonadFail m
|
|
)
|
|
=> Either RmCommand RmOptions
|
|
-> (ReaderT AppState m (VEither RmEffects (Maybe VersionInfo))
|
|
-> m (VEither RmEffects (Maybe VersionInfo)))
|
|
-> (ReaderT LeanAppState m () -> m ())
|
|
-> m ExitCode
|
|
rm rmCommand runAppState runLogger = case rmCommand of
|
|
(Right rmopts) -> do
|
|
runLogger (logWarn "This is an old-style command for removing GHC. Use 'ghcup rm ghc' instead.")
|
|
rmGHC' rmopts
|
|
(Left (RmGHC rmopts)) -> rmGHC' rmopts
|
|
(Left (RmCabal rmopts)) -> rmCabal' rmopts
|
|
(Left (RmHLS rmopts)) -> rmHLS' rmopts
|
|
(Left (RmStack rmopts)) -> rmStack' rmopts
|
|
|
|
where
|
|
rmGHC' RmOptions{..} =
|
|
runRm runAppState (do
|
|
liftE $
|
|
rmGHCVer ghcVer
|
|
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
|
pure (getVersionInfo ghcVer GHC dls)
|
|
)
|
|
>>= \case
|
|
VRight vi -> do
|
|
runLogger $ logGHCPostRm ghcVer
|
|
postRmLog vi
|
|
pure ExitSuccess
|
|
VLeft e -> do
|
|
runLogger $ logError $ T.pack $ prettyHFError e
|
|
pure $ ExitFailure 7
|
|
|
|
rmCabal' tv =
|
|
runRm runAppState (do
|
|
liftE $
|
|
rmCabalVer tv
|
|
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
|
pure (getVersionInfo (mkTVer tv) Cabal dls)
|
|
)
|
|
>>= \case
|
|
VRight vi -> do
|
|
postRmLog vi
|
|
pure ExitSuccess
|
|
VLeft e -> do
|
|
runLogger $ logError $ T.pack $ prettyHFError e
|
|
pure $ ExitFailure 15
|
|
|
|
rmHLS' tv =
|
|
runRm runAppState (do
|
|
liftE $
|
|
rmHLSVer tv
|
|
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
|
pure (getVersionInfo (mkTVer tv) HLS dls)
|
|
)
|
|
>>= \case
|
|
VRight vi -> do
|
|
postRmLog vi
|
|
pure ExitSuccess
|
|
VLeft e -> do
|
|
runLogger $ logError $ T.pack $ prettyHFError e
|
|
pure $ ExitFailure 15
|
|
|
|
rmStack' tv =
|
|
runRm runAppState (do
|
|
liftE $
|
|
rmStackVer tv
|
|
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
|
pure (getVersionInfo (mkTVer tv) Stack dls)
|
|
)
|
|
>>= \case
|
|
VRight vi -> do
|
|
postRmLog vi
|
|
pure ExitSuccess
|
|
VLeft e -> do
|
|
runLogger $ logError $ T.pack $ prettyHFError e
|
|
pure $ ExitFailure 15
|
|
|
|
postRmLog vi =
|
|
forM_ (_viPostRemove =<< vi) $ \msg ->
|
|
runLogger $ logInfo msg
|