packages feed

ghcup-0.1.50.0: lib-opt/GHCup/OptParse/DInfo.hs

{-# LANGUAGE CPP               #-}
{-# LANGUAGE DataKinds         #-}
{-# LANGUAGE TypeApplications  #-}
{-# LANGUAGE FlexibleContexts  #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell   #-}
{-# LANGUAGE QuasiQuotes       #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE RankNTypes #-}

module GHCup.OptParse.DInfo where




import           GHCup
import           GHCup.Errors
import           GHCup.Version
import           GHCup.Types
import           GHCup.Utils.Dirs
import           GHCup.Prelude
import           GHCup.Prelude.Logger
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



    -----------------
    --[ 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 = (\(c, u) -> (T.unpack . channelAliasText $ c, T.unpack . decUTF8Safe . serializeURIRef'$ u)) <$> diChannels
  maxLength = (+1) . maximum . fmap (length . fst) $ channels
  whenWin x = if isWindows then x else mempty




    ---------------------------
    --[ Effect interpreters ]--
    ---------------------------


type DInfoEffects = '[ NoCompatiblePlatform , NoCompatibleArch , DistroNotFound ]

runDebugInfo :: (ReaderT env m (VEither DInfoEffects a) -> m (VEither DInfoEffects a))
             -> Excepts DInfoEffects (ReaderT env m) a
             -> m (VEither DInfoEffects a)
runDebugInfo runAppState =
        runAppState
        . runE
          @DInfoEffects



    ------------------
    --[ Entrypoint ]--
    ------------------



dinfo :: ( Monad m
         , MonadMask m
         , MonadUnliftIO m
         , MonadFail m
         , Alternative m
         )
      => (ReaderT AppState m (VEither DInfoEffects DebugInfo)
          -> m (VEither DInfoEffects DebugInfo))
      -> (ReaderT LeanAppState m () -> m ())
      -> m ExitCode
dinfo runAppState runLogger = do
  runDebugInfo runAppState (liftE getDebugInfo)
    >>= \case
          VRight di -> do
            liftIO $ putStrLn $ prettyDebugInfo di
            pure ExitSuccess
          VLeft e -> do
            runLogger $ logError $ T.pack $ prettyHFError e
            pure $ ExitFailure 8