ghcup-0.2.1.0: lib-opt/GHCup/OptParse/DebugInfo.hs
{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE RankNTypes #-}
module GHCup.OptParse.DebugInfo where
import GHCup.Command.DebugInfo
import GHCup.Errors
import GHCup.Hardcoded.Version
import GHCup.Types
import GHCup.Query.GHCupDirs
import GHCup.Prelude
import GHCup.Prelude.Process
#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.List ( intercalate )
import Data.Variant.Excepts
import Options.Applicative hiding ( style )
import Prelude hiding ( appendFile )
import System.Exit
import System.FilePath
import Text.PrettyPrint.HughesPJClass ( prettyShow )
import URI.ByteString (serializeURIRef')
import qualified Data.Text as T
import Control.Exception.Safe (MonadMask)
import Language.Haskell.TH
import Data.Bifunctor (bimap)
-----------------
--[ Utilities ]--
-----------------
describe_result :: String
describe_result = $( LitE . StringL <$>
runIO (do
CapturedProcess{..} <- do
dirs <- liftIO getAllDirs
let settings = AppState (defaultSettings { noNetwork = True })
dirs
defaultKeyBindings
flip runReaderT settings $ executeOut "git" ["describe"] Nothing
case _exitCode of
ExitSuccess -> pure . T.unpack . decUTF8Safe' $ _stdOut
ExitFailure _ -> pure numericVer
)
)
prettyDebugInfo :: DebugInfo -> String
prettyDebugInfo DebugInfo { diDirs = Dirs { .. }, ..} =
"===== Main ======" <> "\n" <>
"Architecture: " <> prettyShow diArch <> "\n" <>
"Platform: " <> prettyShow diPlatform <> "\n" <>
"GHCup Version: " <> describe_result <> "\n" <>
"===== Directories ======" <> "\n" <>
"base: " <> fromGHCupPath baseDir <> "\n" <>
"bin: " <> binDir <> "\n" <>
"GHCs: " <> (fromGHCupPath baseDir </> "ghc") <> "\n" <>
"cache: " <> fromGHCupPath cacheDir <> "\n" <>
"logs: " <> fromGHCupPath logsDir <> "\n" <>
"config: " <> fromGHCupPath confDir <> "\n" <>
"db: " <> fromGHCupPath dbDir <> "\n" <>
whenWin ("recycle: " <> fromGHCupPath recycleDir <> "\n") <>
"temp: " <> fromGHCupPath tmpDir <> "\n" <>
whenWin ("msys2: " <> msys2Dir <> "\n") <>
"\n===== Metadata ======\n" <>
intercalate "\n" ((\(c, u) -> pad (c <> ":") <> " " <> u) <$> channels)
where
pad xs
| xl < maxLength = xs <> replicate (maxLength - xl) ' '
| otherwise = xs
where
xl = length xs
channels = bimap (T.unpack . channelAliasText) (T.unpack . decUTF8Safe . serializeURIRef') <$> diChannels
maxLength = (+1) . maximum . fmap (length . fst) $ channels
whenWin x = if isWindows then x else mempty
---------------------------
--[ Effect interpreters ]--
---------------------------
type DInfoEffects = '[ NoCompatiblePlatform , NoCompatibleArch , DistroNotFound ]
------------------
--[ Entrypoint ]--
------------------
dinfo :: ( Monad m
, MonadMask m
, MonadUnliftIO m
, MonadFail m
, Alternative m
)
=> (IO (AppState, IO ()), LeanAppState)
-> m ExitCode
dinfo (getAppState', leanAppstate) = do
run (liftE getDebugInfo)
>>= \case
(VRight di, up) -> do
liftIO $ putStrLn $ prettyDebugInfo di
liftIO up
pure ExitSuccess
(VLeft e, _) -> do
runLogger $ logError $ T.pack $ prettyHFError e
pure $ ExitFailure 8
where
runLogger = flip runReaderT leanAppstate
run action' = do
(appstate', up) <- liftIO getAppState'
r <- flip runReaderT appstate'
. runResourceT
. runE
@DInfoEffects
$ action'
pure (r, up)