ghcup-hs/lib/GHCup/Types.hs

569 lines
15 KiB
Haskell
Raw Normal View History

{-# OPTIONS_GHC -Wno-orphans #-}
2020-04-25 10:06:41 +00:00
{-# LANGUAGE CPP #-}
2021-07-15 11:32:48 +00:00
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE DataKinds #-}
2020-04-25 10:06:41 +00:00
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE FlexibleContexts #-}
2021-07-15 11:32:48 +00:00
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE DuplicateRecordFields #-}
2020-01-11 20:15:05 +00:00
2020-07-21 23:08:58 +00:00
{-|
Module : GHCup.Types
Description : GHCup types
Copyright : (c) Julian Ospald, 2020
2020-07-30 18:04:02 +00:00
License : LGPL-3.0
2020-07-21 23:08:58 +00:00
Maintainer : hasufell@hasufell.de
Stability : experimental
2021-05-14 21:09:45 +00:00
Portability : portable
2020-07-21 23:08:58 +00:00
-}
2021-05-14 21:09:45 +00:00
module GHCup.Types
( module GHCup.Types
#if defined(BRICK)
, Key(..)
#endif
)
where
2020-01-11 20:15:05 +00:00
2021-05-14 21:09:45 +00:00
import Control.Applicative
2021-07-15 11:32:48 +00:00
import Control.DeepSeq ( NFData, rnf )
2021-05-14 21:09:45 +00:00
import Control.Monad.Logger
2020-01-11 20:15:05 +00:00
import Data.Map.Strict ( Map )
import Data.List.NonEmpty ( NonEmpty (..) )
2020-01-11 20:15:05 +00:00
import Data.Text ( Text )
import Data.Versions
2021-05-14 21:09:45 +00:00
import Haskus.Utils.Variant.Excepts
import Text.PrettyPrint.HughesPJClass (Pretty, pPrint, text)
2020-01-11 20:15:05 +00:00
import URI.ByteString
2021-05-14 21:09:45 +00:00
#if defined(BRICK)
import Graphics.Vty ( Key(..) )
#endif
2020-01-11 20:15:05 +00:00
2021-05-14 21:09:45 +00:00
import qualified Control.Monad.Trans.Class as Trans
import qualified Data.Text as T
2020-01-11 20:15:05 +00:00
import qualified GHC.Generics as GHC
2021-05-14 21:09:45 +00:00
#if !defined(BRICK)
data Key = KEsc | KChar Char | KBS | KEnter
| KLeft | KRight | KUp | KDown
| KUpLeft | KUpRight | KDownLeft | KDownRight | KCenter
| KFun Int | KBackTab | KPrtScr | KPause | KIns
| KHome | KPageUp | KDel | KEnd | KPageDown | KBegin | KMenu
deriving (Eq,Show,Read,Ord,GHC.Generic)
#endif
2020-01-11 20:15:05 +00:00
2020-04-10 15:36:27 +00:00
--------------------
--[ GHCInfo Tree ]--
--------------------
data GHCupInfo = GHCupInfo
{ _toolRequirements :: ToolRequirements
, _ghcupDownloads :: GHCupDownloads
2021-05-14 21:09:45 +00:00
, _globalTools :: Map GlobalTool DownloadInfo
2020-04-10 15:36:27 +00:00
}
deriving (Show, GHC.Generic)
2021-07-15 11:32:48 +00:00
instance NFData GHCupInfo
2020-04-10 15:36:27 +00:00
-------------------------
--[ Requirements Tree ]--
-------------------------
type ToolRequirements = Map Tool ToolReqVersionSpec
type ToolReqVersionSpec = Map (Maybe Version) PlatformReqSpec
type PlatformReqSpec = Map Platform PlatformReqVersionSpec
type PlatformReqVersionSpec = Map (Maybe VersionRange) Requirements
2020-04-10 15:36:27 +00:00
data Requirements = Requirements
{ _distroPKGs :: [Text]
, _notes :: Text
}
deriving (Show, GHC.Generic)
2021-07-15 11:32:48 +00:00
instance NFData Requirements
2020-04-10 15:36:27 +00:00
2020-01-11 20:15:05 +00:00
---------------------
--[ Download Tree ]--
---------------------
-- | Description of all binary and source downloads. This is a tree
-- of nested maps.
type GHCupDownloads = Map Tool ToolVersionSpec
type ToolVersionSpec = Map Version VersionInfo
type ArchitectureSpec = Map Architecture PlatformSpec
type PlatformSpec = Map Platform PlatformVersionSpec
type PlatformVersionSpec = Map (Maybe VersionRange) DownloadInfo
2020-01-11 20:15:05 +00:00
-- | An installable tool.
data Tool = GHC
| Cabal
| GHCup
| HLS
2021-05-14 22:31:36 +00:00
| Stack
2021-01-02 06:58:08 +00:00
deriving (Eq, GHC.Generic, Ord, Show, Enum, Bounded)
2020-01-11 20:15:05 +00:00
2021-08-25 16:54:58 +00:00
instance Pretty Tool where
pPrint GHC = text "ghc"
pPrint Cabal = text "cabal"
pPrint GHCup = text "ghcup"
pPrint HLS = text "hls"
pPrint Stack = text "stack"
2021-07-15 11:32:48 +00:00
instance NFData Tool
2021-05-14 21:09:45 +00:00
data GlobalTool = ShimGen
deriving (Eq, GHC.Generic, Ord, Show, Enum, Bounded)
2021-07-15 11:32:48 +00:00
instance NFData GlobalTool
2020-01-11 20:15:05 +00:00
-- | All necessary information of a tool version, including
-- source download and per-architecture downloads.
data VersionInfo = VersionInfo
{ _viTags :: [Tag] -- ^ version specific tag
, _viChangeLog :: Maybe URI
, _viSourceDL :: Maybe DownloadInfo -- ^ source tarball
, _viArch :: ArchitectureSpec -- ^ descend for binary downloads per arch
-- informative messages
, _viPostInstall :: Maybe Text
, _viPostRemove :: Maybe Text
, _viPreCompile :: Maybe Text
2020-01-11 20:15:05 +00:00
}
2020-09-13 18:46:34 +00:00
deriving (Eq, GHC.Generic, Show)
2020-01-11 20:15:05 +00:00
2021-07-15 11:32:48 +00:00
instance NFData VersionInfo
2020-01-11 20:15:05 +00:00
-- | A tag. These are currently attached to a version of a tool.
data Tag = Latest
| Recommended
2020-07-28 18:55:00 +00:00
| Prerelease
2020-04-22 00:33:35 +00:00
| Base PVP
| Old -- ^ old version are hidden by default in TUI
2020-04-22 00:33:35 +00:00
| UnknownTag String -- ^ used for upwardscompat
2020-09-13 18:46:34 +00:00
deriving (Ord, Eq, GHC.Generic, Show) -- FIXME: manual JSON instance
2020-01-11 20:15:05 +00:00
2021-07-15 11:32:48 +00:00
instance NFData Tag
tagToString :: Tag -> String
tagToString Recommended = "recommended"
tagToString Latest = "latest"
tagToString Prerelease = "prerelease"
tagToString (Base pvp'') = "base-" ++ T.unpack (prettyPVP pvp'')
tagToString (UnknownTag t ) = t
tagToString Old = ""
instance Pretty Tag where
pPrint Recommended = text "recommended"
pPrint Latest = text "latest"
pPrint Prerelease = text "prerelease"
pPrint (Base pvp'') = text ("base-" ++ T.unpack (prettyPVP pvp''))
pPrint (UnknownTag t ) = text t
pPrint Old = mempty
2020-01-11 20:15:05 +00:00
data Architecture = A_64
| A_32
2020-06-27 17:00:13 +00:00
| A_PowerPC
| A_PowerPC64
| A_Sparc
| A_Sparc64
| A_ARM
| A_ARM64
2020-01-11 20:15:05 +00:00
deriving (Eq, GHC.Generic, Ord, Show)
2021-07-15 11:32:48 +00:00
instance NFData Architecture
archToString :: Architecture -> String
archToString A_64 = "x86_64"
archToString A_32 = "i386"
archToString A_PowerPC = "powerpc"
archToString A_PowerPC64 = "powerpc64"
archToString A_Sparc = "sparc"
archToString A_Sparc64 = "sparc64"
archToString A_ARM = "arm"
archToString A_ARM64 = "aarch64"
instance Pretty Architecture where
pPrint = text . archToString
2020-01-11 20:15:05 +00:00
data Platform = Linux LinuxDistro
-- ^ must exit
| Darwin
-- ^ must exit
| FreeBSD
2021-05-14 21:09:45 +00:00
| Windows
-- ^ must exit
2020-01-11 20:15:05 +00:00
deriving (Eq, GHC.Generic, Ord, Show)
2021-07-15 11:32:48 +00:00
instance NFData Platform
platformToString :: Platform -> String
platformToString (Linux distro) = "linux-" ++ distroToString distro
platformToString Darwin = "darwin"
platformToString FreeBSD = "freebsd"
2021-05-14 21:09:45 +00:00
platformToString Windows = "windows"
instance Pretty Platform where
pPrint = text . platformToString
2020-01-11 20:15:05 +00:00
data LinuxDistro = Debian
| Ubuntu
| Mint
| Fedora
| CentOS
| RedHat
| Alpine
| AmazonLinux
2021-08-25 10:26:40 +00:00
| Solus
2020-01-11 20:15:05 +00:00
-- rolling
| Gentoo
| Exherbo
-- not known
| UnknownLinux
-- ^ must exit
deriving (Eq, GHC.Generic, Ord, Show)
2021-07-15 11:32:48 +00:00
instance NFData LinuxDistro
distroToString :: LinuxDistro -> String
distroToString Debian = "debian"
distroToString Ubuntu = "ubuntu"
distroToString Mint= "mint"
distroToString Fedora = "fedora"
distroToString CentOS = "centos"
distroToString RedHat = "redhat"
distroToString Alpine = "alpine"
distroToString AmazonLinux = "amazon"
2021-08-25 10:26:40 +00:00
distroToString Solus = "solus"
distroToString Gentoo = "gentoo"
distroToString Exherbo = "exherbo"
distroToString UnknownLinux = "unknown"
instance Pretty LinuxDistro where
pPrint = text . distroToString
2020-01-11 20:15:05 +00:00
-- | An encapsulation of a download. This can be used
-- to download, extract and install a tool.
data DownloadInfo = DownloadInfo
{ _dlUri :: URI
2020-08-06 11:28:20 +00:00
, _dlSubdir :: Maybe TarDir
2020-01-11 20:15:05 +00:00
, _dlHash :: Text
}
deriving (Eq, Ord, GHC.Generic, Show)
2020-01-11 20:15:05 +00:00
2021-07-15 11:32:48 +00:00
instance NFData DownloadInfo
2020-01-11 20:15:05 +00:00
--------------
--[ Others ]--
--------------
2020-08-06 11:28:20 +00:00
-- | How to descend into a tar archive.
2021-05-14 21:09:45 +00:00
data TarDir = RealDir FilePath
2020-08-06 11:28:20 +00:00
| RegexDir String -- ^ will be compiled to regex, the first match will "win"
deriving (Eq, Ord, GHC.Generic, Show)
2020-08-06 11:28:20 +00:00
2021-07-15 11:32:48 +00:00
instance NFData TarDir
instance Pretty TarDir where
2021-05-14 21:09:45 +00:00
pPrint (RealDir path) = text path
pPrint (RegexDir regex) = text regex
2020-08-06 11:28:20 +00:00
2020-01-11 20:15:05 +00:00
-- | Where to fetch GHCupDownloads from.
data URLSource = GHCupURL
| OwnSource URI
2020-04-10 15:36:27 +00:00
| OwnSpec GHCupInfo
2020-10-25 13:17:17 +00:00
| AddSource (Either GHCupInfo URI) -- ^ merge with GHCupURL
2020-09-13 18:46:34 +00:00
deriving (GHC.Generic, Show)
2020-01-11 20:15:05 +00:00
2021-07-15 11:32:48 +00:00
instance NFData URLSource
instance NFData (URIRef Absolute) where
rnf (URI !_ !_ !_ !_ !_) = ()
2020-01-11 20:15:05 +00:00
data UserSettings = UserSettings
{ uCache :: Maybe Bool
, uNoVerify :: Maybe Bool
, uVerbose :: Maybe Bool
, uKeepDirs :: Maybe KeepDirs
, uDownloader :: Maybe Downloader
, uKeyBindings :: Maybe UserKeyBindings
2020-10-25 13:17:17 +00:00
, uUrlSource :: Maybe URLSource
2021-07-18 21:29:09 +00:00
, uNoNetwork :: Maybe Bool
}
deriving (Show, GHC.Generic)
defaultUserSettings :: UserSettings
2021-07-18 21:29:09 +00:00
defaultUserSettings = UserSettings Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing
2021-08-11 14:19:31 +00:00
fromSettings :: Settings -> Maybe KeyBindings -> UserSettings
fromSettings Settings{..} Nothing =
UserSettings {
uCache = Just cache
, uNoVerify = Just noVerify
, uVerbose = Just verbose
, uKeepDirs = Just keepDirs
, uDownloader = Just downloader
, uNoNetwork = Just noNetwork
, uKeyBindings = Nothing
, uUrlSource = Just urlSource
}
fromSettings Settings{..} (Just KeyBindings{..}) =
let ukb = UserKeyBindings
{ kUp = Just bUp
, kDown = Just bDown
, kQuit = Just bQuit
, kInstall = Just bInstall
, kUninstall = Just bUninstall
, kSet = Just bSet
, kChangelog = Just bChangelog
, kShowAll = Just bShowAllVersions
, kShowAllTools = Just bShowAllTools
}
in UserSettings {
uCache = Just cache
, uNoVerify = Just noVerify
, uVerbose = Just verbose
, uKeepDirs = Just keepDirs
, uDownloader = Just downloader
, uNoNetwork = Just noNetwork
, uKeyBindings = Just ukb
, uUrlSource = Just urlSource
}
data UserKeyBindings = UserKeyBindings
2021-05-14 21:09:45 +00:00
{ kUp :: Maybe Key
, kDown :: Maybe Key
, kQuit :: Maybe Key
, kInstall :: Maybe Key
, kUninstall :: Maybe Key
, kSet :: Maybe Key
, kChangelog :: Maybe Key
, kShowAll :: Maybe Key
, kShowAllTools :: Maybe Key
}
deriving (Show, GHC.Generic)
data KeyBindings = KeyBindings
2021-05-14 21:09:45 +00:00
{ bUp :: Key
, bDown :: Key
, bQuit :: Key
, bInstall :: Key
, bUninstall :: Key
, bSet :: Key
, bChangelog :: Key
, bShowAllVersions :: Key
, bShowAllTools :: Key
}
deriving (Show, GHC.Generic)
2021-07-15 11:32:48 +00:00
instance NFData KeyBindings
instance NFData Key
defaultKeyBindings :: KeyBindings
defaultKeyBindings = KeyBindings
2021-05-14 21:09:45 +00:00
{ bUp = KUp
, bDown = KDown
, bQuit = KChar 'q'
, bInstall = KChar 'i'
, bUninstall = KChar 'u'
, bSet = KChar 's'
, bChangelog = KChar 'c'
, bShowAllVersions = KChar 'a'
, bShowAllTools = KChar 't'
}
2020-10-23 23:06:53 +00:00
data AppState = AppState
{ settings :: Settings
, dirs :: Dirs
, keyBindings :: KeyBindings
, ghcupInfo :: GHCupInfo
, pfreq :: PlatformRequest
} deriving (Show, GHC.Generic)
2021-07-18 21:29:09 +00:00
instance NFData AppState
data LeanAppState = LeanAppState
{ settings :: Settings
, dirs :: Dirs
, keyBindings :: KeyBindings
2021-07-15 11:32:48 +00:00
} deriving (Show, GHC.Generic)
2021-07-18 21:29:09 +00:00
instance NFData LeanAppState
2020-10-23 23:06:53 +00:00
2020-01-11 20:15:05 +00:00
data Settings = Settings
2020-10-23 23:06:53 +00:00
{ cache :: Bool
2020-04-29 17:12:58 +00:00
, noVerify :: Bool
, keepDirs :: KeepDirs
, downloader :: Downloader
2020-07-13 09:52:34 +00:00
, verbose :: Bool
2020-10-25 13:17:17 +00:00
, urlSource :: URLSource
2021-07-18 21:29:09 +00:00
, noNetwork :: Bool
2020-01-11 20:15:05 +00:00
}
deriving (Show, GHC.Generic)
2020-01-11 20:15:05 +00:00
2021-07-15 11:32:48 +00:00
instance NFData Settings
2020-07-31 18:10:40 +00:00
data Dirs = Dirs
2021-05-14 21:09:45 +00:00
{ baseDir :: FilePath
, binDir :: FilePath
, cacheDir :: FilePath
, logsDir :: FilePath
, confDir :: FilePath
2021-07-22 13:45:08 +00:00
, recycleDir :: FilePath -- mainly used on windows
2020-07-31 18:10:40 +00:00
}
2021-07-15 11:32:48 +00:00
deriving (Show, GHC.Generic)
instance NFData Dirs
2020-01-11 20:15:05 +00:00
2020-04-22 16:12:40 +00:00
data KeepDirs = Always
| Errors
| Never
2021-07-15 11:32:48 +00:00
deriving (Eq, Show, Ord, GHC.Generic)
instance NFData KeepDirs
2020-04-22 16:12:40 +00:00
2020-04-29 17:12:58 +00:00
data Downloader = Curl
| Wget
#if defined(INTERNAL_DOWNLOADER)
| Internal
#endif
2021-07-15 11:32:48 +00:00
deriving (Eq, Show, Ord, GHC.Generic)
instance NFData Downloader
2020-04-22 16:12:40 +00:00
2020-01-11 20:15:05 +00:00
data DebugInfo = DebugInfo
2021-05-14 21:09:45 +00:00
{ diBaseDir :: FilePath
, diBinDir :: FilePath
, diGHCDir :: FilePath
, diCacheDir :: FilePath
2020-03-17 17:39:01 +00:00
, diArch :: Architecture
, diPlatform :: PlatformResult
2020-01-11 20:15:05 +00:00
}
deriving Show
data SetGHC = SetGHCOnly -- ^ unversioned 'ghc'
| SetGHC_XY -- ^ ghc-x.y
| SetGHC_XYZ -- ^ ghc-x.y.z
deriving (Eq, Show)
data PlatformResult = PlatformResult
{ _platform :: Platform
, _distroVersion :: Maybe Versioning
}
2021-07-15 11:32:48 +00:00
deriving (Eq, Show, GHC.Generic)
instance NFData PlatformResult
2020-01-11 20:15:05 +00:00
platResToString :: PlatformResult -> String
platResToString PlatformResult { _platform = plat, _distroVersion = Just v' }
= show plat <> ", " <> T.unpack (prettyV v')
platResToString PlatformResult { _platform = plat, _distroVersion = Nothing }
= show plat
instance Pretty PlatformResult where
pPrint = text . platResToString
2020-01-11 20:15:05 +00:00
data PlatformRequest = PlatformRequest
{ _rArch :: Architecture
, _rPlatform :: Platform
, _rVersion :: Maybe Versioning
}
2021-07-15 11:32:48 +00:00
deriving (Eq, Show, GHC.Generic)
instance NFData PlatformRequest
2020-04-25 10:06:41 +00:00
pfReqToString :: PlatformRequest -> String
pfReqToString (PlatformRequest arch plat ver) =
archToString arch ++ "-" ++ platformToString plat ++ pver
where
pver = case ver of
2021-03-11 16:03:51 +00:00
Just v' -> "-" ++ T.unpack (prettyV v')
Nothing -> ""
2020-04-25 10:06:41 +00:00
instance Pretty PlatformRequest where
pPrint = text . pfReqToString
2020-04-25 10:06:41 +00:00
-- | A GHC identified by the target platform triple
-- and the version.
data GHCTargetVersion = GHCTargetVersion
{ _tvTarget :: Maybe Text
, _tvVersion :: Version
}
deriving (Ord, Eq, Show)
2021-04-28 16:45:48 +00:00
data GitBranch = GitBranch
{ ref :: String
, repo :: Maybe String
}
deriving (Ord, Eq, Show)
2020-04-25 10:06:41 +00:00
mkTVer :: Version -> GHCTargetVersion
mkTVer = GHCTargetVersion Nothing
tVerToText :: GHCTargetVersion -> Text
tVerToText (GHCTargetVersion (Just t) v') = t <> "-" <> prettyVer v'
tVerToText (GHCTargetVersion Nothing v') = prettyVer v'
2020-04-25 10:06:41 +00:00
-- | Assembles a path of the form: <target-triple>-<version>
instance Pretty GHCTargetVersion where
pPrint = text . T.unpack . tVerToText
2020-04-25 10:06:41 +00:00
-- | A comparator and a version.
data VersionCmp = VR_gt Versioning
| VR_gteq Versioning
| VR_lt Versioning
| VR_lteq Versioning
| VR_eq Versioning
deriving (Eq, GHC.Generic, Ord, Show)
2021-07-15 11:32:48 +00:00
instance NFData VersionCmp
-- | A version range. Supports && and ||, but not arbitrary
-- combinations. This is a little simplified.
data VersionRange = SimpleRange (NonEmpty VersionCmp) -- And
| OrRange (NonEmpty VersionCmp) VersionRange
deriving (Eq, GHC.Generic, Ord, Show)
2021-07-15 11:32:48 +00:00
instance NFData VersionRange
instance Pretty Versioning where
pPrint = text . T.unpack . prettyV
instance Pretty Version where
pPrint = text . T.unpack . prettyVer
2021-05-14 21:09:45 +00:00
instance (Monad m, Alternative m) => Alternative (LoggingT m) where
empty = Trans.lift empty
{-# INLINE empty #-}
m <|> n = LoggingT $ \ r -> runLoggingT m r <|> runLoggingT n r
{-# INLINE (<|>) #-}
instance MonadLogger m => MonadLogger (Excepts e m) where
monadLoggerLog a b c d = Trans.lift $ monadLoggerLog a b c d