packages feed

ghcup 0.1.14.2 → 0.1.17.2

raw patch · 48 files changed

+17692/−7808 lines, 48 filesdep +Cabaldep +HsYAML-aesondep +Win32dep −concurrent-outputdep −generics-sopdep −hpathdep ~asyncdep ~brickdep ~hspecPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: Cabal, HsYAML-aeson, Win32, bzlib, cabal-plan, deepseq, directory, disk-free-space, filepath, process, retry, temporary, unliftio-core

Dependencies removed: concurrent-output, generics-sop, hpath, hpath-directory, hpath-filepath, hpath-io, hpath-posix, monad-logger, optics-vl, parsec, streamly, streamly-bytestring, streamly-posix, string-interpolate, tar-bytestring, yaml

Dependency ranges changed: async, brick, hspec, hspec-golden-aeson, io-streams, libarchive, lzma-static, optics, template-haskell, unix-bytestring

API changes (from Hackage documentation)

- GHCup.Download: downloadBS :: (MonadReader AppState m, MonadCatch m, MonadIO m, MonadLogger m) => URI -> Excepts '[FileDoesNotExistError, HTTPStatusError, URIParseError, UnsupportedScheme, NoLocationHeader, TooManyRedirs, ProcessError] m ByteString
- GHCup.Download: readFromCache :: (MonadIO m, MonadCatch m, MonadLogger m, MonadReader AppState m) => Excepts '[JSONError, FileDoesNotExistError] m GHCupInfo
- GHCup.Types: [_distroPKGs] :: Requirements -> [Text]
- GHCup.Types: [_distroVersion] :: PlatformResult -> Maybe Versioning
- GHCup.Types: [_dlHash] :: DownloadInfo -> Text
- GHCup.Types: [_dlSubdir] :: DownloadInfo -> Maybe TarDir
- GHCup.Types: [_dlUri] :: DownloadInfo -> URI
- GHCup.Types: [_ghcupDownloads] :: GHCupInfo -> GHCupDownloads
- GHCup.Types: [_notes] :: Requirements -> Text
- GHCup.Types: [_platform] :: PlatformResult -> Platform
- GHCup.Types: [_rArch] :: PlatformRequest -> Architecture
- GHCup.Types: [_rPlatform] :: PlatformRequest -> Platform
- GHCup.Types: [_rVersion] :: PlatformRequest -> Maybe Versioning
- GHCup.Types: [_toolRequirements] :: GHCupInfo -> ToolRequirements
- GHCup.Types: [_tvTarget] :: GHCTargetVersion -> Maybe Text
- GHCup.Types: [_tvVersion] :: GHCTargetVersion -> Version
- GHCup.Types: [_viArch] :: VersionInfo -> ArchitectureSpec
- GHCup.Types: [_viChangeLog] :: VersionInfo -> Maybe URI
- GHCup.Types: [_viPostInstall] :: VersionInfo -> Maybe Text
- GHCup.Types: [_viPostRemove] :: VersionInfo -> Maybe Text
- GHCup.Types: [_viPreCompile] :: VersionInfo -> Maybe Text
- GHCup.Types: [_viSourceDL] :: VersionInfo -> Maybe DownloadInfo
- GHCup.Types: [_viTags] :: VersionInfo -> [Tag]
- GHCup.Types: [bChangelog] :: KeyBindings -> Key
- GHCup.Types: [bDown] :: KeyBindings -> Key
- GHCup.Types: [bInstall] :: KeyBindings -> Key
- GHCup.Types: [bQuit] :: KeyBindings -> Key
- GHCup.Types: [bSet] :: KeyBindings -> Key
- GHCup.Types: [bShowAll] :: KeyBindings -> Key
- GHCup.Types: [bUninstall] :: KeyBindings -> Key
- GHCup.Types: [bUp] :: KeyBindings -> Key
- GHCup.Types: [baseDir] :: Dirs -> Path Abs
- GHCup.Types: [binDir] :: Dirs -> Path Abs
- GHCup.Types: [cacheDir] :: Dirs -> Path Abs
- GHCup.Types: [cache] :: Settings -> Bool
- GHCup.Types: [confDir] :: Dirs -> Path Abs
- GHCup.Types: [diArch] :: DebugInfo -> Architecture
- GHCup.Types: [diBaseDir] :: DebugInfo -> Path Abs
- GHCup.Types: [diBinDir] :: DebugInfo -> Path Abs
- GHCup.Types: [diCacheDir] :: DebugInfo -> Path Abs
- GHCup.Types: [diGHCDir] :: DebugInfo -> Path Abs
- GHCup.Types: [diPlatform] :: DebugInfo -> PlatformResult
- GHCup.Types: [dirs] :: AppState -> Dirs
- GHCup.Types: [downloader] :: Settings -> Downloader
- GHCup.Types: [kChangelog] :: UserKeyBindings -> Maybe Key
- GHCup.Types: [kDown] :: UserKeyBindings -> Maybe Key
- GHCup.Types: [kInstall] :: UserKeyBindings -> Maybe Key
- GHCup.Types: [kQuit] :: UserKeyBindings -> Maybe Key
- GHCup.Types: [kSet] :: UserKeyBindings -> Maybe Key
- GHCup.Types: [kShowAll] :: UserKeyBindings -> Maybe Key
- GHCup.Types: [kUninstall] :: UserKeyBindings -> Maybe Key
- GHCup.Types: [kUp] :: UserKeyBindings -> Maybe Key
- GHCup.Types: [keepDirs] :: Settings -> KeepDirs
- GHCup.Types: [keyBindings] :: AppState -> KeyBindings
- GHCup.Types: [logsDir] :: Dirs -> Path Abs
- GHCup.Types: [noVerify] :: Settings -> Bool
- GHCup.Types: [settings] :: AppState -> Settings
- GHCup.Types: [uCache] :: UserSettings -> Maybe Bool
- GHCup.Types: [uDownloader] :: UserSettings -> Maybe Downloader
- GHCup.Types: [uKeepDirs] :: UserSettings -> Maybe KeepDirs
- GHCup.Types: [uKeyBindings] :: UserSettings -> Maybe UserKeyBindings
- GHCup.Types: [uNoVerify] :: UserSettings -> Maybe Bool
- GHCup.Types: [uUrlSource] :: UserSettings -> Maybe URLSource
- GHCup.Types: [uVerbose] :: UserSettings -> Maybe Bool
- GHCup.Types: [urlSource] :: Settings -> URLSource
- GHCup.Types: [verbose] :: Settings -> Bool
- GHCup.Types.JSON: instance Data.Aeson.Types.FromJSON.FromJSON (HPath.Internal.Path HPath.Rel)
- GHCup.Types.JSON: instance Data.Aeson.Types.FromJSON.FromJSON Graphics.Vty.Input.Events.Key
- GHCup.Types.JSON: instance Data.Aeson.Types.ToJSON.ToJSON (HPath.Internal.Path HPath.Rel)
- GHCup.Types.JSON: instance Data.Aeson.Types.ToJSON.ToJSON Graphics.Vty.Input.Events.Key
- GHCup.Utils: createDirRecursive' :: Path b -> IO ()
- GHCup.Utils: forFold :: (Foldable t, Applicative m, Monoid b) => t a -> (a -> m b) -> m b
- GHCup.Utils: getCache :: MonadReader AppState m => m Bool
- GHCup.Utils: getDownloader :: MonadReader AppState m => m Downloader
- GHCup.Utils: getGHCForMajor :: (MonadReader AppState m, MonadIO m, MonadThrow m) => Int -> Int -> Maybe Text -> m (Maybe GHCTargetVersion)
- GHCup.Utils: getInstalledCabals' :: (MonadLogger m, MonadReader AppState m, MonadIO m, MonadCatch m) => Maybe Version -> m [Either (Path Rel) Version]
- GHCup.Utils: getLatestGHCFor :: Int -> Int -> GHCupDownloads -> Maybe (Version, VersionInfo)
- GHCup.Utils: ghcLinkVersion :: MonadThrow m => ByteString -> m GHCTargetVersion
- GHCup.Utils: traverseFold :: (Foldable t, Applicative m, Monoid b) => (a -> m b) -> t a -> m b
- GHCup.Utils: urlBaseName :: MonadThrow m => ByteString -> m (Path Rel)
- GHCup.Utils.Dirs: getDirs :: IO Dirs
- GHCup.Utils.File: CapturedProcess :: ExitCode -> ByteString -> ByteString -> CapturedProcess
- GHCup.Utils.File: NoSuchPid :: ByteString -> [ByteString] -> ProcessError
- GHCup.Utils.File: NonZeroExit :: Int -> ByteString -> [ByteString] -> ProcessError
- GHCup.Utils.File: PStopped :: ByteString -> [ByteString] -> ProcessError
- GHCup.Utils.File: PTerminated :: ByteString -> [ByteString] -> ProcessError
- GHCup.Utils.File: [_exitCode] :: CapturedProcess -> ExitCode
- GHCup.Utils.File: [_stdErr] :: CapturedProcess -> ByteString
- GHCup.Utils.File: [_stdOut] :: CapturedProcess -> ByteString
- GHCup.Utils.File: data CapturedProcess
- GHCup.Utils.File: data ProcessError
- GHCup.Utils.File: exitCode :: Lens' CapturedProcess ExitCode
- GHCup.Utils.File: findExecutable :: Path Rel -> IO (Maybe (Path Abs))
- GHCup.Utils.File: findFiles :: Path Abs -> Regex -> IO [Path Rel]
- GHCup.Utils.File: findFiles' :: Path Abs -> Parsec Void Text () -> IO [Path Rel]
- GHCup.Utils.File: instance GHC.Classes.Eq GHCup.Utils.File.CapturedProcess
- GHCup.Utils.File: instance GHC.Show.Show GHCup.Utils.File.CapturedProcess
- GHCup.Utils.File: instance GHC.Show.Show GHCup.Utils.File.ProcessError
- GHCup.Utils.File: instance Text.PrettyPrint.HughesPJClass.Pretty GHCup.Utils.File.ProcessError
- GHCup.Utils.File: isInPath :: Path Abs -> IO Bool
- GHCup.Utils.File: isShadowed :: Path Abs -> IO (Maybe (Path Abs))
- GHCup.Utils.File: searchPath :: [Path Abs] -> Path Rel -> IO (Maybe (Path Abs))
- GHCup.Utils.File: stdErr :: Lens' CapturedProcess ByteString
- GHCup.Utils.File: stdOut :: Lens' CapturedProcess ByteString
- GHCup.Utils.Logger: LoggerConfig :: Bool -> (ByteString -> IO ()) -> (ByteString -> IO ()) -> LoggerConfig
- GHCup.Utils.Logger: [colorOutter] :: LoggerConfig -> ByteString -> IO ()
- GHCup.Utils.Logger: [lcPrintDebug] :: LoggerConfig -> Bool
- GHCup.Utils.Logger: [rawOutter] :: LoggerConfig -> ByteString -> IO ()
- GHCup.Utils.Logger: data LoggerConfig
- GHCup.Utils.Logger: myLoggerT :: LoggerConfig -> LoggingT m a -> m a
- GHCup.Utils.Prelude: addToCurrentEnv :: MonadIO m => [(ByteString, ByteString)] -> m [(ByteString, ByteString)]
+ GHCup: ListAvailable :: ListCriteria
+ GHCup: checkIfToolInstalled :: (MonadIO m, MonadReader env m, HasDirs env, MonadCatch m) => Tool -> Version -> m Bool
+ GHCup: compileHLS :: (MonadMask m, MonadCatch m, MonadReader env m, HasDirs env, HasSettings env, HasPlatformReq env, HasGHCupInfo env, HasLog env, MonadResource m, MonadIO m, MonadUnliftIO m, MonadFail m) => Either Version GitBranch -> [Version] -> Maybe Int -> Maybe Version -> Maybe FilePath -> Maybe FilePath -> Maybe FilePath -> Maybe FilePath -> Excepts '[NoDownload, GPGError, DownloadFailed, DigestError, UnknownArchive, TarDirDoesNotExist, ArchiveResult, BuildFailed, NotInstalled] m Version
+ GHCup: fetchGHCSrc :: (MonadFail m, MonadMask m, MonadCatch m, MonadReader env m, HasDirs env, HasSettings env, HasPlatformReq env, HasGHCupInfo env, HasLog env, MonadResource m, MonadIO m, MonadUnliftIO m) => Version -> Maybe FilePath -> Excepts '[DigestError, GPGError, DownloadFailed, NoDownload] m FilePath
+ GHCup: fetchToolBindist :: (MonadFail m, MonadMask m, MonadCatch m, MonadReader env m, HasDirs env, HasSettings env, HasPlatformReq env, HasGHCupInfo env, HasLog env, MonadResource m, MonadIO m, MonadUnliftIO m) => Version -> Tool -> Maybe FilePath -> Excepts '[DigestError, GPGError, DownloadFailed, NoDownload] m FilePath
+ GHCup: installCabalUnpacked :: (MonadCatch m, HasLog env, MonadIO m, MonadReader env m) => FilePath -> FilePath -> Maybe Version -> Bool -> Excepts '[CopyError, FileAlreadyExistsError] m ()
+ GHCup: installHLSPostInst :: (MonadReader env m, HasDirs env, HasLog env, MonadIO m, MonadCatch m, MonadMask m, MonadFail m, MonadUnliftIO m) => Maybe FilePath -> Version -> Excepts '[NotInstalled] m ()
+ GHCup: installHLSUnpacked :: (MonadReader env m, MonadFail m, HasLog env, MonadCatch m, MonadIO m) => FilePath -> FilePath -> Maybe Version -> Bool -> Excepts '[CopyError, FileAlreadyExistsError] m ()
+ GHCup: installStackBin :: (MonadMask m, MonadCatch m, MonadReader env m, HasDirs env, HasSettings env, HasPlatformReq env, HasGHCupInfo env, HasLog env, MonadResource m, MonadIO m, MonadUnliftIO m, MonadFail m) => Version -> Maybe FilePath -> Bool -> Excepts '[AlreadyInstalled, CopyError, DigestError, GPGError, DownloadFailed, NoDownload, NotInstalled, UnknownArchive, TarDirDoesNotExist, ArchiveResult, FileAlreadyExistsError] m ()
+ GHCup: installStackBindist :: (MonadMask m, MonadCatch m, MonadReader env m, HasPlatformReq env, HasDirs env, HasSettings env, HasLog env, MonadResource m, MonadIO m, MonadUnliftIO m, MonadFail m) => DownloadInfo -> Version -> Maybe FilePath -> Bool -> Excepts '[AlreadyInstalled, CopyError, DigestError, GPGError, DownloadFailed, NoDownload, NotInstalled, UnknownArchive, TarDirDoesNotExist, ArchiveResult, FileAlreadyExistsError] m ()
+ GHCup: installStackUnpacked :: (MonadReader env m, HasLog env, MonadCatch m, MonadIO m) => FilePath -> FilePath -> Maybe Version -> Bool -> Excepts '[CopyError, FileAlreadyExistsError] m ()
+ GHCup: rmCache :: (MonadReader env m, HasDirs env, HasLog env, MonadIO m, MonadMask m) => m ()
+ GHCup: rmGhcup :: (MonadReader env m, HasDirs env, MonadIO m, MonadCatch m, HasLog env, MonadMask m, MonadUnliftIO m) => m ()
+ GHCup: rmGhcupDirs :: (MonadReader env m, HasDirs env, MonadIO m, HasLog env, MonadCatch m, MonadMask m) => m [FilePath]
+ GHCup: rmHLSNoGHC :: (MonadReader env m, HasDirs env, HasLog env, MonadIO m, MonadMask m) => m ()
+ GHCup: rmOldGHC :: (MonadReader env m, HasGHCupInfo env, HasDirs env, HasLog env, MonadIO m, MonadFail m, MonadMask m, MonadUnliftIO m) => Excepts '[NotInstalled] m ()
+ GHCup: rmProfilingLibs :: (MonadReader env m, HasDirs env, HasLog env, MonadIO m, MonadFail m, MonadMask m, MonadUnliftIO m) => m ()
+ GHCup: rmShareDir :: (MonadReader env m, HasDirs env, HasLog env, MonadIO m, MonadFail m, MonadMask m, MonadUnliftIO m) => m ()
+ GHCup: rmStackVer :: (MonadMask m, MonadReader env m, HasDirs env, MonadThrow m, HasLog env, MonadIO m, MonadFail m, MonadCatch m, MonadUnliftIO m) => Version -> Excepts '[NotInstalled] m ()
+ GHCup: rmTmp :: (MonadReader env m, HasDirs env, HasLog env, MonadIO m, MonadMask m) => m ()
+ GHCup: rmTool :: (MonadReader env m, HasDirs env, HasLog env, MonadFail m, MonadMask m, MonadUnliftIO m) => ListResult -> Excepts '[NotInstalled] m ()
+ GHCup: setStack :: (MonadMask m, MonadReader env m, HasDirs env, HasLog env, MonadThrow m, MonadFail m, MonadIO m, MonadUnliftIO m) => Version -> Excepts '[NotInstalled] m ()
+ GHCup: throwIfFileAlreadyExists :: MonadIO m => FilePath -> Excepts '[FileAlreadyExistsError] m ()
+ GHCup: unsetCabal :: (MonadMask m, MonadReader env m, HasDirs env, MonadIO m) => m ()
+ GHCup: unsetGHC :: (MonadReader env m, HasDirs env, HasLog env, MonadThrow m, MonadFail m, MonadIO m, MonadMask m) => Maybe Text -> Excepts '[NotInstalled] m ()
+ GHCup: unsetHLS :: (MonadMask m, MonadReader env m, HasDirs env, MonadIO m) => m ()
+ GHCup: unsetStack :: (MonadMask m, MonadReader env m, HasDirs env, MonadIO m) => m ()
+ GHCup: warnAboutHlsCompatibility :: (MonadReader env m, HasDirs env, HasLog env, MonadThrow m, MonadCatch m, MonadIO m) => m ()
+ GHCup: whereIsTool :: (MonadReader env m, HasDirs env, HasLog env, MonadThrow m, MonadFail m, MonadIO m, MonadCatch m, MonadMask m, MonadUnliftIO m) => Tool -> GHCTargetVersion -> Excepts '[NotInstalled] m FilePath
+ GHCup.Download: downloadCached' :: (MonadReader env m, HasDirs env, HasSettings env, MonadMask m, MonadThrow m, HasLog env, MonadIO m, MonadUnliftIO m) => DownloadInfo -> Maybe FilePath -> Maybe FilePath -> Excepts '[DigestError, DownloadFailed, GPGError] m FilePath
+ GHCup.Download: etagsFile :: FilePath -> FilePath
+ GHCup.Download: getGpgOpts :: IO [String]
+ GHCup.Download: getLastHeader :: Text -> Text
+ GHCup.Download: tmpFile :: FilePath -> FilePath
+ GHCup.Download: urlBaseName :: ByteString -> ByteString
+ GHCup.Download: yamlFromCache :: (MonadReader env m, HasDirs env) => URI -> m FilePath
+ GHCup.Errors: DirNotEmpty :: FilePath -> DirNotEmpty
+ GHCup.Errors: FileAlreadyExistsError :: FilePath -> FileAlreadyExistsError
+ GHCup.Errors: GPGError :: V xs -> GPGError
+ GHCup.Errors: HTTPNotModified :: Text -> HTTPNotModified
+ GHCup.Errors: HadrianNotFound :: HadrianNotFound
+ GHCup.Errors: MalformedHeaders :: Text -> MalformedHeaders
+ GHCup.Errors: NoNetwork :: NoNetwork
+ GHCup.Errors: NoUrlBase :: Text -> NoUrlBase
+ GHCup.Errors: [path] :: DirNotEmpty -> FilePath
+ GHCup.Errors: data DirNotEmpty
+ GHCup.Errors: data FileAlreadyExistsError
+ GHCup.Errors: data GPGError
+ GHCup.Errors: data HTTPNotModified
+ GHCup.Errors: data HadrianNotFound
+ GHCup.Errors: data MalformedHeaders
+ GHCup.Errors: data NoNetwork
+ GHCup.Errors: data NoUrlBase
+ GHCup.Errors: instance GHC.Exception.Type.Exception GHCup.Errors.NoUrlBase
+ GHCup.Errors: instance GHC.Show.Show GHCup.Errors.FileAlreadyExistsError
+ GHCup.Errors: instance GHC.Show.Show GHCup.Errors.GPGError
+ GHCup.Errors: instance GHC.Show.Show GHCup.Errors.HTTPNotModified
+ GHCup.Errors: instance GHC.Show.Show GHCup.Errors.HadrianNotFound
+ GHCup.Errors: instance GHC.Show.Show GHCup.Errors.MalformedHeaders
+ GHCup.Errors: instance GHC.Show.Show GHCup.Errors.NoNetwork
+ GHCup.Errors: instance GHC.Show.Show GHCup.Errors.NoUrlBase
+ GHCup.Errors: instance Text.PrettyPrint.HughesPJClass.Pretty Data.Text.Internal.Text
+ GHCup.Errors: instance Text.PrettyPrint.HughesPJClass.Pretty GHCup.Errors.DirNotEmpty
+ GHCup.Errors: instance Text.PrettyPrint.HughesPJClass.Pretty GHCup.Errors.FileAlreadyExistsError
+ GHCup.Errors: instance Text.PrettyPrint.HughesPJClass.Pretty GHCup.Errors.GPGError
+ GHCup.Errors: instance Text.PrettyPrint.HughesPJClass.Pretty GHCup.Errors.HTTPNotModified
+ GHCup.Errors: instance Text.PrettyPrint.HughesPJClass.Pretty GHCup.Errors.HadrianNotFound
+ GHCup.Errors: instance Text.PrettyPrint.HughesPJClass.Pretty GHCup.Errors.MalformedHeaders
+ GHCup.Errors: instance Text.PrettyPrint.HughesPJClass.Pretty GHCup.Errors.NoNetwork
+ GHCup.Errors: instance Text.PrettyPrint.HughesPJClass.Pretty GHCup.Errors.NoUrlBase
+ GHCup.Types: Debug :: LogLevel
+ GHCup.Types: Error :: LogLevel
+ GHCup.Types: GPGLax :: GPGSetting
+ GHCup.Types: GPGNone :: GPGSetting
+ GHCup.Types: GPGStrict :: GPGSetting
+ GHCup.Types: GitBranch :: String -> Maybe String -> GitBranch
+ GHCup.Types: Info :: LogLevel
+ GHCup.Types: KBS :: Key
+ GHCup.Types: KBackTab :: Key
+ GHCup.Types: KBegin :: Key
+ GHCup.Types: KCenter :: Key
+ GHCup.Types: KChar :: Char -> Key
+ GHCup.Types: KDel :: Key
+ GHCup.Types: KDown :: Key
+ GHCup.Types: KDownLeft :: Key
+ GHCup.Types: KDownRight :: Key
+ GHCup.Types: KEnd :: Key
+ GHCup.Types: KEnter :: Key
+ GHCup.Types: KEsc :: Key
+ GHCup.Types: KFun :: Int -> Key
+ GHCup.Types: KHome :: Key
+ GHCup.Types: KIns :: Key
+ GHCup.Types: KLeft :: Key
+ GHCup.Types: KMenu :: Key
+ GHCup.Types: KPageDown :: Key
+ GHCup.Types: KPageUp :: Key
+ GHCup.Types: KPause :: Key
+ GHCup.Types: KPrtScr :: Key
+ GHCup.Types: KRight :: Key
+ GHCup.Types: KUp :: Key
+ GHCup.Types: KUpLeft :: Key
+ GHCup.Types: KUpRight :: Key
+ GHCup.Types: LeanAppState :: Settings -> Dirs -> KeyBindings -> LoggerConfig -> LeanAppState
+ GHCup.Types: LoggerConfig :: Bool -> (Text -> IO ()) -> (Text -> IO ()) -> Bool -> LoggerConfig
+ GHCup.Types: ShimGen :: GlobalTool
+ GHCup.Types: Stack :: Tool
+ GHCup.Types: Warn :: LogLevel
+ GHCup.Types: Windows :: Platform
+ GHCup.Types: [$sel:_distroPKGs:Requirements] :: Requirements -> [Text]
+ GHCup.Types: [$sel:_distroVersion:PlatformResult] :: PlatformResult -> Maybe Versioning
+ GHCup.Types: [$sel:_dlHash:DownloadInfo] :: DownloadInfo -> Text
+ GHCup.Types: [$sel:_dlSubdir:DownloadInfo] :: DownloadInfo -> Maybe TarDir
+ GHCup.Types: [$sel:_dlUri:DownloadInfo] :: DownloadInfo -> URI
+ GHCup.Types: [$sel:_ghcupDownloads:GHCupInfo] :: GHCupInfo -> GHCupDownloads
+ GHCup.Types: [$sel:_globalTools:GHCupInfo] :: GHCupInfo -> Map GlobalTool DownloadInfo
+ GHCup.Types: [$sel:_notes:Requirements] :: Requirements -> Text
+ GHCup.Types: [$sel:_platform:PlatformResult] :: PlatformResult -> Platform
+ GHCup.Types: [$sel:_rArch:PlatformRequest] :: PlatformRequest -> Architecture
+ GHCup.Types: [$sel:_rPlatform:PlatformRequest] :: PlatformRequest -> Platform
+ GHCup.Types: [$sel:_rVersion:PlatformRequest] :: PlatformRequest -> Maybe Versioning
+ GHCup.Types: [$sel:_toolRequirements:GHCupInfo] :: GHCupInfo -> ToolRequirements
+ GHCup.Types: [$sel:_tvTarget:GHCTargetVersion] :: GHCTargetVersion -> Maybe Text
+ GHCup.Types: [$sel:_tvVersion:GHCTargetVersion] :: GHCTargetVersion -> Version
+ GHCup.Types: [$sel:_viArch:VersionInfo] :: VersionInfo -> ArchitectureSpec
+ GHCup.Types: [$sel:_viChangeLog:VersionInfo] :: VersionInfo -> Maybe URI
+ GHCup.Types: [$sel:_viPostInstall:VersionInfo] :: VersionInfo -> Maybe Text
+ GHCup.Types: [$sel:_viPostRemove:VersionInfo] :: VersionInfo -> Maybe Text
+ GHCup.Types: [$sel:_viPreCompile:VersionInfo] :: VersionInfo -> Maybe Text
+ GHCup.Types: [$sel:_viSourceDL:VersionInfo] :: VersionInfo -> Maybe DownloadInfo
+ GHCup.Types: [$sel:_viTags:VersionInfo] :: VersionInfo -> [Tag]
+ GHCup.Types: [$sel:bChangelog:KeyBindings] :: KeyBindings -> Key
+ GHCup.Types: [$sel:bDown:KeyBindings] :: KeyBindings -> Key
+ GHCup.Types: [$sel:bInstall:KeyBindings] :: KeyBindings -> Key
+ GHCup.Types: [$sel:bQuit:KeyBindings] :: KeyBindings -> Key
+ GHCup.Types: [$sel:bSet:KeyBindings] :: KeyBindings -> Key
+ GHCup.Types: [$sel:bShowAllTools:KeyBindings] :: KeyBindings -> Key
+ GHCup.Types: [$sel:bShowAllVersions:KeyBindings] :: KeyBindings -> Key
+ GHCup.Types: [$sel:bUninstall:KeyBindings] :: KeyBindings -> Key
+ GHCup.Types: [$sel:bUp:KeyBindings] :: KeyBindings -> Key
+ GHCup.Types: [$sel:baseDir:Dirs] :: Dirs -> FilePath
+ GHCup.Types: [$sel:binDir:Dirs] :: Dirs -> FilePath
+ GHCup.Types: [$sel:cache:Settings] :: Settings -> Bool
+ GHCup.Types: [$sel:cacheDir:Dirs] :: Dirs -> FilePath
+ GHCup.Types: [$sel:confDir:Dirs] :: Dirs -> FilePath
+ GHCup.Types: [$sel:consoleOutter:LoggerConfig] :: LoggerConfig -> Text -> IO ()
+ GHCup.Types: [$sel:diArch:DebugInfo] :: DebugInfo -> Architecture
+ GHCup.Types: [$sel:diBaseDir:DebugInfo] :: DebugInfo -> FilePath
+ GHCup.Types: [$sel:diBinDir:DebugInfo] :: DebugInfo -> FilePath
+ GHCup.Types: [$sel:diCacheDir:DebugInfo] :: DebugInfo -> FilePath
+ GHCup.Types: [$sel:diGHCDir:DebugInfo] :: DebugInfo -> FilePath
+ GHCup.Types: [$sel:diPlatform:DebugInfo] :: DebugInfo -> PlatformResult
+ GHCup.Types: [$sel:dirs:AppState] :: AppState -> Dirs
+ GHCup.Types: [$sel:dirs:LeanAppState] :: LeanAppState -> Dirs
+ GHCup.Types: [$sel:downloader:Settings] :: Settings -> Downloader
+ GHCup.Types: [$sel:fancyColors:LoggerConfig] :: LoggerConfig -> Bool
+ GHCup.Types: [$sel:fileOutter:LoggerConfig] :: LoggerConfig -> Text -> IO ()
+ GHCup.Types: [$sel:ghcupInfo:AppState] :: AppState -> GHCupInfo
+ GHCup.Types: [$sel:gpgSetting:Settings] :: Settings -> GPGSetting
+ GHCup.Types: [$sel:kChangelog:UserKeyBindings] :: UserKeyBindings -> Maybe Key
+ GHCup.Types: [$sel:kDown:UserKeyBindings] :: UserKeyBindings -> Maybe Key
+ GHCup.Types: [$sel:kInstall:UserKeyBindings] :: UserKeyBindings -> Maybe Key
+ GHCup.Types: [$sel:kQuit:UserKeyBindings] :: UserKeyBindings -> Maybe Key
+ GHCup.Types: [$sel:kSet:UserKeyBindings] :: UserKeyBindings -> Maybe Key
+ GHCup.Types: [$sel:kShowAll:UserKeyBindings] :: UserKeyBindings -> Maybe Key
+ GHCup.Types: [$sel:kShowAllTools:UserKeyBindings] :: UserKeyBindings -> Maybe Key
+ GHCup.Types: [$sel:kUninstall:UserKeyBindings] :: UserKeyBindings -> Maybe Key
+ GHCup.Types: [$sel:kUp:UserKeyBindings] :: UserKeyBindings -> Maybe Key
+ GHCup.Types: [$sel:keepDirs:Settings] :: Settings -> KeepDirs
+ GHCup.Types: [$sel:keyBindings:AppState] :: AppState -> KeyBindings
+ GHCup.Types: [$sel:keyBindings:LeanAppState] :: LeanAppState -> KeyBindings
+ GHCup.Types: [$sel:lcPrintDebug:LoggerConfig] :: LoggerConfig -> Bool
+ GHCup.Types: [$sel:loggerConfig:AppState] :: AppState -> LoggerConfig
+ GHCup.Types: [$sel:loggerConfig:LeanAppState] :: LeanAppState -> LoggerConfig
+ GHCup.Types: [$sel:logsDir:Dirs] :: Dirs -> FilePath
+ GHCup.Types: [$sel:noColor:Settings] :: Settings -> Bool
+ GHCup.Types: [$sel:noNetwork:Settings] :: Settings -> Bool
+ GHCup.Types: [$sel:noVerify:Settings] :: Settings -> Bool
+ GHCup.Types: [$sel:pfreq:AppState] :: AppState -> PlatformRequest
+ GHCup.Types: [$sel:recycleDir:Dirs] :: Dirs -> FilePath
+ GHCup.Types: [$sel:ref:GitBranch] :: GitBranch -> String
+ GHCup.Types: [$sel:repo:GitBranch] :: GitBranch -> Maybe String
+ GHCup.Types: [$sel:settings:AppState] :: AppState -> Settings
+ GHCup.Types: [$sel:settings:LeanAppState] :: LeanAppState -> Settings
+ GHCup.Types: [$sel:uCache:UserSettings] :: UserSettings -> Maybe Bool
+ GHCup.Types: [$sel:uDownloader:UserSettings] :: UserSettings -> Maybe Downloader
+ GHCup.Types: [$sel:uGPGSetting:UserSettings] :: UserSettings -> Maybe GPGSetting
+ GHCup.Types: [$sel:uKeepDirs:UserSettings] :: UserSettings -> Maybe KeepDirs
+ GHCup.Types: [$sel:uKeyBindings:UserSettings] :: UserSettings -> Maybe UserKeyBindings
+ GHCup.Types: [$sel:uNoNetwork:UserSettings] :: UserSettings -> Maybe Bool
+ GHCup.Types: [$sel:uNoVerify:UserSettings] :: UserSettings -> Maybe Bool
+ GHCup.Types: [$sel:uUrlSource:UserSettings] :: UserSettings -> Maybe URLSource
+ GHCup.Types: [$sel:uVerbose:UserSettings] :: UserSettings -> Maybe Bool
+ GHCup.Types: [$sel:urlSource:Settings] :: Settings -> URLSource
+ GHCup.Types: [$sel:verbose:Settings] :: Settings -> Bool
+ GHCup.Types: data GPGSetting
+ GHCup.Types: data GitBranch
+ GHCup.Types: data GlobalTool
+ GHCup.Types: data Key
+ GHCup.Types: data LeanAppState
+ GHCup.Types: data LogLevel
+ GHCup.Types: data LoggerConfig
+ GHCup.Types: fromSettings :: Settings -> Maybe KeyBindings -> UserSettings
+ GHCup.Types: instance Control.DeepSeq.NFData (URI.ByteString.Types.URIRef URI.ByteString.Types.Absolute)
+ GHCup.Types: instance Control.DeepSeq.NFData GHCup.Types.AppState
+ GHCup.Types: instance Control.DeepSeq.NFData GHCup.Types.Architecture
+ GHCup.Types: instance Control.DeepSeq.NFData GHCup.Types.Dirs
+ GHCup.Types: instance Control.DeepSeq.NFData GHCup.Types.DownloadInfo
+ GHCup.Types: instance Control.DeepSeq.NFData GHCup.Types.Downloader
+ GHCup.Types: instance Control.DeepSeq.NFData GHCup.Types.GHCupInfo
+ GHCup.Types: instance Control.DeepSeq.NFData GHCup.Types.GPGSetting
+ GHCup.Types: instance Control.DeepSeq.NFData GHCup.Types.GlobalTool
+ GHCup.Types: instance Control.DeepSeq.NFData GHCup.Types.KeepDirs
+ GHCup.Types: instance Control.DeepSeq.NFData GHCup.Types.Key
+ GHCup.Types: instance Control.DeepSeq.NFData GHCup.Types.KeyBindings
+ GHCup.Types: instance Control.DeepSeq.NFData GHCup.Types.LeanAppState
+ GHCup.Types: instance Control.DeepSeq.NFData GHCup.Types.LinuxDistro
+ GHCup.Types: instance Control.DeepSeq.NFData GHCup.Types.LoggerConfig
+ GHCup.Types: instance Control.DeepSeq.NFData GHCup.Types.Platform
+ GHCup.Types: instance Control.DeepSeq.NFData GHCup.Types.PlatformRequest
+ GHCup.Types: instance Control.DeepSeq.NFData GHCup.Types.PlatformResult
+ GHCup.Types: instance Control.DeepSeq.NFData GHCup.Types.Requirements
+ GHCup.Types: instance Control.DeepSeq.NFData GHCup.Types.Settings
+ GHCup.Types: instance Control.DeepSeq.NFData GHCup.Types.Tag
+ GHCup.Types: instance Control.DeepSeq.NFData GHCup.Types.TarDir
+ GHCup.Types: instance Control.DeepSeq.NFData GHCup.Types.Tool
+ GHCup.Types: instance Control.DeepSeq.NFData GHCup.Types.URLSource
+ GHCup.Types: instance Control.DeepSeq.NFData GHCup.Types.VersionCmp
+ GHCup.Types: instance Control.DeepSeq.NFData GHCup.Types.VersionInfo
+ GHCup.Types: instance Control.DeepSeq.NFData GHCup.Types.VersionRange
+ GHCup.Types: instance GHC.Classes.Eq GHCup.Types.GPGSetting
+ GHCup.Types: instance GHC.Classes.Eq GHCup.Types.GitBranch
+ GHCup.Types: instance GHC.Classes.Eq GHCup.Types.GlobalTool
+ GHCup.Types: instance GHC.Classes.Eq GHCup.Types.Key
+ GHCup.Types: instance GHC.Classes.Eq GHCup.Types.LogLevel
+ GHCup.Types: instance GHC.Classes.Ord GHCup.Types.GPGSetting
+ GHCup.Types: instance GHC.Classes.Ord GHCup.Types.GitBranch
+ GHCup.Types: instance GHC.Classes.Ord GHCup.Types.GlobalTool
+ GHCup.Types: instance GHC.Classes.Ord GHCup.Types.Key
+ GHCup.Types: instance GHC.Classes.Ord GHCup.Types.LogLevel
+ GHCup.Types: instance GHC.Enum.Bounded GHCup.Types.GlobalTool
+ GHCup.Types: instance GHC.Enum.Enum GHCup.Types.GlobalTool
+ GHCup.Types: instance GHC.Generics.Generic GHCup.Types.AppState
+ GHCup.Types: instance GHC.Generics.Generic GHCup.Types.Dirs
+ GHCup.Types: instance GHC.Generics.Generic GHCup.Types.Downloader
+ GHCup.Types: instance GHC.Generics.Generic GHCup.Types.GPGSetting
+ GHCup.Types: instance GHC.Generics.Generic GHCup.Types.GlobalTool
+ GHCup.Types: instance GHC.Generics.Generic GHCup.Types.KeepDirs
+ GHCup.Types: instance GHC.Generics.Generic GHCup.Types.Key
+ GHCup.Types: instance GHC.Generics.Generic GHCup.Types.LeanAppState
+ GHCup.Types: instance GHC.Generics.Generic GHCup.Types.PlatformRequest
+ GHCup.Types: instance GHC.Generics.Generic GHCup.Types.PlatformResult
+ GHCup.Types: instance GHC.Read.Read GHCup.Types.Key
+ GHCup.Types: instance GHC.Show.Show (GHC.Types.IO ())
+ GHCup.Types: instance GHC.Show.Show (a -> b)
+ GHCup.Types: instance GHC.Show.Show GHCup.Types.GPGSetting
+ GHCup.Types: instance GHC.Show.Show GHCup.Types.GitBranch
+ GHCup.Types: instance GHC.Show.Show GHCup.Types.GlobalTool
+ GHCup.Types: instance GHC.Show.Show GHCup.Types.Key
+ GHCup.Types: instance GHC.Show.Show GHCup.Types.LeanAppState
+ GHCup.Types: instance GHC.Show.Show GHCup.Types.LogLevel
+ GHCup.Types: instance GHC.Show.Show GHCup.Types.LoggerConfig
+ GHCup.Types: instance Text.PrettyPrint.HughesPJClass.Pretty GHCup.Types.Tool
+ GHCup.Types.JSON: instance Data.Aeson.Types.FromJSON.FromJSON GHCup.Types.GPGSetting
+ GHCup.Types.JSON: instance Data.Aeson.Types.FromJSON.FromJSON GHCup.Types.GlobalTool
+ GHCup.Types.JSON: instance Data.Aeson.Types.FromJSON.FromJSON GHCup.Types.Key
+ GHCup.Types.JSON: instance Data.Aeson.Types.FromJSON.FromJSONKey GHCup.Types.GlobalTool
+ GHCup.Types.JSON: instance Data.Aeson.Types.ToJSON.ToJSON GHCup.Types.GPGSetting
+ GHCup.Types.JSON: instance Data.Aeson.Types.ToJSON.ToJSON GHCup.Types.GlobalTool
+ GHCup.Types.JSON: instance Data.Aeson.Types.ToJSON.ToJSON GHCup.Types.Key
+ GHCup.Types.JSON: instance Data.Aeson.Types.ToJSON.ToJSON GHCup.Types.KeyBindings
+ GHCup.Types.JSON: instance Data.Aeson.Types.ToJSON.ToJSON GHCup.Types.Settings
+ GHCup.Types.JSON: instance Data.Aeson.Types.ToJSON.ToJSONKey GHCup.Types.GlobalTool
+ GHCup.Types.Optics: _Stack :: Prism' Tool ()
+ GHCup.Types.Optics: _Windows :: Prism' Platform ()
+ GHCup.Types.Optics: getAppState :: MonadReader AppState m => m AppState
+ GHCup.Types.Optics: getCache :: (MonadReader env m, HasSettings env) => m Bool
+ GHCup.Types.Optics: getDirs :: (MonadReader env m, LabelOptic' "dirs" A_Lens env Dirs) => m Dirs
+ GHCup.Types.Optics: getDownloader :: (MonadReader env m, HasSettings env) => m Downloader
+ GHCup.Types.Optics: getGHCupInfo :: (MonadReader env m, LabelOptic' "ghcupInfo" A_Lens env GHCupInfo) => m GHCupInfo
+ GHCup.Types.Optics: getKeyBindings :: (MonadReader env m, LabelOptic' "keyBindings" A_Lens env KeyBindings) => m KeyBindings
+ GHCup.Types.Optics: getLeanAppState :: (MonadReader env m, LabelOptic' "settings" A_Lens env Settings, LabelOptic' "dirs" A_Lens env Dirs, LabelOptic' "keyBindings" A_Lens env KeyBindings, LabelOptic' "loggerConfig" A_Lens env LoggerConfig) => m LeanAppState
+ GHCup.Types.Optics: getLogCleanup :: (MonadReader env m, LabelOptic' "logCleanup" A_Lens env (IO ())) => m (IO ())
+ GHCup.Types.Optics: getPlatformReq :: (MonadReader env m, LabelOptic' "pfreq" A_Lens env PlatformRequest) => m PlatformRequest
+ GHCup.Types.Optics: getSettings :: (MonadReader env m, LabelOptic' "settings" A_Lens env Settings) => m Settings
+ GHCup.Types.Optics: gets :: forall f a env m. (MonadReader env m, LabelOptic' f A_Lens env a) => m a
+ GHCup.Types.Optics: globalTools :: Lens' GHCupInfo (Map GlobalTool DownloadInfo)
+ GHCup.Types.Optics: instance Optics.Label.LabelOptic "dirs" Optics.Internal.Optic.Types.A_Lens GHCup.Types.Dirs GHCup.Types.Dirs GHCup.Types.Dirs GHCup.Types.Dirs
+ GHCup.Types.Optics: type HasDirs env = (LabelOptic' "dirs" A_Lens env Dirs)
+ GHCup.Types.Optics: type HasGHCupInfo env = (LabelOptic' "ghcupInfo" A_Lens env GHCupInfo)
+ GHCup.Types.Optics: type HasKeyBindings env = (LabelOptic' "keyBindings" A_Lens env KeyBindings)
+ GHCup.Types.Optics: type HasLog env = (LabelOptic' "loggerConfig" A_Lens env LoggerConfig)
+ GHCup.Types.Optics: type HasPlatformReq env = (LabelOptic' "pfreq" A_Lens env PlatformRequest)
+ GHCup.Types.Optics: type HasSettings env = (LabelOptic' "settings" A_Lens env Settings)
+ GHCup.Utils: createLink :: (MonadMask m, MonadThrow m, HasLog env, MonadIO m, MonadReader env m, HasDirs env, MonadUnliftIO m, MonadFail m) => FilePath -> FilePath -> m ()
+ GHCup.Utils: enableAnsiSupport :: IO (Either String Bool)
+ GHCup.Utils: ensureDirectories :: Dirs -> IO ()
+ GHCup.Utils: ensureGlobalTools :: (MonadMask m, MonadThrow m, HasLog env, MonadIO m, MonadReader env m, HasDirs env, HasSettings env, HasGHCupInfo env, MonadUnliftIO m, MonadFail m) => Excepts '[GPGError, DigestError, DownloadFailed, NoDownload] m ()
+ GHCup.Utils: exeExt :: String
+ GHCup.Utils: exeExt' :: ByteString
+ GHCup.Utils: getGHCForPVP :: (MonadReader env m, HasDirs env, MonadIO m, MonadThrow m) => PVP -> Maybe Text -> m (Maybe GHCTargetVersion)
+ GHCup.Utils: getGHCForPVP' :: MonadThrow m => PVP -> [(PVP, Maybe Text)] -> Maybe Text -> m (Maybe GHCTargetVersion)
+ GHCup.Utils: getInstalledStacks :: (MonadReader env m, HasDirs env, MonadIO m, MonadCatch m) => m [Either FilePath Version]
+ GHCup.Utils: getLatestToolFor :: MonadThrow m => Tool -> PVP -> GHCupDownloads -> m (Maybe (PVP, VersionInfo))
+ GHCup.Utils: getLinkTarget :: FilePath -> IO FilePath
+ GHCup.Utils: ghcBinaryName :: GHCTargetVersion -> String
+ GHCup.Utils: hlsGHCVersions' :: (MonadReader env m, HasDirs env, MonadIO m, MonadThrow m, MonadCatch m) => Version -> m [Version]
+ GHCup.Utils: makeOut :: (MonadReader env m, HasDirs env, MonadIO m) => [String] -> Maybe FilePath -> m CapturedProcess
+ GHCup.Utils: matchPVPrefix :: PVP -> PVP -> Bool
+ GHCup.Utils: pathIsLink :: FilePath -> IO Bool
+ GHCup.Utils: rmBDir :: (MonadReader env m, HasLog env, MonadUnliftIO m, MonadIO m) => FilePath -> m ()
+ GHCup.Utils: rmLink :: (MonadReader env m, HasDirs env, MonadIO m, MonadMask m) => FilePath -> m ()
+ GHCup.Utils: stackInstalled :: (MonadIO m, MonadReader env m, HasDirs env, MonadCatch m) => Version -> m Bool
+ GHCup.Utils: stackSet :: (MonadReader env m, HasDirs env, MonadIO m, MonadThrow m, MonadCatch m, HasLog env) => m (Maybe Version)
+ GHCup.Utils: toL :: PVP -> [Int]
+ GHCup.Utils.Dirs: cleanupTrash :: (MonadIO m, MonadMask m, MonadReader env m, HasLog env, HasDirs env, HasSettings env) => m ()
+ GHCup.Utils.Dirs: getAllDirs :: IO Dirs
+ GHCup.Utils.Dirs: getConfigFilePath :: MonadIO m => m FilePath
+ GHCup.Utils.Dirs: ghcupBaseDir :: IO FilePath
+ GHCup.Utils.Dirs: ghcupCacheDir :: IO FilePath
+ GHCup.Utils.Dirs: useXDG :: IO Bool
+ GHCup.Utils.File: newFilePerms :: FileMode
+ GHCup.Utils.File.Common: CapturedProcess :: ExitCode -> ByteString -> ByteString -> CapturedProcess
+ GHCup.Utils.File.Common: NoSuchPid :: FilePath -> [String] -> ProcessError
+ GHCup.Utils.File.Common: NonZeroExit :: Int -> FilePath -> [String] -> ProcessError
+ GHCup.Utils.File.Common: PStopped :: FilePath -> [String] -> ProcessError
+ GHCup.Utils.File.Common: PTerminated :: FilePath -> [String] -> ProcessError
+ GHCup.Utils.File.Common: [_exitCode] :: CapturedProcess -> ExitCode
+ GHCup.Utils.File.Common: [_stdErr] :: CapturedProcess -> ByteString
+ GHCup.Utils.File.Common: [_stdOut] :: CapturedProcess -> ByteString
+ GHCup.Utils.File.Common: checkFileAlreadyExists :: MonadIO m => FilePath -> m Bool
+ GHCup.Utils.File.Common: data CapturedProcess
+ GHCup.Utils.File.Common: data ProcessError
+ GHCup.Utils.File.Common: exitCode :: Lens' CapturedProcess ExitCode
+ GHCup.Utils.File.Common: findFiles :: FilePath -> Regex -> IO [FilePath]
+ GHCup.Utils.File.Common: findFiles' :: FilePath -> Parsec Void Text a -> IO [FilePath]
+ GHCup.Utils.File.Common: findFilesDeep :: FilePath -> Regex -> IO [FilePath]
+ GHCup.Utils.File.Common: instance GHC.Classes.Eq GHCup.Utils.File.Common.CapturedProcess
+ GHCup.Utils.File.Common: instance GHC.Show.Show GHCup.Utils.File.Common.CapturedProcess
+ GHCup.Utils.File.Common: instance GHC.Show.Show GHCup.Utils.File.Common.ProcessError
+ GHCup.Utils.File.Common: instance Text.PrettyPrint.HughesPJClass.Pretty GHCup.Utils.File.Common.ProcessError
+ GHCup.Utils.File.Common: isInPath :: FilePath -> IO Bool
+ GHCup.Utils.File.Common: isShadowed :: FilePath -> IO (Maybe FilePath)
+ GHCup.Utils.File.Common: searchPath :: [FilePath] -> FilePath -> IO (Maybe FilePath)
+ GHCup.Utils.File.Common: stdErr :: Lens' CapturedProcess ByteString
+ GHCup.Utils.File.Common: stdOut :: Lens' CapturedProcess ByteString
+ GHCup.Utils.Logger: logDebug :: (MonadReader env m, LabelOptic' "loggerConfig" A_Lens env LoggerConfig, MonadIO m) => Text -> m ()
+ GHCup.Utils.Logger: logError :: (MonadReader env m, LabelOptic' "loggerConfig" A_Lens env LoggerConfig, MonadIO m) => Text -> m ()
+ GHCup.Utils.Logger: logInfo :: (MonadReader env m, LabelOptic' "loggerConfig" A_Lens env LoggerConfig, MonadIO m) => Text -> m ()
+ GHCup.Utils.Logger: logInternal :: (MonadReader env m, LabelOptic' "loggerConfig" A_Lens env LoggerConfig, MonadIO m) => LogLevel -> Text -> m ()
+ GHCup.Utils.Logger: logWarn :: (MonadReader env m, LabelOptic' "loggerConfig" A_Lens env LoggerConfig, MonadIO m) => Text -> m ()
+ GHCup.Utils.MegaParsec: ghcProjectVersion :: Parsec Void Text Version
+ GHCup.Utils.MegaParsec: pathSep :: Parsec Void Text Char
+ GHCup.Utils.Prelude: breakOn :: Eq a => [a] -> [a] -> ([a], [a])
+ GHCup.Utils.Prelude: catchWarn :: forall es m env. (Pretty (V es), MonadReader env m, HasLog env, MonadIO m, Monad m) => Excepts es m () -> Excepts '[] m ()
+ GHCup.Utils.Prelude: copyDirectoryRecursive :: FilePath -> FilePath -> (FilePath -> FilePath -> IO ()) -> IO ()
+ GHCup.Utils.Prelude: copyFileE :: (CopyError :< xs, MonadCatch m, MonadIO m) => FilePath -> FilePath -> Excepts xs m ()
+ GHCup.Utils.Prelude: createDirRecursive' :: FilePath -> IO ()
+ GHCup.Utils.Prelude: dropPrefix :: Eq a => [a] -> [a] -> [a]
+ GHCup.Utils.Prelude: dropSuffix :: Eq a => [a] -> [a] -> [a]
+ GHCup.Utils.Prelude: findM :: Monad m => (a -> m Bool) -> [a] -> m (Maybe a)
+ GHCup.Utils.Prelude: forFold :: (Foldable t, Applicative m, Monoid b) => t a -> (a -> m b) -> m b
+ GHCup.Utils.Prelude: getDirectoryContentsRecursive :: FilePath -> IO [FilePath]
+ GHCup.Utils.Prelude: isNewLine :: Word8 -> Bool
+ GHCup.Utils.Prelude: pvpFromList :: [Int] -> PVP
+ GHCup.Utils.Prelude: recycleFile :: (MonadIO m, MonadMask m, MonadReader env m, HasDirs env) => FilePath -> m ()
+ GHCup.Utils.Prelude: recyclePathForcibly :: (MonadIO m, MonadReader env m, HasDirs env, MonadMask m) => FilePath -> m ()
+ GHCup.Utils.Prelude: rmDirectory :: (MonadIO m, MonadMask m) => FilePath -> m ()
+ GHCup.Utils.Prelude: rmDirectoryLink :: (MonadIO m, MonadMask m, MonadReader env m, HasDirs env) => FilePath -> m ()
+ GHCup.Utils.Prelude: rmFile :: (MonadIO m, MonadMask m) => FilePath -> m ()
+ GHCup.Utils.Prelude: rmPathForcibly :: (MonadIO m, MonadMask m) => FilePath -> m ()
+ GHCup.Utils.Prelude: split :: (a -> Bool) -> [a] -> [[a]]
+ GHCup.Utils.Prelude: splitOn :: Eq a => [a] -> [a] -> [[a]]
+ GHCup.Utils.Prelude: splitOnPVP :: String -> String -> (String, String)
+ GHCup.Utils.Prelude: stripNewline :: String -> String
+ GHCup.Utils.Prelude: stripNewline' :: Text -> Text
+ GHCup.Utils.Prelude: stripNewlineEnd :: String -> String
+ GHCup.Utils.Prelude: stripSuffix :: Eq a => [a] -> [a] -> Maybe [a]
+ GHCup.Utils.Prelude: traverseFold :: (Foldable t, Applicative m, Monoid b) => (a -> m b) -> t a -> m b
+ GHCup.Utils.Prelude: verToS :: Version -> String
+ GHCup.Utils.Prelude: versionToPVP :: MonadThrow m => Version -> m PVP
- GHCup: availableToolVersions :: GHCupDownloads -> Tool -> Map Version [Tag]
+ GHCup: availableToolVersions :: GHCupDownloads -> Tool -> Map Version VersionInfo
- GHCup: compileGHC :: (MonadMask m, MonadReader AppState m, MonadThrow m, MonadResource m, MonadLogger m, MonadIO m, MonadFail m) => GHCupDownloads -> GHCTargetVersion -> Either Version (Path Abs) -> Maybe Int -> Maybe (Path Abs) -> Maybe (Path Abs) -> [Text] -> PlatformRequest -> Excepts '[AlreadyInstalled, BuildFailed, DigestError, DownloadFailed, GHCupSetError, NoDownload, NotFoundInPATH, PatchFailed, UnknownArchive, TarDirDoesNotExist, NotInstalled, ArchiveResult] m ()
+ GHCup: compileGHC :: (MonadMask m, MonadReader env m, HasDirs env, HasPlatformReq env, HasGHCupInfo env, HasSettings env, MonadThrow m, MonadResource m, HasLog env, MonadIO m, MonadUnliftIO m, MonadFail m) => Either GHCTargetVersion GitBranch -> Maybe Version -> Either Version FilePath -> Maybe Int -> Maybe FilePath -> Maybe FilePath -> [Text] -> Maybe String -> Bool -> Maybe FilePath -> Excepts '[AlreadyInstalled, BuildFailed, DigestError, GPGError, DownloadFailed, GHCupSetError, NoDownload, NotFoundInPATH, PatchFailed, UnknownArchive, TarDirDoesNotExist, NotInstalled, DirNotEmpty, ArchiveResult] m GHCTargetVersion
- GHCup: getDebugInfo :: (MonadReader AppState m, MonadLogger m, MonadCatch m, MonadIO m) => Excepts '[NoCompatiblePlatform, NoCompatibleArch, DistroNotFound] m DebugInfo
+ GHCup: getDebugInfo :: (Alternative m, MonadFail m, MonadReader env m, HasDirs env, HasLog env, MonadCatch m, MonadIO m) => Excepts '[NoCompatiblePlatform, NoCompatibleArch, DistroNotFound] m DebugInfo
- GHCup: installCabalBin :: (MonadMask m, MonadCatch m, MonadReader AppState m, MonadLogger m, MonadResource m, MonadIO m, MonadFail m) => GHCupDownloads -> Version -> PlatformRequest -> Excepts '[AlreadyInstalled, CopyError, DigestError, DownloadFailed, NoDownload, NotInstalled, UnknownArchive, TarDirDoesNotExist, ArchiveResult] m ()
+ GHCup: installCabalBin :: (MonadMask m, MonadCatch m, MonadReader env m, HasPlatformReq env, HasGHCupInfo env, HasDirs env, HasSettings env, HasLog env, MonadResource m, MonadIO m, MonadUnliftIO m, MonadFail m) => Version -> Maybe FilePath -> Bool -> Excepts '[AlreadyInstalled, CopyError, DigestError, GPGError, DownloadFailed, NoDownload, NotInstalled, UnknownArchive, TarDirDoesNotExist, ArchiveResult, FileAlreadyExistsError] m ()
- GHCup: installCabalBindist :: (MonadMask m, MonadCatch m, MonadReader AppState m, MonadLogger m, MonadResource m, MonadIO m, MonadFail m) => DownloadInfo -> Version -> PlatformRequest -> Excepts '[AlreadyInstalled, CopyError, DigestError, DownloadFailed, NoDownload, NotInstalled, UnknownArchive, TarDirDoesNotExist, ArchiveResult] m ()
+ GHCup: installCabalBindist :: (MonadMask m, MonadCatch m, MonadReader env m, HasPlatformReq env, HasDirs env, HasSettings env, HasLog env, MonadResource m, MonadIO m, MonadUnliftIO m, MonadFail m) => DownloadInfo -> Version -> Maybe FilePath -> Bool -> Excepts '[AlreadyInstalled, CopyError, DigestError, GPGError, DownloadFailed, NoDownload, NotInstalled, UnknownArchive, TarDirDoesNotExist, ArchiveResult, FileAlreadyExistsError] m ()
- GHCup: installGHCBin :: (MonadFail m, MonadMask m, MonadCatch m, MonadReader AppState m, MonadLogger m, MonadResource m, MonadIO m) => GHCupDownloads -> Version -> PlatformRequest -> Excepts '[AlreadyInstalled, BuildFailed, DigestError, DownloadFailed, NoDownload, NotInstalled, UnknownArchive, TarDirDoesNotExist, ArchiveResult] m ()
+ GHCup: installGHCBin :: (MonadFail m, MonadMask m, MonadCatch m, MonadReader env m, HasPlatformReq env, HasGHCupInfo env, HasDirs env, HasSettings env, HasLog env, MonadResource m, MonadIO m, MonadUnliftIO m) => Version -> Maybe FilePath -> Bool -> Excepts '[AlreadyInstalled, BuildFailed, DigestError, GPGError, DownloadFailed, NoDownload, NotInstalled, UnknownArchive, TarDirDoesNotExist, DirNotEmpty, ArchiveResult] m ()
- GHCup: installGHCBindist :: (MonadFail m, MonadMask m, MonadCatch m, MonadReader AppState m, MonadLogger m, MonadResource m, MonadIO m) => DownloadInfo -> Version -> PlatformRequest -> Excepts '[AlreadyInstalled, BuildFailed, DigestError, DownloadFailed, NoDownload, NotInstalled, UnknownArchive, TarDirDoesNotExist, ArchiveResult] m ()
+ GHCup: installGHCBindist :: (MonadFail m, MonadMask m, MonadCatch m, MonadReader env m, HasDirs env, HasSettings env, HasPlatformReq env, HasLog env, MonadResource m, MonadIO m, MonadUnliftIO m) => DownloadInfo -> Version -> Maybe FilePath -> Bool -> Excepts '[AlreadyInstalled, BuildFailed, DigestError, GPGError, DownloadFailed, NoDownload, NotInstalled, UnknownArchive, TarDirDoesNotExist, DirNotEmpty, ArchiveResult] m ()
- GHCup: installHLSBin :: (MonadMask m, MonadCatch m, MonadReader AppState m, MonadLogger m, MonadResource m, MonadIO m, MonadFail m) => GHCupDownloads -> Version -> PlatformRequest -> Excepts '[AlreadyInstalled, CopyError, DigestError, DownloadFailed, NoDownload, NotInstalled, UnknownArchive, TarDirDoesNotExist, ArchiveResult] m ()
+ GHCup: installHLSBin :: (MonadMask m, MonadCatch m, MonadReader env m, HasPlatformReq env, HasGHCupInfo env, HasDirs env, HasSettings env, HasLog env, MonadResource m, MonadIO m, MonadUnliftIO m, MonadFail m) => Version -> Maybe FilePath -> Bool -> Excepts '[AlreadyInstalled, CopyError, DigestError, GPGError, DownloadFailed, NoDownload, NotInstalled, UnknownArchive, TarDirDoesNotExist, ArchiveResult, FileAlreadyExistsError] m ()
- GHCup: installHLSBindist :: (MonadMask m, MonadCatch m, MonadReader AppState m, MonadLogger m, MonadResource m, MonadIO m, MonadFail m) => DownloadInfo -> Version -> PlatformRequest -> Excepts '[AlreadyInstalled, CopyError, DigestError, DownloadFailed, NoDownload, NotInstalled, UnknownArchive, TarDirDoesNotExist, ArchiveResult] m ()
+ GHCup: installHLSBindist :: (MonadMask m, MonadCatch m, MonadReader env m, HasPlatformReq env, HasDirs env, HasSettings env, HasLog env, MonadResource m, MonadIO m, MonadUnliftIO m, MonadFail m) => DownloadInfo -> Version -> Maybe FilePath -> Bool -> Excepts '[AlreadyInstalled, CopyError, DigestError, GPGError, DownloadFailed, NoDownload, NotInstalled, UnknownArchive, TarDirDoesNotExist, ArchiveResult, FileAlreadyExistsError] m ()
- GHCup: installPackedGHC :: (MonadMask m, MonadCatch m, MonadReader AppState m, MonadThrow m, MonadLogger m, MonadIO m) => Path Abs -> Maybe TarDir -> Path Abs -> Version -> PlatformRequest -> Excepts '[BuildFailed, UnknownArchive, TarDirDoesNotExist, ArchiveResult] m ()
+ GHCup: installPackedGHC :: (MonadMask m, MonadCatch m, MonadReader env m, HasDirs env, HasPlatformReq env, HasSettings env, MonadThrow m, HasLog env, MonadIO m, MonadUnliftIO m, MonadFail m) => FilePath -> Maybe TarDir -> FilePath -> Version -> Bool -> Excepts '[BuildFailed, UnknownArchive, TarDirDoesNotExist, DirNotEmpty, ArchiveResult] m ()
- GHCup: installUnpackedGHC :: (MonadReader AppState m, MonadThrow m, MonadLogger m, MonadIO m) => Path Abs -> Path Abs -> Version -> PlatformRequest -> Excepts '[ProcessError] m ()
+ GHCup: installUnpackedGHC :: (MonadReader env m, HasPlatformReq env, HasDirs env, HasSettings env, MonadThrow m, HasLog env, MonadIO m, MonadUnliftIO m, MonadMask m) => FilePath -> FilePath -> Version -> Excepts '[ProcessError] m ()
- GHCup: listVersions :: (MonadCatch m, MonadLogger m, MonadThrow m, MonadLogger m, MonadIO m, MonadReader AppState m) => GHCupDownloads -> Maybe Tool -> Maybe ListCriteria -> PlatformRequest -> m [ListResult]
+ GHCup: listVersions :: (MonadCatch m, HasLog env, MonadThrow m, HasLog env, MonadIO m, MonadReader env m, HasDirs env, HasPlatformReq env, HasGHCupInfo env) => Maybe Tool -> Maybe ListCriteria -> m [ListResult]
- GHCup: postGHCInstall :: (MonadReader AppState m, MonadLogger m, MonadThrow m, MonadFail m, MonadIO m, MonadCatch m) => GHCTargetVersion -> Excepts '[NotInstalled] m ()
+ GHCup: postGHCInstall :: (MonadReader env m, HasDirs env, HasLog env, MonadThrow m, MonadFail m, MonadIO m, MonadCatch m, MonadMask m, MonadUnliftIO m) => GHCTargetVersion -> Excepts '[NotInstalled] m ()
- GHCup: rmCabalVer :: (MonadReader AppState m, MonadThrow m, MonadLogger m, MonadIO m, MonadFail m, MonadCatch m) => Version -> Excepts '[NotInstalled] m ()
+ GHCup: rmCabalVer :: (MonadMask m, MonadReader env m, HasDirs env, MonadThrow m, HasLog env, MonadIO m, MonadFail m, MonadCatch m, MonadUnliftIO m) => Version -> Excepts '[NotInstalled] m ()
- GHCup: rmGHCVer :: (MonadReader AppState m, MonadThrow m, MonadLogger m, MonadIO m, MonadFail m, MonadCatch m) => GHCTargetVersion -> Excepts '[NotInstalled] m ()
+ GHCup: rmGHCVer :: (MonadReader env m, HasDirs env, MonadThrow m, HasLog env, MonadIO m, MonadFail m, MonadCatch m, MonadMask m, MonadUnliftIO m) => GHCTargetVersion -> Excepts '[NotInstalled] m ()
- GHCup: rmHLSVer :: (MonadReader AppState m, MonadThrow m, MonadLogger m, MonadIO m, MonadFail m, MonadCatch m) => Version -> Excepts '[NotInstalled] m ()
+ GHCup: rmHLSVer :: (MonadMask m, MonadReader env m, HasDirs env, MonadThrow m, HasLog env, MonadIO m, MonadFail m, MonadCatch m, MonadUnliftIO m) => Version -> Excepts '[NotInstalled] m ()
- GHCup: setCabal :: (MonadReader AppState m, MonadLogger m, MonadThrow m, MonadFail m, MonadIO m) => Version -> Excepts '[NotInstalled] m ()
+ GHCup: setCabal :: (MonadMask m, MonadReader env m, HasDirs env, HasLog env, MonadFail m, MonadIO m, MonadUnliftIO m) => Version -> Excepts '[NotInstalled] m ()
- GHCup: setGHC :: (MonadReader AppState m, MonadLogger m, MonadThrow m, MonadFail m, MonadIO m, MonadCatch m) => GHCTargetVersion -> SetGHC -> Excepts '[NotInstalled] m GHCTargetVersion
+ GHCup: setGHC :: (MonadReader env m, HasDirs env, HasLog env, MonadThrow m, MonadFail m, MonadIO m, MonadCatch m, MonadMask m, MonadUnliftIO m) => GHCTargetVersion -> SetGHC -> Excepts '[NotInstalled] m GHCTargetVersion
- GHCup: setHLS :: (MonadCatch m, MonadReader AppState m, MonadLogger m, MonadThrow m, MonadFail m, MonadIO m) => Version -> Excepts '[NotInstalled] m ()
+ GHCup: setHLS :: (MonadReader env m, HasDirs env, HasLog env, MonadIO m, MonadMask m, MonadFail m, MonadUnliftIO m) => Version -> Excepts '[NotInstalled] m ()
- GHCup: upgradeGHCup :: (MonadMask m, MonadReader AppState m, MonadCatch m, MonadLogger m, MonadThrow m, MonadResource m, MonadIO m) => GHCupDownloads -> Maybe (Path Abs) -> Bool -> PlatformRequest -> Excepts '[CopyError, DigestError, DownloadFailed, NoDownload, NoUpdate] m Version
+ GHCup: upgradeGHCup :: (MonadMask m, MonadReader env m, HasDirs env, HasPlatformReq env, HasGHCupInfo env, HasSettings env, MonadCatch m, HasLog env, MonadThrow m, MonadFail m, MonadResource m, MonadIO m, MonadUnliftIO m) => Maybe FilePath -> Bool -> Excepts '[CopyError, DigestError, GPGError, GPGError, DownloadFailed, NoDownload, NoUpdate] m Version
- GHCup.Download: checkDigest :: (MonadIO m, MonadThrow m, MonadLogger m, MonadReader AppState m) => DownloadInfo -> Path Abs -> Excepts '[DigestError] m ()
+ GHCup.Download: checkDigest :: (MonadReader env m, HasDirs env, HasSettings env, MonadIO m, MonadThrow m, HasLog env) => Text -> FilePath -> Excepts '[DigestError] m ()
- GHCup.Download: download :: (MonadMask m, MonadReader AppState m, MonadThrow m, MonadLogger m, MonadIO m) => DownloadInfo -> Path Abs -> Maybe (Path Rel) -> Excepts '[DigestError, DownloadFailed] m (Path Abs)
+ GHCup.Download: download :: (MonadReader env m, HasSettings env, HasDirs env, MonadMask m, MonadThrow m, HasLog env, MonadIO m) => URI -> Maybe URI -> Maybe Text -> FilePath -> Maybe FilePath -> Bool -> Excepts '[DigestError, DownloadFailed, GPGError] m FilePath
- GHCup.Download: downloadCached :: (MonadMask m, MonadResource m, MonadThrow m, MonadLogger m, MonadIO m, MonadReader AppState m) => DownloadInfo -> Maybe (Path Rel) -> Excepts '[DigestError, DownloadFailed] m (Path Abs)
+ GHCup.Download: downloadCached :: (MonadReader env m, HasDirs env, HasSettings env, MonadMask m, MonadResource m, MonadThrow m, HasLog env, MonadIO m, MonadUnliftIO m) => DownloadInfo -> Maybe FilePath -> Excepts '[DigestError, DownloadFailed, GPGError] m FilePath
- GHCup.Download: getBase :: (MonadFail m, MonadIO m, MonadCatch m, MonadLogger m, MonadReader AppState m) => Excepts '[JSONError, FileDoesNotExistError] m GHCupInfo
+ GHCup.Download: getBase :: (MonadReader env m, HasDirs env, HasSettings env, MonadFail m, MonadIO m, MonadCatch m, HasLog env, MonadMask m) => URI -> Excepts '[GPGError, DigestError, JSONError, FileDoesNotExistError] m GHCupInfo
- GHCup.Download: getCurlOpts :: IO [ByteString]
+ GHCup.Download: getCurlOpts :: IO [String]
- GHCup.Download: getDownloadInfo :: Tool -> Version -> PlatformRequest -> GHCupDownloads -> Either NoDownload DownloadInfo
+ GHCup.Download: getDownloadInfo :: (MonadReader env m, HasPlatformReq env, HasGHCupInfo env) => Tool -> Version -> Excepts '[NoDownload] m DownloadInfo
- GHCup.Download: getDownloadsF :: (FromJSONKey Tool, FromJSONKey Version, FromJSON VersionInfo, MonadIO m, MonadCatch m, MonadLogger m, MonadThrow m, MonadFail m, MonadReader AppState m) => URLSource -> Excepts '[JSONError, DownloadFailed, FileDoesNotExistError] m GHCupInfo
+ GHCup.Download: getDownloadsF :: (FromJSONKey Tool, FromJSONKey Version, FromJSON VersionInfo, MonadReader env m, HasSettings env, HasDirs env, MonadIO m, MonadCatch m, HasLog env, MonadThrow m, MonadFail m, MonadMask m) => Excepts '[DigestError, GPGError, JSONError, DownloadFailed, FileDoesNotExistError] m GHCupInfo
- GHCup.Download: getWgetOpts :: IO [ByteString]
+ GHCup.Download: getWgetOpts :: IO [String]
- GHCup.Errors: BuildFailed :: Path Abs -> V es -> BuildFailed
+ GHCup.Errors: BuildFailed :: FilePath -> V es -> BuildFailed
- GHCup.Errors: DigestError :: Text -> Text -> DigestError
+ GHCup.Errors: DigestError :: FilePath -> Text -> Text -> DigestError
- GHCup.Errors: DownloadFailed :: V (x : xs) -> DownloadFailed
+ GHCup.Errors: DownloadFailed :: V xs -> DownloadFailed
- GHCup.Errors: FileDoesNotExistError :: ByteString -> FileDoesNotExistError
+ GHCup.Errors: FileDoesNotExistError :: FilePath -> FileDoesNotExistError
- GHCup.Errors: HTTPStatusError :: Int -> HTTPStatusError
+ GHCup.Errors: HTTPStatusError :: Int -> Map (CI ByteString) ByteString -> HTTPStatusError
- GHCup.Errors: NotFoundInPATH :: Path Rel -> NotFoundInPATH
+ GHCup.Errors: NotFoundInPATH :: FilePath -> NotFoundInPATH
- GHCup.Errors: UnknownArchive :: ByteString -> UnknownArchive
+ GHCup.Errors: UnknownArchive :: FilePath -> UnknownArchive
- GHCup.Platform: getLinuxDistro :: (MonadCatch m, MonadIO m) => Excepts '[DistroNotFound] m (LinuxDistro, Maybe Versioning)
+ GHCup.Platform: getLinuxDistro :: (Alternative m, MonadCatch m, MonadIO m, MonadFail m) => Excepts '[DistroNotFound] m (LinuxDistro, Maybe Versioning)
- GHCup.Platform: getPlatform :: (MonadLogger m, MonadCatch m, MonadIO m) => Excepts '[NoCompatiblePlatform, DistroNotFound] m PlatformResult
+ GHCup.Platform: getPlatform :: (Alternative m, MonadReader env m, HasLog env, MonadCatch m, MonadIO m, MonadFail m) => Excepts '[NoCompatiblePlatform, DistroNotFound] m PlatformResult
- GHCup.Platform: platformRequest :: (MonadLogger m, MonadCatch m, MonadIO m) => Excepts '[NoCompatiblePlatform, NoCompatibleArch, DistroNotFound] m PlatformRequest
+ GHCup.Platform: platformRequest :: (MonadReader env m, Alternative m, MonadFail m, HasLog env, MonadCatch m, MonadIO m) => Excepts '[NoCompatiblePlatform, NoCompatibleArch, DistroNotFound] m PlatformRequest
- GHCup.Types: AppState :: Settings -> Dirs -> KeyBindings -> AppState
+ GHCup.Types: AppState :: Settings -> Dirs -> KeyBindings -> GHCupInfo -> PlatformRequest -> LoggerConfig -> AppState
- GHCup.Types: DebugInfo :: Path Abs -> Path Abs -> Path Abs -> Path Abs -> Architecture -> PlatformResult -> DebugInfo
+ GHCup.Types: DebugInfo :: FilePath -> FilePath -> FilePath -> FilePath -> Architecture -> PlatformResult -> DebugInfo
- GHCup.Types: Dirs :: Path Abs -> Path Abs -> Path Abs -> Path Abs -> Path Abs -> Dirs
+ GHCup.Types: Dirs :: FilePath -> FilePath -> FilePath -> FilePath -> FilePath -> FilePath -> Dirs
- GHCup.Types: GHCupInfo :: ToolRequirements -> GHCupDownloads -> GHCupInfo
+ GHCup.Types: GHCupInfo :: ToolRequirements -> GHCupDownloads -> Map GlobalTool DownloadInfo -> GHCupInfo
- GHCup.Types: KeyBindings :: Key -> Key -> Key -> Key -> Key -> Key -> Key -> Key -> KeyBindings
+ GHCup.Types: KeyBindings :: Key -> Key -> Key -> Key -> Key -> Key -> Key -> Key -> Key -> KeyBindings
- GHCup.Types: RealDir :: Path Rel -> TarDir
+ GHCup.Types: RealDir :: FilePath -> TarDir
- GHCup.Types: Settings :: Bool -> Bool -> KeepDirs -> Downloader -> Bool -> URLSource -> Settings
+ GHCup.Types: Settings :: Bool -> Bool -> KeepDirs -> Downloader -> Bool -> URLSource -> Bool -> GPGSetting -> Bool -> Settings
- GHCup.Types: UserKeyBindings :: Maybe Key -> Maybe Key -> Maybe Key -> Maybe Key -> Maybe Key -> Maybe Key -> Maybe Key -> Maybe Key -> UserKeyBindings
+ GHCup.Types: UserKeyBindings :: Maybe Key -> Maybe Key -> Maybe Key -> Maybe Key -> Maybe Key -> Maybe Key -> Maybe Key -> Maybe Key -> Maybe Key -> UserKeyBindings
- GHCup.Types: UserSettings :: Maybe Bool -> Maybe Bool -> Maybe Bool -> Maybe KeepDirs -> Maybe Downloader -> Maybe UserKeyBindings -> Maybe URLSource -> UserSettings
+ GHCup.Types: UserSettings :: Maybe Bool -> Maybe Bool -> Maybe Bool -> Maybe KeepDirs -> Maybe Downloader -> Maybe UserKeyBindings -> Maybe URLSource -> Maybe Bool -> Maybe GPGSetting -> UserSettings
- GHCup.Utils: applyPatches :: (MonadLogger m, MonadIO m) => Path Abs -> Path Abs -> Excepts '[PatchFailed] m ()
+ GHCup.Utils: applyPatches :: (MonadReader env m, HasDirs env, HasLog env, MonadIO m) => FilePath -> FilePath -> Excepts '[PatchFailed] m ()
- GHCup.Utils: cabalInstalled :: (MonadLogger m, MonadIO m, MonadReader AppState m, MonadCatch m) => Version -> m Bool
+ GHCup.Utils: cabalInstalled :: (MonadIO m, MonadReader env m, HasDirs env, MonadCatch m) => Version -> m Bool
- GHCup.Utils: cabalSet :: (MonadLogger m, MonadReader AppState m, MonadIO m, MonadThrow m, MonadCatch m) => m (Maybe Version)
+ GHCup.Utils: cabalSet :: (HasLog env, MonadReader env m, HasDirs env, MonadIO m, MonadThrow m, MonadCatch m) => m (Maybe Version)
- GHCup.Utils: darwinNotarization :: Platform -> Path Abs -> IO (Either ProcessError ())
+ GHCup.Utils: darwinNotarization :: (MonadReader env m, HasDirs env, MonadIO m) => Platform -> FilePath -> m (Either ProcessError ())
- GHCup.Utils: getArchiveFiles :: (MonadLogger m, MonadIO m, MonadThrow m) => Path Abs -> Excepts '[UnknownArchive, ArchiveResult] m [ByteString]
+ GHCup.Utils: getArchiveFiles :: (MonadReader env m, HasLog env, MonadIO m, MonadThrow m) => FilePath -> Excepts '[UnknownArchive, ArchiveResult] m [FilePath]
- GHCup.Utils: getInstalledCabals :: (MonadLogger m, MonadReader AppState m, MonadIO m, MonadCatch m) => m [Either (Path Rel) Version]
+ GHCup.Utils: getInstalledCabals :: (MonadReader env m, HasDirs env, MonadIO m, MonadCatch m) => m [Either FilePath Version]
- GHCup.Utils: getInstalledGHCs :: (MonadReader AppState m, MonadIO m) => m [Either (Path Rel) GHCTargetVersion]
+ GHCup.Utils: getInstalledGHCs :: (MonadReader env m, HasDirs env, MonadIO m) => m [Either FilePath GHCTargetVersion]
- GHCup.Utils: getInstalledHLSs :: (MonadReader AppState m, MonadIO m, MonadCatch m) => m [Either (Path Rel) Version]
+ GHCup.Utils: getInstalledHLSs :: (MonadReader env m, HasDirs env, MonadIO m, MonadCatch m) => m [Either FilePath Version]
- GHCup.Utils: getTagged :: Tag -> AffineFold (Map Version VersionInfo) (Version, VersionInfo)
+ GHCup.Utils: getTagged :: Tag -> Fold (Map Version VersionInfo) (Version, VersionInfo)
- GHCup.Utils: ghcInstalled :: (MonadIO m, MonadReader AppState m, MonadThrow m) => GHCTargetVersion -> m Bool
+ GHCup.Utils: ghcInstalled :: (MonadIO m, MonadReader env m, HasDirs env, MonadThrow m) => GHCTargetVersion -> m Bool
- GHCup.Utils: ghcLinkDestination :: (MonadReader AppState m, MonadThrow m, MonadIO m) => ByteString -> GHCTargetVersion -> m ByteString
+ GHCup.Utils: ghcLinkDestination :: (MonadReader env m, HasDirs env, MonadThrow m, MonadIO m) => FilePath -> GHCTargetVersion -> m FilePath
- GHCup.Utils: ghcSet :: (MonadReader AppState m, MonadThrow m, MonadIO m) => Maybe Text -> m (Maybe GHCTargetVersion)
+ GHCup.Utils: ghcSet :: (MonadReader env m, HasDirs env, MonadThrow m, MonadIO m) => Maybe Text -> m (Maybe GHCTargetVersion)
- GHCup.Utils: ghcSrcInstalled :: (MonadIO m, MonadReader AppState m, MonadThrow m) => GHCTargetVersion -> m Bool
+ GHCup.Utils: ghcSrcInstalled :: (MonadIO m, MonadReader env m, HasDirs env, MonadThrow m) => GHCTargetVersion -> m Bool
- GHCup.Utils: ghcToolFiles :: (MonadReader AppState m, MonadThrow m, MonadFail m, MonadIO m) => GHCTargetVersion -> Excepts '[NotInstalled] m [Path Rel]
+ GHCup.Utils: ghcToolFiles :: (MonadReader env m, HasDirs env, MonadThrow m, MonadFail m, MonadIO m) => GHCTargetVersion -> Excepts '[NotInstalled] m [FilePath]
- GHCup.Utils: ghcUpSrcBuiltFile :: Path Rel
+ GHCup.Utils: ghcUpSrcBuiltFile :: FilePath
- GHCup.Utils: hlsAllBinaries :: (MonadReader AppState m, MonadIO m, MonadThrow m) => Version -> m [Path Rel]
+ GHCup.Utils: hlsAllBinaries :: (MonadReader env m, HasDirs env, MonadIO m, MonadThrow m) => Version -> m [FilePath]
- GHCup.Utils: hlsGHCVersions :: (MonadReader AppState m, MonadIO m, MonadThrow m, MonadCatch m) => m [Version]
+ GHCup.Utils: hlsGHCVersions :: (MonadReader env m, HasDirs env, MonadIO m, MonadThrow m, MonadCatch m) => m [Version]
- GHCup.Utils: hlsInstalled :: (MonadIO m, MonadReader AppState m, MonadCatch m) => Version -> m Bool
+ GHCup.Utils: hlsInstalled :: (MonadIO m, MonadReader env m, HasDirs env, MonadCatch m) => Version -> m Bool
- GHCup.Utils: hlsServerBinaries :: (MonadReader AppState m, MonadIO m) => Version -> m [Path Rel]
+ GHCup.Utils: hlsServerBinaries :: (MonadReader env m, HasDirs env, MonadIO m) => Version -> Maybe Version -> m [FilePath]
- GHCup.Utils: hlsSet :: (MonadReader AppState m, MonadIO m, MonadThrow m, MonadCatch m) => m (Maybe Version)
+ GHCup.Utils: hlsSet :: (MonadReader env m, HasDirs env, MonadIO m, MonadThrow m, MonadCatch m) => m (Maybe Version)
- GHCup.Utils: hlsSymlinks :: (MonadReader AppState m, MonadIO m, MonadCatch m) => m [Path Rel]
+ GHCup.Utils: hlsSymlinks :: (MonadReader env m, HasDirs env, MonadIO m, MonadCatch m) => m [FilePath]
- GHCup.Utils: hlsWrapperBinary :: (MonadReader AppState m, MonadThrow m, MonadIO m) => Version -> m (Maybe (Path Rel))
+ GHCup.Utils: hlsWrapperBinary :: (MonadReader env m, HasDirs env, MonadThrow m, MonadIO m) => Version -> m (Maybe FilePath)
- GHCup.Utils: intoSubdir :: (MonadLogger m, MonadIO m, MonadThrow m, MonadCatch m) => Path Abs -> TarDir -> Excepts '[TarDirDoesNotExist] m (Path Abs)
+ GHCup.Utils: intoSubdir :: (MonadReader env m, HasLog env, MonadIO m, MonadThrow m, MonadCatch m) => FilePath -> TarDir -> Excepts '[TarDirDoesNotExist] m FilePath
- GHCup.Utils: make :: (MonadThrow m, MonadIO m, MonadReader AppState m) => [ByteString] -> Maybe (Path Abs) -> m (Either ProcessError ())
+ GHCup.Utils: make :: (MonadThrow m, MonadIO m, MonadReader env m, HasDirs env, HasSettings env) => [String] -> Maybe FilePath -> m (Either ProcessError ())
- GHCup.Utils: rmMajorSymlinks :: (MonadReader AppState m, MonadIO m, MonadLogger m, MonadThrow m, MonadFail m, MonadReader AppState m) => GHCTargetVersion -> Excepts '[NotInstalled] m ()
+ GHCup.Utils: rmMajorSymlinks :: (MonadReader env m, HasDirs env, MonadIO m, HasLog env, MonadThrow m, MonadFail m, MonadMask m) => GHCTargetVersion -> Excepts '[NotInstalled] m ()
- GHCup.Utils: rmMinorSymlinks :: (MonadReader AppState m, MonadIO m, MonadLogger m, MonadThrow m, MonadFail m, MonadReader AppState m) => GHCTargetVersion -> Excepts '[NotInstalled] m ()
+ GHCup.Utils: rmMinorSymlinks :: (MonadReader env m, HasDirs env, MonadIO m, HasLog env, MonadThrow m, MonadFail m, MonadMask m) => GHCTargetVersion -> Excepts '[NotInstalled] m ()
- GHCup.Utils: rmPlain :: (MonadReader AppState m, MonadLogger m, MonadThrow m, MonadFail m, MonadIO m) => Maybe Text -> Excepts '[NotInstalled] m ()
+ GHCup.Utils: rmPlain :: (MonadReader env m, HasDirs env, HasLog env, MonadThrow m, MonadFail m, MonadIO m, MonadMask m) => Maybe Text -> Excepts '[NotInstalled] m ()
- GHCup.Utils: runBuildAction :: (Show (V e), MonadReader AppState m, MonadIO m, MonadMask m) => Path Abs -> Maybe (Path Abs) -> Excepts e m a -> Excepts '[BuildFailed] m a
+ GHCup.Utils: runBuildAction :: (Pretty (V e), Show (V e), PopVariant BuildFailed e, ToVariantMaybe BuildFailed e, MonadReader env m, HasDirs env, HasSettings env, MonadIO m, MonadMask m, HasLog env, MonadUnliftIO m, MonadFail m, MonadCatch m) => FilePath -> Maybe FilePath -> Excepts e m a -> Excepts '[BuildFailed] m a
- GHCup.Utils: unpackToDir :: (MonadLogger m, MonadIO m, MonadThrow m) => Path Abs -> Path Abs -> Excepts '[UnknownArchive, ArchiveResult] m ()
+ GHCup.Utils: unpackToDir :: (MonadReader env m, HasLog env, MonadIO m, MonadThrow m) => FilePath -> FilePath -> Excepts '[UnknownArchive, ArchiveResult] m ()
- GHCup.Utils.Dirs: ghcupGHCBaseDir :: MonadReader AppState m => m (Path Abs)
+ GHCup.Utils.Dirs: ghcupGHCBaseDir :: (MonadReader env m, HasDirs env) => m FilePath
- GHCup.Utils.Dirs: ghcupGHCDir :: (MonadReader AppState m, MonadThrow m) => GHCTargetVersion -> m (Path Abs)
+ GHCup.Utils.Dirs: ghcupGHCDir :: (MonadReader env m, HasDirs env, MonadThrow m) => GHCTargetVersion -> m FilePath
- GHCup.Utils.Dirs: mkGhcupTmpDir :: (MonadThrow m, MonadIO m) => m (Path Abs)
+ GHCup.Utils.Dirs: mkGhcupTmpDir :: (MonadReader env m, HasDirs env, MonadUnliftIO m, HasLog env, MonadCatch m, MonadThrow m, MonadMask m, MonadIO m) => m FilePath
- GHCup.Utils.Dirs: parseGHCupGHCDir :: MonadThrow m => Path Rel -> m GHCTargetVersion
+ GHCup.Utils.Dirs: parseGHCupGHCDir :: MonadThrow m => FilePath -> m GHCTargetVersion
- GHCup.Utils.Dirs: relativeSymlink :: Path Abs -> Path Abs -> ByteString
+ GHCup.Utils.Dirs: relativeSymlink :: FilePath -> FilePath -> FilePath
- GHCup.Utils.Dirs: withGHCupTmpDir :: (MonadResource m, MonadThrow m, MonadIO m) => m (Path Abs)
+ GHCup.Utils.Dirs: withGHCupTmpDir :: (MonadReader env m, HasDirs env, HasLog env, HasSettings env, MonadUnliftIO m, MonadCatch m, MonadResource m, MonadThrow m, MonadMask m, MonadIO m) => m FilePath
- GHCup.Utils.File: chmod_755 :: (MonadLogger m, MonadIO m) => Path a -> m ()
+ GHCup.Utils.File: chmod_755 :: (MonadReader env m, HasLog env, MonadIO m) => FilePath -> m ()
- GHCup.Utils.File: createRegularFileFd :: FileMode -> Path b -> IO Fd
+ GHCup.Utils.File: createRegularFileFd :: FileMode -> FilePath -> IO Fd
- GHCup.Utils.File: exec :: ByteString -> Bool -> [ByteString] -> Maybe (Path Abs) -> Maybe [(ByteString, ByteString)] -> IO (Either ProcessError ())
+ GHCup.Utils.File: exec :: MonadIO m => String -> [String] -> Maybe FilePath -> Maybe [(String, String)] -> m (Either ProcessError ())
- GHCup.Utils.File: execLogged :: (MonadReader AppState m, MonadIO m, MonadThrow m) => ByteString -> Bool -> [ByteString] -> Path Rel -> Maybe (Path Abs) -> Maybe [(ByteString, ByteString)] -> m (Either ProcessError ())
+ GHCup.Utils.File: execLogged :: (MonadReader env m, HasSettings env, HasDirs env, MonadIO m, MonadThrow m) => FilePath -> [String] -> Maybe FilePath -> FilePath -> Maybe [(String, String)] -> m (Either ProcessError ())
- GHCup.Utils.File: executeOut :: Path b -> [ByteString] -> Maybe (Path Abs) -> IO CapturedProcess
+ GHCup.Utils.File: executeOut :: MonadIO m => FilePath -> [String] -> Maybe FilePath -> m CapturedProcess
- GHCup.Utils.File: isBrokenSymlink :: Path Abs -> IO Bool
+ GHCup.Utils.File: isBrokenSymlink :: FilePath -> IO Bool
- GHCup.Utils.File: toProcessError :: ByteString -> [ByteString] -> Maybe ProcessStatus -> Either ProcessError ()
+ GHCup.Utils.File: toProcessError :: FilePath -> [String] -> Maybe ProcessStatus -> Either ProcessError ()
- GHCup.Utils.Logger: initGHCupFileLogging :: (MonadIO m, MonadReader AppState m) => Path Rel -> m (Path Abs)
+ GHCup.Utils.Logger: initGHCupFileLogging :: (MonadReader env m, HasDirs env, MonadIO m, MonadMask m) => m FilePath
- GHCup.Utils.Prelude: hideErrorDef :: [IOErrorType] -> a -> IO a -> IO a
+ GHCup.Utils.Prelude: hideErrorDef :: (MonadIO m, MonadCatch m) => [IOErrorType] -> a -> m a -> m a
- GHCup.Utils.Prelude: hideErrorDefM :: [IOErrorType] -> IO a -> IO a -> IO a
+ GHCup.Utils.Prelude: hideErrorDefM :: (MonadIO m, MonadCatch m) => [IOErrorType] -> m a -> m a -> m a
- GHCup.Utils.Prelude: pvpToVersion :: PVP -> Version
+ GHCup.Utils.Prelude: pvpToVersion :: MonadThrow m => PVP -> m Version

Files

− CHANGELOG.md
@@ -1,134 +0,0 @@-# Revision history for ghcup--## 0.1.14.2 -- 2021-05-12--* Remove dead dependency on ascii-string--## 0.1.14.1 -- 2021-04-11--* Make internal symlink target parser more lax, fixes [#119](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/119)-* Prepare for hackage release--## 0.1.14 -- 2021-03-07--* Major bugfix: fix handling of stray versions wrt [#116](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/116)-* Fix error messages and overhaul pretty printing wrt [#115](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/115)--## 0.1.13 -- 2021-02-26--* Support ARMv7/AARCH64-* Add command line completions for installed and available versions wrt [MR #70](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/70)-* Allow to cycle through set tools wrt [#114](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/114)-* Fix item selection with unavailable versions wrt [#107](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/107)-* Allow for dynamic post-install, post-remove and pre-compile msgs wrt [MR #68](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/68)-* Alert user if upgraded ghcup is shadowed by old ghcup wrt [#111](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/111)-* Fix to `ghcup` directory creation and placement for the XDG install mode ([MR #49](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/49))-* Do 755 permissions on executables, wrt #97-* Add [NO_COLOR](https://no-color.org/) support wrt [MR #47](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/47)--## 0.1.12 -- 2020-11-21--* Fix disappearing HLS symlinks wrt #91-* improve TUI:-  - separators between tools sections-  - reverse list order so latest is on top-  - expand the blues selected bar-  - show new latest versions in bright white-* allow configuration file and setting TUI hotkeys wrt #41-  - see https://gitlab.haskell.org/haskell/ghcup-hs#configuration for a more in-depth explanation-* add a `--set` switch to `ghcup install ghc` to automatically set as default after install-* emit warnings when CC/LD is set wrt #82-* add support for version ranges in distro specifiers wrt #84-  - e.g. `"(>= 19 && <= 20) || ==0.2.2"` is a valid version key for distro--## 0.1.11 -- 2020-09-23--* Add support for installing haskell-language-server, wrt #65-* When compiling GHC from source create a bindist first, store that bindist in `~/.ghcup/cache` and install it, wrt #51-* Allow to compile over existing version (`ghcup compile ghc -v 8.6.5 -b 8.6.5`) and replace it wrt #59-* simplify installing from custom bindist wrt #60-  - `ghcup install ghc -u <url> <version>`-* fix bug when cabal isn't marked executable in bindist-* fix bug when `~/.ghcup` is a valid symlink wrt #49-* Drop support for compiling cabal from source (the old bootstrap script is discontinued)--## 0.1.10 -- 2020-08-14--* Show stray Cabals (useful for pre-releases or compiled ones)--## 0.1.9 -- 2020-08-14--* Fix bug when uninstalling all cabal versions-* Fix bug when setting a non-installed ghc version as current default-* Use yaml instead of generated json for download info for ease of adding new GHC versions #44-* Allow pre-release versions of GHC/cabal-* Add XDG dirs support (set `GHCUP_USE_XDG_DIRS`) wrt #39-* Allow to specify regex for tarball subdir (e.g. `ghc-.*`)-* Allow installing arbitrary bindists more seamlessly:-  - e.g. installing GHC HEAD: `ghcup -n install ghc -u '{"dlHash": "", "dlSubdir": { "RegexDir": "ghc-.*"}, "dlUri": "https://gitlab.haskell.org/api/v4/projects/1/jobs/artifacts/master/raw/ghc-x86_64-fedora27-linux.tar.xz?job=validate-x86_64-linux-fedora27" }' head`-* Avoid duplicate edits to .bashrc/.zshrc wrt #43--## 0.1.8 -- 2020-07-21--* Fix bug in logging thread dying on newlines-* Allow to install from arbitrary bindists: `ghcup -n install ghc -u '{"dlHash": "", "dlSubdir": "ghc-8.10.1", "dlUri": "https://github.com/commercialhaskell/ghc/releases/download/ghc-8.10.1-release/ghc-8.10.1-x86_64-deb9-linux.tar.xz"}' 8.10.1`--## 0.1.7 -- 2020-07-20--* Fix a bug in libarchive not unpacking some uncleanly packed bindists-* Improved fish support in bootstrap-haskell-* Only check for upgrades when not upgrading-* Fix platform detection for i386 docker images-* Improve alpine support-  - more/proper bindists-  - don't fall back to glibc based bindists-  - install bindists with `--disable-ld-override` to avoid ld.gold bugs--## 0.1.6 -- 2020-07-13--* Create a new curses (brick) based TUI, accessible via `ghcup tui` #24-* Support multiple installed versions of cabal #23-* Improvements to `ghcup list` (show unavailable bindists for platform)-* Fix redhat downloads #29-* Support for hadrian bindists (fixes alpine-8.10.1) #31-* Add FreeBSD bindists 8.6.5 and 8.8.3-* Fix memory leak during unpack--## 0.1.5 -- 2020-04-30--* Fix errors when PATH variable contains path components that are actually files-* Add `--version` and `--numeric-version` options-* Add `changelog` command-* Also check for available GHC and Cabal updates on start-* Add base versions as tags for every GHC version (these are "installable" tags and the latest GHC version matching the tag will be picked)-* Added `--format-raw` to list subcommand-* Allow to install X.Y versions (e.g.: ghcup install 8.8)-* Implement `--keep=<always|errors|never>` to control temporary build directories cleanup-* Add proper shell completions to the repo-* Fix building of documentation-* Allow to work in offline mode and use cached files if possible-* Allow to set the downloader via `--downloader=<curl|wget>`-* Support for compiling and installing a cross GHC (see README). This is experimental.--## 0.1.4 -- 2020-04-16--* build on all platforms with curl (as a binary), wrt https://gitlab.haskell.org/haskell/ghcup-hs/issues/6-* Fix unlinking of ghc symlinks after new installation, wrt https://gitlab.haskell.org/haskell/ghcup-hs/issues/7--## 0.1.3 -- 2020-04-15--* Fix lesser bug when skipping ghcup update--## 0.1.2 -- 2020-04-15--* Fix bug when removing the set GHC version-* Fix use of undocumented `GHCUP_INSTALL_BASE_PREFIX` variable-* skip upgrade if ghcup is already latest version--## 0.1.1 -- 2020-04-15--* fix awful fdopendir bug on mac bug by updating hpath-posix--## 0.1.0--* First version. Released on an unsuspecting world.
− HACKING.md
@@ -1,75 +0,0 @@-# HACKING--## Design decisions--### Using [Excepts](https://hackage.haskell.org/package/haskus-utils-variant-3.0/docs/Haskus-Utils-Variant-Excepts.html) as a beefed up ExceptT--This is an open variant, similar to [plucky](https://hackage.haskell.org/package/plucky) or [oops](https://github.com/i-am-tom/oops) and allows us to combine different error types. Maybe it is too much and it's a little bit [unergonomic](https://github.com/haskus/packages/issues/32) at times. If it really hurts maintenance, it will be removed. It was more of an experiment.--### No use of filepath or directory--Filepath and directory have two fundamental problems: 1. they use String as filepath (see [AFPP](https://gitlab.haskell.org/ghc/ghc/-/wikis/proposal/abstract-file-path) as to why this is wrong) and 2. they try very hard to be cross-platform at the expense of low-level correctness. Instead, we use the [hpath](https://github.com/hasufell/hpath) libraries for file and filepath related stuff, which also gives us stronger filepath types.--### No use of haskell-TLS--I consider haskell-TLS an interesting experiment, but not a battle-tested and peer-reviewed crypto implementation. There is little to no research about what the intricacies of using haskell for low-level crypto are and how vulnerable such binaries are. Instead, we use either curl the binary (for FreeBSD and mac) or http-io-streams, which works with OpenSSL bindings.--### Optics instead of lens--They're a little safer (less Monoid weirdness with view) and have better error messages. Consider the following wit lens--```-> view (_Just . to (++ "abc")) Nothing-""-```--vs optics--```-> view (_Just % to (++ "abc")) Nothing--<interactive>:2:1: error:-    • An_AffineFold cannot be used as A_Getter-    • In the expression: view (_Just % to (++ "abc")) Nothing-      In an equation for ‘it’: it = view (_Just % to (++ "abc")) Nothing-```--### Strict and StrictData on by default--Kazu Yamamoto [explained it in his PR](https://github.com/yesodweb/wai/pull/752#issuecomment-501531386) very well. I like to agree with him. The instances where we need non-strict behavior, we annotate it.--## Code style and formatting--1. Brittany-2. mtl-style preferred-3. no overly pointfree style--## Code structure--Main functionality is in `GHCup` module. Utility functions are-organised tree-ish in `GHCup.Utils` and `GHCup.Utils.*`.--Anything dealing with ghcup specific directories is in-`GHCup.Utils.Dirs`.--Download information on where to fetch bindists from is in the appropriate-yaml files: `ghcup-<yaml-ver>.yaml`.--## Common Tasks--### Adding a new GHC version--1. open the latest `ghcup-<yaml-ver>.yaml`-2. find the latest ghc version (in yaml tree e.g. `ghcupDownloads -> GHC -> 8.10.3`)-3. copy-paste it-4. adjust the version, tags, changelog, source url-5. adjust the various bindist urls (make sure to also change the yaml anchors)-6. run `cabal run exe:ghcup-gen -- check-tarballs -f ghcup-<yaml-ver>.yaml -u 'ghc-8\.10\.4'`--## Major refactors--1. First major refactor included adding cross support. This added-   `GHCTargetVersion`, which includes the target in addition to the version.-   Most of the `Version` parameters to functions had to be replaced with-   that and ensured the logic is consistent for cross and non-cross-   installs.
README.md view
@@ -1,25 +1,33 @@ `ghcup` makes it easy to install specific versions of `ghc` on GNU/Linux,-macOS (aka Darwin) and FreeBSD and can also bootstrap a fresh Haskell developer environment from scratch.+macOS (aka Darwin), FreeBSD and Windows and can also bootstrap a fresh Haskell developer environment from scratch. It follows the unix UNIX philosophy of [do one thing and do it well](https://en.wikipedia.org/wiki/Unix_philosophy#Do_One_Thing_and_Do_It_Well).  Similar in scope to [rustup](https://github.com/rust-lang-nursery/rustup.rs), [pyenv](https://github.com/pyenv/pyenv) and [jenv](http://www.jenv.be). -*Ubuntu users may prefer [hvr's ppa](https://launchpad.net/~hvr/+archive/ubuntu/ghc).*- ## Table of Contents +[![Join the chat at Libera.chat](https://img.shields.io/badge/chat-on%20libera%20IRC-brightgreen.svg)](https://kiwiirc.com/nextclient/irc.libera.chat/?nick=Guest%7C?#haskell,#haskell-ghcup)+[![Join the chat at Matrix.org](https://img.shields.io/matrix/haskell-tooling:matrix.org?label=chat%20on%20matrix.org)](https://app.element.io/#/room/#haskell-tooling:matrix.org)+[![Join the chat at Discord](https://img.shields.io/discord/280033776820813825?label=chat%20on%20discord)](https://discord.gg/pKYf3zDQU7)+[![Join the chat at https://gitter.im/haskell/ghcup](https://badges.gitter.im/haskell/ghcup.svg)](https://gitter.im/haskell/ghcup?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)+<a href="https://opencollective.com/ghcup#category-CONTRIBUTE"><img src="https://opencollective.com/webpack/donate/button@2x.png?color=blue" alt="Donate" width="150"></a>+    * [Installation](#installation)-     * [Simple bootstrap](#simple-bootstrap)+     * [Supported platforms](#supported-platforms)      * [Manual install](#manual-install)      * [Vim integration](#vim-integration)    * [Usage](#usage)      * [Configuration](#configuration)+     * [GPG verification](#gpg-verification)      * [Manpages](#manpages)      * [Shell-completion](#shell-completion)-     * [Cross support](#cross-support)+     * [Compiling GHC from source](#compiling-ghc-from-source)      * [XDG support](#xdg-support)      * [Env variables](#env-variables)      * [Installing custom bindists](#installing-custom-bindists)+     * [Isolated Installs](#isolated-installs)+     * [CI](#ci)+     * [Tips and tricks](#tips-and-tricks)    * [Design goals](#design-goals)    * [How](#how)    * [Known users](#known-users)@@ -28,10 +36,60 @@  ## Installation -### Simple bootstrap+Most users should follow the instructions at [https://www.haskell.org/ghcup/](https://www.haskell.org/ghcup/).+Advanced users may want to perform a [manual installation](#manual-install). -Follow the instructions at [https://www.haskell.org/ghcup/](https://www.haskell.org/ghcup/)+### Supported platforms +This list may not be exhaustive and specifies support for bindists only.++| Platform | Architecture | ghcup | GHC | cabal | HLS | stack | +| ------ | ------ | ------ | ------ | ------ | ------ | ------ |+| Windows 7 | amd64 | ❔ | ✅ | ✅ | ✅ | ✅ |+| Windows 10 | amd64 | ✅ | ✅ | ✅ | ✅ | ✅ |+| Windows Server 2016 | amd64 | ✅ | ✅ | ✅ | ✅ | ✅ |+| Windows Server 2019 | amd64 | ✅ | ✅ | ✅ | ✅ | ✅ |+| Windows Server 2022 | amd64 | ✅ | ✅ | ✅ | ✅ | ✅ |+| Windows WSL1 | amd64 | ❌ | ❔ | ❔ | ❔ | ❔ |+| Windows WSL2 | amd64 | ✅ | ✅ | ✅ | ✅ | ✅ |+| MacOS >=13 | amd64 | ✅ | ✅ | ✅ | ✅ | ✅ |+| MacOS <13 | amd64 | ❌ | ❔ | ❔ | ❔ | ❔ |+| MacOS | aarch64 | ✅ | ✅ | ✅ | ⚠️ | ❌ |+| FreeBSD | amd64 | ✅ | ⚠️ | ✅ | ⚠️ | ❌ |+| Linux generic | x86 | ✅ | ✅ | ✅ | ✅ | ✅ |+| Linux generic | amd64 | ✅ | ✅ | ✅ | ✅ | ✅ |+| Linux generic | aarch64 | ✅ | ⚠️ | ✅ | ⚠️ | ❌ |+| Linux generic | armv7 | ✅ | ⚠️ | ✅ | ⚠️ | ❌ |++#### Windows 7++May or may not work, several issues:++* https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/140+* https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/197++#### WSL1++Unsupported. GHC may or may not work. Upgrade to WSL2.++#### MacOS <13++Not supported. Would require separate binaries, since >=13 binaries are incompatible.+Please upgrade.++#### MacOS aarch64++HLS bindists are still experimental. Stack is theoretically supported, but has no binaries yet.++#### FreeBSD++Lacks some upstream bindists and may need compat libs, since most bindists are built on FreeBSD-12.+HLS bindists are experimental.++#### Linux ARMv7/AARCH64++Lower availability of bindists. HLS only has experimental ones. Stack not supported currently.+ ### Manual install  Download the binary for your platform at [https://downloads.haskell.org/~ghcup/](https://downloads.haskell.org/~ghcup/)@@ -79,16 +137,44 @@ ghcup upgrade ``` -Generally this is meant to be used with [`cabal-install`](https://hackage.haskell.org/package/cabal-install), which+GHCup works very well with [`cabal-install`](https://hackage.haskell.org/package/cabal-install), which handles your haskell packages and can demand that [a specific version](https://cabal.readthedocs.io/en/latest/nix-local-build.html#cfg-flag---with-compiler)  of `ghc` is available, which `ghcup` can do.  ### Configuration  A configuration file can be put in `~/.ghcup/config.yaml`. The default config file-explaining all possible configurations can be found in this repo: [config.yaml](./config.yaml).+explaining all possible configurations can be found in this repo: [config.yaml](./data/config.yaml). -Partial configuration is fine. Command line options always overwrite the config file settings.+Partial configuration is fine. Command line options always override the config file settings. +### GPG verification++GHCup supports verifying the GPG signature of the metadata file. The metadata file then contains SHA256 hashes of all downloads, so+this is cryptographically secure.++First, obtain the gpg key:++```sh+gpg --batch --keyserver keys.openpgp.org --recv-keys 7784930957807690A66EBDBE3786C5262ECB4A3F+```++Then verify the gpg key in one of these ways:++1. find out where I live and visit me to do offline key signing+2. figure out my mobile phone number and call me to verify the fingerprint+3. more boring: contact me on Libera IRC (`maerwald`) and verify the fingerprint++Once you've verified the key, you have to figure out if you trust me.++If you trust me, then you can configure gpg in `~/.ghcup/config.yaml`:++```yml+gpg-setting: GPGLax # GPGStrict | GPGLax | GPGNone+```++In `GPGStrict` mode, ghcup will fail if verification fails. In `GPGLax` mode it will just print a warning.+You can also pass the mode via `ghcup --gpg <strict|lax|none>`.+ ### Manpages  For man pages to work you need [man-db](http://man-db.nongnu.org/) as your `man` provider, then issue `man ghc`. Manpages only work for the currently set ghc.@@ -96,15 +182,27 @@  ### Shell-completion -Shell completions are in `shell-completions`.+Shell completions are in [scripts/shell-completions](./scripts/shell-completions) directory of this repository.  For bash: install `shell-completions/bash` as e.g. `/etc/bash_completion.d/ghcup` (depending on distro) and make sure your bashrc sources the startup script (`/usr/share/bash-completion/bash_completion` on some distros). -### Cross support+### Compiling GHC from source +Compiling from source is supported for both source tarballs and arbitrary git refs. See `ghcup compile ghc --help`+for a list of all available options.++If you need to overwrite the existing `build.mk`, check the default files+in [data/build_mk](./data/build_mk), copy them somewhere, adjust them and+pass `--config path/to/build.mk` to `ghcup compile ghc`.+Common `build.mk` options are explained [here](https://gitlab.haskell.org/ghc/ghc/-/wikis/building/using#build-configuration).++Make sure your system meets all the [prerequisites](https://gitlab.haskell.org/ghc/ghc/-/wikis/building/preparation).++#### Cross support+ ghcup can compile and install a cross GHC for any target. However, this requires that the build host has a complete cross toolchain and various libraries installed for the target platform.@@ -125,6 +223,9 @@ * `XDG_BIN_HOME`: binaries end up here (default: `~/.local/bin`) * `XDG_CONFIG_HOME`: the config file is stored in `ghcup` subdir as `config.yaml` (default: `~/.config`) +**Note that `ghcup` makes some assumptions about structure of files in `XDG_BIN_HOME`. So if you have other tools+installing e.g. stack/cabal/ghc into it, this will likely clash. In that case consider disabling XDG support.**+ ### Env variables  This is the complete list of env variables that change GHCup behavior:@@ -134,6 +235,8 @@ * `GHCUP_INSTALL_BASE_PREFIX`: the base of ghcup (default: `$HOME`) * `GHCUP_CURL_OPTS`: additional options that can be passed to curl * `GHCUP_WGET_OPTS`: additional options that can be passed to wget+* `GHCUP_GPG_OPTS`: additional options that can be passed to gpg+* `GHCUP_SKIP_UPDATE_CHECK`: Skip the (possibly annoying) update check when you run a command * `CC`/`LD` etc.: full environment is passed to the build system when compiling GHC via GHCup  ### Installing custom bindists@@ -152,6 +255,160 @@ GHCup always needs to know which version the bindist corresponds to (this is not automatically detected). +### Isolated installs++Ghcup also enables you to install a tool (GHC, Cabal, HLS, Stack) at an isolated location of your choosing.+These installs, as the name suggests, are separate from your main installs and DO NOT conflict with them.+++- No symlinks are made to these isolated installed tools, you'd have to manually point to them wherever you intend to use them.++- These installs, can also NOT be deleted from ghcup, you'd have to go and manually delete these.++You need to use the `--isolate` or `-i` flag followed by the directory path.++Examples:-++1. install an isolated GHC version at location /home/user/isolated_dir/ghc/  +   - `ghcup install ghc 8.10.5 --isolate /home/user/isolated_dir/ghc`++2. isolated install Cabal at a location you desire  +   - `ghcup install cabal --isolate /home/username/my_isolated_dir/`++3. do an isolated install with a custom bindist  +   - `ghcup install ghc --isolate /home/username/my_isolated_dir/ -u 'https://gitlab.haskell.org/api/v4/projects/1/jobs/artifacts/master/raw/ghc-x86_64-fedora27-linux.tar.xz?job=validate-x86_64-linux-fedora27' head`++4. isolated install HLS  +   - `ghcup install hls --isolate /home/username/dir/hls/`++5. you can even compile ghc to an isolated location.  +   - `ghcup compile ghc -j 4 -v 9.0.1 -b 8.10.5 -i /home/username/my/dir/ghc` +   ---  ++### CI++On windows, ghcup can be installed automatically on a CI runner like so:++```ps+Set-ExecutionPolicy Bypass -Scope Process -Force;[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072;Invoke-Command -ScriptBlock ([ScriptBlock]::Create((Invoke-WebRequest https://www.haskell.org/ghcup/sh/bootstrap-haskell.ps1 -UseBasicParsing))) -ArgumentList $false,$true,$true,$false,$false,$false,$false,"C:\"+```++On linux/darwin/freebsd, run the following on your runner:++```sh+curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | BOOTSTRAP_HASKELL_NONINTERACTIVE=1 BOOTSTRAP_HASKELL_MINIMAL=1 sh+```++This will just install `ghcup` and on windows additionally `msys2`.++#### Example github workflow++On github workflows you can use https://github.com/haskell/actions/++If you want to install ghcup manually though, here's an example config:++```yml+name: Haskell CI++on:+  push:+    branches: [ master ]+  pull_request:+    branches: [ master ]++jobs:+  build-cabal:++    runs-on: ${{ matrix.os }}+    strategy:+      fail-fast: false+      matrix:+        os: [ubuntu-latest, macOS-latest, windows-latest]+        ghc: ['8.10.7', '9.0.1']+        cabal: ['3.4.0.0']++    steps:+    - uses: actions/checkout@v2++    - if: matrix.os == 'windows-latest'+      name: Install ghcup on windows+      run: Set-ExecutionPolicy Bypass -Scope Process -Force;[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072;Invoke-Command -ScriptBlock ([ScriptBlock]::Create((Invoke-WebRequest https://www.haskell.org/ghcup/sh/bootstrap-haskell.ps1 -UseBasicParsing))) -ArgumentList $false,$true,$true,$false,$false,$false,$false,"C:\"++    - if: matrix.os == 'windows-latest'+      name: Add ghcup to PATH+      run: echo "/c/ghcup/bin" >> $GITHUB_PATH+      shell: bash++    - if: matrix.os != 'windows-latest'+      name: Install ghcup on non-windows+      run: curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | BOOTSTRAP_HASKELL_NONINTERACTIVE=1 BOOTSTRAP_HASKELL_MINIMAL=1 sh++    - name: Install ghc/cabal+      run: |+        ghcup install ghc ${{ matrix.ghc }}+        ghcup install cabal ${{ matrix.cabal }}+      shell: bash++    - name: Update cabal index+      run: cabal update+      shell: bash++    - name: Build+      run: cabal build --enable-tests --enable-benchmarks+      shell: bash++    - name: Run tests+      run: cabal test+      shell: bash+```+   +### Tips and tricks++#### with_ghc wrapper (e.g. for HLS)++Due to some HLS [bugs](https://github.com/mpickering/hie-bios/issues/194) it's necessary that the `ghc` in PATH+is the one defined in `cabal.project`. With some simple shell functions, we can start our editor with the appropriate+path prepended.++For bash, in e.g. `~/.bashrc` define:++```sh+with_ghc() {+  local np=$(ghcup --offline whereis -d ghc $1 || { ghcup --cache install ghc $1 && ghcup whereis -d ghc $1 ;})+  if [ -e "${np}" ] ; then+    shift+    PATH="$np:$PATH" "$@"+  else+    >&2 echo "Cannot find or install GHC version $1"+    return 1+  fi+}+```++For fish shell, in e.g. `~/.config/fish/config.fish` define:++```fish+function with_ghc+  set --local np (ghcup --offline whereis -d ghc $argv[1] ; or begin ghcup --cache install ghc $argv[1] ; and ghcup whereis -d ghc $argv[1] ; end)+  if test -e "$np"+    PATH="$np:$PATH" $argv[2..-1]+  else+    echo "Cannot find or install GHC version $argv[1]" 1>&2+    return 1+  end+end+```++Then start a new shell and issue:++```sh+# replace 'code' with your editor+with_ghc 8.10.5 code path/to/haskell/source+```++Cabal and HLS will now see `8.10.5` as the primary GHC, without the need to+run `ghcup set` all the time when switching between projects.+ ## Design goals  1. simplicity@@ -180,8 +437,13 @@  ## Known users -* Github action [haskell/actions/setup](https://github.com/haskell/actions/tree/main/setup)-* [vabal](https://github.com/Franciman/vabal)+* Github actions:+	- [actions/virtual-environments](https://github.com/actions/virtual-environments)+	- [haskell/actions/setup](https://github.com/haskell/actions/tree/main/setup)+* mirrors:+	- [sjtug](https://mirror.sjtu.edu.cn/docs/ghcup)+* tools:+	- [vabal](https://github.com/Franciman/vabal)  ## Known problems @@ -228,16 +490,110 @@ the correct dependencies. Refer to [the official docs](https://ghc.haskell.org/trac/ghc/wiki/Building/Preparation/Linux) on how to prepare your environment for building GHC. +### Stack support++There may be a number of bugs when trying to make ghcup installed GHC versions work with stack,+such as:++- https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/188++Further, stack's upgrade procedure may break/confuse ghcup. There are a number of integration+issues discussed here:++- https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/153++### Windows support++Windows support is in early stages. Since windows doesn't support symbolic links properly,+ghcup uses a [shimgen wrapper](https://github.com/71/scoop-better-shimexe). It seems to work+well, but there may be unknown issues with that approach.++Windows 7 and Powershell 2.0 aren't well supported at the moment, also see:++- https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/140+- https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/197+ ## FAQ -1. Why reimplement stack?+### Why reimplement stack? -ghcup is not a reimplementation of stack. The only common part is automatic installation of GHC, but even that differs in scope and design.+GHCup is not a reimplementation of stack. The only common part is automatic installation of GHC,+but even that differs in scope and design. -2. Why not support windows?+### Why should I use ghcup over stack? -Consider using [Chocolatey](https://chocolatey.org/search?q=ghc) or [ghcups](https://github.com/kakkun61/ghcups).+GHCup is not a replacement for stack. Instead, it supports installing and managing stack versions.+It does the same for cabal, GHC and HLS. As such, It doesn't make a workflow choice for you. -3. Why the haskell reimplementation?+### Why should I let ghcup manage stack? -Why not?+You don't need to. However, some users seem to prefer to have a central tool that manages cabal and stack+at the same time. Additionally, it can allow better sharing of GHC installation across these tools.+Also see:++* https://docs.haskellstack.org/en/stable/yaml_configuration/#system-ghc+* https://github.com/commercialhaskell/stack/pull/5585++### Why does ghcup not use stack code?++Oddly, this question has been asked a couple of times. For the curious, here are a few reasons:++1. GHCup started as a shell script. At the time of rewriting it in Haskell, the authors didn't even know that stack exposes *some* of its [installation API](https://hackage.haskell.org/package/stack-2.5.1.1/docs/Stack-Setup.html)+2. Even if they did, it doesn't seem it would have satisfied their needs+	  - it didn't support cabal installation, which was the main motivation behind GHCup back then+	  - depending on a codebase as big as stack for a central part of one's application without having a short contribution pipeline would likely have caused stagnation or resulted in simply copy-pasting the relevant code in order to adjust it+	  - it's not clear how GHCup would have been implemented with the provided API. It seems the codebases are fairly different. GHCup does a lot of symlink handling to expose a central `bin/` directory that users can easily put in PATH, without having to worry about anything more. It also provides explicit removal functionality, GHC cross-compilation, a TUI, etc etc.+3. GHCup is built around unix principles and supposed to be simple.++### Why not unify...++#### ...stack and Cabal and do away with standalone installers++GHCup is not involved in such decisions. cabal-install and stack might have a+sufficiently different user experience to warrant having a choice.++#### ...installer implementations and have a common library++This sounds like an interesting goal. However, GHC installation isn't a hard engineering problem+and the shared code wouldn't be too exciting. For such an effort to make sense, all involved+parties would need to collaborate and have a short pipeline to get patches in.++It's true this would solve the integration problem, but following unix principles, we can+do similar via **hooks**. Both cabal and stack can support installation hooks. These hooks+can then call into ghcup or anything else, also see:++* https://github.com/haskell/cabal/issues/7394+* https://github.com/commercialhaskell/stack/pull/5585++#### ...installers (like, all of it)++So far, there hasn't been an **open** discussion about this. Is this even a good idea?+Sometimes projects converge eventually if their overlap is big enough, sometimes they don't.++While unification sounds like a simplification of the ecosystem, it also takes away choice.+Take `curl` and `wget` as an example.++How bad do we need this?++### Why not support windows?++Windows is supported since GHCup version 0.1.15.1.++### Why the haskell reimplementation?++GHCup started as a portable posix shell script of maybe 50 LOC. GHC installation itself can be carried out in+about ~3 lines of shell code (download, unpack , configure+make install). However, much convenient functionality+has been added since, as well as ensuring that all operations are safe and correct. The shell script ended up with+over 2k LOC, which was very hard to maintain.++The main concern when switching from a portable shell script to haskell was platform/architecture support.+However, ghcup now re-uses GHCs CI infrastructure and as such is perfectly in sync with all platforms that+GHC supports.++### Is GHCup affiliated with the Haskell Foundation?++There has been some collaboration: Windows and Stack support were mainly requested by the Haskell Foundation+and those seemed interesting features to add.++Other than that, GHCup is dedicated only to its users and is supported by haskell.org through hosting and CI+infrastructure.
− RELEASING.md
@@ -1,19 +0,0 @@-# RELEASING--1. update `GHCup.Version` module. `ghcupURL` must only be updated if we change the `_toolRequirements` type or the YAML representation of it. The version of the YAML represents the change increments. `ghcUpVer` is the current application version.--2. Update version in ghcup.cabal--3. Add ChangeLog entry--4. Add/fix downloads in `ghcup-<ver>.yaml`, then verify with `ghcup-gen check -f ghcup-<ver>.yaml`--5. Commit and git push with tag. Wait for tests to succeed and release artifacts to build.--6. Download release artifacts and upload them `downloads.haskell.org/ghcup`--7. Add release artifacts to yaml file (see point 4.)--8. Upload the final `ghcup-<ver>.yaml` to `webhost.haskell.org/ghcup/data/`.--9. Update bootstrap-haskell and symlinks on `downloads.haskell.org/ghcup`
app/ghcup-gen/Main.hs view
@@ -11,22 +11,33 @@ module Main where  import           GHCup.Types-import           GHCup.Types.JSON               ( )+import           GHCup.Errors+import           GHCup.Platform+import           GHCup.Utils.Dirs import           GHCup.Utils.Logger+import           GHCup.Types.JSON               ( ) +import           Control.Monad.Trans.Reader     ( runReaderT )+import           Control.Monad.IO.Class import           Data.Char                      ( toLower )+import           Data.Maybe #if !MIN_VERSION_base(4,13,0) import           Data.Semigroup                 ( (<>) ) #endif import           Options.Applicative     hiding ( style )+import           Haskus.Utils.Variant.Excepts import           System.Console.Pretty+import           System.Environment import           System.Exit-import           System.IO                      ( stdout )+import           System.IO                      ( stderr ) import           Text.Regex.Posix import           Validate+import           Text.PrettyPrint.HughesPJClass ( prettyShow ) +import qualified Data.Text.IO                  as T+import qualified Data.Text                     as T import qualified Data.ByteString               as B-import qualified Data.Yaml                     as Y+import qualified Data.YAML.Aeson               as Y   data Options = Options@@ -69,13 +80,15 @@   long "tarball-filter" <> short 'u' <> metavar "<tool>-<version>" <> value def     <> help "Only check certain tarballs (format: <tool>-<version>)"   where-    def = TarballFilter Nothing (makeRegex ("" :: String))+    def = TarballFilter (Right Nothing) (makeRegex ("" :: String))     readm = do       s <- str       case span (/= '-') s of         (_, []) -> fail "invalid format, missing '-' after the tool name"         (t, v) | [tool] <- [ tool | tool <- [minBound..maxBound], low (show tool) == low t ] ->-          pure (TarballFilter $ Just tool) <*> makeRegexOptsM compIgnoreCase execBlank (drop 1 v)+          pure (TarballFilter $ Right $ Just tool) <*> makeRegexOptsM compIgnoreCase execBlank (drop 1 v)+        (t, v) | [tool] <- [ tool | tool <- [minBound..maxBound], low (show tool) == low t ] ->+          pure (TarballFilter $ Left tool) <*> makeRegexOptsM compIgnoreCase execBlank (drop 1 v)         _ -> fail "invalid tool"     low = fmap toLower @@ -103,28 +116,42 @@  main :: IO () main = do+  no_color <- isJust <$> lookupEnv "NO_COLOR"+  let loggerConfig = LoggerConfig { lcPrintDebug  = True+                                  , consoleOutter = T.hPutStr stderr+                                  , fileOutter    = \_ -> pure ()+                                  , fancyColors   = not no_color+                                  }+  dirs <- liftIO getAllDirs+  let leanAppstate = LeanAppState (Settings True False Never Curl True GHCupURL False GPGNone False) dirs defaultKeyBindings loggerConfig++  pfreq <- (+    flip runReaderT leanAppstate . runE @'[NoCompatiblePlatform, NoCompatibleArch, DistroNotFound] $ platformRequest+    ) >>= \case+            VRight r -> pure r+            VLeft e -> do+              flip runReaderT leanAppstate $ logError $ T.pack $ prettyShow e+              liftIO $ exitWith (ExitFailure 2)++  let appstate = AppState (Settings True False Never Curl True GHCupURL False GPGNone False) dirs defaultKeyBindings (GHCupInfo mempty mempty mempty) pfreq loggerConfig+   _ <- customExecParser (prefs showHelpOnError) (info (opts <**> helper) idm)     >>= \Options {..} -> case optCommand of-          ValidateYAML vopts -> case vopts of-            ValidateYAMLOpts { vInput = Nothing } ->-              B.getContents >>= valAndExit validate-            ValidateYAMLOpts { vInput = Just StdInput } ->-              B.getContents >>= valAndExit validate-            ValidateYAMLOpts { vInput = Just (FileInput file) } ->-              B.readFile file >>= valAndExit validate-          ValidateTarballs vopts tarballFilter -> case vopts of-            ValidateYAMLOpts { vInput = Nothing } ->-              B.getContents >>= valAndExit (validateTarballs tarballFilter)-            ValidateYAMLOpts { vInput = Just StdInput } ->-              B.getContents >>= valAndExit (validateTarballs tarballFilter)-            ValidateYAMLOpts { vInput = Just (FileInput file) } ->-              B.readFile file >>= valAndExit (validateTarballs tarballFilter)+          ValidateYAML vopts -> withValidateYamlOpts vopts (\dl m -> flip runReaderT appstate $ validate dl m)+          ValidateTarballs vopts tarballFilter -> withValidateYamlOpts vopts (\dl m -> flip runReaderT appstate $ validateTarballs tarballFilter dl m)   pure ()   where+  withValidateYamlOpts vopts f = case vopts of+    ValidateYAMLOpts { vInput = Nothing } ->+      B.getContents >>= valAndExit f+    ValidateYAMLOpts { vInput = Just StdInput } ->+      B.getContents >>= valAndExit f+    ValidateYAMLOpts { vInput = Just (FileInput file) } ->+      B.readFile file >>= valAndExit f   valAndExit f contents = do-    (GHCupInfo _ av) <- case Y.decodeEither' contents of+    (GHCupInfo _ av gt) <- case Y.decode1Strict contents of       Right r -> pure r-      Left  e -> die (color Red $ show e)-    myLoggerT (LoggerConfig True (B.hPut stdout) (\_ -> pure ())) (f av)+      Left  (_, e) -> die (color Red $ show e)+    f av gt       >>= exitWith
app/ghcup-gen/Validate.hs view
@@ -5,6 +5,7 @@ {-# LANGUAGE TemplateHaskell  #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE ViewPatterns     #-}+{-# LANGUAGE OverloadedStrings #-}  module Validate where @@ -17,15 +18,11 @@ import           GHCup.Utils.Logger import           GHCup.Utils.Version.QQ -#if defined(TAR)-import qualified Codec.Archive.Tar             as Tar-#else import           Codec.Archive-#endif+import           Control.Applicative import           Control.Exception.Safe import           Control.Monad import           Control.Monad.IO.Class-import           Control.Monad.Logger import           Control.Monad.Reader.Class import           Control.Monad.Trans.Class      ( lift ) import           Control.Monad.Trans.Reader     ( runReaderT )@@ -35,19 +32,15 @@ import           Data.Containers.ListUtils      ( nubOrd ) import           Data.IORef import           Data.List-import           Data.String.Interpolate import           Data.Versions-import           HPath                          ( toFilePath ) import           Haskus.Utils.Variant.Excepts import           Optics+import           System.FilePath import           System.Exit-import           System.IO-import           System.Posix.FilePath import           Text.ParserCombinators.ReadP import           Text.PrettyPrint.HughesPJClass ( prettyShow ) import           Text.Regex.Posix -import qualified Data.ByteString               as B import qualified Data.Map.Strict               as M import qualified Data.Text                     as T import qualified Data.Version                  as V@@ -65,10 +58,11 @@   liftIO $ modifyIORef ref (+ 1)  -validate :: (Monad m, MonadLogger m, MonadThrow m, MonadIO m, MonadUnliftIO m)+validate :: (Monad m, MonadReader env m, HasLog env, MonadThrow m, MonadIO m, MonadUnliftIO m)          => GHCupDownloads+         -> M.Map GlobalTool DownloadInfo          -> m ExitCode-validate dls = do+validate dls _ = do   ref <- liftIO $ newIORef 0    -- verify binary downloads --@@ -91,36 +85,39 @@     if e > 0       then pure $ ExitFailure e       else do-        lift $ $(logInfo) [i|All good|]+        lift $ logInfo "All good"         pure ExitSuccess  where   checkHasRequiredPlatforms t v tags arch pspecs = do     let v' = prettyVer v         arch' = prettyShow arch     when (notElem (Linux UnknownLinux) pspecs) $ do-      lift $ $(logError)-        [i|Linux UnknownLinux missing for for #{t} #{v'} #{arch'}|]+      lift $ logError $+        "Linux UnknownLinux missing for for " <> T.pack (prettyShow t) <> " " <> v' <> " " <> T.pack arch'       addError     when ((notElem Darwin pspecs) && arch == A_64) $ do-      lift $ $(logError) [i|Darwin missing for #{t} #{v'} #{arch'}|]+      lift $ logError $ "Darwin missing for for " <> T.pack (prettyShow t) <> " " <> v' <> " " <> T.pack arch'       addError-    when ((notElem FreeBSD pspecs) && arch == A_64) $ lift $ $(logWarn)-      [i|FreeBSD missing for #{t} #{v'} #{arch'}|]+    when ((notElem FreeBSD pspecs) && arch == A_64) $ lift $ logWarn $+      "FreeBSD missing for for " <> T.pack (prettyShow t) <> " " <> v' <> " " <> T.pack arch'+    when (notElem Windows pspecs && arch == A_64) $ do+      lift $ logError $ "Windows missing for for " <> T.pack (prettyShow t) <> " " <> v' <> " " <> T.pack arch'+      addError      -- alpine needs to be set explicitly, because     -- we cannot assume that "Linux UnknownLinux" runs on Alpine     -- (although it could be static)     when (notElem (Linux Alpine) pspecs) $       case t of-        GHCup | arch `elem` [A_64, A_32] -> lift ($(logError) [i|Linux Alpine missing for #{t} #{v'} #{arch}|]) >> addError+        GHCup | arch `elem` [A_64, A_32] -> lift (logError $ "Linux Alpine missing for " <> T.pack (prettyShow t) <> " " <> v' <> " " <> T.pack (prettyShow arch)) >> addError         Cabal | v > [vver|2.4.1.0|]-              , arch `elem` [A_64, A_32] -> lift ($(logError) [i|Linux Alpine missing for #{t} #{v'} #{arch'}|]) >> addError+              , arch `elem` [A_64, A_32] -> lift (logError $ "Linux Alpine missing for " <> T.pack (prettyShow t) <> " " <> v' <> " " <> T.pack (prettyShow arch)) >> addError         GHC | Latest `elem` tags || Recommended `elem` tags-            , arch `elem` [A_64, A_32] -> lift ($(logError) [i|Linux Alpine missing for #{t} #{v'} #{arch'}|])-        _ -> lift $ $(logWarn) [i|Linux Alpine missing for #{t} #{v'} #{arch'}|]+            , arch `elem` [A_64, A_32] -> lift (logError $ "Linux Alpine missing for " <> T.pack (prettyShow t) <> " " <> v' <> " " <> T.pack (prettyShow arch))+        _ -> lift $ logWarn $ "Linux Alpine missing for " <> T.pack (prettyShow t) <> " " <> v' <> " " <> T.pack (prettyShow arch)    checkUniqueTags tool = do-    let allTags = join $ M.elems $ availableToolVersions dls tool+    let allTags = join $ fmap _viTags $ M.elems $ availableToolVersions dls tool     let nonUnique =           fmap fst             .   filter (\(_, b) -> not b)@@ -137,7 +134,7 @@     case join nonUnique of       [] -> pure ()       xs -> do-        lift $ $(logError) [i|Tags not unique for #{tool}: #{xs}|]+        lift $ logError $ "Tags not unique for " <> T.pack (prettyShow tool) <> ": " <> T.pack (prettyShow xs)         addError    where     isUniqueTag Latest         = True@@ -153,24 +150,24 @@       case [ x | (x,"") <- readP_to_S V.parseVersion (T.unpack . prettyVer $ v) ] of         [_] -> pure ()         _   -> do-          lift $ $(logError) [i|GHC version #{v} is not valid |]+          lift $ logError $ "GHC version " <> prettyVer v <> " is not valid"           addError    -- a tool must have at least one of each mandatory tags   checkMandatoryTags tool = do-    let allTags = join $ M.elems $ availableToolVersions dls tool+    let allTags = join $ fmap _viTags $ M.elems $ availableToolVersions dls tool     forM_ [Latest, Recommended] $ \t -> case elem t allTags of       False -> do-        lift $ $(logError) [i|Tag #{t} missing from #{tool}|]+        lift $ logError $ "Tag " <> T.pack (prettyShow t) <> " missing from " <> T.pack (prettyShow tool)         addError       True -> pure ()    -- all GHC versions must have a base tag   checkGHCHasBaseVersion = do     let allTags = M.toList $ availableToolVersions dls GHC-    forM allTags $ \(ver, tags) -> case any isBase tags of+    forM allTags $ \(ver, _viTags -> tags) -> case any isBase tags of       False -> do-        lift $ $(logError) [i|Base tag missing from GHC ver #{ver}|]+        lift $ logError $ "Base tag missing from GHC ver " <> prettyVer ver         addError       True -> pure () @@ -178,91 +175,106 @@   isBase _        = False  data TarballFilter = TarballFilter-  { tfTool    :: Maybe Tool+  { tfTool    :: Either GlobalTool (Maybe Tool)   , tfVersion :: Regex   }  validateTarballs :: ( Monad m-                    , MonadLogger m+                    , MonadReader env m+                    , HasLog env+                    , HasDirs env+                    , HasSettings env                     , MonadThrow m                     , MonadIO m                     , MonadUnliftIO m                     , MonadMask m+                    , Alternative m+                    , MonadFail m                     )                  => TarballFilter                  -> GHCupDownloads+                 -> M.Map GlobalTool DownloadInfo                  -> m ExitCode-validateTarballs (TarballFilter tool versionRegex) dls = do+validateTarballs (TarballFilter etool versionRegex) dls gt = do   ref <- liftIO $ newIORef 0 -  flip runReaderT ref $ do-     -- download/verify all tarballs-    let dlis = nubOrd $ dls ^.. each-          %& indices (maybe (const True) (==) tool) %> each-          %& indices (matchTest versionRegex . T.unpack . prettyVer)-          % (viSourceDL % _Just `summing` viArch % each % each % each)-    when (null dlis) $ $(logError) [i|no tarballs selected by filter|] *> addError-    forM_ dlis downloadAll+   -- download/verify all tarballs+  let dlis = either (const []) (\tool -> nubOrd $ dls ^.. each %& indices (maybe (const True) (==) tool) %> each %& indices (matchTest versionRegex . T.unpack . prettyVer) % (viSourceDL % _Just `summing` viArch % each % each % each)) etool+  let gdlis = nubOrd $ gt ^.. each+  let allDls = either (const gdlis) (const dlis) etool+  when (null allDls) $ logError "no tarballs selected by filter" *> (flip runReaderT ref addError)+  forM_ allDls (downloadAll ref) -    -- exit-    e <- liftIO $ readIORef ref-    if e > 0-      then pure $ ExitFailure e-      else do-        lift $ $(logInfo) [i|All good|]-        pure ExitSuccess+  -- exit+  e <- liftIO $ readIORef ref+  if e > 0+    then pure $ ExitFailure e+    else do+      logInfo "All good"+      pure ExitSuccess   where-  runLogger = myLoggerT LoggerConfig { lcPrintDebug = True-                                     , colorOutter  = B.hPut stderr-                                     , rawOutter    = \_ -> pure ()-                                     }-  downloadAll dli = do-    dirs <- liftIO getDirs-    let settings = AppState (Settings True False Never Curl False GHCupURL) dirs defaultKeyBindings--    r <--      runLogger-      . flip runReaderT settings-      . runResourceT+  downloadAll :: ( MonadUnliftIO m+                 , MonadIO m+                 , MonadReader env m+                 , HasLog env+                 , HasDirs env+                 , HasSettings env+                 , MonadCatch m+                 , MonadMask m+                 , MonadThrow m+                 )+              => IORef Int+              -> DownloadInfo+              -> m ()+  downloadAll ref dli = do+    r <- runResourceT       . runE @'[DigestError+               , GPGError                , DownloadFailed                , UnknownArchive-#if defined(TAR)-               , Tar.FormatError-#else                , ArchiveResult-#endif                ]       $ do-        p <- liftE $ downloadCached dli Nothing-        fmap (head . splitDirectories . head)-          . liftE-          . getArchiveFiles-          $ p+        case etool of+          Right (Just GHCup) -> do+            tmpUnpack <- lift mkGhcupTmpDir+            _ <- liftE $ download (_dlUri dli) Nothing (Just (_dlHash dli)) tmpUnpack Nothing False+            pure Nothing+          Right _ -> do+            p <- liftE $ downloadCached dli Nothing+            fmap (Just . head . splitDirectories . head)+              . liftE+              . getArchiveFiles+              $ p+          Left ShimGen -> do+            tmpUnpack <- lift mkGhcupTmpDir+            _ <- liftE $ download (_dlUri dli) Nothing (Just (_dlHash dli)) tmpUnpack Nothing False+            pure Nothing     case r of-      VRight basePath -> do+      VRight (Just basePath) -> do         case _dlSubdir dli of-          Just (RealDir (toFilePath -> prel)) -> do-            lift $ $(logInfo)-              [i|verifying subdir: #{prel}|]+          Just (RealDir prel) -> do+            logInfo+              $ " verifying subdir: " <> T.pack prel             when (basePath /= prel) $ do-              lift $ $(logError)-                [i|Subdir doesn't match: expected "#{prel}", got "#{basePath}"|]-              addError+              logError $+                "Subdir doesn't match: expected " <> T.pack prel <> ", got " <> T.pack basePath+              (flip runReaderT ref addError)           Just (RegexDir regexString) -> do-            lift $ $(logInfo)-              [i|verifying subdir (regex): #{regexString}|]+            logInfo $+              "verifying subdir (regex): " <> T.pack regexString             let regex = makeRegexOpts                   compIgnoreCase                   execBlank                   regexString             when (not (match regex basePath)) $ do-              lift $ $(logError)-                [i|Subdir doesn't match: expected regex "#{regexString}", got "#{basePath}"|]-              addError+              logError $+                "Subdir doesn't match: expected regex " <> T.pack regexString <> ", got " <> T.pack basePath+              (flip runReaderT ref addError)           Nothing -> pure ()+      VRight Nothing -> pure ()       VLeft  e -> do-        lift $ $(logError)-          [i|Could not download (or verify hash) of #{dli}, Error was: #{e}|]-        addError+        logError $+          "Could not download (or verify hash) of " <> T.pack (show dli) <> ", Error was: " <> T.pack (prettyShow e)+        (flip runReaderT ref addError)
app/ghcup/BrickMain.hs view
@@ -6,16 +6,18 @@ {-# LANGUAGE TemplateHaskell   #-} {-# LANGUAGE TypeApplications  #-} {-# LANGUAGE ViewPatterns      #-}+{-# LANGUAGE RankNTypes        #-}  module BrickMain where  import           GHCup import           GHCup.Download import           GHCup.Errors-import           GHCup.Types+import           GHCup.Types         hiding ( LeanAppState(..) ) import           GHCup.Utils-import           GHCup.Utils.File import           GHCup.Utils.Logger+import           GHCup.Utils.Prelude ( decUTF8Safe )+import           GHCup.Utils.File  import           Brick import           Brick.Widgets.Border@@ -25,48 +27,44 @@                                                 , listSelectedAttr                                                 , listAttr                                                 )-#if !defined(TAR) import           Codec.Archive-#endif import           Control.Exception.Safe-import           Control.Monad.Logger import           Control.Monad.Reader+import           Control.Monad.Trans.Except import           Control.Monad.Trans.Resource import           Data.Bool import           Data.Functor import           Data.List import           Data.Maybe import           Data.IORef-import           Data.String.Interpolate import           Data.Vector                    ( Vector                                                 , (!?)                                                 ) import           Data.Versions           hiding ( str ) import           Haskus.Utils.Variant.Excepts import           Prelude                 hiding ( appendFile )-import           System.Environment import           System.Exit import           System.IO.Unsafe import           Text.PrettyPrint.HughesPJClass ( prettyShow ) import           URI.ByteString -import qualified GHCup.Types                   as GT- import qualified Data.Text                     as T import qualified Graphics.Vty                  as Vty import qualified Data.Vector                   as V  +hiddenTools :: [Tool]+hiddenTools = [] + data BrickData = BrickData   { lr    :: [ListResult]-  , dls   :: GHCupDownloads-  , pfreq :: PlatformRequest   }   deriving Show  data BrickSettings = BrickSettings-  { showAll :: Bool+  { showAllVersions :: Bool+  , showAllTools    :: Bool   }   deriving Show @@ -95,19 +93,24 @@   [ (bQuit, const "Quit"     , halt)   , (bInstall, const "Install"  , withIOAction install')   , (bUninstall, const "Uninstall", withIOAction del')-  , (bSet, const "Set"      , withIOAction set')+  , (bSet, const "Set"      , withIOAction ((liftIO .) . set'))   , (bChangelog, const "ChangeLog", withIOAction changelog')-  , ( bShowAll+  , ( bShowAllVersions     , \BrickSettings {..} ->-       if showAll then "Hide old versions" else "Show all versions"-    , hideShowHandler+       if showAllVersions then "Don't show all versions" else "Show all versions"+    , hideShowHandler (not . showAllVersions) showAllTools     )+  , ( bShowAllTools+    , \BrickSettings {..} ->+       if showAllTools then "Don't show all tools" else "Show all tools"+    , hideShowHandler showAllVersions (not . showAllTools)+    )   , (bUp, const "Up", \BrickState {..} -> continue BrickState{ appState = moveCursor 1 appState Up, .. })   , (bDown, const "Down", \BrickState {..} -> continue BrickState{ appState = moveCursor 1 appState Down, .. })   ]  where-  hideShowHandler BrickState{..} =-    let newAppSettings   = appSettings { showAll = not . showAll $ appSettings }+  hideShowHandler f p BrickState{..} =+    let newAppSettings   = appSettings { showAllVersions = f appSettings , showAllTools = p appSettings }         newInternalState = constructList appData newAppSettings (Just appState)     in  continue (BrickState appData newAppSettings newInternalState appKeys) @@ -161,7 +164,7 @@           | elem Latest lTag && not lInstalled =               withAttr "hooray"           | otherwise = id-        active = if b then forceAttr "active" else id+        active = if b then putCursor "GHCup" (Location (0,0)) . forceAttr "active" else id     in  hooray $ active $ dim           (   marks           <+> padLeft (Pad 2)@@ -194,6 +197,7 @@   printTool GHC = str "GHC"   printTool GHCup = str "GHCup"   printTool HLS = str "HLS"+  printTool Stack = str "Stack"    printNotes ListResult {..} =     (if hlsPowered then [withAttr "hls-powered" $ str "hls-powered"] else mempty@@ -248,7 +252,7 @@   , appHandleEvent  = eventHandler   , appStartEvent   = return   , appAttrMap      = const attrs-  , appChooseCursor = neverShowCursor+  , appChooseCursor = showFirstCursor   }  defaultAttributes :: Bool -> AttrMap@@ -316,21 +320,25 @@  -- | Suspend the current UI and run an IO action in terminal. If the -- IO action returns a Left value, then it's thrown as userError.-withIOAction :: (BrickState -> (Int, ListResult) -> IO (Either String a))+withIOAction :: (BrickState+                 -> (Int, ListResult)+                 -> ReaderT AppState IO (Either String a))              -> BrickState              -> EventM n (Next BrickState) withIOAction action as = case listSelectedElement' (appState as) of   Nothing      -> continue as-  Just (ix, e) -> suspendAndResume $ do-    action as (ix, e) >>= \case-      Left  err -> putStrLn ("Error: " <> err)-      Right _   -> putStrLn "Success"-    getAppData Nothing (pfreq . appData $ as) >>= \case-      Right data' -> do-        putStrLn "Press enter to continue"-        _ <- getLine-        pure (updateList data' as)-      Left err -> throwIO $ userError err+  Just (ix, e) -> do+    suspendAndResume $ do+      settings <- readIORef settings'+      flip runReaderT settings $ action as (ix, e) >>= \case+        Left  err -> liftIO $ putStrLn ("Error: " <> err)+        Right _   -> liftIO $ putStrLn "Success"+      getAppData Nothing >>= \case+        Right data' -> do+          putStrLn "Press enter to continue"+          _ <- getLine+          pure (updateList data' as)+        Left err -> throwIO $ userError err   -- | Update app data and list internal state based on new evidence.@@ -351,7 +359,9 @@               -> Maybe BrickInternalState               -> BrickInternalState constructList appD appSettings =-  replaceLR (filterVisible (showAll appSettings)) (lr appD)+  replaceLR (filterVisible (showAllVersions appSettings)+                           (showAllTools appSettings))+            (lr appD)  listSelectedElement' :: BrickInternalState -> Maybe (Int, ListResult) listSelectedElement' BrickInternalState{..} = fmap (ix, ) $ clr !? ix@@ -384,27 +394,32 @@     lTool e1 == lTool e2 && lVer e1 == lVer e2 && lCross e1 == lCross e2  -filterVisible :: Bool -> ListResult -> Bool-filterVisible showAll e | lInstalled e = True-                        | showAll      = True-                        | otherwise    = not (elem Old (lTag e))+filterVisible :: Bool -> Bool -> ListResult -> Bool+filterVisible v t e | lInstalled e = True+                    | v+                    , not t+                    , not (elem (lTool e) hiddenTools) = True+                    | not v+                    , t+                    , not (elem Old (lTag e)) = True+                    | v+                    , t = True+                    | otherwise = not (elem Old (lTag e)) &&+                                  not (elem (lTool e) hiddenTools)  -install' :: BrickState -> (Int, ListResult) -> IO (Either String ())-install' BrickState { appData = BrickData {..} } (_, ListResult {..}) = do-  settings <- readIORef settings'-  l        <- readIORef logger'-  let runLogger = myLoggerT l+install' :: (MonadReader AppState m, MonadIO m, MonadThrow m, MonadFail m, MonadMask m, MonadUnliftIO m)+         => BrickState+         -> (Int, ListResult)+         -> m (Either String ())+install' _ (_, ListResult {..}) = do+  AppState { ghcupInfo = GHCupInfo { _ghcupDownloads = dls }} <- ask    let run =-        runLogger-          . flip runReaderT settings-          . runResourceT+        runResourceT           . runE             @'[ AlreadyInstalled-#if !defined(TAR)               , ArchiveResult-#endif               , UnknownArchive               , FileDoesNotExistError               , CopyError@@ -413,46 +428,49 @@               , BuildFailed               , TagNotFound               , DigestError+              , GPGError               , DownloadFailed+              , DirNotEmpty               , NoUpdate               , TarDirDoesNotExist+              , FileAlreadyExistsError               ]    run (do       case lTool of         GHC   -> do           let vi = getVersionInfo lVer GHC dls-          liftE $ installGHCBin dls lVer pfreq $> vi+          liftE $ installGHCBin lVer Nothing False $> vi         Cabal -> do           let vi = getVersionInfo lVer Cabal dls-          liftE $ installCabalBin dls lVer pfreq $> vi+          liftE $ installCabalBin lVer Nothing False $> vi         GHCup -> do           let vi = snd <$> getLatest dls GHCup-          liftE $ upgradeGHCup dls Nothing False pfreq $> vi+          liftE $ upgradeGHCup Nothing False $> vi         HLS   -> do           let vi = getVersionInfo lVer HLS dls-          liftE $ installHLSBin dls lVer pfreq $> vi+          liftE $ installHLSBin lVer Nothing False $> vi+        Stack -> do+          let vi = getVersionInfo lVer Stack dls+          liftE $ installStackBin lVer Nothing False $> vi     )     >>= \case           VRight vi                         -> do             forM_ (_viPostInstall =<< vi) $ \msg ->-              runLogger $ $(logInfo) msg+              logInfo msg             pure $ Right ()           VLeft  (V (AlreadyInstalled _ _)) -> pure $ Right ()           VLeft (V NoUpdate) -> pure $ Right ()-          VLeft e -> pure $ Left [i|#{prettyShow e}-Also check the logs in ~/.ghcup/logs|]+          VLeft e -> pure $ Left $ prettyShow e <> "\n"+            <> "Also check the logs in ~/.ghcup/logs"   set' :: BrickState -> (Int, ListResult) -> IO (Either String ()) set' _ (_, ListResult {..}) = do   settings <- readIORef settings'-  l        <- readIORef logger'-  let runLogger = myLoggerT l    let run =-        runLogger-          . flip runReaderT settings+        flip runReaderT settings           . runE @'[FileDoesNotExistError , NotInstalled , TagNotFound]    run (do@@ -460,6 +478,7 @@         GHC   -> liftE $ setGHC (GHCTargetVersion lCross lVer) SetGHCOnly $> ()         Cabal -> liftE $ setCabal lVer $> ()         HLS   -> liftE $ setHLS lVer $> ()+        Stack -> liftE $ setStack lVer $> ()         GHCup -> pure ()     )     >>= \case@@ -467,13 +486,14 @@           VLeft  e -> pure $ Left (prettyShow e)  -del' :: BrickState -> (Int, ListResult) -> IO (Either String ())-del' BrickState { appData = BrickData {..} } (_, ListResult {..}) = do-  settings <- readIORef settings'-  l        <- readIORef logger'-  let runLogger = myLoggerT l+del' :: (MonadReader AppState m, MonadIO m, MonadFail m, MonadMask m, MonadUnliftIO m)+     => BrickState+     -> (Int, ListResult)+     -> m (Either String ())+del' _ (_, ListResult {..}) = do+  AppState { ghcupInfo = GHCupInfo { _ghcupDownloads = dls }} <- ask -  let run = runLogger . flip runReaderT settings . runE @'[NotInstalled]+  let run = runE @'[NotInstalled]    run (do       let vi = getVersionInfo lVer lTool dls@@ -481,27 +501,33 @@         GHC   -> liftE $ rmGHCVer (GHCTargetVersion lCross lVer) $> vi         Cabal -> liftE $ rmCabalVer lVer $> vi         HLS   -> liftE $ rmHLSVer lVer $> vi+        Stack -> liftE $ rmStackVer lVer $> vi         GHCup -> pure Nothing     )     >>= \case           VRight vi -> do             forM_ (join $ fmap _viPostRemove vi) $ \msg ->-              runLogger $ $(logInfo) msg+              logInfo msg             pure $ Right ()           VLeft  e -> pure $ Left (prettyShow e)  -changelog' :: BrickState -> (Int, ListResult) -> IO (Either String ())-changelog' BrickState { appData = BrickData {..} } (_, ListResult {..}) = do+changelog' :: (MonadReader AppState m, MonadIO m)+           => BrickState+           -> (Int, ListResult)+           -> m (Either String ())+changelog' _ (_, ListResult {..}) = do+  AppState { pfreq, ghcupInfo = GHCupInfo { _ghcupDownloads = dls }} <- ask   case getChangeLog dls lTool (Left lVer) of-    Nothing -> pure $ Left-      [i|Could not find ChangeLog for #{lTool}, version #{prettyVer lVer}|]+    Nothing -> pure $ Left $+      "Could not find ChangeLog for " <> prettyShow lTool <> ", version " <> T.unpack (prettyVer lVer)     Just uri -> do       let cmd = case _rPlatform pfreq of             Darwin  -> "open"             Linux _ -> "xdg-open"             FreeBSD -> "xdg-open"-      exec cmd True [serializeURIRef' uri] Nothing Nothing >>= \case+            Windows -> "start"+      exec cmd [T.unpack $ decUTF8Safe $ serializeURIRef' uri] Nothing Nothing >>= \case         Right _ -> pure $ Right ()         Left  e -> pure $ Left $ prettyShow e @@ -509,97 +535,80 @@ settings' :: IORef AppState {-# NOINLINE settings' #-} settings' = unsafePerformIO $ do-  dirs <- getDirs+  dirs <- getAllDirs+  let loggerConfig = LoggerConfig { lcPrintDebug  = False+                                  , consoleOutter = \_ -> pure ()+                                  , fileOutter    = \_ -> pure ()+                                  , fancyColors   = True+                                  }   newIORef $ AppState (Settings { cache      = True                                 , noVerify   = False                                 , keepDirs   = Never                                 , downloader = Curl                                 , verbose    = False                                 , urlSource  = GHCupURL+                                , noNetwork  = False+                                , gpgSetting = GPGNone+                                , noColor    = False                                 , ..                                 })                       dirs                       defaultKeyBindings+                      (GHCupInfo mempty mempty mempty)+                      (PlatformRequest A_64 Darwin Nothing)+                      loggerConfig   -logger' :: IORef LoggerConfig-{-# NOINLINE logger' #-}-logger' = unsafePerformIO-  (newIORef $ LoggerConfig { lcPrintDebug = False-                           , colorOutter  = \_ -> pure ()-                           , rawOutter    = \_ -> pure ()-                           }-  )-- brickMain :: AppState-          -> LoggerConfig-          -> GHCupDownloads-          -> PlatformRequest           -> IO ()-brickMain s l av pfreq' = do+brickMain s = do   writeIORef settings' s-  -- logger interpreter-  writeIORef logger'   l-  let runLogger = myLoggerT l -  no_color <- isJust <$> lookupEnv "NO_COLOR"--  eAppData <- getAppData (Just av) pfreq'+  eAppData <- getAppData (Just $ ghcupInfo s)   case eAppData of     Right ad ->       defaultMain-          (app (defaultAttributes no_color) (dimAttributes no_color))+          (app (defaultAttributes (noColor $ settings s)) (dimAttributes (noColor $ settings s)))           (BrickState ad                     defaultAppSettings                     (constructList ad defaultAppSettings Nothing)-                    (keyBindings s)+                    (keyBindings (s :: AppState))            )         $> ()     Left e -> do-      runLogger ($(logError) [i|Error building app state: #{show e}|])+      flip runReaderT s $ logError $ "Error building app state: " <> T.pack (show e)       exitWith $ ExitFailure 2   defaultAppSettings :: BrickSettings-defaultAppSettings = BrickSettings { showAll = False }+defaultAppSettings = BrickSettings { showAllVersions = False, showAllTools = False }  -getDownloads' :: IO (Either String GHCupDownloads)-getDownloads' = do+getGHCupInfo :: IO (Either String GHCupInfo)+getGHCupInfo = do   settings <- readIORef settings'-  l        <- readIORef logger'-  let runLogger = myLoggerT l    r <--    runLogger-    . flip runReaderT settings-    . runE @'[JSONError , DownloadFailed , FileDoesNotExistError]-    $ fmap _ghcupDownloads+    flip runReaderT settings+    . runE @'[DigestError, GPGError, JSONError , DownloadFailed , FileDoesNotExistError]     $ liftE-    $ getDownloadsF (urlSource . GT.settings $ settings)+    $ getDownloadsF    case r of     VRight a -> pure $ Right a     VLeft  e -> pure $ Left (prettyShow e)  -getAppData :: Maybe GHCupDownloads-           -> PlatformRequest+getAppData :: Maybe GHCupInfo            -> IO (Either String BrickData)-getAppData mg pfreq' = do-  settings <- readIORef settings'-  l        <- readIORef logger'-  let runLogger = myLoggerT l--  r <- maybe getDownloads' (pure . Right) mg+getAppData mgi = runExceptT $ do+  r <- ExceptT $ maybe getGHCupInfo (pure . Right) mgi+  liftIO $ modifyIORef settings' (\s -> s { ghcupInfo = r })+  settings <- liftIO $ readIORef settings' -  runLogger . flip runReaderT settings $ do-    case r of-      Right dls -> do-        lV <- listVersions dls Nothing Nothing pfreq'-        pure $ Right $ BrickData (reverse lV) dls pfreq'-      Left e -> pure $ Left [i|#{e}|]+  flip runReaderT settings $ do+    lV <- listVersions Nothing Nothing+    pure $ BrickData (reverse lV) 
app/ghcup/Main.hs view
@@ -21,1846 +21,3080 @@ import           GHCup.Platform import           GHCup.Requirements import           GHCup.Types-import           GHCup.Utils-import           GHCup.Utils.File-import           GHCup.Utils.Logger-import           GHCup.Utils.MegaParsec-import           GHCup.Utils.Prelude-import           GHCup.Utils.String.QQ-import           GHCup.Version--#if !defined(TAR)-import           Codec.Archive-#endif-import           Control.Concurrent-import           Control.Exception.Safe-#if !MIN_VERSION_base(4,13,0)-import           Control.Monad.Fail             ( MonadFail )-#endif-import           Control.Monad.Logger-import           Control.Monad.Reader-import           Control.Monad.Trans.Resource-import           Data.Bifunctor-import           Data.Char-import           Data.Either-import           Data.Functor-import           Data.List                      ( intercalate, nub, sort, sortBy )-import           Data.List.NonEmpty             (NonEmpty ((:|)))-import           Data.Maybe-import           Data.String.Interpolate-import           Data.Text                      ( Text )-import           Data.Versions           hiding ( str )-import           Data.Void-import           GHC.IO.Encoding-import           Haskus.Utils.Variant.Excepts-import           HPath-import           HPath.IO-import           Language.Haskell.TH-import           Options.Applicative     hiding ( style )-import           Options.Applicative.Help.Pretty ( text )-import           Prelude                 hiding ( appendFile )-import           Safe-import           System.Console.Pretty   hiding ( color )-import qualified System.Console.Pretty         as Pretty-import           System.Environment-import           System.Exit-import           System.IO               hiding ( appendFile )-import           Text.Read               hiding ( lift )-import           Text.PrettyPrint.HughesPJClass ( prettyShow )-import           URI.ByteString--import qualified Data.ByteString               as B-import qualified Data.ByteString.UTF8          as UTF8-import qualified Data.Map.Strict               as M-import qualified Data.Text                     as T-import qualified Data.Text.IO                  as T-import qualified Data.Text.Encoding            as E-import qualified Text.Megaparsec               as MP-import qualified Text.Megaparsec.Char          as MPC------data Options = Options-  {-  -- global options-    optVerbose   :: Maybe Bool-  , optCache     :: Maybe Bool-  , optUrlSource :: Maybe URI-  , optNoVerify  :: Maybe Bool-  , optKeepDirs  :: Maybe KeepDirs-  , optsDownloader :: Maybe Downloader-  -- commands-  , optCommand   :: Command-  }--data Command-  = Install (Either InstallCommand InstallOptions)-  | InstallCabalLegacy InstallOptions-  | Set (Either SetCommand SetOptions)-  | List ListOptions-  | Rm (Either RmCommand RmOptions)-  | DInfo-  | Compile CompileCommand-  | Upgrade UpgradeOpts Bool-  | ToolRequirements-  | ChangeLog ChangeLogOptions-#if defined(BRICK)-  | Interactive-#endif--data ToolVersion = ToolVersion GHCTargetVersion -- target is ignored for cabal-                 | ToolTag Tag--prettyToolVer :: ToolVersion -> String-prettyToolVer (ToolVersion v') = T.unpack $ tVerToText v'-prettyToolVer (ToolTag t) = show t--toSetToolVer :: Maybe ToolVersion -> SetToolVersion-toSetToolVer (Just (ToolVersion v')) = SetToolVersion v'-toSetToolVer (Just (ToolTag t')) = SetToolTag t'-toSetToolVer Nothing = SetRecommended---data InstallCommand = InstallGHC InstallOptions-                    | InstallCabal InstallOptions-                    | InstallHLS InstallOptions--data InstallOptions = InstallOptions-  { instVer      :: Maybe ToolVersion-  , instPlatform :: Maybe PlatformRequest-  , instBindist  :: Maybe URI-  , instSet      :: Bool-  }--data SetCommand = SetGHC SetOptions-                | SetCabal SetOptions-                | SetHLS SetOptions---- a superset of ToolVersion-data SetToolVersion = SetToolVersion GHCTargetVersion-                    | SetToolTag Tag-                    | SetRecommended-                    | SetNext--data SetOptions = SetOptions-  { sToolVer :: SetToolVersion-  }--data ListOptions = ListOptions-  { loTool     :: Maybe Tool-  , lCriteria  :: Maybe ListCriteria-  , lRawFormat :: Bool-  }--data RmCommand = RmGHC RmOptions-               | RmCabal Version-               | RmHLS Version--data RmOptions = RmOptions-  { ghcVer :: GHCTargetVersion-  }---data CompileCommand = CompileGHC GHCCompileOptions---data GHCCompileOptions = GHCCompileOptions-  { targetVer    :: Version-  , bootstrapGhc :: Either Version (Path Abs)-  , jobs         :: Maybe Int-  , buildConfig  :: Maybe (Path Abs)-  , patchDir     :: Maybe (Path Abs)-  , crossTarget  :: Maybe Text-  , addConfArgs  :: [Text]-  , setCompile   :: Bool-  }--data CabalCompileOptions = CabalCompileOptions-  { targetVer    :: Version-  , bootstrapGhc :: Either Version (Path Abs)-  , jobs         :: Maybe Int-  , buildConfig  :: Maybe (Path Abs)-  , patchDir     :: Maybe (Path Abs)-  }--data UpgradeOpts = UpgradeInplace-                 | UpgradeAt (Path Abs)-                 | UpgradeGHCupDir-                 deriving Show--data ChangeLogOptions = ChangeLogOptions-  { clOpen    :: Bool-  , clTool    :: Maybe Tool-  , clToolVer :: Maybe ToolVersion-  }----- https://github.com/pcapriotti/optparse-applicative/issues/148---- | A switch that can be enabled using --foo and disabled using --no-foo.------ The option modifier is applied to only the option that is *not* enabled--- by default. For example:------ > invertableSwitch "recursive" True (help "do not recurse into directories")------ This example makes --recursive enabled by default, so--- the help is shown only for --no-recursive.-invertableSwitch-    :: String              -- ^ long option-    -> Char                -- ^ short option for the non-default option-    -> Bool                -- ^ is switch enabled by default?-    -> Mod FlagFields Bool -- ^ option modifier-    -> Parser (Maybe Bool)-invertableSwitch longopt shortopt defv optmod = invertableSwitch' longopt shortopt defv-    (if defv then mempty else optmod)-    (if defv then optmod else mempty)---- | Allows providing option modifiers for both --foo and --no-foo.-invertableSwitch'-    :: String              -- ^ long option (eg "foo")-    -> Char                -- ^ short option for the non-default option-    -> Bool                -- ^ is switch enabled by default?-    -> Mod FlagFields Bool -- ^ option modifier for --foo-    -> Mod FlagFields Bool -- ^ option modifier for --no-foo-    -> Parser (Maybe Bool)-invertableSwitch' longopt shortopt defv enmod dismod = optional-    ( flag' True (enmod <> long longopt <> if defv then mempty else short shortopt)-    <|> flag' False (dismod <> long nolongopt <> if defv then short shortopt else mempty)-    )-  where-    nolongopt = "no-" ++ longopt---opts :: Parser Options-opts =-  Options-    <$> invertableSwitch "verbose" 'v' False (help "Enable verbosity (default: disabled)")-    <*> invertableSwitch "cache" 'c' False (help "Cache downloads in ~/.ghcup/cache (default: disabled)")-    <*> (optional-          (option-            (eitherReader parseUri)-            (  short 's'-            <> long "url-source"-            <> metavar "URL"-            <> help "Alternative ghcup download info url"-            <> internal-            )-          )-        )-    <*> (fmap . fmap) not (invertableSwitch "verify" 'n' True (help "Disable tarball checksum verification (default: enabled)"))-    <*> optional (option-          (eitherReader keepOnParser)-          (  long "keep"-          <> metavar "<always|errors|never>"-          <> help-               "Keep build directories? (default: errors)"-          <> hidden-          ))-    <*> optional (option-          (eitherReader downloaderParser)-          (  long "downloader"-#if defined(INTERNAL_DOWNLOADER)-          <> metavar "<internal|curl|wget>"-          <> help-          "Downloader to use (default: internal)"-#else-          <> metavar "<curl|wget>"-          <> help-          "Downloader to use (default: curl)"-#endif-          <> hidden-          ))-    <*> com- where-  parseUri s' =-    first show $ parseURI strictURIParserOptions (UTF8.fromString s')---com :: Parser Command-com =-  subparser-#if defined(BRICK)-      (  command-          "tui"-          (   (\_ -> Interactive)-          <$> (info-                helper-                (  progDesc "Start the interactive GHCup UI"-                )-              )-          )-      <>  command-#else-      (  command-#endif-          "install"-          (   Install-          <$> info-                (installParser <**> helper)-                (  progDesc "Install or update GHC/cabal"-                <> footerDoc (Just $ text installToolFooter)-                )-          )-      <> command-           "set"-           (info-             (Set <$> setParser <**> helper)-             (  progDesc "Set currently active GHC/cabal version"-             <> footerDoc (Just $ text setFooter)-             )-           )-      <> command-           "rm"-           (info-             (Rm <$> rmParser <**> helper)-             (  progDesc "Remove a GHC/cabal version"-             <> footerDoc (Just $ text rmFooter)-             )-           )--      <> command-           "list"-           (info (List <$> listOpts <**> helper)-                 (progDesc "Show available GHCs and other tools")-           )-      <> command-           "upgrade"-           (info-             (    (Upgrade <$> upgradeOptsP <*> switch-                    (short 'f' <> long "force" <> help "Force update")-                  )-             <**> helper-             )-             (progDesc "Upgrade ghcup")-           )-      <> command-           "compile"-           (   Compile-           <$> info (compileP <**> helper)-                    (progDesc "Compile a tool from source")-           )-      <> commandGroup "Main commands:"-      )-    <|> subparser-          (  command-              "debug-info"-              ((\_ -> DInfo) <$> info helper (progDesc "Show debug info"))-          <> command-               "tool-requirements"-               (   (\_ -> ToolRequirements)-               <$> info helper-                        (progDesc "Show the requirements for ghc/cabal")-               )-          <> command-               "changelog"-               (info-                  (fmap ChangeLog changelogP <**> helper)-                  (  progDesc "Find/show changelog"-                  <> footerDoc (Just $ text changeLogFooter)-                  )-               )-          <> commandGroup "Other commands:"-          <> hidden-          )-    <|> subparser-          (  command-              "install-cabal"-              (info-                 ((InstallCabalLegacy <$> installOpts (Just Cabal)) <**> helper)-                 (  progDesc "Install or update cabal"-                 <> footerDoc (Just $ text installCabalFooter)-                 )-              )-          <> internal-          )- where-  installToolFooter :: String-  installToolFooter = [s|Discussion:-  Installs GHC or cabal. When no command is given, installs GHC-  with the specified version/tag.-  It is recommended to always specify a subcommand (ghc/cabal/hls).|]--  setFooter :: String-  setFooter = [s|Discussion:-  Sets the currently active GHC or cabal version. When no command is given,-  defaults to setting GHC with the specified version/tag (if no tag-  is given, sets GHC to 'recommended' version).-  It is recommended to always specify a subcommand (ghc/cabal/hls).|]--  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).|]--  changeLogFooter :: String-  changeLogFooter = [s|Discussion:-  By default returns the URI of the ChangeLog of the latest GHC release.-  Pass '-o' to automatically open via xdg-open.|]---installCabalFooter :: String-installCabalFooter = [s|Discussion:-  Installs the specified cabal-install version (or a recommended default one)-  into "~/.ghcup/bin", so it can be overwritten by later-  "cabal install cabal-install", which installs into "~/.cabal/bin" by-  default. Make sure to set up your PATH appropriately, so the cabal-  installation takes precedence.|]---installParser :: Parser (Either InstallCommand InstallOptions)-installParser =-  (Left <$> subparser-      (  command-          "ghc"-          (   InstallGHC-          <$> info-                (installOpts (Just GHC) <**> helper)-                (  progDesc "Install GHC"-                <> footerDoc (Just $ text installGHCFooter)-                )-          )-      <> command-           "cabal"-           (   InstallCabal-           <$> info-                 (installOpts (Just Cabal) <**> helper)-                 (  progDesc "Install Cabal"-                 <> footerDoc (Just $ text installCabalFooter)-                 )-           )-      <> command-           "hls"-           (   InstallHLS-           <$> info-                 (installOpts (Just HLS) <**> helper)-                 (  progDesc "Install haskell-languge-server"-                 <> footerDoc (Just $ text installHLSFooter)-                 )-           )-      )-    )-    <|> (Right <$> installOpts Nothing)- where-  installHLSFooter :: String-  installHLSFooter = [s|Discussion:-  Installs haskell-language-server binaries and wrapper-  into "~/.ghcup/bin"--Examples:-  # install recommended GHC-  ghcup install hls|]--  installGHCFooter :: String-  installGHCFooter = [s|Discussion:-  Installs the specified GHC version (or a recommended default one) into-  a self-contained "~/.ghcup/ghc/<ghcver>" directory-  and symlinks the ghc binaries to "~/.ghcup/bin/<binary>-<ghcver>".--Examples:-  # install recommended GHC-  ghcup install ghc--  # install latest GHC-  ghcup install ghc latest--  # install GHC 8.10.2-  ghcup install ghc 8.10.2--  # install GHC head fedora bindist-  ghcup install ghc -u https://gitlab.haskell.org/api/v4/projects/1/jobs/artifacts/master/raw/ghc-x86_64-fedora27-linux.tar.xz?job=validate-x86_64-linux-fedora27 head|]---installOpts :: Maybe Tool -> Parser InstallOptions-installOpts tool =-  (\p (u, v) b -> InstallOptions v p u b)-    <$> optional-          (option-            (eitherReader platformParser)-            (  short 'p'-            <> long "platform"-            <> metavar "PLATFORM"-            <> help-                 "Override for platform (triple matching ghc tarball names), e.g. x86_64-fedora27-linux"-            )-          )-    <*> (   (   (,)-            <$> optional-                  (option-                    (eitherReader bindistParser)-                    (short 'u' <> long "url" <> metavar "BINDIST_URL" <> help-                      "Install the specified version from this bindist"-                    )-                  )-            <*> (Just <$> toolVersionArgument Nothing tool)-            )-        <|> pure (Nothing, Nothing)-        )-    <*> flag-          False-          True-          (long "set" <> help-            "Set as active version after install"-          )---setParser :: Parser (Either SetCommand SetOptions)-setParser =-  (Left <$> subparser-      (  command-          "ghc"-          (   SetGHC-          <$> info-                (setOpts (Just GHC) <**> helper)-                (  progDesc "Set GHC version"-                <> footerDoc (Just $ text setGHCFooter)-                )-          )-      <> command-           "cabal"-           (   SetCabal-           <$> info-                 (setOpts (Just Cabal) <**> helper)-                 (  progDesc "Set Cabal version"-                 <> footerDoc (Just $ text setCabalFooter)-                 )-           )-      <> command-           "hls"-           (   SetHLS-           <$> info-                 (setOpts (Just HLS) <**> helper)-                 (  progDesc "Set haskell-language-server version"-                 <> footerDoc (Just $ text setHLSFooter)-                 )-           )-      )-    )-    <|> (Right <$> setOpts Nothing)- where-  setGHCFooter :: String-  setGHCFooter = [s|Discussion:-    Sets the the current GHC version by creating non-versioned-    symlinks for all ghc binaries of the specified version in-    "~/.ghcup/bin/<binary>".|]--  setCabalFooter :: String-  setCabalFooter = [s|Discussion:-    Sets the the current Cabal version.|]--  setHLSFooter :: String-  setHLSFooter = [s|Discussion:-    Sets the the current haskell-language-server version.|]---setOpts :: Maybe Tool -> Parser SetOptions-setOpts tool = SetOptions <$>-    (fromMaybe SetRecommended <$>-      optional (setVersionArgument (Just ListInstalled) tool))--listOpts :: Parser ListOptions-listOpts =-  ListOptions-    <$> optional-          (option-            (eitherReader toolParser)-            (short 't' <> long "tool" <> metavar "<ghc|cabal>" <> help-              "Tool to list versions for. Default is all"-            )-          )-    <*> optional-          (option-            (eitherReader criteriaParser)-            (  short 'c'-            <> long "show-criteria"-            <> metavar "<installed|set>"-            <> help "Show only installed or set tool versions"-            )-          )-    <*> switch-          (short 'r' <> long "raw-format" <> help "More machine-parsable format"-          )---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' (Just ListInstalled) (Just Cabal) <**> helper)-                    (progDesc "Remove Cabal version")-           )-      <> command-           "hls"-           (   RmHLS-           <$> info (versionParser' (Just ListInstalled) (Just HLS) <**> helper)-                    (progDesc "Remove haskell-language-server version")-           )-      )-    )-    <|> (Right <$> rmOpts Nothing)----rmOpts :: Maybe Tool -> Parser RmOptions-rmOpts tool = RmOptions <$> versionArgument (Just ListInstalled) tool---changelogP :: Parser ChangeLogOptions-changelogP =-  (\x y -> ChangeLogOptions x y)-    <$> switch (short 'o' <> long "open" <> help "xdg-open the changelog url")-    <*> optional-          (option-            (eitherReader-              (\s' -> case fmap toLower s' of-                "ghc"   -> Right GHC-                "cabal" -> Right Cabal-                "ghcup" -> Right GHCup-                e       -> Left e-              )-            )-            (short 't' <> long "tool" <> metavar "<ghc|cabal|ghcup>" <> help-              "Open changelog for given tool (default: ghc)"-            )-          )-    <*> optional (toolVersionArgument Nothing Nothing)--compileP :: Parser CompileCommand-compileP = subparser-  (  command-      "ghc"-      (   CompileGHC-      <$> info-            (ghcCompileOpts <**> helper)-            (  progDesc "Compile GHC from source"-            <> footerDoc (Just $ text compileFooter)-            )-      )-  )- where-  compileFooter = [s|Discussion:-  Compiles and installs the specified GHC version into-  a self-contained "~/.ghcup/ghc/<ghcver>" directory-  and symlinks the ghc binaries to "~/.ghcup/bin/<binary>-<ghcver>".--  This also allows building a cross-compiler. Consult the documentation-  first: <https://gitlab.haskell.org/ghc/ghc/-/wikis/building/cross-compiling#configuring-the-build>--ENV variables:-  Various toolchain variables will be passed onto the ghc build system,-  such as: CC, LD, OBJDUMP, NM, AR, RANLIB.--Examples:-  ghcup compile ghc -j 4 -v 8.4.2 -b 8.2.2-  # specify path to bootstrap ghc-  ghcup compile ghc -j 4 -v 8.4.2 -b /usr/bin/ghc-8.2.2-  # build cross compiler-  ghcup compile ghc -j 4 -v 8.4.2 -b 8.2.2 -x armv7-unknown-linux-gnueabihf --config $(pwd)/build.mk -- --enable-unregisterised|]---ghcCompileOpts :: Parser GHCCompileOptions-ghcCompileOpts =-  (\CabalCompileOptions {..} crossTarget addConfArgs setCompile -> GHCCompileOptions { .. }-    )-    <$> cabalCompileOpts-    <*> optional-          (option-            str-            (short 'x' <> long "cross-target" <> metavar "CROSS_TARGET" <> help-              "Build cross-compiler for this platform"-            )-          )-    <*> many (argument str (metavar "CONFIGURE_ARGS" <> help "Additional arguments to configure, prefix with '-- ' (longopts)"))-    <*> flag-          False-          True-          (long "set" <> help-            "Set as active version after install"-          )--cabalCompileOpts :: Parser CabalCompileOptions-cabalCompileOpts =-  CabalCompileOptions-    <$> option-          (eitherReader-            (first (const "Not a valid version") . version . T.pack)-          )-          (short 'v' <> long "version" <> metavar "VERSION" <> help-            "The tool version to compile"-          )-    <*> option-          (eitherReader-            (\x ->-              (bimap (const "Not a valid version") Left . version . T.pack $ x)-                <|> (bimap show Right . parseAbs . E.encodeUtf8 . T.pack $ x)-            )-          )-          (  short 'b'-          <> long "bootstrap-ghc"-          <> metavar "BOOTSTRAP_GHC"-          <> help-               "The GHC version (or full path) to bootstrap with (must be installed)"-          )-    <*> optional-          (option-            (eitherReader (readEither @Int))-            (short 'j' <> long "jobs" <> metavar "JOBS" <> help-              "How many jobs to use for make"-            )-          )-    <*> optional-          (option-            (eitherReader-              (\x ->-                first show . parseAbs . E.encodeUtf8 . T.pack $ x :: Either-                    String-                    (Path Abs)-              )-            )-            (short 'c' <> long "config" <> metavar "CONFIG" <> help-              "Absolute path to build config file"-            )-          )-    <*> optional-          (option-            (eitherReader-              (\x ->-                first show . parseAbs . E.encodeUtf8 . T.pack $ x :: Either-                    String-                    (Path Abs)-              )-            )-            (short 'p' <> long "patchdir" <> metavar "PATCH_DIR" <> help-              "Absolute path to patch directory (applied in order, uses -p1)"-            )-          )---toolVersionParser :: Parser ToolVersion-toolVersionParser = verP' <|> toolP- where-  verP' = ToolVersion <$> versionParser-  toolP =-    ToolTag-      <$> option-            (eitherReader tagEither)-            (short 't' <> long "tag" <> metavar "TAG" <> help "The target tag")---- | same as toolVersionParser, except as an argument.-toolVersionArgument :: Maybe ListCriteria -> Maybe Tool -> Parser ToolVersion-toolVersionArgument criteria tool =-  argument (eitherReader toolVersionEither)-    (metavar "VERSION|TAG"-    <> completer (tagCompleter (fromMaybe GHC tool) [])-    <> foldMap (completer . versionCompleter criteria) tool)---setVersionArgument :: Maybe ListCriteria -> Maybe Tool -> Parser SetToolVersion-setVersionArgument criteria tool =-  argument (eitherReader setEither)-    (metavar "VERSION|TAG|next"-    <> completer (tagCompleter (fromMaybe GHC tool) ["next"])-    <> foldMap (completer . versionCompleter criteria) tool)- where-  setEither s' =-        parseSet s'-    <|> second SetToolTag (tagEither s')-    <|> second SetToolVersion (tVersionEither s')-  parseSet s' = case fmap toLower s' of-                  "next" -> Right SetNext-                  other  -> Left [i|Unknown tag/version #{other}|]---versionArgument :: Maybe ListCriteria -> Maybe Tool -> Parser GHCTargetVersion-versionArgument criteria tool = argument (eitherReader tVersionEither) (metavar "VERSION" <> foldMap (completer . versionCompleter criteria) tool)---tagCompleter :: Tool -> [String] -> Completer-tagCompleter tool add = listIOCompleter $ do-  let loggerConfig = LoggerConfig-        { lcPrintDebug = False-        , colorOutter  = mempty-        , rawOutter    = mempty-        }--      runLogger = myLoggerT loggerConfig--  dirs <- getDirs-  let simpleSettings = Settings False False Never Curl False GHCupURL-      simpleAppState = AppState simpleSettings dirs defaultKeyBindings-      runEnv = runLogger . flip runReaderT simpleAppState--  mGhcUpInfo <- runEnv . runE $ readFromCache--  case mGhcUpInfo of-    VRight dls -> do-      let allTags = filter (\t -> t /= Old)-            $ join-            $ M.elems-            $ availableToolVersions (_ghcupDownloads dls) tool-      pure $ nub $ (add ++) $ fmap tagToString allTags-    VLeft _ -> pure  (nub $ ["recommended", "latest"] ++ add)---versionCompleter :: Maybe ListCriteria -> Tool -> Completer-versionCompleter criteria tool = listIOCompleter $ do-  let loggerConfig = LoggerConfig-        { lcPrintDebug = False-        , colorOutter  = mempty-        , rawOutter    = mempty-        }--      runLogger = myLoggerT loggerConfig--  mpFreq <- runLogger . runE $ platformRequest--  forFold mpFreq $ \pfreq -> do-    dirs <- getDirs-    let simpleSettings = Settings False False Never Curl False GHCupURL-        simpleAppState = AppState simpleSettings dirs defaultKeyBindings-        runEnv = runLogger . flip runReaderT simpleAppState--    mGhcUpInfo <- runEnv . runE $ readFromCache--    forFold mGhcUpInfo $ \(GHCupInfo _ dls) -> do-      installedVersions <- runEnv $ listVersions dls (Just tool) criteria pfreq-      return $ T.unpack . prettyVer . lVer <$> installedVersions---versionParser :: Parser GHCTargetVersion-versionParser = option-  (eitherReader tVersionEither)-  (short 'v' <> long "version" <> metavar "VERSION" <> help "The target version"-  )--versionParser' :: Maybe ListCriteria -> Maybe Tool -> Parser Version-versionParser' criteria tool = argument-  (eitherReader (first show . version . T.pack))-  (metavar "VERSION"  <> foldMap (completer . versionCompleter criteria) tool)---tagEither :: String -> Either String Tag-tagEither s' = case fmap toLower s' of-  "recommended" -> Right Recommended-  "latest"      -> Right Latest-  ('b':'a':'s':'e':'-':ver') -> case pvp (T.pack ver') of-                                  Right x -> Right (Base x)-                                  Left  _ -> Left [i|Invalid PVP version for base #{ver'}|]-  other         -> Left [i|Unknown tag #{other}|]---tVersionEither :: String -> Either String GHCTargetVersion-tVersionEither =-  first (const "Not a valid version") . MP.parse ghcTargetVerP "" . T.pack---toolVersionEither :: String -> Either String ToolVersion-toolVersionEither s' =-  second ToolTag (tagEither s') <|> second ToolVersion (tVersionEither s')---toolParser :: String -> Either String Tool-toolParser s' | t == T.pack "ghc"   = Right GHC-              | t == T.pack "cabal" = Right Cabal-              | otherwise           = Left ("Unknown tool: " <> s')-  where t = T.toLower (T.pack s')---criteriaParser :: String -> Either String ListCriteria-criteriaParser s' | t == T.pack "installed" = Right ListInstalled-                  | t == T.pack "set"       = Right ListSet-                  | otherwise               = Left ("Unknown criteria: " <> s')-  where t = T.toLower (T.pack s')---keepOnParser :: String -> Either String KeepDirs-keepOnParser s' | t == T.pack "always" = Right Always-                | t == T.pack "errors" = Right Errors-                | t == T.pack "never"  = Right Never-                | otherwise            = Left ("Unknown keep value: " <> s')-  where t = T.toLower (T.pack s')---downloaderParser :: String -> Either String Downloader-downloaderParser s' | t == T.pack "curl"     = Right Curl-                    | t == T.pack "wget"     = Right Wget-#if defined(INTERNAL_DOWNLOADER)-                    | t == T.pack "internal" = Right Internal-#endif-                    | otherwise = Left ("Unknown downloader value: " <> s')-  where t = T.toLower (T.pack s')---platformParser :: String -> Either String PlatformRequest-platformParser s' = case MP.parse (platformP <* MP.eof) "" (T.pack s') of-  Right r -> pure r-  Left  e -> Left $ errorBundlePretty e- where-  archP :: MP.Parsec Void Text Architecture-  archP = MP.try (MP.chunk "x86_64" $> A_64) <|> (MP.chunk "i386" $> A_32)-  platformP :: MP.Parsec Void Text PlatformRequest-  platformP = choice'-    [ (\a mv -> PlatformRequest a FreeBSD mv)-    <$> (archP <* MP.chunk "-")-    <*> (  MP.chunk "portbld"-        *> (   MP.try (Just <$> verP (MP.chunk "-freebsd" <* MP.eof))-           <|> pure Nothing-           )-        <* MP.chunk "-freebsd"-        )-    , (\a mv -> PlatformRequest a Darwin mv)-    <$> (archP <* MP.chunk "-")-    <*> (  MP.chunk "apple"-        *> (   MP.try (Just <$> verP (MP.chunk "-darwin" <* MP.eof))-           <|> pure Nothing-           )-        <* MP.chunk "-darwin"-        )-    , (\a d mv -> PlatformRequest a (Linux d) mv)-    <$> (archP <* MP.chunk "-")-    <*> distroP-    <*> ((MP.try (Just <$> verP (MP.chunk "-linux" <* MP.eof)) <|> pure Nothing-         )-        <* MP.chunk "-linux"-        )-    ]-  distroP :: MP.Parsec Void Text LinuxDistro-  distroP = choice'-    [ MP.chunk "debian" $> Debian-    , MP.chunk "deb" $> Debian-    , MP.chunk "ubuntu" $> Ubuntu-    , MP.chunk "mint" $> Mint-    , MP.chunk "fedora" $> Fedora-    , MP.chunk "centos" $> CentOS-    , MP.chunk "redhat" $> RedHat-    , MP.chunk "alpine" $> Alpine-    , MP.chunk "gentoo" $> Gentoo-    , MP.chunk "exherbo" $> Exherbo-    , MP.chunk "unknown" $> UnknownLinux-    ]---bindistParser :: String -> Either String URI-bindistParser = first show . parseURI strictURIParserOptions . UTF8.fromString---toSettings :: Options -> IO AppState-toSettings options = do-  dirs <- getDirs-  userConf <- runE @'[ JSONError ] ghcupConfigFile >>= \case-    VRight r -> pure r-    VLeft (V (JSONDecodeError e)) -> do-      B.hPut stderr ("Error decoding config file: " <> (E.encodeUtf8 . T.pack . show $ e))-      pure defaultUserSettings-    _ -> do-      die "Unexpected error!"-  pure $ mergeConf options dirs userConf- where-   mergeConf :: Options -> Dirs -> UserSettings -> AppState-   mergeConf Options{..} dirs UserSettings{..} =-     let cache       = fromMaybe (fromMaybe False uCache) optCache-         noVerify    = fromMaybe (fromMaybe False uNoVerify) optNoVerify-         verbose     = fromMaybe (fromMaybe False uVerbose) optVerbose-         keepDirs    = fromMaybe (fromMaybe Errors uKeepDirs) optKeepDirs-         downloader  = fromMaybe (fromMaybe defaultDownloader uDownloader) optsDownloader-         keyBindings = maybe defaultKeyBindings mergeKeys uKeyBindings-         urlSource   = maybe (fromMaybe GHCupURL uUrlSource) OwnSource optUrlSource-     in AppState (Settings {..}) dirs keyBindings-#if defined(INTERNAL_DOWNLOADER)-   defaultDownloader = Internal-#else-   defaultDownloader = Curl-#endif-   mergeKeys :: UserKeyBindings -> KeyBindings-   mergeKeys UserKeyBindings {..} =-     let KeyBindings {..} = defaultKeyBindings-     in KeyBindings {-           bUp = fromMaybe bUp kUp-         , bDown = fromMaybe bDown kDown-         , bQuit = fromMaybe bQuit kQuit-         , bInstall = fromMaybe bInstall kInstall-         , bUninstall = fromMaybe bUninstall kUninstall-         , bSet = fromMaybe bSet kSet-         , bChangelog = fromMaybe bChangelog kChangelog-         , bShowAll = fromMaybe bShowAll kShowAll-         }---upgradeOptsP :: Parser UpgradeOpts-upgradeOptsP =-  flag'-      UpgradeInplace-      (short 'i' <> long "inplace" <> help-        "Upgrade ghcup in-place (wherever it's at)"-      )-    <|> (   UpgradeAt-        <$> option-              (eitherReader-                (\x ->-                  first show . parseAbs . E.encodeUtf8 . T.pack $ x :: Either-                      String-                      (Path Abs)-                )-              )-              (short 't' <> long "target" <> metavar "TARGET_DIR" <> help-                "Absolute filepath to write ghcup into"-              )-        )-    <|> pure UpgradeGHCupDir----describe_result :: String-describe_result = $( LitE . StringL <$>-                     runIO (do-                             CapturedProcess{..} <- executeOut [rel|git|] ["describe"] Nothing-                             case _exitCode of-                               ExitSuccess   -> pure . T.unpack . decUTF8Safe $ _stdOut-                               ExitFailure _ -> pure numericVer-                     )-                   )---main :: IO ()-main = do-  let versionHelp = infoOption-        ( ("The GHCup Haskell installer, version " <>)-          (head . lines $ describe_result)-        )-        (long "version" <> help "Show version" <> hidden)-  let numericVersionHelp = infoOption-        numericVer-        (  long "numeric-version"-        <> help "Show the numeric version (for use in scripts)"-        <> hidden-        )-  let listCommands = infoOption-        "install set rm install-cabal list upgrade compile debug-info tool-requirements changelog"-        (  long "list-commands"-        <> help "List available commands for shell completion"-        <> internal-        )--  let main_footer = [s|Discussion:-  ghcup installs the Glasgow Haskell Compiler from the official-  release channels, enabling you to easily switch between different-  versions. It maintains a self-contained ~/.ghcup directory.--ENV variables:-  * TMPDIR: where ghcup does the work (unpacking, building, ...)-  * GHCUP_INSTALL_BASE_PREFIX: the base of ghcup (default: $HOME)-  * GHCUP_USE_XDG_DIRS: set to anything to use XDG style directories--Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]--  customExecParser-      (prefs showHelpOnError)-      (info (opts <**> helper <**> versionHelp <**> numericVersionHelp <**> listCommands)-            (footerDoc (Just $ text main_footer))-      )-    >>= \opt@Options {..} -> do-          appstate@AppState{dirs = Dirs{..}, ..} <- toSettings opt--          -- create ~/.ghcup dir-          createDirRecursive' baseDir--          -- logger interpreter-          logfile <- flip runReaderT appstate $ initGHCupFileLogging [rel|ghcup.log|]-          let loggerConfig = LoggerConfig-                { lcPrintDebug = verbose settings-                , colorOutter  = B.hPut stderr-                , rawOutter    = appendFile logfile-                }-          let runLogger = myLoggerT loggerConfig---          --------------------------          -- Effect interpreters ---          ---------------------------          let runInstTool' appstate' =-                runLogger-                  . flip runReaderT appstate'-                  . runResourceT-                  . runE-                    @'[ AlreadyInstalled-                      , UnknownArchive-#if !defined(TAR)-                      , ArchiveResult-#endif-                      , FileDoesNotExistError-                      , CopyError-                      , NoDownload-                      , NotInstalled-                      , BuildFailed-                      , TagNotFound-                      , DigestError-                      , DownloadFailed-                      , TarDirDoesNotExist-                      , NextVerNotFound-                      , NoToolVersionSet-                      ]--          let runInstTool = runInstTool' appstate--          let-            runSetGHC =-              runLogger-                . flip runReaderT appstate-                . runE-                  @'[ FileDoesNotExistError-                    , NotInstalled-                    , TagNotFound-                    , NextVerNotFound-                    , NoToolVersionSet-                    ]--          let-            runSetCabal =-              runLogger-                . flip runReaderT appstate-                . runE-                  @'[ NotInstalled-                    , TagNotFound-                    , NextVerNotFound-                    , NoToolVersionSet-                    ]--          let-            runSetHLS =-              runLogger-                . flip runReaderT appstate-                . runE-                  @'[ NotInstalled-                    , TagNotFound-                    , NextVerNotFound-                    , NoToolVersionSet-                    ]--          let runListGHC = runLogger . flip runReaderT appstate--          let runRm =-                runLogger . flip runReaderT appstate . runE @'[NotInstalled]--          let runDebugInfo =-                runLogger-                  . flip runReaderT appstate-                  . runE-                    @'[NoCompatiblePlatform , NoCompatibleArch , DistroNotFound]--          let runCompileGHC =-                runLogger-                  . flip runReaderT appstate-                  . runResourceT-                  . runE-                    @'[ AlreadyInstalled-                      , BuildFailed-                      , DigestError-                      , DownloadFailed-                      , GHCupSetError-                      , NoDownload-                      , NotFoundInPATH-                      , PatchFailed-                      , UnknownArchive-                      , TarDirDoesNotExist-                      , NotInstalled-#if !defined(TAR)-                      , ArchiveResult-#endif-                      ]--          let runUpgrade =-                runLogger-                  . flip runReaderT appstate-                  . runResourceT-                  . runE-                    @'[ DigestError-                      , NoDownload-                      , NoUpdate-                      , FileDoesNotExistError-                      , CopyError-                      , DownloadFailed-                      ]---          -----------------------------------------          -- Getting download and platform info ---          ------------------------------------------          pfreq <- (-            runLogger . runE @'[NoCompatiblePlatform, NoCompatibleArch, DistroNotFound] . liftE $ platformRequest-            ) >>= \case-                    VRight r -> pure r-                    VLeft e -> do-                      runLogger-                        ($(logError) $ T.pack $ prettyShow e)-                      exitWith (ExitFailure 2)---          (GHCupInfo treq dls) <--            ( runLogger-              . flip runReaderT appstate-              . runE @'[JSONError , DownloadFailed, FileDoesNotExistError]-              $ liftE-              $ getDownloadsF (urlSource settings)-              )-              >>= \case-                    VRight r -> pure r-                    VLeft  e -> do-                      runLogger-                        ($(logError) $ T.pack $ prettyShow e)-                      exitWith (ExitFailure 2)--          case optCommand of-            Upgrade _ _ -> pure ()-            _ -> runLogger $ flip runReaderT appstate $ checkForUpdates dls pfreq----          ------------------------          -- Command functions ---          -------------------------          let installGHC InstallOptions{..} =-                  (case instBindist of-                     Nothing -> runInstTool $ do-                       (v, vi) <- liftE $ fromVersion dls instVer GHC-                       liftE $ installGHCBin dls (_tvVersion v) (fromMaybe pfreq instPlatform)-                       when instSet $ void $ liftE $ setGHC v SetGHCOnly-                       pure vi-                     Just uri -> runInstTool' appstate{ settings = settings {noVerify = True}} $ do-                       (v, vi) <- liftE $ fromVersion dls instVer GHC-                       liftE $ installGHCBindist-                         (DownloadInfo uri (Just $ RegexDir "ghc-.*") "")-                         (_tvVersion v)-                         (fromMaybe pfreq instPlatform)-                       when instSet $ void $ liftE $ setGHC v SetGHCOnly-                       pure vi-                    )-                    >>= \case-                          VRight vi -> do-                            runLogger $ $(logInfo) "GHC installation successful"-                            forM_ (_viPostInstall =<< vi) $ \msg ->-                              runLogger $ $(logInfo) msg-                            pure ExitSuccess-                          VLeft (V (AlreadyInstalled _ v)) -> do-                            runLogger $ $(logWarn)-                              [i|GHC ver #{prettyVer v} already installed; if you really want to reinstall it, you may want to run 'ghcup rm ghc #{prettyVer v}' first|]-                            pure ExitSuccess-                          VLeft err@(V (BuildFailed tmpdir _)) -> do-                            case keepDirs settings of-                              Never -> runLogger ($(logError) $ T.pack $ prettyShow err)-                              _ -> runLogger ($(logError) [i|#{prettyShow err}-    Check the logs at #{logsDir} and the build directory #{tmpdir} for more clues.-    Make sure to clean up #{tmpdir} afterwards.|])-                            pure $ ExitFailure 3-                          VLeft e -> do-                            runLogger $ do-                              $(logError) $ T.pack $ prettyShow e-                              $(logError) [i|Also check the logs in #{logsDir}|]-                            pure $ ExitFailure 3---          let installCabal InstallOptions{..} =-                (case instBindist of-                   Nothing -> runInstTool $ do-                     (v, vi) <- liftE $ fromVersion dls instVer Cabal-                     liftE $ installCabalBin dls (_tvVersion v) (fromMaybe pfreq instPlatform)-                     pure vi-                   Just uri -> runInstTool' appstate{ settings = settings { noVerify = True}} $ do-                     (v, vi) <- liftE $ fromVersion dls instVer Cabal-                     liftE $ installCabalBindist-                         (DownloadInfo uri Nothing "")-                         (_tvVersion v)-                         (fromMaybe pfreq instPlatform)-                     pure vi-                  )-                  >>= \case-                        VRight vi -> do-                          runLogger $ $(logInfo) "Cabal installation successful"-                          forM_ (_viPostInstall =<< vi) $ \msg ->-                            runLogger $ $(logInfo) msg-                          pure ExitSuccess-                        VLeft (V (AlreadyInstalled _ v)) -> do-                          runLogger $ $(logWarn)-                            [i|Cabal ver #{prettyVer v} already installed; if you really want to reinstall it, you may want to run 'ghcup rm cabal #{prettyVer v}' first|]-                          pure ExitSuccess-                        VLeft e -> do-                          runLogger $ do-                            $(logError) $ T.pack $ prettyShow e-                            $(logError) [i|Also check the logs in #{logsDir}|]-                          pure $ ExitFailure 4--          let installHLS InstallOptions{..} =-                (case instBindist of-                   Nothing -> runInstTool $ do-                     (v, vi) <- liftE $ fromVersion dls instVer HLS-                     liftE $ installHLSBin dls (_tvVersion v) (fromMaybe pfreq instPlatform)-                     pure vi-                   Just uri -> runInstTool' appstate{ settings = settings { noVerify = True}} $ do-                     (v, vi) <- liftE $ fromVersion dls instVer HLS-                     liftE $ installHLSBindist-                         (DownloadInfo uri Nothing "")-                         (_tvVersion v)-                         (fromMaybe pfreq instPlatform)-                     pure vi-                  )-                  >>= \case-                        VRight vi -> do-                          runLogger $ $(logInfo) "HLS installation successful"-                          forM_ (_viPostInstall =<< vi) $ \msg ->-                            runLogger $ $(logInfo) msg-                          pure ExitSuccess-                        VLeft (V (AlreadyInstalled _ v)) -> do-                          runLogger $ $(logWarn)-                            [i|HLS ver #{prettyVer v} already installed; if you really want to reinstall it, you may want to run 'ghcup rm hls #{prettyVer v}' first|]-                          pure ExitSuccess-                        VLeft e -> do-                          runLogger $ do-                            $(logError) $ T.pack $ prettyShow e-                            $(logError) [i|Also check the logs in #{logsDir}|]-                          pure $ ExitFailure 4---          let setGHC' SetOptions{..} =-                runSetGHC (do-                    v <- liftE $ fst <$> fromVersion' dls sToolVer GHC-                    liftE $ setGHC v SetGHCOnly-                  )-                  >>= \case-                        VRight GHCTargetVersion{..} -> do-                          runLogger-                            $ $(logInfo)-                                [i|GHC #{prettyVer _tvVersion} successfully set as default version#{maybe "" (" for cross target " <>) _tvTarget}|]-                          pure ExitSuccess-                        VLeft e -> do-                          runLogger $ $(logError) $ T.pack $ prettyShow e-                          pure $ ExitFailure 5--          let setCabal' SetOptions{..} =-                runSetCabal (do-                    v <- liftE $ fst <$> fromVersion' dls sToolVer Cabal-                    liftE $ setCabal (_tvVersion v)-                    pure v-                  )-                  >>= \case-                        VRight GHCTargetVersion{..} -> do-                          runLogger-                            $ $(logInfo)-                                [i|Cabal #{prettyVer _tvVersion} successfully set as default version|]-                          pure ExitSuccess-                        VLeft  e -> do-                          runLogger $ $(logError) $ T.pack $ prettyShow e-                          pure $ ExitFailure 14--          let setHLS' SetOptions{..} =-                runSetHLS (do-                    v <- liftE $ fst <$> fromVersion' dls sToolVer HLS-                    liftE $ setHLS (_tvVersion v)-                    pure v-                  )-                  >>= \case-                        VRight GHCTargetVersion{..} -> do-                          runLogger-                            $ $(logInfo)-                                [i|HLS #{prettyVer _tvVersion} successfully set as default version|]-                          pure ExitSuccess-                        VLeft  e -> do-                          runLogger $ $(logError) $ T.pack $ prettyShow e-                          pure $ ExitFailure 14--          let rmGHC' RmOptions{..} =-                runRm (do-                    liftE $-                      rmGHCVer ghcVer-                    pure (getVersionInfo (_tvVersion ghcVer) GHC dls)-                  )-                  >>= \case-                        VRight vi -> do-                          forM_ (_viPostRemove =<< vi) $ \msg ->-                            runLogger $ $(logInfo) msg-                          pure ExitSuccess-                        VLeft  e -> do-                          runLogger $ $(logError) $ T.pack $ prettyShow e-                          pure $ ExitFailure 7--          let rmCabal' tv =-                runRm (do-                    liftE $-                      rmCabalVer tv-                    pure (getVersionInfo tv Cabal dls)-                  )-                  >>= \case-                        VRight vi -> do-                          forM_ (_viPostRemove =<< vi) $ \msg ->-                            runLogger $ $(logInfo) msg-                          pure ExitSuccess-                        VLeft  e -> do-                          runLogger $ $(logError) $ T.pack $ prettyShow e-                          pure $ ExitFailure 15--          let rmHLS' tv =-                runRm (do-                    liftE $-                      rmHLSVer tv-                    pure (getVersionInfo tv HLS dls)-                  )-                  >>= \case-                        VRight vi -> do-                          forM_ (_viPostRemove =<< vi) $ \msg ->-                            runLogger $ $(logInfo) msg-                          pure ExitSuccess-                        VLeft  e -> do-                          runLogger $ $(logError) $ T.pack $ prettyShow e-                          pure $ ExitFailure 15---          res <- case optCommand of-#if defined(BRICK)-            Interactive -> liftIO $ brickMain appstate loggerConfig dls pfreq >> pure ExitSuccess-#endif-            Install (Right iopts) -> do-              runLogger ($(logWarn) [i|This is an old-style command for installing GHC. Use 'ghcup install ghc' instead.|])-              installGHC iopts-            Install (Left (InstallGHC iopts)) -> installGHC iopts-            Install (Left (InstallCabal iopts)) -> installCabal iopts-            Install (Left (InstallHLS iopts)) -> installHLS iopts-            InstallCabalLegacy iopts -> do-              runLogger ($(logWarn) [i|This is an old-style command for installing cabal. Use 'ghcup install cabal' instead.|])-              installCabal iopts--            Set (Right sopts) -> do-              runLogger ($(logWarn) [i|This is an old-style command for setting GHC. Use 'ghcup set ghc' instead.|])-              setGHC' sopts-            Set (Left (SetGHC sopts)) -> setGHC' sopts-            Set (Left (SetCabal sopts)) -> setCabal' sopts-            Set (Left (SetHLS sopts)) -> setHLS' sopts--            List ListOptions {..} ->-              runListGHC (do-                  l <- listVersions dls loTool lCriteria pfreq-                  liftIO $ printListResult lRawFormat l-                  pure ExitSuccess-                )--            Rm (Right rmopts) -> do-              runLogger ($(logWarn) [i|This is an old-style command for removing GHC. Use 'ghcup rm ghc' instead.|])-              rmGHC' rmopts-            Rm (Left (RmGHC rmopts)) -> rmGHC' rmopts-            Rm (Left (RmCabal rmopts)) -> rmCabal' rmopts-            Rm (Left (RmHLS rmopts)) -> rmHLS' rmopts--            DInfo ->-              do runDebugInfo $ liftE getDebugInfo-                >>= \case-                      VRight dinfo -> do-                        putStrLn $ prettyDebugInfo dinfo-                        pure ExitSuccess-                      VLeft e -> do-                        runLogger $ $(logError) $ T.pack $ prettyShow e-                        pure $ ExitFailure 8--            Compile (CompileGHC GHCCompileOptions {..}) ->-              runCompileGHC (do-                let vi = getVersionInfo targetVer GHC dls-                forM_ (_viPreCompile =<< vi) $ \msg -> do-                  lift $ $(logInfo) msg-                  lift $ $(logInfo)-                    "...waiting for 5 seconds, you can still abort..."-                  liftIO $ threadDelay 5000000 -- for compilation, give the user a sec to intervene-                liftE $ compileGHC dls-                            (GHCTargetVersion crossTarget targetVer)-                            bootstrapGhc-                            jobs-                            buildConfig-                            patchDir-                            addConfArgs-                            pfreq-                when setCompile $ void $ liftE $-                  setGHC (GHCTargetVersion crossTarget targetVer) SetGHCOnly-                pure vi-                )-                >>= \case-                      VRight vi -> do-                        runLogger $ $(logInfo)-                          "GHC successfully compiled and installed"-                        forM_ (_viPostInstall =<< vi) $ \msg ->-                          runLogger $ $(logInfo) msg-                        pure ExitSuccess-                      VLeft (V (AlreadyInstalled _ v)) -> do-                        runLogger $ $(logWarn)-                          [i|GHC ver #{prettyVer v} already installed; if you really want to reinstall it, you may want to run 'ghcup rm ghc #{prettyVer v}' first|]-                        pure ExitSuccess-                      VLeft err@(V (BuildFailed tmpdir _)) -> do-                        case keepDirs settings of-                          Never -> runLogger $ $(logError) $ T.pack $ prettyShow err-                          _ -> runLogger ($(logError) [i|#{prettyShow err}-Check the logs at #{logsDir} and the build directory #{tmpdir} for more clues.-Make sure to clean up #{tmpdir} afterwards.|])-                        pure $ ExitFailure 9-                      VLeft e -> do-                        runLogger $ $(logError) $ T.pack $ prettyShow e-                        pure $ ExitFailure 9--            Upgrade uOpts force -> do-              target <- case uOpts of-                UpgradeInplace -> do-                  efp <- liftIO getExecutablePath-                  p   <- parseAbs . E.encodeUtf8 . T.pack $ efp-                  pure $ Just p-                (UpgradeAt p)   -> pure $ Just p-                UpgradeGHCupDir -> pure (Just (binDir </> [rel|ghcup|]))--              runUpgrade (liftE $ upgradeGHCup dls target force pfreq) >>= \case-                VRight v' -> do-                  let pretty_v = prettyVer v'-                  let vi = fromJust $ snd <$> getLatest dls GHCup-                  runLogger $ $(logInfo)-                    [i|Successfully upgraded GHCup to version #{pretty_v}|]-                  forM_ (_viPostInstall vi) $ \msg ->-                    runLogger $ $(logInfo) msg-                  pure ExitSuccess-                VLeft (V NoUpdate) -> do-                  runLogger $ $(logWarn) [i|No GHCup update available|]-                  pure ExitSuccess-                VLeft e -> do-                  runLogger $ $(logError) $ T.pack $ prettyShow e-                  pure $ ExitFailure 11--            ToolRequirements ->-              runLogger-                (runE-                  @'[NoCompatiblePlatform , DistroNotFound , NoToolRequirements]-                $ do-                    platform <- liftE getPlatform-                    req      <- getCommonRequirements platform treq ?? NoToolRequirements-                    liftIO $ T.hPutStr stdout (prettyRequirements req)-                )-                >>= \case-                      VRight _ -> pure ExitSuccess-                      VLeft  e -> do-                        runLogger $ $(logError) $ T.pack $ prettyShow e-                        pure $ ExitFailure 12--            ChangeLog ChangeLogOptions{..} -> do-              let tool = fromMaybe GHC clTool-                  ver' = maybe-                    (Right Latest)-                    (\case-                      ToolVersion tv -> Left (_tvVersion tv) -- FIXME: ugly sharing of ToolVersion-                      ToolTag     t  -> Right t-                    )-                    clToolVer-                  muri = getChangeLog dls tool ver'-              case muri of-                Nothing -> do-                  runLogger-                    ($(logWarn)-                      [i|Could not find ChangeLog for #{tool}, version #{either (T.unpack . prettyVer) show ver'}|]-                    )-                  pure ExitSuccess-                Just uri -> do-                  let uri' = T.unpack . decUTF8Safe . serializeURIRef' $ uri-                      cmd = case _rPlatform pfreq of-                              Darwin  -> "open"-                              Linux _ -> "xdg-open"-                              FreeBSD -> "xdg-open"--                  if clOpen-                    then-                      exec cmd-                           True-                           [serializeURIRef' uri]-                           Nothing-                           Nothing-                        >>= \case-                              Right _ -> pure ExitSuccess-                              Left  e -> runLogger ($(logError) [i|#{e}|])-                                >> pure (ExitFailure 13)-                    else putStrLn uri' >> pure ExitSuccess--          case res of-            ExitSuccess        -> pure ()-            ef@(ExitFailure _) -> exitWith ef-  pure ()--fromVersion :: (MonadLogger m, MonadFail m, MonadReader AppState m, MonadThrow m, MonadIO m, MonadCatch m)-            => GHCupDownloads-            -> Maybe ToolVersion-            -> Tool-            -> Excepts '[TagNotFound, NextVerNotFound, NoToolVersionSet] m (GHCTargetVersion, Maybe VersionInfo)-fromVersion av tv = fromVersion' av (toSetToolVer tv)--fromVersion' :: (MonadLogger m, MonadFail m, MonadReader AppState m, MonadThrow m, MonadIO m, MonadCatch m)-             => GHCupDownloads-             -> SetToolVersion-             -> Tool-             -> Excepts '[TagNotFound, NextVerNotFound, NoToolVersionSet] m (GHCTargetVersion, Maybe VersionInfo)-fromVersion' av SetRecommended tool =-  (\(x, y) -> (mkTVer x, Just y)) <$> getRecommended av tool-    ?? TagNotFound Recommended tool-fromVersion' av (SetToolVersion v) tool = do-  let vi = getVersionInfo (_tvVersion v) tool av-  case pvp $ prettyVer (_tvVersion v) of-    Left _ -> pure (v, vi)-    Right (PVP (major' :|[minor'])) ->-      case getLatestGHCFor (fromIntegral major') (fromIntegral minor') av of-        Just (v', vi') -> pure (GHCTargetVersion (_tvTarget v) v', Just vi')-        Nothing -> pure (v, vi)-    Right _ -> pure (v, vi)-fromVersion' av  (SetToolTag Latest) tool =-  (\(x, y) -> (mkTVer x, Just y)) <$> getLatest av tool ?? TagNotFound Latest tool-fromVersion' av (SetToolTag Recommended) tool =-  (\(x, y) -> (mkTVer x, Just y)) <$> getRecommended av tool ?? TagNotFound Recommended tool-fromVersion' av (SetToolTag (Base pvp'')) GHC =-  (\(x, y) -> (mkTVer x, Just y)) <$> getLatestBaseVersion av pvp'' ?? TagNotFound (Base pvp'') GHC-fromVersion' av SetNext tool = do-  next <- case tool of-    GHC -> do-      set <- fmap _tvVersion $ ghcSet Nothing !? NoToolVersionSet tool-      ghcs <- rights <$> lift getInstalledGHCs-      (headMay-        . tail-        . dropWhile (\GHCTargetVersion {..} -> _tvVersion /= set)-        . cycle-        . sortBy (\x y -> compare (_tvVersion x) (_tvVersion y))-        . filter (\GHCTargetVersion {..} -> _tvTarget == Nothing)-        $ ghcs) ?? NoToolVersionSet tool-    Cabal -> do-      set <- cabalSet !? NoToolVersionSet tool-      cabals <- rights <$> lift getInstalledCabals-      (fmap (GHCTargetVersion Nothing)-        . headMay-        . tail-        . dropWhile (/= set)-        . cycle-        . sort-        $ cabals) ?? NoToolVersionSet tool-    HLS -> do-      set <- hlsSet !? NoToolVersionSet tool-      hlses <- rights <$> lift getInstalledHLSs-      (fmap (GHCTargetVersion Nothing)-        . headMay-        . tail-        . dropWhile (/= set)-        . cycle-        . sort-        $ hlses) ?? NoToolVersionSet tool-    GHCup -> fail "GHCup cannot be set"-  let vi = getVersionInfo (_tvVersion next) tool av-  pure (next, vi)-fromVersion' _ (SetToolTag t') tool =-  throwE $ TagNotFound t' tool---printListResult :: Bool -> [ListResult] -> IO ()-printListResult raw lr = do-  -- https://gitlab.haskell.org/ghc/ghc/issues/8118-  setLocaleEncoding utf8--  no_color <- isJust <$> lookupEnv "NO_COLOR"--  let-    color | raw || no_color = flip const-          | otherwise       = Pretty.color--  let-    printTag Recommended        = color Green "recommended"-    printTag Latest             = color Yellow "latest"-    printTag Prerelease         = color Red "prerelease"-    printTag (Base       pvp'') = "base-" ++ T.unpack (prettyPVP pvp'')-    printTag (UnknownTag t    ) = t-    printTag Old                = ""--  let-    rows =-      (\x -> if raw-          then x-          else [color Green "", "Tool", "Version", "Tags", "Notes"] : x-        )-        . fmap-            (\ListResult {..} ->-              let marks = if-                    | lSet       -> (color Green "✔✔")-                    | lInstalled -> (color Green "✓ ")-                    | otherwise  -> (color Red "✗ ")-              in-                (if raw then [] else [marks])-                  ++ [ fmap toLower . show $ lTool-                     , case lCross of-                       Nothing -> T.unpack . prettyVer $ lVer-                       Just c  -> T.unpack (c <> "-" <> prettyVer lVer)-                     , intercalate "," $ (filter (/= "") . fmap printTag $ sort lTag)-                     , intercalate ","-                     $  (if hlsPowered-                          then [color Green "hls-powered"]-                          else mempty-                        )-                     ++ (if fromSrc then [color Blue "compiled"] else mempty)-                     ++ (if lStray then [color Yellow "stray"] else mempty)-                     ++ (if lNoBindist-                          then [color Red "no-bindist"]-                          else mempty-                        )-                     ]-            )-        $ lr-  let cols =-        foldr (\xs ys -> zipWith (:) xs ys) (replicate (length rows) []) rows-      lengths = fmap maximum . (fmap . fmap) strWidth $ cols-      padded  = fmap (\xs -> zipWith padTo xs lengths) rows--  forM_ padded $ \row -> putStrLn $ intercalate " " row- where--  padTo str' x =-    let lstr = strWidth str'-        add' = x - lstr-    in  if add' < 0 then str' else str' ++ replicate add' ' '--  -- | Calculate the render width of a string, considering-  -- wide characters (counted as double width), ANSI escape codes-  -- (not counted), and line breaks (in a multi-line string, the longest-  -- line determines the width).-  strWidth :: String -> Int-  strWidth =-    maximum-      . (0 :)-      . map (foldr (\a b -> charWidth a + b) 0)-      . lines-      . stripAnsi--  -- | Strip ANSI escape sequences from a string.-  ---  -- >>> stripAnsi "\ESC[31m-1\ESC[m"-  -- "-1"-  stripAnsi :: String -> String-  stripAnsi s' =-    case-        MP.parseMaybe (many $ "" <$ MP.try ansi <|> pure <$> MP.anySingle) s'-      of-        Nothing -> error "Bad ansi escape"  -- PARTIAL: should not happen-        Just xs -> concat xs-   where-      -- This parses lots of invalid ANSI escape codes, but that should be fine-    ansi =-      MPC.string "\ESC[" *> digitSemicolons *> suffix MP.<?> "ansi" :: MP.Parsec-          Void-          String-          Char-    digitSemicolons = MP.takeWhileP Nothing (\c -> isDigit c || c == ';')-    suffix = MP.oneOf ['A', 'B', 'C', 'D', 'H', 'J', 'K', 'f', 'm', 's', 'u']--  -- | Get the designated render width of a character: 0 for a combining-  -- character, 1 for a regular character, 2 for a wide character.-  -- (Wide characters are rendered as exactly double width in apps and-  -- fonts that support it.) (From Pandoc.)-  charWidth :: Char -> Int-  charWidth c = case c of-    _ | c < '\x0300'                     -> 1-      | c >= '\x0300' && c <= '\x036F'   -> 0-      |  -- combining-        c >= '\x0370' && c <= '\x10FC'   -> 1-      | c >= '\x1100' && c <= '\x115F'   -> 2-      | c >= '\x1160' && c <= '\x11A2'   -> 1-      | c >= '\x11A3' && c <= '\x11A7'   -> 2-      | c >= '\x11A8' && c <= '\x11F9'   -> 1-      | c >= '\x11FA' && c <= '\x11FF'   -> 2-      | c >= '\x1200' && c <= '\x2328'   -> 1-      | c >= '\x2329' && c <= '\x232A'   -> 2-      | c >= '\x232B' && c <= '\x2E31'   -> 1-      | c >= '\x2E80' && c <= '\x303E'   -> 2-      | c == '\x303F'                    -> 1-      | c >= '\x3041' && c <= '\x3247'   -> 2-      | c >= '\x3248' && c <= '\x324F'   -> 1-      | -- ambiguous-        c >= '\x3250' && c <= '\x4DBF'   -> 2-      | c >= '\x4DC0' && c <= '\x4DFF'   -> 1-      | c >= '\x4E00' && c <= '\xA4C6'   -> 2-      | c >= '\xA4D0' && c <= '\xA95F'   -> 1-      | c >= '\xA960' && c <= '\xA97C'   -> 2-      | c >= '\xA980' && c <= '\xABF9'   -> 1-      | c >= '\xAC00' && c <= '\xD7FB'   -> 2-      | c >= '\xD800' && c <= '\xDFFF'   -> 1-      | c >= '\xE000' && c <= '\xF8FF'   -> 1-      | -- ambiguous-        c >= '\xF900' && c <= '\xFAFF'   -> 2-      | c >= '\xFB00' && c <= '\xFDFD'   -> 1-      | c >= '\xFE00' && c <= '\xFE0F'   -> 1-      | -- ambiguous-        c >= '\xFE10' && c <= '\xFE19'   -> 2-      | c >= '\xFE20' && c <= '\xFE26'   -> 1-      | c >= '\xFE30' && c <= '\xFE6B'   -> 2-      | c >= '\xFE70' && c <= '\xFEFF'   -> 1-      | c >= '\xFF01' && c <= '\xFF60'   -> 2-      | c >= '\xFF61' && c <= '\x16A38'  -> 1-      | c >= '\x1B000' && c <= '\x1B001' -> 2-      | c >= '\x1D000' && c <= '\x1F1FF' -> 1-      | c >= '\x1F200' && c <= '\x1F251' -> 2-      | c >= '\x1F300' && c <= '\x1F773' -> 1-      | c >= '\x20000' && c <= '\x3FFFD' -> 2-      | otherwise                        -> 1---checkForUpdates :: ( MonadReader AppState m-                   , MonadCatch m-                   , MonadLogger m-                   , MonadThrow m-                   , MonadIO m-                   , MonadFail m-                   , MonadLogger m-                   )-                => GHCupDownloads-                -> PlatformRequest-                -> m ()-checkForUpdates dls pfreq = do-  lInstalled <- listVersions dls Nothing (Just ListInstalled) pfreq-  let latestInstalled tool = (fmap lVer . lastMay . filter (\lr -> lTool lr == tool)) lInstalled--  forM_ (getLatest dls GHCup) $ \(l, _) -> do-    (Right ghc_ver) <- pure $ version $ prettyPVP ghcUpVer-    when (l > ghc_ver)-      $ $(logWarn)-          [i|New GHCup version available: #{prettyVer l}. To upgrade, run 'ghcup upgrade'|]--  forM_ (getLatest dls GHC) $ \(l, _) -> do-    let mghc_ver = latestInstalled GHC-    forM mghc_ver $ \ghc_ver ->-      when (l > ghc_ver)-        $ $(logWarn)-            [i|New GHC version available: #{prettyVer l}. To upgrade, run 'ghcup install ghc #{prettyVer l}'|]--  forM_ (getLatest dls Cabal) $ \(l, _) -> do-    let mcabal_ver = latestInstalled Cabal-    forM mcabal_ver $ \cabal_ver ->-      when (l > cabal_ver)-        $ $(logWarn)-            [i|New Cabal version available: #{prettyVer l}. To upgrade, run 'ghcup install cabal #{prettyVer l}'|]--  forM_ (getLatest dls HLS) $ \(l, _) -> do-    let mhls_ver = latestInstalled HLS-    forM mhls_ver $ \hls_ver ->-      when (l > hls_ver)-        $ $(logWarn)-            [i|New HLS version available: #{prettyVer l}. To upgrade, run 'ghcup install hls #{prettyVer l}'|]---prettyDebugInfo :: DebugInfo -> String-prettyDebugInfo DebugInfo {..} = [i|Debug Info-==========-GHCup base dir: #{toFilePath diBaseDir}-GHCup bin dir: #{toFilePath diBinDir}-GHCup GHC directory: #{toFilePath diGHCDir}-GHCup cache directory: #{toFilePath diCacheDir}-Architecture: #{prettyShow diArch}-Platform: #{prettyShow diPlatform}-Version: #{describe_result}|]+import           GHCup.Types.Optics+import           GHCup.Utils+import           GHCup.Utils.File+import           GHCup.Utils.Logger+import           GHCup.Utils.MegaParsec+import           GHCup.Utils.Prelude+import           GHCup.Utils.String.QQ+import           GHCup.Version++import           Cabal.Plan ( findPlanJson, SearchPlanJson(..) )+import           Codec.Archive+import           Control.Concurrent+import           Control.Concurrent.Async+import           Control.DeepSeq                ( force )+import           Control.Exception              ( evaluate )+import           Control.Exception.Safe+#if !MIN_VERSION_base(4,13,0)+import           Control.Monad.Fail             ( MonadFail )+#endif+import           Control.Monad.Reader+import           Control.Monad.Trans.Resource+import           Data.Aeson                     ( decodeStrict', Value )+import           Data.Aeson.Encode.Pretty       ( encodePretty )+import           Data.Bifunctor+import           Data.Char+import           Data.Either+import           Data.Functor+import           Data.List                      ( intercalate, nub, sort, sortBy )+import           Data.Maybe+import           Data.Text                      ( Text )+import           Data.Versions           hiding ( str )+import           Data.Void+import           GHC.IO.Encoding+import           Haskus.Utils.Variant.Excepts+import           Language.Haskell.TH+import           Language.Haskell.TH.Syntax     ( Quasi(qAddDependentFile) )+import           Options.Applicative     hiding ( style )+import           Options.Applicative.Help.Pretty ( text )+import           Prelude                 hiding ( appendFile )+import           Safe+import           System.Console.Pretty   hiding ( color )+import qualified System.Console.Pretty         as Pretty+import           System.Environment+import           System.Exit+import           System.FilePath+import           System.IO               hiding ( appendFile )+import           Text.Read               hiding ( lift )+import           Text.PrettyPrint.HughesPJClass ( prettyShow )+import           URI.ByteString++import qualified Data.ByteString               as B+import qualified Data.ByteString.UTF8          as UTF8+import qualified Data.Map.Strict               as M+import qualified Data.Text                     as T+import qualified Data.Text.IO                  as T+import qualified Data.Text.Encoding            as E+import qualified Data.YAML.Aeson               as Y+import qualified Text.Megaparsec               as MP+import qualified Text.Megaparsec.Char          as MPC++++data Options = Options+  {+  -- global options+    optVerbose     :: Maybe Bool+  , optCache       :: Maybe Bool+  , optUrlSource   :: Maybe URI+  , optNoVerify    :: Maybe Bool+  , optKeepDirs    :: Maybe KeepDirs+  , optsDownloader :: Maybe Downloader+  , optNoNetwork   :: Maybe Bool+  , optGpg         :: Maybe GPGSetting+  -- commands+  , optCommand     :: Command+  }++data Command+  = Install (Either InstallCommand InstallOptions)+  | InstallCabalLegacy InstallOptions+  | Set (Either SetCommand SetOptions)+  | UnSet UnsetCommand+  | List ListOptions+  | Rm (Either RmCommand RmOptions)+  | DInfo+  | Compile CompileCommand+  | Config ConfigCommand+  | Whereis WhereisOptions WhereisCommand+  | Upgrade UpgradeOpts Bool+  | ToolRequirements+  | ChangeLog ChangeLogOptions+  | Nuke+#if defined(BRICK)+  | Interactive+#endif+  | Prefetch PrefetchCommand+  | GC GCOptions++data ToolVersion = ToolVersion GHCTargetVersion -- target is ignored for cabal+                 | ToolTag Tag++prettyToolVer :: ToolVersion -> String+prettyToolVer (ToolVersion v') = T.unpack $ tVerToText v'+prettyToolVer (ToolTag t) = show t++toSetToolVer :: Maybe ToolVersion -> SetToolVersion+toSetToolVer (Just (ToolVersion v')) = SetToolVersion v'+toSetToolVer (Just (ToolTag t')) = SetToolTag t'+toSetToolVer Nothing = SetRecommended+++data InstallCommand = InstallGHC InstallOptions+                    | InstallCabal InstallOptions+                    | InstallHLS InstallOptions+                    | InstallStack InstallOptions++data InstallOptions = InstallOptions+  { instVer      :: Maybe ToolVersion+  , instPlatform :: Maybe PlatformRequest+  , instBindist  :: Maybe URI+  , instSet      :: Bool+  , isolateDir   :: Maybe FilePath+  , forceInstall :: Bool+  }++data GCOptions = GCOptions+  { gcOldGHC :: Bool+  , gcProfilingLibs :: Bool+  , gcShareDir :: Bool+  , gcHLSNoGHC :: Bool+  , gcCache :: Bool+  , gcTmp :: Bool+  }++data SetCommand = SetGHC SetOptions+                | SetCabal SetOptions+                | SetHLS SetOptions+                | SetStack SetOptions++data UnsetCommand = UnsetGHC   UnsetOptions+                  | UnsetCabal UnsetOptions+                  | UnsetHLS   UnsetOptions+                  | UnsetStack UnsetOptions++-- a superset of ToolVersion+data SetToolVersion = SetToolVersion GHCTargetVersion+                    | SetToolTag Tag+                    | SetRecommended+                    | SetNext++data SetOptions = SetOptions+  { sToolVer :: SetToolVersion+  }++data UnsetOptions = UnsetOptions+  { sToolVer :: Maybe Text -- target platform triple+  }++data ListOptions = ListOptions+  { loTool     :: Maybe Tool+  , lCriteria  :: Maybe ListCriteria+  , lRawFormat :: Bool+  }++data RmCommand = RmGHC RmOptions+               | RmCabal Version+               | RmHLS Version+               | RmStack Version++data RmOptions = RmOptions+  { ghcVer :: GHCTargetVersion+  }+++data CompileCommand = CompileGHC GHCCompileOptions+                    | CompileHLS HLSCompileOptions++data ConfigCommand = ShowConfig | SetConfig String String | InitConfig++data GHCCompileOptions = GHCCompileOptions+  { targetGhc    :: Either Version GitBranch+  , bootstrapGhc :: Either Version FilePath+  , jobs         :: Maybe Int+  , buildConfig  :: Maybe FilePath+  , patchDir     :: Maybe FilePath+  , crossTarget  :: Maybe Text+  , addConfArgs  :: [Text]+  , setCompile   :: Bool+  , ovewrwiteVer :: Maybe Version+  , buildFlavour :: Maybe String+  , hadrian      :: Bool+  , isolateDir   :: Maybe FilePath+  }++data HLSCompileOptions = HLSCompileOptions+  { targetHLS    :: Either Version GitBranch+  , jobs         :: Maybe Int+  , setCompile   :: Bool+  , ovewrwiteVer :: Maybe Version+  , isolateDir   :: Maybe FilePath+  , cabalProject :: Maybe FilePath+  , cabalProjectLocal :: Maybe FilePath+  , patchDir     :: Maybe FilePath+  , targetGHCs   :: [ToolVersion]+  }++data UpgradeOpts = UpgradeInplace+                 | UpgradeAt FilePath+                 | UpgradeGHCupDir+                 deriving Show++data ChangeLogOptions = ChangeLogOptions+  { clOpen    :: Bool+  , clTool    :: Maybe Tool+  , clToolVer :: Maybe ToolVersion+  }+++data WhereisCommand = WhereisTool Tool (Maybe ToolVersion)+                    | WhereisBaseDir+                    | WhereisBinDir+                    | WhereisCacheDir+                    | WhereisLogsDir+                    | WhereisConfDir++data WhereisOptions = WhereisOptions {+   directory :: Bool+}++data PrefetchOptions = PrefetchOptions {+  pfCacheDir :: Maybe FilePath+}++data PrefetchCommand = PrefetchGHC PrefetchGHCOptions (Maybe ToolVersion)+                     | PrefetchCabal PrefetchOptions (Maybe ToolVersion)+                     | PrefetchHLS PrefetchOptions (Maybe ToolVersion)+                     | PrefetchStack PrefetchOptions (Maybe ToolVersion)+                     | PrefetchMetadata++data PrefetchGHCOptions = PrefetchGHCOptions {+    pfGHCSrc :: Bool+  , pfGHCCacheDir :: Maybe FilePath+}+++-- https://github.com/pcapriotti/optparse-applicative/issues/148++-- | A switch that can be enabled using --foo and disabled using --no-foo.+--+-- The option modifier is applied to only the option that is *not* enabled+-- by default. For example:+--+-- > invertableSwitch "recursive" True (help "do not recurse into directories")+--+-- This example makes --recursive enabled by default, so+-- the help is shown only for --no-recursive.+invertableSwitch+    :: String              -- ^ long option+    -> Char                -- ^ short option for the non-default option+    -> Bool                -- ^ is switch enabled by default?+    -> Mod FlagFields Bool -- ^ option modifier+    -> Parser (Maybe Bool)+invertableSwitch longopt shortopt defv optmod = invertableSwitch' longopt shortopt defv+    (if defv then mempty else optmod)+    (if defv then optmod else mempty)++-- | Allows providing option modifiers for both --foo and --no-foo.+invertableSwitch'+    :: String              -- ^ long option (eg "foo")+    -> Char                -- ^ short option for the non-default option+    -> Bool                -- ^ is switch enabled by default?+    -> Mod FlagFields Bool -- ^ option modifier for --foo+    -> Mod FlagFields Bool -- ^ option modifier for --no-foo+    -> Parser (Maybe Bool)+invertableSwitch' longopt shortopt defv enmod dismod = optional+    ( flag' True ( enmod <> long longopt <> if defv then mempty else short shortopt)+    <|> flag' False (dismod <> long nolongopt <> if defv then short shortopt else mempty)+    )+  where+    nolongopt = "no-" ++ longopt+++opts :: Parser Options+opts =+  Options+    <$> invertableSwitch "verbose" 'v' False (help "Enable verbosity (default: disabled)")+    <*> invertableSwitch "cache" 'c' False (help "Cache downloads in ~/.ghcup/cache (default: disabled)")+    <*> (optional+          (option+            (eitherReader parseUri)+            (  short 's'+            <> long "url-source"+            <> metavar "URL"+            <> help "Alternative ghcup download info url"+            <> internal+            )+          )+        )+    <*> (fmap . fmap) not (invertableSwitch "verify" 'n' True (help "Disable tarball checksum verification (default: enabled)"))+    <*> optional (option+          (eitherReader keepOnParser)+          (  long "keep"+          <> metavar "<always|errors|never>"+          <> help+               "Keep build directories? (default: errors)"+          <> hidden+          ))+    <*> optional (option+          (eitherReader downloaderParser)+          (  long "downloader"+#if defined(INTERNAL_DOWNLOADER)+          <> metavar "<internal|curl|wget>"+          <> help+          "Downloader to use (default: internal)"+#else+          <> metavar "<curl|wget>"+          <> help+          "Downloader to use (default: curl)"+#endif+          <> hidden+          ))+    <*> invertableSwitch "offline" 'o' False (help "Don't do any network calls, trying cached assets and failing if missing.")+    <*> optional (option+          (eitherReader gpgParser)+          (  long "gpg"+          <> metavar "<strict|lax|none>"+          <> help+          "GPG verification (default: none)"+          ))+    <*> com+ where+  parseUri s' =+    first show $ parseURI strictURIParserOptions (UTF8.fromString s')+++com :: Parser Command+com =+  subparser+#if defined(BRICK)+      (  command+          "tui"+          (   (\_ -> Interactive)+          <$> (info+                helper+                (  progDesc "Start the interactive GHCup UI"+                )+              )+          )+      <>  command+#else+      (  command+#endif+          "install"+          (   Install+          <$> info+                (installParser <**> helper)+                (  progDesc "Install or update GHC/cabal/HLS/stack"+                <> footerDoc (Just $ text installToolFooter)+                )+          )+      <> command+           "set"+           (info+             (Set <$> setParser <**> helper)+             (  progDesc "Set currently active GHC/cabal version"+             <> footerDoc (Just $ text setFooter)+             )+           )+      <> command+           "unset"+           (info+             (UnSet <$> unsetParser <**> helper)+             (  progDesc "Unset currently active GHC/cabal version"+             <> footerDoc (Just $ text unsetFooter)+             )+           )+      <> command+           "rm"+           (info+             (Rm <$> rmParser <**> helper)+             (  progDesc "Remove a GHC/cabal/HLS/stack version"+             <> footerDoc (Just $ text rmFooter)+             )+           )++      <> command+           "list"+           (info (List <$> listOpts <**> helper)+                 (progDesc "Show available GHCs and other tools")+           )+      <> command+           "upgrade"+           (info+             (    (Upgrade <$> upgradeOptsP <*> switch+                    (short 'f' <> long "force" <> help "Force update")+                  )+             <**> helper+             )+             (progDesc "Upgrade ghcup")+           )+      <> command+           "compile"+           (   Compile+           <$> info (compileP <**> helper)+                    (progDesc "Compile a tool from source")+           )+      <> command+           "whereis"+            (info+             (   (Whereis+                     <$> (WhereisOptions <$> switch (short 'd' <> long "directory" <> help "return directory of the binary instead of the binary location"))+                     <*> whereisP+                 ) <**> helper+             )+             (progDesc "Find a tools location"+             <> footerDoc ( Just $ text whereisFooter ))+           )+      <> command+           "prefetch"+            (info+             (   (Prefetch+                     <$> prefetchP+                 ) <**> helper+             )+             (progDesc "Prefetch assets"+             <> footerDoc ( Just $ text prefetchFooter ))+           )+      <> command+           "gc"+            (info+             (   (GC+                     <$> gcP+                 ) <**> helper+             )+             (progDesc "Garbage collection"+             <> footerDoc ( Just $ text gcFooter ))+           )+      <> commandGroup "Main commands:"+      )+    <|> subparser+          (  command+              "debug-info"+              ((\_ -> DInfo) <$> info helper (progDesc "Show debug info"))+          <> command+               "tool-requirements"+               (   (\_ -> ToolRequirements)+               <$> info helper+                        (progDesc "Show the requirements for ghc/cabal")+               )+          <> command+               "changelog"+               (info+                  (fmap ChangeLog changelogP <**> helper)+                  (  progDesc "Find/show changelog"+                  <> footerDoc (Just $ text changeLogFooter)+                  )+               )+          <> command+               "config"+               (   Config+               <$> info (configP <**> helper)+                        (progDesc "Show or set config" <> footerDoc (Just $ text configFooter))+               )+          <> commandGroup "Other commands:"+          <> hidden+          )+    <|> subparser+          (  command+              "install-cabal"+              (info+                 ((InstallCabalLegacy <$> installOpts (Just Cabal)) <**> helper)+                 (  progDesc "Install or update cabal"+                 <> footerDoc (Just $ text installCabalFooter)+                 )+              )+          <> internal+          )+     <|> subparser+          (command+              "nuke"+               (info (pure Nuke <**> helper)+                     (progDesc "Completely remove ghcup from your system"))+           <> commandGroup "Nuclear Commands:"+           <> hidden+          )++ where+  installToolFooter :: String+  installToolFooter = [s|Discussion:+  Installs GHC or cabal. When no command is given, installs GHC+  with the specified version/tag.+  It is recommended to always specify a subcommand (ghc/cabal/hls/stack).|]++  setFooter :: String+  setFooter = [s|Discussion:+  Sets the currently active GHC or cabal version. When no command is given,+  defaults to setting GHC with the specified version/tag (if no tag+  is given, sets GHC to 'recommended' version).+  It is recommended to always specify a subcommand (ghc/cabal/hls/stack).|]++  unsetFooter :: String+  unsetFooter = [s|Discussion:+  Unsets the currently active GHC or cabal version.|]++  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).|]++  changeLogFooter :: String+  changeLogFooter = [s|Discussion:+  By default returns the URI of the ChangeLog of the latest GHC release.+  Pass '-o' to automatically open via xdg-open.|]++  whereisFooter :: String+  whereisFooter = [s|Discussion:+  Finds the location of a tool. For GHC, this is the ghc binary, that+  usually resides in a self-contained "~/.ghcup/ghc/<ghcver>" directory.+  For cabal/stack/hls this the binary usually at "~/.ghcup/bin/<tool>-<ver>".++Examples:+  # outputs ~/.ghcup/ghc/8.10.5/bin/ghc.exe+  ghcup whereis ghc 8.10.5+  # outputs ~/.ghcup/ghc/8.10.5/bin/+  ghcup whereis --directory ghc 8.10.5+  # outputs ~/.ghcup/bin/cabal-3.4.0.0+  ghcup whereis cabal 3.4.0.0+  # outputs ~/.ghcup/bin/+  ghcup whereis --directory cabal 3.4.0.0|]++  prefetchFooter :: String+  prefetchFooter = [s|Discussion:+  Prefetches tools or assets into "~/.ghcup/cache" directory. This can+  be then combined later with '--offline' flag, ensuring all assets that+  are required for offline use have been prefetched.++Examples:+  ghcup prefetch metadata+  ghcup prefetch ghc 8.10.5+  ghcup --offline install ghc 8.10.5|]++  gcFooter :: String+  gcFooter = [s|Discussion:+  Performs garbage collection. If no switches are specified, does nothing.|]++configFooter :: String+configFooter = [s|Examples:++# show current config+ghcup config++# initialize config+ghcup config init++# set <key> <value> configuration pair+ghcup config <key> <value>|]++installCabalFooter :: String+installCabalFooter = [s|Discussion:+  Installs the specified cabal-install version (or a recommended default one)+  into "~/.ghcup/bin", so it can be overwritten by later+  "cabal install cabal-install", which installs into "~/.cabal/bin" by+  default. Make sure to set up your PATH appropriately, so the cabal+  installation takes precedence.|]+++installParser :: Parser (Either InstallCommand InstallOptions)+installParser =+  (Left <$> subparser+      (  command+          "ghc"+          (   InstallGHC+          <$> info+                (installOpts (Just GHC) <**> helper)+                (  progDesc "Install GHC"+                <> footerDoc (Just $ text installGHCFooter)+                )+          )+      <> command+           "cabal"+           (   InstallCabal+           <$> info+                 (installOpts (Just Cabal) <**> helper)+                 (  progDesc "Install Cabal"+                 <> footerDoc (Just $ text installCabalFooter)+                 )+           )+      <> command+           "hls"+           (   InstallHLS+           <$> info+                 (installOpts (Just HLS) <**> helper)+                 (  progDesc "Install haskell-language-server"+                 <> footerDoc (Just $ text installHLSFooter)+                 )+           )+      <> command+           "stack"+           (   InstallStack+           <$> info+                 (installOpts (Just Stack) <**> helper)+                 (  progDesc "Install stack"+                 <> footerDoc (Just $ text installStackFooter)+                 )+           )+      )+    )+    <|> (Right <$> installOpts Nothing)+ where+  installHLSFooter :: String+  installHLSFooter = [s|Discussion:+  Installs haskell-language-server binaries and wrapper+  into "~/.ghcup/bin"++Examples:+  # install recommended HLS+  ghcup install hls|]++  installStackFooter :: String+  installStackFooter = [s|Discussion:+  Installs stack binaries into "~/.ghcup/bin"++Examples:+  # install recommended Stack+  ghcup install stack|]++  installGHCFooter :: String+  installGHCFooter = [s|Discussion:+  Installs the specified GHC version (or a recommended default one) into+  a self-contained "~/.ghcup/ghc/<ghcver>" directory+  and symlinks the ghc binaries to "~/.ghcup/bin/<binary>-<ghcver>".++Examples:+  # install recommended GHC+  ghcup install ghc++  # install latest GHC+  ghcup install ghc latest++  # install GHC 8.10.2+  ghcup install ghc 8.10.2++  # install GHC head fedora bindist+  ghcup install ghc -u https://gitlab.haskell.org/api/v4/projects/1/jobs/artifacts/master/raw/ghc-x86_64-fedora27-linux.tar.xz?job=validate-x86_64-linux-fedora27 head|]+++installOpts :: Maybe Tool -> Parser InstallOptions+installOpts tool =+  (\p (u, v) b is f -> InstallOptions v p u b is f)+    <$> optional+          (option+            (eitherReader platformParser)+            (  short 'p'+            <> long "platform"+            <> metavar "PLATFORM"+            <> help+                 "Override for platform (triple matching ghc tarball names), e.g. x86_64-fedora27-linux"+            )+          )+    <*> (   (   (,)+            <$> optional+                  (option+                    (eitherReader bindistParser)+                    (short 'u' <> long "url" <> metavar "BINDIST_URL" <> help+                      "Install the specified version from this bindist"+                    )+                  )+            <*> (Just <$> toolVersionArgument Nothing tool)+            )+        <|> pure (Nothing, Nothing)+        )+    <*> flag+          False+          True+          (long "set" <> help+            "Set as active version after install"+          )+    <*> optional+          (option+           (eitherReader isolateParser)+           (  short 'i'+           <> long "isolate"+           <> metavar "DIR"+           <> help "install in an isolated dir instead of the default one"+           )+          )+    <*> switch+          (short 'f' <> long "force" <> help "Force install")+          +++setParser :: Parser (Either SetCommand SetOptions)+setParser =+  (Left <$> subparser+      (  command+          "ghc"+          (   SetGHC+          <$> info+                (setOpts (Just GHC) <**> helper)+                (  progDesc "Set GHC version"+                <> footerDoc (Just $ text setGHCFooter)+                )+          )+      <> command+           "cabal"+           (   SetCabal+           <$> info+                 (setOpts (Just Cabal) <**> helper)+                 (  progDesc "Set Cabal version"+                 <> footerDoc (Just $ text setCabalFooter)+                 )+           )+      <> command+           "hls"+           (   SetHLS+           <$> info+                 (setOpts (Just HLS) <**> helper)+                 (  progDesc "Set haskell-language-server version"+                 <> footerDoc (Just $ text setHLSFooter)+                 )+           )+      <> command+           "stack"+           (   SetStack+           <$> info+                 (setOpts (Just Stack) <**> helper)+                 (  progDesc "Set stack version"+                 <> footerDoc (Just $ text setStackFooter)+                 )+           )+      )+    )+    <|> (Right <$> setOpts Nothing)+ where+  setGHCFooter :: String+  setGHCFooter = [s|Discussion:+    Sets the the current GHC version by creating non-versioned+    symlinks for all ghc binaries of the specified version in+    "~/.ghcup/bin/<binary>".|]++  setCabalFooter :: String+  setCabalFooter = [s|Discussion:+    Sets the the current Cabal version.|]++  setStackFooter :: String+  setStackFooter = [s|Discussion:+    Sets the the current Stack version.|]++  setHLSFooter :: String+  setHLSFooter = [s|Discussion:+    Sets the the current haskell-language-server version.|]++unsetParser :: Parser UnsetCommand+unsetParser =+  (subparser+      (  command+          "ghc"+          (   UnsetGHC+          <$> info+                (unsetOpts <**> helper)+                (  progDesc "Unset GHC version"+                <> footerDoc (Just $ text unsetGHCFooter)+                )+          )+      <> command+           "cabal"+           (   UnsetCabal+           <$> info+                (unsetOpts <**> helper)+                 (  progDesc "Unset Cabal version"+                 <> footerDoc (Just $ text unsetCabalFooter)+                 )+           )+      <> command+           "hls"+           (   UnsetHLS+           <$> info+                 (unsetOpts <**> helper)+                 (  progDesc "Unset haskell-language-server version"+                 <> footerDoc (Just $ text unsetHLSFooter)+                 )+           )+      <> command+           "stack"+           (   UnsetStack+           <$> info+                 (unsetOpts <**> helper)+                 (  progDesc "Unset stack version"+                 <> footerDoc (Just $ text unsetStackFooter)+                 )+           )+      )+    )+ where+  unsetGHCFooter :: String+  unsetGHCFooter = [s|Discussion:+    Unsets the the current GHC version. That means there won't+    be a ~/.ghcup/bin/ghc anymore.|]++  unsetCabalFooter :: String+  unsetCabalFooter = [s|Discussion:+    Unsets the the current Cabal version.|]++  unsetStackFooter :: String+  unsetStackFooter = [s|Discussion:+    Unsets the the current Stack version.|]++  unsetHLSFooter :: String+  unsetHLSFooter = [s|Discussion:+    Unsets the the current haskell-language-server version.|]+++setOpts :: Maybe Tool -> Parser SetOptions+setOpts tool = SetOptions <$>+    (fromMaybe SetRecommended <$>+      optional (setVersionArgument (Just ListInstalled) tool))++unsetOpts :: Parser UnsetOptions+unsetOpts = UnsetOptions . fmap T.pack <$> optional (argument str (metavar "TRIPLE"))++listOpts :: Parser ListOptions+listOpts =+  ListOptions+    <$> optional+          (option+            (eitherReader toolParser)+            (short 't' <> long "tool" <> metavar "<ghc|cabal|hls|stack>" <> help+              "Tool to list versions for. Default is all"+            )+          )+    <*> optional+          (option+            (eitherReader criteriaParser)+            (  short 'c'+            <> long "show-criteria"+            <> metavar "<installed|set|available>"+            <> help "Show only installed/set/available tool versions"+            )+          )+    <*> switch+          (short 'r' <> long "raw-format" <> help "More machine-parsable format"+          )+++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' (Just ListInstalled) (Just Cabal) <**> helper)+                    (progDesc "Remove Cabal version")+           )+      <> command+           "hls"+           (   RmHLS+           <$> info (versionParser' (Just ListInstalled) (Just HLS) <**> helper)+                    (progDesc "Remove haskell-language-server version")+           )+      <> command+           "stack"+           (   RmStack+           <$> info (versionParser' (Just ListInstalled) (Just Stack) <**> helper)+                    (progDesc "Remove stack version")+           )+      )+    )+    <|> (Right <$> rmOpts Nothing)++++rmOpts :: Maybe Tool -> Parser RmOptions+rmOpts tool = RmOptions <$> versionArgument (Just ListInstalled) tool+++changelogP :: Parser ChangeLogOptions+changelogP =+  (\x y -> ChangeLogOptions x y)+    <$> switch (short 'o' <> long "open" <> help "xdg-open the changelog url")+    <*> optional+          (option+            (eitherReader+              (\s' -> case fmap toLower s' of+                "ghc"   -> Right GHC+                "cabal" -> Right Cabal+                "ghcup" -> Right GHCup+                "stack" -> Right Stack+                e       -> Left e+              )+            )+            (short 't' <> long "tool" <> metavar "<ghc|cabal|ghcup>" <> help+              "Open changelog for given tool (default: ghc)"+            )+          )+    <*> optional (toolVersionArgument Nothing Nothing)++compileP :: Parser CompileCommand+compileP = subparser+  (  command+      "ghc"+      (   CompileGHC+      <$> info+            (ghcCompileOpts <**> helper)+            (  progDesc "Compile GHC from source"+            <> footerDoc (Just $ text compileFooter)+            )+      )+  <>  command+      "hls"+      (   CompileHLS+      <$> info+            (hlsCompileOpts <**> helper)+            (  progDesc "Compile HLS from source"+            <> footerDoc (Just $ text compileHLSFooter)+            )+      )+  )+ where+  compileFooter = [s|Discussion:+  Compiles and installs the specified GHC version into+  a self-contained "~/.ghcup/ghc/<ghcver>" directory+  and symlinks the ghc binaries to "~/.ghcup/bin/<binary>-<ghcver>".++  This also allows building a cross-compiler. Consult the documentation+  first: <https://gitlab.haskell.org/ghc/ghc/-/wikis/building/cross-compiling#configuring-the-build>++ENV variables:+  Various toolchain variables will be passed onto the ghc build system,+  such as: CC, LD, OBJDUMP, NM, AR, RANLIB.++Examples:+  # compile from known version+  ghcup compile ghc -j 4 -v 8.4.2 -b 8.2.2+  # compile from git commit/reference+  ghcup compile ghc -j 4 -g master -b 8.2.2+  # specify path to bootstrap ghc+  ghcup compile ghc -j 4 -v 8.4.2 -b /usr/bin/ghc-8.2.2+  # build cross compiler+  ghcup compile ghc -j 4 -v 8.4.2 -b 8.2.2 -x armv7-unknown-linux-gnueabihf --config $(pwd)/build.mk -- --enable-unregisterised|]++  compileHLSFooter = [s|Discussion:+  Compiles and installs the specified HLS version.+  The last argument is a list of GHC versions to compile for.+  These need to be available in PATH prior to compilation.++Examples:+  ghcup compile hls -v 1.4.0 -j 12 8.10.5 8.10.7 9.0.1|]++configP :: Parser ConfigCommand+configP = subparser+      (  command "init" initP+      <> command "set"  setP -- [set] KEY VALUE at help lhs+      <> command "show" showP+      )+    <|> argsP -- add show for a single option+    <|> pure ShowConfig+ where+  initP = info (pure InitConfig) (progDesc "Write default config to ~/.ghcup/config.yaml")+  showP = info (pure ShowConfig) (progDesc "Show current config (default)")+  setP  = info argsP (progDesc "Set config KEY to VALUE")+  argsP = SetConfig <$> argument str (metavar "KEY") <*> argument str (metavar "VALUE")++whereisP :: Parser WhereisCommand+whereisP = subparser+  (commandGroup "Tools locations:" <> +    command+      "ghc"+      (WhereisTool GHC <$> info+        ( optional (toolVersionArgument Nothing (Just GHC)) <**> helper )+        ( progDesc "Get GHC location"+        <> footerDoc (Just $ text whereisGHCFooter ))+      )+      <>+     command+      "cabal"+      (WhereisTool Cabal <$> info+        ( optional (toolVersionArgument Nothing (Just Cabal)) <**> helper )+        ( progDesc "Get cabal location"+        <> footerDoc (Just $ text whereisCabalFooter ))+      )+      <>+     command+      "hls"+      (WhereisTool HLS <$> info+        ( optional (toolVersionArgument Nothing (Just HLS)) <**> helper )+        ( progDesc "Get HLS location"+        <> footerDoc (Just $ text whereisHLSFooter ))+      )+      <>+     command+      "stack"+      (WhereisTool Stack <$> info+        ( optional (toolVersionArgument Nothing (Just Stack)) <**> helper )+        ( progDesc "Get stack location"+        <> footerDoc (Just $ text whereisStackFooter ))+      )+      <>+     command+      "ghcup"+      (WhereisTool GHCup <$> info ( (pure Nothing) <**> helper ) ( progDesc "Get ghcup location" ))+    ) <|> subparser ( commandGroup "Directory locations:"+      <>+     command+      "basedir"+      (info (pure WhereisBaseDir <**> helper)+            ( progDesc "Get ghcup base directory location" )+      )+      <>+     command+      "bindir"+      (info (pure WhereisBinDir <**> helper)+            ( progDesc "Get ghcup binary directory location" )+      )+      <>+     command+      "cachedir"+      (info (pure WhereisCacheDir <**> helper)+            ( progDesc "Get ghcup cache directory location" )+      )+      <>+     command+      "logsdir"+      (info (pure WhereisLogsDir <**> helper)+            ( progDesc "Get ghcup logs directory location" )+      )+      <>+     command+      "confdir"+      (info (pure WhereisConfDir <**> helper)+            ( progDesc "Get ghcup config directory location" )+      )+  )+ where+  whereisGHCFooter = [s|Discussion:+  Finds the location of a GHC executable, which usually resides in+  a self-contained "~/.ghcup/ghc/<ghcver>" directory.++Examples:+  # outputs ~/.ghcup/ghc/8.10.5/bin/ghc.exe+  ghcup whereis ghc 8.10.5+  # outputs ~/.ghcup/ghc/8.10.5/bin/+  ghcup whereis --directory ghc 8.10.5 |]++  whereisCabalFooter = [s|Discussion:+  Finds the location of a Cabal executable, which usually resides in+  "~/.ghcup/bin/".++Examples:+  # outputs ~/.ghcup/bin/cabal-3.4.0.0+  ghcup whereis cabal 3.4.0.0+  # outputs ~/.ghcup/bin+  ghcup whereis --directory cabal 3.4.0.0|]++  whereisHLSFooter = [s|Discussion:+  Finds the location of a HLS executable, which usually resides in+  "~/.ghcup/bin/".++Examples:+  # outputs ~/.ghcup/bin/haskell-language-server-wrapper-1.2.0+  ghcup whereis hls 1.2.0+  # outputs ~/.ghcup/bin/+  ghcup whereis --directory hls 1.2.0|]++  whereisStackFooter = [s|Discussion:+  Finds the location of a stack executable, which usually resides in+  "~/.ghcup/bin/".++Examples:+  # outputs ~/.ghcup/bin/stack-2.7.1+  ghcup whereis stack 2.7.1+  # outputs ~/.ghcup/bin/+  ghcup whereis --directory stack 2.7.1|]+++prefetchP :: Parser PrefetchCommand+prefetchP = subparser+  (  command+      "ghc"+      (info +        (PrefetchGHC+          <$> (PrefetchGHCOptions+                <$> ( switch (short 's' <> long "source" <> help "Download source tarball instead of bindist") <**> helper )+                <*> optional (option str (short 'd' <> long "directory" <> help "directory to download into (default: ~/.ghcup/cache/)")))+          <*> ( optional (toolVersionArgument Nothing (Just GHC)) ))+        ( progDesc "Download GHC assets for installation")+      )+      <>+     command+      "cabal"+      (info +        (PrefetchCabal+          <$> fmap PrefetchOptions (optional (option str (short 'd' <> long "directory" <> help "directory to download into (default: ~/.ghcup/cache/)")))+          <*> ( optional (toolVersionArgument Nothing (Just Cabal)) <**> helper ))+        ( progDesc "Download cabal assets for installation")+      )+      <>+     command+      "hls"+      (info +        (PrefetchHLS+          <$> fmap PrefetchOptions (optional (option str (short 'd' <> long "directory" <> help "directory to download into (default: ~/.ghcup/cache/)")))+          <*> ( optional (toolVersionArgument Nothing (Just HLS)) <**> helper ))+        ( progDesc "Download HLS assets for installation")+      )+      <>+     command+      "stack"+      (info +        (PrefetchStack+          <$> fmap PrefetchOptions (optional (option str (short 'd' <> long "directory" <> help "directory to download into (default: ~/.ghcup/cache/)")))+          <*> ( optional (toolVersionArgument Nothing (Just Stack)) <**> helper ))+        ( progDesc "Download stack assets for installation")+      )+      <>+     command+      "metadata"+      (const PrefetchMetadata <$> info+        helper+        ( progDesc "Download ghcup's metadata, needed for various operations")+      )+  )++gcP :: Parser GCOptions+gcP =+  GCOptions+  <$> +    switch+      (short 'o' <> long "ghc-old" <> help "Remove GHC versions marked as 'old'")+  <*> +    switch+      (short 'p' <> long "profiling-libs" <> help "Remove profiling libs of GHC versions")+  <*> +    switch+      (short 's' <> long "share-dir" <> help "Remove GHC share directories (documentation)")+  <*> +    switch+      (short 'h' <> long "hls-no-ghc" <> help "Remove HLS versions that don't have a corresponding installed GHC version")+  <*> +    switch+      (short 'c' <> long "cache" <> help "GC the GHCup cache")+  <*> +    switch+      (short 't' <> long "tmpdirs" <> help "Remove tmpdir leftovers")+++ghcCompileOpts :: Parser GHCCompileOptions+ghcCompileOpts =+  GHCCompileOptions+    <$> ((Left <$> option+          (eitherReader+            (first (const "Not a valid version") . version . T.pack)+          )+          (short 'v' <> long "version" <> metavar "VERSION" <> help+            "The tool version to compile"+          )+          ) <|>+          (Right <$> (GitBranch <$> option+          str+          (short 'g' <> long "git-ref" <> metavar "GIT_REFERENCE" <> help+            "The git commit/branch/ref to build from"+          ) <*>+          optional (option str (short 'r' <> long "repository" <> metavar "GIT_REPOSITORY" <> help "The git repository to build from (defaults to GHC upstream)"))+          )))+    <*> option+          (eitherReader+            (\x ->+              (bimap (const "Not a valid version") Left . version . T.pack $ x) <|> (if isPathSeparator (head x) then pure $ Right x else Left "Not an absolute Path")+            )+          )+          (  short 'b'+          <> long "bootstrap-ghc"+          <> metavar "BOOTSTRAP_GHC"+          <> help+               "The GHC version (or full path) to bootstrap with (must be installed)"+          )+    <*> optional+          (option+            (eitherReader (readEither @Int))+            (short 'j' <> long "jobs" <> metavar "JOBS" <> help+              "How many jobs to use for make"+            )+          )+    <*> optional+          (option+            str+            (short 'c' <> long "config" <> metavar "CONFIG" <> help+              "Absolute path to build config file"+            )+          )+    <*> optional+          (option+            str+            (short 'p' <> long "patchdir" <> metavar "PATCH_DIR" <> help+              "Absolute path to patch directory (applies all .patch and .diff files in order using -p1)"+            )+          )+    <*> optional+          (option+            str+            (short 'x' <> long "cross-target" <> metavar "CROSS_TARGET" <> help+              "Build cross-compiler for this platform"+            )+          )+    <*> many (argument str (metavar "CONFIGURE_ARGS" <> help "Additional arguments to configure, prefix with '-- ' (longopts)"))+    <*> flag+          False+          True+          (long "set" <> help+            "Set as active version after install"+          )+    <*> optional+          (option+            (eitherReader+              (first (const "Not a valid version") . version . T.pack)+            )+            (short 'o' <> long "overwrite-version" <> metavar "OVERWRITE_VERSION" <> help+              "Allows to overwrite the finally installed VERSION with a different one, e.g. when you build 8.10.4 with your own patches, you might want to set this to '8.10.4-p1'"+            )+          )+    <*> optional+          (option+            str+            (short 'f' <> long "flavour" <> metavar "BUILD_FLAVOUR" <> help+              "Set the compile build flavour (this value depends on the build system type: 'make' vs 'hadrian')"+            )+          )+    <*> switch+          (long "hadrian" <> help "Use the hadrian build system instead of make (only git versions seem to be properly supported atm)"+          )+    <*> optional+          (option+            (eitherReader isolateParser)+            (  short 'i'+            <> long "isolate"+            <> metavar "DIR"+            <> help "install in an isolated directory instead of the default one, no symlinks to this installation will be made"+            )+           )++hlsCompileOpts :: Parser HLSCompileOptions+hlsCompileOpts =+  HLSCompileOptions+    <$> ((Left <$> option+          (eitherReader+            (first (const "Not a valid version") . version . T.pack)+          )+          (short 'v' <> long "version" <> metavar "VERSION" <> help+            "The tool version to compile"+          )+          ) <|>+          (Right <$> (GitBranch <$> option+          str+          (short 'g' <> long "git-ref" <> metavar "GIT_REFERENCE" <> help+            "The git commit/branch/ref to build from"+          ) <*>+          optional (option str (short 'r' <> long "repository" <> metavar "GIT_REPOSITORY" <> help "The git repository to build from (defaults to GHC upstream)"))+          )))+    <*> optional+          (option+            (eitherReader (readEither @Int))+            (short 'j' <> long "jobs" <> metavar "JOBS" <> help+              "How many jobs to use for make"+            )+          )+    <*> flag+          False+          True+          (long "set" <> help+            "Set as active version after install"+          )+    <*> optional+          (option+            (eitherReader+              (first (const "Not a valid version") . version . T.pack)+            )+            (short 'o' <> long "overwrite-version" <> metavar "OVERWRITE_VERSION" <> help+              "Allows to overwrite the finally installed VERSION with a different one, e.g. when you build 8.10.4 with your own patches, you might want to set this to '8.10.4-p1'"+            )+          )+    <*> optional+          (option+            (eitherReader isolateParser)+            (  short 'i'+            <> long "isolate"+            <> metavar "DIR"+            <> help "install in an isolated directory instead of the default one, no symlinks to this installation will be made"+            )+           )+    <*> optional+          (option+            str+            (long "cabal-project" <> metavar "CABAL_PROJECT" <> help+              "If relative, specifies the path to cabal.project inside the unpacked HLS tarball/checkout. If absolute, will copy the file over."+            )+          )+    <*> optional+          (option+            (eitherReader absolutePathParser)+            (long "cabal-project-local" <> metavar "CABAL_PROJECT_LOCAL" <> help+              "Absolute path to a cabal.project.local to be used for the build. Will be copied over."+            )+          )+    <*> optional+          (option+            (eitherReader absolutePathParser)+            (short 'p' <> long "patchdir" <> metavar "PATCH_DIR" <> help+              "Absolute path to patch directory (applies all .patch and .diff files in order using -p1)"+            )+          )+    <*> some (toolVersionArgument Nothing (Just GHC))+++toolVersionParser :: Parser ToolVersion+toolVersionParser = verP' <|> toolP+ where+  verP' = ToolVersion <$> versionParser+  toolP =+    ToolTag+      <$> option+            (eitherReader tagEither)+            (short 't' <> long "tag" <> metavar "TAG" <> help "The target tag")++-- | same as toolVersionParser, except as an argument.+toolVersionArgument :: Maybe ListCriteria -> Maybe Tool -> Parser ToolVersion+toolVersionArgument criteria tool =+  argument (eitherReader toolVersionEither)+    (metavar (mv tool)+    <> completer (tagCompleter (fromMaybe GHC tool) [])+    <> foldMap (completer . versionCompleter criteria) tool)+ where+  mv (Just GHC) = "GHC_VERSION|TAG"+  mv (Just HLS) = "HLS_VERSION|TAG"+  mv _          = "VERSION|TAG"+++setVersionArgument :: Maybe ListCriteria -> Maybe Tool -> Parser SetToolVersion+setVersionArgument criteria tool =+  argument (eitherReader setEither)+    (metavar "VERSION|TAG|next"+    <> completer (tagCompleter (fromMaybe GHC tool) ["next"])+    <> foldMap (completer . versionCompleter criteria) tool)+ where+  setEither s' =+        parseSet s'+    <|> second SetToolTag (tagEither s')+    <|> second SetToolVersion (tVersionEither s')+  parseSet s' = case fmap toLower s' of+                  "next" -> Right SetNext+                  other  -> Left $ "Unknown tag/version " <> other+++versionArgument :: Maybe ListCriteria -> Maybe Tool -> Parser GHCTargetVersion+versionArgument criteria tool = argument (eitherReader tVersionEither) (metavar "VERSION" <> foldMap (completer . versionCompleter criteria) tool)+++tagCompleter :: Tool -> [String] -> Completer+tagCompleter tool add = listIOCompleter $ do+  dirs' <- liftIO getAllDirs+  let loggerConfig = LoggerConfig+        { lcPrintDebug   = False+        , consoleOutter  = mempty+        , fileOutter     = mempty+        , fancyColors    = False+        }+  let appState = LeanAppState+        (Settings True False Never Curl False GHCupURL True GPGNone False)+        dirs'+        defaultKeyBindings+        loggerConfig++  mGhcUpInfo <- flip runReaderT appState . runE $ getDownloadsF+  case mGhcUpInfo of+    VRight ghcupInfo -> do+      let allTags = filter (\t -> t /= Old)+            $ join+            $ fmap _viTags+            $ M.elems+            $ availableToolVersions (_ghcupDownloads ghcupInfo) tool+      pure $ nub $ (add ++) $ fmap tagToString allTags+    VLeft _ -> pure  (nub $ ["recommended", "latest"] ++ add)+++versionCompleter :: Maybe ListCriteria -> Tool -> Completer+versionCompleter criteria tool = listIOCompleter $ do+  dirs' <- liftIO getAllDirs+  let loggerConfig = LoggerConfig+        { lcPrintDebug   = False+        , consoleOutter  = mempty+        , fileOutter     = mempty+        , fancyColors    = False+        }+  let settings = Settings True False Never Curl False GHCupURL True GPGNone False+  let leanAppState = LeanAppState+                   settings+                   dirs'+                   defaultKeyBindings+                   loggerConfig+  mpFreq <- flip runReaderT leanAppState . runE $ platformRequest+  mGhcUpInfo <- flip runReaderT leanAppState . runE $ getDownloadsF+  forFold mpFreq $ \pfreq -> do+    forFold mGhcUpInfo $ \ghcupInfo -> do+      let appState = AppState+            settings+            dirs'+            defaultKeyBindings+            ghcupInfo+            pfreq+            loggerConfig++          runEnv = flip runReaderT appState++      installedVersions <- runEnv $ listVersions (Just tool) criteria+      return $ T.unpack . prettyVer . lVer <$> installedVersions+++versionParser :: Parser GHCTargetVersion+versionParser = option+  (eitherReader tVersionEither)+  (short 'v' <> long "version" <> metavar "VERSION" <> help "The target version"+  )++versionParser' :: Maybe ListCriteria -> Maybe Tool -> Parser Version+versionParser' criteria tool = argument+  (eitherReader (first show . version . T.pack))+  (metavar "VERSION"  <> foldMap (completer . versionCompleter criteria) tool)+++tagEither :: String -> Either String Tag+tagEither s' = case fmap toLower s' of+  "recommended" -> Right Recommended+  "latest"      -> Right Latest+  ('b':'a':'s':'e':'-':ver') -> case pvp (T.pack ver') of+                                  Right x -> Right (Base x)+                                  Left  _ -> Left $ "Invalid PVP version for base " <> ver'+  other         -> Left $ "Unknown tag " <> other+++tVersionEither :: String -> Either String GHCTargetVersion+tVersionEither =+  first (const "Not a valid version") . MP.parse ghcTargetVerP "" . T.pack+++toolVersionEither :: String -> Either String ToolVersion+toolVersionEither s' =+  second ToolTag (tagEither s') <|> second ToolVersion (tVersionEither s')+++toolParser :: String -> Either String Tool+toolParser s' | t == T.pack "ghc"   = Right GHC+              | t == T.pack "cabal" = Right Cabal+              | t == T.pack "hls"   = Right HLS+              | t == T.pack "stack" = Right Stack+              | otherwise           = Left ("Unknown tool: " <> s')+  where t = T.toLower (T.pack s')+++criteriaParser :: String -> Either String ListCriteria+criteriaParser s' | t == T.pack "installed" = Right ListInstalled+                  | t == T.pack "set"       = Right ListSet+                  | t == T.pack "available" = Right ListAvailable+                  | otherwise               = Left ("Unknown criteria: " <> s')+  where t = T.toLower (T.pack s')+++keepOnParser :: String -> Either String KeepDirs+keepOnParser s' | t == T.pack "always" = Right Always+                | t == T.pack "errors" = Right Errors+                | t == T.pack "never"  = Right Never+                | otherwise            = Left ("Unknown keep value: " <> s')+  where t = T.toLower (T.pack s')+++downloaderParser :: String -> Either String Downloader+downloaderParser s' | t == T.pack "curl"     = Right Curl+                    | t == T.pack "wget"     = Right Wget+#if defined(INTERNAL_DOWNLOADER)+                    | t == T.pack "internal" = Right Internal+#endif+                    | otherwise = Left ("Unknown downloader value: " <> s')+  where t = T.toLower (T.pack s')++gpgParser :: String -> Either String GPGSetting+gpgParser s' | t == T.pack "strict" = Right GPGStrict+             | t == T.pack "lax"    = Right GPGLax+             | t == T.pack "none"   = Right GPGNone+             | otherwise = Left ("Unknown gpg setting value: " <> s')+  where t = T.toLower (T.pack s')+++platformParser :: String -> Either String PlatformRequest+platformParser s' = case MP.parse (platformP <* MP.eof) "" (T.pack s') of+  Right r -> pure r+  Left  e -> Left $ errorBundlePretty e+ where+  archP :: MP.Parsec Void Text Architecture+  archP = MP.try (MP.chunk "x86_64" $> A_64) <|> (MP.chunk "i386" $> A_32)+  platformP :: MP.Parsec Void Text PlatformRequest+  platformP = choice'+    [ (\a mv -> PlatformRequest a FreeBSD mv)+    <$> (archP <* MP.chunk "-")+    <*> (  MP.chunk "portbld"+        *> (   MP.try (Just <$> verP (MP.chunk "-freebsd" <* MP.eof))+           <|> pure Nothing+           )+        <* MP.chunk "-freebsd"+        )+    , (\a mv -> PlatformRequest a Darwin mv)+    <$> (archP <* MP.chunk "-")+    <*> (  MP.chunk "apple"+        *> (   MP.try (Just <$> verP (MP.chunk "-darwin" <* MP.eof))+           <|> pure Nothing+           )+        <* MP.chunk "-darwin"+        )+    , (\a d mv -> PlatformRequest a (Linux d) mv)+    <$> (archP <* MP.chunk "-")+    <*> distroP+    <*> ((MP.try (Just <$> verP (MP.chunk "-linux" <* MP.eof)) <|> pure Nothing+         )+        <* MP.chunk "-linux"+        )+    ]+  distroP :: MP.Parsec Void Text LinuxDistro+  distroP = choice'+    [ MP.chunk "debian" $> Debian+    , MP.chunk "deb" $> Debian+    , MP.chunk "ubuntu" $> Ubuntu+    , MP.chunk "mint" $> Mint+    , MP.chunk "fedora" $> Fedora+    , MP.chunk "centos" $> CentOS+    , MP.chunk "redhat" $> RedHat+    , MP.chunk "alpine" $> Alpine+    , MP.chunk "gentoo" $> Gentoo+    , MP.chunk "exherbo" $> Exherbo+    , MP.chunk "unknown" $> UnknownLinux+    ]+++bindistParser :: String -> Either String URI+bindistParser = first show . parseURI strictURIParserOptions . UTF8.fromString++isolateParser :: FilePath -> Either String FilePath+isolateParser f = case isValid f of+              True -> Right $ normalise f+              False -> Left "Please enter a valid filepath for isolate dir."++absolutePathParser :: FilePath -> Either String FilePath+absolutePathParser f = case isValid f && isAbsolute f of+              True -> Right $ normalise f+              False -> Left "Please enter a valid absolute filepath."++toSettings :: Options -> IO (Settings, KeyBindings)+toSettings options = do+  noColor <- isJust <$> lookupEnv "NO_COLOR"+  userConf <- runE @'[ JSONError ] ghcupConfigFile >>= \case+    VRight r -> pure r+    VLeft (V (JSONDecodeError e)) -> do+      B.hPut stderr ("Error decoding config file: " <> (E.encodeUtf8 . T.pack . show $ e))+      pure defaultUserSettings+    _ -> do+      die "Unexpected error!"+  pure $ mergeConf options userConf noColor+ where+   mergeConf :: Options -> UserSettings -> Bool -> (Settings, KeyBindings)+   mergeConf Options{..} UserSettings{..} noColor =+     let cache       = fromMaybe (fromMaybe False uCache) optCache+         noVerify    = fromMaybe (fromMaybe False uNoVerify) optNoVerify+         verbose     = fromMaybe (fromMaybe False uVerbose) optVerbose+         keepDirs    = fromMaybe (fromMaybe Errors uKeepDirs) optKeepDirs+         downloader  = fromMaybe (fromMaybe defaultDownloader uDownloader) optsDownloader+         keyBindings = maybe defaultKeyBindings mergeKeys uKeyBindings+         urlSource   = maybe (fromMaybe GHCupURL uUrlSource) OwnSource optUrlSource+         noNetwork   = fromMaybe (fromMaybe False uNoNetwork) optNoNetwork+         gpgSetting  = fromMaybe (fromMaybe GPGNone uGPGSetting) optGpg+     in (Settings {..}, keyBindings)+#if defined(INTERNAL_DOWNLOADER)+   defaultDownloader = Internal+#else+   defaultDownloader = Curl+#endif+   mergeKeys :: UserKeyBindings -> KeyBindings+   mergeKeys UserKeyBindings {..} =+     let KeyBindings {..} = defaultKeyBindings+     in KeyBindings {+           bUp = fromMaybe bUp kUp+         , bDown = fromMaybe bDown kDown+         , bQuit = fromMaybe bQuit kQuit+         , bInstall = fromMaybe bInstall kInstall+         , bUninstall = fromMaybe bUninstall kUninstall+         , bSet = fromMaybe bSet kSet+         , bChangelog = fromMaybe bChangelog kChangelog+         , bShowAllVersions = fromMaybe bShowAllVersions kShowAll+         , bShowAllTools = fromMaybe bShowAllTools kShowAllTools+         }++updateSettings :: Monad m => UTF8.ByteString -> Settings -> Excepts '[JSONError] m Settings+updateSettings config settings = do+  settings' <- lE' JSONDecodeError . first snd . Y.decode1Strict $ config+  pure $ mergeConf settings' settings+  where+   mergeConf :: UserSettings -> Settings -> Settings+   mergeConf UserSettings{..} Settings{..} =+     let cache'      = fromMaybe cache uCache+         noVerify'   = fromMaybe noVerify uNoVerify+         keepDirs'   = fromMaybe keepDirs uKeepDirs+         downloader' = fromMaybe downloader uDownloader+         verbose'    = fromMaybe verbose uVerbose+         urlSource'  = fromMaybe urlSource uUrlSource+         noNetwork'  = fromMaybe noNetwork uNoNetwork+         gpgSetting' = fromMaybe gpgSetting uGPGSetting+     in Settings cache' noVerify' keepDirs' downloader' verbose' urlSource' noNetwork' gpgSetting' noColor++upgradeOptsP :: Parser UpgradeOpts+upgradeOptsP =+  flag'+      UpgradeInplace+      (short 'i' <> long "inplace" <> help+        "Upgrade ghcup in-place (wherever it's at)"+      )+    <|> (   UpgradeAt+        <$> option+              str+              (short 't' <> long "target" <> metavar "TARGET_DIR" <> help+                "Absolute filepath to write ghcup into"+              )+        )+    <|> pure UpgradeGHCupDir++++describe_result :: String+describe_result = $( LitE . StringL <$>+                     runIO (do+                             CapturedProcess{..} <-  do+                              dirs <- liftIO getAllDirs+                              let settings = AppState (Settings True False Never Curl False GHCupURL False GPGNone False)+                                               dirs+                                               defaultKeyBindings+                              flip runReaderT settings $ executeOut "git" ["describe"] Nothing+                             case _exitCode of+                               ExitSuccess   -> pure . T.unpack . decUTF8Safe' $ _stdOut+                               ExitFailure _ -> pure numericVer+                     )+                   )++plan_json :: String+plan_json = $( do+                (fp, c) <- runIO (handleIO (\_ -> pure ("", "")) $ do+                             fp <- findPlanJson (ProjectRelativeToDir ".")+                             c <- B.readFile fp+                             (Just res) <- pure $ decodeStrict' @Value c+                             pure (fp, T.unpack $ decUTF8Safe' $ encodePretty res))+                when (not . null $ fp ) $ qAddDependentFile fp+                pure . LitE . StringL $ c)++formatConfig :: UserSettings -> String+formatConfig settings+  = UTF8.toString . Y.encode1Strict $ settings++main :: IO ()+main = do+  -- https://gitlab.haskell.org/ghc/ghc/issues/8118+  setLocaleEncoding utf8++  void enableAnsiSupport++  let versionHelp = infoOption+        ( ("The GHCup Haskell installer, version " <>)+          (head . lines $ describe_result)+        )+        (long "version" <> help "Show version" <> hidden)+  let planJson = infoOption+        plan_json+        (long "plan-json" <> help "Show the build-time configuration" <> internal)+  let numericVersionHelp = infoOption+        numericVer+        (  long "numeric-version"+        <> help "Show the numeric version (for use in scripts)"+        <> hidden+        )+  let listCommands = infoOption+        "install set rm install-cabal list upgrade compile debug-info tool-requirements changelog"+        (  long "list-commands"+        <> help "List available commands for shell completion"+        <> internal+        )++  let main_footer = [s|Discussion:+  ghcup installs the Glasgow Haskell Compiler from the official+  release channels, enabling you to easily switch between different+  versions. It maintains a self-contained ~/.ghcup directory.++ENV variables:+  * TMPDIR: where ghcup does the work (unpacking, building, ...)+  * GHCUP_INSTALL_BASE_PREFIX: the base of ghcup (default: $HOME)+  * GHCUP_USE_XDG_DIRS: set to anything to use XDG style directories++Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]++  customExecParser+      (prefs showHelpOnError)+      (info (opts <**> helper <**> versionHelp <**> numericVersionHelp <**> planJson <**> listCommands)+            (footerDoc (Just $ text main_footer))+      )+    >>= \opt@Options {..} -> do+          dirs@Dirs{..} <- getAllDirs++          -- create ~/.ghcup dir+          ensureDirectories dirs++          (settings, keybindings) <- toSettings opt+++          -- logger interpreter+          logfile <- flip runReaderT dirs initGHCupFileLogging+          no_color <- isJust <$> lookupEnv "NO_COLOR"+          let loggerConfig = LoggerConfig+                { lcPrintDebug = verbose settings+                , consoleOutter  = T.hPutStr stderr+                , fileOutter    =+                    case optCommand of+                      Nuke -> \_ -> pure ()+                      _ -> T.appendFile logfile+                , fancyColors = not no_color+                }+          let leanAppstate = LeanAppState settings dirs keybindings loggerConfig+          let runLogger = flip runReaderT leanAppstate+          let siletRunLogger = flip runReaderT (leanAppstate { loggerConfig = loggerConfig { consoleOutter = \_ -> pure () } } :: LeanAppState)+++          -------------------------+          -- Setting up appstate --+          -------------------------+++              appState = do+                pfreq <- (+                  runLogger . runE @'[NoCompatiblePlatform, NoCompatibleArch, DistroNotFound] . liftE $ platformRequest+                  ) >>= \case+                          VRight r -> pure r+                          VLeft e -> do+                            runLogger+                              (logError $ T.pack $ prettyShow e)+                            exitWith (ExitFailure 2)++                ghcupInfo <-+                  ( flip runReaderT leanAppstate+                    . runE @'[DigestError, GPGError, JSONError , DownloadFailed, FileDoesNotExistError]+                    $ liftE+                    $ getDownloadsF+                    )+                    >>= \case+                          VRight r -> pure r+                          VLeft  e -> do+                            runLogger+                              (logError $ T.pack $ prettyShow e)+                            exitWith (ExitFailure 2)+                let s' = AppState settings dirs keybindings ghcupInfo pfreq loggerConfig++                race_ (liftIO $ flip runReaderT s' cleanupTrash)+                      (threadDelay 5000000 >> runLogger (logWarn $ "Killing cleanup thread (exceeded 5s timeout)... please remove leftover files in " <> T.pack recycleDir <> " manually"))++                case optCommand of+                  Nuke -> pure ()+                  Whereis _ _ -> pure ()+                  DInfo -> pure ()+                  ToolRequirements -> pure ()+                  ChangeLog _ -> pure ()+                  UnSet _ -> pure ()+#if defined(BRICK)+                  Interactive -> pure ()+#endif+                  _ -> lookupEnv "GHCUP_SKIP_UPDATE_CHECK" >>= \case+                         Nothing -> flip runReaderT s' checkForUpdates+                         Just _ -> pure ()++                -- TODO: always run for windows+                (siletRunLogger $ flip runReaderT s' $ runE ensureGlobalTools) >>= \case+                  VRight _ -> pure ()+                  VLeft e -> do+                    runLogger+                      (logError $ T.pack $ prettyShow e)+                    exitWith (ExitFailure 30)+                pure s'+++#if defined(IS_WINDOWS)+              -- FIXME: windows needs 'ensureGlobalTools', which requires+              -- full appstate+              runLeanAppState = runAppState+#else+              runLeanAppState = flip runReaderT leanAppstate+#endif+              runAppState action' = do+                s' <- liftIO appState+                flip runReaderT s' action'+                  ++++          -------------------------+          -- Effect interpreters --+          -------------------------+++          let runInstTool' appstate' mInstPlatform =+                  flip runReaderT (maybe appstate' (\x -> appstate'{ pfreq = x } :: AppState) mInstPlatform)+                  . runResourceT+                  . runE+                    @'[ AlreadyInstalled+                      , UnknownArchive+                      , ArchiveResult+                      , FileDoesNotExistError+                      , CopyError+                      , NotInstalled+                      , DirNotEmpty+                      , NoDownload+                      , NotInstalled+                      , BuildFailed+                      , TagNotFound+                      , DigestError+                      , GPGError+                      , DownloadFailed+                      , TarDirDoesNotExist+                      , NextVerNotFound+                      , NoToolVersionSet+                      , FileAlreadyExistsError+                      ]++          let runInstTool mInstPlatform action' = do+                s' <- liftIO appState+                runInstTool' s' mInstPlatform action'++          let+            runLeanSetGHC =+                runLeanAppState+                . runE+                  @'[ FileDoesNotExistError+                    , NotInstalled+                    , TagNotFound+                    , NextVerNotFound+                    , NoToolVersionSet+                    ]++            runSetGHC =+                runAppState+                . runE+                  @'[ FileDoesNotExistError+                    , NotInstalled+                    , TagNotFound+                    , NextVerNotFound+                    , NoToolVersionSet+                    ]++            runUnsetGHC =+                runLeanAppState+                . runE+                  @'[ NotInstalled ]++          let+            runLeanSetCabal =+                runLeanAppState+                . runE+                  @'[ NotInstalled+                    , TagNotFound+                    , NextVerNotFound+                    , NoToolVersionSet+                    ]++            runSetCabal =+                runAppState+                . runE+                  @'[ NotInstalled+                    , TagNotFound+                    , NextVerNotFound+                    , NoToolVersionSet+                    ]++          let+            runSetHLS =+                runAppState+                . runE+                  @'[ NotInstalled+                    , TagNotFound+                    , NextVerNotFound+                    , NoToolVersionSet+                    ]++            runLeanSetHLS =+                runLeanAppState+                . runE+                  @'[ NotInstalled+                    , TagNotFound+                    , NextVerNotFound+                    , NoToolVersionSet+                    ]++          let runListGHC = runAppState++          let runRm =+                runAppState . runE @'[NotInstalled]++          let runNuke s' =+                flip runReaderT s' . runE @'[NotInstalled]++          let runDebugInfo =+                  runAppState+                  . runE+                    @'[NoCompatiblePlatform , NoCompatibleArch , DistroNotFound]++          let runCompileGHC =+                  runAppState+                  . runResourceT+                  . runE+                    @'[ AlreadyInstalled+                      , BuildFailed+                      , DigestError+                      , GPGError+                      , DownloadFailed+                      , GHCupSetError+                      , NoDownload+                      , NotFoundInPATH+                      , PatchFailed+                      , UnknownArchive+                      , TarDirDoesNotExist+                      , NotInstalled+                      , DirNotEmpty+                      , ArchiveResult+                      ]++          let runCompileHLS =+                  runAppState+                  . runResourceT+                  . runE+                    @'[ AlreadyInstalled+                      , BuildFailed+                      , DigestError+                      , GPGError+                      , DownloadFailed+                      , GHCupSetError+                      , NoDownload+                      , NotFoundInPATH+                      , PatchFailed+                      , UnknownArchive+                      , TarDirDoesNotExist+                      , TagNotFound+                      , NextVerNotFound+                      , NoToolVersionSet+                      , NotInstalled+                      , DirNotEmpty+                      , ArchiveResult+                      ]++          let+            runLeanWhereIs =+                -- Don't use runLeanAppState here, which is disabled on windows.+                -- This is the only command on all platforms that doesn't need full appstate.+                flip runReaderT leanAppstate+                . runE+                  @'[ NotInstalled+                    , NoToolVersionSet+                    , NextVerNotFound+                    , TagNotFound+                    ]++            runWhereIs =+                runAppState+                . runE+                  @'[ NotInstalled+                    , NoToolVersionSet+                    , NextVerNotFound+                    , TagNotFound+                    ]++          let runUpgrade =+                  runAppState+                  . runResourceT+                  . runE+                    @'[ DigestError+                      , GPGError+                      , NoDownload+                      , NoUpdate+                      , FileDoesNotExistError+                      , CopyError+                      , DownloadFailed+                      ]++          let runPrefetch =+                  runAppState+                  . runResourceT+                  . runE+                    @'[ TagNotFound+                      , NextVerNotFound+                      , NoToolVersionSet+                      , NoDownload+                      , DigestError+                      , GPGError+                      , DownloadFailed+                      , JSONError+                      , FileDoesNotExistError+                      ]++          let runGC =+                  runAppState+                  . runResourceT+                  . runE+                    @'[ NotInstalled+                      ]+++          -----------------------+          -- Command functions --+          -----------------------++          let installGHC InstallOptions{..} =+                (case instBindist of+                   Nothing -> runInstTool instPlatform $ do+                     (v, vi) <- liftE $ fromVersion instVer GHC+                     liftE $ installGHCBin+                               (_tvVersion v)+                               isolateDir+                               forceInstall+                     when instSet $ void $ liftE $ setGHC v SetGHCOnly+                     pure vi+                   Just uri -> do+                     s' <- liftIO appState+                     runInstTool' s'{ settings = settings {noVerify = True}} instPlatform $ do+                       (v, vi) <- liftE $ fromVersion instVer GHC+                       liftE $ installGHCBindist+                                 (DownloadInfo uri (Just $ RegexDir "ghc-.*") "")+                                 (_tvVersion v)+                                 isolateDir+                                 forceInstall+                       when instSet $ void $ liftE $ setGHC v SetGHCOnly+                       pure vi+                  )+                    >>= \case+                          VRight vi -> do+                            runLogger $ logInfo "GHC installation successful"+                            forM_ (_viPostInstall =<< vi) $ \msg ->+                              runLogger $ logInfo msg+                            pure ExitSuccess+                          VLeft (V (AlreadyInstalled _ v)) -> do+                            runLogger $ logWarn $+                              "GHC ver " <> prettyVer v <> " already installed; if you really want to reinstall it, you may want to run 'ghcup install ghc --force " <> prettyVer v <> "'"+                            pure ExitSuccess+                          VLeft (V (DirNotEmpty fp)) -> do+                            runLogger $ logWarn $+                              "Install directory " <> T.pack fp <> " is not empty. Use 'ghcup install ghc --isolate " <> T.pack fp <> " --force ..." <> "' to install regardless."+                            pure $ ExitFailure 3+                          VLeft err@(V (BuildFailed tmpdir _)) -> do+                            case keepDirs settings of+                              Never -> runLogger $ (logError $ T.pack $ prettyShow err)+                              _ -> runLogger $ (logError $ T.pack (prettyShow err) <> "\n" <>+                                "Check the logs at " <> T.pack logsDir <> " and the build directory " <> T.pack tmpdir <> " for more clues." <> "\n" <>+                                "Make sure to clean up " <> T.pack tmpdir <> " afterwards.")+                            pure $ ExitFailure 3+                          VLeft e -> do+                            runLogger $ do+                              logError $ T.pack $ prettyShow e+                              logError $ "Also check the logs in " <> T.pack logsDir+                            pure $ ExitFailure 3+++          let installCabal InstallOptions{..} =+                (case instBindist of+                   Nothing -> runInstTool instPlatform $ do+                     (v, vi) <- liftE $ fromVersion instVer Cabal+                     liftE $ installCabalBin+                               (_tvVersion v)+                               isolateDir+                               forceInstall+                     pure vi+                   Just uri -> do+                     s' <- appState+                     runInstTool' s'{ settings = settings { noVerify = True}} instPlatform $ do+                       (v, vi) <- liftE $ fromVersion instVer Cabal+                       liftE $ installCabalBindist +                                 (DownloadInfo uri Nothing "")+                                 (_tvVersion v)+                                 isolateDir+                                 forceInstall+                       pure vi+                  )+                  >>= \case+                        VRight vi -> do+                          runLogger $ logInfo "Cabal installation successful"+                          forM_ (_viPostInstall =<< vi) $ \msg ->+                            runLogger $ logInfo msg+                          pure ExitSuccess+                        VLeft (V (AlreadyInstalled _ v)) -> do+                          runLogger $ logWarn $+                            "Cabal ver " <> prettyVer v <> " already installed; if you really want to reinstall it, you may want to run 'ghcup install cabal --force " <> prettyVer v <> "'"+                          pure ExitSuccess+                        VLeft (V (FileAlreadyExistsError fp)) -> do+                          runLogger $ logWarn $+                            "File " <> T.pack fp <> " already exists. Use 'ghcup install cabal --isolate " <> T.pack fp <> " --force ..." <> "' if you want to overwrite."+                          pure $ ExitFailure 3+                        VLeft e -> do+                          runLogger $ do+                            logError $ T.pack $ prettyShow e+                            logError $ "Also check the logs in " <> T.pack logsDir+                          pure $ ExitFailure 4++          let installHLS InstallOptions{..} =+                 (case instBindist of+                   Nothing -> runInstTool instPlatform $ do+                     (v, vi) <- liftE $ fromVersion instVer HLS+                     liftE $ installHLSBin+                               (_tvVersion v)+                               isolateDir+                               forceInstall+                     pure vi+                   Just uri -> do+                     s' <- appState+                     runInstTool' s'{ settings = settings { noVerify = True}} instPlatform $ do+                       (v, vi) <- liftE $ fromVersion instVer HLS+                       liftE $ installHLSBindist+                                 (DownloadInfo uri Nothing "")+                                 (_tvVersion v)+                                 isolateDir+                                 forceInstall+                       pure vi+                  )+                  >>= \case+                        VRight vi -> do+                          runLogger $ logInfo "HLS installation successful"+                          forM_ (_viPostInstall =<< vi) $ \msg ->+                            runLogger $ logInfo msg+                          pure ExitSuccess+                        VLeft (V (AlreadyInstalled _ v)) -> do+                          runLogger $ logWarn $+                              "HLS ver "+                            <> prettyVer v+                            <> " already installed; if you really want to reinstall it, you may want to run 'ghcup install hls --force "+                            <> prettyVer v+                            <> "'"+                          pure ExitSuccess+                        VLeft (V (FileAlreadyExistsError fp)) -> do+                          runLogger $ logWarn $+                            "File " <> T.pack fp <> " already exists. Use 'ghcup install hls --isolate " <> T.pack fp <> " --force ..." <> "' if you want to overwrite."+                          pure $ ExitFailure 3+                        VLeft e -> do+                          runLogger $ do+                            logError $ T.pack $ prettyShow e+                            logError $ "Also check the logs in " <> T.pack logsDir+                          pure $ ExitFailure 4++          let installStack InstallOptions{..} =+                 (case instBindist of+                    Nothing -> runInstTool instPlatform $ do+                      (v, vi) <- liftE $ fromVersion instVer Stack+                      liftE $ installStackBin+                                (_tvVersion v)+                                isolateDir+                                forceInstall+                      pure vi+                    Just uri -> do+                      s' <- appState+                      runInstTool' s'{ settings = settings { noVerify = True}} instPlatform $ do+                        (v, vi) <- liftE $ fromVersion instVer Stack+                        liftE $ installStackBindist+                                  (DownloadInfo uri Nothing "")+                                  (_tvVersion v)+                                  isolateDir+                                  forceInstall+                        pure vi+                  )+                  >>= \case+                        VRight vi -> do+                          runLogger $ logInfo "Stack installation successful"+                          forM_ (_viPostInstall =<< vi) $ \msg ->+                            runLogger $ logInfo msg+                          pure ExitSuccess+                        VLeft (V (AlreadyInstalled _ v)) -> do+                          runLogger $ logWarn $+                            "Stack ver " <> prettyVer v <> " already installed; if you really want to reinstall it, you may want to run 'ghcup install stack --force " <> prettyVer v <> "'"+                          pure ExitSuccess+                        VLeft (V (FileAlreadyExistsError fp)) -> do+                          runLogger $ logWarn $+                            "File " <> T.pack fp <> " already exists. Use 'ghcup install stack --isolate " <> T.pack fp <> " --force ..." <> "' if you want to overwrite."+                          pure $ ExitFailure 3+                        VLeft e -> do+                          runLogger $ do+                            logError $ T.pack $ prettyShow e+                            logError $ "Also check the logs in " <> T.pack logsDir+                          pure $ ExitFailure 4+++          let setGHC' SetOptions{ sToolVer } =+                case sToolVer of+                  (SetToolVersion v) -> runLeanSetGHC (liftE $ setGHC v SetGHCOnly >> pure v)+                  _ -> runSetGHC (do+                      v <- liftE $ fst <$> fromVersion' sToolVer GHC+                      liftE $ setGHC v SetGHCOnly+                    )+                  >>= \case+                        VRight GHCTargetVersion{..} -> do+                          runLogger+                            $ logInfo $+                                "GHC " <> prettyVer _tvVersion <> " successfully set as default version" <> maybe "" (" for cross target " <>) _tvTarget+                          pure ExitSuccess+                        VLeft e -> do+                          runLogger $ logError $ T.pack $ prettyShow e+                          pure $ ExitFailure 5++          let setCabal' SetOptions{ sToolVer } =+                case sToolVer of+                  (SetToolVersion v) -> runLeanSetCabal (liftE $ setCabal (_tvVersion v) >> pure v)+                  _ -> runSetCabal (do+                      v <- liftE $ fst <$> fromVersion' sToolVer Cabal+                      liftE $ setCabal (_tvVersion v)+                      pure v+                    )+                  >>= \case+                        VRight GHCTargetVersion{..} -> do+                          runLogger+                            $ logInfo $+                                "Cabal " <> prettyVer _tvVersion <> " successfully set as default version"+                          pure ExitSuccess+                        VLeft  e -> do+                          runLogger $ logError $ T.pack $ prettyShow e+                          pure $ ExitFailure 14++          let setHLS' SetOptions{ sToolVer } =+                case sToolVer of+                  (SetToolVersion v) -> runLeanSetHLS (liftE $ setHLS (_tvVersion v) >> pure v)+                  _ -> runSetHLS (do+                      v <- liftE $ fst <$> fromVersion' sToolVer HLS+                      liftE $ setHLS (_tvVersion v)+                      pure v+                    )+                  >>= \case+                        VRight GHCTargetVersion{..} -> do+                          runLogger+                            $ logInfo $+                                "HLS " <> prettyVer _tvVersion <> " successfully set as default version"+                          pure ExitSuccess+                        VLeft  e -> do+                          runLogger $ logError $ T.pack $ prettyShow e+                          pure $ ExitFailure 14++          let setStack' SetOptions{ sToolVer } =+                case sToolVer of+                  (SetToolVersion v) -> runSetCabal (liftE $ setStack (_tvVersion v) >> pure v)+                  _ -> runSetCabal (do+                        v <- liftE $ fst <$> fromVersion' sToolVer Stack+                        liftE $ setStack (_tvVersion v)+                        pure v+                      )+                  >>= \case+                        VRight GHCTargetVersion{..} -> do+                          runLogger+                            $ logInfo $+                                "Stack " <> prettyVer _tvVersion <> " successfully set as default version"+                          pure ExitSuccess+                        VLeft  e -> do+                          runLogger $ logError $ T.pack $ prettyShow e+                          pure $ ExitFailure 14++          let rmGHC' RmOptions{..} =+                runRm (do+                    liftE $+                      rmGHCVer ghcVer+                    GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo+                    pure (getVersionInfo (_tvVersion ghcVer) GHC dls)+                  )+                  >>= \case+                        VRight vi -> do+                          forM_ (_viPostRemove =<< vi) $ \msg ->+                            runLogger $ logInfo msg+                          pure ExitSuccess+                        VLeft  e -> do+                          runLogger $ logError $ T.pack $ prettyShow e+                          pure $ ExitFailure 7++          let rmCabal' tv =+                runRm (do+                    liftE $+                      rmCabalVer tv+                    GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo+                    pure (getVersionInfo tv Cabal dls)+                  )+                  >>= \case+                        VRight vi -> do+                          forM_ (_viPostRemove =<< vi) $ \msg ->+                            runLogger $ logInfo msg+                          pure ExitSuccess+                        VLeft  e -> do+                          runLogger $ logError $ T.pack $ prettyShow e+                          pure $ ExitFailure 15++          let rmHLS' tv =+                runRm (do+                    liftE $+                      rmHLSVer tv+                    GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo+                    pure (getVersionInfo tv HLS dls)+                  )+                  >>= \case+                        VRight vi -> do+                          forM_ (_viPostRemove =<< vi) $ \msg ->+                            runLogger $ logInfo msg+                          pure ExitSuccess+                        VLeft  e -> do+                          runLogger $ logError $ T.pack $ prettyShow e+                          pure $ ExitFailure 15++          let rmStack' tv =+                runRm (do+                    liftE $+                      rmStackVer tv+                    GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo+                    pure (getVersionInfo tv Stack dls)+                  )+                  >>= \case+                        VRight vi -> do+                          forM_ (_viPostRemove =<< vi) $ \msg ->+                            runLogger $ logInfo msg+                          pure ExitSuccess+                        VLeft  e -> do+                          runLogger $ logError $ T.pack $ prettyShow e+                          pure $ ExitFailure 15++          res <- case optCommand of+#if defined(BRICK)+            Interactive -> do+              s' <- appState+              liftIO $ brickMain s' >> pure ExitSuccess+#endif+            Install (Right iopts) -> do+              runLogger (logWarn "This is an old-style command for installing GHC. Use 'ghcup install ghc' instead.")+              installGHC iopts+            Install (Left (InstallGHC iopts)) -> installGHC iopts+            Install (Left (InstallCabal iopts)) -> installCabal iopts+            Install (Left (InstallHLS iopts)) -> installHLS iopts+            Install (Left (InstallStack iopts)) -> installStack iopts+            InstallCabalLegacy iopts -> do+              runLogger (logWarn "This is an old-style command for installing cabal. Use 'ghcup install cabal' instead.")+              installCabal iopts++            Set (Right sopts) -> do+              runLogger (logWarn "This is an old-style command for setting GHC. Use 'ghcup set ghc' instead.")+              setGHC' sopts+            Set (Left (SetGHC sopts)) -> setGHC' sopts+            Set (Left (SetCabal sopts)) -> setCabal' sopts+            Set (Left (SetHLS sopts)) -> setHLS' sopts+            Set (Left (SetStack sopts)) -> setStack' sopts++            UnSet (UnsetGHC (UnsetOptions triple)) -> runUnsetGHC (unsetGHC triple)+                  >>= \case+                        VRight _ -> do+                          runLogger $ logInfo "GHC successfully unset"+                          pure ExitSuccess+                        VLeft  e -> do+                          runLogger $ logError $ T.pack $ prettyShow e+                          pure $ ExitFailure 14+            UnSet (UnsetCabal (UnsetOptions _)) -> do+              runAppState unsetCabal+              runLogger $ logInfo "Cabal successfully unset"+              pure ExitSuccess+            UnSet (UnsetHLS (UnsetOptions _)) -> do+              runAppState unsetHLS+              runLogger $ logInfo "HLS successfully unset"+              pure ExitSuccess+            UnSet (UnsetStack (UnsetOptions _)) -> do+              runAppState unsetStack+              runLogger $ logInfo "Stack successfully unset"+              pure ExitSuccess++            List ListOptions {..} ->+              runListGHC (do+                  l <- listVersions loTool lCriteria+                  liftIO $ printListResult no_color lRawFormat l+                  pure ExitSuccess+                )++            Rm (Right rmopts) -> do+              runLogger (logWarn "This is an old-style command for removing GHC. Use 'ghcup rm ghc' instead.")+              rmGHC' rmopts+            Rm (Left (RmGHC rmopts)) -> rmGHC' rmopts+            Rm (Left (RmCabal rmopts)) -> rmCabal' rmopts+            Rm (Left (RmHLS rmopts)) -> rmHLS' rmopts+            Rm (Left (RmStack rmopts)) -> rmStack' rmopts++            DInfo ->+              do runDebugInfo $ liftE getDebugInfo+                >>= \case+                      VRight dinfo -> do+                        putStrLn $ prettyDebugInfo dinfo+                        pure ExitSuccess+                      VLeft e -> do+                        runLogger $ logError $ T.pack $ prettyShow e+                        pure $ ExitFailure 8++            Compile (CompileHLS HLSCompileOptions { .. }) -> do+              runCompileHLS (do+                case targetHLS of+                  Left targetVer -> do+                    GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo+                    let vi = getVersionInfo targetVer HLS dls+                    forM_ (_viPreCompile =<< vi) $ \msg -> do+                      lift $ logInfo msg+                      lift $ logInfo+                        "...waiting for 5 seconds, you can still abort..."+                      liftIO $ threadDelay 5000000 -- for compilation, give the user a sec to intervene+                  Right _ -> pure ()+                ghcs <- liftE $ forM targetGHCs (\ghc -> fmap (_tvVersion . fst) . fromVersion (Just ghc) $ GHC)+                targetVer <- liftE $ compileHLS+                            targetHLS+                            ghcs+                            jobs+                            ovewrwiteVer+                            isolateDir+                            cabalProject+                            cabalProjectLocal+                            patchDir+                GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo+                let vi = getVersionInfo targetVer HLS dls+                when setCompile $ void $ liftE $+                  setHLS targetVer+                pure (vi, targetVer)+                )+                >>= \case+                      VRight (vi, tv) -> do+                        runLogger $ logInfo+                          "HLS successfully compiled and installed"+                        forM_ (_viPostInstall =<< vi) $ \msg ->+                          runLogger $ logInfo msg+                        putStr (T.unpack $ prettyVer tv)+                        pure ExitSuccess+                      VLeft err@(V (BuildFailed tmpdir _)) -> do+                        case keepDirs settings of+                          Never -> runLogger $ logError $ T.pack $ prettyShow err+                          _ -> runLogger $ (logError $ T.pack (prettyShow err) <> "\n" <>+                                "Check the logs at " <> T.pack logsDir <> " and the build directory "+                                <> T.pack tmpdir <> " for more clues." <> "\n" <>+                                "Make sure to clean up " <> T.pack tmpdir <> " afterwards.")+                        pure $ ExitFailure 9+                      VLeft e -> do+                        runLogger $ logError $ T.pack $ prettyShow e+                        pure $ ExitFailure 9+            Compile (CompileGHC GHCCompileOptions { hadrian = True, crossTarget = Just _ }) -> do+              runLogger $ logError "Hadrian cross compile support is not yet implemented!"+              pure $ ExitFailure 9+            Compile (CompileGHC GHCCompileOptions {..}) ->+              runCompileGHC (do+                case targetGhc of+                  Left targetVer -> do+                    GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo+                    let vi = getVersionInfo targetVer GHC dls+                    forM_ (_viPreCompile =<< vi) $ \msg -> do+                      lift $ logInfo msg+                      lift $ logInfo+                        "...waiting for 5 seconds, you can still abort..."+                      liftIO $ threadDelay 5000000 -- for compilation, give the user a sec to intervene+                  Right _ -> pure ()+                targetVer <- liftE $ compileGHC+                            (first (GHCTargetVersion crossTarget) targetGhc)+                            ovewrwiteVer+                            bootstrapGhc+                            jobs+                            buildConfig+                            patchDir+                            addConfArgs+                            buildFlavour+                            hadrian+                            isolateDir+                GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo+                let vi = getVersionInfo (_tvVersion targetVer) GHC dls+                when setCompile $ void $ liftE $+                  setGHC targetVer SetGHCOnly+                pure (vi, targetVer)+                )+                >>= \case+                      VRight (vi, tv) -> do+                        runLogger $ logInfo+                          "GHC successfully compiled and installed"+                        forM_ (_viPostInstall =<< vi) $ \msg ->+                          runLogger $ logInfo msg+                        putStr (T.unpack $ tVerToText tv)+                        pure ExitSuccess+                      VLeft (V (AlreadyInstalled _ v)) -> do+                        runLogger $ logWarn $+                          "GHC ver " <> prettyVer v <> " already installed; if you really want to reinstall it, you may want to run 'ghcup install ghc --force " <> prettyVer v <> "'"+                        pure ExitSuccess+                      VLeft (V (DirNotEmpty fp)) -> do+                        runLogger $ logWarn $+                          "Install directory " <> T.pack fp <> " is not empty. Use 'ghcup install ghc --isolate " <> T.pack fp <> " --force ..." <> "' to install regardless."+                        pure $ ExitFailure 3+                      VLeft err@(V (BuildFailed tmpdir _)) -> do+                        case keepDirs settings of+                          Never -> runLogger $ logError $ T.pack $ prettyShow err+                          _ -> runLogger $ (logError $ T.pack (prettyShow err) <> "\n" <>+                                "Check the logs at " <> T.pack logsDir <> " and the build directory "+                                <> T.pack tmpdir <> " for more clues." <> "\n" <>+                                "Make sure to clean up " <> T.pack tmpdir <> " afterwards.")+                        pure $ ExitFailure 9+                      VLeft e -> do+                        runLogger $ logError $ T.pack $ prettyShow e+                        pure $ ExitFailure 9++            Config InitConfig -> do+              path <- getConfigFilePath+              writeFile path $ formatConfig $ fromSettings settings (Just keybindings)+              runLogger $ logDebug $ "config.yaml initialized at " <> T.pack path+              pure ExitSuccess++            Config ShowConfig -> do+              putStrLn $ formatConfig $ fromSettings settings (Just keybindings)+              pure ExitSuccess++            Config (SetConfig k v) -> do+              case v of+                "" -> do+                  runLogger $ logError "Empty values are not allowed"+                  pure $ ExitFailure 55+                _  -> do+                  r <- runE @'[JSONError] $ do+                    settings' <- updateSettings (UTF8.fromString (k <> ": " <> v <> "\n")) settings+                    path <- liftIO getConfigFilePath+                    liftIO $ writeFile path $ formatConfig $ fromSettings settings' (Just keybindings)+                    runLogger $ logDebug $ T.pack $ show settings'+                    pure ()++                  case r of+                      VRight _ -> pure ExitSuccess+                      VLeft (V (JSONDecodeError e)) -> do+                        runLogger $ logError $ "Error decoding config: " <> T.pack e+                        pure $ ExitFailure 65+                      VLeft _ -> pure $ ExitFailure 65++            Whereis WhereisOptions{..} (WhereisTool tool (Just (ToolVersion v))) ->+              runLeanWhereIs (do+                loc <- liftE $ whereIsTool tool v+                if directory+                then pure $ takeDirectory loc+                else pure loc+                )+                >>= \case+                      VRight r -> do+                        putStr r+                        pure ExitSuccess+                      VLeft e -> do+                        runLogger $ logError $ T.pack $ prettyShow e+                        pure $ ExitFailure 30++            Whereis WhereisOptions{..} (WhereisTool tool whereVer) ->+              runWhereIs (do+                (v, _) <- liftE $ fromVersion whereVer tool+                loc <- liftE $ whereIsTool tool v+                if directory+                then pure $ takeDirectory loc+                else pure loc+                )+                >>= \case+                      VRight r -> do+                        putStr r+                        pure ExitSuccess+                      VLeft e -> do+                        runLogger $ logError $ T.pack $ prettyShow e+                        pure $ ExitFailure 30++            Whereis _ WhereisBaseDir -> do+              putStr baseDir+              pure ExitSuccess++            Whereis _ WhereisBinDir -> do+              putStr binDir+              pure ExitSuccess++            Whereis _ WhereisCacheDir -> do+              putStr cacheDir+              pure ExitSuccess++            Whereis _ WhereisLogsDir -> do+              putStr logsDir+              pure ExitSuccess++            Whereis _ WhereisConfDir -> do+              putStr confDir+              pure ExitSuccess++            Upgrade uOpts force' -> do+              target <- case uOpts of+                UpgradeInplace  -> Just <$> liftIO getExecutablePath+                (UpgradeAt p)   -> pure $ Just p+                UpgradeGHCupDir -> pure (Just (binDir </> "ghcup" <> exeExt))++              runUpgrade (do+                v' <- liftE $ upgradeGHCup target force'+                GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo+                pure (v', dls)+                ) >>= \case+                  VRight (v', dls) -> do+                    let pretty_v = prettyVer v'+                    let vi = fromJust $ snd <$> getLatest dls GHCup+                    runLogger $ logInfo $+                      "Successfully upgraded GHCup to version " <> pretty_v+                    forM_ (_viPostInstall vi) $ \msg ->+                      runLogger $ logInfo msg+                    pure ExitSuccess+                  VLeft (V NoUpdate) -> do+                    runLogger $ logWarn "No GHCup update available"+                    pure ExitSuccess+                  VLeft e -> do+                    runLogger $ logError $ T.pack $ prettyShow e+                    pure $ ExitFailure 11++            ToolRequirements -> do+              s' <- appState+              flip runReaderT s'+                $ (runE+                    @'[NoCompatiblePlatform , DistroNotFound , NoToolRequirements]+                  $ do+                      GHCupInfo { .. } <- lift getGHCupInfo+                      platform' <- liftE getPlatform+                      req      <- getCommonRequirements platform' _toolRequirements ?? NoToolRequirements+                      liftIO $ T.hPutStr stdout (prettyRequirements req)+                  )+                  >>= \case+                        VRight _ -> pure ExitSuccess+                        VLeft  e -> do+                          runLogger $ logError $ T.pack $ prettyShow e+                          pure $ ExitFailure 12++            ChangeLog ChangeLogOptions{..} -> do+              GHCupInfo { _ghcupDownloads = dls } <- runAppState getGHCupInfo+              let tool = fromMaybe GHC clTool+                  ver' = maybe+                    (Right Latest)+                    (\case+                      ToolVersion tv -> Left (_tvVersion tv) -- FIXME: ugly sharing of ToolVersion+                      ToolTag     t  -> Right t+                    )+                    clToolVer+                  muri = getChangeLog dls tool ver'+              case muri of+                Nothing -> do+                  runLogger+                    (logWarn $+                      "Could not find ChangeLog for " <> T.pack (prettyShow tool) <> ", version " <> either prettyVer (T.pack . show) ver'+                    )+                  pure ExitSuccess+                Just uri -> do+                  s' <- appState+                  pfreq <- flip runReaderT s' getPlatformReq+                  let uri' = T.unpack . decUTF8Safe . serializeURIRef' $ uri+                      cmd = case _rPlatform pfreq of+                              Darwin  -> "open"+                              Linux _ -> "xdg-open"+                              FreeBSD -> "xdg-open"+                              Windows -> "start"++                  if clOpen+                    then do+                      flip runReaderT s' $+                        exec cmd+                             [T.unpack $ decUTF8Safe $ serializeURIRef' uri]+                             Nothing+                             Nothing+                          >>= \case+                                Right _ -> pure ExitSuccess+                                Left  e -> logError (T.pack $ prettyShow e)+                                  >> pure (ExitFailure 13)+                    else putStrLn uri' >> pure ExitSuccess++            Nuke -> do+              s' <- liftIO appState+              void $ liftIO $ evaluate $ force s'+              runNuke s' (do+                   lift $ logWarn "WARNING: This will remove GHCup and all installed components from your system."+                   lift $ logWarn "Waiting 10 seconds before commencing, if you want to cancel it, now would be the time."+                   liftIO $ threadDelay 10000000  -- wait 10s++                   lift $ logInfo "Initiating Nuclear Sequence 🚀🚀🚀"+                   lift $ logInfo "Nuking in 3...2...1"+              +                   lInstalled <- lift $ listVersions Nothing (Just ListInstalled)++                   forM_ lInstalled (liftE . rmTool)++                   lift rmGhcupDirs++                   ) >>= \case+                            VRight leftOverFiles+                              | null leftOverFiles -> do+                                  runLogger $ logInfo "Nuclear Annihilation complete!"+                                  pure ExitSuccess+                              | otherwise -> do+                                  runLogger $ logError "These Files have survived Nuclear Annihilation, you may remove them manually."+                                  forM_ leftOverFiles putStrLn+                                  pure ExitSuccess++                            VLeft e -> do+                              runLogger $ logError $ T.pack $ prettyShow e+                              pure $ ExitFailure 15+            Prefetch pfCom ->+              runPrefetch (do+                case pfCom of+                  PrefetchGHC+                    (PrefetchGHCOptions pfGHCSrc pfCacheDir) mt -> do+                      forM_ pfCacheDir (liftIO . createDirRecursive')+                      (v, _) <- liftE $ fromVersion mt GHC+                      if pfGHCSrc+                      then liftE $ fetchGHCSrc (_tvVersion v) pfCacheDir+                      else liftE $ fetchToolBindist (_tvVersion v) GHC pfCacheDir+                  PrefetchCabal (PrefetchOptions {pfCacheDir}) mt   -> do+                    forM_ pfCacheDir (liftIO . createDirRecursive')+                    (v, _) <- liftE $ fromVersion mt Cabal+                    liftE $ fetchToolBindist (_tvVersion v) Cabal pfCacheDir+                  PrefetchHLS (PrefetchOptions {pfCacheDir}) mt   -> do+                    forM_ pfCacheDir (liftIO . createDirRecursive')+                    (v, _) <- liftE $ fromVersion mt HLS+                    liftE $ fetchToolBindist (_tvVersion v) HLS pfCacheDir+                  PrefetchStack (PrefetchOptions {pfCacheDir}) mt   -> do+                    forM_ pfCacheDir (liftIO . createDirRecursive')+                    (v, _) <- liftE $ fromVersion mt Stack+                    liftE $ fetchToolBindist (_tvVersion v) Stack pfCacheDir+                  PrefetchMetadata -> do+                    _ <- liftE $ getDownloadsF+                    pure ""+                   ) >>= \case+                            VRight _ -> do+                                  pure ExitSuccess+                            VLeft e -> do+                              runLogger $ logError $ T.pack $ prettyShow e+                              pure $ ExitFailure 15+            GC GCOptions{..} ->+              runGC (do+                  when gcOldGHC rmOldGHC+                  lift $ when gcProfilingLibs rmProfilingLibs+                  lift $ when gcShareDir rmShareDir+                  lift $ when gcHLSNoGHC rmHLSNoGHC+                  lift $ when gcCache rmCache+                  lift $ when gcTmp rmTmp+                   ) >>= \case+                            VRight _ -> do+                                  pure ExitSuccess+                            VLeft e -> do+                              runLogger $ logError $ T.pack $ prettyShow e+                              pure $ ExitFailure 27+++          case res of+            ExitSuccess        -> pure ()+            ef@(ExitFailure _) -> exitWith ef+++  pure ()++fromVersion :: ( HasLog env+               , MonadFail m+               , MonadReader env m+               , HasGHCupInfo env+               , HasDirs env+               , MonadThrow m+               , MonadIO m+               , MonadCatch m+               )+            => Maybe ToolVersion+            -> Tool+            -> Excepts+                 '[ TagNotFound+                  , NextVerNotFound+                  , NoToolVersionSet+                  ] m (GHCTargetVersion, Maybe VersionInfo)+fromVersion tv = fromVersion' (toSetToolVer tv)++fromVersion' :: ( HasLog env+                , MonadFail m+                , MonadReader env m+                , HasGHCupInfo env+                , HasDirs env+                , MonadThrow m+                , MonadIO m+                , MonadCatch m+                )+             => SetToolVersion+             -> Tool+             -> Excepts+                  '[ TagNotFound+                   , NextVerNotFound+                   , NoToolVersionSet+                   ] m (GHCTargetVersion, Maybe VersionInfo)+fromVersion' SetRecommended tool = do+  GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo+  (\(x, y) -> (mkTVer x, Just y)) <$> getRecommended dls tool+    ?? TagNotFound Recommended tool+fromVersion' (SetToolVersion v) tool = do+  GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo+  let vi = getVersionInfo (_tvVersion v) tool dls+  case pvp $ prettyVer (_tvVersion v) of -- need to be strict here+    Left _ -> pure (v, vi)+    Right pvpIn ->+      lift (getLatestToolFor tool pvpIn dls) >>= \case+        Just (pvp_, vi') -> do+          v' <- lift $ pvpToVersion pvp_+          when (v' /= (_tvVersion v)) $ lift $ logWarn ("Assuming you meant version " <> prettyVer v')+          pure (GHCTargetVersion (_tvTarget v) v', Just vi')+        Nothing -> pure (v, vi)+fromVersion' (SetToolTag Latest) tool = do+  GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo+  (\(x, y) -> (mkTVer x, Just y)) <$> getLatest dls tool ?? TagNotFound Latest tool+fromVersion' (SetToolTag Recommended) tool = do+  GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo+  (\(x, y) -> (mkTVer x, Just y)) <$> getRecommended dls tool ?? TagNotFound Recommended tool+fromVersion' (SetToolTag (Base pvp'')) GHC = do+  GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo+  (\(x, y) -> (mkTVer x, Just y)) <$> getLatestBaseVersion dls pvp'' ?? TagNotFound (Base pvp'') GHC+fromVersion' SetNext tool = do+  GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo+  next <- case tool of+    GHC -> do+      set <- fmap _tvVersion $ ghcSet Nothing !? NoToolVersionSet tool+      ghcs <- rights <$> lift getInstalledGHCs+      (headMay+        . tail+        . dropWhile (\GHCTargetVersion {..} -> _tvVersion /= set)+        . cycle+        . sortBy (\x y -> compare (_tvVersion x) (_tvVersion y))+        . filter (\GHCTargetVersion {..} -> _tvTarget == Nothing)+        $ ghcs) ?? NoToolVersionSet tool+    Cabal -> do+      set <- cabalSet !? NoToolVersionSet tool+      cabals <- rights <$> lift getInstalledCabals+      (fmap (GHCTargetVersion Nothing)+        . headMay+        . tail+        . dropWhile (/= set)+        . cycle+        . sort+        $ cabals) ?? NoToolVersionSet tool+    HLS -> do+      set <- hlsSet !? NoToolVersionSet tool+      hlses <- rights <$> lift getInstalledHLSs+      (fmap (GHCTargetVersion Nothing)+        . headMay+        . tail+        . dropWhile (/= set)+        . cycle+        . sort+        $ hlses) ?? NoToolVersionSet tool+    Stack -> do+      set <- stackSet !? NoToolVersionSet tool+      stacks <- rights <$> lift getInstalledStacks+      (fmap (GHCTargetVersion Nothing)+        . headMay+        . tail+        . dropWhile (/= set)+        . cycle+        . sort+        $ stacks) ?? NoToolVersionSet tool+    GHCup -> fail "GHCup cannot be set"+  let vi = getVersionInfo (_tvVersion next) tool dls+  pure (next, vi)+fromVersion' (SetToolTag t') tool =+  throwE $ TagNotFound t' tool+++printListResult :: Bool -> Bool -> [ListResult] -> IO ()+printListResult no_color raw lr = do++  let+    color | raw || no_color = flip const+          | otherwise       = Pretty.color++  let+    printTag Recommended        = color Green "recommended"+    printTag Latest             = color Yellow "latest"+    printTag Prerelease         = color Red "prerelease"+    printTag (Base       pvp'') = "base-" ++ T.unpack (prettyPVP pvp'')+    printTag (UnknownTag t    ) = t+    printTag Old                = ""++  let+    rows =+      (\x -> if raw+          then x+          else [color Green "", "Tool", "Version", "Tags", "Notes"] : x+        )+        . fmap+            (\ListResult {..} ->+              let marks = if+#if defined(IS_WINDOWS)+                    | lSet       -> (color Green "IS")+                    | lInstalled -> (color Green "I ")+                    | otherwise  -> (color Red "X ")+#else+                    | lSet       -> (color Green "✔✔")+                    | lInstalled -> (color Green "✓ ")+                    | otherwise  -> (color Red "✗ ")+#endif+              in+                (if raw then [] else [marks])+                  ++ [ fmap toLower . show $ lTool+                     , case lCross of+                       Nothing -> T.unpack . prettyVer $ lVer+                       Just c  -> T.unpack (c <> "-" <> prettyVer lVer)+                     , intercalate "," $ (filter (/= "") . fmap printTag $ sort lTag)+                     , intercalate ","+                     $  (if hlsPowered+                          then [color Green "hls-powered"]+                          else mempty+                        )+                     ++ (if fromSrc then [color Blue "compiled"] else mempty)+                     ++ (if lStray then [color Yellow "stray"] else mempty)+                     ++ (if lNoBindist+                          then [color Red "no-bindist"]+                          else mempty+                        )+                     ]+            )+        $ lr+  let cols =+        foldr (\xs ys -> zipWith (:) xs ys) (replicate (length rows) []) rows+      lengths = fmap maximum . (fmap . fmap) strWidth $ cols+      padded  = fmap (\xs -> zipWith padTo xs lengths) rows++  forM_ padded $ \row -> putStrLn $ intercalate " " row+ where++  padTo str' x =+    let lstr = strWidth str'+        add' = x - lstr+    in  if add' < 0 then str' else str' ++ replicate add' ' '++  -- | Calculate the render width of a string, considering+  -- wide characters (counted as double width), ANSI escape codes+  -- (not counted), and line breaks (in a multi-line string, the longest+  -- line determines the width).+  strWidth :: String -> Int+  strWidth =+    maximum+      . (0 :)+      . map (foldr (\a b -> charWidth a + b) 0)+      . lines+      . stripAnsi++  -- | Strip ANSI escape sequences from a string.+  --+  -- >>> stripAnsi "\ESC[31m-1\ESC[m"+  -- "-1"+  stripAnsi :: String -> String+  stripAnsi s' =+    case+        MP.parseMaybe (many $ "" <$ MP.try ansi <|> pure <$> MP.anySingle) s'+      of+        Nothing -> error "Bad ansi escape"  -- PARTIAL: should not happen+        Just xs -> concat xs+   where+      -- This parses lots of invalid ANSI escape codes, but that should be fine+    ansi =+      MPC.string "\ESC[" *> digitSemicolons *> suffix MP.<?> "ansi" :: MP.Parsec+          Void+          String+          Char+    digitSemicolons = MP.takeWhileP Nothing (\c -> isDigit c || c == ';')+    suffix = MP.oneOf ['A', 'B', 'C', 'D', 'H', 'J', 'K', 'f', 'm', 's', 'u']++  -- | Get the designated render width of a character: 0 for a combining+  -- character, 1 for a regular character, 2 for a wide character.+  -- (Wide characters are rendered as exactly double width in apps and+  -- fonts that support it.) (From Pandoc.)+  charWidth :: Char -> Int+  charWidth c = case c of+    _ | c < '\x0300'                     -> 1+      | c >= '\x0300' && c <= '\x036F'   -> 0+      |  -- combining+        c >= '\x0370' && c <= '\x10FC'   -> 1+      | c >= '\x1100' && c <= '\x115F'   -> 2+      | c >= '\x1160' && c <= '\x11A2'   -> 1+      | c >= '\x11A3' && c <= '\x11A7'   -> 2+      | c >= '\x11A8' && c <= '\x11F9'   -> 1+      | c >= '\x11FA' && c <= '\x11FF'   -> 2+      | c >= '\x1200' && c <= '\x2328'   -> 1+      | c >= '\x2329' && c <= '\x232A'   -> 2+      | c >= '\x232B' && c <= '\x2E31'   -> 1+      | c >= '\x2E80' && c <= '\x303E'   -> 2+      | c == '\x303F'                    -> 1+      | c >= '\x3041' && c <= '\x3247'   -> 2+      | c >= '\x3248' && c <= '\x324F'   -> 1+      | -- ambiguous+        c >= '\x3250' && c <= '\x4DBF'   -> 2+      | c >= '\x4DC0' && c <= '\x4DFF'   -> 1+      | c >= '\x4E00' && c <= '\xA4C6'   -> 2+      | c >= '\xA4D0' && c <= '\xA95F'   -> 1+      | c >= '\xA960' && c <= '\xA97C'   -> 2+      | c >= '\xA980' && c <= '\xABF9'   -> 1+      | c >= '\xAC00' && c <= '\xD7FB'   -> 2+      | c >= '\xD800' && c <= '\xDFFF'   -> 1+      | c >= '\xE000' && c <= '\xF8FF'   -> 1+      | -- ambiguous+        c >= '\xF900' && c <= '\xFAFF'   -> 2+      | c >= '\xFB00' && c <= '\xFDFD'   -> 1+      | c >= '\xFE00' && c <= '\xFE0F'   -> 1+      | -- ambiguous+        c >= '\xFE10' && c <= '\xFE19'   -> 2+      | c >= '\xFE20' && c <= '\xFE26'   -> 1+      | c >= '\xFE30' && c <= '\xFE6B'   -> 2+      | c >= '\xFE70' && c <= '\xFEFF'   -> 1+      | c >= '\xFF01' && c <= '\xFF60'   -> 2+      | c >= '\xFF61' && c <= '\x16A38'  -> 1+      | c >= '\x1B000' && c <= '\x1B001' -> 2+      | c >= '\x1D000' && c <= '\x1F1FF' -> 1+      | c >= '\x1F200' && c <= '\x1F251' -> 2+      | c >= '\x1F300' && c <= '\x1F773' -> 1+      | c >= '\x20000' && c <= '\x3FFFD' -> 2+      | otherwise                        -> 1+++checkForUpdates :: ( MonadReader env m+                   , HasGHCupInfo env+                   , HasDirs env+                   , HasPlatformReq env+                   , MonadCatch m+                   , HasLog env+                   , MonadThrow m+                   , MonadIO m+                   , MonadFail m+                   )+                => m ()+checkForUpdates = do+  GHCupInfo { _ghcupDownloads = dls } <- getGHCupInfo+  lInstalled <- listVersions Nothing (Just ListInstalled)+  let latestInstalled tool = (fmap lVer . lastMay . filter (\lr -> lTool lr == tool)) lInstalled++  forM_ (getLatest dls GHCup) $ \(l, _) -> do+    (Right ghc_ver) <- pure $ version $ prettyPVP ghcUpVer+    when (l > ghc_ver)+      $ logWarn $+          "New GHCup version available: " <> prettyVer l <> ". To upgrade, run 'ghcup upgrade'"++  forM_ (getLatest dls GHC) $ \(l, _) -> do+    let mghc_ver = latestInstalled GHC+    forM mghc_ver $ \ghc_ver ->+      when (l > ghc_ver)+        $ logWarn $+          "New GHC version available: " <> prettyVer l <> ". To upgrade, run 'ghcup install ghc " <> prettyVer l <> "'"++  forM_ (getLatest dls Cabal) $ \(l, _) -> do+    let mcabal_ver = latestInstalled Cabal+    forM mcabal_ver $ \cabal_ver ->+      when (l > cabal_ver)+        $ logWarn $+          "New Cabal version available: " <> prettyVer l <> ". To upgrade, run 'ghcup install cabal " <> prettyVer l <> "'"++  forM_ (getLatest dls HLS) $ \(l, _) -> do+    let mhls_ver = latestInstalled HLS+    forM mhls_ver $ \hls_ver ->+      when (l > hls_ver)+        $ logWarn $+          "New HLS version available: " <> prettyVer l <> ". To upgrade, run 'ghcup install hls " <> prettyVer l <> "'"++  forM_ (getLatest dls Stack) $ \(l, _) -> do+    let mstack_ver = latestInstalled Stack+    forM mstack_ver $ \stack_ver ->+      when (l > stack_ver)+        $ logWarn $+          "New Stack version available: " <> prettyVer l <> ". To upgrade, run 'ghcup install stack " <> prettyVer l <> "'"+++prettyDebugInfo :: DebugInfo -> String+prettyDebugInfo DebugInfo {..} = "Debug Info" <> "\n" <>+  "==========" <> "\n" <>+  "GHCup base dir: " <> diBaseDir <> "\n" <>+  "GHCup bin dir: " <> diBinDir <> "\n" <>+  "GHCup GHC directory: " <> diGHCDir <> "\n" <>+  "GHCup cache directory: " <> diCacheDir <> "\n" <>+  "Architecture: " <> prettyShow diArch <> "\n" <>+  "Platform: " <> prettyShow diPlatform <> "\n" <>+  "Version: " <> describe_result 
− config.yaml
@@ -1,61 +0,0 @@-# Cache downloads in ~/.ghcup/cache-cache: False-# Skip tarball checksum verification-no-verify: False-# enable verbosity-verbose: False-# When to keep build directories-keep-dirs: Errors  # Always | Never | Errors-# Which downloader to use-downloader: Curl   # Curl | Wget | Internal--# TUI key bindings,-# see https://hackage.haskell.org/package/vty-5.31/docs/Graphics-Vty-Input-Events.html#t:Key-# for possible values.-key-bindings:-  up:-    KUp: []-  down:-    KDown: []-  quit:-    KChar: 'q'-  install:-    KChar: 'i'-  uninstall:-    KChar: 'u'-  set:-    KChar: 's'-  changelog:-    KChar: 'c'-  show-all:-    KChar: 'a'--# Where to get GHC/cabal/hls download info/versions from. For more detailed explanation-# check the 'URLSource' type in the code.-url-source:-  ## Use the internal download uri, this is the default-  GHCupURL: []--  ## Example 1: Read download info from this location instead-  ## Accepts file/http/https scheme-  # OwnSource: "file:///home/jule/git/ghcup-hs/ghcup-0.0.3.yaml"--  ## Example 2: Add custom tarballs to the default downloads, overwriting duplicate versions-  # AddSource:-    # Left:-      # toolRequirements: {} # this is ignored-      # ghcupDownloads:-        # GHC:-          # 9.10.2:-            # viTags: []-            # viArch:-              # A_64:-                # Linux_UnknownLinux:-                  # unknown_versioning:-                    # dlUri: https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-x86_64-deb8-linux.tar.bz2-                    # dlSubdir: ghc-7.10.3-                    # dlHash: 01cfbad8dff1e8b34a5fdca8caeaf843b56e36af919e29cd68870d2588563db5--  ## Example 3: Add a custom download file to the default downloads, overwriting duplicate versions-  # AddSource:-    # Right: "file:///home/jule/git/ghcup-hs/ghcup-custom.yaml"
+ data/build_mk/cross view
@@ -0,0 +1,9 @@+V=0+BUILD_MAN = NO+BUILD_SPHINX_HTML = NO+BUILD_SPHINX_PDF = NO+HADDOCK_DOCS = NO+ifneq "$(BuildFlavour)" ""+include mk/flavours/$(BuildFlavour).mk+endif+Stage1Only = YES
+ data/build_mk/default view
@@ -0,0 +1,8 @@+V=0+BUILD_MAN = NO+BUILD_SPHINX_HTML = NO+BUILD_SPHINX_PDF = NO+HADDOCK_DOCS = YES+ifneq "$(BuildFlavour)" ""+include mk/flavours/$(BuildFlavour).mk+endif
+ data/config.yaml view
@@ -0,0 +1,67 @@+# Cache downloads in ~/.ghcup/cache+cache: False+# Skip tarball checksum verification+no-verify: False+# enable verbosity+verbose: False+# When to keep build directories+keep-dirs: Errors  # Always | Never | Errors+# Which downloader to use+downloader: Curl   # Curl | Wget | Internal+# whether to run in offline mode+no-network: False+# whether/how to do gpg verification+gpg-setting: GPGNone # GPGStrict | GPGLax | GPGNone++# TUI key bindings,+# see https://hackage.haskell.org/package/vty-5.31/docs/Graphics-Vty-Input-Events.html#t:Key+# for possible values.+key-bindings:+  up:+    KUp: []+  down:+    KDown: []+  quit:+    KChar: 'q'+  install:+    KChar: 'i'+  uninstall:+    KChar: 'u'+  set:+    KChar: 's'+  changelog:+    KChar: 'c'+  show-all:+    KChar: 'a'+  show-all-tools:+    KChar: 't'++# Where to get GHC/cabal/hls download info/versions from. For more detailed explanation+# check the 'URLSource' type in the code.+url-source:+  ## Use the internal download uri, this is the default+  GHCupURL: []++  ## Example 1: Read download info from this location instead+  ## Accepts file/http/https scheme+  # OwnSource: "file:///home/jule/git/ghcup-hs/ghcup-0.0.3.yaml"++  ## Example 2: Add custom tarballs to the default downloads, overwriting duplicate versions+  # AddSource:+    # Left:+      # toolRequirements: {} # this is ignored+      # ghcupDownloads:+        # GHC:+          # 9.10.2:+            # viTags: []+            # viArch:+              # A_64:+                # Linux_UnknownLinux:+                  # unknown_versioning:+                    # dlUri: https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-x86_64-deb8-linux.tar.bz2+                    # dlSubdir: ghc-7.10.3+                    # dlHash: 01cfbad8dff1e8b34a5fdca8caeaf843b56e36af919e29cd68870d2588563db5++  ## Example 3: Add a custom download file to the default downloads, overwriting duplicate versions+  # AddSource:+    # Right: "file:///home/jule/git/ghcup-hs/ghcup-custom.yaml"
+ data/metadata/ghcup-0.0.4.yaml view
@@ -0,0 +1,1932 @@+---+toolRequirements:+  GHC:+    unknown_version:+      Linux_Debian:+        unknown_versioning:+          distroPKGs:+          - build-essential+          - curl+          - libffi-dev+          - libffi6+          - libgmp-dev+          - libgmp10+          - libncurses-dev+          - libncurses5+          - libtinfo5+          notes: ''+      Linux_Ubuntu:+        unknown_versioning:+          distroPKGs:+          - build-essential+          - curl+          - libffi-dev+          - libffi6+          - libgmp-dev+          - libgmp10+          - libncurses-dev+          - libncurses5+          - libtinfo5+          notes: ''+        "( >= 20.04 && < 20.10 )":+          distroPKGs:+          - build-essential+          - curl+          - libffi-dev+          - libffi7+          - libgmp-dev+          - libgmp10+          - libncurses-dev+          - libncurses5+          - libtinfo5+          notes: ''+        "( >= 20.10 )":+          distroPKGs:+          - build-essential+          - curl+          - libffi-dev+          - libffi8ubuntu1+          - libgmp-dev+          - libgmp10+          - libncurses-dev+          - libncurses5+          - libtinfo5+          notes: ''+      Linux_CentOS:+        '( >= 7 && < 8 )':+          distroPKGs:+          - gcc+          - gcc-c+++          - gmp+          - gmp-devel+          - make+          - ncurses+          - xz+          - perl+          notes: ''+        unknown_versioning:+          distroPKGs:+          - gcc+          - gcc-c+++          - gmp+          - gmp-devel+          - make+          - ncurses+          - ncurses-compat-libs+          - xz+          - perl+          notes: ''+      Linux_Fedora:+        unknown_versioning:+          distroPKGs:+          - gcc+          - gcc-c+++          - gmp+          - gmp-devel+          - make+          - ncurses+          - ncurses-compat-libs+          - xz+          - perl+          notes: ''+      Linux_Alpine:+        unknown_versioning:+          distroPKGs:+          - curl+          - gcc+          - g+++          - gmp-dev+          - ncurses-dev+          - libffi-dev+          - make+          - xz+          - tar+          - perl+          notes: ''+      Linux_UnknownLinux:+        unknown_versioning:+          distroPKGs: []+          notes: 'You need the following packages: curl g++ gcc gmp make ncurses realpath+            xz-utils. Consult your distro documentation on the exact names of those+            packages.'+      Darwin:+        unknown_versioning:+          distroPKGs: []+          notes: On OS X, in the course of running ghcup you will be given a dialog+            box to install the command line tools. Accept and the requirements will+            be installed for you. You will then need to run the command again.+      FreeBSD:+        unknown_versioning:+          distroPKGs:+          - curl+          - gcc+          - gmp+          - gmake+          - ncurses+          - perl5+          - libffi+          - libiconv+          notes: ''+ghcupDownloads:+  GHC:+    7.10.3:+      viTags:+      - base-4.8.2.0+      - old+      viChangeLog: https://downloads.haskell.org/~ghc/7.10.3/docs/html/users_guide/release-7-10-1.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-src.tar.xz+        dlSubdir: ghc-7.10.3+        dlHash: cf90cedce1c28fd0e2b9e72fe8a938756668d18ea1fcc884a19f698658ac4fef+      viPostRemove: &ghc-post-remove "After removing GHC you might also want to clean up your cabal store at: ~/.cabal/store/ghc-<ghcver>"+      viPostInstall: "GHC-7.10.3 may give linking errors on most modern distros. You may have to pass '--ghc-option=-optc-no-pie --ghc-option=-optl-no-pie' to cabal build/install. Also see https://gitlab.haskell.org/ghc/ghc/-/issues/18763"+      viArch:+        A_64:+          Linux_Debian:+            unknown_versioning: &ghc-7103-64-deb8+              dlUri: https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-x86_64-deb8-linux.tar.bz2+              dlSubdir: ghc-7.10.3+              dlHash: 01cfbad8dff1e8b34a5fdca8caeaf843b56e36af919e29cd68870d2588563db5+          Linux_Ubuntu:+            unknown_versioning: *ghc-7103-64-deb8+          Linux_Mint:+            unknown_versioning: *ghc-7103-64-deb8+          Linux_CentOS:+            unknown_versioning: &ghc-7103-64-centos+              dlUri: https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-x86_64-centos67-linux.tar.bz2+              dlSubdir: ghc-7.10.3+              dlHash: a8957f7a2fd81720c5d3dc403571d77d31115ff5f42edb2917c36d8e714220d4+          Linux_AmazonLinux:+            unknown_versioning: *ghc-7103-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-7103-64-deb8+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-x86_64-apple-darwin.tar.bz2+              dlSubdir: ghc-7.10.3+              dlHash: 80893e367e8318105f7db2064adf202e3d96b1f014e792b73e92f2cacf0b757a+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-x86_64-portbld-freebsd.tar.bz2+              dlSubdir: ghc-7.10.3+              dlHash: 2aa396edd2bb651f4bc7eef7a396913ea24923de5aafdc76df6295333e487e48+        A_32:+          Linux_Debian:+            unknown_versioning: &ghc-7103-32-deb8+              dlUri: https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-i386-deb8-linux.tar.bz2+              dlSubdir: ghc-7.10.3+              dlHash: d2ccf072457fb100503f6f5430a1e3589ca525a97424263d036b0550bc277f0c+          Linux_Ubuntu:+            unknown_versioning: *ghc-7103-32-deb8+          Linux_Mint:+            unknown_versioning: *ghc-7103-32-deb8+          Linux_CentOS:+            unknown_versioning: &ghc-7103-32-centos+              dlUri: https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-i386-centos67-linux.tar.bz2+              dlSubdir: ghc-7.10.3+              dlHash: c50aa20275e8d1ba9148f380eb7598bc148143281fc17c9acd38ea7b325852bd+          Linux_AmazonLinux:+            unknown_versioning: *ghc-7103-32-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-7103-32-deb8+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-i386-portbld-freebsd.tar.bz2+              dlSubdir: ghc-7.10.3+              dlHash: 3dde05577c6f94dcb0ba201ebd53ab88553bbc9a3aa8e72237162ed7a9d588a3+    8.0.2:+      viTags:+      - base-4.9.1.0+      - old+      viChangeLog: https://downloads.haskell.org/~ghc/8.0.2/docs/html/users_guide/8.0.1-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.0.2/ghc-8.0.2-src.tar.xz+        dlSubdir: ghc-8.0.2+        dlHash: 11625453e1d0686b3fa6739988f70ecac836cadc30b9f0c8b49ef9091d6118b1+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 7 && < 8 )':+              dlUri: https://downloads.haskell.org/~ghc/8.0.2/ghc-8.0.2-x86_64-deb7-linux.tar.xz+              dlSubdir: ghc-8.0.2+              dlHash: b2f5c304b57ac5840a0d2ef763a3c6fa858c70840f749cfad12ed227da973c0a+            unknown_versioning: &ghc-802-64-deb8+              dlUri: https://downloads.haskell.org/~ghc/8.0.2/ghc-8.0.2-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.0.2+              dlHash: 5ee68290db00ca0b79d57bc3a5bdce470de9ce9da0b098a7ce6c504605856c8f+          Linux_Ubuntu:+            unknown_versioning: *ghc-802-64-deb8+          Linux_Mint:+            unknown_versioning: *ghc-802-64-deb8+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.0.2/ghc-8.0.2-x86_64-alpine-linux.tar.xz+              dlSubdir: ghc-8.0.2+              dlHash: 517783b660a27ebf95b2568d47292fd633d5f9a4de4c80ad1ccf05e1b9d7313f+          Linux_UnknownLinux:+            unknown_versioning: *ghc-802-64-deb8+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.0.2/ghc-8.0.2-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.0.2+              dlHash: ff50a2df9f002f33b9f09717ebf5ec5a47906b9b65cc57b1f9849f8b2e06788d+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.0.2/ghc-8.0.2-x86_64-portbld-freebsd.tar.xz+              dlSubdir: ghc-8.0.2+              dlHash: b36a20e5cae24d70bbb6116ae486f21811e9384f15d3892d260f02fba3e3bb8c+        A_32:+          Linux_Debian:+            '( >= 7 && < 8 )':+              dlUri: https://downloads.haskell.org/~ghc/8.0.2/ghc-8.0.2-i386-deb7-linux.tar.xz+              dlSubdir: ghc-8.0.2+              dlHash: 07ead3a49f8c9df4b429e7a2f96f6f31bcab8d3ff8277a9aed0201d13ddad448+            unknown_versioning: &ghc-802-32-deb8+              dlUri: https://downloads.haskell.org/~ghc/8.0.2/ghc-8.0.2-i386-deb8-linux.tar.xz+              dlSubdir: ghc-8.0.2+              dlHash: 818621342a2161b8afcc995a0765816bb40aefbfa1db2c8a7d59c04d8b18228a+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.0.2/ghc-8.0.2-i386-alpine-linux.tar.xz+              dlSubdir: ghc-8.0.2+              dlHash: b4cd12a1048b2fff2f23c9eec0dd3a1174d54d017f8d79ec79af4534118e6881+          Linux_UnknownLinux:+            unknown_versioning: *ghc-802-32-deb8+    8.2.2:+      viTags:+      - base-4.10.1.0+      - old+      viChangeLog: https://downloads.haskell.org/~ghc/8.2.2/docs/html/users_guide/8.2.2-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-src.tar.xz+        dlSubdir: ghc-8.2.2+        dlHash: bb8ec3634aa132d09faa270bbd604b82dfa61f04855655af6f9d14a9eedc05fc+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 7 && < 8 )': &ghc-822-64-deb7+              dlUri: https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-x86_64-deb7-linux.tar.xz+              dlSubdir: ghc-8.2.2+              dlHash: cd7afbca54edf9890da9f432c63366556246c85c1198e40c99df5af01c555834+            unknown_versioning: &ghc-822-64-deb8+              dlUri: https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.2.2+              dlHash: 48e205c62b9dc1ccf6739a4bc15a71e56dde2f891a9d786a1b115f0286111b2a+          Linux_Ubuntu:+            unknown_versioning: *ghc-822-64-deb8+          Linux_Mint:+            unknown_versioning: *ghc-822-64-deb8+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.2.2/ghc-8.2.2-x86_64-alpine-linux.tar.xz+              dlSubdir: ghc-8.2.2+              dlHash: adcf3a320a3c402aba07ae9586990dc3c0b550e96aeffb1b9e194313d3ba716d+          Linux_UnknownLinux:+            unknown_versioning: *ghc-822-64-deb7+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.2.2+              dlHash: f90fcf62f7e0936a6dfc3601cf663729bfe9bbf85097d2d75f0a16f8c2e95c27+          FreeBSD:+            '( >= 10 && < 11 )':+              dlUri: https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-x86_64-portbld10_3-freebsd.tar.xz+              dlSubdir: ghc-8.2.2+              dlHash: 9e99aaeaec4b2c6d660d80246c0d4dbd41fda88f1eb7a908b29dc8fa8d663949+            '( >= 11 && < 12 )': &ghc-822-64-fbsd11+              dlUri: https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-x86_64-portbld11-freebsd.tar.xz+              dlSubdir: ghc-8.2.2+              dlHash: cd351c704b92b9af23994024df07de8ca7090ea7675d5c8b14b2be857a46d804+            unknown_versioning: *ghc-822-64-fbsd11+        A_32:+          Linux_Debian:+            '( >= 7 && < 8 )':+              dlUri: https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-i386-deb7-linux.tar.xz+              dlSubdir: ghc-8.2.2+              dlHash: cd18766b1a9b74fc6c90003a719ecab158f281f9a755d8b1bd3fd764ba6947b5+            unknown_versioning: &ghc-822-32-deb8+              dlUri: https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-i386-deb8-linux.tar.xz+              dlSubdir: ghc-8.2.2+              dlHash: 9e67d72d76482e0ba91c718e727b00386a1a12a32ed719714976dc56ca8c8223+          Linux_Ubuntu:+            unknown_versioning: *ghc-822-32-deb8+          Linux_Mint:+            unknown_versioning: *ghc-822-32-deb8+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.2.2/ghc-8.2.2-i386-alpine-linux.tar.xz+              dlSubdir: ghc-8.2.2+              dlHash: 467534c32552cfd318753112dbc70af003693aad4b0081f2a07e61f5b5ea2c22+          Linux_UnknownLinux:+            unknown_versioning: *ghc-822-32-deb8+    8.4.1:+      viTags:+      - base-4.11.0.0+      - old+      viChangeLog: https://downloads.haskell.org/~ghc/8.4.1/docs/html/users_guide/8.4.1-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.4.1/ghc-8.4.1-src.tar.xz+        dlSubdir: ghc-8.4.1+        dlHash: 39ae2f25192408f355693e5a3c8b6ff613ddb7c4da998fdf26210143a61839d2+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.4.1/ghc-8.4.1-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.4.1+              dlHash: 427c77a934b30c3f1de992c38c072afb4323fe6fb30dbac919ca8cb6ae98fbd9+          Linux_Ubuntu:+            unknown_versioning: &ghc-841-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.4.1/ghc-8.4.1-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.4.1+              dlHash: 89328a013e64b9b56825a9071fea5616ddd623d37fd41e8fb913dfebc609e7ea+          Linux_Mint:+            unknown_versioning: *ghc-841-64-fedora+          Linux_Fedora:+            unknown_versioning: *ghc-841-64-fedora+          Linux_UnknownLinux:+            unknown_versioning: *ghc-841-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.4.1/ghc-8.4.1-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.4.1+              dlHash: d774e39f3a0105843efd06709b214ee332c30203e6c5902dd6ed45e36285f9b7+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.4.1/ghc-8.4.1-x86_64-portbld11-freebsd.tar.xz+              dlSubdir: ghc-8.4.1+              dlHash: e748daec098445c6190090fe32bb2817a1140553be5acd2188e1af05ad24e5aa+        A_32:+          Linux_Debian:+            unknown_versioning: &ghc-841-32-deb8+              dlUri: https://downloads.haskell.org/~ghc/8.4.1/ghc-8.4.1-i386-deb8-linux.tar.xz+              dlSubdir: ghc-8.4.1+              dlHash: c56c589c76c7ddcb77cdbef885a811761e669d3e76868b723d5be56dedcd4f69+          Linux_Ubuntu:+            unknown_versioning: *ghc-841-32-deb8+          Linux_Mint:+            unknown_versioning: *ghc-841-32-deb8+          Linux_UnknownLinux:+            unknown_versioning: *ghc-841-32-deb8+    8.4.2:+      viTags:+      - base-4.11.1.0+      - old+      viChangeLog: https://downloads.haskell.org/~ghc/8.4.2/docs/html/users_guide/8.4.2-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.4.2/ghc-8.4.2-src.tar.xz+        dlSubdir: ghc-8.4.2+        dlHash: 01cc32f24a06bf3b2428351b6d7fec791e82d042426d29ad9e5a245b35f0047b+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 8 && < 9 )':+              dlUri: https://downloads.haskell.org/~ghc/8.4.2/ghc-8.4.2-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.4.2+              dlHash: 246f66eb56f4ad0f1c7755502cfc8f9972f2d067dede17e151f6f479c1f76fbd+            unknown_versioning: &ghc-842-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.4.2/ghc-8.4.2-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.4.2+              dlHash: 3f4f5bbd2cdab4e7015ada9196d8d9b3a1ad274293cef011f85c46854596cb57+          Linux_Ubuntu:+            unknown_versioning: &ghc-842-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.4.2/ghc-8.4.2-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.4.2+              dlHash: d057b5c833596dbe4ae5d0dc2994f6cc5d0f4c2a21ea1d7900821d165fd4e846+            '( >= 16 && < 19 )': *ghc-842-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-842-64-fedora+          Linux_Fedora:+            unknown_versioning: *ghc-842-64-fedora+          Linux_UnknownLinux:+            unknown_versioning: *ghc-842-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.4.2/ghc-8.4.2-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.4.2+              dlHash: 87469222042b9ac23f9db216a8d4e5107297bdbbb99df71eb4d9e7208455def2+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.4.2/ghc-8.4.2-x86_64-portbld-freebsd.tar.xz+              dlSubdir: ghc-8.4.2+              dlHash: e9ed417fdf94c2ff2c6e344ed16f332bf6b591511f6442c0d9ea94854882b66c+        A_32:+          Linux_Debian:+            unknown_versioning: &ghc-842-32-deb8+              dlUri: https://downloads.haskell.org/~ghc/8.4.2/ghc-8.4.2-i386-deb8-linux.tar.xz+              dlSubdir: ghc-8.4.2+              dlHash: 2d849c30b4c1eac25dc74333501920921e22fa483153f404993808bbda93df05+          Linux_Ubuntu:+            unknown_versioning: *ghc-842-32-deb8+          Linux_Mint:+            unknown_versioning: *ghc-842-32-deb8+          Linux_UnknownLinux:+            unknown_versioning: *ghc-842-32-deb8+    8.4.3:+      viTags:+      - base-4.11.1.0+      - old+      viChangeLog: https://downloads.haskell.org/~ghc/8.4.3/docs/html/users_guide/8.4.3-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.4.3/ghc-8.4.3-src.tar.xz+        dlSubdir: ghc-8.4.3+        dlHash: ae47afda985830de8811243255aa3744dfb9207cb980af74393298b2b62160d6+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 8 && < 9 )':+              dlUri: https://downloads.haskell.org/~ghc/8.4.3/ghc-8.4.3-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.4.3+              dlHash: 30a402c6d4754a6c020e0547f19ae3ac42e907e35349aa932d347f73e421a8e2+            unknown_versioning: &ghc-843-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.4.3/ghc-8.4.3-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.4.3+              dlHash: 2e4f53afb872ad9c640f31aea283b3ff4c5028b65808a1920739900aef7d15c9+          Linux_Ubuntu:+            unknown_versioning: &ghc-843-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.4.3/ghc-8.4.3-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.4.3+              dlHash: 269e7a4d3f336491b88409a020998122b30a3a729af78d33be86d3b3f8000c3e+            '( >= 16 && < 19 )': *ghc-843-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-843-64-fedora+          Linux_Fedora:+            unknown_versioning: *ghc-843-64-fedora+          Linux_UnknownLinux:+            unknown_versioning: *ghc-843-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.4.3/ghc-8.4.3-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.4.3+              dlHash: af0b455f6c46b9802b4b48dad996619cfa27cc6e2bf2ce5532387b4a8c00aa64+        A_32:+          Linux_Debian:+            unknown_versioning: &ghc-843-32-deb8+              dlUri: https://downloads.haskell.org/~ghc/8.4.3/ghc-8.4.3-i386-deb8-linux.tar.xz+              dlSubdir: ghc-8.4.3+              dlHash: f5763983a26dedd88b65a0b17267359a3981b83a642569b26334423f684f8b8c+          Linux_Ubuntu:+            unknown_versioning: *ghc-843-32-deb8+          Linux_Mint:+            unknown_versioning: *ghc-843-32-deb8+          Linux_UnknownLinux:+            unknown_versioning: *ghc-843-32-deb8+    8.4.4:+      viTags:+      - base-4.11.1.0+      viChangeLog: https://downloads.haskell.org/~ghc/8.4.4/docs/html/users_guide/8.4.4-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-src.tar.xz+        dlSubdir: ghc-8.4.4+        dlHash: 11117735a58e507c481c09f3f39ae5a314e9fbf49fc3109528f99ea7959004b2+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 8 && < 9 )':+              dlUri: https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.4.4+              dlHash: 4c2a8857f76b7f3e34ecba0b51015d5cb8b767fe5377a7ec477abde10705ab1a+            unknown_versioning: &ghc-844-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.4.4+              dlHash: 47c80a32d8f02838a2401414c94ba260d1fe82b7d090479994522242c767cc83+          Linux_Ubuntu:+            unknown_versioning: &ghc-844-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.4.4+              dlHash: 8ab2befddc14d1434d0aad0c5d3c7e0c2b78ff84caa3429fa62527bfc6b86095+            '( >= 16 && < 19 )': *ghc-844-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-844-64-fedora+          Linux_Fedora:+            unknown_versioning: *ghc-844-64-fedora+          Linux_CentOS:+            unknown_versioning: &ghc-844-64-centos+              dlUri: https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-x86_64-centos70-linux.tar.xz+              dlSubdir: ghc-8.4.4+              dlHash: 83a96650f5a92b1e4d7651d256d6438624342d40e780e68125033435a54cd674+          Linux_RedHat:+            unknown_versioning: *ghc-844-64-centos+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.4.4/ghc-8.4.4-x86_64-alpine-linux.tar.xz+              dlSubdir: ghc-8.4.4+              dlHash: 336affff8314d3dc5e85d9c09015ae2ba8a7658b459c8c8ae77ecaa551a56ae7+          Linux_AmazonLinux:+            unknown_versioning: *ghc-844-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-844-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.4.4+              dlHash: 28dc89ebd231335337c656f4c5ead2ae2a1acc166aafe74a14f084393c5ef03a+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-x86_64-portbld-freebsd11.tar.xz+              dlSubdir: ghc-8.4.4+              dlHash: 44fbd142d1c355d6110595c59c760e2c73866ff9259ec85ebf814edb244d1940+        A_32:+          Linux_Debian:+            unknown_versioning: &ghc-844-32-deb8+              dlUri: https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-i386-deb8-linux.tar.xz+              dlSubdir: ghc-8.4.4+              dlHash: 678bafaabea6af70ba71ccf0210bb437f9f5591ec28ac1cbbbd5f7aa6894e450+          Linux_Ubuntu:+            unknown_versioning: *ghc-844-32-deb8+          Linux_Mint:+            unknown_versioning: *ghc-844-32-deb8+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.4.4/ghc-8.4.4-i386-alpine-linux.tar.xz+              dlSubdir: ghc-8.4.4+              dlHash: 892888d388ef5c9cadf5cfba1146d62237c25b9b066fb62fee940b2b285fd308+          Linux_UnknownLinux:+            unknown_versioning: *ghc-844-32-deb8+    8.6.1:+      viTags:+      - base-4.12.0.0+      - old+      viChangeLog: https://downloads.haskell.org/~ghc/8.6.1/docs/html/users_guide/8.6.1-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.6.1/ghc-8.6.1-src.tar.xz+        dlSubdir: ghc-8.6.1+        dlHash: 2c25c26d1e5c47c7cbb2a1d8e6456524033e7a71409184dd3125e3fc5a3c7036+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 8 && < 9 )':+              dlUri: https://downloads.haskell.org/~ghc/8.6.1/ghc-8.6.1-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.6.1+              dlHash: 6d8784401b7dd80c90fa17306ec0539920e3987399a2c7ef247989e53197dc42+            unknown_versioning: &ghc-861-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.6.1/ghc-8.6.1-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.6.1+              dlHash: 97d44f303868d74e4d13a2e99c82ffce3d25fd54c704675e5a1939e0d824dbf0+          Linux_Ubuntu:+            unknown_versioning: &ghc-861-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.6.1/ghc-8.6.1-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.6.1+              dlHash: da903fbcf11ee6c977a8b7dac3f04dbc098d674def587880b6624b8f32588beb+            '( >= 16 && < 19 )': *ghc-861-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-861-64-fedora+          Linux_Fedora:+            unknown_versioning: *ghc-861-64-fedora+          Linux_UnknownLinux:+            unknown_versioning: *ghc-861-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.6.1/ghc-8.6.1-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.6.1+              dlHash: 9692cdfd202b0e039ea0c3dde5dbf653736c836ca1df46504b179b572100808c+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.6.1/ghc-8.6.1-x86_64-portbld-freebsd.tar.xz+              dlSubdir: ghc-8.6.1+              dlHash: 51403b054a3a649039ac988e1d1112561f96750bfced63df864091a3fab36f08+        A_32:+          Linux_Debian:+            unknown_versioning: &ghc-861-32-deb8+              dlUri: https://downloads.haskell.org/~ghc/8.6.1/ghc-8.6.1-i386-deb8-linux.tar.xz+              dlSubdir: ghc-8.6.1+              dlHash: 83573af96e3dec8f67c1a844512f92cbf7d51ae7ceca53d948fc2a3300abd05c+          Linux_Ubuntu:+            unknown_versioning: *ghc-861-32-deb8+          Linux_Mint:+            unknown_versioning: *ghc-861-32-deb8+          Linux_UnknownLinux:+            unknown_versioning: *ghc-861-32-deb8+    8.6.2:+      viTags:+      - base-4.12.0.0+      - old+      viChangeLog: https://downloads.haskell.org/~ghc/8.6.2/docs/html/users_guide/8.6.2-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.6.2/ghc-8.6.2-src.tar.xz+        dlSubdir: ghc-8.6.2+        dlHash: caaa819d21280ecde90a4773143dee188711e9ff175a27cfbaee56eb851d76d5+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            unknown_versioning: &ghc-862-64-deb8+              dlUri: https://downloads.haskell.org/~ghc/8.6.2/ghc-8.6.2-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.6.2+              dlHash: 13f96e8b83bb5bb60f955786ff9085744c24927a33be8a17773f84c7c248533a+          Linux_Ubuntu:+            unknown_versioning: &ghc-862-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.6.2/ghc-8.6.2-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.6.2+              dlHash: 702aa5dfa1639c37953ceb7571a5057d9fb0562aecb197b277953a037d78047d+            '( >= 16 && < 19 )': *ghc-862-64-deb8+          Linux_Mint:+            unknown_versioning: *ghc-862-64-fedora+          Linux_Fedora:+            unknown_versioning: *ghc-862-64-fedora+          Linux_UnknownLinux:+            unknown_versioning: *ghc-862-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.6.2/ghc-8.6.2-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.6.2+              dlHash: 8ec46a25872226dd7e5cf7271e3f3450c05f32144b96e6b9cb44cc4079db50dc+        A_32:+          Linux_Debian:+            unknown_versioning: &ghc-862-32-deb8+              dlUri: https://downloads.haskell.org/~ghc/8.6.2/ghc-8.6.2-i386-deb8-linux.tar.xz+              dlSubdir: ghc-8.6.2+              dlHash: a288026d9ef22f7ac387edab6b29ef7dcb3b28945c8ea532a15c1fa35d4733ed+          Linux_Ubuntu:+            unknown_versioning: *ghc-862-32-deb8+          Linux_Mint:+            unknown_versioning: *ghc-862-32-deb8+          Linux_UnknownLinux:+            unknown_versioning: *ghc-862-32-deb8+    8.6.3:+      viTags:+      - base-4.12.0.0+      - old+      viChangeLog: https://downloads.haskell.org/~ghc/8.6.3/docs/html/users_guide/8.6.3-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.6.3/ghc-8.6.3-src.tar.xz+        dlSubdir: ghc-8.6.3+        dlHash: 9f9e37b7971935d88ba80426c36af14b1e0b3ec1d9c860f44a4391771bc07f23+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 8 && < 9 )':+              dlUri: https://downloads.haskell.org/~ghc/8.6.3/ghc-8.6.3-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.6.3+              dlHash: 291ca565374f4d51cc311488581f3279d3167a064fabfd4a6722fe2bd4532fd5+            unknown_versioning: &ghc-863-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.6.3/ghc-8.6.3-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.6.3+              dlHash: e7954c8ed9b422a09c6ab737e4a0865a2725d034ba0e272bd5c70db910797f99+          Linux_Ubuntu:+            unknown_versioning: &ghc-863-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.6.3/ghc-8.6.3-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.6.3+              dlHash: 52ae92f4e8bb2ac0b7847287ea3da37081f5f7bf8bbb7c78ac35fde537d1a89f+            '( >= 16 && < 19 )': *ghc-863-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-863-64-fedora+          Linux_Fedora:+            unknown_versioning: *ghc-863-64-fedora+          Linux_CentOS:+            unknown_versioning: &ghc-863-64-centos+              dlUri: https://downloads.haskell.org/~ghc/8.6.3/ghc-8.6.3-x86_64-centos7-linux.tar.xz+              dlSubdir: ghc-8.6.3+              dlHash: 355bd85c69933c31bbe99b4269ce719acfd0aad0b45e359ac39b9bb13996acc6+          Linux_RedHat:+            unknown_versioning: *ghc-863-64-centos+          Linux_AmazonLinux:+            unknown_versioning: *ghc-863-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-863-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.6.3/ghc-8.6.3-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.6.3+              dlHash: 79d069a1a7d74cfdd7ac2a2711c45d3ddc6265b988a0cefa342714b24f997fc1+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.6.3/ghc-8.6.3-x86_64-portbld-freebsd.tar.xz+              dlSubdir: ghc-8.6.3+              dlHash: bc2419fa180f8a7808c49775987866435995df9bdd9ce08bcd38352d63ba6031+        A_32:+          Linux_Debian:+            unknown_versioning: &ghc-863-32-deb8+              dlUri: https://downloads.haskell.org/~ghc/8.6.3/ghc-8.6.3-i386-deb8-linux.tar.xz+              dlSubdir: ghc-8.6.3+              dlHash: b57070ba8c70b1333a3e47ce124baf791be39c20a592954772532fd6dd51882f+          Linux_Ubuntu:+            unknown_versioning: *ghc-863-32-deb8+          Linux_Mint:+            unknown_versioning: *ghc-863-32-deb8+          Linux_UnknownLinux:+            unknown_versioning: *ghc-863-32-deb8+    8.6.4:+      viTags:+      - base-4.12.0.0+      - old+      viChangeLog: https://downloads.haskell.org/~ghc/8.6.4/docs/html/users_guide/8.6.4-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.6.4/ghc-8.6.4-src.tar.xz+        dlSubdir: ghc-8.6.4+        dlHash: 5b5d07e4463203a433c3ed3df461ba6cce11b6d2b9b264db31f3429075d0303a+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 8 && < 9 )':+              dlUri: https://downloads.haskell.org/~ghc/8.6.4/ghc-8.6.4-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.6.4+              dlHash: 34ef5fc8ddf2fc32a027180bea5b1c8a81ea840c87faace2977a572188d4b42d+            unknown_versioning: &ghc-864-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.6.4/ghc-8.6.4-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.6.4+              dlHash: ef74222ef3c01c3fc5b926f67e8b4ef612fe8efa40ac937317cff9b0eed8d863+          Linux_Ubuntu:+            unknown_versioning: &ghc-864-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.6.4/ghc-8.6.4-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.6.4+              dlHash: e0b1ada7a679d6c35f9d7a1192ed35fde054f3650bb0bd2570d103729ad3b846+            '( >= 16 && < 19 )': *ghc-864-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-864-64-fedora+          Linux_Fedora:+            unknown_versioning: *ghc-864-64-fedora+          Linux_UnknownLinux:+            unknown_versioning: *ghc-864-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.6.4/ghc-8.6.4-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.6.4+              dlHash: cccb58f142fe41b601d73690809f6089f7715b6a50a09aa3d0104176ab4db09e+        A_32:+          Linux_Debian:+            unknown_versioning: &ghc-864-32-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.6.4/ghc-8.6.4-i386-deb9-linux.tar.xz+              dlSubdir: ghc-8.6.4+              dlHash: 5e2ce88f4d13d23ac37e278e0c7b51c801008931359b9fa8a631d804d2da552c+          Linux_Ubuntu:+            unknown_versioning: *ghc-864-32-deb9+          Linux_Mint:+            unknown_versioning: *ghc-864-32-deb9+          Linux_UnknownLinux:+            unknown_versioning: *ghc-864-32-deb9+    8.6.5:+      viTags:+      - base-4.12.0.0+      viChangeLog: https://downloads.haskell.org/~ghc/8.6.5/docs/html/users_guide/8.6.5-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-src.tar.xz+        dlSubdir: ghc-8.6.5+        dlHash: 4d4aa1e96f4001b934ac6193ab09af5d6172f41f5a5d39d8e43393b9aafee361+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 8 && < 9 )':+              dlUri: https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.6.5+              dlHash: c419fd0aa9065fe4d2eb9a248e323860c696ddf3859749ca96a84938aee49107+            unknown_versioning: &ghc-865-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.6.5+              dlHash: bc75f5601a9f41d58b2ba161b9e28fad52143a7229060f1e084168d9b2e914df+          Linux_Ubuntu:+            unknown_versioning: &ghc-865-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.6.5+              dlHash: cf78b53eaf336083e7a05f4a3000afbae4abe5bbc77ef80cc40e09d04ac5b4a1+            '( >= 16 && < 19 )': *ghc-865-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-865-64-fedora+          Linux_Fedora:+            unknown_versioning: *ghc-865-64-fedora+          Linux_CentOS:+            unknown_versioning: &ghc-865-64-centos+              dlUri: https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-x86_64-centos7-linux.tar.xz+              dlSubdir: ghc-8.6.5+              dlHash: 80ab566f4411299f9e5922d60749ca80f989d697db19e03ed875619d699f0edf+          Linux_RedHat:+            unknown_versioning: *ghc-865-64-centos+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.6.5/ghc-8.6.5-x86_64-alpine-linux.tar.xz+              dlSubdir: ghc-8.6.5+              dlHash: b9d3ed7f7aa24ef2d58bb579252289caa0b8877adee3685e3af2fb73d440afdc+          Linux_AmazonLinux:+            unknown_versioning: *ghc-865-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-865-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.6.5+              dlHash: dfc1bdb1d303a87a8552aa17f5b080e61351f2823c2b99071ec23d0837422169+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.6.5/ghc-8.6.5-x86_64-portbld-freebsd.tar.xz+              dlSubdir: ghc-8.6.5+              dlHash: 83a3059a630d40a98e26cb5b520354e12094a96e36ba2f5ab002dad94cf2fb37+        A_32:+          Linux_Debian:+            unknown_versioning: &ghc-865-32-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-i386-deb9-linux.tar.xz+              dlSubdir: ghc-8.6.5+              dlHash: 1cddb907393a669342b1a922dd16d505d9d93d50bd9433a54a8162f8701250dc+          Linux_Ubuntu:+            unknown_versioning: *ghc-865-32-deb9+          Linux_Mint:+            unknown_versioning: *ghc-865-32-deb9+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.6.5/ghc-8.6.5-i386-alpine-linux.tar.xz+              dlSubdir: ghc-8.6.5+              dlHash: 3737837550d9b177acfe150e3a3cd4545427ded020487c2ed5194d7b8f116349+          Linux_UnknownLinux:+            unknown_versioning: *ghc-865-32-deb9+        A_ARM64:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-aarch64-ubuntu18.04-linux.tar.xz+              dlSubdir: ghc-8.6.5+              dlHash: 1852589037e4b2805ab517bc430e25a3125c4a118a1674ffefbb443394a0c786+    8.8.1:+      viTags:+      - base-4.13.0.0+      - old+      viChangeLog: https://downloads.haskell.org/~ghc/8.8.1/docs/html/users_guide/8.8.1-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.8.1/ghc-8.8.1-src.tar.xz+        dlSubdir: ghc-8.8.1+        dlHash: 908a83d9b814da74585de9d39687189e6260ec3848131f9d9236cab8a123721a+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 8 && < 9 )':+              dlUri: https://downloads.haskell.org/~ghc/8.8.1/ghc-8.8.1-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.8.1+              dlHash: fd96eb851971fbc3332bf2fa7821732cfa8b37e5a076a69f6a06f83f0ea7ccc5+            unknown_versioning: &ghc-881-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.8.1/ghc-8.8.1-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.8.1+              dlHash: 620fd560535b63cac5f8c97354ccddf93fa940cca78e2d19f6f98b7e67c6a723+          Linux_Ubuntu:+            unknown_versioning: &ghc-881-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.8.1/ghc-8.8.1-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.8.1+              dlHash: 851a78df620bc056c34b252c97040d5755e294993fa8afa5429708b5229204d6+            '( >= 16 && < 19 )': *ghc-881-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-881-64-fedora+          Linux_Fedora:+            unknown_versioning: *ghc-881-64-fedora+          Linux_CentOS:+            unknown_versioning: &ghc-881-64-centos+              dlUri: https://downloads.haskell.org/~ghc/8.8.1/ghc-8.8.1-x86_64-centos7-linux.tar.xz+              dlSubdir: ghc-8.8.1+              dlHash: 6cdd34e4dbaeb801e805811f91cf43a2d5f64b22f884718ffbd3542a2f4dd14f+          Linux_RedHat:+            unknown_versioning: *ghc-881-64-centos+          Linux_AmazonLinux:+            unknown_versioning: *ghc-881-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-881-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.8.1/ghc-8.8.1-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.8.1+              dlHash: 38c8917b47c31bedf58c9305dfca3abe198d8d35570366f0773c4e2948bd8abe+        A_32:+          Linux_Debian:+            unknown_versioning: &ghc-881-32-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.8.1/ghc-8.8.1-i386-deb9-linux.tar.xz+              dlSubdir: ghc-8.8.1+              dlHash: 3d3bb75aff2dd79ec87ace10483368681fbc328ff00ebf15edad33420f00f7f5+          Linux_Ubuntu:+            unknown_versioning: *ghc-881-32-deb9+          Linux_Mint:+            unknown_versioning: *ghc-881-32-deb9+          Linux_UnknownLinux:+            unknown_versioning: *ghc-881-32-deb9+    8.8.2:+      viTags:+      - base-4.13.0.0+      - old+      viChangeLog: https://downloads.haskell.org/~ghc/8.8.2/docs/html/users_guide/8.8.2-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.8.2/ghc-8.8.2-src.tar.xz+        dlSubdir: ghc-8.8.2+        dlHash: 01cea54d90686b97bcc9960b108beaffccd4336dee930dcf9beaf52b1f370a0b+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 8 && < 9 )':+              dlUri: https://downloads.haskell.org/~ghc/8.8.2/ghc-8.8.2-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.8.2+              dlHash: fbe69652eba75dadb758d00292247d17fb018c29cac5acd79843e56311256c9f+            unknown_versioning: &ghc-882-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.8.2/ghc-8.8.2-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.8.2+              dlHash: 7b2d66c2d5d8c15750da5833d3018634a5eb792a5662282e3abfeb112c2a1cc3+          Linux_Ubuntu:+            unknown_versioning: &ghc-882-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.8.2/ghc-8.8.2-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.8.2+              dlHash: dbe2db717b33460f790e155e487d2a31c9b21a9d245f0c9490ad65844c3ea21f+            '( >= 16 && < 19 )': *ghc-882-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-882-64-fedora+          Linux_Fedora:+            unknown_versioning: *ghc-882-64-fedora+          Linux_CentOS:+            unknown_versioning: &ghc-882-64-centos+              dlUri: https://downloads.haskell.org/~ghc/8.8.2/ghc-8.8.2-x86_64-centos7-linux.tar.xz+              dlSubdir: ghc-8.8.2+              dlHash: f065a017d7a38f235f186ffe32d8261a4fd39c7e945d5cde85c0984c2569db99+          Linux_RedHat:+            unknown_versioning: *ghc-882-64-centos+          Linux_AmazonLinux:+            unknown_versioning: *ghc-882-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-882-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.8.2/ghc-8.8.2-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.8.2+              dlHash: 25c5c1a70036abf3f22b2b19c10d26adfdb08e8f8574f89d4b2042de5947f990+        A_32:+          Linux_Debian:+            unknown_versioning: &ghc-882-32-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.8.2/ghc-8.8.2-i386-deb9-linux.tar.xz+              dlSubdir: ghc-8.8.2+              dlHash: ad1c628082c32635a436905a7ff83eaa4246347d869be5ef6b33c3bf85e8f00c+          Linux_Ubuntu:+            unknown_versioning: *ghc-882-32-deb9+          Linux_Mint:+            unknown_versioning: *ghc-882-32-deb9+          Linux_UnknownLinux:+            unknown_versioning: *ghc-882-32-deb9+    8.8.3:+      viTags:+      - base-4.13.0.0+      - old+      viChangeLog: https://downloads.haskell.org/~ghc/8.8.3/docs/html/users_guide/8.8.3-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-src.tar.xz+        dlSubdir: ghc-8.8.3+        dlHash: e0dcc0aaf3e234c5978f29e6df62947e97720ab404ec0158343df211c5480f89+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 8 && < 9 )':+              dlUri: https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.8.3+              dlHash: 92b9fadc442976968d2c190c14e000d737240a7d721581cda8d8741b7bd402f0+            unknown_versioning: &ghc-883-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.8.3+              dlHash: 42fde2ef5a143e1e6b47ae8875162ea2d4d54b06f0f7fa32ee4f0eb86f2be7ad+          Linux_Ubuntu:+            unknown_versioning: &ghc-883-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.8.3+              dlHash: 45ee1de3bfc98cbcc4886b65fc7651ade2d3820aa85eac2dbe9bc7bf91e7c818+            '( >= 16 && < 19 )': *ghc-883-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-883-64-fedora+          Linux_Fedora:+            unknown_versioning: *ghc-883-64-fedora+          Linux_CentOS:+            unknown_versioning: &ghc-883-64-centos+              dlUri: https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-x86_64-centos7-linux.tar.xz+              dlSubdir: ghc-8.8.3+              dlHash: 4b2b5313f7c12b81e54efcb26705fa9e4ad5b98f2b58bfc76fb0c9ba1d55eb1f+          Linux_RedHat:+            unknown_versioning: *ghc-883-64-centos+          Linux_AmazonLinux:+            unknown_versioning: *ghc-883-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-883-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.8.3+              dlHash: 7016de90dd226b06fc79d0759c5d4c83c2ab01d8c678905442c28bd948dbb782+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.8.3/ghc-8.8.3-x86_64-portbld-freebsd.tar.xz+              dlSubdir: ghc-8.8.3+              dlHash: 569719075b4d14b3875a899df522090ae31e6fe085e6dffe518e875b09a2f0be+        A_32:+          Linux_Debian:+            unknown_versioning: &ghc-883-32-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-i386-deb9-linux.tar.xz+              dlSubdir: ghc-8.8.3+              dlHash: 441e2c7a4fc83ebf179712bd939b555cda7c6633545b7c8ac38049f9d85003ae+          Linux_Ubuntu:+            unknown_versioning: *ghc-883-32-deb9+          Linux_Mint:+            unknown_versioning: *ghc-883-32-deb9+          Linux_UnknownLinux:+            unknown_versioning: *ghc-883-32-deb9+        A_ARM64:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-aarch64-deb9-linux.tar.xz+              dlSubdir: ghc-8.8.3+              dlHash: 2a6821d0e7326cfa7670851702924bbab3b092415ba41247c37419158327eed9+    8.8.4:+      viTags:+      - base-4.13.0.0+      viChangeLog: https://downloads.haskell.org/~ghc/8.8.4/docs/html/users_guide/8.8.4-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.8.4/ghc-8.8.4-src.tar.xz+        dlSubdir: ghc-8.8.4+        dlHash: f0505e38b2235ff9f1090b51f44d6c8efd371068e5a6bb42a2a6d8b67b5ffc2d+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 8 && < 9 )':+              dlUri: https://downloads.haskell.org/~ghc/8.8.4/ghc-8.8.4-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.8.4+              dlHash: 51a36892f1264744195274187298d13ac62bce2da86d4ddf76d8054ab90f2feb+            unknown_versioning: &ghc-884-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.8.4/ghc-8.8.4-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.8.4+              dlHash: 4862559d221153caf978f4bf2c15a82c114d1e1f43b298b2ecff2ac94b586d20+          Linux_Ubuntu:+            unknown_versioning: &ghc-884-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.8.4/ghc-8.8.4-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.8.4+              dlHash: f32e37f8aa03e74bad533ae02f62dc27a4521e78199576af490888ba34b515db+            '( >= 16 && < 19 )': *ghc-884-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-884-64-fedora+          Linux_Fedora:+            unknown_versioning: *ghc-884-64-fedora+          Linux_CentOS:+            unknown_versioning: &ghc-884-64-centos+              dlUri: https://downloads.haskell.org/~ghc/8.8.4/ghc-8.8.4-x86_64-centos7-linux.tar.xz+              dlSubdir: ghc-8.8.4+              dlHash: a12aa4b1fd3c64240a8a6d15196d33e1c0e0d55b51ff78c387242126d0ef7910+          Linux_RedHat:+            unknown_versioning: *ghc-884-64-centos+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.8.4/ghc-8.8.4-x86_64-alpine-linux.tar.xz+              dlSubdir: ghc-8.8.4+              dlHash: 90c6a1661de7f20c7d169cd6270125035b3332063e45103ce028df0beecf434e+          Linux_AmazonLinux:+            unknown_versioning: *ghc-884-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-884-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.8.4/ghc-8.8.4-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.8.4+              dlHash: e80a789e9d8cfb41dd87f3284b75432427c4461c1731d220d04ead8733ccdb5e+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.8.4/ghc-8.8.4-x86_64-portbld-freebsd.tar.xz+              dlSubdir: ghc-8.8.4+              dlHash: 8cebe5ccf454e82acd1ff52ca57590d1ab0f3f44a981b46257ec12158c8c447e+        A_32:+          Linux_Debian:+            unknown_versioning: &ghc-884-32-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.8.4/ghc-8.8.4-i386-deb9-linux.tar.xz+              dlSubdir: ghc-8.8.4+              dlHash: 43dd954910c9027694312cef0aabc7774d102d0422b7172802cfb72f7d5da3a0+          Linux_Ubuntu:+            unknown_versioning: *ghc-884-32-deb9+          Linux_Mint:+            unknown_versioning: *ghc-884-32-deb9+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.8.4/ghc-8.8.4-i386-alpine-linux.tar.xz+              dlSubdir: ghc-8.8.4+              dlHash: 1d18e89ee031197e55c48683e78a7ffc67601ac5fd9f73aac555eb064b3859a2+          Linux_UnknownLinux:+            unknown_versioning: *ghc-884-32-deb9+    8.10.1:+      viTags:+      - base-4.14.0.0+      - old+      viChangeLog: https://downloads.haskell.org/~ghc/8.10.1/docs/html/users_guide/8.10.1-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-src.tar.xz+        dlSubdir: ghc-8.10.1+        dlHash: 4e3b07f83a266b3198310f19f71e371ebce97c769b14f0d688f4cbf2a2a1edf5+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-8101-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.10.1+              dlHash: d1cf7886f27af070f3b7dbe1975a78b43ef2d32b86362cbe953e79464fe70761+            '( >= 10 && < 11 )': &ghc-8101-64-deb10+              dlUri: https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-x86_64-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.1+              dlHash: c1e31d798b013699b3c0de4fda27fb4cda47f572df0e75e3bd598a3012060615+            unknown_versioning: *ghc-8101-64-deb9+          Linux_Ubuntu:+            unknown_versioning: &ghc-8101-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.10.1+              dlHash: 3c4cd72b4806045779739e8f5d1658e30e57123d88c2c8966422cdbcae448470+            '( >= 16 && < 19 )': *ghc-8101-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-8101-64-fedora+          Linux_Fedora:+            '( >= 27 && < 28 )': *ghc-8101-64-fedora+            unknown_versioning: *ghc-8101-64-fedora+          Linux_CentOS:+            '( >= 7 && < 8 )': &ghc-8101-64-centos+              dlUri: https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-x86_64-centos7-linux.tar.xz+              dlSubdir: ghc-8.10.1+              dlHash: 0618b94854edc6be5302489df905e627820b71be6b66c950f5e3088fe92df0a1+            unknown_versioning: *ghc-8101-64-centos+          Linux_RedHat:+            unknown_versioning: *ghc-8101-64-centos+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-x86_64-alpine3.10-linux-integer-simple.tar.xz+              dlSubdir: ghc-8.10.1-x86_64-unknown-linux+              dlHash: cb13b645d103e2fba2eb8dfcc4e5f2fbd9550c00c4df42f342b4210436dcb8a8+          Linux_AmazonLinux:+            unknown_versioning: *ghc-8101-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-8101-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.10.1+              dlHash: 65b1ca361093de4804a7e40b3e68178e1ef720f84f743641ec8d95e56a45b3a8+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.10.1/ghc-8.10.1-x86_64-portbld-freebsd.tar.xz+              dlSubdir: ghc-8.10.1+              dlHash: e8646ec9b60fd40aa9505ee055f22f04601290ab7a1342c2cf37c34de9d3f142+        A_32:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-8101-32-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-i386-deb9-linux.tar.xz+              dlSubdir: ghc-8.10.1+              dlHash: 8b53eef2c827b5f634d72920a93c0c9dd66ea288691a2bfe28def45d3c686ee2+            unknown_versioning: *ghc-8101-32-deb9+          Linux_Ubuntu:+            unknown_versioning: *ghc-8101-32-deb9+          Linux_Mint:+            unknown_versioning: *ghc-8101-32-deb9+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.10.1/ghc-8.10.1-i386-alpine-linux.tar.xz+              dlSubdir: ghc-8.10.1+              dlHash: 7360cc6b29e9b4ab08f6ea5bc3bcca6f5c216933e81ef1620dcdd700f1fdb289+          Linux_UnknownLinux:+            unknown_versioning: *ghc-8101-32-deb9+        A_ARM64:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-aarch64-deb9-linux.tar.xz+              dlSubdir: ghc-8.10.1+              dlHash: c099011e07999db917e797fb5d89c31f075a562556ab99be8ab0accbf2a94db7+        A_ARM:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-armv7-deb9-linux.tar.xz+              dlSubdir: ghc-8.10.1+              dlHash: afe1bde2b0d6deb0320b9460fffe5d9427e302df85aec866b9c1458777d52b28+    8.10.2:+      viTags:+      - old+      - base-4.14.1.0+      viChangeLog: https://downloads.haskell.org/~ghc/8.10.2/docs/html/users_guide/8.10.2-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-src.tar.xz+        dlSubdir: ghc-8.10.2+        dlHash: 9c573a4621a78723950617c223559bdc325ea6a3409264aedf68f05510b0880b+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-8102-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.10.2+              dlHash: 4dbe3b479e76767bfeb4cbb7a4db8b761c4720266193483ca370b2ace3f10f7c+            '( >= 10 && < 11 )': &ghc-8102-64-deb10+              dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-x86_64-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.2+              dlHash: 94513d82c38c848f489113a75fa5ef4e5a8e3ecfaa74ca90e2620d2193ff1632+            unknown_versioning: *ghc-8102-64-deb9+          Linux_Ubuntu:+            unknown_versioning: &ghc-8102-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.10.2+              dlHash: 8c675da83e9b3c2f64ebb407b5f9ebb2c1f21aa5d701020614fdce644a542e3b+            '( >= 16 && < 19 )': *ghc-8102-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-8102-64-fedora+          Linux_Fedora:+            '( >= 27 && < 28 )': *ghc-8102-64-fedora+            unknown_versioning: *ghc-8102-64-fedora+          Linux_CentOS:+            '( >= 7 && < 8 )': &ghc-8102-64-centos+              dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-x86_64-centos7-linux.tar.xz+              dlSubdir: ghc-8.10.2+              dlHash: fd2dccd6f496915a5f962dab24e7eeb8bee49bcc38e74b17eac76159083538fa+            unknown_versioning: *ghc-8102-64-centos+          Linux_RedHat:+            unknown_versioning: *ghc-8102-64-centos+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-x86_64-alpine3.10-linux-integer-simple.tar.xz+              dlSubdir: ghc-8.10.2-x86_64-unknown-linux+              dlHash: 14d09a508f2a3a11875c140be8e6c5f6982ac5cd448f089ca10b7adc955fec76+          Linux_AmazonLinux:+            unknown_versioning: *ghc-8102-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-8102-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.10.2+              dlHash: edb772b00c0d7f18bb56ad27765162ee09c508104d40f82128c9114a02f6cfc2+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-x86_64-unknown-freebsd.tar.xz+              dlSubdir: ghc-8.10.2+              dlHash: 9e5957f3497f4b58ecd3699568d9caaa11a47a6d7e902032c261e450fa0f6686+        A_32:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-8102-32-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-i386-deb9-linux.tar.xz+              dlSubdir: ghc-8.10.2+              dlHash: 9dae2a86ad43d08f72c783542c944d1556b075aa20a8063efae5034ea88e7c2f+            unknown_versioning: *ghc-8102-32-deb9+          Linux_Ubuntu:+            unknown_versioning: *ghc-8102-32-deb9+          Linux_Mint:+            unknown_versioning: *ghc-8102-32-deb9+          Linux_UnknownLinux:+            unknown_versioning: *ghc-8102-32-deb9+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.10.2/ghc-8.10.2-i386-alpine-linux.tar.xz+              dlSubdir: ghc-8.10.2+              dlHash: 9ee1cf1e85e9536088b3c9e80e975074e525ea378cd4eb156071bbc4b7b38327+        A_ARM64:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-aarch64-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.2+              dlHash: 5cf24189077e6e2dce2aa16367ad8a53f603e751a15010dfb23d067206e55593+        A_ARM:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-armv7-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.2+              dlHash: bb9c97826b1f4d7a8ef8bce0616b612f1ded10480ef10fcf7fb4e6d10a6681c8+    8.10.3:+      viTags:+      - old+      - base-4.14.1.0+      viChangeLog: https://downloads.haskell.org/~ghc/8.10.3/docs/html/users_guide/8.10.3-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-src.tar.xz+        dlSubdir: ghc-8.10.3+        dlHash: ccdc8319549028a708d7163e2967382677b1a5a379ff94d948195b5cf46eb931+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-8103-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.10.3+              dlHash: 95e4aadea30701fe5ab84d15f757926d843ded7115e11c4cd827809ca830718d+            '( >= 10 && < 11 )': &ghc-8103-64-deb10+              dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-x86_64-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.3+              dlHash: c8f3d9f0e61a89eaba1d3ad8fb2eced1af0e81576811261b887993bee12538ac+            unknown_versioning: *ghc-8103-64-deb9+          Linux_Ubuntu:+            unknown_versioning: &ghc-8103-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.10.3+              dlHash: f8739b12008712d6b6a9ffc6c39f9d05af77ef3bcb932c9aff20fa0893c8c159+            '( >= 16 && < 19 )': *ghc-8103-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-8103-64-deb10+          Linux_Fedora:+            '( >= 27 && < 28 )': *ghc-8103-64-fedora+            unknown_versioning: *ghc-8103-64-fedora+          Linux_CentOS:+            '( >= 7 && < 8 )': &ghc-8103-64-centos+              dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-x86_64-centos7-linux.tar.xz+              dlSubdir: ghc-8.10.3+              dlHash: f562ca61979ff1d21e34e69e59028cb742a8eff8d84e46bbd3a750f2ac7d8ed1+            unknown_versioning: *ghc-8103-64-centos+          Linux_RedHat:+            unknown_versioning: *ghc-8103-64-centos+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-x86_64-alpine3.10-linux-integer-simple.tar.xz+              dlSubdir: ghc-8.10.3-x86_64-unknown-linux+              dlHash: 8506c478ebbfb5441c3c36c07c36fc8532cacb2b3e13c6733bd44cb17b3ce96c+          Linux_AmazonLinux:+            unknown_versioning: *ghc-8103-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-8103-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.10.3+              dlHash: 2635f35d76e44e69afdfd37cae89d211975cc20f71f784363b72003e59f22015+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-x86_64-portbld-freebsd.tar.xz+              dlSubdir: ghc-8.10.3+              dlHash: 749007e995104db05cf6e3ad5bc36238cab8afac8055145661e5730e8f8af040+        A_32:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-8103-32-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-i386-deb9-linux.tar.xz+              dlSubdir: ghc-8.10.3+              dlHash: f0addd2a16b705f58ff9e8702c3ddf3e2d6bd0d3555707b5b5095e51bafee7b1+            unknown_versioning: *ghc-8103-32-deb9+          Linux_Ubuntu:+            unknown_versioning: *ghc-8103-32-deb9+          Linux_Mint:+            unknown_versioning: *ghc-8103-32-deb9+          Linux_UnknownLinux:+            unknown_versioning: *ghc-8103-32-deb9+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.10.3/ghc-8.10.3-i386-alpine-linux.tar.xz+              dlSubdir: ghc-8.10.3+              dlHash: 309201cdefd2d13b8b3fd09c26c6137048c490d219a0a9c7407c3ce1d011f60c+        A_ARM64:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-aarch64-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.3+              dlHash: a531432d505a1fe886cdc8639d168eb1c92d76464c1270713e01ce81891bbadb+        A_ARM:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-armv7-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.3+              dlHash: b823b58cae36fbac0741680ca7605180fa4cf4c6ae439123d282184b94d32fd6+    8.10.4:+      viTags:+      - base-4.14.1.0+      viChangeLog: https://downloads.haskell.org/~ghc/8.10.4/docs/html/users_guide/8.10.4-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-src.tar.xz+        dlSubdir: ghc-8.10.4+        dlHash: 52af871b4e08550257d720c2944ac85727d0b948407cef1bebfe7508c224910e+      viPostRemove: *ghc-post-remove+      viPreCompile: &ghc-pre-compile "If you have autoconf >= 2.70 you'll need this patch https://gitlab.haskell.org/ghc/ghc/-/snippets/2040 (see the --patchdir option)"+      viArch:+        A_64:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-8104-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.10.4+              dlHash: 5694200a5c38f22c142baf850b1d2f3784211d2ec9302e11693259a1ae8e38b7+            '( >= 10 && < 11 )': &ghc-8104-64-deb10+              dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-x86_64-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.4+              dlHash: 816365565e9927459b035515a7db6a0db62f9796f327389b6f8a0035d12fbda0+            unknown_versioning: *ghc-8104-64-deb9+          Linux_Ubuntu:+            unknown_versioning: &ghc-8104-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.10.4+              dlHash: a189eed900a8717d6d7906bafd10b9a9a9688ad942d1c75e19df480376dff9ea+            '( >= 16 && < 19 )': *ghc-8104-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-8104-64-deb10+          Linux_Fedora:+            '( >= 27 && < 28 )': *ghc-8104-64-fedora+            unknown_versioning: *ghc-8104-64-fedora+          Linux_CentOS:+            '( >= 7 && < 8 )': &ghc-8104-64-centos+              dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-x86_64-centos7-linux.tar.xz+              dlSubdir: ghc-8.10.4+              dlHash: fb8a91f0cf06594172aff46c2f6f7486179e1c3760855c79fbdd3012598cc2cd+            unknown_versioning: *ghc-8104-64-centos+          Linux_RedHat:+            unknown_versioning: *ghc-8104-64-centos+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-x86_64-alpine3.10-linux-integer-simple.tar.xz+              dlSubdir: ghc-8.10.4-x86_64-unknown-linux+              dlHash: 74c2c07537832708502716ef4ec40019f8e552ddda13c8eadf8f7c4b03a79359+          Linux_AmazonLinux:+            unknown_versioning: *ghc-8104-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-8104-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.10.4+              dlHash: 725ecf6543e63b81a3581fb8c97afd21a08ae11bc0fa4f8ee25d45f0362ef6d5+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-x86_64-portbld-freebsd.tar.xz+              dlSubdir: ghc-8.10.4+              dlHash: c9776a2ccf9629b03e967206a507fcdcb6c5189800a626e9461ababf6733c357+        A_32:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-8104-32-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-i386-deb9-linux.tar.xz+              dlSubdir: ghc-8.10.4+              dlHash: 0022c5b9ac22825bb7b4745af3d92cef0ba1ecd01fab3ef387ddbd47146569ad+            unknown_versioning: *ghc-8104-32-deb9+          Linux_Ubuntu:+            unknown_versioning: *ghc-8104-32-deb9+          Linux_Mint:+            unknown_versioning: *ghc-8104-32-deb9+          Linux_UnknownLinux:+            unknown_versioning: *ghc-8104-32-deb9+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.10.4/ghc-8.10.4-i386-alpine-linux.tar.xz+              dlSubdir: ghc-8.10.4+              dlHash: 9161a98bed763692101854d83af69c1316030cfe5ee6f6acde283d04ef139735+        A_ARM64:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-aarch64-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.4+              dlHash: 249da6310be799a5eefe0579b6dae1701eb984afb980fe08309d19cf704038ed+        A_ARM:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-armv7-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.4+              dlHash: 0d18ef83593272f6196a41cc3abdc48dfe5e14372db75d71ea19fe35320c4e81+    8.10.5:+      viTags:+      - Recommended+      - base-4.14.2.0+      viChangeLog: https://downloads.haskell.org/~ghc/8.10.5/docs/html/users_guide/8.10.5-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.10.5/ghc-8.10.5-src.tar.xz+        dlSubdir: ghc-8.10.5+        dlHash: f10941f16e4fbd98580ab5241b9271bb0851304560c4d5ca127e3b0e20e3076f+      viPostRemove: *ghc-post-remove+      viPreCompile: *ghc-pre-compile+      viArch:+        A_64:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-8105-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.10.5/ghc-8.10.5-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.10.5+              dlHash: 15e71325c3bdfe3804be0f84c2fc5c913d811322d19b0f4d4cff20f29cdd804d+            '( >= 10 && < 11 )': &ghc-8105-64-deb10+              dlUri: https://downloads.haskell.org/~ghc/8.10.5/ghc-8.10.5-x86_64-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.5+              dlHash: bc623c20ca4c5c18e952071ba14aa0cfc5c94d34219bffaa615f7b491f376787+            unknown_versioning: *ghc-8105-64-deb9+          Linux_Ubuntu:+            unknown_versioning: &ghc-8105-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.10.5/ghc-8.10.5-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.10.5+              dlHash: 73528ebfb219b50aa9042ee51a0a2bd764828d605f058404989d0b645752d210+            '( >= 16 && < 19 )': *ghc-8105-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-8105-64-deb10+          Linux_Fedora:+            '( >= 27 && < 28 )': *ghc-8105-64-fedora+            unknown_versioning: *ghc-8105-64-fedora+          Linux_CentOS:+            '( >= 7 && < 8 )': &ghc-8105-64-centos+              dlUri: https://downloads.haskell.org/~ghc/8.10.5/ghc-8.10.5-x86_64-centos7-linux.tar.xz+              dlSubdir: ghc-8.10.5+              dlHash: 4cdb259ec74d1408dab45dab20dcedc21690f39921c2ea4546486fb3e81f4fbd+            unknown_versioning: *ghc-8105-64-centos+          Linux_RedHat:+            unknown_versioning: *ghc-8105-64-centos+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.5/ghc-8.10.5-x86_64-alpine3.10-linux-integer-simple.tar.xz+              dlSubdir: ghc-8.10.5-x86_64-unknown-linux+              dlHash: f4d7cd9ed12a4b8592219c9a63a86db1a256a09fa9e6ed755a60afc57dc782e2+          Linux_AmazonLinux:+            unknown_versioning: *ghc-8105-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-8105-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.5/ghc-8.10.5-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.10.5+              dlHash: ef0f47eff8962d58fa447123636cf8ef31c1e5b2d0ae90177d3388861ddf4a22+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghcup/unofficial-bindists/ghc/8.10.5/ghc-8.10.5-x86_64-portbld-freebsd.tar.xz+              dlSubdir: ghc-8.10.5+              dlHash: 11a0b490bfb2f57b5bc87c69c197542eafce1b4991cc22f625179a6c6e567834+        A_32:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-8105-32-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.10.5/ghc-8.10.5-i386-deb9-linux.tar.xz+              dlSubdir: ghc-8.10.5+              dlHash: 0ccb5b2c1222374874795c35410754dd650f649b774872abbea2a4ef21ac9c9d+            unknown_versioning: *ghc-8105-32-deb9+          Linux_Ubuntu:+            unknown_versioning: *ghc-8105-32-deb9+          Linux_Mint:+            unknown_versioning: *ghc-8105-32-deb9+          Linux_UnknownLinux:+            unknown_versioning: *ghc-8105-32-deb9+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghcup/unofficial-bindists/ghc/8.10.5/ghc-8.10.5-i386-alpine-linux.tar.xz+              dlSubdir: ghc-8.10.5+              dlHash: 0e91abe61607f9375d4e252ee9c261e4856df396f60641bb1b880ab8a3a83ea7+        A_ARM64:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.5/ghc-8.10.5-aarch64-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.5+              dlHash: 9a085cd8a7f8e0ace21ac67dbf659a56fcf41564b48817ba42cd8a1aac7f0ddc+        A_ARM:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.5/ghc-8.10.5-armv7-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.5+              dlHash: 56170d1a8450e18b7eb9c23c94723da352815b27ec250bb23742a62f16dcab6c+    9.0.1:+      viTags:+      - Latest+      - base-4.15.0.0+      viChangeLog: https://downloads.haskell.org/~ghc/9.0.1/docs/html/users_guide/9.0.1-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-src.tar.xz+        dlSubdir: ghc-9.0.1+        dlHash: a5230314e4065f9fcc371dfe519748fd85c825b279abf72a24e09b83578a35f9+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-901-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-9.0.1+              dlHash: 4ca6252492f59fe589029fadca4b6f922d6a9f0ff39d19a2bd9886fde4e183d5+            '( >= 10 && < 11 )': &ghc-901-64-deb10+              dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-x86_64-deb10-linux.tar.xz+              dlSubdir: ghc-9.0.1+              dlHash: c253e7eb62cc9da6524c491c85ec8d3727c2ca6035a8653388e636aaa30a2a0f+            unknown_versioning: *ghc-901-64-deb9+          Linux_Ubuntu:+            unknown_versioning: &ghc-901-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-9.0.1+              dlHash: 1fb8e27eeec51b4cdbfd1b3c16727adc5f77388d3e925e63799d8232647f316d+            '( >= 16 && < 19 )': *ghc-901-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-901-64-deb10+          Linux_Fedora:+            '( >= 27 && < 28 )': *ghc-901-64-fedora+            unknown_versioning: *ghc-901-64-fedora+          Linux_CentOS:+            '( >= 7 && < 8 )': &ghc-901-64-centos+              dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-x86_64-centos7-linux.tar.xz+              dlSubdir: ghc-9.0.1+              dlHash: a23750950b6995a66ba59afe82bbc505bd3479d6ab59cf66f45bc6c056e4d87b+            unknown_versioning: *ghc-901-64-centos+          Linux_RedHat:+            unknown_versioning: *ghc-901-64-centos+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-x86_64-alpine3.10-linux-integer-simple.tar.xz+              dlSubdir: ghc-9.0.1-x86_64-unknown-linux+              dlHash: 7c1a0154c9e361b75be6cb0305533bb8a3b963c54e8092ffd1759e5710805a5c+          Linux_AmazonLinux:+            unknown_versioning: *ghc-901-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-901-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-9.0.1+              dlHash: 122d60509147d0117779d275f0215bde2ff63a64cda9d88f149432d0cae71b22+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-x86_64-portbld-freebsd.tar.xz+              dlSubdir: ghc-9.0.1+              dlHash: 9dbc06d8832cae5c9f86dd7b2db729b3748a47beb4fd4b1e62bb66119817c3c1+        A_32:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-901-32-deb9+              dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-i386-deb9-linux.tar.xz+              dlSubdir: ghc-9.0.1+              dlHash: 880e37cea8328401bcfecfe4bb56eb85195f30135b140140b3f24094264f8ba5+            unknown_versioning: *ghc-901-32-deb9+          Linux_Ubuntu:+            unknown_versioning: *ghc-901-32-deb9+          Linux_Mint:+            unknown_versioning: *ghc-901-32-deb9+          Linux_UnknownLinux:+            unknown_versioning: *ghc-901-32-deb9+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/9.0.1/ghc-9.0.1-i386-alpine-linux.tar.xz+              dlSubdir: ghc-9.0.1+              dlHash: ebfeb3b91e6f2bb5a49fd3376746f7fd1b89e62e9838bf5b1530a8756ff1e6aa+        A_ARM64:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-aarch64-deb9-linux.tar.xz+              dlSubdir: ghc-9.0.1+              dlHash: fac7a0bdfc83c05df94024a2d67b8f00a9cd2733b9cb41fb8ad76be399014906+        A_ARM:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-armv7-deb9-linux.tar.xz+              dlSubdir: ghc-9.0.1+              dlHash: 6f404f9b88468407b3a9ec5800bcc2d01dd453ef3d63414853b4fbbd4d8df496+    9.2.0.20210422:+      viTags:+      - Prerelease+      - base-4.16.0.0+      viChangeLog: https://downloads.haskell.org/~ghc/9.2.1-alpha2/docs/html/users_guide/index.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/9.2.1-alpha2/ghc-9.2.0.20210422-src.tar.xz+        dlSubdir: ghc-9.2.0.20210422+        dlHash: 69be189e6e7f8d51a9078ac8f177176bc5bff54edc8352974c50c1f0e110df27+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-921-alpha2-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/9.2.1-alpha2/ghc-9.2.0.20210422-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-9.2.0.20210422+              dlHash: 7262f3a230cd6945c588882e03941301877a9eb12e58c5975ad264596c2e12f2+            '( >= 10 && < 11 )': &ghc-921-alpha2-64-deb10+              dlUri: https://downloads.haskell.org/~ghc/9.2.1-alpha2/ghc-9.2.0.20210422-x86_64-deb10-linux.tar.xz+              dlSubdir: ghc-9.2.0.20210422+              dlHash: 6d36cd08576bdee7473fee66b4b8ceb72011983a7d5aa3ec587403815a73e37b+            unknown_versioning: *ghc-921-alpha2-64-deb9+          Linux_Ubuntu:+            unknown_versioning: &ghc-921-alpha2-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/9.2.1-alpha2/ghc-9.2.0.20210422-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-9.2.0.20210422+              dlHash: 95624192ff0982690bc9093632d6351fdc6f72e6df380b392449229c39a0354b+            '( >= 16 && < 19 )': *ghc-921-alpha2-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-921-alpha2-64-deb10+          Linux_Fedora:+            '( >= 27 && < 28 )': *ghc-921-alpha2-64-fedora+            unknown_versioning: *ghc-921-alpha2-64-fedora+          Linux_CentOS:+            '( >= 7 && < 8 )': &ghc-921-alpha2-64-centos+              dlUri: https://downloads.haskell.org/~ghc/9.2.1-alpha2/ghc-9.2.0.20210422-x86_64-centos7-linux.tar.xz+              dlSubdir: ghc-9.2.0.20210422+              dlHash: dee4f158f2d59bfe97ec3f5773b6b31aa911f9b128a5e56eeefa2dccc754d295+            unknown_versioning: *ghc-921-alpha2-64-centos+          Linux_RedHat:+            unknown_versioning: *ghc-921-alpha2-64-centos+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/9.2.1-alpha2/ghc-9.2.0.20210422-x86_64-alpine3.10-linux-integer-simple.tar.xz+              dlSubdir: ghc-9.2.0.20210422-x86_64-unknown-linux+              dlHash: f61ae72925325ca7b316e40121e8d6bad94794016d3fa59bcbc8dbe116a7f13c+          Linux_AmazonLinux:+            unknown_versioning: *ghc-921-alpha2-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-921-alpha2-64-fedora+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/9.2.1-alpha2/ghc-9.2.0.20210422-x86_64-unknown-freebsd.tar.xz+              dlSubdir: ghc-9.2.0.20210422+              dlHash: 195728e02398ea6154fe713b7782a0cae856eb0d9d90f5d09cd0cca610c985e2+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/9.2.1-alpha2/ghc-9.2.0.20210422-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-9.2.0.20210422+              dlHash: 8884c059f2b76e4c4309ff6bd7a7dde37663f751fd26220e9a2bcabb4d69a401+        A_32:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-921-alpha2-32-deb9+              dlUri: https://downloads.haskell.org/~ghc/9.2.1-alpha2/ghc-9.2.0.20210422-i386-deb9-linux.tar.xz+              dlSubdir: ghc-9.2.0.20210422+              dlHash: a378ec3fd31a9fa2a7134e98159e189362fe969f04031515616e9cc3182c861a+            unknown_versioning: *ghc-921-alpha2-32-deb9+          Linux_Ubuntu:+            unknown_versioning: *ghc-921-alpha2-32-deb9+          Linux_Mint:+            unknown_versioning: *ghc-921-alpha2-32-deb9+          Linux_UnknownLinux:+            unknown_versioning: *ghc-921-alpha2-32-deb9+        A_ARM64:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/9.2.1-alpha2/ghc-9.2.0.20210422-aarch64-deb10-linux.tar.xz+              dlSubdir: ghc-9.2.0.20210422+              dlHash: fd2f4d0f6122f752aca396fe1a13e7d14d037dc45806bb0404a031eeeeb1994c+        A_ARM:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/9.2.1-alpha2/ghc-9.2.0.20210422-armv7-deb10-linux.tar.xz+              dlSubdir: ghc-9.2.0.20210422+              dlHash: dab7d7785d6ccafb130526b666669fc974ba5c90fc9aaf2024f9c65bcbd097d3+  Cabal:+    2.4.1.0:+      viTags:+        - old+      viChangeLog: https://downloads.haskell.org/~cabal/cabal-install-2.4.1.0/changelog+      viArch:+        A_64:+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-2.4.1.0/cabal-install-2.4.1.0-x86_64-alpine-linux-musl.tar.xz+              dlSubdir:+              dlHash: 720bef015f834a03deb7180be2952a44e7c2e6c8429137570404c3de4f46b984+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-2.4.1.0/cabal-install-2.4.1.0-x86_64-unknown-linux.tar.xz+              dlSubdir:+              dlHash: 6136c189ffccaa39916f9cb5788f757166444a2d0c473b987856a79ecbf0c714+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-2.4.1.0/cabal-install-2.4.1.0-x86_64-apple-darwin-sierra.tar.xz+              dlSubdir:+              dlHash: 56361cf4b0d920fe23174751fea1fb82a8e1ce522bd9706a3fbe47a72e458c9c+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-2.4.1.0/cabal-install-2.4.1.0-x86_64-portbld-freebsd.tar.xz+              dlSubdir:+              dlHash: 33b7d37ea0688c93436eac9ec139d9967687875aa1fa13f2bb73bf05a9a59a1d+        A_32:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-2.4.1.0/cabal-install-2.4.1.0-i386-unknown-linux.tar.xz+              dlSubdir:+              dlHash: b2da736cc27609442b10f77fc1a687aba603a7a33045b722dbf1a0066fade198+    3.0.0.0:+      viTags:+        - old+      viChangeLog: https://downloads.haskell.org/~cabal/cabal-install-3.0.0.0/changelog+      viArch:+        A_64:+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.0.0.0/cabal-install-3.0.0.0-x86_64-alpine-linux-musl.tar.xz+              dlHash: 2b7ea63601e11a0db2941b96e6a7036a48efc2a1ab3849d7dfce08b45f5daa58+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.0.0.0/cabal-install-3.0.0.0-x86_64-unknown-linux.tar.xz+              dlHash: ee911ba67a70756eedeac662955b896d7e89432a99372aa45d2c6e71fa95a5e4+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.0.0.0/cabal-install-3.0.0.0-x86_64-apple-darwin17.7.0.tar.xz+              dlHash: d4857e068560515e4cbb0e8ca124c370e07892f2a28804d87152834e5fe2b845+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.0.0.0/cabal-install-3.0.0.0-x86_64-portbld-freebsd.tar.xz+              dlHash: 2240842ab2ae7b955feb8b526aba1c7991248c803383107adf39990441294d2a+        A_32:+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.0.0.0/cabal-install-3.0.0.0-i386-alpine-linux-musl.tar.xz+              dlHash: ac018f061993d40bf146517e32629bcab274b4d9f5527b1c37a665ebdf3f5ac6+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.0.0.0/cabal-install-3.0.0.0-i386-unknown-linux.tar.xz+              dlHash: 6898ccd6e6dc0872999c06daaf61d546164e12f60a1880d09852c9f0c59c5cf6+    3.2.0.0:+      viTags:+      - old+      viChangeLog: https://downloads.haskell.org/~cabal/cabal-install-3.2.0.0/changelog+      viArch:+        A_64:+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.2.0.0/cabal-install-3.2.0.0-x86_64-alpine-linux-musl.tar.xz+              dlHash: 8bae37a1ce8b5f10440b5591fed734935e1411c1b765258325ffe268e2cc2042+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.2.0.0/cabal-install-3.2.0.0-x86_64-unknown-linux.tar.xz+              dlHash: 32d1f7cf1065c37cb0ef99a66adb405f409b9763f14c0926f5424ae408c738ac+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.2.0.0/cabal-install-3.2.0.0-x86_64-apple-darwin17.7.0.tar.xz+              dlHash: 9197c17d2ece0f934f5b33e323cfcaf486e4681952687bc3d249488ce3cbe0e9+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.2.0.0/cabal-install-3.2.0.0-x86_64-portbld-freebsd.tar.xz+              dlHash: f1e35151cca91541b0fb4bdb3ed18f3c348038eab751845ad19c11307d66c273+        A_32:+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.2.0.0/cabal-install-3.2.0.0-i386-alpine-linux-musl.tar.xz+              dlHash: c2a419dedf730987b60daf8d24e871d115a09ea608d740d7c61b36e3f5b9c830+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.2.0.0/cabal-install-3.2.0.0-i386-unknown-linux.tar.xz+              dlHash: 2b3ac28549916de5f3379241797eaf60e84b6c001f2abbe73d9fadbbaf768e93+    3.4.0.0:+      viTags:+      - Recommended+      - Latest+      viChangeLog: https://github.com/haskell/cabal/blob/master/release-notes/cabal-install-3.4.0.0.md+      viArch:+        A_64:+          Linux_Ubuntu:+            unknown_versioning: &cabal-3400-ubuntu+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.4.0.0/cabal-install-3.4.0.0-x86_64-ubuntu-16.04.tar.xz+              dlHash: cf28f9ffd763476aa2b1730d85cbf155d366fac541f78ee3951e8cb2d6de63e6+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.4.0.0/cabal-install-3.4.0.0-x86_64-alpine-3.11.6-static-noofd.tar.xz+              dlHash: c74073fe79110946182e522fcadc8dcabf07c87583e8cf7801ed4e0c327241f6+          Linux_UnknownLinux:+            unknown_versioning: *cabal-3400-ubuntu+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.4.0.0/cabal-install-3.4.0.0-x86_64-darwin-sierra.tar.xz+              dlHash: cb10be9a53e856aa2d852fd88fb6944f138783ffe0ea84d93c9a69244e34ea91+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.4.0.0/cabal-install-3.4.0.0-x86_64-freebsd-12.1-release.tar.xz+              dlHash: a1e2db664ec00e42a1e071a4181f6476f6e0bad321f1ddc0cf27831119f4c6d4+        A_32:+          Linux_UnknownLinux:+            unknown_versioning: &cabal-3400-32+              dlUri: https://downloads.haskell.org/~ghcup/unofficial-bindists/cabal/3.4.0.0/cabal-install-3.4.0.0-i386-unknown-linux.tar.xz+              dlHash: cc62a471e9e68a6a9933e54f75bf0cffae67a1d2220df1152ab887c38eb6bc8a+          Linux_Alpine:+            unknown_versioning: *cabal-3400-32+        A_ARM64:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.4.0.0/cabal-install-3.4.0.0-aarch64-ubuntu-18.04.tar.xz+              dlHash: 04d378347896dfdc3510b192b97489815cfa5d692f46e2758da0f789e682b8f0+        A_ARM:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghcup/unofficial-bindists/cabal/3.4.0.0/cabal-install-3.4.0.0-armv7-linux-bootstrapped.tar.xz+              dlHash: 16c0d1eaba24bed14f3e152970179a45d9f9bb5cc839b2c210ad06eb7d4826ed+  GHCup:+    0.1.16.2:+      viTags:+      - Recommended+      - Latest+      viChangeLog: https://gitlab.haskell.org/haskell/ghcup-hs/-/blob/master/CHANGELOG.md+      viSourceDL:+      viArch:+        A_64:+          Linux_UnknownLinux:+            unknown_versioning: &ghcup-64+              dlUri: https://downloads.haskell.org/~ghcup/0.1.16.2/x86_64-linux-ghcup-0.1.16.2+              dlHash: d5e43b95ce1d42263376e414f7eb7c5dd440271c7c6cd9bad446fdeff3823893+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghcup/0.1.16.2/x86_64-apple-darwin-ghcup-0.1.16.2+              dlHash: a334620ccce7705211b2142882dde544003e6030af4b91a44c890542a90f879f+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghcup/0.1.16.2/x86_64-portbld-freebsd-ghcup-0.1.16.2+              dlHash: 92359592a5694375e53b22628920086bf4bbf0faff5be018a0ed3e745a6426a9+          Linux_Alpine:+            unknown_versioning: *ghcup-64+        A_32:+          Linux_UnknownLinux:+            unknown_versioning: &ghcup-32+              dlUri: https://downloads.haskell.org/~ghcup/0.1.16.2/i386-linux-ghcup-0.1.16.2+              dlHash: 01968ca6decac7b6e8ba6e2c817870d3fa47289a6507e0c1ab563f7b6eec0e38+          Linux_Alpine:+            unknown_versioning: *ghcup-32+        A_ARM64:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghcup/0.1.16.2/aarch64-linux-ghcup-0.1.16.2+              dlHash: 0bdbfc724e0ddabb266156eea83c2c4e19c6ed79dd06db0c29b7d69df8d9fa8c+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghcup/0.1.16.2/aarch64-apple-darwin-ghcup-0.1.16.2+              dlHash: 8854e991a2ba1350abda59dab96ce50ae7729d1ce99399d67929ef31e90f1da5+        A_ARM:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghcup/0.1.16.2/armv7-linux-ghcup-0.1.16.2+              dlHash: 983ebb5b584bfa600704216a63f94b40d36a02573834e90ef1042c8472d9ad57+  HLS:+    1.1.0:+      viTags:+        - Recommended+        - Latest+      viChangeLog: https://github.com/haskell/haskell-language-server/blob/master/ChangeLog.md#110+      viPostInstall: "This is just the server part of your LSP configuration. Consult the README on how to configure HLS, your project and your LSP client in your editor: https://github.com/haskell/haskell-language-server/blob/master/README.md"+      viArch:+        A_64:+          Linux_UnknownLinux:+            unknown_versioning: &hls-64+              dlUri: https://github.com/haskell/haskell-language-server/releases/download/1.1.0/haskell-language-server-Linux-1.1.0.tar.gz+              dlHash: 0f0dadb0e9a08273658f565fd71c636801959b954be2737f38f2a1aac522208f+          Darwin:+            unknown_versioning:+              dlUri: https://github.com/haskell/haskell-language-server/releases/download/1.1.0/haskell-language-server-macOS-1.1.0.tar.gz+              dlHash: 4e89b192e2f49637d772e974f2c17b16da067ecd5912575eaa542551de97681b+          Linux_Alpine:+            unknown_versioning: *hls-64
+ data/metadata/ghcup-0.0.5.yaml view
@@ -0,0 +1,2235 @@+---+globalTools:+  ShimGen:+    dlUri: https://downloads.haskell.org/~ghcup/shimgen/shim-2.exe+    dlHash: 7c55e201f71860c5babea886007c8fa44b861abf50d1c07e5677eb0bda387a70+toolRequirements:+  GHC:+    unknown_version:+      Linux_Debian:+        unknown_versioning:+          distroPKGs:+          - build-essential+          - curl+          - libffi-dev+          - libffi6+          - libgmp-dev+          - libgmp10+          - libncurses-dev+          - libncurses5+          - libtinfo5+          notes: ''+      Linux_Ubuntu:+        unknown_versioning:+          distroPKGs:+          - build-essential+          - curl+          - libffi-dev+          - libffi6+          - libgmp-dev+          - libgmp10+          - libncurses-dev+          - libncurses5+          - libtinfo5+          notes: ''+        "( >= 20.04 && < 20.10 )":+          distroPKGs:+          - build-essential+          - curl+          - libffi-dev+          - libffi7+          - libgmp-dev+          - libgmp10+          - libncurses-dev+          - libncurses5+          - libtinfo5+          notes: ''+        "( >= 20.10 )":+          distroPKGs:+          - build-essential+          - curl+          - libffi-dev+          - libffi8ubuntu1+          - libgmp-dev+          - libgmp10+          - libncurses-dev+          - libncurses5+          - libtinfo5+          notes: ''+      Linux_CentOS:+        '( >= 7 && < 8 )':+          distroPKGs:+          - gcc+          - gcc-c+++          - gmp+          - gmp-devel+          - make+          - ncurses+          - xz+          - perl+          notes: ''+        unknown_versioning:+          distroPKGs:+          - gcc+          - gcc-c+++          - gmp+          - gmp-devel+          - make+          - ncurses+          - ncurses-compat-libs+          - xz+          - perl+          notes: ''+      Linux_Fedora:+        unknown_versioning:+          distroPKGs:+          - gcc+          - gcc-c+++          - gmp+          - gmp-devel+          - make+          - ncurses+          - ncurses-compat-libs+          - xz+          - perl+          notes: ''+      Linux_Alpine:+        unknown_versioning:+          distroPKGs:+          - binutils-gold+          - curl+          - gcc+          - g+++          - gmp-dev+          - ncurses-dev+          - libffi-dev+          - make+          - xz+          - tar+          - perl+          notes: ''+      Linux_UnknownLinux:+        unknown_versioning:+          distroPKGs: []+          notes: 'You need the following packages: curl g++ gcc gmp make ncurses realpath+            xz-utils. Consult your distro documentation on the exact names of those+            packages.'+      Darwin:+        unknown_versioning:+          distroPKGs: []+          notes: On OS X, in the course of running ghcup you will be given a dialog+            box to install the command line tools. Accept and the requirements will+            be installed for you. You will then need to run the command again.+      FreeBSD:+        unknown_versioning:+          distroPKGs:+          - curl+          - gcc+          - gmp+          - gmake+          - ncurses+          - perl5+          - libffi+          - libiconv+          notes: ''+      Windows:+        unknown_versioning:+          distroPKGs: []+          notes: On Windows, msys2 should already have been set up during the installation,+            so most users should just press ENTER.+            If you are installing manually, make sure to have a working mingw64 toolchain and+            shell.+ghcupDownloads:+  GHC:+    7.10.3:+      viTags:+      - base-4.8.2.0+      - old+      viChangeLog: https://downloads.haskell.org/~ghc/7.10.3/docs/html/users_guide/release-7-10-1.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-src.tar.xz+        dlSubdir: ghc-7.10.3+        dlHash: cf90cedce1c28fd0e2b9e72fe8a938756668d18ea1fcc884a19f698658ac4fef+      viPostRemove: &ghc-post-remove "After removing GHC you might also want to clean up your cabal store at: ~/.cabal/store/ghc-<ghcver>"+      viPostInstall: "GHC-7.10.3 may give linking errors on most modern distros. You may have to pass '--ghc-option=-optc-no-pie --ghc-option=-optl-no-pie' to cabal build/install. Also see https://gitlab.haskell.org/ghc/ghc/-/issues/18763"+      viArch:+        A_64:+          Linux_Debian:+            unknown_versioning: &ghc-7103-64-deb8+              dlUri: https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-x86_64-deb8-linux.tar.bz2+              dlSubdir: ghc-7.10.3+              dlHash: 01cfbad8dff1e8b34a5fdca8caeaf843b56e36af919e29cd68870d2588563db5+          Linux_Ubuntu:+            unknown_versioning: *ghc-7103-64-deb8+          Linux_Mint:+            unknown_versioning: *ghc-7103-64-deb8+          Linux_CentOS:+            unknown_versioning: &ghc-7103-64-centos+              dlUri: https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-x86_64-centos67-linux.tar.bz2+              dlSubdir: ghc-7.10.3+              dlHash: a8957f7a2fd81720c5d3dc403571d77d31115ff5f42edb2917c36d8e714220d4+          Linux_AmazonLinux:+            unknown_versioning: *ghc-7103-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-7103-64-deb8+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-x86_64-apple-darwin.tar.bz2+              dlSubdir: ghc-7.10.3+              dlHash: 80893e367e8318105f7db2064adf202e3d96b1f014e792b73e92f2cacf0b757a+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-x86_64-portbld-freebsd.tar.bz2+              dlSubdir: ghc-7.10.3+              dlHash: 2aa396edd2bb651f4bc7eef7a396913ea24923de5aafdc76df6295333e487e48+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-7.10.3+              dlHash: 63e1689fc9e2809ae4d7f422b4dc810052e54c9aa2afd08746e234180e711dde+        A_32:+          Linux_Debian:+            unknown_versioning: &ghc-7103-32-deb8+              dlUri: https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-i386-deb8-linux.tar.bz2+              dlSubdir: ghc-7.10.3+              dlHash: d2ccf072457fb100503f6f5430a1e3589ca525a97424263d036b0550bc277f0c+          Linux_Ubuntu:+            unknown_versioning: *ghc-7103-32-deb8+          Linux_Mint:+            unknown_versioning: *ghc-7103-32-deb8+          Linux_CentOS:+            unknown_versioning: &ghc-7103-32-centos+              dlUri: https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-i386-centos67-linux.tar.bz2+              dlSubdir: ghc-7.10.3+              dlHash: c50aa20275e8d1ba9148f380eb7598bc148143281fc17c9acd38ea7b325852bd+          Linux_AmazonLinux:+            unknown_versioning: *ghc-7103-32-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-7103-32-deb8+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-i386-portbld-freebsd.tar.bz2+              dlSubdir: ghc-7.10.3+              dlHash: 3dde05577c6f94dcb0ba201ebd53ab88553bbc9a3aa8e72237162ed7a9d588a3+    8.0.2:+      viTags:+      - base-4.9.1.0+      - old+      viChangeLog: https://downloads.haskell.org/~ghc/8.0.2/docs/html/users_guide/8.0.1-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.0.2/ghc-8.0.2-src.tar.xz+        dlSubdir: ghc-8.0.2+        dlHash: 11625453e1d0686b3fa6739988f70ecac836cadc30b9f0c8b49ef9091d6118b1+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 7 && < 8 )':+              dlUri: https://downloads.haskell.org/~ghc/8.0.2/ghc-8.0.2-x86_64-deb7-linux.tar.xz+              dlSubdir: ghc-8.0.2+              dlHash: b2f5c304b57ac5840a0d2ef763a3c6fa858c70840f749cfad12ed227da973c0a+            unknown_versioning: &ghc-802-64-deb8+              dlUri: https://downloads.haskell.org/~ghc/8.0.2/ghc-8.0.2-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.0.2+              dlHash: 5ee68290db00ca0b79d57bc3a5bdce470de9ce9da0b098a7ce6c504605856c8f+          Linux_Ubuntu:+            unknown_versioning: *ghc-802-64-deb8+          Linux_Mint:+            unknown_versioning: *ghc-802-64-deb8+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.0.2/ghc-8.0.2-x86_64-alpine-linux.tar.xz+              dlSubdir: ghc-8.0.2+              dlHash: 517783b660a27ebf95b2568d47292fd633d5f9a4de4c80ad1ccf05e1b9d7313f+          Linux_UnknownLinux:+            unknown_versioning: *ghc-802-64-deb8+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.0.2/ghc-8.0.2-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.0.2+              dlHash: ff50a2df9f002f33b9f09717ebf5ec5a47906b9b65cc57b1f9849f8b2e06788d+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.0.2/ghc-8.0.2-x86_64-portbld-freebsd.tar.xz+              dlSubdir: ghc-8.0.2+              dlHash: b36a20e5cae24d70bbb6116ae486f21811e9384f15d3892d260f02fba3e3bb8c+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.0.2/ghc-8.0.2-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-8.0.2+              dlHash: 8c42c1f4af995205b9816a1e97e2752fe758544c1f5fe77958cdcd319c9c2d53+        A_32:+          Linux_Debian:+            '( >= 7 && < 8 )':+              dlUri: https://downloads.haskell.org/~ghc/8.0.2/ghc-8.0.2-i386-deb7-linux.tar.xz+              dlSubdir: ghc-8.0.2+              dlHash: 07ead3a49f8c9df4b429e7a2f96f6f31bcab8d3ff8277a9aed0201d13ddad448+            unknown_versioning: &ghc-802-32-deb8+              dlUri: https://downloads.haskell.org/~ghc/8.0.2/ghc-8.0.2-i386-deb8-linux.tar.xz+              dlSubdir: ghc-8.0.2+              dlHash: 818621342a2161b8afcc995a0765816bb40aefbfa1db2c8a7d59c04d8b18228a+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.0.2/ghc-8.0.2-i386-alpine-linux.tar.xz+              dlSubdir: ghc-8.0.2+              dlHash: b4cd12a1048b2fff2f23c9eec0dd3a1174d54d017f8d79ec79af4534118e6881+          Linux_UnknownLinux:+            unknown_versioning: *ghc-802-32-deb8+    8.2.2:+      viTags:+      - base-4.10.1.0+      - old+      viChangeLog: https://downloads.haskell.org/~ghc/8.2.2/docs/html/users_guide/8.2.2-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-src.tar.xz+        dlSubdir: ghc-8.2.2+        dlHash: bb8ec3634aa132d09faa270bbd604b82dfa61f04855655af6f9d14a9eedc05fc+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 7 && < 8 )': &ghc-822-64-deb7+              dlUri: https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-x86_64-deb7-linux.tar.xz+              dlSubdir: ghc-8.2.2+              dlHash: cd7afbca54edf9890da9f432c63366556246c85c1198e40c99df5af01c555834+            unknown_versioning: &ghc-822-64-deb8+              dlUri: https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.2.2+              dlHash: 48e205c62b9dc1ccf6739a4bc15a71e56dde2f891a9d786a1b115f0286111b2a+          Linux_Ubuntu:+            unknown_versioning: *ghc-822-64-deb8+          Linux_Mint:+            unknown_versioning: *ghc-822-64-deb8+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.2.2/ghc-8.2.2-x86_64-alpine-linux.tar.xz+              dlSubdir: ghc-8.2.2+              dlHash: adcf3a320a3c402aba07ae9586990dc3c0b550e96aeffb1b9e194313d3ba716d+          Linux_UnknownLinux:+            unknown_versioning: *ghc-822-64-deb7+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.2.2+              dlHash: f90fcf62f7e0936a6dfc3601cf663729bfe9bbf85097d2d75f0a16f8c2e95c27+          FreeBSD:+            '( >= 10 && < 11 )':+              dlUri: https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-x86_64-portbld10_3-freebsd.tar.xz+              dlSubdir: ghc-8.2.2+              dlHash: 9e99aaeaec4b2c6d660d80246c0d4dbd41fda88f1eb7a908b29dc8fa8d663949+            '( >= 11 && < 12 )': &ghc-822-64-fbsd11+              dlUri: https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-x86_64-portbld11-freebsd.tar.xz+              dlSubdir: ghc-8.2.2+              dlHash: cd351c704b92b9af23994024df07de8ca7090ea7675d5c8b14b2be857a46d804+            unknown_versioning: *ghc-822-64-fbsd11+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-8.2.2+              dlHash: 1e033df2092aa546e763e7be63167720b32df64f76673ea1ce7ae7c9f564b223+        A_32:+          Linux_Debian:+            '( >= 7 && < 8 )':+              dlUri: https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-i386-deb7-linux.tar.xz+              dlSubdir: ghc-8.2.2+              dlHash: cd18766b1a9b74fc6c90003a719ecab158f281f9a755d8b1bd3fd764ba6947b5+            unknown_versioning: &ghc-822-32-deb8+              dlUri: https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-i386-deb8-linux.tar.xz+              dlSubdir: ghc-8.2.2+              dlHash: 9e67d72d76482e0ba91c718e727b00386a1a12a32ed719714976dc56ca8c8223+          Linux_Ubuntu:+            unknown_versioning: *ghc-822-32-deb8+          Linux_Mint:+            unknown_versioning: *ghc-822-32-deb8+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.2.2/ghc-8.2.2-i386-alpine-linux.tar.xz+              dlSubdir: ghc-8.2.2+              dlHash: 467534c32552cfd318753112dbc70af003693aad4b0081f2a07e61f5b5ea2c22+          Linux_UnknownLinux:+            unknown_versioning: *ghc-822-32-deb8+    8.4.1:+      viTags:+      - base-4.11.0.0+      - old+      viChangeLog: https://downloads.haskell.org/~ghc/8.4.1/docs/html/users_guide/8.4.1-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.4.1/ghc-8.4.1-src.tar.xz+        dlSubdir: ghc-8.4.1+        dlHash: 39ae2f25192408f355693e5a3c8b6ff613ddb7c4da998fdf26210143a61839d2+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.4.1/ghc-8.4.1-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.4.1+              dlHash: 427c77a934b30c3f1de992c38c072afb4323fe6fb30dbac919ca8cb6ae98fbd9+          Linux_Ubuntu:+            unknown_versioning: &ghc-841-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.4.1/ghc-8.4.1-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.4.1+              dlHash: 89328a013e64b9b56825a9071fea5616ddd623d37fd41e8fb913dfebc609e7ea+          Linux_Mint:+            unknown_versioning: *ghc-841-64-fedora+          Linux_Fedora:+            unknown_versioning: *ghc-841-64-fedora+          Linux_UnknownLinux:+            unknown_versioning: *ghc-841-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.4.1/ghc-8.4.1-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.4.1+              dlHash: d774e39f3a0105843efd06709b214ee332c30203e6c5902dd6ed45e36285f9b7+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.4.1/ghc-8.4.1-x86_64-portbld11-freebsd.tar.xz+              dlSubdir: ghc-8.4.1+              dlHash: e748daec098445c6190090fe32bb2817a1140553be5acd2188e1af05ad24e5aa+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.4.1/ghc-8.4.1-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-8.4.1+              dlHash: 328b013fc651d34e075019107e58bb6c8a578f0155cf3ad4557e6f2661b03131+        A_32:+          Linux_Debian:+            unknown_versioning: &ghc-841-32-deb8+              dlUri: https://downloads.haskell.org/~ghc/8.4.1/ghc-8.4.1-i386-deb8-linux.tar.xz+              dlSubdir: ghc-8.4.1+              dlHash: c56c589c76c7ddcb77cdbef885a811761e669d3e76868b723d5be56dedcd4f69+          Linux_Ubuntu:+            unknown_versioning: *ghc-841-32-deb8+          Linux_Mint:+            unknown_versioning: *ghc-841-32-deb8+          Linux_UnknownLinux:+            unknown_versioning: *ghc-841-32-deb8+    8.4.2:+      viTags:+      - base-4.11.1.0+      - old+      viChangeLog: https://downloads.haskell.org/~ghc/8.4.2/docs/html/users_guide/8.4.2-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.4.2/ghc-8.4.2-src.tar.xz+        dlSubdir: ghc-8.4.2+        dlHash: 01cc32f24a06bf3b2428351b6d7fec791e82d042426d29ad9e5a245b35f0047b+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 8 && < 9 )':+              dlUri: https://downloads.haskell.org/~ghc/8.4.2/ghc-8.4.2-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.4.2+              dlHash: 246f66eb56f4ad0f1c7755502cfc8f9972f2d067dede17e151f6f479c1f76fbd+            unknown_versioning: &ghc-842-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.4.2/ghc-8.4.2-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.4.2+              dlHash: 3f4f5bbd2cdab4e7015ada9196d8d9b3a1ad274293cef011f85c46854596cb57+          Linux_Ubuntu:+            unknown_versioning: &ghc-842-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.4.2/ghc-8.4.2-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.4.2+              dlHash: d057b5c833596dbe4ae5d0dc2994f6cc5d0f4c2a21ea1d7900821d165fd4e846+            '( >= 16 && < 19 )': *ghc-842-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-842-64-fedora+          Linux_Fedora:+            unknown_versioning: *ghc-842-64-fedora+          Linux_UnknownLinux:+            unknown_versioning: *ghc-842-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.4.2/ghc-8.4.2-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.4.2+              dlHash: 87469222042b9ac23f9db216a8d4e5107297bdbbb99df71eb4d9e7208455def2+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.4.2/ghc-8.4.2-x86_64-portbld-freebsd.tar.xz+              dlSubdir: ghc-8.4.2+              dlHash: e9ed417fdf94c2ff2c6e344ed16f332bf6b591511f6442c0d9ea94854882b66c+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.4.2/ghc-8.4.2-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-8.4.2+              dlHash: 797634aa9812fc6b2084a24ddb4fde44fa83a2f59daea82e0af81ca3dd323fde+        A_32:+          Linux_Debian:+            unknown_versioning: &ghc-842-32-deb8+              dlUri: https://downloads.haskell.org/~ghc/8.4.2/ghc-8.4.2-i386-deb8-linux.tar.xz+              dlSubdir: ghc-8.4.2+              dlHash: 2d849c30b4c1eac25dc74333501920921e22fa483153f404993808bbda93df05+          Linux_Ubuntu:+            unknown_versioning: *ghc-842-32-deb8+          Linux_Mint:+            unknown_versioning: *ghc-842-32-deb8+          Linux_UnknownLinux:+            unknown_versioning: *ghc-842-32-deb8+    8.4.3:+      viTags:+      - base-4.11.1.0+      - old+      viChangeLog: https://downloads.haskell.org/~ghc/8.4.3/docs/html/users_guide/8.4.3-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.4.3/ghc-8.4.3-src.tar.xz+        dlSubdir: ghc-8.4.3+        dlHash: ae47afda985830de8811243255aa3744dfb9207cb980af74393298b2b62160d6+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 8 && < 9 )':+              dlUri: https://downloads.haskell.org/~ghc/8.4.3/ghc-8.4.3-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.4.3+              dlHash: 30a402c6d4754a6c020e0547f19ae3ac42e907e35349aa932d347f73e421a8e2+            unknown_versioning: &ghc-843-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.4.3/ghc-8.4.3-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.4.3+              dlHash: 2e4f53afb872ad9c640f31aea283b3ff4c5028b65808a1920739900aef7d15c9+          Linux_Ubuntu:+            unknown_versioning: &ghc-843-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.4.3/ghc-8.4.3-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.4.3+              dlHash: 269e7a4d3f336491b88409a020998122b30a3a729af78d33be86d3b3f8000c3e+            '( >= 16 && < 19 )': *ghc-843-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-843-64-fedora+          Linux_Fedora:+            unknown_versioning: *ghc-843-64-fedora+          Linux_UnknownLinux:+            unknown_versioning: *ghc-843-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.4.3/ghc-8.4.3-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.4.3+              dlHash: af0b455f6c46b9802b4b48dad996619cfa27cc6e2bf2ce5532387b4a8c00aa64+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.4.3/ghc-8.4.3-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-8.4.3+              dlHash: 8a83cfbf9ae84de0443c39c93b931693bdf2a6d4bf163ffb41855f80f4bf883e+        A_32:+          Linux_Debian:+            unknown_versioning: &ghc-843-32-deb8+              dlUri: https://downloads.haskell.org/~ghc/8.4.3/ghc-8.4.3-i386-deb8-linux.tar.xz+              dlSubdir: ghc-8.4.3+              dlHash: f5763983a26dedd88b65a0b17267359a3981b83a642569b26334423f684f8b8c+          Linux_Ubuntu:+            unknown_versioning: *ghc-843-32-deb8+          Linux_Mint:+            unknown_versioning: *ghc-843-32-deb8+          Linux_UnknownLinux:+            unknown_versioning: *ghc-843-32-deb8+    8.4.4:+      viTags:+      - base-4.11.1.0+      viChangeLog: https://downloads.haskell.org/~ghc/8.4.4/docs/html/users_guide/8.4.4-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-src.tar.xz+        dlSubdir: ghc-8.4.4+        dlHash: 11117735a58e507c481c09f3f39ae5a314e9fbf49fc3109528f99ea7959004b2+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 8 && < 9 )':+              dlUri: https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.4.4+              dlHash: 4c2a8857f76b7f3e34ecba0b51015d5cb8b767fe5377a7ec477abde10705ab1a+            unknown_versioning: &ghc-844-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.4.4+              dlHash: 47c80a32d8f02838a2401414c94ba260d1fe82b7d090479994522242c767cc83+          Linux_Ubuntu:+            unknown_versioning: &ghc-844-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.4.4+              dlHash: 8ab2befddc14d1434d0aad0c5d3c7e0c2b78ff84caa3429fa62527bfc6b86095+            '( >= 16 && < 19 )': *ghc-844-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-844-64-fedora+          Linux_Fedora:+            unknown_versioning: *ghc-844-64-fedora+          Linux_CentOS:+            unknown_versioning: &ghc-844-64-centos+              dlUri: https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-x86_64-centos70-linux.tar.xz+              dlSubdir: ghc-8.4.4+              dlHash: 83a96650f5a92b1e4d7651d256d6438624342d40e780e68125033435a54cd674+          Linux_RedHat:+            unknown_versioning: *ghc-844-64-centos+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.4.4/ghc-8.4.4-x86_64-alpine-linux.tar.xz+              dlSubdir: ghc-8.4.4+              dlHash: 336affff8314d3dc5e85d9c09015ae2ba8a7658b459c8c8ae77ecaa551a56ae7+          Linux_AmazonLinux:+            unknown_versioning: *ghc-844-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-844-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.4.4+              dlHash: 28dc89ebd231335337c656f4c5ead2ae2a1acc166aafe74a14f084393c5ef03a+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-x86_64-portbld-freebsd11.tar.xz+              dlSubdir: ghc-8.4.4+              dlHash: 44fbd142d1c355d6110595c59c760e2c73866ff9259ec85ebf814edb244d1940+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-8.4.4+              dlHash: da29dbb0f1199611c7d5bb7b0dd6a7426ca98f67dfd6da1526b033cd3830dc05+        A_32:+          Linux_Debian:+            unknown_versioning: &ghc-844-32-deb8+              dlUri: https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-i386-deb8-linux.tar.xz+              dlSubdir: ghc-8.4.4+              dlHash: 678bafaabea6af70ba71ccf0210bb437f9f5591ec28ac1cbbbd5f7aa6894e450+          Linux_Ubuntu:+            unknown_versioning: *ghc-844-32-deb8+          Linux_Mint:+            unknown_versioning: *ghc-844-32-deb8+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.4.4/ghc-8.4.4-i386-alpine-linux.tar.xz+              dlSubdir: ghc-8.4.4+              dlHash: 892888d388ef5c9cadf5cfba1146d62237c25b9b066fb62fee940b2b285fd308+          Linux_UnknownLinux:+            unknown_versioning: *ghc-844-32-deb8+    8.6.1:+      viTags:+      - base-4.12.0.0+      - old+      viChangeLog: https://downloads.haskell.org/~ghc/8.6.1/docs/html/users_guide/8.6.1-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.6.1/ghc-8.6.1-src.tar.xz+        dlSubdir: ghc-8.6.1+        dlHash: 2c25c26d1e5c47c7cbb2a1d8e6456524033e7a71409184dd3125e3fc5a3c7036+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 8 && < 9 )':+              dlUri: https://downloads.haskell.org/~ghc/8.6.1/ghc-8.6.1-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.6.1+              dlHash: 6d8784401b7dd80c90fa17306ec0539920e3987399a2c7ef247989e53197dc42+            unknown_versioning: &ghc-861-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.6.1/ghc-8.6.1-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.6.1+              dlHash: 97d44f303868d74e4d13a2e99c82ffce3d25fd54c704675e5a1939e0d824dbf0+          Linux_Ubuntu:+            unknown_versioning: &ghc-861-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.6.1/ghc-8.6.1-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.6.1+              dlHash: da903fbcf11ee6c977a8b7dac3f04dbc098d674def587880b6624b8f32588beb+            '( >= 16 && < 19 )': *ghc-861-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-861-64-fedora+          Linux_Fedora:+            unknown_versioning: *ghc-861-64-fedora+          Linux_UnknownLinux:+            unknown_versioning: *ghc-861-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.6.1/ghc-8.6.1-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.6.1+              dlHash: 9692cdfd202b0e039ea0c3dde5dbf653736c836ca1df46504b179b572100808c+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.6.1/ghc-8.6.1-x86_64-portbld-freebsd.tar.xz+              dlSubdir: ghc-8.6.1+              dlHash: 51403b054a3a649039ac988e1d1112561f96750bfced63df864091a3fab36f08+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.6.1/ghc-8.6.1-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-8.6.1+              dlHash: 7316d9cb5e486460476754f872c7bac30ee2082e42f46da4342f872d10b88099+        A_32:+          Linux_Debian:+            unknown_versioning: &ghc-861-32-deb8+              dlUri: https://downloads.haskell.org/~ghc/8.6.1/ghc-8.6.1-i386-deb8-linux.tar.xz+              dlSubdir: ghc-8.6.1+              dlHash: 83573af96e3dec8f67c1a844512f92cbf7d51ae7ceca53d948fc2a3300abd05c+          Linux_Ubuntu:+            unknown_versioning: *ghc-861-32-deb8+          Linux_Mint:+            unknown_versioning: *ghc-861-32-deb8+          Linux_UnknownLinux:+            unknown_versioning: *ghc-861-32-deb8+    8.6.2:+      viTags:+      - base-4.12.0.0+      - old+      viChangeLog: https://downloads.haskell.org/~ghc/8.6.2/docs/html/users_guide/8.6.2-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.6.2/ghc-8.6.2-src.tar.xz+        dlSubdir: ghc-8.6.2+        dlHash: caaa819d21280ecde90a4773143dee188711e9ff175a27cfbaee56eb851d76d5+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            unknown_versioning: &ghc-862-64-deb8+              dlUri: https://downloads.haskell.org/~ghc/8.6.2/ghc-8.6.2-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.6.2+              dlHash: 13f96e8b83bb5bb60f955786ff9085744c24927a33be8a17773f84c7c248533a+          Linux_Ubuntu:+            unknown_versioning: &ghc-862-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.6.2/ghc-8.6.2-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.6.2+              dlHash: 702aa5dfa1639c37953ceb7571a5057d9fb0562aecb197b277953a037d78047d+            '( >= 16 && < 19 )': *ghc-862-64-deb8+          Linux_Mint:+            unknown_versioning: *ghc-862-64-fedora+          Linux_Fedora:+            unknown_versioning: *ghc-862-64-fedora+          Linux_UnknownLinux:+            unknown_versioning: *ghc-862-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.6.2/ghc-8.6.2-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.6.2+              dlHash: 8ec46a25872226dd7e5cf7271e3f3450c05f32144b96e6b9cb44cc4079db50dc+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.6.2/ghc-8.6.2-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-8.6.2+              dlHash: 9a398e133cab09ff2610834337355d4e26c35e0665403fb9ff8db79315f74d3d+        A_32:+          Linux_Debian:+            unknown_versioning: &ghc-862-32-deb8+              dlUri: https://downloads.haskell.org/~ghc/8.6.2/ghc-8.6.2-i386-deb8-linux.tar.xz+              dlSubdir: ghc-8.6.2+              dlHash: a288026d9ef22f7ac387edab6b29ef7dcb3b28945c8ea532a15c1fa35d4733ed+          Linux_Ubuntu:+            unknown_versioning: *ghc-862-32-deb8+          Linux_Mint:+            unknown_versioning: *ghc-862-32-deb8+          Linux_UnknownLinux:+            unknown_versioning: *ghc-862-32-deb8+    8.6.3:+      viTags:+      - base-4.12.0.0+      - old+      viChangeLog: https://downloads.haskell.org/~ghc/8.6.3/docs/html/users_guide/8.6.3-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.6.3/ghc-8.6.3-src.tar.xz+        dlSubdir: ghc-8.6.3+        dlHash: 9f9e37b7971935d88ba80426c36af14b1e0b3ec1d9c860f44a4391771bc07f23+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 8 && < 9 )':+              dlUri: https://downloads.haskell.org/~ghc/8.6.3/ghc-8.6.3-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.6.3+              dlHash: 291ca565374f4d51cc311488581f3279d3167a064fabfd4a6722fe2bd4532fd5+            unknown_versioning: &ghc-863-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.6.3/ghc-8.6.3-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.6.3+              dlHash: e7954c8ed9b422a09c6ab737e4a0865a2725d034ba0e272bd5c70db910797f99+          Linux_Ubuntu:+            unknown_versioning: &ghc-863-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.6.3/ghc-8.6.3-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.6.3+              dlHash: 52ae92f4e8bb2ac0b7847287ea3da37081f5f7bf8bbb7c78ac35fde537d1a89f+            '( >= 16 && < 19 )': *ghc-863-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-863-64-fedora+          Linux_Fedora:+            unknown_versioning: *ghc-863-64-fedora+          Linux_CentOS:+            unknown_versioning: &ghc-863-64-centos+              dlUri: https://downloads.haskell.org/~ghc/8.6.3/ghc-8.6.3-x86_64-centos7-linux.tar.xz+              dlSubdir: ghc-8.6.3+              dlHash: 355bd85c69933c31bbe99b4269ce719acfd0aad0b45e359ac39b9bb13996acc6+          Linux_RedHat:+            unknown_versioning: *ghc-863-64-centos+          Linux_AmazonLinux:+            unknown_versioning: *ghc-863-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-863-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.6.3/ghc-8.6.3-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.6.3+              dlHash: 79d069a1a7d74cfdd7ac2a2711c45d3ddc6265b988a0cefa342714b24f997fc1+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.6.3/ghc-8.6.3-x86_64-portbld-freebsd.tar.xz+              dlSubdir: ghc-8.6.3+              dlHash: bc2419fa180f8a7808c49775987866435995df9bdd9ce08bcd38352d63ba6031+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.6.3/ghc-8.6.3-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-8.6.3+              dlHash: 2fec383904e5fa79413e9afd328faf9bc700006c8c3d4bcdd8d4f2ccf0f7fa2a+        A_32:+          Linux_Debian:+            unknown_versioning: &ghc-863-32-deb8+              dlUri: https://downloads.haskell.org/~ghc/8.6.3/ghc-8.6.3-i386-deb8-linux.tar.xz+              dlSubdir: ghc-8.6.3+              dlHash: b57070ba8c70b1333a3e47ce124baf791be39c20a592954772532fd6dd51882f+          Linux_Ubuntu:+            unknown_versioning: *ghc-863-32-deb8+          Linux_Mint:+            unknown_versioning: *ghc-863-32-deb8+          Linux_UnknownLinux:+            unknown_versioning: *ghc-863-32-deb8+    8.6.4:+      viTags:+      - base-4.12.0.0+      - old+      viChangeLog: https://downloads.haskell.org/~ghc/8.6.4/docs/html/users_guide/8.6.4-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.6.4/ghc-8.6.4-src.tar.xz+        dlSubdir: ghc-8.6.4+        dlHash: 5b5d07e4463203a433c3ed3df461ba6cce11b6d2b9b264db31f3429075d0303a+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 8 && < 9 )':+              dlUri: https://downloads.haskell.org/~ghc/8.6.4/ghc-8.6.4-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.6.4+              dlHash: 34ef5fc8ddf2fc32a027180bea5b1c8a81ea840c87faace2977a572188d4b42d+            unknown_versioning: &ghc-864-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.6.4/ghc-8.6.4-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.6.4+              dlHash: ef74222ef3c01c3fc5b926f67e8b4ef612fe8efa40ac937317cff9b0eed8d863+          Linux_Ubuntu:+            unknown_versioning: &ghc-864-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.6.4/ghc-8.6.4-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.6.4+              dlHash: e0b1ada7a679d6c35f9d7a1192ed35fde054f3650bb0bd2570d103729ad3b846+            '( >= 16 && < 19 )': *ghc-864-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-864-64-fedora+          Linux_Fedora:+            unknown_versioning: *ghc-864-64-fedora+          Linux_UnknownLinux:+            unknown_versioning: *ghc-864-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.6.4/ghc-8.6.4-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.6.4+              dlHash: cccb58f142fe41b601d73690809f6089f7715b6a50a09aa3d0104176ab4db09e+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.6.4/ghc-8.6.4-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-8.6.4+              dlHash: e8d021b7a90772fc559862079da20538498d991956d7557b468ca19ddda22a08+        A_32:+          Linux_Debian:+            unknown_versioning: &ghc-864-32-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.6.4/ghc-8.6.4-i386-deb9-linux.tar.xz+              dlSubdir: ghc-8.6.4+              dlHash: 5e2ce88f4d13d23ac37e278e0c7b51c801008931359b9fa8a631d804d2da552c+          Linux_Ubuntu:+            unknown_versioning: *ghc-864-32-deb9+          Linux_Mint:+            unknown_versioning: *ghc-864-32-deb9+          Linux_UnknownLinux:+            unknown_versioning: *ghc-864-32-deb9+    8.6.5:+      viTags:+      - base-4.12.0.0+      viChangeLog: https://downloads.haskell.org/~ghc/8.6.5/docs/html/users_guide/8.6.5-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-src.tar.xz+        dlSubdir: ghc-8.6.5+        dlHash: 4d4aa1e96f4001b934ac6193ab09af5d6172f41f5a5d39d8e43393b9aafee361+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 8 && < 9 )':+              dlUri: https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.6.5+              dlHash: c419fd0aa9065fe4d2eb9a248e323860c696ddf3859749ca96a84938aee49107+            unknown_versioning: &ghc-865-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.6.5+              dlHash: bc75f5601a9f41d58b2ba161b9e28fad52143a7229060f1e084168d9b2e914df+          Linux_Ubuntu:+            unknown_versioning: &ghc-865-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.6.5+              dlHash: cf78b53eaf336083e7a05f4a3000afbae4abe5bbc77ef80cc40e09d04ac5b4a1+            '( >= 16 && < 19 )': *ghc-865-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-865-64-fedora+          Linux_Fedora:+            unknown_versioning: *ghc-865-64-fedora+          Linux_CentOS:+            unknown_versioning: &ghc-865-64-centos+              dlUri: https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-x86_64-centos7-linux.tar.xz+              dlSubdir: ghc-8.6.5+              dlHash: 80ab566f4411299f9e5922d60749ca80f989d697db19e03ed875619d699f0edf+          Linux_RedHat:+            unknown_versioning: *ghc-865-64-centos+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.6.5/ghc-8.6.5-x86_64-alpine-linux.tar.xz+              dlSubdir: ghc-8.6.5+              dlHash: b9d3ed7f7aa24ef2d58bb579252289caa0b8877adee3685e3af2fb73d440afdc+          Linux_AmazonLinux:+            unknown_versioning: *ghc-865-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-865-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.6.5+              dlHash: dfc1bdb1d303a87a8552aa17f5b080e61351f2823c2b99071ec23d0837422169+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.6.5/ghc-8.6.5-x86_64-portbld-freebsd.tar.xz+              dlSubdir: ghc-8.6.5+              dlHash: 83a3059a630d40a98e26cb5b520354e12094a96e36ba2f5ab002dad94cf2fb37+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-8.6.5+              dlHash: 457024c6ea43bdce340af428d86319931f267089398b859b00efdfe2fd4ce93f+        A_32:+          Linux_Debian:+            unknown_versioning: &ghc-865-32-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-i386-deb9-linux.tar.xz+              dlSubdir: ghc-8.6.5+              dlHash: 1cddb907393a669342b1a922dd16d505d9d93d50bd9433a54a8162f8701250dc+          Linux_Ubuntu:+            unknown_versioning: *ghc-865-32-deb9+          Linux_Mint:+            unknown_versioning: *ghc-865-32-deb9+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.6.5/ghc-8.6.5-i386-alpine-linux.tar.xz+              dlSubdir: ghc-8.6.5+              dlHash: 3737837550d9b177acfe150e3a3cd4545427ded020487c2ed5194d7b8f116349+          Linux_UnknownLinux:+            unknown_versioning: *ghc-865-32-deb9+        A_ARM64:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-aarch64-ubuntu18.04-linux.tar.xz+              dlSubdir: ghc-8.6.5+              dlHash: 1852589037e4b2805ab517bc430e25a3125c4a118a1674ffefbb443394a0c786+    8.8.1:+      viTags:+      - base-4.13.0.0+      - old+      viChangeLog: https://downloads.haskell.org/~ghc/8.8.1/docs/html/users_guide/8.8.1-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.8.1/ghc-8.8.1-src.tar.xz+        dlSubdir: ghc-8.8.1+        dlHash: 908a83d9b814da74585de9d39687189e6260ec3848131f9d9236cab8a123721a+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 8 && < 9 )':+              dlUri: https://downloads.haskell.org/~ghc/8.8.1/ghc-8.8.1-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.8.1+              dlHash: fd96eb851971fbc3332bf2fa7821732cfa8b37e5a076a69f6a06f83f0ea7ccc5+            unknown_versioning: &ghc-881-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.8.1/ghc-8.8.1-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.8.1+              dlHash: 620fd560535b63cac5f8c97354ccddf93fa940cca78e2d19f6f98b7e67c6a723+          Linux_Ubuntu:+            unknown_versioning: &ghc-881-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.8.1/ghc-8.8.1-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.8.1+              dlHash: 851a78df620bc056c34b252c97040d5755e294993fa8afa5429708b5229204d6+            '( >= 16 && < 19 )': *ghc-881-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-881-64-fedora+          Linux_Fedora:+            unknown_versioning: *ghc-881-64-fedora+          Linux_CentOS:+            unknown_versioning: &ghc-881-64-centos+              dlUri: https://downloads.haskell.org/~ghc/8.8.1/ghc-8.8.1-x86_64-centos7-linux.tar.xz+              dlSubdir: ghc-8.8.1+              dlHash: 6cdd34e4dbaeb801e805811f91cf43a2d5f64b22f884718ffbd3542a2f4dd14f+          Linux_RedHat:+            unknown_versioning: *ghc-881-64-centos+          Linux_AmazonLinux:+            unknown_versioning: *ghc-881-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-881-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.8.1/ghc-8.8.1-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.8.1+              dlHash: 38c8917b47c31bedf58c9305dfca3abe198d8d35570366f0773c4e2948bd8abe+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.8.1/ghc-8.8.1-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-8.8.1+              dlHash: 29e56e6af38017a5a76b2b6995a39d3988fa58131e4b55b62dd317ba7186ac9b+        A_32:+          Linux_Debian:+            unknown_versioning: &ghc-881-32-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.8.1/ghc-8.8.1-i386-deb9-linux.tar.xz+              dlSubdir: ghc-8.8.1+              dlHash: 3d3bb75aff2dd79ec87ace10483368681fbc328ff00ebf15edad33420f00f7f5+          Linux_Ubuntu:+            unknown_versioning: *ghc-881-32-deb9+          Linux_Mint:+            unknown_versioning: *ghc-881-32-deb9+          Linux_UnknownLinux:+            unknown_versioning: *ghc-881-32-deb9+    8.8.2:+      viTags:+      - base-4.13.0.0+      - old+      viChangeLog: https://downloads.haskell.org/~ghc/8.8.2/docs/html/users_guide/8.8.2-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.8.2/ghc-8.8.2-src.tar.xz+        dlSubdir: ghc-8.8.2+        dlHash: 01cea54d90686b97bcc9960b108beaffccd4336dee930dcf9beaf52b1f370a0b+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 8 && < 9 )':+              dlUri: https://downloads.haskell.org/~ghc/8.8.2/ghc-8.8.2-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.8.2+              dlHash: fbe69652eba75dadb758d00292247d17fb018c29cac5acd79843e56311256c9f+            unknown_versioning: &ghc-882-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.8.2/ghc-8.8.2-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.8.2+              dlHash: 7b2d66c2d5d8c15750da5833d3018634a5eb792a5662282e3abfeb112c2a1cc3+          Linux_Ubuntu:+            unknown_versioning: &ghc-882-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.8.2/ghc-8.8.2-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.8.2+              dlHash: dbe2db717b33460f790e155e487d2a31c9b21a9d245f0c9490ad65844c3ea21f+            '( >= 16 && < 19 )': *ghc-882-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-882-64-fedora+          Linux_Fedora:+            unknown_versioning: *ghc-882-64-fedora+          Linux_CentOS:+            unknown_versioning: &ghc-882-64-centos+              dlUri: https://downloads.haskell.org/~ghc/8.8.2/ghc-8.8.2-x86_64-centos7-linux.tar.xz+              dlSubdir: ghc-8.8.2+              dlHash: f065a017d7a38f235f186ffe32d8261a4fd39c7e945d5cde85c0984c2569db99+          Linux_RedHat:+            unknown_versioning: *ghc-882-64-centos+          Linux_AmazonLinux:+            unknown_versioning: *ghc-882-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-882-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.8.2/ghc-8.8.2-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.8.2+              dlHash: 25c5c1a70036abf3f22b2b19c10d26adfdb08e8f8574f89d4b2042de5947f990+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.8.2/ghc-8.8.2-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-8.8.2+              dlHash: e25d9b16ee62cafc7387af2cd021eea676a99cd2c32b83533b016162c63065d9+        A_32:+          Linux_Debian:+            unknown_versioning: &ghc-882-32-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.8.2/ghc-8.8.2-i386-deb9-linux.tar.xz+              dlSubdir: ghc-8.8.2+              dlHash: ad1c628082c32635a436905a7ff83eaa4246347d869be5ef6b33c3bf85e8f00c+          Linux_Ubuntu:+            unknown_versioning: *ghc-882-32-deb9+          Linux_Mint:+            unknown_versioning: *ghc-882-32-deb9+          Linux_UnknownLinux:+            unknown_versioning: *ghc-882-32-deb9+    8.8.3:+      viTags:+      - base-4.13.0.0+      - old+      viChangeLog: https://downloads.haskell.org/~ghc/8.8.3/docs/html/users_guide/8.8.3-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-src.tar.xz+        dlSubdir: ghc-8.8.3+        dlHash: e0dcc0aaf3e234c5978f29e6df62947e97720ab404ec0158343df211c5480f89+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 8 && < 9 )':+              dlUri: https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.8.3+              dlHash: 92b9fadc442976968d2c190c14e000d737240a7d721581cda8d8741b7bd402f0+            unknown_versioning: &ghc-883-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.8.3+              dlHash: 42fde2ef5a143e1e6b47ae8875162ea2d4d54b06f0f7fa32ee4f0eb86f2be7ad+          Linux_Ubuntu:+            unknown_versioning: &ghc-883-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.8.3+              dlHash: 45ee1de3bfc98cbcc4886b65fc7651ade2d3820aa85eac2dbe9bc7bf91e7c818+            '( >= 16 && < 19 )': *ghc-883-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-883-64-fedora+          Linux_Fedora:+            unknown_versioning: *ghc-883-64-fedora+          Linux_CentOS:+            unknown_versioning: &ghc-883-64-centos+              dlUri: https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-x86_64-centos7-linux.tar.xz+              dlSubdir: ghc-8.8.3+              dlHash: 4b2b5313f7c12b81e54efcb26705fa9e4ad5b98f2b58bfc76fb0c9ba1d55eb1f+          Linux_RedHat:+            unknown_versioning: *ghc-883-64-centos+          Linux_AmazonLinux:+            unknown_versioning: *ghc-883-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-883-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.8.3+              dlHash: 7016de90dd226b06fc79d0759c5d4c83c2ab01d8c678905442c28bd948dbb782+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.8.3/ghc-8.8.3-x86_64-portbld-freebsd.tar.xz+              dlSubdir: ghc-8.8.3+              dlHash: 569719075b4d14b3875a899df522090ae31e6fe085e6dffe518e875b09a2f0be+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-8.8.3+              dlHash: e22586762af0911c06e8140f1792e3ca381a3a482a20d67b9054883038b3a422+        A_32:+          Linux_Debian:+            unknown_versioning: &ghc-883-32-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-i386-deb9-linux.tar.xz+              dlSubdir: ghc-8.8.3+              dlHash: 441e2c7a4fc83ebf179712bd939b555cda7c6633545b7c8ac38049f9d85003ae+          Linux_Ubuntu:+            unknown_versioning: *ghc-883-32-deb9+          Linux_Mint:+            unknown_versioning: *ghc-883-32-deb9+          Linux_UnknownLinux:+            unknown_versioning: *ghc-883-32-deb9+        A_ARM64:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-aarch64-deb9-linux.tar.xz+              dlSubdir: ghc-8.8.3+              dlHash: 2a6821d0e7326cfa7670851702924bbab3b092415ba41247c37419158327eed9+    8.8.4:+      viTags:+      - base-4.13.0.0+      viChangeLog: https://downloads.haskell.org/~ghc/8.8.4/docs/html/users_guide/8.8.4-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.8.4/ghc-8.8.4-src.tar.xz+        dlSubdir: ghc-8.8.4+        dlHash: f0505e38b2235ff9f1090b51f44d6c8efd371068e5a6bb42a2a6d8b67b5ffc2d+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 8 && < 9 )':+              dlUri: https://downloads.haskell.org/~ghc/8.8.4/ghc-8.8.4-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.8.4+              dlHash: 51a36892f1264744195274187298d13ac62bce2da86d4ddf76d8054ab90f2feb+            unknown_versioning: &ghc-884-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.8.4/ghc-8.8.4-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.8.4+              dlHash: 4862559d221153caf978f4bf2c15a82c114d1e1f43b298b2ecff2ac94b586d20+          Linux_Ubuntu:+            unknown_versioning: &ghc-884-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.8.4/ghc-8.8.4-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.8.4+              dlHash: f32e37f8aa03e74bad533ae02f62dc27a4521e78199576af490888ba34b515db+            '( >= 16 && < 19 )': *ghc-884-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-884-64-fedora+          Linux_Fedora:+            unknown_versioning: *ghc-884-64-fedora+          Linux_CentOS:+            unknown_versioning: &ghc-884-64-centos+              dlUri: https://downloads.haskell.org/~ghc/8.8.4/ghc-8.8.4-x86_64-centos7-linux.tar.xz+              dlSubdir: ghc-8.8.4+              dlHash: a12aa4b1fd3c64240a8a6d15196d33e1c0e0d55b51ff78c387242126d0ef7910+          Linux_RedHat:+            unknown_versioning: *ghc-884-64-centos+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.8.4/ghc-8.8.4-x86_64-alpine-linux.tar.xz+              dlSubdir: ghc-8.8.4+              dlHash: 90c6a1661de7f20c7d169cd6270125035b3332063e45103ce028df0beecf434e+          Linux_AmazonLinux:+            unknown_versioning: *ghc-884-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-884-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.8.4/ghc-8.8.4-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.8.4+              dlHash: e80a789e9d8cfb41dd87f3284b75432427c4461c1731d220d04ead8733ccdb5e+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.8.4/ghc-8.8.4-x86_64-portbld-freebsd.tar.xz+              dlSubdir: ghc-8.8.4+              dlHash: 8cebe5ccf454e82acd1ff52ca57590d1ab0f3f44a981b46257ec12158c8c447e+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.8.4/ghc-8.8.4-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-8.8.4+              dlHash: d185055d2c8dc3bfe5b88afd59d6877eb1e722b672d1c9649f18296e148ed71f+        A_32:+          Linux_Debian:+            unknown_versioning: &ghc-884-32-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.8.4/ghc-8.8.4-i386-deb9-linux.tar.xz+              dlSubdir: ghc-8.8.4+              dlHash: 43dd954910c9027694312cef0aabc7774d102d0422b7172802cfb72f7d5da3a0+          Linux_Ubuntu:+            unknown_versioning: *ghc-884-32-deb9+          Linux_Mint:+            unknown_versioning: *ghc-884-32-deb9+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.8.4/ghc-8.8.4-i386-alpine-linux.tar.xz+              dlSubdir: ghc-8.8.4+              dlHash: 1d18e89ee031197e55c48683e78a7ffc67601ac5fd9f73aac555eb064b3859a2+          Linux_UnknownLinux:+            unknown_versioning: *ghc-884-32-deb9+    8.10.1:+      viTags:+      - base-4.14.0.0+      - old+      viChangeLog: https://downloads.haskell.org/~ghc/8.10.1/docs/html/users_guide/8.10.1-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-src.tar.xz+        dlSubdir: ghc-8.10.1+        dlHash: 4e3b07f83a266b3198310f19f71e371ebce97c769b14f0d688f4cbf2a2a1edf5+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-8101-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.10.1+              dlHash: d1cf7886f27af070f3b7dbe1975a78b43ef2d32b86362cbe953e79464fe70761+            '( >= 10 && < 11 )': &ghc-8101-64-deb10+              dlUri: https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-x86_64-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.1+              dlHash: c1e31d798b013699b3c0de4fda27fb4cda47f572df0e75e3bd598a3012060615+            unknown_versioning: *ghc-8101-64-deb9+          Linux_Ubuntu:+            unknown_versioning: &ghc-8101-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.10.1+              dlHash: 3c4cd72b4806045779739e8f5d1658e30e57123d88c2c8966422cdbcae448470+            '( >= 16 && < 19 )': *ghc-8101-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-8101-64-fedora+          Linux_Fedora:+            '( >= 27 && < 28 )': *ghc-8101-64-fedora+            unknown_versioning: *ghc-8101-64-fedora+          Linux_CentOS:+            '( >= 7 && < 8 )': &ghc-8101-64-centos+              dlUri: https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-x86_64-centos7-linux.tar.xz+              dlSubdir: ghc-8.10.1+              dlHash: 0618b94854edc6be5302489df905e627820b71be6b66c950f5e3088fe92df0a1+            unknown_versioning: *ghc-8101-64-centos+          Linux_RedHat:+            unknown_versioning: *ghc-8101-64-centos+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-x86_64-alpine3.10-linux-integer-simple.tar.xz+              dlSubdir: ghc-8.10.1-x86_64-unknown-linux+              dlHash: cb13b645d103e2fba2eb8dfcc4e5f2fbd9550c00c4df42f342b4210436dcb8a8+          Linux_AmazonLinux:+            unknown_versioning: *ghc-8101-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-8101-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.10.1+              dlHash: 65b1ca361093de4804a7e40b3e68178e1ef720f84f743641ec8d95e56a45b3a8+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.10.1/ghc-8.10.1-x86_64-portbld-freebsd.tar.xz+              dlSubdir: ghc-8.10.1+              dlHash: e8646ec9b60fd40aa9505ee055f22f04601290ab7a1342c2cf37c34de9d3f142+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-8.10.1+              dlHash: 38a3166ea50cccd5bae7e1680eae3aae2b4ae31b61f82a1d8168fb821f43bd67+        A_32:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-8101-32-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-i386-deb9-linux.tar.xz+              dlSubdir: ghc-8.10.1+              dlHash: 8b53eef2c827b5f634d72920a93c0c9dd66ea288691a2bfe28def45d3c686ee2+            unknown_versioning: *ghc-8101-32-deb9+          Linux_Ubuntu:+            unknown_versioning: *ghc-8101-32-deb9+          Linux_Mint:+            unknown_versioning: *ghc-8101-32-deb9+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.10.1/ghc-8.10.1-i386-alpine-linux.tar.xz+              dlSubdir: ghc-8.10.1+              dlHash: 7360cc6b29e9b4ab08f6ea5bc3bcca6f5c216933e81ef1620dcdd700f1fdb289+          Linux_UnknownLinux:+            unknown_versioning: *ghc-8101-32-deb9+        A_ARM64:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-aarch64-deb9-linux.tar.xz+              dlSubdir: ghc-8.10.1+              dlHash: c099011e07999db917e797fb5d89c31f075a562556ab99be8ab0accbf2a94db7+        A_ARM:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-armv7-deb9-linux.tar.xz+              dlSubdir: ghc-8.10.1+              dlHash: afe1bde2b0d6deb0320b9460fffe5d9427e302df85aec866b9c1458777d52b28+    8.10.2:+      viTags:+      - old+      - base-4.14.1.0+      viChangeLog: https://downloads.haskell.org/~ghc/8.10.2/docs/html/users_guide/8.10.2-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-src.tar.xz+        dlSubdir: ghc-8.10.2+        dlHash: 9c573a4621a78723950617c223559bdc325ea6a3409264aedf68f05510b0880b+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-8102-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.10.2+              dlHash: 4dbe3b479e76767bfeb4cbb7a4db8b761c4720266193483ca370b2ace3f10f7c+            '( >= 10 && < 11 )': &ghc-8102-64-deb10+              dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-x86_64-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.2+              dlHash: 94513d82c38c848f489113a75fa5ef4e5a8e3ecfaa74ca90e2620d2193ff1632+            unknown_versioning: *ghc-8102-64-deb9+          Linux_Ubuntu:+            unknown_versioning: &ghc-8102-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.10.2+              dlHash: 8c675da83e9b3c2f64ebb407b5f9ebb2c1f21aa5d701020614fdce644a542e3b+            '( >= 16 && < 19 )': *ghc-8102-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-8102-64-fedora+          Linux_Fedora:+            '( >= 27 && < 28 )': *ghc-8102-64-fedora+            unknown_versioning: *ghc-8102-64-fedora+          Linux_CentOS:+            '( >= 7 && < 8 )': &ghc-8102-64-centos+              dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-x86_64-centos7-linux.tar.xz+              dlSubdir: ghc-8.10.2+              dlHash: fd2dccd6f496915a5f962dab24e7eeb8bee49bcc38e74b17eac76159083538fa+            unknown_versioning: *ghc-8102-64-centos+          Linux_RedHat:+            unknown_versioning: *ghc-8102-64-centos+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-x86_64-alpine3.10-linux-integer-simple.tar.xz+              dlSubdir: ghc-8.10.2-x86_64-unknown-linux+              dlHash: 14d09a508f2a3a11875c140be8e6c5f6982ac5cd448f089ca10b7adc955fec76+          Linux_AmazonLinux:+            unknown_versioning: *ghc-8102-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-8102-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.10.2+              dlHash: edb772b00c0d7f18bb56ad27765162ee09c508104d40f82128c9114a02f6cfc2+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-x86_64-unknown-freebsd.tar.xz+              dlSubdir: ghc-8.10.2+              dlHash: 9e5957f3497f4b58ecd3699568d9caaa11a47a6d7e902032c261e450fa0f6686+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-8.10.2+              dlHash: dcae4c173b9896e07ff048de5509aa0a4537233150e06e5ce8848303dfadc176+        A_32:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-8102-32-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-i386-deb9-linux.tar.xz+              dlSubdir: ghc-8.10.2+              dlHash: 9dae2a86ad43d08f72c783542c944d1556b075aa20a8063efae5034ea88e7c2f+            unknown_versioning: *ghc-8102-32-deb9+          Linux_Ubuntu:+            unknown_versioning: *ghc-8102-32-deb9+          Linux_Mint:+            unknown_versioning: *ghc-8102-32-deb9+          Linux_UnknownLinux:+            unknown_versioning: *ghc-8102-32-deb9+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.10.2/ghc-8.10.2-i386-alpine-linux.tar.xz+              dlSubdir: ghc-8.10.2+              dlHash: 9ee1cf1e85e9536088b3c9e80e975074e525ea378cd4eb156071bbc4b7b38327+        A_ARM64:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-aarch64-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.2+              dlHash: 5cf24189077e6e2dce2aa16367ad8a53f603e751a15010dfb23d067206e55593+        A_ARM:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-armv7-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.2+              dlHash: bb9c97826b1f4d7a8ef8bce0616b612f1ded10480ef10fcf7fb4e6d10a6681c8+    8.10.3:+      viTags:+      - old+      - base-4.14.1.0+      viChangeLog: https://downloads.haskell.org/~ghc/8.10.3/docs/html/users_guide/8.10.3-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-src.tar.xz+        dlSubdir: ghc-8.10.3+        dlHash: ccdc8319549028a708d7163e2967382677b1a5a379ff94d948195b5cf46eb931+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-8103-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.10.3+              dlHash: 95e4aadea30701fe5ab84d15f757926d843ded7115e11c4cd827809ca830718d+            '( >= 10 && < 11 )': &ghc-8103-64-deb10+              dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-x86_64-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.3+              dlHash: c8f3d9f0e61a89eaba1d3ad8fb2eced1af0e81576811261b887993bee12538ac+            unknown_versioning: *ghc-8103-64-deb9+          Linux_Ubuntu:+            unknown_versioning: &ghc-8103-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.10.3+              dlHash: f8739b12008712d6b6a9ffc6c39f9d05af77ef3bcb932c9aff20fa0893c8c159+            '( >= 16 && < 19 )': *ghc-8103-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-8103-64-deb10+          Linux_Fedora:+            '( >= 27 && < 28 )': *ghc-8103-64-fedora+            unknown_versioning: *ghc-8103-64-fedora+          Linux_CentOS:+            '( >= 7 && < 8 )': &ghc-8103-64-centos+              dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-x86_64-centos7-linux.tar.xz+              dlSubdir: ghc-8.10.3+              dlHash: f562ca61979ff1d21e34e69e59028cb742a8eff8d84e46bbd3a750f2ac7d8ed1+            unknown_versioning: *ghc-8103-64-centos+          Linux_RedHat:+            unknown_versioning: *ghc-8103-64-centos+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-x86_64-alpine3.10-linux-integer-simple.tar.xz+              dlSubdir: ghc-8.10.3-x86_64-unknown-linux+              dlHash: 8506c478ebbfb5441c3c36c07c36fc8532cacb2b3e13c6733bd44cb17b3ce96c+          Linux_AmazonLinux:+            unknown_versioning: *ghc-8103-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-8103-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.10.3+              dlHash: 2635f35d76e44e69afdfd37cae89d211975cc20f71f784363b72003e59f22015+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-x86_64-portbld-freebsd.tar.xz+              dlSubdir: ghc-8.10.3+              dlHash: 749007e995104db05cf6e3ad5bc36238cab8afac8055145661e5730e8f8af040+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-8.10.3+              dlHash: 927a6c699533a115cd49772ef2c753d9af2c13bf9f0b2d3bd13645cc6a144ee3+        A_32:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-8103-32-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-i386-deb9-linux.tar.xz+              dlSubdir: ghc-8.10.3+              dlHash: f0addd2a16b705f58ff9e8702c3ddf3e2d6bd0d3555707b5b5095e51bafee7b1+            unknown_versioning: *ghc-8103-32-deb9+          Linux_Ubuntu:+            unknown_versioning: *ghc-8103-32-deb9+          Linux_Mint:+            unknown_versioning: *ghc-8103-32-deb9+          Linux_UnknownLinux:+            unknown_versioning: *ghc-8103-32-deb9+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.10.3/ghc-8.10.3-i386-alpine-linux.tar.xz+              dlSubdir: ghc-8.10.3+              dlHash: 309201cdefd2d13b8b3fd09c26c6137048c490d219a0a9c7407c3ce1d011f60c+        A_ARM64:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-aarch64-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.3+              dlHash: a531432d505a1fe886cdc8639d168eb1c92d76464c1270713e01ce81891bbadb+        A_ARM:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-armv7-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.3+              dlHash: b823b58cae36fbac0741680ca7605180fa4cf4c6ae439123d282184b94d32fd6+    8.10.4:+      viTags:+      - base-4.14.1.0+      viChangeLog: https://downloads.haskell.org/~ghc/8.10.4/docs/html/users_guide/8.10.4-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-src.tar.xz+        dlSubdir: ghc-8.10.4+        dlHash: 52af871b4e08550257d720c2944ac85727d0b948407cef1bebfe7508c224910e+      viPostRemove: *ghc-post-remove+      viPreCompile: &ghc-pre-compile "If you have autoconf >= 2.70 you'll need this patch https://gitlab.haskell.org/ghc/ghc/-/snippets/2040 (see the --patchdir option)"+      viArch:+        A_64:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-8104-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.10.4+              dlHash: 5694200a5c38f22c142baf850b1d2f3784211d2ec9302e11693259a1ae8e38b7+            '( >= 10 && < 11 )': &ghc-8104-64-deb10+              dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-x86_64-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.4+              dlHash: 816365565e9927459b035515a7db6a0db62f9796f327389b6f8a0035d12fbda0+            unknown_versioning: *ghc-8104-64-deb9+          Linux_Ubuntu:+            unknown_versioning: &ghc-8104-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.10.4+              dlHash: a189eed900a8717d6d7906bafd10b9a9a9688ad942d1c75e19df480376dff9ea+            '( >= 16 && < 19 )': *ghc-8104-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-8104-64-deb10+          Linux_Fedora:+            '( >= 27 && < 28 )': *ghc-8104-64-fedora+            unknown_versioning: *ghc-8104-64-fedora+          Linux_CentOS:+            '( >= 7 && < 8 )': &ghc-8104-64-centos+              dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-x86_64-centos7-linux.tar.xz+              dlSubdir: ghc-8.10.4+              dlHash: fb8a91f0cf06594172aff46c2f6f7486179e1c3760855c79fbdd3012598cc2cd+            unknown_versioning: *ghc-8104-64-centos+          Linux_RedHat:+            unknown_versioning: *ghc-8104-64-centos+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-x86_64-alpine3.10-linux-integer-simple.tar.xz+              dlSubdir: ghc-8.10.4-x86_64-unknown-linux+              dlHash: 74c2c07537832708502716ef4ec40019f8e552ddda13c8eadf8f7c4b03a79359+          Linux_AmazonLinux:+            unknown_versioning: *ghc-8104-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-8104-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.10.4+              dlHash: 725ecf6543e63b81a3581fb8c97afd21a08ae11bc0fa4f8ee25d45f0362ef6d5+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-x86_64-portbld-freebsd.tar.xz+              dlSubdir: ghc-8.10.4+              dlHash: c9776a2ccf9629b03e967206a507fcdcb6c5189800a626e9461ababf6733c357+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-8.10.4+              dlHash: e9175a276504c3390a5e0084954e6997d56078737dbe7158049518892cf6bfb2+        A_32:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-8104-32-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-i386-deb9-linux.tar.xz+              dlSubdir: ghc-8.10.4+              dlHash: 0022c5b9ac22825bb7b4745af3d92cef0ba1ecd01fab3ef387ddbd47146569ad+            unknown_versioning: *ghc-8104-32-deb9+          Linux_Ubuntu:+            unknown_versioning: *ghc-8104-32-deb9+          Linux_Mint:+            unknown_versioning: *ghc-8104-32-deb9+          Linux_UnknownLinux:+            unknown_versioning: *ghc-8104-32-deb9+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.10.4/ghc-8.10.4-i386-alpine-linux.tar.xz+              dlSubdir: ghc-8.10.4+              dlHash: 9161a98bed763692101854d83af69c1316030cfe5ee6f6acde283d04ef139735+        A_ARM64:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-aarch64-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.4+              dlHash: 249da6310be799a5eefe0579b6dae1701eb984afb980fe08309d19cf704038ed+        A_ARM:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-armv7-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.4+              dlHash: 0d18ef83593272f6196a41cc3abdc48dfe5e14372db75d71ea19fe35320c4e81+    8.10.5:+      viTags:+      - Recommended+      - base-4.14.2.0+      viChangeLog: https://downloads.haskell.org/~ghc/8.10.5/docs/html/users_guide/8.10.5-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.10.5/ghc-8.10.5-src.tar.xz+        dlSubdir: ghc-8.10.5+        dlHash: f10941f16e4fbd98580ab5241b9271bb0851304560c4d5ca127e3b0e20e3076f+      viPostRemove: *ghc-post-remove+      viPreCompile: *ghc-pre-compile+      viArch:+        A_64:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-8105-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.10.5/ghc-8.10.5-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.10.5+              dlHash: 15e71325c3bdfe3804be0f84c2fc5c913d811322d19b0f4d4cff20f29cdd804d+            '( >= 10 && < 11 )': &ghc-8105-64-deb10+              dlUri: https://downloads.haskell.org/~ghc/8.10.5/ghc-8.10.5-x86_64-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.5+              dlHash: bc623c20ca4c5c18e952071ba14aa0cfc5c94d34219bffaa615f7b491f376787+            unknown_versioning: *ghc-8105-64-deb9+          Linux_Ubuntu:+            unknown_versioning: &ghc-8105-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.10.5/ghc-8.10.5-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.10.5+              dlHash: 73528ebfb219b50aa9042ee51a0a2bd764828d605f058404989d0b645752d210+            '( >= 16 && < 19 )': *ghc-8105-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-8105-64-deb10+          Linux_Fedora:+            '( >= 27 && < 28 )': *ghc-8105-64-fedora+            unknown_versioning: *ghc-8105-64-fedora+          Linux_CentOS:+            '( >= 7 && < 8 )': &ghc-8105-64-centos+              dlUri: https://downloads.haskell.org/~ghc/8.10.5/ghc-8.10.5-x86_64-centos7-linux.tar.xz+              dlSubdir: ghc-8.10.5+              dlHash: 4cdb259ec74d1408dab45dab20dcedc21690f39921c2ea4546486fb3e81f4fbd+            unknown_versioning: *ghc-8105-64-centos+          Linux_RedHat:+            unknown_versioning: *ghc-8105-64-centos+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.5/ghc-8.10.5-x86_64-alpine3.10-linux-integer-simple.tar.xz+              dlSubdir: ghc-8.10.5-x86_64-unknown-linux+              dlHash: f4d7cd9ed12a4b8592219c9a63a86db1a256a09fa9e6ed755a60afc57dc782e2+          Linux_AmazonLinux:+            unknown_versioning: *ghc-8105-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-8105-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.5/ghc-8.10.5-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.10.5+              dlHash: ef0f47eff8962d58fa447123636cf8ef31c1e5b2d0ae90177d3388861ddf4a22+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghcup/unofficial-bindists/ghc/8.10.5/ghc-8.10.5-x86_64-portbld-freebsd.tar.xz+              dlSubdir: ghc-8.10.5+              dlHash: 11a0b490bfb2f57b5bc87c69c197542eafce1b4991cc22f625179a6c6e567834+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.5/ghc-8.10.5-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-8.10.5+              dlHash: 4443d989df4f2680f681a4d8b8db310ce9582d21743984016b0eb0163b0c9998+        A_32:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-8105-32-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.10.5/ghc-8.10.5-i386-deb9-linux.tar.xz+              dlSubdir: ghc-8.10.5+              dlHash: 0ccb5b2c1222374874795c35410754dd650f649b774872abbea2a4ef21ac9c9d+            unknown_versioning: *ghc-8105-32-deb9+          Linux_Ubuntu:+            unknown_versioning: *ghc-8105-32-deb9+          Linux_Mint:+            unknown_versioning: *ghc-8105-32-deb9+          Linux_UnknownLinux:+            unknown_versioning: *ghc-8105-32-deb9+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghcup/unofficial-bindists/ghc/8.10.5/ghc-8.10.5-i386-alpine-linux.tar.xz+              dlSubdir: ghc-8.10.5+              dlHash: 0e91abe61607f9375d4e252ee9c261e4856df396f60641bb1b880ab8a3a83ea7+        A_ARM64:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.5/ghc-8.10.5-aarch64-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.5+              dlHash: 9a085cd8a7f8e0ace21ac67dbf659a56fcf41564b48817ba42cd8a1aac7f0ddc+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.5/ghc-8.10.5-aarch64-apple-darwin.tar.xz+              dlSubdir: ghc-8.10.5+              dlHash: 03684e70ff03d041b9a4e0f84c177953a241ab8ec7a028c72fa21ac67e66cb09+        A_ARM:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.5/ghc-8.10.5-armv7-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.5+              dlHash: 56170d1a8450e18b7eb9c23c94723da352815b27ec250bb23742a62f16dcab6c+    9.0.1:+      viTags:+      - Latest+      - base-4.15.0.0+      viChangeLog: https://downloads.haskell.org/~ghc/9.0.1/docs/html/users_guide/9.0.1-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-src.tar.xz+        dlSubdir: ghc-9.0.1+        dlHash: a5230314e4065f9fcc371dfe519748fd85c825b279abf72a24e09b83578a35f9+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-901-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-9.0.1+              dlHash: 4ca6252492f59fe589029fadca4b6f922d6a9f0ff39d19a2bd9886fde4e183d5+            '( >= 10 && < 11 )': &ghc-901-64-deb10+              dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-x86_64-deb10-linux.tar.xz+              dlSubdir: ghc-9.0.1+              dlHash: c253e7eb62cc9da6524c491c85ec8d3727c2ca6035a8653388e636aaa30a2a0f+            unknown_versioning: *ghc-901-64-deb9+          Linux_Ubuntu:+            unknown_versioning: &ghc-901-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-9.0.1+              dlHash: 1fb8e27eeec51b4cdbfd1b3c16727adc5f77388d3e925e63799d8232647f316d+            '( >= 16 && < 19 )': *ghc-901-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-901-64-deb10+          Linux_Fedora:+            '( >= 27 && < 28 )': *ghc-901-64-fedora+            unknown_versioning: *ghc-901-64-fedora+          Linux_CentOS:+            '( >= 7 && < 8 )': &ghc-901-64-centos+              dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-x86_64-centos7-linux.tar.xz+              dlSubdir: ghc-9.0.1+              dlHash: a23750950b6995a66ba59afe82bbc505bd3479d6ab59cf66f45bc6c056e4d87b+            unknown_versioning: *ghc-901-64-centos+          Linux_RedHat:+            unknown_versioning: *ghc-901-64-centos+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-x86_64-alpine3.10-linux-integer-simple.tar.xz+              dlSubdir: ghc-9.0.1-x86_64-unknown-linux+              dlHash: 7c1a0154c9e361b75be6cb0305533bb8a3b963c54e8092ffd1759e5710805a5c+          Linux_AmazonLinux:+            unknown_versioning: *ghc-901-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-901-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-9.0.1+              dlHash: 122d60509147d0117779d275f0215bde2ff63a64cda9d88f149432d0cae71b22+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-x86_64-portbld-freebsd.tar.xz+              dlSubdir: ghc-9.0.1+              dlHash: 9dbc06d8832cae5c9f86dd7b2db729b3748a47beb4fd4b1e62bb66119817c3c1+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-9.0.1-x86_64-unknown-mingw32+              dlHash: 4f4ab118df01cbc7e7c510096deca0cb25025339a97730de0466416296202493+        A_32:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-901-32-deb9+              dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-i386-deb9-linux.tar.xz+              dlSubdir: ghc-9.0.1+              dlHash: 880e37cea8328401bcfecfe4bb56eb85195f30135b140140b3f24094264f8ba5+            unknown_versioning: *ghc-901-32-deb9+          Linux_Ubuntu:+            unknown_versioning: *ghc-901-32-deb9+          Linux_Mint:+            unknown_versioning: *ghc-901-32-deb9+          Linux_UnknownLinux:+            unknown_versioning: *ghc-901-32-deb9+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/9.0.1/ghc-9.0.1-i386-alpine-linux.tar.xz+              dlSubdir: ghc-9.0.1+              dlHash: ebfeb3b91e6f2bb5a49fd3376746f7fd1b89e62e9838bf5b1530a8756ff1e6aa+        A_ARM64:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-aarch64-deb9-linux.tar.xz+              dlSubdir: ghc-9.0.1+              dlHash: fac7a0bdfc83c05df94024a2d67b8f00a9cd2733b9cb41fb8ad76be399014906+        A_ARM:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-armv7-deb9-linux.tar.xz+              dlSubdir: ghc-9.0.1+              dlHash: 6f404f9b88468407b3a9ec5800bcc2d01dd453ef3d63414853b4fbbd4d8df496+    9.2.0.20210422:+      viTags:+      - Prerelease+      - base-4.16.0.0+      viChangeLog: https://downloads.haskell.org/~ghc/9.2.1-alpha2/docs/html/users_guide/index.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/9.2.1-alpha2/ghc-9.2.0.20210422-src.tar.xz+        dlSubdir: ghc-9.2.0.20210422+        dlHash: 69be189e6e7f8d51a9078ac8f177176bc5bff54edc8352974c50c1f0e110df27+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-921-alpha2-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/9.2.1-alpha2/ghc-9.2.0.20210422-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-9.2.0.20210422+              dlHash: 7262f3a230cd6945c588882e03941301877a9eb12e58c5975ad264596c2e12f2+            '( >= 10 && < 11 )': &ghc-921-alpha2-64-deb10+              dlUri: https://downloads.haskell.org/~ghc/9.2.1-alpha2/ghc-9.2.0.20210422-x86_64-deb10-linux.tar.xz+              dlSubdir: ghc-9.2.0.20210422+              dlHash: 6d36cd08576bdee7473fee66b4b8ceb72011983a7d5aa3ec587403815a73e37b+            unknown_versioning: *ghc-921-alpha2-64-deb9+          Linux_Ubuntu:+            unknown_versioning: &ghc-921-alpha2-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/9.2.1-alpha2/ghc-9.2.0.20210422-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-9.2.0.20210422+              dlHash: 95624192ff0982690bc9093632d6351fdc6f72e6df380b392449229c39a0354b+            '( >= 16 && < 19 )': *ghc-921-alpha2-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-921-alpha2-64-deb10+          Linux_Fedora:+            '( >= 27 && < 28 )': *ghc-921-alpha2-64-fedora+            unknown_versioning: *ghc-921-alpha2-64-fedora+          Linux_CentOS:+            '( >= 7 && < 8 )': &ghc-921-alpha2-64-centos+              dlUri: https://downloads.haskell.org/~ghc/9.2.1-alpha2/ghc-9.2.0.20210422-x86_64-centos7-linux.tar.xz+              dlSubdir: ghc-9.2.0.20210422+              dlHash: dee4f158f2d59bfe97ec3f5773b6b31aa911f9b128a5e56eeefa2dccc754d295+            unknown_versioning: *ghc-921-alpha2-64-centos+          Linux_RedHat:+            unknown_versioning: *ghc-921-alpha2-64-centos+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/9.2.1-alpha2/ghc-9.2.0.20210422-x86_64-alpine3.10-linux-integer-simple.tar.xz+              dlSubdir: ghc-9.2.0.20210422-x86_64-unknown-linux+              dlHash: f61ae72925325ca7b316e40121e8d6bad94794016d3fa59bcbc8dbe116a7f13c+          Linux_AmazonLinux:+            unknown_versioning: *ghc-921-alpha2-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-921-alpha2-64-fedora+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/9.2.1-alpha2/ghc-9.2.0.20210422-x86_64-unknown-freebsd.tar.xz+              dlSubdir: ghc-9.2.0.20210422+              dlHash: 195728e02398ea6154fe713b7782a0cae856eb0d9d90f5d09cd0cca610c985e2+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/9.2.1-alpha2/ghc-9.2.0.20210422-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-9.2.0.20210422+              dlHash: 8884c059f2b76e4c4309ff6bd7a7dde37663f751fd26220e9a2bcabb4d69a401+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/9.2.1-alpha2/ghc-9.2.0.20210422-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-9.2.0.20210422-x86_64-unknown-mingw32+              dlHash: 33f173b754d18f26bb27f52bb77a92fd22a48675daa2b43a1879bf01dddd7e8f+        A_32:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-921-alpha2-32-deb9+              dlUri: https://downloads.haskell.org/~ghc/9.2.1-alpha2/ghc-9.2.0.20210422-i386-deb9-linux.tar.xz+              dlSubdir: ghc-9.2.0.20210422+              dlHash: a378ec3fd31a9fa2a7134e98159e189362fe969f04031515616e9cc3182c861a+            unknown_versioning: *ghc-921-alpha2-32-deb9+          Linux_Ubuntu:+            unknown_versioning: *ghc-921-alpha2-32-deb9+          Linux_Mint:+            unknown_versioning: *ghc-921-alpha2-32-deb9+          Linux_UnknownLinux:+            unknown_versioning: *ghc-921-alpha2-32-deb9+        A_ARM64:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/9.2.1-alpha2/ghc-9.2.0.20210422-aarch64-deb10-linux.tar.xz+              dlSubdir: ghc-9.2.0.20210422+              dlHash: fd2f4d0f6122f752aca396fe1a13e7d14d037dc45806bb0404a031eeeeb1994c+        A_ARM:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/9.2.1-alpha2/ghc-9.2.0.20210422-armv7-deb10-linux.tar.xz+              dlSubdir: ghc-9.2.0.20210422+              dlHash: dab7d7785d6ccafb130526b666669fc974ba5c90fc9aaf2024f9c65bcbd097d3+  Cabal:+    2.4.1.0:+      viTags:+        - old+      viChangeLog: https://downloads.haskell.org/~cabal/cabal-install-2.4.1.0/changelog+      viArch:+        A_64:+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-2.4.1.0/cabal-install-2.4.1.0-x86_64-alpine-linux-musl.tar.xz+              dlSubdir:+              dlHash: 720bef015f834a03deb7180be2952a44e7c2e6c8429137570404c3de4f46b984+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-2.4.1.0/cabal-install-2.4.1.0-x86_64-unknown-linux.tar.xz+              dlSubdir:+              dlHash: 6136c189ffccaa39916f9cb5788f757166444a2d0c473b987856a79ecbf0c714+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-2.4.1.0/cabal-install-2.4.1.0-x86_64-apple-darwin-sierra.tar.xz+              dlSubdir:+              dlHash: 56361cf4b0d920fe23174751fea1fb82a8e1ce522bd9706a3fbe47a72e458c9c+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-2.4.1.0/cabal-install-2.4.1.0-x86_64-portbld-freebsd.tar.xz+              dlSubdir:+              dlHash: 33b7d37ea0688c93436eac9ec139d9967687875aa1fa13f2bb73bf05a9a59a1d+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-2.4.1.0/cabal-install-2.4.1.0-x86_64-unknown-mingw32.zip+              dlSubdir:+              dlHash: 95f233efedb1ebf0e6db015fa2f55c1ed00b9938d207ec63c066f706fb4b6373+        A_32:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-2.4.1.0/cabal-install-2.4.1.0-i386-unknown-linux.tar.xz+              dlSubdir:+              dlHash: b2da736cc27609442b10f77fc1a687aba603a7a33045b722dbf1a0066fade198+    3.0.0.0:+      viTags:+        - old+      viChangeLog: https://downloads.haskell.org/~cabal/cabal-install-3.0.0.0/changelog+      viArch:+        A_64:+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.0.0.0/cabal-install-3.0.0.0-x86_64-alpine-linux-musl.tar.xz+              dlHash: 2b7ea63601e11a0db2941b96e6a7036a48efc2a1ab3849d7dfce08b45f5daa58+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.0.0.0/cabal-install-3.0.0.0-x86_64-unknown-linux.tar.xz+              dlHash: ee911ba67a70756eedeac662955b896d7e89432a99372aa45d2c6e71fa95a5e4+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.0.0.0/cabal-install-3.0.0.0-x86_64-apple-darwin17.7.0.tar.xz+              dlHash: d4857e068560515e4cbb0e8ca124c370e07892f2a28804d87152834e5fe2b845+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.0.0.0/cabal-install-3.0.0.0-x86_64-portbld-freebsd.tar.xz+              dlHash: 2240842ab2ae7b955feb8b526aba1c7991248c803383107adf39990441294d2a+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.0.0.0/cabal-install-3.0.0.0-x86_64-unknown-mingw32.zip+              dlSubdir:+              dlHash: 8889963ebef5e829d86329fdb59832c107efd117cf7862a605f2fe2d2360de1f+        A_32:+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.0.0.0/cabal-install-3.0.0.0-i386-alpine-linux-musl.tar.xz+              dlHash: ac018f061993d40bf146517e32629bcab274b4d9f5527b1c37a665ebdf3f5ac6+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.0.0.0/cabal-install-3.0.0.0-i386-unknown-linux.tar.xz+              dlHash: 6898ccd6e6dc0872999c06daaf61d546164e12f60a1880d09852c9f0c59c5cf6+    3.2.0.0:+      viTags:+      - old+      viChangeLog: https://downloads.haskell.org/~cabal/cabal-install-3.2.0.0/changelog+      viArch:+        A_64:+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.2.0.0/cabal-install-3.2.0.0-x86_64-alpine-linux-musl.tar.xz+              dlHash: 8bae37a1ce8b5f10440b5591fed734935e1411c1b765258325ffe268e2cc2042+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.2.0.0/cabal-install-3.2.0.0-x86_64-unknown-linux.tar.xz+              dlHash: 32d1f7cf1065c37cb0ef99a66adb405f409b9763f14c0926f5424ae408c738ac+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.2.0.0/cabal-install-3.2.0.0-x86_64-apple-darwin17.7.0.tar.xz+              dlHash: 9197c17d2ece0f934f5b33e323cfcaf486e4681952687bc3d249488ce3cbe0e9+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.2.0.0/cabal-install-3.2.0.0-x86_64-portbld-freebsd.tar.xz+              dlHash: f1e35151cca91541b0fb4bdb3ed18f3c348038eab751845ad19c11307d66c273+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.2.0.0/cabal-install-3.2.0.0-x86_64-unknown-mingw32.zip+              dlSubdir:+              dlHash: 17778c3ade0482bc37f451eec326f8fce8fbe1f12b1d6aacb2e2b9e34786c054+        A_32:+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.2.0.0/cabal-install-3.2.0.0-i386-alpine-linux-musl.tar.xz+              dlHash: c2a419dedf730987b60daf8d24e871d115a09ea608d740d7c61b36e3f5b9c830+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.2.0.0/cabal-install-3.2.0.0-i386-unknown-linux.tar.xz+              dlHash: 2b3ac28549916de5f3379241797eaf60e84b6c001f2abbe73d9fadbbaf768e93+    3.4.0.0:+      viTags:+      - Recommended+      - Latest+      viChangeLog: https://github.com/haskell/cabal/blob/master/release-notes/cabal-install-3.4.0.0.md+      viArch:+        A_64:+          Linux_Ubuntu:+            unknown_versioning: &cabal-3400-ubuntu+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.4.0.0/cabal-install-3.4.0.0-x86_64-ubuntu-16.04.tar.xz+              dlHash: cf28f9ffd763476aa2b1730d85cbf155d366fac541f78ee3951e8cb2d6de63e6+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.4.0.0/cabal-install-3.4.0.0-x86_64-alpine-3.11.6-static-noofd.tar.xz+              dlHash: c74073fe79110946182e522fcadc8dcabf07c87583e8cf7801ed4e0c327241f6+          Linux_UnknownLinux:+            unknown_versioning: *cabal-3400-ubuntu+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.4.0.0/cabal-install-3.4.0.0-x86_64-darwin-sierra.tar.xz+              dlHash: cb10be9a53e856aa2d852fd88fb6944f138783ffe0ea84d93c9a69244e34ea91+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.4.0.0/cabal-install-3.4.0.0-x86_64-freebsd-12.1-release.tar.xz+              dlHash: a1e2db664ec00e42a1e071a4181f6476f6e0bad321f1ddc0cf27831119f4c6d4+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghcup/unofficial-bindists/cabal/3.4.0.0/cabal-install-3.4.0.0-x86_64-windows.zip+              dlSubdir:+              dlHash: c898496b199a3ebf41fb399c12a0cb55a470a67e758cee4b08b9f304c4be6979+        A_32:+          Linux_UnknownLinux:+            unknown_versioning: &cabal-3400-32+              dlUri: https://downloads.haskell.org/~ghcup/unofficial-bindists/cabal/3.4.0.0/cabal-install-3.4.0.0-i386-unknown-linux.tar.xz+              dlHash: cc62a471e9e68a6a9933e54f75bf0cffae67a1d2220df1152ab887c38eb6bc8a+          Linux_Alpine:+            unknown_versioning: *cabal-3400-32+        A_ARM64:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.4.0.0/cabal-install-3.4.0.0-aarch64-ubuntu-18.04.tar.xz+              dlHash: 04d378347896dfdc3510b192b97489815cfa5d692f46e2758da0f789e682b8f0+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghcup/unofficial-bindists/cabal/3.4.0.0/cabal-install-3.4.0.0-aarch64-darwin-big-sur.tar.xz+              dlHash: 46d8f96446a6bcdb81b3a9fbc14b137dc4f08436b46fe6446c5fba7bcb9b3d75++        A_ARM:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghcup/unofficial-bindists/cabal/3.4.0.0/cabal-install-3.4.0.0-armv7-linux-bootstrapped.tar.xz+              dlHash: 16c0d1eaba24bed14f3e152970179a45d9f9bb5cc839b2c210ad06eb7d4826ed+  GHCup:+    0.1.16.2:+      viTags:+      - Recommended+      - Latest+      viChangeLog: https://gitlab.haskell.org/haskell/ghcup-hs/-/blob/master/CHANGELOG.md+      viSourceDL:+      viArch:+        A_64:+          Linux_UnknownLinux:+            unknown_versioning: &ghcup-64+              dlUri: https://downloads.haskell.org/~ghcup/0.1.16.2/x86_64-linux-ghcup-0.1.16.2+              dlHash: d5e43b95ce1d42263376e414f7eb7c5dd440271c7c6cd9bad446fdeff3823893+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghcup/0.1.16.2/x86_64-apple-darwin-ghcup-0.1.16.2+              dlHash: a334620ccce7705211b2142882dde544003e6030af4b91a44c890542a90f879f+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghcup/0.1.16.2/x86_64-portbld-freebsd-ghcup-0.1.16.2+              dlHash: 92359592a5694375e53b22628920086bf4bbf0faff5be018a0ed3e745a6426a9+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghcup/0.1.16.2/x86_64-mingw64-ghcup-0.1.16.2.exe+              dlHash: ec78872a84213968c490675127b9aad2285980b747c68207801ae824b98c7948+          Linux_Alpine:+            unknown_versioning: *ghcup-64+        A_32:+          Linux_UnknownLinux:+            unknown_versioning: &ghcup-32+              dlUri: https://downloads.haskell.org/~ghcup/0.1.16.2/i386-linux-ghcup-0.1.16.2+              dlHash: 01968ca6decac7b6e8ba6e2c817870d3fa47289a6507e0c1ab563f7b6eec0e38+          Linux_Alpine:+            unknown_versioning: *ghcup-32+        A_ARM64:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghcup/0.1.16.2/aarch64-linux-ghcup-0.1.16.2+              dlHash: 0bdbfc724e0ddabb266156eea83c2c4e19c6ed79dd06db0c29b7d69df8d9fa8c+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghcup/0.1.16.2/aarch64-apple-darwin-ghcup-0.1.16.2+              dlHash: 8854e991a2ba1350abda59dab96ce50ae7729d1ce99399d67929ef31e90f1da5+        A_ARM:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghcup/0.1.16.2/armv7-linux-ghcup-0.1.16.2+              dlHash: 983ebb5b584bfa600704216a63f94b40d36a02573834e90ef1042c8472d9ad57+  HLS:+    1.1.0:+      viTags: []+      viChangeLog: https://github.com/haskell/haskell-language-server/blob/master/ChangeLog.md#110+      viPostInstall: &hls-post-install |+        This is just the server part of your LSP configuration. Consult the README on how to+        configure HLS, your project and your LSP client in your editor:+          https://github.com/haskell/haskell-language-server/blob/master/README.md+      viArch:+        A_64:+          Linux_UnknownLinux:+            unknown_versioning: &hls-110-64+              dlUri: https://github.com/haskell/haskell-language-server/releases/download/1.1.0/haskell-language-server-Linux-1.1.0.tar.gz+              dlHash: 0f0dadb0e9a08273658f565fd71c636801959b954be2737f38f2a1aac522208f+          Darwin:+            unknown_versioning:+              dlUri: https://github.com/haskell/haskell-language-server/releases/download/1.1.0/haskell-language-server-macOS-1.1.0.tar.gz+              dlHash: 4e89b192e2f49637d772e974f2c17b16da067ecd5912575eaa542551de97681b+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/hls/1.1.0/haskell-language-server-Windows-1.1.0.tar.gz+              dlHash: a1d3f451e64a041aa527a25da29e4716a2de6ae347cef4ef9312fc7611e168cc+          Linux_Alpine:+            unknown_versioning: *hls-110-64+    1.2.0:+      viTags: []+      viChangeLog: https://github.com/haskell/haskell-language-server/blob/master/ChangeLog.md#120+      viPostInstall: *hls-post-install+      viArch:+        A_64:+          Linux_UnknownLinux:+            unknown_versioning: &hls-120-64+              dlUri: https://github.com/haskell/haskell-language-server/releases/download/1.2.0/haskell-language-server-Linux-1.2.0.tar.gz+              dlHash: d29ee22f7bd706da2e2a1bd7640e25bb9736adeafb34eef47d29ea143b0fa927+          Darwin:+            unknown_versioning:+              dlUri: https://github.com/haskell/haskell-language-server/releases/download/1.2.0/haskell-language-server-macOS-1.2.0.tar.gz+              dlHash: a310d8a3e9c5c4218210f750682c74a0f82ad0f59995adde0dbe775115b1e357+          Windows:+            unknown_versioning:+              dlUri: https://github.com/haskell/haskell-language-server/releases/download/1.2.0/haskell-language-server-Windows-1.2.0.tar.gz+              dlHash: 961c6ff12c9a9c7a4609f239c5ac70d7d16753cdb8c10348a6a51feeaa0b6aea+          Linux_Alpine:+            unknown_versioning: *hls-120-64+    1.3.0:+      viTags:+        - Recommended+        - Latest+      viChangeLog: https://github.com/haskell/haskell-language-server/blob/master/ChangeLog.md#130+      viPostInstall: *hls-post-install+      viArch:+        A_64:+          Linux_UnknownLinux:+            unknown_versioning: &hls-130-64+              dlUri: https://github.com/haskell/haskell-language-server/releases/download/1.3.0/haskell-language-server-Linux-1.3.0.tar.gz+              dlHash: d29ee22f7bd706da2e2a1bd7640e25bb9736adeafb34eef47d29ea143b0fa927+          Darwin:+            unknown_versioning:+              dlUri: https://github.com/haskell/haskell-language-server/releases/download/1.3.0/haskell-language-server-macOS-1.3.0.tar.gz+              dlHash: a310d8a3e9c5c4218210f750682c74a0f82ad0f59995adde0dbe775115b1e357+          Windows:+            unknown_versioning:+              dlUri: https://github.com/haskell/haskell-language-server/releases/download/1.3.0/haskell-language-server-Windows-1.3.0.tar.gz+              dlHash: 961c6ff12c9a9c7a4609f239c5ac70d7d16753cdb8c10348a6a51feeaa0b6aea+          Linux_Alpine:+            unknown_versioning: *hls-130-64+  Stack:+    2.5.1:+      viTags:+        - old+      viChangeLog: https://github.com/commercialhaskell/stack/blob/master/ChangeLog.md#v251+      viPostInstall: &stack-post |+        Stack manages GHC versions internally by default. In order to make it use ghcup installed+        GHC versions you can run the following commands:+          stack config set install-ghc false --global+          stack config set system-ghc  true  --global+        +        On windows, you may find the following config options useful too:+          skip-msys, extra-path, extra-include-dirs, extra-lib-dirs++        Also check out: https://docs.haskellstack.org/en/stable/yaml_configuration++        !!! Additionally, you should upgrade stack only through ghcup and not use 'stack upgrade' !!!+      viArch:+        A_64:+          Linux_UnknownLinux:+            unknown_versioning: &stack-251-64+              dlUri: https://github.com/commercialhaskell/stack/releases/download/v2.5.1/stack-2.5.1-linux-x86_64.tar.gz+              dlHash: c83b6c93d6541c0bce2175085a04062020f4160a86116e20f3b343b562f2d1e8+              dlSubdir:+                RegexDir: "stack-.*"+          Darwin:+            unknown_versioning:+              dlUri: https://github.com/commercialhaskell/stack/releases/download/v2.5.1/stack-2.5.1-osx-x86_64.tar.gz+              dlHash: f4aedfa8fbe371f77286ee97ec5c3c553842e7ae15b2952a8b8442dccba04bf0+              dlSubdir:+                RegexDir: "stack-.*"+          Windows:+            unknown_versioning:+              dlUri: https://github.com/commercialhaskell/stack/releases/download/v2.5.1/stack-2.5.1-windows-x86_64.tar.gz+              dlHash: 57150b422cfd42249f5e629d0eb678df6d95dabe486ced57e8298d300b940d41+              dlSubdir:+                RegexDir: "stack-.*"+          Linux_Alpine:+            unknown_versioning: *stack-251-64+    2.7.1:+      viTags:+        - old+      viChangeLog: https://github.com/commercialhaskell/stack/blob/master/ChangeLog.md#v271+      viPostInstall: *stack-post+      viArch:+        A_64:+          Linux_UnknownLinux:+            unknown_versioning: &stack-271-64+              dlUri: https://github.com/commercialhaskell/stack/releases/download/v2.7.1/stack-2.7.1-linux-x86_64.tar.gz+              dlHash: 2bc47749ee4be5eccb52a2d4a6a00b0f3b28b92517742b40c675836d7db2777d+              dlSubdir:+                RegexDir: "stack-.*"+          Darwin:+            unknown_versioning:+              dlUri: https://github.com/commercialhaskell/stack/releases/download/v2.7.1/stack-2.7.1-osx-x86_64.tar.gz+              dlHash: 4248c6fbc87e8a2c06f39e867eb5ef28eae0d99470137cb415356c631c0dcbf2+              dlSubdir:+                RegexDir: "stack-.*"+          Windows:+            unknown_versioning:+              dlUri: https://github.com/commercialhaskell/stack/releases/download/v2.7.1/stack-2.7.1-windows-x86_64.tar.gz+              dlHash: 8452f5fc9235620a84863f2f68e5f681c72d0d181cde50482f178a966ee0ceb9+              dlSubdir:+                RegexDir: "stack-.*"+          Linux_Alpine:+            unknown_versioning: *stack-271-64+    2.7.3:+      viTags:+        - Latest+        - Recommended+      viChangeLog: https://github.com/commercialhaskell/stack/blob/master/ChangeLog.md#v273+      viPostInstall: *stack-post+      viArch:+        A_64:+          Linux_UnknownLinux:+            unknown_versioning: &stack-273-64+              dlUri: https://github.com/commercialhaskell/stack/releases/download/v2.7.3/stack-2.7.3-linux-x86_64.tar.gz+              dlHash: a6c090555fa1c64aa61c29aa4449765a51d79e870cf759cde192937cd614e72b+              dlSubdir:+                RegexDir: "stack-.*"+          Darwin:+            unknown_versioning:+              dlUri: https://github.com/commercialhaskell/stack/releases/download/v2.7.3/stack-2.7.3-osx-x86_64.tar.gz+              dlHash: 42e5000a00af44a7b26852421ac63ce75f510ad1a97742cb131107088ee9fe30+              dlSubdir:+                RegexDir: "stack-.*"+          Windows:+            unknown_versioning:+              dlUri: https://github.com/commercialhaskell/stack/releases/download/v2.7.3/stack-2.7.3-windows-x86_64.tar.gz+              dlHash: e6ba12e0ecabf0df2567d88a0d247da238bc114bcccfca4195f5e86472c9330c+              dlSubdir:+                RegexDir: "stack-.*"+          Linux_Alpine:+            unknown_versioning: *stack-273-64+
+ data/metadata/ghcup-0.0.6.yaml view
@@ -0,0 +1,2534 @@+---+globalTools:+  ShimGen:+    dlUri: https://downloads.haskell.org/~ghcup/shimgen/shim-2.exe+    dlHash: 7c55e201f71860c5babea886007c8fa44b861abf50d1c07e5677eb0bda387a70+toolRequirements:+  GHC:+    unknown_version:+      Linux_Debian:+        unknown_versioning:+          distroPKGs:+          - build-essential+          - curl+          - libffi-dev+          - libffi6+          - libgmp-dev+          - libgmp10+          - libncurses-dev+          - libncurses5+          - libtinfo5+          notes: ''+        ">= 11":+          distroPKGs:+          - build-essential+          - curl+          - libffi-dev+          - libffi7+          - libgmp-dev+          - libgmp10+          - libncurses-dev+          - libncurses5+          - libtinfo5+          notes: ''+      Linux_Ubuntu:+        unknown_versioning:+          distroPKGs:+          - build-essential+          - curl+          - libffi-dev+          - libffi6+          - libgmp-dev+          - libgmp10+          - libncurses-dev+          - libncurses5+          - libtinfo5+          notes: ''+        "( >= 20.04 && < 20.10 )":+          distroPKGs:+          - build-essential+          - curl+          - libffi-dev+          - libffi7+          - libgmp-dev+          - libgmp10+          - libncurses-dev+          - libncurses5+          - libtinfo5+          notes: ''+        "( >= 20.10 )":+          distroPKGs:+          - build-essential+          - curl+          - libffi-dev+          - libffi8ubuntu1+          - libgmp-dev+          - libgmp10+          - libncurses-dev+          - libncurses5+          - libtinfo5+          notes: ''+      Linux_CentOS:+        '( >= 7 && < 8 )':+          distroPKGs:+          - gcc+          - gmp+          - gmp-devel+          - make+          - ncurses+          - xz+          - perl+          notes: ''+        unknown_versioning:+          distroPKGs:+          - gcc+          - gmp+          - gmp-devel+          - make+          - ncurses+          - ncurses-compat-libs+          - xz+          - perl+          notes: ''+      Linux_Fedora:+        unknown_versioning:+          distroPKGs:+          - gcc+          - gmp+          - gmp-devel+          - make+          - ncurses+          - ncurses-compat-libs+          - xz+          - perl+          notes: ''+      Linux_Alpine:+        unknown_versioning:+          distroPKGs:+          - binutils-gold+          - curl+          - gcc+          - gmp-dev+          - libc-dev+          - libffi-dev+          - make+          - musl-dev+          - ncurses-dev+          - perl+          - tar+          - xz+          notes: ''+      Linux_UnknownLinux:+        unknown_versioning:+          distroPKGs: []+          notes: 'You need the following packages: curl g++ gcc gmp make ncurses realpath+            xz-utils. Consult your distro documentation on the exact names of those+            packages.'+      Darwin:+        unknown_versioning:+          distroPKGs: []+          notes: On OS X, in the course of running ghcup you will be given a dialog+            box to install the command line tools. Accept and the requirements will+            be installed for you. You will then need to run the command again.+      FreeBSD:+        unknown_versioning:+          distroPKGs:+          - curl+          - gcc+          - gmp+          - gmake+          - ncurses+          - perl5+          - libffi+          - libiconv+          notes: ''+      Windows:+        unknown_versioning:+          distroPKGs: []+          notes: On Windows, msys2 should already have been set up during the installation,+            so most users should just press ENTER.+            If you are installing manually, make sure to have a working mingw64 toolchain and+            shell.+ghcupDownloads:+  GHC:+    7.10.3:+      viTags:+      - base-4.8.2.0+      - old+      viChangeLog: https://downloads.haskell.org/~ghc/7.10.3/docs/html/users_guide/release-7-10-1.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-src.tar.xz+        dlSubdir: ghc-7.10.3+        dlHash: cf90cedce1c28fd0e2b9e72fe8a938756668d18ea1fcc884a19f698658ac4fef+      viPostRemove: &ghc-post-remove "After removing GHC you might also want to clean up your cabal store at: ~/.cabal/store/ghc-<ghcver>"+      viPostInstall: "GHC-7.10.3 may give linking errors on most modern distros. You may have to pass '--ghc-option=-optc-no-pie --ghc-option=-optl-no-pie' to cabal build/install. Also see https://gitlab.haskell.org/ghc/ghc/-/issues/18763"+      viArch:+        A_64:+          Linux_Debian:+            unknown_versioning: &ghc-7103-64-deb8+              dlUri: https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-x86_64-deb8-linux.tar.bz2+              dlSubdir: ghc-7.10.3+              dlHash: 01cfbad8dff1e8b34a5fdca8caeaf843b56e36af919e29cd68870d2588563db5+          Linux_Ubuntu:+            unknown_versioning: *ghc-7103-64-deb8+          Linux_Mint:+            unknown_versioning: *ghc-7103-64-deb8+          Linux_CentOS:+            unknown_versioning: &ghc-7103-64-centos+              dlUri: https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-x86_64-centos67-linux.tar.bz2+              dlSubdir: ghc-7.10.3+              dlHash: a8957f7a2fd81720c5d3dc403571d77d31115ff5f42edb2917c36d8e714220d4+          Linux_AmazonLinux:+            unknown_versioning: *ghc-7103-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-7103-64-deb8+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-x86_64-apple-darwin.tar.bz2+              dlSubdir: ghc-7.10.3+              dlHash: 80893e367e8318105f7db2064adf202e3d96b1f014e792b73e92f2cacf0b757a+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-x86_64-portbld-freebsd.tar.bz2+              dlSubdir: ghc-7.10.3+              dlHash: 2aa396edd2bb651f4bc7eef7a396913ea24923de5aafdc76df6295333e487e48+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-7.10.3+              dlHash: 63e1689fc9e2809ae4d7f422b4dc810052e54c9aa2afd08746e234180e711dde+        A_32:+          Linux_Debian:+            unknown_versioning: &ghc-7103-32-deb8+              dlUri: https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-i386-deb8-linux.tar.bz2+              dlSubdir: ghc-7.10.3+              dlHash: d2ccf072457fb100503f6f5430a1e3589ca525a97424263d036b0550bc277f0c+          Linux_Ubuntu:+            unknown_versioning: *ghc-7103-32-deb8+          Linux_Mint:+            unknown_versioning: *ghc-7103-32-deb8+          Linux_CentOS:+            unknown_versioning: &ghc-7103-32-centos+              dlUri: https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-i386-centos67-linux.tar.bz2+              dlSubdir: ghc-7.10.3+              dlHash: c50aa20275e8d1ba9148f380eb7598bc148143281fc17c9acd38ea7b325852bd+          Linux_AmazonLinux:+            unknown_versioning: *ghc-7103-32-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-7103-32-deb8+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-i386-portbld-freebsd.tar.bz2+              dlSubdir: ghc-7.10.3+              dlHash: 3dde05577c6f94dcb0ba201ebd53ab88553bbc9a3aa8e72237162ed7a9d588a3+    8.0.2:+      viTags:+      - base-4.9.1.0+      - old+      viChangeLog: https://downloads.haskell.org/~ghc/8.0.2/docs/html/users_guide/8.0.1-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.0.2/ghc-8.0.2-src.tar.xz+        dlSubdir: ghc-8.0.2+        dlHash: 11625453e1d0686b3fa6739988f70ecac836cadc30b9f0c8b49ef9091d6118b1+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 7 && < 8 )':+              dlUri: https://downloads.haskell.org/~ghc/8.0.2/ghc-8.0.2-x86_64-deb7-linux.tar.xz+              dlSubdir: ghc-8.0.2+              dlHash: b2f5c304b57ac5840a0d2ef763a3c6fa858c70840f749cfad12ed227da973c0a+            unknown_versioning: &ghc-802-64-deb8+              dlUri: https://downloads.haskell.org/~ghc/8.0.2/ghc-8.0.2-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.0.2+              dlHash: 5ee68290db00ca0b79d57bc3a5bdce470de9ce9da0b098a7ce6c504605856c8f+          Linux_Ubuntu:+            unknown_versioning: *ghc-802-64-deb8+          Linux_Mint:+            unknown_versioning: *ghc-802-64-deb8+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.0.2/ghc-8.0.2-x86_64-alpine-linux.tar.xz+              dlSubdir: ghc-8.0.2+              dlHash: 517783b660a27ebf95b2568d47292fd633d5f9a4de4c80ad1ccf05e1b9d7313f+          Linux_UnknownLinux:+            unknown_versioning: *ghc-802-64-deb8+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.0.2/ghc-8.0.2-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.0.2+              dlHash: ff50a2df9f002f33b9f09717ebf5ec5a47906b9b65cc57b1f9849f8b2e06788d+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.0.2/ghc-8.0.2-x86_64-portbld-freebsd.tar.xz+              dlSubdir: ghc-8.0.2+              dlHash: b36a20e5cae24d70bbb6116ae486f21811e9384f15d3892d260f02fba3e3bb8c+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.0.2/ghc-8.0.2-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-8.0.2+              dlHash: 8c42c1f4af995205b9816a1e97e2752fe758544c1f5fe77958cdcd319c9c2d53+        A_32:+          Linux_Debian:+            '( >= 7 && < 8 )':+              dlUri: https://downloads.haskell.org/~ghc/8.0.2/ghc-8.0.2-i386-deb7-linux.tar.xz+              dlSubdir: ghc-8.0.2+              dlHash: 07ead3a49f8c9df4b429e7a2f96f6f31bcab8d3ff8277a9aed0201d13ddad448+            unknown_versioning: &ghc-802-32-deb8+              dlUri: https://downloads.haskell.org/~ghc/8.0.2/ghc-8.0.2-i386-deb8-linux.tar.xz+              dlSubdir: ghc-8.0.2+              dlHash: 818621342a2161b8afcc995a0765816bb40aefbfa1db2c8a7d59c04d8b18228a+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.0.2/ghc-8.0.2-i386-alpine-linux.tar.xz+              dlSubdir: ghc-8.0.2+              dlHash: b4cd12a1048b2fff2f23c9eec0dd3a1174d54d017f8d79ec79af4534118e6881+          Linux_UnknownLinux:+            unknown_versioning: *ghc-802-32-deb8+    8.2.2:+      viTags:+      - base-4.10.1.0+      - old+      viChangeLog: https://downloads.haskell.org/~ghc/8.2.2/docs/html/users_guide/8.2.2-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-src.tar.xz+        dlSubdir: ghc-8.2.2+        dlHash: bb8ec3634aa132d09faa270bbd604b82dfa61f04855655af6f9d14a9eedc05fc+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 7 && < 8 )': &ghc-822-64-deb7+              dlUri: https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-x86_64-deb7-linux.tar.xz+              dlSubdir: ghc-8.2.2+              dlHash: cd7afbca54edf9890da9f432c63366556246c85c1198e40c99df5af01c555834+            unknown_versioning: &ghc-822-64-deb8+              dlUri: https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.2.2+              dlHash: 48e205c62b9dc1ccf6739a4bc15a71e56dde2f891a9d786a1b115f0286111b2a+          Linux_Ubuntu:+            unknown_versioning: *ghc-822-64-deb8+          Linux_Mint:+            unknown_versioning: *ghc-822-64-deb8+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.2.2/ghc-8.2.2-x86_64-alpine-linux.tar.xz+              dlSubdir: ghc-8.2.2+              dlHash: adcf3a320a3c402aba07ae9586990dc3c0b550e96aeffb1b9e194313d3ba716d+          Linux_UnknownLinux:+            unknown_versioning: *ghc-822-64-deb7+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.2.2+              dlHash: f90fcf62f7e0936a6dfc3601cf663729bfe9bbf85097d2d75f0a16f8c2e95c27+          FreeBSD:+            '( >= 10 && < 11 )':+              dlUri: https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-x86_64-portbld10_3-freebsd.tar.xz+              dlSubdir: ghc-8.2.2+              dlHash: 9e99aaeaec4b2c6d660d80246c0d4dbd41fda88f1eb7a908b29dc8fa8d663949+            '( >= 11 && < 12 )': &ghc-822-64-fbsd11+              dlUri: https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-x86_64-portbld11-freebsd.tar.xz+              dlSubdir: ghc-8.2.2+              dlHash: cd351c704b92b9af23994024df07de8ca7090ea7675d5c8b14b2be857a46d804+            unknown_versioning: *ghc-822-64-fbsd11+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-8.2.2+              dlHash: 1e033df2092aa546e763e7be63167720b32df64f76673ea1ce7ae7c9f564b223+        A_32:+          Linux_Debian:+            '( >= 7 && < 8 )':+              dlUri: https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-i386-deb7-linux.tar.xz+              dlSubdir: ghc-8.2.2+              dlHash: cd18766b1a9b74fc6c90003a719ecab158f281f9a755d8b1bd3fd764ba6947b5+            unknown_versioning: &ghc-822-32-deb8+              dlUri: https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-i386-deb8-linux.tar.xz+              dlSubdir: ghc-8.2.2+              dlHash: 9e67d72d76482e0ba91c718e727b00386a1a12a32ed719714976dc56ca8c8223+          Linux_Ubuntu:+            unknown_versioning: *ghc-822-32-deb8+          Linux_Mint:+            unknown_versioning: *ghc-822-32-deb8+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.2.2/ghc-8.2.2-i386-alpine-linux.tar.xz+              dlSubdir: ghc-8.2.2+              dlHash: 467534c32552cfd318753112dbc70af003693aad4b0081f2a07e61f5b5ea2c22+          Linux_UnknownLinux:+            unknown_versioning: *ghc-822-32-deb8+    8.4.1:+      viTags:+      - base-4.11.0.0+      - old+      viChangeLog: https://downloads.haskell.org/~ghc/8.4.1/docs/html/users_guide/8.4.1-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.4.1/ghc-8.4.1-src.tar.xz+        dlSubdir: ghc-8.4.1+        dlHash: 39ae2f25192408f355693e5a3c8b6ff613ddb7c4da998fdf26210143a61839d2+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.4.1/ghc-8.4.1-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.4.1+              dlHash: 427c77a934b30c3f1de992c38c072afb4323fe6fb30dbac919ca8cb6ae98fbd9+          Linux_Ubuntu:+            unknown_versioning: &ghc-841-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.4.1/ghc-8.4.1-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.4.1+              dlHash: 89328a013e64b9b56825a9071fea5616ddd623d37fd41e8fb913dfebc609e7ea+          Linux_Mint:+            unknown_versioning: *ghc-841-64-fedora+          Linux_Fedora:+            unknown_versioning: *ghc-841-64-fedora+          Linux_UnknownLinux:+            unknown_versioning: *ghc-841-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.4.1/ghc-8.4.1-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.4.1+              dlHash: d774e39f3a0105843efd06709b214ee332c30203e6c5902dd6ed45e36285f9b7+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.4.1/ghc-8.4.1-x86_64-portbld11-freebsd.tar.xz+              dlSubdir: ghc-8.4.1+              dlHash: e748daec098445c6190090fe32bb2817a1140553be5acd2188e1af05ad24e5aa+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.4.1/ghc-8.4.1-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-8.4.1+              dlHash: 328b013fc651d34e075019107e58bb6c8a578f0155cf3ad4557e6f2661b03131+        A_32:+          Linux_Debian:+            unknown_versioning: &ghc-841-32-deb8+              dlUri: https://downloads.haskell.org/~ghc/8.4.1/ghc-8.4.1-i386-deb8-linux.tar.xz+              dlSubdir: ghc-8.4.1+              dlHash: c56c589c76c7ddcb77cdbef885a811761e669d3e76868b723d5be56dedcd4f69+          Linux_Ubuntu:+            unknown_versioning: *ghc-841-32-deb8+          Linux_Mint:+            unknown_versioning: *ghc-841-32-deb8+          Linux_UnknownLinux:+            unknown_versioning: *ghc-841-32-deb8+    8.4.2:+      viTags:+      - base-4.11.1.0+      - old+      viChangeLog: https://downloads.haskell.org/~ghc/8.4.2/docs/html/users_guide/8.4.2-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.4.2/ghc-8.4.2-src.tar.xz+        dlSubdir: ghc-8.4.2+        dlHash: 01cc32f24a06bf3b2428351b6d7fec791e82d042426d29ad9e5a245b35f0047b+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 8 && < 9 )':+              dlUri: https://downloads.haskell.org/~ghc/8.4.2/ghc-8.4.2-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.4.2+              dlHash: 246f66eb56f4ad0f1c7755502cfc8f9972f2d067dede17e151f6f479c1f76fbd+            unknown_versioning: &ghc-842-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.4.2/ghc-8.4.2-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.4.2+              dlHash: 3f4f5bbd2cdab4e7015ada9196d8d9b3a1ad274293cef011f85c46854596cb57+          Linux_Ubuntu:+            unknown_versioning: &ghc-842-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.4.2/ghc-8.4.2-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.4.2+              dlHash: d057b5c833596dbe4ae5d0dc2994f6cc5d0f4c2a21ea1d7900821d165fd4e846+            '( >= 16 && < 19 )': *ghc-842-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-842-64-fedora+          Linux_Fedora:+            unknown_versioning: *ghc-842-64-fedora+          Linux_UnknownLinux:+            unknown_versioning: *ghc-842-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.4.2/ghc-8.4.2-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.4.2+              dlHash: 87469222042b9ac23f9db216a8d4e5107297bdbbb99df71eb4d9e7208455def2+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.4.2/ghc-8.4.2-x86_64-portbld-freebsd.tar.xz+              dlSubdir: ghc-8.4.2+              dlHash: e9ed417fdf94c2ff2c6e344ed16f332bf6b591511f6442c0d9ea94854882b66c+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.4.2/ghc-8.4.2-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-8.4.2+              dlHash: 797634aa9812fc6b2084a24ddb4fde44fa83a2f59daea82e0af81ca3dd323fde+        A_32:+          Linux_Debian:+            unknown_versioning: &ghc-842-32-deb8+              dlUri: https://downloads.haskell.org/~ghc/8.4.2/ghc-8.4.2-i386-deb8-linux.tar.xz+              dlSubdir: ghc-8.4.2+              dlHash: 2d849c30b4c1eac25dc74333501920921e22fa483153f404993808bbda93df05+          Linux_Ubuntu:+            unknown_versioning: *ghc-842-32-deb8+          Linux_Mint:+            unknown_versioning: *ghc-842-32-deb8+          Linux_UnknownLinux:+            unknown_versioning: *ghc-842-32-deb8+    8.4.3:+      viTags:+      - base-4.11.1.0+      - old+      viChangeLog: https://downloads.haskell.org/~ghc/8.4.3/docs/html/users_guide/8.4.3-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.4.3/ghc-8.4.3-src.tar.xz+        dlSubdir: ghc-8.4.3+        dlHash: ae47afda985830de8811243255aa3744dfb9207cb980af74393298b2b62160d6+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 8 && < 9 )':+              dlUri: https://downloads.haskell.org/~ghc/8.4.3/ghc-8.4.3-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.4.3+              dlHash: 30a402c6d4754a6c020e0547f19ae3ac42e907e35349aa932d347f73e421a8e2+            unknown_versioning: &ghc-843-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.4.3/ghc-8.4.3-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.4.3+              dlHash: 2e4f53afb872ad9c640f31aea283b3ff4c5028b65808a1920739900aef7d15c9+          Linux_Ubuntu:+            unknown_versioning: &ghc-843-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.4.3/ghc-8.4.3-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.4.3+              dlHash: 269e7a4d3f336491b88409a020998122b30a3a729af78d33be86d3b3f8000c3e+            '( >= 16 && < 19 )': *ghc-843-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-843-64-fedora+          Linux_Fedora:+            unknown_versioning: *ghc-843-64-fedora+          Linux_UnknownLinux:+            unknown_versioning: *ghc-843-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.4.3/ghc-8.4.3-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.4.3+              dlHash: af0b455f6c46b9802b4b48dad996619cfa27cc6e2bf2ce5532387b4a8c00aa64+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.4.3/ghc-8.4.3-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-8.4.3+              dlHash: 8a83cfbf9ae84de0443c39c93b931693bdf2a6d4bf163ffb41855f80f4bf883e+        A_32:+          Linux_Debian:+            unknown_versioning: &ghc-843-32-deb8+              dlUri: https://downloads.haskell.org/~ghc/8.4.3/ghc-8.4.3-i386-deb8-linux.tar.xz+              dlSubdir: ghc-8.4.3+              dlHash: f5763983a26dedd88b65a0b17267359a3981b83a642569b26334423f684f8b8c+          Linux_Ubuntu:+            unknown_versioning: *ghc-843-32-deb8+          Linux_Mint:+            unknown_versioning: *ghc-843-32-deb8+          Linux_UnknownLinux:+            unknown_versioning: *ghc-843-32-deb8+    8.4.4:+      viTags:+      - base-4.11.1.0+      viChangeLog: https://downloads.haskell.org/~ghc/8.4.4/docs/html/users_guide/8.4.4-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-src.tar.xz+        dlSubdir: ghc-8.4.4+        dlHash: 11117735a58e507c481c09f3f39ae5a314e9fbf49fc3109528f99ea7959004b2+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 8 && < 9 )':+              dlUri: https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.4.4+              dlHash: 4c2a8857f76b7f3e34ecba0b51015d5cb8b767fe5377a7ec477abde10705ab1a+            unknown_versioning: &ghc-844-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.4.4+              dlHash: 47c80a32d8f02838a2401414c94ba260d1fe82b7d090479994522242c767cc83+          Linux_Ubuntu:+            unknown_versioning: &ghc-844-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.4.4+              dlHash: 8ab2befddc14d1434d0aad0c5d3c7e0c2b78ff84caa3429fa62527bfc6b86095+            '( >= 16 && < 19 )': *ghc-844-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-844-64-fedora+          Linux_Fedora:+            unknown_versioning: *ghc-844-64-fedora+          Linux_CentOS:+            unknown_versioning: &ghc-844-64-centos+              dlUri: https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-x86_64-centos70-linux.tar.xz+              dlSubdir: ghc-8.4.4+              dlHash: 83a96650f5a92b1e4d7651d256d6438624342d40e780e68125033435a54cd674+          Linux_RedHat:+            unknown_versioning: *ghc-844-64-centos+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.4.4/ghc-8.4.4-x86_64-alpine-linux.tar.xz+              dlSubdir: ghc-8.4.4+              dlHash: 336affff8314d3dc5e85d9c09015ae2ba8a7658b459c8c8ae77ecaa551a56ae7+          Linux_AmazonLinux:+            unknown_versioning: *ghc-844-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-844-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.4.4+              dlHash: 28dc89ebd231335337c656f4c5ead2ae2a1acc166aafe74a14f084393c5ef03a+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-x86_64-portbld-freebsd11.tar.xz+              dlSubdir: ghc-8.4.4+              dlHash: 44fbd142d1c355d6110595c59c760e2c73866ff9259ec85ebf814edb244d1940+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-8.4.4+              dlHash: da29dbb0f1199611c7d5bb7b0dd6a7426ca98f67dfd6da1526b033cd3830dc05+        A_32:+          Linux_Debian:+            unknown_versioning: &ghc-844-32-deb8+              dlUri: https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-i386-deb8-linux.tar.xz+              dlSubdir: ghc-8.4.4+              dlHash: 678bafaabea6af70ba71ccf0210bb437f9f5591ec28ac1cbbbd5f7aa6894e450+          Linux_Ubuntu:+            unknown_versioning: *ghc-844-32-deb8+          Linux_Mint:+            unknown_versioning: *ghc-844-32-deb8+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.4.4/ghc-8.4.4-i386-alpine-linux.tar.xz+              dlSubdir: ghc-8.4.4+              dlHash: 892888d388ef5c9cadf5cfba1146d62237c25b9b066fb62fee940b2b285fd308+          Linux_UnknownLinux:+            unknown_versioning: *ghc-844-32-deb8+    8.6.1:+      viTags:+      - base-4.12.0.0+      - old+      viChangeLog: https://downloads.haskell.org/~ghc/8.6.1/docs/html/users_guide/8.6.1-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.6.1/ghc-8.6.1-src.tar.xz+        dlSubdir: ghc-8.6.1+        dlHash: 2c25c26d1e5c47c7cbb2a1d8e6456524033e7a71409184dd3125e3fc5a3c7036+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 8 && < 9 )':+              dlUri: https://downloads.haskell.org/~ghc/8.6.1/ghc-8.6.1-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.6.1+              dlHash: 6d8784401b7dd80c90fa17306ec0539920e3987399a2c7ef247989e53197dc42+            unknown_versioning: &ghc-861-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.6.1/ghc-8.6.1-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.6.1+              dlHash: 97d44f303868d74e4d13a2e99c82ffce3d25fd54c704675e5a1939e0d824dbf0+          Linux_Ubuntu:+            unknown_versioning: &ghc-861-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.6.1/ghc-8.6.1-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.6.1+              dlHash: da903fbcf11ee6c977a8b7dac3f04dbc098d674def587880b6624b8f32588beb+            '( >= 16 && < 19 )': *ghc-861-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-861-64-fedora+          Linux_Fedora:+            unknown_versioning: *ghc-861-64-fedora+          Linux_UnknownLinux:+            unknown_versioning: *ghc-861-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.6.1/ghc-8.6.1-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.6.1+              dlHash: 9692cdfd202b0e039ea0c3dde5dbf653736c836ca1df46504b179b572100808c+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.6.1/ghc-8.6.1-x86_64-portbld-freebsd.tar.xz+              dlSubdir: ghc-8.6.1+              dlHash: 51403b054a3a649039ac988e1d1112561f96750bfced63df864091a3fab36f08+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.6.1/ghc-8.6.1-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-8.6.1+              dlHash: 7316d9cb5e486460476754f872c7bac30ee2082e42f46da4342f872d10b88099+        A_32:+          Linux_Debian:+            unknown_versioning: &ghc-861-32-deb8+              dlUri: https://downloads.haskell.org/~ghc/8.6.1/ghc-8.6.1-i386-deb8-linux.tar.xz+              dlSubdir: ghc-8.6.1+              dlHash: 83573af96e3dec8f67c1a844512f92cbf7d51ae7ceca53d948fc2a3300abd05c+          Linux_Ubuntu:+            unknown_versioning: *ghc-861-32-deb8+          Linux_Mint:+            unknown_versioning: *ghc-861-32-deb8+          Linux_UnknownLinux:+            unknown_versioning: *ghc-861-32-deb8+    8.6.2:+      viTags:+      - base-4.12.0.0+      - old+      viChangeLog: https://downloads.haskell.org/~ghc/8.6.2/docs/html/users_guide/8.6.2-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.6.2/ghc-8.6.2-src.tar.xz+        dlSubdir: ghc-8.6.2+        dlHash: caaa819d21280ecde90a4773143dee188711e9ff175a27cfbaee56eb851d76d5+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            unknown_versioning: &ghc-862-64-deb8+              dlUri: https://downloads.haskell.org/~ghc/8.6.2/ghc-8.6.2-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.6.2+              dlHash: 13f96e8b83bb5bb60f955786ff9085744c24927a33be8a17773f84c7c248533a+          Linux_Ubuntu:+            unknown_versioning: &ghc-862-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.6.2/ghc-8.6.2-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.6.2+              dlHash: 702aa5dfa1639c37953ceb7571a5057d9fb0562aecb197b277953a037d78047d+            '( >= 16 && < 19 )': *ghc-862-64-deb8+          Linux_Mint:+            unknown_versioning: *ghc-862-64-fedora+          Linux_Fedora:+            unknown_versioning: *ghc-862-64-fedora+          Linux_UnknownLinux:+            unknown_versioning: *ghc-862-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.6.2/ghc-8.6.2-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.6.2+              dlHash: 8ec46a25872226dd7e5cf7271e3f3450c05f32144b96e6b9cb44cc4079db50dc+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.6.2/ghc-8.6.2-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-8.6.2+              dlHash: 9a398e133cab09ff2610834337355d4e26c35e0665403fb9ff8db79315f74d3d+        A_32:+          Linux_Debian:+            unknown_versioning: &ghc-862-32-deb8+              dlUri: https://downloads.haskell.org/~ghc/8.6.2/ghc-8.6.2-i386-deb8-linux.tar.xz+              dlSubdir: ghc-8.6.2+              dlHash: a288026d9ef22f7ac387edab6b29ef7dcb3b28945c8ea532a15c1fa35d4733ed+          Linux_Ubuntu:+            unknown_versioning: *ghc-862-32-deb8+          Linux_Mint:+            unknown_versioning: *ghc-862-32-deb8+          Linux_UnknownLinux:+            unknown_versioning: *ghc-862-32-deb8+    8.6.3:+      viTags:+      - base-4.12.0.0+      - old+      viChangeLog: https://downloads.haskell.org/~ghc/8.6.3/docs/html/users_guide/8.6.3-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.6.3/ghc-8.6.3-src.tar.xz+        dlSubdir: ghc-8.6.3+        dlHash: 9f9e37b7971935d88ba80426c36af14b1e0b3ec1d9c860f44a4391771bc07f23+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 8 && < 9 )':+              dlUri: https://downloads.haskell.org/~ghc/8.6.3/ghc-8.6.3-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.6.3+              dlHash: 291ca565374f4d51cc311488581f3279d3167a064fabfd4a6722fe2bd4532fd5+            unknown_versioning: &ghc-863-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.6.3/ghc-8.6.3-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.6.3+              dlHash: e7954c8ed9b422a09c6ab737e4a0865a2725d034ba0e272bd5c70db910797f99+          Linux_Ubuntu:+            unknown_versioning: &ghc-863-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.6.3/ghc-8.6.3-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.6.3+              dlHash: 52ae92f4e8bb2ac0b7847287ea3da37081f5f7bf8bbb7c78ac35fde537d1a89f+            '( >= 16 && < 19 )': *ghc-863-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-863-64-fedora+          Linux_Fedora:+            unknown_versioning: *ghc-863-64-fedora+          Linux_CentOS:+            unknown_versioning: &ghc-863-64-centos+              dlUri: https://downloads.haskell.org/~ghc/8.6.3/ghc-8.6.3-x86_64-centos7-linux.tar.xz+              dlSubdir: ghc-8.6.3+              dlHash: 355bd85c69933c31bbe99b4269ce719acfd0aad0b45e359ac39b9bb13996acc6+          Linux_RedHat:+            unknown_versioning: *ghc-863-64-centos+          Linux_AmazonLinux:+            unknown_versioning: *ghc-863-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-863-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.6.3/ghc-8.6.3-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.6.3+              dlHash: 79d069a1a7d74cfdd7ac2a2711c45d3ddc6265b988a0cefa342714b24f997fc1+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.6.3/ghc-8.6.3-x86_64-portbld-freebsd.tar.xz+              dlSubdir: ghc-8.6.3+              dlHash: bc2419fa180f8a7808c49775987866435995df9bdd9ce08bcd38352d63ba6031+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.6.3/ghc-8.6.3-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-8.6.3+              dlHash: 2fec383904e5fa79413e9afd328faf9bc700006c8c3d4bcdd8d4f2ccf0f7fa2a+        A_32:+          Linux_Debian:+            unknown_versioning: &ghc-863-32-deb8+              dlUri: https://downloads.haskell.org/~ghc/8.6.3/ghc-8.6.3-i386-deb8-linux.tar.xz+              dlSubdir: ghc-8.6.3+              dlHash: b57070ba8c70b1333a3e47ce124baf791be39c20a592954772532fd6dd51882f+          Linux_Ubuntu:+            unknown_versioning: *ghc-863-32-deb8+          Linux_Mint:+            unknown_versioning: *ghc-863-32-deb8+          Linux_UnknownLinux:+            unknown_versioning: *ghc-863-32-deb8+    8.6.4:+      viTags:+      - base-4.12.0.0+      - old+      viChangeLog: https://downloads.haskell.org/~ghc/8.6.4/docs/html/users_guide/8.6.4-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.6.4/ghc-8.6.4-src.tar.xz+        dlSubdir: ghc-8.6.4+        dlHash: 5b5d07e4463203a433c3ed3df461ba6cce11b6d2b9b264db31f3429075d0303a+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 8 && < 9 )':+              dlUri: https://downloads.haskell.org/~ghc/8.6.4/ghc-8.6.4-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.6.4+              dlHash: 34ef5fc8ddf2fc32a027180bea5b1c8a81ea840c87faace2977a572188d4b42d+            unknown_versioning: &ghc-864-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.6.4/ghc-8.6.4-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.6.4+              dlHash: ef74222ef3c01c3fc5b926f67e8b4ef612fe8efa40ac937317cff9b0eed8d863+          Linux_Ubuntu:+            unknown_versioning: &ghc-864-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.6.4/ghc-8.6.4-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.6.4+              dlHash: e0b1ada7a679d6c35f9d7a1192ed35fde054f3650bb0bd2570d103729ad3b846+            '( >= 16 && < 19 )': *ghc-864-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-864-64-fedora+          Linux_Fedora:+            unknown_versioning: *ghc-864-64-fedora+          Linux_UnknownLinux:+            unknown_versioning: *ghc-864-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.6.4/ghc-8.6.4-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.6.4+              dlHash: cccb58f142fe41b601d73690809f6089f7715b6a50a09aa3d0104176ab4db09e+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.6.4/ghc-8.6.4-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-8.6.4+              dlHash: e8d021b7a90772fc559862079da20538498d991956d7557b468ca19ddda22a08+        A_32:+          Linux_Debian:+            unknown_versioning: &ghc-864-32-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.6.4/ghc-8.6.4-i386-deb9-linux.tar.xz+              dlSubdir: ghc-8.6.4+              dlHash: 5e2ce88f4d13d23ac37e278e0c7b51c801008931359b9fa8a631d804d2da552c+          Linux_Ubuntu:+            unknown_versioning: *ghc-864-32-deb9+          Linux_Mint:+            unknown_versioning: *ghc-864-32-deb9+          Linux_UnknownLinux:+            unknown_versioning: *ghc-864-32-deb9+    8.6.5:+      viTags:+      - base-4.12.0.0+      viChangeLog: https://downloads.haskell.org/~ghc/8.6.5/docs/html/users_guide/8.6.5-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-src.tar.xz+        dlSubdir: ghc-8.6.5+        dlHash: 4d4aa1e96f4001b934ac6193ab09af5d6172f41f5a5d39d8e43393b9aafee361+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 8 && < 9 )':+              dlUri: https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.6.5+              dlHash: c419fd0aa9065fe4d2eb9a248e323860c696ddf3859749ca96a84938aee49107+            unknown_versioning: &ghc-865-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.6.5+              dlHash: bc75f5601a9f41d58b2ba161b9e28fad52143a7229060f1e084168d9b2e914df+          Linux_Ubuntu:+            unknown_versioning: &ghc-865-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.6.5+              dlHash: cf78b53eaf336083e7a05f4a3000afbae4abe5bbc77ef80cc40e09d04ac5b4a1+            '( >= 16 && < 19 )': *ghc-865-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-865-64-fedora+          Linux_Fedora:+            unknown_versioning: *ghc-865-64-fedora+          Linux_CentOS:+            unknown_versioning: &ghc-865-64-centos+              dlUri: https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-x86_64-centos7-linux.tar.xz+              dlSubdir: ghc-8.6.5+              dlHash: 80ab566f4411299f9e5922d60749ca80f989d697db19e03ed875619d699f0edf+          Linux_RedHat:+            unknown_versioning: *ghc-865-64-centos+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.6.5/ghc-8.6.5-x86_64-alpine-linux.tar.xz+              dlSubdir: ghc-8.6.5+              dlHash: b9d3ed7f7aa24ef2d58bb579252289caa0b8877adee3685e3af2fb73d440afdc+          Linux_AmazonLinux:+            unknown_versioning: *ghc-865-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-865-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.6.5+              dlHash: dfc1bdb1d303a87a8552aa17f5b080e61351f2823c2b99071ec23d0837422169+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.6.5/ghc-8.6.5-x86_64-portbld-freebsd.tar.xz+              dlSubdir: ghc-8.6.5+              dlHash: 83a3059a630d40a98e26cb5b520354e12094a96e36ba2f5ab002dad94cf2fb37+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-8.6.5+              dlHash: 457024c6ea43bdce340af428d86319931f267089398b859b00efdfe2fd4ce93f+        A_32:+          Linux_Debian:+            unknown_versioning: &ghc-865-32-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-i386-deb9-linux.tar.xz+              dlSubdir: ghc-8.6.5+              dlHash: 1cddb907393a669342b1a922dd16d505d9d93d50bd9433a54a8162f8701250dc+          Linux_Ubuntu:+            unknown_versioning: *ghc-865-32-deb9+          Linux_Mint:+            unknown_versioning: *ghc-865-32-deb9+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.6.5/ghc-8.6.5-i386-alpine-linux.tar.xz+              dlSubdir: ghc-8.6.5+              dlHash: 3737837550d9b177acfe150e3a3cd4545427ded020487c2ed5194d7b8f116349+          Linux_UnknownLinux:+            unknown_versioning: *ghc-865-32-deb9+        A_ARM64:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-aarch64-ubuntu18.04-linux.tar.xz+              dlSubdir: ghc-8.6.5+              dlHash: 1852589037e4b2805ab517bc430e25a3125c4a118a1674ffefbb443394a0c786+    8.8.1:+      viTags:+      - base-4.13.0.0+      - old+      viChangeLog: https://downloads.haskell.org/~ghc/8.8.1/docs/html/users_guide/8.8.1-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.8.1/ghc-8.8.1-src.tar.xz+        dlSubdir: ghc-8.8.1+        dlHash: 908a83d9b814da74585de9d39687189e6260ec3848131f9d9236cab8a123721a+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 8 && < 9 )':+              dlUri: https://downloads.haskell.org/~ghc/8.8.1/ghc-8.8.1-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.8.1+              dlHash: fd96eb851971fbc3332bf2fa7821732cfa8b37e5a076a69f6a06f83f0ea7ccc5+            unknown_versioning: &ghc-881-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.8.1/ghc-8.8.1-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.8.1+              dlHash: 620fd560535b63cac5f8c97354ccddf93fa940cca78e2d19f6f98b7e67c6a723+          Linux_Ubuntu:+            unknown_versioning: &ghc-881-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.8.1/ghc-8.8.1-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.8.1+              dlHash: 851a78df620bc056c34b252c97040d5755e294993fa8afa5429708b5229204d6+            '( >= 16 && < 19 )': *ghc-881-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-881-64-fedora+          Linux_Fedora:+            unknown_versioning: *ghc-881-64-fedora+          Linux_CentOS:+            unknown_versioning: &ghc-881-64-centos+              dlUri: https://downloads.haskell.org/~ghc/8.8.1/ghc-8.8.1-x86_64-centos7-linux.tar.xz+              dlSubdir: ghc-8.8.1+              dlHash: 6cdd34e4dbaeb801e805811f91cf43a2d5f64b22f884718ffbd3542a2f4dd14f+          Linux_RedHat:+            unknown_versioning: *ghc-881-64-centos+          Linux_AmazonLinux:+            unknown_versioning: *ghc-881-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-881-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.8.1/ghc-8.8.1-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.8.1+              dlHash: 38c8917b47c31bedf58c9305dfca3abe198d8d35570366f0773c4e2948bd8abe+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.8.1/ghc-8.8.1-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-8.8.1+              dlHash: 29e56e6af38017a5a76b2b6995a39d3988fa58131e4b55b62dd317ba7186ac9b+        A_32:+          Linux_Debian:+            unknown_versioning: &ghc-881-32-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.8.1/ghc-8.8.1-i386-deb9-linux.tar.xz+              dlSubdir: ghc-8.8.1+              dlHash: 3d3bb75aff2dd79ec87ace10483368681fbc328ff00ebf15edad33420f00f7f5+          Linux_Ubuntu:+            unknown_versioning: *ghc-881-32-deb9+          Linux_Mint:+            unknown_versioning: *ghc-881-32-deb9+          Linux_UnknownLinux:+            unknown_versioning: *ghc-881-32-deb9+    8.8.2:+      viTags:+      - base-4.13.0.0+      - old+      viChangeLog: https://downloads.haskell.org/~ghc/8.8.2/docs/html/users_guide/8.8.2-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.8.2/ghc-8.8.2-src.tar.xz+        dlSubdir: ghc-8.8.2+        dlHash: 01cea54d90686b97bcc9960b108beaffccd4336dee930dcf9beaf52b1f370a0b+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 8 && < 9 )':+              dlUri: https://downloads.haskell.org/~ghc/8.8.2/ghc-8.8.2-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.8.2+              dlHash: fbe69652eba75dadb758d00292247d17fb018c29cac5acd79843e56311256c9f+            unknown_versioning: &ghc-882-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.8.2/ghc-8.8.2-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.8.2+              dlHash: 7b2d66c2d5d8c15750da5833d3018634a5eb792a5662282e3abfeb112c2a1cc3+          Linux_Ubuntu:+            unknown_versioning: &ghc-882-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.8.2/ghc-8.8.2-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.8.2+              dlHash: dbe2db717b33460f790e155e487d2a31c9b21a9d245f0c9490ad65844c3ea21f+            '( >= 16 && < 19 )': *ghc-882-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-882-64-fedora+          Linux_Fedora:+            unknown_versioning: *ghc-882-64-fedora+          Linux_CentOS:+            unknown_versioning: &ghc-882-64-centos+              dlUri: https://downloads.haskell.org/~ghc/8.8.2/ghc-8.8.2-x86_64-centos7-linux.tar.xz+              dlSubdir: ghc-8.8.2+              dlHash: f065a017d7a38f235f186ffe32d8261a4fd39c7e945d5cde85c0984c2569db99+          Linux_RedHat:+            unknown_versioning: *ghc-882-64-centos+          Linux_AmazonLinux:+            unknown_versioning: *ghc-882-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-882-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.8.2/ghc-8.8.2-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.8.2+              dlHash: 25c5c1a70036abf3f22b2b19c10d26adfdb08e8f8574f89d4b2042de5947f990+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.8.2/ghc-8.8.2-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-8.8.2+              dlHash: e25d9b16ee62cafc7387af2cd021eea676a99cd2c32b83533b016162c63065d9+        A_32:+          Linux_Debian:+            unknown_versioning: &ghc-882-32-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.8.2/ghc-8.8.2-i386-deb9-linux.tar.xz+              dlSubdir: ghc-8.8.2+              dlHash: ad1c628082c32635a436905a7ff83eaa4246347d869be5ef6b33c3bf85e8f00c+          Linux_Ubuntu:+            unknown_versioning: *ghc-882-32-deb9+          Linux_Mint:+            unknown_versioning: *ghc-882-32-deb9+          Linux_UnknownLinux:+            unknown_versioning: *ghc-882-32-deb9+    8.8.3:+      viTags:+      - base-4.13.0.0+      - old+      viChangeLog: https://downloads.haskell.org/~ghc/8.8.3/docs/html/users_guide/8.8.3-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-src.tar.xz+        dlSubdir: ghc-8.8.3+        dlHash: e0dcc0aaf3e234c5978f29e6df62947e97720ab404ec0158343df211c5480f89+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 8 && < 9 )':+              dlUri: https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.8.3+              dlHash: 92b9fadc442976968d2c190c14e000d737240a7d721581cda8d8741b7bd402f0+            unknown_versioning: &ghc-883-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.8.3+              dlHash: 42fde2ef5a143e1e6b47ae8875162ea2d4d54b06f0f7fa32ee4f0eb86f2be7ad+          Linux_Ubuntu:+            unknown_versioning: &ghc-883-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.8.3+              dlHash: 45ee1de3bfc98cbcc4886b65fc7651ade2d3820aa85eac2dbe9bc7bf91e7c818+            '( >= 16 && < 19 )': *ghc-883-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-883-64-fedora+          Linux_Fedora:+            unknown_versioning: *ghc-883-64-fedora+          Linux_CentOS:+            unknown_versioning: &ghc-883-64-centos+              dlUri: https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-x86_64-centos7-linux.tar.xz+              dlSubdir: ghc-8.8.3+              dlHash: 4b2b5313f7c12b81e54efcb26705fa9e4ad5b98f2b58bfc76fb0c9ba1d55eb1f+          Linux_RedHat:+            unknown_versioning: *ghc-883-64-centos+          Linux_AmazonLinux:+            unknown_versioning: *ghc-883-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-883-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.8.3+              dlHash: 7016de90dd226b06fc79d0759c5d4c83c2ab01d8c678905442c28bd948dbb782+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.8.3/ghc-8.8.3-x86_64-portbld-freebsd.tar.xz+              dlSubdir: ghc-8.8.3+              dlHash: 569719075b4d14b3875a899df522090ae31e6fe085e6dffe518e875b09a2f0be+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-8.8.3+              dlHash: e22586762af0911c06e8140f1792e3ca381a3a482a20d67b9054883038b3a422+        A_32:+          Linux_Debian:+            unknown_versioning: &ghc-883-32-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-i386-deb9-linux.tar.xz+              dlSubdir: ghc-8.8.3+              dlHash: 441e2c7a4fc83ebf179712bd939b555cda7c6633545b7c8ac38049f9d85003ae+          Linux_Ubuntu:+            unknown_versioning: *ghc-883-32-deb9+          Linux_Mint:+            unknown_versioning: *ghc-883-32-deb9+          Linux_UnknownLinux:+            unknown_versioning: *ghc-883-32-deb9+        A_ARM64:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-aarch64-deb9-linux.tar.xz+              dlSubdir: ghc-8.8.3+              dlHash: 2a6821d0e7326cfa7670851702924bbab3b092415ba41247c37419158327eed9+    8.8.4:+      viTags:+      - base-4.13.0.0+      viChangeLog: https://downloads.haskell.org/~ghc/8.8.4/docs/html/users_guide/8.8.4-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.8.4/ghc-8.8.4-src.tar.xz+        dlSubdir: ghc-8.8.4+        dlHash: f0505e38b2235ff9f1090b51f44d6c8efd371068e5a6bb42a2a6d8b67b5ffc2d+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 8 && < 9 )':+              dlUri: https://downloads.haskell.org/~ghc/8.8.4/ghc-8.8.4-x86_64-deb8-linux.tar.xz+              dlSubdir: ghc-8.8.4+              dlHash: 51a36892f1264744195274187298d13ac62bce2da86d4ddf76d8054ab90f2feb+            unknown_versioning: &ghc-884-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.8.4/ghc-8.8.4-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.8.4+              dlHash: 4862559d221153caf978f4bf2c15a82c114d1e1f43b298b2ecff2ac94b586d20+          Linux_Ubuntu:+            unknown_versioning: &ghc-884-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.8.4/ghc-8.8.4-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.8.4+              dlHash: f32e37f8aa03e74bad533ae02f62dc27a4521e78199576af490888ba34b515db+            '( >= 16 && < 19 )': *ghc-884-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-884-64-fedora+          Linux_Fedora:+            unknown_versioning: *ghc-884-64-fedora+          Linux_CentOS:+            unknown_versioning: &ghc-884-64-centos+              dlUri: https://downloads.haskell.org/~ghc/8.8.4/ghc-8.8.4-x86_64-centos7-linux.tar.xz+              dlSubdir: ghc-8.8.4+              dlHash: a12aa4b1fd3c64240a8a6d15196d33e1c0e0d55b51ff78c387242126d0ef7910+          Linux_RedHat:+            unknown_versioning: *ghc-884-64-centos+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.8.4/ghc-8.8.4-x86_64-alpine-linux.tar.xz+              dlSubdir: ghc-8.8.4+              dlHash: 90c6a1661de7f20c7d169cd6270125035b3332063e45103ce028df0beecf434e+          Linux_AmazonLinux:+            unknown_versioning: *ghc-884-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-884-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.8.4/ghc-8.8.4-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.8.4+              dlHash: e80a789e9d8cfb41dd87f3284b75432427c4461c1731d220d04ead8733ccdb5e+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.8.4/ghc-8.8.4-x86_64-portbld-freebsd.tar.xz+              dlSubdir: ghc-8.8.4+              dlHash: 8cebe5ccf454e82acd1ff52ca57590d1ab0f3f44a981b46257ec12158c8c447e+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.8.4/ghc-8.8.4-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-8.8.4+              dlHash: d185055d2c8dc3bfe5b88afd59d6877eb1e722b672d1c9649f18296e148ed71f+        A_32:+          Linux_Debian:+            unknown_versioning: &ghc-884-32-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.8.4/ghc-8.8.4-i386-deb9-linux.tar.xz+              dlSubdir: ghc-8.8.4+              dlHash: 43dd954910c9027694312cef0aabc7774d102d0422b7172802cfb72f7d5da3a0+          Linux_Ubuntu:+            unknown_versioning: *ghc-884-32-deb9+          Linux_Mint:+            unknown_versioning: *ghc-884-32-deb9+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.8.4/ghc-8.8.4-i386-alpine-linux.tar.xz+              dlSubdir: ghc-8.8.4+              dlHash: 1d18e89ee031197e55c48683e78a7ffc67601ac5fd9f73aac555eb064b3859a2+          Linux_UnknownLinux:+            unknown_versioning: *ghc-884-32-deb9+    8.10.1:+      viTags:+      - base-4.14.0.0+      - old+      viChangeLog: https://downloads.haskell.org/~ghc/8.10.1/docs/html/users_guide/8.10.1-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-src.tar.xz+        dlSubdir: ghc-8.10.1+        dlHash: 4e3b07f83a266b3198310f19f71e371ebce97c769b14f0d688f4cbf2a2a1edf5+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-8101-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.10.1+              dlHash: d1cf7886f27af070f3b7dbe1975a78b43ef2d32b86362cbe953e79464fe70761+            '( >= 10 && < 11 )': &ghc-8101-64-deb10+              dlUri: https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-x86_64-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.1+              dlHash: c1e31d798b013699b3c0de4fda27fb4cda47f572df0e75e3bd598a3012060615+            unknown_versioning: *ghc-8101-64-deb9+          Linux_Ubuntu:+            unknown_versioning: &ghc-8101-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.10.1+              dlHash: 3c4cd72b4806045779739e8f5d1658e30e57123d88c2c8966422cdbcae448470+            '( >= 16 && < 19 )': *ghc-8101-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-8101-64-fedora+          Linux_Fedora:+            '( >= 27 && < 28 )': *ghc-8101-64-fedora+            unknown_versioning: *ghc-8101-64-fedora+          Linux_CentOS:+            '( >= 7 && < 8 )': &ghc-8101-64-centos+              dlUri: https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-x86_64-centos7-linux.tar.xz+              dlSubdir: ghc-8.10.1+              dlHash: 0618b94854edc6be5302489df905e627820b71be6b66c950f5e3088fe92df0a1+            unknown_versioning: *ghc-8101-64-centos+          Linux_RedHat:+            unknown_versioning: *ghc-8101-64-centos+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-x86_64-alpine3.10-linux-integer-simple.tar.xz+              dlSubdir: ghc-8.10.1-x86_64-unknown-linux+              dlHash: cb13b645d103e2fba2eb8dfcc4e5f2fbd9550c00c4df42f342b4210436dcb8a8+          Linux_AmazonLinux:+            unknown_versioning: *ghc-8101-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-8101-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.10.1+              dlHash: 65b1ca361093de4804a7e40b3e68178e1ef720f84f743641ec8d95e56a45b3a8+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.10.1/ghc-8.10.1-x86_64-portbld-freebsd.tar.xz+              dlSubdir: ghc-8.10.1+              dlHash: e8646ec9b60fd40aa9505ee055f22f04601290ab7a1342c2cf37c34de9d3f142+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-8.10.1+              dlHash: 38a3166ea50cccd5bae7e1680eae3aae2b4ae31b61f82a1d8168fb821f43bd67+        A_32:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-8101-32-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-i386-deb9-linux.tar.xz+              dlSubdir: ghc-8.10.1+              dlHash: 8b53eef2c827b5f634d72920a93c0c9dd66ea288691a2bfe28def45d3c686ee2+            unknown_versioning: *ghc-8101-32-deb9+          Linux_Ubuntu:+            unknown_versioning: *ghc-8101-32-deb9+          Linux_Mint:+            unknown_versioning: *ghc-8101-32-deb9+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.10.1/ghc-8.10.1-i386-alpine-linux.tar.xz+              dlSubdir: ghc-8.10.1+              dlHash: 7360cc6b29e9b4ab08f6ea5bc3bcca6f5c216933e81ef1620dcdd700f1fdb289+          Linux_UnknownLinux:+            unknown_versioning: *ghc-8101-32-deb9+        A_ARM64:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-aarch64-deb9-linux.tar.xz+              dlSubdir: ghc-8.10.1+              dlHash: c099011e07999db917e797fb5d89c31f075a562556ab99be8ab0accbf2a94db7+        A_ARM:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-armv7-deb9-linux.tar.xz+              dlSubdir: ghc-8.10.1+              dlHash: afe1bde2b0d6deb0320b9460fffe5d9427e302df85aec866b9c1458777d52b28+    8.10.2:+      viTags:+      - old+      - base-4.14.1.0+      viChangeLog: https://downloads.haskell.org/~ghc/8.10.2/docs/html/users_guide/8.10.2-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-src.tar.xz+        dlSubdir: ghc-8.10.2+        dlHash: 9c573a4621a78723950617c223559bdc325ea6a3409264aedf68f05510b0880b+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-8102-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.10.2+              dlHash: 4dbe3b479e76767bfeb4cbb7a4db8b761c4720266193483ca370b2ace3f10f7c+            '( >= 10 && < 11 )': &ghc-8102-64-deb10+              dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-x86_64-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.2+              dlHash: 94513d82c38c848f489113a75fa5ef4e5a8e3ecfaa74ca90e2620d2193ff1632+            unknown_versioning: *ghc-8102-64-deb9+          Linux_Ubuntu:+            unknown_versioning: &ghc-8102-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.10.2+              dlHash: 8c675da83e9b3c2f64ebb407b5f9ebb2c1f21aa5d701020614fdce644a542e3b+            '( >= 16 && < 19 )': *ghc-8102-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-8102-64-fedora+          Linux_Fedora:+            '( >= 27 && < 28 )': *ghc-8102-64-fedora+            unknown_versioning: *ghc-8102-64-fedora+          Linux_CentOS:+            '( >= 7 && < 8 )': &ghc-8102-64-centos+              dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-x86_64-centos7-linux.tar.xz+              dlSubdir: ghc-8.10.2+              dlHash: fd2dccd6f496915a5f962dab24e7eeb8bee49bcc38e74b17eac76159083538fa+            unknown_versioning: *ghc-8102-64-centos+          Linux_RedHat:+            unknown_versioning: *ghc-8102-64-centos+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-x86_64-alpine3.10-linux-integer-simple.tar.xz+              dlSubdir: ghc-8.10.2-x86_64-unknown-linux+              dlHash: 14d09a508f2a3a11875c140be8e6c5f6982ac5cd448f089ca10b7adc955fec76+          Linux_AmazonLinux:+            unknown_versioning: *ghc-8102-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-8102-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.10.2+              dlHash: edb772b00c0d7f18bb56ad27765162ee09c508104d40f82128c9114a02f6cfc2+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-x86_64-unknown-freebsd.tar.xz+              dlSubdir: ghc-8.10.2+              dlHash: 9e5957f3497f4b58ecd3699568d9caaa11a47a6d7e902032c261e450fa0f6686+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-8.10.2+              dlHash: dcae4c173b9896e07ff048de5509aa0a4537233150e06e5ce8848303dfadc176+        A_32:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-8102-32-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-i386-deb9-linux.tar.xz+              dlSubdir: ghc-8.10.2+              dlHash: 9dae2a86ad43d08f72c783542c944d1556b075aa20a8063efae5034ea88e7c2f+            unknown_versioning: *ghc-8102-32-deb9+          Linux_Ubuntu:+            unknown_versioning: *ghc-8102-32-deb9+          Linux_Mint:+            unknown_versioning: *ghc-8102-32-deb9+          Linux_UnknownLinux:+            unknown_versioning: *ghc-8102-32-deb9+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.10.2/ghc-8.10.2-i386-alpine-linux.tar.xz+              dlSubdir: ghc-8.10.2+              dlHash: 9ee1cf1e85e9536088b3c9e80e975074e525ea378cd4eb156071bbc4b7b38327+        A_ARM64:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-aarch64-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.2+              dlHash: 5cf24189077e6e2dce2aa16367ad8a53f603e751a15010dfb23d067206e55593+        A_ARM:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-armv7-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.2+              dlHash: bb9c97826b1f4d7a8ef8bce0616b612f1ded10480ef10fcf7fb4e6d10a6681c8+    8.10.3:+      viTags:+      - old+      - base-4.14.1.0+      viChangeLog: https://downloads.haskell.org/~ghc/8.10.3/docs/html/users_guide/8.10.3-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-src.tar.xz+        dlSubdir: ghc-8.10.3+        dlHash: ccdc8319549028a708d7163e2967382677b1a5a379ff94d948195b5cf46eb931+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-8103-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.10.3+              dlHash: 95e4aadea30701fe5ab84d15f757926d843ded7115e11c4cd827809ca830718d+            '( >= 10 && < 11 )': &ghc-8103-64-deb10+              dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-x86_64-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.3+              dlHash: c8f3d9f0e61a89eaba1d3ad8fb2eced1af0e81576811261b887993bee12538ac+            unknown_versioning: *ghc-8103-64-deb9+          Linux_Ubuntu:+            unknown_versioning: &ghc-8103-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.10.3+              dlHash: f8739b12008712d6b6a9ffc6c39f9d05af77ef3bcb932c9aff20fa0893c8c159+            '( >= 16 && < 19 )': *ghc-8103-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-8103-64-deb10+          Linux_Fedora:+            '( >= 27 && < 28 )': *ghc-8103-64-fedora+            unknown_versioning: *ghc-8103-64-fedora+          Linux_CentOS:+            '( >= 7 && < 8 )': &ghc-8103-64-centos+              dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-x86_64-centos7-linux.tar.xz+              dlSubdir: ghc-8.10.3+              dlHash: f562ca61979ff1d21e34e69e59028cb742a8eff8d84e46bbd3a750f2ac7d8ed1+            unknown_versioning: *ghc-8103-64-centos+          Linux_RedHat:+            unknown_versioning: *ghc-8103-64-centos+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-x86_64-alpine3.10-linux-integer-simple.tar.xz+              dlSubdir: ghc-8.10.3-x86_64-unknown-linux+              dlHash: 8506c478ebbfb5441c3c36c07c36fc8532cacb2b3e13c6733bd44cb17b3ce96c+          Linux_AmazonLinux:+            unknown_versioning: *ghc-8103-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-8103-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.10.3+              dlHash: 2635f35d76e44e69afdfd37cae89d211975cc20f71f784363b72003e59f22015+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-x86_64-portbld-freebsd.tar.xz+              dlSubdir: ghc-8.10.3+              dlHash: 749007e995104db05cf6e3ad5bc36238cab8afac8055145661e5730e8f8af040+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-8.10.3+              dlHash: 927a6c699533a115cd49772ef2c753d9af2c13bf9f0b2d3bd13645cc6a144ee3+        A_32:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-8103-32-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-i386-deb9-linux.tar.xz+              dlSubdir: ghc-8.10.3+              dlHash: f0addd2a16b705f58ff9e8702c3ddf3e2d6bd0d3555707b5b5095e51bafee7b1+            unknown_versioning: *ghc-8103-32-deb9+          Linux_Ubuntu:+            unknown_versioning: *ghc-8103-32-deb9+          Linux_Mint:+            unknown_versioning: *ghc-8103-32-deb9+          Linux_UnknownLinux:+            unknown_versioning: *ghc-8103-32-deb9+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.10.3/ghc-8.10.3-i386-alpine-linux.tar.xz+              dlSubdir: ghc-8.10.3+              dlHash: 309201cdefd2d13b8b3fd09c26c6137048c490d219a0a9c7407c3ce1d011f60c+        A_ARM64:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-aarch64-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.3+              dlHash: a531432d505a1fe886cdc8639d168eb1c92d76464c1270713e01ce81891bbadb+        A_ARM:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-armv7-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.3+              dlHash: b823b58cae36fbac0741680ca7605180fa4cf4c6ae439123d282184b94d32fd6+    8.10.4:+      viTags:+      - old+      - base-4.14.1.0+      viChangeLog: https://downloads.haskell.org/~ghc/8.10.4/docs/html/users_guide/8.10.4-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-src.tar.xz+        dlSubdir: ghc-8.10.4+        dlHash: 52af871b4e08550257d720c2944ac85727d0b948407cef1bebfe7508c224910e+      viPostRemove: *ghc-post-remove+      viPreCompile: &ghc-pre-compile "If you have autoconf >= 2.70 you'll need this patch https://gitlab.haskell.org/ghc/ghc/-/snippets/2040 (see the --patchdir option)"+      viArch:+        A_64:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-8104-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.10.4+              dlHash: 5694200a5c38f22c142baf850b1d2f3784211d2ec9302e11693259a1ae8e38b7+            '( >= 10 && < 11 )': &ghc-8104-64-deb10+              dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-x86_64-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.4+              dlHash: 816365565e9927459b035515a7db6a0db62f9796f327389b6f8a0035d12fbda0+            unknown_versioning: *ghc-8104-64-deb9+          Linux_Ubuntu:+            unknown_versioning: &ghc-8104-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.10.4+              dlHash: a189eed900a8717d6d7906bafd10b9a9a9688ad942d1c75e19df480376dff9ea+            '( >= 16 && < 19 )': *ghc-8104-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-8104-64-deb10+          Linux_Fedora:+            '( >= 27 && < 28 )': *ghc-8104-64-fedora+            unknown_versioning: *ghc-8104-64-fedora+          Linux_CentOS:+            '( >= 7 && < 8 )': &ghc-8104-64-centos+              dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-x86_64-centos7-linux.tar.xz+              dlSubdir: ghc-8.10.4+              dlHash: fb8a91f0cf06594172aff46c2f6f7486179e1c3760855c79fbdd3012598cc2cd+            unknown_versioning: *ghc-8104-64-centos+          Linux_RedHat:+            unknown_versioning: *ghc-8104-64-centos+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-x86_64-alpine3.10-linux-integer-simple.tar.xz+              dlSubdir: ghc-8.10.4-x86_64-unknown-linux+              dlHash: 74c2c07537832708502716ef4ec40019f8e552ddda13c8eadf8f7c4b03a79359+          Linux_AmazonLinux:+            unknown_versioning: *ghc-8104-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-8104-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.10.4+              dlHash: 725ecf6543e63b81a3581fb8c97afd21a08ae11bc0fa4f8ee25d45f0362ef6d5+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-x86_64-portbld-freebsd.tar.xz+              dlSubdir: ghc-8.10.4+              dlHash: c9776a2ccf9629b03e967206a507fcdcb6c5189800a626e9461ababf6733c357+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-8.10.4+              dlHash: e9175a276504c3390a5e0084954e6997d56078737dbe7158049518892cf6bfb2+        A_32:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-8104-32-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-i386-deb9-linux.tar.xz+              dlSubdir: ghc-8.10.4+              dlHash: 0022c5b9ac22825bb7b4745af3d92cef0ba1ecd01fab3ef387ddbd47146569ad+            unknown_versioning: *ghc-8104-32-deb9+          Linux_Ubuntu:+            unknown_versioning: *ghc-8104-32-deb9+          Linux_Mint:+            unknown_versioning: *ghc-8104-32-deb9+          Linux_UnknownLinux:+            unknown_versioning: *ghc-8104-32-deb9+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.10.4/ghc-8.10.4-i386-alpine-linux.tar.xz+              dlSubdir: ghc-8.10.4+              dlHash: 9161a98bed763692101854d83af69c1316030cfe5ee6f6acde283d04ef139735+        A_ARM64:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-aarch64-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.4+              dlHash: 249da6310be799a5eefe0579b6dae1701eb984afb980fe08309d19cf704038ed+        A_ARM:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-armv7-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.4+              dlHash: 0d18ef83593272f6196a41cc3abdc48dfe5e14372db75d71ea19fe35320c4e81+    8.10.5:+      viTags:+      - old+      - base-4.14.2.0+      viChangeLog: https://downloads.haskell.org/~ghc/8.10.5/docs/html/users_guide/8.10.5-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.10.5/ghc-8.10.5-src.tar.xz+        dlSubdir: ghc-8.10.5+        dlHash: f10941f16e4fbd98580ab5241b9271bb0851304560c4d5ca127e3b0e20e3076f+      viPostRemove: *ghc-post-remove+      viPreCompile: *ghc-pre-compile+      viPostInstall: &ghc-8105-post-install |+        GHC 8.10.5 and 8.10.6 have several issues on Darwin, e.g.+          https://gitlab.haskell.org/ghc/ghc/-/issues/19950+        Consider upgrading to 8.10.7 via+          ghcup install ghc --set 8.10.7+      viArch:+        A_64:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-8105-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.10.5/ghc-8.10.5-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.10.5+              dlHash: 15e71325c3bdfe3804be0f84c2fc5c913d811322d19b0f4d4cff20f29cdd804d+            '( >= 10 && < 11 )': &ghc-8105-64-deb10+              dlUri: https://downloads.haskell.org/~ghc/8.10.5/ghc-8.10.5-x86_64-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.5+              dlHash: bc623c20ca4c5c18e952071ba14aa0cfc5c94d34219bffaa615f7b491f376787+            unknown_versioning: *ghc-8105-64-deb9+          Linux_Ubuntu:+            unknown_versioning: &ghc-8105-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.10.5/ghc-8.10.5-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.10.5+              dlHash: 73528ebfb219b50aa9042ee51a0a2bd764828d605f058404989d0b645752d210+            '( >= 16 && < 19 )': *ghc-8105-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-8105-64-deb10+          Linux_Fedora:+            '( >= 27 && < 28 )': *ghc-8105-64-fedora+            unknown_versioning: *ghc-8105-64-fedora+          Linux_CentOS:+            '( >= 7 && < 8 )': &ghc-8105-64-centos+              dlUri: https://downloads.haskell.org/~ghc/8.10.5/ghc-8.10.5-x86_64-centos7-linux.tar.xz+              dlSubdir: ghc-8.10.5+              dlHash: 4cdb259ec74d1408dab45dab20dcedc21690f39921c2ea4546486fb3e81f4fbd+            unknown_versioning: *ghc-8105-64-centos+          Linux_RedHat:+            unknown_versioning: *ghc-8105-64-centos+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.5/ghc-8.10.5-x86_64-alpine3.10-linux-integer-simple.tar.xz+              dlSubdir: ghc-8.10.5-x86_64-unknown-linux+              dlHash: f4d7cd9ed12a4b8592219c9a63a86db1a256a09fa9e6ed755a60afc57dc782e2+          Linux_AmazonLinux:+            unknown_versioning: *ghc-8105-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-8105-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.5/ghc-8.10.5-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.10.5+              dlHash: ef0f47eff8962d58fa447123636cf8ef31c1e5b2d0ae90177d3388861ddf4a22+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghcup/unofficial-bindists/ghc/8.10.5/ghc-8.10.5-x86_64-portbld-freebsd.tar.xz+              dlSubdir: ghc-8.10.5+              dlHash: 11a0b490bfb2f57b5bc87c69c197542eafce1b4991cc22f625179a6c6e567834+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.5/ghc-8.10.5-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-8.10.5+              dlHash: 4443d989df4f2680f681a4d8b8db310ce9582d21743984016b0eb0163b0c9998+        A_32:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-8105-32-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.10.5/ghc-8.10.5-i386-deb9-linux.tar.xz+              dlSubdir: ghc-8.10.5+              dlHash: 0ccb5b2c1222374874795c35410754dd650f649b774872abbea2a4ef21ac9c9d+            unknown_versioning: *ghc-8105-32-deb9+          Linux_Ubuntu:+            unknown_versioning: *ghc-8105-32-deb9+          Linux_Mint:+            unknown_versioning: *ghc-8105-32-deb9+          Linux_UnknownLinux:+            unknown_versioning: *ghc-8105-32-deb9+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghcup/unofficial-bindists/ghc/8.10.5/ghc-8.10.5-i386-alpine-linux.tar.xz+              dlSubdir: ghc-8.10.5+              dlHash: 0e91abe61607f9375d4e252ee9c261e4856df396f60641bb1b880ab8a3a83ea7+        A_ARM64:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.5/ghc-8.10.5-aarch64-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.5+              dlHash: 9a085cd8a7f8e0ace21ac67dbf659a56fcf41564b48817ba42cd8a1aac7f0ddc+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.5/ghc-8.10.5-aarch64-apple-darwin.tar.xz+              dlSubdir: ghc-8.10.5+              dlHash: 03684e70ff03d041b9a4e0f84c177953a241ab8ec7a028c72fa21ac67e66cb09+        A_ARM:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.5/ghc-8.10.5-armv7-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.5+              dlHash: 56170d1a8450e18b7eb9c23c94723da352815b27ec250bb23742a62f16dcab6c+    8.10.6:+      viTags:+      - old+      - base-4.14.3.0+      viChangeLog: https://downloads.haskell.org/~ghc/8.10.6/docs/html/users_guide/8.10.6-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.10.6/ghc-8.10.6-src.tar.xz+        dlSubdir: ghc-8.10.6+        dlHash: 43afba72a533408b42c1492bd047b5e37e5f7204e41a5cedd3182cc841610ce9+      viPostRemove: *ghc-post-remove+      viPreCompile: *ghc-pre-compile+      viPostInstall: *ghc-8105-post-install+      viArch:+        A_64:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-8106-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.10.6/ghc-8.10.6-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.10.6+              dlHash: c14b631437ebc867f1fe1648579bc1dbe1a9b9ad31d7c801c3c77639523a83ae+            '( >= 10 && < 11 )': &ghc-8106-64-deb10+              dlUri: https://downloads.haskell.org/~ghc/8.10.6/ghc-8.10.6-x86_64-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.6+              dlHash: 95be925e310b8c419e1099d620a727a1ca2d8c918f33eb905a8221d7eb16467b+            unknown_versioning: *ghc-8106-64-deb9+          Linux_Ubuntu:+            unknown_versioning: &ghc-8106-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.10.6/ghc-8.10.6-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.10.6+              dlHash: c452b84565cfc07c476694dd0fd389ed6d2b83619490b3c238f6bded438eddb1+            '( >= 16 && < 19 )': *ghc-8106-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-8106-64-deb10+          Linux_Fedora:+            '( >= 27 && < 28 )': *ghc-8106-64-fedora+            unknown_versioning: *ghc-8106-64-fedora+          Linux_CentOS:+            '( >= 7 && < 8 )': &ghc-8106-64-centos+              dlUri: https://downloads.haskell.org/~ghc/8.10.6/ghc-8.10.6-x86_64-centos7-linux.tar.xz+              dlSubdir: ghc-8.10.6+              dlHash: 71bb69b7185cbb44a941f5214b241a55e158f69b103f10214a05de7845f77e45+            unknown_versioning: *ghc-8106-64-centos+          Linux_RedHat:+            unknown_versioning: *ghc-8106-64-centos+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.6/ghc-8.10.6-x86_64-alpine3.10-linux-integer-simple.tar.xz+              dlSubdir: ghc-8.10.6-x86_64-unknown-linux+              dlHash: f6c86909f665c9a01b9703450a500a5206a951ee43e6a0a227eebe1da0987d6a+          Linux_AmazonLinux:+            unknown_versioning: *ghc-8106-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-8106-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.6/ghc-8.10.6-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.10.6+              dlHash: 32ab41da04d56cae2297d6e45caa88180f99cec0e33f2756cfbc48c0c60b5721+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.6/ghc-8.10.6-x86_64-unknown-freebsd.tar.xz+              dlSubdir: ghc-8.10.6+              dlHash: 268b9c0c55c70b0ebd7848c0e6c7f6c743b2f3082fb19f17b753c2536c354241+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.6/ghc-8.10.6-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-8.10.6+              dlHash: ff62f4a245c2427a1a5e6f5f1c2ad7521f69f9274a27ffb17c76f252ca573f3b+        A_32:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-8106-32-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.10.6/ghc-8.10.6-i386-deb9-linux.tar.xz+              dlSubdir: ghc-8.10.6+              dlHash: 31f934423d7971b462eaa53cf87b15265d11420578c5a8a04304348cb90f1c13+            unknown_versioning: *ghc-8106-32-deb9+          Linux_Ubuntu:+            unknown_versioning: *ghc-8106-32-deb9+          Linux_Mint:+            unknown_versioning: *ghc-8106-32-deb9+          Linux_UnknownLinux:+            unknown_versioning: *ghc-8106-32-deb9+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghcup/unofficial-bindists/ghc/8.10.6/ghc-8.10.6-i386-alpine-linux.tar.xz+              dlSubdir: ghc-8.10.6+              dlHash: f29974a67d76b64d0eb58603d60424c684a871e3107cebe45cf5b9b85f83b4c0+        A_ARM64:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.6/ghc-8.10.6-aarch64-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.6+              dlHash: 1ea27a7776e3cbd0881ecf2eb03eb5176e2cef177a12271a1c33417f4fa48a59+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.6/ghc-8.10.6-aarch64-apple-darwin.tar.xz+              dlSubdir: ghc-8.10.6+              dlHash: 9e43fc3a39d2f2762262c63868653984e381e29eff6386f7325aad501b9190ad+        A_ARM:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.6/ghc-8.10.6-armv7-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.6+              dlHash: d54de8306aa8b33afabf2ac94408e1f82c8e982a2a3346168c071b92bdb464c0+    8.10.7:+      viTags:+      - Recommended+      - base-4.14.3.0+      viChangeLog: https://downloads.haskell.org/~ghc/8.10.7/docs/html/users_guide/8.10.7-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/8.10.7/ghc-8.10.7-src.tar.xz+        dlSubdir: ghc-8.10.7+        dlHash: e3eef6229ce9908dfe1ea41436befb0455fefb1932559e860ad4c606b0d03c9d+      viPostRemove: *ghc-post-remove+      viPreCompile: *ghc-pre-compile+      viArch:+        A_64:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-8107-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.10.7/ghc-8.10.7-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-8.10.7+              dlHash: ced9870ea351af64fb48274b81a664cdb6a9266775f1598a79cbb6fdd5770a23+            '( >= 10 && < 11 )': &ghc-8107-64-deb10+              dlUri: https://downloads.haskell.org/~ghc/8.10.7/ghc-8.10.7-x86_64-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.7+              dlHash: a13719bca87a0d3ac0c7d4157a4e60887009a7f1a8dbe95c4759ec413e086d30+            unknown_versioning: *ghc-8107-64-deb9+          Linux_Ubuntu:+            unknown_versioning: &ghc-8107-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/8.10.7/ghc-8.10.7-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-8.10.7+              dlHash: b6ed67049a23054a8042e65c9976d5e196e5ee4e83b29b2ee35c8a22ab1e5b73+            '( >= 16 && < 19 )': *ghc-8107-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-8107-64-deb10+          Linux_Fedora:+            '( >= 27 && < 28 )': *ghc-8107-64-fedora+            unknown_versioning: *ghc-8107-64-fedora+          Linux_CentOS:+            '( >= 7 && < 8 )': &ghc-8107-64-centos+              dlUri: https://downloads.haskell.org/~ghc/8.10.7/ghc-8.10.7-x86_64-centos7-linux.tar.xz+              dlSubdir: ghc-8.10.7+              dlHash: 262a50bfb5b7c8770e0d99f54d42e5876968da7bf93e2e4d6cfe397891a36d05+            unknown_versioning: *ghc-8107-64-centos+          Linux_RedHat:+            unknown_versioning: *ghc-8107-64-centos+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.7/ghc-8.10.7-x86_64-alpine3.10-linux-integer-simple.tar.xz+              dlSubdir: ghc-8.10.7-x86_64-unknown-linux+              dlHash: 16903df850ef73d5246f2ff169cbf57ecab76c2ac5acfa9928934282cfad575c+          Linux_AmazonLinux:+            unknown_versioning: *ghc-8107-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-8107-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.7/ghc-8.10.7-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-8.10.7+              dlHash: 287db0f9c338c9f53123bfa8731b0996803ee50f6ee847fe388092e5e5132047+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.7/ghc-8.10.7-x86_64-unknown-freebsd.tar.xz+              dlSubdir: ghc-8.10.7+              dlHash: 45e35d24bc700e1093efa39189e9fa01498069881aed2fa8779c011941a80da1+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.7/ghc-8.10.7-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-8.10.7+              dlHash: b6515b0ea3f7a6e34d92e7fcd0c1fef50d6030fe8f46883000185289a4b8ea9a+        A_32:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-8107-32-deb9+              dlUri: https://downloads.haskell.org/~ghc/8.10.7/ghc-8.10.7-i386-deb9-linux.tar.xz+              dlSubdir: ghc-8.10.7+              dlHash: fbfc1ef194f4e7a4c0da8c11cc69b17458a4b928b609b3622c97acc4acd5c5ab+            unknown_versioning: *ghc-8107-32-deb9+          Linux_Ubuntu:+            unknown_versioning: *ghc-8107-32-deb9+          Linux_Mint:+            unknown_versioning: *ghc-8107-32-deb9+          Linux_UnknownLinux:+            unknown_versioning: *ghc-8107-32-deb9+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghcup/unofficial-bindists/ghc/8.10.7/ghc-8.10.7-i386-alpine-linux.tar.xz+              dlSubdir: ghc-8.10.7+              dlHash: 3110e6ee029d9d8062158b54b06f71a21b0fac87bf0e085f9be5bbcf73f99e6d+        A_ARM64:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.7/ghc-8.10.7-aarch64-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.7+              dlHash: fad2417f9b295233bf8ade79c0e6140896359e87be46cb61cd1d35863d9d0e55+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.7/ghc-8.10.7-aarch64-apple-darwin.tar.xz+              dlSubdir: ghc-8.10.7+              dlHash: dc469fc3c35fd2a33a5a575ffce87f13de7b98c2d349a41002e200a56d9bba1c+        A_ARM:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/8.10.7/ghc-8.10.7-armv7-deb10-linux.tar.xz+              dlSubdir: ghc-8.10.7+              dlHash: 3949c31bdf7d3b4afb765ea8246bca4ca9707c5d988d9961a244f0da100956a2+    9.0.1:+      viTags:+      - Latest+      - base-4.15.0.0+      viChangeLog: https://downloads.haskell.org/~ghc/9.0.1/docs/html/users_guide/9.0.1-notes.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-src.tar.xz+        dlSubdir: ghc-9.0.1+        dlHash: a5230314e4065f9fcc371dfe519748fd85c825b279abf72a24e09b83578a35f9+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-901-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-9.0.1+              dlHash: 4ca6252492f59fe589029fadca4b6f922d6a9f0ff39d19a2bd9886fde4e183d5+            '( >= 10 && < 11 )': &ghc-901-64-deb10+              dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-x86_64-deb10-linux.tar.xz+              dlSubdir: ghc-9.0.1+              dlHash: c253e7eb62cc9da6524c491c85ec8d3727c2ca6035a8653388e636aaa30a2a0f+            unknown_versioning: *ghc-901-64-deb9+          Linux_Ubuntu:+            unknown_versioning: &ghc-901-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-9.0.1+              dlHash: 1fb8e27eeec51b4cdbfd1b3c16727adc5f77388d3e925e63799d8232647f316d+            '( >= 16 && < 19 )': *ghc-901-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-901-64-deb10+          Linux_Fedora:+            '( >= 27 && < 28 )': *ghc-901-64-fedora+            unknown_versioning: *ghc-901-64-fedora+          Linux_CentOS:+            '( >= 7 && < 8 )': &ghc-901-64-centos+              dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-x86_64-centos7-linux.tar.xz+              dlSubdir: ghc-9.0.1+              dlHash: a23750950b6995a66ba59afe82bbc505bd3479d6ab59cf66f45bc6c056e4d87b+            unknown_versioning: *ghc-901-64-centos+          Linux_RedHat:+            unknown_versioning: *ghc-901-64-centos+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-x86_64-alpine3.10-linux-integer-simple.tar.xz+              dlSubdir: ghc-9.0.1-x86_64-unknown-linux+              dlHash: 7c1a0154c9e361b75be6cb0305533bb8a3b963c54e8092ffd1759e5710805a5c+          Linux_AmazonLinux:+            unknown_versioning: *ghc-901-64-centos+          Linux_UnknownLinux:+            unknown_versioning: *ghc-901-64-fedora+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-9.0.1+              dlHash: 122d60509147d0117779d275f0215bde2ff63a64cda9d88f149432d0cae71b22+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-x86_64-portbld-freebsd.tar.xz+              dlSubdir: ghc-9.0.1+              dlHash: 9dbc06d8832cae5c9f86dd7b2db729b3748a47beb4fd4b1e62bb66119817c3c1+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-9.0.1-x86_64-unknown-mingw32+              dlHash: 4f4ab118df01cbc7e7c510096deca0cb25025339a97730de0466416296202493+        A_32:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-901-32-deb9+              dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-i386-deb9-linux.tar.xz+              dlSubdir: ghc-9.0.1+              dlHash: 880e37cea8328401bcfecfe4bb56eb85195f30135b140140b3f24094264f8ba5+            unknown_versioning: *ghc-901-32-deb9+          Linux_Ubuntu:+            unknown_versioning: *ghc-901-32-deb9+          Linux_Mint:+            unknown_versioning: *ghc-901-32-deb9+          Linux_UnknownLinux:+            unknown_versioning: *ghc-901-32-deb9+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/9.0.1/ghc-9.0.1-i386-alpine-linux.tar.xz+              dlSubdir: ghc-9.0.1+              dlHash: ebfeb3b91e6f2bb5a49fd3376746f7fd1b89e62e9838bf5b1530a8756ff1e6aa+        A_ARM64:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-aarch64-deb9-linux.tar.xz+              dlSubdir: ghc-9.0.1+              dlHash: fac7a0bdfc83c05df94024a2d67b8f00a9cd2733b9cb41fb8ad76be399014906+        A_ARM:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-armv7-deb9-linux.tar.xz+              dlSubdir: ghc-9.0.1+              dlHash: 6f404f9b88468407b3a9ec5800bcc2d01dd453ef3d63414853b4fbbd4d8df496+    9.2.0.20210821:+      viTags:+      - Prerelease+      - base-4.16.0.0+      viChangeLog: https://downloads.haskell.org/~ghc/9.2.1-rc1/docs/html/users_guide/index.html+      viSourceDL:+        dlUri: https://downloads.haskell.org/~ghc/9.2.1-rc1/ghc-9.2.0.20210821-src.tar.xz+        dlSubdir: ghc-9.2.0.20210821+        dlHash: 7c4772d9a22a1774a13f67a570719c339f744b1607fbddfdf4702bb1fbbd57e0+      viPostRemove: *ghc-post-remove+      viArch:+        A_64:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-921-rc1-64-deb9+              dlUri: https://downloads.haskell.org/~ghc/9.2.1-rc1/ghc-9.2.0.20210821-x86_64-deb9-linux.tar.xz+              dlSubdir: ghc-9.2.0.20210821+              dlHash: 4a561cb97f0cbe51de676d4e29968d49beb415a0190514d8f1a8f8ae0405f313+            '( >= 10 && < 11 )': &ghc-921-rc1-64-deb10+              dlUri: https://downloads.haskell.org/~ghc/9.2.1-rc1/ghc-9.2.0.20210821-x86_64-deb10-linux.tar.xz+              dlSubdir: ghc-9.2.0.20210821+              dlHash: 28112271739b490635e7fd6ed1936949c3a3c41d4a7d95833bb47f420dd1a815+            unknown_versioning: *ghc-921-rc1-64-deb9+          Linux_Ubuntu:+            unknown_versioning: &ghc-921-rc1-64-fedora+              dlUri: https://downloads.haskell.org/~ghc/9.2.1-rc1/ghc-9.2.0.20210821-x86_64-fedora27-linux.tar.xz+              dlSubdir: ghc-9.2.0.20210821+              dlHash: 3c4d3874e4438baf54bdf8bcbdca60a7416ca88c32da1823127dd3159bbede62+            '( >= 16 && < 19 )': *ghc-921-rc1-64-deb9+          Linux_Mint:+            unknown_versioning: *ghc-921-rc1-64-deb10+          Linux_Fedora:+            '( >= 27 && < 28 )': *ghc-921-rc1-64-fedora+            unknown_versioning: *ghc-921-rc1-64-fedora+          Linux_UnknownLinux:+            unknown_versioning: *ghc-921-rc1-64-fedora+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/9.2.1-rc1/ghc-9.2.0.20210821-x86_64-unknown-freebsd.tar.xz+              dlSubdir: ghc-9.2.0.20210821+              dlHash: ed31d0ca40588fcbed4f03e83e49abea7babb37e528bb36ab3c1fb6191c4c422+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/9.2.1-rc1/ghc-9.2.0.20210821-x86_64-apple-darwin.tar.xz+              dlSubdir: ghc-9.2.0.20210821-x86_64-apple-darwin+              dlHash: 38199ca35117cc1f4372a4b6692596f8639688c286d2a0d09bc7336826c05e10+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/9.2.1-rc1/ghc-9.2.0.20210821-x86_64-unknown-mingw32.tar.xz+              dlSubdir: ghc-9.2.0.20210821-x86_64-unknown-mingw32+              dlHash: 3926620698cb43b9e9a5381b4c3b7b84d22c67b3509a546581aa17afecd6a846+        A_32:+          Linux_Debian:+            '( >= 9 && < 10 )': &ghc-921-rc1-32-deb9+              dlUri: https://downloads.haskell.org/~ghc/9.2.1-rc1/ghc-9.2.0.20210821-i386-deb9-linux.tar.xz+              dlSubdir: ghc-9.2.0.20210821+              dlHash: 30b25b787a787473988a785606b01099ce077f99d5c08940c0024537433f5084+            unknown_versioning: *ghc-921-rc1-32-deb9+          Linux_Ubuntu:+            unknown_versioning: *ghc-921-rc1-32-deb9+          Linux_Mint:+            unknown_versioning: *ghc-921-rc1-32-deb9+          Linux_UnknownLinux:+            unknown_versioning: *ghc-921-rc1-32-deb9+        A_ARM64:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/9.2.1-rc1/ghc-9.2.0.20210821-aarch64-deb10-linux.tar.xz+              dlSubdir: ghc-9.2.0.20210821+              dlHash: 289fc361be4a3199ac15449e30405a9831454811dd454e81eab73bfcdd2c4088+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/9.2.1-rc1/ghc-9.2.0.20210821-aarch64-apple-darwin.tar.xz+              dlSubdir: ghc-9.2.0.20210821-aarch64-apple-darwin+              dlHash: 0d763fb619cfa32fa37c113c446e13bebc2215db5946e5fa8fd8400559cf4152+        A_ARM:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghc/9.2.1-rc1/ghc-9.2.0.20210821-armv7-deb10-linux.tar.xz+              dlSubdir: ghc-9.2.0.20210821+              dlHash: 9ff0be63191181700a1f51c453056c2dab16e11ecb7a4b1dd72e4b7aad5999a6+  Cabal:+    2.4.1.0:+      viTags:+        - old+      viChangeLog: https://downloads.haskell.org/~cabal/cabal-install-2.4.1.0/changelog+      viArch:+        A_64:+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-2.4.1.0/cabal-install-2.4.1.0-x86_64-alpine-linux-musl.tar.xz+              dlSubdir:+              dlHash: 720bef015f834a03deb7180be2952a44e7c2e6c8429137570404c3de4f46b984+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-2.4.1.0/cabal-install-2.4.1.0-x86_64-unknown-linux.tar.xz+              dlSubdir:+              dlHash: 6136c189ffccaa39916f9cb5788f757166444a2d0c473b987856a79ecbf0c714+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-2.4.1.0/cabal-install-2.4.1.0-x86_64-apple-darwin-sierra.tar.xz+              dlSubdir:+              dlHash: 56361cf4b0d920fe23174751fea1fb82a8e1ce522bd9706a3fbe47a72e458c9c+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-2.4.1.0/cabal-install-2.4.1.0-x86_64-portbld-freebsd.tar.xz+              dlSubdir:+              dlHash: 33b7d37ea0688c93436eac9ec139d9967687875aa1fa13f2bb73bf05a9a59a1d+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-2.4.1.0/cabal-install-2.4.1.0-x86_64-unknown-mingw32.zip+              dlSubdir:+              dlHash: 95f233efedb1ebf0e6db015fa2f55c1ed00b9938d207ec63c066f706fb4b6373+        A_32:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-2.4.1.0/cabal-install-2.4.1.0-i386-unknown-linux.tar.xz+              dlSubdir:+              dlHash: b2da736cc27609442b10f77fc1a687aba603a7a33045b722dbf1a0066fade198+    3.0.0.0:+      viTags:+        - old+      viChangeLog: https://downloads.haskell.org/~cabal/cabal-install-3.0.0.0/changelog+      viArch:+        A_64:+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.0.0.0/cabal-install-3.0.0.0-x86_64-alpine-linux-musl.tar.xz+              dlHash: 2b7ea63601e11a0db2941b96e6a7036a48efc2a1ab3849d7dfce08b45f5daa58+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.0.0.0/cabal-install-3.0.0.0-x86_64-unknown-linux.tar.xz+              dlHash: ee911ba67a70756eedeac662955b896d7e89432a99372aa45d2c6e71fa95a5e4+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.0.0.0/cabal-install-3.0.0.0-x86_64-apple-darwin17.7.0.tar.xz+              dlHash: d4857e068560515e4cbb0e8ca124c370e07892f2a28804d87152834e5fe2b845+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.0.0.0/cabal-install-3.0.0.0-x86_64-portbld-freebsd.tar.xz+              dlHash: 2240842ab2ae7b955feb8b526aba1c7991248c803383107adf39990441294d2a+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.0.0.0/cabal-install-3.0.0.0-x86_64-unknown-mingw32.zip+              dlSubdir:+              dlHash: 8889963ebef5e829d86329fdb59832c107efd117cf7862a605f2fe2d2360de1f+        A_32:+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.0.0.0/cabal-install-3.0.0.0-i386-alpine-linux-musl.tar.xz+              dlHash: ac018f061993d40bf146517e32629bcab274b4d9f5527b1c37a665ebdf3f5ac6+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.0.0.0/cabal-install-3.0.0.0-i386-unknown-linux.tar.xz+              dlHash: 6898ccd6e6dc0872999c06daaf61d546164e12f60a1880d09852c9f0c59c5cf6+    3.2.0.0:+      viTags:+      - old+      viChangeLog: https://downloads.haskell.org/~cabal/cabal-install-3.2.0.0/changelog+      viArch:+        A_64:+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.2.0.0/cabal-install-3.2.0.0-x86_64-alpine-linux-musl.tar.xz+              dlHash: 8bae37a1ce8b5f10440b5591fed734935e1411c1b765258325ffe268e2cc2042+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.2.0.0/cabal-install-3.2.0.0-x86_64-unknown-linux.tar.xz+              dlHash: 32d1f7cf1065c37cb0ef99a66adb405f409b9763f14c0926f5424ae408c738ac+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.2.0.0/cabal-install-3.2.0.0-x86_64-apple-darwin17.7.0.tar.xz+              dlHash: 9197c17d2ece0f934f5b33e323cfcaf486e4681952687bc3d249488ce3cbe0e9+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.2.0.0/cabal-install-3.2.0.0-x86_64-portbld-freebsd.tar.xz+              dlHash: f1e35151cca91541b0fb4bdb3ed18f3c348038eab751845ad19c11307d66c273+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.2.0.0/cabal-install-3.2.0.0-x86_64-unknown-mingw32.zip+              dlSubdir:+              dlHash: 17778c3ade0482bc37f451eec326f8fce8fbe1f12b1d6aacb2e2b9e34786c054+        A_32:+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.2.0.0/cabal-install-3.2.0.0-i386-alpine-linux-musl.tar.xz+              dlHash: c2a419dedf730987b60daf8d24e871d115a09ea608d740d7c61b36e3f5b9c830+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.2.0.0/cabal-install-3.2.0.0-i386-unknown-linux.tar.xz+              dlHash: 2b3ac28549916de5f3379241797eaf60e84b6c001f2abbe73d9fadbbaf768e93+    3.4.0.0:+      viTags: []+      viChangeLog: https://github.com/haskell/cabal/blob/master/release-notes/cabal-install-3.4.0.0.md+      viArch:+        A_64:+          Linux_Ubuntu:+            unknown_versioning: &cabal-3400-ubuntu+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.4.0.0/cabal-install-3.4.0.0-x86_64-ubuntu-16.04.tar.xz+              dlHash: cf28f9ffd763476aa2b1730d85cbf155d366fac541f78ee3951e8cb2d6de63e6+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.4.0.0/cabal-install-3.4.0.0-x86_64-alpine-3.11.6-static-noofd.tar.xz+              dlHash: c74073fe79110946182e522fcadc8dcabf07c87583e8cf7801ed4e0c327241f6+          Linux_UnknownLinux:+            unknown_versioning: *cabal-3400-ubuntu+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.4.0.0/cabal-install-3.4.0.0-x86_64-darwin-sierra.tar.xz+              dlHash: cb10be9a53e856aa2d852fd88fb6944f138783ffe0ea84d93c9a69244e34ea91+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.4.0.0/cabal-install-3.4.0.0-x86_64-freebsd-12.1-release.tar.xz+              dlHash: a1e2db664ec00e42a1e071a4181f6476f6e0bad321f1ddc0cf27831119f4c6d4+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghcup/unofficial-bindists/cabal/3.4.0.0/cabal-install-3.4.0.0-x86_64-windows.zip+              dlSubdir:+              dlHash: c898496b199a3ebf41fb399c12a0cb55a470a67e758cee4b08b9f304c4be6979+        A_32:+          Linux_UnknownLinux:+            unknown_versioning: &cabal-3400-32+              dlUri: https://downloads.haskell.org/~ghcup/unofficial-bindists/cabal/3.4.0.0/cabal-install-3.4.0.0-i386-unknown-linux.tar.xz+              dlHash: cc62a471e9e68a6a9933e54f75bf0cffae67a1d2220df1152ab887c38eb6bc8a+          Linux_Alpine:+            unknown_versioning: *cabal-3400-32+        A_ARM64:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.4.0.0/cabal-install-3.4.0.0-aarch64-ubuntu-18.04.tar.xz+              dlHash: 04d378347896dfdc3510b192b97489815cfa5d692f46e2758da0f789e682b8f0+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghcup/unofficial-bindists/cabal/3.4.0.0/cabal-install-3.4.0.0-aarch64-darwin-big-sur.tar.xz+              dlHash: 46d8f96446a6bcdb81b3a9fbc14b137dc4f08436b46fe6446c5fba7bcb9b3d75++        A_ARM:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghcup/unofficial-bindists/cabal/3.4.0.0/cabal-install-3.4.0.0-armv7-linux-bootstrapped.tar.xz+              dlHash: 16c0d1eaba24bed14f3e152970179a45d9f9bb5cc839b2c210ad06eb7d4826ed+    3.6.0.0:+      viTags:+      - Recommended+      - Latest+      viChangeLog: https://github.com/haskell/cabal/blob/master/release-notes/cabal-install-3.6.0.0.md+      viArch:+        A_64:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.6.0.0/cabal-install-3.6.0.0-x86_64-linux.tar.xz+              dlHash: bfcb7350966dafe95051b5fc9fcb989c5708ab9e78191e71fc04647061668a11+          Linux_Alpine:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.6.0.0/cabal-install-3.6.0.0-x86_64-linux-alpine.tar.xz+              dlHash: 3203d71b7ee87fc9dce74b452ae07f420afe8817b5e6f84e54798442f4ccdda8+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.6.0.0/cabal-install-3.6.0.0-x86_64-darwin.tar.xz+              dlHash: 8e1367a4a1fc86ff0fd82ee057320a7b974595ba7999457b42035467ba06190c+          FreeBSD:+            '( >= 12 && < 13 )':+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.6.0.0/cabal-install-3.6.0.0-x86_64-freebsd.tar.xz+              dlHash: 56b5b37396c16a29f164a6963f24bd88f09e1d37448542ed61a683325f0a868b+            '( >= 13 )':+              dlUri: https://downloads.haskell.org/~ghcup/unofficial-bindists/cabal/3.6.0.0/cabal-install-3.6.0.0-x86_64-freebsd13.tar.xz+              dlHash: a283aa498702a3e286aa08e004c2a389538cbb47ec7096a25682fb7d57f6bb7f+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.6.0.0/cabal-install-3.6.0.0-x86_64-windows.zip+              dlSubdir:+              dlHash: 8222b49b6eac3d06aaa390bc688f467e8f949a38943567f46246f8320fd72ded+        A_ARM64:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.6.0.0/cabal-install-3.6.0.0-aarch64-linux-deb10.tar.xz+              dlHash: 534f71cd4e1d9758dc73066cc5733c5838874710aeb3aa88541de6c6d042d9ec+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghcup/unofficial-bindists/cabal/3.6.0.0/cabal-install-3.6.0.0-aarch64-darwin-big-sur.tar.xz+              dlHash: 7acf740946d996ede835edf68887e6b2f1e16d1b95e94054d266463f38d136d9+        A_ARM:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghcup/unofficial-bindists/cabal/3.6.0.0/cabal-install-3.6.0.0-armv7-linux.tar.xz+              dlHash: 11b5ca042a8bf45971224f2127a3e9d6b803f09210042ca80a254bea06f01a2e+  GHCup:+    0.1.17.2:+      viTags:+      - Recommended+      - Latest+      viChangeLog: https://gitlab.haskell.org/haskell/ghcup-hs/-/blob/master/CHANGELOG.md+      viSourceDL:+      viArch:+        A_64:+          Linux_UnknownLinux:+            unknown_versioning: &ghcup-64+              dlUri: https://downloads.haskell.org/~ghcup/0.1.17.2/x86_64-linux-ghcup-0.1.17.2+              dlHash: e9adb022b9bcfe501caca39e76ae7241af0f30fbb466a2202837a7a578607daf+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghcup/0.1.17.2/x86_64-apple-darwin-ghcup-0.1.17.2+              dlHash: 9418dab0f603b25f925739d66ca2328e876ce5197c131d7e75060f8edf7c57c9+          FreeBSD:+            '( >= 12 && < 13 )':+              dlUri: https://downloads.haskell.org/~ghcup/0.1.17.2/x86_64-portbld-freebsd12-ghcup-0.1.17.2+              dlHash: b6f0558e66f95a0772a60902c2c96202d0271d8d963db436a1359f1c4e1d2947+            '( >= 13 )':+              dlUri: https://downloads.haskell.org/~ghcup/0.1.17.2/x86_64-portbld-freebsd13-ghcup-0.1.17.2+              dlHash: 5bd5760dd29117ca2797a87b79f99b804743e7e64fcdcfe6ad6436314423ef84+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghcup/0.1.17.2/x86_64-mingw64-ghcup-0.1.17.2.exe+              dlHash: 17ab704551c691067d590760c513891d0d0d375efb59dc3c99219fdf352fed71+          Linux_Alpine:+            unknown_versioning: *ghcup-64+        A_32:+          Linux_UnknownLinux:+            unknown_versioning: &ghcup-32+              dlUri: https://downloads.haskell.org/~ghcup/0.1.17.2/i386-linux-ghcup-0.1.17.2+              dlHash: eb29a33ed9798c94ed05b10c66c2cd6690a4d5aa79ed7ce6a9b8564e0c095ff4+          Linux_Alpine:+            unknown_versioning: *ghcup-32+        A_ARM64:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghcup/0.1.17.2/aarch64-linux-ghcup-0.1.17.2+              dlHash: ad72641877f91f1cc5142151dafad68566f439114f96a738837ed549430173a5+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghcup/0.1.17.2/aarch64-apple-darwin-ghcup-0.1.17.2+              dlHash: bf8691a88627b02253c2068537dc16e7eb1d3dbb22bcb1342cb7f0d00df08fd5+        A_ARM:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/~ghcup/0.1.17.2/armv7-linux-ghcup-0.1.17.2+              dlHash: 03f2f8aaa8393372e9f7e16061703eda3f497b9604171825995389f3d5cc8f8f+  HLS:+    1.1.0:+      viTags:+        - old+      viChangeLog: https://github.com/haskell/haskell-language-server/blob/master/ChangeLog.md#110+      viPostInstall: &hls-post-install |+        This is just the server part of your LSP configuration. Consult the README on how to+        configure HLS, your project and your LSP client in your editor:+          https://github.com/haskell/haskell-language-server/blob/master/README.md+      viArch:+        A_64:+          Linux_UnknownLinux:+            unknown_versioning: &hls-110-64+              dlUri: https://github.com/haskell/haskell-language-server/releases/download/1.1.0/haskell-language-server-Linux-1.1.0.tar.gz+              dlHash: 0f0dadb0e9a08273658f565fd71c636801959b954be2737f38f2a1aac522208f+          Darwin:+            unknown_versioning:+              dlUri: https://github.com/haskell/haskell-language-server/releases/download/1.1.0/haskell-language-server-macOS-1.1.0.tar.gz+              dlHash: 4e89b192e2f49637d772e974f2c17b16da067ecd5912575eaa542551de97681b+          Windows:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/hls/1.1.0/haskell-language-server-Windows-1.1.0.tar.gz+              dlHash: a1d3f451e64a041aa527a25da29e4716a2de6ae347cef4ef9312fc7611e168cc+          Linux_Alpine:+            unknown_versioning: *hls-110-64+    1.2.0:+      viTags:+        - old+      viChangeLog: https://github.com/haskell/haskell-language-server/blob/master/ChangeLog.md#120+      viPostInstall: *hls-post-install+      viArch:+        A_64:+          Linux_UnknownLinux:+            unknown_versioning: &hls-120-64+              dlUri: https://github.com/haskell/haskell-language-server/releases/download/1.2.0/haskell-language-server-Linux-1.2.0.tar.gz+              dlHash: d29ee22f7bd706da2e2a1bd7640e25bb9736adeafb34eef47d29ea143b0fa927+          Darwin:+            unknown_versioning:+              dlUri: https://github.com/haskell/haskell-language-server/releases/download/1.2.0/haskell-language-server-macOS-1.2.0.tar.gz+              dlHash: a310d8a3e9c5c4218210f750682c74a0f82ad0f59995adde0dbe775115b1e357+          Windows:+            unknown_versioning:+              dlUri: https://github.com/haskell/haskell-language-server/releases/download/1.2.0/haskell-language-server-Windows-1.2.0.tar.gz+              dlHash: 961c6ff12c9a9c7a4609f239c5ac70d7d16753cdb8c10348a6a51feeaa0b6aea+          Linux_Alpine:+            unknown_versioning: *hls-120-64+    1.3.0:+      viTags: []+      viChangeLog: https://github.com/haskell/haskell-language-server/blob/master/ChangeLog.md#130+      viPostInstall: *hls-post-install+      viArch:+        A_64:+          Linux_UnknownLinux:+            unknown_versioning: &hls-130-64+              dlUri: https://github.com/haskell/haskell-language-server/releases/download/1.3.0/haskell-language-server-Linux-1.3.0.tar.gz+              dlHash: 0f232cd4316f5215eb82c6d8f568260e1862a9b39a68ec37662e5e87b714f271+          Darwin:+            unknown_versioning:+              dlUri: https://github.com/haskell/haskell-language-server/releases/download/1.3.0/haskell-language-server-macOS-1.3.0.tar.gz+              dlHash: 2ce9763718544c2e1ff6b005d9bdc86178dcdaf71e63dc68d3fcd23457abf180+          Windows:+            unknown_versioning:+              dlUri: https://github.com/haskell/haskell-language-server/releases/download/1.3.0/haskell-language-server-Windows-1.3.0.tar.gz+              dlHash: 46aac7be888e29a9907cf56698c1ce1475c148b5e6cc099513e9ef74a0520dcf+          Linux_Alpine:+            unknown_versioning: *hls-130-64+    1.4.0:+      viTags:+        - Recommended+        - Latest+      viChangeLog: https://github.com/haskell/haskell-language-server/blob/master/ChangeLog.md#140+      viPostInstall: *hls-post-install+      viSourceDL:+        dlUri: https://downloads.haskell.org/ghcup/src/haskell-language-server/1.4.0/haskell-language-server-1.4.0.tar.gz+        dlSubdir: haskell-language-server-1.4.0+        dlHash: c5d7dbf7fae9aa3ed2c1184b49e82d8ac623ca786494ef6602cfe11735d28db0+      viArch:+        A_64:+          Linux_UnknownLinux:+            unknown_versioning: &hls-140-64+              dlUri: https://github.com/haskell/haskell-language-server/releases/download/1.4.0/haskell-language-server-Linux-1.4.0.tar.gz+              dlHash: f93c114441911ccce55649702adc9553cb4c9f953c37878321d2806a3525fee8+          Darwin:+            unknown_versioning:+              dlUri: https://github.com/haskell/haskell-language-server/releases/download/1.4.0/haskell-language-server-macOS-1.4.0.tar.gz+              dlHash: a7f0ac6be93ffb08cc239e5f5fead99b061061825f99566c1be33ee60cab62a4+          FreeBSD:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/haskell-language-server/1.4.0/haskell-language-server-freebsd-1.4.0.tar.gz+              dlHash: 6b2ad2398ed8c3964dea017e3d5e553b54c10ba1373d7653d2edd019854f4da2+          Windows:+            unknown_versioning:+              dlUri: https://github.com/haskell/haskell-language-server/releases/download/1.4.0/haskell-language-server-Windows-1.4.0.tar.gz+              dlHash: 0ec77cee750037b7a0ede817b46a913a702821f4098c6a858bcb686cb30f7efd+          Linux_Alpine:+            unknown_versioning: *hls-140-64+        A_ARM64:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/haskell-language-server/1.4.0/haskell-language-server-linux-aarch64-1.4.0.tar.gz+              dlHash: 8ad97e2bf1c538e637edec194e1cd9939019955bb749cb470f34bbe5a067b001+          Darwin:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/haskell-language-server/1.4.0/haskell-language-server-macOS-aarch64-1.4.0.tar.gz+              dlHash: 70c6fe38e987ba44c1e19173486c01f666ffb30a74cd5a7968296a5aba4c2dd0+        A_ARM:+          Linux_UnknownLinux:+            unknown_versioning:+              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/haskell-language-server/1.4.0/haskell-language-server-linux-armv7-1.4.0.tar.gz+              dlHash: 4a921fbca06b02f3b1c0930cec5e65e9362b603e7715680ec7b150f18bd703d6+  Stack:+    2.5.1:+      viTags:+        - old+      viChangeLog: https://github.com/commercialhaskell/stack/blob/master/ChangeLog.md#v251+      viPostInstall: &stack-post |+        Stack manages GHC versions internally by default. In order to make it use ghcup installed+        GHC versions you can run the following commands:+          stack config set install-ghc false --global+          stack config set system-ghc  true  --global+        +        On windows, you may find the following config options useful too:+          skip-msys, extra-path, extra-include-dirs, extra-lib-dirs++        Also check out: https://docs.haskellstack.org/en/stable/yaml_configuration++        !!! Additionally, you should upgrade stack only through ghcup and not use 'stack upgrade' !!!+      viArch:+        A_64:+          Linux_UnknownLinux:+            unknown_versioning: &stack-251-64+              dlUri: https://github.com/commercialhaskell/stack/releases/download/v2.5.1/stack-2.5.1-linux-x86_64.tar.gz+              dlHash: c83b6c93d6541c0bce2175085a04062020f4160a86116e20f3b343b562f2d1e8+              dlSubdir:+                RegexDir: "stack-.*"+          Darwin:+            unknown_versioning:+              dlUri: https://github.com/commercialhaskell/stack/releases/download/v2.5.1/stack-2.5.1-osx-x86_64.tar.gz+              dlHash: f4aedfa8fbe371f77286ee97ec5c3c553842e7ae15b2952a8b8442dccba04bf0+              dlSubdir:+                RegexDir: "stack-.*"+          Windows:+            unknown_versioning:+              dlUri: https://github.com/commercialhaskell/stack/releases/download/v2.5.1/stack-2.5.1-windows-x86_64.tar.gz+              dlHash: 57150b422cfd42249f5e629d0eb678df6d95dabe486ced57e8298d300b940d41+              dlSubdir:+                RegexDir: "stack-.*"+          Linux_Alpine:+            unknown_versioning: *stack-251-64+    2.7.1:+      viTags:+        - old+      viChangeLog: https://github.com/commercialhaskell/stack/blob/master/ChangeLog.md#v271+      viPostInstall: *stack-post+      viArch:+        A_64:+          Linux_UnknownLinux:+            unknown_versioning: &stack-271-64+              dlUri: https://github.com/commercialhaskell/stack/releases/download/v2.7.1/stack-2.7.1-linux-x86_64.tar.gz+              dlHash: 2bc47749ee4be5eccb52a2d4a6a00b0f3b28b92517742b40c675836d7db2777d+              dlSubdir:+                RegexDir: "stack-.*"+          Darwin:+            unknown_versioning:+              dlUri: https://github.com/commercialhaskell/stack/releases/download/v2.7.1/stack-2.7.1-osx-x86_64.tar.gz+              dlHash: 4248c6fbc87e8a2c06f39e867eb5ef28eae0d99470137cb415356c631c0dcbf2+              dlSubdir:+                RegexDir: "stack-.*"+          Windows:+            unknown_versioning:+              dlUri: https://github.com/commercialhaskell/stack/releases/download/v2.7.1/stack-2.7.1-windows-x86_64.tar.gz+              dlHash: 8452f5fc9235620a84863f2f68e5f681c72d0d181cde50482f178a966ee0ceb9+              dlSubdir:+                RegexDir: "stack-.*"+          Linux_Alpine:+            unknown_versioning: *stack-271-64+    2.7.3:+      viTags:+        - Latest+        - Recommended+      viChangeLog: https://github.com/commercialhaskell/stack/blob/master/ChangeLog.md#v273+      viPostInstall: *stack-post+      viArch:+        A_64:+          Linux_UnknownLinux:+            unknown_versioning: &stack-273-64+              dlUri: https://github.com/commercialhaskell/stack/releases/download/v2.7.3/stack-2.7.3-linux-x86_64.tar.gz+              dlHash: a6c090555fa1c64aa61c29aa4449765a51d79e870cf759cde192937cd614e72b+              dlSubdir:+                RegexDir: "stack-.*"+          Darwin:+            unknown_versioning:+              dlUri: https://github.com/commercialhaskell/stack/releases/download/v2.7.3/stack-2.7.3-osx-x86_64.tar.gz+              dlHash: 42e5000a00af44a7b26852421ac63ce75f510ad1a97742cb131107088ee9fe30+              dlSubdir:+                RegexDir: "stack-.*"+          Windows:+            unknown_versioning:+              dlUri: https://github.com/commercialhaskell/stack/releases/download/v2.7.3/stack-2.7.3-windows-x86_64.tar.gz+              dlHash: e6ba12e0ecabf0df2567d88a0d247da238bc114bcccfca4195f5e86472c9330c+              dlSubdir:+                RegexDir: "stack-.*"+          Linux_Alpine:+            unknown_versioning: *stack-273-64+
+ docs/CHANGELOG.md view
@@ -0,0 +1,210 @@+# Revision history for ghcup++## 0.1.17.2 -- 2021-09-30++* Honour GHC bootstrap compiler during git clone stages wrt [#250](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/250)+* Speed up `unset` command+* Fix `--overwrite-version` for `ghcup compile ghc` wrt [#253](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/253)+* Apply patches before bootstrap++## 0.1.17.1 -- 2021-09-26++* Fix `NO_COLOR`+* Fix `ghcup list -t` for hls/stack, wrt [#244](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/244)+* Get rid of concurrent-output+* Improve cli interface with partial versions (e.g. `ghcup install ghc 8`)+* Fix HLS compilation builds+* Implement `ghcup gc` (garbage collection) command++## 0.1.17 -- 2021-09-20++* Add `--force` option to install/compile wrt [#210](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/210) by Arjun Kathuria+* Implement compiling HLS from source wrt [#201](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/201)+* Implement experimental GPG verification of the metadata file (see README) wrt [#263](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/236)+* Add `ghcup unset` command wrt [#145](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/145)+* Add `ghcup whereis bindir` etc wrt [#221](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/221)+* Greatly reduce dependency footprint wrt [#212](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/212)+* Add `ghcup --plan-json`+* Improve `--patchdir` option for GHC compilation wrt [#226](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/226)+* Try to improve logging and failure modes, especially during downloads+* Add descriptive warnings when HLS and GHC versions are incompatible+* Improve curl header parsing wrt [#213](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/213)++## 0.1.16.2 -- 2021-08-12++* Add isolated installations wrt [#141](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/141) by Arjun Kathuria+* Implement config cli MVP wrt [#134](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/134) by Oleksii Dorozhkin+* Fix `ghcup compile ghc --flavor`+* Fix minor installation bug causing increased disk space wrt [#139](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/139)+* Improved error handling wrt [#136](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/136)+* Various improvements to metadata download when using `file://` and `--offline` wrt [#137](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/137)++## 0.1.16.1 -- 2021-07-29++* Add 'nuke' subcommand wrt [#135](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/135), implemented by Arjun Kathuria+* Add uninstallation powershell script on windows wrt [#150](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/150)+* Improve logging+* Fix building GHC cross compiler wrt [#180](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/180)+* Allow to use hadrian as build system (for git based versions only) wrt [#35](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/35)+* Allow passing `--flavor` to `ghcup compile ghc`+* Support new GHC `bin/` directory format wrt [ghc/ghc#20074](https://gitlab.haskell.org/ghc/ghc/-/issues/20074#note_363720)+* Implement `whereis` subcommand wrt [#173](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/173)+* Add `--offline` switch and `prefetch` subcommand wrt [#186](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/186)+* Implement ETAGs hashing for metadata downloads to speed up `ghcup list` wrt [#193](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/193)+* Avoid unnecessary fetching of ghcup metadata in some commands+* Avoid unnecessary update checks for some commands+* Preserve mtimes on unpacked GHC tarballs on windows wrt [#187](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/187), fixing issues with `ghc-pkg`+* Fix lesser bug in `ghcup list` for stray stack versions wrt [#183](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/183)+* Major redo on how file removal on windows works, avoiding partial removals etc, wrt [#165](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/165)+* Improve ghcup tui for screen readers wrt [github/#4](https://github.com/haskell/ghcup-hs/pull/4), thanks to Mario Lang++## 0.1.15.2 -- 2021-06-13++* Remove legacy handling of cabal binary and be more graceful about binaries not installed by ghcup (e.g. stack)+* Fix GHC compilation from git+* Fix 'ghcup upgrade' on windows+* Allow to skip update checks via `GHCUP_SKIP_UPDATE_CHECK`+* Use libarchive on windows as well, fixing unpack errors wrt [#147](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/147)++## 0.1.15.1 -- 2021-06-11++* Add Apple Silicon support+* Add windows support wrt [#130](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/130)+* Add stack support+* Warn when /tmp doesn't have 5GB or more of disk space+* Allow to compile GHC from git repo wrt [#126](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/126)+* Allow to set custom ghc version when running 'ghcup compile ghc' wrt [#136](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/136)+* Add date to GHC bindist names created by ghcup++## 0.1.14.2 -- 2021-05-12++* Remove dead dependency on ascii-string++## 0.1.14.1 -- 2021-04-11++* Make internal symlink target parser more lax, fixes [#119](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/119)+* Prepare for hackage release++## 0.1.14 -- 2021-03-07++* Major bugfix: fix handling of stray versions wrt [#116](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/116)+* Fix error messages and overhaul pretty printing wrt [#115](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/115)++## 0.1.13 -- 2021-02-26++* Support ARMv7/AARCH64+* Add command line completions for installed and available versions wrt [MR #70](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/70)+* Allow to cycle through set tools wrt [#114](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/114)+* Fix item selection with unavailable versions wrt [#107](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/107)+* Allow for dynamic post-install, post-remove and pre-compile msgs wrt [MR #68](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/68)+* Alert user if upgraded ghcup is shadowed by old ghcup wrt [#111](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/111)+* Fix to `ghcup` directory creation and placement for the XDG install mode ([MR #49](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/49))+* Do 755 permissions on executables, wrt #97+* Add [NO_COLOR](https://no-color.org/) support wrt [MR #47](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/47)++## 0.1.12 -- 2020-11-21++* Fix disappearing HLS symlinks wrt #91+* improve TUI:+  - separators between tools sections+  - reverse list order so latest is on top+  - expand the blues selected bar+  - show new latest versions in bright white+* allow configuration file and setting TUI hotkeys wrt #41+  - see https://gitlab.haskell.org/haskell/ghcup-hs#configuration for a more in-depth explanation+* add a `--set` switch to `ghcup install ghc` to automatically set as default after install+* emit warnings when CC/LD is set wrt #82+* add support for version ranges in distro specifiers wrt #84+  - e.g. `"(>= 19 && <= 20) || ==0.2.2"` is a valid version key for distro++## 0.1.11 -- 2020-09-23++* Add support for installing haskell-language-server, wrt #65+* When compiling GHC from source create a bindist first, store that bindist in `~/.ghcup/cache` and install it, wrt #51+* Allow to compile over existing version (`ghcup compile ghc -v 8.6.5 -b 8.6.5`) and replace it wrt #59+* simplify installing from custom bindist wrt #60+  - `ghcup install ghc -u <url> <version>`+* fix bug when cabal isn't marked executable in bindist+* fix bug when `~/.ghcup` is a valid symlink wrt #49+* Drop support for compiling cabal from source (the old bootstrap script is discontinued)++## 0.1.10 -- 2020-08-14++* Show stray Cabals (useful for pre-releases or compiled ones)++## 0.1.9 -- 2020-08-14++* Fix bug when uninstalling all cabal versions+* Fix bug when setting a non-installed ghc version as current default+* Use yaml instead of generated json for download info for ease of adding new GHC versions #44+* Allow pre-release versions of GHC/cabal+* Add XDG dirs support (set `GHCUP_USE_XDG_DIRS`) wrt #39+* Allow to specify regex for tarball subdir (e.g. `ghc-.*`)+* Allow installing arbitrary bindists more seamlessly:+  - e.g. installing GHC HEAD: `ghcup -n install ghc -u '{"dlHash": "", "dlSubdir": { "RegexDir": "ghc-.*"}, "dlUri": "https://gitlab.haskell.org/api/v4/projects/1/jobs/artifacts/master/raw/ghc-x86_64-fedora27-linux.tar.xz?job=validate-x86_64-linux-fedora27" }' head`+* Avoid duplicate edits to .bashrc/.zshrc wrt #43++## 0.1.8 -- 2020-07-21++* Fix bug in logging thread dying on newlines+* Allow to install from arbitrary bindists: `ghcup -n install ghc -u '{"dlHash": "", "dlSubdir": "ghc-8.10.1", "dlUri": "https://github.com/commercialhaskell/ghc/releases/download/ghc-8.10.1-release/ghc-8.10.1-x86_64-deb9-linux.tar.xz"}' 8.10.1`++## 0.1.7 -- 2020-07-20++* Fix a bug in libarchive not unpacking some uncleanly packed bindists+* Improved fish support in bootstrap-haskell+* Only check for upgrades when not upgrading+* Fix platform detection for i386 docker images+* Improve alpine support+  - more/proper bindists+  - don't fall back to glibc based bindists+  - install bindists with `--disable-ld-override` to avoid ld.gold bugs++## 0.1.6 -- 2020-07-13++* Create a new curses (brick) based TUI, accessible via `ghcup tui` #24+* Support multiple installed versions of cabal #23+* Improvements to `ghcup list` (show unavailable bindists for platform)+* Fix redhat downloads #29+* Support for hadrian bindists (fixes alpine-8.10.1) #31+* Add FreeBSD bindists 8.6.5 and 8.8.3+* Fix memory leak during unpack++## 0.1.5 -- 2020-04-30++* Fix errors when PATH variable contains path components that are actually files+* Add `--version` and `--numeric-version` options+* Add `changelog` command+* Also check for available GHC and Cabal updates on start+* Add base versions as tags for every GHC version (these are "installable" tags and the latest GHC version matching the tag will be picked)+* Added `--format-raw` to list subcommand+* Allow to install X.Y versions (e.g.: ghcup install 8.8)+* Implement `--keep=<always|errors|never>` to control temporary build directories cleanup+* Add proper shell completions to the repo+* Fix building of documentation+* Allow to work in offline mode and use cached files if possible+* Allow to set the downloader via `--downloader=<curl|wget>`+* Support for compiling and installing a cross GHC (see README). This is experimental.++## 0.1.4 -- 2020-04-16++* build on all platforms with curl (as a binary), wrt https://gitlab.haskell.org/haskell/ghcup-hs/issues/6+* Fix unlinking of ghc symlinks after new installation, wrt https://gitlab.haskell.org/haskell/ghcup-hs/issues/7++## 0.1.3 -- 2020-04-15++* Fix lesser bug when skipping ghcup update++## 0.1.2 -- 2020-04-15++* Fix bug when removing the set GHC version+* Fix use of undocumented `GHCUP_INSTALL_BASE_PREFIX` variable+* skip upgrade if ghcup is already latest version++## 0.1.1 -- 2020-04-15++* fix awful fdopendir bug on mac bug by updating hpath-posix++## 0.1.0++* First version. Released on an unsuspecting world.
+ docs/HACKING.md view
@@ -0,0 +1,75 @@+# HACKING++## Design decisions++### Using [Excepts](https://hackage.haskell.org/package/haskus-utils-variant-3.0/docs/Haskus-Utils-Variant-Excepts.html) as a beefed up ExceptT++This is an open variant, similar to [plucky](https://hackage.haskell.org/package/plucky) or [oops](https://github.com/i-am-tom/oops) and allows us to combine different error types. Maybe it is too much and it's a little bit [unergonomic](https://github.com/haskus/packages/issues/32) at times. If it really hurts maintenance, it will be removed. It was more of an experiment.++### No use of haskell-TLS++I consider haskell-TLS an interesting experiment, but not a battle-tested and peer-reviewed crypto implementation. There is little to no research about what the intricacies of using haskell for low-level crypto are and how vulnerable such binaries are. Instead, we use either curl the binary (for FreeBSD and mac) or http-io-streams, which works with OpenSSL bindings.++### Optics instead of lens++They're a little safer (less Monoid weirdness with view) and have better error messages. Consider the following wit lens++```+> view (_Just . to (++ "abc")) Nothing+""+```++vs optics++```+> view (_Just % to (++ "abc")) Nothing++<interactive>:2:1: error:+    • An_AffineFold cannot be used as A_Getter+    • In the expression: view (_Just % to (++ "abc")) Nothing+      In an equation for ‘it’: it = view (_Just % to (++ "abc")) Nothing+```++### Strict and StrictData on by default++Kazu Yamamoto [explained it in his PR](https://github.com/yesodweb/wai/pull/752#issuecomment-501531386) very well. I like to agree with him. The instances where we need non-strict behavior, we annotate it.++## Code style and formatting++1. Brittany+2. mtl-style preferred+3. no overly pointfree style++## Code structure++Main functionality is in `GHCup` module. Utility functions are+organised tree-ish in `GHCup.Utils` and `GHCup.Utils.*`.++Anything dealing with ghcup specific directories is in+`GHCup.Utils.Dirs`.++Download information on where to fetch bindists from is in the appropriate+yaml files: `ghcup-<yaml-ver>.yaml`.++## Common Tasks++### Adding a new GHC version++1. open the latest `ghcup-<yaml-ver>.yaml`+2. find the latest ghc version (in yaml tree e.g. `ghcupDownloads -> GHC -> 8.10.3`)+3. copy-paste it+4. adjust the version, tags, changelog, source url+5. adjust the various bindist urls (make sure to also change the yaml anchors)+6. run `cabal run exe:ghcup-gen -- check-tarballs -f ghcup-<yaml-ver>.yaml -u 'ghc-8\.10\.4'`++## Major refactors++1. First major refactor included adding cross support. This added+   `GHCTargetVersion`, which includes the target in addition to the version.+   Most of the `Version` parameters to functions had to be replaced with+   that and ensured the logic is consistent for cross and non-cross+   installs.+2. This refactor added windows support wrt [#130](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/130).+   The major changes here were switching `hpath` library out for `filepath`/`directory` (sadly) and+   introducing a non-unix way of handling processes via the `process` library. It also introduced considerable+   amounts of CPP wrt file handling, installation etc.
+ docs/RELEASING.md view
@@ -0,0 +1,21 @@+# RELEASING++1. Update version in `ghcup.cabal` and `boostrap-haskell` (`ghver` variable at the top of the script)++2. Update `GHCup.Version` module. `ghcupURL` must only be updated if we change the `GHCupInfo` type or the YAML representation of it. The version of the YAML represents the change increments. `ghcUpVer` is the current application version, read from `ghcup.cabal`.++3. Add ChangeLog entry++4. Add/fix downloads in `ghcup-<ver>.yaml` (under `data/metadata`), then verify with `ghcup-gen check -f ghcup-<ver>.yaml` and possibly (example only) `ghcup-gen check-tarballs -f ghcup-<ver>.yaml -u 'ghc-8.10.7'`. Generally, new GHC/cabal/stack/hls versions are only added to the latest yaml file. New GHCup versions are added to all (great care must be taken here to not break the parser... e.g. ARM platforms don't parse in all older formats).++5. Commit and git push with tag. Wait for tests to succeed and release artifacts to build.++6. Download release artifacts and upload them `downloads.haskell.org/ghcup` along with checksum files (`sha256sum --tag * > SHA256SUMS && gpg --detach-sign -u <your-email> SHA256SUMS`)++7. Add ghcup release artifacts to ALL yaml files (see point 4.)++8. Upload the final `ghcup-<ver>.yaml` to `webhost.haskell.org/ghcup/data/`.++9. Update `bootstrap-haskell` and `bootstrap-haskell.ps1` to `webhost.haskell.org/ghcup/sh/`++10. Update the ghcup symlinks at `downloads.haskell.org/ghcup`
− ghcup-0.0.4.yaml
@@ -1,1833 +0,0 @@-----toolRequirements:-  GHC:-    unknown_version:-      Linux_Debian:-        unknown_versioning:-          distroPKGs:-          - build-essential-          - curl-          - libffi-dev-          - libffi6-          - libgmp-dev-          - libgmp10-          - libncurses-dev-          - libncurses5-          - libtinfo5-          notes: ''-      Linux_Ubuntu:-        unknown_versioning:-          distroPKGs:-          - build-essential-          - curl-          - libffi-dev-          - libffi6-          - libgmp-dev-          - libgmp10-          - libncurses-dev-          - libncurses5-          - libtinfo5-          notes: ''-        "( >= 20.04 && < 20.10 )":-          distroPKGs:-          - build-essential-          - curl-          - libffi-dev-          - libffi7-          - libgmp-dev-          - libgmp10-          - libncurses-dev-          - libncurses5-          - libtinfo5-          notes: ''-        "( >= 20.10 )":-          distroPKGs:-          - build-essential-          - curl-          - libffi-dev-          - libffi8ubuntu1-          - libgmp-dev-          - libgmp10-          - libncurses-dev-          - libncurses5-          - libtinfo5-          notes: ''-      Linux_CentOS:-        '( >= 7 && < 8 )':-          distroPKGs:-          - gcc-          - gcc-c++-          - gmp-          - gmp-devel-          - make-          - ncurses-          - xz-          - perl-          notes: ''-        unknown_versioning:-          distroPKGs:-          - gcc-          - gcc-c++-          - gmp-          - gmp-devel-          - make-          - ncurses-          - ncurses-compat-libs-          - xz-          - perl-          notes: ''-      Linux_Fedora:-        unknown_versioning:-          distroPKGs:-          - gcc-          - gcc-c++-          - gmp-          - gmp-devel-          - make-          - ncurses-          - ncurses-compat-libs-          - xz-          - perl-          notes: ''-      Linux_Alpine:-        unknown_versioning:-          distroPKGs:-          - curl-          - gcc-          - g++-          - gmp-dev-          - ncurses-dev-          - libffi-dev-          - make-          - xz-          - tar-          - perl-          notes: ''-      Linux_UnknownLinux:-        unknown_versioning:-          distroPKGs: []-          notes: 'You need the following packages: curl g++ gcc gmp make ncurses realpath-            xz-utils. Consult your distro documentation on the exact names of those-            packages.'-      Darwin:-        unknown_versioning:-          distroPKGs: []-          notes: On OS X, in the course of running ghcup you will be given a dialog-            box to install the command line tools. Accept and the requirements will-            be installed for you. You will then need to run the command again.-      FreeBSD:-        unknown_versioning:-          distroPKGs:-          - curl-          - gcc-          - gmp-          - gmake-          - ncurses-          - perl5-          - libffi-          - libiconv-          notes: ''-ghcupDownloads:-  GHC:-    7.10.3:-      viTags:-      - base-4.8.2.0-      - old-      viChangeLog: https://downloads.haskell.org/~ghc/7.10.3/docs/html/users_guide/release-7-10-1.html-      viSourceDL:-        dlUri: https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-src.tar.xz-        dlSubdir: ghc-7.10.3-        dlHash: cf90cedce1c28fd0e2b9e72fe8a938756668d18ea1fcc884a19f698658ac4fef-      viPostRemove: &ghc-post-remove "After removing GHC you might also want to clean up your cabal store at: ~/.cabal/store/ghc-<ghcver>"-      viArch:-        A_64:-          Linux_Debian:-            unknown_versioning: &ghc-7103-64-deb8-              dlUri: https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-x86_64-deb8-linux.tar.bz2-              dlSubdir: ghc-7.10.3-              dlHash: 01cfbad8dff1e8b34a5fdca8caeaf843b56e36af919e29cd68870d2588563db5-          Linux_Ubuntu:-            unknown_versioning: *ghc-7103-64-deb8-          Linux_Mint:-            unknown_versioning: *ghc-7103-64-deb8-          Linux_CentOS:-            unknown_versioning: &ghc-7103-64-centos-              dlUri: https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-x86_64-centos67-linux.tar.bz2-              dlSubdir: ghc-7.10.3-              dlHash: a8957f7a2fd81720c5d3dc403571d77d31115ff5f42edb2917c36d8e714220d4-          Linux_AmazonLinux:-            unknown_versioning: *ghc-7103-64-centos-          Linux_UnknownLinux:-            unknown_versioning: *ghc-7103-64-deb8-          Darwin:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-x86_64-apple-darwin.tar.bz2-              dlSubdir: ghc-7.10.3-              dlHash: 80893e367e8318105f7db2064adf202e3d96b1f014e792b73e92f2cacf0b757a-          FreeBSD:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-x86_64-portbld-freebsd.tar.bz2-              dlSubdir: ghc-7.10.3-              dlHash: 2aa396edd2bb651f4bc7eef7a396913ea24923de5aafdc76df6295333e487e48-        A_32:-          Linux_Debian:-            unknown_versioning: &ghc-7103-32-deb8-              dlUri: https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-i386-deb8-linux.tar.bz2-              dlSubdir: ghc-7.10.3-              dlHash: d2ccf072457fb100503f6f5430a1e3589ca525a97424263d036b0550bc277f0c-          Linux_Ubuntu:-            unknown_versioning: *ghc-7103-32-deb8-          Linux_Mint:-            unknown_versioning: *ghc-7103-32-deb8-          Linux_CentOS:-            unknown_versioning: &ghc-7103-32-centos-              dlUri: https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-i386-centos67-linux.tar.bz2-              dlSubdir: ghc-7.10.3-              dlHash: c50aa20275e8d1ba9148f380eb7598bc148143281fc17c9acd38ea7b325852bd-          Linux_AmazonLinux:-            unknown_versioning: *ghc-7103-32-centos-          Linux_UnknownLinux:-            unknown_versioning: *ghc-7103-32-deb8-          FreeBSD:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-i386-portbld-freebsd.tar.bz2-              dlSubdir: ghc-7.10.3-              dlHash: 3dde05577c6f94dcb0ba201ebd53ab88553bbc9a3aa8e72237162ed7a9d588a3-    8.0.2:-      viTags:-      - base-4.9.1.0-      - old-      viChangeLog: https://downloads.haskell.org/~ghc/8.0.2/docs/html/users_guide/8.0.1-notes.html-      viSourceDL:-        dlUri: https://downloads.haskell.org/~ghc/8.0.2/ghc-8.0.2-src.tar.xz-        dlSubdir: ghc-8.0.2-        dlHash: 11625453e1d0686b3fa6739988f70ecac836cadc30b9f0c8b49ef9091d6118b1-      viPostRemove: *ghc-post-remove-      viArch:-        A_64:-          Linux_Debian:-            '( >= 7 && < 8 )':-              dlUri: https://downloads.haskell.org/~ghc/8.0.2/ghc-8.0.2-x86_64-deb7-linux.tar.xz-              dlSubdir: ghc-8.0.2-              dlHash: b2f5c304b57ac5840a0d2ef763a3c6fa858c70840f749cfad12ed227da973c0a-            unknown_versioning: &ghc-802-64-deb8-              dlUri: https://downloads.haskell.org/~ghc/8.0.2/ghc-8.0.2-x86_64-deb8-linux.tar.xz-              dlSubdir: ghc-8.0.2-              dlHash: 5ee68290db00ca0b79d57bc3a5bdce470de9ce9da0b098a7ce6c504605856c8f-          Linux_Ubuntu:-            unknown_versioning: *ghc-802-64-deb8-          Linux_Mint:-            unknown_versioning: *ghc-802-64-deb8-          Linux_Alpine:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.0.2/ghc-8.0.2-x86_64-alpine-linux.tar.xz-              dlSubdir: ghc-8.0.2-              dlHash: 517783b660a27ebf95b2568d47292fd633d5f9a4de4c80ad1ccf05e1b9d7313f-          Linux_UnknownLinux:-            unknown_versioning: *ghc-802-64-deb8-          Darwin:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/8.0.2/ghc-8.0.2-x86_64-apple-darwin.tar.xz-              dlSubdir: ghc-8.0.2-              dlHash: ff50a2df9f002f33b9f09717ebf5ec5a47906b9b65cc57b1f9849f8b2e06788d-          FreeBSD:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/8.0.2/ghc-8.0.2-x86_64-portbld-freebsd.tar.xz-              dlSubdir: ghc-8.0.2-              dlHash: b36a20e5cae24d70bbb6116ae486f21811e9384f15d3892d260f02fba3e3bb8c-        A_32:-          Linux_Debian:-            '( >= 7 && < 8 )':-              dlUri: https://downloads.haskell.org/~ghc/8.0.2/ghc-8.0.2-i386-deb7-linux.tar.xz-              dlSubdir: ghc-8.0.2-              dlHash: 07ead3a49f8c9df4b429e7a2f96f6f31bcab8d3ff8277a9aed0201d13ddad448-            unknown_versioning: &ghc-802-32-deb8-              dlUri: https://downloads.haskell.org/~ghc/8.0.2/ghc-8.0.2-i386-deb8-linux.tar.xz-              dlSubdir: ghc-8.0.2-              dlHash: 818621342a2161b8afcc995a0765816bb40aefbfa1db2c8a7d59c04d8b18228a-          Linux_Alpine:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.0.2/ghc-8.0.2-i386-alpine-linux.tar.xz-              dlSubdir: ghc-8.0.2-              dlHash: b4cd12a1048b2fff2f23c9eec0dd3a1174d54d017f8d79ec79af4534118e6881-          Linux_UnknownLinux:-            unknown_versioning: *ghc-802-32-deb8-    8.2.2:-      viTags:-      - base-4.10.1.0-      - old-      viChangeLog: https://downloads.haskell.org/~ghc/8.2.2/docs/html/users_guide/8.2.2-notes.html-      viSourceDL:-        dlUri: https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-src.tar.xz-        dlSubdir: ghc-8.2.2-        dlHash: bb8ec3634aa132d09faa270bbd604b82dfa61f04855655af6f9d14a9eedc05fc-      viPostRemove: *ghc-post-remove-      viArch:-        A_64:-          Linux_Debian:-            '( >= 7 && < 8 )': &ghc-822-64-deb7-              dlUri: https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-x86_64-deb7-linux.tar.xz-              dlSubdir: ghc-8.2.2-              dlHash: cd7afbca54edf9890da9f432c63366556246c85c1198e40c99df5af01c555834-            unknown_versioning: &ghc-822-64-deb8-              dlUri: https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-x86_64-deb8-linux.tar.xz-              dlSubdir: ghc-8.2.2-              dlHash: 48e205c62b9dc1ccf6739a4bc15a71e56dde2f891a9d786a1b115f0286111b2a-          Linux_Ubuntu:-            unknown_versioning: *ghc-822-64-deb8-          Linux_Mint:-            unknown_versioning: *ghc-822-64-deb8-          Linux_Alpine:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.2.2/ghc-8.2.2-x86_64-alpine-linux.tar.xz-              dlSubdir: ghc-8.2.2-              dlHash: adcf3a320a3c402aba07ae9586990dc3c0b550e96aeffb1b9e194313d3ba716d-          Linux_UnknownLinux:-            unknown_versioning: *ghc-822-64-deb7-          Darwin:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-x86_64-apple-darwin.tar.xz-              dlSubdir: ghc-8.2.2-              dlHash: f90fcf62f7e0936a6dfc3601cf663729bfe9bbf85097d2d75f0a16f8c2e95c27-          FreeBSD:-            '( >= 10 && < 11 )':-              dlUri: https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-x86_64-portbld10_3-freebsd.tar.xz-              dlSubdir: ghc-8.2.2-              dlHash: 9e99aaeaec4b2c6d660d80246c0d4dbd41fda88f1eb7a908b29dc8fa8d663949-            '( >= 11 && < 12 )': &ghc-822-64-fbsd11-              dlUri: https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-x86_64-portbld11-freebsd.tar.xz-              dlSubdir: ghc-8.2.2-              dlHash: cd351c704b92b9af23994024df07de8ca7090ea7675d5c8b14b2be857a46d804-            unknown_versioning: *ghc-822-64-fbsd11-        A_32:-          Linux_Debian:-            '( >= 7 && < 8 )':-              dlUri: https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-i386-deb7-linux.tar.xz-              dlSubdir: ghc-8.2.2-              dlHash: cd18766b1a9b74fc6c90003a719ecab158f281f9a755d8b1bd3fd764ba6947b5-            unknown_versioning: &ghc-822-32-deb8-              dlUri: https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-i386-deb8-linux.tar.xz-              dlSubdir: ghc-8.2.2-              dlHash: 9e67d72d76482e0ba91c718e727b00386a1a12a32ed719714976dc56ca8c8223-          Linux_Ubuntu:-            unknown_versioning: *ghc-822-32-deb8-          Linux_Mint:-            unknown_versioning: *ghc-822-32-deb8-          Linux_Alpine:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.2.2/ghc-8.2.2-i386-alpine-linux.tar.xz-              dlSubdir: ghc-8.2.2-              dlHash: 467534c32552cfd318753112dbc70af003693aad4b0081f2a07e61f5b5ea2c22-          Linux_UnknownLinux:-            unknown_versioning: *ghc-822-32-deb8-    8.4.1:-      viTags:-      - base-4.11.0.0-      - old-      viChangeLog: https://downloads.haskell.org/~ghc/8.4.1/docs/html/users_guide/8.4.1-notes.html-      viSourceDL:-        dlUri: https://downloads.haskell.org/~ghc/8.4.1/ghc-8.4.1-src.tar.xz-        dlSubdir: ghc-8.4.1-        dlHash: 39ae2f25192408f355693e5a3c8b6ff613ddb7c4da998fdf26210143a61839d2-      viPostRemove: *ghc-post-remove-      viArch:-        A_64:-          Linux_Debian:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/8.4.1/ghc-8.4.1-x86_64-deb8-linux.tar.xz-              dlSubdir: ghc-8.4.1-              dlHash: 427c77a934b30c3f1de992c38c072afb4323fe6fb30dbac919ca8cb6ae98fbd9-          Linux_Ubuntu:-            unknown_versioning: &ghc-841-64-fedora-              dlUri: https://downloads.haskell.org/~ghc/8.4.1/ghc-8.4.1-x86_64-fedora27-linux.tar.xz-              dlSubdir: ghc-8.4.1-              dlHash: 89328a013e64b9b56825a9071fea5616ddd623d37fd41e8fb913dfebc609e7ea-          Linux_Mint:-            unknown_versioning: *ghc-841-64-fedora-          Linux_Fedora:-            unknown_versioning: *ghc-841-64-fedora-          Linux_UnknownLinux:-            unknown_versioning: *ghc-841-64-fedora-          Darwin:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/8.4.1/ghc-8.4.1-x86_64-apple-darwin.tar.xz-              dlSubdir: ghc-8.4.1-              dlHash: d774e39f3a0105843efd06709b214ee332c30203e6c5902dd6ed45e36285f9b7-          FreeBSD:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/8.4.1/ghc-8.4.1-x86_64-portbld11-freebsd.tar.xz-              dlSubdir: ghc-8.4.1-              dlHash: e748daec098445c6190090fe32bb2817a1140553be5acd2188e1af05ad24e5aa-        A_32:-          Linux_Debian:-            unknown_versioning: &ghc-841-32-deb8-              dlUri: https://downloads.haskell.org/~ghc/8.4.1/ghc-8.4.1-i386-deb8-linux.tar.xz-              dlSubdir: ghc-8.4.1-              dlHash: c56c589c76c7ddcb77cdbef885a811761e669d3e76868b723d5be56dedcd4f69-          Linux_Ubuntu:-            unknown_versioning: *ghc-841-32-deb8-          Linux_Mint:-            unknown_versioning: *ghc-841-32-deb8-          Linux_UnknownLinux:-            unknown_versioning: *ghc-841-32-deb8-    8.4.2:-      viTags:-      - base-4.11.1.0-      - old-      viChangeLog: https://downloads.haskell.org/~ghc/8.4.2/docs/html/users_guide/8.4.2-notes.html-      viSourceDL:-        dlUri: https://downloads.haskell.org/~ghc/8.4.2/ghc-8.4.2-src.tar.xz-        dlSubdir: ghc-8.4.2-        dlHash: 01cc32f24a06bf3b2428351b6d7fec791e82d042426d29ad9e5a245b35f0047b-      viPostRemove: *ghc-post-remove-      viArch:-        A_64:-          Linux_Debian:-            '( >= 8 && < 9 )':-              dlUri: https://downloads.haskell.org/~ghc/8.4.2/ghc-8.4.2-x86_64-deb8-linux.tar.xz-              dlSubdir: ghc-8.4.2-              dlHash: 246f66eb56f4ad0f1c7755502cfc8f9972f2d067dede17e151f6f479c1f76fbd-            unknown_versioning: &ghc-842-64-deb9-              dlUri: https://downloads.haskell.org/~ghc/8.4.2/ghc-8.4.2-x86_64-deb9-linux.tar.xz-              dlSubdir: ghc-8.4.2-              dlHash: 3f4f5bbd2cdab4e7015ada9196d8d9b3a1ad274293cef011f85c46854596cb57-          Linux_Ubuntu:-            unknown_versioning: &ghc-842-64-fedora-              dlUri: https://downloads.haskell.org/~ghc/8.4.2/ghc-8.4.2-x86_64-fedora27-linux.tar.xz-              dlSubdir: ghc-8.4.2-              dlHash: d057b5c833596dbe4ae5d0dc2994f6cc5d0f4c2a21ea1d7900821d165fd4e846-            '( >= 16 && < 19 )': *ghc-842-64-deb9-          Linux_Mint:-            unknown_versioning: *ghc-842-64-fedora-          Linux_Fedora:-            unknown_versioning: *ghc-842-64-fedora-          Linux_UnknownLinux:-            unknown_versioning: *ghc-842-64-fedora-          Darwin:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/8.4.2/ghc-8.4.2-x86_64-apple-darwin.tar.xz-              dlSubdir: ghc-8.4.2-              dlHash: 87469222042b9ac23f9db216a8d4e5107297bdbbb99df71eb4d9e7208455def2-          FreeBSD:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/8.4.2/ghc-8.4.2-x86_64-portbld-freebsd.tar.xz-              dlSubdir: ghc-8.4.2-              dlHash: e9ed417fdf94c2ff2c6e344ed16f332bf6b591511f6442c0d9ea94854882b66c-        A_32:-          Linux_Debian:-            unknown_versioning: &ghc-842-32-deb8-              dlUri: https://downloads.haskell.org/~ghc/8.4.2/ghc-8.4.2-i386-deb8-linux.tar.xz-              dlSubdir: ghc-8.4.2-              dlHash: 2d849c30b4c1eac25dc74333501920921e22fa483153f404993808bbda93df05-          Linux_Ubuntu:-            unknown_versioning: *ghc-842-32-deb8-          Linux_Mint:-            unknown_versioning: *ghc-842-32-deb8-          Linux_UnknownLinux:-            unknown_versioning: *ghc-842-32-deb8-    8.4.3:-      viTags:-      - base-4.11.1.0-      - old-      viChangeLog: https://downloads.haskell.org/~ghc/8.4.3/docs/html/users_guide/8.4.3-notes.html-      viSourceDL:-        dlUri: https://downloads.haskell.org/~ghc/8.4.3/ghc-8.4.3-src.tar.xz-        dlSubdir: ghc-8.4.3-        dlHash: ae47afda985830de8811243255aa3744dfb9207cb980af74393298b2b62160d6-      viPostRemove: *ghc-post-remove-      viArch:-        A_64:-          Linux_Debian:-            '( >= 8 && < 9 )':-              dlUri: https://downloads.haskell.org/~ghc/8.4.3/ghc-8.4.3-x86_64-deb8-linux.tar.xz-              dlSubdir: ghc-8.4.3-              dlHash: 30a402c6d4754a6c020e0547f19ae3ac42e907e35349aa932d347f73e421a8e2-            unknown_versioning: &ghc-843-64-deb9-              dlUri: https://downloads.haskell.org/~ghc/8.4.3/ghc-8.4.3-x86_64-deb9-linux.tar.xz-              dlSubdir: ghc-8.4.3-              dlHash: 2e4f53afb872ad9c640f31aea283b3ff4c5028b65808a1920739900aef7d15c9-          Linux_Ubuntu:-            unknown_versioning: &ghc-843-64-fedora-              dlUri: https://downloads.haskell.org/~ghc/8.4.3/ghc-8.4.3-x86_64-fedora27-linux.tar.xz-              dlSubdir: ghc-8.4.3-              dlHash: 269e7a4d3f336491b88409a020998122b30a3a729af78d33be86d3b3f8000c3e-            '( >= 16 && < 19 )': *ghc-843-64-deb9-          Linux_Mint:-            unknown_versioning: *ghc-843-64-fedora-          Linux_Fedora:-            unknown_versioning: *ghc-843-64-fedora-          Linux_UnknownLinux:-            unknown_versioning: *ghc-843-64-fedora-          Darwin:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/8.4.3/ghc-8.4.3-x86_64-apple-darwin.tar.xz-              dlSubdir: ghc-8.4.3-              dlHash: af0b455f6c46b9802b4b48dad996619cfa27cc6e2bf2ce5532387b4a8c00aa64-        A_32:-          Linux_Debian:-            unknown_versioning: &ghc-843-32-deb8-              dlUri: https://downloads.haskell.org/~ghc/8.4.3/ghc-8.4.3-i386-deb8-linux.tar.xz-              dlSubdir: ghc-8.4.3-              dlHash: f5763983a26dedd88b65a0b17267359a3981b83a642569b26334423f684f8b8c-          Linux_Ubuntu:-            unknown_versioning: *ghc-843-32-deb8-          Linux_Mint:-            unknown_versioning: *ghc-843-32-deb8-          Linux_UnknownLinux:-            unknown_versioning: *ghc-843-32-deb8-    8.4.4:-      viTags:-      - base-4.11.1.0-      viChangeLog: https://downloads.haskell.org/~ghc/8.4.4/docs/html/users_guide/8.4.4-notes.html-      viSourceDL:-        dlUri: https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-src.tar.xz-        dlSubdir: ghc-8.4.4-        dlHash: 11117735a58e507c481c09f3f39ae5a314e9fbf49fc3109528f99ea7959004b2-      viPostRemove: *ghc-post-remove-      viArch:-        A_64:-          Linux_Debian:-            '( >= 8 && < 9 )':-              dlUri: https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-x86_64-deb8-linux.tar.xz-              dlSubdir: ghc-8.4.4-              dlHash: 4c2a8857f76b7f3e34ecba0b51015d5cb8b767fe5377a7ec477abde10705ab1a-            unknown_versioning: &ghc-844-64-deb9-              dlUri: https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-x86_64-deb9-linux.tar.xz-              dlSubdir: ghc-8.4.4-              dlHash: 47c80a32d8f02838a2401414c94ba260d1fe82b7d090479994522242c767cc83-          Linux_Ubuntu:-            unknown_versioning: &ghc-844-64-fedora-              dlUri: https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-x86_64-fedora27-linux.tar.xz-              dlSubdir: ghc-8.4.4-              dlHash: 8ab2befddc14d1434d0aad0c5d3c7e0c2b78ff84caa3429fa62527bfc6b86095-            '( >= 16 && < 19 )': *ghc-844-64-deb9-          Linux_Mint:-            unknown_versioning: *ghc-844-64-fedora-          Linux_Fedora:-            unknown_versioning: *ghc-844-64-fedora-          Linux_CentOS:-            unknown_versioning: &ghc-844-64-centos-              dlUri: https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-x86_64-centos70-linux.tar.xz-              dlSubdir: ghc-8.4.4-              dlHash: 83a96650f5a92b1e4d7651d256d6438624342d40e780e68125033435a54cd674-          Linux_RedHat:-            unknown_versioning: *ghc-844-64-centos-          Linux_Alpine:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.4.4/ghc-8.4.4-x86_64-alpine-linux.tar.xz-              dlSubdir: ghc-8.4.4-              dlHash: 336affff8314d3dc5e85d9c09015ae2ba8a7658b459c8c8ae77ecaa551a56ae7-          Linux_AmazonLinux:-            unknown_versioning: *ghc-844-64-centos-          Linux_UnknownLinux:-            unknown_versioning: *ghc-844-64-fedora-          Darwin:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-x86_64-apple-darwin.tar.xz-              dlSubdir: ghc-8.4.4-              dlHash: 28dc89ebd231335337c656f4c5ead2ae2a1acc166aafe74a14f084393c5ef03a-          FreeBSD:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-x86_64-portbld-freebsd11.tar.xz-              dlSubdir: ghc-8.4.4-              dlHash: 44fbd142d1c355d6110595c59c760e2c73866ff9259ec85ebf814edb244d1940-        A_32:-          Linux_Debian:-            unknown_versioning: &ghc-844-32-deb8-              dlUri: https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-i386-deb8-linux.tar.xz-              dlSubdir: ghc-8.4.4-              dlHash: 678bafaabea6af70ba71ccf0210bb437f9f5591ec28ac1cbbbd5f7aa6894e450-          Linux_Ubuntu:-            unknown_versioning: *ghc-844-32-deb8-          Linux_Mint:-            unknown_versioning: *ghc-844-32-deb8-          Linux_Alpine:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.4.4/ghc-8.4.4-i386-alpine-linux.tar.xz-              dlSubdir: ghc-8.4.4-              dlHash: 892888d388ef5c9cadf5cfba1146d62237c25b9b066fb62fee940b2b285fd308-          Linux_UnknownLinux:-            unknown_versioning: *ghc-844-32-deb8-    8.6.1:-      viTags:-      - base-4.12.0.0-      - old-      viChangeLog: https://downloads.haskell.org/~ghc/8.6.1/docs/html/users_guide/8.6.1-notes.html-      viSourceDL:-        dlUri: https://downloads.haskell.org/~ghc/8.6.1/ghc-8.6.1-src.tar.xz-        dlSubdir: ghc-8.6.1-        dlHash: 2c25c26d1e5c47c7cbb2a1d8e6456524033e7a71409184dd3125e3fc5a3c7036-      viPostRemove: *ghc-post-remove-      viArch:-        A_64:-          Linux_Debian:-            '( >= 8 && < 9 )':-              dlUri: https://downloads.haskell.org/~ghc/8.6.1/ghc-8.6.1-x86_64-deb8-linux.tar.xz-              dlSubdir: ghc-8.6.1-              dlHash: 6d8784401b7dd80c90fa17306ec0539920e3987399a2c7ef247989e53197dc42-            unknown_versioning: &ghc-861-64-deb9-              dlUri: https://downloads.haskell.org/~ghc/8.6.1/ghc-8.6.1-x86_64-deb9-linux.tar.xz-              dlSubdir: ghc-8.6.1-              dlHash: 97d44f303868d74e4d13a2e99c82ffce3d25fd54c704675e5a1939e0d824dbf0-          Linux_Ubuntu:-            unknown_versioning: &ghc-861-64-fedora-              dlUri: https://downloads.haskell.org/~ghc/8.6.1/ghc-8.6.1-x86_64-fedora27-linux.tar.xz-              dlSubdir: ghc-8.6.1-              dlHash: da903fbcf11ee6c977a8b7dac3f04dbc098d674def587880b6624b8f32588beb-            '( >= 16 && < 19 )': *ghc-861-64-deb9-          Linux_Mint:-            unknown_versioning: *ghc-861-64-fedora-          Linux_Fedora:-            unknown_versioning: *ghc-861-64-fedora-          Linux_UnknownLinux:-            unknown_versioning: *ghc-861-64-fedora-          Darwin:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/8.6.1/ghc-8.6.1-x86_64-apple-darwin.tar.xz-              dlSubdir: ghc-8.6.1-              dlHash: 9692cdfd202b0e039ea0c3dde5dbf653736c836ca1df46504b179b572100808c-          FreeBSD:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/8.6.1/ghc-8.6.1-x86_64-portbld-freebsd.tar.xz-              dlSubdir: ghc-8.6.1-              dlHash: 51403b054a3a649039ac988e1d1112561f96750bfced63df864091a3fab36f08-        A_32:-          Linux_Debian:-            unknown_versioning: &ghc-861-32-deb8-              dlUri: https://downloads.haskell.org/~ghc/8.6.1/ghc-8.6.1-i386-deb8-linux.tar.xz-              dlSubdir: ghc-8.6.1-              dlHash: 83573af96e3dec8f67c1a844512f92cbf7d51ae7ceca53d948fc2a3300abd05c-          Linux_Ubuntu:-            unknown_versioning: *ghc-861-32-deb8-          Linux_Mint:-            unknown_versioning: *ghc-861-32-deb8-          Linux_UnknownLinux:-            unknown_versioning: *ghc-861-32-deb8-    8.6.2:-      viTags:-      - base-4.12.0.0-      - old-      viChangeLog: https://downloads.haskell.org/~ghc/8.6.2/docs/html/users_guide/8.6.2-notes.html-      viSourceDL:-        dlUri: https://downloads.haskell.org/~ghc/8.6.2/ghc-8.6.2-src.tar.xz-        dlSubdir: ghc-8.6.2-        dlHash: caaa819d21280ecde90a4773143dee188711e9ff175a27cfbaee56eb851d76d5-      viPostRemove: *ghc-post-remove-      viArch:-        A_64:-          Linux_Debian:-            unknown_versioning: &ghc-862-64-deb8-              dlUri: https://downloads.haskell.org/~ghc/8.6.2/ghc-8.6.2-x86_64-deb8-linux.tar.xz-              dlSubdir: ghc-8.6.2-              dlHash: 13f96e8b83bb5bb60f955786ff9085744c24927a33be8a17773f84c7c248533a-          Linux_Ubuntu:-            unknown_versioning: &ghc-862-64-fedora-              dlUri: https://downloads.haskell.org/~ghc/8.6.2/ghc-8.6.2-x86_64-fedora27-linux.tar.xz-              dlSubdir: ghc-8.6.2-              dlHash: 702aa5dfa1639c37953ceb7571a5057d9fb0562aecb197b277953a037d78047d-            '( >= 16 && < 19 )': *ghc-862-64-deb8-          Linux_Mint:-            unknown_versioning: *ghc-862-64-fedora-          Linux_Fedora:-            unknown_versioning: *ghc-862-64-fedora-          Linux_UnknownLinux:-            unknown_versioning: *ghc-862-64-fedora-          Darwin:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/8.6.2/ghc-8.6.2-x86_64-apple-darwin.tar.xz-              dlSubdir: ghc-8.6.2-              dlHash: 8ec46a25872226dd7e5cf7271e3f3450c05f32144b96e6b9cb44cc4079db50dc-        A_32:-          Linux_Debian:-            unknown_versioning: &ghc-862-32-deb8-              dlUri: https://downloads.haskell.org/~ghc/8.6.2/ghc-8.6.2-i386-deb8-linux.tar.xz-              dlSubdir: ghc-8.6.2-              dlHash: a288026d9ef22f7ac387edab6b29ef7dcb3b28945c8ea532a15c1fa35d4733ed-          Linux_Ubuntu:-            unknown_versioning: *ghc-862-32-deb8-          Linux_Mint:-            unknown_versioning: *ghc-862-32-deb8-          Linux_UnknownLinux:-            unknown_versioning: *ghc-862-32-deb8-    8.6.3:-      viTags:-      - base-4.12.0.0-      - old-      viChangeLog: https://downloads.haskell.org/~ghc/8.6.3/docs/html/users_guide/8.6.3-notes.html-      viSourceDL:-        dlUri: https://downloads.haskell.org/~ghc/8.6.3/ghc-8.6.3-src.tar.xz-        dlSubdir: ghc-8.6.3-        dlHash: 9f9e37b7971935d88ba80426c36af14b1e0b3ec1d9c860f44a4391771bc07f23-      viPostRemove: *ghc-post-remove-      viArch:-        A_64:-          Linux_Debian:-            '( >= 8 && < 9 )':-              dlUri: https://downloads.haskell.org/~ghc/8.6.3/ghc-8.6.3-x86_64-deb8-linux.tar.xz-              dlSubdir: ghc-8.6.3-              dlHash: 291ca565374f4d51cc311488581f3279d3167a064fabfd4a6722fe2bd4532fd5-            unknown_versioning: &ghc-863-64-deb9-              dlUri: https://downloads.haskell.org/~ghc/8.6.3/ghc-8.6.3-x86_64-deb9-linux.tar.xz-              dlSubdir: ghc-8.6.3-              dlHash: e7954c8ed9b422a09c6ab737e4a0865a2725d034ba0e272bd5c70db910797f99-          Linux_Ubuntu:-            unknown_versioning: &ghc-863-64-fedora-              dlUri: https://downloads.haskell.org/~ghc/8.6.3/ghc-8.6.3-x86_64-fedora27-linux.tar.xz-              dlSubdir: ghc-8.6.3-              dlHash: 52ae92f4e8bb2ac0b7847287ea3da37081f5f7bf8bbb7c78ac35fde537d1a89f-            '( >= 16 && < 19 )': *ghc-863-64-deb9-          Linux_Mint:-            unknown_versioning: *ghc-863-64-fedora-          Linux_Fedora:-            unknown_versioning: *ghc-863-64-fedora-          Linux_CentOS:-            unknown_versioning: &ghc-863-64-centos-              dlUri: https://downloads.haskell.org/~ghc/8.6.3/ghc-8.6.3-x86_64-centos7-linux.tar.xz-              dlSubdir: ghc-8.6.3-              dlHash: 355bd85c69933c31bbe99b4269ce719acfd0aad0b45e359ac39b9bb13996acc6-          Linux_RedHat:-            unknown_versioning: *ghc-863-64-centos-          Linux_AmazonLinux:-            unknown_versioning: *ghc-863-64-centos-          Linux_UnknownLinux:-            unknown_versioning: *ghc-863-64-fedora-          Darwin:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/8.6.3/ghc-8.6.3-x86_64-apple-darwin.tar.xz-              dlSubdir: ghc-8.6.3-              dlHash: 79d069a1a7d74cfdd7ac2a2711c45d3ddc6265b988a0cefa342714b24f997fc1-          FreeBSD:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/8.6.3/ghc-8.6.3-x86_64-portbld-freebsd.tar.xz-              dlSubdir: ghc-8.6.3-              dlHash: bc2419fa180f8a7808c49775987866435995df9bdd9ce08bcd38352d63ba6031-        A_32:-          Linux_Debian:-            unknown_versioning: &ghc-863-32-deb8-              dlUri: https://downloads.haskell.org/~ghc/8.6.3/ghc-8.6.3-i386-deb8-linux.tar.xz-              dlSubdir: ghc-8.6.3-              dlHash: b57070ba8c70b1333a3e47ce124baf791be39c20a592954772532fd6dd51882f-          Linux_Ubuntu:-            unknown_versioning: *ghc-863-32-deb8-          Linux_Mint:-            unknown_versioning: *ghc-863-32-deb8-          Linux_UnknownLinux:-            unknown_versioning: *ghc-863-32-deb8-    8.6.4:-      viTags:-      - base-4.12.0.0-      - old-      viChangeLog: https://downloads.haskell.org/~ghc/8.6.4/docs/html/users_guide/8.6.4-notes.html-      viSourceDL:-        dlUri: https://downloads.haskell.org/~ghc/8.6.4/ghc-8.6.4-src.tar.xz-        dlSubdir: ghc-8.6.4-        dlHash: 5b5d07e4463203a433c3ed3df461ba6cce11b6d2b9b264db31f3429075d0303a-      viPostRemove: *ghc-post-remove-      viArch:-        A_64:-          Linux_Debian:-            '( >= 8 && < 9 )':-              dlUri: https://downloads.haskell.org/~ghc/8.6.4/ghc-8.6.4-x86_64-deb8-linux.tar.xz-              dlSubdir: ghc-8.6.4-              dlHash: 34ef5fc8ddf2fc32a027180bea5b1c8a81ea840c87faace2977a572188d4b42d-            unknown_versioning: &ghc-864-64-deb9-              dlUri: https://downloads.haskell.org/~ghc/8.6.4/ghc-8.6.4-x86_64-deb9-linux.tar.xz-              dlSubdir: ghc-8.6.4-              dlHash: ef74222ef3c01c3fc5b926f67e8b4ef612fe8efa40ac937317cff9b0eed8d863-          Linux_Ubuntu:-            unknown_versioning: &ghc-864-64-fedora-              dlUri: https://downloads.haskell.org/~ghc/8.6.4/ghc-8.6.4-x86_64-fedora27-linux.tar.xz-              dlSubdir: ghc-8.6.4-              dlHash: e0b1ada7a679d6c35f9d7a1192ed35fde054f3650bb0bd2570d103729ad3b846-            '( >= 16 && < 19 )': *ghc-864-64-deb9-          Linux_Mint:-            unknown_versioning: *ghc-864-64-fedora-          Linux_Fedora:-            unknown_versioning: *ghc-864-64-fedora-          Linux_UnknownLinux:-            unknown_versioning: *ghc-864-64-fedora-          Darwin:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/8.6.4/ghc-8.6.4-x86_64-apple-darwin.tar.xz-              dlSubdir: ghc-8.6.4-              dlHash: cccb58f142fe41b601d73690809f6089f7715b6a50a09aa3d0104176ab4db09e-        A_32:-          Linux_Debian:-            unknown_versioning: &ghc-864-32-deb9-              dlUri: https://downloads.haskell.org/~ghc/8.6.4/ghc-8.6.4-i386-deb9-linux.tar.xz-              dlSubdir: ghc-8.6.4-              dlHash: 5e2ce88f4d13d23ac37e278e0c7b51c801008931359b9fa8a631d804d2da552c-          Linux_Ubuntu:-            unknown_versioning: *ghc-864-32-deb9-          Linux_Mint:-            unknown_versioning: *ghc-864-32-deb9-          Linux_UnknownLinux:-            unknown_versioning: *ghc-864-32-deb9-    8.6.5:-      viTags:-      - base-4.12.0.0-      viChangeLog: https://downloads.haskell.org/~ghc/8.6.5/docs/html/users_guide/8.6.5-notes.html-      viSourceDL:-        dlUri: https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-src.tar.xz-        dlSubdir: ghc-8.6.5-        dlHash: 4d4aa1e96f4001b934ac6193ab09af5d6172f41f5a5d39d8e43393b9aafee361-      viPostRemove: *ghc-post-remove-      viArch:-        A_64:-          Linux_Debian:-            '( >= 8 && < 9 )':-              dlUri: https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-x86_64-deb8-linux.tar.xz-              dlSubdir: ghc-8.6.5-              dlHash: c419fd0aa9065fe4d2eb9a248e323860c696ddf3859749ca96a84938aee49107-            unknown_versioning: &ghc-865-64-deb9-              dlUri: https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-x86_64-deb9-linux.tar.xz-              dlSubdir: ghc-8.6.5-              dlHash: bc75f5601a9f41d58b2ba161b9e28fad52143a7229060f1e084168d9b2e914df-          Linux_Ubuntu:-            unknown_versioning: &ghc-865-64-fedora-              dlUri: https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-x86_64-fedora27-linux.tar.xz-              dlSubdir: ghc-8.6.5-              dlHash: cf78b53eaf336083e7a05f4a3000afbae4abe5bbc77ef80cc40e09d04ac5b4a1-            '( >= 16 && < 19 )': *ghc-865-64-deb9-          Linux_Mint:-            unknown_versioning: *ghc-865-64-fedora-          Linux_Fedora:-            unknown_versioning: *ghc-865-64-fedora-          Linux_CentOS:-            unknown_versioning: &ghc-865-64-centos-              dlUri: https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-x86_64-centos7-linux.tar.xz-              dlSubdir: ghc-8.6.5-              dlHash: 80ab566f4411299f9e5922d60749ca80f989d697db19e03ed875619d699f0edf-          Linux_RedHat:-            unknown_versioning: *ghc-865-64-centos-          Linux_Alpine:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.6.5/ghc-8.6.5-x86_64-alpine-linux.tar.xz-              dlSubdir: ghc-8.6.5-              dlHash: b9d3ed7f7aa24ef2d58bb579252289caa0b8877adee3685e3af2fb73d440afdc-          Linux_AmazonLinux:-            unknown_versioning: *ghc-865-64-centos-          Linux_UnknownLinux:-            unknown_versioning: *ghc-865-64-fedora-          Darwin:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-x86_64-apple-darwin.tar.xz-              dlSubdir: ghc-8.6.5-              dlHash: dfc1bdb1d303a87a8552aa17f5b080e61351f2823c2b99071ec23d0837422169-          FreeBSD:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.6.5/ghc-8.6.5-x86_64-portbld-freebsd.tar.xz-              dlSubdir: ghc-8.6.5-              dlHash: 83a3059a630d40a98e26cb5b520354e12094a96e36ba2f5ab002dad94cf2fb37-        A_32:-          Linux_Debian:-            unknown_versioning: &ghc-865-32-deb9-              dlUri: https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-i386-deb9-linux.tar.xz-              dlSubdir: ghc-8.6.5-              dlHash: 1cddb907393a669342b1a922dd16d505d9d93d50bd9433a54a8162f8701250dc-          Linux_Ubuntu:-            unknown_versioning: *ghc-865-32-deb9-          Linux_Mint:-            unknown_versioning: *ghc-865-32-deb9-          Linux_Alpine:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.6.5/ghc-8.6.5-i386-alpine-linux.tar.xz-              dlSubdir: ghc-8.6.5-              dlHash: 3737837550d9b177acfe150e3a3cd4545427ded020487c2ed5194d7b8f116349-          Linux_UnknownLinux:-            unknown_versioning: *ghc-865-32-deb9-        A_ARM64:-          Linux_UnknownLinux:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-aarch64-ubuntu18.04-linux.tar.xz-              dlSubdir: ghc-8.6.5-              dlHash: 1852589037e4b2805ab517bc430e25a3125c4a118a1674ffefbb443394a0c786-    8.8.1:-      viTags:-      - base-4.13.0.0-      - old-      viChangeLog: https://downloads.haskell.org/~ghc/8.8.1/docs/html/users_guide/8.8.1-notes.html-      viSourceDL:-        dlUri: https://downloads.haskell.org/~ghc/8.8.1/ghc-8.8.1-src.tar.xz-        dlSubdir: ghc-8.8.1-        dlHash: 908a83d9b814da74585de9d39687189e6260ec3848131f9d9236cab8a123721a-      viPostRemove: *ghc-post-remove-      viArch:-        A_64:-          Linux_Debian:-            '( >= 8 && < 9 )':-              dlUri: https://downloads.haskell.org/~ghc/8.8.1/ghc-8.8.1-x86_64-deb8-linux.tar.xz-              dlSubdir: ghc-8.8.1-              dlHash: fd96eb851971fbc3332bf2fa7821732cfa8b37e5a076a69f6a06f83f0ea7ccc5-            unknown_versioning: &ghc-881-64-deb9-              dlUri: https://downloads.haskell.org/~ghc/8.8.1/ghc-8.8.1-x86_64-deb9-linux.tar.xz-              dlSubdir: ghc-8.8.1-              dlHash: 620fd560535b63cac5f8c97354ccddf93fa940cca78e2d19f6f98b7e67c6a723-          Linux_Ubuntu:-            unknown_versioning: &ghc-881-64-fedora-              dlUri: https://downloads.haskell.org/~ghc/8.8.1/ghc-8.8.1-x86_64-fedora27-linux.tar.xz-              dlSubdir: ghc-8.8.1-              dlHash: 851a78df620bc056c34b252c97040d5755e294993fa8afa5429708b5229204d6-            '( >= 16 && < 19 )': *ghc-881-64-deb9-          Linux_Mint:-            unknown_versioning: *ghc-881-64-fedora-          Linux_Fedora:-            unknown_versioning: *ghc-881-64-fedora-          Linux_CentOS:-            unknown_versioning: &ghc-881-64-centos-              dlUri: https://downloads.haskell.org/~ghc/8.8.1/ghc-8.8.1-x86_64-centos7-linux.tar.xz-              dlSubdir: ghc-8.8.1-              dlHash: 6cdd34e4dbaeb801e805811f91cf43a2d5f64b22f884718ffbd3542a2f4dd14f-          Linux_RedHat:-            unknown_versioning: *ghc-881-64-centos-          Linux_AmazonLinux:-            unknown_versioning: *ghc-881-64-centos-          Linux_UnknownLinux:-            unknown_versioning: *ghc-881-64-fedora-          Darwin:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/8.8.1/ghc-8.8.1-x86_64-apple-darwin.tar.xz-              dlSubdir: ghc-8.8.1-              dlHash: 38c8917b47c31bedf58c9305dfca3abe198d8d35570366f0773c4e2948bd8abe-        A_32:-          Linux_Debian:-            unknown_versioning: &ghc-881-32-deb9-              dlUri: https://downloads.haskell.org/~ghc/8.8.1/ghc-8.8.1-i386-deb9-linux.tar.xz-              dlSubdir: ghc-8.8.1-              dlHash: 3d3bb75aff2dd79ec87ace10483368681fbc328ff00ebf15edad33420f00f7f5-          Linux_Ubuntu:-            unknown_versioning: *ghc-881-32-deb9-          Linux_Mint:-            unknown_versioning: *ghc-881-32-deb9-          Linux_UnknownLinux:-            unknown_versioning: *ghc-881-32-deb9-    8.8.2:-      viTags:-      - base-4.13.0.0-      - old-      viChangeLog: https://downloads.haskell.org/~ghc/8.8.2/docs/html/users_guide/8.8.2-notes.html-      viSourceDL:-        dlUri: https://downloads.haskell.org/~ghc/8.8.2/ghc-8.8.2-src.tar.xz-        dlSubdir: ghc-8.8.2-        dlHash: 01cea54d90686b97bcc9960b108beaffccd4336dee930dcf9beaf52b1f370a0b-      viPostRemove: *ghc-post-remove-      viArch:-        A_64:-          Linux_Debian:-            '( >= 8 && < 9 )':-              dlUri: https://downloads.haskell.org/~ghc/8.8.2/ghc-8.8.2-x86_64-deb8-linux.tar.xz-              dlSubdir: ghc-8.8.2-              dlHash: fbe69652eba75dadb758d00292247d17fb018c29cac5acd79843e56311256c9f-            unknown_versioning: &ghc-882-64-deb9-              dlUri: https://downloads.haskell.org/~ghc/8.8.2/ghc-8.8.2-x86_64-deb9-linux.tar.xz-              dlSubdir: ghc-8.8.2-              dlHash: 7b2d66c2d5d8c15750da5833d3018634a5eb792a5662282e3abfeb112c2a1cc3-          Linux_Ubuntu:-            unknown_versioning: &ghc-882-64-fedora-              dlUri: https://downloads.haskell.org/~ghc/8.8.2/ghc-8.8.2-x86_64-fedora27-linux.tar.xz-              dlSubdir: ghc-8.8.2-              dlHash: dbe2db717b33460f790e155e487d2a31c9b21a9d245f0c9490ad65844c3ea21f-            '( >= 16 && < 19 )': *ghc-882-64-deb9-          Linux_Mint:-            unknown_versioning: *ghc-882-64-fedora-          Linux_Fedora:-            unknown_versioning: *ghc-882-64-fedora-          Linux_CentOS:-            unknown_versioning: &ghc-882-64-centos-              dlUri: https://downloads.haskell.org/~ghc/8.8.2/ghc-8.8.2-x86_64-centos7-linux.tar.xz-              dlSubdir: ghc-8.8.2-              dlHash: f065a017d7a38f235f186ffe32d8261a4fd39c7e945d5cde85c0984c2569db99-          Linux_RedHat:-            unknown_versioning: *ghc-882-64-centos-          Linux_AmazonLinux:-            unknown_versioning: *ghc-882-64-centos-          Linux_UnknownLinux:-            unknown_versioning: *ghc-882-64-fedora-          Darwin:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/8.8.2/ghc-8.8.2-x86_64-apple-darwin.tar.xz-              dlSubdir: ghc-8.8.2-              dlHash: 25c5c1a70036abf3f22b2b19c10d26adfdb08e8f8574f89d4b2042de5947f990-        A_32:-          Linux_Debian:-            unknown_versioning: &ghc-882-32-deb9-              dlUri: https://downloads.haskell.org/~ghc/8.8.2/ghc-8.8.2-i386-deb9-linux.tar.xz-              dlSubdir: ghc-8.8.2-              dlHash: ad1c628082c32635a436905a7ff83eaa4246347d869be5ef6b33c3bf85e8f00c-          Linux_Ubuntu:-            unknown_versioning: *ghc-882-32-deb9-          Linux_Mint:-            unknown_versioning: *ghc-882-32-deb9-          Linux_UnknownLinux:-            unknown_versioning: *ghc-882-32-deb9-    8.8.3:-      viTags:-      - base-4.13.0.0-      - old-      viChangeLog: https://downloads.haskell.org/~ghc/8.8.3/docs/html/users_guide/8.8.3-notes.html-      viSourceDL:-        dlUri: https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-src.tar.xz-        dlSubdir: ghc-8.8.3-        dlHash: e0dcc0aaf3e234c5978f29e6df62947e97720ab404ec0158343df211c5480f89-      viPostRemove: *ghc-post-remove-      viArch:-        A_64:-          Linux_Debian:-            '( >= 8 && < 9 )':-              dlUri: https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-x86_64-deb8-linux.tar.xz-              dlSubdir: ghc-8.8.3-              dlHash: 92b9fadc442976968d2c190c14e000d737240a7d721581cda8d8741b7bd402f0-            unknown_versioning: &ghc-883-64-deb9-              dlUri: https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-x86_64-deb9-linux.tar.xz-              dlSubdir: ghc-8.8.3-              dlHash: 42fde2ef5a143e1e6b47ae8875162ea2d4d54b06f0f7fa32ee4f0eb86f2be7ad-          Linux_Ubuntu:-            unknown_versioning: &ghc-883-64-fedora-              dlUri: https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-x86_64-fedora27-linux.tar.xz-              dlSubdir: ghc-8.8.3-              dlHash: 45ee1de3bfc98cbcc4886b65fc7651ade2d3820aa85eac2dbe9bc7bf91e7c818-            '( >= 16 && < 19 )': *ghc-883-64-deb9-          Linux_Mint:-            unknown_versioning: *ghc-883-64-fedora-          Linux_Fedora:-            unknown_versioning: *ghc-883-64-fedora-          Linux_CentOS:-            unknown_versioning: &ghc-883-64-centos-              dlUri: https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-x86_64-centos7-linux.tar.xz-              dlSubdir: ghc-8.8.3-              dlHash: 4b2b5313f7c12b81e54efcb26705fa9e4ad5b98f2b58bfc76fb0c9ba1d55eb1f-          Linux_RedHat:-            unknown_versioning: *ghc-883-64-centos-          Linux_AmazonLinux:-            unknown_versioning: *ghc-883-64-centos-          Linux_UnknownLinux:-            unknown_versioning: *ghc-883-64-fedora-          Darwin:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-x86_64-apple-darwin.tar.xz-              dlSubdir: ghc-8.8.3-              dlHash: 7016de90dd226b06fc79d0759c5d4c83c2ab01d8c678905442c28bd948dbb782-          FreeBSD:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.8.3/ghc-8.8.3-x86_64-portbld-freebsd.tar.xz-              dlSubdir: ghc-8.8.3-              dlHash: 569719075b4d14b3875a899df522090ae31e6fe085e6dffe518e875b09a2f0be-        A_32:-          Linux_Debian:-            unknown_versioning: &ghc-883-32-deb9-              dlUri: https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-i386-deb9-linux.tar.xz-              dlSubdir: ghc-8.8.3-              dlHash: 441e2c7a4fc83ebf179712bd939b555cda7c6633545b7c8ac38049f9d85003ae-          Linux_Ubuntu:-            unknown_versioning: *ghc-883-32-deb9-          Linux_Mint:-            unknown_versioning: *ghc-883-32-deb9-          Linux_UnknownLinux:-            unknown_versioning: *ghc-883-32-deb9-        A_ARM64:-          Linux_UnknownLinux:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-aarch64-deb9-linux.tar.xz-              dlSubdir: ghc-8.8.3-              dlHash: 2a6821d0e7326cfa7670851702924bbab3b092415ba41247c37419158327eed9-    8.8.4:-      viTags:-      - base-4.13.0.0-      viChangeLog: https://downloads.haskell.org/~ghc/8.8.4/docs/html/users_guide/8.8.4-notes.html-      viSourceDL:-        dlUri: https://downloads.haskell.org/~ghc/8.8.4/ghc-8.8.4-src.tar.xz-        dlSubdir: ghc-8.8.4-        dlHash: f0505e38b2235ff9f1090b51f44d6c8efd371068e5a6bb42a2a6d8b67b5ffc2d-      viPostRemove: *ghc-post-remove-      viArch:-        A_64:-          Linux_Debian:-            '( >= 8 && < 9 )':-              dlUri: https://downloads.haskell.org/~ghc/8.8.4/ghc-8.8.4-x86_64-deb8-linux.tar.xz-              dlSubdir: ghc-8.8.4-              dlHash: 51a36892f1264744195274187298d13ac62bce2da86d4ddf76d8054ab90f2feb-            unknown_versioning: &ghc-884-64-deb9-              dlUri: https://downloads.haskell.org/~ghc/8.8.4/ghc-8.8.4-x86_64-deb9-linux.tar.xz-              dlSubdir: ghc-8.8.4-              dlHash: 4862559d221153caf978f4bf2c15a82c114d1e1f43b298b2ecff2ac94b586d20-          Linux_Ubuntu:-            unknown_versioning: &ghc-884-64-fedora-              dlUri: https://downloads.haskell.org/~ghc/8.8.4/ghc-8.8.4-x86_64-fedora27-linux.tar.xz-              dlSubdir: ghc-8.8.4-              dlHash: f32e37f8aa03e74bad533ae02f62dc27a4521e78199576af490888ba34b515db-            '( >= 16 && < 19 )': *ghc-884-64-deb9-          Linux_Mint:-            unknown_versioning: *ghc-884-64-fedora-          Linux_Fedora:-            unknown_versioning: *ghc-884-64-fedora-          Linux_CentOS:-            unknown_versioning: &ghc-884-64-centos-              dlUri: https://downloads.haskell.org/~ghc/8.8.4/ghc-8.8.4-x86_64-centos7-linux.tar.xz-              dlSubdir: ghc-8.8.4-              dlHash: a12aa4b1fd3c64240a8a6d15196d33e1c0e0d55b51ff78c387242126d0ef7910-          Linux_RedHat:-            unknown_versioning: *ghc-884-64-centos-          Linux_Alpine:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.8.4/ghc-8.8.4-x86_64-alpine-linux.tar.xz-              dlSubdir: ghc-8.8.4-              dlHash: 90c6a1661de7f20c7d169cd6270125035b3332063e45103ce028df0beecf434e-          Linux_AmazonLinux:-            unknown_versioning: *ghc-884-64-centos-          Linux_UnknownLinux:-            unknown_versioning: *ghc-884-64-fedora-          Darwin:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/8.8.4/ghc-8.8.4-x86_64-apple-darwin.tar.xz-              dlSubdir: ghc-8.8.4-              dlHash: e80a789e9d8cfb41dd87f3284b75432427c4461c1731d220d04ead8733ccdb5e-          FreeBSD:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.8.4/ghc-8.8.4-x86_64-portbld-freebsd.tar.xz-              dlSubdir: ghc-8.8.4-              dlHash: 8cebe5ccf454e82acd1ff52ca57590d1ab0f3f44a981b46257ec12158c8c447e-        A_32:-          Linux_Debian:-            unknown_versioning: &ghc-884-32-deb9-              dlUri: https://downloads.haskell.org/~ghc/8.8.4/ghc-8.8.4-i386-deb9-linux.tar.xz-              dlSubdir: ghc-8.8.4-              dlHash: 43dd954910c9027694312cef0aabc7774d102d0422b7172802cfb72f7d5da3a0-          Linux_Ubuntu:-            unknown_versioning: *ghc-884-32-deb9-          Linux_Mint:-            unknown_versioning: *ghc-884-32-deb9-          Linux_Alpine:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.8.4/ghc-8.8.4-i386-alpine-linux.tar.xz-              dlSubdir: ghc-8.8.4-              dlHash: 1d18e89ee031197e55c48683e78a7ffc67601ac5fd9f73aac555eb064b3859a2-          Linux_UnknownLinux:-            unknown_versioning: *ghc-884-32-deb9-    8.10.1:-      viTags:-      - base-4.14.0.0-      - old-      viChangeLog: https://downloads.haskell.org/~ghc/8.10.1/docs/html/users_guide/8.10.1-notes.html-      viSourceDL:-        dlUri: https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-src.tar.xz-        dlSubdir: ghc-8.10.1-        dlHash: 4e3b07f83a266b3198310f19f71e371ebce97c769b14f0d688f4cbf2a2a1edf5-      viPostRemove: *ghc-post-remove-      viArch:-        A_64:-          Linux_Debian:-            '( >= 9 && < 10 )': &ghc-8101-64-deb9-              dlUri: https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-x86_64-deb9-linux.tar.xz-              dlSubdir: ghc-8.10.1-              dlHash: d1cf7886f27af070f3b7dbe1975a78b43ef2d32b86362cbe953e79464fe70761-            '( >= 10 && < 11 )': &ghc-8101-64-deb10-              dlUri: https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-x86_64-deb10-linux.tar.xz-              dlSubdir: ghc-8.10.1-              dlHash: c1e31d798b013699b3c0de4fda27fb4cda47f572df0e75e3bd598a3012060615-            unknown_versioning: *ghc-8101-64-deb9-          Linux_Ubuntu:-            unknown_versioning: &ghc-8101-64-fedora-              dlUri: https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-x86_64-fedora27-linux.tar.xz-              dlSubdir: ghc-8.10.1-              dlHash: 3c4cd72b4806045779739e8f5d1658e30e57123d88c2c8966422cdbcae448470-            '( >= 16 && < 19 )': *ghc-8101-64-deb9-          Linux_Mint:-            unknown_versioning: *ghc-8101-64-fedora-          Linux_Fedora:-            '( >= 27 && < 28 )': *ghc-8101-64-fedora-            unknown_versioning: *ghc-8101-64-fedora-          Linux_CentOS:-            '( >= 7 && < 8 )': &ghc-8101-64-centos-              dlUri: https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-x86_64-centos7-linux.tar.xz-              dlSubdir: ghc-8.10.1-              dlHash: 0618b94854edc6be5302489df905e627820b71be6b66c950f5e3088fe92df0a1-            unknown_versioning: *ghc-8101-64-centos-          Linux_RedHat:-            unknown_versioning: *ghc-8101-64-centos-          Linux_Alpine:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-x86_64-alpine3.10-linux-integer-simple.tar.xz-              dlSubdir: ghc-8.10.1-x86_64-unknown-linux-              dlHash: cb13b645d103e2fba2eb8dfcc4e5f2fbd9550c00c4df42f342b4210436dcb8a8-          Linux_AmazonLinux:-            unknown_versioning: *ghc-8101-64-centos-          Linux_UnknownLinux:-            unknown_versioning: *ghc-8101-64-fedora-          Darwin:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-x86_64-apple-darwin.tar.xz-              dlSubdir: ghc-8.10.1-              dlHash: 65b1ca361093de4804a7e40b3e68178e1ef720f84f743641ec8d95e56a45b3a8-          FreeBSD:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.10.1/ghc-8.10.1-x86_64-portbld-freebsd.tar.xz-              dlSubdir: ghc-8.10.1-              dlHash: e8646ec9b60fd40aa9505ee055f22f04601290ab7a1342c2cf37c34de9d3f142-        A_32:-          Linux_Debian:-            '( >= 9 && < 10 )': &ghc-8101-32-deb9-              dlUri: https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-i386-deb9-linux.tar.xz-              dlSubdir: ghc-8.10.1-              dlHash: 8b53eef2c827b5f634d72920a93c0c9dd66ea288691a2bfe28def45d3c686ee2-            unknown_versioning: *ghc-8101-32-deb9-          Linux_Ubuntu:-            unknown_versioning: *ghc-8101-32-deb9-          Linux_Mint:-            unknown_versioning: *ghc-8101-32-deb9-          Linux_Alpine:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.10.1/ghc-8.10.1-i386-alpine-linux.tar.xz-              dlSubdir: ghc-8.10.1-              dlHash: 7360cc6b29e9b4ab08f6ea5bc3bcca6f5c216933e81ef1620dcdd700f1fdb289-          Linux_UnknownLinux:-            unknown_versioning: *ghc-8101-32-deb9-        A_ARM64:-          Linux_UnknownLinux:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-aarch64-deb9-linux.tar.xz-              dlSubdir: ghc-8.10.1-              dlHash: c099011e07999db917e797fb5d89c31f075a562556ab99be8ab0accbf2a94db7-        A_ARM:-          Linux_UnknownLinux:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-armv7-deb9-linux.tar.xz-              dlSubdir: ghc-8.10.1-              dlHash: afe1bde2b0d6deb0320b9460fffe5d9427e302df85aec866b9c1458777d52b28-    8.10.2:-      viTags:-      - old-      - base-4.14.1.0-      viChangeLog: https://downloads.haskell.org/~ghc/8.10.2/docs/html/users_guide/8.10.2-notes.html-      viSourceDL:-        dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-src.tar.xz-        dlSubdir: ghc-8.10.2-        dlHash: 9c573a4621a78723950617c223559bdc325ea6a3409264aedf68f05510b0880b-      viPostRemove: *ghc-post-remove-      viArch:-        A_64:-          Linux_Debian:-            '( >= 9 && < 10 )': &ghc-8102-64-deb9-              dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-x86_64-deb9-linux.tar.xz-              dlSubdir: ghc-8.10.2-              dlHash: 4dbe3b479e76767bfeb4cbb7a4db8b761c4720266193483ca370b2ace3f10f7c-            '( >= 10 && < 11 )': &ghc-8102-64-deb10-              dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-x86_64-deb10-linux.tar.xz-              dlSubdir: ghc-8.10.2-              dlHash: 94513d82c38c848f489113a75fa5ef4e5a8e3ecfaa74ca90e2620d2193ff1632-            unknown_versioning: *ghc-8102-64-deb9-          Linux_Ubuntu:-            unknown_versioning: &ghc-8102-64-fedora-              dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-x86_64-fedora27-linux.tar.xz-              dlSubdir: ghc-8.10.2-              dlHash: 8c675da83e9b3c2f64ebb407b5f9ebb2c1f21aa5d701020614fdce644a542e3b-            '( >= 16 && < 19 )': *ghc-8102-64-deb9-          Linux_Mint:-            unknown_versioning: *ghc-8102-64-fedora-          Linux_Fedora:-            '( >= 27 && < 28 )': *ghc-8102-64-fedora-            unknown_versioning: *ghc-8102-64-fedora-          Linux_CentOS:-            '( >= 7 && < 8 )': &ghc-8102-64-centos-              dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-x86_64-centos7-linux.tar.xz-              dlSubdir: ghc-8.10.2-              dlHash: fd2dccd6f496915a5f962dab24e7eeb8bee49bcc38e74b17eac76159083538fa-            unknown_versioning: *ghc-8102-64-centos-          Linux_RedHat:-            unknown_versioning: *ghc-8102-64-centos-          Linux_Alpine:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-x86_64-alpine3.10-linux-integer-simple.tar.xz-              dlSubdir: ghc-8.10.2-x86_64-unknown-linux-              dlHash: 14d09a508f2a3a11875c140be8e6c5f6982ac5cd448f089ca10b7adc955fec76-          Linux_AmazonLinux:-            unknown_versioning: *ghc-8102-64-centos-          Linux_UnknownLinux:-            unknown_versioning: *ghc-8102-64-fedora-          Darwin:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-x86_64-apple-darwin.tar.xz-              dlSubdir: ghc-8.10.2-              dlHash: edb772b00c0d7f18bb56ad27765162ee09c508104d40f82128c9114a02f6cfc2-          FreeBSD:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-x86_64-unknown-freebsd.tar.xz-              dlSubdir: ghc-8.10.2-              dlHash: 9e5957f3497f4b58ecd3699568d9caaa11a47a6d7e902032c261e450fa0f6686-        A_32:-          Linux_Debian:-            '( >= 9 && < 10 )': &ghc-8102-32-deb9-              dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-i386-deb9-linux.tar.xz-              dlSubdir: ghc-8.10.2-              dlHash: 9dae2a86ad43d08f72c783542c944d1556b075aa20a8063efae5034ea88e7c2f-            unknown_versioning: *ghc-8102-32-deb9-          Linux_Ubuntu:-            unknown_versioning: *ghc-8102-32-deb9-          Linux_Mint:-            unknown_versioning: *ghc-8102-32-deb9-          Linux_UnknownLinux:-            unknown_versioning: *ghc-8102-32-deb9-          Linux_Alpine:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.10.2/ghc-8.10.2-i386-alpine-linux.tar.xz-              dlSubdir: ghc-8.10.2-              dlHash: 9ee1cf1e85e9536088b3c9e80e975074e525ea378cd4eb156071bbc4b7b38327-        A_ARM64:-          Linux_UnknownLinux:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-aarch64-deb10-linux.tar.xz-              dlSubdir: ghc-8.10.2-              dlHash: 5cf24189077e6e2dce2aa16367ad8a53f603e751a15010dfb23d067206e55593-        A_ARM:-          Linux_UnknownLinux:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-armv7-deb10-linux.tar.xz-              dlSubdir: ghc-8.10.2-              dlHash: bb9c97826b1f4d7a8ef8bce0616b612f1ded10480ef10fcf7fb4e6d10a6681c8-    8.10.3:-      viTags:-      - base-4.14.1.0-      viChangeLog: https://downloads.haskell.org/~ghc/8.10.3/docs/html/users_guide/8.10.3-notes.html-      viSourceDL:-        dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-src.tar.xz-        dlSubdir: ghc-8.10.3-        dlHash: ccdc8319549028a708d7163e2967382677b1a5a379ff94d948195b5cf46eb931-      viPostRemove: *ghc-post-remove-      viArch:-        A_64:-          Linux_Debian:-            '( >= 9 && < 10 )': &ghc-8103-64-deb9-              dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-x86_64-deb9-linux.tar.xz-              dlSubdir: ghc-8.10.3-              dlHash: 95e4aadea30701fe5ab84d15f757926d843ded7115e11c4cd827809ca830718d-            '( >= 10 && < 11 )': &ghc-8103-64-deb10-              dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-x86_64-deb10-linux.tar.xz-              dlSubdir: ghc-8.10.3-              dlHash: c8f3d9f0e61a89eaba1d3ad8fb2eced1af0e81576811261b887993bee12538ac-            unknown_versioning: *ghc-8103-64-deb9-          Linux_Ubuntu:-            unknown_versioning: &ghc-8103-64-fedora-              dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-x86_64-fedora27-linux.tar.xz-              dlSubdir: ghc-8.10.3-              dlHash: f8739b12008712d6b6a9ffc6c39f9d05af77ef3bcb932c9aff20fa0893c8c159-            '( >= 16 && < 19 )': *ghc-8103-64-deb9-          Linux_Mint:-            unknown_versioning: *ghc-8103-64-deb10-          Linux_Fedora:-            '( >= 27 && < 28 )': *ghc-8103-64-fedora-            unknown_versioning: *ghc-8103-64-fedora-          Linux_CentOS:-            '( >= 7 && < 8 )': &ghc-8103-64-centos-              dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-x86_64-centos7-linux.tar.xz-              dlSubdir: ghc-8.10.3-              dlHash: f562ca61979ff1d21e34e69e59028cb742a8eff8d84e46bbd3a750f2ac7d8ed1-            unknown_versioning: *ghc-8103-64-centos-          Linux_RedHat:-            unknown_versioning: *ghc-8103-64-centos-          Linux_Alpine:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-x86_64-alpine3.10-linux-integer-simple.tar.xz-              dlSubdir: ghc-8.10.3-x86_64-unknown-linux-              dlHash: 8506c478ebbfb5441c3c36c07c36fc8532cacb2b3e13c6733bd44cb17b3ce96c-          Linux_AmazonLinux:-            unknown_versioning: *ghc-8103-64-centos-          Linux_UnknownLinux:-            unknown_versioning: *ghc-8103-64-fedora-          Darwin:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-x86_64-apple-darwin.tar.xz-              dlSubdir: ghc-8.10.3-              dlHash: 2635f35d76e44e69afdfd37cae89d211975cc20f71f784363b72003e59f22015-          FreeBSD:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-x86_64-portbld-freebsd.tar.xz-              dlSubdir: ghc-8.10.3-              dlHash: 749007e995104db05cf6e3ad5bc36238cab8afac8055145661e5730e8f8af040-        A_32:-          Linux_Debian:-            '( >= 9 && < 10 )': &ghc-8103-32-deb9-              dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-i386-deb9-linux.tar.xz-              dlSubdir: ghc-8.10.3-              dlHash: f0addd2a16b705f58ff9e8702c3ddf3e2d6bd0d3555707b5b5095e51bafee7b1-            unknown_versioning: *ghc-8103-32-deb9-          Linux_Ubuntu:-            unknown_versioning: *ghc-8103-32-deb9-          Linux_Mint:-            unknown_versioning: *ghc-8103-32-deb9-          Linux_UnknownLinux:-            unknown_versioning: *ghc-8103-32-deb9-          Linux_Alpine:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.10.3/ghc-8.10.3-i386-alpine-linux.tar.xz-              dlSubdir: ghc-8.10.3-              dlHash: 309201cdefd2d13b8b3fd09c26c6137048c490d219a0a9c7407c3ce1d011f60c-        A_ARM64:-          Linux_UnknownLinux:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-aarch64-deb10-linux.tar.xz-              dlSubdir: ghc-8.10.3-              dlHash: a531432d505a1fe886cdc8639d168eb1c92d76464c1270713e01ce81891bbadb-        A_ARM:-          Linux_UnknownLinux:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/8.10.3/ghc-8.10.3-armv7-deb10-linux.tar.xz-              dlSubdir: ghc-8.10.3-              dlHash: b823b58cae36fbac0741680ca7605180fa4cf4c6ae439123d282184b94d32fd6-    8.10.4:-      viTags:-      - Recommended-      - base-4.14.1.0-      viChangeLog: https://downloads.haskell.org/~ghc/8.10.4/docs/html/users_guide/8.10.4-notes.html-      viSourceDL:-        dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-src.tar.xz-        dlSubdir: ghc-8.10.4-        dlHash: 52af871b4e08550257d720c2944ac85727d0b948407cef1bebfe7508c224910e-      viPostRemove: *ghc-post-remove-      viPreCompile: "If you have autoconf >= 2.70 you'll need this patch https://gitlab.haskell.org/ghc/ghc/-/snippets/2040 (see the --patchdir option)"-      viArch:-        A_64:-          Linux_Debian:-            '( >= 9 && < 10 )': &ghc-8104-64-deb9-              dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-x86_64-deb9-linux.tar.xz-              dlSubdir: ghc-8.10.4-              dlHash: 5694200a5c38f22c142baf850b1d2f3784211d2ec9302e11693259a1ae8e38b7-            '( >= 10 && < 11 )': &ghc-8104-64-deb10-              dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-x86_64-deb10-linux.tar.xz-              dlSubdir: ghc-8.10.4-              dlHash: 816365565e9927459b035515a7db6a0db62f9796f327389b6f8a0035d12fbda0-            unknown_versioning: *ghc-8104-64-deb9-          Linux_Ubuntu:-            unknown_versioning: &ghc-8104-64-fedora-              dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-x86_64-fedora27-linux.tar.xz-              dlSubdir: ghc-8.10.4-              dlHash: a189eed900a8717d6d7906bafd10b9a9a9688ad942d1c75e19df480376dff9ea-            '( >= 16 && < 19 )': *ghc-8104-64-deb9-          Linux_Mint:-            unknown_versioning: *ghc-8104-64-deb10-          Linux_Fedora:-            '( >= 27 && < 28 )': *ghc-8104-64-fedora-            unknown_versioning: *ghc-8104-64-fedora-          Linux_CentOS:-            '( >= 7 && < 8 )': &ghc-8104-64-centos-              dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-x86_64-centos7-linux.tar.xz-              dlSubdir: ghc-8.10.4-              dlHash: fb8a91f0cf06594172aff46c2f6f7486179e1c3760855c79fbdd3012598cc2cd-            unknown_versioning: *ghc-8104-64-centos-          Linux_RedHat:-            unknown_versioning: *ghc-8104-64-centos-          Linux_Alpine:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-x86_64-alpine3.10-linux-integer-simple.tar.xz-              dlSubdir: ghc-8.10.4-x86_64-unknown-linux-              dlHash: 74c2c07537832708502716ef4ec40019f8e552ddda13c8eadf8f7c4b03a79359-          Linux_AmazonLinux:-            unknown_versioning: *ghc-8104-64-centos-          Linux_UnknownLinux:-            unknown_versioning: *ghc-8104-64-fedora-          Darwin:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-x86_64-apple-darwin.tar.xz-              dlSubdir: ghc-8.10.4-              dlHash: 725ecf6543e63b81a3581fb8c97afd21a08ae11bc0fa4f8ee25d45f0362ef6d5-          FreeBSD:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-x86_64-portbld-freebsd.tar.xz-              dlSubdir: ghc-8.10.4-              dlHash: c9776a2ccf9629b03e967206a507fcdcb6c5189800a626e9461ababf6733c357-        A_32:-          Linux_Debian:-            '( >= 9 && < 10 )': &ghc-8104-32-deb9-              dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-i386-deb9-linux.tar.xz-              dlSubdir: ghc-8.10.4-              dlHash: 0022c5b9ac22825bb7b4745af3d92cef0ba1ecd01fab3ef387ddbd47146569ad-            unknown_versioning: *ghc-8104-32-deb9-          Linux_Ubuntu:-            unknown_versioning: *ghc-8104-32-deb9-          Linux_Mint:-            unknown_versioning: *ghc-8104-32-deb9-          Linux_UnknownLinux:-            unknown_versioning: *ghc-8104-32-deb9-          Linux_Alpine:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/8.10.4/ghc-8.10.4-i386-alpine-linux.tar.xz-              dlSubdir: ghc-8.10.4-              dlHash: 9161a98bed763692101854d83af69c1316030cfe5ee6f6acde283d04ef139735-        A_ARM64:-          Linux_UnknownLinux:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-aarch64-deb10-linux.tar.xz-              dlSubdir: ghc-8.10.4-              dlHash: 249da6310be799a5eefe0579b6dae1701eb984afb980fe08309d19cf704038ed-        A_ARM:-          Linux_UnknownLinux:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/8.10.4/ghc-8.10.4-armv7-deb10-linux.tar.xz-              dlSubdir: ghc-8.10.4-              dlHash: 0d18ef83593272f6196a41cc3abdc48dfe5e14372db75d71ea19fe35320c4e81-    9.0.1:-      viTags:-      - Latest-      - base-4.15.0.0-      viChangeLog: https://downloads.haskell.org/~ghc/9.0.1/docs/html/users_guide/9.0.1-notes.html-      viSourceDL:-        dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-src.tar.xz-        dlSubdir: ghc-9.0.1-        dlHash: a5230314e4065f9fcc371dfe519748fd85c825b279abf72a24e09b83578a35f9-      viPostRemove: *ghc-post-remove-      viArch:-        A_64:-          Linux_Debian:-            '( >= 9 && < 10 )': &ghc-901-64-deb9-              dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-x86_64-deb9-linux.tar.xz-              dlSubdir: ghc-9.0.1-              dlHash: 4ca6252492f59fe589029fadca4b6f922d6a9f0ff39d19a2bd9886fde4e183d5-            '( >= 10 && < 11 )': &ghc-901-64-deb10-              dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-x86_64-deb10-linux.tar.xz-              dlSubdir: ghc-9.0.1-              dlHash: c253e7eb62cc9da6524c491c85ec8d3727c2ca6035a8653388e636aaa30a2a0f-            unknown_versioning: *ghc-901-64-deb9-          Linux_Ubuntu:-            unknown_versioning: &ghc-901-64-fedora-              dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-x86_64-fedora27-linux.tar.xz-              dlSubdir: ghc-9.0.1-              dlHash: 1fb8e27eeec51b4cdbfd1b3c16727adc5f77388d3e925e63799d8232647f316d-            '( >= 16 && < 19 )': *ghc-901-64-deb9-          Linux_Mint:-            unknown_versioning: *ghc-901-64-deb10-          Linux_Fedora:-            '( >= 27 && < 28 )': *ghc-901-64-fedora-            unknown_versioning: *ghc-901-64-fedora-          Linux_CentOS:-            '( >= 7 && < 8 )': &ghc-901-64-centos-              dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-x86_64-centos7-linux.tar.xz-              dlSubdir: ghc-9.0.1-              dlHash: a23750950b6995a66ba59afe82bbc505bd3479d6ab59cf66f45bc6c056e4d87b-            unknown_versioning: *ghc-901-64-centos-          Linux_RedHat:-            unknown_versioning: *ghc-901-64-centos-          Linux_Alpine:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-x86_64-alpine3.10-linux-integer-simple.tar.xz-              dlSubdir: ghc-9.0.1-x86_64-unknown-linux-              dlHash: 7c1a0154c9e361b75be6cb0305533bb8a3b963c54e8092ffd1759e5710805a5c-          Linux_AmazonLinux:-            unknown_versioning: *ghc-901-64-centos-          Linux_UnknownLinux:-            unknown_versioning: *ghc-901-64-fedora-          Darwin:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-x86_64-apple-darwin.tar.xz-              dlSubdir: ghc-9.0.1-              dlHash: 122d60509147d0117779d275f0215bde2ff63a64cda9d88f149432d0cae71b22-          FreeBSD:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-x86_64-portbld-freebsd.tar.xz-              dlSubdir: ghc-9.0.1-              dlHash: 9dbc06d8832cae5c9f86dd7b2db729b3748a47beb4fd4b1e62bb66119817c3c1-        A_32:-          Linux_Debian:-            '( >= 9 && < 10 )': &ghc-901-32-deb9-              dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-i386-deb9-linux.tar.xz-              dlSubdir: ghc-9.0.1-              dlHash: 880e37cea8328401bcfecfe4bb56eb85195f30135b140140b3f24094264f8ba5-            unknown_versioning: *ghc-901-32-deb9-          Linux_Ubuntu:-            unknown_versioning: *ghc-901-32-deb9-          Linux_Mint:-            unknown_versioning: *ghc-901-32-deb9-          Linux_UnknownLinux:-            unknown_versioning: *ghc-901-32-deb9-          Linux_Alpine:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/9.0.1/ghc-9.0.1-i386-alpine-linux.tar.xz-              dlSubdir: ghc-9.0.1-              dlHash: ebfeb3b91e6f2bb5a49fd3376746f7fd1b89e62e9838bf5b1530a8756ff1e6aa-        A_ARM64:-          Linux_UnknownLinux:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-aarch64-deb9-linux.tar.xz-              dlSubdir: ghc-9.0.1-              dlHash: fac7a0bdfc83c05df94024a2d67b8f00a9cd2733b9cb41fb8ad76be399014906-        A_ARM:-          Linux_UnknownLinux:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/9.0.1/ghc-9.0.1-armv7-deb9-linux.tar.xz-              dlSubdir: ghc-9.0.1-              dlHash: 6f404f9b88468407b3a9ec5800bcc2d01dd453ef3d63414853b4fbbd4d8df496-    9.2.0.20210331:-      viTags:-      - Prerelease-      - base-4.16.0.0-      viChangeLog: https://downloads.haskell.org/~ghc/9.2.1-alpha1/docs/html/users_guide/9.2.1-notes.html-      viSourceDL:-        dlUri: https://downloads.haskell.org/~ghc/9.2.1-alpha1/ghc-9.2.0.20210331-src.tar.xz-        dlSubdir: ghc-9.2.0.20210331-        dlHash: 3ec8ec2fb77e14d68ac1c092f3e8605b6822e24f7e6dc7139dccf8feaf168699-      viPostRemove: *ghc-post-remove-      viArch:-        A_64:-          Linux_Debian:-            '( >= 9 && < 10 )': &ghc-921-alpha1-64-deb9-              dlUri: https://downloads.haskell.org/~ghc/9.2.1-alpha1/ghc-9.2.0.20210331-x86_64-deb9-linux.tar.xz-              dlSubdir: ghc-9.2.0.20210331-              dlHash: c13613cb6285a689c5b89c93fad5c6c0e95d66c8936338c44d92a1312f507006-            '( >= 10 && < 11 )': &ghc-921-alpha1-64-deb10-              dlUri: https://downloads.haskell.org/~ghc/9.2.1-alpha1/ghc-9.2.0.20210331-x86_64-deb10-linux.tar.xz-              dlSubdir: ghc-9.2.0.20210331-              dlHash: 2b2a0e2bad54d1a41440c093a199207b58ff314bea7edf73387916e9952d6a53-            unknown_versioning: *ghc-921-alpha1-64-deb9-          Linux_Ubuntu:-            unknown_versioning: &ghc-921-alpha1-64-fedora-              dlUri: https://downloads.haskell.org/~ghc/9.2.1-alpha1/ghc-9.2.0.20210331-x86_64-fedora27-linux.tar.xz-              dlSubdir: ghc-9.2.0.20210331-              dlHash: c7e648ac313c268aaa3a9651b00650da6eb293abfe14e44f44da22a758c233e7-            '( >= 16 && < 19 )': *ghc-921-alpha1-64-deb9-          Linux_Mint:-            unknown_versioning: *ghc-921-alpha1-64-deb10-          Linux_Fedora:-            '( >= 27 && < 28 )': *ghc-921-alpha1-64-fedora-            unknown_versioning: *ghc-921-alpha1-64-fedora-          Linux_CentOS:-            '( >= 7 && < 8 )': &ghc-921-alpha1-64-centos-              dlUri: https://downloads.haskell.org/~ghc/9.2.1-alpha1/ghc-9.2.0.20210331-x86_64-centos7-linux.tar.xz-              dlSubdir: ghc-9.2.0.20210331-              dlHash: 50556cc42be665957f2bd8e5deeceb26e58e88badfa0c99a44117fda2d63200c-            unknown_versioning: *ghc-921-alpha1-64-centos-          Linux_RedHat:-            unknown_versioning: *ghc-921-alpha1-64-centos-          Linux_Alpine:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/9.2.1-alpha1/ghc-9.2.0.20210331-x86_64-alpine3.10-linux-integer-simple.tar.xz-              dlSubdir: ghc-9.2.0.20210331-x86_64-unknown-linux-              dlHash: bab5f5d0ecd6522da372a9a0f0eeebbbecf0bd94788847aa3cd5bdb36682d48a-          Linux_AmazonLinux:-            unknown_versioning: *ghc-921-alpha1-64-centos-          Linux_UnknownLinux:-            unknown_versioning: *ghc-921-alpha1-64-fedora-          Darwin:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/9.2.1-alpha1/ghc-9.2.0.20210331-x86_64-apple-darwin.tar.xz-              dlSubdir: ghc-9.2.0.20210331-              dlHash: cfd7d0479ce80607c11cf96fe25d4804783c6ebc623ca9adcb5436e3499c9c5b-        A_32:-          Linux_Debian:-            '( >= 9 && < 10 )': &ghc-921-alpha1-32-deb9-              dlUri: https://downloads.haskell.org/~ghc/9.2.1-alpha1/ghc-9.2.0.20210331-i386-deb9-linux.tar.xz-              dlSubdir: ghc-9.2.0.20210331-              dlHash: 58ccac8e89e60b4261dfa8ca0e17d335b99f2a1fecb90322436cfea3bdce2240-            unknown_versioning: *ghc-921-alpha1-32-deb9-          Linux_Ubuntu:-            unknown_versioning: *ghc-921-alpha1-32-deb9-          Linux_Mint:-            unknown_versioning: *ghc-921-alpha1-32-deb9-          Linux_UnknownLinux:-            unknown_versioning: *ghc-921-alpha1-32-deb9-        A_ARM64:-          Linux_UnknownLinux:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/9.2.1-alpha1/ghc-9.2.0.20210331-aarch64-deb10-linux.tar.xz-              dlSubdir: ghc-9.2.0.20210331-              dlHash: df355e1ed34cf0fef11444299020041f03d6c67f6c5c342db1f76b71fd31e6fe-        A_ARM:-          Linux_UnknownLinux:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghc/9.2.1-alpha1/ghc-9.2.0.20210331-armv7-deb10-linux.tar.xz-              dlSubdir: ghc-9.2.0.20210331-              dlHash: 2c5133fb83943371ad8556328db4acb9081271b7c77ceaf2b74817dd0de3b486-  Cabal:-    2.4.1.0:-      viTags:-        - old-      viChangeLog: https://downloads.haskell.org/~cabal/cabal-install-2.4.1.0/changelog-      viArch:-        A_64:-          Linux_Alpine:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~cabal/cabal-install-2.4.1.0/cabal-install-2.4.1.0-x86_64-alpine-linux-musl.tar.xz-              dlSubdir:-              dlHash: 720bef015f834a03deb7180be2952a44e7c2e6c8429137570404c3de4f46b984-          Linux_UnknownLinux:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~cabal/cabal-install-2.4.1.0/cabal-install-2.4.1.0-x86_64-unknown-linux.tar.xz-              dlSubdir:-              dlHash: 6136c189ffccaa39916f9cb5788f757166444a2d0c473b987856a79ecbf0c714-          Darwin:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~cabal/cabal-install-2.4.1.0/cabal-install-2.4.1.0-x86_64-apple-darwin-sierra.tar.xz-              dlSubdir:-              dlHash: 56361cf4b0d920fe23174751fea1fb82a8e1ce522bd9706a3fbe47a72e458c9c-          FreeBSD:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~cabal/cabal-install-2.4.1.0/cabal-install-2.4.1.0-x86_64-portbld-freebsd.tar.xz-              dlSubdir:-              dlHash: 33b7d37ea0688c93436eac9ec139d9967687875aa1fa13f2bb73bf05a9a59a1d-        A_32:-          Linux_UnknownLinux:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~cabal/cabal-install-2.4.1.0/cabal-install-2.4.1.0-i386-unknown-linux.tar.xz-              dlSubdir:-              dlHash: b2da736cc27609442b10f77fc1a687aba603a7a33045b722dbf1a0066fade198-    3.0.0.0:-      viTags:-        - old-      viChangeLog: https://downloads.haskell.org/~cabal/cabal-install-3.0.0.0/changelog-      viArch:-        A_64:-          Linux_Alpine:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.0.0.0/cabal-install-3.0.0.0-x86_64-alpine-linux-musl.tar.xz-              dlHash: 2b7ea63601e11a0db2941b96e6a7036a48efc2a1ab3849d7dfce08b45f5daa58-          Linux_UnknownLinux:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.0.0.0/cabal-install-3.0.0.0-x86_64-unknown-linux.tar.xz-              dlHash: ee911ba67a70756eedeac662955b896d7e89432a99372aa45d2c6e71fa95a5e4-          Darwin:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.0.0.0/cabal-install-3.0.0.0-x86_64-apple-darwin17.7.0.tar.xz-              dlHash: d4857e068560515e4cbb0e8ca124c370e07892f2a28804d87152834e5fe2b845-          FreeBSD:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.0.0.0/cabal-install-3.0.0.0-x86_64-portbld-freebsd.tar.xz-              dlHash: 2240842ab2ae7b955feb8b526aba1c7991248c803383107adf39990441294d2a-        A_32:-          Linux_Alpine:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.0.0.0/cabal-install-3.0.0.0-i386-alpine-linux-musl.tar.xz-              dlHash: ac018f061993d40bf146517e32629bcab274b4d9f5527b1c37a665ebdf3f5ac6-          Linux_UnknownLinux:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.0.0.0/cabal-install-3.0.0.0-i386-unknown-linux.tar.xz-              dlHash: 6898ccd6e6dc0872999c06daaf61d546164e12f60a1880d09852c9f0c59c5cf6-    3.2.0.0:-      viTags:-      - old-      viChangeLog: https://downloads.haskell.org/~cabal/cabal-install-3.2.0.0/changelog-      viArch:-        A_64:-          Linux_Alpine:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.2.0.0/cabal-install-3.2.0.0-x86_64-alpine-linux-musl.tar.xz-              dlHash: 8bae37a1ce8b5f10440b5591fed734935e1411c1b765258325ffe268e2cc2042-          Linux_UnknownLinux:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.2.0.0/cabal-install-3.2.0.0-x86_64-unknown-linux.tar.xz-              dlHash: 32d1f7cf1065c37cb0ef99a66adb405f409b9763f14c0926f5424ae408c738ac-          Darwin:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.2.0.0/cabal-install-3.2.0.0-x86_64-apple-darwin17.7.0.tar.xz-              dlHash: 9197c17d2ece0f934f5b33e323cfcaf486e4681952687bc3d249488ce3cbe0e9-          FreeBSD:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.2.0.0/cabal-install-3.2.0.0-x86_64-portbld-freebsd.tar.xz-              dlHash: f1e35151cca91541b0fb4bdb3ed18f3c348038eab751845ad19c11307d66c273-        A_32:-          Linux_Alpine:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.2.0.0/cabal-install-3.2.0.0-i386-alpine-linux-musl.tar.xz-              dlHash: c2a419dedf730987b60daf8d24e871d115a09ea608d740d7c61b36e3f5b9c830-          Linux_UnknownLinux:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.2.0.0/cabal-install-3.2.0.0-i386-unknown-linux.tar.xz-              dlHash: 2b3ac28549916de5f3379241797eaf60e84b6c001f2abbe73d9fadbbaf768e93-    3.4.0.0:-      viTags:-      - Recommended-      - Latest-      viChangeLog: https://github.com/haskell/cabal/blob/master/release-notes/cabal-install-3.4.0.0.md-      viArch:-        A_64:-          Linux_Ubuntu:-            unknown_versioning: &cabal-3400-ubuntu-              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.4.0.0/cabal-install-3.4.0.0-x86_64-ubuntu-16.04.tar.xz-              dlHash: cf28f9ffd763476aa2b1730d85cbf155d366fac541f78ee3951e8cb2d6de63e6-          Linux_Alpine:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.4.0.0/cabal-install-3.4.0.0-x86_64-alpine-3.11.6-static-noofd.tar.xz-              dlHash: c74073fe79110946182e522fcadc8dcabf07c87583e8cf7801ed4e0c327241f6-          Linux_UnknownLinux:-            unknown_versioning: *cabal-3400-ubuntu-          Darwin:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.4.0.0/cabal-install-3.4.0.0-x86_64-darwin-sierra.tar.xz-              dlHash: cb10be9a53e856aa2d852fd88fb6944f138783ffe0ea84d93c9a69244e34ea91-          FreeBSD:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.4.0.0/cabal-install-3.4.0.0-x86_64-freebsd-12.1-release.tar.xz-              dlHash: a1e2db664ec00e42a1e071a4181f6476f6e0bad321f1ddc0cf27831119f4c6d4-        A_32:-          Linux_UnknownLinux:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.4.0.0/cabal-install-3.4.0.0-i386-debian-9.tar.xz-              dlHash: ef3750644a53f7b1fad141b2ad02d4c7a3b239ec0cbfa7f0528fb02c1dfcebce-          Linux_Alpine:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/cabal/3.4.0.0/cabal-install-3.4.0.0-i386-alpine-linux-musl.tar.gz-              dlHash: 95adb65f3a72aa8d9ce83685bc06e1eee5b801f56e204e27e957e8a35abd9cf8-        A_ARM64:-          Linux_UnknownLinux:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.4.0.0/cabal-install-3.4.0.0-aarch64-ubuntu-18.04.tar.xz-              dlHash: 04d378347896dfdc3510b192b97489815cfa5d692f46e2758da0f789e682b8f0-        A_ARM:-          Linux_UnknownLinux:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghcup/unofficial-bindists/cabal/3.4.0.0/cabal-install-3.4.0.0-armv7-linux-bootstrapped.tar.xz-              dlHash: 16c0d1eaba24bed14f3e152970179a45d9f9bb5cc839b2c210ad06eb7d4826ed-  GHCup:-    0.1.14:-      viTags:-      - Recommended-      - Latest-      viChangeLog: https://gitlab.haskell.org/haskell/ghcup-hs/-/blob/master/CHANGELOG.md-      viSourceDL:-      viArch:-        A_64:-          Linux_UnknownLinux:-            unknown_versioning: &ghcup-64-              dlUri: https://downloads.haskell.org/~ghcup/0.1.14/x86_64-linux-ghcup-0.1.14-              dlHash: e9b314d248f4d4604ce64cee1be7161c77c8940efd11986c9205779ec3b598dd-          Darwin:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghcup/0.1.14/x86_64-apple-darwin-ghcup-0.1.14-              dlHash: 69ede9db36c0ae631b679fceb87dd856d4753ee26f33610da37dd7a694809919-          FreeBSD:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghcup/0.1.14/x86_64-portbld-freebsd-ghcup-0.1.14-              dlHash: 68b09404cf49061da539463f42f8ad67c9cef5c5d3f68a3c7c4f6760e8442bb9-          Linux_Alpine:-            unknown_versioning: *ghcup-64-        A_32:-          Linux_UnknownLinux:-            unknown_versioning: &ghcup-32-              dlUri: https://downloads.haskell.org/~ghcup/0.1.14/i386-linux-ghcup-0.1.14-              dlHash: ecb1157f010d2421764c52ab0cdbbf9a5c3da555827172c7b904d5f3f96c80fa-          Linux_Alpine:-            unknown_versioning: *ghcup-32-        A_ARM64:-          Linux_UnknownLinux:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghcup/0.1.14/aarch64-linux-ghcup-0.1.14-              dlHash: 78a15f8a03917a89b67536af0993d7526d2722248a3a5cd8c500adffd7cd7691-        A_ARM:-          Linux_UnknownLinux:-            unknown_versioning:-              dlUri: https://downloads.haskell.org/~ghcup/0.1.14/armv7-linux-ghcup-0.1.14-              dlHash: 5484dc9e16553c3d1707a9f83404c3c795dc01d01ef998cf173caf960abe793b-  HLS:-    1.0.0:-      viTags:-        - Recommended-        - Latest-      viChangeLog: https://github.com/haskell/haskell-language-server/blob/master/ChangeLog.md#100-      viPostInstall: "This is just the server part of your LSP configuration. Consult the README on how to configure HLS, your project and your LSP client in your editor: https://github.com/haskell/haskell-language-server/blob/master/README.md"-      viArch:-        A_64:-          Linux_UnknownLinux:-            unknown_versioning: &hls-64-              dlUri: https://github.com/haskell/haskell-language-server/releases/download/1.0.0/haskell-language-server-Linux-1.0.0.tar.gz-              dlHash: 4fab18998c5f67118a26b75b059f3b3e2ad345b6325515a552d1a24cdf87ed3f-          Darwin:-            unknown_versioning:-              dlUri: https://github.com/haskell/haskell-language-server/releases/download/1.0.0/haskell-language-server-macOS-1.0.0.tar.gz-              dlHash: 74e7624c889c0235f0b02d7e7f164d5eb95b611d584fc8602f0b3a099b73f8be-          Linux_Alpine:-            unknown_versioning: *hls-64
ghcup.cabal view
@@ -1,48 +1,52 @@-cabal-version:   3.0-name:            ghcup-version:         0.1.14.2-license:         LGPL-3.0-only-license-file:    LICENSE-copyright:       Julian Ospald 2020-maintainer:      hasufell@posteo.de-author:          Julian Ospald-homepage:        https://gitlab.haskell.org/haskell/ghcup-hs-bug-reports:     https://gitlab.haskell.org/haskell/ghcup-hs/issues-synopsis:        ghc toolchain installer+cabal-version:      3.0+name:               ghcup+version:            0.1.17.2+license:            LGPL-3.0-only+license-file:       LICENSE+copyright:          Julian Ospald 2020+maintainer:         hasufell@posteo.de+author:             Julian Ospald+homepage:           https://gitlab.haskell.org/haskell/ghcup-hs+bug-reports:        https://gitlab.haskell.org/haskell/ghcup-hs/issues+synopsis:           ghc toolchain installer description:   A rewrite of the shell script ghcup, for providing   a more stable user experience and exposing an API. -category:        System-build-type:      Simple-extra-doc-files: CHANGELOG.md-                 README.md-                 HACKING.md-                 RELEASING.md-                 config.yaml-                 ghcup-0.0.4.yaml+category:           System+build-type:         Simple+extra-doc-files:+  data/config.yaml+  data/metadata/ghcup-0.0.4.yaml+  data/metadata/ghcup-0.0.5.yaml+  data/metadata/ghcup-0.0.6.yaml+  docs/CHANGELOG.md+  docs/HACKING.md+  docs/RELEASING.md+  README.md +extra-source-files:+  data/build_mk/cross+  data/build_mk/default+ source-repository head   type:     git   location: https://gitlab.haskell.org/haskell/ghcup-hs.git  flag tui-  description: Build the brick powered tui (ghcup tui)+  description:+    Build the brick powered tui (ghcup tui). This is disabled on windows.+   default:     False   manual:      True  flag internal-downloader   description:-    Compile the internal downloader, which links against OpenSSL+    Compile the internal downloader, which links against OpenSSL. This is disabled on windows.    default:     False   manual:      True -flag tar-  description: Use tar-bytestring instead of libarchive-  default:     False-  manual:      True- library   exposed-modules:     GHCup@@ -57,6 +61,7 @@     GHCup.Utils     GHCup.Utils.Dirs     GHCup.Utils.File+    GHCup.Utils.File.Common     GHCup.Utils.Logger     GHCup.Utils.MegaParsec     GHCup.Utils.Prelude@@ -69,14 +74,19 @@   autogen-modules:    Paths_ghcup   default-language:   Haskell2010   default-extensions:+    DeriveGeneric     LambdaCase     MultiWayIf+    NamedFieldPuns     PackageImports+    QuasiQuotes     RecordWildCards     ScopedTypeVariables-    Strict     StrictData     TupleSections+    TypeApplications+    TypeFamilies+    ViewPatterns    ghc-options:     -Wall -fwarn-tabs -fwarn-incomplete-uni-patterns@@ -89,28 +99,24 @@     , base16-bytestring     >=0.1.1.6    && <1.1     , binary                ^>=0.8.6.0     , bytestring            ^>=0.10-    , bz2                   >=0.5.0.5    && <1.1+    , Cabal     , case-insensitive      ^>=1.2.1.0     , casing                ^>=0.1.4.1-    , concurrent-output     ^>=1.10.11     , containers            ^>=0.6     , cryptohash-sha256     ^>=0.11.101.0-    , generics-sop          ^>=0.5+    , deepseq               ^>=1.4.4.0+    , directory             ^>=1.3.6.0+    , disk-free-space       ^>=0.1.0.1+    , filepath              ^>=1.4.2.1     , haskus-utils-types    ^>=1.5     , haskus-utils-variant  >=3.0        && <3.2-    , hpath                 >=0.11       && <0.13-    , hpath-directory       ^>=0.14.1-    , hpath-filepath        ^>=0.10.3-    , hpath-io              ^>=0.14.1-    , hpath-posix           ^>=0.13.2-    , lzma-static           ^>=5.2.5.2+    , HsYAML-aeson          ^>=0.2.0.0+    , libarchive            ^>=3.0.3.0+    , lzma-static           ^>=5.2.5.3     , megaparsec            >=8.0.0      && <9.1-    , monad-logger          ^>=0.3.31     , mtl                   ^>=2.2-    , optics                >=0.2        && <0.5-    , optics-vl             ^>=0.2+    , optics                ^>=0.4     , os-release            ^>=1.0.0-    , parsec                ^>=3.1     , pretty                ^>=1.1.3.1     , pretty-terminal       ^>=0.1.0.0     , regex-posix           ^>=0.96@@ -118,43 +124,53 @@     , safe                  ^>=0.3.18     , safe-exceptions       ^>=0.1     , split                 ^>=0.2.3.4-    , streamly              ^>=0.7.3-    , streamly-bytestring   ^>=0.1.2-    , streamly-posix        ^>=0.1.0.0     , strict-base           ^>=0.4-    , string-interpolate    >=0.2.0.0    && <0.4-    , template-haskell      >=2.7        && <2.17+    , template-haskell      >=2.7        && <2.18+    , temporary             ^>=1.3     , text                  ^>=1.2.4.0     , time                  ^>=1.9.3     , transformers          ^>=0.5-    , unix                  ^>=2.7-    , unix-bytestring       ^>=0.3+    , unliftio-core         ^>=0.2.0.1     , unordered-containers  ^>=0.2.10.0     , uri-bytestring        ^>=0.3.2.2-    , utf8-string           ^>=1.0     , vector                ^>=0.12-    , versions              ^>=4.0.1-    , vty                   >=5.28.2     && <5.34+    , versions              >=4.0.1      && <5.1     , word8                 ^>=0.1.3-    , yaml                  ^>=0.11.4.0     , zlib                  ^>=0.6.2.2 -  if flag(internal-downloader)+  if (flag(internal-downloader) && !os(windows))     exposed-modules: GHCup.Download.IOStreams     cpp-options:     -DINTERNAL_DOWNLOADER     build-depends:       , HsOpenSSL              >=0.11.4.18       , http-io-streams        >=0.1.2.0-      , io-streams             >=1.5+      , io-streams             >=1.5.2.1       , terminal-progress-bar  >=0.4.1 -  if flag(tar)-    cpp-options:   -DTAR-    build-depends: tar-bytestring ^>=0.6.3.1+  if os(windows)+    cpp-options:   -DIS_WINDOWS+    other-modules: GHCup.Utils.File.Windows+    build-depends:+      , bzlib+      , process  ^>=1.6.11.0+      , retry    ^>=0.8.1.2+      , Win32    ^>=2.10    else-    build-depends: libarchive ^>=3.0.0.0+    other-modules:+      GHCup.Utils.File.Posix+      System.Console.Terminal.Common+      System.Console.Terminal.Posix +    build-depends:+      , bz2              >=0.5.0.5 && <1.1+      , unix             ^>=2.7+      , unix-bytestring  ^>=0.3.7.3++  if (flag(tui) && !os(windows))+    cpp-options:   -DBRICK+    build-depends: vty >=5.28.2 && <5.34+ executable ghcup   main-is:            Main.hs   hs-source-dirs:     app/ghcup@@ -162,10 +178,10 @@   default-extensions:     LambdaCase     MultiWayIf+    NamedFieldPuns     PackageImports     RecordWildCards     ScopedTypeVariables-    Strict     StrictData     TupleSections @@ -175,15 +191,19 @@    build-depends:     , aeson                 >=1.4      && <1.6+    , aeson-pretty          ^>=0.8.8+    , async                 ^>=2.2.3     , base                  >=4.13     && <5     , bytestring            ^>=0.10+    , cabal-plan            ^>=0.7.2     , containers            ^>=0.6+    , deepseq               ^>=1.4+    , filepath              ^>=1.4.2.1     , ghcup     , haskus-utils-variant  >=3.0      && <3.2-    , hpath                 >=0.11     && <0.13-    , hpath-io              ^>=0.14.1+    , HsYAML-aeson          ^>=0.2.0.0+    , libarchive            ^>=3.0.3.0     , megaparsec            >=8.0.0    && <9.1-    , monad-logger          ^>=0.3.31     , mtl                   ^>=2.2     , optparse-applicative  >=0.15.1.0 && <0.17     , pretty                ^>=1.1.3.1@@ -191,29 +211,26 @@     , resourcet             ^>=1.2.2     , safe                  ^>=0.3.18     , safe-exceptions       ^>=0.1-    , string-interpolate    >=0.2.0.0  && <0.4-    , template-haskell      >=2.7      && <2.17+    , template-haskell      >=2.7      && <2.18     , text                  ^>=1.2.4.0     , uri-bytestring        ^>=0.3.2.2     , utf8-string           ^>=1.0-    , versions              ^>=4.0.1+    , versions              >=4.0.1    && <5.1    if flag(internal-downloader)     cpp-options: -DINTERNAL_DOWNLOADER -  if flag(tui)+  if (flag(tui) && !os(windows))     cpp-options:   -DBRICK     other-modules: BrickMain     build-depends:-      , brick   >=0.5    && <0.62-      , vector  ^>=0.12-      , vty     >=5.28.2 && <5.34--  if flag(tar)-    cpp-options: -DTAR+      , brick         ^>=0.64+      , transformers  ^>=0.5+      , vector        ^>=0.12+      , vty           >=5.28.2 && <5.34 -  else-    build-depends: libarchive ^>=3.0.0.0+  if os(windows)+    cpp-options: -DIS_WINDOWS  executable ghcup-gen   main-is:            Main.hs@@ -221,54 +238,49 @@   other-modules:      Validate   default-language:   Haskell2010   default-extensions:+    DeriveGeneric     LambdaCase     MultiWayIf+    NamedFieldPuns     PackageImports+    QuasiQuotes     RecordWildCards     ScopedTypeVariables+    StrictData     TupleSections+    TypeApplications+    TypeFamilies+    ViewPatterns    ghc-options:     -Wall -fwarn-tabs -fwarn-incomplete-uni-patterns     -fwarn-incomplete-record-updates -threaded    build-depends:-    , aeson                 >=1.4      && <1.6-    , aeson-pretty          ^>=0.8.8     , base                  >=4.13     && <5     , bytestring            ^>=0.10     , containers            ^>=0.6+    , filepath              ^>=1.4.2.1     , ghcup     , haskus-utils-variant  >=3.0      && <3.2-    , hpath                 >=0.11     && <0.13-    , hpath-filepath        ^>=0.10.3-    , monad-logger          ^>=0.3.31+    , HsYAML-aeson          ^>=0.2.0.0+    , libarchive            ^>=3.0.3.0     , mtl                   ^>=2.2-    , optics                >=0.2      && <0.5+    , optics                ^>=0.4     , optparse-applicative  >=0.15.1.0 && <0.17     , pretty                ^>=1.1.3.1     , pretty-terminal       ^>=0.1.0.0     , regex-posix           ^>=0.96     , resourcet             ^>=1.2.2     , safe-exceptions       ^>=0.1-    , string-interpolate    >=0.2.0.0  && <0.4     , text                  ^>=1.2.4.0     , transformers          ^>=0.5-    , uri-bytestring        ^>=0.3.2.2-    , utf8-string           ^>=1.0-    , versions              ^>=4.0.1-    , yaml                  ^>=0.11.4.0--  if flag(tar)-    cpp-options:   -DTAR-    build-depends: tar-bytestring ^>=0.6.3.1--  else-    build-depends: libarchive ^>=3.0.0.0+    , versions              >=4.0.1    && <5.1  test-suite ghcup-test   type:               exitcode-stdio-1.0   main-is:            Main.hs+  build-tool-depends: hspec-discover:hspec-discover -any   hs-source-dirs:     test   other-modules:     GHCup.ArbitraryTypes@@ -294,11 +306,10 @@     , containers                ^>=0.6     , generic-arbitrary         ^>=0.1.0     , ghcup-    , hpath                     >=0.11    && <0.13-    , hspec                     ^>=2.7.4-    , hspec-golden-aeson        >=0.7     && <0.10+    , hspec                     ^>=2.7.10+    , hspec-golden-aeson        ^>=0.9     , QuickCheck                ^>=2.14.1     , quickcheck-arbitrary-adt  ^>=0.3.1.0     , text                      ^>=1.2.4.0     , uri-bytestring            ^>=0.3.2.2-    , versions                  ^>=4.0.1+    , versions                  >=4.0.1   && <5.1
lib/GHCup.hs view
@@ -1,1372 +1,2842 @@ {-# LANGUAGE CPP                   #-}-{-# LANGUAGE DataKinds             #-}-{-# LANGUAGE DeriveGeneric         #-}-{-# LANGUAGE FlexibleContexts      #-}-{-# LANGUAGE FlexibleInstances     #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE OverloadedStrings     #-}-{-# LANGUAGE QuasiQuotes           #-}-{-# LANGUAGE TemplateHaskell       #-}-{-# LANGUAGE TypeApplications      #-}-{-# LANGUAGE TypeFamilies          #-}-{-# LANGUAGE ViewPatterns          #-}--{-|-Module      : GHCup-Description : GHCup installation functions-Copyright   : (c) Julian Ospald, 2020-License     : LGPL-3.0-Maintainer  : hasufell@hasufell.de-Stability   : experimental-Portability : POSIX--This module contains the main functions that correspond-to the command line interface, like installation, listing versions-and so on.--These are the entry points.--}-module GHCup where---import           GHCup.Download-import           GHCup.Errors-import           GHCup.Platform-import           GHCup.Types-import           GHCup.Types.JSON               ( )-import           GHCup.Types.Optics-import           GHCup.Utils-import           GHCup.Utils.File-import           GHCup.Utils.Prelude-import           GHCup.Utils.String.QQ-import           GHCup.Utils.Version.QQ-import           GHCup.Version--#if !defined(TAR)-import           Codec.Archive                  ( ArchiveResult )-#endif-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.Logger-import           Control.Monad.Reader-import           Control.Monad.Trans.Resource-                                         hiding ( throwM )-import           Data.ByteString                ( ByteString )-import           Data.Either-import           Data.List-import           Data.Maybe-import           Data.String.Interpolate-import           Data.Text                      ( Text )-import           Data.Versions-import           Data.Word8-import           GHC.IO.Exception-import           HPath-import           HPath.IO                hiding ( hideError )-import           Haskus.Utils.Variant.Excepts-import           Optics-import           Prelude                 hiding ( abs-                                                , readFile-                                                , writeFile-                                                )-import           Safe                    hiding ( at )-import           System.IO.Error-import           System.Posix.Env.ByteString    ( getEnvironment, getEnv )-import           System.Posix.FilePath          ( getSearchPath, takeExtension )-import           System.Posix.Files.ByteString-import           Text.Regex.Posix--import qualified Crypto.Hash.SHA256            as SHA256-import qualified Data.ByteString.Base16        as B16-import qualified Data.ByteString               as B-import qualified Data.ByteString.Lazy          as BL-import qualified Data.Map.Strict               as Map-import qualified Data.Text                     as T-import qualified Data.Text.Encoding            as E----    --------------------------    --[ Tool installation ]---    ------------------------------ | Like 'installGHCBin', except takes the 'DownloadInfo' as--- argument instead of looking it up from 'GHCupDownloads'.-installGHCBindist :: ( MonadFail m-                     , MonadMask m-                     , MonadCatch m-                     , MonadReader AppState m-                     , MonadLogger m-                     , MonadResource m-                     , MonadIO m-                     )-                  => DownloadInfo    -- ^ where/how to download-                  -> Version         -- ^ the version to install-                  -> PlatformRequest -- ^ the platform to install on-                  -> Excepts-                       '[ AlreadyInstalled-                        , BuildFailed-                        , DigestError-                        , DownloadFailed-                        , NoDownload-                        , NotInstalled-                        , UnknownArchive-                        , TarDirDoesNotExist-#if !defined(TAR)-                        , ArchiveResult-#endif-                        ]-                       m-                       ()-installGHCBindist dlinfo ver pfreq = do-  let tver = mkTVer ver-  lift $ $(logDebug) [i|Requested to install GHC with #{ver}|]-  whenM (lift $ ghcInstalled tver) (throwE $ AlreadyInstalled GHC ver)--  -- download (or use cached version)-  dl                           <- liftE $ downloadCached dlinfo Nothing--  -- prepare paths-  ghcdir <- lift $ ghcupGHCDir tver--  toolchainSanityChecks-  -  liftE $ installPackedGHC dl (view dlSubdir dlinfo) ghcdir ver pfreq--  liftE $ postGHCInstall tver-- where-  toolchainSanityChecks = do-    r <- forM ["CC", "LD"] (liftIO . getEnv)-    case catMaybes r of-      [] -> pure ()-      _ -> do-        lift $ $(logWarn) "CC/LD environment variable is set. This will change the compiler/linker"-        lift $ $(logWarn) "GHC uses internally and can cause defunct GHC in some cases (e.g. in Anaconda"-        lift $ $(logWarn) "environments). If you encounter problems, unset CC and LD and reinstall."----- | Install a packed GHC distribution. This only deals with unpacking and the GHC--- build system and nothing else.-installPackedGHC :: ( MonadMask m-                    , MonadCatch m-                    , MonadReader AppState m-                    , MonadThrow m-                    , MonadLogger m-                    , MonadIO m-                    )-                 => Path Abs          -- ^ Path to the packed GHC bindist-                 -> Maybe TarDir      -- ^ Subdir of the archive-                 -> Path Abs          -- ^ Path to install to-                 -> Version           -- ^ The GHC version-                 -> PlatformRequest-                 -> Excepts-                      '[ BuildFailed-                       , UnknownArchive-                       , TarDirDoesNotExist-#if !defined(TAR)-                       , ArchiveResult-#endif-                       ] m ()-installPackedGHC dl msubdir inst ver pfreq@PlatformRequest{..} = do-  -- unpack-  tmpUnpack <- lift mkGhcupTmpDir-  liftE $ unpackToDir tmpUnpack dl-  void $ liftIO $ darwinNotarization _rPlatform tmpUnpack--  -- the subdir of the archive where we do the work-  workdir <- maybe (pure tmpUnpack)-                   (liftE . intoSubdir tmpUnpack)-                   msubdir--  liftE $ runBuildAction tmpUnpack-                         (Just inst)-                         (installUnpackedGHC workdir inst ver pfreq)----- | Install an unpacked GHC distribution. This only deals with the GHC--- build system and nothing else.-installUnpackedGHC :: ( MonadReader AppState m-                      , MonadThrow m-                      , MonadLogger m-                      , MonadIO m-                      )-                   => Path Abs      -- ^ Path to the unpacked GHC bindist (where the configure script resides)-                   -> Path Abs      -- ^ Path to install to-                   -> Version       -- ^ The GHC version-                   -> PlatformRequest-                   -> Excepts '[ProcessError] m ()-installUnpackedGHC path inst ver PlatformRequest{..} = do-  lift $ $(logInfo) "Installing GHC (this may take a while)"-  lEM $ execLogged "./configure"-                   False-                   (("--prefix=" <> toFilePath inst) : alpineArgs)-                   [rel|ghc-configure|]-                   (Just path)-                   Nothing-  lEM $ make ["install"] (Just path)-  pure ()- where-  alpineArgs-    | ver >= [vver|8.2.2|], Linux Alpine <- _rPlatform-    = ["--disable-ld-override"]-    | otherwise-    = []----- | Installs GHC into @~\/.ghcup\/ghc/\<ver\>@ and places the--- following symlinks in @~\/.ghcup\/bin@:------   * @ghc-x.y.z -> ..\/ghc\/x.y.z\/bin/ghc@---   * @ghc-x.y   -> ..\/ghc\/x.y.z\/bin/ghc@ (if x.y.z is the latest x.y version)-installGHCBin :: ( MonadFail m-                 , MonadMask m-                 , MonadCatch m-                 , MonadReader AppState m-                 , MonadLogger m-                 , MonadResource m-                 , MonadIO m-                 )-              => GHCupDownloads  -- ^ the download info to look up the tarball from-              -> Version         -- ^ the version to install-              -> PlatformRequest -- ^ the platform to install on-              -> Excepts-                   '[ AlreadyInstalled-                    , BuildFailed-                    , DigestError-                    , DownloadFailed-                    , NoDownload-                    , NotInstalled-                    , UnknownArchive-                    , TarDirDoesNotExist-#if !defined(TAR)-                    , ArchiveResult-#endif-                    ]-                   m-                   ()-installGHCBin bDls ver pfreq = do-  dlinfo <- lE $ getDownloadInfo GHC ver pfreq bDls-  installGHCBindist dlinfo ver pfreq----- | Like 'installCabalBin', except takes the 'DownloadInfo' as--- argument instead of looking it up from 'GHCupDownloads'.-installCabalBindist :: ( MonadMask m-                       , MonadCatch m-                       , MonadReader AppState m-                       , MonadLogger m-                       , MonadResource m-                       , MonadIO m-                       , MonadFail m-                       )-                    => DownloadInfo-                    -> Version-                    -> PlatformRequest-                    -> Excepts-                         '[ AlreadyInstalled-                          , CopyError-                          , DigestError-                          , DownloadFailed-                          , NoDownload-                          , NotInstalled-                          , UnknownArchive-                          , TarDirDoesNotExist-#if !defined(TAR)-                          , ArchiveResult-#endif-                          ]-                         m-                         ()-installCabalBindist dlinfo ver PlatformRequest {..} = do-  lift $ $(logDebug) [i|Requested to install cabal version #{ver}|]--  AppState {dirs = Dirs {..}} <- lift ask--  whenM-      (lift (cabalInstalled ver) >>= \a -> liftIO $-        handleIO (\_ -> pure False)-          $ fmap (\x -> a && isSymbolicLink x)-          -- ignore when the installation is a legacy cabal (binary, not symlink)-          $ getSymbolicLinkStatus (toFilePath (binDir </> [rel|cabal|]))-      )-      (throwE $ AlreadyInstalled Cabal ver)--  -- download (or use cached version)-  dl                           <- liftE $ downloadCached dlinfo Nothing--  -- unpack-  tmpUnpack                    <- lift withGHCupTmpDir-  liftE $ unpackToDir tmpUnpack dl-  void $ liftIO $ darwinNotarization _rPlatform tmpUnpack--  -- the subdir of the archive where we do the work-  workdir <- maybe (pure tmpUnpack) (liftE . intoSubdir tmpUnpack) (view dlSubdir dlinfo)--  liftE $ installCabal' workdir binDir--  -- create symlink if this is the latest version-  cVers <- lift $ fmap rights getInstalledCabals-  let lInstCabal = headMay . reverse . sort $ cVers-  when (maybe True (ver >=) lInstCabal) $ liftE $ setCabal ver-- where-  -- | Install an unpacked cabal distribution.-  installCabal' :: (MonadLogger m, MonadCatch m, MonadIO m)-                => Path Abs      -- ^ Path to the unpacked cabal bindist (where the executable resides)-                -> Path Abs      -- ^ Path to install to-                -> Excepts '[CopyError] m ()-  installCabal' path inst = do-    lift $ $(logInfo) "Installing cabal"-    let cabalFile = [rel|cabal|]-    liftIO $ createDirRecursive' inst-    destFileName <- lift $ parseRel (toFilePath cabalFile <> "-" <> verToBS ver)-    let destPath = inst </> destFileName-    handleIO (throwE . CopyError . show) $ liftIO $ copyFile-      (path </> cabalFile)-      destPath-      Overwrite-    lift $ chmod_755 destPath----- | Installs cabal into @~\/.ghcup\/bin/cabal-\<ver\>@ and--- creates a default @cabal -> cabal-x.y.z.q@ symlink for--- the latest installed version.-installCabalBin :: ( MonadMask m-                   , MonadCatch m-                   , MonadReader AppState m-                   , MonadLogger m-                   , MonadResource m-                   , MonadIO m-                   , MonadFail m-                   )-                => GHCupDownloads-                -> Version-                -> PlatformRequest-                -> Excepts-                     '[ AlreadyInstalled-                      , CopyError-                      , DigestError-                      , DownloadFailed-                      , NoDownload-                      , NotInstalled-                      , UnknownArchive-                      , TarDirDoesNotExist-#if !defined(TAR)-                      , ArchiveResult-#endif-                      ]-                     m-                     ()-installCabalBin bDls ver pfreq = do-  dlinfo <- lE $ getDownloadInfo Cabal ver pfreq bDls-  installCabalBindist dlinfo ver pfreq----- | Like 'installHLSBin, except takes the 'DownloadInfo' as--- argument instead of looking it up from 'GHCupDownloads'.-installHLSBindist :: ( MonadMask m-                     , MonadCatch m-                     , MonadReader AppState m-                     , MonadLogger m-                     , MonadResource m-                     , MonadIO m-                     , MonadFail m-                     )-                  => DownloadInfo-                  -> Version-                  -> PlatformRequest-                  -> Excepts-                       '[ AlreadyInstalled-                        , CopyError-                        , DigestError-                        , DownloadFailed-                        , NoDownload-                        , NotInstalled-                        , UnknownArchive-                        , TarDirDoesNotExist-#if !defined(TAR)-                        , ArchiveResult-#endif-                        ]-                       m-                       ()-installHLSBindist dlinfo ver PlatformRequest{..} = do-  lift $ $(logDebug) [i|Requested to install hls version #{ver}|]--  AppState {dirs = Dirs {..}} <- lift ask--  whenM (lift (hlsInstalled ver))-    (throwE $ AlreadyInstalled HLS ver)--  -- download (or use cached version)-  dl                           <- liftE $ downloadCached dlinfo Nothing--  -- unpack-  tmpUnpack                    <- lift withGHCupTmpDir-  liftE $ unpackToDir tmpUnpack dl-  void $ liftIO $ darwinNotarization _rPlatform tmpUnpack--  -- the subdir of the archive where we do the work-  workdir <- maybe (pure tmpUnpack) (liftE . intoSubdir tmpUnpack) (view dlSubdir dlinfo)--  liftE $ installHLS' workdir binDir--  -- create symlink if this is the latest version-  hlsVers <- lift $ fmap rights getInstalledHLSs-  let lInstHLS = headMay . reverse . sort $ hlsVers-  when (maybe True (ver >=) lInstHLS) $ liftE $ setHLS ver-- where-  -- | Install an unpacked hls distribution.-  installHLS' :: (MonadFail m, MonadLogger m, MonadCatch m, MonadIO m)-                => Path Abs      -- ^ Path to the unpacked hls bindist (where the executable resides)-                -> Path Abs      -- ^ Path to install to-                -> Excepts '[CopyError] m ()-  installHLS' path inst = do-    lift $ $(logInfo) "Installing HLS"-    liftIO $ createDirRecursive' inst--    -- install haskell-language-server-<ghcver>-    bins@(_:_) <- liftIO $ findFiles-      path-      (makeRegexOpts compExtended-                     execBlank-                     ([s|^haskell-language-server-[0-9].*$|] :: ByteString)-      )-    forM_ bins $ \f -> do-      toF <- parseRel (toFilePath f <> "~" <> verToBS ver)-      handleIO (throwE . CopyError . show) $ liftIO $ copyFile-        (path </> f)-        (inst </> toF)-        Overwrite-      lift $ chmod_755 (inst </> toF)--    -- install haskell-language-server-wrapper-    let wrapper = [rel|haskell-language-server-wrapper|]-    toF <- parseRel (toFilePath wrapper <> "-" <> verToBS ver)-    handleIO (throwE . CopyError . show) $ liftIO $ copyFile-      (path </> wrapper)-      (inst </> toF)-      Overwrite-    lift $ chmod_755 (inst </> toF)----- | Installs hls binaries @haskell-language-server-\<ghcver\>@--- into @~\/.ghcup\/bin/@, as well as @haskell-languager-server-wrapper@.-installHLSBin :: ( MonadMask m-                 , MonadCatch m-                 , MonadReader AppState m-                 , MonadLogger m-                 , MonadResource m-                 , MonadIO m-                 , MonadFail m-                 )-              => GHCupDownloads-              -> Version-              -> PlatformRequest-              -> Excepts-                   '[ AlreadyInstalled-                    , CopyError-                    , DigestError-                    , DownloadFailed-                    , NoDownload-                    , NotInstalled-                    , UnknownArchive-                    , TarDirDoesNotExist-#if !defined(TAR)-                    , ArchiveResult-#endif-                    ]-                   m-                   ()-installHLSBin bDls ver pfreq = do-  dlinfo <- lE $ getDownloadInfo HLS ver pfreq bDls-  installHLSBindist dlinfo ver pfreq-----    ----------------------    --[ Set GHC/cabal ]---    --------------------------- | Set GHC symlinks in @~\/.ghcup\/bin@ for the requested GHC version. The behavior depends--- on `SetGHC`:------   * SetGHCOnly: @~\/.ghcup\/bin\/ghc -> ~\/.ghcup\/ghc\/\<ver\>\/bin\/ghc@---   * SetGHC_XY: @~\/.ghcup\/bin\/ghc-X.Y -> ~\/.ghcup\/ghc\/\<ver\>\/bin\/ghc@---   * SetGHC_XYZ: @~\/.ghcup\/bin\/ghc-\<ver\> -> ~\/.ghcup\/ghc\/\<ver\>\/bin\/ghc@------ Additionally creates a @~\/.ghcup\/share -> ~\/.ghcup\/ghc\/\<ver\>\/share symlink@--- for 'SetGHCOnly' constructor.-setGHC :: ( MonadReader AppState m-          , MonadLogger m-          , MonadThrow m-          , MonadFail m-          , MonadIO m-          , MonadCatch m-          )-       => GHCTargetVersion-       -> SetGHC-       -> Excepts '[NotInstalled] m GHCTargetVersion-setGHC ver sghc = do-  let verBS = verToBS (_tvVersion ver)-  ghcdir                        <- lift $ ghcupGHCDir ver--  whenM (lift $ not <$> ghcInstalled ver) (throwE (NotInstalled GHC ver))--  -- symlink destination-  AppState { dirs = Dirs {..} } <- lift ask-  liftIO $ createDirRecursive' binDir--  -- first delete the old symlinks (this fixes compatibility issues-  -- with old ghcup)-  case sghc of-    SetGHCOnly -> liftE $ rmPlain (_tvTarget ver)-    SetGHC_XY  -> liftE $ rmMajorSymlinks ver-    SetGHC_XYZ -> liftE $ rmMinorSymlinks ver--  -- for ghc tools (ghc, ghci, haddock, ...)-  verfiles <- ghcToolFiles ver-  forM_ verfiles $ \file -> do-    mTargetFile <- case sghc of-      SetGHCOnly -> pure $ Just file-      SetGHC_XY  -> do-        v' <--          handle-            (\(e :: ParseError) -> lift $ $(logWarn) [i|#{e}|] >> pure Nothing)-          $ fmap Just-          $ getMajorMinorV (_tvVersion ver)-        forM v' $ \(mj, mi) ->-          let major' = E.encodeUtf8 $ intToText mj <> "." <> intToText mi-          in  parseRel (toFilePath file <> B.singleton _hyphen <> major')-      SetGHC_XYZ ->-        fmap Just $ parseRel (toFilePath file <> B.singleton _hyphen <> verBS)--    -- create symlink-    forM mTargetFile $ \targetFile -> do-      let fullF = binDir </> targetFile-      destL <- lift $ ghcLinkDestination (toFilePath file) ver-      lift $ $(logDebug) [i|ln -s #{destL} #{toFilePath fullF}|]-      liftIO $ createSymlink fullF destL--  -- create symlink for share dir-  when (isNothing . _tvTarget $ ver) $ lift $ symlinkShareDir ghcdir verBS--  pure ver-- where--  symlinkShareDir :: (MonadReader AppState m, MonadIO m, MonadLogger m)-                  => Path Abs-                  -> ByteString-                  -> m ()-  symlinkShareDir ghcdir verBS = do-    AppState { dirs = Dirs {..} } <- ask-    let destdir = baseDir-    case sghc of-      SetGHCOnly -> do-        let sharedir     = [rel|share|]-        let fullsharedir = ghcdir </> sharedir-        whenM (liftIO $ doesDirectoryExist fullsharedir) $ do-          let fullF   = destdir </> sharedir-          let targetF = "./ghc/" <> verBS <> "/" <> toFilePath sharedir-          $(logDebug) [i|rm -f #{fullF}|]-          liftIO $ hideError doesNotExistErrorType $ deleteFile fullF-          $(logDebug) [i|ln -s #{targetF} #{fullF}|]-          liftIO $ createSymlink fullF targetF-      _ -> pure ()------ | Set the @~\/.ghcup\/bin\/cabal@ symlink.-setCabal :: (MonadReader AppState m, MonadLogger m, MonadThrow m, MonadFail m, MonadIO m)-         => Version-         -> Excepts '[NotInstalled] m ()-setCabal ver = do-  let verBS = verToBS ver-  targetFile <- parseRel ("cabal-" <> verBS)--  -- symlink destination-  AppState {dirs = Dirs {..}} <- lift ask-  liftIO $ createDirRecursive' binDir--  whenM (liftIO $ not <$> doesFileExist (binDir </> targetFile))-    $ throwE-    $ NotInstalled Cabal (GHCTargetVersion Nothing ver)--  let cabalbin = binDir </> [rel|cabal|]--  -- delete old file (may be binary or symlink)-  lift $ $(logDebug) [i|rm -f #{toFilePath cabalbin}|]-  liftIO $ hideError doesNotExistErrorType $ deleteFile-    cabalbin--  -- create symlink-  let destL = toFilePath targetFile-  lift $ $(logDebug) [i|ln -s #{destL} #{toFilePath cabalbin}|]-  liftIO $ createSymlink cabalbin destL--  pure ()------- | Set the haskell-language-server symlinks.-setHLS :: ( MonadCatch m-          , MonadReader AppState m-          , MonadLogger m-          , MonadThrow m-          , MonadFail m-          , MonadIO m-          )-       => Version-       -> Excepts '[NotInstalled] m ()-setHLS ver = do-  AppState { dirs = Dirs {..} } <- lift ask-  liftIO $ createDirRecursive' binDir--  -- Delete old symlinks, since these might have different ghc versions than the-  -- selected version, so we could end up with stray or incorrect symlinks.-  oldSyms <- lift hlsSymlinks-  forM_ oldSyms $ \f -> do-    lift $ $(logDebug) [i|rm #{toFilePath (binDir </> f)}|]-    liftIO $ deleteFile (binDir </> f)--  -- set haskell-language-server-<ghcver> symlinks-  bins <- lift $ hlsServerBinaries ver-  when (null bins) $ throwE $ NotInstalled HLS (GHCTargetVersion Nothing ver)--  forM_ bins $ \f -> do-    let destL = toFilePath f-    target <- parseRel . head . B.split _tilde . toFilePath $ f--    lift $ $(logDebug) [i|rm -f #{toFilePath (binDir </> target)}|]-    liftIO $ hideError doesNotExistErrorType $ deleteFile (binDir </> target)--    lift $ $(logDebug) [i|ln -s #{destL} #{toFilePath (binDir </> target)}|]-    liftIO $ createSymlink (binDir </> target) destL--  -- set haskell-language-server-wrapper symlink-  let destL = "haskell-language-server-wrapper-" <> verToBS ver-  let wrapper = binDir </> [rel|haskell-language-server-wrapper|]--  lift $ $(logDebug) [i|rm -f #{toFilePath wrapper}|]-  liftIO $ hideError doesNotExistErrorType $ deleteFile wrapper--  lift $ $(logDebug) [i|ln -s #{destL} #{toFilePath wrapper}|]-  liftIO $ createSymlink wrapper destL--  pure ()------    -------------------    --[ List tools ]---    ----------------------- | Filter data type for 'listVersions'.-data ListCriteria = ListInstalled-                  | ListSet-                  deriving Show---- | A list result describes a single tool version--- and various of its properties.-data ListResult = ListResult-  { lTool      :: Tool-  , lVer       :: Version-  , lCross     :: Maybe Text -- ^ currently only for GHC-  , lTag       :: [Tag]-  , lInstalled :: Bool-  , lSet       :: Bool -- ^ currently active version-  , fromSrc    :: Bool -- ^ compiled from source-  , lStray     :: Bool -- ^ not in download info-  , lNoBindist :: Bool -- ^ whether the version is available for this platform/arch-  , hlsPowered :: Bool-  }-  deriving (Eq, Ord, Show)----- | Extract all available tool versions and their tags.-availableToolVersions :: GHCupDownloads -> Tool -> Map.Map Version [Tag]-availableToolVersions av tool = view-  (at tool % non Map.empty % to (fmap _viTags))-  av----- | List all versions from the download info, as well as stray--- versions.-listVersions :: ( MonadCatch m-                , MonadLogger m-                , MonadThrow m-                , MonadLogger m-                , MonadIO m-                , MonadReader AppState m-                )-             => GHCupDownloads-             -> Maybe Tool-             -> Maybe ListCriteria-             -> PlatformRequest-             -> m [ListResult]-listVersions av lt' criteria pfreq = do-  -- some annoying work to avoid too much repeated IO-  cSet <- cabalSet-  cabals <- getInstalledCabals' cSet-  hlsSet' <- hlsSet-  hlses <- getInstalledHLSs--  go lt' cSet cabals hlsSet' hlses- where-  go lt cSet cabals hlsSet' hlses = do-    case lt of-      Just t -> do-        -- get versions from GHCupDownloads-        let avTools = availableToolVersions av t-        lr <- filter' <$> forM (Map.toList avTools) (toListResult t cSet cabals hlsSet' hlses)--        case t of-          GHC -> do-            slr <- strayGHCs avTools-            pure (sort (slr ++ lr))-          Cabal -> do-            slr <- strayCabals avTools cSet cabals-            pure (sort (slr ++ lr))-          HLS -> do-            slr <- strayHLS avTools-            pure (sort (slr ++ lr))-          GHCup -> pure lr-      Nothing -> do-        ghcvers   <- go (Just GHC) cSet cabals hlsSet' hlses-        cabalvers <- go (Just Cabal) cSet cabals hlsSet' hlses-        hlsvers   <- go (Just HLS) cSet cabals hlsSet' hlses-        ghcupvers <- go (Just GHCup) cSet cabals hlsSet' hlses-        pure (ghcvers <> cabalvers <> hlsvers <> ghcupvers)-  strayGHCs :: (MonadCatch m, MonadReader AppState m, MonadThrow m, MonadLogger m, MonadIO m)-            => Map.Map Version [Tag]-            -> m [ListResult]-  strayGHCs avTools = do-    ghcs <- getInstalledGHCs-    fmap catMaybes $ forM ghcs $ \case-      Right tver@GHCTargetVersion{ _tvTarget = Nothing, .. } -> do-        case Map.lookup _tvVersion avTools of-          Just _  -> pure Nothing-          Nothing -> do-            lSet    <- fmap (maybe False (\(GHCTargetVersion _ v ) -> v == _tvVersion)) $ ghcSet Nothing-            fromSrc <- ghcSrcInstalled tver-            hlsPowered <- fmap (elem _tvVersion) hlsGHCVersions-            pure $ Just $ ListResult-              { lTool      = GHC-              , lVer       = _tvVersion-              , lCross     = Nothing-              , lTag       = []-              , lInstalled = True-              , lStray     = isNothing (Map.lookup _tvVersion avTools)-              , lNoBindist = False-              , ..-              }-      Right tver@GHCTargetVersion{ .. } -> do-        lSet    <- fmap (maybe False (\(GHCTargetVersion _ v ) -> v == _tvVersion)) $ ghcSet _tvTarget-        fromSrc <- ghcSrcInstalled tver-        hlsPowered <- fmap (elem _tvVersion) hlsGHCVersions-        pure $ Just $ ListResult-          { lTool      = GHC-          , lVer       = _tvVersion-          , lCross     = _tvTarget-          , lTag       = []-          , lInstalled = True-          , lStray     = True -- NOTE: cross currently cannot be installed via bindist-          , lNoBindist = False-          , ..-          }-      Left e -> do-        $(logWarn)-          [i|Could not parse version of stray directory #{toFilePath e}|]-        pure Nothing--  strayCabals :: (MonadReader AppState m, MonadCatch m, MonadThrow m, MonadLogger m, MonadIO m)-            => Map.Map Version [Tag]-            -> Maybe Version-            -> [Either (Path Rel) Version]-            -> m [ListResult]-  strayCabals avTools cSet cabals = do-    fmap catMaybes $ forM cabals $ \case-      Right ver ->-        case Map.lookup ver avTools of-          Just _  -> pure Nothing-          Nothing -> do-            let lSet = cSet == Just ver-            pure $ Just $ ListResult-              { lTool      = Cabal-              , lVer       = ver-              , lCross     = Nothing-              , lTag       = []-              , lInstalled = True-              , lStray     = isNothing (Map.lookup ver avTools)-              , lNoBindist = False-              , fromSrc    = False -- actually, we don't know :>-              , hlsPowered = False-              , ..-              }-      Left e -> do-        $(logWarn)-          [i|Could not parse version of stray directory #{toFilePath e}|]-        pure Nothing--  strayHLS :: (MonadReader AppState m, MonadCatch m, MonadThrow m, MonadLogger m, MonadIO m)-           => Map.Map Version [Tag]-           -> m [ListResult]-  strayHLS avTools = do-    hlss <- getInstalledHLSs-    fmap catMaybes $ forM hlss $ \case-      Right ver ->-        case Map.lookup ver avTools of-          Just _  -> pure Nothing-          Nothing -> do-            lSet    <- fmap (== Just ver) hlsSet-            pure $ Just $ ListResult-              { lTool      = HLS-              , lVer       = ver-              , lCross     = Nothing-              , lTag       = []-              , lInstalled = True-              , lStray     = isNothing (Map.lookup ver avTools)-              , lNoBindist = False-              , fromSrc    = False -- actually, we don't know :>-              , hlsPowered = False-              , ..-              }-      Left e -> do-        $(logWarn)-          [i|Could not parse version of stray directory #{toFilePath e}|]-        pure Nothing--  -- NOTE: this are not cross ones, because no bindists-  toListResult :: (MonadLogger m, MonadReader AppState m, MonadIO m, MonadCatch m)-               => Tool-               -> Maybe Version-               -> [Either (Path Rel) Version]-               -> Maybe Version-               -> [Either (Path Rel) Version]-               -> (Version, [Tag])-               -> m ListResult-  toListResult t cSet cabals hlsSet' hlses (v, tags) = case t of-    GHC -> do-      let lNoBindist = isLeft $ getDownloadInfo GHC v pfreq av-      let tver = mkTVer v-      lSet       <- fmap (maybe False (\(GHCTargetVersion _ v') -> v' == v)) $ ghcSet Nothing-      lInstalled <- ghcInstalled tver-      fromSrc    <- ghcSrcInstalled tver-      hlsPowered <- fmap (elem v) hlsGHCVersions-      pure ListResult { lVer = v, lCross = Nothing , lTag = tags, lTool = t, lStray = False, .. }-    Cabal -> do-      let lNoBindist = isLeft $ getDownloadInfo Cabal v pfreq av-      let lSet = cSet == Just v-      let lInstalled = elem v $ rights cabals-      pure ListResult { lVer    = v-                      , lCross  = Nothing-                      , lTag    = tags-                      , lTool   = t-                      , fromSrc = False-                      , lStray  = False-                      , hlsPowered = False-                      , ..-                      }-    GHCup -> do-      let lSet       = prettyPVP ghcUpVer == prettyVer v-      let lInstalled = lSet-      pure ListResult { lVer    = v-                      , lTag    = tags-                      , lCross  = Nothing-                      , lTool   = t-                      , fromSrc = False-                      , lStray  = False-                      , lNoBindist = False-                      , hlsPowered = False-                      , ..-                      }-    HLS -> do-      let lNoBindist = isLeft $ getDownloadInfo HLS v pfreq av-      let lSet = hlsSet' == Just v-      let lInstalled = elem v $ rights hlses-      pure ListResult { lVer    = v-                      , lCross  = Nothing-                      , lTag    = tags-                      , lTool   = t-                      , fromSrc = False-                      , lStray  = False-                      , hlsPowered = False-                      , ..-                      }---  filter' :: [ListResult] -> [ListResult]-  filter' lr = case criteria of-    Nothing            -> lr-    Just ListInstalled -> filter (\ListResult {..} -> lInstalled) lr-    Just ListSet       -> filter (\ListResult {..} -> lSet) lr----    ---------------------    --[ GHC/cabal rm ]---    ------------------------- | Delete a ghc version and all its symlinks.------ This may leave GHCup without a "set" version.--- Will try to fix the ghc-x.y symlink after removal (e.g. to an--- older version).-rmGHCVer :: ( MonadReader AppState m-            , MonadThrow m-            , MonadLogger m-            , MonadIO m-            , MonadFail m-            , MonadCatch m-            )-         => GHCTargetVersion-         -> Excepts '[NotInstalled] m ()-rmGHCVer ver = do-  isSetGHC <- lift $ fmap (== Just ver) $ ghcSet (_tvTarget ver)--  whenM (lift $ fmap not $ ghcInstalled ver) (throwE (NotInstalled GHC ver))-  dir <- lift $ ghcupGHCDir ver--  -- this isn't atomic, order matters-  when isSetGHC $ do-    lift $ $(logInfo) [i|Removing ghc symlinks|]-    liftE $ rmPlain (_tvTarget ver)--  lift $ $(logInfo) [i|Removing ghc-x.y.z symlinks|]-  liftE $ rmMinorSymlinks ver--  lift $ $(logInfo) [i|Removing/rewiring ghc-x.y symlinks|]-  -- first remove-  handle (\(_ :: ParseError) -> pure ()) $ liftE $ rmMajorSymlinks ver-  -- then fix them (e.g. with an earlier version)--  lift $ $(logInfo) [i|Removing directory recursively: #{toFilePath dir}|]-  liftIO $ deleteDirRecursive dir--  v' <--    handle-      (\(e :: ParseError) -> lift $ $(logWarn) [i|#{e}|] >> pure Nothing)-    $ fmap Just-    $ getMajorMinorV (_tvVersion ver)-  forM_ v' $ \(mj, mi) -> lift (getGHCForMajor mj mi (_tvTarget ver))-    >>= mapM_ (\v -> liftE $ setGHC v SetGHC_XY)--  AppState { dirs = Dirs {..} } <- lift ask--  liftIO-    $ hideError doesNotExistErrorType-    $ deleteFile (baseDir </> [rel|share|])----- | Delete a cabal version. Will try to fix the @cabal@ symlink--- after removal (e.g. setting it to an older version).-rmCabalVer :: (MonadReader AppState m, MonadThrow m, MonadLogger m, MonadIO m, MonadFail m, MonadCatch m)-           => Version-           -> Excepts '[NotInstalled] m ()-rmCabalVer ver = do-  whenM (lift $ fmap not $ cabalInstalled ver) $ throwE (NotInstalled Cabal (GHCTargetVersion Nothing ver))--  cSet      <- lift cabalSet--  AppState {dirs = Dirs {..}} <- lift ask--  cabalFile <- lift $ parseRel ("cabal-" <> verToBS ver)-  liftIO $ hideError doesNotExistErrorType $ deleteFile (binDir </> cabalFile)--  when (Just ver == cSet) $ do-    cVers <- lift $ fmap rights getInstalledCabals-    case headMay . reverse . sort $ cVers of-      Just latestver -> setCabal latestver-      Nothing        -> liftIO $ hideError doesNotExistErrorType $ deleteFile-        (binDir </> [rel|cabal|])----- | Delete a hls version. Will try to fix the hls symlinks--- after removal (e.g. setting it to an older version).-rmHLSVer :: (MonadReader AppState m, MonadThrow m, MonadLogger m, MonadIO m, MonadFail m, MonadCatch m)-         => Version-         -> Excepts '[NotInstalled] m ()-rmHLSVer ver = do-  whenM (lift $ fmap not $ hlsInstalled ver) $ throwE (NotInstalled HLS (GHCTargetVersion Nothing ver))--  isHlsSet      <- lift hlsSet--  AppState {dirs = Dirs {..}} <- lift ask--  bins <- lift $ hlsAllBinaries ver-  forM_ bins $ \f -> liftIO $ deleteFile (binDir </> f)--  when (Just ver == isHlsSet) $ do-    -- delete all set symlinks-    oldSyms <- lift hlsSymlinks-    forM_ oldSyms $ \f -> do-      lift $ $(logDebug) [i|rm #{toFilePath (binDir </> f)}|]-      liftIO $ deleteFile (binDir </> f)-    -- set latest hls-    hlsVers <- lift $ fmap rights getInstalledHLSs-    case headMay . reverse . sort $ hlsVers of-      Just latestver -> setHLS latestver-      Nothing        -> pure ()-----    -------------------    --[ Debug info ]---    ---------------------getDebugInfo :: (MonadReader AppState m, MonadLogger m, MonadCatch m, MonadIO m)-             => Excepts-                  '[NoCompatiblePlatform , NoCompatibleArch , DistroNotFound]-                  m-                  DebugInfo-getDebugInfo = do-  AppState {dirs = Dirs {..}} <- lift ask-  let diBaseDir  = baseDir-  let diBinDir   = binDir-  diGHCDir       <- lift ghcupGHCBaseDir-  let diCacheDir = cacheDir-  diArch         <- lE getArchitecture-  diPlatform     <- liftE getPlatform-  pure $ DebugInfo { .. }-----    ----------------    --[ Compile ]---    -------------------- | Compile a GHC from source. This behaves wrt symlinks and installation--- the same as 'installGHCBin'.-compileGHC :: ( MonadMask m-              , MonadReader AppState m-              , MonadThrow m-              , MonadResource m-              , MonadLogger m-              , MonadIO m-              , MonadFail m-              )-           => GHCupDownloads-           -> GHCTargetVersion           -- ^ version to install-           -> Either Version (Path Abs)  -- ^ version to bootstrap with-           -> Maybe Int                  -- ^ jobs-           -> Maybe (Path Abs)           -- ^ build config-           -> Maybe (Path Abs)           -- ^ patch directory-           -> [Text]                     -- ^ additional args to ./configure-           -> PlatformRequest-           -> Excepts-                '[ AlreadyInstalled-                 , BuildFailed-                 , DigestError-                 , DownloadFailed-                 , GHCupSetError-                 , NoDownload-                 , NotFoundInPATH-                 , PatchFailed-                 , UnknownArchive-                 , TarDirDoesNotExist-                 , NotInstalled-#if !defined(TAR)-                 , ArchiveResult-#endif-                 ]-                m-                ()-compileGHC dls tver bstrap jobs mbuildConfig patchdir aargs pfreq@PlatformRequest{..}-  = do-    lift $ $(logDebug) [i|Requested to compile: #{tver} with #{bstrap}|]--    alreadyInstalled <- lift $ ghcInstalled tver-    alreadySet <- fmap (== Just tver) $ lift $ ghcSet (_tvTarget tver)--    -- download source tarball-    dlInfo <--      preview (ix GHC % ix (tver ^. tvVersion) % viSourceDL % _Just) dls-        ?? NoDownload-    dl        <- liftE $ downloadCached dlInfo Nothing--    -- unpack-    tmpUnpack <- lift mkGhcupTmpDir-    liftE $ unpackToDir tmpUnpack dl-    void $ liftIO $ darwinNotarization _rPlatform tmpUnpack--    bghc <- case bstrap of-      Right g    -> pure $ Right g-      Left  bver -> Left <$> parseRel ("ghc-" <> verToBS bver)-    workdir <- maybe (pure tmpUnpack)-                     (liftE . intoSubdir tmpUnpack)-                     (view dlSubdir dlInfo)-    ghcdir         <- lift $ ghcupGHCDir tver--    (bindist, bmk) <- liftE $ runBuildAction-      tmpUnpack-      Nothing-      (do-        b   <- compileBindist bghc ghcdir workdir-        bmk <- liftIO $ readFileStrict (build_mk workdir)-        pure (b, bmk)-      )--    when alreadyInstalled $ do-      lift $ $(logInfo) [i|Deleting existing installation|]-      liftE $ rmGHCVer tver-    liftE $ installPackedGHC bindist-                             (view dlSubdir dlInfo)-                             ghcdir-                             (tver ^. tvVersion)-                             pfreq--    liftIO $ writeFile (ghcdir </> ghcUpSrcBuiltFile) (Just newFilePerms) bmk--    reThrowAll GHCupSetError $ postGHCInstall tver--    -- restore-    when alreadySet $ liftE $ void $ setGHC tver SetGHCOnly-- where-  defaultConf = case _tvTarget tver of-    Nothing -> [s|-V=0-BUILD_MAN = NO-BUILD_SPHINX_HTML = NO-BUILD_SPHINX_PDF = NO-HADDOCK_DOCS = YES|]-    Just _ -> [s|-V=0-BUILD_MAN = NO-BUILD_SPHINX_HTML = NO-BUILD_SPHINX_PDF = NO-HADDOCK_DOCS = NO-Stage1Only = YES|]--  compileBindist :: ( MonadReader AppState m-                    , MonadThrow m-                    , MonadCatch m-                    , MonadLogger m-                    , MonadIO m-                    , MonadFail m-                    )-                 => Either (Path Rel) (Path Abs)-                 -> Path Abs-                 -> Path Abs-                 -> Excepts-                      '[FileDoesNotExistError, InvalidBuildConfig, PatchFailed, ProcessError, NotFoundInPATH, CopyError]-                      m-                      (Path Abs)  -- ^ output path of bindist-  compileBindist bghc ghcdir workdir = do-    lift $ $(logInfo) [i|configuring build|]-    liftE checkBuildConfig--    AppState { dirs = Dirs {..} } <- lift ask--    forM_ patchdir $ \dir -> liftE $ applyPatches dir workdir--    cEnv <- liftIO getEnvironment--    if-      | _tvVersion tver >= [vver|8.8.0|] -> do-        bghcPath <- case bghc of-          Right ghc' -> pure ghc'-          Left  bver -> do-            spaths <- catMaybes . fmap parseAbs <$> liftIO getSearchPath-            liftIO (searchPath spaths bver) !? NotFoundInPATH bver-        lEM $ execLogged-          "./configure"-          False-          (  ["--prefix=" <> toFilePath ghcdir]-          ++ maybe mempty-                    (\x -> ["--target=" <> E.encodeUtf8 x])-                    (_tvTarget tver)-          ++ fmap E.encodeUtf8 aargs-          )-          [rel|ghc-conf|]-          (Just workdir)-          (Just (("GHC", toFilePath bghcPath) : cEnv))-      | otherwise -> do-        lEM $ execLogged-          "./configure"-          False-          (  [ "--prefix=" <> toFilePath ghcdir-             , "--with-ghc=" <> either toFilePath toFilePath bghc-             ]-          ++ maybe mempty-                   (\x -> ["--target=" <> E.encodeUtf8 x])-                   (_tvTarget tver)-          ++ fmap E.encodeUtf8 aargs-          )-          [rel|ghc-conf|]-          (Just workdir)-          (Just cEnv)--    case mbuildConfig of-      Just bc -> liftIOException-        doesNotExistErrorType-        (FileDoesNotExistError $ toFilePath bc)-        (liftIO $ copyFile bc (build_mk workdir) Overwrite)-      Nothing ->-        liftIO $ writeFile (build_mk workdir) (Just newFilePerms) defaultConf--    lift $ $(logInfo) [i|Building (this may take a while)...|]-    lEM $ make (maybe [] (\j -> ["-j" <> fS (show j)]) jobs) (Just workdir)--    lift $ $(logInfo) [i|Creating bindist...|]-    lEM $ make ["binary-dist"] (Just workdir)-    [tar] <- liftIO $ findFiles-      workdir-      (makeRegexOpts compExtended-                     execBlank-                     ([s|^ghc-.*\.tar\..*$|] :: ByteString)-      )-    c       <- liftIO $ readFile (workdir </> tar)-    cDigest <--      fmap (T.take 8)-      . lift-      . throwEither-      . E.decodeUtf8'-      . B16.encode-      . SHA256.hashlazy-      $ c-    tarName <--      parseRel-        [i|ghc-#{tVerToText tver}-#{pfReqToString pfreq}-#{cDigest}.tar#{takeExtension (toFilePath tar)}|]-    let tarPath = cacheDir </> tarName-    handleIO (throwE . CopyError . show) $ liftIO $ copyFile (workdir </> tar)-                                                             tarPath-                                                             Strict-    lift $ $(logInfo) [i|Copied bindist to #{tarPath}|]-    pure tarPath--  build_mk workdir = workdir </> [rel|mk/build.mk|]--  checkBuildConfig :: (MonadCatch m, MonadIO m)-                   => Excepts-                        '[FileDoesNotExistError, InvalidBuildConfig]-                        m-                        ()-  checkBuildConfig = do-    c <- case mbuildConfig of-      Just bc -> do-        BL.toStrict <$> liftIOException-          doesNotExistErrorType-          (FileDoesNotExistError $ toFilePath bc)-          (liftIO $ readFile bc)-      Nothing -> pure defaultConf-    let lines' = fmap T.strip . T.lines $ decUTF8Safe c--   -- for cross, we need Stage1Only-    case _tvTarget tver of-      Just _ -> when ("Stage1Only = YES" `notElem` lines') $ throwE-        (InvalidBuildConfig-          [s|Cross compiling needs to be a Stage1 build, add "Stage1Only = YES" to your config!|]-        )-      Nothing -> pure ()-----    ----------------------    --[ Upgrade GHCup ]---    -------------------------- | Upgrade ghcup and place it in @~\/.ghcup\/bin\/ghcup@,--- if no path is provided.-upgradeGHCup :: ( MonadMask m-                , MonadReader AppState m-                , MonadCatch m-                , MonadLogger m-                , MonadThrow m-                , MonadResource m-                , MonadIO m-                )-             => GHCupDownloads-             -> Maybe (Path Abs)  -- ^ full file destination to write ghcup into-             -> Bool              -- ^ whether to force update regardless-                                  --   of currently installed version-             -> PlatformRequest-             -> Excepts-                  '[ CopyError-                   , DigestError-                   , DownloadFailed-                   , NoDownload-                   , NoUpdate-                   ]-                  m-                  Version-upgradeGHCup dls mtarget force pfreq = do-  AppState {dirs = Dirs {..}} <- lift ask-  lift $ $(logInfo) [i|Upgrading GHCup...|]-  let latestVer = fromJust $ fst <$> getLatest dls GHCup-  when (not force && (latestVer <= pvpToVersion ghcUpVer)) $ throwE NoUpdate-  dli   <- lE $ getDownloadInfo GHCup latestVer pfreq dls-  tmp   <- lift withGHCupTmpDir-  let fn = [rel|ghcup|]-  p <- liftE $ download dli tmp (Just fn)-  let destDir = dirname destFile-      destFile = fromMaybe (binDir </> fn) mtarget-  lift $ $(logDebug) [i|mkdir -p #{toFilePath destDir}|]-  liftIO $ createDirRecursive' destDir-  lift $ $(logDebug) [i|rm -f #{toFilePath destFile}|]-  liftIO $ hideError NoSuchThing $ deleteFile destFile-  lift $ $(logDebug) [i|cp #{toFilePath p} #{toFilePath destFile}|]-  handleIO (throwE . CopyError . show) $ liftIO $ copyFile p-                                                           destFile-                                                           Overwrite-  lift $ chmod_755 destFile--  liftIO (isInPath destFile) >>= \b -> unless b $-    lift $ $(logWarn) [i|"#{toFilePath (dirname destFile)}" is not in PATH! You have to add it in order to use ghcup.|]-  liftIO (isShadowed destFile) >>= \case-    Nothing -> pure ()-    Just pa -> lift $ $(logWarn) [i|ghcup is shadowed by "#{toFilePath pa}". The upgrade will not be in effect, unless you remove "#{toFilePath pa}" or make sure "#{toFilePath destDir}" comes before "#{toFilePath (dirname pa)}" in PATH.|]--  pure latestVer----    --------------    --[ Other ]---    ------------------ | Creates @ghc-x.y.z@ and @ghc-x.y@ symlinks. This is used for--- both installing from source and bindist.-postGHCInstall :: ( MonadReader AppState m-                  , MonadLogger m-                  , MonadThrow m-                  , MonadFail m-                  , MonadIO m-                  , MonadCatch m-                  )-               => GHCTargetVersion-               -> Excepts '[NotInstalled] m ()-postGHCInstall ver@GHCTargetVersion {..} = do-  void $ liftE $ setGHC ver SetGHC_XYZ--  -- Create ghc-x.y symlinks. This may not be the current-  -- version, create it regardless.-  v' <--    handle (\(e :: ParseError) -> lift $ $(logWarn) [i|#{e}|] >> pure Nothing)-    $ fmap Just-    $ getMajorMinorV _tvVersion-  forM_ v' $ \(mj, mi) -> lift (getGHCForMajor mj mi _tvTarget)-    >>= mapM_ (\v -> liftE $ setGHC v SetGHC_XY)-+{-# LANGUAGE BangPatterns          #-}+{-# LANGUAGE DataKinds             #-}+{-# LANGUAGE FlexibleContexts      #-}+{-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings     #-}+{-# LANGUAGE TemplateHaskell       #-}+{-# LANGUAGE QuasiQuotes           #-}++{-|+Module      : GHCup+Description : GHCup installation functions+Copyright   : (c) Julian Ospald, 2020+License     : LGPL-3.0+Maintainer  : hasufell@hasufell.de+Stability   : experimental+Portability : portable++This module contains the main functions that correspond+to the command line interface, like installation, listing versions+and so on.++These are the entry points.+-}+module GHCup where+++import           GHCup.Download+import           GHCup.Errors+import           GHCup.Platform+import           GHCup.Types+import           GHCup.Types.JSON               ( )+import           GHCup.Types.Optics+import           GHCup.Utils+import           GHCup.Utils.File+import           GHCup.Utils.Logger+import           GHCup.Utils.Prelude+import           GHCup.Utils.String.QQ+import           GHCup.Utils.Version.QQ+import           GHCup.Version++import           Codec.Archive                  ( ArchiveResult )+import           Control.Applicative+import           Control.DeepSeq                ( force )+import           Control.Exception              ( evaluate )+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 )+#if defined(IS_WINDOWS)+import           Control.Monad.IO.Unlift        ( MonadUnliftIO( withRunInIO ) )+#endif+import           Data.ByteString                ( ByteString )+import           Data.Either+import           Data.List+import           Data.Maybe+import           Data.List.NonEmpty             ( NonEmpty((:|)) )+import           Data.String                    ( fromString )+import           Data.Text                      ( Text )+import           Data.Time.Clock+import           Data.Time.Format.ISO8601+import           Data.Versions+import           Distribution.Types.Version   hiding ( Version )+import           Distribution.Types.PackageId+import           Distribution.Types.PackageDescription+import           Distribution.Types.GenericPackageDescription+import           Distribution.PackageDescription.Parsec+import           GHC.IO.Exception+import           Haskus.Utils.Variant.Excepts+import           Language.Haskell.TH+import           Language.Haskell.TH.Syntax     ( Quasi(qAddDependentFile) )+import           Optics+import           Prelude                 hiding ( abs+                                                , writeFile+                                                )+import           Safe                    hiding ( at )+import           System.Directory        hiding ( findFiles )+import           System.Environment+import           System.FilePath+import           System.IO.Error+import           System.IO.Temp+import           Text.PrettyPrint.HughesPJClass ( prettyShow )+import           Text.Regex.Posix++import qualified Crypto.Hash.SHA256            as SHA256+import qualified Data.List.NonEmpty            as NE+import qualified Data.ByteString.Base16        as B16+import qualified Data.ByteString               as B+import qualified Data.ByteString.Lazy          as BL+import qualified Data.Map.Strict               as Map+import qualified Data.Text                     as T+import qualified Data.Text.IO                  as T+import qualified Data.Text.Encoding            as E+#if defined(IS_WINDOWS)+import qualified System.Win32.File             as Win32+#endif+import qualified Text.Megaparsec               as MP+import GHCup.Utils.MegaParsec+import Control.Concurrent (threadDelay)+++    ---------------------+    --[ Tool fetching ]--+    ---------------------+++fetchToolBindist :: ( MonadFail m+                    , MonadMask m+                    , MonadCatch m+                    , MonadReader env m+                    , HasDirs env+                    , HasSettings env+                    , HasPlatformReq env+                    , HasGHCupInfo env+                    , HasLog env+                    , MonadResource m+                    , MonadIO m+                    , MonadUnliftIO m+                    )+                 => Version+                 -> Tool+                 -> Maybe FilePath+                 -> Excepts+                      '[ DigestError+                       , GPGError+                       , DownloadFailed+                       , NoDownload+                       ]+                      m+                      FilePath+fetchToolBindist v t mfp = do+  dlinfo <- liftE $ getDownloadInfo t v+  liftE $ downloadCached' dlinfo Nothing mfp+++fetchGHCSrc :: ( MonadFail m+               , MonadMask m+               , MonadCatch m+               , MonadReader env m+               , HasDirs env+               , HasSettings env+               , HasPlatformReq env+               , HasGHCupInfo env+               , HasLog env+               , MonadResource m+               , MonadIO m+               , MonadUnliftIO m+               )+            => Version+            -> Maybe FilePath+            -> Excepts+                 '[ DigestError+                  , GPGError+                  , DownloadFailed+                  , NoDownload+                  ]+                 m+                 FilePath+fetchGHCSrc v mfp = do+  GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo+  dlInfo <-+    preview (ix GHC % ix v % viSourceDL % _Just) dls+      ?? NoDownload+  liftE $ downloadCached' dlInfo Nothing mfp++++    -------------------------+    --[ Tool installation ]--+    -------------------------+++-- | Like 'installGHCBin', except takes the 'DownloadInfo' as+-- argument instead of looking it up from 'GHCupDownloads'.+installGHCBindist :: ( MonadFail m+                     , MonadMask m+                     , MonadCatch m+                     , MonadReader env m+                     , HasDirs env+                     , HasSettings env+                     , HasPlatformReq env+                     , HasLog env+                     , MonadResource m+                     , MonadIO m+                     , MonadUnliftIO m+                     )+                  => DownloadInfo    -- ^ where/how to download+                  -> Version         -- ^ the version to install+                  -> Maybe FilePath  -- ^ isolated filepath if user passed any+                  -> Bool            -- ^ Force install+                  -> Excepts+                       '[ AlreadyInstalled+                        , BuildFailed+                        , DigestError+                        , GPGError+                        , DownloadFailed+                        , NoDownload+                        , NotInstalled+                        , UnknownArchive+                        , TarDirDoesNotExist+                        , DirNotEmpty+                        , ArchiveResult+                        ]+                       m+                       ()+installGHCBindist dlinfo ver isoFilepath forceInstall = do+  let tver = mkTVer ver++  lift $ logDebug $ "Requested to install GHC with " <> prettyVer ver++  regularGHCInstalled <- lift $ checkIfToolInstalled GHC ver+  +  if+    | not forceInstall+    , regularGHCInstalled+    , Nothing <- isoFilepath -> do+        throwE $ AlreadyInstalled GHC ver++    | forceInstall+    , regularGHCInstalled+    , Nothing <- isoFilepath -> do+        lift $ logInfo "Removing the currently installed GHC version first!"+        liftE $ rmGHCVer tver++    | otherwise -> pure ()++  -- download (or use cached version)+  dl <- liftE $ downloadCached dlinfo Nothing++  -- prepare paths+  ghcdir <- lift $ ghcupGHCDir tver++  toolchainSanityChecks++  case isoFilepath of+    Just isoDir -> do                        -- isolated install+      lift $ logInfo $ "isolated installing GHC to " <> T.pack isoDir+      liftE $ installPackedGHC dl (view dlSubdir dlinfo) isoDir ver forceInstall+    Nothing -> do                            -- regular install+      liftE $ installPackedGHC dl (view dlSubdir dlinfo) ghcdir ver forceInstall++      -- make symlinks & stuff when regular install,+      liftE $ postGHCInstall tver++ where+  toolchainSanityChecks = do+    r <- forM ["CC", "LD"] (liftIO . lookupEnv)+    case catMaybes r of+      [] -> pure ()+      _ -> do+        lift $ logWarn $ "CC/LD environment variable is set. This will change the compiler/linker"+         <> "\n" <> "GHC uses internally and can cause defunct GHC in some cases (e.g. in Anaconda"+         <> "\n" <> "environments). If you encounter problems, unset CC and LD and reinstall."+++-- | Install a packed GHC distribution. This only deals with unpacking and the GHC+-- build system and nothing else.+installPackedGHC :: ( MonadMask m+                    , MonadCatch m+                    , MonadReader env m+                    , HasDirs env+                    , HasPlatformReq env+                    , HasSettings env+                    , MonadThrow m+                    , HasLog env+                    , MonadIO m+                    , MonadUnliftIO m+                    , MonadFail m+                    )+                 => FilePath          -- ^ Path to the packed GHC bindist+                 -> Maybe TarDir      -- ^ Subdir of the archive+                 -> FilePath          -- ^ Path to install to+                 -> Version           -- ^ The GHC version+                 -> Bool              -- ^ Force install+                 -> Excepts+                      '[ BuildFailed+                       , UnknownArchive+                       , TarDirDoesNotExist+                       , DirNotEmpty+                       , ArchiveResult+                       ] m ()+installPackedGHC dl msubdir inst ver forceInstall = do+  PlatformRequest {..} <- lift getPlatformReq++  unless forceInstall+    (liftE $ installDestSanityCheck inst)++  -- unpack+  tmpUnpack <- lift mkGhcupTmpDir+  liftE $ unpackToDir tmpUnpack dl+  liftE $ catchWarn $ lEM @_ @'[ProcessError] $ darwinNotarization _rPlatform tmpUnpack++  -- the subdir of the archive where we do the work+  workdir <- maybe (pure tmpUnpack)+                   (liftE . intoSubdir tmpUnpack)+                   msubdir+  +  liftE $ runBuildAction tmpUnpack+                         (Just inst)+                         (installUnpackedGHC workdir inst ver)+ where+  -- | Does basic checks for isolated installs+  -- Isolated Directory:+  --   1. if it doesn't exist -> proceed+  --   2. if it exists and is empty -> proceed+  --   3. if it exists and is non-empty -> panic and leave the house+  installDestSanityCheck :: ( MonadIO m+                            , MonadCatch m+                            ) =>+                            FilePath ->+                            Excepts '[DirNotEmpty] m ()+  installDestSanityCheck isoDir = do+    hideErrorDef [doesNotExistErrorType] () $ do+      contents <- liftIO $ getDirectoryContentsRecursive isoDir+      unless (null contents) (throwE $ DirNotEmpty isoDir)++++-- | Install an unpacked GHC distribution. This only deals with the GHC+-- build system and nothing else.+installUnpackedGHC :: ( MonadReader env m+                      , HasPlatformReq env+                      , HasDirs env+                      , HasSettings env+                      , MonadThrow m+                      , HasLog env+                      , MonadIO m+                      , MonadUnliftIO m+                      , MonadMask m+                      )+                   => FilePath      -- ^ Path to the unpacked GHC bindist (where the configure script resides)+                   -> FilePath      -- ^ Path to install to+                   -> Version       -- ^ The GHC version+                   -> Excepts '[ProcessError] m ()+installUnpackedGHC path inst ver = do+#if defined(IS_WINDOWS)+  lift $ logInfo "Installing GHC (this may take a while)"+  -- Windows bindists are relocatable and don't need+  -- to run configure.+  -- We also must make sure to preserve mtime to not confuse ghc-pkg.+  lift $ withRunInIO $ \run -> flip onException (run $ recyclePathForcibly inst) $ copyDirectoryRecursive path inst $ \source dest -> do+    mtime <- getModificationTime source+    Win32.moveFile source dest+    setModificationTime dest mtime+#else+  PlatformRequest {..} <- lift getPlatformReq++  let alpineArgs+       | ver >= [vver|8.2.2|], Linux Alpine <- _rPlatform+       = ["--disable-ld-override"]+       | otherwise+       = []++  lift $ logInfo "Installing GHC (this may take a while)"+  lEM $ execLogged "sh"+                   ("./configure" : ("--prefix=" <> inst) +                    : alpineArgs+                   )+                   (Just path)+                   "ghc-configure"+                   Nothing+  lEM $ make ["install"] (Just path)+  pure ()+#endif+++-- | Installs GHC into @~\/.ghcup\/ghc/\<ver\>@ and places the+-- following symlinks in @~\/.ghcup\/bin@:+--+--   * @ghc-x.y.z -> ..\/ghc\/x.y.z\/bin/ghc@+--   * @ghc-x.y   -> ..\/ghc\/x.y.z\/bin/ghc@ (if x.y.z is the latest x.y version)+installGHCBin :: ( MonadFail m+                 , MonadMask m+                 , MonadCatch m+                 , MonadReader env m+                 , HasPlatformReq env+                 , HasGHCupInfo env+                 , HasDirs env+                 , HasSettings env+                 , HasLog env+                 , MonadResource m+                 , MonadIO m+                 , MonadUnliftIO m+                 )+              => Version         -- ^ the version to install+              -> Maybe FilePath  -- ^ isolated install filepath, if user passed any+              -> Bool            -- ^ force install+              -> Excepts+                   '[ AlreadyInstalled+                    , BuildFailed+                    , DigestError+                    , GPGError+                    , DownloadFailed+                    , NoDownload+                    , NotInstalled+                    , UnknownArchive+                    , TarDirDoesNotExist+                    , DirNotEmpty+                    , ArchiveResult+                    ]+                   m+                   ()+installGHCBin ver isoFilepath forceInstall = do+  dlinfo <- liftE $ getDownloadInfo GHC ver+  installGHCBindist dlinfo ver isoFilepath forceInstall+++-- | Like 'installCabalBin', except takes the 'DownloadInfo' as+-- argument instead of looking it up from 'GHCupDownloads'.+installCabalBindist :: ( MonadMask m+                       , MonadCatch m+                       , MonadReader env m+                       , HasPlatformReq env+                       , HasDirs env+                       , HasSettings env+                       , HasLog env+                       , MonadResource m+                       , MonadIO m+                       , MonadUnliftIO m+                       , MonadFail m+                       )+                    => DownloadInfo+                    -> Version+                    -> Maybe FilePath -- ^ isolated install filepath, if user provides any.+                    -> Bool           -- ^ Force install +                    -> Excepts+                         '[ AlreadyInstalled+                          , CopyError+                          , DigestError+                          , GPGError+                          , DownloadFailed+                          , NoDownload+                          , NotInstalled+                          , UnknownArchive+                          , TarDirDoesNotExist+                          , ArchiveResult+                          , FileAlreadyExistsError+                          ]+                         m+                         ()+installCabalBindist dlinfo ver isoFilepath forceInstall = do+  lift $ logDebug $ "Requested to install cabal version " <> prettyVer ver++  PlatformRequest {..} <- lift getPlatformReq+  Dirs {..} <- lift getDirs++  -- check if we already have a regular cabal already installed+  regularCabalInstalled <- lift $ checkIfToolInstalled Cabal ver++  if+    | not forceInstall+    , regularCabalInstalled+    ,  Nothing <- isoFilepath -> do+        throwE $ AlreadyInstalled Cabal ver+        +    | forceInstall+    , regularCabalInstalled+    , Nothing <- isoFilepath -> do+        lift $ logInfo "Removing the currently installed version first!"+        liftE $ rmCabalVer ver++    | otherwise -> pure ()++               +  -- download (or use cached version)+  dl <- liftE $ downloadCached dlinfo Nothing++  -- unpack+  tmpUnpack <- lift withGHCupTmpDir+  liftE $ unpackToDir tmpUnpack dl+  liftE $ catchWarn $ lEM @_ @'[ProcessError] $ darwinNotarization _rPlatform tmpUnpack++  -- the subdir of the archive where we do the work+  workdir <- maybe (pure tmpUnpack) (liftE . intoSubdir tmpUnpack) (view dlSubdir dlinfo)++  case isoFilepath of+    Just isoDir -> do             -- isolated install+      lift $ logInfo $ "isolated installing Cabal to " <> T.pack isoDir+      liftE $ installCabalUnpacked workdir isoDir Nothing forceInstall++    Nothing -> do                 -- regular install+      liftE $ installCabalUnpacked workdir binDir (Just ver) forceInstall++      -- create symlink if this is the latest version for regular installs+      cVers <- lift $ fmap rights getInstalledCabals+      let lInstCabal = headMay . reverse . sort $ cVers+      when (maybe True (ver >=) lInstCabal) $ liftE $ setCabal ver+      +-- | Install an unpacked cabal distribution.Symbol+installCabalUnpacked :: (MonadCatch m, HasLog env, MonadIO m, MonadReader env m)+              => FilePath      -- ^ Path to the unpacked cabal bindist (where the executable resides)+              -> FilePath      -- ^ Path to install to+              -> Maybe Version -- ^ Nothing for isolated install+              -> Bool          -- ^ Force Install+              -> Excepts '[CopyError, FileAlreadyExistsError] m ()+installCabalUnpacked path inst mver' forceInstall = do+  lift $ logInfo "Installing cabal"+  let cabalFile = "cabal"+  liftIO $ createDirRecursive' inst+  let destFileName = cabalFile+        <> maybe "" (("-" <>) . T.unpack . prettyVer) mver'+        <> exeExt+  let destPath = inst </> destFileName++  unless forceInstall          -- Overwrite it when it IS a force install+    (liftE $ throwIfFileAlreadyExists destPath)+    +  copyFileE+    (path </> cabalFile <> exeExt)+    destPath+  lift $ chmod_755 destPath++-- | Installs cabal into @~\/.ghcup\/bin/cabal-\<ver\>@ and+-- creates a default @cabal -> cabal-x.y.z.q@ symlink for+-- the latest installed version.+installCabalBin :: ( MonadMask m+                   , MonadCatch m+                   , MonadReader env m+                   , HasPlatformReq env+                   , HasGHCupInfo env+                   , HasDirs env+                   , HasSettings env+                   , HasLog env+                   , MonadResource m+                   , MonadIO m+                   , MonadUnliftIO m+                   , MonadFail m+                   )+                => Version+                -> Maybe FilePath -- isolated install Path, if user provided any+                -> Bool           -- force install+                -> Excepts+                     '[ AlreadyInstalled+                      , CopyError+                      , DigestError+                      , GPGError+                      , DownloadFailed+                      , NoDownload+                      , NotInstalled+                      , UnknownArchive+                      , TarDirDoesNotExist+                      , ArchiveResult+                      , FileAlreadyExistsError+                      ]+                     m+                     ()+installCabalBin ver isoFilepath forceInstall = do+  dlinfo <- liftE $ getDownloadInfo Cabal ver+  installCabalBindist dlinfo ver isoFilepath forceInstall+++-- | Like 'installHLSBin, except takes the 'DownloadInfo' as+-- argument instead of looking it up from 'GHCupDownloads'.+installHLSBindist :: ( MonadMask m+                     , MonadCatch m+                     , MonadReader env m+                     , HasPlatformReq env+                     , HasDirs env+                     , HasSettings env+                     , HasLog env+                     , MonadResource m+                     , MonadIO m+                     , MonadUnliftIO m+                     , MonadFail m+                     )+                  => DownloadInfo+                  -> Version+                  -> Maybe FilePath -- ^ isolated install path, if user passed any+                  -> Bool           -- ^ Force install+                  -> Excepts+                       '[ AlreadyInstalled+                        , CopyError+                        , DigestError+                        , GPGError+                        , DownloadFailed+                        , NoDownload+                        , NotInstalled+                        , UnknownArchive+                        , TarDirDoesNotExist+                        , ArchiveResult+                        , FileAlreadyExistsError+                        ]+                       m+                       ()+installHLSBindist dlinfo ver isoFilepath forceInstall = do+  lift $ logDebug $ "Requested to install hls version " <> prettyVer ver++  PlatformRequest {..} <- lift getPlatformReq+  Dirs {..} <- lift getDirs++  regularHLSInstalled <- lift $ checkIfToolInstalled HLS ver++  if+    | not forceInstall+    , regularHLSInstalled+    , Nothing <- isoFilepath -> do      -- regular install+        throwE $ AlreadyInstalled HLS ver++    | forceInstall+    , regularHLSInstalled+    , Nothing <- isoFilepath -> do      -- regular forced install+        lift $ logInfo "Removing the currently installed version of HLS before force installing!"+        liftE $ rmHLSVer ver++    | otherwise -> pure ()+    +  -- download (or use cached version)+  dl <- liftE $ downloadCached dlinfo Nothing++  -- unpack+  tmpUnpack <- lift withGHCupTmpDir+  liftE $ unpackToDir tmpUnpack dl+  liftE $ catchWarn $ lEM @_ @'[ProcessError] $ darwinNotarization _rPlatform tmpUnpack++  -- the subdir of the archive where we do the work+  workdir <- maybe (pure tmpUnpack) (liftE . intoSubdir tmpUnpack) (view dlSubdir dlinfo)++  case isoFilepath of+    Just isoDir -> do+      lift $ logInfo $ "isolated installing HLS to " <> T.pack isoDir+      liftE $ installHLSUnpacked workdir isoDir Nothing forceInstall++    Nothing -> do+      liftE $ installHLSUnpacked workdir binDir (Just ver) forceInstall++  liftE $ installHLSPostInst isoFilepath ver+++-- | Install an unpacked hls distribution.+installHLSUnpacked :: (MonadReader env m, MonadFail m, HasLog env, MonadCatch m, MonadIO m)+              => FilePath      -- ^ Path to the unpacked hls bindist (where the executable resides)+              -> FilePath      -- ^ Path to install to+              -> Maybe Version -- ^ Nothing for isolated install+              -> Bool          -- ^ is it a force install+              -> Excepts '[CopyError, FileAlreadyExistsError] m ()+installHLSUnpacked path inst mver' forceInstall = do+  lift $ logInfo "Installing HLS"+  liftIO $ createDirRecursive' inst++  -- install haskell-language-server-<ghcver>+  bins@(_:_) <- liftIO $ findFiles+    path+    (makeRegexOpts compExtended+                   execBlank+                   ([s|^haskell-language-server-[0-9].*$|] :: ByteString)+    )+  forM_ bins $ \f -> do+    let toF = dropSuffix exeExt f+              <> maybe "" (("~" <>) . T.unpack . prettyVer) mver'+              <> exeExt++    let srcPath = path </> f+    let destPath = inst </> toF++    unless forceInstall   -- if it is a force install, overwrite it.+      (liftE $ throwIfFileAlreadyExists destPath)+      +    copyFileE+      srcPath+      destPath+    lift $ chmod_755 destPath++  -- install haskell-language-server-wrapper+  let wrapper = "haskell-language-server-wrapper"+      toF = wrapper+            <> maybe "" (("-" <>) . T.unpack . prettyVer) mver'+            <> exeExt+      srcWrapperPath = path </> wrapper <> exeExt+      destWrapperPath = inst </> toF++  unless forceInstall+    (liftE $ throwIfFileAlreadyExists destWrapperPath)+      +  copyFileE+    srcWrapperPath+    destWrapperPath+    +  lift $ chmod_755 destWrapperPath+++installHLSPostInst :: (MonadReader env m, HasDirs env, HasLog env, MonadIO m, MonadCatch m, MonadMask m, MonadFail m, MonadUnliftIO m)+                   => Maybe FilePath+                   -> Version+                   -> Excepts '[NotInstalled] m ()+installHLSPostInst isoFilepath ver = +  case isoFilepath of+    Just _ -> pure ()+    Nothing -> do+      -- create symlink if this is the latest version in a regular install+      hlsVers <- lift $ fmap rights getInstalledHLSs+      let lInstHLS = headMay . reverse . sort $ hlsVers+      when (maybe True (ver >=) lInstHLS) $ liftE $ setHLS ver+++-- | Installs hls binaries @haskell-language-server-\<ghcver\>@+-- into @~\/.ghcup\/bin/@, as well as @haskell-languager-server-wrapper@.+installHLSBin :: ( MonadMask m+                 , MonadCatch m+                 , MonadReader env m+                 , HasPlatformReq env+                 , HasGHCupInfo env+                 , HasDirs env+                 , HasSettings env+                 , HasLog env+                 , MonadResource m+                 , MonadIO m+                 , MonadUnliftIO m+                 , MonadFail m+                 )+              => Version+              -> Maybe FilePath  -- isolated install Dir (if any)+              -> Bool            -- force install+              -> Excepts+                   '[ AlreadyInstalled+                    , CopyError+                    , DigestError+                    , GPGError+                    , DownloadFailed+                    , NoDownload+                    , NotInstalled+                    , UnknownArchive+                    , TarDirDoesNotExist+                    , ArchiveResult+                    , FileAlreadyExistsError+                    ]+                   m+                   ()+installHLSBin ver isoFilepath forceInstall = do+  dlinfo <- liftE $ getDownloadInfo HLS ver+  installHLSBindist dlinfo ver isoFilepath forceInstall+++compileHLS :: ( MonadMask m+              , MonadCatch m+              , MonadReader env m+              , HasDirs env+              , HasSettings env+              , HasPlatformReq env+              , HasGHCupInfo env+              , HasLog env+              , MonadResource m+              , MonadIO m+              , MonadUnliftIO m+              , MonadFail m+              )+           => Either Version GitBranch+           -> [Version]+           -> Maybe Int+           -> Maybe Version+           -> Maybe FilePath+           -> Maybe FilePath+           -> Maybe FilePath+           -> Maybe FilePath+           -> Excepts '[ NoDownload+                       , GPGError+                       , DownloadFailed+                       , DigestError+                       , UnknownArchive+                       , TarDirDoesNotExist+                       , ArchiveResult+                       , BuildFailed+                       , NotInstalled+                       ] m Version+compileHLS targetHLS ghcs jobs ov isolateDir cabalProject cabalProjectLocal patchdir = do+  PlatformRequest { .. } <- lift getPlatformReq+  GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo+  Dirs { .. } <- lift getDirs++  (workdir, tver) <- case targetHLS of+    -- unpack from version tarball+    Left tver -> do+      lift $ logDebug $ "Requested to compile: " <> prettyVer tver++      -- download source tarball+      dlInfo <-+        preview (ix HLS % ix tver % viSourceDL % _Just) dls+          ?? NoDownload+      dl <- liftE $ downloadCached dlInfo Nothing++      -- unpack+      tmpUnpack <- lift mkGhcupTmpDir+      liftE $ unpackToDir tmpUnpack dl+      liftE $ catchWarn $ lEM @_ @'[ProcessError] $ darwinNotarization _rPlatform tmpUnpack++      workdir <- maybe (pure tmpUnpack)+                       (liftE . intoSubdir tmpUnpack)+                       (view dlSubdir dlInfo)++      pure (workdir, tver)++    -- clone from git+    Right GitBranch{..} -> do+      tmpUnpack <- lift mkGhcupTmpDir+      let git args = execLogged "git" ("--no-pager":args) (Just tmpUnpack) "git" Nothing+      tver <- reThrowAll @_ @'[ProcessError] DownloadFailed $ do+        let rep = fromMaybe "https://github.com/haskell/haskell-language-server.git" repo+        lift $ logInfo $ "Fetching git repo " <> T.pack rep <> " at ref " <> T.pack ref <> " (this may take a while)"+        lEM $ git [ "init" ]+        lEM $ git [ "remote"+                  , "add"+                  , "origin"+                  , fromString rep ]++        let fetch_args = +                  [ "fetch"+                  , "--depth"+                  , "1"+                  , "--quiet"+                  , "origin"+                  , fromString ref ]+        lEM $ git fetch_args++        lEM $ git [ "checkout", "FETCH_HEAD" ]+        (Just gpd) <- parseGenericPackageDescriptionMaybe <$> liftIO (B.readFile (tmpUnpack </> "haskell-language-server.cabal"))+        pure . (\c -> Version Nothing c [] Nothing)+          . NE.fromList . fmap (NE.fromList . (:[]) . digits . fromIntegral)+          . versionNumbers+          . pkgVersion+          . package+          . packageDescription+          $ gpd++      liftE $ catchWarn $ lEM @_ @'[ProcessError] $ darwinNotarization _rPlatform tmpUnpack+      lift $ logInfo $ "Git version " <> T.pack ref <> " corresponds to HLS version " <> prettyVer tver++      pure (tmpUnpack, tver)++  -- the version that's installed may differ from the+  -- compiled version, so the user can overwrite it+  let installVer = fromMaybe tver ov++  liftE $ runBuildAction+    workdir+    Nothing+    (reThrowAll @_ @'[PatchFailed, ProcessError, FileAlreadyExistsError, CopyError] @'[BuildFailed] (BuildFailed workdir) $ do+      let installDir = workdir </> "out"+      liftIO $ createDirRecursive' installDir++      -- apply patches+      forM_ patchdir (\dir -> liftE $ applyPatches dir workdir)++      -- set up project files+      cp <- case cabalProject of+        Just cp+          | isAbsolute cp -> do+              copyFileE cp (workdir </> "cabal.project")+              pure "cabal.project"+          | otherwise -> pure (takeFileName cp)+        Nothing -> pure "cabal.project"+      forM_ cabalProjectLocal $ \cpl -> copyFileE cpl (workdir </> cp <.> "local")++      let targets = ["exe:haskell-language-server", "exe:haskell-language-server-wrapper"]++      artifacts <- forM (sort ghcs) $ \ghc -> do+        let ghcInstallDir = installDir </> T.unpack (prettyVer ghc)+        liftIO $ createDirRecursive' ghcInstallDir+        lift $ logInfo $ "Building HLS " <> prettyVer installVer <> " for GHC version " <> prettyVer ghc+        liftE $ lEM @_ @'[ProcessError] $+          execLogged "cabal" ( [ "v2-build"+                               , "-w"+                               , "ghc-" <> T.unpack (prettyVer ghc)+                               ] +++                               maybe [] (\j -> ["--jobs=" <> show j]) jobs +++                               [ "--project-file=" <> cp+                               ] ++ targets+                             )+          (Just workdir) "cabal" Nothing+        forM_ targets $ \target -> do+          let cabal = "cabal"+              args = ["list-bin", target]+          CapturedProcess{..} <- lift $ executeOut cabal args  (Just workdir) +          case _exitCode of+            ExitFailure i -> throwE (NonZeroExit i cabal args)+            _ -> pure ()+          let cbin = stripNewlineEnd . T.unpack . decUTF8Safe' $ _stdOut+          copyFileE cbin (ghcInstallDir </> takeFileName cbin)+        pure ghcInstallDir++      forM_ artifacts $ \artifact -> do+        liftIO $ renameFile (artifact </> "haskell-language-server" <.> exeExt)+          (installDir </> "haskell-language-server-" <> takeFileName artifact <.> exeExt)+        liftIO $ renameFile (artifact </> "haskell-language-server-wrapper" <.> exeExt)+          (installDir </> "haskell-language-server-wrapper" <.> exeExt)+        liftIO $ rmPathForcibly artifact++      case isolateDir of+        Just isoDir -> do+          lift $ logInfo $ "isolated installing HLS to " <> T.pack isoDir+          liftE $ installHLSUnpacked installDir isoDir Nothing True+        Nothing -> do+          liftE $ installHLSUnpacked installDir binDir (Just installVer) True+    )++  liftE $ installHLSPostInst isolateDir installVer++  pure installVer++++-- | Installs stack into @~\/.ghcup\/bin/stack-\<ver\>@ and+-- creates a default @stack -> stack-x.y.z.q@ symlink for+-- the latest installed version.+installStackBin :: ( MonadMask m+                   , MonadCatch m+                   , MonadReader env m+                   , HasDirs env+                   , HasSettings env+                   , HasPlatformReq env+                   , HasGHCupInfo env+                   , HasLog env+                   , MonadResource m+                   , MonadIO m+                   , MonadUnliftIO m+                   , MonadFail m+                   )+                => Version+                -> Maybe FilePath  -- ^ isolate install Dir (if any)+                -> Bool            -- ^ Force install+                -> Excepts+                     '[ AlreadyInstalled+                      , CopyError+                      , DigestError+                      , GPGError+                      , DownloadFailed+                      , NoDownload+                      , NotInstalled+                      , UnknownArchive+                      , TarDirDoesNotExist+                      , ArchiveResult+                      , FileAlreadyExistsError+                      ]+                     m+                     ()+installStackBin ver isoFilepath forceInstall = do+  dlinfo <- liftE $ getDownloadInfo Stack ver+  installStackBindist dlinfo ver isoFilepath forceInstall+++-- | Like 'installStackBin', except takes the 'DownloadInfo' as+-- argument instead of looking it up from 'GHCupDownloads'.+installStackBindist :: ( MonadMask m+                       , MonadCatch m+                       , MonadReader env m+                       , HasPlatformReq env+                       , HasDirs env+                       , HasSettings env+                       , HasLog env+                       , MonadResource m+                       , MonadIO m+                       , MonadUnliftIO m+                       , MonadFail m+                       )+                    => DownloadInfo+                    -> Version+                    -> Maybe FilePath -- ^ isolate install Dir (if any)+                    -> Bool           -- ^ Force install+                    -> Excepts+                         '[ AlreadyInstalled+                          , CopyError+                          , DigestError+                          , GPGError+                          , DownloadFailed+                          , NoDownload+                          , NotInstalled+                          , UnknownArchive+                          , TarDirDoesNotExist+                          , ArchiveResult+                          , FileAlreadyExistsError+                          ]+                         m+                         ()+installStackBindist dlinfo ver isoFilepath forceInstall = do+  lift $ logDebug $ "Requested to install stack version " <> prettyVer ver++  PlatformRequest {..} <- lift getPlatformReq+  Dirs {..} <- lift getDirs++  regularStackInstalled <- lift $ checkIfToolInstalled Stack ver++  if+    | not forceInstall+    , regularStackInstalled+    , Nothing <- isoFilepath -> do+        throwE $ AlreadyInstalled Stack ver++    | forceInstall+    , regularStackInstalled+    , Nothing <- isoFilepath -> do+        lift $ logInfo "Removing the currently installed version of Stack first!"+        liftE $ rmStackVer ver++    | otherwise -> pure ()++  -- download (or use cached version)+  dl <- liftE $ downloadCached dlinfo Nothing++  -- unpack+  tmpUnpack <- lift withGHCupTmpDir+  liftE $ unpackToDir tmpUnpack dl+  liftE $ catchWarn $ lEM @_ @'[ProcessError] $ darwinNotarization _rPlatform tmpUnpack++  -- the subdir of the archive where we do the work+  workdir <- maybe (pure tmpUnpack) (liftE . intoSubdir tmpUnpack) (view dlSubdir dlinfo)++  case isoFilepath of+    Just isoDir -> do                 -- isolated install+      lift $ logInfo $ "isolated installing Stack to " <> T.pack isoDir+      liftE $ installStackUnpacked workdir isoDir Nothing forceInstall+    Nothing -> do                     -- regular install+      liftE $ installStackUnpacked workdir binDir (Just ver) forceInstall++      -- create symlink if this is the latest version and a regular install+      sVers <- lift $ fmap rights getInstalledStacks+      let lInstStack = headMay . reverse . sort $ sVers+      when (maybe True (ver >=) lInstStack) $ liftE $ setStack ver+++-- | Install an unpacked stack distribution.+installStackUnpacked :: (MonadReader env m, HasLog env, MonadCatch m, MonadIO m)+              => FilePath      -- ^ Path to the unpacked stack bindist (where the executable resides)+              -> FilePath      -- ^ Path to install to+              -> Maybe Version -- ^ Nothing for isolated installs+              -> Bool          -- ^ Force install+              -> Excepts '[CopyError, FileAlreadyExistsError] m ()+installStackUnpacked path inst mver' forceInstall = do+  lift $ logInfo "Installing stack"+  let stackFile = "stack"+  liftIO $ createDirRecursive' inst+  let destFileName = stackFile+                     <> maybe "" (("-" <>) .  T.unpack . prettyVer) mver'+                     <> exeExt+      destPath = inst </> destFileName++  unless forceInstall+    (liftE $ throwIfFileAlreadyExists destPath)+      +  copyFileE+    (path </> stackFile <> exeExt)+    destPath+  lift $ chmod_755 destPath+++    ---------------------+    --[ Set GHC/cabal ]--+    ---------------------++++-- | Set GHC symlinks in @~\/.ghcup\/bin@ for the requested GHC version. The behavior depends+-- on `SetGHC`:+--+--   * SetGHCOnly: @~\/.ghcup\/bin\/ghc -> ~\/.ghcup\/ghc\/\<ver\>\/bin\/ghc@+--   * SetGHC_XY: @~\/.ghcup\/bin\/ghc-X.Y -> ~\/.ghcup\/ghc\/\<ver\>\/bin\/ghc@+--   * SetGHC_XYZ: @~\/.ghcup\/bin\/ghc-\<ver\> -> ~\/.ghcup\/ghc\/\<ver\>\/bin\/ghc@+--+-- Additionally creates a @~\/.ghcup\/share -> ~\/.ghcup\/ghc\/\<ver\>\/share symlink@+-- for 'SetGHCOnly' constructor.+setGHC :: ( MonadReader env m+          , HasDirs env+          , HasLog env+          , MonadThrow m+          , MonadFail m+          , MonadIO m+          , MonadCatch m+          , MonadMask m+          , MonadUnliftIO m+          )+       => GHCTargetVersion+       -> SetGHC+       -> Excepts '[NotInstalled] m GHCTargetVersion+setGHC ver sghc = do+  let verS = T.unpack $ prettyVer (_tvVersion ver)+  ghcdir                        <- lift $ ghcupGHCDir ver++  whenM (lift $ not <$> ghcInstalled ver) (throwE (NotInstalled GHC ver))++  -- symlink destination+  Dirs {..} <- lift getDirs++  -- first delete the old symlinks (this fixes compatibility issues+  -- with old ghcup)+  case sghc of+    SetGHCOnly -> liftE $ rmPlain (_tvTarget ver)+    SetGHC_XY  -> liftE $ rmMajorSymlinks ver+    SetGHC_XYZ -> liftE $ rmMinorSymlinks ver++  -- for ghc tools (ghc, ghci, haddock, ...)+  verfiles <- ghcToolFiles ver+  forM_ verfiles $ \file -> do+    mTargetFile <- case sghc of+      SetGHCOnly -> pure $ Just file+      SetGHC_XY  -> do+        handle+            (\(e :: ParseError) -> lift $ logWarn (T.pack $ displayException e) >> pure Nothing)+          $ do +            (mj, mi) <- getMajorMinorV (_tvVersion ver)+            let major' = intToText mj <> "." <> intToText mi+            pure $ Just (file <> "-" <> T.unpack major')+      SetGHC_XYZ ->+        pure $ Just (file <> "-" <> verS)++    -- create symlink+    forM mTargetFile $ \targetFile -> do+      let fullF = binDir </> targetFile  <> exeExt+          fileWithExt = file <> exeExt+      destL <- lift $ ghcLinkDestination fileWithExt ver+      lift $ createLink destL fullF++  -- create symlink for share dir+  when (isNothing . _tvTarget $ ver) $ lift $ symlinkShareDir ghcdir verS++  when (sghc == SetGHCOnly) $ lift warnAboutHlsCompatibility++  pure ver++ where++  symlinkShareDir :: ( MonadReader env m+                     , HasDirs env+                     , MonadIO m+                     , HasLog env+                     , MonadCatch m+                     , MonadMask m+                     )+                  => FilePath+                  -> String+                  -> m ()+  symlinkShareDir ghcdir ver' = do+    Dirs {..} <- getDirs+    let destdir = baseDir+    case sghc of+      SetGHCOnly -> do+        let sharedir     = "share"+        let fullsharedir = ghcdir </> sharedir+        whenM (liftIO $ doesDirectoryExist fullsharedir) $ do+          let fullF   = destdir </> sharedir+          let targetF = "." </> "ghc" </> ver' </> sharedir+          logDebug $ "rm -f " <> T.pack fullF+          hideError doesNotExistErrorType $ rmDirectoryLink fullF+          logDebug $ "ln -s " <> T.pack targetF <> " " <> T.pack fullF+          liftIO+#if defined(IS_WINDOWS)+            -- On windows we need to be more permissive+            -- in case symlinks can't be created, be just+            -- give up here. This symlink isn't strictly necessary.+            $ hideError permissionErrorType+            $ hideError illegalOperationErrorType+#endif+            $ createDirectoryLink targetF fullF+      _ -> pure ()++unsetGHC :: ( MonadReader env m+            , HasDirs env+            , HasLog env+            , MonadThrow m+            , MonadFail m+            , MonadIO m+            , MonadMask m+            )+         => Maybe Text+         -> Excepts '[NotInstalled] m ()+unsetGHC = rmPlain+++-- | Set the @~\/.ghcup\/bin\/cabal@ symlink.+setCabal :: ( MonadMask m+            , MonadReader env m+            , HasDirs env+            , HasLog env+            , MonadFail m+            , MonadIO m+            , MonadUnliftIO m)+         => Version+         -> Excepts '[NotInstalled] m ()+setCabal ver = do+  let targetFile = "cabal-" <> T.unpack (prettyVer ver) <> exeExt++  -- symlink destination+  Dirs {..} <- lift getDirs++  whenM (liftIO $ not <$> doesFileExist (binDir </> targetFile))+    $ throwE+    $ NotInstalled Cabal (GHCTargetVersion Nothing ver)++  let cabalbin = binDir </> "cabal" <> exeExt++  -- create link+  let destL = targetFile+  lift $ createLink destL cabalbin++  pure ()++unsetCabal :: ( MonadMask m+              , MonadReader env m+              , HasDirs env+              , MonadIO m)+           => m ()+unsetCabal = do+  Dirs {..} <- getDirs+  let cabalbin = binDir </> "cabal" <> exeExt+  hideError doesNotExistErrorType $ rmLink cabalbin+++-- | Set the haskell-language-server symlinks.+setHLS :: ( MonadReader env m+          , HasDirs env+          , HasLog env+          , MonadIO m+          , MonadMask m+          , MonadFail m+          , MonadUnliftIO m+          )+       => Version+       -> Excepts '[NotInstalled] m ()+setHLS ver = do+  Dirs {..} <- lift getDirs++  -- Delete old symlinks, since these might have different ghc versions than the+  -- selected version, so we could end up with stray or incorrect symlinks.+  oldSyms <- lift hlsSymlinks+  forM_ oldSyms $ \f -> do+    lift $ logDebug $ "rm " <> T.pack (binDir </> f)+    lift $ rmLink (binDir </> f)++  -- set haskell-language-server-<ghcver> symlinks+  bins <- lift $ hlsServerBinaries ver Nothing+  when (null bins) $ throwE $ NotInstalled HLS (GHCTargetVersion Nothing ver)++  forM_ bins $ \f -> do+    let destL = f+    let target = (<> exeExt) . head . splitOn "~" $ f+    lift $ createLink destL (binDir </> target)++  -- set haskell-language-server-wrapper symlink+  let destL = "haskell-language-server-wrapper-" <> T.unpack (prettyVer ver) <> exeExt+  let wrapper = binDir </> "haskell-language-server-wrapper" <> exeExt++  lift $ createLink destL wrapper++  lift warnAboutHlsCompatibility++  pure ()+++unsetHLS :: ( MonadMask m+            , MonadReader env m+            , HasDirs env+            , MonadIO m)+         => m ()+unsetHLS = do+  Dirs {..} <- getDirs+  let wrapper = binDir </> "haskell-language-server-wrapper" <> exeExt+  bins   <- liftIO $ handleIO (\_ -> pure []) $ findFiles'+    binDir+    (MP.chunk "haskell-language-server-" <* pvp' <* MP.chunk (T.pack exeExt) <* MP.eof)+  forM_ bins (hideError doesNotExistErrorType . rmLink . (binDir </>))+  hideError doesNotExistErrorType $ rmLink wrapper+++-- | Set the @~\/.ghcup\/bin\/stack@ symlink.+setStack :: ( MonadMask m+            , MonadReader env m+            , HasDirs env+            , HasLog env+            , MonadThrow m+            , MonadFail m+            , MonadIO m+            , MonadUnliftIO m+            )+         => Version+         -> Excepts '[NotInstalled] m ()+setStack ver = do+  let targetFile = "stack-" <> T.unpack (prettyVer ver) <> exeExt++  -- symlink destination+  Dirs {..} <- lift getDirs++  whenM (liftIO $ not <$> doesFileExist (binDir </> targetFile))+    $ throwE+    $ NotInstalled Stack (GHCTargetVersion Nothing ver)++  let stackbin = binDir </> "stack" <> exeExt++  lift $ createLink targetFile stackbin++  pure ()+++unsetStack :: ( MonadMask m+              , MonadReader env m+              , HasDirs env+              , MonadIO m)+           => m ()+unsetStack = do+  Dirs {..} <- getDirs+  let stackbin = binDir </> "stack" <> exeExt+  hideError doesNotExistErrorType $ rmLink stackbin+++-- | Warn if the installed and set HLS is not compatible with the installed and+-- set GHC version.+warnAboutHlsCompatibility :: ( MonadReader env m+                             , HasDirs env+                             , HasLog env+                             , MonadThrow m+                             , MonadCatch m+                             , MonadIO m+                             )+                          => m ()+warnAboutHlsCompatibility = do+  supportedGHC <- hlsGHCVersions+  currentGHC   <- fmap _tvVersion <$> ghcSet Nothing+  currentHLS   <- hlsSet++  case (currentGHC, currentHLS) of+    (Just gv, Just hv) | gv `notElem` supportedGHC -> do+      logWarn $+        "GHC " <> T.pack (prettyShow gv) <> " is not compatible with " <>+        "Haskell Language Server " <> T.pack (prettyShow hv) <> "." <> "\n" <>+        "Haskell IDE support may not work until this is fixed." <> "\n" <>+        "Install a different HLS version, or install and set one of the following GHCs:" <> "\n" <>+        T.pack (prettyShow supportedGHC)+        +    _ -> return ()++    ------------------+    --[ List tools ]--+    ------------------+++-- | Filter data type for 'listVersions'.+data ListCriteria = ListInstalled+                  | ListSet+                  | ListAvailable+                  deriving Show++-- | A list result describes a single tool version+-- and various of its properties.+data ListResult = ListResult+  { lTool      :: Tool+  , lVer       :: Version+  , lCross     :: Maybe Text -- ^ currently only for GHC+  , lTag       :: [Tag]+  , lInstalled :: Bool+  , lSet       :: Bool -- ^ currently active version+  , fromSrc    :: Bool -- ^ compiled from source+  , lStray     :: Bool -- ^ not in download info+  , lNoBindist :: Bool -- ^ whether the version is available for this platform/arch+  , hlsPowered :: Bool+  }+  deriving (Eq, Ord, Show)+++-- | Extract all available tool versions and their tags.+availableToolVersions :: GHCupDownloads -> Tool -> Map.Map Version VersionInfo+availableToolVersions av tool = view+  (at tool % non Map.empty)+  av+++-- | List all versions from the download info, as well as stray+-- versions.+listVersions :: ( MonadCatch m+                , HasLog env+                , MonadThrow m+                , HasLog env+                , MonadIO m+                , MonadReader env m+                , HasDirs env+                , HasPlatformReq env+                , HasGHCupInfo env+                )+             => Maybe Tool+             -> Maybe ListCriteria+             -> m [ListResult]+listVersions lt' criteria = do+  -- some annoying work to avoid too much repeated IO+  cSet <- cabalSet+  cabals <- getInstalledCabals+  hlsSet' <- hlsSet+  hlses <- getInstalledHLSs+  sSet <- stackSet+  stacks <- getInstalledStacks++  go lt' cSet cabals hlsSet' hlses sSet stacks+ where+  go lt cSet cabals hlsSet' hlses sSet stacks = do+    case lt of+      Just t -> do+        GHCupInfo { _ghcupDownloads = dls } <- getGHCupInfo+        -- get versions from GHCupDownloads+        let avTools = availableToolVersions dls t+        lr <- filter' <$> forM (Map.toList avTools) (toListResult t cSet cabals hlsSet' hlses sSet stacks)++        case t of+          GHC -> do+            slr <- strayGHCs avTools+            pure (sort (slr ++ lr))+          Cabal -> do+            slr <- strayCabals avTools cSet cabals+            pure (sort (slr ++ lr))+          HLS -> do+            slr <- strayHLS avTools hlsSet' hlses+            pure (sort (slr ++ lr))+          Stack -> do+            slr <- strayStacks avTools sSet stacks+            pure (sort (slr ++ lr))+          GHCup -> do+            let cg = maybeToList $ currentGHCup avTools+            pure (sort (cg ++ lr))+      Nothing -> do+        ghcvers   <- go (Just GHC) cSet cabals hlsSet' hlses sSet stacks+        cabalvers <- go (Just Cabal) cSet cabals hlsSet' hlses sSet stacks+        hlsvers   <- go (Just HLS) cSet cabals hlsSet' hlses sSet stacks+        ghcupvers <- go (Just GHCup) cSet cabals hlsSet' hlses sSet stacks+        stackvers <- go (Just Stack) cSet cabals hlsSet' hlses sSet stacks+        pure (ghcvers <> cabalvers <> hlsvers <> stackvers <> ghcupvers)+  strayGHCs :: ( MonadCatch m+               , MonadReader env m+               , HasDirs env+               , MonadThrow m+               , HasLog env+               , MonadIO m+               )+            => Map.Map Version VersionInfo+            -> m [ListResult]+  strayGHCs avTools = do+    ghcs <- getInstalledGHCs+    fmap catMaybes $ forM ghcs $ \case+      Right tver@GHCTargetVersion{ _tvTarget = Nothing, .. } -> do+        case Map.lookup _tvVersion avTools of+          Just _  -> pure Nothing+          Nothing -> do+            lSet    <- fmap (maybe False (\(GHCTargetVersion _ v ) -> v == _tvVersion)) $ ghcSet Nothing+            fromSrc <- ghcSrcInstalled tver+            hlsPowered <- fmap (elem _tvVersion) hlsGHCVersions+            pure $ Just $ ListResult+              { lTool      = GHC+              , lVer       = _tvVersion+              , lCross     = Nothing+              , lTag       = []+              , lInstalled = True+              , lStray     = isNothing (Map.lookup _tvVersion avTools)+              , lNoBindist = False+              , ..+              }+      Right tver@GHCTargetVersion{ .. } -> do+        lSet    <- fmap (maybe False (\(GHCTargetVersion _ v ) -> v == _tvVersion)) $ ghcSet _tvTarget+        fromSrc <- ghcSrcInstalled tver+        hlsPowered <- fmap (elem _tvVersion) hlsGHCVersions+        pure $ Just $ ListResult+          { lTool      = GHC+          , lVer       = _tvVersion+          , lCross     = _tvTarget+          , lTag       = []+          , lInstalled = True+          , lStray     = True -- NOTE: cross currently cannot be installed via bindist+          , lNoBindist = False+          , ..+          }+      Left e -> do+        logWarn+          $ "Could not parse version of stray directory" <> T.pack e+        pure Nothing++  strayCabals :: ( MonadReader env m+                 , HasDirs env+                 , MonadCatch m+                 , MonadThrow m+                 , HasLog env+                 , MonadIO m+                 )+            => Map.Map Version VersionInfo+            -> Maybe Version+            -> [Either FilePath Version]+            -> m [ListResult]+  strayCabals avTools cSet cabals = do+    fmap catMaybes $ forM cabals $ \case+      Right ver ->+        case Map.lookup ver avTools of+          Just _  -> pure Nothing+          Nothing -> do+            let lSet = cSet == Just ver+            pure $ Just $ ListResult+              { lTool      = Cabal+              , lVer       = ver+              , lCross     = Nothing+              , lTag       = []+              , lInstalled = True+              , lStray     = isNothing (Map.lookup ver avTools)+              , lNoBindist = False+              , fromSrc    = False -- actually, we don't know :>+              , hlsPowered = False+              , ..+              }+      Left e -> do+        logWarn+          $ "Could not parse version of stray directory" <> T.pack e+        pure Nothing++  strayHLS :: ( MonadReader env m+              , HasDirs env+              , MonadCatch m+              , MonadThrow m+              , HasLog env+              , MonadIO m)+           => Map.Map Version VersionInfo+           -> Maybe Version+           -> [Either FilePath Version]+           -> m [ListResult]+  strayHLS avTools hlsSet' hlss = do+    fmap catMaybes $ forM hlss $ \case+      Right ver ->+        case Map.lookup ver avTools of+          Just _  -> pure Nothing+          Nothing -> do+            let lSet = hlsSet' == Just ver+            pure $ Just $ ListResult+              { lTool      = HLS+              , lVer       = ver+              , lCross     = Nothing+              , lTag       = []+              , lInstalled = True+              , lStray     = isNothing (Map.lookup ver avTools)+              , lNoBindist = False+              , fromSrc    = False -- actually, we don't know :>+              , hlsPowered = False+              , ..+              }+      Left e -> do+        logWarn+          $ "Could not parse version of stray directory" <> T.pack e+        pure Nothing++  strayStacks :: ( MonadReader env m+                 , HasDirs env+                 , MonadCatch m+                 , MonadThrow m+                 , HasLog env+                 , MonadIO m+                 )+              => Map.Map Version VersionInfo+              -> Maybe Version+              -> [Either FilePath Version]+              -> m [ListResult]+  strayStacks avTools stackSet' stacks = do+    fmap catMaybes $ forM stacks $ \case+      Right ver ->+        case Map.lookup ver avTools of+          Just _  -> pure Nothing+          Nothing -> do+            let lSet = stackSet' == Just ver+            pure $ Just $ ListResult+              { lTool      = Stack+              , lVer       = ver+              , lCross     = Nothing+              , lTag       = []+              , lInstalled = True+              , lStray     = isNothing (Map.lookup ver avTools)+              , lNoBindist = False+              , fromSrc    = False -- actually, we don't know :>+              , hlsPowered = False+              , ..+              }+      Left e -> do+        logWarn+          $ "Could not parse version of stray directory" <> T.pack e+        pure Nothing++  currentGHCup :: Map.Map Version VersionInfo -> Maybe ListResult+  currentGHCup av =+    let currentVer = fromJust $ pvpToVersion ghcUpVer+        listVer    = Map.lookup currentVer av+        latestVer  = fst <$> headOf (getTagged Latest) av+        recommendedVer = fst <$> headOf (getTagged Latest) av+        isOld  = maybe True (> currentVer) latestVer && maybe True (> currentVer) recommendedVer+    in if | Map.member currentVer av -> Nothing+          | otherwise -> Just $ ListResult { lVer    = currentVer+                                           , lTag    = maybe (if isOld then [Old] else []) _viTags listVer+                                           , lCross  = Nothing+                                           , lTool   = GHCup+                                           , fromSrc = False+                                           , lStray  = isNothing listVer+                                           , lSet    = True+                                           , lInstalled = True+                                           , lNoBindist = False+                                           , hlsPowered = False+                                           }++  -- NOTE: this are not cross ones, because no bindists+  toListResult :: ( HasLog env+                  , MonadReader env m+                  , HasDirs env+                  , HasGHCupInfo env+                  , HasPlatformReq env+                  , MonadIO m+                  , MonadCatch m+                  )+               => Tool+               -> Maybe Version+               -> [Either FilePath Version]+               -> Maybe Version+               -> [Either FilePath Version]+               -> Maybe Version+               -> [Either FilePath Version]+               -> (Version, VersionInfo)+               -> m ListResult+  toListResult t cSet cabals hlsSet' hlses stackSet' stacks (v, _viTags -> tags) = do+    case t of+      GHC -> do+        lNoBindist <- fmap (isLeft . veitherToEither) $ runE @'[NoDownload] $ getDownloadInfo GHC v+        let tver = mkTVer v+        lSet       <- fmap (maybe False (\(GHCTargetVersion _ v') -> v' == v)) $ ghcSet Nothing+        lInstalled <- ghcInstalled tver+        fromSrc    <- ghcSrcInstalled tver+        hlsPowered <- fmap (elem v) hlsGHCVersions+        pure ListResult { lVer = v, lCross = Nothing , lTag = tags, lTool = t, lStray = False, .. }+      Cabal -> do+        lNoBindist <- fmap (isLeft . veitherToEither) $ runE @'[NoDownload] $ getDownloadInfo Cabal v+        let lSet = cSet == Just v+        let lInstalled = elem v $ rights cabals+        pure ListResult { lVer    = v+                        , lCross  = Nothing+                        , lTag    = tags+                        , lTool   = t+                        , fromSrc = False+                        , lStray  = False+                        , hlsPowered = False+                        , ..+                        }+      GHCup -> do+        let lSet       = prettyPVP ghcUpVer == prettyVer v+        let lInstalled = lSet+        pure ListResult { lVer    = v+                        , lTag    = tags+                        , lCross  = Nothing+                        , lTool   = t+                        , fromSrc = False+                        , lStray  = False+                        , lNoBindist = False+                        , hlsPowered = False+                        , ..+                        }+      HLS -> do+        lNoBindist <- fmap (isLeft . veitherToEither) $ runE @'[NoDownload] $ getDownloadInfo HLS v+        let lSet = hlsSet' == Just v+        let lInstalled = elem v $ rights hlses+        pure ListResult { lVer    = v+                        , lCross  = Nothing+                        , lTag    = tags+                        , lTool   = t+                        , fromSrc = False+                        , lStray  = False+                        , hlsPowered = False+                        , ..+                        }+      Stack -> do+        lNoBindist <- fmap (isLeft . veitherToEither) $ runE @'[NoDownload] $ getDownloadInfo Stack v+        let lSet = stackSet' == Just v+        let lInstalled = elem v $ rights stacks+        pure ListResult { lVer    = v+                        , lCross  = Nothing+                        , lTag    = tags+                        , lTool   = t+                        , fromSrc = False+                        , lStray  = False+                        , hlsPowered = False+                        , ..+                        }+++  filter' :: [ListResult] -> [ListResult]+  filter' lr = case criteria of+    Nothing            -> lr+    Just ListInstalled -> filter (\ListResult {..} -> lInstalled) lr+    Just ListSet       -> filter (\ListResult {..} -> lSet) lr+    Just ListAvailable -> filter (\ListResult {..} -> not lNoBindist) lr++++    --------------------+    --[ GHC/cabal rm ]--+    --------------------+++-- | Delete a ghc version and all its symlinks.+--+-- This may leave GHCup without a "set" version.+-- Will try to fix the ghc-x.y symlink after removal (e.g. to an+-- older version).+rmGHCVer :: ( MonadReader env m+            , HasDirs env+            , MonadThrow m+            , HasLog env+            , MonadIO m+            , MonadFail m+            , MonadCatch m+            , MonadMask m+            , MonadUnliftIO m+            )+         => GHCTargetVersion+         -> Excepts '[NotInstalled] m ()+rmGHCVer ver = do+  isSetGHC <- lift $ fmap (== Just ver) $ ghcSet (_tvTarget ver)++  whenM (lift $ fmap not $ ghcInstalled ver) (throwE (NotInstalled GHC ver))+  dir <- lift $ ghcupGHCDir ver++  -- this isn't atomic, order matters+  when isSetGHC $ do+    lift $ logInfo "Removing ghc symlinks"+    liftE $ rmPlain (_tvTarget ver)++  lift $ logInfo "Removing ghc-x.y.z symlinks"+  liftE $ rmMinorSymlinks ver++  lift $ logInfo "Removing/rewiring ghc-x.y symlinks"+  -- first remove+  handle (\(_ :: ParseError) -> pure ()) $ liftE $ rmMajorSymlinks ver+  -- then fix them (e.g. with an earlier version)++  lift $ logInfo $ "Removing directory recursively: " <> T.pack dir+  lift $ recyclePathForcibly dir++  v' <-+    handle+      (\(e :: ParseError) -> lift $ logWarn (T.pack $ displayException e) >> pure Nothing)+    $ fmap Just+    $ getMajorMinorV (_tvVersion ver)+  forM_ v' $ \(mj, mi) -> lift (getGHCForPVP (PVP (fromIntegral mj :| [fromIntegral mi])) (_tvTarget ver))+    >>= mapM_ (\v -> liftE $ setGHC v SetGHC_XY)++  Dirs {..} <- lift getDirs++  lift $ hideError doesNotExistErrorType $ rmDirectoryLink (baseDir </> "share")+++-- | Delete a cabal version. Will try to fix the @cabal@ symlink+-- after removal (e.g. setting it to an older version).+rmCabalVer :: ( MonadMask m+              , MonadReader env m+              , HasDirs env+              , MonadThrow m+              , HasLog env+              , MonadIO m+              , MonadFail m+              , MonadCatch m+              , MonadUnliftIO m+              )+           => Version+           -> Excepts '[NotInstalled] m ()+rmCabalVer ver = do+  whenM (lift $ fmap not $ cabalInstalled ver) $ throwE (NotInstalled Cabal (GHCTargetVersion Nothing ver))++  cSet      <- lift cabalSet++  Dirs {..} <- lift getDirs++  let cabalFile = "cabal-" <> T.unpack (prettyVer ver) <> exeExt+  lift $ hideError doesNotExistErrorType $ recycleFile (binDir </> cabalFile)++  when (Just ver == cSet) $ do+    cVers <- lift $ fmap rights getInstalledCabals+    case headMay . reverse . sort $ cVers of+      Just latestver -> setCabal latestver+      Nothing        -> lift $ rmLink (binDir </> "cabal" <> exeExt)+++-- | Delete a hls version. Will try to fix the hls symlinks+-- after removal (e.g. setting it to an older version).+rmHLSVer :: ( MonadMask m+            , MonadReader env m+            , HasDirs env+            , MonadThrow m+            , HasLog env+            , MonadIO m+            , MonadFail m+            , MonadCatch m+            , MonadUnliftIO m+            )+         => Version+         -> Excepts '[NotInstalled] m ()+rmHLSVer ver = do+  whenM (lift $ fmap not $ hlsInstalled ver) $ throwE (NotInstalled HLS (GHCTargetVersion Nothing ver))++  isHlsSet      <- lift hlsSet++  Dirs {..} <- lift getDirs++  bins <- lift $ hlsAllBinaries ver+  forM_ bins $ \f -> lift $ recycleFile (binDir </> f)++  when (Just ver == isHlsSet) $ do+    -- delete all set symlinks+    oldSyms <- lift hlsSymlinks+    forM_ oldSyms $ \f -> do+      let fullF = binDir </> f+      lift $ logDebug $ "rm " <> T.pack fullF+      lift $ rmLink fullF+    -- set latest hls+    hlsVers <- lift $ fmap rights getInstalledHLSs+    case headMay . reverse . sort $ hlsVers of+      Just latestver -> setHLS latestver+      Nothing        -> pure ()+++-- | Delete a stack version. Will try to fix the @stack@ symlink+-- after removal (e.g. setting it to an older version).+rmStackVer :: ( MonadMask m+              , MonadReader env m+              , HasDirs env+              , MonadThrow m+              , HasLog env+              , MonadIO m+              , MonadFail m+              , MonadCatch m+              , MonadUnliftIO m+              )+           => Version+           -> Excepts '[NotInstalled] m ()+rmStackVer ver = do+  whenM (lift $ fmap not $ stackInstalled ver) $ throwE (NotInstalled Stack (GHCTargetVersion Nothing ver))++  sSet      <- lift stackSet++  Dirs {..} <- lift getDirs++  let stackFile = "stack-" <> T.unpack (prettyVer ver) <> exeExt+  lift $ hideError doesNotExistErrorType $ recycleFile (binDir </> stackFile)++  when (Just ver == sSet) $ do+    sVers <- lift $ fmap rights getInstalledStacks+    case headMay . reverse . sort $ sVers of+      Just latestver -> setStack latestver+      Nothing        -> lift $ rmLink (binDir </> "stack" <> exeExt)+++-- assuming the current scheme of having just 1 ghcup bin, no version info is required.+rmGhcup :: ( MonadReader env m+           , HasDirs env+           , MonadIO m+           , MonadCatch m+           , HasLog env+           , MonadMask m+           , MonadUnliftIO m+           )+        => m ()+rmGhcup = do+  Dirs { .. } <- getDirs+  let ghcupFilename = "ghcup" <> exeExt+  let ghcupFilepath = binDir </> ghcupFilename++  currentRunningExecPath <- liftIO getExecutablePath++  -- if paths do no exist, warn user, and continue to compare them, as is,+  -- which should eventually fail and result in a non-standard install warning++  p1 <- handleIO' doesNotExistErrorType+                  (handlePathNotPresent currentRunningExecPath)+                  (liftIO $ canonicalizePath currentRunningExecPath)++  p2 <- handleIO' doesNotExistErrorType+                  (handlePathNotPresent ghcupFilepath)+                  (liftIO $ canonicalizePath ghcupFilepath)++  let areEqualPaths = equalFilePath p1 p2++  unless areEqualPaths $ logWarn $ nonStandardInstallLocationMsg currentRunningExecPath++#if defined(IS_WINDOWS)+  -- since it doesn't seem possible to delete a running exe on windows+  -- we move it to temp dir, to be deleted at next reboot+  tempFilepath <- mkGhcupTmpDir+  hideError UnsupportedOperation $+            liftIO $ hideError NoSuchThing $+            Win32.moveFileEx ghcupFilepath (Just (tempFilepath </> "ghcup")) 0+#else+  -- delete it.+  hideError doesNotExistErrorType $ rmFile ghcupFilepath+#endif++  where+    handlePathNotPresent fp _err = do+      logDebug $ "Error: The path does not exist, " <> T.pack fp+      pure fp++    nonStandardInstallLocationMsg path = T.pack $+      "current ghcup is invoked from a non-standard location: \n"+      <> path <>+      "\n you may have to uninstall it manually."++rmTool :: ( MonadReader env m+          , HasDirs env+          , HasLog env+          , MonadFail m+          , MonadMask m+          , MonadUnliftIO m)+          => ListResult+          -> Excepts '[NotInstalled ] m ()+rmTool ListResult {lVer, lTool, lCross} = do+  case lTool of+    GHC ->+      let ghcTargetVersion = GHCTargetVersion lCross lVer+      in rmGHCVer ghcTargetVersion+    HLS -> rmHLSVer lVer+    Cabal -> rmCabalVer lVer+    Stack -> rmStackVer lVer+    GHCup -> lift rmGhcup+++rmGhcupDirs :: ( MonadReader env m+               , HasDirs env+               , MonadIO m+               , HasLog env+               , MonadCatch m+               , MonadMask m )+            => m [FilePath]+rmGhcupDirs = do+  Dirs+    { baseDir+    , binDir+    , logsDir+    , cacheDir+    , recycleDir+    } <- getDirs++  let envFilePath = baseDir </> "env"++  confFilePath <- getConfigFilePath++  handleRm $ rmEnvFile  envFilePath+  handleRm $ rmConfFile confFilePath+  +  -- for xdg dirs, the order matters here+  handleRm $ rmDir logsDir+  handleRm $ rmDir cacheDir++  handleRm $ rmBinDir binDir+  handleRm $ rmDir recycleDir+#if defined(IS_WINDOWS)+  logInfo $ "removing " <> T.pack (baseDir </> "msys64")+  handleRm $ rmPathForcibly (baseDir </> "msys64")+#endif++  handleRm $ removeEmptyDirsRecursive baseDir++  -- report files in baseDir that are left-over after+  -- the standard location deletions above+  hideErrorDef [doesNotExistErrorType] [] $ reportRemainingFiles baseDir++  where+    handleRm :: (MonadReader env m, MonadCatch m, HasLog env, MonadIO m)  => m () -> m ()+    handleRm = handleIO (\e -> logDebug $ "Part of the cleanup action failed with error: " <> T.pack (displayException e) <> "\n"+                                <> "continuing regardless...")++    rmEnvFile :: (HasLog env, MonadReader env m, HasDirs env, MonadMask m, MonadIO m, MonadCatch m) => FilePath -> m ()+    rmEnvFile enFilePath = do+      logInfo "Removing Ghcup Environment File"+      hideErrorDef [permissionErrorType] () $ deleteFile enFilePath++    rmConfFile :: (HasLog env, MonadReader env m, HasDirs env, MonadMask m, MonadIO m, MonadCatch m) => FilePath -> m ()+    rmConfFile confFilePath = do+      logInfo "removing Ghcup Config File"+      hideErrorDef [permissionErrorType] () $ deleteFile confFilePath++    rmDir :: (HasLog env, MonadReader env m, HasDirs env, MonadMask m, MonadIO m, MonadCatch m) => FilePath -> m ()+    rmDir dir =+      -- 'getDirectoryContentsRecursive' is lazy IO. In case+      -- an error leaks through, we catch it here as well,+      -- althought 'deleteFile' should already handle it.+      hideErrorDef [doesNotExistErrorType] () $ do+        logInfo $ "removing " <> T.pack dir+        contents <- liftIO $ getDirectoryContentsRecursive dir+        forM_ contents (deleteFile . (dir </>))++    rmBinDir :: (MonadReader env m, HasDirs env, MonadMask m, MonadIO m, MonadCatch m) => FilePath -> m ()+    rmBinDir binDir = do+#if !defined(IS_WINDOWS)+      isXDGStyle <- liftIO useXDG+      if not isXDGStyle+        then removeDirIfEmptyOrIsSymlink binDir+        else pure ()+#else+      removeDirIfEmptyOrIsSymlink binDir+#endif++    reportRemainingFiles :: MonadIO m => FilePath -> m [FilePath]+    reportRemainingFiles dir = do+      -- force the files so the errors don't leak+      (force -> !remainingFiles) <- liftIO+        (getDirectoryContentsRecursive dir >>= evaluate)+      let normalizedFilePaths = fmap normalise remainingFiles+      let sortedByDepthRemainingFiles = sortBy (flip compareFn) normalizedFilePaths+      let remainingFilesAbsolute = fmap (dir </>) sortedByDepthRemainingFiles++      pure remainingFilesAbsolute++      where+        calcDepth :: FilePath -> Int+        calcDepth = length . filter isPathSeparator++        compareFn :: FilePath -> FilePath -> Ordering+        compareFn fp1 fp2 = compare (calcDepth fp1) (calcDepth fp2)++    removeEmptyDirsRecursive :: (MonadReader env m, HasDirs env, MonadMask m, MonadIO m, MonadCatch m) => FilePath -> m ()+    removeEmptyDirsRecursive fp = do+      cs <- liftIO $ listDirectory fp >>= filterM doesDirectoryExist . fmap (fp </>)+      forM_ cs removeEmptyDirsRecursive+      hideError InappropriateType $ removeDirIfEmptyOrIsSymlink fp+        ++    -- we expect only files inside cache/log dir+    -- we report remaining files/dirs later,+    -- hence the force/quiet mode in these delete functions below.++    deleteFile :: (MonadReader env m, HasDirs env, MonadMask m, MonadIO m) => FilePath -> m ()+    deleteFile filepath = do+      hideError doesNotExistErrorType+        $ hideError InappropriateType $ rmFile filepath++    removeDirIfEmptyOrIsSymlink :: (MonadReader env m, HasDirs env, MonadMask m, MonadIO m, MonadCatch m) => FilePath -> m ()+    removeDirIfEmptyOrIsSymlink filepath =+      hideError UnsatisfiedConstraints $+      handleIO' InappropriateType+            (handleIfSym filepath)+            (liftIO $ rmDirectory filepath)+      where+        handleIfSym fp e = do+          isSym <- liftIO $ pathIsSymbolicLink fp+          if isSym+          then deleteFile fp+          else liftIO $ ioError e++++    ------------------+    --[ Debug info ]--+    ------------------+++getDebugInfo :: ( Alternative m+                , MonadFail m+                , MonadReader env m+                , HasDirs env+                , HasLog env+                , MonadCatch m+                , MonadIO m+                )+             => Excepts+                  '[NoCompatiblePlatform , NoCompatibleArch , DistroNotFound]+                  m+                  DebugInfo+getDebugInfo = do+  Dirs {..} <- lift getDirs+  let diBaseDir  = baseDir+  let diBinDir   = binDir+  diGHCDir       <- lift ghcupGHCBaseDir+  let diCacheDir = cacheDir+  diArch         <- lE getArchitecture+  diPlatform     <- liftE getPlatform+  pure $ DebugInfo { .. }+++++    ---------------+    --[ Compile ]--+    ---------------+++-- | Compile a GHC from source. This behaves wrt symlinks and installation+-- the same as 'installGHCBin'.+compileGHC :: ( MonadMask m+              , MonadReader env m+              , HasDirs env+              , HasPlatformReq env+              , HasGHCupInfo env+              , HasSettings env+              , MonadThrow m+              , MonadResource m+              , HasLog env+              , MonadIO m+              , MonadUnliftIO m+              , MonadFail m+              )+           => Either GHCTargetVersion GitBranch          -- ^ version to install+           -> Maybe Version            -- ^ overwrite version+           -> Either Version FilePath  -- ^ version to bootstrap with+           -> Maybe Int                -- ^ jobs+           -> Maybe FilePath           -- ^ build config+           -> Maybe FilePath           -- ^ patch directory+           -> [Text]                   -- ^ additional args to ./configure+           -> Maybe String             -- ^ build flavour+           -> Bool+           -> Maybe FilePath           -- ^ isolate dir+           -> Excepts+                '[ AlreadyInstalled+                 , BuildFailed+                 , DigestError+                 , GPGError+                 , DownloadFailed+                 , GHCupSetError+                 , NoDownload+                 , NotFoundInPATH+                 , PatchFailed+                 , UnknownArchive+                 , TarDirDoesNotExist+                 , NotInstalled+                 , DirNotEmpty+                 , ArchiveResult+                 ]+                m+                GHCTargetVersion+compileGHC targetGhc ov bstrap jobs mbuildConfig patchdir aargs buildFlavour hadrian isolateDir+  = do+    PlatformRequest { .. } <- lift getPlatformReq+    GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo++    bghc <- case bstrap of+      Right g    -> pure $ Right g+      Left  bver -> pure $ Left ("ghc-" <> (T.unpack . prettyVer $ bver) <> exeExt)++    (workdir, tmpUnpack, tver) <- case targetGhc of+      -- unpack from version tarball+      Left tver -> do+        lift $ logDebug $ "Requested to compile: " <> tVerToText tver <> " with " <> either prettyVer T.pack bstrap++        -- download source tarball+        dlInfo <-+          preview (ix GHC % ix (tver ^. tvVersion) % viSourceDL % _Just) dls+            ?? NoDownload+        dl <- liftE $ downloadCached dlInfo Nothing++        -- unpack+        tmpUnpack <- lift mkGhcupTmpDir+        liftE $ unpackToDir tmpUnpack dl+        liftE $ catchWarn $ lEM @_ @'[ProcessError] $ darwinNotarization _rPlatform tmpUnpack++        workdir <- maybe (pure tmpUnpack)+                         (liftE . intoSubdir tmpUnpack)+                         (view dlSubdir dlInfo)+        forM_ patchdir (\dir -> liftE $ applyPatches dir workdir)++        pure (workdir, tmpUnpack, tver)++      -- clone from git+      Right GitBranch{..} -> do+        tmpUnpack <- lift mkGhcupTmpDir+        let git args = execLogged "git" ("--no-pager":args) (Just tmpUnpack) "git" Nothing+        tver <- reThrowAll @_ @'[PatchFailed, ProcessError, NotFoundInPATH] DownloadFailed $ do+          let rep = fromMaybe "https://gitlab.haskell.org/ghc/ghc.git" repo+          lift $ logInfo $ "Fetching git repo " <> T.pack rep <> " at ref " <> T.pack ref <> " (this may take a while)"+          lEM $ git [ "init" ]+          lEM $ git [ "remote"+                    , "add"+                    , "origin"+                    , fromString rep ]++          let fetch_args = +                    [ "fetch"+                    , "--depth"+                    , "1"+                    , "--quiet"+                    , "origin"+                    , fromString ref ]+          lEM $ git fetch_args++          lEM $ git [ "checkout", "FETCH_HEAD" ]+          lEM $ git [ "submodule", "update", "--init", "--depth", "1" ]+          forM_ patchdir (\dir -> liftE $ applyPatches dir tmpUnpack)+          env <- liftE $ ghcEnv bghc+          lEM $ execLogged "python3" ["./boot"] (Just tmpUnpack) "ghc-bootstrap" (Just env)+          lEM $ execLogged "sh" ["./configure"] (Just tmpUnpack) "ghc-bootstrap" (Just env)+          CapturedProcess {..} <- lift $ makeOut+            ["show!", "--quiet", "VALUE=ProjectVersion" ] (Just tmpUnpack)+          case _exitCode of+            ExitSuccess -> throwEither . MP.parse ghcProjectVersion "" . decUTF8Safe' $ _stdOut+            ExitFailure c -> fail ("Could not figure out GHC project version. Exit code was: " <> show c <> ". Error was: " <> T.unpack (decUTF8Safe' _stdErr))++        liftE $ catchWarn $ lEM @_ @'[ProcessError] $ darwinNotarization _rPlatform tmpUnpack+        lift $ logInfo $ "Git version " <> T.pack ref <> " corresponds to GHC version " <> prettyVer tver++        pure (tmpUnpack, tmpUnpack, GHCTargetVersion Nothing tver)+    -- the version that's installed may differ from the+    -- compiled version, so the user can overwrite it+    let installVer = maybe tver (\ov' -> tver { _tvVersion = ov' }) ov++    alreadyInstalled <- lift $ ghcInstalled installVer+    alreadySet <- fmap (== Just installVer) $ lift $ ghcSet (_tvTarget installVer)++    when alreadyInstalled $ do+      case isolateDir of+        Just isoDir ->+          lift $ logWarn $ "GHC " <> T.pack (prettyShow installVer) <> " already installed. Isolate installing to " <> T.pack isoDir+        Nothing ->+          lift $ logWarn $ "GHC " <> T.pack (prettyShow installVer) <> " already installed. Will overwrite existing version."+      lift $ logWarn+        "...waiting for 10 seconds before continuing, you can still abort..."+      liftIO $ threadDelay 10000000 -- give the user a sec to intervene++    ghcdir <- case isolateDir of+      Just isoDir -> pure isoDir+      Nothing -> lift $ ghcupGHCDir installVer++    (mBindist, bmk) <- liftE $ runBuildAction+      tmpUnpack+      Nothing+      (do+        b <- if hadrian+             then compileHadrianBindist bghc tver workdir ghcdir+             else compileMakeBindist bghc tver workdir ghcdir+        bmk <- liftIO $ handleIO (\_ -> pure "") $ B.readFile (build_mk workdir)+        pure (b, bmk)+      )++    case isolateDir of+      Nothing ->+        -- only remove old ghc in regular installs+        when alreadyInstalled $ do+          lift $ logInfo "Deleting existing installation"+          liftE $ rmGHCVer installVer+          +      _ -> pure ()++    forM_ mBindist $ \bindist -> do+      liftE $ installPackedGHC bindist+                               (Just $ RegexDir "ghc-.*")+                               ghcdir+                               (installVer ^. tvVersion)+                               False       -- not a force install, since we already overwrite when compiling.++    liftIO $ B.writeFile (ghcdir </> ghcUpSrcBuiltFile) bmk+    +    case isolateDir of+      -- set and make symlinks for regular (non-isolated) installs+      Nothing -> do+        reThrowAll GHCupSetError $ postGHCInstall installVer+        -- restore+        when alreadySet $ liftE $ void $ setGHC installVer SetGHCOnly+        +      _ -> pure ()++    pure installVer++ where+  defaultConf = +    let cross_mk = $(LitE . StringL <$> (qAddDependentFile "data/build_mk/cross" >> runIO (readFile "data/build_mk/cross")))+        default_mk = $(LitE . StringL <$> (qAddDependentFile "data/build_mk/default" >> runIO (readFile "data/build_mk/default")))+    in case targetGhc of+         Left (GHCTargetVersion (Just _) _) -> cross_mk+         _ -> default_mk++  compileHadrianBindist :: ( MonadReader env m+                           , HasDirs env+                           , HasSettings env+                           , HasPlatformReq env+                           , MonadThrow m+                           , MonadCatch m+                           , HasLog env+                           , MonadIO m+                           , MonadFail m+                           )+                        => Either FilePath FilePath+                        -> GHCTargetVersion+                        -> FilePath+                        -> FilePath+                        -> Excepts+                             '[ FileDoesNotExistError+                              , HadrianNotFound+                              , InvalidBuildConfig+                              , PatchFailed+                              , ProcessError+                              , NotFoundInPATH+                              , CopyError]+                             m+                             (Maybe FilePath)  -- ^ output path of bindist, None for cross+  compileHadrianBindist bghc tver workdir ghcdir = do+    lEM $ execLogged "python3" ["./boot"] (Just workdir) "ghc-bootstrap" Nothing++    liftE $ configureBindist bghc tver workdir ghcdir++    lift $ logInfo "Building (this may take a while)..."+    hadrian_build <- liftE $ findHadrianFile workdir+    lEM $ execLogged hadrian_build+                          ( maybe [] (\j  -> ["-j" <> show j]         ) jobs+                         ++ maybe [] (\bf -> ["--flavour=" <> bf]) buildFlavour+                         ++ ["binary-dist"]+                          )+                          (Just workdir) "ghc-make" Nothing+    [tar] <- liftIO $ findFiles+      (workdir </> "_build" </> "bindist")+      (makeRegexOpts compExtended+                     execBlank+                     ([s|^ghc-.*\.tar\..*$|] :: ByteString)+      )+    liftE $ fmap Just $ copyBindist tver tar (workdir </> "_build" </> "bindist")++  findHadrianFile :: (MonadIO m)+                  => FilePath+                  -> Excepts+                       '[HadrianNotFound]+                       m+                       FilePath+  findHadrianFile workdir = do+#if defined(IS_WINDOWS)+    let possible_files = ((workdir </> "hadrian") </>) <$> ["build.bat"]+#else   +    let possible_files = ((workdir </> "hadrian") </>) <$> ["build", "build.sh"]+#endif+    exsists <- forM possible_files (\f -> liftIO (doesFileExist f) <&> (,f))+    case filter fst exsists of+      [] -> throwE HadrianNotFound+      ((_, x):_) -> pure x++  compileMakeBindist :: ( MonadReader env m+                        , HasDirs env+                        , HasSettings env+                        , HasPlatformReq env+                        , MonadThrow m+                        , MonadCatch m+                        , HasLog env+                        , MonadIO m+                        , MonadFail m+                        )+                     => Either FilePath FilePath+                     -> GHCTargetVersion+                     -> FilePath+                     -> FilePath+                     -> Excepts+                          '[ FileDoesNotExistError+                           , HadrianNotFound+                           , InvalidBuildConfig+                           , PatchFailed+                           , ProcessError+                           , NotFoundInPATH+                           , CopyError]+                          m+                       (Maybe FilePath)  -- ^ output path of bindist, None for cross+  compileMakeBindist bghc tver workdir ghcdir = do+    liftE $ configureBindist bghc tver workdir ghcdir++    case mbuildConfig of+      Just bc -> liftIOException+        doesNotExistErrorType+        (FileDoesNotExistError bc)+        (liftIO $ copyFile bc (build_mk workdir))+      Nothing ->+        liftIO $ T.writeFile (build_mk workdir) (addBuildFlavourToConf defaultConf)++    liftE $ checkBuildConfig (build_mk workdir)++    lift $ logInfo "Building (this may take a while)..."+    lEM $ make (maybe [] (\j -> ["-j" <> fS (show j)]) jobs) (Just workdir)++    if | isCross tver -> do+          lift $ logInfo "Installing cross toolchain..."+          lEM $ make ["install"] (Just workdir)+          pure Nothing+       | otherwise -> do+          lift $ logInfo "Creating bindist..."+          lEM $ make ["binary-dist"] (Just workdir)+          [tar] <- liftIO $ findFiles+            workdir+            (makeRegexOpts compExtended+                           execBlank+                           ([s|^ghc-.*\.tar\..*$|] :: ByteString)+            )+          liftE $ fmap Just $ copyBindist tver tar workdir++  build_mk workdir = workdir </> "mk" </> "build.mk"++  copyBindist :: ( MonadReader env m+                 , HasDirs env+                 , HasSettings env+                 , HasPlatformReq env+                 , MonadIO m+                 , MonadThrow m+                 , MonadCatch m+                 , HasLog env+                 )+              => GHCTargetVersion+              -> FilePath           -- ^ tar file+              -> FilePath           -- ^ workdir+              -> Excepts+                   '[CopyError]+                   m+                   FilePath+  copyBindist tver tar workdir = do+    Dirs {..} <- lift getDirs+    pfreq <- lift getPlatformReq+    c       <- liftIO $ BL.readFile (workdir </> tar)+    cDigest <-+      fmap (T.take 8)+      . lift+      . throwEither+      . E.decodeUtf8'+      . B16.encode+      . SHA256.hashlazy+      $ c+    cTime <- liftIO getCurrentTime+    let tarName = makeValid ("ghc-"+                            <> T.unpack (tVerToText tver)+                            <> "-"+                            <> pfReqToString pfreq+                            <> "-"+                            <> iso8601Show cTime+                            <> "-"+                            <> T.unpack cDigest+                            <> ".tar"+                            <> takeExtension tar)+    let tarPath = cacheDir </> tarName+    copyFileE (workdir </> tar)+                                                             tarPath+    lift $ logInfo $ "Copied bindist to " <> T.pack tarPath+    pure tarPath++  checkBuildConfig :: (MonadReader env m, MonadCatch m, MonadIO m, HasLog env)+                   => FilePath+                   -> Excepts+                        '[FileDoesNotExistError, InvalidBuildConfig]+                        m+                        ()+  checkBuildConfig bc = do+    c <- liftIOException+           doesNotExistErrorType+           (FileDoesNotExistError bc)+           (liftIO $ B.readFile bc)+    let lines' = fmap T.strip . T.lines $ decUTF8Safe c++   -- for cross, we need Stage1Only+    case targetGhc of+      Left (GHCTargetVersion (Just _) _) -> when ("Stage1Only = YES" `notElem` lines') $ throwE+        (InvalidBuildConfig+          [s|Cross compiling needs to be a Stage1 build, add "Stage1Only = YES" to your config!|]+        )+      _ -> pure ()++    forM_ buildFlavour $ \bf ->+      when (T.pack ("BuildFlavour = " <> bf) `notElem` lines') $ do+        lift $ logWarn $ "Customly specified build config overwrites --flavour=" <> T.pack bf <> " switch! Waiting 5 seconds..."+        liftIO $ threadDelay 5000000++  addBuildFlavourToConf bc = case buildFlavour of+    Just bf -> "BuildFlavour = " <> T.pack bf <> "\n" <> bc+    Nothing -> bc++  isCross :: GHCTargetVersion -> Bool+  isCross = isJust . _tvTarget+++  configureBindist :: ( MonadReader env m+                      , HasDirs env+                      , HasSettings env+                      , HasPlatformReq env+                      , MonadThrow m+                      , MonadCatch m+                      , HasLog env+                      , MonadIO m+                      , MonadFail m+                      )+                   => Either FilePath FilePath+                   -> GHCTargetVersion+                   -> FilePath+                   -> FilePath+                   -> Excepts+                        '[ FileDoesNotExistError+                         , InvalidBuildConfig+                         , PatchFailed+                         , ProcessError+                         , NotFoundInPATH+                         , CopyError+                         ]+                        m+                        ()+  configureBindist bghc tver workdir ghcdir = do+    lift $ logInfo [s|configuring build|]++    if | _tvVersion tver >= [vver|8.8.0|] -> do+          env <- liftE $ ghcEnv bghc+          lEM $ execLogged+            "sh"+            ("./configure" :  maybe mempty+                      (\x -> ["--target=" <> T.unpack x])+                      (_tvTarget tver)+            ++ ["--prefix=" <> ghcdir]+#if defined(IS_WINDOWS)+            ++ ["--enable-tarballs-autodownload"]+#endif+            ++ fmap T.unpack aargs+            )+            (Just workdir)+            "ghc-conf"+            (Just env)+       | otherwise -> do+        lEM $ execLogged+          "sh"+          (  [ "./configure", "--with-ghc=" <> either id id bghc+             ]+          ++ maybe mempty+                   (\x -> ["--target=" <> T.unpack x])+                   (_tvTarget tver)+          ++ ["--prefix=" <> ghcdir]+#if defined(IS_WINDOWS)+          ++ ["--enable-tarballs-autodownload"]+#endif+          ++ fmap T.unpack aargs+          )+          (Just workdir)+          "ghc-conf"+          Nothing+    pure ()++  ghcEnv :: MonadIO m => Either FilePath FilePath -> Excepts '[NotFoundInPATH] m [(String, String)]+  ghcEnv bghc = do+    cEnv <- liftIO getEnvironment+    bghcPath <- case bghc of+      Right ghc' -> pure ghc'+      Left  bver -> do+        spaths <- liftIO getSearchPath+        liftIO (searchPath spaths bver) !? NotFoundInPATH bver+    pure (("GHC", bghcPath) : cEnv)+++++++    ---------------------+    --[ Upgrade GHCup ]--+    ---------------------+++-- | Upgrade ghcup and place it in @~\/.ghcup\/bin\/ghcup@,+-- if no path is provided.+upgradeGHCup :: ( MonadMask m+                , MonadReader env m+                , HasDirs env+                , HasPlatformReq env+                , HasGHCupInfo env+                , HasSettings env+                , MonadCatch m+                , HasLog env+                , MonadThrow m+                , MonadFail m+                , MonadResource m+                , MonadIO m+                , MonadUnliftIO m+                )+             => Maybe FilePath    -- ^ full file destination to write ghcup into+             -> Bool              -- ^ whether to force update regardless+                                  --   of currently installed version+             -> Excepts+                  '[ CopyError+                   , DigestError+                   , GPGError+                   , GPGError+                   , DownloadFailed+                   , NoDownload+                   , NoUpdate+                   ]+                  m+                  Version+upgradeGHCup mtarget force' = do+  Dirs {..} <- lift getDirs+  GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo++  lift $ logInfo "Upgrading GHCup..."+  let latestVer = fromJust $ fst <$> getLatest dls GHCup+  (Just ghcupPVPVer) <- pure $ pvpToVersion ghcUpVer+  when (not force' && (latestVer <= ghcupPVPVer)) $ throwE NoUpdate+  dli   <- liftE $ getDownloadInfo GHCup latestVer+  tmp   <- lift withGHCupTmpDir+  let fn = "ghcup" <> exeExt+  p <- liftE $ download (_dlUri dli) Nothing (Just (_dlHash dli)) tmp (Just fn) False+  let destDir = takeDirectory destFile+      destFile = fromMaybe (binDir </> fn) mtarget+  lift $ logDebug $ "mkdir -p " <> T.pack destDir+  liftIO $ createDirRecursive' destDir+  lift $ logDebug $ "rm -f " <> T.pack destFile+  lift $ hideError NoSuchThing $ recycleFile destFile+  lift $ logDebug $ "cp " <> T.pack p <> " " <> T.pack destFile+  copyFileE p+                                                           destFile+  lift $ chmod_755 destFile++  liftIO (isInPath destFile) >>= \b -> unless b $+    lift $ logWarn $ T.pack (takeFileName destFile) <> " is not in PATH! You have to add it in order to use ghcup."+  liftIO (isShadowed destFile) >>= \case+    Nothing -> pure ()+    Just pa -> lift $ logWarn $ "ghcup is shadowed by "+      <> T.pack pa+      <> ". The upgrade will not be in effect, unless you remove "+      <> T.pack pa+      <> " or make sure "+      <> T.pack destDir+      <> " comes before "+      <> T.pack (takeFileName pa)+      <> " in PATH."++  pure latestVer++++    -------------+    --[ Other ]--+    -------------++++-- | Creates @ghc-x.y.z@ and @ghc-x.y@ symlinks. This is used for+-- both installing from source and bindist.+postGHCInstall :: ( MonadReader env m+                  , HasDirs env+                  , HasLog env+                  , MonadThrow m+                  , MonadFail m+                  , MonadIO m+                  , MonadCatch m+                  , MonadMask m+                  , MonadUnliftIO m+                  )+               => GHCTargetVersion+               -> Excepts '[NotInstalled] m ()+postGHCInstall ver@GHCTargetVersion {..} = do+  void $ liftE $ setGHC ver SetGHC_XYZ++  -- Create ghc-x.y symlinks. This may not be the current+  -- version, create it regardless.+  v' <-+    handle (\(e :: ParseError) -> lift $ logWarn (T.pack $ displayException e) >> pure Nothing)+    $ fmap Just+    $ getMajorMinorV _tvVersion+  forM_ v' $ \(mj, mi) -> lift (getGHCForPVP (PVP (fromIntegral mj :| [fromIntegral mi])) _tvTarget)+    >>= mapM_ (\v -> liftE $ setGHC v SetGHC_XY)+++-- | Reports the binary location of a given tool:+--+--   * for GHC, this reports: @~\/.ghcup\/ghc\/\<ver\>\/bin\/ghc@+--   * for cabal, this reports @~\/.ghcup\/bin\/cabal-\<ver\>@+--   * for hls, this reports @~\/.ghcup\/bin\/haskell-language-server-wrapper-\<ver\>@+--   * for stack, this reports @~\/.ghcup\/bin\/stack-\<ver\>@+--   * for ghcup, this reports the location of the currently running executable+whereIsTool :: ( MonadReader env m+               , HasDirs env+               , HasLog env+               , MonadThrow m+               , MonadFail m+               , MonadIO m+               , MonadCatch m+               , MonadMask m+               , MonadUnliftIO m+               )+            => Tool+            -> GHCTargetVersion+            -> Excepts '[NotInstalled] m FilePath+whereIsTool tool ver@GHCTargetVersion {..} = do+  dirs <- lift getDirs++  case tool of+    GHC -> do+      whenM (lift $ fmap not $ ghcInstalled ver)+        $ throwE (NotInstalled GHC ver)+      bdir <- lift $ ghcupGHCDir ver+      pure (bdir </> "bin" </> ghcBinaryName ver)+    Cabal -> do+      whenM (lift $ fmap not $ cabalInstalled _tvVersion)+        $ throwE (NotInstalled Cabal (GHCTargetVersion Nothing _tvVersion))+      pure (binDir dirs </> "cabal-" <> T.unpack (prettyVer _tvVersion) <> exeExt)+    HLS -> do+      whenM (lift $ fmap not $ hlsInstalled _tvVersion)+        $ throwE (NotInstalled HLS (GHCTargetVersion Nothing _tvVersion))+      pure (binDir dirs </> "haskell-language-server-wrapper-" <> T.unpack (prettyVer _tvVersion) <> exeExt)++    Stack -> do+      whenM (lift $ fmap not $ stackInstalled _tvVersion)+        $ throwE (NotInstalled Stack (GHCTargetVersion Nothing _tvVersion))+      pure (binDir dirs </> "stack-" <> T.unpack (prettyVer _tvVersion) <> exeExt)+    GHCup -> do+      currentRunningExecPath <- liftIO getExecutablePath+      liftIO $ canonicalizePath currentRunningExecPath++-- | Doesn't work for cross GHC.+checkIfToolInstalled :: ( MonadIO m+                        , MonadReader env m+                        , HasDirs env+                        , MonadCatch m) =>+                        Tool ->+                        Version ->+                        m Bool++checkIfToolInstalled tool ver =+  case tool of+    Cabal -> cabalInstalled ver+    HLS   -> hlsInstalled ver+    Stack -> stackInstalled ver+    GHC   -> ghcInstalled $ mkTVer ver+    _     -> pure False++throwIfFileAlreadyExists :: ( MonadIO m ) =>+                            FilePath ->+                            Excepts '[FileAlreadyExistsError] m ()++throwIfFileAlreadyExists fp = whenM (checkFileAlreadyExists fp)+                                (throwE $ FileAlreadyExistsError fp)++++    --------------------------+    --[ Garbage collection ]--+    --------------------------+++rmOldGHC :: ( MonadReader env m+            , HasGHCupInfo env+            , HasDirs env+            , HasLog env+            , MonadIO m+            , MonadFail m+            , MonadMask m+            , MonadUnliftIO m+            )+         => Excepts '[NotInstalled] m ()+rmOldGHC = do+  GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo+  let oldGHCs = mkTVer <$> toListOf (ix GHC % getTagged Old % to fst) dls+  ghcs <- lift $ fmap rights getInstalledGHCs+  forM_ ghcs $ \ghc -> when (ghc `elem` oldGHCs) $ rmGHCVer ghc++++rmProfilingLibs :: ( MonadReader env m+                   , HasDirs env+                   , HasLog env+                   , MonadIO m+                   , MonadFail m+                   , MonadMask m+                   , MonadUnliftIO m+                   )+                => m ()+rmProfilingLibs = do+  ghcs <- fmap rights getInstalledGHCs++  let regexes :: [ByteString]+      regexes = [[s|.*_p\.a$|], [s|.*\.p_hi$|]]++  forM_ regexes $ \regex ->+    forM_ ghcs $ \ghc -> do+      d <- ghcupGHCDir ghc+      matches <- liftIO $ handleIO (\_ -> pure []) $ findFilesDeep+        d+        (makeRegexOpts compExtended+                       execBlank+                       regex+        )+      forM_ matches $ \m -> do+        let p = 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 <- fmap rights getInstalledGHCs+  forM_ ghcs $ \ghc -> do+    d <- ghcupGHCDir ghc+    let p = d </> "share"+    logDebug $ "rm -rf " <> T.pack p+    rmPathForcibly p+++rmHLSNoGHC :: ( MonadReader env m+              , HasDirs env+              , HasLog env+              , MonadIO m+              , MonadMask m+              )+           => m ()+rmHLSNoGHC = do+  Dirs {..} <- getDirs+  ghcs <- fmap rights getInstalledGHCs+  hlses <- fmap rights getInstalledHLSs+  forM_ hlses $ \hls -> do+    hlsGHCs <- fmap mkTVer <$> hlsGHCVersions' hls+    forM_ hlsGHCs $ \ghc -> do +      when (ghc `notElem` ghcs) $ do+        bins <- hlsServerBinaries hls (Just $ _tvVersion ghc)+        forM_ bins $ \bin -> do+          let f = binDir </> bin+          logDebug $ "rm " <> T.pack f+          rmFile f+++rmCache :: ( MonadReader env m+           , HasDirs env+           , HasLog env+           , MonadIO m+           , MonadMask m+           )+        => m ()+rmCache = do+  Dirs {..} <- getDirs+  contents <- liftIO $ listDirectory cacheDir+  forM_ contents $ \f -> do+    let p = cacheDir </> f+    logDebug $ "rm " <> T.pack p+    rmFile p+++rmTmp :: ( MonadReader env m+         , HasDirs env+         , HasLog env+         , MonadIO m+         , MonadMask m+         )+      => m ()+rmTmp = do+  tmpdir <- liftIO getCanonicalTemporaryDirectory+  ghcup_dirs <- liftIO $ handleIO (\_ -> pure []) $ findFiles+    tmpdir+    (makeRegexOpts compExtended+                   execBlank+                   ([s|^ghcup-.*$|] :: ByteString)+    )+  forM_ ghcup_dirs $ \f -> do+    let p = tmpdir </> f+    logDebug $ "rm -rf " <> T.pack p+    rmPathForcibly p
lib/GHCup/Download.hs view
@@ -1,10 +1,7 @@ {-# LANGUAGE CPP                   #-} {-# LANGUAGE DataKinds             #-}-{-# LANGUAGE DeriveGeneric         #-} {-# LANGUAGE FlexibleContexts      #-} {-# LANGUAGE OverloadedStrings     #-}-{-# LANGUAGE QuasiQuotes           #-}-{-# LANGUAGE TemplateHaskell       #-} {-# LANGUAGE TypeApplications      #-} {-# LANGUAGE TypeFamilies          #-} @@ -16,7 +13,7 @@ License     : LGPL-3.0 Maintainer  : hasufell@hasufell.de Stability   : experimental-Portability : POSIX+Portability : portable  Module for handling all download related functions. @@ -34,10 +31,11 @@ #endif import           GHCup.Errors import           GHCup.Types-import           GHCup.Types.JSON               ( ) import           GHCup.Types.Optics-import           GHCup.Utils+import           GHCup.Types.JSON               ( )+import           GHCup.Utils.Dirs import           GHCup.Utils.File+import           GHCup.Utils.Logger import           GHCup.Utils.Prelude import           GHCup.Version @@ -47,7 +45,6 @@ #if !MIN_VERSION_base(4,13,0) import           Control.Monad.Fail             ( MonadFail ) #endif-import           Control.Monad.Logger import           Control.Monad.Reader import           Control.Monad.Trans.Resource                                          hiding ( throwM )@@ -55,45 +52,42 @@ import           Data.Bifunctor import           Data.ByteString                ( ByteString ) #if defined(INTERNAL_DOWNLOADER)-import           Data.CaseInsensitive           ( CI )+import           Data.CaseInsensitive           ( mk ) #endif-import           Data.List                      ( find ) import           Data.Maybe-import           Data.String.Interpolate+import           Data.List import           Data.Time.Clock import           Data.Time.Clock.POSIX-#if defined(INTERNAL_DOWNLOADER)-import           Data.Time.Format-#endif import           Data.Versions-import           Data.Word8-import           GHC.IO.Exception-import           HPath-import           HPath.IO                     as HIO hiding ( hideError )+import           Data.Word8              hiding ( isSpace ) import           Haskus.Utils.Variant.Excepts+#if defined(INTERNAL_DOWNLOADER)+import           Network.Http.Client     hiding ( URL )+#endif import           Optics import           Prelude                 hiding ( abs                                                 , readFile                                                 , writeFile                                                 )+import           Safe+import           System.Directory+import           System.Environment+import           System.Exit+import           System.FilePath import           System.IO.Error-import           System.Posix.Env.ByteString    ( getEnv )+import           System.IO.Temp+import           Text.PrettyPrint.HughesPJClass ( prettyShow ) import           URI.ByteString  import qualified Crypto.Hash.SHA256            as SHA256-import qualified Data.ByteString               as BS+import qualified Data.ByteString               as B import qualified Data.ByteString.Base16        as B16 import qualified Data.ByteString.Lazy          as L import qualified Data.Map.Strict               as M-#if defined(INTERNAL_DOWNLOADER)-import qualified Data.CaseInsensitive          as CI import qualified Data.Text                     as T-#endif+import qualified Data.Text.IO                  as T import qualified Data.Text.Encoding            as E-import qualified Data.Yaml                     as Y-import qualified System.Posix.Files.ByteString as PF-import qualified System.Posix.RawFilePath.Directory-                                               as RD+import qualified Data.YAML.Aeson               as Y   @@ -110,32 +104,32 @@ getDownloadsF :: ( FromJSONKey Tool                  , FromJSONKey Version                  , FromJSON VersionInfo+                 , MonadReader env m+                 , HasSettings env+                 , HasDirs env                  , MonadIO m                  , MonadCatch m-                 , MonadLogger m+                 , HasLog env                  , MonadThrow m                  , MonadFail m-                 , MonadReader AppState m+                 , MonadMask m                  )-              => URLSource-              -> Excepts-                   '[JSONError , DownloadFailed , FileDoesNotExistError]+              => Excepts+                   '[DigestError, GPGError, JSONError , DownloadFailed , FileDoesNotExistError]                    m                    GHCupInfo-getDownloadsF urlSource = do+getDownloadsF = do+  Settings { urlSource } <- lift getSettings   case urlSource of-    GHCupURL -> liftE getBase-    (OwnSource url) -> do-      bs <- reThrowAll DownloadFailed $ downloadBS url-      lE' JSONDecodeError $ first show $ Y.decodeEither' (L.toStrict bs)+    GHCupURL -> liftE $ getBase ghcupURL+    (OwnSource url) -> liftE $ getBase url     (OwnSpec av) -> pure av     (AddSource (Left ext)) -> do-      base <- liftE getBase+      base <- liftE $ getBase ghcupURL       pure (mergeGhcupInfo base ext)     (AddSource (Right uri)) -> do-      base <- liftE getBase-      bsExt <- reThrowAll DownloadFailed $ downloadBS uri-      ext <- lE' JSONDecodeError $ first show $ Y.decodeEither' (L.toStrict bsExt)+      base <- liftE $ getBase ghcupURL+      ext  <- liftE $ getBase uri       pure (mergeGhcupInfo base ext)      where@@ -143,181 +137,174 @@   mergeGhcupInfo :: GHCupInfo -- ^ base to merge with                  -> GHCupInfo -- ^ extension overwriting the base                  -> GHCupInfo-  mergeGhcupInfo (GHCupInfo tr base) (GHCupInfo _ ext) =-    let new = M.mapWithKey (\k a -> case M.lookup k ext of+  mergeGhcupInfo (GHCupInfo tr base base2) (GHCupInfo _ ext ext2) =+    let newDownloads = M.mapWithKey (\k a -> case M.lookup k ext of                                         Just a' -> M.union a' a                                         Nothing -> a-                           ) base-    in GHCupInfo tr new+                                    ) base+        newGlobalTools = M.union base2 ext2+    in GHCupInfo tr newDownloads newGlobalTools  -readFromCache :: (MonadIO m, MonadCatch m, MonadLogger m, MonadReader AppState m)-              => Excepts '[JSONError, FileDoesNotExistError] m GHCupInfo-readFromCache = do-  AppState {dirs = Dirs {..}} <- lift ask-  lift $ $(logWarn)-    [i|Could not get download info, trying cached version (this may not be recent!)|]-  let path = view pathL' ghcupURL-  yaml_file <- (cacheDir </>) <$> urlBaseName path-  bs        <--    handleIO' NoSuchThing-              (\_ -> throwE $ FileDoesNotExistError (toFilePath yaml_file))-    $ liftIO-    $ readFile yaml_file-  lE' JSONDecodeError $ first show $ Y.decodeEither' (L.toStrict bs)+yamlFromCache :: (MonadReader env m, HasDirs env) => URI -> m FilePath+yamlFromCache uri = do+  Dirs{..} <- getDirs+  pure (cacheDir </> (T.unpack . decUTF8Safe . urlBaseName . view pathL' $ uri))  -getBase :: (MonadFail m, MonadIO m, MonadCatch m, MonadLogger m, MonadReader AppState m)-        => Excepts '[JSONError , FileDoesNotExistError] m GHCupInfo-getBase =-  handleIO (\_ -> readFromCache)-  $ catchE @_ @'[JSONError, FileDoesNotExistError]-      (\(DownloadFailed _) -> readFromCache)-  (reThrowAll @_ @_ @'[JSONError, DownloadFailed] DownloadFailed (smartDl ghcupURL)-    >>= (liftE . lE' @_ @_ @'[JSONError] JSONDecodeError . first show . Y.decodeEither' . L.toStrict))-    where+etagsFile :: FilePath -> FilePath+etagsFile = (<.> "etags")+++getBase :: ( MonadReader env m+           , HasDirs env+           , HasSettings env+           , MonadFail m+           , MonadIO m+           , MonadCatch m+           , HasLog env+           , MonadMask m+           )+        => URI+        -> Excepts '[GPGError, DigestError, JSONError, FileDoesNotExistError] m GHCupInfo+getBase uri = do+  Settings { noNetwork, downloader } <- lift getSettings++  -- try to download yaml... usually this writes it into cache dir,+  -- but in some cases not (e.g. when using file://), so we honour+  -- the return filepath, if any+  mYaml <- if noNetwork && view (uriSchemeL' % schemeBSL') uri /= "file" -- for file://, let it fall through+           then pure Nothing+           else handleIO (\e -> lift (warnCache (displayException e) downloader) >> pure Nothing)+               . catchE @_ @_ @'[] (\e@(DownloadFailed _) -> lift (warnCache (prettyShow e) downloader) >> pure Nothing)+               . fmap Just+               . smartDl+               $ uri++  -- if we didn't get a filepath from the download, use the cached yaml+  actualYaml <- maybe (lift $ yamlFromCache uri) pure mYaml+  yamlContents <- liftIOException doesNotExistErrorType (FileDoesNotExistError actualYaml) $ liftIO $ L.readFile actualYaml+  lift $ logDebug $ "Decoding yaml at: " <> T.pack actualYaml++  liftE+    . onE_ (onError actualYaml)+    . lE' @_ @_ @'[JSONError] JSONDecodeError+    . first (\(_, e) -> unlines [e, "Consider removing " <> actualYaml <> " manually."])+    . Y.decode1+    $ yamlContents+ where+  -- On error, remove the etags file and set access time to 0. This should ensure the next invocation+  -- may re-download and succeed.+  onError :: (MonadReader env m, HasLog env, MonadMask m, MonadCatch m, MonadIO m) => FilePath -> m ()+  onError fp = do+    let efp = etagsFile fp+    handleIO (\e -> logWarn $ "Couldn't remove file " <> T.pack efp <> ", error was: " <> T.pack (displayException e))+      (hideError doesNotExistErrorType $ rmFile efp)+    liftIO $ hideError doesNotExistErrorType $ setAccessTime fp (posixSecondsToUTCTime (fromIntegral @Int 0))++  warnCache :: (MonadReader env m, HasLog env, MonadMask m, MonadCatch m, MonadIO m) => FilePath -> Downloader -> m ()+  warnCache s downloader' = do+    let tryDownloder = case downloader' of+                         Curl -> "Wget"+                         Wget -> "Curl"+#if defined(INTERNAL_DOWNLOADER)+                         Internal -> "Curl"+#endif+    logWarn $ "Could not get download info, trying cached version (this may not be recent!)" <> "\n" <>+      "If this problem persists, consider switching downloader via: " <> "\n    " <>+      "ghcup config set downloader " <> tryDownloder+    logDebug $ "Error was: " <> T.pack s+   -- First check if the json file is in the ~/.ghcup/cache dir   -- and check it's access time. If it has been accessed within the   -- last 5 minutes, just reuse it.   ---  -- If not, then send a HEAD request and check for modification time.-  -- Only download the file if the modification time is newer-  -- than the local file.-  --   -- Always save the local file with the mod time of the remote file.-  smartDl :: forall m1-           . ( MonadCatch m1+  smartDl :: forall m1 env1+           . ( MonadReader env1 m1+             , HasDirs env1+             , HasSettings env1+             , MonadCatch m1              , MonadIO m1              , MonadFail m1-             , MonadLogger m1-             , MonadReader AppState m1+             , HasLog env1+             , MonadMask m1              )           => URI           -> Excepts-               '[ FileDoesNotExistError-                , HTTPStatusError-                , URIParseError-                , UnsupportedScheme-                , NoLocationHeader-                , TooManyRedirs-                , ProcessError+               '[ DownloadFailed+                , DigestError+                , GPGError                 ]                m1-               L.ByteString+               FilePath   smartDl uri' = do-    AppState {dirs = Dirs {..}} <- lift ask-    let path = view pathL' uri'-    json_file <- (cacheDir </>) <$> urlBaseName path-    e         <- liftIO $ doesFileExist json_file-    if e-      then do-        accessTime <--          PF.accessTimeHiRes-            <$> liftIO (PF.getFileStatus (toFilePath json_file))-        currentTime <- liftIO getPOSIXTime+    json_file <- lift $ yamlFromCache uri'+    let scheme = view (uriSchemeL' % schemeBSL') uri'+    e <- liftIO $ doesFileExist json_file+    currentTime <- liftIO getCurrentTime+    Dirs { cacheDir } <- lift getDirs -        -- access time won't work on most linuxes, but we can try regardless-        if (currentTime - accessTime) > 300-          then do -- no access in last 5 minutes, re-check upstream mod time-            getModTime >>= \case-              Just modTime -> do-                fileMod <- liftIO $ getModificationTime json_file-                if modTime > fileMod-                  then dlWithMod modTime json_file-                  else liftIO $ readFile json_file-              Nothing -> do-                lift $ $(logDebug) [i|Unable to get/parse Last-Modified header|]-                dlWithoutMod json_file-          else -- access in less than 5 minutes, re-use file-               liftIO $ readFile json_file-      else do-        liftIO $ createDirRecursive' cacheDir-        getModTime >>= \case-          Just modTime -> dlWithMod modTime json_file-          Nothing -> do-            -- although we don't know last-modified, we still save-            -- it to a file, so we might use it in offline mode-            lift $ $(logDebug) [i|Unable to get/parse Last-Modified header|]-            dlWithoutMod json_file+       -- for local files, let's short-circuit and ignore access time+    if | scheme == "file" -> liftE $ download uri' Nothing Nothing cacheDir Nothing True+       | e -> do+          accessTime <- liftIO $ getAccessTime json_file +          -- access time won't work on most linuxes, but we can try regardless+          if | ((utcTimeToPOSIXSeconds currentTime - utcTimeToPOSIXSeconds accessTime) > 300) ->+                -- no access in last 5 minutes, re-check upstream mod time+                dlWithMod currentTime json_file+             | otherwise -> pure json_file+       | otherwise -> dlWithMod currentTime json_file    where     dlWithMod modTime json_file = do-      bs <- liftE $ downloadBS uri'-      liftIO $ writeFileWithModTime modTime json_file bs-      pure bs-    dlWithoutMod json_file = do-      bs <- liftE $ downloadBS uri'-      liftIO $ hideError doesNotExistErrorType $ deleteFile json_file-      liftIO $ writeFileL json_file (Just newFilePerms) bs-      liftIO $ setModificationTime json_file (fromIntegral @Int 0)-      pure bs---    getModTime = do-#if !defined(INTERNAL_DOWNLOADER)-      pure Nothing-#else-      headers <--        handleIO (\_ -> pure mempty)-        $ liftE-        $ ( catchAllE-              (\_ ->-                pure mempty :: Excepts '[] m1 (M.Map (CI ByteString) ByteString)-              )-          $ getHead uri'-          )-      pure $ parseModifiedHeader headers--  parseModifiedHeader :: (M.Map (CI ByteString) ByteString) -> Maybe UTCTime-  parseModifiedHeader headers =-    (M.lookup (CI.mk "Last-Modified") headers) >>= \h -> parseTimeM-      True-      defaultTimeLocale-      "%a, %d %b %Y %H:%M:%S %Z"-      (T.unpack . decUTF8Safe $ h)--#endif--  writeFileWithModTime :: UTCTime -> Path Abs -> L.ByteString -> IO ()-  writeFileWithModTime utctime path content = do-    let mod_time = utcTimeToPOSIXSeconds utctime-    writeFileL path (Just newFilePerms) content-    setModificationTimeHiRes path mod_time+      let (dir, fn) = splitFileName json_file+      f <- liftE $ download uri' (Just $ over pathL' (<> ".sig") uri') Nothing dir (Just fn) True+      liftIO $ setModificationTime f modTime+      liftIO $ setAccessTime f modTime+      pure f  -getDownloadInfo :: Tool+getDownloadInfo :: ( MonadReader env m+                   , HasPlatformReq env+                   , HasGHCupInfo env+                   )+                => Tool                 -> Version                 -- ^ tool version-                -> PlatformRequest-                -> GHCupDownloads-                -> Either NoDownload DownloadInfo-getDownloadInfo t v (PlatformRequest a p mv) dls = maybe-  (Left NoDownload)-  Right-  (case p of-    -- non-musl won't work on alpine-    Linux Alpine -> with_distro <|> without_distro_ver-    _            -> with_distro <|> without_distro_ver <|> without_distro-  )+                -> Excepts+                     '[NoDownload]+                     m+                     DownloadInfo+getDownloadInfo t v = do+  (PlatformRequest a p mv) <- lift getPlatformReq+  GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo - where-  with_distro        = distro_preview id id-  without_distro_ver = distro_preview id (const Nothing)-  without_distro     = distro_preview (set _Linux UnknownLinux) (const Nothing)+  let distro_preview f g =+        let platformVersionSpec =+              preview (ix t % ix v % viArch % ix a % ix (f p)) dls+            mv' = g mv+        in  fmap snd+              .   find+                    (\(mverRange, _) -> maybe+                      (isNothing mv')+                      (\range -> maybe False (`versionRange` range) mv')+                      mverRange+                    )+              .   M.toList+              =<< platformVersionSpec+      with_distro        = distro_preview id id+      without_distro_ver = distro_preview id (const Nothing)+      without_distro     = distro_preview (set _Linux UnknownLinux) (const Nothing) -  distro_preview f g =-    let platformVersionSpec =-          preview (ix t % ix v % viArch % ix a % ix (f p)) dls-        mv' = g mv-    in  fmap snd-          .   find-                (\(mverRange, _) -> maybe-                  (isNothing mv')-                  (\range -> maybe False (`versionRange` range) mv')-                  mverRange-                )-          .   M.toList-          =<< platformVersionSpec+  maybe+    (throwE NoDownload)+    pure+    (case p of+      -- non-musl won't work on alpine+      Linux Alpine -> with_distro <|> without_distro_ver+      _            -> with_distro <|> without_distro_ver <|> without_distro+    )   -- | Tries to download from the given http or https url@@ -327,196 +314,375 @@ --   2. otherwise create a random file -- -- The file must not exist.-download :: ( MonadMask m-            , MonadReader AppState m+download :: ( MonadReader env m+            , HasSettings env+            , HasDirs env+            , MonadMask m             , MonadThrow m-            , MonadLogger m+            , HasLog env             , MonadIO m             )-         => DownloadInfo-         -> Path Abs          -- ^ destination dir-         -> Maybe (Path Rel)  -- ^ optional filename-         -> Excepts '[DigestError , DownloadFailed] m (Path Abs)-download dli dest mfn+         => URI+         -> Maybe URI         -- ^ URI for gpg sig+         -> Maybe T.Text      -- ^ expected hash+         -> FilePath          -- ^ destination dir (ignored for file:// scheme)+         -> Maybe FilePath    -- ^ optional filename+         -> Bool              -- ^ whether to read an write etags+         -> Excepts '[DigestError , DownloadFailed, GPGError] m FilePath+download uri gpgUri eDigest dest mfn etags   | scheme == "https" = dl   | scheme == "http"  = dl-  | scheme == "file"  = cp+  | scheme == "file"  = do+      let destFile' = T.unpack . decUTF8Safe $ view pathL' uri+      lift $ logDebug $ "using local file: " <> T.pack destFile'+      forM_ eDigest (liftE . flip checkDigest destFile')+      pure destFile'   | otherwise = throwE $ DownloadFailed (variantFromValue UnsupportedScheme)   where-  scheme = view (dlUri % uriSchemeL' % schemeBSL') dli-  cp     = do-    -- destination dir must exist-    liftIO $ createDirRecursive' dest-    destFile <- getDestFile-    fromFile <- parseAbs path-    liftIO $ copyFile fromFile destFile Strict-    pure destFile+  scheme = view (uriSchemeL' % schemeBSL') uri   dl = do-    let uri' = decUTF8Safe (serializeURIRef' (view dlUri dli))-    lift $ $(logInfo) [i|downloading: #{uri'}|]+    baseDestFile <- liftE . reThrowAll @_ @_ @'[DownloadFailed] DownloadFailed $ getDestFile uri mfn+    lift $ logInfo $ "downloading: " <> (decUTF8Safe . serializeURIRef') uri <> " as file " <> T.pack baseDestFile      -- destination dir must exist     liftIO $ createDirRecursive' dest-    destFile <- getDestFile +     -- download     flip onException-         (liftIO $ hideError doesNotExistErrorType $ deleteFile destFile)-     $ catchAllE @_ @'[ProcessError, DownloadFailed, UnsupportedScheme]-          (\e ->-            liftIO (hideError doesNotExistErrorType $ deleteFile destFile)-              >> (throwE . DownloadFailed $ e)+         (lift $ hideError doesNotExistErrorType $ recycleFile (tmpFile baseDestFile))+     $ catchAllE @_ @'[GPGError, ProcessError, DownloadFailed, UnsupportedScheme, DigestError] @'[DigestError, DownloadFailed, GPGError]+          (\e' -> do+            lift $ hideError doesNotExistErrorType $ recycleFile (tmpFile baseDestFile)+            case e' of+              V e@GPGError {} -> throwE e+              V e@DigestError {} -> throwE e+              _ -> throwE (DownloadFailed e')           ) $ do-              lift getDownloader >>= \case-                Curl -> do-                  o' <- liftIO getCurlOpts-                  liftE $ lEM @_ @'[ProcessError] $ liftIO $ exec "curl" True-                    (o' ++ ["-fL", "-o", toFilePath destFile, serializeURIRef' $ view dlUri dli]) Nothing Nothing-                Wget -> do-                  o' <- liftIO getWgetOpts-                  liftE $ lEM @_ @'[ProcessError] $ liftIO $ exec "wget" True-                    (o' ++ ["-O", toFilePath destFile , serializeURIRef' $ view dlUri dli]) Nothing Nothing+              Settings{ downloader, noNetwork, gpgSetting } <- lift getSettings+              when noNetwork $ throwE (DownloadFailed (V NoNetwork :: V '[NoNetwork]))+              downloadAction <- case downloader of+                    Curl -> do+                      o' <- liftIO getCurlOpts+                      if etags+                        then pure $ curlEtagsDL o'+                        else pure $ curlDL o'+                    Wget -> do+                      o' <- liftIO getWgetOpts+                      if etags+                        then pure $ wgetEtagsDL o'+                        else pure $ wgetDL o' #if defined(INTERNAL_DOWNLOADER)-                Internal -> do-                  (https, host, fullPath, port) <- liftE $ uriToQuadruple (view dlUri dli)-                  liftE $ downloadToFile https host fullPath port destFile+                    Internal -> do+                      if etags+                        then pure (\fp -> liftE . internalEtagsDL fp)+                        else pure (\fp -> liftE . internalDL fp) #endif+              liftE $ downloadAction baseDestFile uri+              case (gpgUri, gpgSetting) of+                (_, GPGNone) -> pure ()+                (Just gpgUri', _) -> do+                  gpgDestFile <- liftE . reThrowAll @_ @_ @'[DownloadFailed] DownloadFailed $ getDestFile gpgUri' Nothing+                  liftE $ flip onException+                       (lift $ hideError doesNotExistErrorType $ recycleFile (tmpFile gpgDestFile))+                   $ catchAllE @_ @'[GPGError, ProcessError, UnsupportedScheme, DownloadFailed] @'[GPGError]+                        (\e -> if gpgSetting == GPGStrict then throwE (GPGError e) else lift $ logWarn $ T.pack (prettyShow (GPGError e))+                        ) $ do+                      o' <- liftIO getGpgOpts+                      lift $ logDebug $ "downloading: " <> (decUTF8Safe . serializeURIRef') gpgUri' <> " as file " <> T.pack gpgDestFile+                      liftE $ downloadAction gpgDestFile gpgUri'+                      lift $ logInfo $ "verifying signature of: " <> T.pack baseDestFile+                      let args = o' ++ ["--batch", "--verify", "--quiet", "--no-tty", gpgDestFile, baseDestFile]+                      cp <- lift $ executeOut "gpg" args Nothing+                      case cp of+                        CapturedProcess { _exitCode = ExitFailure i, _stdErr } -> do+                          lift $ logDebug $ decUTF8Safe' _stdErr+                          throwE (GPGError @'[ProcessError] (V (NonZeroExit i "gpg" args)))+                        CapturedProcess { _stdErr } -> lift $ logDebug $ decUTF8Safe' _stdErr+                _ -> pure () -    liftE $ checkDigest dli destFile-    pure destFile+              forM_ eDigest (liftE . flip checkDigest baseDestFile)+    pure baseDestFile +  curlDL :: (MonadCatch m, MonadMask m, MonadIO m) => [String] -> FilePath -> URI -> Excepts '[ProcessError, DownloadFailed, UnsupportedScheme] m ()+  curlDL o' destFile (decUTF8Safe . serializeURIRef' -> uri') = do+    let destFileTemp = tmpFile destFile+    flip finally (try @_ @SomeException $ rmFile destFileTemp) $ do+      liftE $ lEM @_ @'[ProcessError] $ exec "curl"+        (o' ++ ["-fL", "-o", destFileTemp, T.unpack uri']) Nothing Nothing+      liftIO $ renameFile destFileTemp destFile++  curlEtagsDL :: (MonadReader env m, HasLog env, MonadCatch m, MonadMask m, MonadIO m)+              => [String] -> FilePath -> URI -> Excepts '[ProcessError, DownloadFailed, UnsupportedScheme] m ()+  curlEtagsDL o' destFile (decUTF8Safe . serializeURIRef' -> uri') = do+    let destFileTemp = tmpFile destFile+    dh <- liftIO $ emptySystemTempFile "curl-header"+    flip finally (try @_ @SomeException $ rmFile dh) $+      flip finally (try @_ @SomeException $ rmFile destFileTemp) $ do+        metag <- lift $ readETag destFile+        liftE $ lEM @_ @'[ProcessError] $ exec "curl"+            (o' ++ (if etags then ["--dump-header", dh] else [])+                ++ maybe [] (\t -> ["-H", "If-None-Match: " <> T.unpack t]) metag+                ++ ["-fL", "-o", destFileTemp, T.unpack uri']) Nothing Nothing+        headers <- liftIO $ T.readFile dh++        -- this nonsense is necessary, because some older versions of curl would overwrite+        -- the destination file when 304 is returned+        case fmap T.words . listToMaybe . fmap T.strip . T.lines . getLastHeader $ headers of+          Just (http':sc:_)+            | sc == "304"+            , T.pack "HTTP" `T.isPrefixOf` http' -> lift $ logDebug "Status code was 304, not overwriting"+            | T.pack "HTTP" `T.isPrefixOf` http' -> do+                lift $ logDebug $ "Status code was " <> sc <> ", overwriting"+                liftIO $ renameFile destFileTemp destFile+          _ -> liftE $ throwE @_ @'[DownloadFailed] (DownloadFailed (toVariantAt @0 (MalformedHeaders headers)+            :: V '[MalformedHeaders]))++        lift $ writeEtags destFile (parseEtags headers)++  wgetDL :: (MonadCatch m, MonadMask m, MonadIO m) => [String] -> FilePath -> URI -> Excepts '[ProcessError, DownloadFailed, UnsupportedScheme] m ()+  wgetDL o' destFile (decUTF8Safe . serializeURIRef' -> uri') = do+    let destFileTemp = tmpFile destFile+    flip finally (try @_ @SomeException $ rmFile destFileTemp) $ do+      let opts = o' ++ ["-O", destFileTemp , T.unpack uri']+      liftE $ lEM @_ @'[ProcessError] $ exec "wget" opts Nothing Nothing+      liftIO $ renameFile destFileTemp destFile+++  wgetEtagsDL :: (MonadReader env m, HasLog env, MonadCatch m, MonadMask m, MonadIO m)+              => [String] -> FilePath -> URI -> Excepts '[ProcessError, DownloadFailed, UnsupportedScheme] m ()+  wgetEtagsDL o' destFile (decUTF8Safe . serializeURIRef' -> uri') = do+    let destFileTemp = tmpFile destFile+    flip finally (try @_ @SomeException $ rmFile destFileTemp) $ do+      metag <- lift $ readETag destFile+      let opts = o' ++ maybe [] (\t -> ["--header", "If-None-Match: " <> T.unpack t]) metag+                    ++ ["-q", "-S", "-O", destFileTemp , T.unpack uri']+      CapturedProcess {_exitCode, _stdErr} <- lift $ executeOut "wget" opts Nothing+      case _exitCode of+        ExitSuccess -> do+          liftIO $ renameFile destFileTemp destFile+          lift $ writeEtags destFile (parseEtags (decUTF8Safe' _stdErr))+        ExitFailure i'+          | i' == 8+          , Just _ <- find (T.pack "304 Not Modified" `T.isInfixOf`) . T.lines . decUTF8Safe' $ _stdErr+                   -> do+                        lift $ logDebug "Not modified, skipping download"+                        lift $ writeEtags destFile (parseEtags (decUTF8Safe' _stdErr))+          | otherwise -> throwE (NonZeroExit i' "wget" opts)++#if defined(INTERNAL_DOWNLOADER)+  internalDL :: (MonadCatch m, MonadMask m, MonadIO m)+             => FilePath -> URI -> Excepts '[DownloadFailed, UnsupportedScheme] m ()+  internalDL destFile uri' = do+    let destFileTemp = tmpFile destFile+    flip finally (try @_ @SomeException $ rmFile destFileTemp) $ do+      (https, host, fullPath, port) <- liftE $ uriToQuadruple uri'+      void $ liftE $ catchE @HTTPNotModified+                 @'[DownloadFailed]+            (\e@(HTTPNotModified _) ->+              throwE @_ @'[DownloadFailed] (DownloadFailed (toVariantAt @0 e :: V '[HTTPNotModified])))+        $ downloadToFile https host fullPath port destFileTemp mempty+      liftIO $ renameFile destFileTemp destFile+++  internalEtagsDL :: (MonadReader env m, HasLog env, MonadCatch m, MonadMask m, MonadIO m)+                  => FilePath -> URI -> Excepts '[DownloadFailed, UnsupportedScheme] m ()+  internalEtagsDL destFile uri' = do+    let destFileTemp = tmpFile destFile+    flip finally (try @_ @SomeException $ rmFile destFileTemp) $ do+      (https, host, fullPath, port) <- liftE $ uriToQuadruple uri'+      metag <- lift $ readETag destFile+      let addHeaders = maybe mempty (\etag -> M.fromList [ (mk . E.encodeUtf8 . T.pack $ "If-None-Match"+                                                         , E.encodeUtf8 etag)]) metag+      liftE+        $ catchE @HTTPNotModified @'[DownloadFailed] @'[] (\(HTTPNotModified etag) -> lift $ writeEtags destFile (pure $ Just etag))+        $ do+          r <- downloadToFile https host fullPath port destFileTemp addHeaders+          liftIO $ renameFile destFileTemp destFile+          lift $ writeEtags destFile (pure $ decUTF8Safe <$> getHeader r "etag")+#endif++   -- Manage to find a file we can write the body into.-  getDestFile :: MonadThrow m => m (Path Abs)-  getDestFile = maybe (urlBaseName path <&> (dest </>)) (pure . (dest </>)) mfn+  getDestFile :: Monad m => URI -> Maybe FilePath -> Excepts '[NoUrlBase] m FilePath+  getDestFile uri' mfn' = +    let path = view pathL' uri'+    in case mfn' of+        Just fn -> pure (dest </> fn)+        Nothing+          | let urlBase = T.unpack (decUTF8Safe (urlBaseName path))+          , not (null urlBase) -> pure (dest </> urlBase)+          -- TODO: remove this once we use hpath again+          | otherwise -> throwE $ NoUrlBase (decUTF8Safe . serializeURIRef' $ uri') -  path        = view (dlUri % pathL') dli+  parseEtags :: (MonadReader env m, HasLog env, MonadIO m, MonadThrow m) => T.Text -> m (Maybe T.Text)+  parseEtags stderr = do+    let mEtag = find (\line -> T.pack "etag:" `T.isPrefixOf` T.toLower line) . fmap T.strip . T.lines . getLastHeader $ stderr+    case T.words <$> mEtag of+      (Just []) -> do+        logDebug "Couldn't parse etags, no input: "+        pure Nothing+      (Just [_, etag']) -> do+        logDebug $ "Parsed etag: " <> etag'+        pure (Just etag')+      (Just xs) -> do+        logDebug ("Couldn't parse etags, unexpected input: " <> T.unwords xs)+        pure Nothing+      Nothing -> do+        logDebug "No etags header found"+        pure Nothing +  writeEtags :: (MonadReader env m, HasLog env, MonadIO m, MonadThrow m) => FilePath -> m (Maybe T.Text) -> m ()+  writeEtags destFile getTags = do+    getTags >>= \case+      Just t -> do+        logDebug $ "Writing etagsFile " <> T.pack (etagsFile destFile)+        liftIO $ T.writeFile (etagsFile destFile) t+      Nothing ->+        logDebug "No etags files written" +  readETag :: (MonadReader env m, HasLog env, MonadCatch m, MonadIO m) => FilePath -> m (Maybe T.Text)+  readETag fp = do+    e <- liftIO $ doesFileExist fp+    if e+    then do+      rE <- try @_ @SomeException $ liftIO $ fmap stripNewline' $ T.readFile (etagsFile fp)+      case rE of+        (Right et) -> do+          logDebug $ "Read etag: " <> et+          pure (Just et)+        (Left _) -> do+          logDebug "Etag file doesn't exist (yet)"+          pure Nothing+    else do+      logDebug $ "Skipping and deleting etags file because destination file " <> T.pack fp <> " doesn't exist"+      liftIO $ hideError doesNotExistErrorType $ rmFile (etagsFile fp)+      pure Nothing++ -- | Download into tmpdir or use cached version, if it exists. If filename -- is omitted, infers the filename from the url.-downloadCached :: ( MonadMask m+downloadCached :: ( MonadReader env m+                  , HasDirs env+                  , HasSettings env+                  , MonadMask m                   , MonadResource m                   , MonadThrow m-                  , MonadLogger m+                  , HasLog env                   , MonadIO m-                  , MonadReader AppState m+                  , MonadUnliftIO m                   )                => DownloadInfo-               -> Maybe (Path Rel)  -- ^ optional filename-               -> Excepts '[DigestError , DownloadFailed] m (Path Abs)+               -> Maybe FilePath  -- ^ optional filename+               -> Excepts '[DigestError , DownloadFailed, GPGError] m FilePath downloadCached dli mfn = do-  cache <- lift getCache+  Settings{ cache } <- lift getSettings   case cache of-    True -> do-      AppState {dirs = Dirs {..}} <- lift ask-      fn       <- maybe (urlBaseName $ view (dlUri % pathL') dli) pure mfn-      let cachfile = cacheDir </> fn-      fileExists <- liftIO $ doesFileExist cachfile-      if-        | fileExists -> do-          liftE $ checkDigest dli cachfile-          pure cachfile-        | otherwise -> liftE $ download dli cacheDir mfn+    True -> downloadCached' dli mfn Nothing     False -> do       tmp <- lift withGHCupTmpDir-      liftE $ download dli tmp mfn+      liftE $ download (_dlUri dli) Nothing (Just (_dlHash dli)) tmp mfn False  +downloadCached' :: ( MonadReader env m+                   , HasDirs env+                   , HasSettings env+                   , MonadMask m+                   , MonadThrow m+                   , HasLog env+                   , MonadIO m+                   , MonadUnliftIO m+                   )+                => DownloadInfo+                -> Maybe FilePath  -- ^ optional filename+                -> Maybe FilePath  -- ^ optional destination dir (default: cacheDir)+                -> Excepts '[DigestError , DownloadFailed, GPGError] m FilePath+downloadCached' dli mfn mDestDir = do+  Dirs { cacheDir } <- lift getDirs+  let destDir = fromMaybe cacheDir mDestDir+  let fn = fromMaybe ((T.unpack . decUTF8Safe) $ urlBaseName $ view (dlUri % pathL') dli) mfn+  let cachfile = destDir </> fn+  fileExists <- liftIO $ doesFileExist cachfile+  if+    | fileExists -> do+      liftE $ checkDigest (view dlHash dli) cachfile+      pure cachfile+    | otherwise -> liftE $ download (_dlUri dli) Nothing (Just (_dlHash dli)) destDir mfn False  ++     ------------------     --[ Low-level ]--     ------------------   ---- | This is used for downloading the JSON.-downloadBS :: (MonadReader AppState m, MonadCatch m, MonadIO m, MonadLogger m)-           => URI-           -> Excepts-                '[ FileDoesNotExistError-                 , HTTPStatusError-                 , URIParseError-                 , UnsupportedScheme-                 , NoLocationHeader-                 , TooManyRedirs-                 , ProcessError-                 ]-                m-                L.ByteString-downloadBS uri'-  | scheme == "https"-  = dl True-  | scheme == "http"-  = dl False-  | scheme == "file"-  = liftIOException doesNotExistErrorType (FileDoesNotExistError path)-    (liftIO $ RD.readFile path)-  | otherwise-  = throwE UnsupportedScheme-- where-  scheme = view (uriSchemeL' % schemeBSL') uri'-  path   = view pathL' uri'-#if defined(INTERNAL_DOWNLOADER)-  dl https = do-#else-  dl _ = do-#endif-    lift $ $(logDebug) [i|downloading: #{serializeURIRef' uri'}|]-    lift getDownloader >>= \case-      Curl -> do-        o' <- liftIO getCurlOpts-        let exe = [rel|curl|]-            args = o' ++ ["-sSfL", serializeURIRef' uri']-        liftIO (executeOut exe args Nothing) >>= \case-          CapturedProcess ExitSuccess stdout _ -> do-            pure $ L.fromStrict stdout-          CapturedProcess (ExitFailure i') _ _ -> throwE $ NonZeroExit i' (toFilePath exe) args-      Wget -> do-        o' <- liftIO getWgetOpts-        let exe = [rel|wget|]-            args = o' ++ ["-qO-", serializeURIRef' uri']-        liftIO (executeOut exe args Nothing) >>= \case-          CapturedProcess ExitSuccess stdout _ -> do-            pure $ L.fromStrict stdout-          CapturedProcess (ExitFailure i') _ _ -> throwE $ NonZeroExit i' (toFilePath exe) args-#if defined(INTERNAL_DOWNLOADER)-      Internal -> do-        (_, host', fullPath', port') <- liftE $ uriToQuadruple uri'-        liftE $ downloadBS' https host' fullPath' port'-#endif---checkDigest :: (MonadIO m, MonadThrow m, MonadLogger m, MonadReader AppState m)-            => DownloadInfo-            -> Path Abs+checkDigest :: ( MonadReader env m+               , HasDirs env+               , HasSettings env+               , MonadIO m+               , MonadThrow m+               , HasLog env+               )+            => T.Text     -- ^ the hash+            -> FilePath             -> Excepts '[DigestError] m ()-checkDigest dli file = do-  verify <- lift ask <&> (not . noVerify . settings)+checkDigest eDigest file = do+  Settings{ noVerify } <- lift getSettings+  let verify = not noVerify   when verify $ do-    p' <- toFilePath <$> basename file-    lift $ $(logInfo) [i|verifying digest of: #{p'}|]-    c <- liftIO $ readFile file+    let p' = takeFileName file+    lift $ logInfo $ "verifying digest of: " <> T.pack p'+    c <- liftIO $ L.readFile file     cDigest <- throwEither . E.decodeUtf8' . B16.encode . SHA256.hashlazy $ c-    let eDigest = view dlHash dli-    when ((cDigest /= eDigest) && verify) $ throwE (DigestError cDigest eDigest)+    when ((cDigest /= eDigest) && verify) $ throwE (DigestError file cDigest eDigest)   -- | Get additional curl args from env. This is an undocumented option.-getCurlOpts :: IO [ByteString]+getCurlOpts :: IO [String] getCurlOpts =-  getEnv "GHCUP_CURL_OPTS" >>= \case-    Just r  -> pure $ BS.split _space r+  lookupEnv "GHCUP_CURL_OPTS" >>= \case+    Just r  -> pure $ splitOn " " r     Nothing -> pure []   -- | Get additional wget args from env. This is an undocumented option.-getWgetOpts :: IO [ByteString]+getWgetOpts :: IO [String] getWgetOpts =-  getEnv "GHCUP_WGET_OPTS" >>= \case-    Just r  -> pure $ BS.split _space r+  lookupEnv "GHCUP_WGET_OPTS" >>= \case+    Just r  -> pure $ splitOn " " r     Nothing -> pure [] +-- | Get additional gpg args from env. This is an undocumented option.+getGpgOpts :: IO [String]+getGpgOpts =+  lookupEnv "GHCUP_GPG_OPTS" >>= \case+    Just r  -> pure $ splitOn " " r+    Nothing -> pure []++-- | Get the url base name.+--+-- >>> urlBaseName "/foo/bar/baz"+-- "baz"+urlBaseName :: ByteString  -- ^ the url path (without scheme and host)+            -> ByteString+urlBaseName = snd . B.breakEnd (== _slash) . urlDecode False+++-- | Curl saves all intermediate connect headers as well, not just the last one, so we make an effort to take the+-- last HTTP block only. Passing '--suppress-connect-headers' would be better, but it isn't supported by all versions,+-- also see:+--   https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/213+--+-- >>> getLastHeader "\n\nHTTP/1.0 200 Connection established\n\nHTTP/1.1 304 Not Modified\n"+-- "HTTP/1.1 304 Not Modified\n"+-- >>> getLastHeader "HTTP/1.1 304 Not Modified\n"+-- "HTTP/1.1 304 Not Modified\n"+getLastHeader :: T.Text -> T.Text+getLastHeader = T.unlines . lastDef [] . filter (\x -> not (null x)) . splitOn [""] . fmap T.stripEnd . T.lines+++tmpFile :: FilePath -> FilePath+tmpFile = (<.> "tmp")
lib/GHCup/Download/IOStreams.hs view
@@ -9,9 +9,7 @@  import           GHCup.Download.Utils import           GHCup.Errors-import           GHCup.Types.Optics import           GHCup.Types.JSON               ( )-import           GHCup.Utils.File import           GHCup.Utils.Prelude  import           Control.Applicative@@ -20,12 +18,10 @@ import           Control.Monad.Reader import           Data.ByteString                ( ByteString ) import           Data.ByteString.Builder-import           Data.CaseInsensitive           ( CI )+import           Data.CaseInsensitive           ( CI, original, mk ) import           Data.IORef import           Data.Maybe import           Data.Text.Read-import           HPath-import           HPath.IO                      as HIO import           Haskus.Utils.Variant.Excepts import           Network.Http.Client     hiding ( URL ) import           Optics@@ -33,10 +29,6 @@                                                 , readFile                                                 , writeFile                                                 )-import "unix"    System.Posix.IO.ByteString-                                         hiding ( fdWrite )-import "unix-bytestring" System.Posix.IO.ByteString-                                                ( fdWrite ) import           System.ProgressBar import           URI.ByteString @@ -72,7 +64,7 @@ downloadBS' https host path port = do   bref <- liftIO $ newIORef (mempty :: Builder)   let stepper bs = modifyIORef bref (<> byteString bs)-  downloadInternal False https host path port stepper+  void $ downloadInternal False https host path port stepper (pure ()) mempty   liftIO (readIORef bref <&> toLazyByteString)  @@ -81,13 +73,18 @@                -> ByteString       -- ^ host (e.g. "www.example.com")                -> ByteString       -- ^ path (e.g. "/my/file") including query                -> Maybe Int        -- ^ optional port (e.g. 3000)-               -> Path Abs         -- ^ destination file to create and write to-               -> Excepts '[DownloadFailed] m ()-downloadToFile https host fullPath port destFile = do-  fd <- liftIO $ createRegularFileFd newFilePerms destFile-  let stepper = fdWrite fd-  flip finally (liftIO $ closeFd fd)-    $ reThrowAll DownloadFailed $ downloadInternal True https host fullPath port stepper+               -> FilePath         -- ^ destination file to create and write to+               -> M.Map (CI ByteString) ByteString -- ^ additional headers+               -> Excepts '[DownloadFailed, HTTPNotModified] m Response+downloadToFile https host fullPath port destFile addHeaders = do+  let stepper = BS.appendFile destFile+      setup = BS.writeFile destFile mempty+  catchAllE (\case+              (V (HTTPStatusError i headers))+                | i == 304+                , Just e <- M.lookup (mk "etag") headers -> throwE $ HTTPNotModified (decUTF8Safe e)+              v -> throwE $ DownloadFailed v+            ) $ downloadInternal True https host fullPath port stepper setup addHeaders   downloadInternal :: MonadIO m@@ -97,6 +94,8 @@                  -> ByteString  -- ^ path with query                  -> Maybe Int   -- ^ optional port                  -> (ByteString -> IO a)   -- ^ the consuming step function+                 -> IO a                   -- ^ setup action+                 -> M.Map (CI ByteString) ByteString -- ^ additional headers                  -> Excepts                       '[ HTTPStatusError                        , URIParseError@@ -105,19 +104,21 @@                        , TooManyRedirs                        ]                       m-                      ()+                      Response downloadInternal = go (5 :: Int)   where-  go redirs progressBar https host path port consumer = do+  go redirs progressBar https host path port consumer setup addHeaders = do     r <- liftIO $ withConnection' https host port action     veitherToExcepts r >>= \case-      Just r' ->+      Right r' ->         if redirs > 0 then followRedirectURL r' else throwE TooManyRedirs-      Nothing -> pure ()+      Left res -> pure res    where     action c = do-      let q = buildRequest1 $ http GET path+      let q = buildRequest1 $ do+                http GET path+                flip M.traverseWithKey addHeaders $ \key val -> setHeader (original key) val        sendRequest c q emptyBody @@ -126,28 +127,30 @@         (\r i' -> runE $ do           let scode = getStatusCode r           if-            | scode >= 200 && scode < 300 -> downloadStream r i' >> pure Nothing+            | scode >= 200 && scode < 300 -> liftIO $ downloadStream r i' >> pure (Left r)+            | scode == 304 -> throwE $ HTTPStatusError scode (getHeaderMap r)             | scode >= 300 && scode < 400 -> case getHeader r "Location" of-              Just r' -> pure $ Just r'+              Just r' -> pure $ Right r'               Nothing -> throwE NoLocationHeader-            | otherwise -> throwE $ HTTPStatusError scode+            | otherwise -> throwE $ HTTPStatusError scode (getHeaderMap r)         )      followRedirectURL bs = case parseURI strictURIParserOptions bs of       Right uri' -> do         (https', host', fullPath', port') <- liftE $ uriToQuadruple uri'-        go (redirs - 1) progressBar https' host' fullPath' port' consumer+        go (redirs - 1) progressBar https' host' fullPath' port' consumer setup addHeaders       Left e -> throwE e      downloadStream r i' = do+      void setup       let size = case getHeader r "Content-Length" of             Just x' -> case decimal $ decUTF8Safe x' of               Left  _       -> 0               Right (r', _) -> r'             Nothing -> 0 -      mpb <- if progressBar-        then Just <$> liftIO (newProgressBar defStyle 10 (Progress 0 size ()))+      (mpb :: Maybe (ProgressBar ())) <- if progressBar+        then Just <$> newProgressBar defStyle 10 (Progress 0 size ())         else pure Nothing        outStream <- liftIO $ Streams.makeOutputStream@@ -159,79 +162,6 @@         )       liftIO $ Streams.connect i' outStream --getHead :: (MonadCatch m, MonadIO m)-        => URI-        -> Excepts-             '[ HTTPStatusError-              , URIParseError-              , UnsupportedScheme-              , NoLocationHeader-              , TooManyRedirs-              , ProcessError-              ]-             m-             (M.Map (CI ByteString) ByteString)-getHead uri' | scheme == "https" = head' True-             | scheme == "http"  = head' False-             | otherwise         = throwE UnsupportedScheme-- where-  scheme = view (uriSchemeL' % schemeBSL') uri'-  head' https = do-    (_, host', fullPath', port') <- liftE $ uriToQuadruple uri'-    liftE $ headInternal https host' fullPath' port'---headInternal :: MonadIO m-             => Bool        -- ^ https?-             -> ByteString  -- ^ host-             -> ByteString  -- ^ path with query-             -> Maybe Int   -- ^ optional port-             -> Excepts-                  '[ HTTPStatusError-                   , URIParseError-                   , UnsupportedScheme-                   , TooManyRedirs-                   , NoLocationHeader-                   ]-                  m-                  (M.Map (CI ByteString) ByteString)-headInternal = go (5 :: Int)-- where-  go redirs https host path port = do-    r <- liftIO $ withConnection' https host port action-    veitherToExcepts r >>= \case-      Left r' ->-        if redirs > 0 then followRedirectURL r' else throwE TooManyRedirs-      Right hs -> pure hs-   where--    action c = do-      let q = buildRequest1 $ http HEAD path--      sendRequest c q emptyBody--      unsafeReceiveResponse-        c-        (\r _ -> runE $ do-          let scode = getStatusCode r-          if-            | scode >= 200 && scode < 300 -> do-              let headers = getHeaderMap r-              pure $ Right headers-            | scode >= 300 && scode < 400 -> case getHeader r "Location" of-              Just r' -> pure $ Left r'-              Nothing -> throwE NoLocationHeader-            | otherwise -> throwE $ HTTPStatusError scode-        )--    followRedirectURL bs = case parseURI strictURIParserOptions bs of-      Right uri' -> do-        (https', host', fullPath', port') <- liftE $ uriToQuadruple uri'-        go (redirs - 1) https' host' fullPath' port'-      Left e -> throwE e   withConnection' :: Bool
lib/GHCup/Errors.hs view
@@ -4,7 +4,6 @@ {-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE StandaloneDeriving #-}-{-# LANGUAGE QuasiQuotes           #-} {-# LANGUAGE TypeOperators           #-} {-# LANGUAGE FlexibleInstances           #-} @@ -15,29 +14,28 @@ License     : LGPL-3.0 Maintainer  : hasufell@hasufell.de Stability   : experimental-Portability : POSIX+Portability : portable -} module GHCup.Errors where  import           GHCup.Types-import           GHCup.Utils.Prelude -#if !defined(TAR) import           Codec.Archive-#endif import           Control.Exception.Safe import           Data.ByteString                ( ByteString )-import           Data.String.Interpolate+import           Data.CaseInsensitive           ( CI ) import           Data.Text                      ( Text ) import           Data.Versions-import           HPath import           Haskus.Utils.Variant-import           Text.PrettyPrint-import           Text.PrettyPrint.HughesPJClass+import           Text.PrettyPrint               hiding ( (<>) )+import           Text.PrettyPrint.HughesPJClass hiding ( (<>) ) import           URI.ByteString +import qualified Data.Map.Strict               as M+import qualified Data.Text                     as T  +     ------------------------     --[ Low-level errors ]--     ------------------------@@ -52,7 +50,7 @@   pPrint (NoCompatiblePlatform str') =     text ("Could not find a compatible platform. Got: " ++ str') --- | Unable to find a download for the requested versio/distro.+-- | Unable to find a download for the requested version/distro. data NoDownload = NoDownload   deriving Show @@ -84,12 +82,12 @@     text "Unable to figure out the distribution of the host."  -- | The archive format is unknown. We don't know how to extract it.-data UnknownArchive = UnknownArchive ByteString+data UnknownArchive = UnknownArchive FilePath   deriving Show  instance Pretty UnknownArchive where   pPrint (UnknownArchive file) =-    text [i|The archive format is unknown. We don't know how to extract the file "#{decUTF8Safe file}"|]+    text $ "The archive format is unknown. We don't know how to extract the file " <> file  -- | The scheme is not supported (such as ftp). data UnsupportedScheme = UnsupportedScheme@@ -112,7 +110,7 @@  instance Pretty TagNotFound where   pPrint (TagNotFound tag tool) =-    text "Unable to find tag" <+> pPrint tag <+> text [i|of tool "#{tool}"|]+    text "Unable to find tag" <+> pPrint tag <+> text "of tool" <+> pPrint tool  -- | Unable to find the next version of a tool (the one after the currently -- set one).@@ -121,7 +119,7 @@  instance Pretty NextVerNotFound where   pPrint (NextVerNotFound tool) =-    text [i|Unable to find next (the one after the currently set one) version of tool "#{tool}"|]+    text "Unable to find next (the one after the currently set one) version of tool" <+> pPrint tool  -- | The tool (such as GHC) is already installed with that version. data AlreadyInstalled = AlreadyInstalled Tool Version@@ -129,8 +127,15 @@  instance Pretty AlreadyInstalled where   pPrint (AlreadyInstalled tool ver') =-    text [i|#{tool}-#{prettyShow ver'} is already installed|]+    pPrint tool <+> text "-" <+> pPrint ver' <+> text "is already installed" +-- | The Directory is supposed to be empty, but wasn't.+data DirNotEmpty = DirNotEmpty {path :: FilePath}++instance Pretty DirNotEmpty where+  pPrint (DirNotEmpty path) = do+    text $ "The directory was expected to be empty, but isn't: " <> path+ -- | The tool is not installed. Some operations rely on a tool -- to be installed (such as setting the current GHC version). data NotInstalled = NotInstalled Tool GHCTargetVersion@@ -138,15 +143,15 @@  instance Pretty NotInstalled where   pPrint (NotInstalled tool ver) =-    text [i|The version "#{prettyShow ver}" of the tool "#{tool}" is not installed.|]+    text "The version" <+> pPrint ver <+> text "of the tool" <+> pPrint tool <+> text "is not installed."  -- | An executable was expected to be in PATH, but was not found.-data NotFoundInPATH = NotFoundInPATH (Path Rel)+data NotFoundInPATH = NotFoundInPATH FilePath   deriving Show  instance Pretty NotFoundInPATH where   pPrint (NotFoundInPATH exe) =-    text [i|The exe "#{decUTF8Safe . toFilePath $ exe}" was not found in PATH.|]+    text $ "The exe " <> exe <> " was not found in PATH."  -- | JSON decoding failed. data JSONError = JSONDecodeError String@@ -154,17 +159,27 @@  instance Pretty JSONError where   pPrint (JSONDecodeError err) =-    text [i|JSON decoding failed with: #{err}|]+    text $ "JSON decoding failed with: " <> err  -- | A file that is supposed to exist does not exist -- (e.g. when we use file scheme to "download" something).-data FileDoesNotExistError = FileDoesNotExistError ByteString+data FileDoesNotExistError = FileDoesNotExistError FilePath   deriving Show  instance Pretty FileDoesNotExistError where   pPrint (FileDoesNotExistError file) =-    text [i|File "#{decUTF8Safe file}" does not exist.|]+    text $ "File " <> file <> " does not exist." +-- | The file already exists+-- (e.g. when we use isolated installs with the same path).+-- (e.g. This is done to prevent any overwriting)+data FileAlreadyExistsError = FileAlreadyExistsError FilePath+  deriving Show++instance Pretty FileAlreadyExistsError where+  pPrint (FileAlreadyExistsError file) =+    text $ "File " <> file <> " Already exists."+ data TarDirDoesNotExist = TarDirDoesNotExist TarDir   deriving Show @@ -173,28 +188,54 @@     text "Tar directory does not exist:" <+> pPrint dir  -- | File digest verification failed.-data DigestError = DigestError Text Text+data DigestError = DigestError FilePath Text Text   deriving Show  instance Pretty DigestError where-  pPrint (DigestError currentDigest expectedDigest) =-    text [i|Digest error: expected "#{expectedDigest}", but got "#{currentDigest}"|]+  pPrint (DigestError fp currentDigest expectedDigest) =+    text "Digest error for" <+> text (fp <> ": expected")+      <+> text (T.unpack expectedDigest) <+> text "but got" <+> pPrint currentDigest <+> text+      "\nConsider removing the file in case it's cached and try again." +-- | File digest verification failed.+data GPGError = forall xs . (ToVariantMaybe DownloadFailed xs, PopVariant DownloadFailed xs, Show (V xs), Pretty (V xs)) => GPGError (V xs)++deriving instance Show GPGError++instance Pretty GPGError where+  pPrint (GPGError reason) = text "GPG verify failed:" <+> pPrint reason+ -- | Unexpected HTTP status.-data HTTPStatusError = HTTPStatusError Int+data HTTPStatusError = HTTPStatusError Int (M.Map (CI ByteString) ByteString)   deriving Show  instance Pretty HTTPStatusError where-  pPrint (HTTPStatusError status) =-    text [i|Unexpected HTTP status: #{status}|]+  pPrint (HTTPStatusError status _) =+    text "Unexpected HTTP status:" <+> pPrint status +-- | Malformed headers.+data MalformedHeaders = MalformedHeaders Text+  deriving Show++instance Pretty MalformedHeaders where+  pPrint (MalformedHeaders h) =+    text "Headers are malformed: " <+> pPrint h++-- | Unexpected HTTP status.+data HTTPNotModified = HTTPNotModified Text+  deriving Show++instance Pretty HTTPNotModified where+  pPrint (HTTPNotModified etag) =+    text "Remote resource not modifed, etag was:" <+> pPrint etag+ -- | The 'Location' header was expected during a 3xx redirect, but not found. data NoLocationHeader = NoLocationHeader   deriving Show  instance Pretty NoLocationHeader where   pPrint NoLocationHeader =-    text [i|The 'Location' header was expected during a 3xx redirect, but not found.|]+    text "The 'Location' header was expected during a 3xx redirect, but not found."  -- | Too many redirects. data TooManyRedirs = TooManyRedirs@@ -202,7 +243,7 @@  instance Pretty TooManyRedirs where   pPrint TooManyRedirs =-    text [i|Too many redirections.|]+    text "Too many redirections."  -- | A patch could not be applied. data PatchFailed = PatchFailed@@ -210,7 +251,7 @@  instance Pretty PatchFailed where   pPrint PatchFailed =-    text [i|A patch could not be applied.|]+    text "A patch could not be applied."  -- | The tool requirements could not be found. data NoToolRequirements = NoToolRequirements@@ -218,53 +259,73 @@  instance Pretty NoToolRequirements where   pPrint NoToolRequirements =-    text [i|The Tool requirements could not be found.|]+    text "The Tool requirements could not be found."  data InvalidBuildConfig = InvalidBuildConfig Text   deriving Show  instance Pretty InvalidBuildConfig where   pPrint (InvalidBuildConfig reason) =-    text [i|The build config is invalid. Reason was: #{reason}|]+    text "The build config is invalid. Reason was:" <+> pPrint reason  data NoToolVersionSet = NoToolVersionSet Tool   deriving Show  instance Pretty NoToolVersionSet where   pPrint (NoToolVersionSet tool) =-    text [i|No version is set for tool "#{tool}".|]+    text "No version is set for tool" <+> pPrint tool <+> text "." +data NoNetwork = NoNetwork+  deriving Show +instance Pretty NoNetwork where+  pPrint NoNetwork =+    text "A download was required or requested, but '--offline' was specified."++data HadrianNotFound = HadrianNotFound+  deriving Show++instance Pretty HadrianNotFound where+  pPrint HadrianNotFound =+    text "Could not find Hadrian build files. Does this GHC version support Hadrian builds?"++     -------------------------     --[ High-level errors ]--     -------------------------  -- | A download failed. The underlying error is encapsulated.-data DownloadFailed = forall x xs . (Show x, Show (V xs), Pretty x, Pretty (V xs)) => DownloadFailed (V (x ': xs))+data DownloadFailed = forall xs . (ToVariantMaybe DownloadFailed xs, PopVariant DownloadFailed xs, Show (V xs), Pretty (V xs)) => DownloadFailed (V xs)  instance Pretty DownloadFailed where   pPrint (DownloadFailed reason) =-    text "Download failed:" <+> pPrint reason+    case reason of+      VMaybe (_ :: DownloadFailed) -> pPrint reason+      _ -> text "Download failed:" <+> pPrint reason  deriving instance Show DownloadFailed   -- | A build failed.-data BuildFailed = forall es . Show (V es) => BuildFailed (Path Abs) (V es)+data BuildFailed = forall es . (ToVariantMaybe BuildFailed es, PopVariant BuildFailed es, Pretty (V es), Show (V es)) => BuildFailed FilePath (V es)  instance Pretty BuildFailed where   pPrint (BuildFailed path reason) =-    text [i|BuildFailed failed in dir "#{decUTF8Safe . toFilePath $ path}": #{reason}|]+    case reason of+      VMaybe (_ :: BuildFailed) -> pPrint reason+      _ -> text "BuildFailed failed in dir" <+> text (path <> ":") <+> pPrint reason  deriving instance Show BuildFailed   -- | Setting the current GHC version failed.-data GHCupSetError = forall es . Show (V es) => GHCupSetError (V es)+data GHCupSetError = forall es . (ToVariantMaybe GHCupSetError es, PopVariant GHCupSetError es, Show (V es), Pretty (V es)) => GHCupSetError (V es)  instance Pretty GHCupSetError where   pPrint (GHCupSetError reason) =-    text [i|Setting the current GHC version failed: #{reason}|]+    case reason of+      VMaybe (_ :: GHCupSetError) -> pPrint reason+      _ -> text "Setting the current GHC version failed:" <+> pPrint reason  deriving instance Show GHCupSetError @@ -280,7 +341,7 @@  instance Pretty ParseError where   pPrint (ParseError reason) =-    text [i|Parsing failed: #{reason}|]+    text "Parsing failed:" <+> pPrint reason  instance Exception ParseError @@ -290,12 +351,21 @@  instance Pretty UnexpectedListLength where   pPrint (UnexpectedListLength reason) =-    text [i|List length unexpected: #{reason}|]+    text "List length unexpected:" <+> pPrint reason  instance Exception UnexpectedListLength +data NoUrlBase = NoUrlBase Text+  deriving Show +instance Pretty NoUrlBase where+  pPrint (NoUrlBase url) =+    text "Couldn't get a base filename from url" <+> pPrint url +instance Exception NoUrlBase+++     ------------------------     --[ orphan instances ]--     ------------------------@@ -315,23 +385,22 @@  instance Pretty URIParseError where   pPrint (MalformedScheme reason) =-    text [i|Failed to parse URI. Malformed scheme: #{reason}|]+    text "Failed to parse URI. Malformed scheme:" <+> text (show reason)   pPrint MalformedUserInfo =-    text [i|Failed to parse URI. Malformed user info.|]+    text "Failed to parse URI. Malformed user info."   pPrint MalformedQuery =-    text [i|Failed to parse URI. Malformed query.|]+    text "Failed to parse URI. Malformed query."   pPrint MalformedFragment =-    text [i|Failed to parse URI. Malformed fragment.|]+    text "Failed to parse URI. Malformed fragment."   pPrint MalformedHost =-    text [i|Failed to parse URI. Malformed host.|]+    text "Failed to parse URI. Malformed host."   pPrint MalformedPort =-    text [i|Failed to parse URI. Malformed port.|]+    text "Failed to parse URI. Malformed port."   pPrint MalformedPath =-    text [i|Failed to parse URI. Malformed path.|]+    text "Failed to parse URI. Malformed path."   pPrint (OtherError err) =-    text [i|Failed to parse URI: #{err}|]+    text "Failed to parse URI:" <+> pPrint err -#if !defined(TAR) instance Pretty ArchiveResult where   pPrint ArchiveFatal = text "Archive result: fatal"   pPrint ArchiveFailed = text "Archive result: failed"@@ -339,4 +408,6 @@   pPrint ArchiveRetry = text "Archive result: retry"   pPrint ArchiveOk = text "Archive result: Ok"   pPrint ArchiveEOF = text "Archive result: EOF"-#endif++instance Pretty T.Text where+  pPrint = text . T.unpack
lib/GHCup/Platform.hs view
@@ -13,49 +13,52 @@ License     : LGPL-3.0 Maintainer  : hasufell@hasufell.de Stability   : experimental-Portability : POSIX+Portability : portable -} module GHCup.Platform where   import           GHCup.Errors import           GHCup.Types+import           GHCup.Types.Optics import           GHCup.Types.JSON               ( ) import           GHCup.Utils.File+import           GHCup.Utils.Logger import           GHCup.Utils.Prelude import           GHCup.Utils.String.QQ  import           Control.Applicative import           Control.Exception.Safe import           Control.Monad-import           Control.Monad.Logger import           Control.Monad.Reader import           Data.ByteString                ( ByteString ) import           Data.Foldable import           Data.Maybe-import           Data.String.Interpolate import           Data.Text                      ( Text ) import           Data.Versions-import           HPath-import           HPath.IO import           Haskus.Utils.Variant.Excepts import           Prelude                 hiding ( abs                                                 , readFile                                                 , writeFile                                                 ) import           System.Info+import           System.Directory import           System.OsRelease+import           Text.PrettyPrint.HughesPJClass ( prettyShow ) import           Text.Regex.Posix  import qualified Data.Text                     as T+import qualified Data.Text.IO                  as T ++     --------------------------     --[ Platform detection ]--     --------------------------   -- | Get the full platform request, consisting of architecture, distro, ...-platformRequest :: (MonadLogger m, MonadCatch m, MonadIO m)+platformRequest :: (MonadReader env m, Alternative m, MonadFail m, HasLog env, MonadCatch m, MonadIO m)                 => Excepts                      '[NoCompatiblePlatform, NoCompatibleArch, DistroNotFound]                      m@@ -80,7 +83,7 @@   what          -> Left (NoCompatibleArch what)  -getPlatform :: (MonadLogger m, MonadCatch m, MonadIO m)+getPlatform :: (Alternative m, MonadReader env m, HasLog env, MonadCatch m, MonadIO m, MonadFail m)             => Excepts                  '[NoCompatiblePlatform, DistroNotFound]                  m@@ -95,36 +98,34 @@         either (const Nothing) Just           . versioning           -- TODO: maybe do this somewhere else-          . getMajorVersion-          . decUTF8Safe+          . decUTF8Safe'         <$> getDarwinVersion       pure $ PlatformResult { _platform = Darwin, _distroVersion = ver }     "freebsd" -> do       ver <--        either (const Nothing) Just . versioning . decUTF8Safe+        either (const Nothing) Just . versioning . decUTF8Safe'           <$> getFreeBSDVersion       pure $ PlatformResult { _platform = FreeBSD, _distroVersion = ver }+    "mingw32" -> pure PlatformResult { _platform = Windows, _distroVersion = Nothing }     what -> throwE $ NoCompatiblePlatform what-  lift $ $(logDebug) [i|Identified Platform as: #{pfr}|]+  lift $ logDebug $ "Identified Platform as: " <> T.pack (prettyShow pfr)   pure pfr  where-  getMajorVersion = T.intercalate "." . take 2 . T.split (== '.')-  getFreeBSDVersion =-    liftIO $ fmap _stdOut $ executeOut [rel|freebsd-version|] [] Nothing-  getDarwinVersion = liftIO $ fmap _stdOut $ executeOut [rel|sw_vers|]+  getFreeBSDVersion = lift $ fmap _stdOut $ executeOut "freebsd-version" [] Nothing+  getDarwinVersion = lift $ fmap _stdOut $ executeOut "sw_vers"                                                         ["-productVersion"]                                                         Nothing  -getLinuxDistro :: (MonadCatch m, MonadIO m)+getLinuxDistro :: (Alternative m, MonadCatch m, MonadIO m, MonadFail m)                => Excepts '[DistroNotFound] m (LinuxDistro, Maybe Versioning) getLinuxDistro = do   -- TODO: don't do alternative on IO, because it hides bugs-  (name, ver) <- handleIO (\_ -> throwE DistroNotFound) $ liftIO $ asum-    [ try_os_release+  (name, ver) <- handleIO (\_ -> throwE DistroNotFound) $ lift $ asum+    [ liftIO try_os_release     , try_lsb_release_cmd-    , try_redhat_release-    , try_debian_version+    , liftIO try_redhat_release+    , liftIO try_debian_version     ]   let parsedVer = ver >>= either (const Nothing) Just . versioning       distro    = if@@ -141,18 +142,16 @@         | otherwise                -> UnknownLinux   pure (distro, parsedVer)  where-  hasWord t matches = foldr (\x y -> match (regex x) (T.unpack t) || y)-                            False-                            matches+  hasWord t = any (\x -> match (regex x) (T.unpack t))    where     regex x = makeRegexOpts compIgnoreCase execBlank ([s|\<|] ++ x ++ [s|\>|]) -  lsb_release_cmd :: Path Rel-  lsb_release_cmd = [rel|lsb-release|]-  redhat_release :: Path Abs-  redhat_release = [abs|/etc/redhat-release|]-  debian_version :: Path Abs-  debian_version = [abs|/etc/debian_version|]+  lsb_release_cmd :: FilePath+  lsb_release_cmd = "lsb-release"+  redhat_release :: FilePath+  redhat_release = "/etc/redhat-release"+  debian_version :: FilePath+  debian_version = "/etc/debian_version"    try_os_release :: IO (Text, Maybe Text)   try_os_release = do@@ -160,16 +159,17 @@       fmap osRelease <$> parseOsRelease     pure (T.pack name, fmap T.pack version_id) -  try_lsb_release_cmd :: IO (Text, Maybe Text)+  try_lsb_release_cmd :: (MonadFail m, MonadIO m)+                      => m (Text, Maybe Text)   try_lsb_release_cmd = do-    (Just _) <- findExecutable lsb_release_cmd+    (Just _) <- liftIO $ findExecutable lsb_release_cmd     name     <- fmap _stdOut $ executeOut lsb_release_cmd ["-si"] Nothing     ver      <- fmap _stdOut $ executeOut lsb_release_cmd ["-sr"] Nothing-    pure (decUTF8Safe name, Just $ decUTF8Safe ver)+    pure (decUTF8Safe' name, Just $ decUTF8Safe' ver)    try_redhat_release :: IO (Text, Maybe Text)   try_redhat_release = do-    t <- fmap decUTF8Safe' $ readFile redhat_release+    t <- T.readFile redhat_release     let nameRegex n =           makeRegexOpts compIgnoreCase                         execBlank@@ -191,5 +191,5 @@    try_debian_version :: IO (Text, Maybe Text)   try_debian_version = do-    ver <- readFile debian_version-    pure (T.pack "debian", Just . decUTF8Safe' $ ver)+    ver <- T.readFile debian_version+    pure (T.pack "debian", Just ver)
lib/GHCup/Requirements.hs view
@@ -7,7 +7,7 @@ License     : LGPL-3.0 Maintainer  : hasufell@hasufell.de Stability   : experimental-Portability : POSIX+Portability : portable -} module GHCup.Requirements where @@ -60,9 +60,10 @@ prettyRequirements :: Requirements -> T.Text prettyRequirements Requirements {..} =   let d = if not . null $ _distroPKGs-        then-          "\n  Please install the following distro packages: "-            <> T.intercalate " " _distroPKGs+        then "\n  Please ensure the following distro packages "+          <> "are installed before continuing (you can exit ghcup "+          <> "and return at any time): "+          <> T.intercalate " " _distroPKGs         else ""       n = if not . T.null $ _notes then "\n  Note: " <> _notes else ""   in  "System requirements " <> d <> n
lib/GHCup/Types.hs view
@@ -1,8 +1,12 @@ {-# OPTIONS_GHC -Wno-orphans #-} {-# LANGUAGE CPP               #-}+{-# LANGUAGE BangPatterns      #-}+{-# LANGUAGE DataKinds         #-} {-# LANGUAGE DeriveGeneric     #-} {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE QuasiQuotes           #-}+{-# LANGUAGE FlexibleContexts  #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE DuplicateRecordFields #-}  {-| Module      : GHCup.Types@@ -11,27 +15,41 @@ License     : LGPL-3.0 Maintainer  : hasufell@hasufell.de Stability   : experimental-Portability : POSIX+Portability : portable -}-module GHCup.Types where+module GHCup.Types+  ( module GHCup.Types+#if defined(BRICK)+  , Key(..)+#endif+  )+  where +import           Control.DeepSeq                ( NFData, rnf ) import           Data.Map.Strict                ( Map ) import           Data.List.NonEmpty             ( NonEmpty (..) )-import           Data.String.Interpolate import           Data.Text                      ( Text ) import           Data.Versions-import           HPath import           Text.PrettyPrint.HughesPJClass (Pretty, pPrint, text) import           URI.ByteString+#if defined(BRICK)+import           Graphics.Vty                   ( Key(..) )+#endif  import qualified Data.Text                     as T-import qualified Data.Text.Encoding            as E-import qualified Data.Text.Encoding.Error      as E import qualified GHC.Generics                  as GHC-import qualified Graphics.Vty                  as Vty  +#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 +     --------------------     --[ GHCInfo Tree ]--     --------------------@@ -40,11 +58,14 @@ data GHCupInfo = GHCupInfo   { _toolRequirements :: ToolRequirements   , _ghcupDownloads   :: GHCupDownloads+  , _globalTools      :: Map GlobalTool DownloadInfo   }   deriving (Show, GHC.Generic) +instance NFData GHCupInfo  +     -------------------------     --[ Requirements Tree ]--     -------------------------@@ -62,10 +83,12 @@   }   deriving (Show, GHC.Generic) +instance NFData Requirements    +     ---------------------     --[ Download Tree ]--     ---------------------@@ -85,9 +108,24 @@           | Cabal           | GHCup           | HLS+          | Stack   deriving (Eq, GHC.Generic, Ord, Show, Enum, Bounded) +instance Pretty Tool where+  pPrint GHC = text "ghc"+  pPrint Cabal = text "cabal"+  pPrint GHCup = text "ghcup"+  pPrint HLS = text "hls"+  pPrint Stack = text "stack" +instance NFData Tool++data GlobalTool = ShimGen+  deriving (Eq, GHC.Generic, Ord, Show, Enum, Bounded)++instance NFData GlobalTool++ -- | All necessary information of a tool version, including -- source download and per-architecture downloads. data VersionInfo = VersionInfo@@ -102,16 +140,20 @@   }   deriving (Eq, GHC.Generic, Show) +instance NFData VersionInfo + -- | A tag. These are currently attached to a version of a tool. data Tag = Latest          | Recommended          | Prerelease          | Base PVP-         | Old                -- ^ old version are hidden by default in TUI+         | Old                -- ^ old versions are hidden by default in TUI          | UnknownTag String  -- ^ used for upwardscompat          deriving (Ord, Eq, GHC.Generic, Show) -- FIXME: manual JSON instance +instance NFData Tag+ tagToString :: Tag -> String tagToString Recommended        = "recommended" tagToString Latest             = "latest"@@ -138,6 +180,8 @@                   | A_ARM64   deriving (Eq, GHC.Generic, Ord, Show) +instance NFData Architecture+ archToString :: Architecture -> String archToString A_64 = "x86_64" archToString A_32 = "i386"@@ -156,12 +200,17 @@               | Darwin               -- ^ must exit               | FreeBSD+              | Windows+              -- ^ must exit   deriving (Eq, GHC.Generic, Ord, Show) +instance NFData Platform+ platformToString :: Platform -> String platformToString (Linux distro) = "linux-" ++ distroToString distro platformToString Darwin = "darwin" platformToString FreeBSD = "freebsd"+platformToString Windows = "windows"  instance Pretty Platform where   pPrint = text . platformToString@@ -182,10 +231,12 @@                  -- ^ must exit   deriving (Eq, GHC.Generic, Ord, Show) +instance NFData LinuxDistro+ distroToString :: LinuxDistro -> String distroToString Debian = "debian" distroToString Ubuntu = "ubuntu"-distroToString Mint= "mint"+distroToString Mint = "mint" distroToString Fedora = "fedora" distroToString CentOS = "centos" distroToString RedHat = "redhat"@@ -208,6 +259,7 @@   }   deriving (Eq, Ord, GHC.Generic, Show) +instance NFData DownloadInfo   @@ -217,12 +269,14 @@   -- | How to descend into a tar archive.-data TarDir = RealDir (Path Rel)+data TarDir = RealDir FilePath             | RegexDir String     -- ^ will be compiled to regex, the first match will "win"             deriving (Eq, Ord, GHC.Generic, Show) +instance NFData TarDir+ instance Pretty TarDir where-  pPrint (RealDir path) = text [i|#{E.decodeUtf8With E.lenientDecode . toFilePath $ path}|]+  pPrint (RealDir path) = text path   pPrint (RegexDir regex) = text regex  @@ -233,7 +287,11 @@                | AddSource (Either GHCupInfo URI) -- ^ merge with GHCupURL                deriving (GHC.Generic, Show) +instance NFData URLSource+instance NFData (URIRef Absolute) where+  rnf (URI !_ !_ !_ !_ !_) = () + data UserSettings = UserSettings   { uCache       :: Maybe Bool   , uNoVerify    :: Maybe Bool@@ -242,54 +300,114 @@   , uDownloader  :: Maybe Downloader   , uKeyBindings :: Maybe UserKeyBindings   , uUrlSource   :: Maybe URLSource+  , uNoNetwork   :: Maybe Bool+  , uGPGSetting  :: Maybe GPGSetting   }   deriving (Show, GHC.Generic)  defaultUserSettings :: UserSettings-defaultUserSettings = UserSettings Nothing Nothing Nothing Nothing Nothing Nothing Nothing+defaultUserSettings = UserSettings Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing +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+    , uGPGSetting = Just gpgSetting+  }+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+    , uGPGSetting = Just gpgSetting+  }+ data UserKeyBindings = UserKeyBindings-  { kUp        :: Maybe Vty.Key-  , kDown      :: Maybe Vty.Key-  , kQuit      :: Maybe Vty.Key-  , kInstall   :: Maybe Vty.Key-  , kUninstall :: Maybe Vty.Key-  , kSet       :: Maybe Vty.Key-  , kChangelog :: Maybe Vty.Key-  , kShowAll   :: Maybe Vty.Key+  { 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-  { bUp        :: Vty.Key-  , bDown      :: Vty.Key-  , bQuit      :: Vty.Key-  , bInstall   :: Vty.Key-  , bUninstall :: Vty.Key-  , bSet       :: Vty.Key-  , bChangelog :: Vty.Key-  , bShowAll   :: Vty.Key+  { bUp        :: Key+  , bDown      :: Key+  , bQuit      :: Key+  , bInstall   :: Key+  , bUninstall :: Key+  , bSet       :: Key+  , bChangelog :: Key+  , bShowAllVersions :: Key+  , bShowAllTools :: Key   }   deriving (Show, GHC.Generic) +instance NFData KeyBindings+instance NFData Key+ defaultKeyBindings :: KeyBindings defaultKeyBindings = KeyBindings-  { bUp = Vty.KUp-  , bDown = Vty.KDown-  , bQuit = Vty.KChar 'q'-  , bInstall = Vty.KChar 'i'-  , bUninstall = Vty.KChar 'u'-  , bSet = Vty.KChar 's'-  , bChangelog = Vty.KChar 'c'-  , bShowAll = Vty.KChar 'a'+  { 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'   }  data AppState = AppState   { settings :: Settings   , dirs :: Dirs   , keyBindings :: KeyBindings-  } deriving (Show)+  , ghcupInfo :: GHCupInfo+  , pfreq :: PlatformRequest+  , loggerConfig :: LoggerConfig+  } deriving (Show, GHC.Generic) +instance NFData AppState++data LeanAppState = LeanAppState+  { settings :: Settings+  , dirs :: Dirs+  , keyBindings :: KeyBindings+  , loggerConfig :: LoggerConfig+  } deriving (Show, GHC.Generic)++instance NFData LeanAppState++ data Settings = Settings   { cache      :: Bool   , noVerify   :: Bool@@ -297,35 +415,54 @@   , downloader :: Downloader   , verbose    :: Bool   , urlSource  :: URLSource+  , noNetwork  :: Bool+  , gpgSetting :: GPGSetting+  , noColor    :: Bool -- this also exists in LoggerConfig   }   deriving (Show, GHC.Generic) +instance NFData Settings+ data Dirs = Dirs-  { baseDir  :: Path Abs-  , binDir   :: Path Abs-  , cacheDir :: Path Abs-  , logsDir  :: Path Abs-  , confDir  :: Path Abs+  { baseDir  :: FilePath+  , binDir   :: FilePath+  , cacheDir :: FilePath+  , logsDir  :: FilePath+  , confDir  :: FilePath+  , recycleDir :: FilePath -- mainly used on windows   }-  deriving Show+  deriving (Show, GHC.Generic) +instance NFData Dirs+ data KeepDirs = Always               | Errors               | Never-  deriving (Eq, Show, Ord)+  deriving (Eq, Show, Ord, GHC.Generic) +instance NFData KeepDirs+ data Downloader = Curl                 | Wget #if defined(INTERNAL_DOWNLOADER)                 | Internal #endif-  deriving (Eq, Show, Ord)+  deriving (Eq, Show, Ord, GHC.Generic) +instance NFData Downloader++data GPGSetting = GPGStrict+                | GPGLax+                | GPGNone+  deriving (Eq, Show, Ord, GHC.Generic)++instance NFData GPGSetting+ data DebugInfo = DebugInfo-  { diBaseDir  :: Path Abs-  , diBinDir   :: Path Abs-  , diGHCDir   :: Path Abs-  , diCacheDir :: Path Abs+  { diBaseDir  :: FilePath+  , diBinDir   :: FilePath+  , diGHCDir   :: FilePath+  , diCacheDir :: FilePath   , diArch     :: Architecture   , diPlatform :: PlatformResult   }@@ -342,8 +479,10 @@   { _platform      :: Platform   , _distroVersion :: Maybe Versioning   }-  deriving (Eq, Show)+  deriving (Eq, Show, GHC.Generic) +instance NFData PlatformResult+ platResToString :: PlatformResult -> String platResToString PlatformResult { _platform = plat, _distroVersion = Just v' }   = show plat <> ", " <> T.unpack (prettyV v')@@ -358,8 +497,10 @@   , _rPlatform :: Platform   , _rVersion  :: Maybe Versioning   }-  deriving (Eq, Show)+  deriving (Eq, Show, GHC.Generic) +instance NFData PlatformRequest+ pfReqToString :: PlatformRequest -> String pfReqToString (PlatformRequest arch plat ver) =   archToString arch ++ "-" ++ platformToString plat ++ pver@@ -379,6 +520,11 @@   }   deriving (Ord, Eq, Show) +data GitBranch = GitBranch+  { ref  :: String+  , repo :: Maybe String+  }+  deriving (Ord, Eq, Show)  mkTVer :: Version -> GHCTargetVersion mkTVer = GHCTargetVersion Nothing@@ -400,16 +546,43 @@                 | VR_eq Versioning   deriving (Eq, GHC.Generic, Ord, Show) +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) +instance NFData VersionRange  instance Pretty Versioning where   pPrint = text . T.unpack . prettyV  instance Pretty Version where   pPrint = text . T.unpack . prettyVer++instance Show (a -> b) where+  show _ = "<function>"++instance Show (IO ()) where+  show _ = "<io>"+++data LogLevel = Warn+              | Info+              | Debug+              | Error+  deriving (Eq, Ord, Show)++data LoggerConfig = LoggerConfig+  { lcPrintDebug   :: Bool            -- ^ whether to print debug in colorOutter+  , consoleOutter  :: T.Text -> IO () -- ^ how to write the console output+  , fileOutter     :: T.Text -> IO () -- ^ how to write the file output+  , fancyColors    :: Bool+  }+  deriving Show++instance NFData LoggerConfig where+  rnf (LoggerConfig !lcPrintDebug !_ !_ !fancyColors) = rnf (lcPrintDebug, fancyColors)
lib/GHCup/Types/JSON.hs view
@@ -17,13 +17,15 @@ License     : LGPL-3.0 Maintainer  : hasufell@hasufell.de Stability   : experimental-Portability : POSIX+Portability : portable -} module GHCup.Types.JSON where  import           GHCup.Types import           GHCup.Utils.MegaParsec import           GHCup.Utils.Prelude+import           GHCup.Utils.Logger             () -- TH is broken shite and needs GHCup.Utils.Logger for linking, although we don't depend on the file.+                                                   -- This is due to the boot file.  import           Control.Applicative            ( (<|>) ) import           Data.Aeson@@ -33,38 +35,28 @@ import           Data.Text.Encoding            as E import           Data.Versions import           Data.Void-import           Data.Word8-import           HPath import           URI.ByteString import           Text.Casing -import qualified Data.ByteString               as BS import qualified Data.List.NonEmpty            as NE import qualified Data.Text                     as T-import qualified Graphics.Vty                  as Vty import qualified Text.Megaparsec               as MP import qualified Text.Megaparsec.Char          as MPC  -deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } { fieldLabelModifier = removeLensFieldLabel } ''Architecture+deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''Architecture deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''LinuxDistro-deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''Mess+deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''VSep+deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''VUnit deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''MChunk deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''Platform+deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''Mess deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''SemVer deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''Tool-deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''VSep-deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''VUnit-deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''VersionInfo-deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''DownloadInfo-deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''GHCupInfo-deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''Requirements+deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''GlobalTool deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''KeepDirs deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''Downloader-deriveJSON defaultOptions { sumEncoding = ObjectWithSingleField } ''URLSource-deriveJSON defaultOptions { fieldLabelModifier = \str' -> maybe str' T.unpack . T.stripPrefix (T.pack "u-") . T.pack . kebab $ str' } ''UserSettings-deriveJSON defaultOptions { fieldLabelModifier = \str' -> maybe str' T.unpack . T.stripPrefix (T.pack "k-") . T.pack . kebab $ str' } ''UserKeyBindings-deriveJSON defaultOptions { sumEncoding = ObjectWithSingleField } ''Vty.Key+deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''GPGSetting  instance ToJSON Tag where   toJSON Latest             = String "Latest"@@ -128,11 +120,13 @@     Darwin  -> T.pack "Darwin"     FreeBSD -> T.pack "FreeBSD"     Linux d -> T.pack ("Linux_" <> show d)+    Windows -> T.pack "Windows"  instance FromJSONKey Platform where   fromJSONKey = FromJSONKeyTextParser $ \t -> if     | T.pack "Darwin" == t -> pure Darwin     | T.pack "FreeBSD" == t -> pure FreeBSD+    | T.pack "Windows" == t -> pure Windows     | T.pack "Linux_" `T.isPrefixOf` t -> case         T.stripPrefix (T.pack "Linux_") t       of@@ -199,19 +193,11 @@ instance FromJSONKey Tool where   fromJSONKey = genericFromJSONKey defaultJSONKeyOptions -instance ToJSON (Path Rel) where-  toJSON p = case and . fmap isAscii . BS.unpack $ fp of-    True  -> toJSON . decUTF8Safe $ fp-    False -> String "/not/a/valid/path"-    where fp = toFilePath p--instance FromJSON (Path Rel) where-  parseJSON = withText "HPath Rel" $ \t -> do-    let d = encodeUtf8 t-    case parseRel d of-      Right x -> pure x-      Left  e -> fail $ "Failure in HPath Rel (FromJSON)" <> show e+instance ToJSONKey GlobalTool where+  toJSONKey = genericToJSONKey defaultJSONKeyOptions +instance FromJSONKey GlobalTool where+  fromJSONKey = genericFromJSONKey defaultJSONKeyOptions  instance ToJSON TarDir where   toJSON (RealDir  p) = toJSON p@@ -322,3 +308,17 @@     just t = case MP.parse versionRangeP "" t of       Right x -> pure $ Just x       Left  e -> fail $ "Failure in (Maybe VersionRange) (FromJSONKey)" <> MP.errorBundlePretty e++++deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''Requirements+deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''DownloadInfo+deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''VersionInfo+deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''GHCupInfo+deriveJSON defaultOptions { sumEncoding = ObjectWithSingleField } ''URLSource+deriveJSON defaultOptions { sumEncoding = ObjectWithSingleField } ''Key+deriveJSON defaultOptions { fieldLabelModifier = \str' -> maybe str' T.unpack . T.stripPrefix (T.pack "k-") . T.pack . kebab $ str' } ''UserKeyBindings+deriveJSON defaultOptions { fieldLabelModifier = \str' -> maybe str' T.unpack . T.stripPrefix (T.pack "u-") . T.pack . kebab $ str' } ''UserSettings++deriveToJSON defaultOptions { fieldLabelModifier = kebab } ''Settings+deriveToJSON defaultOptions { fieldLabelModifier = drop 2 . kebab } ''KeyBindings -- move under key-bindings key
lib/GHCup/Types/Optics.hs view
@@ -1,4 +1,12 @@-{-# LANGUAGE TemplateHaskell #-}+{-# OPTIONS_GHC -Wno-orphans #-}+{-# LANGUAGE TemplateHaskell       #-}+{-# LANGUAGE ConstraintKinds       #-}+{-# LANGUAGE DataKinds             #-}+{-# LANGUAGE DuplicateRecordFields #-}+{-# LANGUAGE FlexibleContexts      #-}+{-# LANGUAGE AllowAmbiguousTypes   #-}+{-# LANGUAGE MultiParamTypeClasses   #-}+{-# LANGUAGE OverloadedStrings   #-}  {-| Module      : GHCup.Types.Optics@@ -7,16 +15,18 @@ License     : LGPL-3.0 Maintainer  : hasufell@hasufell.de Stability   : experimental-Portability : POSIX+Portability : portable -} module GHCup.Types.Optics where  import           GHCup.Types -import           Data.ByteString                ( ByteString )+import           Control.Monad.Reader+import           Data.ByteString         ( ByteString ) import           Optics import           URI.ByteString + makePrisms ''Tool makePrisms ''Architecture makePrisms ''LinuxDistro@@ -58,3 +68,95 @@  queryL' :: Lens' (URIRef a) Query queryL' = lensVL queryL++++    ----------------------+    --[ Lens utilities ]--+    ----------------------+++gets :: forall f a env m . (MonadReader env m, LabelOptic' f A_Lens env a)+     => m a+gets = asks (^. labelOptic @f)+++getAppState :: MonadReader AppState m => m AppState+getAppState = ask+++getLeanAppState :: ( MonadReader env m+                   , LabelOptic' "settings"    A_Lens env Settings+                   , LabelOptic' "dirs"        A_Lens env Dirs+                   , LabelOptic' "keyBindings" A_Lens env KeyBindings+                   , LabelOptic' "loggerConfig" A_Lens env LoggerConfig+                   )+                => m LeanAppState+getLeanAppState = do+  s <- gets @"settings"+  d <- gets @"dirs"+  k <- gets @"keyBindings"+  l <- gets @"loggerConfig"+  pure (LeanAppState s d k l)+++getSettings :: ( MonadReader env m+               , LabelOptic' "settings" A_Lens env Settings+               )+            => m Settings+getSettings = gets @"settings"+++getDirs :: ( MonadReader env m+           , LabelOptic' "dirs" A_Lens env Dirs+           )+        => m Dirs+getDirs = gets @"dirs"+++getLogCleanup :: ( MonadReader env m+                 , LabelOptic' "logCleanup" A_Lens env (IO ())+                 )+              => m (IO ())+getLogCleanup = gets @"logCleanup"+++getKeyBindings :: ( MonadReader env m+                  , LabelOptic' "keyBindings" A_Lens env KeyBindings+                  )+               => m KeyBindings+getKeyBindings = gets @"keyBindings"+++getGHCupInfo :: ( MonadReader env m+                , LabelOptic' "ghcupInfo" A_Lens env GHCupInfo+                )+             => m GHCupInfo+getGHCupInfo = gets @"ghcupInfo"+++getPlatformReq :: ( MonadReader env m+                  , LabelOptic' "pfreq" A_Lens env PlatformRequest+                  )+               => m PlatformRequest+getPlatformReq = gets @"pfreq"+++type HasSettings env = (LabelOptic' "settings" A_Lens env Settings)+type HasDirs env = (LabelOptic' "dirs" A_Lens env Dirs)+type HasKeyBindings env = (LabelOptic' "keyBindings" A_Lens env KeyBindings)+type HasGHCupInfo env = (LabelOptic' "ghcupInfo" A_Lens env GHCupInfo)+type HasPlatformReq env = (LabelOptic' "pfreq" A_Lens env PlatformRequest)+type HasLog env = (LabelOptic' "loggerConfig" A_Lens env LoggerConfig)+++getCache :: (MonadReader env m, HasSettings env) => m Bool+getCache = getSettings <&> cache+++getDownloader :: (MonadReader env m, HasSettings env) => m Downloader+getDownloader = getSettings <&> downloader+++instance LabelOptic "dirs" A_Lens Dirs Dirs Dirs Dirs where+  labelOptic = lens id (\_ d -> d)
lib/GHCup/Utils.hs view
@@ -14,870 +14,1160 @@ License     : LGPL-3.0 Maintainer  : hasufell@hasufell.de Stability   : experimental-Portability : POSIX--This module contains GHCup helpers specific to-installation and introspection of files/versions etc.--}-module GHCup.Utils-  ( module GHCup.Utils.Dirs-  , module GHCup.Utils-  )-where---import           GHCup.Errors-import           GHCup.Types-import           GHCup.Types.Optics-import           GHCup.Types.JSON               ( )-import           GHCup.Utils.Dirs-import           GHCup.Utils.File-import           GHCup.Utils.MegaParsec-import           GHCup.Utils.Prelude-import           GHCup.Utils.String.QQ--#if !defined(TAR)-import           Codec.Archive           hiding ( Directory )-#endif-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.Logger-import           Control.Monad.Reader-import           Data.ByteString                ( ByteString )-import           Data.Either-import           Data.Foldable-import           Data.List-import           Data.List.NonEmpty             ( NonEmpty( (:|) ))-import           Data.List.Split-import           Data.Maybe-import           Data.String.Interpolate-import           Data.Text                      ( Text )-import           Data.Versions-import           Data.Word8-import           GHC.IO.Exception-import           HPath-import           HPath.IO                hiding ( hideError )-import           Haskus.Utils.Variant.Excepts-import           Optics-import           Prelude                 hiding ( abs-                                                , readFile-                                                , writeFile-                                                )-import           Safe-import           System.IO.Error-import           System.Posix.FilePath          ( getSearchPath-                                                , takeFileName-                                                )-import           System.Posix.Files.ByteString  ( readSymbolicLink )-import           Text.Regex.Posix-import           URI.ByteString--#if defined(TAR)-import qualified Codec.Archive.Tar             as Tar-#endif-import qualified Codec.Compression.BZip        as BZip-import qualified Codec.Compression.GZip        as GZip-import qualified Codec.Compression.Lzma        as Lzma-import qualified Data.ByteString               as B-import qualified Data.ByteString.Lazy          as BL-import qualified Data.Map.Strict               as Map-#if !defined(TAR)-import qualified Data.Text                     as T-#endif-import qualified Data.Text.Encoding            as E-import qualified Text.Megaparsec               as MP------    -------------------------    --[ Symlink handling ]---    ----------------------------- | The symlink destination of a ghc tool.-ghcLinkDestination :: (MonadReader AppState m, MonadThrow m, MonadIO m)-                   => ByteString -- ^ the tool, such as 'ghc', 'haddock' etc.-                   -> GHCTargetVersion-                   -> m ByteString-ghcLinkDestination tool ver = do-  AppState { dirs = Dirs {..} } <- ask-  t <- parseRel tool-  ghcd <- ghcupGHCDir ver-  pure (relativeSymlink binDir (ghcd </> [rel|bin|] </> t))----- | Removes the minor GHC symlinks, e.g. ghc-8.6.5.-rmMinorSymlinks :: ( MonadReader AppState m-                   , MonadIO m-                   , MonadLogger m-                   , MonadThrow m-                   , MonadFail m-                   , MonadReader AppState m-                   )-                => GHCTargetVersion-                -> Excepts '[NotInstalled] m ()-rmMinorSymlinks tv@GHCTargetVersion{..} = do-  AppState { dirs = Dirs {..} } <- lift ask--  files                         <- liftE $ ghcToolFiles tv-  forM_ files $ \f -> do-    f_xyz <- liftIO $ parseRel (toFilePath f <> B.singleton _hyphen <> verToBS _tvVersion)-    let fullF = binDir </> f_xyz-    lift $ $(logDebug) [i|rm -f #{toFilePath fullF}|]-    liftIO $ hideError doesNotExistErrorType $ deleteFile fullF----- | Removes the set ghc version for the given target, if any.-rmPlain :: ( MonadReader AppState m-           , MonadLogger m-           , MonadThrow m-           , MonadFail m-           , MonadIO m-           )-        => Maybe Text -- ^ target-        -> Excepts '[NotInstalled] m ()-rmPlain target = do-  AppState { dirs = Dirs {..} } <- lift ask-  mtv                           <- lift $ ghcSet target-  forM_ mtv $ \tv -> do-    files <- liftE $ ghcToolFiles tv-    forM_ files $ \f -> do-      let fullF = binDir </> f-      lift $ $(logDebug) [i|rm -f #{toFilePath fullF}|]-      liftIO $ hideError doesNotExistErrorType $ deleteFile fullF-    -- old ghcup-    let hdc_file = binDir </> [rel|haddock-ghc|]-    lift $ $(logDebug) [i|rm -f #{toFilePath hdc_file}|]-    liftIO $ hideError doesNotExistErrorType $ deleteFile hdc_file----- | Remove the major GHC symlink, e.g. ghc-8.6.-rmMajorSymlinks :: ( MonadReader AppState m-                   , MonadIO m-                   , MonadLogger m-                   , MonadThrow m-                   , MonadFail m-                   , MonadReader AppState m-                   )-                => GHCTargetVersion-                -> Excepts '[NotInstalled] m ()-rmMajorSymlinks tv@GHCTargetVersion{..} = do-  AppState { dirs = Dirs {..} } <- lift ask-  (mj, mi) <- getMajorMinorV _tvVersion-  let v' = intToText mj <> "." <> intToText mi--  files                         <- liftE $ ghcToolFiles tv-  forM_ files $ \f -> do-    f_xyz <- liftIO $ parseRel (toFilePath f <> B.singleton _hyphen <> E.encodeUtf8 v')-    let fullF = binDir </> f_xyz-    lift $ $(logDebug) [i|rm -f #{toFilePath fullF}|]-    liftIO $ hideError doesNotExistErrorType $ deleteFile fullF-----    ------------------------------------    --[ Set/Installed introspection ]---    ---------------------------------------- | Whethe the given GHC versin is installed.-ghcInstalled :: (MonadIO m, MonadReader AppState m, MonadThrow m) => GHCTargetVersion -> m Bool-ghcInstalled ver = do-  ghcdir <- ghcupGHCDir ver-  liftIO $ doesDirectoryExist ghcdir----- | Whether the given GHC version is installed from source.-ghcSrcInstalled :: (MonadIO m, MonadReader AppState m, MonadThrow m) => GHCTargetVersion -> m Bool-ghcSrcInstalled ver = do-  ghcdir <- ghcupGHCDir ver-  liftIO $ doesFileExist (ghcdir </> ghcUpSrcBuiltFile)----- | Whether the given GHC version is set as the current.-ghcSet :: (MonadReader AppState m, MonadThrow m, MonadIO m)-       => Maybe Text   -- ^ the target of the GHC version, if any-                       --  (e.g. armv7-unknown-linux-gnueabihf)-       -> m (Maybe GHCTargetVersion)-ghcSet mtarget = do-  AppState {dirs = Dirs {..}} <- ask-  ghc    <- parseRel $ E.encodeUtf8 (maybe "ghc" (<> "-ghc") mtarget)-  let ghcBin = binDir </> ghc--  -- link destination is of the form ../ghc/<ver>/bin/ghc-  -- for old ghcup, it is ../ghc/<ver>/bin/ghc-<ver>-  liftIO $ handleIO' NoSuchThing (\_ -> pure Nothing) $ do-    link <- readSymbolicLink $ toFilePath ghcBin-    Just <$> ghcLinkVersion link--ghcLinkVersion :: MonadThrow m => ByteString -> m GHCTargetVersion-ghcLinkVersion bs = do-  t <- throwEither $ E.decodeUtf8' bs-  throwEither $ MP.parse parser "ghcLinkVersion" t- where-  parser =-      (do-         _    <- parseUntil1 (MP.chunk "/ghc/")-         _    <- MP.chunk "/ghc/"-         r    <- parseUntil1 (MP.chunk "/")-         rest <- MP.getInput-         MP.setInput r-         x <- ghcTargetVerP-         MP.setInput rest-         pure x-       )-      <* MP.chunk "/"-      <* MP.takeRest-      <* MP.eof----- | Get all installed GHCs by reading ~/.ghcup/ghc/<dir>.--- If a dir cannot be parsed, returns left.-getInstalledGHCs :: (MonadReader AppState m, MonadIO m) => m [Either (Path Rel) GHCTargetVersion]-getInstalledGHCs = do-  ghcdir <- ghcupGHCBaseDir-  fs     <- liftIO $ hideErrorDef [NoSuchThing] [] $ getDirsFiles' ghcdir-  forM fs $ \f -> case parseGHCupGHCDir f of-    Right r -> pure $ Right r-    Left  _ -> pure $ Left f----- | Get all installed cabals, by matching on @~\/.ghcup\/bin/cabal-*@.-getInstalledCabals :: (MonadLogger m, MonadReader AppState m, MonadIO m, MonadCatch m)-                   => m [Either (Path Rel) Version]-getInstalledCabals = do-  cs <- cabalSet -- for legacy cabal-  getInstalledCabals' cs---getInstalledCabals' :: (MonadLogger m, MonadReader AppState m, MonadIO m, MonadCatch m)-                   => Maybe Version-                   -> m [Either (Path Rel) Version]-getInstalledCabals' cs = do-  AppState {dirs = Dirs {..}} <- ask-  bins   <- liftIO $ handleIO (\_ -> pure []) $ findFiles-    binDir-    (makeRegexOpts compExtended execBlank ([s|^cabal-.*$|] :: ByteString))-  vs <- forM bins $ \f -> case fmap (version . decUTF8Safe) . B.stripPrefix "cabal-" . toFilePath $ f of-    Just (Right r) -> pure $ Right r-    Just (Left  _) -> pure $ Left f-    Nothing        -> pure $ Left f-  pure $ maybe vs (\x -> nub $ Right x:vs) cs----- | Whether the given cabal version is installed.-cabalInstalled :: (MonadLogger m, MonadIO m, MonadReader AppState m, MonadCatch m) => Version -> m Bool-cabalInstalled ver = do-  vers <- fmap rights getInstalledCabals-  pure $ elem ver vers----- Return the currently set cabal version, if any.-cabalSet :: (MonadLogger m, MonadReader AppState m, MonadIO m, MonadThrow m, MonadCatch m) => m (Maybe Version)-cabalSet = do-  AppState {dirs = Dirs {..}} <- ask-  let cabalbin = binDir </> [rel|cabal|]-  b        <- handleIO (\_ -> pure False) $ fmap (== SymbolicLink) $ liftIO $ getFileType cabalbin-  if-    | b -> do-      handleIO' NoSuchThing (\_ -> pure Nothing) $ do-        broken <- liftIO $ isBrokenSymlink cabalbin-        if broken-          then do-            $(logWarn) [i|Symlink #{cabalbin} is broken.|]-            pure Nothing-          else do-            link <- liftIO $ readSymbolicLink $ toFilePath cabalbin-            case linkVersion link of-              Right v -> pure $ Just v-              Left err -> do-                $(logWarn) [i|Failed to parse cabal symlink target with: "#{err}". The symlink #{toFilePath cabalbin} needs to point to valid cabal binary, such as 'cabal-3.4.0.0'.|]-                pure Nothing-    | otherwise -> do -- legacy behavior-      mc <- liftIO $ handleIO (\_ -> pure Nothing) $ fmap Just $ executeOut-        cabalbin-        ["--numeric-version"]-        Nothing-      fmap join $ forM mc $ \c -> if-        | not (B.null (_stdOut c)), _exitCode c == ExitSuccess -> do-          let reportedVer = fst . B.spanEnd (== _lf) . _stdOut $ c-          case version $ decUTF8Safe reportedVer of-            Left  e -> throwM e-            Right r -> pure $ Just r-        | otherwise -> pure Nothing- where-  -- We try to be extra permissive with link destination parsing,-  -- because of:-  --   https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/119-  linkVersion :: MonadThrow m => ByteString -> m Version-  linkVersion bs = do-    t <- throwEither $ E.decodeUtf8' bs-    throwEither $ MP.parse parser "" t--  parser-    =   MP.try (stripAbsolutePath *> cabalParse)-    <|> MP.try (stripRelativePath *> cabalParse)-    <|> cabalParse-  -- parses the version of "cabal-3.2.0.0" -> "3.2.0.0"-  cabalParse = MP.chunk "cabal-" *> version'-  -- parses any path component ending with path separator,-  -- e.g. "foo/"-  stripPathComponet = parseUntil1 "/" *> MP.chunk "/"-  -- parses an absolute path up until the last path separator,-  -- e.g. "/bar/baz/foo" -> "/bar/baz/", leaving "foo"-  stripAbsolutePath = MP.chunk "/" *> MP.many (MP.try stripPathComponet)-  -- parses a relative path up until the last path separator,-  -- e.g. "bar/baz/foo" -> "bar/baz/", leaving "foo"-  stripRelativePath = MP.many (MP.try stripPathComponet)------ | Get all installed hls, by matching on--- @~\/.ghcup\/bin/haskell-language-server-wrapper-<\hlsver\>@.-getInstalledHLSs :: (MonadReader AppState m, MonadIO m, MonadCatch m)-                 => m [Either (Path Rel) Version]-getInstalledHLSs = do-  AppState { dirs = Dirs {..} } <- ask-  bins                          <- liftIO $ handleIO (\_ -> pure []) $ findFiles-    binDir-    (makeRegexOpts compExtended-                   execBlank-                   ([s|^haskell-language-server-wrapper-.*$|] :: ByteString)-    )-  forM bins $ \f ->-    case-          fmap (version . decUTF8Safe) . B.stripPrefix "haskell-language-server-wrapper-" . toFilePath $ f-      of-        Just (Right r) -> pure $ Right r-        Just (Left  _) -> pure $ Left f-        Nothing        -> pure $ Left f----- | Whether the given HLS version is installed.-hlsInstalled :: (MonadIO m, MonadReader AppState m, MonadCatch m) => Version -> m Bool-hlsInstalled ver = do-  vers <- fmap rights getInstalledHLSs-  pure $ elem ver vers------ Return the currently set hls version, if any.-hlsSet :: (MonadReader AppState m, MonadIO m, MonadThrow m, MonadCatch m) => m (Maybe Version)-hlsSet = do-  AppState {dirs = Dirs {..}} <- ask-  let hlsBin = binDir </> [rel|haskell-language-server-wrapper|]--  liftIO $ handleIO' NoSuchThing (\_ -> pure Nothing) $ do-    broken <- isBrokenSymlink hlsBin-    if broken-      then pure Nothing-      else do-        link <- readSymbolicLink $ toFilePath hlsBin-        Just <$> linkVersion link- where-  linkVersion :: MonadThrow m => ByteString -> m Version-  linkVersion bs = do-    t <- throwEither $ E.decodeUtf8' bs-    throwEither $ MP.parse parser "" t-   where-    parser =-      MP.chunk "haskell-language-server-wrapper-" *> version'----- | Return the GHC versions the currently selected HLS supports.-hlsGHCVersions :: ( MonadReader AppState m-                  , MonadIO m-                  , MonadThrow m-                  , MonadCatch m-                  )-               => m [Version]-hlsGHCVersions = do-  h                             <- hlsSet-  vers                          <- forM h $ \h' -> do-    bins <- hlsServerBinaries h'-    pure $ fmap-      (version-        . decUTF8Safe-        . fromJust-        . B.stripPrefix "haskell-language-server-"-        . head-        . B.split _tilde-        . toFilePath-      )-      bins-  pure . rights . concat . maybeToList $ vers----- | Get all server binaries for an hls version, if any.-hlsServerBinaries :: (MonadReader AppState m, MonadIO m)-                  => Version-                  -> m [Path Rel]-hlsServerBinaries ver = do-  AppState { dirs = Dirs {..} } <- ask-  liftIO $ handleIO (\_ -> pure []) $ findFiles-    binDir-    (makeRegexOpts-      compExtended-      execBlank-      ([s|^haskell-language-server-.*~|] <> escapeVerRex ver <> [s|$|] :: ByteString-      )-    )----- | Get the wrapper binary for an hls version, if any.-hlsWrapperBinary :: (MonadReader AppState m, MonadThrow m, MonadIO m)-                 => Version-                 -> m (Maybe (Path Rel))-hlsWrapperBinary ver = do-  AppState { dirs = Dirs {..} } <- ask-  wrapper                       <- liftIO $ handleIO (\_ -> pure []) $ findFiles-    binDir-    (makeRegexOpts-      compExtended-      execBlank-      ([s|^haskell-language-server-wrapper-|] <> escapeVerRex ver <> [s|$|] :: ByteString-      )-    )-  case wrapper of-    []  -> pure Nothing-    [x] -> pure $ Just x-    _   -> throwM $ UnexpectedListLength-      "There were multiple hls wrapper binaries for a single version"----- | Get all binaries for an hls version, if any.-hlsAllBinaries :: (MonadReader AppState m, MonadIO m, MonadThrow m) => Version -> m [Path Rel]-hlsAllBinaries ver = do-  hls     <- hlsServerBinaries ver-  wrapper <- hlsWrapperBinary ver-  pure (maybeToList wrapper ++ hls)----- | Get the active symlinks for hls.-hlsSymlinks :: (MonadReader AppState m, MonadIO m, MonadCatch m) => m [Path Rel]-hlsSymlinks = do-  AppState { dirs = Dirs {..} } <- ask-  oldSyms                       <- liftIO $ handleIO (\_ -> pure []) $ findFiles-    binDir-    (makeRegexOpts compExtended-                   execBlank-                   ([s|^haskell-language-server-.*$|] :: ByteString)-    )-  filterM-    ( fmap (== SymbolicLink)-    . liftIO-    . getFileType-    . (binDir </>)-    )-    oldSyms----    ------------------------------------------    --[ Major version introspection (X.Y) ]---    ---------------------------------------------- | Extract (major, minor) from any version.-getMajorMinorV :: MonadThrow m => Version -> m (Int, Int)-getMajorMinorV Version {..} = case _vChunks of-  ((Digits x :| []) :| ((Digits y :| []):_)) -> pure (fromIntegral x, fromIntegral y)-  _ -> throwM $ ParseError "Could not parse X.Y from version"---matchMajor :: Version -> Int -> Int -> Bool-matchMajor v' major' minor' = case getMajorMinorV v' of-  Just (x, y) -> x == major' && y == minor'-  Nothing     -> False----- | Get the latest installed full GHC version that satisfies X.Y.--- This reads `ghcupGHCBaseDir`.-getGHCForMajor :: (MonadReader AppState m, MonadIO m, MonadThrow m)-               => Int        -- ^ major version component-               -> Int        -- ^ minor version component-               -> Maybe Text -- ^ the target triple-               -> m (Maybe GHCTargetVersion)-getGHCForMajor major' minor' mt = do-  ghcs <- rights <$> getInstalledGHCs--  pure-    . lastMay-    . sortBy (\x y -> compare (_tvVersion x) (_tvVersion y))-    . filter-        (\GHCTargetVersion {..} ->-          _tvTarget == mt && matchMajor _tvVersion major' minor'-        )-    $ ghcs----- | Get the latest available ghc for X.Y major version.-getLatestGHCFor :: Int -- ^ major version component-                -> Int -- ^ minor version component-                -> GHCupDownloads-                -> Maybe (Version, VersionInfo)-getLatestGHCFor major' minor' dls =-  preview (ix GHC % to Map.toDescList) dls >>= lastMay . filter (\(v, _) -> matchMajor v major' minor')-----    ------------------    --[ Unpacking ]---    ----------------------- | Unpack an archive to a temporary directory and return that path.-unpackToDir :: (MonadLogger m, MonadIO m, MonadThrow m)-            => Path Abs       -- ^ destination dir-            -> Path Abs       -- ^ archive path-            -> Excepts '[UnknownArchive-#if !defined(TAR)-                        , ArchiveResult-#endif-                        ] m ()-unpackToDir dest av = do-  fp <- decUTF8Safe . toFilePath <$> basename av-  let dfp = decUTF8Safe . toFilePath $ dest-  lift $ $(logInfo) [i|Unpacking: #{fp} to #{dfp}|]-  fn <- toFilePath <$> basename av--#if defined(TAR)-  let untar :: MonadIO m => BL.ByteString -> Excepts '[] m ()-      untar = liftIO . Tar.unpack (toFilePath dest) . Tar.read--      rf :: MonadIO m => Path Abs -> Excepts '[] m BL.ByteString-      rf = liftIO . readFile-#else-  let untar :: MonadIO m => BL.ByteString -> Excepts '[ArchiveResult] m ()-      untar = lEM . liftIO . runArchiveM . unpackToDirLazy (T.unpack . decUTF8Safe . toFilePath $ dest)--      rf :: MonadIO m => Path Abs -> Excepts '[ArchiveResult] m BL.ByteString-      rf = liftIO . readFile-#endif--  -- extract, depending on file extension-  if-    | ".tar.gz" `B.isSuffixOf` fn -> liftE-      (untar . GZip.decompress =<< rf av)-    | ".tar.xz" `B.isSuffixOf` fn -> do-      filecontents <- liftE $ rf av-      let decompressed = Lzma.decompress filecontents-      liftE $ untar decompressed-    | ".tar.bz2" `B.isSuffixOf` fn ->-      liftE (untar . BZip.decompress =<< rf av)-    | ".tar" `B.isSuffixOf` fn -> liftE (untar =<< rf av)-    | otherwise -> throwE $ UnknownArchive fn---getArchiveFiles :: (MonadLogger m, MonadIO m, MonadThrow m)-                => Path Abs       -- ^ archive path-                -> Excepts '[UnknownArchive-#if defined(TAR)-                            , Tar.FormatError-#else-                            , ArchiveResult-#endif-                            ] m [ByteString]-getArchiveFiles av = do-  fn <- toFilePath <$> basename av--#if defined(TAR)-  let entries :: Monad m => BL.ByteString -> Excepts '[Tar.FormatError] m [ByteString]-      entries =-          lE @Tar.FormatError-          . Tar.foldEntries-            (\e x -> fmap (Tar.entryPath e :) x)-            (Right [])-            (\e -> Left e)-          . Tar.read--      rf :: MonadIO m => Path Abs -> Excepts '[Tar.FormatError] m BL.ByteString-      rf = liftIO . readFile-#else-  let entries :: Monad m => BL.ByteString -> Excepts '[ArchiveResult] m [ByteString]-      entries = (fmap . fmap) (E.encodeUtf8 . T.pack . filepath) . lE . readArchiveBSL--      rf :: MonadIO m => Path Abs -> Excepts '[ArchiveResult] m BL.ByteString-      rf = liftIO . readFile-#endif--  -- extract, depending on file extension-  if-    | ".tar.gz" `B.isSuffixOf` fn -> liftE-      (entries . GZip.decompress =<< rf av)-    | ".tar.xz" `B.isSuffixOf` fn -> do-      filecontents <- liftE $ rf av-      let decompressed = Lzma.decompress filecontents-      liftE $ entries decompressed-    | ".tar.bz2" `B.isSuffixOf` fn ->-      liftE (entries . BZip.decompress =<< rf av)-    | ".tar" `B.isSuffixOf` fn -> liftE (entries =<< rf av)-    | otherwise -> throwE $ UnknownArchive fn---intoSubdir :: (MonadLogger m, MonadIO m, MonadThrow m, MonadCatch m)-           => Path Abs       -- ^ unpacked tar dir-           -> TarDir         -- ^ how to descend-           -> Excepts '[TarDirDoesNotExist] m (Path Abs)-intoSubdir bdir tardir = case tardir of-  RealDir pr -> do-    whenM (fmap not . liftIO . doesDirectoryExist $ (bdir </> pr))-          (throwE $ TarDirDoesNotExist tardir)-    pure (bdir </> pr)-  RegexDir r -> do-    let rs = splitOn "/" r-    foldlM-      (\y x ->-        (handleIO (\_ -> pure []) . liftIO . findFiles y . regex $ x) >>= (\case-          []      -> throwE $ TarDirDoesNotExist tardir-          (p : _) -> pure (y </> p)) . sort-      )-      bdir-      rs-    where regex = makeRegexOpts compIgnoreCase execBlank-----    -------------    --[ Tags ]---    ----------------- | Get the tool version that has this tag. If multiple have it,--- picks the greatest version.-getTagged :: Tag-          -> AffineFold (Map.Map Version VersionInfo) (Version, VersionInfo)-getTagged tag =-  to (Map.filter (\VersionInfo {..} -> tag `elem` _viTags))-  % to Map.toDescList-  % _head--getLatest :: GHCupDownloads -> Tool -> Maybe (Version, VersionInfo)-getLatest av tool = headOf (ix tool % getTagged Latest) av--getRecommended :: GHCupDownloads -> Tool -> Maybe (Version, VersionInfo)-getRecommended av tool = headOf (ix tool % getTagged Recommended) av----- | Gets the latest GHC with a given base version.-getLatestBaseVersion :: GHCupDownloads -> PVP -> Maybe (Version, VersionInfo)-getLatestBaseVersion av pvpVer =-  headOf (ix GHC % getTagged (Base pvpVer)) av----    ------------------------    --[ AppState Getter ]---    --------------------------getCache :: MonadReader AppState m => m Bool-getCache = ask <&> cache . settings---getDownloader :: MonadReader AppState m => m Downloader-getDownloader = ask <&> downloader . settings----    --------------    --[ Other ]---    ----------------urlBaseName :: MonadThrow m-            => ByteString  -- ^ the url path (without scheme and host)-            -> m (Path Rel)-urlBaseName = parseRel . snd . B.breakEnd (== _slash) . urlDecode False----- | Get tool files from @~\/.ghcup\/bin\/ghc\/\<ver\>\/bin\/\*@--- while ignoring @*-\<ver\>@ symlinks and accounting for cross triple prefix.------ Returns unversioned relative files, e.g.:------   - @["hsc2hs","haddock","hpc","runhaskell","ghc","ghc-pkg","ghci","runghc","hp2ps"]@-ghcToolFiles :: (MonadReader AppState m, MonadThrow m, MonadFail m, MonadIO m)-             => GHCTargetVersion-             -> Excepts '[NotInstalled] m [Path Rel]-ghcToolFiles ver = do-  ghcdir <- lift $ ghcupGHCDir ver-  let bindir = ghcdir </> [rel|bin|]--  -- fail if ghc is not installed-  whenM (fmap not $ liftIO $ doesDirectoryExist ghcdir)-        (throwE (NotInstalled GHC ver))--  files    <- liftIO $ getDirsFiles' bindir-  -- figure out the <ver> suffix, because this might not be `Version` for-  -- alpha/rc releases, but x.y.a.somedate.--  -- for cross, this won't be "ghc", but e.g.-  -- "armv7-unknown-linux-gnueabihf-ghc"-  [ghcbin] <- liftIO $ findFiles-    bindir-    (makeRegexOpts compExtended-                   execBlank-                   ([s|^([a-zA-Z0-9_-]*[a-zA-Z0-9_]-)?ghc$|] :: ByteString)-    )--  let ghcbinPath = bindir </> ghcbin-  ghcIsHadrian    <- liftIO $ isHadrian ghcbinPath-  onlyUnversioned <- if ghcIsHadrian-    then pure id-    else do-      (Just symver) <--        B.stripPrefix (toFilePath ghcbin <> "-") . takeFileName-          <$> liftIO (readSymbolicLink $ toFilePath ghcbinPath)-      when (B.null symver)-           (throwIO $ userError "Fatal: ghc symlink target is broken")-      pure $ filter (\x -> not $ symver `B.isSuffixOf` toFilePath x)--  pure $ onlyUnversioned files- where-    -- GHC is moving some builds to Hadrian for bindists,-    -- which doesn't create versioned binaries.-    -- https://gitlab.haskell.org/haskell/ghcup-hs/issues/31-  isHadrian :: Path Abs -- ^ ghcbin path-            -> IO Bool-  isHadrian = fmap (/= SymbolicLink) . getFileType----- | This file, when residing in @~\/.ghcup\/ghc\/\<ver\>\/@ signals that--- this GHC was built from source. It contains the build config.-ghcUpSrcBuiltFile :: Path Rel-ghcUpSrcBuiltFile = [rel|.ghcup_src_built|]----- | Calls gmake if it exists in PATH, otherwise make.-make :: (MonadThrow m, MonadIO m, MonadReader AppState m)-     => [ByteString]-     -> Maybe (Path Abs)-     -> m (Either ProcessError ())-make args workdir = do-  spaths    <- catMaybes . fmap parseAbs <$> liftIO getSearchPath-  has_gmake <- isJust <$> liftIO (searchPath spaths [rel|gmake|])-  let mymake = if has_gmake then "gmake" else "make"-  execLogged mymake True args [rel|ghc-make|] workdir Nothing----- | Try to apply patches in order. Fails with 'PatchFailed'--- on first failure.-applyPatches :: (MonadLogger m, MonadIO m)-             => Path Abs   -- ^ dir containing patches-             -> Path Abs   -- ^ dir to apply patches in-             -> Excepts '[PatchFailed] m ()-applyPatches pdir ddir = do-  patches <- liftIO $ getDirsFiles pdir-  forM_ (sort patches) $ \patch' -> do-    lift $ $(logInfo) [i|Applying patch #{patch'}|]-    fmap (either (const Nothing) Just)-         (liftIO $ exec-           "patch"-           True-           ["-p1", "-i", toFilePath patch']-           (Just ddir)-           Nothing)-      !? PatchFailed----- | https://gitlab.haskell.org/ghc/ghc/-/issues/17353-darwinNotarization :: Platform -> Path Abs -> IO (Either ProcessError ())-darwinNotarization Darwin path = exec-  "xattr"-  True-  ["-r", "-d", "com.apple.quarantine", toFilePath path]-  Nothing-  Nothing-darwinNotarization _ _ = pure $ Right ()---getChangeLog :: GHCupDownloads -> Tool -> Either Version Tag -> Maybe URI-getChangeLog dls tool (Left v') =-  preview (ix tool % ix v' % viChangeLog % _Just) dls-getChangeLog dls tool (Right tag) =-  preview (ix tool % getTagged tag % to snd % viChangeLog % _Just) dls----- | Execute a build action while potentially cleaning up:------   1. the build directory, depending on the KeepDirs setting---   2. the install destination, depending on whether the build failed-runBuildAction :: (Show (V e), MonadReader AppState m, MonadIO m, MonadMask m)-               => Path Abs          -- ^ build directory (cleaned up depending on Settings)-               -> Maybe (Path Abs)  -- ^ dir to *always* clean up on exception-               -> Excepts e m a-               -> Excepts '[BuildFailed] m a-runBuildAction bdir instdir action = do-  AppState { settings = Settings {..} } <- lift ask-  let exAction = do-        forM_ instdir $ \dir ->-          liftIO $ hideError doesNotExistErrorType $ deleteDirRecursive dir-        when (keepDirs == Never)-          $ liftIO-          $ hideError doesNotExistErrorType-          $ deleteDirRecursive bdir-  v <--    flip onException exAction-    $ catchAllE-        (\es -> do-          exAction-          throwE (BuildFailed bdir es)-        ) action--  when (keepDirs == Never || keepDirs == Errors) $ liftIO $ deleteDirRecursive-    bdir-  pure v----- | More permissive version of 'createDirRecursive'. This doesn't--- error when the destination is a symlink to a directory.-createDirRecursive' :: Path b -> IO ()-createDirRecursive' p =-  handleIO (\e -> if isAlreadyExistsError e then isSymlinkDir e else throwIO e)-    . createDirRecursive newDirPerms-    $ p-- where-  isSymlinkDir e = do-    ft <- getFileType p-    case ft of-      SymbolicLink -> do-        rp <- canonicalizePath p-        rft <- getFileType rp-        case rft of-          Directory -> pure ()-          _ -> throwIO e-      _ -> throwIO e---getVersionInfo :: Version-               -> Tool-               -> GHCupDownloads-               -> Maybe VersionInfo-getVersionInfo v' tool =-  headOf-    ( ix tool-    % to (Map.filterWithKey (\k _ -> k == v'))-    % to Map.elems-    % _head-    )----- Gathering monoidal values-traverseFold :: (Foldable t, Applicative m, Monoid b) => (a -> m b) -> t a -> m b-traverseFold f = foldl (\mb a -> (<>) <$> mb <*> f a) (pure mempty)---- | Gathering monoidal values-forFold :: (Foldable t, Applicative m, Monoid b) => t a -> (a -> m b) -> m b-forFold = \t -> (`traverseFold` t)+Portability : portable++This module contains GHCup helpers specific to+installation and introspection of files/versions etc.+-}+module GHCup.Utils+  ( module GHCup.Utils.Dirs+  , module GHCup.Utils+  )+where+++#if defined(IS_WINDOWS)+import           GHCup.Download+#endif+import           GHCup.Errors+import           GHCup.Types+import           GHCup.Types.Optics+import           GHCup.Types.JSON               ( )+import           GHCup.Utils.Dirs+import           GHCup.Utils.File+import           GHCup.Utils.Logger+import           GHCup.Utils.MegaParsec+import           GHCup.Utils.Prelude+import           GHCup.Utils.String.QQ++import           Codec.Archive           hiding ( Directory )+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           Control.Monad.IO.Unlift        ( MonadUnliftIO( withRunInIO ) )+#if defined(IS_WINDOWS)+import           Data.Bits+#endif+import           Data.ByteString                ( ByteString )+import           Data.Either+import           Data.Foldable+import           Data.List+import           Data.List.NonEmpty             ( NonEmpty( (:|) ))+import           Data.Maybe+import           Data.Text                      ( Text )+import           Data.Versions+import           GHC.IO.Exception+import           Haskus.Utils.Variant.Excepts+import           Optics+import           Safe+import           System.Directory      hiding   ( findFiles )+import           System.FilePath+import           System.IO.Error+#if defined(IS_WINDOWS)+import           System.Win32.Console+import           System.Win32.File     hiding ( copyFile )+import           System.Win32.Types+#endif+import           Text.PrettyPrint.HughesPJClass hiding ( (<>) )+import           Text.Regex.Posix+import           URI.ByteString++import qualified Codec.Compression.BZip        as BZip+import qualified Codec.Compression.GZip        as GZip+import qualified Codec.Compression.Lzma        as Lzma+import qualified Data.ByteString.Lazy          as BL+import qualified Data.Map.Strict               as Map+import qualified Data.Text                     as T+import qualified Data.Text.Encoding            as E+import qualified Text.Megaparsec               as MP+import qualified Data.List.NonEmpty            as NE+++-- $setup+-- >>> :set -XOverloadedStrings+-- >>> :set -XDataKinds+-- >>> :set -XTypeApplications+-- >>> :set -XQuasiQuotes+-- >>> import System.Directory+-- >>> import URI.ByteString+-- >>> import qualified Data.Text as T+-- >>> import GHCup.Utils.Prelude+-- >>> import GHCup.Download+-- >>> import GHCup.Version+-- >>> import GHCup.Errors+-- >>> import GHCup.Types+-- >>> import GHCup.Types.Optics+-- >>> import Optics+-- >>> import GHCup.Utils.Version.QQ+-- >>> import qualified Data.Text.Encoding as E+-- >>> import Control.Monad.Reader+-- >>> import Haskus.Utils.Variant.Excepts+-- >>> import Text.PrettyPrint.HughesPJClass ( prettyShow )+-- >>> let lc = LoggerConfig { lcPrintDebug = False, consoleOutter = mempty, fileOutter = mempty, fancyColors = False }+-- >>> dirs' <- getAllDirs+-- >>> let installedVersions = [ ([pver|8.10.7|], Nothing), ([pver|8.10.4|], Nothing), ([pver|8.8.4|], Nothing), ([pver|8.8.3|], Nothing) ]+-- >>> let settings = Settings True False Never Curl False GHCupURL True GPGNone False+-- >>> let leanAppState = LeanAppState settings dirs' defaultKeyBindings lc+-- >>> cwd <- getCurrentDirectory+-- >>> (Right ref) <- pure $ parseURI strictURIParserOptions $ "file://" <> E.encodeUtf8 (T.pack cwd) <> "/data/metadata/" <> (urlBaseName . view pathL' $ ghcupURL)+-- >>> (VRight r) <- (fmap . fmap) _ghcupDownloads $ flip runReaderT leanAppState . runE @'[DigestError, GPGError, JSONError , DownloadFailed , FileDoesNotExistError] $ liftE $ getBase ref++++    ------------------------+    --[ Symlink handling ]--+    ------------------------+++-- | The symlink destination of a ghc tool.+ghcLinkDestination :: ( MonadReader env m+                      , HasDirs env+                      , MonadThrow m, MonadIO m)+                   => FilePath -- ^ the tool, such as 'ghc', 'haddock' etc.+                   -> GHCTargetVersion+                   -> m FilePath+ghcLinkDestination tool ver = do+  Dirs {..}  <- getDirs+  ghcd <- ghcupGHCDir ver+  pure (relativeSymlink binDir (ghcd </> "bin" </> tool))+++-- | Removes the minor GHC symlinks, e.g. ghc-8.6.5.+rmMinorSymlinks :: ( MonadReader env m+                   , HasDirs env+                   , MonadIO m+                   , HasLog env+                   , MonadThrow m+                   , MonadFail m+                   , MonadMask m+                   )+                => GHCTargetVersion+                -> Excepts '[NotInstalled] m ()+rmMinorSymlinks tv@GHCTargetVersion{..} = do+  Dirs {..}  <- lift getDirs++  files                         <- liftE $ ghcToolFiles tv+  forM_ files $ \f -> do+    let f_xyz = f <> "-" <> T.unpack (prettyVer _tvVersion) <> exeExt+    let fullF = binDir </> f_xyz+    lift $ logDebug ("rm -f " <> T.pack fullF)+    lift $ hideError doesNotExistErrorType $ rmLink fullF+++-- | Removes the set ghc version for the given target, if any.+rmPlain :: ( MonadReader env m+           , HasDirs env+           , HasLog env+           , MonadThrow m+           , MonadFail m+           , MonadIO m+           , MonadMask m+           )+        => Maybe Text -- ^ target+        -> Excepts '[NotInstalled] m ()+rmPlain target = do+  Dirs {..}  <- lift getDirs+  mtv                           <- lift $ ghcSet target+  forM_ mtv $ \tv -> do+    files <- liftE $ ghcToolFiles tv+    forM_ files $ \f -> do+      let fullF = binDir </> f <> exeExt+      lift $ logDebug ("rm -f " <> T.pack fullF)+      lift $ hideError doesNotExistErrorType $ rmLink fullF+    -- old ghcup+    let hdc_file = binDir </> "haddock-ghc" <> exeExt+    lift $ logDebug ("rm -f " <> T.pack hdc_file)+    lift $ hideError doesNotExistErrorType $ rmLink hdc_file+++-- | Remove the major GHC symlink, e.g. ghc-8.6.+rmMajorSymlinks :: ( MonadReader env m+                   , HasDirs env+                   , MonadIO m+                   , HasLog env+                   , MonadThrow m+                   , MonadFail m+                   , MonadMask m+                   )+                => GHCTargetVersion+                -> Excepts '[NotInstalled] m ()+rmMajorSymlinks tv@GHCTargetVersion{..} = do+  Dirs {..}  <- lift getDirs+  (mj, mi) <- getMajorMinorV _tvVersion+  let v' = intToText mj <> "." <> intToText mi++  files                         <- liftE $ ghcToolFiles tv+  forM_ files $ \f -> do+    let f_xy = f <> "-" <> T.unpack v' <> exeExt+    let fullF = binDir </> f_xy+    lift $ logDebug ("rm -f " <> T.pack fullF)+    lift $ hideError doesNotExistErrorType $ rmLink fullF+++++    -----------------------------------+    --[ Set/Installed introspection ]--+    -----------------------------------+++-- | Whether the given GHC versin is installed.+ghcInstalled :: (MonadIO m, MonadReader env m, HasDirs env, MonadThrow m) => GHCTargetVersion -> m Bool+ghcInstalled ver = do+  ghcdir <- ghcupGHCDir ver+  liftIO $ doesDirectoryExist ghcdir+++-- | Whether the given GHC version is installed from source.+ghcSrcInstalled :: (MonadIO m, MonadReader env m, HasDirs env, MonadThrow m) => GHCTargetVersion -> m Bool+ghcSrcInstalled ver = do+  ghcdir <- ghcupGHCDir ver+  liftIO $ doesFileExist (ghcdir </> ghcUpSrcBuiltFile)+++-- | Whether the given GHC version is set as the current.+ghcSet :: (MonadReader env m, HasDirs env, MonadThrow m, MonadIO m)+       => Maybe Text   -- ^ the target of the GHC version, if any+                       --  (e.g. armv7-unknown-linux-gnueabihf)+       -> m (Maybe GHCTargetVersion)+ghcSet mtarget = do+  Dirs {..}  <- getDirs+  let ghc = maybe "ghc" (\t -> T.unpack t <> "-ghc") mtarget+  let ghcBin = binDir </> ghc <> exeExt++  -- link destination is of the form ../ghc/<ver>/bin/ghc+  -- for old ghcup, it is ../ghc/<ver>/bin/ghc-<ver>+  liftIO $ handleIO' NoSuchThing (\_ -> pure Nothing) $ do+    link <- liftIO $ getLinkTarget ghcBin+    Just <$> ghcLinkVersion link+ where+  ghcLinkVersion :: MonadThrow m => FilePath -> m GHCTargetVersion+  ghcLinkVersion (T.pack . dropSuffix exeExt -> t) = throwEither $ MP.parse parser "ghcLinkVersion" t+   where+    parser =+        (do+           _    <- parseUntil1 ghcSubPath+           _    <- ghcSubPath+           r    <- parseUntil1 pathSep+           rest <- MP.getInput+           MP.setInput r+           x <- ghcTargetVerP+           MP.setInput rest+           pure x+         )+        <* pathSep+        <* MP.takeRest+        <* MP.eof+    ghcSubPath = pathSep <* MP.chunk "ghc" *> pathSep++-- | Get all installed GHCs by reading ~/.ghcup/ghc/<dir>.+-- If a dir cannot be parsed, returns left.+getInstalledGHCs :: (MonadReader env m, HasDirs env, MonadIO m) => m [Either FilePath GHCTargetVersion]+getInstalledGHCs = do+  ghcdir <- ghcupGHCBaseDir+  fs     <- liftIO $ hideErrorDef [NoSuchThing] [] $ listDirectory ghcdir+  forM fs $ \f -> case parseGHCupGHCDir f of+    Right r -> pure $ Right r+    Left  _ -> pure $ Left f+++-- | Get all installed cabals, by matching on @~\/.ghcup\/bin/cabal-*@.+getInstalledCabals :: ( MonadReader env m+                      , HasDirs env+                      , MonadIO m+                      , MonadCatch m+                      )+                   => m [Either FilePath Version]+getInstalledCabals = do+  Dirs {..} <- getDirs+  bins   <- liftIO $ handleIO (\_ -> pure []) $ findFiles+    binDir+    (makeRegexOpts compExtended execBlank ([s|^cabal-.*$|] :: ByteString))+  vs <- forM bins $ \f -> case version . T.pack <$> (stripSuffix exeExt =<< stripPrefix "cabal-" f) of+    Just (Right r) -> pure $ Right r+    Just (Left  _) -> pure $ Left f+    Nothing        -> pure $ Left f+  pure $ nub vs+++-- | Whether the given cabal version is installed.+cabalInstalled :: (MonadIO m, MonadReader env m, HasDirs env, MonadCatch m) => Version -> m Bool+cabalInstalled ver = do+  vers <- fmap rights getInstalledCabals+  pure $ elem ver vers+++-- Return the currently set cabal version, if any.+cabalSet :: (HasLog env, MonadReader env m, HasDirs env, MonadIO m, MonadThrow m, MonadCatch m) => m (Maybe Version)+cabalSet = do+  Dirs {..}  <- getDirs+  let cabalbin = binDir </> "cabal" <> exeExt++  handleIO' NoSuchThing (\_ -> pure Nothing) $ do+    broken <- liftIO $ isBrokenSymlink cabalbin+    if broken+      then pure Nothing+      else do+        link <- liftIO+          $ handleIO' InvalidArgument+            (\e -> pure $ Left (toException e))+          $ fmap Right $ getLinkTarget cabalbin+        case linkVersion =<< link of+          Right v -> pure $ Just v+          Left err -> do+            logWarn $ "Failed to parse cabal symlink target with: "+              <> T.pack (displayException err)+              <> ". The symlink "+              <> T.pack cabalbin+              <> " needs to point to valid cabal binary, such as 'cabal-3.4.0.0'."+            pure Nothing+ where+  -- We try to be extra permissive with link destination parsing,+  -- because of:+  --   https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/119+  linkVersion :: MonadThrow m => FilePath -> m Version+  linkVersion = throwEither . MP.parse parser "linkVersion" . T.pack . dropSuffix exeExt++  parser+    =   MP.try (stripAbsolutePath *> cabalParse)+    <|> MP.try (stripRelativePath *> cabalParse)+    <|> cabalParse+  -- parses the version of "cabal-3.2.0.0" -> "3.2.0.0"+  cabalParse = MP.chunk "cabal-" *> version'+  -- parses any path component ending with path separator,+  -- e.g. "foo/"+  stripPathComponet = parseUntil1 pathSep *> pathSep+  -- parses an absolute path up until the last path separator,+  -- e.g. "/bar/baz/foo" -> "/bar/baz/", leaving "foo"+  stripAbsolutePath = pathSep *> MP.many (MP.try stripPathComponet)+  -- parses a relative path up until the last path separator,+  -- e.g. "bar/baz/foo" -> "bar/baz/", leaving "foo"+  stripRelativePath = MP.many (MP.try stripPathComponet)++++-- | Get all installed hls, by matching on+-- @~\/.ghcup\/bin/haskell-language-server-wrapper-<\hlsver\>@.+getInstalledHLSs :: (MonadReader env m, HasDirs env, MonadIO m, MonadCatch m)+                 => m [Either FilePath Version]+getInstalledHLSs = do+  Dirs {..}  <- getDirs+  bins                          <- liftIO $ handleIO (\_ -> pure []) $ findFiles+    binDir+    (makeRegexOpts compExtended+                   execBlank+                   ([s|^haskell-language-server-wrapper-.*$|] :: ByteString)+    )+  forM bins $ \f ->+    case+          version . T.pack <$> (stripSuffix exeExt =<< stripPrefix "haskell-language-server-wrapper-" f)+      of+        Just (Right r) -> pure $ Right r+        Just (Left  _) -> pure $ Left f+        Nothing        -> pure $ Left f++-- | Get all installed stacks, by matching on+-- @~\/.ghcup\/bin/stack-<\stackver\>@.+getInstalledStacks :: (MonadReader env m, HasDirs env, MonadIO m, MonadCatch m)+                   => m [Either FilePath Version]+getInstalledStacks = do+  Dirs {..}  <- getDirs+  bins                          <- liftIO $ handleIO (\_ -> pure []) $ findFiles+    binDir+    (makeRegexOpts compExtended+                   execBlank+                   ([s|^stack-.*$|] :: ByteString)+    )+  forM bins $ \f ->+    case version . T.pack <$> (stripSuffix exeExt =<< stripPrefix "stack-" f) of+        Just (Right r) -> pure $ Right r+        Just (Left  _) -> pure $ Left f+        Nothing        -> pure $ Left f++-- Return the currently set stack version, if any.+-- TODO: there's a lot of code duplication here :>+stackSet :: (MonadReader env m, HasDirs env, MonadIO m, MonadThrow m, MonadCatch m, HasLog env) => m (Maybe Version)+stackSet = do+  Dirs {..}  <- getDirs+  let stackBin = binDir </> "stack" <> exeExt++  handleIO' NoSuchThing (\_ -> pure Nothing) $ do+    broken <- liftIO $ isBrokenSymlink stackBin+    if broken+      then pure Nothing+      else do+        link <- liftIO+          $ handleIO' InvalidArgument+            (\e -> pure $ Left (toException e))+          $ fmap Right $ getLinkTarget stackBin+        case linkVersion =<< link of+          Right v -> pure $ Just v+          Left err -> do+            logWarn $ "Failed to parse stack symlink target with: "+              <> T.pack (displayException err)+              <> ". The symlink "+              <> T.pack stackBin+              <> " needs to point to valid stack binary, such as 'stack-2.7.1'."+            pure Nothing+ where+  linkVersion :: MonadThrow m => FilePath -> m Version+  linkVersion = throwEither . MP.parse parser "" . T.pack . dropSuffix exeExt+   where+    parser+      =   MP.try (stripAbsolutePath *> cabalParse)+      <|> MP.try (stripRelativePath *> cabalParse)+      <|> cabalParse+    -- parses the version of "stack-2.7.1" -> "2.7.1"+    cabalParse = MP.chunk "stack-" *> version'+    -- parses any path component ending with path separator,+    -- e.g. "foo/"+    stripPathComponet = parseUntil1 pathSep *> pathSep+    -- parses an absolute path up until the last path separator,+    -- e.g. "/bar/baz/foo" -> "/bar/baz/", leaving "foo"+    stripAbsolutePath = pathSep *> MP.many (MP.try stripPathComponet)+    -- parses a relative path up until the last path separator,+    -- e.g. "bar/baz/foo" -> "bar/baz/", leaving "foo"+    stripRelativePath = MP.many (MP.try stripPathComponet)++-- | Whether the given Stack version is installed.+stackInstalled :: (MonadIO m, MonadReader env m, HasDirs env, MonadCatch m) => Version -> m Bool+stackInstalled ver = do+  vers <- fmap rights getInstalledStacks+  pure $ elem ver vers++-- | Whether the given HLS version is installed.+hlsInstalled :: (MonadIO m, MonadReader env m, HasDirs env, MonadCatch m) => Version -> m Bool+hlsInstalled ver = do+  vers <- fmap rights getInstalledHLSs+  pure $ elem ver vers++++-- Return the currently set hls version, if any.+hlsSet :: (MonadReader env m, HasDirs env, MonadIO m, MonadThrow m, MonadCatch m) => m (Maybe Version)+hlsSet = do+  Dirs {..}  <- getDirs+  let hlsBin = binDir </> "haskell-language-server-wrapper" <> exeExt++  liftIO $ handleIO' NoSuchThing (\_ -> pure Nothing) $ do+    broken <- isBrokenSymlink hlsBin+    if broken+      then pure Nothing+      else do+        link <- liftIO $ getLinkTarget hlsBin+        Just <$> linkVersion link+ where+  linkVersion :: MonadThrow m => FilePath -> m Version+  linkVersion = throwEither . MP.parse parser "" . T.pack . dropSuffix exeExt+   where+    parser+      =   MP.try (stripAbsolutePath *> cabalParse)+      <|> MP.try (stripRelativePath *> cabalParse)+      <|> cabalParse+    -- parses the version of "haskell-language-server-wrapper-1.1.0" -> "1.1.0"+    cabalParse = MP.chunk "haskell-language-server-wrapper-" *> version'+    -- parses any path component ending with path separator,+    -- e.g. "foo/"+    stripPathComponet = parseUntil1 pathSep *> pathSep+    -- parses an absolute path up until the last path separator,+    -- e.g. "/bar/baz/foo" -> "/bar/baz/", leaving "foo"+    stripAbsolutePath = pathSep *> MP.many (MP.try stripPathComponet)+    -- parses a relative path up until the last path separator,+    -- e.g. "bar/baz/foo" -> "bar/baz/", leaving "foo"+    stripRelativePath = MP.many (MP.try stripPathComponet)+++-- | Return the GHC versions the currently selected HLS supports.+hlsGHCVersions :: ( MonadReader env m+                  , HasDirs env+                  , MonadIO m+                  , MonadThrow m+                  , MonadCatch m+                  )+               => m [Version]+hlsGHCVersions = do+  h <- hlsSet+  fromMaybe [] <$> forM h hlsGHCVersions'+++hlsGHCVersions' :: ( MonadReader env m+                   , HasDirs env+                   , MonadIO m+                   , MonadThrow m+                   , MonadCatch m+                   )+                => Version+                -> m [Version]+hlsGHCVersions' v' = do+  bins <- hlsServerBinaries v' Nothing+  let vers = fmap+        (version+          . T.pack+          . fromJust+          . stripPrefix "haskell-language-server-"+          . head+          . splitOn "~"+          )+        bins+  pure . sortBy (flip compare) . rights $ vers+++-- | Get all server binaries for an hls version, if any.+hlsServerBinaries :: (MonadReader env m, HasDirs env, MonadIO m)+                  => Version+                  -> Maybe Version   -- ^ optional GHC version+                  -> m [FilePath]+hlsServerBinaries ver mghcVer = do+  Dirs {..}  <- getDirs+  liftIO $ handleIO (\_ -> pure []) $ findFiles+    binDir+    (makeRegexOpts+      compExtended+      execBlank+      ([s|^haskell-language-server-|]+        <> maybe [s|.*|] escapeVerRex mghcVer+        <> [s|~|]+        <> escapeVerRex ver+        <> E.encodeUtf8 (T.pack exeExt)+        <> [s|$|] :: ByteString+      )+    )+++-- | Get the wrapper binary for an hls version, if any.+hlsWrapperBinary :: (MonadReader env m, HasDirs env, MonadThrow m, MonadIO m)+                 => Version+                 -> m (Maybe FilePath)+hlsWrapperBinary ver = do+  Dirs {..}  <- getDirs+  wrapper <- liftIO $ handleIO (\_ -> pure []) $ findFiles+    binDir+    (makeRegexOpts+      compExtended+      execBlank+      ([s|^haskell-language-server-wrapper-|] <> escapeVerRex ver <> E.encodeUtf8 (T.pack exeExt) <> [s|$|] :: ByteString+      )+    )+  case wrapper of+    []  -> pure Nothing+    [x] -> pure $ Just x+    _   -> throwM $ UnexpectedListLength+      "There were multiple hls wrapper binaries for a single version"+++-- | Get all binaries for an hls version, if any.+hlsAllBinaries :: (MonadReader env m, HasDirs env, MonadIO m, MonadThrow m) => Version -> m [FilePath]+hlsAllBinaries ver = do+  hls     <- hlsServerBinaries ver Nothing+  wrapper <- hlsWrapperBinary ver+  pure (maybeToList wrapper ++ hls)+++-- | Get the active symlinks for hls.+hlsSymlinks :: (MonadReader env m, HasDirs env, MonadIO m, MonadCatch m) => m [FilePath]+hlsSymlinks = do+  Dirs {..}  <- getDirs+  oldSyms                       <- liftIO $ handleIO (\_ -> pure []) $ findFiles+    binDir+    (makeRegexOpts compExtended+                   execBlank+                   ([s|^haskell-language-server-.*$|] :: ByteString)+    )+  filterM+    ( liftIO+    . pathIsLink+    . (binDir </>)+    )+    oldSyms++++    -----------------------------------------+    --[ Major version introspection (X.Y) ]--+    -----------------------------------------+++-- | Extract (major, minor) from any version.+getMajorMinorV :: MonadThrow m => Version -> m (Int, Int)+getMajorMinorV Version {..} = case _vChunks of+  ((Digits x :| []) :| ((Digits y :| []):_)) -> pure (fromIntegral x, fromIntegral y)+  _ -> throwM $ ParseError "Could not parse X.Y from version"+++matchMajor :: Version -> Int -> Int -> Bool+matchMajor v' major' minor' = case getMajorMinorV v' of+  Just (x, y) -> x == major' && y == minor'+  Nothing     -> False++-- | Match PVP prefix.+--+-- >>> matchPVPrefix [pver|8.8|] [pver|8.8.4|]+-- True+-- >>> matchPVPrefix [pver|8|] [pver|8.8.4|]+-- True+-- >>> matchPVPrefix [pver|8.10|] [pver|8.8.4|]+-- False+-- >>> matchPVPrefix [pver|8.10|] [pver|8.10.7|]+-- True+matchPVPrefix :: PVP -> PVP -> Bool+matchPVPrefix (toL -> prefix) (toL -> full) = and $ zipWith (==) prefix full++toL :: PVP -> [Int]+toL (PVP inner) = fmap fromIntegral $ NE.toList inner+++-- | Get the latest installed full GHC version that satisfies the given (possibly partial)+-- PVP version.+getGHCForPVP :: (MonadReader env m, HasDirs env, MonadIO m, MonadThrow m)+             => PVP+             -> Maybe Text -- ^ the target triple+             -> m (Maybe GHCTargetVersion)+getGHCForPVP pvpIn mt = do+  ghcs <- rights <$> getInstalledGHCs+  -- we're permissive here... failed parse just means we have no match anyway+  let ghcs' = catMaybes $ flip fmap ghcs $ \GHCTargetVersion{..} -> do+        pvp_ <- versionToPVP _tvVersion+        pure (pvp_, _tvTarget)++  getGHCForPVP' pvpIn ghcs' mt++-- | Like 'getGHCForPVP', except with explicit input parameter.+--+-- >>> fmap prettyShow $ getGHCForPVP' [pver|8|] installedVersions Nothing+-- "Just 8.10.7"+-- >>> fmap prettyShow $ getGHCForPVP' [pver|8.8|] installedVersions Nothing+-- "Just 8.8.4"+-- >>> fmap prettyShow $ getGHCForPVP' [pver|8.10.4|] installedVersions Nothing+-- "Just 8.10.4"+getGHCForPVP' :: MonadThrow m+             => PVP+             -> [(PVP, Maybe Text)] -- ^ installed GHCs+             -> Maybe Text          -- ^ the target triple+             -> m (Maybe GHCTargetVersion)+getGHCForPVP' pvpIn ghcs' mt = do+  let mResult = lastMay+                  . sortBy (\(x, _) (y, _) -> compare x y)+                  . filter+                      (\(pvp_, target) ->+                        target == mt && matchPVPrefix pvp_ pvpIn+                      )+                  $ ghcs'+  forM mResult $ \(pvp_, target) -> do+    ver' <- pvpToVersion pvp_+    pure (GHCTargetVersion target ver')+++-- | Get the latest available ghc for the given PVP version, which+-- may only contain parts.+--+-- >>> (fmap . fmap) fst $ getLatestToolFor GHC [pver|8|] r+-- Just (PVP {_pComponents = 8 :| [10,7]})+-- >>> (fmap . fmap) fst $ getLatestToolFor GHC [pver|8.8|] r+-- Just (PVP {_pComponents = 8 :| [8,4]})+-- >>> (fmap . fmap) fst $ getLatestToolFor GHC [pver|8.8.4|] r+-- Just (PVP {_pComponents = 8 :| [8,4]})+getLatestToolFor :: MonadThrow m+                 => Tool+                 -> PVP+                 -> GHCupDownloads+                 -> m (Maybe (PVP, VersionInfo))+getLatestToolFor tool pvpIn dls = do+  let ls = fromMaybe [] $ preview (ix tool % to Map.toDescList) dls+  let ps = catMaybes $ fmap (\(v, vi) -> (,vi) <$> versionToPVP v) ls+  pure . headMay . filter (\(v, _) -> matchPVPrefix pvpIn v) $ ps++++++    -----------------+    --[ Unpacking ]--+    -----------------++++-- | Unpack an archive to a temporary directory and return that path.+unpackToDir :: (MonadReader env m, HasLog env, MonadIO m, MonadThrow m)+            => FilePath       -- ^ destination dir+            -> FilePath       -- ^ archive path+            -> Excepts '[UnknownArchive+                        , ArchiveResult+                        ] m ()+unpackToDir dfp av = do+  let fn = takeFileName av+  lift $ logInfo $ "Unpacking: " <> T.pack fn <> " to " <> T.pack dfp++  let untar :: MonadIO m => BL.ByteString -> Excepts '[ArchiveResult] m ()+      untar = lEM . liftIO . runArchiveM . unpackToDirLazy dfp++      rf :: MonadIO m => FilePath -> Excepts '[ArchiveResult] m BL.ByteString+      rf = liftIO . BL.readFile++  -- extract, depending on file extension+  if+    | ".tar.gz" `isSuffixOf` fn -> liftE+      (untar . GZip.decompress =<< rf av)+    | ".tar.xz" `isSuffixOf` fn -> do+      filecontents <- liftE $ rf av+      let decompressed = Lzma.decompress filecontents+      liftE $ untar decompressed+    | ".tar.bz2" `isSuffixOf` fn ->+      liftE (untar . BZip.decompress =<< rf av)+    | ".tar" `isSuffixOf` fn -> liftE (untar =<< rf av)+    | ".zip" `isSuffixOf` fn -> liftE (untar =<< rf av)+    | otherwise -> throwE $ UnknownArchive fn+++getArchiveFiles :: (MonadReader env m, HasLog env, MonadIO m, MonadThrow m)+                => FilePath       -- ^ archive path+                -> Excepts '[UnknownArchive+                            , ArchiveResult+                            ] m [FilePath]+getArchiveFiles av = do+  let fn = takeFileName av++  let entries :: Monad m => BL.ByteString -> Excepts '[ArchiveResult] m [FilePath]+      entries = (fmap . fmap) filepath . lE . readArchiveBSL++      rf :: MonadIO m => FilePath -> Excepts '[ArchiveResult] m BL.ByteString+      rf = liftIO . BL.readFile++  -- extract, depending on file extension+  if+    | ".tar.gz" `isSuffixOf` fn -> liftE+      (entries . GZip.decompress =<< rf av)+    | ".tar.xz" `isSuffixOf` fn -> do+      filecontents <- liftE $ rf av+      let decompressed = Lzma.decompress filecontents+      liftE $ entries decompressed+    | ".tar.bz2" `isSuffixOf` fn ->+      liftE (entries . BZip.decompress =<< rf av)+    | ".tar" `isSuffixOf` fn -> liftE (entries =<< rf av)+    | ".zip" `isSuffixOf` fn -> liftE (entries =<< rf av)+    | otherwise -> throwE $ UnknownArchive fn+++intoSubdir :: (MonadReader env m, HasLog env, MonadIO m, MonadThrow m, MonadCatch m)+           => FilePath       -- ^ unpacked tar dir+           -> TarDir         -- ^ how to descend+           -> Excepts '[TarDirDoesNotExist] m FilePath+intoSubdir bdir tardir = case tardir of+  RealDir pr -> do+    whenM (fmap not . liftIO . doesDirectoryExist $ (bdir </> pr))+          (throwE $ TarDirDoesNotExist tardir)+    pure (bdir </> pr)+  RegexDir r -> do+    let rs = split (`elem` pathSeparators) r+    foldlM+      (\y x ->+        (handleIO (\_ -> pure []) . liftIO . findFiles y . regex $ x) >>= (\case+          []      -> throwE $ TarDirDoesNotExist tardir+          (p : _) -> pure (y </> p)) . sort+      )+      bdir+      rs+    where regex = makeRegexOpts compIgnoreCase execBlank+++++    ------------+    --[ Tags ]--+    ------------+++-- | Get the tool version that has this tag. If multiple have it,+-- picks the greatest version.+getTagged :: Tag+          -> Fold (Map.Map Version VersionInfo) (Version, VersionInfo)+getTagged tag =+  to (Map.toDescList . Map.filter (\VersionInfo {..} -> tag `elem` _viTags))+  % folding id++getLatest :: GHCupDownloads -> Tool -> Maybe (Version, VersionInfo)+getLatest av tool = headOf (ix tool % getTagged Latest) av++getRecommended :: GHCupDownloads -> Tool -> Maybe (Version, VersionInfo)+getRecommended av tool = headOf (ix tool % getTagged Recommended) av+++-- | Gets the latest GHC with a given base version.+getLatestBaseVersion :: GHCupDownloads -> PVP -> Maybe (Version, VersionInfo)+getLatestBaseVersion av pvpVer =+  headOf (ix GHC % getTagged (Base pvpVer)) av+++++    -------------+    --[ Other ]--+    -------------+++-- | Get tool files from @~\/.ghcup\/bin\/ghc\/\<ver\>\/bin\/\*@+-- while ignoring @*-\<ver\>@ symlinks and accounting for cross triple prefix.+--+-- Returns unversioned relative files without extension, e.g.:+--+--   - @["hsc2hs","haddock","hpc","runhaskell","ghc","ghc-pkg","ghci","runghc","hp2ps"]@+ghcToolFiles :: (MonadReader env m, HasDirs env, MonadThrow m, MonadFail m, MonadIO m)+             => GHCTargetVersion+             -> Excepts '[NotInstalled] m [FilePath]+ghcToolFiles ver = do+  ghcdir <- lift $ ghcupGHCDir ver+  let bindir = ghcdir </> "bin"++  -- fail if ghc is not installed+  whenM (fmap not $ liftIO $ doesDirectoryExist ghcdir)+        (throwE (NotInstalled GHC ver))++  files <- liftIO (listDirectory bindir >>= filterM (doesFileExist . (bindir </>)))+  pure (getUniqueTools . groupToolFiles . fmap (dropSuffix exeExt) $ files)++ where++  groupToolFiles :: [FilePath] -> [[(FilePath, String)]]+  groupToolFiles = groupBy (\(a, _) (b, _) -> a == b) . fmap (splitOnPVP "-")++  getUniqueTools :: [[(FilePath, String)]] -> [String]+  getUniqueTools = filter (isNotAnyInfix blackListedTools) . nub . fmap fst . filter ((== "") . snd) . concat++  blackListedTools :: [String]+  blackListedTools = ["haddock-ghc"]++  isNotAnyInfix :: [String] -> String -> Bool+  isNotAnyInfix xs t = foldr (\a b -> not (a `isInfixOf` t) && b) True xs+++-- | This file, when residing in @~\/.ghcup\/ghc\/\<ver\>\/@ signals that+-- this GHC was built from source. It contains the build config.+ghcUpSrcBuiltFile :: FilePath+ghcUpSrcBuiltFile = ".ghcup_src_built"+++-- | Calls gmake if it exists in PATH, otherwise make.+make :: ( MonadThrow m+        , MonadIO m+        , MonadReader env m+        , HasDirs env+        , HasSettings env+        )+     => [String]+     -> Maybe FilePath+     -> m (Either ProcessError ())+make args workdir = do+  spaths    <- liftIO getSearchPath+  has_gmake <- isJust <$> liftIO (searchPath spaths "gmake")+  let mymake = if has_gmake then "gmake" else "make"+  execLogged mymake args workdir "ghc-make" Nothing++makeOut :: (MonadReader env m, HasDirs env, MonadIO m)+        => [String]+        -> Maybe FilePath+        -> m CapturedProcess+makeOut args workdir = do+  spaths    <- liftIO getSearchPath+  has_gmake <- isJust <$> liftIO (searchPath spaths "gmake")+  let mymake = if has_gmake then "gmake" else "make"+  executeOut mymake args workdir+++-- | Try to apply patches in order. Fails with 'PatchFailed'+-- on first failure.+applyPatches :: (MonadReader env m, HasDirs env, HasLog env, MonadIO m)+             => FilePath   -- ^ dir containing patches+             -> FilePath   -- ^ dir to apply patches in+             -> Excepts '[PatchFailed] m ()+applyPatches pdir ddir = do+  patches <- (fmap . fmap) (pdir </>) $ liftIO $ findFiles+      pdir+      (makeRegexOpts compExtended+                     execBlank+                     ([s|.+\.(patch|diff)$|] :: ByteString)+      )+  forM_ (sort patches) $ \patch' -> do+    lift $ logInfo $ "Applying patch " <> T.pack patch'+    fmap (either (const Nothing) Just)+         (exec+           "patch"+           ["-p1", "-i", patch']+           (Just ddir)+           Nothing)+      !? PatchFailed+++-- | https://gitlab.haskell.org/ghc/ghc/-/issues/17353+darwinNotarization :: (MonadReader env m, HasDirs env, MonadIO m)+                   => Platform+                   -> FilePath+                   -> m (Either ProcessError ())+darwinNotarization Darwin path = exec+  "xattr"+  ["-r", "-d", "com.apple.quarantine", path]+  Nothing+  Nothing+darwinNotarization _ _ = pure $ Right ()+++getChangeLog :: GHCupDownloads -> Tool -> Either Version Tag -> Maybe URI+getChangeLog dls tool (Left v') =+  preview (ix tool % ix v' % viChangeLog % _Just) dls+getChangeLog dls tool (Right tag) =+  preview (ix tool % pre (getTagged tag) % to snd % viChangeLog % _Just) dls+++-- | Execute a build action while potentially cleaning up:+--+--   1. the build directory, depending on the KeepDirs setting+--   2. the install destination, depending on whether the build failed+runBuildAction :: ( Pretty (V e)+                  , Show (V e)+                  , PopVariant BuildFailed e+                  , ToVariantMaybe BuildFailed e+                  , MonadReader env m+                  , HasDirs env+                  , HasSettings env+                  , MonadIO m+                  , MonadMask m+                  , HasLog env+                  , MonadUnliftIO m+                  , MonadFail m+                  , MonadCatch m+                  )+               => FilePath        -- ^ build directory (cleaned up depending on Settings)+               -> Maybe FilePath  -- ^ dir to *always* clean up on exception+               -> Excepts e m a+               -> Excepts '[BuildFailed] m a+runBuildAction bdir instdir action = do+  Settings {..} <- lift getSettings+  let exAction = do+        forM_ instdir $ \dir ->+          lift $ hideError doesNotExistErrorType $ recyclePathForcibly dir+        when (keepDirs == Never)+          $ lift $ rmBDir bdir+  v <-+    flip onException exAction+    $ catchAllE+        (\es -> do+          exAction+          throwE (BuildFailed bdir es)+        ) action++  when (keepDirs == Never || keepDirs == Errors) $ lift $ rmBDir bdir+  pure v+++-- | Remove a build directory, ignoring if it doesn't exist and gracefully+-- printing other errors without crashing.+rmBDir :: (MonadReader env m, HasLog env, MonadUnliftIO m, MonadIO m) => FilePath -> m ()+rmBDir dir = withRunInIO (\run -> run $+           liftIO $ handleIO (\e -> run $ logWarn $+               "Couldn't remove build dir " <> T.pack dir <> ", error was: " <> T.pack (displayException e))+           $ hideError doesNotExistErrorType+           $ rmPathForcibly dir)+++getVersionInfo :: Version+               -> Tool+               -> GHCupDownloads+               -> Maybe VersionInfo+getVersionInfo v' tool =+  headOf+    ( ix tool+    % to (Map.filterWithKey (\k _ -> k == v'))+    % to Map.elems+    % _head+    )+++-- | The file extension for executables.+exeExt :: String+#if defined(IS_WINDOWS)+exeExt = ".exe"+#else+exeExt = ""+#endif++-- | The file extension for executables.+exeExt' :: ByteString+#if defined(IS_WINDOWS)+exeExt' = ".exe"+#else+exeExt' = ""+#endif+++-- | Enables ANSI support on windows, does nothing on unix.+--+-- Returns 'Left str' on errors and 'Right bool' on success, where+-- 'bool' markes whether ansi support was already enabled.+--+-- This function never crashes.+--+-- Rip-off of https://docs.rs/ansi_term/0.12.1/x86_64-pc-windows-msvc/src/ansi_term/windows.rs.html#10-61+enableAnsiSupport :: IO (Either String Bool)+#if defined(IS_WINDOWS)+enableAnsiSupport = handleIO (pure . Left . displayException) $ do+  -- ref: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew+  -- Using `CreateFileW("CONOUT$", ...)` to retrieve the console handle works correctly even if STDOUT and/or STDERR are redirected+  h <- createFile "CONOUT$" (gENERIC_WRITE .|. gENERIC_READ)+    fILE_SHARE_WRITE Nothing oPEN_EXISTING 0 Nothing+  when (h == iNVALID_HANDLE_VALUE ) $ fail "invalid handle value"++  -- ref: https://docs.microsoft.com/en-us/windows/console/getconsolemode+  m <- getConsoleMode h++  -- VT processing not already enabled?+  if ((m .&. eNABLE_VIRTUAL_TERMINAL_PROCESSING) == 0)+  -- https://docs.microsoft.com/en-us/windows/console/setconsolemode+  then setConsoleMode h (m .|. eNABLE_VIRTUAL_TERMINAL_PROCESSING)+    >> pure (Right False)+  else pure (Right True)+#else+enableAnsiSupport = pure (Right True)+#endif+++-- | On unix, we can use symlinks, so we just get the+-- symbolic link target.+--+-- On windows, we have to emulate symlinks via shims,+-- see 'createLink'.+getLinkTarget :: FilePath -> IO FilePath+getLinkTarget fp = do+#if defined(IS_WINDOWS)+  content <- readFile (dropExtension fp <.> "shim")+  [p] <- pure . filter ("path = " `isPrefixOf`) . lines $ content+  pure $ stripNewline $ dropPrefix "path = " p+#else+  getSymbolicLinkTarget fp+#endif+++-- | Checks whether the path is a link.+pathIsLink :: FilePath -> IO Bool+#if defined(IS_WINDOWS)+pathIsLink fp = doesPathExist (dropExtension fp <.> "shim")+#else+pathIsLink = pathIsSymbolicLink+#endif+++rmLink :: (MonadReader env m, HasDirs env, MonadIO m, MonadMask m) => FilePath -> m ()+#if defined(IS_WINDOWS)+rmLink fp = do+  hideError doesNotExistErrorType . recycleFile $ fp+  hideError doesNotExistErrorType . recycleFile $ (dropExtension fp <.> "shim")+#else+rmLink = hideError doesNotExistErrorType . recycleFile+#endif+++-- | Creates a symbolic link on unix and a fake symlink on windows for+-- executables, which:+--     1. is a shim exe+--     2. has a corresponding .shim file in the same directory that+--        contains the target+--+-- This overwrites previously existing files.+--+-- On windows, this requires that 'ensureGlobalTools' was run beforehand.+createLink :: ( MonadMask m+              , MonadThrow m+              , HasLog env+              , MonadIO m+              , MonadReader env m+              , HasDirs env+              , MonadUnliftIO m+              , MonadFail m+              )+           => FilePath      -- ^ path to the target executable+           -> FilePath      -- ^ path to be created+           -> m ()+createLink link exe = do+#if defined(IS_WINDOWS)+  dirs <- getDirs+  let shimGen = cacheDir dirs </> "gs.exe"++  let shim = dropExtension exe <.> "shim"+      -- For hardlinks, link needs to be absolute.+      -- If link is relative, it's relative to the target exe.+      -- Note that (</>) drops lhs when rhs is absolute.+      fullLink = takeDirectory exe </> link+      shimContents = "path = " <> fullLink++  logDebug $ "rm -f " <> T.pack exe+  rmLink exe++  logDebug $ "ln -s " <> T.pack fullLink <> " " <> T.pack exe+  liftIO $ copyFile shimGen exe+  liftIO $ writeFile shim shimContents+#else+  logDebug $ "rm -f " <> T.pack exe+  hideError doesNotExistErrorType $ recycleFile exe++  logDebug $ "ln -s " <> T.pack link <> " " <> T.pack exe+  liftIO $ createFileLink link exe+#endif+++ensureGlobalTools :: ( MonadMask m+                     , MonadThrow m+                     , HasLog env+                     , MonadIO m+                     , MonadReader env m+                     , HasDirs env+                     , HasSettings env+                     , HasGHCupInfo env+                     , MonadUnliftIO m+                     , MonadFail m+                     )+                  => Excepts '[GPGError, DigestError , DownloadFailed, NoDownload] m ()+ensureGlobalTools = do+#if defined(IS_WINDOWS)+  (GHCupInfo _ _ gTools) <- lift getGHCupInfo+  dirs <- lift getDirs+  shimDownload <- liftE $ lE @_ @'[NoDownload]+    $ maybe (Left NoDownload) Right $ Map.lookup ShimGen gTools+  let dl = downloadCached' shimDownload (Just "gs.exe") Nothing+  void $ (\(DigestError _ _ _) -> do+      lift $ logWarn "Digest doesn't match, redownloading gs.exe..."+      lift $ logDebug ("rm -f " <> T.pack (cacheDir dirs </> "gs.exe"))+      lift $ hideError doesNotExistErrorType $ recycleFile (cacheDir dirs </> "gs.exe")+      liftE @'[GPGError, DigestError , DownloadFailed] $ dl+    ) `catchE` (liftE @'[GPGError, DigestError , DownloadFailed] dl)+  pure ()+#else+  pure ()+#endif+++-- | Ensure ghcup directory structure exists.+ensureDirectories :: Dirs -> IO ()+ensureDirectories (Dirs baseDir binDir cacheDir logsDir confDir trashDir) = do+  createDirRecursive' baseDir+  createDirRecursive' (baseDir </> "ghc")+  createDirRecursive' binDir+  createDirRecursive' cacheDir+  createDirRecursive' logsDir+  createDirRecursive' confDir+  createDirRecursive' trashDir+  pure ()+++-- | For ghc without arch triple, this is:+--+--    - ghc-<ver> (e.g. ghc-8.10.4)+--+-- For ghc with arch triple:+--+--    - <triple>-ghc-<ver> (e.g. arm-linux-gnueabihf-ghc-8.10.4)+ghcBinaryName :: GHCTargetVersion -> String+ghcBinaryName (GHCTargetVersion (Just t) v') = T.unpack (t <> "-ghc-" <> prettyVer v' <> T.pack exeExt)+ghcBinaryName (GHCTargetVersion Nothing  v') = T.unpack ("ghc-" <> prettyVer v' <> T.pack exeExt)
+ lib/GHCup/Utils.hs-boot view
@@ -0,0 +1,4 @@+module GHCup.Utils where++getLinkTarget :: FilePath -> IO FilePath+pathIsLink :: FilePath -> IO Bool
lib/GHCup/Utils/Dirs.hs view
@@ -1,7 +1,7 @@+{-# LANGUAGE CPP                   #-} {-# LANGUAGE DataKinds             #-} {-# LANGUAGE OverloadedStrings     #-} {-# LANGUAGE FlexibleContexts      #-}-{-# LANGUAGE QuasiQuotes           #-} {-# LANGUAGE ViewPatterns          #-}  {-|@@ -11,17 +11,24 @@ License     : LGPL-3.0 Maintainer  : hasufell@hasufell.de Stability   : experimental-Portability : POSIX+Portability : portable -} module GHCup.Utils.Dirs-  ( getDirs+  ( getAllDirs+  , ghcupBaseDir   , ghcupConfigFile+  , ghcupCacheDir   , ghcupGHCBaseDir   , ghcupGHCDir   , mkGhcupTmpDir   , parseGHCupGHCDir   , relativeSymlink   , withGHCupTmpDir+  , getConfigFilePath+#if !defined(IS_WINDOWS)+  , useXDG+#endif+  , cleanupTrash   ) where @@ -29,39 +36,32 @@ import           GHCup.Errors import           GHCup.Types import           GHCup.Types.JSON               ( )+import           GHCup.Types.Optics import           GHCup.Utils.MegaParsec+import           GHCup.Utils.Logger import           GHCup.Utils.Prelude -import           Control.Applicative import           Control.Exception.Safe import           Control.Monad+import           Control.Monad.IO.Unlift import           Control.Monad.Reader-import           Control.Monad.Trans.Resource+import           Control.Monad.Trans.Resource hiding (throwM) import           Data.Bifunctor-import           Data.ByteString                ( ByteString ) import           Data.Maybe import           GHC.IO.Exception               ( IOErrorType(NoSuchThing) ) import           Haskus.Utils.Variant.Excepts-import           HPath-import           HPath.IO import           Optics-import           Prelude                 hiding ( abs-                                                , readFile-                                                , writeFile-                                                )-import           System.Posix.Env.ByteString    ( getEnv-                                                , getEnvDefault-                                                )-import           System.Posix.FilePath   hiding ( (</>) )-import           System.Posix.Temp.ByteString   ( mkdtemp )+import           System.Directory                                                +import           System.DiskSpace                                                +import           System.Environment+import           System.FilePath+import           System.IO.Temp -import qualified Data.ByteString.Lazy          as L-import qualified Data.ByteString.UTF8          as UTF8-import qualified Data.Text.Encoding            as E-import qualified Data.Yaml                     as Y-import qualified System.Posix.FilePath         as FP-import qualified System.Posix.User             as PU+import qualified Data.ByteString               as BS+import qualified Data.Text                     as T+import qualified Data.YAML.Aeson               as Y import qualified Text.Megaparsec               as MP+import Control.Concurrent (threadDelay)   @@ -74,105 +74,134 @@ -- -- If 'GHCUP_USE_XDG_DIRS' is set (to anything), -- then uses 'XDG_DATA_HOME/ghcup' as per xdg spec.-ghcupBaseDir :: IO (Path Abs)+ghcupBaseDir :: IO FilePath ghcupBaseDir = do+#if defined(IS_WINDOWS)+  bdir <- fromMaybe "C:\\" <$> lookupEnv "GHCUP_INSTALL_BASE_PREFIX"+  pure (bdir </> "ghcup")+#else   xdg <- useXDG   if xdg     then do-      bdir <- getEnv "XDG_DATA_HOME" >>= \case-        Just r  -> parseAbs r+      bdir <- lookupEnv "XDG_DATA_HOME" >>= \case+        Just r  -> pure r         Nothing -> do           home <- liftIO getHomeDirectory-          pure (home </> [rel|.local/share|])-      pure (bdir </> [rel|ghcup|])+          pure (home </> ".local" </> "share")+      pure (bdir </> "ghcup")     else do-      bdir <- getEnv "GHCUP_INSTALL_BASE_PREFIX" >>= \case-        Just r  -> parseAbs r+      bdir <- lookupEnv "GHCUP_INSTALL_BASE_PREFIX" >>= \case+        Just r  -> pure r         Nothing -> liftIO getHomeDirectory-      pure (bdir </> [rel|.ghcup|])+      pure (bdir </> ".ghcup")+#endif   -- | ~/.ghcup by default -- -- If 'GHCUP_USE_XDG_DIRS' is set (to anything), -- then uses 'XDG_CONFIG_HOME/ghcup' as per xdg spec.-ghcupConfigDir :: IO (Path Abs)+ghcupConfigDir :: IO FilePath ghcupConfigDir = do+#if defined(IS_WINDOWS)+  ghcupBaseDir+#else   xdg <- useXDG   if xdg     then do-      bdir <- getEnv "XDG_CONFIG_HOME" >>= \case-        Just r  -> parseAbs r+      bdir <- lookupEnv "XDG_CONFIG_HOME" >>= \case+        Just r  -> pure r         Nothing -> do           home <- liftIO getHomeDirectory-          pure (home </> [rel|.config|])-      pure (bdir </> [rel|ghcup|])+          pure (home </> ".config")+      pure (bdir </> "ghcup")     else do-      bdir <- getEnv "GHCUP_INSTALL_BASE_PREFIX" >>= \case-        Just r  -> parseAbs r+      bdir <- lookupEnv "GHCUP_INSTALL_BASE_PREFIX" >>= \case+        Just r  -> pure r         Nothing -> liftIO getHomeDirectory-      pure (bdir </> [rel|.ghcup|])+      pure (bdir </> ".ghcup")+#endif   -- | If 'GHCUP_USE_XDG_DIRS' is set (to anything), -- then uses 'XDG_BIN_HOME' env var or defaults to '~/.local/bin' -- (which, sadly is not strictly xdg spec).-ghcupBinDir :: IO (Path Abs)+ghcupBinDir :: IO FilePath ghcupBinDir = do+#if defined(IS_WINDOWS)+  ghcupBaseDir <&> (</> "bin")+#else   xdg <- useXDG   if xdg     then do-      getEnv "XDG_BIN_HOME" >>= \case-        Just r  -> parseAbs r+      lookupEnv "XDG_BIN_HOME" >>= \case+        Just r  -> pure r         Nothing -> do           home <- liftIO getHomeDirectory-          pure (home </> [rel|.local/bin|])-    else ghcupBaseDir <&> (</> [rel|bin|])+          pure (home </> ".local" </> "bin")+    else ghcupBaseDir <&> (</> "bin")+#endif   -- | Defaults to '~/.ghcup/cache'. -- -- If 'GHCUP_USE_XDG_DIRS' is set (to anything), -- then uses 'XDG_CACHE_HOME/ghcup' as per xdg spec.-ghcupCacheDir :: IO (Path Abs)+ghcupCacheDir :: IO FilePath ghcupCacheDir = do+#if defined(IS_WINDOWS)+  ghcupBaseDir <&> (</> "cache")+#else   xdg <- useXDG   if xdg     then do-      bdir <- getEnv "XDG_CACHE_HOME" >>= \case-        Just r  -> parseAbs r+      bdir <- lookupEnv "XDG_CACHE_HOME" >>= \case+        Just r  -> pure r         Nothing -> do           home <- liftIO getHomeDirectory-          pure (home </> [rel|.cache|])-      pure (bdir </> [rel|ghcup|])-    else ghcupBaseDir <&> (</> [rel|cache|])+          pure (home </> ".cache")+      pure (bdir </> "ghcup")+    else ghcupBaseDir <&> (</> "cache")+#endif   -- | Defaults to '~/.ghcup/logs'. -- -- If 'GHCUP_USE_XDG_DIRS' is set (to anything), -- then uses 'XDG_CACHE_HOME/ghcup/logs' as per xdg spec.-ghcupLogsDir :: IO (Path Abs)+ghcupLogsDir :: IO FilePath ghcupLogsDir = do+#if defined(IS_WINDOWS)+  ghcupBaseDir <&> (</> "logs")+#else   xdg <- useXDG   if xdg     then do-      bdir <- getEnv "XDG_CACHE_HOME" >>= \case-        Just r  -> parseAbs r+      bdir <- lookupEnv "XDG_CACHE_HOME" >>= \case+        Just r  -> pure r         Nothing -> do           home <- liftIO getHomeDirectory-          pure (home </> [rel|.cache|])-      pure (bdir </> [rel|ghcup/logs|])-    else ghcupBaseDir <&> (</> [rel|logs|])+          pure (home </> ".cache")+      pure (bdir </> "ghcup" </> "logs")+    else ghcupBaseDir <&> (</> "logs")+#endif  -getDirs :: IO Dirs-getDirs = do-  baseDir  <- ghcupBaseDir-  binDir   <- ghcupBinDir-  cacheDir <- ghcupCacheDir-  logsDir  <- ghcupLogsDir-  confDir  <- ghcupConfigDir+-- | '~/.ghcup/trash'.+-- Mainly used on windows to improve file removal operations+ghcupRecycleDir :: IO FilePath+ghcupRecycleDir = ghcupBaseDir <&> (</> "trash")++++getAllDirs :: IO Dirs+getAllDirs = do+  baseDir    <- ghcupBaseDir+  binDir     <- ghcupBinDir+  cacheDir   <- ghcupCacheDir+  logsDir    <- ghcupLogsDir+  confDir    <- ghcupConfigDir+  recycleDir <- ghcupRecycleDir   pure Dirs { .. }  @@ -181,16 +210,19 @@     --[ GHCup files ]--     ------------------- +getConfigFilePath :: (MonadIO m) => m FilePath+getConfigFilePath = do+  confDir <- liftIO ghcupConfigDir+  pure $ confDir </> "config.yaml"  ghcupConfigFile :: (MonadIO m)                 => Excepts '[JSONError] m UserSettings ghcupConfigFile = do-  confDir <- liftIO ghcupConfigDir-  let file = confDir </> [rel|config.yaml|]-  bs <- liftIO $ handleIO' NoSuchThing (\_ -> pure Nothing) $ Just <$> readFile file-  case bs of+  filepath <- getConfigFilePath+  contents <- liftIO $ handleIO' NoSuchThing (\_ -> pure Nothing) $ Just <$> BS.readFile filepath+  case contents of       Nothing -> pure defaultUserSettings-      Just bs' -> lE' JSONDecodeError . first show . Y.decodeEither' . L.toStrict $ bs'+      Just contents' -> lE' JSONDecodeError . first snd . Y.decode1Strict $ contents'       -------------------------@@ -199,75 +231,129 @@   -- | ~/.ghcup/ghc by default.-ghcupGHCBaseDir :: (MonadReader AppState m) => m (Path Abs)+ghcupGHCBaseDir :: (MonadReader env m, HasDirs env) => m FilePath ghcupGHCBaseDir = do-  AppState { dirs = Dirs {..} } <- ask-  pure (baseDir </> [rel|ghc|])+  Dirs {..}  <- getDirs+  pure (baseDir </> "ghc")   -- | Gets '~/.ghcup/ghc/<ghcupGHCDir>'. -- The dir may be of the form --   * armv7-unknown-linux-gnueabihf-8.8.3 --   * 8.8.4-ghcupGHCDir :: (MonadReader AppState m, MonadThrow m)+ghcupGHCDir :: (MonadReader env m, HasDirs env, MonadThrow m)             => GHCTargetVersion-            -> m (Path Abs)+            -> m FilePath ghcupGHCDir ver = do-  ghcbasedir    <- ghcupGHCBaseDir-  verdir        <- parseRel $ E.encodeUtf8 (tVerToText ver)+  ghcbasedir <- ghcupGHCBaseDir+  let verdir = T.unpack $ tVerToText ver   pure (ghcbasedir </> verdir)   -- | See 'ghcupToolParser'.-parseGHCupGHCDir :: MonadThrow m => Path Rel -> m GHCTargetVersion-parseGHCupGHCDir (toFilePath -> f) = do-  fp <- throwEither $ E.decodeUtf8' f+parseGHCupGHCDir :: MonadThrow m => FilePath -> m GHCTargetVersion+parseGHCupGHCDir (T.pack -> fp) =   throwEither $ MP.parse ghcTargetVerP "" fp  -mkGhcupTmpDir :: (MonadThrow m, MonadIO m) => m (Path Abs)+mkGhcupTmpDir :: ( MonadReader env m+                 , HasDirs env+                 , MonadUnliftIO m+                 , HasLog env+                 , MonadCatch m+                 , MonadThrow m+                 , MonadMask m+                 , MonadIO m)+              => m FilePath mkGhcupTmpDir = do-  tmpdir <- liftIO $ getEnvDefault "TMPDIR" "/tmp"-  tmp    <- liftIO $ mkdtemp (tmpdir FP.</> "ghcup-")-  parseAbs tmp+  tmpdir <- liftIO getCanonicalTemporaryDirectory +  let minSpace = 5000 -- a rough guess, aight?+  space <- handleIO (\_ -> pure Nothing) $ fmap Just $ liftIO $ getAvailSpace tmpdir+  when (maybe False (toBytes minSpace >) space) $ do+    logWarn ("Possibly insufficient disk space on "+      <> T.pack tmpdir+      <> ". At least "+      <> T.pack (show minSpace)+      <> " MB are recommended, but only "+      <> toMB (fromJust space)+      <> " are free. Consider freeing up disk space or setting TMPDIR env variable.")+    logWarn+      "...waiting for 10 seconds before continuing anyway, you can still abort..."+    liftIO $ threadDelay 10000000 -- give the user a sec to intervene -withGHCupTmpDir :: (MonadResource m, MonadThrow m, MonadIO m) => m (Path Abs)-withGHCupTmpDir = snd <$> allocate mkGhcupTmpDir deleteDirRecursive+  liftIO $ createTempDirectory tmpdir "ghcup"+ where+  toBytes mb = mb * 1024 * 1024+  toMB b = T.pack $ show (truncate' (fromIntegral b / (1024 * 1024) :: Double) 2)+  truncate' :: Double -> Int -> Double+  truncate' x n = fromIntegral (floor (x * t) :: Integer) / t+      where t = 10^n  +withGHCupTmpDir :: ( MonadReader env m+                   , HasDirs env+                   , HasLog env+                   , HasSettings env+                   , MonadUnliftIO m+                   , MonadCatch m+                   , MonadResource m+                   , MonadThrow m+                   , MonadMask m+                   , MonadIO m)+                => m FilePath+withGHCupTmpDir = snd <$> withRunInIO (\run ->+  run+    $ allocate+        (run mkGhcupTmpDir)+        (\fp ->+            handleIO (\e -> run+                $ logDebug ("Resource cleanup failed for " <> T.pack fp <> ", error was: " <> T.pack (displayException e)))+            . rmPathForcibly+            $ fp))  ++     --------------     --[ Others ]--     --------------  -getHomeDirectory :: IO (Path Abs)-getHomeDirectory = do-  e <- getEnv "HOME"-  case e of-    Just fp -> parseAbs fp-    Nothing -> do-      h <- PU.homeDirectory <$> (PU.getEffectiveUserID >>= PU.getUserEntryForID)-      parseAbs $ UTF8.fromString h -- this is a guess--+#if !defined(IS_WINDOWS) useXDG :: IO Bool-useXDG = isJust <$> getEnv "GHCUP_USE_XDG_DIRS"+useXDG = isJust <$> lookupEnv "GHCUP_USE_XDG_DIRS"+#endif  -relativeSymlink :: Path Abs  -- ^ the path in which to create the symlink-                -> Path Abs  -- ^ the symlink destination-                -> ByteString-relativeSymlink (toFilePath -> p1) (toFilePath -> p2) =+relativeSymlink :: FilePath  -- ^ the path in which to create the symlink+                -> FilePath  -- ^ the symlink destination+                -> FilePath+relativeSymlink p1 p2 =   let d1      = splitDirectories p1       d2      = splitDirectories p2       common  = takeWhile (\(x, y) -> x == y) $ zip d1 d2       cPrefix = drop (length common) d1   in  joinPath (replicate (length cPrefix) "..")-        <> joinPath ("/" : drop (length common) d2)-+        <> joinPath ([pathSeparator] : drop (length common) d2)  +cleanupTrash :: ( MonadIO m+                , MonadMask m+                , MonadReader env m+                , HasLog env+                , HasDirs env+                , HasSettings env+                )+             => m ()+cleanupTrash = do+  Dirs { recycleDir } <- getDirs+  contents <- liftIO $ listDirectory recycleDir+  if null contents+  then pure ()+  else do+    logWarn ("Removing leftover files in " <> T.pack recycleDir)+    forM_ contents (\fp -> handleIO (\e ->+        logDebug ("Resource cleanup failed for " <> T.pack fp <> ", error was: " <> T.pack (displayException e))+      ) $ liftIO $ removePathForcibly (recycleDir </> fp)) 
lib/GHCup/Utils/File.hs view
@@ -1,494 +1,17 @@-{-# LANGUAGE QuasiQuotes       #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE FlexibleContexts  #-}-{-# LANGUAGE TemplateHaskell   #-}-{-# LANGUAGE ViewPatterns      #-}--{-|-Module      : GHCup.Utils.File-Description : File and unix APIs-Copyright   : (c) Julian Ospald, 2020-License     : LGPL-3.0-Maintainer  : hasufell@hasufell.de-Stability   : experimental-Portability : POSIX--This module handles file and executable handling.-Some of these functions use sophisticated logging.--}-module GHCup.Utils.File where--import           GHCup.Utils.Prelude-import           GHCup.Types--import           Control.Concurrent-import           Control.Concurrent.Async-import           Control.Exception              ( evaluate )-import           Control.Exception.Safe-import           Control.Monad-import           Control.Monad.Logger-import           Control.Monad.Reader-import           Control.Monad.Trans.State.Strict-import           Data.ByteString                ( ByteString )-import           Data.Foldable-import           Data.Functor-import           Data.IORef-import           Data.Maybe-import           Data.Sequence                  ( Seq, (|>) )-import           Data.String.Interpolate-import           Data.Text                      ( Text )-import           Data.Void-import           Data.Word8-import           GHC.IO.Exception-import           HPath-import           HPath.IO                hiding ( hideError )-import           Optics                  hiding ((<|), (|>))-import           System.Console.Pretty   hiding ( Pretty )-import           System.Console.Regions-import           System.IO.Error-import           System.Posix.Directory.ByteString-import           System.Posix.FD               as FD-import           System.Posix.FilePath   hiding ( (</>) )-import           System.Posix.Files.ByteString-import           System.Posix.Foreign           ( oExcl )-import "unix"    System.Posix.IO.ByteString-                                         hiding ( openFd )-import           System.Posix.Process           ( ProcessStatus(..) )-import           System.Posix.Types-import           Text.PrettyPrint.HughesPJClass hiding ( (<>) )-import           Text.Regex.Posix---import qualified Control.Exception             as EX-import qualified Data.Sequence                 as Sq-import qualified Data.Text                     as T-import qualified Data.Text.Encoding            as E-import qualified System.Posix.Process.ByteString-                                               as SPPB-import           Streamly.External.Posix.DirStream-import qualified Streamly.Prelude              as S-import qualified Text.Megaparsec               as MP-import qualified Data.ByteString               as BS-import qualified "unix-bytestring" System.Posix.IO.ByteString-                                               as SPIB----data ProcessError = NonZeroExit Int ByteString [ByteString]-                  | PTerminated ByteString [ByteString]-                  | PStopped ByteString [ByteString]-                  | NoSuchPid ByteString [ByteString]-                  deriving Show--instance Pretty ProcessError where-  pPrint (NonZeroExit e exe args) =-    text [i|Process "#{decUTF8Safe exe}" with arguments #{fmap decUTF8Safe args} failed with exit code #{e}.|]-  pPrint (PTerminated exe args) =-    text [i|Process "#{decUTF8Safe exe}" with arguments #{fmap decUTF8Safe args} terminated.|]-  pPrint (PStopped exe args) =-    text [i|Process "#{decUTF8Safe exe}" with arguments #{fmap decUTF8Safe args} stopped.|]-  pPrint (NoSuchPid exe args) =-    text [i|Could not find PID for process running "#{decUTF8Safe exe}" with arguments #{fmap decUTF8Safe args}.|]--data CapturedProcess = CapturedProcess-  { _exitCode :: ExitCode-  , _stdOut   :: ByteString-  , _stdErr   :: ByteString-  }-  deriving (Eq, Show)--makeLenses ''CapturedProcess----- | Find the given executable by searching all *absolute* PATH components.--- Relative paths in PATH are ignored.------ This shouldn't throw IO exceptions, unless getting the environment variable--- PATH does.-findExecutable :: Path Rel -> IO (Maybe (Path Abs))-findExecutable ex = do-  sPaths <- fmap (catMaybes . fmap parseAbs) getSearchPath-  -- We don't want exceptions to mess up our result. If we can't-  -- figure out if a file exists, then treat it as a negative result.-  asum $ fmap-    (handleIO (\_ -> pure Nothing)-      -- asum for short-circuiting behavior-      . (\s' -> (isExecutable (s' </> ex) >>= guard) $> Just (s' </> ex))-    )-    sPaths----- | Execute the given command and collect the stdout, stderr and the exit code.--- The command is run in a subprocess.-executeOut :: Path b            -- ^ command as filename, e.g. 'ls'-           -> [ByteString]      -- ^ arguments to the command-           -> Maybe (Path Abs)  -- ^ chdir to this path-           -> IO CapturedProcess-executeOut path args chdir = captureOutStreams $ do-  maybe (pure ()) (changeWorkingDirectory . toFilePath) chdir-  SPPB.executeFile (toFilePath path) True args Nothing---execLogged :: (MonadReader AppState m, MonadIO m, MonadThrow m)-           => ByteString       -- ^ thing to execute-           -> Bool             -- ^ whether to search PATH for the thing-           -> [ByteString]     -- ^ args for the thing-           -> Path Rel         -- ^ log filename-           -> Maybe (Path Abs) -- ^ optionally chdir into this-           -> Maybe [(ByteString, ByteString)] -- ^ optional environment-           -> m (Either ProcessError ())-execLogged exe spath args lfile chdir env = do-  AppState { settings = Settings {..}, dirs = Dirs {..} } <- ask-  logfile       <- (logsDir </>) <$> parseRel (toFilePath lfile <> ".log")-  liftIO $ bracket (createFile (toFilePath logfile) newFilePerms)-                   closeFd-                   (action verbose)- where-  action verbose fd = do-    actionWithPipes $ \(stdoutRead, stdoutWrite) -> do-      -- start the thread that logs to stdout-      pState <- newEmptyMVar-      done   <- newEmptyMVar-      void-        $ forkIO-        $ EX.handle (\(_ :: IOException) -> pure ())-        $ EX.finally-            (if verbose-              then tee fd stdoutRead-              else printToRegion fd stdoutRead 6 pState-            )-            (putMVar done ())--      -- fork the subprocess-      pid <- SPPB.forkProcess $ do-        void $ dupTo stdoutWrite stdOutput-        void $ dupTo stdoutWrite stdError-        closeFd stdoutRead-        closeFd stdoutWrite--        -- execute the action-        maybe (pure ()) (changeWorkingDirectory . toFilePath) chdir-        void $ SPPB.executeFile exe spath args env--      closeFd stdoutWrite--      -- wait for the subprocess to finish-      e <- toProcessError exe args <$!> SPPB.getProcessStatus True True pid-      putMVar pState (either (const False) (const True) e)--      void $ race (takeMVar done) (threadDelay (1000000 * 3))-      closeFd stdoutRead--      pure e--  tee :: Fd -> Fd -> IO ()-  tee fileFd fdIn = readTilEOF lineAction fdIn--   where-    lineAction :: ByteString -> IO ()-    lineAction bs' = do-      void $ SPIB.fdWrite fileFd (bs' <> "\n")-      void $ SPIB.fdWrite stdOutput (bs' <> "\n")--  -- Reads fdIn and logs the output in a continous scrolling area-  -- of 'size' terminal lines. Also writes to a log file.-  printToRegion :: Fd -> Fd -> Int -> MVar Bool -> IO ()-  printToRegion fileFd fdIn size pState = do-    void $ displayConsoleRegions $ do-      rs <--        liftIO-        . fmap Sq.fromList-        . sequence-        . replicate size-        . openConsoleRegion-        $ Linear-      flip runStateT mempty-        $ handle-            (\(ex :: SomeException) -> do-              ps <- liftIO $ takeMVar pState-              when ps (forM_ rs (liftIO . closeConsoleRegion))-              throw ex-            )-        $ readTilEOF (lineAction rs) fdIn--   where-    -- action to perform line by line-    -- TODO: do this with vty for efficiency-    lineAction :: (MonadMask m, MonadIO m)-               => Seq ConsoleRegion-               -> ByteString-               -> StateT (Seq ByteString) m ()-    lineAction rs = \bs' -> do-      void $ liftIO $ SPIB.fdWrite fileFd (bs' <> "\n")-      modify (swapRegs bs')-      regs <- get-      liftIO $ forM_ (Sq.zip regs rs) $ \(bs, r) -> setConsoleRegion r $ do-        w <- consoleWidth-        return-          . T.pack-          . color Blue-          . T.unpack-          . decUTF8Safe-          . trim w-          . (\b -> "[ " <> toFilePath lfile <> " ] " <> b)-          $ bs--    swapRegs :: a -> Seq a -> Seq a-    swapRegs bs = \regs -> if-      | Sq.length regs < size -> regs |> bs-      | otherwise             -> Sq.drop 1 regs |> bs--    -- trim output line to terminal width-    trim :: Int -> ByteString -> ByteString-    trim w = \bs -> if-      | BS.length bs > w && w > 5 -> BS.take (w - 4) bs <> "..."-      | otherwise                 -> bs--  -- Consecutively read from Fd in 512 chunks until we hit-  -- newline or EOF.-  readLine :: MonadIO m-           => Fd          -- ^ input file descriptor-           -> ByteString  -- ^ rest buffer (read across newline)-           -> m (ByteString, ByteString, Bool) -- ^ (full line, rest, eof)-  readLine fd = go-   where-    go inBs = do-      -- if buffer is not empty, process it first-      mbs <- if BS.length inBs == 0-               -- otherwise attempt read-               then liftIO-                    $ handleIO (\e -> if isEOFError e then pure Nothing else ioError e)-                    $ fmap Just-                    $ SPIB.fdRead fd 512-               else pure $ Just inBs-      case mbs of-        Nothing -> pure ("", "", True)-        Just bs -> do-          -- split on newline-          let (line, rest) = BS.span (/= _lf) bs-          if-            | BS.length rest /= 0 -> pure (line, BS.tail rest, False)-            -- if rest is empty, then there was no newline, process further-            | otherwise           -> (\(l, r, b) -> (line <> l, r, b)) <$!> go mempty--  readTilEOF :: MonadIO m => (ByteString -> m a) -> Fd -> m ()-  readTilEOF ~action' fd' = go mempty-   where-    go bs' = do-      (bs, rest, eof) <- readLine fd' bs'-      if eof-         then liftIO $ ioError (mkIOError eofErrorType "" Nothing Nothing)-         else void (action' bs) >> go rest----- | Capture the stdout and stderr of the given action, which--- is run in a subprocess. Stdin is closed. You might want to--- 'race' this to make sure it terminates.-captureOutStreams :: IO a-                     -- ^ the action to execute in a subprocess-                  -> IO CapturedProcess-captureOutStreams action = do-  actionWithPipes $ \(parentStdoutRead, childStdoutWrite) ->-    actionWithPipes $ \(parentStderrRead, childStderrWrite) -> do-      pid <- SPPB.forkProcess $ do-        -- dup stdout-        void $ dupTo childStdoutWrite stdOutput-        closeFd childStdoutWrite-        closeFd parentStdoutRead--        -- dup stderr-        void $ dupTo childStderrWrite stdError-        closeFd childStderrWrite-        closeFd parentStderrRead--        -- execute the action-        a <- action-        void $ evaluate a--      -- close everything we don't need-      closeFd childStdoutWrite-      closeFd childStderrWrite--      -- start thread that writes the output-      refOut <- newIORef BS.empty-      refErr <- newIORef BS.empty-      done   <- newEmptyMVar-      _      <--        forkIO-        $ EX.handle (\(_ :: IOException) -> pure ())-        $ flip EX.finally (putMVar done ())-        $ writeStds parentStdoutRead parentStderrRead refOut refErr--      status <- SPPB.getProcessStatus True True pid-      void $ race (takeMVar done) (threadDelay (1000000 * 3))--      case status of-        -- readFd will take care of closing the fd-        Just (SPPB.Exited es) -> do-          stdout' <- readIORef refOut-          stderr' <- readIORef refErr-          pure $ CapturedProcess { _exitCode = es-                                 , _stdOut   = stdout'-                                 , _stdErr   = stderr'-                                 }--        _ -> throwIO $ userError ("No such PID " ++ show pid)-- where-  writeStds pout perr rout rerr = do-    doneOut <- newEmptyMVar-    void-      $ forkIO-      $ hideError eofErrorType-      $ flip EX.finally (putMVar doneOut ())-      $ readTilEOF (\x -> modifyIORef' rout (<> x)) pout-    doneErr <- newEmptyMVar-    void-      $ forkIO-      $ hideError eofErrorType-      $ flip EX.finally (putMVar doneErr ())-      $ readTilEOF (\x -> modifyIORef' rerr (<> x)) perr-    takeMVar doneOut-    takeMVar doneErr--  readTilEOF ~action' fd' = do-    bs <- SPIB.fdRead fd' 512-    void $ action' bs-    readTilEOF action' fd'---actionWithPipes :: ((Fd, Fd) -> IO b) -> IO b-actionWithPipes a =-  createPipe >>= \(p1, p2) -> flip finally (cleanup [p1, p2]) $ a (p1, p2)--cleanup :: [Fd] -> IO ()-cleanup fds = for_ fds $ \fd -> handleIO (\_ -> pure ()) $ closeFd fd------ | Create a new regular file in write-only mode. The file must not exist.-createRegularFileFd :: FileMode -> Path b -> IO Fd-createRegularFileFd fm dest =-  FD.openFd (toFilePath dest) WriteOnly [oExcl] (Just fm)----- | Thin wrapper around `executeFile`.-exec :: ByteString       -- ^ thing to execute-     -> Bool             -- ^ whether to search PATH for the thing-     -> [ByteString]     -- ^ args for the thing-     -> Maybe (Path Abs) -- ^ optionally chdir into this-     -> Maybe [(ByteString, ByteString)] -- ^ optional environment-     -> IO (Either ProcessError ())-exec exe spath args chdir env = do-  pid <- SPPB.forkProcess $ do-    maybe (pure ()) (changeWorkingDirectory . toFilePath) chdir-    SPPB.executeFile exe spath args env--  fmap (toProcessError exe args) $ SPPB.getProcessStatus True True pid---toProcessError :: ByteString-               -> [ByteString]-               -> Maybe ProcessStatus-               -> Either ProcessError ()-toProcessError exe args mps = case mps of-  Just (SPPB.Exited (ExitFailure xi)) -> Left $ NonZeroExit xi exe args-  Just (SPPB.Exited ExitSuccess    ) -> Right ()-  Just (Terminated _ _             ) -> Left $ PTerminated exe args-  Just (Stopped _                  ) -> Left $ PStopped exe args-  Nothing                            -> Left $ NoSuchPid exe args----- | Search for a file in the search paths.------ Catches `PermissionDenied` and `NoSuchThing` and returns `Nothing`.-searchPath :: [Path Abs] -> Path Rel -> IO (Maybe (Path Abs))-searchPath paths needle = go paths- where-  go [] = pure Nothing-  go (x : xs) =-    hideErrorDefM [InappropriateType, PermissionDenied, NoSuchThing] (go xs)-      $ do-          dirStream <- openDirStream (toFilePath x)-          S.findM (\(_, p) -> isMatch x p) (dirContentsStream dirStream)-            >>= \case-                  Just _  -> pure $ Just (x </> needle)-                  Nothing -> go xs-  isMatch basedir p = do-    if p == toFilePath needle-      then isExecutable (basedir </> needle)-      else pure False----- | Check wether a binary is shadowed by another one that comes before--- it in PATH. Returns the path to said binary, if any.-isShadowed :: Path Abs -> IO (Maybe (Path Abs))-isShadowed p = do-  let dir = dirname p-  fn <- basename p-  spaths <- catMaybes . fmap parseAbs <$> liftIO getSearchPath-  if dir `elem` spaths-  then do-    let shadowPaths = takeWhile (/= dir) spaths-    searchPath shadowPaths fn-  else pure Nothing----- | Check whether the binary is in PATH. This returns only `True`--- if the directory containing the binary is part of PATH.-isInPath :: Path Abs -> IO Bool-isInPath p = do-  let dir = dirname p-  fn <- basename p-  spaths <- catMaybes . fmap parseAbs <$> liftIO getSearchPath-  if dir `elem` spaths-  then isJust <$> searchPath [dir] fn-  else pure False---findFiles :: Path Abs -> Regex -> IO [Path Rel]-findFiles path regex = do-  dirStream <- openDirStream (toFilePath path)-  f         <--    (fmap . fmap) snd-    . S.toList-    . S.filter (\(_, p) -> match regex p)-    $ dirContentsStream dirStream-  pure $ parseRel =<< f---findFiles' :: Path Abs -> MP.Parsec Void Text () -> IO [Path Rel]-findFiles' path parser = do-  dirStream <- openDirStream (toFilePath path)-  f         <--    (fmap . fmap) snd-    . S.toList-    . S.filter (\(_, p) -> case E.decodeUtf8' p of-                             Left _ -> False-                             Right p' -> isJust $ MP.parseMaybe parser p')-    $ dirContentsStream dirStream-  pure $ parseRel =<< f---isBrokenSymlink :: Path Abs -> IO Bool-isBrokenSymlink p =-  handleIO-      (\e -> if ioeGetErrorType e == NoSuchThing then pure True else throwIO e)-    $ do-        _ <- canonicalizePath p-        pure False+{-# LANGUAGE CPP #-} +module GHCup.Utils.File (+  module GHCup.Utils.File.Common,+#if IS_WINDOWS+  module GHCup.Utils.File.Windows+#else+  module GHCup.Utils.File.Posix+#endif+) where -chmod_755 :: (MonadLogger m, MonadIO m) => Path a -> m ()-chmod_755 (toFilePath -> fp) = do-  let exe_mode =-          nullFileMode-            `unionFileModes` ownerExecuteMode-            `unionFileModes` ownerReadMode-            `unionFileModes` ownerWriteMode-            `unionFileModes` groupExecuteMode-            `unionFileModes` groupReadMode-            `unionFileModes` otherExecuteMode-            `unionFileModes` otherReadMode-  $(logDebug) [i|chmod 755 #{fp}|]-  liftIO $ setFileMode fp exe_mode+import GHCup.Utils.File.Common+#if IS_WINDOWS+import GHCup.Utils.File.Windows+#else+import GHCup.Utils.File.Posix+#endif
+ lib/GHCup/Utils/File/Common.hs view
@@ -0,0 +1,120 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE FlexibleContexts  #-}+{-# LANGUAGE TemplateHaskell   #-}+{-# LANGUAGE ViewPatterns      #-}++module GHCup.Utils.File.Common where++import           GHCup.Utils.Prelude++import           Control.Monad.Reader+import           Data.Maybe+import           Data.Text               ( Text )+import           Data.Void+import           GHC.IO.Exception+import           Optics                  hiding ((<|), (|>))+import           System.Directory+import           System.FilePath+import           Text.PrettyPrint.HughesPJClass hiding ( (<>) )+import           Text.Regex.Posix++import qualified Data.Text                     as T+import qualified Data.ByteString.Lazy          as BL+import qualified Text.Megaparsec               as MP++++data ProcessError = NonZeroExit Int FilePath [String]+                  | PTerminated FilePath [String]+                  | PStopped FilePath [String]+                  | NoSuchPid FilePath [String]+                  deriving Show++instance Pretty ProcessError where+  pPrint (NonZeroExit e exe args) =+    text "Process" <+> pPrint exe <+> text "with arguments" <+> pPrint args <+> text "failed with exit code" <+> text (show e <> ".")+  pPrint (PTerminated exe args) =+    text "Process" <+> pPrint exe <+> text "with arguments" <+> pPrint args <+> text "terminated."+  pPrint (PStopped exe args) =+    text "Process" <+> pPrint exe <+> text "with arguments" <+> pPrint args <+> text "stopped."+  pPrint (NoSuchPid exe args) =+    text "Could not find PID for process running " <+> pPrint exe <+> text " with arguments " <+> text (show args) <+> text "."++data CapturedProcess = CapturedProcess+  { _exitCode :: ExitCode+  , _stdOut   :: BL.ByteString+  , _stdErr   :: BL.ByteString+  }+  deriving (Eq, Show)++makeLenses ''CapturedProcess++++-- | Search for a file in the search paths.+--+-- Catches `PermissionDenied` and `NoSuchThing` and returns `Nothing`.+searchPath :: [FilePath] -> FilePath -> IO (Maybe FilePath)+searchPath paths needle = go paths+ where+  go [] = pure Nothing+  go (x : xs) =+    hideErrorDefM [InappropriateType, PermissionDenied, NoSuchThing] (go xs)+      $ do+          contents <- listDirectory x+          findM (isMatch x) contents >>= \case+            Just _ -> pure $ Just (x </> needle)+            Nothing -> go xs+  isMatch basedir p = do+    if p == needle+      then isExecutable (basedir </> needle)+      else pure False++  isExecutable :: FilePath -> IO Bool+  isExecutable file = executable <$> getPermissions file+++-- | Check wether a binary is shadowed by another one that comes before+-- it in PATH. Returns the path to said binary, if any.+isShadowed :: FilePath -> IO (Maybe FilePath)+isShadowed p = do+  let dir = takeDirectory p+  let fn = takeFileName p+  spaths <- liftIO getSearchPath+  if dir `elem` spaths+  then do+    let shadowPaths = takeWhile (/= dir) spaths+    searchPath shadowPaths fn+  else pure Nothing+++-- | Check whether the binary is in PATH. This returns only `True`+-- if the directory containing the binary is part of PATH.+isInPath :: FilePath -> IO Bool+isInPath p = do+  let dir = takeDirectory p+  let fn = takeFileName p+  spaths <- liftIO getSearchPath+  if dir `elem` spaths+  then isJust <$> searchPath [dir] fn+  else pure False+++findFiles :: FilePath -> Regex -> IO [FilePath]+findFiles path regex = do+  contents <- listDirectory path+  pure $ filter (match regex) contents++findFilesDeep :: FilePath -> Regex -> IO [FilePath]+findFilesDeep path regex = do+  contents <- getDirectoryContentsRecursive path+  pure $ filter (match regex) contents++findFiles' :: FilePath -> MP.Parsec Void Text a -> IO [FilePath]+findFiles' path parser = do+  contents <- listDirectory path+  pure $ filter (\fp -> either (const False) (const True) $ MP.parse parser "" (T.pack fp)) contents+++checkFileAlreadyExists :: (MonadIO m) => FilePath -> m Bool+checkFileAlreadyExists fp = liftIO $ doesFileExist fp
+ lib/GHCup/Utils/File/Common.hs-boot view
@@ -0,0 +1,5 @@+module GHCup.Utils.File.Common where++import           Text.Regex.Posix++findFiles :: FilePath -> Regex -> IO [FilePath]
+ lib/GHCup/Utils/File/Posix.hs view
@@ -0,0 +1,399 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE FlexibleContexts  #-}++{-|+Module      : GHCup.Utils.File.Posix+Description : File and unix APIs+Copyright   : (c) Julian Ospald, 2020+License     : LGPL-3.0+Maintainer  : hasufell@hasufell.de+Stability   : experimental+Portability : POSIX++This module handles file and executable handling.+Some of these functions use sophisticated logging.+-}+module GHCup.Utils.File.Posix where++import           GHCup.Utils.File.Common+import           GHCup.Utils.Prelude+import           GHCup.Utils.Logger+import           GHCup.Types+import           GHCup.Types.Optics++import           Control.Concurrent+import           Control.Concurrent.Async+import           Control.Exception              ( evaluate )+import           Control.Exception.Safe+import           Control.Monad+import           Control.Monad.Reader+import           Control.Monad.Trans.State.Strict+import           Data.ByteString                ( ByteString )+import           Data.Foldable+import           Data.IORef+import           Data.Sequence                  ( Seq, (|>) )+import           Data.List+import           Data.Word8+import           GHC.IO.Exception+import           System.Console.Terminal.Common+import           System.IO.Error+import           System.FilePath+import           System.Directory+import           System.Posix.Directory+import           System.Posix.Files+import           System.Posix.IO+import           System.Posix.Process           ( ProcessStatus(..) )+import           System.Posix.Types+++import qualified Control.Exception             as EX+import qualified Data.Sequence                 as Sq+import qualified Data.Text                     as T+import qualified Data.Text.Encoding            as E+import qualified System.Posix.Process          as SPP+import qualified System.Console.Terminal.Posix as TP+import qualified Data.ByteString               as BS+import qualified Data.ByteString.Lazy          as BL+import qualified "unix-bytestring" System.Posix.IO.ByteString+                                               as SPIB++++-- | Execute the given command and collect the stdout, stderr and the exit code.+-- The command is run in a subprocess.+executeOut :: MonadIO m+           => FilePath          -- ^ command as filename, e.g. 'ls'+           -> [String]          -- ^ arguments to the command+           -> Maybe FilePath    -- ^ chdir to this path+           -> m CapturedProcess+executeOut path args chdir = liftIO $ captureOutStreams $ do+  maybe (pure ()) changeWorkingDirectory chdir+  SPP.executeFile path True args Nothing+++execLogged :: ( MonadReader env m+              , HasSettings env+              , HasDirs env+              , MonadIO m+              , MonadThrow m)+           => FilePath         -- ^ thing to execute+           -> [String]         -- ^ args for the thing+           -> Maybe FilePath   -- ^ optionally chdir into this+           -> FilePath         -- ^ log filename (opened in append mode)+           -> Maybe [(String, String)] -- ^ optional environment+           -> m (Either ProcessError ())+execLogged exe args chdir lfile env = do+  Settings {..} <- getSettings+  Dirs {..} <- getDirs+  let logfile = logsDir </> lfile <> ".log"+  liftIO $ bracket (openFd logfile WriteOnly (Just newFilePerms) defaultFileFlags{ append = True })+                   closeFd+                   (action verbose noColor)+ where+  action verbose no_color fd = do+    actionWithPipes $ \(stdoutRead, stdoutWrite) -> do+      -- start the thread that logs to stdout+      pState <- newEmptyMVar+      done   <- newEmptyMVar+      void+        $ forkIO+        $ EX.handle (\(_ :: IOException) -> pure ())+        $ EX.finally+            (if verbose+              then tee fd stdoutRead+              else printToRegion fd stdoutRead 6 pState no_color+            )+            (putMVar done ())++      -- fork the subprocess+      pid <- SPP.forkProcess $ do+        void $ dupTo stdoutWrite stdOutput+        void $ dupTo stdoutWrite stdError+        closeFd stdoutRead+        closeFd stdoutWrite++        -- execute the action+        maybe (pure ()) changeWorkingDirectory chdir+        void $ SPP.executeFile exe (not ("./" `isPrefixOf` exe)) args env++      closeFd stdoutWrite++      -- wait for the subprocess to finish+      e <- toProcessError exe args <$!> SPP.getProcessStatus True True pid+      putMVar pState (either (const False) (const True) e)++      void $ race (takeMVar done) (threadDelay (1000000 * 3))+      closeFd stdoutRead++      pure e++  tee :: Fd -> Fd -> IO ()+  tee fileFd = readTilEOF lineAction++   where+    lineAction :: ByteString -> IO ()+    lineAction bs' = do+      void $ SPIB.fdWrite fileFd (bs' <> "\n")+      void $ SPIB.fdWrite stdOutput (bs' <> "\n")++  -- Reads fdIn and logs the output in a continous scrolling area+  -- of 'size' terminal lines. Also writes to a log file.+  printToRegion :: Fd -> Fd -> Int -> MVar Bool -> Bool -> IO ()+  printToRegion fileFd fdIn size pState no_color = do+    -- init region+    forM_ [1..size] $ \_ -> BS.putStr "\n"++    void $ flip runStateT mempty+      $ do+        handle+          (\(ex :: SomeException) -> do+            ps <- liftIO $ takeMVar pState+            when ps (liftIO $ BS.putStr (pos1 <> moveLineUp size <> clearScreen))+            throw ex+          ) $ readTilEOF lineAction fdIn++   where+    clearScreen :: ByteString+    clearScreen = "\x1b[0J"+    clearLine :: ByteString+    clearLine = "\x1b[2K"+    moveLineUp :: Int -> ByteString+    moveLineUp n = "\x1b[" <> E.encodeUtf8 (T.pack (show n)) <> "A"+    moveLineDown :: Int -> ByteString+    moveLineDown n = "\x1b[" <> E.encodeUtf8 (T.pack (show n)) <> "B"+    pos1 :: ByteString+    pos1 = "\r"+    overwriteNthLine :: Int -> ByteString -> ByteString+    overwriteNthLine n str = pos1 <> moveLineUp n <> clearLine <> str <> moveLineDown n <> pos1++    blue :: ByteString -> ByteString+    blue bs +      | no_color = bs+      | otherwise = "\x1b[0;34m" <> bs <> "\x1b[0m"++    -- action to perform line by line+    lineAction :: (MonadMask m, MonadIO m)+               => ByteString+               -> StateT (Seq ByteString) m ()+    lineAction = \bs' -> do+      void $ liftIO $ SPIB.fdWrite fileFd (bs' <> "\n")+      modify (swapRegs bs')+      liftIO TP.size >>= \case+        Nothing -> pure ()+        Just (Window _ w) -> do+          regs <- get+          liftIO $ forM_ (Sq.zip regs (Sq.fromList [0..(Sq.length regs - 1)])) $ \(bs, i) -> do+              BS.putStr+              . overwriteNthLine (size - i)+              . trim w+              . blue+              . (\b -> "[ " <> E.encodeUtf8 (T.pack lfile) <> " ] " <> b)+              $ bs++    swapRegs :: a -> Seq a -> Seq a+    swapRegs bs = \regs -> if+      | Sq.length regs < size -> regs |> bs+      | otherwise             -> Sq.drop 1 regs |> bs++    -- trim output line to terminal width+    trim :: Int -> ByteString -> ByteString+    trim w = \bs -> if+      | BS.length bs > w && w > 5 -> BS.take (w - 4) bs <> "..."+      | otherwise                 -> bs++  -- Consecutively read from Fd in 512 chunks until we hit+  -- newline or EOF.+  readLine :: MonadIO m+           => Fd          -- ^ input file descriptor+           -> ByteString  -- ^ rest buffer (read across newline)+           -> m (ByteString, ByteString, Bool) -- ^ (full line, rest, eof)+  readLine fd = go+   where+    go inBs = do+      -- if buffer is not empty, process it first+      mbs <- if BS.length inBs == 0+               -- otherwise attempt read+               then liftIO+                    $ handleIO (\e -> if isEOFError e then pure Nothing else ioError e)+                    $ fmap Just+                    $ SPIB.fdRead fd 512+               else pure $ Just inBs+      case mbs of+        Nothing -> pure ("", "", True)+        Just bs -> do+          -- split on newline+          let (line, rest) = BS.span (/= _lf) bs+          if+            | BS.length rest /= 0 -> pure (line, BS.tail rest, False)+            -- if rest is empty, then there was no newline, process further+            | otherwise           -> (\(l, r, b) -> (line <> l, r, b)) <$!> go mempty++  readTilEOF :: MonadIO m => (ByteString -> m a) -> Fd -> m ()+  readTilEOF ~action' fd' = go mempty+   where+    go bs' = do+      (bs, rest, eof) <- readLine fd' bs'+      if eof+         then liftIO $ ioError (mkIOError eofErrorType "" Nothing Nothing)+         else void (action' bs) >> go rest+++-- | Capture the stdout and stderr of the given action, which+-- is run in a subprocess. Stdin is closed. You might want to+-- 'race' this to make sure it terminates.+captureOutStreams :: IO a+                     -- ^ the action to execute in a subprocess+                  -> IO CapturedProcess+captureOutStreams action = do+  actionWithPipes $ \(parentStdoutRead, childStdoutWrite) ->+    actionWithPipes $ \(parentStderrRead, childStderrWrite) -> do+      pid <- SPP.forkProcess $ do+        -- dup stdout+        void $ dupTo childStdoutWrite stdOutput+        closeFd childStdoutWrite+        closeFd parentStdoutRead++        -- dup stderr+        void $ dupTo childStderrWrite stdError+        closeFd childStderrWrite+        closeFd parentStderrRead++        -- execute the action+        a <- action+        void $ evaluate a++      -- close everything we don't need+      closeFd childStdoutWrite+      closeFd childStderrWrite++      -- start thread that writes the output+      refOut <- newIORef BL.empty+      refErr <- newIORef BL.empty+      done   <- newEmptyMVar+      _      <-+        forkIO+        $ EX.handle (\(_ :: IOException) -> pure ())+        $ flip EX.finally (putMVar done ())+        $ writeStds parentStdoutRead parentStderrRead refOut refErr++      status <- SPP.getProcessStatus True True pid+      void $ race (takeMVar done) (threadDelay (1000000 * 3))++      case status of+        -- readFd will take care of closing the fd+        Just (SPP.Exited es) -> do+          stdout' <- readIORef refOut+          stderr' <- readIORef refErr+          pure $ CapturedProcess { _exitCode = es+                                 , _stdOut   = stdout'+                                 , _stdErr   = stderr'+                                 }++        _ -> throwIO $ userError ("No such PID " ++ show pid)++ where+  writeStds :: Fd -> Fd -> IORef BL.ByteString -> IORef BL.ByteString -> IO ()+  writeStds pout perr rout rerr = do+    doneOut <- newEmptyMVar+    void+      $ forkIO+      $ hideError eofErrorType+      $ flip EX.finally (putMVar doneOut ())+      $ readTilEOF (\x -> modifyIORef' rout (<> BL.fromStrict x)) pout+    doneErr <- newEmptyMVar+    void+      $ forkIO+      $ hideError eofErrorType+      $ flip EX.finally (putMVar doneErr ())+      $ readTilEOF (\x -> modifyIORef' rerr (<> BL.fromStrict x)) perr+    takeMVar doneOut+    takeMVar doneErr++  readTilEOF ~action' fd' = do+    bs <- SPIB.fdRead fd' 512+    void $ action' bs+    readTilEOF action' fd'+++actionWithPipes :: ((Fd, Fd) -> IO b) -> IO b+actionWithPipes a =+  createPipe >>= \(p1, p2) -> flip finally (cleanup [p1, p2]) $ a (p1, p2)++cleanup :: [Fd] -> IO ()+cleanup fds = for_ fds $ \fd -> handleIO (\_ -> pure ()) $ closeFd fd++++-- | Create a new regular file in write-only mode. The file must not exist.+createRegularFileFd :: FileMode -> FilePath -> IO Fd+createRegularFileFd fm dest =+  openFd dest WriteOnly (Just fm) defaultFileFlags{ exclusive = True }+++-- | Thin wrapper around `executeFile`.+exec :: MonadIO m+     => String           -- ^ thing to execute+     -> [String]         -- ^ args for the thing+     -> Maybe FilePath   -- ^ optionally chdir into this+     -> Maybe [(String, String)] -- ^ optional environment+     -> m (Either ProcessError ())+exec exe args chdir env = liftIO $ do+  pid <- SPP.forkProcess $ do+    maybe (pure ()) changeWorkingDirectory chdir+    SPP.executeFile exe (not ("./" `isPrefixOf` exe)) args env++  fmap (toProcessError exe args) $ SPP.getProcessStatus True True pid+++toProcessError :: FilePath+               -> [String]+               -> Maybe ProcessStatus+               -> Either ProcessError ()+toProcessError exe args mps = case mps of+  Just (SPP.Exited (ExitFailure xi)) -> Left $ NonZeroExit xi exe args+  Just (SPP.Exited ExitSuccess    ) -> Right ()+  Just (Terminated _ _             ) -> Left $ PTerminated exe args+  Just (Stopped _                  ) -> Left $ PStopped exe args+  Nothing                            -> Left $ NoSuchPid exe args++++chmod_755 :: (MonadReader env m, HasLog env, MonadIO m) => FilePath -> m ()+chmod_755 fp = do+  let exe_mode =+          nullFileMode+            `unionFileModes` ownerExecuteMode+            `unionFileModes` ownerReadMode+            `unionFileModes` ownerWriteMode+            `unionFileModes` groupExecuteMode+            `unionFileModes` groupReadMode+            `unionFileModes` otherExecuteMode+            `unionFileModes` otherReadMode+  logDebug ("chmod 755 " <> T.pack fp)+  liftIO $ setFileMode fp exe_mode+++-- |Default permissions for a new file.+newFilePerms :: FileMode+newFilePerms =+  ownerWriteMode+    `unionFileModes` ownerReadMode+    `unionFileModes` groupWriteMode+    `unionFileModes` groupReadMode+    `unionFileModes` otherWriteMode+    `unionFileModes` otherReadMode+++-- | Checks whether the binary is a broken link.+isBrokenSymlink :: FilePath -> IO Bool+isBrokenSymlink fp = do+  try (pathIsSymbolicLink fp) >>= \case+    Right True -> do+      let symDir = takeDirectory fp+      tfp <- getSymbolicLinkTarget fp+      not <$> doesPathExist+        -- this drops 'symDir' if 'tfp' is absolute+        (symDir </> tfp)+    Right b -> pure b+    Left e | isDoesNotExistError e -> pure False+           | otherwise -> throwIO e
+ lib/GHCup/Utils/File/Windows.hs view
@@ -0,0 +1,266 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE FlexibleContexts  #-}++{-|+Module      : GHCup.Utils.File.Windows+Description : File and windows APIs+Copyright   : (c) Julian Ospald, 2020+License     : LGPL-3.0+Maintainer  : hasufell@hasufell.de+Stability   : experimental+Portability : Windows++This module handles file and executable handling.+Some of these functions use sophisticated logging.+-}+module GHCup.Utils.File.Windows where++import {-# SOURCE #-} GHCup.Utils ( getLinkTarget, pathIsLink )+import           GHCup.Utils.Dirs+import           GHCup.Utils.File.Common+import           GHCup.Types+import           GHCup.Types.Optics++import           Control.Concurrent+import           Control.DeepSeq+import           Control.Exception.Safe+import           Control.Monad+import           Control.Monad.Reader+import           Data.List+import           Foreign.C.Error+import           GHC.IO.Exception+import           GHC.IO.Handle+import           System.Directory+import           System.Environment+import           System.FilePath+import           System.IO+import           System.Process+ +import qualified Control.Exception             as EX+import qualified Data.ByteString               as BS+import qualified Data.ByteString.Lazy          as BL+import qualified Data.Map.Strict               as Map++++toProcessError :: FilePath+               -> [FilePath]+               -> ExitCode+               -> Either ProcessError ()+toProcessError exe args exitcode = case exitcode of+  (ExitFailure xi) -> Left $ NonZeroExit xi exe args+  ExitSuccess -> Right ()+++-- | @readCreateProcessWithExitCode@ works exactly like 'readProcessWithExitCode' except that it+-- lets you pass 'CreateProcess' giving better flexibility.+--+-- Note that @Handle@s provided for @std_in@, @std_out@, or @std_err@ via the CreateProcess+-- record will be ignored.+--+-- @since 1.2.3.0+readCreateProcessWithExitCodeBS+    :: CreateProcess+    -> BL.ByteString+    -> IO (ExitCode, BL.ByteString, BL.ByteString) -- ^ exitcode, stdout, stderr+readCreateProcessWithExitCodeBS cp input = do+    let cp_opts = cp {+                    std_in  = CreatePipe,+                    std_out = CreatePipe,+                    std_err = CreatePipe+                  }+    withCreateProcess_ "readCreateProcessWithExitCodeBS" cp_opts $+      \mb_inh mb_outh mb_errh ph ->+        case (mb_inh, mb_outh, mb_errh) of+          (Just inh, Just outh, Just errh) -> do++            out <- BS.hGetContents outh+            err <- BS.hGetContents errh++            -- fork off threads to start consuming stdout & stderr+            withForkWait  (EX.evaluate $ rnf out) $ \waitOut ->+             withForkWait (EX.evaluate $ rnf err) $ \waitErr -> do++              -- now write any input+              unless (BL.null input) $+                ignoreSigPipe $ BL.hPut inh input+              -- hClose performs implicit hFlush, and thus may trigger a SIGPIPE+              ignoreSigPipe $ hClose inh++              -- wait on the output+              waitOut+              waitErr++              hClose outh+              hClose errh++            -- wait on the process+            ex <- waitForProcess ph+            return (ex, BL.fromStrict out, BL.fromStrict err)++          (Nothing,_,_) -> error "readCreateProcessWithExitCodeBS: Failed to get a stdin handle."+          (_,Nothing,_) -> error "readCreateProcessWithExitCodeBS: Failed to get a stdout handle."+          (_,_,Nothing) -> error "readCreateProcessWithExitCodeBS: Failed to get a stderr handle."+ where+  ignoreSigPipe :: IO () -> IO ()+  ignoreSigPipe = EX.handle $ \e -> case e of+                                     IOError { ioe_type  = ResourceVanished+                                             , ioe_errno = Just ioe }+                                       | Errno ioe == ePIPE -> return ()+                                     _ -> throwIO e+  -- wrapper so we can get exceptions with the appropriate function name.+  withCreateProcess_+    :: String+    -> CreateProcess+    -> (Maybe Handle -> Maybe Handle -> Maybe Handle -> ProcessHandle -> IO a)+    -> IO a+  withCreateProcess_ fun c action =+      EX.bracketOnError (createProcess_ fun c) cleanupProcess+                       (\(m_in, m_out, m_err, ph) -> action m_in m_out m_err ph)++-- | Fork a thread while doing something else, but kill it if there's an+-- exception.+--+-- This is important in the cases above because we want to kill the thread+-- that is holding the Handle lock, because when we clean up the process we+-- try to close that handle, which could otherwise deadlock.+--+withForkWait :: IO () -> (IO () ->  IO a) -> IO a+withForkWait async' body = do+  waitVar <- newEmptyMVar :: IO (MVar (Either SomeException ()))+  mask $ \restore -> do+    tid <- forkIO $ try (restore async') >>= putMVar waitVar+    let wait' = takeMVar waitVar >>= either throwIO return+    restore (body wait') `EX.onException` killThread tid+++-- | Execute the given command and collect the stdout, stderr and the exit code.+-- The command is run in a subprocess.+executeOut :: MonadIO m+           => FilePath          -- ^ command as filename, e.g. 'ls'+           -> [String]          -- ^ arguments to the command+           -> Maybe FilePath    -- ^ chdir to this path+           -> m CapturedProcess+executeOut path args chdir = do+  cp <- createProcessWithMingwPath ((proc path args){ cwd = chdir })+  (exit, out, err) <- liftIO $ readCreateProcessWithExitCodeBS cp ""+  pure $ CapturedProcess exit out err+++execLogged :: ( MonadReader env m+              , HasDirs env+              , HasSettings env+              , MonadIO m+              , MonadThrow m)+           => FilePath         -- ^ thing to execute+           -> [String]         -- ^ args for the thing+           -> Maybe FilePath   -- ^ optionally chdir into this+           -> FilePath         -- ^ log filename (opened in append mode)+           -> Maybe [(String, String)] -- ^ optional environment+           -> m (Either ProcessError ())+execLogged exe args chdir lfile env = do+  Dirs {..} <- getDirs+  let stdoutLogfile = logsDir </> lfile <> ".stdout.log"+      stderrLogfile = logsDir </> lfile <> ".stderr.log"+  cp <- createProcessWithMingwPath ((proc exe args)+    { cwd = chdir+    , env = env+    , std_in = CreatePipe+    , std_out = CreatePipe+    , std_err = CreatePipe+    })+  fmap (toProcessError exe args)+    $ liftIO+    $ withCreateProcess cp+    $ \_ mout merr ph ->+        case (mout, merr) of+          (Just cStdout, Just cStderr) -> do+            withForkWait (tee stdoutLogfile cStdout) $ \waitOut ->+              withForkWait (tee stderrLogfile cStderr) $ \waitErr -> do+                waitOut+                waitErr+            waitForProcess ph+          _ -> fail "Could not acquire out/err handle"++ where+  tee :: FilePath -> Handle -> IO ()+  tee logFile handle' = go+    where+      go = do+        some <- BS.hGetSome handle' 512+        if BS.null some+          then pure ()+          else do+            void $ BS.appendFile logFile some+            void $ BS.hPut stdout some+            go+        ++-- | Thin wrapper around `executeFile`.+exec :: MonadIO m+     => FilePath       -- ^ thing to execute+     -> [FilePath]     -- ^ args for the thing+     -> Maybe FilePath   -- ^ optionally chdir into this+     -> Maybe [(String, String)] -- ^ optional environment+     -> m (Either ProcessError ())+exec exe args chdir env = do+  cp <- createProcessWithMingwPath ((proc exe args) { cwd = chdir, env = env })+  exit_code <- liftIO $ withCreateProcess cp $ \_ _ _ p -> waitForProcess p+  pure $ toProcessError exe args exit_code+++-- | Thin wrapper around `executeFile`.+execShell :: MonadIO m+          => FilePath       -- ^ thing to execute+          -> [FilePath]     -- ^ args for the thing+          -> Maybe FilePath   -- ^ optionally chdir into this+          -> Maybe [(String, String)] -- ^ optional environment+          -> m (Either ProcessError ())+execShell exe args chdir env = do+  let cmd = exe <> " " <> concatMap (' ':) args+  cp <- createProcessWithMingwPath ((shell cmd) { cwd = chdir, env = env })+  exit_code <- liftIO $ withCreateProcess cp $ \_ _ _ p -> waitForProcess p+  pure $ toProcessError cmd [] exit_code+++chmod_755 :: MonadIO m => FilePath -> m ()+chmod_755 fp =+  let perm = setOwnerWritable True emptyPermissions+  in liftIO $ setPermissions fp perm+++createProcessWithMingwPath :: MonadIO m+                          => CreateProcess+                          -> m CreateProcess+createProcessWithMingwPath cp = do+  msys2Dir <- liftIO ghcupMsys2Dir+  cEnv <- Map.fromList <$> maybe (liftIO getEnvironment) pure (env cp)+  let mingWPaths = [msys2Dir </> "usr" </> "bin"+                   ,msys2Dir </> "mingw64" </> "bin"]+      paths = ["PATH", "Path"]+      curPaths = (\x -> maybe [] splitSearchPath (Map.lookup x cEnv)) =<< paths+      newPath = intercalate [searchPathSeparator] (mingWPaths ++ curPaths)+      envWithoutPath = foldr (\x y -> Map.delete x y) cEnv paths+      envWithNewPath = Map.insert "Path" newPath envWithoutPath+  liftIO $ setEnv "Path" newPath+  pure $ cp { env = Just $ Map.toList envWithNewPath }++ghcupMsys2Dir :: IO FilePath+ghcupMsys2Dir =+  lookupEnv "GHCUP_MSYS2" >>= \case+    Just fp -> pure fp+    Nothing -> do+      baseDir <- liftIO ghcupBaseDir+      pure (baseDir </> "msys64")++-- | Checks whether the binary is a broken link.+isBrokenSymlink :: FilePath -> IO Bool+isBrokenSymlink fp = do+  b <- pathIsLink fp+  if b+  then do+    tfp <- getLinkTarget fp+    not <$> doesPathExist+      -- this drops 'symDir' if 'tfp' is absolute+      (takeDirectory fp </> tfp)+  else pure False
lib/GHCup/Utils/Logger.hs view
@@ -1,4 +1,7 @@-{-# LANGUAGE FlexibleContexts      #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE QuasiQuotes      #-}+{-# LANGUAGE DataKinds        #-}+{-# LANGUAGE OverloadedStrings   #-}  {-| Module      : GHCup.Utils.Logger@@ -7,69 +10,122 @@ License     : LGPL-3.0 Maintainer  : hasufell@hasufell.de Stability   : experimental-Portability : POSIX+Portability : portable  Here we define our main logger. -} module GHCup.Utils.Logger where  import           GHCup.Types-import           GHCup.Utils+import           GHCup.Types.Optics+import {-# SOURCE #-} GHCup.Utils.File.Common+import           GHCup.Utils.String.QQ +import           Control.Exception.Safe import           Control.Monad import           Control.Monad.IO.Class import           Control.Monad.Reader-import           Control.Monad.Logger-import           HPath-import           HPath.IO+import           Data.Text               ( Text )+import           Optics import           Prelude                 hiding ( appendFile ) import           System.Console.Pretty+import           System.FilePath import           System.IO.Error+import           Text.Regex.Posix  import qualified Data.ByteString               as B+import GHCup.Utils.Prelude+import qualified Data.Text                     as T +logInfo :: ( MonadReader env m+           , LabelOptic' "loggerConfig" A_Lens env LoggerConfig+           , MonadIO m+           )+        => Text+        -> m ()+logInfo = logInternal Info -data LoggerConfig = LoggerConfig-  { lcPrintDebug :: Bool                  -- ^ whether to print debug in colorOutter-  , colorOutter  :: B.ByteString -> IO () -- ^ how to write the color output-  , rawOutter    :: B.ByteString -> IO () -- ^ how to write the full raw output-  }+logWarn :: ( MonadReader env m+           , LabelOptic' "loggerConfig" A_Lens env LoggerConfig+           , MonadIO m+           )+        => Text+        -> m ()+logWarn = logInternal Warn +logDebug :: ( MonadReader env m+            , LabelOptic' "loggerConfig" A_Lens env LoggerConfig+            , MonadIO m+            )+         => Text+         -> m ()+logDebug = logInternal Debug -myLoggerT :: LoggerConfig -> LoggingT m a -> m a-myLoggerT LoggerConfig {..} loggingt = runLoggingT loggingt mylogger- where-  mylogger :: Loc -> LogSource -> LogLevel -> LogStr -> IO ()-  mylogger _ _ level str' = do-    -- color output-    let l = case level of-          LevelDebug   -> toLogStr (style Bold $ color Blue "[ Debug ]")-          LevelInfo    -> toLogStr (style Bold $ color Green "[ Info  ]")-          LevelWarn    -> toLogStr (style Bold $ color Yellow "[ Warn  ]")-          LevelError   -> toLogStr (style Bold $ color Red "[ Error ]")-          LevelOther t -> toLogStr "[ " <> toLogStr t <> toLogStr " ]"-    let out = fromLogStr (l <> toLogStr " " <> str' <> toLogStr "\n")+logError :: ( MonadReader env m+            , LabelOptic' "loggerConfig" A_Lens env LoggerConfig+            , MonadIO m+            )+         => Text+         -> m ()+logError = logInternal Error -    when (lcPrintDebug || (not lcPrintDebug && (level /= LevelDebug)))-      $ colorOutter out -    -- raw output-    let lr = case level of-          LevelDebug   -> toLogStr "Debug: "-          LevelInfo    -> toLogStr "Info:"-          LevelWarn    -> toLogStr "Warn:"-          LevelError   -> toLogStr "Error:"-          LevelOther t -> toLogStr t <> toLogStr ":"-    let outr = fromLogStr (lr <> toLogStr " " <> str' <> toLogStr "\n")-    rawOutter outr+logInternal :: ( MonadReader env m+               , LabelOptic' "loggerConfig" A_Lens env LoggerConfig+               , MonadIO m+               ) => LogLevel+                 -> Text+                 -> m ()+logInternal logLevel msg = do+  LoggerConfig {..} <- gets @"loggerConfig"+  let color' c = if fancyColors then color c else id+  let style' = case logLevel of+        Debug   -> style Bold . color' Blue+        Info    -> style Bold . color' Green+        Warn    -> style Bold . color' Yellow+        Error   -> style Bold . color' Red+  let l = case logLevel of+        Debug   -> style' "[ Debug ]"+        Info    -> style' "[ Info  ]"+        Warn    -> style' "[ Warn  ]"+        Error   -> style' "[ Error ]"+  let strs = T.split (== '\n') msg+  let out = case strs of+              [] -> T.empty+              (x:xs) -> +                  foldr (\a b -> a <> "\n" <> b) mempty+                . ((l <> " " <> x) :)+                . fmap (\line' -> style' "[ ...   ] " <> line' )+                $ xs +  when (lcPrintDebug || (not lcPrintDebug && (logLevel /= Debug)))+    $ liftIO $ consoleOutter out -initGHCupFileLogging :: (MonadIO m, MonadReader AppState m) => Path Rel -> m (Path Abs)-initGHCupFileLogging context = do-  AppState {dirs = Dirs {..}} <- ask-  let logfile = logsDir </> context-  liftIO $ do-    createDirRecursive' logsDir-    hideError doesNotExistErrorType $ deleteFile logfile-    createRegularFile newFilePerms logfile-    pure logfile+  -- raw output+  let lr = case logLevel of+        Debug   -> "Debug:"+        Info    -> "Info:"+        Warn    -> "Warn:"+        Error   -> "Error:"+  let outr = lr <> " " <> msg <> "\n"+  liftIO $ fileOutter outr+++initGHCupFileLogging :: ( MonadReader env m+                        , HasDirs env+                        , MonadIO m+                        , MonadMask m+                        ) => m FilePath+initGHCupFileLogging = do+  Dirs { logsDir } <- getDirs+  let logfile = logsDir </> "ghcup.log"+  logFiles <- liftIO $ findFiles+    logsDir+    (makeRegexOpts compExtended+                   execBlank+                   ([s|^.*\.log$|] :: B.ByteString)+    )+  forM_ logFiles $ hideError doesNotExistErrorType . recycleFile . (logsDir </>)++  liftIO $ writeFile logfile ""+  pure logfile
+ lib/GHCup/Utils/Logger.hs-boot view
@@ -0,0 +1,21 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE QuasiQuotes      #-}+{-# LANGUAGE DataKinds        #-}+{-# LANGUAGE OverloadedStrings   #-}++module GHCup.Utils.Logger where++import           GHCup.Types++import           Control.Monad.IO.Class+import           Control.Monad.Reader+import           Data.Text               ( Text )+import           Optics++logWarn :: ( MonadReader env m+           , LabelOptic' "loggerConfig" A_Lens env LoggerConfig+           , MonadIO m+           )+        => Text+        -> m ()+
lib/GHCup/Utils/MegaParsec.hs view
@@ -8,7 +8,7 @@ License     : LGPL-3.0 Maintainer  : hasufell@hasufell.de Stability   : experimental-Portability : POSIX+Portability : portable -} module GHCup.Utils.MegaParsec where @@ -23,6 +23,7 @@ import           Data.Text                      ( Text ) import           Data.Versions import           Data.Void+import           System.FilePath  import qualified Data.List.NonEmpty            as NE import qualified Data.Text                     as T@@ -67,6 +68,15 @@     <*> (MP.chunk t <* MP.eof)  +-- | Extracts the version from @ProjectVersion="8.10.5"@.+ghcProjectVersion :: MP.Parsec Void Text Version+ghcProjectVersion = do+  _ <- MP.chunk "ProjectVersion=\""+  ver <- parseUntil1 $ MP.chunk "\""+  MP.setInput ver+  version'++ -- | Extracts target triple and version from e.g. --   * armv7-unknown-linux-gnueabihf-8.8.3 --   * armv7-unknown-linux-gnueabihf-8.8.3@@ -108,3 +118,7 @@       v <- versioning'       MP.setInput rest       pure v+++pathSep :: MP.Parsec Void Text Char+pathSep = MP.oneOf pathSeparators
lib/GHCup/Utils/Prelude.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP                 #-} {-# LANGUAGE DataKinds           #-} {-# LANGUAGE FlexibleContexts    #-} {-# LANGUAGE FlexibleInstances   #-}@@ -12,31 +13,55 @@ License     : LGPL-3.0 Maintainer  : hasufell@hasufell.de Stability   : experimental-Portability : POSIX+Portability : portable  GHCup specific prelude. Lots of Excepts functionality. -} module GHCup.Utils.Prelude where +#if defined(IS_WINDOWS)+import           GHCup.Types+#endif+import           GHCup.Errors+import           GHCup.Types.Optics+import {-# SOURCE #-} GHCup.Utils.Logger+ import           Control.Applicative import           Control.Exception.Safe import           Control.Monad import           Control.Monad.IO.Class-import           Control.Monad.Trans.Class      ( lift )+import           Control.Monad.Reader import           Data.Bifunctor import           Data.ByteString                ( ByteString )+import           Data.List                      ( nub, intercalate, stripPrefix, isPrefixOf, dropWhileEnd )+import           Data.Maybe+import           Data.Foldable+import           Data.List.NonEmpty             ( NonEmpty( (:|) )) import           Data.String import           Data.Text                      ( Text ) import           Data.Versions-import           Data.Word8+import           Data.Word8                  hiding ( isDigit ) import           Haskus.Utils.Types.List import           Haskus.Utils.Variant.Excepts+import           Text.PrettyPrint.HughesPJClass ( prettyShow, Pretty ) import           System.IO.Error-import           System.Posix.Env.ByteString    ( getEnvironment )+#if defined(IS_WINDOWS)+import           System.IO.Temp+#endif+import           System.IO.Unsafe+import           System.Directory+import           System.FilePath +#if defined(IS_WINDOWS)+import           Control.Retry+import           GHC.IO.Exception+#endif+ import qualified Data.ByteString               as B import qualified Data.ByteString.Lazy          as L import qualified Data.Strict.Maybe             as S+import qualified Data.List.Split               as Split+import qualified Data.List.NonEmpty            as NE import qualified Data.Text                     as T import qualified Data.Text.Encoding            as E import qualified Data.Text.Encoding.Error      as E@@ -44,9 +69,21 @@ import qualified Data.Text.Lazy.Builder        as B import qualified Data.Text.Lazy.Builder.Int    as B import qualified Data.Text.Lazy.Encoding       as TLE+#if defined(IS_WINDOWS)+import qualified System.Win32.File             as Win32+#endif  +-- $setup+-- >>> import Data.ByteString.Internal (c2w, w2c)+-- >>> import Test.QuickCheck+-- >>> import Data.Word8+-- >>> import qualified Data.Text as T+-- >>> import qualified Data.Char as C+-- >>> import Data.List+-- >>> instance Arbitrary T.Text where arbitrary = T.pack <$> arbitrary + fS :: IsString a => String -> a fS = fromString @@ -140,6 +177,14 @@      -> Excepts es m a lEM' f em = lift em >>= lE . first f +-- for some obscure reason... this won't type-check if we move it to a different module+catchWarn :: forall es m env . ( Pretty (V es)+                             , MonadReader env m+                             , HasLog env+                             , MonadIO m+                             , Monad m) => Excepts es m () -> Excepts '[] m ()+catchWarn = catchAllE @_ @es (\v -> lift $ logWarn (T.pack . prettyShow $ v))+ fromEither :: Either a b -> VEither '[a] b fromEither = either (VLeft . V) VRight @@ -180,14 +225,14 @@ hideError err = handleIO (\e -> if err == ioeGetErrorType e then pure () else liftIO . ioError $ e)  -hideErrorDef :: [IOErrorType] -> a -> IO a -> IO a+hideErrorDef :: (MonadIO m, MonadCatch m) => [IOErrorType] -> a -> m a -> m a hideErrorDef errs def =-  handleIO (\e -> if ioeGetErrorType e `elem` errs then pure def else ioError e)+  handleIO (\e -> if ioeGetErrorType e `elem` errs then pure def else liftIO $ ioError e)  -hideErrorDefM :: [IOErrorType] -> IO a -> IO a -> IO a+hideErrorDefM :: (MonadIO m, MonadCatch m) => [IOErrorType] -> m a -> m a -> m a hideErrorDefM errs def =-  handleIO (\e -> if ioeGetErrorType e `elem` errs then def else ioError e)+  handleIO (\e -> if ioeGetErrorType e `elem` errs then def else liftIO $ ioError e)   -- TODO: does this work?@@ -242,6 +287,8 @@ verToBS :: Version -> ByteString verToBS = E.encodeUtf8 . prettyVer +verToS :: Version -> String+verToS = T.unpack . prettyVer  intToText :: Integral a => a -> T.Text intToText = TL.toStrict . B.toLazyText . B.decimal@@ -252,21 +299,29 @@   maybe str' T.unpack . T.stripPrefix (T.pack "_") . T.pack $ str'  -addToCurrentEnv :: MonadIO m-                => [(ByteString, ByteString)]-                -> m [(ByteString, ByteString)]-addToCurrentEnv adds = do-  cEnv <- liftIO getEnvironment-  pure (adds ++ cEnv)+pvpToVersion :: MonadThrow m => PVP -> m Version+pvpToVersion =+  either (\_ -> throwM $ ParseError "Couldn't convert PVP to Version") pure . version . prettyPVP +versionToPVP :: MonadThrow m => Version -> m PVP+versionToPVP v = either (\_ -> alternative v) pure . pvp . prettyVer $ v+ where+  alternative :: MonadThrow m => Version -> m PVP+  alternative v' = case NE.takeWhile isDigit (_vChunks v') of+    [] -> throwM $ ParseError "Couldn't convert Version to PVP"+    xs -> pure $ pvpFromList (unsafeDigit <$> xs) -pvpToVersion :: PVP -> Version-pvpToVersion =-  either (\_ -> error "Couldn't convert PVP to Version") id-    . version-    . prettyPVP+  isDigit :: VChunk -> Bool+  isDigit (Digits _ :| []) = True+  isDigit _                = False +  unsafeDigit :: VChunk -> Int+  unsafeDigit (Digits x :| []) = fromIntegral x+  unsafeDigit _ = error "unsafeDigit: wrong input" +pvpFromList :: [Int] -> PVP+pvpFromList = PVP . NE.fromList . fmap fromIntegral+ -- | Safe 'decodeUtf8With'. Replaces an invalid input byte with -- the Unicode replacement character U+FFFD. decUTF8Safe :: ByteString -> Text@@ -283,4 +338,409 @@   go [] = []   go (x : xs) | x == _period = [_backslash, _period] ++ go xs               | otherwise    = x : go xs++-- | More permissive version of 'createDirRecursive'. This doesn't+-- error when the destination is a symlink to a directory.+createDirRecursive' :: FilePath -> IO ()+createDirRecursive' p =+  handleIO (\e -> if isAlreadyExistsError e then isSymlinkDir e else throwIO e)+    . createDirectoryIfMissing True+    $ p++ where+  isSymlinkDir e = do+    ft <- pathIsSymbolicLink p+    case ft of+      True -> do+        rp <- canonicalizePath p+        rft <- doesDirectoryExist rp+        case rft of+          True -> pure ()+          _ -> throwIO e+      _ -> throwIO e+++-- | Recursively copy the contents of one directory to another path.+--+-- This is a rip-off of Cabal library.+copyDirectoryRecursive :: FilePath -> FilePath -> (FilePath -> FilePath -> IO ()) -> IO ()+copyDirectoryRecursive srcDir destDir doCopy = do+  srcFiles <- getDirectoryContentsRecursive srcDir+  copyFilesWith destDir [ (srcDir, f)+                          | f <- srcFiles ]+  where+    -- | Common implementation of 'copyFiles', 'installOrdinaryFiles',+    -- 'installExecutableFiles' and 'installMaybeExecutableFiles'.+    copyFilesWith :: FilePath -> [(FilePath, FilePath)] -> IO ()+    copyFilesWith targetDir srcFiles = do++      -- Create parent directories for everything+      let dirs = map (targetDir </>) . nub . map (takeDirectory . snd) $ srcFiles+      traverse_ (createDirectoryIfMissing True) dirs++      -- Copy all the files+      sequence_ [ let src  = srcBase   </> srcFile+                      dest = targetDir </> srcFile+                   in doCopy src dest+                | (srcBase, srcFile) <- srcFiles ]+++-- | List all the files in a directory and all subdirectories.+--+-- The order places files in sub-directories after all the files in their+-- parent directories. The list is generated lazily so is not well defined if+-- the source directory structure changes before the list is used.+--+getDirectoryContentsRecursive :: FilePath -> IO [FilePath]+getDirectoryContentsRecursive topdir = recurseDirectories [""]+  where+    recurseDirectories :: [FilePath] -> IO [FilePath]+    recurseDirectories []         = return []+    recurseDirectories (dir:dirs) = unsafeInterleaveIO $ do+      (files, dirs') <- collect [] [] =<< getDirectoryContents (topdir </> dir)+      files' <- recurseDirectories (dirs' ++ dirs)+      return (files ++ files')++      where+        collect files dirs' []              = return (reverse files+                                                     ,reverse dirs')+        collect files dirs' (entry:entries) | ignore entry+                                            = collect files dirs' entries+        collect files dirs' (entry:entries) = do+          let dirEntry = dir </> entry+          isDirectory <- doesDirectoryExist (topdir </> dirEntry)+          if isDirectory+            then collect files (dirEntry:dirs') entries+            else collect (dirEntry:files) dirs' entries++        ignore ['.']      = True+        ignore ['.', '.'] = True+        ignore _          = False+++-- https://github.com/haskell/directory/issues/110+-- https://github.com/haskell/directory/issues/96+-- https://www.sqlite.org/src/info/89f1848d7f+recyclePathForcibly :: ( MonadIO m+                       , MonadReader env m+                       , HasDirs env+                       , MonadMask m+                       )+                    => FilePath+                    -> m ()+recyclePathForcibly fp = do+#if defined(IS_WINDOWS)+  Dirs { recycleDir } <- getDirs+  tmp <- liftIO $ createTempDirectory recycleDir "recyclePathForcibly"+  let dest = tmp </> takeFileName fp+  liftIO (Win32.moveFileEx fp (Just dest) 0)+      `catch`+      (\e -> if isPermissionError e {- EXDEV on windows -} then recover (liftIO $ removePathForcibly fp) else throwIO e)+      `finally`+        (liftIO $ handleIO (\_ -> pure ()) $ removePathForcibly tmp)+#else+  liftIO $ removePathForcibly fp+#endif+++rmPathForcibly :: ( MonadIO m+                  , MonadMask m+                  )+               => FilePath+               -> m ()+rmPathForcibly fp =+#if defined(IS_WINDOWS)+  recover (liftIO $ removePathForcibly fp)+#else+  liftIO $ removePathForcibly fp+#endif+++rmDirectory :: (MonadIO m, MonadMask m)+            => FilePath+            -> m ()+rmDirectory fp =+#if defined(IS_WINDOWS)+  recover (liftIO $ removeDirectory fp)+#else+  liftIO $ removeDirectory fp+#endif+++-- https://www.sqlite.org/src/info/89f1848d7f+-- https://github.com/haskell/directory/issues/96+recycleFile :: ( MonadIO m+               , MonadMask m+               , MonadReader env m+               , HasDirs env+               )+            => FilePath+            -> m ()+recycleFile fp = do+#if defined(IS_WINDOWS)+  Dirs { recycleDir } <- getDirs+  liftIO $ whenM (doesDirectoryExist fp) $ ioError (IOError Nothing InappropriateType "recycleFile" "" Nothing (Just fp))+  tmp <- liftIO $ createTempDirectory recycleDir "recycleFile"+  let dest = tmp </> takeFileName fp+  liftIO (Win32.moveFileEx fp (Just dest) 0)+    `catch`+      (\e -> if isPermissionError e {- EXDEV on windows -} then recover (liftIO $ removePathForcibly fp) else throwIO e)+    `finally`+      (liftIO $ handleIO (\_ -> pure ()) $ removePathForcibly tmp)+#else+  liftIO $ removeFile fp+#endif+++rmFile :: ( MonadIO m+          , MonadMask m+          )+      => FilePath+      -> m ()+rmFile fp =+#if defined(IS_WINDOWS)+  recover (liftIO $ removeFile fp)+#else+  liftIO $ removeFile fp+#endif+++rmDirectoryLink :: (MonadIO m, MonadMask m, MonadReader env m, HasDirs env)+                => FilePath+                -> m ()+rmDirectoryLink fp = +#if defined(IS_WINDOWS)+  recover (liftIO $ removeDirectoryLink fp)+#else+  liftIO $ removeDirectoryLink fp+#endif+++#if defined(IS_WINDOWS)+recover :: (MonadIO m, MonadMask m) => m a -> m a+recover action = +  recovering (fullJitterBackoff 25000 <> limitRetries 10)+    [\_ -> Handler (\e -> pure $ isPermissionError e)+    ,\_ -> Handler (\e -> pure (ioeGetErrorType e == InappropriateType))+    ,\_ -> Handler (\e -> pure (ioeGetErrorType e == UnsatisfiedConstraints))+    ]+    (\_ -> action)+#endif+++copyFileE :: (CopyError :< xs, MonadCatch m, MonadIO m) => FilePath -> FilePath -> Excepts xs m ()+copyFileE from = handleIO (throwE . CopyError . show) . liftIO . copyFile from+++-- | Gathering monoidal values+--+-- >>> traverseFold (pure . (:["0"])) ["1","2"]+-- ["1","0","2","0"]+-- >>> traverseFold Just ["1","2","3","4","5"]+-- Just "12345"+--+-- prop> \t -> traverseFold Just t === Just (mconcat t)+traverseFold :: (Foldable t, Applicative m, Monoid b) => (a -> m b) -> t a -> m b+traverseFold f = foldl (\mb a -> (<>) <$> mb <*> f a) (pure mempty)++-- | Gathering monoidal values+forFold :: (Foldable t, Applicative m, Monoid b) => t a -> (a -> m b) -> m b+forFold = \t -> (`traverseFold` t)+++-- | Strip @\\r@ and @\\n@ from 'String's+--+-- >>> stripNewline "foo\n\n\n"+-- "foo"+-- >>> stripNewline "foo\n\n\nfoo"+-- "foofoo"+-- >>> stripNewline "foo\r"+-- "foo"+-- >>> stripNewline "foo"+-- "foo"+--+-- prop> \t -> stripNewline (t <> "\n") === stripNewline t+-- prop> \t -> not (any (isNewLine . c2w) t) ==> stripNewline t == t+stripNewline :: String -> String+stripNewline = filter (`notElem` "\n\r")+++-- | Strip @\\r@ and @\\n@ from end of 'String'.+--+-- >>> stripNewlineEnd "foo\n\n\n"+-- "foo"+-- >>> stripNewlineEnd "foo\n\n\nfoo"+-- "foo\n\n\nfoo"+-- >>> stripNewlineEnd "foo\r"+-- "foo"+-- >>> stripNewlineEnd "foo"+-- "foo"+--+-- prop> \t -> stripNewlineEnd (t <> "\n") === stripNewlineEnd t+-- prop> \t -> not (any (isNewLine . c2w) t) ==> stripNewlineEnd t == t+stripNewlineEnd :: String -> String+stripNewlineEnd = dropWhileEnd (`elem` "\n\r")+++-- | Strip @\\r@ and @\\n@ from 'Text's+--+-- >>> stripNewline' "foo\n\n\n"+-- "foo"+-- >>> stripNewline' "foo\n\n\nfoo"+-- "foofoo"+-- >>> stripNewline' "foo\r"+-- "foo"+-- >>> stripNewline' "foo"+-- "foo"+--+-- prop> \t -> stripNewline' (t <> "\n") === stripNewline' t+-- prop> \t -> not (T.any (isNewLine . c2w) t) ==> stripNewline' t == t+stripNewline' :: T.Text -> T.Text+stripNewline' = T.filter (`notElem` "\n\r")+++-- | Is the word8 a newline?+--+-- >>> isNewLine (c2w '\n')+-- True+-- >>> isNewLine (c2w '\r')+-- True+--+-- prop> \w -> w /= _lf && w /= _cr ==> not (isNewLine w)+isNewLine :: Word8 -> Bool+isNewLine w+  | w == _lf = True+  | w == _cr = True+  | otherwise = False+++-- | Split on a PVP suffix.+--+-- >>> splitOnPVP "-" "ghc-iserv-dyn-9.3.20210706"+-- ("ghc-iserv-dyn","9.3.20210706")+-- >>> splitOnPVP "-" "ghc-iserv-dyn"+-- ("ghc-iserv-dyn","")+splitOnPVP :: String -> String -> (String, String)+splitOnPVP c s = case Split.splitOn c s of+  []  -> def+  [_] -> def+  xs+    | let l = last xs+    , (Right _) <- pvp (T.pack l) -> (intercalate c (init xs), l)+    | otherwise -> def+ where+  def = (s, "")++++-- | Like 'find', but where the test can be monadic.+--+-- >>> findM (Just . C.isUpper) "teST"+-- Just (Just 'S')+-- >>> findM (Just . C.isUpper) "test"+-- Just Nothing+-- >>> findM (Just . const True) ["x",undefined]+-- Just (Just "x")+findM :: Monad m => (a -> m Bool) -> [a] -> m (Maybe a)+findM ~p = foldr (\x -> ifM (p x) (pure $ Just x)) (pure Nothing)+++-- | Drops the given suffix from a list.+--   It returns the original sequence if the sequence doesn't end with the given suffix.+--+-- >>> dropSuffix "!" "Hello World!"+-- "Hello World"+-- >>> dropSuffix "!" "Hello World!!"+-- "Hello World!"+-- >>> dropSuffix "!" "Hello World."+-- "Hello World."+dropSuffix :: Eq a => [a] -> [a] -> [a]+dropSuffix a b = fromMaybe b $ stripSuffix a b++-- | Return the prefix of the second list if its suffix+--   matches the entire first list.+--+-- >>> stripSuffix "bar" "foobar"+-- Just "foo"+-- >>> stripSuffix ""    "baz"+-- Just "baz"+-- >>> stripSuffix "foo" "quux"+-- Nothing+stripSuffix :: Eq a => [a] -> [a] -> Maybe [a]+stripSuffix a b = reverse <$> stripPrefix (reverse a) (reverse b)+++-- | Drops the given prefix from a list.+--   It returns the original sequence if the sequence doesn't start with the given prefix.+--+-- >>> dropPrefix "Mr. " "Mr. Men"+-- "Men"+-- >>> dropPrefix "Mr. " "Dr. Men"+-- "Dr. Men"+dropPrefix :: Eq a => [a] -> [a] -> [a]+dropPrefix a b = fromMaybe b $ stripPrefix a b++++-- | Break a list into pieces separated by the first+-- list argument, consuming the delimiter. An empty delimiter is+-- invalid, and will cause an error to be raised.+--+-- >>> splitOn "\r\n" "a\r\nb\r\nd\r\ne"+-- ["a","b","d","e"]+-- >>> splitOn "aaa"  "aaaXaaaXaaaXaaa"+-- ["","X","X","X",""]+-- >>> splitOn "x"    "x"+-- ["",""]+-- >>> splitOn "x"    ""+-- [""]+--+-- prop> \s x -> s /= "" ==> intercalate s (splitOn s x) == x+-- prop> \c x -> splitOn [c] x                           == split (==c) x+splitOn :: Eq a => [a] -> [a] -> [[a]]+splitOn [] _ = error "splitOn, needle may not be empty"+splitOn _ [] = [[]]+splitOn needle haystack = a : if null b then [] else splitOn needle $ drop (length needle) b+    where (a,b) = breakOn needle haystack+++-- | Splits a list into components delimited by separators,+-- where the predicate returns True for a separator element.  The+-- resulting components do not contain the separators.  Two adjacent+-- separators result in an empty component in the output.+--+-- >>> split (== 'a') "aabbaca"+-- ["","","bb","c",""]+-- >>> split (== 'a') ""+-- [""]+-- >>> split (== ':') "::xyz:abc::123::"+-- ["","","xyz","abc","","123","",""]+-- >>> split (== ',') "my,list,here"+-- ["my","list","here"]+split :: (a -> Bool) -> [a] -> [[a]]+split _ [] = [[]]+split f (x:xs)+  | f x = [] : split f xs+  | y:ys <- split f xs = (x:y) : ys+  | otherwise = [[]]+++-- | Find the first instance of @needle@ in @haystack@.+-- The first element of the returned tuple+-- is the prefix of @haystack@ before @needle@ is matched.  The second+-- is the remainder of @haystack@, starting with the match.+-- If you want the remainder /without/ the match, use 'stripInfix'.+--+-- >>> breakOn "::" "a::b::c"+-- ("a","::b::c")+-- >>> breakOn "/" "foobar"+-- ("foobar","")+--+-- prop> \needle haystack -> let (prefix,match) = breakOn needle haystack in prefix ++ match == haystack+breakOn :: Eq a => [a] -> [a] -> ([a], [a])+breakOn needle haystack | needle `isPrefixOf` haystack = ([], haystack)+breakOn _ [] = ([], [])+breakOn needle (x:xs) = first (x:) $ breakOn needle xs++ 
lib/GHCup/Utils/String/QQ.hs view
@@ -7,7 +7,7 @@ License     : LGPL-3.0 Maintainer  : hasufell@hasufell.de Stability   : experimental-Portability : POSIX+Portability : portable  QuasiQuoter for non-interpolated strings, texts and bytestrings. @@ -44,15 +44,14 @@ -- The pattern portion is undefined. s :: QuasiQuoter s = QuasiQuoter-  (\s' -> case and $ fmap isAscii s' of+  (\s' -> case all isAscii s' of     True  -> (\a -> [|fromString a|]) . trimLeadingNewline . removeCRs $ s'     False -> fail "Not ascii"   )-  (error "Cannot use q as a pattern")-  (error "Cannot use q as a type")-  (error "Cannot use q as a dec")+  (error "Cannot use s as a pattern")+  (error "Cannot use s as a type")+  (error "Cannot use s as a dec")  where   removeCRs = filter (/= '\r')   trimLeadingNewline ('\n' : xs) = xs   trimLeadingNewline xs          = xs-
lib/GHCup/Utils/Version/QQ.hs view
@@ -14,7 +14,7 @@ License     : LGPL-3.0 Maintainer  : hasufell@hasufell.de Stability   : experimental-Portability : POSIX+Portability : portable -} module GHCup.Utils.Version.QQ where 
lib/GHCup/Version.hs view
@@ -8,7 +8,7 @@ License     : LGPL-3.0 Maintainer  : hasufell@hasufell.de Stability   : experimental-Portability : POSIX+Portability : portable -} module GHCup.Version where @@ -24,8 +24,11 @@ import qualified Data.Text                     as T  -- | This reflects the API version of the YAML.+--+-- Note that when updating this, CI requires that the file exsists AND the same file exists at+-- 'https://www.haskell.org/ghcup/exp/ghcup-<ver>.yaml' with some newlines added. ghcupURL :: URI-ghcupURL = [uri|https://www.haskell.org/ghcup/data/ghcup-0.0.4.yaml|]+ghcupURL = [uri|https://www.haskell.org/ghcup/data/ghcup-0.0.6.yaml|]  -- | The current ghcup version. ghcUpVer :: PVP
+ lib/System/Console/Terminal/Common.hs view
@@ -0,0 +1,43 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveTraversable #-}++#if __GLASGOW_HASKELL__ >= 702+#define LANGUAGE_DeriveGeneric+{-# LANGUAGE DeriveGeneric #-}+#endif++module System.Console.Terminal.Common+  ( Window(..)+  ) where++import Data.Data (Typeable, Data)++#if __GLASGOW_HASKELL__ < 710+import Data.Foldable (Foldable)+import Data.Traversable (Traversable)+#endif++#ifdef LANGUAGE_DeriveGeneric+import GHC.Generics+  ( Generic+#if __GLASGOW_HASKELL__ >= 706+  , Generic1+#endif+  )+#endif++-- | Terminal window width and height+data Window a = Window+  { height :: !a+  , width  :: !a+  } deriving+    ( Show, Eq, Read, Data, Typeable+    , Foldable, Functor, Traversable+#ifdef LANGUAGE_DeriveGeneric+    , Generic+#if __GLASGOW_HASKELL__ >= 706+    , Generic1+#endif+#endif+    )
+ lib/System/Console/Terminal/Posix.hsc view
@@ -0,0 +1,65 @@+{-# LANGUAGE CApiFFI #-}++module System.Console.Terminal.Posix+  ( size, fdSize, hSize+  ) where++import System.Console.Terminal.Common+import Control.Exception (catch)+import Data.Typeable (cast)+import Foreign+import Foreign.C.Error+import Foreign.C.Types+import GHC.IO.FD (FD(FD, fdFD))+import GHC.IO.Handle.Internals (withHandle_)+import GHC.IO.Handle.Types (Handle, Handle__(Handle__, haDevice))+#if defined(__GLASGOW_HASKELL__) && (__GLASGOW_HASKELL__ < 706)+import Prelude hiding (catch)+#endif+import System.Posix.Types (Fd(Fd))++#include <sys/ioctl.h>+#include <unistd.h>+++#let alignment t = "%lu", (unsigned long)offsetof(struct {char x__; t (y__); }, y__)+++-- Interesting part of @struct winsize@+data CWin = CWin CUShort CUShort++instance Storable CWin where+  sizeOf _ = (#size struct winsize)+  alignment _ = (#alignment struct winsize)+  peek ptr = do+    row <- (#peek struct winsize, ws_row) ptr+    col <- (#peek struct winsize, ws_col) ptr+    return $ CWin row col+  poke ptr (CWin row col) = do+    (#poke struct winsize, ws_row) ptr row+    (#poke struct winsize, ws_col) ptr col+++fdSize :: Integral n => Fd -> IO (Maybe (Window n))+fdSize (Fd fd) = with (CWin 0 0) $ \ws -> do+  _ <- throwErrnoIfMinus1 "ioctl" $+    ioctl fd (#const TIOCGWINSZ) ws+  CWin row col <- peek ws+  return . Just $ Window (fromIntegral row) (fromIntegral col)+ `catch`+  handler+ where+  handler :: IOError -> IO (Maybe (Window h))+  handler _ = return Nothing++foreign import capi "sys/ioctl.h ioctl"+  ioctl :: CInt -> CULong -> Ptr CWin -> IO CInt++size :: Integral n => IO (Maybe (Window n))+size = fdSize (Fd (#const STDOUT_FILENO))++hSize :: Integral n => Handle -> IO (Maybe (Window n))+hSize h = withHandle_ "hSize" h $ \Handle__ { haDevice = dev } ->+  case cast dev of+    Nothing -> return Nothing+    Just FD { fdFD = fd } -> fdSize (Fd fd)
test/GHCup/ArbitraryTypes.hs view
@@ -11,7 +11,6 @@ import           Data.ByteString                ( ByteString ) import           Data.Versions import           Data.List.NonEmpty-import           HPath import           Test.QuickCheck import           Test.QuickCheck.Arbitrary.ADT  ( ToADTArbitrary ) import           Test.QuickCheck.Arbitrary.Generic@@ -67,7 +66,7 @@     ---------------------  instance Arbitrary Scheme where-  arbitrary = oneof [ pure (Scheme "http"), pure (Scheme "https") ]+  arbitrary = elements [ Scheme "http", Scheme "https" ]  instance Arbitrary Host where   arbitrary = genericArbitrary@@ -164,16 +163,15 @@   arbitrary = genericArbitrary   shrink    = genericShrink -instance Arbitrary (Path Rel) where-  arbitrary =-    either (error . show) id . parseRel . E.encodeUtf8 . T.pack-      <$> listOf1 (elements ['a' .. 'z'])- instance Arbitrary TarDir where   arbitrary = genericArbitrary   shrink    = genericShrink  instance Arbitrary Tool where+  arbitrary = genericArbitrary+  shrink    = genericShrink++instance Arbitrary GlobalTool where   arbitrary = genericArbitrary   shrink    = genericShrink 
test/GHCup/Types/JSONSpec.hs view
@@ -13,4 +13,5 @@  spec :: Spec spec = do-  roundtripAndGoldenSpecs (Proxy @GHCupInfo)+  roundtripAndGoldenSpecsWithSettings (defaultSettings { goldenDirectoryOption = CustomDirectoryName "test/golden" }) (Proxy @GHCupInfo)+