Compare commits
4 Commits
isolateDir
...
darwin-cod
| Author | SHA1 | Date | |
|---|---|---|---|
|
43a97fa419
|
|||
|
7e359d7b3c
|
|||
|
8cc333d8d5
|
|||
|
d67dafaf1b
|
@@ -37,6 +37,9 @@ binary=$(ecabal new-exec -w ghc-${GHC_VERSION} --verbose=0 --offline sh -- -c 'c
|
|||||||
ver=$("${binary}" --numeric-version)
|
ver=$("${binary}" --numeric-version)
|
||||||
if [ "${OS}" = "DARWIN" ] ; then
|
if [ "${OS}" = "DARWIN" ] ; then
|
||||||
strip "${binary}"
|
strip "${binary}"
|
||||||
|
# https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/318
|
||||||
|
codesign -s - -o linker-signed -i ghcup -v "${binary}"
|
||||||
|
:
|
||||||
else
|
else
|
||||||
strip -s "${binary}"
|
strip -s "${binary}"
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -176,8 +176,6 @@ else
|
|||||||
[ "$(ghc --numeric-version)" = "${ghc_ver}" ]
|
[ "$(ghc --numeric-version)" = "${ghc_ver}" ]
|
||||||
|
|
||||||
|
|
||||||
ls -lah "$GHCUP_BIN"
|
|
||||||
|
|
||||||
if [ "${OS}" = "DARWIN" ] ; then
|
if [ "${OS}" = "DARWIN" ] ; then
|
||||||
eghcup install hls
|
eghcup install hls
|
||||||
$(eghcup whereis hls) --version
|
$(eghcup whereis hls) --version
|
||||||
|
|||||||
22
CHANGELOG.md
22
CHANGELOG.md
@@ -1,27 +1,5 @@
|
|||||||
# Revision history for ghcup
|
# Revision history for ghcup
|
||||||
|
|
||||||
## 0.1.17.8 -- XXXX-XX-XX
|
|
||||||
|
|
||||||
* Fix HLS build not cleaning up properly on failed installations, fixes [#361](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/361)
|
|
||||||
- this also fixes a significant bug on installation failure when combining `--isolate DIR` with `--force`
|
|
||||||
* Fix parsing of symlinks with multiple slashes, wrt [#353](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/353)
|
|
||||||
|
|
||||||
## 0.1.17.7 -- 2022-04-21
|
|
||||||
|
|
||||||
* Fix `ghcup run` on windows wrt [#345](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/345)
|
|
||||||
|
|
||||||
## 0.1.17.6 -- 2022-03-18
|
|
||||||
|
|
||||||
* 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)
|
|
||||||
* Use predictable /tmp names for `ghcup run`, fixes [#329](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/329)
|
|
||||||
* Fix bug with isolated installation of not previously installed versions
|
|
||||||
* Add `--no-set` to install commands, fixes [#330](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/330)
|
|
||||||
* Fix serious bug in `ghcup list --raw-format -t <tool> -c installed`
|
|
||||||
* Overhaul metadata merging and add `ghcup config add-release-channel URI` wrt [#328](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/328)
|
|
||||||
* Fix max path issues on windows with `ghcup run`
|
|
||||||
|
|
||||||
## 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)
|
||||||
|
|||||||
@@ -446,19 +446,19 @@ install' _ (_, ListResult {..}) = do
|
|||||||
case lTool of
|
case lTool of
|
||||||
GHC -> do
|
GHC -> do
|
||||||
let vi = getVersionInfo lVer GHC dls
|
let vi = getVersionInfo lVer GHC dls
|
||||||
liftE $ installGHCBin lVer GHCupInternal False $> (vi, dirs, ce)
|
liftE $ installGHCBin lVer Nothing False $> (vi, dirs, ce)
|
||||||
Cabal -> do
|
Cabal -> do
|
||||||
let vi = getVersionInfo lVer Cabal dls
|
let vi = getVersionInfo lVer Cabal dls
|
||||||
liftE $ installCabalBin lVer GHCupInternal False $> (vi, dirs, ce)
|
liftE $ installCabalBin lVer Nothing False $> (vi, dirs, ce)
|
||||||
GHCup -> do
|
GHCup -> do
|
||||||
let vi = snd <$> getLatest dls GHCup
|
let vi = snd <$> getLatest dls GHCup
|
||||||
liftE $ upgradeGHCup Nothing False $> (vi, dirs, ce)
|
liftE $ upgradeGHCup Nothing False $> (vi, dirs, ce)
|
||||||
HLS -> do
|
HLS -> do
|
||||||
let vi = getVersionInfo lVer HLS dls
|
let vi = getVersionInfo lVer HLS dls
|
||||||
liftE $ installHLSBin lVer GHCupInternal False $> (vi, dirs, ce)
|
liftE $ installHLSBin lVer Nothing False $> (vi, dirs, ce)
|
||||||
Stack -> do
|
Stack -> do
|
||||||
let vi = getVersionInfo lVer Stack dls
|
let vi = getVersionInfo lVer Stack dls
|
||||||
liftE $ installStackBin lVer GHCupInternal False $> (vi, dirs, ce)
|
liftE $ installStackBin lVer Nothing False $> (vi, dirs, ce)
|
||||||
)
|
)
|
||||||
>>= \case
|
>>= \case
|
||||||
VRight (vi, Dirs{..}, Just ce) -> do
|
VRight (vi, Dirs{..}, Just ce) -> do
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ data Command
|
|||||||
#ifndef DISABLE_UPGRADE
|
#ifndef DISABLE_UPGRADE
|
||||||
| Upgrade UpgradeOpts Bool
|
| Upgrade UpgradeOpts Bool
|
||||||
#endif
|
#endif
|
||||||
| ToolRequirements ToolReqOpts
|
| ToolRequirements
|
||||||
| ChangeLog ChangeLogOptions
|
| ChangeLog ChangeLogOptions
|
||||||
| Nuke
|
| Nuke
|
||||||
#if defined(BRICK)
|
#if defined(BRICK)
|
||||||
@@ -113,8 +113,8 @@ data Command
|
|||||||
opts :: Parser Options
|
opts :: Parser Options
|
||||||
opts =
|
opts =
|
||||||
Options
|
Options
|
||||||
<$> invertableSwitch "verbose" (Just 'v') False (help "Enable verbosity (default: disabled)")
|
<$> invertableSwitch "verbose" 'v' False (help "Enable verbosity (default: disabled)")
|
||||||
<*> invertableSwitch "cache" (Just 'c') False (help "Cache downloads in ~/.ghcup/cache (default: disabled)")
|
<*> invertableSwitch "cache" 'c' False (help "Cache downloads in ~/.ghcup/cache (default: disabled)")
|
||||||
<*> optional (option auto (long "metadata-caching" <> help "How long the yaml metadata caching interval is (in seconds), 0 to disable" <> internal))
|
<*> optional (option auto (long "metadata-caching" <> help "How long the yaml metadata caching interval is (in seconds), 0 to disable" <> internal))
|
||||||
<*> optional
|
<*> optional
|
||||||
(option
|
(option
|
||||||
@@ -124,10 +124,9 @@ 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" (Just 'n') True (help "Disable tarball checksum verification (default: enabled)"))
|
<*> (fmap . fmap) not (invertableSwitch "verify" 'n' True (help "Disable tarball checksum verification (default: enabled)"))
|
||||||
<*> optional (option
|
<*> optional (option
|
||||||
(eitherReader keepOnParser)
|
(eitherReader keepOnParser)
|
||||||
( long "keep"
|
( long "keep"
|
||||||
@@ -135,7 +134,6 @@ 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)
|
||||||
@@ -144,23 +142,20 @@ 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
|
||||||
))
|
))
|
||||||
<*> invertableSwitch "offline" (Just 'o') False (help "Don't do any network calls, trying cached assets and failing if missing.")
|
<*> invertableSwitch "offline" 'o' False (help "Don't do any network calls, trying cached assets and failing if missing.")
|
||||||
<*> optional (option
|
<*> optional (option
|
||||||
(eitherReader gpgParser)
|
(eitherReader gpgParser)
|
||||||
( long "gpg"
|
( long "gpg"
|
||||||
<> 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
|
||||||
@@ -289,8 +284,8 @@ com =
|
|||||||
((\_ -> DInfo) <$> info helper (progDesc "Show debug info"))
|
((\_ -> DInfo) <$> info helper (progDesc "Show debug info"))
|
||||||
<> command
|
<> command
|
||||||
"tool-requirements"
|
"tool-requirements"
|
||||||
( ToolRequirements
|
( (\_ -> ToolRequirements)
|
||||||
<$> info (toolReqP <**> helper)
|
<$> info helper
|
||||||
(progDesc "Show the requirements for ghc/cabal")
|
(progDesc "Show the requirements for ghc/cabal")
|
||||||
)
|
)
|
||||||
<> command
|
<> command
|
||||||
|
|||||||
@@ -76,7 +76,6 @@ changelogP =
|
|||||||
)
|
)
|
||||||
(short 't' <> long "tool" <> metavar "<ghc|cabal|ghcup>" <> help
|
(short 't' <> long "tool" <> metavar "<ghc|cabal|ghcup>" <> help
|
||||||
"Open changelog for given tool (default: ghc)"
|
"Open changelog for given tool (default: ghc)"
|
||||||
<> completer toolCompleter
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
<*> optional (toolVersionArgument Nothing Nothing)
|
<*> optional (toolVersionArgument Nothing Nothing)
|
||||||
|
|||||||
@@ -3,8 +3,6 @@
|
|||||||
{-# LANGUAGE FlexibleContexts #-}
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
{-# LANGUAGE DuplicateRecordFields #-}
|
{-# LANGUAGE DuplicateRecordFields #-}
|
||||||
{-# LANGUAGE TypeApplications #-}
|
|
||||||
{-# LANGUAGE NumericUnderscores #-}
|
|
||||||
|
|
||||||
module GHCup.OptParse.Common where
|
module GHCup.OptParse.Common where
|
||||||
|
|
||||||
@@ -16,55 +14,36 @@ import GHCup.Platform
|
|||||||
import GHCup.Types
|
import GHCup.Types
|
||||||
import GHCup.Types.Optics
|
import GHCup.Types.Optics
|
||||||
import GHCup.Utils
|
import GHCup.Utils
|
||||||
import GHCup.Utils.File
|
|
||||||
import GHCup.Utils.Logger
|
import GHCup.Utils.Logger
|
||||||
import GHCup.Utils.MegaParsec
|
import GHCup.Utils.MegaParsec
|
||||||
import GHCup.Utils.Prelude
|
import GHCup.Utils.Prelude
|
||||||
|
|
||||||
import Control.DeepSeq
|
|
||||||
import Control.Concurrent
|
|
||||||
import Control.Concurrent.Async
|
|
||||||
import Control.Exception.Safe
|
import Control.Exception.Safe
|
||||||
#if !MIN_VERSION_base(4,13,0)
|
#if !MIN_VERSION_base(4,13,0)
|
||||||
import Control.Monad.Fail ( MonadFail )
|
import Control.Monad.Fail ( MonadFail )
|
||||||
#endif
|
#endif
|
||||||
import Control.Monad.Reader
|
import Control.Monad.Reader
|
||||||
import Data.Aeson
|
|
||||||
#if MIN_VERSION_aeson(2,0,0)
|
|
||||||
import qualified Data.Aeson.Key as KM
|
|
||||||
import qualified Data.Aeson.KeyMap as KM
|
|
||||||
#else
|
|
||||||
import qualified Data.HashMap.Strict as KM
|
|
||||||
#endif
|
|
||||||
import Data.ByteString.Lazy ( ByteString )
|
|
||||||
import Data.Bifunctor
|
import Data.Bifunctor
|
||||||
import Data.Char
|
import Data.Char
|
||||||
import Data.Either
|
import Data.Either
|
||||||
import Data.Functor
|
import Data.Functor
|
||||||
import Data.List ( nub, sort, sortBy, isPrefixOf, stripPrefix )
|
import Data.List ( nub, sort, sortBy )
|
||||||
import Data.Maybe
|
import Data.Maybe
|
||||||
import Data.Text ( Text )
|
import Data.Text ( Text )
|
||||||
import Data.Versions hiding ( str )
|
import Data.Versions hiding ( str )
|
||||||
import Data.Void
|
import Data.Void
|
||||||
import qualified Data.Vector as V
|
|
||||||
import GHC.IO.Exception
|
|
||||||
import Haskus.Utils.Variant.Excepts
|
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.FilePath
|
import System.FilePath
|
||||||
import Text.HTML.TagSoup hiding ( Tag )
|
|
||||||
import URI.ByteString
|
import URI.ByteString
|
||||||
|
|
||||||
import qualified Data.ByteString.UTF8 as UTF8
|
import qualified Data.ByteString.UTF8 as UTF8
|
||||||
import qualified Data.Map.Strict as M
|
import qualified Data.Map.Strict as M
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import qualified Text.Megaparsec as MP
|
import qualified Text.Megaparsec as MP
|
||||||
import qualified System.FilePath.Posix as FP
|
|
||||||
import GHCup.Version
|
import GHCup.Version
|
||||||
import Control.Exception (evaluate)
|
|
||||||
|
|
||||||
|
|
||||||
-------------
|
-------------
|
||||||
@@ -138,7 +117,7 @@ versionArgument criteria tool = argument (eitherReader tVersionEither) (metavar
|
|||||||
-- the help is shown only for --no-recursive.
|
-- the help is shown only for --no-recursive.
|
||||||
invertableSwitch
|
invertableSwitch
|
||||||
:: String -- ^ long option
|
:: String -- ^ long option
|
||||||
-> Maybe Char -- ^ short option for the non-default option
|
-> Char -- ^ short option for the non-default option
|
||||||
-> Bool -- ^ is switch enabled by default?
|
-> Bool -- ^ is switch enabled by default?
|
||||||
-> Mod FlagFields Bool -- ^ option modifier
|
-> Mod FlagFields Bool -- ^ option modifier
|
||||||
-> Parser (Maybe Bool)
|
-> Parser (Maybe Bool)
|
||||||
@@ -149,14 +128,14 @@ invertableSwitch longopt shortopt defv optmod = invertableSwitch' longopt shorto
|
|||||||
-- | Allows providing option modifiers for both --foo and --no-foo.
|
-- | Allows providing option modifiers for both --foo and --no-foo.
|
||||||
invertableSwitch'
|
invertableSwitch'
|
||||||
:: String -- ^ long option (eg "foo")
|
:: String -- ^ long option (eg "foo")
|
||||||
-> Maybe Char -- ^ short option for the non-default option
|
-> Char -- ^ short option for the non-default option
|
||||||
-> Bool -- ^ is switch enabled by default?
|
-> Bool -- ^ is switch enabled by default?
|
||||||
-> Mod FlagFields Bool -- ^ option modifier for --foo
|
-> Mod FlagFields Bool -- ^ option modifier for --foo
|
||||||
-> Mod FlagFields Bool -- ^ option modifier for --no-foo
|
-> Mod FlagFields Bool -- ^ option modifier for --no-foo
|
||||||
-> Parser (Maybe Bool)
|
-> Parser (Maybe Bool)
|
||||||
invertableSwitch' longopt shortopt defv enmod dismod = optional
|
invertableSwitch' longopt shortopt defv enmod dismod = optional
|
||||||
( flag' True ( enmod <> long longopt <> if defv then mempty else maybe mempty short shortopt)
|
( flag' True ( enmod <> long longopt <> if defv then mempty else short shortopt)
|
||||||
<|> flag' False (dismod <> long nolongopt <> if defv then maybe mempty short shortopt else mempty)
|
<|> flag' False (dismod <> long nolongopt <> if defv then short shortopt else mempty)
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
nolongopt = "no-" ++ longopt
|
nolongopt = "no-" ++ longopt
|
||||||
@@ -298,126 +277,6 @@ gpgParser s' | t == T.pack "strict" = Right GPGStrict
|
|||||||
--[ Completers ]--
|
--[ Completers ]--
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
|
||||||
toolCompleter :: Completer
|
|
||||||
toolCompleter = listCompleter ["ghc", "cabal", "hls", "stack"]
|
|
||||||
|
|
||||||
gitFileUri :: [String] -> Completer
|
|
||||||
gitFileUri add = mkCompleter $ fileUri' (["git://"] <> add)
|
|
||||||
|
|
||||||
fileUri :: Completer
|
|
||||||
fileUri = mkCompleter $ fileUri' []
|
|
||||||
|
|
||||||
fileUri' :: [String] -> String -> IO [String]
|
|
||||||
fileUri' add = \case
|
|
||||||
"" -> do
|
|
||||||
pwd <- getCurrentDirectory
|
|
||||||
pure $ ["https://", "http://", "file:///", "file://" <> pwd <> "/"] <> add
|
|
||||||
xs
|
|
||||||
| "file:///" `isPrefixOf` xs -> fmap ("file://" <>) <$>
|
|
||||||
case stripPrefix "file://" xs of
|
|
||||||
Nothing -> pure []
|
|
||||||
Just r -> do
|
|
||||||
pwd <- getCurrentDirectory
|
|
||||||
dirs <- compgen "directory" r ["-S", "/"]
|
|
||||||
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 []
|
|
||||||
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.
|
|
||||||
--
|
|
||||||
-- We need to do this so bash doesn't expand out any ~ or other
|
|
||||||
-- chars we want to complete on, or emit an end of line error
|
|
||||||
-- when seeking the close to the quote.
|
|
||||||
--
|
|
||||||
-- NOTE: copied from https://hackage.haskell.org/package/optparse-applicative-0.17.0.0/docs/src/Options.Applicative.Builder.Completer.html#requote
|
|
||||||
requote :: String -> String
|
|
||||||
requote s =
|
|
||||||
let
|
|
||||||
-- Bash doesn't appear to allow "mixed" escaping
|
|
||||||
-- in bash completions. So we don't have to really
|
|
||||||
-- worry about people swapping between strong and
|
|
||||||
-- weak quotes.
|
|
||||||
unescaped =
|
|
||||||
case s of
|
|
||||||
-- It's already strongly quoted, so we
|
|
||||||
-- can use it mostly as is, but we must
|
|
||||||
-- ensure it's closed off at the end and
|
|
||||||
-- there's no single quotes in the
|
|
||||||
-- middle which might confuse bash.
|
|
||||||
('\'': rs) -> unescapeN rs
|
|
||||||
|
|
||||||
-- We're weakly quoted.
|
|
||||||
('"': rs) -> unescapeD rs
|
|
||||||
|
|
||||||
-- We're not quoted at all.
|
|
||||||
-- We need to unescape some characters like
|
|
||||||
-- spaces and quotation marks.
|
|
||||||
elsewise -> unescapeU elsewise
|
|
||||||
in
|
|
||||||
strong unescaped
|
|
||||||
|
|
||||||
where
|
|
||||||
strong ss = '\'' : foldr go "'" ss
|
|
||||||
where
|
|
||||||
-- If there's a single quote inside the
|
|
||||||
-- command: exit from the strong quote and
|
|
||||||
-- emit it the quote escaped, then resume.
|
|
||||||
go '\'' t = "'\\''" ++ t
|
|
||||||
go h t = h : t
|
|
||||||
|
|
||||||
-- Unescape a strongly quoted string
|
|
||||||
-- We have two recursive functions, as we
|
|
||||||
-- can enter and exit the strong escaping.
|
|
||||||
unescapeN = goX
|
|
||||||
where
|
|
||||||
goX ('\'' : xs) = goN xs
|
|
||||||
goX (x : xs) = x : goX xs
|
|
||||||
goX [] = []
|
|
||||||
|
|
||||||
goN ('\\' : '\'' : xs) = '\'' : goN xs
|
|
||||||
goN ('\'' : xs) = goX xs
|
|
||||||
goN (x : xs) = x : goN xs
|
|
||||||
goN [] = []
|
|
||||||
|
|
||||||
-- Unescape an unquoted string
|
|
||||||
unescapeU = goX
|
|
||||||
where
|
|
||||||
goX [] = []
|
|
||||||
goX ('\\' : x : xs) = x : goX xs
|
|
||||||
goX (x : xs) = x : goX xs
|
|
||||||
|
|
||||||
-- Unescape a weakly quoted string
|
|
||||||
unescapeD = goX
|
|
||||||
where
|
|
||||||
-- Reached an escape character
|
|
||||||
goX ('\\' : x : xs)
|
|
||||||
-- If it's true escapable, strip the
|
|
||||||
-- slashes, as we're going to strong
|
|
||||||
-- escape instead.
|
|
||||||
| x `elem` ("$`\"\\\n" :: String) = x : goX xs
|
|
||||||
| otherwise = '\\' : x : goX xs
|
|
||||||
-- We've ended quoted section, so we
|
|
||||||
-- don't recurse on goX, it's done.
|
|
||||||
goX ('"' : xs)
|
|
||||||
= xs
|
|
||||||
-- Not done, but not a special character
|
|
||||||
-- just continue the fold.
|
|
||||||
goX (x : xs)
|
|
||||||
= x : goX xs
|
|
||||||
goX []
|
|
||||||
= []
|
|
||||||
|
|
||||||
|
|
||||||
tagCompleter :: Tool -> [String] -> Completer
|
tagCompleter :: Tool -> [String] -> Completer
|
||||||
tagCompleter tool add = listIOCompleter $ do
|
tagCompleter tool add = listIOCompleter $ do
|
||||||
dirs' <- liftIO getAllDirs
|
dirs' <- liftIO getAllDirs
|
||||||
@@ -475,150 +334,6 @@ versionCompleter criteria tool = listIOCompleter $ do
|
|||||||
return $ T.unpack . prettyVer . lVer <$> installedVersions
|
return $ T.unpack . prettyVer . lVer <$> installedVersions
|
||||||
|
|
||||||
|
|
||||||
toolDlCompleter :: Tool -> Completer
|
|
||||||
toolDlCompleter tool = mkCompleter $ \case
|
|
||||||
"" -> pure (initUrl tool <> ["https://", "http://", "file:///"])
|
|
||||||
word
|
|
||||||
| "file://" `isPrefixOf` word -> fileUri' [] word
|
|
||||||
-- downloads.haskell.org
|
|
||||||
| "https://downloads.haskell.org/" `isPrefixOf` word ->
|
|
||||||
fmap (completePrefix word) . prefixMatch (FP.takeFileName word) <$> fromHRef word
|
|
||||||
|
|
||||||
-- github releases
|
|
||||||
| "https://github.com/haskell/haskell-language-server/releases/download/" `isPrefixOf` word
|
|
||||||
, let xs = splitPath word
|
|
||||||
, (length xs == 6 && last word == '/') || (length xs == 7 && last word /= '/') ->
|
|
||||||
fmap (\x -> completePrefix word x <> "/") . prefixMatch (FP.takeFileName word) <$> getGithubReleases "haskell" "haskell-language-server"
|
|
||||||
| "https://github.com/commercialhaskell/stack/releases/download/" == word
|
|
||||||
, let xs = splitPath word
|
|
||||||
, (length xs == 6 && last word == '/') || (length xs == 7 && last word /= '/') ->
|
|
||||||
fmap (\x -> completePrefix word x <> "/") . prefixMatch (FP.takeFileName word) <$> getGithubReleases "commercialhaskell" "stack"
|
|
||||||
|
|
||||||
-- github release assets
|
|
||||||
| "https://github.com/haskell/haskell-language-server/releases/download/" `isPrefixOf` word
|
|
||||||
, let xs = splitPath word
|
|
||||||
, (length xs == 7 && last word == '/') || length xs == 8
|
|
||||||
, let rel = xs !! 6
|
|
||||||
, length rel > 1 -> do
|
|
||||||
fmap (completePrefix word) . prefixMatch (FP.takeFileName word) <$> getGithubAssets "haskell" "haskell-language-server" (init rel)
|
|
||||||
| "https://github.com/commercialhaskell/stack/releases/download/" `isPrefixOf` word
|
|
||||||
, let xs = splitPath word
|
|
||||||
, (length xs == 7 && last word == '/') || length xs == 8
|
|
||||||
, let rel = xs !! 6
|
|
||||||
, length rel > 1 -> do
|
|
||||||
fmap (completePrefix word) . prefixMatch (FP.takeFileName word) <$> getGithubAssets "commercialhaskell" "stack" (init rel)
|
|
||||||
|
|
||||||
-- github
|
|
||||||
| "https://github.com/c" `isPrefixOf` word -> pure ["https://github.com/commercialhaskell/stack/releases/download/"]
|
|
||||||
| "https://github.com/h" `isPrefixOf` word -> pure ["https://github.com/haskell/haskell-language-server/releases/download/"]
|
|
||||||
| "https://g" `isPrefixOf` word
|
|
||||||
, tool == Stack -> pure ["https://github.com/commercialhaskell/stack/releases/download/"]
|
|
||||||
| "https://g" `isPrefixOf` word
|
|
||||||
, tool == HLS -> pure ["https://github.com/haskell/haskell-language-server/releases/download/"]
|
|
||||||
|
|
||||||
| "https://d" `isPrefixOf` word -> pure $ filter ("https://downloads.haskell.org/" `isPrefixOf`) $ 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 []
|
|
||||||
where
|
|
||||||
initUrl :: Tool -> [String]
|
|
||||||
initUrl GHC = [ "https://downloads.haskell.org/~ghc/"
|
|
||||||
, "https://downloads.haskell.org/~ghcup/unofficial-bindists/ghc/"
|
|
||||||
]
|
|
||||||
initUrl Cabal = [ "https://downloads.haskell.org/~cabal/"
|
|
||||||
, "https://downloads.haskell.org/~ghcup/unofficial-bindists/cabal/"
|
|
||||||
]
|
|
||||||
initUrl GHCup = [ "https://downloads.haskell.org/~ghcup/" ]
|
|
||||||
initUrl HLS = [ "https://github.com/haskell/haskell-language-server/releases/download/"
|
|
||||||
, "https://downloads.haskell.org/~ghcup/unofficial-bindists/haskell-language-server/"
|
|
||||||
]
|
|
||||||
initUrl Stack = [ "https://github.com/commercialhaskell/stack/releases/download/"
|
|
||||||
, "https://downloads.haskell.org/~ghcup/unofficial-bindists/stack/"
|
|
||||||
]
|
|
||||||
|
|
||||||
completePrefix :: String -- ^ url, e.g. 'https://github.com/haskell/haskell-languag'
|
|
||||||
-> String -- ^ match, e.g. 'haskell-language-server'
|
|
||||||
-> String -- ^ result, e.g. 'https://github.com/haskell/haskell-language-server'
|
|
||||||
completePrefix url match =
|
|
||||||
let base = FP.takeDirectory url
|
|
||||||
fn = FP.takeFileName url
|
|
||||||
in if fn `isPrefixOf` match then base <> "/" <> match else url
|
|
||||||
|
|
||||||
prefixMatch :: String -> [String] -> [String]
|
|
||||||
prefixMatch pref = filter (pref `isPrefixOf`)
|
|
||||||
|
|
||||||
fromHRef :: String -> IO [String]
|
|
||||||
fromHRef url = withCurl (FP.takeDirectory url) 2_000_000 $ \stdout ->
|
|
||||||
pure
|
|
||||||
. fmap (T.unpack . decUTF8Safe' . fromAttrib "href")
|
|
||||||
. filter isTagOpen
|
|
||||||
. filter (~== ("<a href>" :: String))
|
|
||||||
. parseTags
|
|
||||||
$ stdout
|
|
||||||
|
|
||||||
withCurl :: String -- ^ url
|
|
||||||
-> Int -- ^ delay
|
|
||||||
-> (ByteString -> IO [String]) -- ^ callback
|
|
||||||
-> IO [String]
|
|
||||||
withCurl url delay cb = do
|
|
||||||
let limit = threadDelay delay
|
|
||||||
race limit (executeOut "curl" ["-fL", url] Nothing) >>= \case
|
|
||||||
Right (CapturedProcess {_exitCode, _stdOut}) -> do
|
|
||||||
case _exitCode of
|
|
||||||
ExitSuccess ->
|
|
||||||
(try @_ @SomeException . cb $ _stdOut) >>= \case
|
|
||||||
Left _ -> pure []
|
|
||||||
Right r' -> do
|
|
||||||
r <- try @_ @SomeException
|
|
||||||
. evaluate
|
|
||||||
. force
|
|
||||||
$ r'
|
|
||||||
either (\_ -> pure []) pure r
|
|
||||||
ExitFailure _ -> pure []
|
|
||||||
Left _ -> pure []
|
|
||||||
|
|
||||||
getGithubReleases :: String
|
|
||||||
-> String
|
|
||||||
-> IO [String]
|
|
||||||
getGithubReleases owner repo = withCurl url 3_000_000 $ \stdout -> do
|
|
||||||
Just xs <- pure $ decode' @Array stdout
|
|
||||||
fmap V.toList $ forM xs $ \x -> do
|
|
||||||
(Object r) <- pure x
|
|
||||||
Just (String name) <- pure $ KM.lookup (mkval "tag_name") r
|
|
||||||
pure $ T.unpack name
|
|
||||||
where
|
|
||||||
url = "https://api.github.com/repos/" <> owner <> "/" <> repo <> "/releases"
|
|
||||||
|
|
||||||
getGithubAssets :: String
|
|
||||||
-> String
|
|
||||||
-> String
|
|
||||||
-> IO [String]
|
|
||||||
getGithubAssets owner repo tag = withCurl url 3_000_000 $ \stdout -> do
|
|
||||||
Just xs <- pure $ decode' @Object stdout
|
|
||||||
Just (Array assets) <- pure $ KM.lookup (mkval "assets") xs
|
|
||||||
as <- fmap V.toList $ forM assets $ \val -> do
|
|
||||||
(Object asset) <- pure val
|
|
||||||
Just (String name) <- pure $ KM.lookup (mkval "name") asset
|
|
||||||
pure $ T.unpack name
|
|
||||||
pure as
|
|
||||||
where
|
|
||||||
url = "https://api.github.com/repos/" <> owner <> "/" <> repo <> "/releases/tags/" <> tag
|
|
||||||
|
|
||||||
|
|
||||||
#if MIN_VERSION_aeson(2,0,0)
|
|
||||||
mkval = KM.fromString
|
|
||||||
#else
|
|
||||||
mkval = id
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-----------------
|
-----------------
|
||||||
|
|||||||
@@ -165,7 +165,6 @@ ghcCompileOpts =
|
|||||||
)
|
)
|
||||||
(short 'v' <> long "version" <> metavar "VERSION" <> help
|
(short 'v' <> long "version" <> metavar "VERSION" <> help
|
||||||
"The tool version to compile"
|
"The tool version to compile"
|
||||||
<> (completer $ versionCompleter Nothing GHC)
|
|
||||||
)
|
)
|
||||||
) <|>
|
) <|>
|
||||||
(Right <$> (GitBranch <$> option
|
(Right <$> (GitBranch <$> option
|
||||||
@@ -173,10 +172,7 @@ 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 (
|
optional (option str (short 'r' <> long "repository" <> metavar "GIT_REPOSITORY" <> help "The git repository to build from (defaults to GHC upstream)"))
|
||||||
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
|
||||||
@@ -189,14 +185,12 @@ ghcCompileOpts =
|
|||||||
<> metavar "BOOTSTRAP_GHC"
|
<> metavar "BOOTSTRAP_GHC"
|
||||||
<> help
|
<> help
|
||||||
"The GHC version (or full path) to bootstrap with (must be installed)"
|
"The GHC version (or full path) to bootstrap with (must be installed)"
|
||||||
<> (completer $ versionCompleter Nothing GHC)
|
|
||||||
)
|
)
|
||||||
<*> optional
|
<*> optional
|
||||||
(option
|
(option
|
||||||
(eitherReader (readEither @Int))
|
(eitherReader (readEither @Int))
|
||||||
(short 'j' <> long "jobs" <> metavar "JOBS" <> help
|
(short 'j' <> long "jobs" <> metavar "JOBS" <> help
|
||||||
"How many jobs to use for make"
|
"How many jobs to use for make"
|
||||||
<> (completer $ listCompleter $ fmap show ([1..12] :: [Int]))
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
<*> optional
|
<*> optional
|
||||||
@@ -204,7 +198,6 @@ ghcCompileOpts =
|
|||||||
str
|
str
|
||||||
(short 'c' <> long "config" <> metavar "CONFIG" <> help
|
(short 'c' <> long "config" <> metavar "CONFIG" <> help
|
||||||
"Absolute path to build config file"
|
"Absolute path to build config file"
|
||||||
<> completer (bashCompleter "file")
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
<*> (optional
|
<*> (optional
|
||||||
@@ -213,7 +206,6 @@ ghcCompileOpts =
|
|||||||
(eitherReader uriParser)
|
(eitherReader uriParser)
|
||||||
(long "patch" <> metavar "PATCH_URI" <> help
|
(long "patch" <> metavar "PATCH_URI" <> help
|
||||||
"URI to a patch (https/http/file)"
|
"URI to a patch (https/http/file)"
|
||||||
<> completer fileUri
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
<|>
|
<|>
|
||||||
@@ -221,7 +213,6 @@ ghcCompileOpts =
|
|||||||
str
|
str
|
||||||
(short 'p' <> long "patchdir" <> metavar "PATCH_DIR" <> help
|
(short 'p' <> long "patchdir" <> metavar "PATCH_DIR" <> help
|
||||||
"Absolute path to patch directory (applies all .patch and .diff files in order using -p1. This order is determined by a quilt series file if it exists, or the patches are lexicographically ordered)"
|
"Absolute path to patch directory (applies all .patch and .diff files in order using -p1. This order is determined by a quilt series file if it exists, or the patches are lexicographically ordered)"
|
||||||
<> completer (bashCompleter "directory")
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -234,7 +225,12 @@ ghcCompileOpts =
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
<*> many (argument str (metavar "CONFIGURE_ARGS" <> help "Additional arguments to configure, prefix with '-- ' (longopts)"))
|
<*> many (argument str (metavar "CONFIGURE_ARGS" <> help "Additional arguments to configure, prefix with '-- ' (longopts)"))
|
||||||
<*> fmap (fromMaybe False) (invertableSwitch "set" Nothing False (help "Set as active version after install"))
|
<*> flag
|
||||||
|
False
|
||||||
|
True
|
||||||
|
(long "set" <> help
|
||||||
|
"Set as active version after install"
|
||||||
|
)
|
||||||
<*> optional
|
<*> optional
|
||||||
(option
|
(option
|
||||||
(eitherReader
|
(eitherReader
|
||||||
@@ -242,7 +238,6 @@ ghcCompileOpts =
|
|||||||
)
|
)
|
||||||
(short 'o' <> long "overwrite-version" <> metavar "OVERWRITE_VERSION" <> help
|
(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'"
|
"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'"
|
||||||
<> (completer $ versionCompleter Nothing GHC)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
<*> optional
|
<*> optional
|
||||||
@@ -262,7 +257,6 @@ ghcCompileOpts =
|
|||||||
<> long "isolate"
|
<> long "isolate"
|
||||||
<> metavar "DIR"
|
<> metavar "DIR"
|
||||||
<> help "install in an isolated directory instead of the default one, no symlinks to this installation will be made"
|
<> help "install in an isolated directory instead of the default one, no symlinks to this installation will be made"
|
||||||
<> completer (bashCompleter "directory")
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -275,7 +269,6 @@ hlsCompileOpts =
|
|||||||
)
|
)
|
||||||
(short 'v' <> long "version" <> metavar "VERSION" <> help
|
(short 'v' <> long "version" <> metavar "VERSION" <> help
|
||||||
"The tool version to compile"
|
"The tool version to compile"
|
||||||
<> (completer $ versionCompleter Nothing HLS)
|
|
||||||
)
|
)
|
||||||
) <|>
|
) <|>
|
||||||
(Right <$> (GitBranch <$> option
|
(Right <$> (GitBranch <$> option
|
||||||
@@ -283,19 +276,21 @@ 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 HLS 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
|
||||||
(eitherReader (readEither @Int))
|
(eitherReader (readEither @Int))
|
||||||
(short 'j' <> long "jobs" <> metavar "JOBS" <> help
|
(short 'j' <> long "jobs" <> metavar "JOBS" <> help
|
||||||
"How many jobs to use for make"
|
"How many jobs to use for make"
|
||||||
<> (completer $ listCompleter $ fmap show ([1..12] :: [Int]))
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
<*> fmap (fromMaybe True) (invertableSwitch "set" Nothing True (help "Don't set as active version after install"))
|
<*> flag
|
||||||
|
False
|
||||||
|
True
|
||||||
|
(long "set" <> help
|
||||||
|
"Set as active version after install"
|
||||||
|
)
|
||||||
<*> optional
|
<*> optional
|
||||||
(option
|
(option
|
||||||
(eitherReader
|
(eitherReader
|
||||||
@@ -303,7 +298,6 @@ hlsCompileOpts =
|
|||||||
)
|
)
|
||||||
(short 'o' <> long "overwrite-version" <> metavar "OVERWRITE_VERSION" <> help
|
(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'"
|
"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'"
|
||||||
<> (completer $ versionCompleter Nothing HLS)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
<*> optional
|
<*> optional
|
||||||
@@ -313,7 +307,6 @@ hlsCompileOpts =
|
|||||||
<> long "isolate"
|
<> long "isolate"
|
||||||
<> metavar "DIR"
|
<> metavar "DIR"
|
||||||
<> help "install in an isolated directory instead of the default one, no symlinks to this installation will be made"
|
<> help "install in an isolated directory instead of the default one, no symlinks to this installation will be made"
|
||||||
<> completer (bashCompleter "directory")
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
<*> optional
|
<*> optional
|
||||||
@@ -321,7 +314,6 @@ hlsCompileOpts =
|
|||||||
((fmap Right $ eitherReader uriParser) <|> (fmap Left str))
|
((fmap Right $ eitherReader uriParser) <|> (fmap Left str))
|
||||||
(long "cabal-project" <> metavar "CABAL_PROJECT" <> help
|
(long "cabal-project" <> metavar "CABAL_PROJECT" <> help
|
||||||
"If relative filepath, specifies the path to cabal.project inside the unpacked HLS tarball/checkout. Otherwise expects a full URI with https/http/file scheme."
|
"If relative filepath, specifies the path to cabal.project inside the unpacked HLS tarball/checkout. Otherwise expects a full URI with https/http/file scheme."
|
||||||
<> completer fileUri
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
<*> optional
|
<*> optional
|
||||||
@@ -329,7 +321,6 @@ hlsCompileOpts =
|
|||||||
(eitherReader uriParser)
|
(eitherReader uriParser)
|
||||||
(long "cabal-project-local" <> metavar "CABAL_PROJECT_LOCAL" <> help
|
(long "cabal-project-local" <> metavar "CABAL_PROJECT_LOCAL" <> help
|
||||||
"URI (https/http/file) to a cabal.project.local to be used for the build. Will be copied over."
|
"URI (https/http/file) to a cabal.project.local to be used for the build. Will be copied over."
|
||||||
<> completer fileUri
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
<*> (optional
|
<*> (optional
|
||||||
@@ -338,7 +329,6 @@ hlsCompileOpts =
|
|||||||
(eitherReader uriParser)
|
(eitherReader uriParser)
|
||||||
(long "patch" <> metavar "PATCH_URI" <> help
|
(long "patch" <> metavar "PATCH_URI" <> help
|
||||||
"URI to a patch (https/http/file)"
|
"URI to a patch (https/http/file)"
|
||||||
<> completer fileUri
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
<|>
|
<|>
|
||||||
@@ -346,7 +336,6 @@ hlsCompileOpts =
|
|||||||
str
|
str
|
||||||
(short 'p' <> long "patchdir" <> metavar "PATCH_DIR" <> help
|
(short 'p' <> long "patchdir" <> metavar "PATCH_DIR" <> help
|
||||||
"Absolute path to patch directory (applies all .patch and .diff files in order using -p1)"
|
"Absolute path to patch directory (applies all .patch and .diff files in order using -p1)"
|
||||||
<> completer (bashCompleter "directory")
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -469,7 +458,7 @@ compile compileCommand settings Dirs{..} runAppState runLogger = do
|
|||||||
ghcs
|
ghcs
|
||||||
jobs
|
jobs
|
||||||
ovewrwiteVer
|
ovewrwiteVer
|
||||||
(maybe GHCupInternal IsolateDir isolateDir)
|
isolateDir
|
||||||
cabalProject
|
cabalProject
|
||||||
cabalProjectLocal
|
cabalProjectLocal
|
||||||
patches
|
patches
|
||||||
@@ -524,7 +513,7 @@ compile compileCommand settings Dirs{..} runAppState runLogger = do
|
|||||||
addConfArgs
|
addConfArgs
|
||||||
buildFlavour
|
buildFlavour
|
||||||
hadrian
|
hadrian
|
||||||
(maybe GHCupInternal IsolateDir isolateDir)
|
isolateDir
|
||||||
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||||
let vi = getVersionInfo (_tvVersion targetVer) GHC dls
|
let vi = getVersionInfo (_tvVersion targetVer) GHC dls
|
||||||
when setCompile $ void $ liftE $
|
when setCompile $ void $ liftE $
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
{-# LANGUAGE DuplicateRecordFields #-}
|
{-# LANGUAGE DuplicateRecordFields #-}
|
||||||
{-# LANGUAGE RankNTypes #-}
|
{-# LANGUAGE RankNTypes #-}
|
||||||
{-# LANGUAGE ExplicitForAll #-}
|
|
||||||
|
|
||||||
module GHCup.OptParse.Config where
|
module GHCup.OptParse.Config where
|
||||||
|
|
||||||
@@ -18,7 +17,6 @@ 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 )
|
||||||
@@ -29,11 +27,10 @@ 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, ParseError )
|
import Options.Applicative hiding ( style )
|
||||||
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
|
||||||
@@ -52,7 +49,6 @@ data ConfigCommand
|
|||||||
= ShowConfig
|
= ShowConfig
|
||||||
| SetConfig String (Maybe String)
|
| SetConfig String (Maybe String)
|
||||||
| InitConfig
|
| InitConfig
|
||||||
| AddReleaseChannel URI
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -66,7 +62,6 @@ 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
|
||||||
@@ -75,8 +70,6 @@ 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")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -121,18 +114,23 @@ formatConfig :: UserSettings -> String
|
|||||||
formatConfig = UTF8.toString . Y.encode
|
formatConfig = UTF8.toString . Y.encode
|
||||||
|
|
||||||
|
|
||||||
updateSettings :: UserSettings -> Settings -> Settings
|
updateSettings :: Monad m => UTF8.ByteString -> Settings -> Excepts '[JSONError] m Settings
|
||||||
updateSettings UserSettings{..} Settings{..} =
|
updateSettings config' settings = do
|
||||||
let cache' = fromMaybe cache uCache
|
settings' <- lE' (JSONDecodeError . displayException) . Y.decodeEither' $ config'
|
||||||
metaCache' = fromMaybe metaCache uMetaCache
|
pure $ mergeConf settings' settings
|
||||||
noVerify' = fromMaybe noVerify uNoVerify
|
where
|
||||||
keepDirs' = fromMaybe keepDirs uKeepDirs
|
mergeConf :: UserSettings -> Settings -> Settings
|
||||||
downloader' = fromMaybe downloader uDownloader
|
mergeConf UserSettings{..} Settings{..} =
|
||||||
verbose' = fromMaybe verbose uVerbose
|
let cache' = fromMaybe cache uCache
|
||||||
urlSource' = fromMaybe urlSource uUrlSource
|
metaCache' = fromMaybe metaCache uMetaCache
|
||||||
noNetwork' = fromMaybe noNetwork uNoNetwork
|
noVerify' = fromMaybe noVerify uNoVerify
|
||||||
gpgSetting' = fromMaybe gpgSetting uGPGSetting
|
keepDirs' = fromMaybe keepDirs uKeepDirs
|
||||||
in Settings cache' metaCache' noVerify' keepDirs' downloader' verbose' urlSource' noNetwork' gpgSetting' noColor
|
downloader' = fromMaybe downloader uDownloader
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -142,7 +140,7 @@ updateSettings UserSettings{..} Settings{..} =
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
config :: forall m. ( Monad m
|
config :: ( Monad m
|
||||||
, MonadMask m
|
, MonadMask m
|
||||||
, MonadUnliftIO m
|
, MonadUnliftIO m
|
||||||
, MonadFail m
|
, MonadFail m
|
||||||
@@ -163,42 +161,27 @@ 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 mv) -> do
|
(SetConfig k (Just v)) ->
|
||||||
r <- runE @'[JSONError, ParseError] $ do
|
case v of
|
||||||
case mv of
|
"" -> do
|
||||||
Just "" ->
|
runLogger $ logError "Empty values are not allowed"
|
||||||
throwE $ ParseError "Empty values are not allowed"
|
pure $ ExitFailure 55
|
||||||
Nothing -> do
|
_ -> doConfig (k <> ": " <> v <> "\n")
|
||||||
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
|
|
||||||
|
|
||||||
AddReleaseChannel uri -> do
|
(SetConfig json Nothing) -> doConfig json
|
||||||
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 :: MonadIO m => UserSettings -> m ()
|
doConfig val = do
|
||||||
doConfig usersettings = do
|
r <- runE @'[JSONError] $ do
|
||||||
let settings' = updateSettings usersettings settings
|
settings' <- updateSettings (UTF8.fromString val) settings
|
||||||
path <- liftIO getConfigFilePath
|
path <- liftIO getConfigFilePath
|
||||||
liftIO $ writeFile path $ formatConfig $ fromSettings settings' (Just keybindings)
|
liftIO $ writeFile path $ formatConfig $ fromSettings settings' (Just keybindings)
|
||||||
runLogger $ logDebug $ T.pack $ show settings'
|
lift $ runLogger $ logDebug $ T.pack $ show settings'
|
||||||
pure ()
|
pure ()
|
||||||
|
|
||||||
decodeSettings = lE' (JSONDecodeError . displayException) . Y.decodeEither' . UTF8.fromString
|
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
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
{-# LANGUAGE QuasiQuotes #-}
|
{-# LANGUAGE QuasiQuotes #-}
|
||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
{-# LANGUAGE DuplicateRecordFields #-}
|
{-# LANGUAGE DuplicateRecordFields #-}
|
||||||
{-# LANGUAGE ViewPatterns #-}
|
|
||||||
|
|
||||||
module GHCup.OptParse.Install where
|
module GHCup.OptParse.Install where
|
||||||
|
|
||||||
@@ -190,15 +189,18 @@ installOpts tool =
|
|||||||
(eitherReader uriParser)
|
(eitherReader uriParser)
|
||||||
(short 'u' <> long "url" <> metavar "BINDIST_URL" <> help
|
(short 'u' <> long "url" <> metavar "BINDIST_URL" <> help
|
||||||
"Install the specified version from this bindist"
|
"Install the specified version from this bindist"
|
||||||
<> completer (toolDlCompleter (fromMaybe GHC tool))
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
<*> (Just <$> toolVersionArgument Nothing tool)
|
<*> (Just <$> toolVersionArgument Nothing tool)
|
||||||
)
|
)
|
||||||
<|> pure (Nothing, Nothing)
|
<|> pure (Nothing, Nothing)
|
||||||
)
|
)
|
||||||
<*> fmap (fromMaybe setDefault) (invertableSwitch "set" Nothing setDefault
|
<*> flag
|
||||||
(help $ if not setDefault then "Set as active version after install" else "Don't set as active version after install"))
|
False
|
||||||
|
True
|
||||||
|
(long "set" <> help
|
||||||
|
"Set as active version after install"
|
||||||
|
)
|
||||||
<*> optional
|
<*> optional
|
||||||
(option
|
(option
|
||||||
(eitherReader isolateParser)
|
(eitherReader isolateParser)
|
||||||
@@ -206,16 +208,10 @@ installOpts tool =
|
|||||||
<> long "isolate"
|
<> long "isolate"
|
||||||
<> metavar "DIR"
|
<> metavar "DIR"
|
||||||
<> help "install in an isolated dir instead of the default one"
|
<> help "install in an isolated dir instead of the default one"
|
||||||
<> completer (bashCompleter "directory")
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
<*> switch
|
<*> switch
|
||||||
(short 'f' <> long "force" <> help "Force install")
|
(short 'f' <> long "force" <> help "Force install")
|
||||||
where
|
|
||||||
setDefault = case tool of
|
|
||||||
Nothing -> False
|
|
||||||
Just GHC -> False
|
|
||||||
Just _ -> True
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -257,48 +253,6 @@ 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)
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@@ -395,10 +349,10 @@ install installCommand settings getAppState' runLogger = case installCommand of
|
|||||||
(v, vi) <- liftE $ fromVersion instVer GHC
|
(v, vi) <- liftE $ fromVersion instVer GHC
|
||||||
void $ liftE $ sequenceE (installGHCBin
|
void $ liftE $ sequenceE (installGHCBin
|
||||||
(_tvVersion v)
|
(_tvVersion v)
|
||||||
(maybe GHCupInternal IsolateDir isolateDir)
|
isolateDir
|
||||||
forceInstall
|
forceInstall
|
||||||
)
|
)
|
||||||
$ when instSet $ when (isNothing isolateDir) $ void $ setGHC v SetGHCOnly Nothing
|
$ when instSet $ void $ setGHC v SetGHCOnly Nothing
|
||||||
pure vi
|
pure vi
|
||||||
Just uri -> do
|
Just uri -> do
|
||||||
runInstGHC s'{ settings = settings {noVerify = True}} instPlatform $ do
|
runInstGHC s'{ settings = settings {noVerify = True}} instPlatform $ do
|
||||||
@@ -406,10 +360,10 @@ install installCommand settings getAppState' runLogger = case installCommand of
|
|||||||
void $ liftE $ sequenceE (installGHCBindist
|
void $ liftE $ sequenceE (installGHCBindist
|
||||||
(DownloadInfo uri (Just $ RegexDir "ghc-.*") "")
|
(DownloadInfo uri (Just $ RegexDir "ghc-.*") "")
|
||||||
(_tvVersion v)
|
(_tvVersion v)
|
||||||
(maybe GHCupInternal IsolateDir isolateDir)
|
isolateDir
|
||||||
forceInstall
|
forceInstall
|
||||||
)
|
)
|
||||||
$ when instSet $ when (isNothing isolateDir) $ void $ setGHC v SetGHCOnly Nothing
|
$ when instSet $ void $ setGHC v SetGHCOnly Nothing
|
||||||
pure vi
|
pure vi
|
||||||
)
|
)
|
||||||
>>= \case
|
>>= \case
|
||||||
@@ -464,22 +418,20 @@ 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
|
||||||
(_tvVersion -> v, vi) <- liftE $ fromVersion instVer Cabal
|
(v, vi) <- liftE $ fromVersion instVer Cabal
|
||||||
void $ liftE $ sequenceE (installCabalBin
|
liftE $ installCabalBin
|
||||||
v
|
(_tvVersion v)
|
||||||
(maybe GHCupInternal IsolateDir isolateDir)
|
isolateDir
|
||||||
forceInstall
|
forceInstall
|
||||||
) $ when instSet $ when (isNothing isolateDir) $ 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
|
||||||
(_tvVersion -> v, vi) <- liftE $ fromVersion instVer Cabal
|
(v, vi) <- liftE $ fromVersion instVer Cabal
|
||||||
void $ liftE $ sequenceE (installCabalBindist
|
liftE $ installCabalBindist
|
||||||
(DownloadInfo uri Nothing "")
|
(DownloadInfo uri Nothing "")
|
||||||
v
|
(_tvVersion v)
|
||||||
(maybe GHCupInternal IsolateDir isolateDir)
|
isolateDir
|
||||||
forceInstall
|
forceInstall
|
||||||
) $ when instSet $ when (isNothing isolateDir) $ void $ setCabal v
|
|
||||||
pure vi
|
pure vi
|
||||||
)
|
)
|
||||||
>>= \case
|
>>= \case
|
||||||
@@ -496,14 +448,6 @@ 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
|
||||||
@@ -515,23 +459,21 @@ 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
|
||||||
(_tvVersion -> v, vi) <- liftE $ fromVersion instVer HLS
|
(v, vi) <- liftE $ fromVersion instVer HLS
|
||||||
void $ liftE $ sequenceE (installHLSBin
|
liftE $ installHLSBin
|
||||||
v
|
(_tvVersion v)
|
||||||
(maybe GHCupInternal IsolateDir isolateDir)
|
isolateDir
|
||||||
forceInstall
|
forceInstall
|
||||||
) $ when instSet $ when (isNothing isolateDir) $ 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
|
||||||
(_tvVersion -> v, vi) <- liftE $ fromVersion instVer HLS
|
(v, vi) <- liftE $ fromVersion instVer HLS
|
||||||
-- TODO: support legacy
|
-- TODO: support legacy
|
||||||
void $ liftE $ sequenceE (installHLSBindist
|
liftE $ installHLSBindist
|
||||||
(DownloadInfo uri (Just $ RegexDir "haskell-language-server-*") "")
|
(DownloadInfo uri (Just $ RegexDir "haskell-language-server-*") "")
|
||||||
v
|
(_tvVersion v)
|
||||||
(maybe GHCupInternal IsolateDir isolateDir)
|
isolateDir
|
||||||
forceInstall
|
forceInstall
|
||||||
) $ when instSet $ when (isNothing isolateDir) $ void $ setHLS v SetHLSOnly Nothing
|
|
||||||
pure vi
|
pure vi
|
||||||
)
|
)
|
||||||
>>= \case
|
>>= \case
|
||||||
@@ -552,18 +494,6 @@ 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
|
||||||
@@ -575,22 +505,20 @@ 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
|
||||||
(_tvVersion -> v, vi) <- liftE $ fromVersion instVer Stack
|
(v, vi) <- liftE $ fromVersion instVer Stack
|
||||||
void $ liftE $ sequenceE (installStackBin
|
liftE $ installStackBin
|
||||||
v
|
(_tvVersion v)
|
||||||
(maybe GHCupInternal IsolateDir isolateDir)
|
isolateDir
|
||||||
forceInstall
|
forceInstall
|
||||||
) $ when instSet $ when (isNothing isolateDir) $ 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
|
||||||
(_tvVersion -> v, vi) <- liftE $ fromVersion instVer Stack
|
(v, vi) <- liftE $ fromVersion instVer Stack
|
||||||
void $ liftE $ sequenceE (installStackBindist
|
liftE $ installStackBindist
|
||||||
(DownloadInfo uri Nothing "")
|
(DownloadInfo uri Nothing "")
|
||||||
v
|
(_tvVersion v)
|
||||||
(maybe GHCupInternal IsolateDir isolateDir)
|
isolateDir
|
||||||
forceInstall
|
forceInstall
|
||||||
) $ when instSet $ when (isNothing isolateDir) $ void $ setStack v
|
|
||||||
pure vi
|
pure vi
|
||||||
)
|
)
|
||||||
>>= \case
|
>>= \case
|
||||||
@@ -607,14 +535,6 @@ 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
|
||||||
|
|||||||
@@ -69,7 +69,6 @@ listOpts =
|
|||||||
(eitherReader toolParser)
|
(eitherReader toolParser)
|
||||||
(short 't' <> long "tool" <> metavar "<ghc|cabal|hls|stack>" <> help
|
(short 't' <> long "tool" <> metavar "<ghc|cabal|hls|stack>" <> help
|
||||||
"Tool to list versions for. Default is all"
|
"Tool to list versions for. Default is all"
|
||||||
<> completer (toolCompleter)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
<*> optional
|
<*> optional
|
||||||
@@ -79,7 +78,6 @@ listOpts =
|
|||||||
<> long "show-criteria"
|
<> long "show-criteria"
|
||||||
<> metavar "<installed|set|available>"
|
<> metavar "<installed|set|available>"
|
||||||
<> help "Show only installed/set/available tool versions"
|
<> help "Show only installed/set/available tool versions"
|
||||||
<> completer (listCompleter ["installed", "set", "available"])
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
<*> switch
|
<*> switch
|
||||||
@@ -143,11 +141,11 @@ printListResult no_color raw lr = do
|
|||||||
)
|
)
|
||||||
$ lr
|
$ lr
|
||||||
let cols =
|
let cols =
|
||||||
foldr (\xs ys -> zipWith (:) xs ys) (repeat []) rows
|
foldr (\xs ys -> zipWith (:) xs ys) (replicate (length rows) []) rows
|
||||||
lengths = fmap (maximum . fmap strWidth) cols
|
lengths = fmap (maximum . fmap strWidth) cols
|
||||||
padded = fmap (\xs -> zipWith padTo xs lengths) rows
|
padded = fmap (\xs -> zipWith padTo xs lengths) rows
|
||||||
|
|
||||||
forM_ (if raw then rows else padded) $ \row -> putStrLn $ unwords row
|
forM_ padded $ \row -> putStrLn $ unwords row
|
||||||
where
|
where
|
||||||
|
|
||||||
padTo str' x =
|
padTo str' x =
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ prefetchP = subparser
|
|||||||
(PrefetchGHC
|
(PrefetchGHC
|
||||||
<$> (PrefetchGHCOptions
|
<$> (PrefetchGHCOptions
|
||||||
<$> ( switch (short 's' <> long "source" <> help "Download source tarball instead of bindist") <**> helper )
|
<$> ( 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/)" <> completer (bashCompleter "directory"))))
|
<*> optional (option str (short 'd' <> long "directory" <> help "directory to download into (default: ~/.ghcup/cache/)")))
|
||||||
<*> optional (toolVersionArgument Nothing (Just GHC)) )
|
<*> optional (toolVersionArgument Nothing (Just GHC)) )
|
||||||
( progDesc "Download GHC assets for installation")
|
( progDesc "Download GHC assets for installation")
|
||||||
)
|
)
|
||||||
@@ -92,7 +92,7 @@ prefetchP = subparser
|
|||||||
"cabal"
|
"cabal"
|
||||||
(info
|
(info
|
||||||
(PrefetchCabal
|
(PrefetchCabal
|
||||||
<$> fmap PrefetchOptions (optional (option str (short 'd' <> long "directory" <> help "directory to download into (default: ~/.ghcup/cache/)" <> completer (bashCompleter "directory"))))
|
<$> fmap PrefetchOptions (optional (option str (short 'd' <> long "directory" <> help "directory to download into (default: ~/.ghcup/cache/)")))
|
||||||
<*> ( optional (toolVersionArgument Nothing (Just Cabal)) <**> helper ))
|
<*> ( optional (toolVersionArgument Nothing (Just Cabal)) <**> helper ))
|
||||||
( progDesc "Download cabal assets for installation")
|
( progDesc "Download cabal assets for installation")
|
||||||
)
|
)
|
||||||
@@ -101,7 +101,7 @@ prefetchP = subparser
|
|||||||
"hls"
|
"hls"
|
||||||
(info
|
(info
|
||||||
(PrefetchHLS
|
(PrefetchHLS
|
||||||
<$> fmap PrefetchOptions (optional (option str (short 'd' <> long "directory" <> help "directory to download into (default: ~/.ghcup/cache/)" <> completer (bashCompleter "directory"))))
|
<$> fmap PrefetchOptions (optional (option str (short 'd' <> long "directory" <> help "directory to download into (default: ~/.ghcup/cache/)")))
|
||||||
<*> ( optional (toolVersionArgument Nothing (Just HLS)) <**> helper ))
|
<*> ( optional (toolVersionArgument Nothing (Just HLS)) <**> helper ))
|
||||||
( progDesc "Download HLS assets for installation")
|
( progDesc "Download HLS assets for installation")
|
||||||
)
|
)
|
||||||
@@ -110,7 +110,7 @@ prefetchP = subparser
|
|||||||
"stack"
|
"stack"
|
||||||
(info
|
(info
|
||||||
(PrefetchStack
|
(PrefetchStack
|
||||||
<$> fmap PrefetchOptions (optional (option str (short 'd' <> long "directory" <> help "directory to download into (default: ~/.ghcup/cache/)" <> completer (bashCompleter "directory"))))
|
<$> fmap PrefetchOptions (optional (option str (short 'd' <> long "directory" <> help "directory to download into (default: ~/.ghcup/cache/)")))
|
||||||
<*> ( optional (toolVersionArgument Nothing (Just Stack)) <**> helper ))
|
<*> ( optional (toolVersionArgument Nothing (Just Stack)) <**> helper ))
|
||||||
( progDesc "Download stack assets for installation")
|
( progDesc "Download stack assets for installation")
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import GHCup.Utils.File
|
|||||||
import GHCup.OptParse.Common
|
import GHCup.OptParse.Common
|
||||||
import GHCup.Errors
|
import GHCup.Errors
|
||||||
import GHCup.Types
|
import GHCup.Types
|
||||||
import GHCup.Types.Optics
|
import GHCup.Types.Optics ( getDirs )
|
||||||
import GHCup.Utils.Logger
|
import GHCup.Utils.Logger
|
||||||
import GHCup.Utils.String.QQ
|
import GHCup.Utils.String.QQ
|
||||||
|
|
||||||
@@ -35,6 +35,7 @@ import Prelude hiding ( appendFile )
|
|||||||
import System.Directory
|
import System.Directory
|
||||||
import System.FilePath
|
import System.FilePath
|
||||||
import System.Environment
|
import System.Environment
|
||||||
|
import System.IO.Temp
|
||||||
import System.Exit
|
import System.Exit
|
||||||
import Text.PrettyPrint.HughesPJClass ( prettyShow )
|
import Text.PrettyPrint.HughesPJClass ( prettyShow )
|
||||||
|
|
||||||
@@ -71,7 +72,6 @@ data RunOptions = RunOptions
|
|||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
runOpts :: Parser RunOptions
|
runOpts :: Parser RunOptions
|
||||||
runOpts =
|
runOpts =
|
||||||
RunOptions
|
RunOptions
|
||||||
@@ -82,34 +82,22 @@ runOpts =
|
|||||||
<*> optional
|
<*> optional
|
||||||
(option
|
(option
|
||||||
(eitherReader toolVersionEither)
|
(eitherReader toolVersionEither)
|
||||||
(metavar "GHC_VERSION" <> long "ghc" <> help "The ghc version"
|
(metavar "GHC_VERSION" <> long "ghc" <> help "The ghc version")
|
||||||
<> completer (tagCompleter GHC [])
|
|
||||||
<> (completer $ versionCompleter Nothing GHC)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
<*> optional
|
<*> optional
|
||||||
(option
|
(option
|
||||||
(eitherReader toolVersionEither)
|
(eitherReader toolVersionEither)
|
||||||
(metavar "CABAL_VERSION" <> long "cabal" <> help "The cabal version"
|
(metavar "CABAL_VERSION" <> long "cabal" <> help "The cabal version")
|
||||||
<> completer (tagCompleter Cabal [])
|
|
||||||
<> (completer $ versionCompleter Nothing Cabal)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
<*> optional
|
<*> optional
|
||||||
(option
|
(option
|
||||||
(eitherReader toolVersionEither)
|
(eitherReader toolVersionEither)
|
||||||
(metavar "HLS_VERSION" <> long "hls" <> help "The HLS version"
|
(metavar "HLS_VERSION" <> long "hls" <> help "The HLS version")
|
||||||
<> completer (tagCompleter HLS [])
|
|
||||||
<> (completer $ versionCompleter Nothing HLS)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
<*> optional
|
<*> optional
|
||||||
(option
|
(option
|
||||||
(eitherReader toolVersionEither)
|
(eitherReader toolVersionEither)
|
||||||
(metavar "STACK_VERSION" <> long "stack" <> help "The stack version"
|
(metavar "STACK_VERSION" <> long "stack" <> help "The stack version")
|
||||||
<> completer (tagCompleter Stack [])
|
|
||||||
<> (completer $ versionCompleter Nothing Stack)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
<*> optional
|
<*> optional
|
||||||
(option
|
(option
|
||||||
@@ -118,7 +106,6 @@ runOpts =
|
|||||||
<> long "bindir"
|
<> long "bindir"
|
||||||
<> metavar "DIR"
|
<> metavar "DIR"
|
||||||
<> help "directory where to create the tool symlinks (default: newly created system temp dir)"
|
<> help "directory where to create the tool symlinks (default: newly created system temp dir)"
|
||||||
<> completer (bashCompleter "directory")
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
<*> many (argument str (metavar "COMMAND" <> help "The command to run, with arguments (use longopts --). If omitted, just prints the created bin/ dir to stdout and exits."))
|
<*> many (argument str (metavar "COMMAND" <> help "The command to run, with arguments (use longopts --). If omitted, just prints the created bin/ dir to stdout and exits."))
|
||||||
@@ -187,16 +174,14 @@ runLeanRUN leanAppstate =
|
|||||||
@RunEffects
|
@RunEffects
|
||||||
|
|
||||||
runRUN :: MonadUnliftIO m
|
runRUN :: MonadUnliftIO m
|
||||||
=> IO AppState
|
=> (ReaderT AppState m (VEither RunEffects a) -> m (VEither RunEffects a))
|
||||||
-> Excepts RunEffects (ResourceT (ReaderT AppState m)) a
|
-> Excepts RunEffects (ResourceT (ReaderT AppState m)) a
|
||||||
-> m (VEither RunEffects a)
|
-> m (VEither RunEffects a)
|
||||||
runRUN appState action' = do
|
runRUN runAppState =
|
||||||
s' <- liftIO appState
|
runAppState
|
||||||
flip runReaderT s'
|
|
||||||
. runResourceT
|
. runResourceT
|
||||||
. runE
|
. runE
|
||||||
@RunEffects
|
@RunEffects
|
||||||
$ action'
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -214,182 +199,110 @@ run :: forall m.
|
|||||||
, MonadUnliftIO m
|
, MonadUnliftIO m
|
||||||
)
|
)
|
||||||
=> RunOptions
|
=> RunOptions
|
||||||
-> IO AppState
|
-> (forall a. ReaderT AppState m (VEither RunEffects a) -> m (VEither RunEffects a))
|
||||||
-> LeanAppState
|
-> LeanAppState
|
||||||
-> (ReaderT LeanAppState m () -> m ())
|
-> (ReaderT LeanAppState m () -> m ())
|
||||||
-> m ExitCode
|
-> m ExitCode
|
||||||
run RunOptions{..} runAppState leanAppstate runLogger = do
|
run RunOptions{..} runAppState leanAppstate runLogger = do
|
||||||
r <- if or (fmap (maybe False isToolTag) [runGHCVer, runCabalVer, runHLSVer, runStackVer]) || runInstTool'
|
tmp <- case runBinDir of
|
||||||
then runRUN runAppState $ do
|
Just bdir -> do
|
||||||
toolchain <- liftE resolveToolchainFull
|
liftIO $ createDirRecursive' bdir
|
||||||
tmp <- case runBinDir of
|
liftIO $ canonicalizePath bdir
|
||||||
Just bindir -> do
|
Nothing -> liftIO (getTemporaryDirectory >>= \tmp -> createTempDirectory tmp "ghcup")
|
||||||
liftIO $ createDirRecursive' bindir
|
r <- do
|
||||||
liftIO $ canonicalizePath bindir
|
addToolsToDir tmp
|
||||||
Nothing -> do
|
|
||||||
d <- liftIO $ predictableTmpDir toolchain
|
|
||||||
liftIO $ createDirRecursive' d
|
|
||||||
liftIO $ canonicalizePath d
|
|
||||||
liftE $ installToolChainFull toolchain tmp
|
|
||||||
pure tmp
|
|
||||||
else runLeanRUN leanAppstate $ do
|
|
||||||
toolchain <- resolveToolchain
|
|
||||||
tmp <- case runBinDir of
|
|
||||||
Just bindir -> do
|
|
||||||
liftIO $ createDirRecursive' bindir
|
|
||||||
liftIO $ canonicalizePath bindir
|
|
||||||
Nothing -> do
|
|
||||||
d <- liftIO $ predictableTmpDir toolchain
|
|
||||||
liftIO $ createDirRecursive' d
|
|
||||||
liftIO $ canonicalizePath d
|
|
||||||
liftE $ installToolChain toolchain tmp
|
|
||||||
pure tmp
|
|
||||||
case r of
|
case r of
|
||||||
VRight tmp -> do
|
VRight _ -> do
|
||||||
case runCOMMAND of
|
case runCOMMAND of
|
||||||
[] -> do
|
[] -> do
|
||||||
liftIO $ putStr tmp
|
liftIO $ putStr tmp
|
||||||
pure ExitSuccess
|
pure ExitSuccess
|
||||||
(cmd:args) -> do
|
(cmd:args) -> do
|
||||||
newEnv <- liftIO $ addToPath tmp
|
newEnv <- liftIO $ addToPath tmp
|
||||||
#ifndef IS_WINDOWS
|
#ifndef IS_WINDOWS
|
||||||
void $ liftIO $ SPP.executeFile cmd True args (Just newEnv)
|
void $ liftIO $ SPP.executeFile cmd True args (Just newEnv)
|
||||||
pure ExitSuccess
|
pure ExitSuccess
|
||||||
#else
|
#else
|
||||||
r' <- runLeanRUN leanAppstate $ liftE $ lEM @_ @'[ProcessError] $ exec cmd args Nothing (Just newEnv)
|
r' <- runLeanRUN leanAppstate $ liftE $ lEM @_ @'[ProcessError] $ exec cmd args Nothing (Just newEnv)
|
||||||
case r' of
|
case r' of
|
||||||
VRight _ -> pure ExitSuccess
|
VRight _ -> pure ExitSuccess
|
||||||
VLeft e -> do
|
VLeft e -> do
|
||||||
runLogger $ logError $ T.pack $ prettyShow e
|
runLogger $ logError $ T.pack $ prettyShow e
|
||||||
pure $ ExitFailure 28
|
pure $ ExitFailure 28
|
||||||
#endif
|
#endif
|
||||||
VLeft e -> do
|
VLeft e -> do
|
||||||
runLogger $ logError $ T.pack $ prettyShow e
|
runLogger $ logError $ T.pack $ prettyShow e
|
||||||
pure $ ExitFailure 27
|
pure $ ExitFailure 27
|
||||||
|
|
||||||
where
|
where
|
||||||
|
|
||||||
isToolTag :: ToolVersion -> Bool
|
isToolTag :: ToolVersion -> Bool
|
||||||
isToolTag (ToolTag _) = True
|
isToolTag (ToolTag _) = True
|
||||||
isToolTag _ = False
|
isToolTag _ = False
|
||||||
|
|
||||||
-- TODO: doesn't work for cross
|
-- TODO: doesn't work for cross
|
||||||
resolveToolchainFull :: ( MonadFail m
|
addToolsToDir tmp
|
||||||
, MonadThrow m
|
| or (fmap (maybe False isToolTag) [runGHCVer, runCabalVer, runHLSVer, runStackVer]) || runInstTool' = runRUN runAppState $ do
|
||||||
, MonadIO m
|
forM_ runGHCVer $ \ver -> do
|
||||||
, MonadCatch m
|
|
||||||
)
|
|
||||||
=> Excepts
|
|
||||||
'[ TagNotFound
|
|
||||||
, NextVerNotFound
|
|
||||||
, NoToolVersionSet
|
|
||||||
] (ResourceT (ReaderT AppState m)) Toolchain
|
|
||||||
resolveToolchainFull = do
|
|
||||||
ghcVer <- forM runGHCVer $ \ver -> do
|
|
||||||
(v, _) <- liftE $ fromVersion (Just ver) GHC
|
(v, _) <- liftE $ fromVersion (Just ver) GHC
|
||||||
pure v
|
installTool GHC v
|
||||||
cabalVer <- forM runCabalVer $ \ver -> do
|
setTool GHC v tmp
|
||||||
|
forM_ runCabalVer $ \ver -> do
|
||||||
(v, _) <- liftE $ fromVersion (Just ver) Cabal
|
(v, _) <- liftE $ fromVersion (Just ver) Cabal
|
||||||
pure v
|
installTool Cabal v
|
||||||
hlsVer <- forM runHLSVer $ \ver -> do
|
setTool Cabal v tmp
|
||||||
|
forM_ runHLSVer $ \ver -> do
|
||||||
(v, _) <- liftE $ fromVersion (Just ver) HLS
|
(v, _) <- liftE $ fromVersion (Just ver) HLS
|
||||||
pure v
|
installTool HLS v
|
||||||
stackVer <- forM runStackVer $ \ver -> do
|
setTool HLS v tmp
|
||||||
|
forM_ runStackVer $ \ver -> do
|
||||||
(v, _) <- liftE $ fromVersion (Just ver) Stack
|
(v, _) <- liftE $ fromVersion (Just ver) Stack
|
||||||
pure v
|
installTool Stack v
|
||||||
pure Toolchain{..}
|
setTool Stack v tmp
|
||||||
|
| otherwise = runLeanRUN leanAppstate $ do
|
||||||
|
case runGHCVer of
|
||||||
|
Just (ToolVersion v) ->
|
||||||
|
setTool GHC v tmp
|
||||||
|
Nothing -> pure ()
|
||||||
|
_ -> fail "Internal error"
|
||||||
|
case runCabalVer of
|
||||||
|
Just (ToolVersion v) ->
|
||||||
|
setTool Cabal v tmp
|
||||||
|
Nothing -> pure ()
|
||||||
|
_ -> fail "Internal error"
|
||||||
|
case runHLSVer of
|
||||||
|
Just (ToolVersion v) ->
|
||||||
|
setTool HLS v tmp
|
||||||
|
Nothing -> pure ()
|
||||||
|
_ -> fail "Internal error"
|
||||||
|
case runStackVer of
|
||||||
|
Just (ToolVersion v) ->
|
||||||
|
setTool Stack v tmp
|
||||||
|
Nothing -> pure ()
|
||||||
|
_ -> fail "Internal error"
|
||||||
|
|
||||||
resolveToolchain = do
|
installTool tool v = do
|
||||||
ghcVer <- case runGHCVer of
|
isInstalled <- checkIfToolInstalled' tool v
|
||||||
Just (ToolVersion v) -> pure $ Just v
|
case tool of
|
||||||
Nothing -> pure Nothing
|
GHC -> do
|
||||||
_ -> fail "Internal error"
|
unless isInstalled $ when (runInstTool' && isNothing (_tvTarget v)) $ void $ liftE $ installGHCBin
|
||||||
cabalVer <- case runCabalVer of
|
(_tvVersion v)
|
||||||
Just (ToolVersion v) -> pure $ Just v
|
Nothing
|
||||||
Nothing -> pure Nothing
|
False
|
||||||
_ -> fail "Internal error"
|
Cabal -> do
|
||||||
hlsVer <- case runHLSVer of
|
unless isInstalled $ when runInstTool' $ void $ liftE $ installCabalBin
|
||||||
Just (ToolVersion v) -> pure $ Just v
|
(_tvVersion v)
|
||||||
Nothing -> pure Nothing
|
Nothing
|
||||||
_ -> fail "Internal error"
|
False
|
||||||
stackVer <- case runStackVer of
|
Stack -> do
|
||||||
Just (ToolVersion v) -> pure $ Just v
|
unless isInstalled $ when runInstTool' $ void $ liftE $ installStackBin
|
||||||
Nothing -> pure Nothing
|
(_tvVersion v)
|
||||||
_ -> fail "Internal error"
|
Nothing
|
||||||
pure Toolchain{..}
|
False
|
||||||
|
HLS -> do
|
||||||
installToolChainFull :: ( MonadFail m
|
unless isInstalled $ when runInstTool' $ void $ liftE $ installHLSBin
|
||||||
, MonadThrow m
|
(_tvVersion v)
|
||||||
, MonadIO m
|
Nothing
|
||||||
, MonadCatch m
|
False
|
||||||
)
|
GHCup -> pure ()
|
||||||
=> Toolchain
|
|
||||||
-> FilePath
|
|
||||||
-> Excepts
|
|
||||||
'[ TagNotFound
|
|
||||||
, NextVerNotFound
|
|
||||||
, NoToolVersionSet
|
|
||||||
, UnknownArchive
|
|
||||||
, TarDirDoesNotExist
|
|
||||||
, ProcessError
|
|
||||||
, NotInstalled
|
|
||||||
, NoDownload
|
|
||||||
, GPGError
|
|
||||||
, DownloadFailed
|
|
||||||
, DirNotEmpty
|
|
||||||
, DigestError
|
|
||||||
, BuildFailed
|
|
||||||
, ArchiveResult
|
|
||||||
, AlreadyInstalled
|
|
||||||
, FileAlreadyExistsError
|
|
||||||
, CopyError
|
|
||||||
] (ResourceT (ReaderT AppState m)) ()
|
|
||||||
installToolChainFull Toolchain{..} tmp = do
|
|
||||||
forM_ [(GHC,) <$> ghcVer, (Cabal,) <$> cabalVer, (HLS,) <$> hlsVer, (Stack,) <$> stackVer] $ \mt -> do
|
|
||||||
isInstalled <- maybe (pure False) (\(tool, v) -> lift $ checkIfToolInstalled' tool v) mt
|
|
||||||
case mt of
|
|
||||||
Just (GHC, v) -> do
|
|
||||||
unless isInstalled $ when (runInstTool' && isNothing (_tvTarget v)) $ void $ liftE $ installGHCBin
|
|
||||||
(_tvVersion v)
|
|
||||||
GHCupInternal
|
|
||||||
False
|
|
||||||
setTool GHC v tmp
|
|
||||||
Just (Cabal, v) -> do
|
|
||||||
unless isInstalled $ when runInstTool' $ void $ liftE $ installCabalBin
|
|
||||||
(_tvVersion v)
|
|
||||||
GHCupInternal
|
|
||||||
False
|
|
||||||
setTool Cabal v tmp
|
|
||||||
Just (Stack, v) -> do
|
|
||||||
unless isInstalled $ when runInstTool' $ void $ liftE $ installStackBin
|
|
||||||
(_tvVersion v)
|
|
||||||
GHCupInternal
|
|
||||||
False
|
|
||||||
setTool Stack v tmp
|
|
||||||
Just (HLS, v) -> do
|
|
||||||
unless isInstalled $ when runInstTool' $ void $ liftE $ installHLSBin
|
|
||||||
(_tvVersion v)
|
|
||||||
GHCupInternal
|
|
||||||
False
|
|
||||||
setTool HLS v tmp
|
|
||||||
_ -> pure ()
|
|
||||||
|
|
||||||
installToolChain :: ( MonadFail m
|
|
||||||
, MonadThrow m
|
|
||||||
, MonadIO m
|
|
||||||
, MonadCatch m
|
|
||||||
)
|
|
||||||
=> Toolchain
|
|
||||||
-> FilePath
|
|
||||||
-> Excepts '[NotInstalled] (ReaderT LeanAppState m) ()
|
|
||||||
installToolChain Toolchain{..} tmp = do
|
|
||||||
forM_ [(GHC,) <$> ghcVer, (Cabal,) <$> cabalVer, (HLS,) <$> hlsVer, (Stack,) <$> stackVer] $ \mt -> do
|
|
||||||
case mt of
|
|
||||||
Just (GHC, v) -> setTool GHC v tmp
|
|
||||||
Just (Cabal, v) -> setTool Cabal v tmp
|
|
||||||
Just (Stack, v) -> setTool Stack v tmp
|
|
||||||
Just (HLS, v) -> setTool HLS v tmp
|
|
||||||
_ -> pure ()
|
|
||||||
|
|
||||||
setTool tool v tmp =
|
setTool tool v tmp =
|
||||||
case tool of
|
case tool of
|
||||||
@@ -411,7 +324,7 @@ run RunOptions{..} runAppState leanAppstate runLogger = do
|
|||||||
if legacy
|
if legacy
|
||||||
then do
|
then do
|
||||||
-- TODO: factor this out
|
-- TODO: factor this out
|
||||||
hlsWrapper <- liftE @_ @'[NotInstalled] $ hlsWrapperBinary v' !? (NotInstalled HLS (mkTVer v'))
|
(Just hlsWrapper) <- hlsWrapperBinary 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 </>))
|
||||||
@@ -433,31 +346,3 @@ run RunOptions{..} runAppState leanAppstate runLogger = do
|
|||||||
envWithNewPath = Map.toList $ Map.insert pathVar newPath envWithoutPath
|
envWithNewPath = Map.toList $ Map.insert pathVar newPath envWithoutPath
|
||||||
liftIO $ setEnv pathVar newPath
|
liftIO $ setEnv pathVar newPath
|
||||||
return envWithNewPath
|
return envWithNewPath
|
||||||
|
|
||||||
predictableTmpDir (Toolchain Nothing Nothing Nothing Nothing) =
|
|
||||||
liftIO (getTemporaryDirectory >>= \tmp -> pure (tmp </> "ghcup-none"))
|
|
||||||
predictableTmpDir Toolchain{..} = do
|
|
||||||
tmp <- getTemporaryDirectory
|
|
||||||
pure $ tmp
|
|
||||||
</> ("ghcup-" <> intercalate "_"
|
|
||||||
( maybe [] ( (:[]) . ("ghc-" <>) . T.unpack . tVerToText) ghcVer
|
|
||||||
<> maybe [] ( (:[]) . ("cabal-" <>) . T.unpack . tVerToText) cabalVer
|
|
||||||
<> maybe [] ( (:[]) . ("hls-" <>) . T.unpack . tVerToText) hlsVer
|
|
||||||
<> maybe [] ( (:[]) . ("stack-" <>) . T.unpack . tVerToText) stackVer
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-------------------------
|
|
||||||
--[ Other local types ]--
|
|
||||||
-------------------------
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
data Toolchain = Toolchain
|
|
||||||
{ ghcVer :: Maybe GHCTargetVersion
|
|
||||||
, cabalVer :: Maybe GHCTargetVersion
|
|
||||||
, hlsVer :: Maybe GHCTargetVersion
|
|
||||||
, stackVer :: Maybe GHCTargetVersion
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
{-# LANGUAGE FlexibleContexts #-}
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
{-# LANGUAGE DuplicateRecordFields #-}
|
{-# LANGUAGE DuplicateRecordFields #-}
|
||||||
{-# LANGUAGE RankNTypes #-}
|
{-# LANGUAGE RankNTypes #-}
|
||||||
{-# LANGUAGE QuasiQuotes #-}
|
|
||||||
|
|
||||||
module GHCup.OptParse.ToolRequirements where
|
module GHCup.OptParse.ToolRequirements where
|
||||||
|
|
||||||
@@ -12,7 +11,6 @@ module GHCup.OptParse.ToolRequirements where
|
|||||||
import GHCup.Errors
|
import GHCup.Errors
|
||||||
import GHCup.Types
|
import GHCup.Types
|
||||||
import GHCup.Utils.Logger
|
import GHCup.Utils.Logger
|
||||||
import GHCup.Utils.String.QQ
|
|
||||||
|
|
||||||
#if !MIN_VERSION_base(4,13,0)
|
#if !MIN_VERSION_base(4,13,0)
|
||||||
import Control.Monad.Fail ( MonadFail )
|
import Control.Monad.Fail ( MonadFail )
|
||||||
@@ -36,41 +34,6 @@ import System.IO
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
---------------
|
|
||||||
--[ Options ]--
|
|
||||||
---------------
|
|
||||||
|
|
||||||
|
|
||||||
data ToolReqOpts = ToolReqOpts
|
|
||||||
{ tlrRaw :: Bool
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
---------------
|
|
||||||
--[ Parsers ]--
|
|
||||||
---------------
|
|
||||||
|
|
||||||
|
|
||||||
toolReqP :: Parser ToolReqOpts
|
|
||||||
toolReqP =
|
|
||||||
ToolReqOpts
|
|
||||||
<$> switch (short 'r' <> long "raw-format" <> help "machine-parsable format")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--------------
|
|
||||||
--[ Footer ]--
|
|
||||||
--------------
|
|
||||||
|
|
||||||
|
|
||||||
toolReqFooter :: String
|
|
||||||
toolReqFooter = [s|Discussion:
|
|
||||||
Print tool requirements on the current platform.
|
|
||||||
If you want to pass this to your package manage, use '--raw-format'.|]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
---------------------------
|
---------------------------
|
||||||
@@ -103,17 +66,14 @@ toolRequirements :: ( Monad m
|
|||||||
, MonadFail m
|
, MonadFail m
|
||||||
, Alternative m
|
, Alternative m
|
||||||
)
|
)
|
||||||
=> ToolReqOpts
|
=> (ReaderT AppState m (VEither ToolRequirementsEffects ()) -> m (VEither ToolRequirementsEffects ()))
|
||||||
-> (ReaderT AppState m (VEither ToolRequirementsEffects ()) -> m (VEither ToolRequirementsEffects ()))
|
|
||||||
-> (ReaderT LeanAppState m () -> m ())
|
-> (ReaderT LeanAppState m () -> m ())
|
||||||
-> m ExitCode
|
-> m ExitCode
|
||||||
toolRequirements ToolReqOpts{..} runAppState runLogger = runToolRequirements runAppState (do
|
toolRequirements runAppState runLogger = runToolRequirements runAppState (do
|
||||||
GHCupInfo { .. } <- lift getGHCupInfo
|
GHCupInfo { .. } <- lift getGHCupInfo
|
||||||
platform' <- liftE getPlatform
|
platform' <- liftE getPlatform
|
||||||
req <- getCommonRequirements platform' _toolRequirements ?? NoToolRequirements
|
req <- getCommonRequirements platform' _toolRequirements ?? NoToolRequirements
|
||||||
if tlrRaw
|
liftIO $ T.hPutStr stdout (prettyRequirements req)
|
||||||
then liftIO $ T.hPutStr stdout (rawRequirements req)
|
|
||||||
else liftIO $ T.hPutStr stdout (prettyRequirements req)
|
|
||||||
)
|
)
|
||||||
>>= \case
|
>>= \case
|
||||||
VRight _ -> pure ExitSuccess
|
VRight _ -> pure ExitSuccess
|
||||||
|
|||||||
@@ -72,7 +72,6 @@ upgradeOptsP =
|
|||||||
str
|
str
|
||||||
(short 't' <> long "target" <> metavar "TARGET_DIR" <> help
|
(short 't' <> long "target" <> metavar "TARGET_DIR" <> help
|
||||||
"Absolute filepath to write ghcup into"
|
"Absolute filepath to write ghcup into"
|
||||||
<> completer (bashCompleter "file")
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
<|> pure UpgradeGHCupDir
|
<|> pure UpgradeGHCupDir
|
||||||
|
|||||||
@@ -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 . (:[]) . Right) optUrlSource
|
urlSource = maybe (fromMaybe (Types.urlSource defaultSettings) uUrlSource) OwnSource 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)
|
||||||
@@ -228,16 +228,14 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
|
|||||||
Nuke -> pure ()
|
Nuke -> pure ()
|
||||||
Whereis _ _ -> pure ()
|
Whereis _ _ -> pure ()
|
||||||
DInfo -> pure ()
|
DInfo -> pure ()
|
||||||
ToolRequirements _ -> pure ()
|
ToolRequirements -> pure ()
|
||||||
ChangeLog _ -> pure ()
|
ChangeLog _ -> pure ()
|
||||||
UnSet _ -> pure ()
|
UnSet _ -> pure ()
|
||||||
#if defined(BRICK)
|
#if defined(BRICK)
|
||||||
Interactive -> pure ()
|
Interactive -> pure ()
|
||||||
#endif
|
#endif
|
||||||
-- check for new tools
|
-- check for new tools
|
||||||
_
|
_ -> lookupEnv "GHCUP_SKIP_UPDATE_CHECK" >>= \case
|
||||||
| Just False <- optVerbose -> pure ()
|
|
||||||
| otherwise -> lookupEnv "GHCUP_SKIP_UPDATE_CHECK" >>= \case
|
|
||||||
Nothing -> void . flip runReaderT s' . runE @'[TagNotFound, NextVerNotFound, NoToolVersionSet] $ do
|
Nothing -> void . flip runReaderT s' . runE @'[TagNotFound, NextVerNotFound, NoToolVersionSet] $ do
|
||||||
newTools <- lift checkForUpdates
|
newTools <- lift checkForUpdates
|
||||||
forM_ newTools $ \newTool@(t, l) -> do
|
forM_ newTools $ \newTool@(t, l) -> do
|
||||||
@@ -310,12 +308,12 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
|
|||||||
#ifndef DISABLE_UPGRADE
|
#ifndef DISABLE_UPGRADE
|
||||||
Upgrade uOpts force' -> upgrade uOpts force' dirs runAppState runLogger
|
Upgrade uOpts force' -> upgrade uOpts force' dirs runAppState runLogger
|
||||||
#endif
|
#endif
|
||||||
ToolRequirements topts -> toolRequirements topts runAppState runLogger
|
ToolRequirements -> toolRequirements runAppState runLogger
|
||||||
ChangeLog changelogOpts -> changelog changelogOpts runAppState runLogger
|
ChangeLog changelogOpts -> changelog changelogOpts runAppState runLogger
|
||||||
Nuke -> nuke appState runLogger
|
Nuke -> nuke appState runLogger
|
||||||
Prefetch pfCom -> prefetch pfCom runAppState runLogger
|
Prefetch pfCom -> prefetch pfCom runAppState runLogger
|
||||||
GC gcOpts -> gc gcOpts runAppState runLogger
|
GC gcOpts -> gc gcOpts runAppState runLogger
|
||||||
Run runCommand -> run runCommand appState leanAppstate runLogger
|
Run runCommand -> run runCommand runAppState leanAppstate runLogger
|
||||||
|
|
||||||
case res of
|
case res of
|
||||||
ExitSuccess -> pure ()
|
ExitSuccess -> pure ()
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ constraints: any.Cabal ==3.6.2.0,
|
|||||||
any.StateVar ==1.2.2,
|
any.StateVar ==1.2.2,
|
||||||
any.abstract-deque ==0.3,
|
any.abstract-deque ==0.3,
|
||||||
abstract-deque -usecas,
|
abstract-deque -usecas,
|
||||||
any.aeson ==2.0.3.0,
|
any.aeson ==2.0.2.0,
|
||||||
aeson -cffi +ordered-keymap,
|
aeson -bytestring-builder -cffi +ordered-keymap,
|
||||||
any.aeson-pretty ==0.8.9,
|
any.aeson-pretty ==0.8.9,
|
||||||
aeson-pretty +lib-only,
|
aeson-pretty +lib-only,
|
||||||
any.alex ==3.2.7.1,
|
any.alex ==3.2.7.1,
|
||||||
@@ -25,14 +25,14 @@ constraints: any.Cabal ==3.6.2.0,
|
|||||||
async -bench,
|
async -bench,
|
||||||
any.atomic-primops ==0.8.4,
|
any.atomic-primops ==0.8.4,
|
||||||
atomic-primops -debug,
|
atomic-primops -debug,
|
||||||
any.attoparsec ==0.14.4,
|
any.attoparsec ==0.13.2.5,
|
||||||
attoparsec -developer,
|
attoparsec -developer,
|
||||||
any.base ==4.14.3.0,
|
any.base ==4.14.3.0,
|
||||||
any.base-compat ==0.12.1,
|
any.base-compat ==0.12.1,
|
||||||
any.base-compat-batteries ==0.12.1,
|
any.base-compat-batteries ==0.12.1,
|
||||||
any.base-orphans ==0.8.6,
|
any.base-orphans ==0.8.6,
|
||||||
any.base16-bytestring ==1.0.2.0,
|
any.base16-bytestring ==1.0.2.0,
|
||||||
any.base64-bytestring ==1.2.1.0,
|
any.base64-bytestring ==1.1.0.0,
|
||||||
any.bifunctors ==5.5.11,
|
any.bifunctors ==5.5.11,
|
||||||
bifunctors +semigroups +tagged,
|
bifunctors +semigroups +tagged,
|
||||||
any.binary ==0.8.8.0,
|
any.binary ==0.8.8.0,
|
||||||
@@ -69,7 +69,7 @@ constraints: any.Cabal ==3.6.2.0,
|
|||||||
any.cryptohash-sha1 ==0.11.101.0,
|
any.cryptohash-sha1 ==0.11.101.0,
|
||||||
any.cryptohash-sha256 ==0.11.102.1,
|
any.cryptohash-sha256 ==0.11.102.1,
|
||||||
cryptohash-sha256 -exe +use-cbits,
|
cryptohash-sha256 -exe +use-cbits,
|
||||||
any.data-clist ==0.2,
|
any.data-clist ==0.1.2.3,
|
||||||
any.data-fix ==0.3.2,
|
any.data-fix ==0.3.2,
|
||||||
any.deepseq ==1.4.4.0,
|
any.deepseq ==1.4.4.0,
|
||||||
any.directory ==1.3.6.0,
|
any.directory ==1.3.6.0,
|
||||||
@@ -82,14 +82,10 @@ constraints: any.Cabal ==3.6.2.0,
|
|||||||
any.filepath ==1.4.2.1,
|
any.filepath ==1.4.2.1,
|
||||||
any.free ==5.1.7,
|
any.free ==5.1.7,
|
||||||
any.fusion-plugin-types ==0.1.0,
|
any.fusion-plugin-types ==0.1.0,
|
||||||
any.generic-arbitrary ==0.2.0,
|
any.generic-arbitrary ==0.1.0,
|
||||||
any.ghc ==8.10.7,
|
|
||||||
any.ghc-boot ==8.10.7,
|
|
||||||
any.ghc-boot-th ==8.10.7,
|
any.ghc-boot-th ==8.10.7,
|
||||||
any.ghc-byteorder ==4.11.0.0.10,
|
any.ghc-byteorder ==4.11.0.0.10,
|
||||||
any.ghc-heap ==8.10.7,
|
|
||||||
any.ghc-prim ==0.6.1,
|
any.ghc-prim ==0.6.1,
|
||||||
any.ghci ==8.10.7,
|
|
||||||
any.happy ==1.20.0,
|
any.happy ==1.20.0,
|
||||||
any.hashable ==1.4.0.2,
|
any.hashable ==1.4.0.2,
|
||||||
hashable +containers +integer-gmp -random-initial-seed,
|
hashable +containers +integer-gmp -random-initial-seed,
|
||||||
@@ -97,12 +93,11 @@ constraints: any.Cabal ==3.6.2.0,
|
|||||||
any.haskus-utils-types ==1.5.1,
|
any.haskus-utils-types ==1.5.1,
|
||||||
any.haskus-utils-variant ==3.2.1,
|
any.haskus-utils-variant ==3.2.1,
|
||||||
any.heaps ==0.4,
|
any.heaps ==0.4,
|
||||||
any.hpc ==0.6.1.0,
|
|
||||||
any.hsc2hs ==0.68.8,
|
any.hsc2hs ==0.68.8,
|
||||||
hsc2hs -in-ghc-tree,
|
hsc2hs -in-ghc-tree,
|
||||||
any.hspec ==2.9.4,
|
any.hspec ==2.7.10,
|
||||||
any.hspec-core ==2.9.4,
|
any.hspec-core ==2.7.10,
|
||||||
any.hspec-discover ==2.9.4,
|
any.hspec-discover ==2.7.10,
|
||||||
any.hspec-expectations ==0.8.2,
|
any.hspec-expectations ==0.8.2,
|
||||||
any.hspec-golden-aeson ==0.9.0.0,
|
any.hspec-golden-aeson ==0.9.0.0,
|
||||||
any.http-io-streams ==0.1.6.0,
|
any.http-io-streams ==0.1.6.0,
|
||||||
@@ -123,7 +118,7 @@ constraints: any.Cabal ==3.6.2.0,
|
|||||||
libyaml-streamly -no-unicode -system-libyaml,
|
libyaml-streamly -no-unicode -system-libyaml,
|
||||||
any.lockfree-queue ==0.2.3.1,
|
any.lockfree-queue ==0.2.3.1,
|
||||||
any.lzma-static ==5.2.5.4,
|
any.lzma-static ==5.2.5.4,
|
||||||
any.megaparsec ==9.2.0,
|
any.megaparsec ==9.0.1,
|
||||||
megaparsec -dev,
|
megaparsec -dev,
|
||||||
any.microlens ==0.4.12.0,
|
any.microlens ==0.4.12.0,
|
||||||
any.microlens-mtl ==0.2.0.1,
|
any.microlens-mtl ==0.2.0.1,
|
||||||
@@ -139,7 +134,7 @@ constraints: any.Cabal ==3.6.2.0,
|
|||||||
optics-core -explicit-generic-labels,
|
optics-core -explicit-generic-labels,
|
||||||
any.optics-extra ==0.4,
|
any.optics-extra ==0.4,
|
||||||
any.optics-th ==0.4,
|
any.optics-th ==0.4,
|
||||||
any.optparse-applicative ==0.17.0.0,
|
any.optparse-applicative ==0.16.1.0,
|
||||||
optparse-applicative +process,
|
optparse-applicative +process,
|
||||||
any.os-release ==1.0.2.1,
|
any.os-release ==1.0.2.1,
|
||||||
os-release -devel,
|
os-release -devel,
|
||||||
@@ -178,14 +173,13 @@ constraints: any.Cabal ==3.6.2.0,
|
|||||||
any.splitmix ==0.1.0.4,
|
any.splitmix ==0.1.0.4,
|
||||||
splitmix -optimised-mixer,
|
splitmix -optimised-mixer,
|
||||||
any.stm ==2.5.0.1,
|
any.stm ==2.5.0.1,
|
||||||
any.streamly ==0.8.2,
|
any.streamly ==0.8.1.1,
|
||||||
streamly -debug -dev -fusion-plugin -has-llvm -inspection -limit-build-mem -no-fusion +opt -streamk -streamly-core -use-c-malloc -use-unliftio,
|
streamly -debug -dev -fusion-plugin -has-llvm -inspection -limit-build-mem -no-fusion +opt -streamk -use-c-malloc,
|
||||||
any.strict ==0.4.0.1,
|
any.strict ==0.4.0.1,
|
||||||
strict +assoc,
|
strict +assoc,
|
||||||
any.strict-base ==0.4.0.0,
|
any.strict-base ==0.4.0.0,
|
||||||
any.tagged ==0.8.6.1,
|
any.tagged ==0.8.6.1,
|
||||||
tagged +deepseq +transformers,
|
tagged +deepseq +transformers,
|
||||||
any.tagsoup ==0.14.8,
|
|
||||||
any.template-haskell ==2.16.0.0,
|
any.template-haskell ==2.16.0.0,
|
||||||
any.temporary ==1.3,
|
any.temporary ==1.3,
|
||||||
any.terminal-progress-bar ==0.4.1,
|
any.terminal-progress-bar ==0.4.1,
|
||||||
@@ -217,7 +211,7 @@ constraints: any.Cabal ==3.6.2.0,
|
|||||||
any.unix-compat ==0.5.4,
|
any.unix-compat ==0.5.4,
|
||||||
unix-compat -old-time,
|
unix-compat -old-time,
|
||||||
any.unliftio-core ==0.2.0.1,
|
any.unliftio-core ==0.2.0.1,
|
||||||
any.unordered-containers ==0.2.17.0,
|
any.unordered-containers ==0.2.16.0,
|
||||||
unordered-containers -debug,
|
unordered-containers -debug,
|
||||||
any.uri-bytestring ==0.3.3.1,
|
any.uri-bytestring ==0.3.3.1,
|
||||||
uri-bytestring -lib-werror,
|
uri-bytestring -lib-werror,
|
||||||
@@ -225,15 +219,15 @@ constraints: any.Cabal ==3.6.2.0,
|
|||||||
any.uuid-types ==1.0.5,
|
any.uuid-types ==1.0.5,
|
||||||
any.vector ==0.12.3.1,
|
any.vector ==0.12.3.1,
|
||||||
vector +boundschecks -internalchecks -unsafechecks -wall,
|
vector +boundschecks -internalchecks -unsafechecks -wall,
|
||||||
any.versions ==5.0.3,
|
any.versions ==5.0.2,
|
||||||
any.vty ==5.33,
|
any.vty ==5.33,
|
||||||
any.witherable ==0.4.2,
|
any.witherable ==0.4.2,
|
||||||
any.word-wrap ==0.5,
|
any.word-wrap ==0.5,
|
||||||
any.word8 ==0.1.3,
|
any.word8 ==0.1.3,
|
||||||
any.xor ==0.0.1.1,
|
any.xor ==0.0.1.0,
|
||||||
any.yaml-streamly ==0.12.1,
|
any.yaml-streamly ==0.12.1,
|
||||||
yaml-streamly +no-examples +no-exe,
|
yaml-streamly +no-examples +no-exe,
|
||||||
any.zlib ==0.6.2.3,
|
any.zlib ==0.6.2.3,
|
||||||
zlib -bundled-c-zlib -non-blocking-ffi -pkg-config,
|
zlib -bundled-c-zlib -non-blocking-ffi -pkg-config,
|
||||||
any.zlib-bindings ==0.1.1.5
|
any.zlib-bindings ==0.1.1.5
|
||||||
index-state: hackage.haskell.org 2022-03-15T16:43:02Z
|
index-state: hackage.haskell.org 2022-02-15T12:16:42Z
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ constraints: any.Cabal ==3.6.2.0,
|
|||||||
any.StateVar ==1.2.2,
|
any.StateVar ==1.2.2,
|
||||||
any.abstract-deque ==0.3,
|
any.abstract-deque ==0.3,
|
||||||
abstract-deque -usecas,
|
abstract-deque -usecas,
|
||||||
any.aeson ==2.0.3.0,
|
any.aeson ==2.0.2.0,
|
||||||
aeson -cffi +ordered-keymap,
|
aeson -bytestring-builder -cffi +ordered-keymap,
|
||||||
any.aeson-pretty ==0.8.9,
|
any.aeson-pretty ==0.8.9,
|
||||||
aeson-pretty +lib-only,
|
aeson-pretty +lib-only,
|
||||||
any.alex ==3.2.7.1,
|
any.alex ==3.2.7.1,
|
||||||
@@ -25,14 +25,14 @@ constraints: any.Cabal ==3.6.2.0,
|
|||||||
async -bench,
|
async -bench,
|
||||||
any.atomic-primops ==0.8.4,
|
any.atomic-primops ==0.8.4,
|
||||||
atomic-primops -debug,
|
atomic-primops -debug,
|
||||||
any.attoparsec ==0.14.4,
|
any.attoparsec ==0.13.2.5,
|
||||||
attoparsec -developer,
|
attoparsec -developer,
|
||||||
any.base ==4.15.1.0,
|
any.base ==4.15.1.0,
|
||||||
any.base-compat ==0.12.1,
|
any.base-compat ==0.12.1,
|
||||||
any.base-compat-batteries ==0.12.1,
|
any.base-compat-batteries ==0.12.1,
|
||||||
any.base-orphans ==0.8.6,
|
any.base-orphans ==0.8.6,
|
||||||
any.base16-bytestring ==1.0.2.0,
|
any.base16-bytestring ==1.0.2.0,
|
||||||
any.base64-bytestring ==1.2.1.0,
|
any.base64-bytestring ==1.1.0.0,
|
||||||
any.bifunctors ==5.5.11,
|
any.bifunctors ==5.5.11,
|
||||||
bifunctors +semigroups +tagged,
|
bifunctors +semigroups +tagged,
|
||||||
any.binary ==0.8.8.0,
|
any.binary ==0.8.8.0,
|
||||||
@@ -69,7 +69,7 @@ constraints: any.Cabal ==3.6.2.0,
|
|||||||
any.cryptohash-sha1 ==0.11.101.0,
|
any.cryptohash-sha1 ==0.11.101.0,
|
||||||
any.cryptohash-sha256 ==0.11.102.1,
|
any.cryptohash-sha256 ==0.11.102.1,
|
||||||
cryptohash-sha256 -exe +use-cbits,
|
cryptohash-sha256 -exe +use-cbits,
|
||||||
any.data-clist ==0.2,
|
any.data-clist ==0.1.2.3,
|
||||||
any.data-fix ==0.3.2,
|
any.data-fix ==0.3.2,
|
||||||
any.deepseq ==1.4.5.0,
|
any.deepseq ==1.4.5.0,
|
||||||
any.directory ==1.3.6.2,
|
any.directory ==1.3.6.2,
|
||||||
@@ -82,15 +82,11 @@ constraints: any.Cabal ==3.6.2.0,
|
|||||||
any.filepath ==1.4.2.1,
|
any.filepath ==1.4.2.1,
|
||||||
any.free ==5.1.7,
|
any.free ==5.1.7,
|
||||||
any.fusion-plugin-types ==0.1.0,
|
any.fusion-plugin-types ==0.1.0,
|
||||||
any.generic-arbitrary ==0.2.0,
|
any.generic-arbitrary ==0.1.0,
|
||||||
any.ghc ==9.0.2,
|
|
||||||
any.ghc-bignum ==1.1,
|
any.ghc-bignum ==1.1,
|
||||||
any.ghc-boot ==9.0.2,
|
|
||||||
any.ghc-boot-th ==9.0.2,
|
any.ghc-boot-th ==9.0.2,
|
||||||
any.ghc-byteorder ==4.11.0.0.10,
|
any.ghc-byteorder ==4.11.0.0.10,
|
||||||
any.ghc-heap ==9.0.2,
|
|
||||||
any.ghc-prim ==0.7.0,
|
any.ghc-prim ==0.7.0,
|
||||||
any.ghci ==9.0.2,
|
|
||||||
any.happy ==1.20.0,
|
any.happy ==1.20.0,
|
||||||
any.hashable ==1.4.0.2,
|
any.hashable ==1.4.0.2,
|
||||||
hashable +containers +integer-gmp -random-initial-seed,
|
hashable +containers +integer-gmp -random-initial-seed,
|
||||||
@@ -98,12 +94,11 @@ constraints: any.Cabal ==3.6.2.0,
|
|||||||
any.haskus-utils-types ==1.5.1,
|
any.haskus-utils-types ==1.5.1,
|
||||||
any.haskus-utils-variant ==3.2.1,
|
any.haskus-utils-variant ==3.2.1,
|
||||||
any.heaps ==0.4,
|
any.heaps ==0.4,
|
||||||
any.hpc ==0.6.1.0,
|
|
||||||
any.hsc2hs ==0.68.8,
|
any.hsc2hs ==0.68.8,
|
||||||
hsc2hs -in-ghc-tree,
|
hsc2hs -in-ghc-tree,
|
||||||
any.hspec ==2.9.4,
|
any.hspec ==2.7.10,
|
||||||
any.hspec-core ==2.9.4,
|
any.hspec-core ==2.7.10,
|
||||||
any.hspec-discover ==2.9.4,
|
any.hspec-discover ==2.7.10,
|
||||||
any.hspec-expectations ==0.8.2,
|
any.hspec-expectations ==0.8.2,
|
||||||
any.hspec-golden-aeson ==0.9.0.0,
|
any.hspec-golden-aeson ==0.9.0.0,
|
||||||
any.http-io-streams ==0.1.6.0,
|
any.http-io-streams ==0.1.6.0,
|
||||||
@@ -123,7 +118,7 @@ constraints: any.Cabal ==3.6.2.0,
|
|||||||
libyaml-streamly -no-unicode -system-libyaml,
|
libyaml-streamly -no-unicode -system-libyaml,
|
||||||
any.lockfree-queue ==0.2.3.1,
|
any.lockfree-queue ==0.2.3.1,
|
||||||
any.lzma-static ==5.2.5.4,
|
any.lzma-static ==5.2.5.4,
|
||||||
any.megaparsec ==9.2.0,
|
any.megaparsec ==9.0.1,
|
||||||
megaparsec -dev,
|
megaparsec -dev,
|
||||||
any.microlens ==0.4.12.0,
|
any.microlens ==0.4.12.0,
|
||||||
any.microlens-mtl ==0.2.0.1,
|
any.microlens-mtl ==0.2.0.1,
|
||||||
@@ -139,7 +134,7 @@ constraints: any.Cabal ==3.6.2.0,
|
|||||||
optics-core -explicit-generic-labels,
|
optics-core -explicit-generic-labels,
|
||||||
any.optics-extra ==0.4,
|
any.optics-extra ==0.4,
|
||||||
any.optics-th ==0.4,
|
any.optics-th ==0.4,
|
||||||
any.optparse-applicative ==0.17.0.0,
|
any.optparse-applicative ==0.16.1.0,
|
||||||
optparse-applicative +process,
|
optparse-applicative +process,
|
||||||
any.os-release ==1.0.2.1,
|
any.os-release ==1.0.2.1,
|
||||||
os-release -devel,
|
os-release -devel,
|
||||||
@@ -178,14 +173,13 @@ constraints: any.Cabal ==3.6.2.0,
|
|||||||
any.splitmix ==0.1.0.4,
|
any.splitmix ==0.1.0.4,
|
||||||
splitmix -optimised-mixer,
|
splitmix -optimised-mixer,
|
||||||
any.stm ==2.5.0.0,
|
any.stm ==2.5.0.0,
|
||||||
any.streamly ==0.8.2,
|
any.streamly ==0.8.1.1,
|
||||||
streamly -debug -dev -fusion-plugin -has-llvm -inspection -limit-build-mem -no-fusion +opt -streamk -streamly-core -use-c-malloc -use-unliftio,
|
streamly -debug -dev -fusion-plugin -has-llvm -inspection -limit-build-mem -no-fusion +opt -streamk -use-c-malloc,
|
||||||
any.strict ==0.4.0.1,
|
any.strict ==0.4.0.1,
|
||||||
strict +assoc,
|
strict +assoc,
|
||||||
any.strict-base ==0.4.0.0,
|
any.strict-base ==0.4.0.0,
|
||||||
any.tagged ==0.8.6.1,
|
any.tagged ==0.8.6.1,
|
||||||
tagged +deepseq +transformers,
|
tagged +deepseq +transformers,
|
||||||
any.tagsoup ==0.14.8,
|
|
||||||
any.template-haskell ==2.17.0.0,
|
any.template-haskell ==2.17.0.0,
|
||||||
any.temporary ==1.3,
|
any.temporary ==1.3,
|
||||||
any.terminal-progress-bar ==0.4.1,
|
any.terminal-progress-bar ==0.4.1,
|
||||||
@@ -217,7 +211,7 @@ constraints: any.Cabal ==3.6.2.0,
|
|||||||
any.unix-compat ==0.5.4,
|
any.unix-compat ==0.5.4,
|
||||||
unix-compat -old-time,
|
unix-compat -old-time,
|
||||||
any.unliftio-core ==0.2.0.1,
|
any.unliftio-core ==0.2.0.1,
|
||||||
any.unordered-containers ==0.2.17.0,
|
any.unordered-containers ==0.2.16.0,
|
||||||
unordered-containers -debug,
|
unordered-containers -debug,
|
||||||
any.uri-bytestring ==0.3.3.1,
|
any.uri-bytestring ==0.3.3.1,
|
||||||
uri-bytestring -lib-werror,
|
uri-bytestring -lib-werror,
|
||||||
@@ -225,15 +219,15 @@ constraints: any.Cabal ==3.6.2.0,
|
|||||||
any.uuid-types ==1.0.5,
|
any.uuid-types ==1.0.5,
|
||||||
any.vector ==0.12.3.1,
|
any.vector ==0.12.3.1,
|
||||||
vector +boundschecks -internalchecks -unsafechecks -wall,
|
vector +boundschecks -internalchecks -unsafechecks -wall,
|
||||||
any.versions ==5.0.3,
|
any.versions ==5.0.2,
|
||||||
any.vty ==5.33,
|
any.vty ==5.33,
|
||||||
any.witherable ==0.4.2,
|
any.witherable ==0.4.2,
|
||||||
any.word-wrap ==0.5,
|
any.word-wrap ==0.5,
|
||||||
any.word8 ==0.1.3,
|
any.word8 ==0.1.3,
|
||||||
any.xor ==0.0.1.1,
|
any.xor ==0.0.1.0,
|
||||||
any.yaml-streamly ==0.12.1,
|
any.yaml-streamly ==0.12.1,
|
||||||
yaml-streamly +no-examples +no-exe,
|
yaml-streamly +no-examples +no-exe,
|
||||||
any.zlib ==0.6.2.3,
|
any.zlib ==0.6.2.3,
|
||||||
zlib -bundled-c-zlib -non-blocking-ffi -pkg-config,
|
zlib -bundled-c-zlib -non-blocking-ffi -pkg-config,
|
||||||
any.zlib-bindings ==0.1.1.5
|
any.zlib-bindings ==0.1.1.5
|
||||||
index-state: hackage.haskell.org 2022-03-15T16:43:02Z
|
index-state: hackage.haskell.org 2022-02-15T12:16:42Z
|
||||||
|
|||||||
@@ -15,9 +15,7 @@ source-repository-package
|
|||||||
|
|
||||||
constraints: http-io-streams -brotli,
|
constraints: http-io-streams -brotli,
|
||||||
any.Cabal ==3.6.2.0,
|
any.Cabal ==3.6.2.0,
|
||||||
any.aeson >= 2.0.1.0,
|
any.aeson >= 2.0.1.0
|
||||||
-- https://github.com/typeable/generic-arbitrary/issues/14
|
|
||||||
any.generic-arbitrary < 0.2.1
|
|
||||||
|
|
||||||
package libarchive
|
package libarchive
|
||||||
flags: -system-libarchive
|
flags: -system-libarchive
|
||||||
|
|||||||
@@ -48,16 +48,12 @@ 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:
|
||||||
# globalTools: {}
|
# toolRequirements: {} # this is ignored
|
||||||
# toolRequirements: {}
|
|
||||||
# ghcupDownloads:
|
# ghcupDownloads:
|
||||||
# GHC:
|
# GHC:
|
||||||
# 9.10.2:
|
# 9.10.2:
|
||||||
@@ -70,8 +66,6 @@ url-source:
|
|||||||
# dlSubdir: ghc-7.10.3
|
# dlSubdir: ghc-7.10.3
|
||||||
# dlHash: 01cfbad8dff1e8b34a5fdca8caeaf843b56e36af919e29cd68870d2588563db5
|
# dlHash: 01cfbad8dff1e8b34a5fdca8caeaf843b56e36af919e29cd68870d2588563db5
|
||||||
|
|
||||||
## Example 3: Add multiple custom download files to the default downloads via right-biased merge (overwriting duplicate
|
## Example 3: Add a custom download file to the default downloads, overwriting duplicate versions
|
||||||
## versions).
|
|
||||||
# AddSource:
|
# AddSource:
|
||||||
# - Right: "file:///home/jule/git/ghcup-hs/ghcup-prereleases.yaml"
|
# Right: "file:///home/jule/git/ghcup-hs/ghcup-custom.yaml"
|
||||||
# - Right: "file:///home/jule/git/ghcup-hs/ghcup-custom.yaml"
|
|
||||||
|
|||||||
Submodule data/metadata updated: 6fae2f7bc2...b1d0995221
@@ -1,8 +1,5 @@
|
|||||||
: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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,12 +108,12 @@ body.homepage>div.container div.col-md-9 {
|
|||||||
|
|
||||||
.bg-primary {
|
.bg-primary {
|
||||||
background-image: none;
|
background-image: none;
|
||||||
background-color: var(--ukraine-top) !important;
|
background-color: var(--theme-purple) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
body .bg-primary {
|
body .bg-primary {
|
||||||
background-image: none;
|
background-image: none;
|
||||||
background-color: var(--ukraine-top);
|
background-color: var(--theme-purple);
|
||||||
border: 0px;
|
border: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,8 +125,8 @@ body .btn-primary {
|
|||||||
|
|
||||||
.navbar.fixed-top {
|
.navbar.fixed-top {
|
||||||
background-image: none;
|
background-image: none;
|
||||||
background-color: var(--ukraine-top);
|
background-color: var(--theme-purple);
|
||||||
border-bottom: 40px solid var(--ukraine-bottom);
|
border-bottom: 5px solid rgba(69, 59, 97, 0.5);
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
201
docs/guide.md
201
docs/guide.md
@@ -1,6 +1,6 @@
|
|||||||
# User Guide
|
# User Guide
|
||||||
|
|
||||||
This is a more in-depth guide specific to GHCup. `ghcup --help` is your friend.
|
`ghcup --help` is your friend.
|
||||||
|
|
||||||
## Basic usage
|
## Basic usage
|
||||||
|
|
||||||
@@ -43,6 +43,13 @@ All of the following are valid arguments to `ghcup install ghc`:
|
|||||||
|
|
||||||
If the argument is omitted, the default is `recommended`.
|
If the argument is omitted, the default is `recommended`.
|
||||||
|
|
||||||
|
## 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](https://gitlab.haskell.org/haskell/ghcup-hs/-/blob/master/data/config.yaml).
|
||||||
|
|
||||||
|
Partial configuration is fine. Command line options always override the config file settings.
|
||||||
|
|
||||||
## Manpages
|
## 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.
|
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.
|
||||||
@@ -57,40 +64,6 @@ as e.g. `/etc/bash_completion.d/ghcup` (depending on distro)
|
|||||||
and make sure your bashrc sources the startup script
|
and make sure your bashrc sources the startup script
|
||||||
(`/usr/share/bash-completion/bash_completion` on some distros).
|
(`/usr/share/bash-completion/bash_completion` on some distros).
|
||||||
|
|
||||||
# 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](https://gitlab.haskell.org/haskell/ghcup-hs/-/blob/master/data/config.yaml).
|
|
||||||
|
|
||||||
Partial configuration is fine. Command line options always override the config file settings.
|
|
||||||
|
|
||||||
## Env variables
|
|
||||||
|
|
||||||
This is the complete list of env variables that change GHCup behavior:
|
|
||||||
|
|
||||||
* `GHCUP_USE_XDG_DIRS`: see [XDG support](#xdg-support) above
|
|
||||||
* `TMPDIR`: where ghcup does the work (unpacking, building, ...)
|
|
||||||
* `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
|
|
||||||
|
|
||||||
### XDG support
|
|
||||||
|
|
||||||
To enable XDG style directories, set the environment variable `GHCUP_USE_XDG_DIRS` to anything.
|
|
||||||
|
|
||||||
Then you can control the locations via XDG environment variables as such:
|
|
||||||
|
|
||||||
* `XDG_DATA_HOME`: GHCs will be unpacked in `ghcup/ghc` subdir (default: `~/.local/share`)
|
|
||||||
* `XDG_CACHE_HOME`: logs and download files will be stored in `ghcup` subdir (default: `~/.cache`)
|
|
||||||
* `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.**
|
|
||||||
|
|
||||||
## Caching
|
## Caching
|
||||||
|
|
||||||
GHCup has a few caching mechanisms to avoid redownloads. All cached files end up in `~/.ghcup/cache` by default.
|
GHCup has a few caching mechanisms to avoid redownloads. All cached files end up in `~/.ghcup/cache` by default.
|
||||||
@@ -110,92 +83,6 @@ have a 5 minutes cache per default depending on the last access time of the file
|
|||||||
|
|
||||||
If you experience problems, consider clearing the cache via `ghcup gc --cache`.
|
If you experience problems, consider clearing the cache via `ghcup gc --cache`.
|
||||||
|
|
||||||
## Metadata
|
|
||||||
|
|
||||||
The metadata are the files that describe tool versions, where to download them etc. and
|
|
||||||
can be viewed here: [https://github.com/haskell/ghcup-metadata](https://github.com/haskell/ghcup-metadata)
|
|
||||||
|
|
||||||
### Mirrors
|
|
||||||
|
|
||||||
GHCup allows to use custom mirrors/download-info hosted by yourself or 3rd parties.
|
|
||||||
|
|
||||||
To use a mirror, set the following option in `~/.ghcup/config.yaml`:
|
|
||||||
|
|
||||||
```yml
|
|
||||||
url-source:
|
|
||||||
# Accepts file/http/https scheme
|
|
||||||
OwnSource: "https://some-url/ghcup-0.0.6.yaml"
|
|
||||||
```
|
|
||||||
|
|
||||||
See [config.yaml](https://gitlab.haskell.org/haskell/ghcup-hs/-/blob/master/data/config.yaml)
|
|
||||||
for more options.
|
|
||||||
|
|
||||||
Alternatively you can do it via a cli switch:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
ghcup --url-source=https://some-url/ghcup-0.0.6.yaml list
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Known mirrors
|
|
||||||
|
|
||||||
1. [https://mirror.sjtu.edu.cn/docs/ghcup](https://mirror.sjtu.edu.cn/docs/ghcup)
|
|
||||||
|
|
||||||
### (Pre-)Release channels
|
|
||||||
|
|
||||||
A release channel is basically just a metadata file location. You can add additional release
|
|
||||||
channels that complement the default one, such as the **prerelease channel** like so:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
ghcup config add-release-channel https://raw.githubusercontent.com/haskell/ghcup-metadata/master/ghcup-prereleases-0.0.7.yaml
|
|
||||||
```
|
|
||||||
|
|
||||||
This will result in `~/.ghcup/config.yaml` to contain this record:
|
|
||||||
|
|
||||||
```yml
|
|
||||||
url-source:
|
|
||||||
AddSource:
|
|
||||||
- Right: https://raw.githubusercontent.com/haskell/ghcup-metadata/master/ghcup-prereleases-0.0.7.yaml
|
|
||||||
```
|
|
||||||
|
|
||||||
You can add as many channels as you like. They are combined under *Last*, so versions from the prerelease channel
|
|
||||||
here overwrite the default ones, if any.
|
|
||||||
|
|
||||||
To remove the channel, delete the entire `url-source` section or set it back to the default:
|
|
||||||
|
|
||||||
```yml
|
|
||||||
url-source:
|
|
||||||
GHCupURL: []
|
|
||||||
```
|
|
||||||
|
|
||||||
If you want to combine your release channel with a mirror, you'd do it like so:
|
|
||||||
|
|
||||||
```yml
|
|
||||||
url-source:
|
|
||||||
OwnSource:
|
|
||||||
# base metadata
|
|
||||||
- "https://mirror.sjtu.edu.cn/ghcup/yaml/ghcup/data/ghcup-0.0.6.yaml"
|
|
||||||
# prerelease channel
|
|
||||||
- "https://raw.githubusercontent.com/haskell/ghcup-metadata/master/ghcup-prereleases-0.0.7.yaml"
|
|
||||||
```
|
|
||||||
|
|
||||||
# More on installation
|
|
||||||
|
|
||||||
## Installing custom bindists
|
|
||||||
|
|
||||||
There are a couple of good use cases to install custom bindists:
|
|
||||||
|
|
||||||
1. manually built bindists (e.g. with patches)
|
|
||||||
- example: `ghcup install ghc -u 'file:///home/mearwald/tmp/ghc-eff-patches/ghc-8.10.2-x86_64-deb10-linux.tar.xz' 8.10.2-eff`
|
|
||||||
2. GHC head CI bindists
|
|
||||||
- example: `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`
|
|
||||||
3. DWARF bindists
|
|
||||||
- example: `ghcup install ghc -u 'https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-x86_64-deb10-linux-dwarf.tar.xz' 8.10.2-dwarf`
|
|
||||||
|
|
||||||
Since the version parser is pretty lax, `8.10.2-eff` and `head` are both valid versions
|
|
||||||
and produce the binaries `ghc-8.10.2-eff` and `ghc-head` respectively.
|
|
||||||
GHCup always needs to know which version the bindist corresponds to (this is not automatically
|
|
||||||
detected).
|
|
||||||
|
|
||||||
## Compiling GHC from source
|
## Compiling GHC from source
|
||||||
|
|
||||||
Compiling from source is supported for both source tarballs and arbitrary git refs. See `ghcup compile ghc --help`
|
Compiling from source is supported for both source tarballs and arbitrary git refs. See `ghcup compile ghc --help`
|
||||||
@@ -219,6 +106,74 @@ For distributions with non-standard locations of cross toolchain and
|
|||||||
libraries, this may need some tweaking of `build.mk` or configure args.
|
libraries, this may need some tweaking of `build.mk` or configure args.
|
||||||
See `ghcup compile ghc --help` for further information.
|
See `ghcup compile ghc --help` for further information.
|
||||||
|
|
||||||
|
## XDG support
|
||||||
|
|
||||||
|
To enable XDG style directories, set the environment variable `GHCUP_USE_XDG_DIRS` to anything.
|
||||||
|
|
||||||
|
Then you can control the locations via XDG environment variables as such:
|
||||||
|
|
||||||
|
* `XDG_DATA_HOME`: GHCs will be unpacked in `ghcup/ghc` subdir (default: `~/.local/share`)
|
||||||
|
* `XDG_CACHE_HOME`: logs and download files will be stored in `ghcup` subdir (default: `~/.cache`)
|
||||||
|
* `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:
|
||||||
|
|
||||||
|
* `GHCUP_USE_XDG_DIRS`: see [XDG support](#xdg-support) above
|
||||||
|
* `TMPDIR`: where ghcup does the work (unpacking, building, ...)
|
||||||
|
* `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
|
||||||
|
|
||||||
|
There are a couple of good use cases to install custom bindists:
|
||||||
|
|
||||||
|
1. manually built bindists (e.g. with patches)
|
||||||
|
- example: `ghcup install ghc -u 'file:///home/mearwald/tmp/ghc-eff-patches/ghc-8.10.2-x86_64-deb10-linux.tar.xz' 8.10.2-eff`
|
||||||
|
2. GHC head CI bindists
|
||||||
|
- example: `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`
|
||||||
|
3. DWARF bindists
|
||||||
|
- example: `ghcup install ghc -u 'https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-x86_64-deb10-linux-dwarf.tar.xz' 8.10.2-dwarf`
|
||||||
|
|
||||||
|
Since the version parser is pretty lax, `8.10.2-eff` and `head` are both valid versions
|
||||||
|
and produce the binaries `ghc-8.10.2-eff` and `ghc-head` respectively.
|
||||||
|
GHCup always needs to know which version the bindist corresponds to (this is not automatically
|
||||||
|
detected).
|
||||||
|
|
||||||
|
## Mirrors
|
||||||
|
|
||||||
|
GHCup allows to use custom mirrors/download-info hosted by yourself or 3rd parties.
|
||||||
|
|
||||||
|
To use a mirror, set the following option in `~/.ghcup/config.yaml`:
|
||||||
|
|
||||||
|
```yml
|
||||||
|
url-source:
|
||||||
|
# Accepts file/http/https scheme
|
||||||
|
OwnSource: "https://some-url/ghcup-0.0.6.yaml"
|
||||||
|
```
|
||||||
|
|
||||||
|
See [config.yaml](https://gitlab.haskell.org/haskell/ghcup-hs/-/blob/master/data/config.yaml)
|
||||||
|
for more options.
|
||||||
|
|
||||||
|
Alternatively you can do it via a cli switch:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
ghcup --url-source=https://some-url/ghcup-0.0.6.yaml list
|
||||||
|
```
|
||||||
|
|
||||||
|
### Known mirrors
|
||||||
|
|
||||||
|
1. [https://mirror.sjtu.edu.cn/docs/ghcup](https://mirror.sjtu.edu.cn/docs/ghcup)
|
||||||
|
|
||||||
## Isolated installs
|
## Isolated installs
|
||||||
|
|
||||||
Ghcup also enables you to install a tool (GHC, Cabal, HLS, Stack) at an isolated location of your choosing.
|
Ghcup also enables you to install a tool (GHC, Cabal, HLS, Stack) at an isolated location of your choosing.
|
||||||
@@ -302,9 +257,9 @@ gpg-setting: GPGLax # GPGStrict | GPGLax | GPGNone
|
|||||||
In `GPGStrict` mode, ghcup will fail if verification fails. In `GPGLax` mode it will just print a warning.
|
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>`.
|
You can also pass the mode via `ghcup --gpg <strict|lax|none>`.
|
||||||
|
|
||||||
# Tips and tricks
|
## Tips and tricks
|
||||||
|
|
||||||
## ghcup run
|
### Execute command with certain GHC in PATH
|
||||||
|
|
||||||
If you don't want to explicitly switch the active GHC all the time and are using
|
If you don't want to explicitly switch the active GHC all the time and are using
|
||||||
tools that rely on the plain `ghc` binary, GHCup provides an easy way to execute
|
tools that rely on the plain `ghc` binary, GHCup provides an easy way to execute
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ hide:
|
|||||||
|
|
||||||
<div class="text-center main-buttons">
|
<div class="text-center main-buttons">
|
||||||
<a href="install/" class="btn btn-primary" role="button">Getting Started</a>
|
<a href="install/" class="btn btn-primary" role="button">Getting Started</a>
|
||||||
<a href="steps/" class="btn btn-primary" role="button">First steps</a>
|
|
||||||
<a href="guide/" class="btn btn-primary" role="button">User Guide</a>
|
<a href="guide/" class="btn btn-primary" role="button">User Guide</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
GHCup makes it easy to install specific versions of GHC on GNU/Linux,
|
GHCup makes it easy to install specific versions of GHC on GNU/Linux,
|
||||||
macOS (aka Darwin), FreeBSD and Windows and can also bootstrap a fresh [Haskell developer environment](./install/#supported-tools) from scratch.
|
macOS (aka Darwin), FreeBSD and Windows and can also bootstrap a fresh [Haskell developer environment](./install/#supported-tools) from scratch.
|
||||||
It follows the 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).
|
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).
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
@@ -22,8 +22,6 @@ For Windows, run this in a PowerShell session:
|
|||||||
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 $true
|
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 $true
|
||||||
```
|
```
|
||||||
|
|
||||||
There's also a [youtube video](https://www.youtube.com/watch?v=bB4fmQiUYPw) explaining installation on windows.
|
|
||||||
|
|
||||||
If you want to know what these scripts do, check out the [source code at the repository](https://gitlab.haskell.org/haskell/ghcup-hs/-/tree/master/scripts/bootstrap). Advanced users may want to perform a [manual installation](#manual-install) and GPG verify the binaries.
|
If you want to know what these scripts do, check out the [source code at the repository](https://gitlab.haskell.org/haskell/ghcup-hs/-/tree/master/scripts/bootstrap). Advanced users may want to perform a [manual installation](#manual-install) and GPG verify the binaries.
|
||||||
|
|
||||||
### Which versions get installed?
|
### Which versions get installed?
|
||||||
@@ -34,101 +32,28 @@ GHCup has two main channels for every tool: **recommended** and **latest**. By d
|
|||||||
|
|
||||||
Also see [tags and shortcuts](../guide/#tags-and-shortcuts) for more information.
|
Also see [tags and shortcuts](../guide/#tags-and-shortcuts) for more information.
|
||||||
|
|
||||||
## Next steps
|
## First steps
|
||||||
|
|
||||||
1. Follow the [First steps guide](../steps) on how to build a "Hello world" program, use `ghc`, run an interactive REPL and create a Haskell project
|
1. To get started with creating a Haskell project, follow the [Getting Started with Haskell and Cabal](https://cabal.readthedocs.io/en/stable/getting-started.html) guide
|
||||||
2. To understand the difference and overlap of `stack` and `cabal`, read on [here](https://gist.github.com/merijn/8152d561fb8b011f9313c48d876ceb07)
|
2. To learn Haskell, try any of those:
|
||||||
3. To learn Haskell proper check out the links at [How to learn Haskell proper](../steps#how-to-learn-haskell-proper)
|
- A beginner friendly [4-lectures course](https://github.com/haskell-beginners-2022/course-plan) with exercises (by [Kowainik](https://kowainik.github.io/))
|
||||||
4. To learn more about Haskell Toolchain management, check out the [ghcup user guide](./guide.md)
|
- An in-depth university [CIS 194 Haskell course](https://www.cis.upenn.edu/~cis194/spring13/) including exercises (by [Brent Yorgey](https://byorgey.wordpress.com/))
|
||||||
|
3. To learn more about Haskell Toolchain management, check out the [ghcup user guide](./guide.md)
|
||||||
|
|
||||||
## Uninstallation
|
## Uninstallation
|
||||||
|
|
||||||
On linux, just run `ghcup nuke`, then make sure any ghcup added lines in your `~/.bashrc` (or similar) are removed.
|
On linux, just run `ghcup nuke`, then make sure any ghcup added lines in your `~/.bashrc` (or similar) are removed.
|
||||||
|
|
||||||
On windows, right click on the `Uninstall Haskell.ps1` PowerShell script on your Desktop and select *Run with PowerShell*.
|
On windows, double-click on the `Uninstall Haskell.ps1` PowerShell script on your Desktop.
|
||||||
|
|
||||||
## Supported tools
|
## Supported tools
|
||||||
|
|
||||||
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**:
|
||||||
|
|
||||||
<details> <summary>Show all supported <a href='https://www.haskell.org/ghc/'>GHC</a> versions</summary>
|
1. [GHC](https://www.haskell.org/ghc/)
|
||||||
<table>
|
2. [cabal-install](https://cabal.readthedocs.io/en/stable/)
|
||||||
<thead><tr><th>GHC Version</th><th>Tags</th></tr></thead>
|
3. [haskell-language-server](https://haskell-language-server.readthedocs.io/en/stable/)
|
||||||
<tbody>
|
4. [stack](https://docs.haskellstack.org/en/stable/README/)
|
||||||
<tr><td>9.2.2</td><td><span style="color:blue">latest</span>, base-4.16.1.0</td></tr>
|
|
||||||
<tr><td>9.2.1</td><td>base-4.16.0.0</td></tr>
|
|
||||||
<tr><td>9.0.2</td><td>base-4.15.1.0</td></tr>
|
|
||||||
<tr><td>9.0.1</td><td>base-4.15.0.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>8.10.6</td><td>base-4.14.3.0</td></tr>
|
|
||||||
<tr><td>8.10.5</td><td>base-4.14.2.0</td></tr>
|
|
||||||
<tr><td>8.10.4</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.2</td><td>base-4.14.1.0</td></tr>
|
|
||||||
<tr><td>8.10.1</td><td>base-4.14.0.0</td></tr>
|
|
||||||
<tr><td>8.8.4</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.2</td><td>base-4.13.0.0</td></tr>
|
|
||||||
<tr><td>8.8.1</td><td>base-4.13.0.0</td></tr>
|
|
||||||
<tr><td>8.6.5</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.3</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.1</td><td>base-4.12.0.0</td></tr>
|
|
||||||
<tr><td>8.4.4</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.2</td><td>base-4.11.1.0</td></tr>
|
|
||||||
<tr><td>8.4.1</td><td>base-4.11.0.0</td></tr>
|
|
||||||
<tr><td>8.2.2</td><td>base-4.10.1.0</td></tr>
|
|
||||||
<tr><td>8.0.2</td><td>base-4.9.1.0</td></tr>
|
|
||||||
<tr><td>7.10.3</td><td>base-4.8.2.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>3.6.2.0</td><td><span style="color:blue">latest</span>, <span style="color:green">recommended</span></td></tr>
|
|
||||||
<tr><td>3.6.0.0</td><td></td></tr>
|
|
||||||
<tr><td>3.4.1.0</td><td></td></tr>
|
|
||||||
<tr><td>3.4.0.0</td><td></td></tr>
|
|
||||||
<tr><td>3.2.0.0</td><td></td></tr>
|
|
||||||
<tr><td>3.0.0.0</td><td></td></tr>
|
|
||||||
<tr><td>2.4.1.0</td><td></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.7.0.0</td><td><span style="color:blue">latest</span>, <span style="color:green">recommended</span></td></tr>
|
|
||||||
<tr><td>1.6.1.0</td><td></td></tr>
|
|
||||||
<tr><td>1.6.0.0</td><td></td></tr>
|
|
||||||
<tr><td>1.5.1</td><td></td></tr>
|
|
||||||
<tr><td>1.5.0</td><td></td></tr>
|
|
||||||
<tr><td>1.4.0</td><td></td></tr>
|
|
||||||
<tr><td>1.3.0</td><td></td></tr>
|
|
||||||
<tr><td>1.2.0</td><td></td></tr>
|
|
||||||
<tr><td>1.1.0</td><td></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.7.5</td><td><span style="color:blue">latest</span>, <span style="color:green">recommended</span></td></tr>
|
|
||||||
<tr><td>2.7.3</td><td></td></tr>
|
|
||||||
<tr><td>2.7.1</td><td></td></tr>
|
|
||||||
<tr><td>2.5.1</td><td></td></tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Supported platforms
|
## Supported platforms
|
||||||
|
|
||||||
|
|||||||
349
docs/steps.md
349
docs/steps.md
@@ -1,349 +0,0 @@
|
|||||||
# First steps
|
|
||||||
|
|
||||||
In this guide we'll take a look at a few core tools that are installed
|
|
||||||
with the Haskell toolchain, namely, `ghc`, `runghc` and `ghci`.
|
|
||||||
These tools can be used to compile, interpret or explore Haskell programs.
|
|
||||||
|
|
||||||
First, let's start by opening your system's command line interface
|
|
||||||
and running `ghc --version` to make sure we have successfully
|
|
||||||
installed a Haskell toolchain:
|
|
||||||
|
|
||||||
```
|
|
||||||
➜ ghc --version
|
|
||||||
The Glorious Glasgow Haskell Compilation System, version 8.10.7
|
|
||||||
```
|
|
||||||
|
|
||||||
If this fails, consult [the Getting started page](../install) for information on
|
|
||||||
how to install Haskell on your computer.
|
|
||||||
|
|
||||||
This guide is partly based on [Gil Mizrahi's blog](https://gilmi.me/blog/post/2021/08/14/hs-core-tools).
|
|
||||||
|
|
||||||
## Compiling programs with ghc
|
|
||||||
|
|
||||||
Running `ghc` invokes the Glasgow Haskell Compiler (GHC), and can be used to
|
|
||||||
compile Haskell modules and programs into native executables and libraries.
|
|
||||||
|
|
||||||
Create a new Haskell source file named `hello.hs`,
|
|
||||||
and write the following code in it:
|
|
||||||
|
|
||||||
```hs
|
|
||||||
main = putStrLn "Hello, Haskell!"
|
|
||||||
```
|
|
||||||
|
|
||||||
Now, we can compile the program by invoking `ghc` with the file name:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
➜ ghc hello.hs
|
|
||||||
[1 of 1] Compiling Main ( hello.hs, hello.o )
|
|
||||||
Linking hello ...
|
|
||||||
```
|
|
||||||
|
|
||||||
For more in-depth information about the files `ghc` produces,
|
|
||||||
follow the [GHC user guide](https://downloads.haskell.org/ghc/latest/docs/html/users_guide/using.html#getting-started-compiling-programs) guide.
|
|
||||||
|
|
||||||
Now we run our program:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
➜ ./hello
|
|
||||||
Hello, Haskell!
|
|
||||||
```
|
|
||||||
|
|
||||||
Alternatively, we can skip the compilation phase by using the command `runghc`:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
➜ runghc hello.hs
|
|
||||||
Hello, Haskell!
|
|
||||||
```
|
|
||||||
|
|
||||||
`runghc` interprets the source file instead of compiling it and does not
|
|
||||||
create build artifacts. This makes it very useful when developing programs
|
|
||||||
and can help accelerate the feedback loop. More information about `runghc`
|
|
||||||
can be found in the
|
|
||||||
[GHC user guide](https://downloads.haskell.org/ghc/latest/docs/html/users_guide/runghc.html).
|
|
||||||
|
|
||||||
### Turning on warnings
|
|
||||||
|
|
||||||
The `-Wall` flag will enable GHC to emit warnings about our code.
|
|
||||||
|
|
||||||
```sh
|
|
||||||
➜ ghc -Wall hello.hs -fforce-recomp
|
|
||||||
[1 of 1] Compiling Main ( hello.hs, hello.o )
|
|
||||||
|
|
||||||
hello.hs:1:1: warning: [-Wmissing-signatures]
|
|
||||||
Top-level binding with no type signature: main :: IO ()
|
|
||||||
|
|
|
||||||
1 | main = putStrLn "Hello, Haskell!"
|
|
||||||
| ^^^^
|
|
||||||
Linking hello ...
|
|
||||||
```
|
|
||||||
|
|
||||||
While Haskell can infer
|
|
||||||
the types of most expressions, it is recommended that top-level definitions
|
|
||||||
are annotated with their types.
|
|
||||||
|
|
||||||
Now our `hello.hs` source file should looks like this:
|
|
||||||
|
|
||||||
```hs
|
|
||||||
main :: IO ()
|
|
||||||
main = putStrLn "Hello, world!"
|
|
||||||
```
|
|
||||||
|
|
||||||
And now GHC will compile `hello.hs` without warnings.
|
|
||||||
|
|
||||||
## An interactive environment
|
|
||||||
|
|
||||||
GHC provides an interactive environment in a form of a
|
|
||||||
Read-Evaluate-Print Loop (REPL) called GHCi.
|
|
||||||
To enter the environment run the program `ghci`.
|
|
||||||
|
|
||||||
```sh
|
|
||||||
➜ ghci
|
|
||||||
GHCi, version 9.0.2: https://www.haskell.org/ghc/ :? for help
|
|
||||||
ghci>
|
|
||||||
```
|
|
||||||
|
|
||||||
It provides an interactive prompt where Haskell expressions can be written and
|
|
||||||
evaluated.
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
ghci> 1 + 1
|
|
||||||
2
|
|
||||||
ghci> putStrLn "Hello, world!"
|
|
||||||
Hello, world!
|
|
||||||
```
|
|
||||||
|
|
||||||
We can define new names:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
ghci> double x = x + x
|
|
||||||
ghci> double 2
|
|
||||||
4
|
|
||||||
```
|
|
||||||
|
|
||||||
We can write multi-line code by surrounding it with `:{` and `:}`:
|
|
||||||
|
|
||||||
```hs
|
|
||||||
ghci> :{
|
|
||||||
| map f list =
|
|
||||||
| case list of
|
|
||||||
| [] -> []
|
|
||||||
| x : xs -> f x : map f xs
|
|
||||||
| :}
|
|
||||||
ghci> map (+1) [1, 2, 3]
|
|
||||||
[2,3,4]
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
We can import Haskell source files using the `:load` command (`:l` for short):
|
|
||||||
|
|
||||||
```sh
|
|
||||||
ghci> :load hello.hs
|
|
||||||
[1 of 1] Compiling Main ( hello.hs, interpreted )
|
|
||||||
Ok, one module loaded.
|
|
||||||
ghci> main
|
|
||||||
Hello, Haskell!
|
|
||||||
```
|
|
||||||
|
|
||||||
As well as import library modules:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
ghci> import Data.Bits
|
|
||||||
ghci> shiftL 32 1
|
|
||||||
64
|
|
||||||
ghci> clearBit 33 0
|
|
||||||
32
|
|
||||||
```
|
|
||||||
|
|
||||||
We can even ask what the type of an expression is using the `:type` command
|
|
||||||
(`:t` for short):
|
|
||||||
|
|
||||||
```sh
|
|
||||||
λ> :type putStrLn
|
|
||||||
putStrLn :: String -> IO ()
|
|
||||||
```
|
|
||||||
|
|
||||||
To exit `ghci`, use the `:quit` command (or `:q` for short)
|
|
||||||
|
|
||||||
```sh
|
|
||||||
ghci> :quit
|
|
||||||
Leaving GHCi.
|
|
||||||
```
|
|
||||||
|
|
||||||
A more thorough introduction to GHCi can be found in the
|
|
||||||
[GHC user guide](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/ghci.html).
|
|
||||||
|
|
||||||
### Using external packages in ghci
|
|
||||||
|
|
||||||
By default, GHCi can only load and use packages that are
|
|
||||||
[included with the GHC installation](https://downloads.haskell.org/ghc/latest/docs/html/users_guide/9.2.2-notes.html#included-libraries).
|
|
||||||
|
|
||||||
However, users of the [cabal-install](https://www.haskell.org/cabal) and
|
|
||||||
[stack](http://haskellstack.org) build tools can download and load external packages
|
|
||||||
very easily using the following commands:
|
|
||||||
|
|
||||||
cabal-install:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
cabal repl --build-depends async,say
|
|
||||||
```
|
|
||||||
|
|
||||||
Stack:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
stack exec --package async --package say -- ghci
|
|
||||||
```
|
|
||||||
|
|
||||||
And the modules of the relevant packages will be available for import:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
GHCi, version 9.0.1: https://www.haskell.org/ghc/ :? for help
|
|
||||||
ghci> import Control.Concurrent.Async
|
|
||||||
ghci> import Say
|
|
||||||
ghci> concurrently_ (sayString "Hello") (sayString "World")
|
|
||||||
Hello
|
|
||||||
World
|
|
||||||
```
|
|
||||||
|
|
||||||
Stack users can also use this feature with `runghc` and `ghc` by replacing
|
|
||||||
`ghci` in the command above, and cabal-install users can generate an
|
|
||||||
environment file that will make `async` and `say` visible for GHC tools
|
|
||||||
in the current directory using this command:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
cabal install --lib async say --package-env .
|
|
||||||
```
|
|
||||||
|
|
||||||
Many more packages are waiting for you on [Hackage](https://hackage.haskell.org).
|
|
||||||
|
|
||||||
## Creating a proper package with modules
|
|
||||||
|
|
||||||
The previous methods to compile Haskell code are for quick experiments and small
|
|
||||||
programs. Usually in Haskell, we create cabal projects, where build tools such as
|
|
||||||
`cabal-install` or `stack` will install necessary dependencies and compile modules
|
|
||||||
in correct order. For simplicity's sake, this section will only use `cabal-install`.
|
|
||||||
|
|
||||||
To get started, run:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mkdir haskell-project
|
|
||||||
cd haskell-project
|
|
||||||
cabal init --interactive
|
|
||||||
```
|
|
||||||
|
|
||||||
If you let it generate a simple project with sensible defaults, then you should have these files:
|
|
||||||
|
|
||||||
* `src/MyLib.hs`: the library module of your project
|
|
||||||
* `app/Main.hs`: the entry point of your project
|
|
||||||
* `haskell-project.cabal`: the "cabal" file, describing your project, its dependencies and how it's built
|
|
||||||
|
|
||||||
To build the project, run:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
cabal build
|
|
||||||
```
|
|
||||||
|
|
||||||
To run the main executable, run:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
➜ cabal run
|
|
||||||
Hello, Haskell!
|
|
||||||
someFunc
|
|
||||||
```
|
|
||||||
|
|
||||||
### Adding dependencies
|
|
||||||
|
|
||||||
Now let's add a dependency and adjust our library module. Open `haskell-project.cabal`
|
|
||||||
and find the library section:
|
|
||||||
|
|
||||||
```
|
|
||||||
library
|
|
||||||
exposed-modules: MyLib
|
|
||||||
|
|
||||||
-- Modules included in this library but not exported.
|
|
||||||
-- other-modules:
|
|
||||||
|
|
||||||
-- LANGUAGE extensions used by modules in this package.
|
|
||||||
-- other-extensions:
|
|
||||||
build-depends: base ^>=4.14.3.0
|
|
||||||
hs-source-dirs: src
|
|
||||||
default-language: Haskell2010
|
|
||||||
```
|
|
||||||
|
|
||||||
The interesting parts here are `exposed-modules` and `build-depends`.
|
|
||||||
To add a dependency, it should look like this:
|
|
||||||
|
|
||||||
```
|
|
||||||
build-depends: base ^>=4.14.3.0
|
|
||||||
, directory
|
|
||||||
```
|
|
||||||
|
|
||||||
Now open `src/MyLib.hs` and change it to:
|
|
||||||
|
|
||||||
```hs
|
|
||||||
module MyLib (someFunc) where
|
|
||||||
|
|
||||||
import System.Directory
|
|
||||||
|
|
||||||
someFunc :: IO ()
|
|
||||||
someFunc = do
|
|
||||||
contents <- listDirectory "src"
|
|
||||||
putStrLn (show contents)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Adding modules
|
|
||||||
|
|
||||||
To add a module to your package, adjust `exposed-modules`, like so
|
|
||||||
|
|
||||||
```
|
|
||||||
exposed-modules: MyLib
|
|
||||||
OtherLib
|
|
||||||
```
|
|
||||||
|
|
||||||
then create `src/OtherLib.hs` with the following contents:
|
|
||||||
|
|
||||||
```hs
|
|
||||||
module OtherLib where
|
|
||||||
|
|
||||||
otherFunc :: String -> Int
|
|
||||||
otherFunc str = length str
|
|
||||||
```
|
|
||||||
|
|
||||||
To use this function interactively, we can run:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
➜ cabal repl
|
|
||||||
ghci> import OtherLib
|
|
||||||
ghci> otherFunc "Hello Haskell"
|
|
||||||
13
|
|
||||||
```
|
|
||||||
|
|
||||||
For further information about how to manage Haskell projects
|
|
||||||
see the [Cabal user guide](https://cabal.readthedocs.io/en/stable/getting-started.html).
|
|
||||||
|
|
||||||
# Where to go from here
|
|
||||||
|
|
||||||
<div class="text-center main-buttons">
|
|
||||||
<a href="https://hackage.haskell.org/" class="btn btn-primary" role="button">Discover Haskell packages</a>
|
|
||||||
<a href="https://hackage.haskell.org/package/base" class="btn btn-primary" role="button">The standard library</a>
|
|
||||||
<a href="https://haskell-language-server.readthedocs.io/en/stable/installation.html" class="btn btn-primary" role="button">Editor setup with HLS</a>
|
|
||||||
<a href="https://play-haskell.tomsmeding.com/play" class="btn btn-primary" role="button">Online playground</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
## How to learn Haskell proper
|
|
||||||
|
|
||||||
To learn Haskell, try any of those:
|
|
||||||
|
|
||||||
- A beginner friendly [4-lectures course](https://github.com/haskell-beginners-2022/course-plan) with exercises (by [Kowainik](https://kowainik.github.io/))
|
|
||||||
- An in-depth university [CIS 194 Haskell course](https://www.cis.upenn.edu/~cis194/spring13/) including exercises (by [Brent Yorgey](https://byorgey.wordpress.com/))
|
|
||||||
|
|
||||||
## Projects to contribute to
|
|
||||||
|
|
||||||
* [https://github.com/haskell/haskell-language-server](https://github.com/haskell/haskell-language-server)
|
|
||||||
* [https://github.com/haskell/cabal](https://github.com/haskell/cabal)
|
|
||||||
* [https://github.com/commercialhaskell/stack](https://github.com/commercialhaskell/stack)
|
|
||||||
* [https://gitlab.haskell.org/haskell/ghcup-hs](https://gitlab.haskell.org/haskell/ghcup-hs)
|
|
||||||
* [https://github.com/jgm/pandoc](https://github.com/jgm/pandoc)
|
|
||||||
* [https://github.com/simonmichael/hledger](https://github.com/simonmichael/hledger)
|
|
||||||
* [https://github.com/koalaman/shellcheck](https://github.com/koalaman/shellcheck)
|
|
||||||
31
ghcup.cabal
31
ghcup.cabal
@@ -1,6 +1,6 @@
|
|||||||
cabal-version: 3.0
|
cabal-version: 3.0
|
||||||
name: ghcup
|
name: ghcup
|
||||||
version: 0.1.17.8
|
version: 0.1.17.5
|
||||||
license: LGPL-3.0-only
|
license: LGPL-3.0-only
|
||||||
license-file: LICENSE
|
license-file: LICENSE
|
||||||
copyright: Julian Ospald 2020
|
copyright: Julian Ospald 2020
|
||||||
@@ -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.3
|
, megaparsec >=8.0.0 && <9.1
|
||||||
, mtl ^>=2.2
|
, mtl ^>=2.2
|
||||||
, optics ^>=0.4
|
, optics ^>=0.4
|
||||||
, os-release ^>=1.0.0
|
, os-release ^>=1.0.0
|
||||||
@@ -236,23 +236,19 @@ 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.3
|
, megaparsec >=8.0.0 && <9.1
|
||||||
, mtl ^>=2.2
|
, mtl ^>=2.2
|
||||||
, optparse-applicative >=0.15.1.0 && <0.18
|
, optparse-applicative >=0.15.1.0 && <0.17
|
||||||
, 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
|
|
||||||
, resourcet ^>=1.2.2
|
, resourcet ^>=1.2.2
|
||||||
, safe ^>=0.3.18
|
, safe ^>=0.3.18
|
||||||
, safe-exceptions ^>=0.1
|
, safe-exceptions ^>=0.1
|
||||||
, tagsoup ^>=0.14
|
|
||||||
, template-haskell >=2.7 && <2.18
|
|
||||||
, temporary ^>=1.3
|
, temporary ^>=1.3
|
||||||
|
, template-haskell >=2.7 && <2.18
|
||||||
, text ^>=1.2.4.0
|
, text ^>=1.2.4.0
|
||||||
, unordered-containers ^>=0.2
|
|
||||||
, uri-bytestring ^>=0.3.2.2
|
, uri-bytestring ^>=0.3.2.2
|
||||||
, utf8-string ^>=1.0
|
, utf8-string ^>=1.0
|
||||||
, vector ^>=0.12
|
|
||||||
, versions >=4.0.1 && <5.1
|
, versions >=4.0.1 && <5.1
|
||||||
, yaml-streamly ^>=0.12.0
|
, yaml-streamly ^>=0.12.0
|
||||||
|
|
||||||
@@ -266,22 +262,23 @@ executable ghcup
|
|||||||
, brick ^>=0.64
|
, brick ^>=0.64
|
||||||
, transformers ^>=0.5
|
, transformers ^>=0.5
|
||||||
, unix ^>=2.7
|
, unix ^>=2.7
|
||||||
|
, vector ^>=0.12
|
||||||
, vty >=5.28.2 && <5.34
|
, vty >=5.28.2 && <5.34
|
||||||
|
|
||||||
if os(windows)
|
if os(windows)
|
||||||
cpp-options: -DIS_WINDOWS
|
cpp-options: -DIS_WINDOWS
|
||||||
|
|
||||||
else
|
else
|
||||||
build-depends: unix ^>=2.7
|
build-depends:
|
||||||
|
, 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: GHCup.OptParse.Upgrade
|
other-modules:
|
||||||
|
GHCup.OptParse.Upgrade
|
||||||
|
|
||||||
test-suite ghcup-test
|
test-suite ghcup-test
|
||||||
type: exitcode-stdio-1.0
|
type: exitcode-stdio-1.0
|
||||||
@@ -310,9 +307,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 && <0.3
|
, generic-arbitrary ^>=0.1.0
|
||||||
, ghcup
|
, ghcup
|
||||||
, hspec >=2.7.10 && <2.10
|
, hspec ^>=2.7.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
|
||||||
|
|||||||
271
lib/GHCup.hs
271
lib/GHCup.hs
@@ -187,7 +187,7 @@ installGHCBindist :: ( MonadFail m
|
|||||||
)
|
)
|
||||||
=> DownloadInfo -- ^ where/how to download
|
=> DownloadInfo -- ^ where/how to download
|
||||||
-> Version -- ^ the version to install
|
-> Version -- ^ the version to install
|
||||||
-> InstallDir
|
-> Maybe FilePath -- ^ isolated filepath if user passed any
|
||||||
-> Bool -- ^ Force install
|
-> Bool -- ^ Force install
|
||||||
-> Excepts
|
-> Excepts
|
||||||
'[ AlreadyInstalled
|
'[ AlreadyInstalled
|
||||||
@@ -205,7 +205,7 @@ installGHCBindist :: ( MonadFail m
|
|||||||
]
|
]
|
||||||
m
|
m
|
||||||
()
|
()
|
||||||
installGHCBindist dlinfo ver installDir forceInstall = do
|
installGHCBindist dlinfo ver isoFilepath forceInstall = do
|
||||||
let tver = mkTVer ver
|
let tver = mkTVer ver
|
||||||
|
|
||||||
lift $ logDebug $ "Requested to install GHC with " <> prettyVer ver
|
lift $ logDebug $ "Requested to install GHC with " <> prettyVer ver
|
||||||
@@ -215,12 +215,12 @@ installGHCBindist dlinfo ver installDir forceInstall = do
|
|||||||
if
|
if
|
||||||
| not forceInstall
|
| not forceInstall
|
||||||
, regularGHCInstalled
|
, regularGHCInstalled
|
||||||
, GHCupInternal <- installDir -> do
|
, Nothing <- isoFilepath -> do
|
||||||
throwE $ AlreadyInstalled GHC ver
|
throwE $ AlreadyInstalled GHC ver
|
||||||
|
|
||||||
| forceInstall
|
| forceInstall
|
||||||
, regularGHCInstalled
|
, regularGHCInstalled
|
||||||
, GHCupInternal <- installDir -> do
|
, Nothing <- isoFilepath -> do
|
||||||
lift $ logInfo "Removing the currently installed GHC version first!"
|
lift $ logInfo "Removing the currently installed GHC version first!"
|
||||||
liftE $ rmGHCVer tver
|
liftE $ rmGHCVer tver
|
||||||
|
|
||||||
@@ -229,18 +229,17 @@ installGHCBindist dlinfo ver installDir forceInstall = do
|
|||||||
-- download (or use cached version)
|
-- download (or use cached version)
|
||||||
dl <- liftE $ downloadCached dlinfo Nothing
|
dl <- liftE $ downloadCached dlinfo Nothing
|
||||||
|
|
||||||
|
-- prepare paths
|
||||||
|
ghcdir <- lift $ ghcupGHCDir tver
|
||||||
|
|
||||||
toolchainSanityChecks
|
toolchainSanityChecks
|
||||||
|
|
||||||
case installDir of
|
case isoFilepath of
|
||||||
IsolateDir isoDir -> do -- isolated install
|
Just isoDir -> do -- isolated install
|
||||||
lift $ logInfo $ "isolated installing GHC to " <> T.pack isoDir
|
lift $ logInfo $ "isolated installing GHC to " <> T.pack isoDir
|
||||||
liftE $ installPackedGHC dl (view dlSubdir dlinfo) (IsolateDirResolved isoDir) ver forceInstall
|
liftE $ installPackedGHC dl (view dlSubdir dlinfo) isoDir ver forceInstall
|
||||||
GHCupInternal -> do -- regular install
|
Nothing -> do -- regular install
|
||||||
-- prepare paths
|
liftE $ installPackedGHC dl (view dlSubdir dlinfo) ghcdir ver forceInstall
|
||||||
ghcdir <- lift $ ghcupGHCDir tver
|
|
||||||
|
|
||||||
liftE $ installPackedGHC dl (view dlSubdir dlinfo) (GHCupDir ghcdir) ver forceInstall
|
|
||||||
|
|
||||||
-- make symlinks & stuff when regular install,
|
-- make symlinks & stuff when regular install,
|
||||||
liftE $ postGHCInstall tver
|
liftE $ postGHCInstall tver
|
||||||
@@ -272,7 +271,7 @@ installPackedGHC :: ( MonadMask m
|
|||||||
)
|
)
|
||||||
=> FilePath -- ^ Path to the packed GHC bindist
|
=> FilePath -- ^ Path to the packed GHC bindist
|
||||||
-> Maybe TarDir -- ^ Subdir of the archive
|
-> Maybe TarDir -- ^ Subdir of the archive
|
||||||
-> InstallDirResolved
|
-> FilePath -- ^ Path to install to
|
||||||
-> Version -- ^ The GHC version
|
-> Version -- ^ The GHC version
|
||||||
-> Bool -- ^ Force install
|
-> Bool -- ^ Force install
|
||||||
-> Excepts
|
-> Excepts
|
||||||
@@ -300,11 +299,7 @@ installPackedGHC dl msubdir inst ver forceInstall = do
|
|||||||
msubdir
|
msubdir
|
||||||
|
|
||||||
liftE $ runBuildAction tmpUnpack
|
liftE $ runBuildAction tmpUnpack
|
||||||
(case inst of
|
(Just inst)
|
||||||
IsolateDirResolved _ -> Nothing -- don't clean up for isolated installs, since that'd potentially delete other
|
|
||||||
-- user files if '--force' is supplied
|
|
||||||
GHCupDir d -> Just d
|
|
||||||
)
|
|
||||||
(installUnpackedGHC workdir inst ver)
|
(installUnpackedGHC workdir inst ver)
|
||||||
|
|
||||||
|
|
||||||
@@ -320,11 +315,11 @@ installUnpackedGHC :: ( MonadReader env m
|
|||||||
, MonadUnliftIO m
|
, MonadUnliftIO m
|
||||||
, MonadMask m
|
, MonadMask m
|
||||||
)
|
)
|
||||||
=> FilePath -- ^ Path to the unpacked GHC bindist (where the configure script resides)
|
=> FilePath -- ^ Path to the unpacked GHC bindist (where the configure script resides)
|
||||||
-> InstallDirResolved -- ^ Path to install to
|
-> FilePath -- ^ Path to install to
|
||||||
-> Version -- ^ The GHC version
|
-> Version -- ^ The GHC version
|
||||||
-> Excepts '[ProcessError] m ()
|
-> Excepts '[ProcessError] m ()
|
||||||
installUnpackedGHC path (fromInstallDir -> inst) ver
|
installUnpackedGHC path inst ver
|
||||||
| isWindows = do
|
| isWindows = do
|
||||||
lift $ logInfo "Installing GHC (this may take a while)"
|
lift $ logInfo "Installing GHC (this may take a while)"
|
||||||
-- Windows bindists are relocatable and don't need
|
-- Windows bindists are relocatable and don't need
|
||||||
@@ -374,7 +369,7 @@ installGHCBin :: ( MonadFail m
|
|||||||
, MonadUnliftIO m
|
, MonadUnliftIO m
|
||||||
)
|
)
|
||||||
=> Version -- ^ the version to install
|
=> Version -- ^ the version to install
|
||||||
-> InstallDir
|
-> Maybe FilePath -- ^ isolated install filepath, if user passed any
|
||||||
-> Bool -- ^ force install
|
-> Bool -- ^ force install
|
||||||
-> Excepts
|
-> Excepts
|
||||||
'[ AlreadyInstalled
|
'[ AlreadyInstalled
|
||||||
@@ -392,9 +387,9 @@ installGHCBin :: ( MonadFail m
|
|||||||
]
|
]
|
||||||
m
|
m
|
||||||
()
|
()
|
||||||
installGHCBin ver installDir forceInstall = do
|
installGHCBin ver isoFilepath forceInstall = do
|
||||||
dlinfo <- liftE $ getDownloadInfo GHC ver
|
dlinfo <- liftE $ getDownloadInfo GHC ver
|
||||||
liftE $ installGHCBindist dlinfo ver installDir forceInstall
|
liftE $ installGHCBindist dlinfo ver isoFilepath forceInstall
|
||||||
|
|
||||||
|
|
||||||
-- | Like 'installCabalBin', except takes the 'DownloadInfo' as
|
-- | Like 'installCabalBin', except takes the 'DownloadInfo' as
|
||||||
@@ -413,7 +408,7 @@ installCabalBindist :: ( MonadMask m
|
|||||||
)
|
)
|
||||||
=> DownloadInfo
|
=> DownloadInfo
|
||||||
-> Version
|
-> Version
|
||||||
-> InstallDir
|
-> Maybe FilePath -- ^ isolated install filepath, if user provides any.
|
||||||
-> Bool -- ^ Force install
|
-> Bool -- ^ Force install
|
||||||
-> Excepts
|
-> Excepts
|
||||||
'[ AlreadyInstalled
|
'[ AlreadyInstalled
|
||||||
@@ -430,7 +425,7 @@ installCabalBindist :: ( MonadMask m
|
|||||||
]
|
]
|
||||||
m
|
m
|
||||||
()
|
()
|
||||||
installCabalBindist dlinfo ver installDir forceInstall = do
|
installCabalBindist dlinfo ver isoFilepath forceInstall = do
|
||||||
lift $ logDebug $ "Requested to install cabal version " <> prettyVer ver
|
lift $ logDebug $ "Requested to install cabal version " <> prettyVer ver
|
||||||
|
|
||||||
PlatformRequest {..} <- lift getPlatformReq
|
PlatformRequest {..} <- lift getPlatformReq
|
||||||
@@ -442,12 +437,12 @@ installCabalBindist dlinfo ver installDir forceInstall = do
|
|||||||
if
|
if
|
||||||
| not forceInstall
|
| not forceInstall
|
||||||
, regularCabalInstalled
|
, regularCabalInstalled
|
||||||
, GHCupInternal <- installDir -> do
|
, Nothing <- isoFilepath -> do
|
||||||
throwE $ AlreadyInstalled Cabal ver
|
throwE $ AlreadyInstalled Cabal ver
|
||||||
|
|
||||||
| forceInstall
|
| forceInstall
|
||||||
, regularCabalInstalled
|
, regularCabalInstalled
|
||||||
, GHCupInternal <- installDir -> do
|
, Nothing <- isoFilepath -> do
|
||||||
lift $ logInfo "Removing the currently installed version first!"
|
lift $ logInfo "Removing the currently installed version first!"
|
||||||
liftE $ rmCabalVer ver
|
liftE $ rmCabalVer ver
|
||||||
|
|
||||||
@@ -465,33 +460,34 @@ installCabalBindist dlinfo ver installDir forceInstall = do
|
|||||||
-- the subdir of the archive where we do the work
|
-- the subdir of the archive where we do the work
|
||||||
workdir <- maybe (pure tmpUnpack) (liftE . intoSubdir tmpUnpack) (view dlSubdir dlinfo)
|
workdir <- maybe (pure tmpUnpack) (liftE . intoSubdir tmpUnpack) (view dlSubdir dlinfo)
|
||||||
|
|
||||||
case installDir of
|
case isoFilepath of
|
||||||
IsolateDir isoDir -> do -- isolated install
|
Just isoDir -> do -- isolated install
|
||||||
lift $ logInfo $ "isolated installing Cabal to " <> T.pack isoDir
|
lift $ logInfo $ "isolated installing Cabal to " <> T.pack isoDir
|
||||||
liftE $ installCabalUnpacked workdir (IsolateDirResolved isoDir) ver forceInstall
|
liftE $ installCabalUnpacked workdir isoDir Nothing forceInstall
|
||||||
|
|
||||||
GHCupInternal -> do -- regular install
|
Nothing -> do -- regular install
|
||||||
liftE $ installCabalUnpacked workdir (GHCupDir binDir) ver forceInstall
|
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
|
-- | Install an unpacked cabal distribution.Symbol
|
||||||
installCabalUnpacked :: (MonadCatch m, HasLog env, MonadIO m, MonadReader env m)
|
installCabalUnpacked :: (MonadCatch m, HasLog env, MonadIO m, MonadReader env m)
|
||||||
=> FilePath -- ^ Path to the unpacked cabal bindist (where the executable resides)
|
=> FilePath -- ^ Path to the unpacked cabal bindist (where the executable resides)
|
||||||
-> InstallDirResolved -- ^ Path to install to
|
-> FilePath -- ^ Path to install to
|
||||||
-> Version
|
-> Maybe Version -- ^ Nothing for isolated install
|
||||||
-> Bool -- ^ Force Install
|
-> Bool -- ^ Force Install
|
||||||
-> Excepts '[CopyError, FileAlreadyExistsError] m ()
|
-> Excepts '[CopyError, FileAlreadyExistsError] m ()
|
||||||
installCabalUnpacked path inst ver forceInstall = do
|
installCabalUnpacked path inst mver' forceInstall = do
|
||||||
lift $ logInfo "Installing cabal"
|
lift $ logInfo "Installing cabal"
|
||||||
let cabalFile = "cabal"
|
let cabalFile = "cabal"
|
||||||
liftIO $ createDirRecursive' (fromInstallDir inst)
|
liftIO $ createDirRecursive' inst
|
||||||
let destFileName = cabalFile
|
let destFileName = cabalFile
|
||||||
<> (case inst of
|
<> maybe "" (("-" <>) . T.unpack . prettyVer) mver'
|
||||||
IsolateDirResolved _ -> ""
|
|
||||||
GHCupDir _ -> ("-" <>) . T.unpack . prettyVer $ ver
|
|
||||||
)
|
|
||||||
<> exeExt
|
<> exeExt
|
||||||
let destPath = fromInstallDir inst </> destFileName
|
let destPath = inst </> destFileName
|
||||||
|
|
||||||
unless forceInstall -- Overwrite it when it IS a force install
|
unless forceInstall -- Overwrite it when it IS a force install
|
||||||
(liftE $ throwIfFileAlreadyExists destPath)
|
(liftE $ throwIfFileAlreadyExists destPath)
|
||||||
@@ -518,7 +514,7 @@ installCabalBin :: ( MonadMask m
|
|||||||
, MonadFail m
|
, MonadFail m
|
||||||
)
|
)
|
||||||
=> Version
|
=> Version
|
||||||
-> InstallDir
|
-> Maybe FilePath -- isolated install Path, if user provided any
|
||||||
-> Bool -- force install
|
-> Bool -- force install
|
||||||
-> Excepts
|
-> Excepts
|
||||||
'[ AlreadyInstalled
|
'[ AlreadyInstalled
|
||||||
@@ -535,9 +531,9 @@ installCabalBin :: ( MonadMask m
|
|||||||
]
|
]
|
||||||
m
|
m
|
||||||
()
|
()
|
||||||
installCabalBin ver installDir forceInstall = do
|
installCabalBin ver isoFilepath forceInstall = do
|
||||||
dlinfo <- liftE $ getDownloadInfo Cabal ver
|
dlinfo <- liftE $ getDownloadInfo Cabal ver
|
||||||
installCabalBindist dlinfo ver installDir forceInstall
|
installCabalBindist dlinfo ver isoFilepath forceInstall
|
||||||
|
|
||||||
|
|
||||||
-- | Like 'installHLSBin, except takes the 'DownloadInfo' as
|
-- | Like 'installHLSBin, except takes the 'DownloadInfo' as
|
||||||
@@ -556,8 +552,8 @@ installHLSBindist :: ( MonadMask m
|
|||||||
)
|
)
|
||||||
=> DownloadInfo
|
=> DownloadInfo
|
||||||
-> Version
|
-> Version
|
||||||
-> InstallDir -- ^ isolated install path, if user passed any
|
-> Maybe FilePath -- ^ isolated install path, if user passed any
|
||||||
-> Bool -- ^ Force install
|
-> Bool -- ^ Force install
|
||||||
-> Excepts
|
-> Excepts
|
||||||
'[ AlreadyInstalled
|
'[ AlreadyInstalled
|
||||||
, CopyError
|
, CopyError
|
||||||
@@ -575,7 +571,7 @@ installHLSBindist :: ( MonadMask m
|
|||||||
]
|
]
|
||||||
m
|
m
|
||||||
()
|
()
|
||||||
installHLSBindist dlinfo ver installDir forceInstall = do
|
installHLSBindist dlinfo ver isoFilepath forceInstall = do
|
||||||
lift $ logDebug $ "Requested to install hls version " <> prettyVer ver
|
lift $ logDebug $ "Requested to install hls version " <> prettyVer ver
|
||||||
|
|
||||||
PlatformRequest {..} <- lift getPlatformReq
|
PlatformRequest {..} <- lift getPlatformReq
|
||||||
@@ -586,12 +582,12 @@ installHLSBindist dlinfo ver installDir forceInstall = do
|
|||||||
if
|
if
|
||||||
| not forceInstall
|
| not forceInstall
|
||||||
, regularHLSInstalled
|
, regularHLSInstalled
|
||||||
, GHCupInternal <- installDir -> do -- regular install
|
, Nothing <- isoFilepath -> do -- regular install
|
||||||
throwE $ AlreadyInstalled HLS ver
|
throwE $ AlreadyInstalled HLS ver
|
||||||
|
|
||||||
| forceInstall
|
| forceInstall
|
||||||
, regularHLSInstalled
|
, regularHLSInstalled
|
||||||
, GHCupInternal <- installDir -> do -- regular forced install
|
, Nothing <- isoFilepath -> do -- regular forced install
|
||||||
lift $ logInfo "Removing the currently installed version of HLS before force installing!"
|
lift $ logInfo "Removing the currently installed version of HLS before force installing!"
|
||||||
liftE $ rmHLSVer ver
|
liftE $ rmHLSVer ver
|
||||||
|
|
||||||
@@ -612,25 +608,25 @@ installHLSBindist dlinfo ver installDir forceInstall = do
|
|||||||
if
|
if
|
||||||
| not forceInstall
|
| not forceInstall
|
||||||
, not legacy
|
, not legacy
|
||||||
, (IsolateDir fp) <- installDir -> liftE $ installDestSanityCheck (IsolateDirResolved fp)
|
, (Just fp) <- isoFilepath -> liftE $ installDestSanityCheck fp
|
||||||
| otherwise -> pure ()
|
| otherwise -> pure ()
|
||||||
|
|
||||||
case installDir of
|
case isoFilepath of
|
||||||
IsolateDir isoDir -> do
|
Just isoDir -> do
|
||||||
lift $ logInfo $ "isolated installing HLS to " <> T.pack isoDir
|
lift $ logInfo $ "isolated installing HLS to " <> T.pack isoDir
|
||||||
if legacy
|
if legacy
|
||||||
then liftE $ installHLSUnpackedLegacy workdir (IsolateDirResolved isoDir) ver forceInstall
|
then liftE $ installHLSUnpackedLegacy workdir isoDir Nothing forceInstall
|
||||||
else liftE $ runBuildAction tmpUnpack Nothing $ installHLSUnpacked workdir (IsolateDirResolved isoDir) ver
|
else liftE $ runBuildAction tmpUnpack Nothing $ installHLSUnpacked workdir isoDir ver
|
||||||
|
|
||||||
GHCupInternal -> do
|
Nothing -> do
|
||||||
if legacy
|
if legacy
|
||||||
then liftE $ installHLSUnpackedLegacy workdir (GHCupDir binDir) ver forceInstall
|
then liftE $ installHLSUnpackedLegacy workdir binDir (Just ver) forceInstall
|
||||||
else do
|
else do
|
||||||
inst <- ghcupHLSDir ver
|
inst <- ghcupHLSDir ver
|
||||||
liftE $ runBuildAction tmpUnpack (Just inst)
|
liftE $ runBuildAction tmpUnpack Nothing $ installHLSUnpacked workdir inst ver
|
||||||
$ installHLSUnpacked workdir (GHCupDir inst) ver
|
|
||||||
liftE $ setHLS ver SetHLS_XYZ Nothing
|
liftE $ setHLS ver SetHLS_XYZ Nothing
|
||||||
|
|
||||||
|
liftE $ installHLSPostInst isoFilepath ver
|
||||||
|
|
||||||
isLegacyHLSBindist :: FilePath -- ^ Path to the unpacked hls bindist
|
isLegacyHLSBindist :: FilePath -- ^ Path to the unpacked hls bindist
|
||||||
-> IO Bool
|
-> IO Bool
|
||||||
@@ -640,10 +636,10 @@ isLegacyHLSBindist path = do
|
|||||||
-- | Install an unpacked hls distribution.
|
-- | Install an unpacked hls distribution.
|
||||||
installHLSUnpacked :: (MonadMask m, MonadUnliftIO m, MonadReader env m, MonadFail m, HasLog env, HasDirs env, HasSettings env, MonadCatch m, MonadIO m)
|
installHLSUnpacked :: (MonadMask m, MonadUnliftIO m, MonadReader env m, MonadFail m, HasLog env, HasDirs env, HasSettings env, MonadCatch m, MonadIO m)
|
||||||
=> FilePath -- ^ Path to the unpacked hls bindist (where the executable resides)
|
=> FilePath -- ^ Path to the unpacked hls bindist (where the executable resides)
|
||||||
-> InstallDirResolved -- ^ Path to install to
|
-> FilePath -- ^ Path to install to
|
||||||
-> Version
|
-> Version
|
||||||
-> Excepts '[ProcessError, CopyError, FileAlreadyExistsError, NotInstalled] m ()
|
-> Excepts '[ProcessError, CopyError, FileAlreadyExistsError, NotInstalled] m ()
|
||||||
installHLSUnpacked path (fromInstallDir -> inst) _ = do
|
installHLSUnpacked path inst _ = do
|
||||||
lift $ logInfo "Installing HLS"
|
lift $ logInfo "Installing HLS"
|
||||||
liftIO $ createDirRecursive' inst
|
liftIO $ createDirRecursive' inst
|
||||||
lEM $ make ["PREFIX=" <> inst, "install"] (Just path)
|
lEM $ make ["PREFIX=" <> inst, "install"] (Just path)
|
||||||
@@ -651,13 +647,13 @@ installHLSUnpacked path (fromInstallDir -> inst) _ = do
|
|||||||
-- | Install an unpacked hls distribution (legacy).
|
-- | Install an unpacked hls distribution (legacy).
|
||||||
installHLSUnpackedLegacy :: (MonadReader env m, MonadFail m, HasLog env, MonadCatch m, MonadIO m)
|
installHLSUnpackedLegacy :: (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 the unpacked hls bindist (where the executable resides)
|
||||||
-> InstallDirResolved -- ^ Path to install to
|
-> FilePath -- ^ Path to install to
|
||||||
-> Version
|
-> Maybe Version -- ^ Nothing for isolated install
|
||||||
-> Bool -- ^ is it a force install
|
-> Bool -- ^ is it a force install
|
||||||
-> Excepts '[CopyError, FileAlreadyExistsError] m ()
|
-> Excepts '[CopyError, FileAlreadyExistsError] m ()
|
||||||
installHLSUnpackedLegacy path installDir ver forceInstall = do
|
installHLSUnpackedLegacy path inst mver' forceInstall = do
|
||||||
lift $ logInfo "Installing HLS"
|
lift $ logInfo "Installing HLS"
|
||||||
liftIO $ createDirRecursive' (fromInstallDir installDir)
|
liftIO $ createDirRecursive' inst
|
||||||
|
|
||||||
-- install haskell-language-server-<ghcver>
|
-- install haskell-language-server-<ghcver>
|
||||||
bins@(_:_) <- liftIO $ findFiles
|
bins@(_:_) <- liftIO $ findFiles
|
||||||
@@ -668,14 +664,11 @@ installHLSUnpackedLegacy path installDir ver forceInstall = do
|
|||||||
)
|
)
|
||||||
forM_ bins $ \f -> do
|
forM_ bins $ \f -> do
|
||||||
let toF = dropSuffix exeExt f
|
let toF = dropSuffix exeExt f
|
||||||
<> (case installDir of
|
<> maybe "" (("~" <>) . T.unpack . prettyVer) mver'
|
||||||
IsolateDirResolved _ -> ""
|
|
||||||
GHCupDir _ -> ("~" <>) . T.unpack . prettyVer $ ver
|
|
||||||
)
|
|
||||||
<> exeExt
|
<> exeExt
|
||||||
|
|
||||||
let srcPath = path </> f
|
let srcPath = path </> f
|
||||||
let destPath = fromInstallDir installDir </> toF
|
let destPath = inst </> toF
|
||||||
|
|
||||||
unless forceInstall -- if it is a force install, overwrite it.
|
unless forceInstall -- if it is a force install, overwrite it.
|
||||||
(liftE $ throwIfFileAlreadyExists destPath)
|
(liftE $ throwIfFileAlreadyExists destPath)
|
||||||
@@ -688,13 +681,10 @@ installHLSUnpackedLegacy path installDir ver forceInstall = do
|
|||||||
-- install haskell-language-server-wrapper
|
-- install haskell-language-server-wrapper
|
||||||
let wrapper = "haskell-language-server-wrapper"
|
let wrapper = "haskell-language-server-wrapper"
|
||||||
toF = wrapper
|
toF = wrapper
|
||||||
<> (case installDir of
|
<> maybe "" (("-" <>) . T.unpack . prettyVer) mver'
|
||||||
IsolateDirResolved _ -> ""
|
|
||||||
GHCupDir _ -> ("-" <>) . T.unpack . prettyVer $ ver
|
|
||||||
)
|
|
||||||
<> exeExt
|
<> exeExt
|
||||||
srcWrapperPath = path </> wrapper <> exeExt
|
srcWrapperPath = path </> wrapper <> exeExt
|
||||||
destWrapperPath = fromInstallDir installDir </> toF
|
destWrapperPath = inst </> toF
|
||||||
|
|
||||||
unless forceInstall
|
unless forceInstall
|
||||||
(liftE $ throwIfFileAlreadyExists destWrapperPath)
|
(liftE $ throwIfFileAlreadyExists destWrapperPath)
|
||||||
@@ -706,6 +696,19 @@ installHLSUnpackedLegacy path installDir ver forceInstall = do
|
|||||||
lift $ chmod_755 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 SetHLSOnly Nothing
|
||||||
|
|
||||||
|
|
||||||
-- | Installs hls binaries @haskell-language-server-\<ghcver\>@
|
-- | Installs hls binaries @haskell-language-server-\<ghcver\>@
|
||||||
-- into @~\/.ghcup\/bin/@, as well as @haskell-languager-server-wrapper@.
|
-- into @~\/.ghcup\/bin/@, as well as @haskell-languager-server-wrapper@.
|
||||||
@@ -723,7 +726,7 @@ installHLSBin :: ( MonadMask m
|
|||||||
, MonadFail m
|
, MonadFail m
|
||||||
)
|
)
|
||||||
=> Version
|
=> Version
|
||||||
-> InstallDir
|
-> Maybe FilePath -- isolated install Dir (if any)
|
||||||
-> Bool -- force install
|
-> Bool -- force install
|
||||||
-> Excepts
|
-> Excepts
|
||||||
'[ AlreadyInstalled
|
'[ AlreadyInstalled
|
||||||
@@ -742,9 +745,9 @@ installHLSBin :: ( MonadMask m
|
|||||||
]
|
]
|
||||||
m
|
m
|
||||||
()
|
()
|
||||||
installHLSBin ver installDir forceInstall = do
|
installHLSBin ver isoFilepath forceInstall = do
|
||||||
dlinfo <- liftE $ getDownloadInfo HLS ver
|
dlinfo <- liftE $ getDownloadInfo HLS ver
|
||||||
installHLSBindist dlinfo ver installDir forceInstall
|
installHLSBindist dlinfo ver isoFilepath forceInstall
|
||||||
|
|
||||||
|
|
||||||
compileHLS :: ( MonadMask m
|
compileHLS :: ( MonadMask m
|
||||||
@@ -764,7 +767,7 @@ compileHLS :: ( MonadMask m
|
|||||||
-> [Version]
|
-> [Version]
|
||||||
-> Maybe Int
|
-> Maybe Int
|
||||||
-> Maybe Version
|
-> Maybe Version
|
||||||
-> InstallDir
|
-> Maybe FilePath
|
||||||
-> Maybe (Either FilePath URI)
|
-> Maybe (Either FilePath URI)
|
||||||
-> Maybe URI
|
-> Maybe URI
|
||||||
-> Maybe (Either FilePath [URI]) -- ^ patches
|
-> Maybe (Either FilePath [URI]) -- ^ patches
|
||||||
@@ -779,7 +782,7 @@ compileHLS :: ( MonadMask m
|
|||||||
, BuildFailed
|
, BuildFailed
|
||||||
, NotInstalled
|
, NotInstalled
|
||||||
] m Version
|
] m Version
|
||||||
compileHLS targetHLS ghcs jobs ov installDir cabalProject cabalProjectLocal patches cabalArgs = do
|
compileHLS targetHLS ghcs jobs ov isolateDir cabalProject cabalProjectLocal patches cabalArgs = do
|
||||||
PlatformRequest { .. } <- lift getPlatformReq
|
PlatformRequest { .. } <- lift getPlatformReq
|
||||||
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||||
Dirs { .. } <- lift getDirs
|
Dirs { .. } <- lift getDirs
|
||||||
@@ -852,8 +855,8 @@ compileHLS targetHLS ghcs jobs ov installDir cabalProject cabalProjectLocal patc
|
|||||||
workdir
|
workdir
|
||||||
Nothing
|
Nothing
|
||||||
(reThrowAll @_ @'[GPGError, DownloadFailed, DigestError, PatchFailed, ProcessError, FileAlreadyExistsError, CopyError] @'[BuildFailed] (BuildFailed workdir) $ do
|
(reThrowAll @_ @'[GPGError, DownloadFailed, DigestError, PatchFailed, ProcessError, FileAlreadyExistsError, CopyError] @'[BuildFailed] (BuildFailed workdir) $ do
|
||||||
let tmpInstallDir = workdir </> "out"
|
let installDir = workdir </> "out"
|
||||||
liftIO $ createDirRecursive' tmpInstallDir
|
liftIO $ createDirRecursive' installDir
|
||||||
|
|
||||||
-- apply patches
|
-- apply patches
|
||||||
liftE $ applyAnyPatch patches workdir
|
liftE $ applyAnyPatch patches workdir
|
||||||
@@ -876,8 +879,8 @@ compileHLS targetHLS ghcs jobs ov installDir cabalProject cabalProjectLocal patc
|
|||||||
cpl <- liftE $ download uri Nothing Nothing tmpUnpack (Just (cp <.> "local")) False
|
cpl <- liftE $ download uri Nothing Nothing tmpUnpack (Just (cp <.> "local")) False
|
||||||
copyFileE cpl (workdir </> cp <.> "local")
|
copyFileE cpl (workdir </> cp <.> "local")
|
||||||
artifacts <- forM (sort ghcs) $ \ghc -> do
|
artifacts <- forM (sort ghcs) $ \ghc -> do
|
||||||
let ghcInstallDir = tmpInstallDir </> T.unpack (prettyVer ghc)
|
let ghcInstallDir = installDir </> T.unpack (prettyVer ghc)
|
||||||
liftIO $ createDirRecursive' tmpInstallDir
|
liftIO $ createDirRecursive' installDir
|
||||||
lift $ logInfo $ "Building HLS " <> prettyVer installVer <> " for GHC version " <> prettyVer ghc
|
lift $ logInfo $ "Building HLS " <> prettyVer installVer <> " for GHC version " <> prettyVer ghc
|
||||||
liftE $ lEM @_ @'[ProcessError] $
|
liftE $ lEM @_ @'[ProcessError] $
|
||||||
execLogged "cabal" ( [ "v2-install"
|
execLogged "cabal" ( [ "v2-install"
|
||||||
@@ -900,19 +903,21 @@ compileHLS targetHLS ghcs jobs ov installDir cabalProject cabalProjectLocal patc
|
|||||||
|
|
||||||
forM_ artifacts $ \artifact -> do
|
forM_ artifacts $ \artifact -> do
|
||||||
liftIO $ renameFile (artifact </> "haskell-language-server" <.> exeExt)
|
liftIO $ renameFile (artifact </> "haskell-language-server" <.> exeExt)
|
||||||
(tmpInstallDir </> "haskell-language-server-" <> takeFileName artifact <.> exeExt)
|
(installDir </> "haskell-language-server-" <> takeFileName artifact <.> exeExt)
|
||||||
liftIO $ renameFile (artifact </> "haskell-language-server-wrapper" <.> exeExt)
|
liftIO $ renameFile (artifact </> "haskell-language-server-wrapper" <.> exeExt)
|
||||||
(tmpInstallDir </> "haskell-language-server-wrapper" <.> exeExt)
|
(installDir </> "haskell-language-server-wrapper" <.> exeExt)
|
||||||
liftIO $ rmPathForcibly artifact
|
liftIO $ rmPathForcibly artifact
|
||||||
|
|
||||||
case installDir of
|
case isolateDir of
|
||||||
IsolateDir isoDir -> do
|
Just isoDir -> do
|
||||||
lift $ logInfo $ "isolated installing HLS to " <> T.pack isoDir
|
lift $ logInfo $ "isolated installing HLS to " <> T.pack isoDir
|
||||||
liftE $ installHLSUnpackedLegacy tmpInstallDir (IsolateDirResolved isoDir) installVer True
|
liftE $ installHLSUnpackedLegacy installDir isoDir Nothing True
|
||||||
GHCupInternal -> do
|
Nothing -> do
|
||||||
liftE $ installHLSUnpackedLegacy tmpInstallDir (GHCupDir binDir) installVer True
|
liftE $ installHLSUnpackedLegacy installDir binDir (Just installVer) True
|
||||||
)
|
)
|
||||||
|
|
||||||
|
liftE $ installHLSPostInst isolateDir installVer
|
||||||
|
|
||||||
pure installVer
|
pure installVer
|
||||||
|
|
||||||
|
|
||||||
@@ -934,7 +939,7 @@ installStackBin :: ( MonadMask m
|
|||||||
, MonadFail m
|
, MonadFail m
|
||||||
)
|
)
|
||||||
=> Version
|
=> Version
|
||||||
-> InstallDir
|
-> Maybe FilePath -- ^ isolate install Dir (if any)
|
||||||
-> Bool -- ^ Force install
|
-> Bool -- ^ Force install
|
||||||
-> Excepts
|
-> Excepts
|
||||||
'[ AlreadyInstalled
|
'[ AlreadyInstalled
|
||||||
@@ -951,9 +956,9 @@ installStackBin :: ( MonadMask m
|
|||||||
]
|
]
|
||||||
m
|
m
|
||||||
()
|
()
|
||||||
installStackBin ver installDir forceInstall = do
|
installStackBin ver isoFilepath forceInstall = do
|
||||||
dlinfo <- liftE $ getDownloadInfo Stack ver
|
dlinfo <- liftE $ getDownloadInfo Stack ver
|
||||||
installStackBindist dlinfo ver installDir forceInstall
|
installStackBindist dlinfo ver isoFilepath forceInstall
|
||||||
|
|
||||||
|
|
||||||
-- | Like 'installStackBin', except takes the 'DownloadInfo' as
|
-- | Like 'installStackBin', except takes the 'DownloadInfo' as
|
||||||
@@ -972,7 +977,7 @@ installStackBindist :: ( MonadMask m
|
|||||||
)
|
)
|
||||||
=> DownloadInfo
|
=> DownloadInfo
|
||||||
-> Version
|
-> Version
|
||||||
-> InstallDir
|
-> Maybe FilePath -- ^ isolate install Dir (if any)
|
||||||
-> Bool -- ^ Force install
|
-> Bool -- ^ Force install
|
||||||
-> Excepts
|
-> Excepts
|
||||||
'[ AlreadyInstalled
|
'[ AlreadyInstalled
|
||||||
@@ -989,7 +994,7 @@ installStackBindist :: ( MonadMask m
|
|||||||
]
|
]
|
||||||
m
|
m
|
||||||
()
|
()
|
||||||
installStackBindist dlinfo ver installDir forceInstall = do
|
installStackBindist dlinfo ver isoFilepath forceInstall = do
|
||||||
lift $ logDebug $ "Requested to install stack version " <> prettyVer ver
|
lift $ logDebug $ "Requested to install stack version " <> prettyVer ver
|
||||||
|
|
||||||
PlatformRequest {..} <- lift getPlatformReq
|
PlatformRequest {..} <- lift getPlatformReq
|
||||||
@@ -1000,12 +1005,12 @@ installStackBindist dlinfo ver installDir forceInstall = do
|
|||||||
if
|
if
|
||||||
| not forceInstall
|
| not forceInstall
|
||||||
, regularStackInstalled
|
, regularStackInstalled
|
||||||
, GHCupInternal <- installDir -> do
|
, Nothing <- isoFilepath -> do
|
||||||
throwE $ AlreadyInstalled Stack ver
|
throwE $ AlreadyInstalled Stack ver
|
||||||
|
|
||||||
| forceInstall
|
| forceInstall
|
||||||
, regularStackInstalled
|
, regularStackInstalled
|
||||||
, GHCupInternal <- installDir -> do
|
, Nothing <- isoFilepath -> do
|
||||||
lift $ logInfo "Removing the currently installed version of Stack first!"
|
lift $ logInfo "Removing the currently installed version of Stack first!"
|
||||||
liftE $ rmStackVer ver
|
liftE $ rmStackVer ver
|
||||||
|
|
||||||
@@ -1022,32 +1027,34 @@ installStackBindist dlinfo ver installDir forceInstall = do
|
|||||||
-- the subdir of the archive where we do the work
|
-- the subdir of the archive where we do the work
|
||||||
workdir <- maybe (pure tmpUnpack) (liftE . intoSubdir tmpUnpack) (view dlSubdir dlinfo)
|
workdir <- maybe (pure tmpUnpack) (liftE . intoSubdir tmpUnpack) (view dlSubdir dlinfo)
|
||||||
|
|
||||||
case installDir of
|
case isoFilepath of
|
||||||
IsolateDir isoDir -> do -- isolated install
|
Just isoDir -> do -- isolated install
|
||||||
lift $ logInfo $ "isolated installing Stack to " <> T.pack isoDir
|
lift $ logInfo $ "isolated installing Stack to " <> T.pack isoDir
|
||||||
liftE $ installStackUnpacked workdir (IsolateDirResolved isoDir) ver forceInstall
|
liftE $ installStackUnpacked workdir isoDir Nothing forceInstall
|
||||||
GHCupInternal -> do -- regular install
|
Nothing -> do -- regular install
|
||||||
liftE $ installStackUnpacked workdir (GHCupDir binDir) ver forceInstall
|
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.
|
-- | Install an unpacked stack distribution.
|
||||||
installStackUnpacked :: (MonadReader env m, HasLog env, MonadCatch m, MonadIO m)
|
installStackUnpacked :: (MonadReader env m, HasLog env, MonadCatch m, MonadIO m)
|
||||||
=> FilePath -- ^ Path to the unpacked stack bindist (where the executable resides)
|
=> FilePath -- ^ Path to the unpacked stack bindist (where the executable resides)
|
||||||
-> InstallDirResolved
|
-> FilePath -- ^ Path to install to
|
||||||
-> Version
|
-> Maybe Version -- ^ Nothing for isolated installs
|
||||||
-> Bool -- ^ Force install
|
-> Bool -- ^ Force install
|
||||||
-> Excepts '[CopyError, FileAlreadyExistsError] m ()
|
-> Excepts '[CopyError, FileAlreadyExistsError] m ()
|
||||||
installStackUnpacked path installDir ver forceInstall = do
|
installStackUnpacked path inst mver' forceInstall = do
|
||||||
lift $ logInfo "Installing stack"
|
lift $ logInfo "Installing stack"
|
||||||
let stackFile = "stack"
|
let stackFile = "stack"
|
||||||
liftIO $ createDirRecursive' (fromInstallDir installDir)
|
liftIO $ createDirRecursive' inst
|
||||||
let destFileName = stackFile
|
let destFileName = stackFile
|
||||||
<> (case installDir of
|
<> maybe "" (("-" <>) . T.unpack . prettyVer) mver'
|
||||||
IsolateDirResolved _ -> ""
|
|
||||||
GHCupDir _ -> ("-" <>) . T.unpack . prettyVer $ ver
|
|
||||||
)
|
|
||||||
<> exeExt
|
<> exeExt
|
||||||
destPath = fromInstallDir installDir </> destFileName
|
destPath = inst </> destFileName
|
||||||
|
|
||||||
unless forceInstall
|
unless forceInstall
|
||||||
(liftE $ throwIfFileAlreadyExists destPath)
|
(liftE $ throwIfFileAlreadyExists destPath)
|
||||||
@@ -1241,7 +1248,7 @@ setHLS :: ( MonadReader env m
|
|||||||
, MonadUnliftIO m
|
, MonadUnliftIO m
|
||||||
)
|
)
|
||||||
=> Version
|
=> Version
|
||||||
-> SetHLS
|
-> SetHLS -- Nothing for legacy
|
||||||
-> Maybe FilePath -- if set, signals that we're not operating in ~/.ghcup/bin
|
-> Maybe FilePath -- if set, signals that we're not operating in ~/.ghcup/bin
|
||||||
-- and don't want mess with other versions
|
-- and don't want mess with other versions
|
||||||
-> Excepts '[NotInstalled] m ()
|
-> Excepts '[NotInstalled] m ()
|
||||||
@@ -2139,7 +2146,7 @@ compileGHC :: ( MonadMask m
|
|||||||
-> [Text] -- ^ additional args to ./configure
|
-> [Text] -- ^ additional args to ./configure
|
||||||
-> Maybe String -- ^ build flavour
|
-> Maybe String -- ^ build flavour
|
||||||
-> Bool
|
-> Bool
|
||||||
-> InstallDir
|
-> Maybe FilePath -- ^ isolate dir
|
||||||
-> Excepts
|
-> Excepts
|
||||||
'[ AlreadyInstalled
|
'[ AlreadyInstalled
|
||||||
, BuildFailed
|
, BuildFailed
|
||||||
@@ -2164,7 +2171,7 @@ compileGHC :: ( MonadMask m
|
|||||||
]
|
]
|
||||||
m
|
m
|
||||||
GHCTargetVersion
|
GHCTargetVersion
|
||||||
compileGHC targetGhc ov bstrap jobs mbuildConfig patches aargs buildFlavour hadrian installDir
|
compileGHC targetGhc ov bstrap jobs mbuildConfig patches aargs buildFlavour hadrian isolateDir
|
||||||
= do
|
= do
|
||||||
PlatformRequest { .. } <- lift getPlatformReq
|
PlatformRequest { .. } <- lift getPlatformReq
|
||||||
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||||
@@ -2237,18 +2244,18 @@ compileGHC targetGhc ov bstrap jobs mbuildConfig patches aargs buildFlavour hadr
|
|||||||
alreadySet <- fmap (== Just installVer) $ lift $ ghcSet (_tvTarget installVer)
|
alreadySet <- fmap (== Just installVer) $ lift $ ghcSet (_tvTarget installVer)
|
||||||
|
|
||||||
when alreadyInstalled $ do
|
when alreadyInstalled $ do
|
||||||
case installDir of
|
case isolateDir of
|
||||||
IsolateDir isoDir ->
|
Just isoDir ->
|
||||||
lift $ logWarn $ "GHC " <> T.pack (prettyShow installVer) <> " already installed. Isolate installing to " <> T.pack isoDir
|
lift $ logWarn $ "GHC " <> T.pack (prettyShow installVer) <> " already installed. Isolate installing to " <> T.pack isoDir
|
||||||
GHCupInternal ->
|
Nothing ->
|
||||||
lift $ logWarn $ "GHC " <> T.pack (prettyShow installVer) <> " already installed. Will overwrite existing version."
|
lift $ logWarn $ "GHC " <> T.pack (prettyShow installVer) <> " already installed. Will overwrite existing version."
|
||||||
lift $ logWarn
|
lift $ logWarn
|
||||||
"...waiting for 10 seconds before continuing, you can still abort..."
|
"...waiting for 10 seconds before continuing, you can still abort..."
|
||||||
liftIO $ threadDelay 10000000 -- give the user a sec to intervene
|
liftIO $ threadDelay 10000000 -- give the user a sec to intervene
|
||||||
|
|
||||||
ghcdir <- case installDir of
|
ghcdir <- case isolateDir of
|
||||||
IsolateDir isoDir -> pure $ IsolateDirResolved isoDir
|
Just isoDir -> pure isoDir
|
||||||
GHCupInternal -> GHCupDir <$> lift (ghcupGHCDir installVer)
|
Nothing -> lift $ ghcupGHCDir installVer
|
||||||
|
|
||||||
(mBindist, bmk) <- liftE $ runBuildAction
|
(mBindist, bmk) <- liftE $ runBuildAction
|
||||||
tmpUnpack
|
tmpUnpack
|
||||||
@@ -2261,8 +2268,8 @@ compileGHC targetGhc ov bstrap jobs mbuildConfig patches aargs buildFlavour hadr
|
|||||||
pure (b, bmk)
|
pure (b, bmk)
|
||||||
)
|
)
|
||||||
|
|
||||||
case installDir of
|
case isolateDir of
|
||||||
GHCupInternal ->
|
Nothing ->
|
||||||
-- only remove old ghc in regular installs
|
-- only remove old ghc in regular installs
|
||||||
when alreadyInstalled $ do
|
when alreadyInstalled $ do
|
||||||
lift $ logInfo "Deleting existing installation"
|
lift $ logInfo "Deleting existing installation"
|
||||||
@@ -2277,11 +2284,11 @@ compileGHC targetGhc ov bstrap jobs mbuildConfig patches aargs buildFlavour hadr
|
|||||||
(installVer ^. tvVersion)
|
(installVer ^. tvVersion)
|
||||||
False -- not a force install, since we already overwrite when compiling.
|
False -- not a force install, since we already overwrite when compiling.
|
||||||
|
|
||||||
liftIO $ B.writeFile (fromInstallDir ghcdir </> ghcUpSrcBuiltFile) bmk
|
liftIO $ B.writeFile (ghcdir </> ghcUpSrcBuiltFile) bmk
|
||||||
|
|
||||||
case installDir of
|
case isolateDir of
|
||||||
-- set and make symlinks for regular (non-isolated) installs
|
-- set and make symlinks for regular (non-isolated) installs
|
||||||
GHCupInternal -> do
|
Nothing -> do
|
||||||
reThrowAll GHCupSetError $ postGHCInstall installVer
|
reThrowAll GHCupSetError $ postGHCInstall installVer
|
||||||
-- restore
|
-- restore
|
||||||
when alreadySet $ liftE $ void $ setGHC installVer SetGHCOnly Nothing
|
when alreadySet $ liftE $ void $ setGHC installVer SetGHCOnly Nothing
|
||||||
@@ -2310,7 +2317,7 @@ compileGHC targetGhc ov bstrap jobs mbuildConfig patches aargs buildFlavour hadr
|
|||||||
)
|
)
|
||||||
=> GHCTargetVersion
|
=> GHCTargetVersion
|
||||||
-> FilePath
|
-> FilePath
|
||||||
-> InstallDirResolved
|
-> FilePath
|
||||||
-> Excepts
|
-> Excepts
|
||||||
'[ FileDoesNotExistError
|
'[ FileDoesNotExistError
|
||||||
, HadrianNotFound
|
, HadrianNotFound
|
||||||
@@ -2369,7 +2376,7 @@ compileGHC targetGhc ov bstrap jobs mbuildConfig patches aargs buildFlavour hadr
|
|||||||
)
|
)
|
||||||
=> GHCTargetVersion
|
=> GHCTargetVersion
|
||||||
-> FilePath
|
-> FilePath
|
||||||
-> InstallDirResolved
|
-> FilePath
|
||||||
-> Excepts
|
-> Excepts
|
||||||
'[ FileDoesNotExistError
|
'[ FileDoesNotExistError
|
||||||
, HadrianNotFound
|
, HadrianNotFound
|
||||||
@@ -2504,7 +2511,7 @@ compileGHC targetGhc ov bstrap jobs mbuildConfig patches aargs buildFlavour hadr
|
|||||||
)
|
)
|
||||||
=> GHCTargetVersion
|
=> GHCTargetVersion
|
||||||
-> FilePath
|
-> FilePath
|
||||||
-> InstallDirResolved
|
-> FilePath
|
||||||
-> Excepts
|
-> Excepts
|
||||||
'[ FileDoesNotExistError
|
'[ FileDoesNotExistError
|
||||||
, InvalidBuildConfig
|
, InvalidBuildConfig
|
||||||
@@ -2515,7 +2522,7 @@ compileGHC targetGhc ov bstrap jobs mbuildConfig patches aargs buildFlavour hadr
|
|||||||
]
|
]
|
||||||
m
|
m
|
||||||
()
|
()
|
||||||
configureBindist tver workdir (fromInstallDir -> ghcdir) = do
|
configureBindist tver workdir ghcdir = do
|
||||||
lift $ logInfo [s|configuring build|]
|
lift $ logInfo [s|configuring build|]
|
||||||
|
|
||||||
if | _tvVersion tver >= [vver|8.8.0|] -> do
|
if | _tvVersion tver >= [vver|8.8.0|] -> do
|
||||||
@@ -2621,7 +2628,7 @@ upgradeGHCup mtarget force' = do
|
|||||||
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||||
|
|
||||||
lift $ logInfo "Upgrading GHCup..."
|
lift $ logInfo "Upgrading GHCup..."
|
||||||
let latestVer = fst (fromJust (getLatest dls GHCup))
|
let latestVer = fromJust $ fst <$> getLatest dls GHCup
|
||||||
(Just ghcupPVPVer) <- pure $ pvpToVersion ghcUpVer ""
|
(Just ghcupPVPVer) <- pure $ pvpToVersion ghcUpVer ""
|
||||||
when (not force' && (latestVer <= ghcupPVPVer)) $ throwE NoUpdate
|
when (not force' && (latestVer <= ghcupPVPVer)) $ throwE NoUpdate
|
||||||
dli <- liftE $ getDownloadInfo GHCup latestVer
|
dli <- liftE $ getDownloadInfo GHCup latestVer
|
||||||
|
|||||||
@@ -121,25 +121,28 @@ 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 exts) -> do
|
(OwnSource url) -> liftE $ getBase url
|
||||||
ext <- liftE $ mapM (either pure getBase) exts
|
|
||||||
mergeGhcupInfo ext
|
|
||||||
(OwnSpec av) -> pure av
|
(OwnSpec av) -> pure av
|
||||||
(AddSource exts) -> do
|
(AddSource (Left ext)) -> do
|
||||||
base <- liftE $ getBase ghcupURL
|
base <- liftE $ getBase ghcupURL
|
||||||
ext <- liftE $ mapM (either pure getBase) exts
|
pure (mergeGhcupInfo base ext)
|
||||||
mergeGhcupInfo (base:ext)
|
(AddSource (Right uri)) -> do
|
||||||
|
base <- liftE $ getBase ghcupURL
|
||||||
|
ext <- liftE $ getBase uri
|
||||||
|
pure (mergeGhcupInfo base ext)
|
||||||
|
|
||||||
where
|
where
|
||||||
mergeGhcupInfo :: MonadFail m
|
|
||||||
=> [GHCupInfo]
|
mergeGhcupInfo :: GHCupInfo -- ^ base to merge with
|
||||||
-> m GHCupInfo
|
-> GHCupInfo -- ^ extension overwriting the base
|
||||||
mergeGhcupInfo [] = fail "mergeGhcupInfo: internal error: need at least one GHCupInfo"
|
-> GHCupInfo
|
||||||
mergeGhcupInfo xs@(GHCupInfo{}: _) =
|
mergeGhcupInfo (GHCupInfo tr base base2) (GHCupInfo _ ext ext2) =
|
||||||
let newDownloads = M.unionsWith (M.unionWith (\_ b2 -> b2)) (_ghcupDownloads <$> xs)
|
let newDownloads = M.mapWithKey (\k a -> case M.lookup k ext of
|
||||||
newGlobalTools = M.unionsWith (\_ a2 -> a2 ) (_globalTools <$> xs)
|
Just a' -> M.union a' a
|
||||||
newToolReqs = M.unionsWith (M.unionWith (\_ b2 -> b2)) (_toolRequirements <$> xs)
|
Nothing -> a
|
||||||
in pure $ GHCupInfo newToolReqs newDownloads newGlobalTools
|
) base
|
||||||
|
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
|
||||||
|
|||||||
@@ -67,9 +67,3 @@ prettyRequirements Requirements {..} =
|
|||||||
else ""
|
else ""
|
||||||
n = if not . T.null $ _notes then "\n Note: " <> _notes else ""
|
n = if not . T.null $ _notes then "\n Note: " <> _notes else ""
|
||||||
in "System requirements " <> d <> n
|
in "System requirements " <> d <> n
|
||||||
|
|
||||||
rawRequirements :: Requirements -> T.Text
|
|
||||||
rawRequirements Requirements {..} =
|
|
||||||
if not . null $ _distroPKGs
|
|
||||||
then T.intercalate " " _distroPKGs
|
|
||||||
else ""
|
|
||||||
|
|||||||
@@ -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 [Either GHCupInfo URI] -- ^ complete source list
|
| OwnSource URI
|
||||||
| 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
|
||||||
@@ -628,16 +628,3 @@ data CapturedProcess = CapturedProcess
|
|||||||
deriving (Eq, Show)
|
deriving (Eq, Show)
|
||||||
|
|
||||||
makeLenses ''CapturedProcess
|
makeLenses ''CapturedProcess
|
||||||
|
|
||||||
|
|
||||||
data InstallDir = IsolateDir FilePath
|
|
||||||
| GHCupInternal
|
|
||||||
deriving (Eq, Show)
|
|
||||||
|
|
||||||
data InstallDirResolved = IsolateDirResolved FilePath
|
|
||||||
| GHCupDir FilePath
|
|
||||||
deriving (Eq, Show)
|
|
||||||
|
|
||||||
fromInstallDir :: InstallDirResolved -> FilePath
|
|
||||||
fromInstallDir (IsolateDirResolved fp) = fp
|
|
||||||
fromInstallDir (GHCupDir fp) = fp
|
|
||||||
|
|||||||
@@ -79,38 +79,6 @@ 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
|
||||||
@@ -346,7 +314,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
|
||||||
deriveToJSON defaultOptions { sumEncoding = ObjectWithSingleField } ''URLSource
|
deriveJSON 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
|
||||||
|
|||||||
@@ -317,10 +317,10 @@ ghcSet mtarget = do
|
|||||||
MP.setInput rest
|
MP.setInput rest
|
||||||
pure x
|
pure x
|
||||||
)
|
)
|
||||||
<* MP.some pathSep
|
<* pathSep
|
||||||
<* MP.takeRest
|
<* MP.takeRest
|
||||||
<* MP.eof
|
<* MP.eof
|
||||||
ghcSubPath = MP.some pathSep <* MP.chunk "ghc" *> MP.some pathSep
|
ghcSubPath = pathSep <* MP.chunk "ghc" *> pathSep
|
||||||
|
|
||||||
-- | Get all installed GHCs by reading ~/.ghcup/ghc/<dir>.
|
-- | Get all installed GHCs by reading ~/.ghcup/ghc/<dir>.
|
||||||
-- If a dir cannot be parsed, returns left.
|
-- If a dir cannot be parsed, returns left.
|
||||||
@@ -398,10 +398,10 @@ cabalSet = do
|
|||||||
cabalParse = MP.chunk "cabal-" *> version'
|
cabalParse = MP.chunk "cabal-" *> version'
|
||||||
-- parses any path component ending with path separator,
|
-- parses any path component ending with path separator,
|
||||||
-- e.g. "foo/"
|
-- e.g. "foo/"
|
||||||
stripPathComponet = parseUntil1 pathSep *> MP.some pathSep
|
stripPathComponet = parseUntil1 pathSep *> pathSep
|
||||||
-- parses an absolute path up until the last path separator,
|
-- parses an absolute path up until the last path separator,
|
||||||
-- e.g. "/bar/baz/foo" -> "/bar/baz/", leaving "foo"
|
-- e.g. "/bar/baz/foo" -> "/bar/baz/", leaving "foo"
|
||||||
stripAbsolutePath = MP.some pathSep *> MP.many (MP.try stripPathComponet)
|
stripAbsolutePath = pathSep *> MP.many (MP.try stripPathComponet)
|
||||||
-- parses a relative path up until the last path separator,
|
-- parses a relative path up until the last path separator,
|
||||||
-- e.g. "bar/baz/foo" -> "bar/baz/", leaving "foo"
|
-- e.g. "bar/baz/foo" -> "bar/baz/", leaving "foo"
|
||||||
stripRelativePath = MP.many (MP.try stripPathComponet)
|
stripRelativePath = MP.many (MP.try stripPathComponet)
|
||||||
@@ -492,10 +492,10 @@ stackSet = do
|
|||||||
cabalParse = MP.chunk "stack-" *> version'
|
cabalParse = MP.chunk "stack-" *> version'
|
||||||
-- parses any path component ending with path separator,
|
-- parses any path component ending with path separator,
|
||||||
-- e.g. "foo/"
|
-- e.g. "foo/"
|
||||||
stripPathComponet = parseUntil1 pathSep *> MP.some pathSep
|
stripPathComponet = parseUntil1 pathSep *> pathSep
|
||||||
-- parses an absolute path up until the last path separator,
|
-- parses an absolute path up until the last path separator,
|
||||||
-- e.g. "/bar/baz/foo" -> "/bar/baz/", leaving "foo"
|
-- e.g. "/bar/baz/foo" -> "/bar/baz/", leaving "foo"
|
||||||
stripAbsolutePath = MP.some pathSep *> MP.many (MP.try stripPathComponet)
|
stripAbsolutePath = pathSep *> MP.many (MP.try stripPathComponet)
|
||||||
-- parses a relative path up until the last path separator,
|
-- parses a relative path up until the last path separator,
|
||||||
-- e.g. "bar/baz/foo" -> "bar/baz/", leaving "foo"
|
-- e.g. "bar/baz/foo" -> "bar/baz/", leaving "foo"
|
||||||
stripRelativePath = MP.many (MP.try stripPathComponet)
|
stripRelativePath = MP.many (MP.try stripPathComponet)
|
||||||
@@ -543,10 +543,10 @@ hlsSet = do
|
|||||||
cabalParse = MP.chunk "haskell-language-server-wrapper-" *> version'
|
cabalParse = MP.chunk "haskell-language-server-wrapper-" *> version'
|
||||||
-- parses any path component ending with path separator,
|
-- parses any path component ending with path separator,
|
||||||
-- e.g. "foo/"
|
-- e.g. "foo/"
|
||||||
stripPathComponet = parseUntil1 pathSep *> MP.some pathSep
|
stripPathComponet = parseUntil1 pathSep *> pathSep
|
||||||
-- parses an absolute path up until the last path separator,
|
-- parses an absolute path up until the last path separator,
|
||||||
-- e.g. "/bar/baz/foo" -> "/bar/baz/", leaving "foo"
|
-- e.g. "/bar/baz/foo" -> "/bar/baz/", leaving "foo"
|
||||||
stripAbsolutePath = MP.some pathSep *> MP.many (MP.try stripPathComponet)
|
stripAbsolutePath = pathSep *> MP.many (MP.try stripPathComponet)
|
||||||
-- parses a relative path up until the last path separator,
|
-- parses a relative path up until the last path separator,
|
||||||
-- e.g. "bar/baz/foo" -> "bar/baz/", leaving "foo"
|
-- e.g. "bar/baz/foo" -> "bar/baz/", leaving "foo"
|
||||||
stripRelativePath = MP.many (MP.try stripPathComponet)
|
stripRelativePath = MP.many (MP.try stripPathComponet)
|
||||||
@@ -1265,10 +1265,9 @@ ghcBinaryName (GHCTargetVersion Nothing _) = T.unpack ("ghc" <> T.pack exeExt)
|
|||||||
installDestSanityCheck :: ( MonadIO m
|
installDestSanityCheck :: ( MonadIO m
|
||||||
, MonadCatch m
|
, MonadCatch m
|
||||||
) =>
|
) =>
|
||||||
InstallDirResolved ->
|
FilePath ->
|
||||||
Excepts '[DirNotEmpty] m ()
|
Excepts '[DirNotEmpty] m ()
|
||||||
installDestSanityCheck (IsolateDirResolved isoDir) = do
|
installDestSanityCheck isoDir = do
|
||||||
hideErrorDef [doesNotExistErrorType] () $ do
|
hideErrorDef [doesNotExistErrorType] () $ do
|
||||||
contents <- liftIO $ getDirectoryContentsRecursive isoDir
|
contents <- liftIO $ getDirectoryContentsRecursive isoDir
|
||||||
unless (null contents) (throwE $ DirNotEmpty isoDir)
|
unless (null contents) (throwE $ DirNotEmpty isoDir)
|
||||||
installDestSanityCheck _ = pure ()
|
|
||||||
|
|||||||
@@ -339,15 +339,13 @@ useXDG = isJust <$> lookupEnv "GHCUP_USE_XDG_DIRS"
|
|||||||
relativeSymlink :: FilePath -- ^ the path in which to create the symlink
|
relativeSymlink :: FilePath -- ^ the path in which to create the symlink
|
||||||
-> FilePath -- ^ the symlink destination
|
-> FilePath -- ^ the symlink destination
|
||||||
-> FilePath
|
-> FilePath
|
||||||
relativeSymlink p1 p2
|
relativeSymlink p1 p2 =
|
||||||
| isWindows = p2 -- windows quickly gets into MAX_PATH issues so we don't care about relative symlinks
|
let d1 = splitDirectories p1
|
||||||
| otherwise =
|
d2 = splitDirectories p2
|
||||||
let d1 = splitDirectories p1
|
common = takeWhile (\(x, y) -> x == y) $ zip d1 d2
|
||||||
d2 = splitDirectories p2
|
cPrefix = drop (length common) d1
|
||||||
common = takeWhile (\(x, y) -> x == y) $ zip d1 d2
|
in joinPath (replicate (length cPrefix) "..")
|
||||||
cPrefix = drop (length common) d1
|
<> joinPath ([pathSeparator] : drop (length common) d2)
|
||||||
in joinPath (replicate (length cPrefix) "..")
|
|
||||||
<> joinPath ([pathSeparator] : drop (length common) d2)
|
|
||||||
|
|
||||||
|
|
||||||
cleanupTrash :: ( MonadIO m
|
cleanupTrash :: ( MonadIO m
|
||||||
|
|||||||
@@ -473,7 +473,7 @@ recyclePathForcibly fp
|
|||||||
liftIO (moveFile fp dest)
|
liftIO (moveFile fp dest)
|
||||||
`catch`
|
`catch`
|
||||||
(\e -> if | isDoesNotExistError e -> pure ()
|
(\e -> if | isDoesNotExistError e -> pure ()
|
||||||
| isPermissionError e || ioeGetErrorType e == UnsupportedOperation {- EXDEV on windows -} -> recover (liftIO $ removePathForcibly fp)
|
| isPermissionError e {- EXDEV on windows -} -> recover (liftIO $ removePathForcibly fp)
|
||||||
| otherwise -> throwIO e)
|
| otherwise -> throwIO e)
|
||||||
`finally`
|
`finally`
|
||||||
liftIO (handleIO (\_ -> pure ()) $ removePathForcibly tmp)
|
liftIO (handleIO (\_ -> pure ()) $ removePathForcibly tmp)
|
||||||
@@ -515,7 +515,7 @@ recycleFile fp
|
|||||||
let dest = tmp </> takeFileName fp
|
let dest = tmp </> takeFileName fp
|
||||||
liftIO (moveFile fp dest)
|
liftIO (moveFile fp dest)
|
||||||
`catch`
|
`catch`
|
||||||
(\e -> if isPermissionError e || ioeGetErrorType e == UnsupportedOperation {- EXDEV on windows -} then recover (liftIO $ removePathForcibly fp) else throwIO e)
|
(\e -> if isPermissionError e {- EXDEV on windows -} then recover (liftIO $ removePathForcibly fp) else throwIO e)
|
||||||
`finally`
|
`finally`
|
||||||
liftIO (handleIO (\_ -> pure ()) $ removePathForcibly tmp)
|
liftIO (handleIO (\_ -> pure ()) $ removePathForcibly tmp)
|
||||||
| otherwise = liftIO $ removeFile fp
|
| otherwise = liftIO $ removeFile fp
|
||||||
|
|||||||
@@ -13,8 +13,7 @@ theme:
|
|||||||
|
|
||||||
nav:
|
nav:
|
||||||
- Home: index.md
|
- Home: index.md
|
||||||
- "Getting started": install.md
|
- "Getting Started": install.md
|
||||||
- "First steps": steps.md
|
|
||||||
- "User Guide": guide.md
|
- "User Guide": guide.md
|
||||||
- "Developer Guide": dev.md
|
- "Developer Guide": dev.md
|
||||||
- About: about.md
|
- About: about.md
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
# * BOOTSTRAP_HASKELL_INSTALL_HLS - whether to install latest hls
|
# * BOOTSTRAP_HASKELL_INSTALL_HLS - whether to install latest hls
|
||||||
# * BOOTSTRAP_HASKELL_ADJUST_BASHRC - whether to adjust PATH in bashrc (prepend)
|
# * BOOTSTRAP_HASKELL_ADJUST_BASHRC - whether to adjust PATH in bashrc (prepend)
|
||||||
# * BOOTSTRAP_HASKELL_ADJUST_CABAL_CONFIG - whether to adjust mingw paths in cabal.config on windows
|
# * BOOTSTRAP_HASKELL_ADJUST_CABAL_CONFIG - whether to adjust mingw paths in cabal.config on windows
|
||||||
# * GHCUP_BASE_URL - the base url for ghcup binary download (use this to overwrite https://downloads.haskell.org/~ghcup with a mirror)
|
|
||||||
|
|
||||||
# License: LGPL-3.0
|
# License: LGPL-3.0
|
||||||
|
|
||||||
@@ -26,8 +25,8 @@
|
|||||||
|
|
||||||
plat="$(uname -s)"
|
plat="$(uname -s)"
|
||||||
arch=$(uname -m)
|
arch=$(uname -m)
|
||||||
ghver="0.1.17.7"
|
ghver="0.1.17.5"
|
||||||
: "${GHCUP_BASE_URL:=https://downloads.haskell.org/~ghcup}"
|
base_url="https://downloads.haskell.org/~ghcup"
|
||||||
|
|
||||||
export GHCUP_SKIP_UPDATE_CHECK=yes
|
export GHCUP_SKIP_UPDATE_CHECK=yes
|
||||||
|
|
||||||
@@ -158,7 +157,7 @@ _done() {
|
|||||||
green "and the \"Mingw package management docs\""
|
green "and the \"Mingw package management docs\""
|
||||||
green "desktop shortcuts."
|
green "desktop shortcuts."
|
||||||
green
|
green
|
||||||
green "If you are new to Haskell, check out https://www.haskell.org/ghcup/steps/"
|
green "If you are new to Haskell, check out https://www.haskell.org/ghcup/install/#first-steps"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
green
|
green
|
||||||
@@ -173,7 +172,7 @@ _done() {
|
|||||||
green "To install other GHC versions and tools, run:"
|
green "To install other GHC versions and tools, run:"
|
||||||
green " ghcup tui"
|
green " ghcup tui"
|
||||||
green
|
green
|
||||||
green "If you are new to Haskell, check out https://www.haskell.org/ghcup/steps/"
|
green "If you are new to Haskell, check out https://www.haskell.org/ghcup/install/#first-steps"
|
||||||
;;
|
;;
|
||||||
|
|
||||||
esac
|
esac
|
||||||
@@ -182,51 +181,6 @@ _done() {
|
|||||||
exit 0
|
exit 0
|
||||||
}
|
}
|
||||||
|
|
||||||
# @FUNCTION: posix_realpath
|
|
||||||
# @USAGE: <file>
|
|
||||||
# @DESCRIPTION:
|
|
||||||
# Portably gets the realpath and prints it to stdout.
|
|
||||||
# This was initially inspired by
|
|
||||||
# https://gist.github.com/tvlooy/cbfbdb111a4ebad8b93e
|
|
||||||
# and
|
|
||||||
# https://stackoverflow.com/a/246128
|
|
||||||
#
|
|
||||||
# If the file does not exist, just prints it appended to the current directory.
|
|
||||||
# @STDOUT: realpath of the given file
|
|
||||||
posix_realpath() {
|
|
||||||
[ -z "$1" ] && die "Internal error: no argument given to posix_realpath"
|
|
||||||
current_loop=0
|
|
||||||
max_loops=50
|
|
||||||
mysource=$1
|
|
||||||
# readlink and '[ -h $path ]' behave different wrt '/sbin/' and '/sbin', so we strip it
|
|
||||||
mysource=${mysource%/}
|
|
||||||
[ -z "${mysource}" ] && mysource=$1
|
|
||||||
|
|
||||||
while [ -h "${mysource}" ]; do
|
|
||||||
current_loop=$((current_loop+1))
|
|
||||||
mydir="$( cd -P "$( dirname "${mysource}" )" > /dev/null 2>&1 && pwd )"
|
|
||||||
mysource="$(readlink "${mysource}")"
|
|
||||||
[ "${mysource%"${mysource#?}"}"x != '/x' ] && mysource="${mydir%/}/${mysource}"
|
|
||||||
|
|
||||||
if [ ${current_loop} -gt ${max_loops} ] ; then
|
|
||||||
(>&2 echo "${1}: Too many levels of symbolic links")
|
|
||||||
echo "$1"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
mydir="$( cd -P "$( dirname "${mysource}" )" > /dev/null 2>&1 && pwd )"
|
|
||||||
|
|
||||||
# TODO: better distinguish between "does not exist" and "permission denied"
|
|
||||||
if [ -z "${mydir}" ] ; then
|
|
||||||
(>&2 echo "${1}: Permission denied")
|
|
||||||
echo "$(pwd)/$1"
|
|
||||||
else
|
|
||||||
echo "${mydir%/}/$(basename "${mysource}")"
|
|
||||||
fi
|
|
||||||
|
|
||||||
unset current_loop max_loops mysource mydir
|
|
||||||
}
|
|
||||||
|
|
||||||
download_ghcup() {
|
download_ghcup() {
|
||||||
|
|
||||||
case "${plat}" in
|
case "${plat}" in
|
||||||
@@ -236,26 +190,26 @@ download_ghcup() {
|
|||||||
# we could be in a 32bit docker container, in which
|
# we could be in a 32bit docker container, in which
|
||||||
# case uname doesn't give us what we want
|
# case uname doesn't give us what we want
|
||||||
if [ "$(getconf LONG_BIT)" = "32" ] ; then
|
if [ "$(getconf LONG_BIT)" = "32" ] ; then
|
||||||
_url=${GHCUP_BASE_URL}/${ghver}/i386-linux-ghcup-${ghver}
|
_url=${base_url}/${ghver}/i386-linux-ghcup-${ghver}
|
||||||
elif [ "$(getconf LONG_BIT)" = "64" ] ; then
|
elif [ "$(getconf LONG_BIT)" = "64" ] ; then
|
||||||
_url=${GHCUP_BASE_URL}/${ghver}/x86_64-linux-ghcup-${ghver}
|
_url=${base_url}/${ghver}/x86_64-linux-ghcup-${ghver}
|
||||||
else
|
else
|
||||||
die "Unknown long bit size: $(getconf LONG_BIT)"
|
die "Unknown long bit size: $(getconf LONG_BIT)"
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
i*86)
|
i*86)
|
||||||
_url=${GHCUP_BASE_URL}/${ghver}/i386-linux-ghcup-${ghver}
|
_url=${base_url}/${ghver}/i386-linux-ghcup-${ghver}
|
||||||
;;
|
;;
|
||||||
armv7*|*armv8l*)
|
armv7*|*armv8l*)
|
||||||
_url=${GHCUP_BASE_URL}/${ghver}/armv7-linux-ghcup-${ghver}
|
_url=${base_url}/${ghver}/armv7-linux-ghcup-${ghver}
|
||||||
;;
|
;;
|
||||||
aarch64|arm64)
|
aarch64|arm64)
|
||||||
# we could be in a 32bit docker container, in which
|
# we could be in a 32bit docker container, in which
|
||||||
# case uname doesn't give us what we want
|
# case uname doesn't give us what we want
|
||||||
if [ "$(getconf LONG_BIT)" = "32" ] ; then
|
if [ "$(getconf LONG_BIT)" = "32" ] ; then
|
||||||
_url=${GHCUP_BASE_URL}/${ghver}/armv7-linux-ghcup-${ghver}
|
_url=${base_url}/${ghver}/armv7-linux-ghcup-${ghver}
|
||||||
elif [ "$(getconf LONG_BIT)" = "64" ] ; then
|
elif [ "$(getconf LONG_BIT)" = "64" ] ; then
|
||||||
_url=${GHCUP_BASE_URL}/${ghver}/aarch64-linux-ghcup-${ghver}
|
_url=${base_url}/${ghver}/aarch64-linux-ghcup-${ghver}
|
||||||
else
|
else
|
||||||
die "Unknown long bit size: $(getconf LONG_BIT)"
|
die "Unknown long bit size: $(getconf LONG_BIT)"
|
||||||
fi
|
fi
|
||||||
@@ -282,15 +236,15 @@ download_ghcup() {
|
|||||||
*) die "Unknown architecture: ${arch}"
|
*) die "Unknown architecture: ${arch}"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
_url=${GHCUP_BASE_URL}/${ghver}/x86_64-freebsd${freebsd_ver}-ghcup-${ghver}
|
_url=${base_url}/${ghver}/x86_64-freebsd${freebsd_ver}-ghcup-${ghver}
|
||||||
;;
|
;;
|
||||||
"Darwin"|"darwin")
|
"Darwin"|"darwin")
|
||||||
case "${arch}" in
|
case "${arch}" in
|
||||||
x86_64|amd64)
|
x86_64|amd64)
|
||||||
_url=${GHCUP_BASE_URL}/${ghver}/x86_64-apple-darwin-ghcup-${ghver}
|
_url=${base_url}/${ghver}/x86_64-apple-darwin-ghcup-${ghver}
|
||||||
;;
|
;;
|
||||||
aarch64|arm64|armv8l)
|
aarch64|arm64|armv8l)
|
||||||
_url=${GHCUP_BASE_URL}/${ghver}/aarch64-apple-darwin-ghcup-${ghver}
|
_url=${base_url}/${ghver}/aarch64-apple-darwin-ghcup-${ghver}
|
||||||
;;
|
;;
|
||||||
i*86)
|
i*86)
|
||||||
die "i386 currently not supported!"
|
die "i386 currently not supported!"
|
||||||
@@ -302,7 +256,7 @@ download_ghcup() {
|
|||||||
MSYS*|MINGW*)
|
MSYS*|MINGW*)
|
||||||
case "${arch}" in
|
case "${arch}" in
|
||||||
x86_64|amd64)
|
x86_64|amd64)
|
||||||
_url=${GHCUP_BASE_URL}/${ghver}/x86_64-mingw64-ghcup-${ghver}.exe
|
_url=${base_url}/${ghver}/x86_64-mingw64-ghcup-${ghver}.exe
|
||||||
;;
|
;;
|
||||||
*) die "Unknown architecture: ${arch}"
|
*) die "Unknown architecture: ${arch}"
|
||||||
;;
|
;;
|
||||||
@@ -473,23 +427,23 @@ adjust_bashrc() {
|
|||||||
;;
|
;;
|
||||||
fish)
|
fish)
|
||||||
mkdir -p "${GHCUP_PROFILE_FILE%/*}"
|
mkdir -p "${GHCUP_PROFILE_FILE%/*}"
|
||||||
sed -i -e '/# ghcup-env$/ s/^#*/#/' "$(posix_realpath "${GHCUP_PROFILE_FILE}")"
|
sed -i -e '/# ghcup-env$/ s/^#*/#/' "${GHCUP_PROFILE_FILE}"
|
||||||
case $1 in
|
case $1 in
|
||||||
1)
|
1)
|
||||||
printf "\n%s" "set -q GHCUP_INSTALL_BASE_PREFIX[1]; or set GHCUP_INSTALL_BASE_PREFIX \$HOME ; set -gx PATH \$HOME/.cabal/bin $GHCUP_BIN \$PATH # ghcup-env" >> "${GHCUP_PROFILE_FILE}"
|
echo "set -q GHCUP_INSTALL_BASE_PREFIX[1]; or set GHCUP_INSTALL_BASE_PREFIX \$HOME ; set -gx PATH \$HOME/.cabal/bin $GHCUP_BIN \$PATH # ghcup-env" >> "${GHCUP_PROFILE_FILE}"
|
||||||
;;
|
;;
|
||||||
2)
|
2)
|
||||||
printf "\n%s" "set -q GHCUP_INSTALL_BASE_PREFIX[1]; or set GHCUP_INSTALL_BASE_PREFIX \$HOME ; set -gx PATH \$HOME/.cabal/bin \$PATH $GHCUP_BIN # ghcup-env" >> "${GHCUP_PROFILE_FILE}"
|
echo "set -q GHCUP_INSTALL_BASE_PREFIX[1]; or set GHCUP_INSTALL_BASE_PREFIX \$HOME ; set -gx PATH \$HOME/.cabal/bin \$PATH $GHCUP_BIN # ghcup-env" >> "${GHCUP_PROFILE_FILE}"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
bash)
|
bash)
|
||||||
sed -i -e '/# ghcup-env$/ s/^#*/#/' "$(posix_realpath "${GHCUP_PROFILE_FILE}")"
|
sed -i -e '/# ghcup-env$/ s/^#*/#/' "${GHCUP_PROFILE_FILE}"
|
||||||
printf "\n%s" "[ -f \"${GHCUP_DIR}/env\" ] && source \"${GHCUP_DIR}/env\" # ghcup-env" >> "${GHCUP_PROFILE_FILE}"
|
echo "[ -f \"${GHCUP_DIR}/env\" ] && source \"${GHCUP_DIR}/env\" # ghcup-env" >> "${GHCUP_PROFILE_FILE}"
|
||||||
case "${plat}" in
|
case "${plat}" in
|
||||||
"Darwin"|"darwin")
|
"Darwin"|"darwin")
|
||||||
if ! grep -q "ghcup-env" "${HOME}/.bash_profile" ; then
|
if ! grep -q "ghcup-env" "${HOME}/.bash_profile" ; then
|
||||||
printf "\n%s" "[[ -f ~/.bashrc ]] && source ~/.bashrc # ghcup-env" >> "${HOME}/.bash_profile"
|
echo "[[ -f ~/.bashrc ]] && source ~/.bashrc # ghcup-env" >> "${HOME}/.bash_profile"
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
MSYS*|MINGW*)
|
MSYS*|MINGW*)
|
||||||
@@ -503,8 +457,8 @@ adjust_bashrc() {
|
|||||||
;;
|
;;
|
||||||
|
|
||||||
zsh)
|
zsh)
|
||||||
sed -i -e '/# ghcup-env$/ s/^#*/#/' "$(posix_realpath "${GHCUP_PROFILE_FILE}")"
|
sed -i -e '/# ghcup-env$/ s/^#*/#/' "${GHCUP_PROFILE_FILE}"
|
||||||
printf "\n%s" "[ -f \"${GHCUP_DIR}/env\" ] && source \"${GHCUP_DIR}/env\" # ghcup-env" >> "${GHCUP_PROFILE_FILE}"
|
echo "[ -f \"${GHCUP_DIR}/env\" ] && source \"${GHCUP_DIR}/env\" # ghcup-env" >> "${GHCUP_PROFILE_FILE}"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
echo
|
echo
|
||||||
|
|||||||
@@ -239,27 +239,7 @@ if ($Silent -and !($InstallDir)) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
while ($true) {
|
while ($true) {
|
||||||
Print-Msg -color Magenta -msg (@'
|
Print-Msg -color Magenta -msg ('Where to install to (this should be a short Path, preferably a Drive like ''C:\''){1}Press enter to accept the default [{0}]:' -f $defaultGhcupBasePrefix, "`n")
|
||||||
Welcome to Haskell!
|
|
||||||
|
|
||||||
This script will download and install the following programs:
|
|
||||||
* ghcup - The Haskell toolchain installer
|
|
||||||
* ghc - The Glasgow Haskell Compiler
|
|
||||||
* msys2 - A linux-style toolchain environment required for many operations
|
|
||||||
* cabal - The Cabal build tool for managing Haskell software
|
|
||||||
* stack - (optional) A cross-platform program for developing Haskell projects
|
|
||||||
* hls - (optional) A language server for developers to integrate with their editor/IDE
|
|
||||||
|
|
||||||
Please note that ANTIVIRUS may interfere with the installation. If you experience problems, consider
|
|
||||||
disabling it temporarily.
|
|
||||||
|
|
||||||
Where to install to (this should be a short Path, preferably a Drive like 'C:\')?
|
|
||||||
If you accept this path, binaries will be installed into '{0}ghcup\bin' and msys2 into '{0}ghcup\msys64'.
|
|
||||||
Press enter to accept the default [{0}]:
|
|
||||||
|
|
||||||
'@ -f $defaultGhcupBasePrefix)
|
|
||||||
|
|
||||||
|
|
||||||
$basePrefixPrompt = Read-Host
|
$basePrefixPrompt = Read-Host
|
||||||
$GhcupBasePrefix = ($defaultGhcupBasePrefix,$basePrefixPrompt)[[bool]$basePrefixPrompt]
|
$GhcupBasePrefix = ($defaultGhcupBasePrefix,$basePrefixPrompt)[[bool]$basePrefixPrompt]
|
||||||
if (!($GhcupBasePrefix.EndsWith('\'))) {
|
if (!($GhcupBasePrefix.EndsWith('\'))) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
resolver: lts-18.28
|
resolver: lts-18.25
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
- .
|
- .
|
||||||
@@ -16,7 +16,6 @@ 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
|
||||||
@@ -40,6 +39,11 @@ 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