Compare commits
13 Commits
url-comple
...
issue-328
| Author | SHA1 | Date | |
|---|---|---|---|
|
2b6d970723
|
|||
|
41ecf897fb
|
|||
|
4c9c6e9223
|
|||
|
8be71c4c5c
|
|||
|
01d310e630
|
|||
|
96cb99e1b5
|
|||
|
2e08efeed7
|
|||
|
04fceb3134
|
|||
|
1f0a891bab
|
|||
|
6c63a65983
|
|||
|
199d3b7aee
|
|||
|
04fc04f586
|
|||
|
3f96a6460a
|
@@ -1,5 +1,11 @@
|
|||||||
# Revision history for ghcup
|
# Revision history for ghcup
|
||||||
|
|
||||||
|
## 0.1.17.6 -- ????-??-??
|
||||||
|
|
||||||
|
* Vastly improve shell completions wrt [#242](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/242)
|
||||||
|
* Fix 'ghcup install cabal/hls/stack --set' wrt [#324](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/324)
|
||||||
|
* Fix bad error message wrt [#323](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/323)
|
||||||
|
|
||||||
## 0.1.17.5 -- 2022-02-26
|
## 0.1.17.5 -- 2022-02-26
|
||||||
|
|
||||||
* Implement `ghcup run` subcommand wrt [#137](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/137)
|
* Implement `ghcup run` subcommand wrt [#137](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/137)
|
||||||
|
|||||||
@@ -124,6 +124,7 @@ opts =
|
|||||||
<> metavar "URL"
|
<> metavar "URL"
|
||||||
<> help "Alternative ghcup download info url"
|
<> help "Alternative ghcup download info url"
|
||||||
<> internal
|
<> internal
|
||||||
|
<> completer fileUri
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
<*> (fmap . fmap) not (invertableSwitch "verify" 'n' True (help "Disable tarball checksum verification (default: enabled)"))
|
<*> (fmap . fmap) not (invertableSwitch "verify" 'n' True (help "Disable tarball checksum verification (default: enabled)"))
|
||||||
@@ -134,6 +135,7 @@ opts =
|
|||||||
<> help
|
<> help
|
||||||
"Keep build directories? (default: errors)"
|
"Keep build directories? (default: errors)"
|
||||||
<> hidden
|
<> hidden
|
||||||
|
<> completer (listCompleter ["always", "errors", "never"])
|
||||||
))
|
))
|
||||||
<*> optional (option
|
<*> optional (option
|
||||||
(eitherReader downloaderParser)
|
(eitherReader downloaderParser)
|
||||||
@@ -142,10 +144,12 @@ opts =
|
|||||||
<> metavar "<internal|curl|wget>"
|
<> metavar "<internal|curl|wget>"
|
||||||
<> help
|
<> help
|
||||||
"Downloader to use (default: internal)"
|
"Downloader to use (default: internal)"
|
||||||
|
<> completer (listCompleter ["internal", "curl", "wget"])
|
||||||
#else
|
#else
|
||||||
<> metavar "<curl|wget>"
|
<> metavar "<curl|wget>"
|
||||||
<> help
|
<> help
|
||||||
"Downloader to use (default: curl)"
|
"Downloader to use (default: curl)"
|
||||||
|
<> completer (listCompleter ["curl", "wget"])
|
||||||
#endif
|
#endif
|
||||||
<> hidden
|
<> hidden
|
||||||
))
|
))
|
||||||
@@ -156,6 +160,7 @@ opts =
|
|||||||
<> metavar "<strict|lax|none>"
|
<> metavar "<strict|lax|none>"
|
||||||
<> help
|
<> help
|
||||||
"GPG verification (default: none)"
|
"GPG verification (default: none)"
|
||||||
|
<> completer (listCompleter ["strict", "lax", "none"])
|
||||||
))
|
))
|
||||||
<*> com
|
<*> com
|
||||||
where
|
where
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ import Haskus.Utils.Variant.Excepts
|
|||||||
import Options.Applicative hiding ( style )
|
import Options.Applicative hiding ( style )
|
||||||
import Prelude hiding ( appendFile )
|
import Prelude hiding ( appendFile )
|
||||||
import Safe
|
import Safe
|
||||||
|
import System.Directory
|
||||||
import System.Process ( readProcess )
|
import System.Process ( readProcess )
|
||||||
import System.FilePath
|
import System.FilePath
|
||||||
import Text.HTML.TagSoup hiding ( Tag )
|
import Text.HTML.TagSoup hiding ( Tag )
|
||||||
@@ -301,20 +302,37 @@ gpgParser s' | t == T.pack "strict" = Right GPGStrict
|
|||||||
toolCompleter :: Completer
|
toolCompleter :: Completer
|
||||||
toolCompleter = listCompleter ["ghc", "cabal", "hls", "stack"]
|
toolCompleter = listCompleter ["ghc", "cabal", "hls", "stack"]
|
||||||
|
|
||||||
|
gitFileUri :: [String] -> Completer
|
||||||
|
gitFileUri add = mkCompleter $ fileUri' (["git://"] <> add)
|
||||||
|
|
||||||
fileUri :: Completer
|
fileUri :: Completer
|
||||||
fileUri = mkCompleter $ \case
|
fileUri = mkCompleter $ fileUri' []
|
||||||
"" -> pure ["https://", "http://", "file:///"]
|
|
||||||
|
fileUri' :: [String] -> String -> IO [String]
|
||||||
|
fileUri' add = \case
|
||||||
|
"" -> do
|
||||||
|
pwd <- getCurrentDirectory
|
||||||
|
pure $ ["https://", "http://", "file:///", "file://" <> pwd <> "/"] <> add
|
||||||
xs
|
xs
|
||||||
| "file://" `isPrefixOf` xs -> fmap ("file://" <>) <$>
|
| "file:///" `isPrefixOf` xs -> fmap ("file://" <>) <$>
|
||||||
case stripPrefix "file://" xs of
|
case stripPrefix "file://" xs of
|
||||||
Nothing -> pure []
|
Nothing -> pure []
|
||||||
Just r -> do
|
Just r -> do
|
||||||
let cmd = unwords ["compgen", "-A", "file", "--", requote r]
|
pwd <- getCurrentDirectory
|
||||||
result <- tryIO $ readProcess "bash" ["-c", cmd] ""
|
dirs <- compgen "directory" r ["-S", "/"]
|
||||||
return . lines . either (const []) id $ result
|
files <- filter (\f -> (f <> "/") `notElem` dirs) <$> compgen "file" r []
|
||||||
|
pure (dirs <> files <> if r `isPrefixOf` pwd then [pwd <> "/"] else [])
|
||||||
|
| xs `isPrefixOf` "file:///" -> pure ["file:///"]
|
||||||
|
| xs `isPrefixOf` "https://" -> pure ["https://"]
|
||||||
|
| xs `isPrefixOf` "http://" -> pure ["http://"]
|
||||||
| otherwise -> pure []
|
| otherwise -> pure []
|
||||||
where
|
where
|
||||||
|
compgen :: String -> String -> [String] -> IO [String]
|
||||||
|
compgen action' r opts = do
|
||||||
|
let cmd = unwords $ ["compgen", "-A", action'] <> opts <> ["--", requote r]
|
||||||
|
result <- tryIO $ readProcess "bash" ["-c", cmd] ""
|
||||||
|
return . lines . either (const []) id $ result
|
||||||
|
|
||||||
-- | Strongly quote the string we pass to compgen.
|
-- | Strongly quote the string we pass to compgen.
|
||||||
--
|
--
|
||||||
-- We need to do this so bash doesn't expand out any ~ or other
|
-- We need to do this so bash doesn't expand out any ~ or other
|
||||||
@@ -459,8 +477,9 @@ versionCompleter criteria tool = listIOCompleter $ do
|
|||||||
|
|
||||||
toolDlCompleter :: Tool -> Completer
|
toolDlCompleter :: Tool -> Completer
|
||||||
toolDlCompleter tool = mkCompleter $ \case
|
toolDlCompleter tool = mkCompleter $ \case
|
||||||
"" -> pure $ initUrl tool
|
"" -> pure (initUrl tool <> ["https://", "http://", "file:///"])
|
||||||
word
|
word
|
||||||
|
| "file://" `isPrefixOf` word -> fileUri' [] word
|
||||||
-- downloads.haskell.org
|
-- downloads.haskell.org
|
||||||
| "https://downloads.haskell.org/" `isPrefixOf` word ->
|
| "https://downloads.haskell.org/" `isPrefixOf` word ->
|
||||||
fmap (completePrefix word) . prefixMatch (FP.takeFileName word) <$> fromHRef word
|
fmap (completePrefix word) . prefixMatch (FP.takeFileName word) <$> fromHRef word
|
||||||
@@ -501,6 +520,10 @@ toolDlCompleter tool = mkCompleter $ \case
|
|||||||
|
|
||||||
| "h" `isPrefixOf` word -> pure $ initUrl tool
|
| "h" `isPrefixOf` word -> pure $ initUrl tool
|
||||||
|
|
||||||
|
| word `isPrefixOf` "file:///" -> pure ["file:///"]
|
||||||
|
| word `isPrefixOf` "https://" -> pure ["https://"]
|
||||||
|
| word `isPrefixOf` "http://" -> pure ["http://"]
|
||||||
|
|
||||||
| otherwise -> pure []
|
| otherwise -> pure []
|
||||||
where
|
where
|
||||||
initUrl :: Tool -> [String]
|
initUrl :: Tool -> [String]
|
||||||
|
|||||||
@@ -173,7 +173,10 @@ ghcCompileOpts =
|
|||||||
(short 'g' <> long "git-ref" <> metavar "GIT_REFERENCE" <> help
|
(short 'g' <> long "git-ref" <> metavar "GIT_REFERENCE" <> help
|
||||||
"The git commit/branch/ref to build from"
|
"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 str (
|
||||||
|
short 'r' <> long "repository" <> metavar "GIT_REPOSITORY" <> help "The git repository to build from (defaults to GHC upstream)"
|
||||||
|
<> completer (gitFileUri ["https://gitlab.haskell.org/ghc/ghc.git"])
|
||||||
|
))
|
||||||
)))
|
)))
|
||||||
<*> option
|
<*> option
|
||||||
(eitherReader
|
(eitherReader
|
||||||
@@ -285,7 +288,9 @@ hlsCompileOpts =
|
|||||||
(short 'g' <> long "git-ref" <> metavar "GIT_REFERENCE" <> help
|
(short 'g' <> long "git-ref" <> metavar "GIT_REFERENCE" <> help
|
||||||
"The git commit/branch/ref to build from"
|
"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 str (short 'r' <> long "repository" <> metavar "GIT_REPOSITORY" <> help "The git repository to build from (defaults to GHC upstream)"
|
||||||
|
<> completer (gitFileUri ["https://github.com/haskell/haskell-language-server.git"])
|
||||||
|
))
|
||||||
)))
|
)))
|
||||||
<*> optional
|
<*> optional
|
||||||
(option
|
(option
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
{-# LANGUAGE DuplicateRecordFields #-}
|
{-# LANGUAGE DuplicateRecordFields #-}
|
||||||
{-# LANGUAGE RankNTypes #-}
|
{-# LANGUAGE RankNTypes #-}
|
||||||
|
{-# LANGUAGE ExplicitForAll #-}
|
||||||
|
|
||||||
module GHCup.OptParse.Config where
|
module GHCup.OptParse.Config where
|
||||||
|
|
||||||
@@ -17,6 +18,7 @@ import GHCup.Utils
|
|||||||
import GHCup.Utils.Prelude
|
import GHCup.Utils.Prelude
|
||||||
import GHCup.Utils.Logger
|
import GHCup.Utils.Logger
|
||||||
import GHCup.Utils.String.QQ
|
import GHCup.Utils.String.QQ
|
||||||
|
import GHCup.OptParse.Common
|
||||||
|
|
||||||
#if !MIN_VERSION_base(4,13,0)
|
#if !MIN_VERSION_base(4,13,0)
|
||||||
import Control.Monad.Fail ( MonadFail )
|
import Control.Monad.Fail ( MonadFail )
|
||||||
@@ -27,10 +29,11 @@ import Control.Monad.Trans.Resource
|
|||||||
import Data.Functor
|
import Data.Functor
|
||||||
import Data.Maybe
|
import Data.Maybe
|
||||||
import Haskus.Utils.Variant.Excepts
|
import Haskus.Utils.Variant.Excepts
|
||||||
import Options.Applicative hiding ( style )
|
import Options.Applicative hiding ( style, ParseError )
|
||||||
import Options.Applicative.Help.Pretty ( text )
|
import Options.Applicative.Help.Pretty ( text )
|
||||||
import Prelude hiding ( appendFile )
|
import Prelude hiding ( appendFile )
|
||||||
import System.Exit
|
import System.Exit
|
||||||
|
import URI.ByteString hiding ( uriParser )
|
||||||
|
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import qualified Data.ByteString.UTF8 as UTF8
|
import qualified Data.ByteString.UTF8 as UTF8
|
||||||
@@ -49,6 +52,7 @@ data ConfigCommand
|
|||||||
= ShowConfig
|
= ShowConfig
|
||||||
| SetConfig String (Maybe String)
|
| SetConfig String (Maybe String)
|
||||||
| InitConfig
|
| InitConfig
|
||||||
|
| AddReleaseChannel URI
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -62,6 +66,7 @@ configP = subparser
|
|||||||
( command "init" initP
|
( command "init" initP
|
||||||
<> command "set" setP -- [set] KEY VALUE at help lhs
|
<> command "set" setP -- [set] KEY VALUE at help lhs
|
||||||
<> command "show" showP
|
<> command "show" showP
|
||||||
|
<> command "add-release-channel" addP
|
||||||
)
|
)
|
||||||
<|> argsP -- add show for a single option
|
<|> argsP -- add show for a single option
|
||||||
<|> pure ShowConfig
|
<|> pure ShowConfig
|
||||||
@@ -70,6 +75,8 @@ configP = subparser
|
|||||||
showP = info (pure ShowConfig) (progDesc "Show current config (default)")
|
showP = info (pure ShowConfig) (progDesc "Show current config (default)")
|
||||||
setP = info argsP (progDesc "Set config KEY to VALUE (or specify as single json value)" <> footerDoc (Just $ text configSetFooter))
|
setP = info argsP (progDesc "Set config KEY to VALUE (or specify as single json value)" <> footerDoc (Just $ text configSetFooter))
|
||||||
argsP = SetConfig <$> argument str (metavar "<JSON_VALUE | YAML_KEY>") <*> optional (argument str (metavar "YAML_VALUE"))
|
argsP = SetConfig <$> argument str (metavar "<JSON_VALUE | YAML_KEY>") <*> optional (argument str (metavar "YAML_VALUE"))
|
||||||
|
addP = info (AddReleaseChannel <$> argument (eitherReader uriParser) (metavar "URI" <> completer fileUri))
|
||||||
|
(progDesc "Add a release channel from a URI")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -114,23 +121,18 @@ formatConfig :: UserSettings -> String
|
|||||||
formatConfig = UTF8.toString . Y.encode
|
formatConfig = UTF8.toString . Y.encode
|
||||||
|
|
||||||
|
|
||||||
updateSettings :: Monad m => UTF8.ByteString -> Settings -> Excepts '[JSONError] m Settings
|
updateSettings :: UserSettings -> Settings -> Settings
|
||||||
updateSettings config' settings = do
|
updateSettings UserSettings{..} Settings{..} =
|
||||||
settings' <- lE' (JSONDecodeError . displayException) . Y.decodeEither' $ config'
|
let cache' = fromMaybe cache uCache
|
||||||
pure $ mergeConf settings' settings
|
metaCache' = fromMaybe metaCache uMetaCache
|
||||||
where
|
noVerify' = fromMaybe noVerify uNoVerify
|
||||||
mergeConf :: UserSettings -> Settings -> Settings
|
keepDirs' = fromMaybe keepDirs uKeepDirs
|
||||||
mergeConf UserSettings{..} Settings{..} =
|
downloader' = fromMaybe downloader uDownloader
|
||||||
let cache' = fromMaybe cache uCache
|
verbose' = fromMaybe verbose uVerbose
|
||||||
metaCache' = fromMaybe metaCache uMetaCache
|
urlSource' = fromMaybe urlSource uUrlSource
|
||||||
noVerify' = fromMaybe noVerify uNoVerify
|
noNetwork' = fromMaybe noNetwork uNoNetwork
|
||||||
keepDirs' = fromMaybe keepDirs uKeepDirs
|
gpgSetting' = fromMaybe gpgSetting uGPGSetting
|
||||||
downloader' = fromMaybe downloader uDownloader
|
in Settings cache' metaCache' noVerify' keepDirs' downloader' verbose' urlSource' noNetwork' gpgSetting' noColor
|
||||||
verbose' = fromMaybe verbose uVerbose
|
|
||||||
urlSource' = fromMaybe urlSource uUrlSource
|
|
||||||
noNetwork' = fromMaybe noNetwork uNoNetwork
|
|
||||||
gpgSetting' = fromMaybe gpgSetting uGPGSetting
|
|
||||||
in Settings cache' metaCache' noVerify' keepDirs' downloader' verbose' urlSource' noNetwork' gpgSetting' noColor
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -140,7 +142,7 @@ updateSettings config' settings = do
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
config :: ( Monad m
|
config :: forall m. ( Monad m
|
||||||
, MonadMask m
|
, MonadMask m
|
||||||
, MonadUnliftIO m
|
, MonadUnliftIO m
|
||||||
, MonadFail m
|
, MonadFail m
|
||||||
@@ -161,27 +163,42 @@ config configCommand settings keybindings runLogger = case configCommand of
|
|||||||
liftIO $ putStrLn $ formatConfig $ fromSettings settings (Just keybindings)
|
liftIO $ putStrLn $ formatConfig $ fromSettings settings (Just keybindings)
|
||||||
pure ExitSuccess
|
pure ExitSuccess
|
||||||
|
|
||||||
(SetConfig k (Just v)) ->
|
(SetConfig k mv) -> do
|
||||||
case v of
|
r <- runE @'[JSONError, ParseError] $ do
|
||||||
"" -> do
|
case mv of
|
||||||
runLogger $ logError "Empty values are not allowed"
|
Just "" ->
|
||||||
pure $ ExitFailure 55
|
throwE $ ParseError "Empty values are not allowed"
|
||||||
_ -> doConfig (k <> ": " <> v <> "\n")
|
Nothing -> do
|
||||||
|
usersettings <- decodeSettings k
|
||||||
|
lift $ doConfig usersettings
|
||||||
|
pure ()
|
||||||
|
Just v -> do
|
||||||
|
usersettings <- decodeSettings (k <> ": " <> v <> "\n")
|
||||||
|
lift $ doConfig usersettings
|
||||||
|
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
|
||||||
|
|
||||||
(SetConfig json Nothing) -> doConfig json
|
AddReleaseChannel uri -> do
|
||||||
|
case urlSource settings of
|
||||||
|
AddSource xs -> do
|
||||||
|
doConfig (defaultUserSettings { uUrlSource = Just $ AddSource (xs <> [Right uri]) })
|
||||||
|
pure ExitSuccess
|
||||||
|
_ -> do
|
||||||
|
doConfig (defaultUserSettings { uUrlSource = Just $ AddSource [Right uri] })
|
||||||
|
pure ExitSuccess
|
||||||
|
|
||||||
where
|
where
|
||||||
doConfig val = do
|
doConfig :: MonadIO m => UserSettings -> m ()
|
||||||
r <- runE @'[JSONError] $ do
|
doConfig usersettings = do
|
||||||
settings' <- updateSettings (UTF8.fromString val) settings
|
let settings' = updateSettings usersettings settings
|
||||||
path <- liftIO getConfigFilePath
|
path <- liftIO getConfigFilePath
|
||||||
liftIO $ writeFile path $ formatConfig $ fromSettings settings' (Just keybindings)
|
liftIO $ writeFile path $ formatConfig $ fromSettings settings' (Just keybindings)
|
||||||
lift $ runLogger $ logDebug $ T.pack $ show settings'
|
runLogger $ logDebug $ T.pack $ show settings'
|
||||||
pure ()
|
pure ()
|
||||||
|
|
||||||
case r of
|
decodeSettings = lE' (JSONDecodeError . displayException) . Y.decodeEither' . UTF8.fromString
|
||||||
VRight _ -> pure ExitSuccess
|
|
||||||
VLeft (V (JSONDecodeError e)) -> do
|
|
||||||
runLogger $ logError $ "Error decoding config: " <> T.pack e
|
|
||||||
pure $ ExitFailure 65
|
|
||||||
VLeft _ -> pure $ ExitFailure 65
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
{-# LANGUAGE QuasiQuotes #-}
|
{-# LANGUAGE QuasiQuotes #-}
|
||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
{-# LANGUAGE DuplicateRecordFields #-}
|
{-# LANGUAGE DuplicateRecordFields #-}
|
||||||
|
{-# LANGUAGE ViewPatterns #-}
|
||||||
|
|
||||||
module GHCup.OptParse.Install where
|
module GHCup.OptParse.Install where
|
||||||
|
|
||||||
@@ -255,6 +256,48 @@ type InstallEffects = '[ AlreadyInstalled
|
|||||||
, NoToolVersionSet
|
, NoToolVersionSet
|
||||||
, FileAlreadyExistsError
|
, FileAlreadyExistsError
|
||||||
, ProcessError
|
, ProcessError
|
||||||
|
|
||||||
|
, (AlreadyInstalled, ())
|
||||||
|
, (UnknownArchive, ())
|
||||||
|
, (ArchiveResult, ())
|
||||||
|
, (FileDoesNotExistError, ())
|
||||||
|
, (CopyError, ())
|
||||||
|
, (NotInstalled, ())
|
||||||
|
, (DirNotEmpty, ())
|
||||||
|
, (NoDownload, ())
|
||||||
|
, (NotInstalled, ())
|
||||||
|
, (BuildFailed, ())
|
||||||
|
, (TagNotFound, ())
|
||||||
|
, (DigestError, ())
|
||||||
|
, (GPGError, ())
|
||||||
|
, (DownloadFailed, ())
|
||||||
|
, (TarDirDoesNotExist, ())
|
||||||
|
, (NextVerNotFound, ())
|
||||||
|
, (NoToolVersionSet, ())
|
||||||
|
, (FileAlreadyExistsError, ())
|
||||||
|
, (ProcessError, ())
|
||||||
|
|
||||||
|
, (AlreadyInstalled, NotInstalled)
|
||||||
|
, (UnknownArchive, NotInstalled)
|
||||||
|
, (ArchiveResult, NotInstalled)
|
||||||
|
, (FileDoesNotExistError, NotInstalled)
|
||||||
|
, (CopyError, NotInstalled)
|
||||||
|
, (NotInstalled, NotInstalled)
|
||||||
|
, (DirNotEmpty, NotInstalled)
|
||||||
|
, (NoDownload, NotInstalled)
|
||||||
|
, (NotInstalled, NotInstalled)
|
||||||
|
, (BuildFailed, NotInstalled)
|
||||||
|
, (TagNotFound, NotInstalled)
|
||||||
|
, (DigestError, NotInstalled)
|
||||||
|
, (GPGError, NotInstalled)
|
||||||
|
, (DownloadFailed, NotInstalled)
|
||||||
|
, (TarDirDoesNotExist, NotInstalled)
|
||||||
|
, (NextVerNotFound, NotInstalled)
|
||||||
|
, (NoToolVersionSet, NotInstalled)
|
||||||
|
, (FileAlreadyExistsError, NotInstalled)
|
||||||
|
, (ProcessError, NotInstalled)
|
||||||
|
|
||||||
|
, ((), NotInstalled)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@@ -420,20 +463,22 @@ install installCommand settings getAppState' runLogger = case installCommand of
|
|||||||
s'@AppState{ dirs = Dirs{ .. } } <- liftIO getAppState'
|
s'@AppState{ dirs = Dirs{ .. } } <- liftIO getAppState'
|
||||||
(case instBindist of
|
(case instBindist of
|
||||||
Nothing -> runInstTool s' instPlatform $ do
|
Nothing -> runInstTool s' instPlatform $ do
|
||||||
(v, vi) <- liftE $ fromVersion instVer Cabal
|
(_tvVersion -> v, vi) <- liftE $ fromVersion instVer Cabal
|
||||||
liftE $ installCabalBin
|
void $ liftE $ sequenceE (installCabalBin
|
||||||
(_tvVersion v)
|
v
|
||||||
isolateDir
|
isolateDir
|
||||||
forceInstall
|
forceInstall
|
||||||
|
) $ when instSet $ void $ setCabal v
|
||||||
pure vi
|
pure vi
|
||||||
Just uri -> do
|
Just uri -> do
|
||||||
runInstTool s'{ settings = settings { noVerify = True}} instPlatform $ do
|
runInstTool s'{ settings = settings { noVerify = True}} instPlatform $ do
|
||||||
(v, vi) <- liftE $ fromVersion instVer Cabal
|
(_tvVersion -> v, vi) <- liftE $ fromVersion instVer Cabal
|
||||||
liftE $ installCabalBindist
|
void $ liftE $ sequenceE (installCabalBindist
|
||||||
(DownloadInfo uri Nothing "")
|
(DownloadInfo uri Nothing "")
|
||||||
(_tvVersion v)
|
v
|
||||||
isolateDir
|
isolateDir
|
||||||
forceInstall
|
forceInstall
|
||||||
|
) $ when instSet $ void $ setCabal v
|
||||||
pure vi
|
pure vi
|
||||||
)
|
)
|
||||||
>>= \case
|
>>= \case
|
||||||
@@ -450,6 +495,14 @@ install installCommand settings getAppState' runLogger = case installCommand of
|
|||||||
runLogger $ logWarn $
|
runLogger $ logWarn $
|
||||||
"File " <> T.pack fp <> " already exists. Use 'ghcup install cabal --isolate " <> T.pack fp <> " --force ..." <> "' if you want to overwrite."
|
"File " <> T.pack fp <> " already exists. Use 'ghcup install cabal --isolate " <> T.pack fp <> " --force ..." <> "' if you want to overwrite."
|
||||||
pure $ ExitFailure 3
|
pure $ ExitFailure 3
|
||||||
|
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
|
VLeft e -> do
|
||||||
runLogger $ do
|
runLogger $ do
|
||||||
logError $ T.pack $ prettyShow e
|
logError $ T.pack $ prettyShow e
|
||||||
@@ -461,21 +514,23 @@ install installCommand settings getAppState' runLogger = case installCommand of
|
|||||||
s'@AppState{ dirs = Dirs{ .. } } <- liftIO getAppState'
|
s'@AppState{ dirs = Dirs{ .. } } <- liftIO getAppState'
|
||||||
(case instBindist of
|
(case instBindist of
|
||||||
Nothing -> runInstTool s' instPlatform $ do
|
Nothing -> runInstTool s' instPlatform $ do
|
||||||
(v, vi) <- liftE $ fromVersion instVer HLS
|
(_tvVersion -> v, vi) <- liftE $ fromVersion instVer HLS
|
||||||
liftE $ installHLSBin
|
void $ liftE $ sequenceE (installHLSBin
|
||||||
(_tvVersion v)
|
v
|
||||||
isolateDir
|
isolateDir
|
||||||
forceInstall
|
forceInstall
|
||||||
|
) $ when instSet $ void $ setHLS v SetHLSOnly Nothing
|
||||||
pure vi
|
pure vi
|
||||||
Just uri -> do
|
Just uri -> do
|
||||||
runInstTool s'{ settings = settings { noVerify = True}} instPlatform $ do
|
runInstTool s'{ settings = settings { noVerify = True}} instPlatform $ do
|
||||||
(v, vi) <- liftE $ fromVersion instVer HLS
|
(_tvVersion -> v, vi) <- liftE $ fromVersion instVer HLS
|
||||||
-- TODO: support legacy
|
-- TODO: support legacy
|
||||||
liftE $ installHLSBindist
|
void $ liftE $ sequenceE (installHLSBindist
|
||||||
(DownloadInfo uri (Just $ RegexDir "haskell-language-server-*") "")
|
(DownloadInfo uri (Just $ RegexDir "haskell-language-server-*") "")
|
||||||
(_tvVersion v)
|
v
|
||||||
isolateDir
|
isolateDir
|
||||||
forceInstall
|
forceInstall
|
||||||
|
) $ when instSet $ void $ setHLS v SetHLSOnly Nothing
|
||||||
pure vi
|
pure vi
|
||||||
)
|
)
|
||||||
>>= \case
|
>>= \case
|
||||||
@@ -496,6 +551,18 @@ install installCommand settings getAppState' runLogger = case installCommand of
|
|||||||
runLogger $ logWarn $
|
runLogger $ logWarn $
|
||||||
"File " <> T.pack fp <> " already exists. Use 'ghcup install hls --isolate " <> T.pack fp <> " --force ..." <> "' if you want to overwrite."
|
"File " <> T.pack fp <> " already exists. Use 'ghcup install hls --isolate " <> T.pack fp <> " --force ..." <> "' if you want to overwrite."
|
||||||
pure $ ExitFailure 3
|
pure $ ExitFailure 3
|
||||||
|
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
|
VLeft e -> do
|
||||||
runLogger $ do
|
runLogger $ do
|
||||||
logError $ T.pack $ prettyShow e
|
logError $ T.pack $ prettyShow e
|
||||||
@@ -507,20 +574,22 @@ install installCommand settings getAppState' runLogger = case installCommand of
|
|||||||
s'@AppState{ dirs = Dirs{ .. } } <- liftIO getAppState'
|
s'@AppState{ dirs = Dirs{ .. } } <- liftIO getAppState'
|
||||||
(case instBindist of
|
(case instBindist of
|
||||||
Nothing -> runInstTool s' instPlatform $ do
|
Nothing -> runInstTool s' instPlatform $ do
|
||||||
(v, vi) <- liftE $ fromVersion instVer Stack
|
(_tvVersion -> v, vi) <- liftE $ fromVersion instVer Stack
|
||||||
liftE $ installStackBin
|
void $ liftE $ sequenceE (installStackBin
|
||||||
(_tvVersion v)
|
v
|
||||||
isolateDir
|
isolateDir
|
||||||
forceInstall
|
forceInstall
|
||||||
|
) $ when instSet $ void $ setStack v
|
||||||
pure vi
|
pure vi
|
||||||
Just uri -> do
|
Just uri -> do
|
||||||
runInstTool s'{ settings = settings { noVerify = True}} instPlatform $ do
|
runInstTool s'{ settings = settings { noVerify = True}} instPlatform $ do
|
||||||
(v, vi) <- liftE $ fromVersion instVer Stack
|
(_tvVersion -> v, vi) <- liftE $ fromVersion instVer Stack
|
||||||
liftE $ installStackBindist
|
void $ liftE $ sequenceE (installStackBindist
|
||||||
(DownloadInfo uri Nothing "")
|
(DownloadInfo uri Nothing "")
|
||||||
(_tvVersion v)
|
v
|
||||||
isolateDir
|
isolateDir
|
||||||
forceInstall
|
forceInstall
|
||||||
|
) $ when instSet $ void $ setStack v
|
||||||
pure vi
|
pure vi
|
||||||
)
|
)
|
||||||
>>= \case
|
>>= \case
|
||||||
@@ -537,6 +606,14 @@ install installCommand settings getAppState' runLogger = case installCommand of
|
|||||||
runLogger $ logWarn $
|
runLogger $ logWarn $
|
||||||
"File " <> T.pack fp <> " already exists. Use 'ghcup install stack --isolate " <> T.pack fp <> " --force ..." <> "' if you want to overwrite."
|
"File " <> T.pack fp <> " already exists. Use 'ghcup install stack --isolate " <> T.pack fp <> " --force ..." <> "' if you want to overwrite."
|
||||||
pure $ ExitFailure 3
|
pure $ ExitFailure 3
|
||||||
|
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
|
VLeft e -> do
|
||||||
runLogger $ do
|
runLogger $ do
|
||||||
logError $ T.pack $ prettyShow e
|
logError $ T.pack $ prettyShow e
|
||||||
|
|||||||
@@ -338,7 +338,7 @@ run RunOptions{..} runAppState leanAppstate runLogger = do
|
|||||||
if legacy
|
if legacy
|
||||||
then do
|
then do
|
||||||
-- TODO: factor this out
|
-- TODO: factor this out
|
||||||
(Just hlsWrapper) <- hlsWrapperBinary v'
|
hlsWrapper <- liftE @_ @'[NotInstalled] $ hlsWrapperBinary v' !? (NotInstalled HLS (mkTVer v'))
|
||||||
cw <- liftIO $ canonicalizePath (binDir </> hlsWrapper)
|
cw <- liftIO $ canonicalizePath (binDir </> hlsWrapper)
|
||||||
lift $ createLink (relativeSymlink tmp cw) (tmp </> takeFileName cw)
|
lift $ createLink (relativeSymlink tmp cw) (tmp </> takeFileName cw)
|
||||||
hlsBins <- hlsServerBinaries v' Nothing >>= liftIO . traverse (canonicalizePath . (binDir </>))
|
hlsBins <- hlsServerBinaries v' Nothing >>= liftIO . traverse (canonicalizePath . (binDir </>))
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ toSettings options = do
|
|||||||
keepDirs = fromMaybe (fromMaybe (Types.keepDirs defaultSettings) uKeepDirs) optKeepDirs
|
keepDirs = fromMaybe (fromMaybe (Types.keepDirs defaultSettings) uKeepDirs) optKeepDirs
|
||||||
downloader = fromMaybe (fromMaybe defaultDownloader uDownloader) optsDownloader
|
downloader = fromMaybe (fromMaybe defaultDownloader uDownloader) optsDownloader
|
||||||
keyBindings = maybe defaultKeyBindings mergeKeys uKeyBindings
|
keyBindings = maybe defaultKeyBindings mergeKeys uKeyBindings
|
||||||
urlSource = maybe (fromMaybe (Types.urlSource defaultSettings) uUrlSource) OwnSource optUrlSource
|
urlSource = maybe (fromMaybe (Types.urlSource defaultSettings) uUrlSource) (OwnSource . (:[]) . Right) optUrlSource
|
||||||
noNetwork = fromMaybe (fromMaybe (Types.noNetwork defaultSettings) uNoNetwork) optNoNetwork
|
noNetwork = fromMaybe (fromMaybe (Types.noNetwork defaultSettings) uNoNetwork) optNoNetwork
|
||||||
gpgSetting = fromMaybe (fromMaybe (Types.gpgSetting defaultSettings) uGPGSetting) optGpg
|
gpgSetting = fromMaybe (fromMaybe (Types.gpgSetting defaultSettings) uGPGSetting) optGpg
|
||||||
in (Settings {..}, keyBindings)
|
in (Settings {..}, keyBindings)
|
||||||
|
|||||||
@@ -48,12 +48,16 @@ url-source:
|
|||||||
|
|
||||||
## Example 1: Read download info from this location instead
|
## Example 1: Read download info from this location instead
|
||||||
## Accepts file/http/https scheme
|
## Accepts file/http/https scheme
|
||||||
|
## Can also be an array of URLs or an array of 'Either GHCupInfo URL', in
|
||||||
|
## which case they are merged right-biased (overwriting duplicate versions).
|
||||||
# OwnSource: "file:///home/jule/git/ghcup-hs/ghcup-0.0.3.yaml"
|
# OwnSource: "file:///home/jule/git/ghcup-hs/ghcup-0.0.3.yaml"
|
||||||
|
|
||||||
## Example 2: Add custom tarballs to the default downloads, overwriting duplicate versions
|
## Example 2: Add custom tarballs to the default downloads, overwriting duplicate versions.
|
||||||
|
## Can also be an array of 'Either GHCupInfo URL', also see Example 3.
|
||||||
# AddSource:
|
# AddSource:
|
||||||
# Left:
|
# Left:
|
||||||
# toolRequirements: {} # this is ignored
|
# globalTools: {}
|
||||||
|
# toolRequirements: {}
|
||||||
# ghcupDownloads:
|
# ghcupDownloads:
|
||||||
# GHC:
|
# GHC:
|
||||||
# 9.10.2:
|
# 9.10.2:
|
||||||
@@ -66,6 +70,8 @@ url-source:
|
|||||||
# dlSubdir: ghc-7.10.3
|
# dlSubdir: ghc-7.10.3
|
||||||
# dlHash: 01cfbad8dff1e8b34a5fdca8caeaf843b56e36af919e29cd68870d2588563db5
|
# dlHash: 01cfbad8dff1e8b34a5fdca8caeaf843b56e36af919e29cd68870d2588563db5
|
||||||
|
|
||||||
## Example 3: Add a custom download file to the default downloads, overwriting duplicate versions
|
## Example 3: Add multiple custom download files to the default downloads via right-biased merge (overwriting duplicate
|
||||||
|
## versions).
|
||||||
# AddSource:
|
# AddSource:
|
||||||
# Right: "file:///home/jule/git/ghcup-hs/ghcup-custom.yaml"
|
# - Right: "file:///home/jule/git/ghcup-hs/ghcup-prereleases.yaml"
|
||||||
|
# - Right: "file:///home/jule/git/ghcup-hs/ghcup-custom.yaml"
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
:root {
|
:root {
|
||||||
--theme-purple: #5E5184;
|
--theme-purple: #5E5184;
|
||||||
|
--theme-purple-dark: rgba(69, 59, 97, 0.5);
|
||||||
|
--ukraine-top: #0057B8;
|
||||||
|
--ukraine-bottom: #FFD700;
|
||||||
--link-pink: #9E358F;
|
--link-pink: #9E358F;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,12 +111,12 @@ body.homepage>div.container div.col-md-9 {
|
|||||||
|
|
||||||
.bg-primary {
|
.bg-primary {
|
||||||
background-image: none;
|
background-image: none;
|
||||||
background-color: var(--theme-purple) !important;
|
background-color: var(--ukraine-top) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
body .bg-primary {
|
body .bg-primary {
|
||||||
background-image: none;
|
background-image: none;
|
||||||
background-color: var(--theme-purple);
|
background-color: var(--ukraine-top);
|
||||||
border: 0px;
|
border: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,8 +128,8 @@ body .btn-primary {
|
|||||||
|
|
||||||
.navbar.fixed-top {
|
.navbar.fixed-top {
|
||||||
background-image: none;
|
background-image: none;
|
||||||
background-color: var(--theme-purple);
|
background-color: var(--ukraine-top);
|
||||||
border-bottom: 5px solid rgba(69, 59, 97, 0.5);
|
border-bottom: 40px solid var(--ukraine-bottom);
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,10 +50,90 @@ On windows, double-click on the `Uninstall Haskell.ps1` PowerShell script on you
|
|||||||
|
|
||||||
GHCup supports the following tools, which are also known as the **Haskell Toolchain**:
|
GHCup supports the following tools, which are also known as the **Haskell Toolchain**:
|
||||||
|
|
||||||
1. [GHC](https://www.haskell.org/ghc/)
|
<details>
|
||||||
2. [cabal-install](https://cabal.readthedocs.io/en/stable/)
|
<summary>Show all supported <a href='https://www.haskell.org/ghc/'>GHC</a> versions</summary>
|
||||||
3. [haskell-language-server](https://haskell-language-server.readthedocs.io/en/stable/)
|
|
||||||
4. [stack](https://docs.haskellstack.org/en/stable/README/)
|
<table>
|
||||||
|
<thead><tr><th>GHC Version</th><th>Tags</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>7.10.3</td><td>base-4.8.2.0</td></tr>
|
||||||
|
<tr><td>8.0.2</td><td>base-4.9.1.0</td></tr>
|
||||||
|
<tr><td>8.2.2</td><td>base-4.10.1.0</td></tr>
|
||||||
|
<tr><td>8.4.1</td><td>base-4.11.0.0</td></tr>
|
||||||
|
<tr><td>8.4.2</td><td>base-4.11.1.0</td></tr>
|
||||||
|
<tr><td>8.4.3</td><td>base-4.11.1.0</td></tr>
|
||||||
|
<tr><td>8.4.4</td><td>base-4.11.1.0</td></tr>
|
||||||
|
<tr><td>8.6.1</td><td>base-4.12.0.0</td></tr>
|
||||||
|
<tr><td>8.6.2</td><td>base-4.12.0.0</td></tr>
|
||||||
|
<tr><td>8.6.3</td><td>base-4.12.0.0</td></tr>
|
||||||
|
<tr><td>8.6.4</td><td>base-4.12.0.0</td></tr>
|
||||||
|
<tr><td>8.6.5</td><td>base-4.12.0.0</td></tr>
|
||||||
|
<tr><td>8.8.1</td><td>base-4.13.0.0</td></tr>
|
||||||
|
<tr><td>8.8.2</td><td>base-4.13.0.0</td></tr>
|
||||||
|
<tr><td>8.8.3</td><td>base-4.13.0.0</td></tr>
|
||||||
|
<tr><td>8.8.4</td><td>base-4.13.0.0</td></tr>
|
||||||
|
<tr><td>8.10.1</td><td>base-4.14.0.0</td></tr>
|
||||||
|
<tr><td>8.10.2</td><td>base-4.14.1.0</td></tr>
|
||||||
|
<tr><td>8.10.3</td><td>base-4.14.1.0</td></tr>
|
||||||
|
<tr><td>8.10.4</td><td>base-4.14.1.0</td></tr>
|
||||||
|
<tr><td>8.10.5</td><td>base-4.14.2.0</td></tr>
|
||||||
|
<tr><td>8.10.6</td><td>base-4.14.3.0</td></tr>
|
||||||
|
<tr><td>8.10.7</td><td><span style="color:green">recommended</span>, base-4.14.3.0</td></tr>
|
||||||
|
<tr><td>9.0.1</td><td>base-4.15.0.0</td></tr>
|
||||||
|
<tr><td>9.0.2</td><td>base-4.15.1.0</td></tr>
|
||||||
|
<tr><td>9.2.1</td><td>base-4.16.0.0</td></tr>
|
||||||
|
<tr><td>9.2.2</td><td><span style="color:blue">latest</span>, base-4.16.1.0</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Show all supported <a href='https://cabal.readthedocs.io/en/stable/'>cabal-install</a> versions</summary>
|
||||||
|
<table>
|
||||||
|
<thead><tr><th>Cabal Version</th><th>Tags</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>2.4.1.0</td><td></td></tr>
|
||||||
|
<tr><td>3.0.0.0</td><td></td></tr>
|
||||||
|
<tr><td>3.2.0.0</td><td></td></tr>
|
||||||
|
<tr><td>3.4.0.0</td><td></td></tr>
|
||||||
|
<tr><td>3.4.1.0</td><td></td></tr>
|
||||||
|
<tr><td>3.6.0.0</td><td></td></tr>
|
||||||
|
<tr><td>3.6.2.0</td><td><span style="color:blue">latest</span>, <span style="color:green">recommended</span></td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Show all supported <a href='https://haskell-language-server.readthedocs.io/en/stable/'>HLS</a> versions</summary>
|
||||||
|
<table>
|
||||||
|
<thead><tr><th>HLS Version</th><th>Tags</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>1.1.0</td><td></td></tr>
|
||||||
|
<tr><td>1.2.0</td><td></td></tr>
|
||||||
|
<tr><td>1.3.0</td><td></td></tr>
|
||||||
|
<tr><td>1.4.0</td><td></td></tr>
|
||||||
|
<tr><td>1.5.0</td><td></td></tr>
|
||||||
|
<tr><td>1.5.1</td><td></td></tr>
|
||||||
|
<tr><td>1.6.0.0</td><td></td></tr>
|
||||||
|
<tr><td>1.6.1.0</td><td><span style="color:blue">latest</span>, <span style="color:green">recommended</span></td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Show all supported <a href='https://docs.haskellstack.org/en/stable/README/'>Stack</a> versions</summary>
|
||||||
|
<table>
|
||||||
|
<thead><tr><th>Stack Version</th><th>Tags</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>2.5.1</td><td></td></tr>
|
||||||
|
<tr><td>2.7.1</td><td></td></tr>
|
||||||
|
<tr><td>2.7.3</td><td></td></tr>
|
||||||
|
<tr><td>2.7.5</td><td><span style="color:blue">latest</span>, <span style="color:green">recommended</span></td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</details>
|
||||||
|
|
||||||
## Supported platforms
|
## Supported platforms
|
||||||
|
|
||||||
|
|||||||
24
ghcup.cabal
24
ghcup.cabal
@@ -121,7 +121,7 @@ library
|
|||||||
, haskus-utils-variant ^>=3.2.1
|
, haskus-utils-variant ^>=3.2.1
|
||||||
, libarchive ^>=3.0.3.0
|
, libarchive ^>=3.0.3.0
|
||||||
, lzma-static ^>=5.2.5.3
|
, lzma-static ^>=5.2.5.3
|
||||||
, megaparsec >=8.0.0 && <9.1
|
, megaparsec >=8.0.0 && <9.3
|
||||||
, mtl ^>=2.2
|
, mtl ^>=2.2
|
||||||
, optics ^>=0.4
|
, optics ^>=0.4
|
||||||
, os-release ^>=1.0.0
|
, os-release ^>=1.0.0
|
||||||
@@ -236,9 +236,9 @@ executable ghcup
|
|||||||
, ghcup
|
, ghcup
|
||||||
, haskus-utils-variant ^>=3.2.1
|
, haskus-utils-variant ^>=3.2.1
|
||||||
, libarchive ^>=3.0.3.0
|
, libarchive ^>=3.0.3.0
|
||||||
, megaparsec >=8.0.0 && <9.1
|
, megaparsec >=8.0.0 && <9.3
|
||||||
, mtl ^>=2.2
|
, mtl ^>=2.2
|
||||||
, optparse-applicative >=0.15.1.0 && <0.17
|
, optparse-applicative >=0.15.1.0 && <0.18
|
||||||
, pretty ^>=1.1.3.1
|
, pretty ^>=1.1.3.1
|
||||||
, pretty-terminal ^>=0.1.0.0
|
, pretty-terminal ^>=0.1.0.0
|
||||||
, process ^>=1.6.11.0
|
, process ^>=1.6.11.0
|
||||||
@@ -246,8 +246,8 @@ executable ghcup
|
|||||||
, safe ^>=0.3.18
|
, safe ^>=0.3.18
|
||||||
, safe-exceptions ^>=0.1
|
, safe-exceptions ^>=0.1
|
||||||
, tagsoup ^>=0.14
|
, tagsoup ^>=0.14
|
||||||
, temporary ^>=1.3
|
|
||||||
, template-haskell >=2.7 && <2.18
|
, template-haskell >=2.7 && <2.18
|
||||||
|
, temporary ^>=1.3
|
||||||
, text ^>=1.2.4.0
|
, text ^>=1.2.4.0
|
||||||
, unordered-containers ^>=0.2
|
, unordered-containers ^>=0.2
|
||||||
, uri-bytestring ^>=0.3.2.2
|
, uri-bytestring ^>=0.3.2.2
|
||||||
@@ -270,18 +270,18 @@ executable ghcup
|
|||||||
|
|
||||||
if os(windows)
|
if os(windows)
|
||||||
cpp-options: -DIS_WINDOWS
|
cpp-options: -DIS_WINDOWS
|
||||||
|
|
||||||
else
|
else
|
||||||
build-depends:
|
build-depends: unix ^>=2.7
|
||||||
, unix ^>=2.7
|
|
||||||
|
|
||||||
if flag(no-exe)
|
if flag(no-exe)
|
||||||
buildable: False
|
buildable: False
|
||||||
|
|
||||||
if (flag(disable-upgrade))
|
if flag(disable-upgrade)
|
||||||
cpp-options: -DDISABLE_UPGRADE
|
cpp-options: -DDISABLE_UPGRADE
|
||||||
|
|
||||||
else
|
else
|
||||||
other-modules:
|
other-modules: GHCup.OptParse.Upgrade
|
||||||
GHCup.OptParse.Upgrade
|
|
||||||
|
|
||||||
test-suite ghcup-test
|
test-suite ghcup-test
|
||||||
type: exitcode-stdio-1.0
|
type: exitcode-stdio-1.0
|
||||||
@@ -310,9 +310,9 @@ test-suite ghcup-test
|
|||||||
, base >=4.12 && <5
|
, base >=4.12 && <5
|
||||||
, bytestring ^>=0.10
|
, bytestring ^>=0.10
|
||||||
, containers ^>=0.6
|
, containers ^>=0.6
|
||||||
, generic-arbitrary ^>=0.1.0
|
, generic-arbitrary >=0.1.0 && <0.3
|
||||||
, ghcup
|
, ghcup
|
||||||
, hspec ^>=2.7.10
|
, hspec >=2.7.10 && <2.10
|
||||||
, hspec-golden-aeson ^>=0.9
|
, hspec-golden-aeson ^>=0.9
|
||||||
, QuickCheck ^>=2.14.1
|
, QuickCheck ^>=2.14.1
|
||||||
, quickcheck-arbitrary-adt ^>=0.3.1.0
|
, quickcheck-arbitrary-adt ^>=0.3.1.0
|
||||||
|
|||||||
@@ -121,28 +121,25 @@ getDownloadsF = do
|
|||||||
Settings { urlSource } <- lift getSettings
|
Settings { urlSource } <- lift getSettings
|
||||||
case urlSource of
|
case urlSource of
|
||||||
GHCupURL -> liftE $ getBase ghcupURL
|
GHCupURL -> liftE $ getBase ghcupURL
|
||||||
(OwnSource url) -> liftE $ getBase url
|
(OwnSource exts) -> do
|
||||||
|
ext <- liftE $ mapM (either pure getBase) exts
|
||||||
|
mergeGhcupInfo ext
|
||||||
(OwnSpec av) -> pure av
|
(OwnSpec av) -> pure av
|
||||||
(AddSource (Left ext)) -> do
|
(AddSource exts) -> do
|
||||||
base <- liftE $ getBase ghcupURL
|
base <- liftE $ getBase ghcupURL
|
||||||
pure (mergeGhcupInfo base ext)
|
ext <- liftE $ mapM (either pure getBase) exts
|
||||||
(AddSource (Right uri)) -> do
|
mergeGhcupInfo (base:ext)
|
||||||
base <- liftE $ getBase ghcupURL
|
|
||||||
ext <- liftE $ getBase uri
|
|
||||||
pure (mergeGhcupInfo base ext)
|
|
||||||
|
|
||||||
where
|
where
|
||||||
|
mergeGhcupInfo :: MonadFail m
|
||||||
mergeGhcupInfo :: GHCupInfo -- ^ base to merge with
|
=> [GHCupInfo]
|
||||||
-> GHCupInfo -- ^ extension overwriting the base
|
-> m GHCupInfo
|
||||||
-> GHCupInfo
|
mergeGhcupInfo [] = fail "mergeGhcupInfo: internal error: need at least one GHCupInfo"
|
||||||
mergeGhcupInfo (GHCupInfo tr base base2) (GHCupInfo _ ext ext2) =
|
mergeGhcupInfo xs@(GHCupInfo{}: _) =
|
||||||
let newDownloads = M.mapWithKey (\k a -> case M.lookup k ext of
|
let newDownloads = M.unionsWith (M.unionWith (\_ b2 -> b2)) (_ghcupDownloads <$> xs)
|
||||||
Just a' -> M.union a' a
|
newGlobalTools = M.unionsWith (\_ a2 -> a2 ) (_globalTools <$> xs)
|
||||||
Nothing -> a
|
newToolReqs = M.unionsWith (M.unionWith (\_ b2 -> b2)) (_toolRequirements <$> xs)
|
||||||
) base
|
in pure $ GHCupInfo newToolReqs newDownloads newGlobalTools
|
||||||
newGlobalTools = M.union base2 ext2
|
|
||||||
in GHCupInfo tr newDownloads newGlobalTools
|
|
||||||
|
|
||||||
|
|
||||||
yamlFromCache :: (MonadReader env m, HasDirs env) => URI -> m FilePath
|
yamlFromCache :: (MonadReader env m, HasDirs env) => URI -> m FilePath
|
||||||
|
|||||||
@@ -286,9 +286,9 @@ instance Pretty TarDir where
|
|||||||
|
|
||||||
-- | Where to fetch GHCupDownloads from.
|
-- | Where to fetch GHCupDownloads from.
|
||||||
data URLSource = GHCupURL
|
data URLSource = GHCupURL
|
||||||
| OwnSource URI
|
| OwnSource [Either GHCupInfo URI] -- ^ complete source list
|
||||||
| OwnSpec GHCupInfo
|
| OwnSpec GHCupInfo
|
||||||
| AddSource (Either GHCupInfo URI) -- ^ merge with GHCupURL
|
| AddSource [Either GHCupInfo URI] -- ^ merge with GHCupURL
|
||||||
deriving (GHC.Generic, Show)
|
deriving (GHC.Generic, Show)
|
||||||
|
|
||||||
instance NFData URLSource
|
instance NFData URLSource
|
||||||
|
|||||||
@@ -79,6 +79,38 @@ instance FromJSON Tag where
|
|||||||
instance ToJSON URI where
|
instance ToJSON URI where
|
||||||
toJSON = toJSON . E.decodeUtf8With E.lenientDecode . serializeURIRef'
|
toJSON = toJSON . E.decodeUtf8With E.lenientDecode . serializeURIRef'
|
||||||
|
|
||||||
|
instance FromJSON URLSource where
|
||||||
|
parseJSON v =
|
||||||
|
parseGHCupURL v
|
||||||
|
<|> parseOwnSourceLegacy v
|
||||||
|
<|> parseOwnSourceNew1 v
|
||||||
|
<|> parseOwnSourceNew2 v
|
||||||
|
<|> parseOwnSpec v
|
||||||
|
<|> legacyParseAddSource v
|
||||||
|
<|> newParseAddSource v
|
||||||
|
where
|
||||||
|
parseOwnSourceLegacy = withObject "URLSource" $ \o -> do
|
||||||
|
r :: URI <- o .: "OwnSource"
|
||||||
|
pure (OwnSource [Right r])
|
||||||
|
parseOwnSourceNew1 = withObject "URLSource" $ \o -> do
|
||||||
|
r :: [URI] <- o .: "OwnSource"
|
||||||
|
pure (OwnSource (fmap Right r))
|
||||||
|
parseOwnSourceNew2 = withObject "URLSource" $ \o -> do
|
||||||
|
r :: [Either GHCupInfo URI] <- o .: "OwnSource"
|
||||||
|
pure (OwnSource r)
|
||||||
|
parseOwnSpec = withObject "URLSource" $ \o -> do
|
||||||
|
r :: GHCupInfo <- o .: "OwnSpec"
|
||||||
|
pure (OwnSpec r)
|
||||||
|
parseGHCupURL = withObject "URLSource" $ \o -> do
|
||||||
|
_ :: [Value] <- o .: "GHCupURL"
|
||||||
|
pure GHCupURL
|
||||||
|
legacyParseAddSource = withObject "URLSource" $ \o -> do
|
||||||
|
r :: Either GHCupInfo URI <- o .: "AddSource"
|
||||||
|
pure (AddSource [r])
|
||||||
|
newParseAddSource = withObject "URLSource" $ \o -> do
|
||||||
|
r :: [Either GHCupInfo URI] <- o .: "AddSource"
|
||||||
|
pure (AddSource r)
|
||||||
|
|
||||||
instance FromJSON URI where
|
instance FromJSON URI where
|
||||||
parseJSON = withText "URL" $ \t ->
|
parseJSON = withText "URL" $ \t ->
|
||||||
case parseURI strictURIParserOptions (encodeUtf8 t) of
|
case parseURI strictURIParserOptions (encodeUtf8 t) of
|
||||||
@@ -314,7 +346,7 @@ deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''Requir
|
|||||||
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''DownloadInfo
|
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''DownloadInfo
|
||||||
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''VersionInfo
|
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''VersionInfo
|
||||||
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''GHCupInfo
|
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''GHCupInfo
|
||||||
deriveJSON defaultOptions { sumEncoding = ObjectWithSingleField } ''URLSource
|
deriveToJSON defaultOptions { sumEncoding = ObjectWithSingleField } ''URLSource
|
||||||
deriveJSON defaultOptions { sumEncoding = ObjectWithSingleField } ''Key
|
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 "k-") . T.pack . kebab $ str' } ''UserKeyBindings
|
||||||
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 "u-") . T.pack . kebab $ str' } ''UserSettings
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ extra-deps:
|
|||||||
- composition-prelude-3.0.0.2@sha256:1ffed216bd28d810fce0b5be83a661e2a892696d73b3f8de5c0f5edb9b5f0090,1216
|
- composition-prelude-3.0.0.2@sha256:1ffed216bd28d810fce0b5be83a661e2a892696d73b3f8de5c0f5edb9b5f0090,1216
|
||||||
- haskus-utils-data-1.4@sha256:bfa94363b94b14779edd6834fbd59dbb847c3d7b8f48e3844f456ffdc077da4a,1466
|
- haskus-utils-data-1.4@sha256:bfa94363b94b14779edd6834fbd59dbb847c3d7b8f48e3844f456ffdc077da4a,1466
|
||||||
- haskus-utils-types-1.5.1@sha256:991c472f4e751e2f0d7aab6ad4220ef151d6160876dcf0511bbf876bbd432020,1298
|
- haskus-utils-types-1.5.1@sha256:991c472f4e751e2f0d7aab6ad4220ef151d6160876dcf0511bbf876bbd432020,1298
|
||||||
|
- haskus-utils-variant-3.2.1@sha256:791f4cf1e786eb578f4d37aef60986641f84c36e130164321f7d01542584066a,2200
|
||||||
- heaps-0.3.6.1@sha256:7928b759ca5180d35722c45948c0bde264229f3c99c1888188a3d9285f13d3d2,1340
|
- heaps-0.3.6.1@sha256:7928b759ca5180d35722c45948c0bde264229f3c99c1888188a3d9285f13d3d2,1340
|
||||||
- hpath-filepath-0.10.4@sha256:e9e44fb5fdbade7f30b5b5451257dbee15b6ef1aae4060034d73008bb3b5d878,1269
|
- hpath-filepath-0.10.4@sha256:e9e44fb5fdbade7f30b5b5451257dbee15b6ef1aae4060034d73008bb3b5d878,1269
|
||||||
- hpath-posix-0.13.3@sha256:abe472cf16bccd3a8b8814865ed3551a728fde0f3a2baea2acc03023bec6c565,1615
|
- hpath-posix-0.13.3@sha256:abe472cf16bccd3a8b8814865ed3551a728fde0f3a2baea2acc03023bec6c565,1615
|
||||||
@@ -39,11 +40,6 @@ extra-deps:
|
|||||||
- xor-0.0.1.0@sha256:f8362b4a68562b9afbcd727ff64c1a303970df3a032e0033d2f4c094c3501df3,2243
|
- xor-0.0.1.0@sha256:f8362b4a68562b9afbcd727ff64c1a303970df3a032e0033d2f4c094c3501df3,2243
|
||||||
- yaml-streamly-0.12.0
|
- yaml-streamly-0.12.0
|
||||||
|
|
||||||
- git: https://github.com/hasufell/packages.git
|
|
||||||
commit: cc0b4688f8bb374fa92f17c856949de795b56291
|
|
||||||
subdirs:
|
|
||||||
- haskus-utils-variant
|
|
||||||
|
|
||||||
flags:
|
flags:
|
||||||
http-io-streams:
|
http-io-streams:
|
||||||
brotli: false
|
brotli: false
|
||||||
|
|||||||
Reference in New Issue
Block a user