Compare commits

..

62 Commits

Author SHA1 Message Date
3c5505d222 Fix disabling installation of stack
Fixes #429
2022-11-10 22:38:30 +08:00
787edc17af Improve stack GHC install script 2022-09-30 13:59:43 +08:00
9902adab6d Make stack GHC install hook posix compliant
See https://github.com/commercialhaskell/stack/issues/5888
2022-09-30 13:29:57 +08:00
156b4724f3 Merge branch 'stack-hook' 2022-09-26 22:53:40 +08:00
e9575aba5c Add stack ghc installation hooks and install stack by default 2022-09-22 00:04:14 +08:00
81c7f6a32a Merge remote-tracking branch 'origin/merge-requests/283' 2022-08-24 22:34:21 +08:00
taylorfausak
ab97c80b80 Fix build error 2022-08-23 11:59:08 +00:00
taylorfausak
04369673ef Fix spacing 2022-08-23 11:19:33 +00:00
taylorfausak
63dfdc2da6 Remove hard-coded reference to "cabal"
Fixes #407.
2022-08-22 19:35:38 +00:00
14de382129 Merge remote-tracking branch 'origin/merge-requests/282' 2022-08-12 22:20:45 +08:00
d97c10dbe6 Merge remote-tracking branch 'origin/merge-requests/281' 2022-08-12 22:20:25 +08:00
Cheng Shao
8420bf093e Update ghc-head bindist URL 2022-08-09 13:32:58 +00:00
amesgen
5e28074522 Account for GHC 9.4.1 2022-08-09 00:43:55 +02:00
c842c41a78 Bump to 0.1.18.1 for hackage 2022-08-06 19:11:47 +08:00
8b93eaad59 cabal-fmt 2022-08-06 19:08:34 +08:00
2cba97cf1c Merge remote-tracking branch 'origin/merge-requests/277' 2022-08-06 19:07:59 +08:00
7d74178295 Merge remote-tracking branch 'origin/merge-requests/279' 2022-08-06 19:07:50 +08:00
c37bef55e9 Merge remote-tracking branch 'origin/merge-requests/278' 2022-08-06 19:07:34 +08:00
837ba8b46a Merge remote-tracking branch 'origin/merge-requests/280' 2022-08-06 17:41:09 +08:00
Dmitrii Kovanikov
c25e73408a Change attribution for the Haskell Beginners 2022 course 2022-08-06 09:33:01 +00:00
why-not-try-calmer
71c3172cf5 Less duplication. 2022-08-05 13:03:02 +02:00
why-not-try-calmer
1f2855a107 Added and referenced solution in case of 'ghc version not found' for Linux VSCode + hls extension users. 2022-08-05 12:51:46 +02:00
Artem Pelenitsyn
d949c4375e docs: add example of installing bindinst specified by job id 2022-08-05 02:27:35 +00:00
FTS
22f0081303 include c header file in sdict 2022-07-30 16:41:16 +00:00
5562be18e3 More docs improvements 2022-07-30 17:18:42 +08:00
6baa891424 Update metadata 2022-07-30 10:51:41 +08:00
a544feffb3 Finalize release 2022-07-30 10:29:34 +08:00
3b6bb0df46 Add changelog 2022-07-29 21:52:56 +08:00
60299b6bb8 Update HLS doc link 2022-07-27 23:29:33 +08:00
4d20f4e07c Merge branch 'issue-391' 2022-07-25 20:33:21 +08:00
5f6b5f845d Add --disable-ld-override for darwin bindists
Fixes #391
2022-07-25 17:57:10 +08:00
b0fecce0d1 Merge remote-tracking branch 'origin/merge-requests/273' 2022-07-24 20:24:00 +08:00
Mike Pilgrem
27c06ddde7 Fix #293 Document expressly how installation scripts can be customised
The proposed addition does not go into the mechanism (the names of the specific environment variables or the PowerShell parameters) but is more express about in what manner the behaviour of the installation scripts can be changed.

Introduces that important flexibility as the first topic under 'More on installation'.

Explains that the PowerShell script finally (by default) runs the script for Unix-like operating systems (so a Windows user understands better that the environment variables in the former are applicable to both, and what is meant by the 'final' bootstrap script in the content of the Windows parameters).

Refers to what has gone before, under 'Continuous integration', rather than repeat the added content.
2022-07-23 21:32:15 +01:00
3154d2839b Merge remote-tracking branch 'origin/merge-requests/272' 2022-07-23 23:27:33 +08:00
Mike Pilgrem
511d8d5ed8 Update guide.md to explain what is meant by 'TUI'. 2022-07-23 14:25:49 +00:00
fe22405ee1 Merge branch 'issue-383' 2022-07-12 20:44:09 +02:00
ea828cd13a Fix non-interactive install on windows 2022-07-12 20:26:57 +02:00
00fa70b9de Merge remote-tracking branch 'origin/merge-requests/266' 2022-07-12 00:15:14 +02:00
823275363c Merge branch 'ghcup-run-improvements' 2022-07-12 00:10:17 +02:00
2f299ee48d Merge branch 'hls-hackage' 2022-07-12 00:06:40 +02:00
7a2a5074fa Fix parsing issues with 'ghcup run' and non-PVP versions
This is a major refactor of some CLI code. We try to distinguish
GHC versions from other versions, so that we can use distinct parsers.

Hopefully this doesn't introduce new bugs.

This also forces ghcup run to use the new internal ~/.ghcup/tmp dir.
2022-07-11 19:45:15 +02:00
ce239ab88e Fix error message 2022-07-11 19:44:10 +02:00
f3c703d655 Support hls in 'ghcup changelog' 2022-07-11 19:44:10 +02:00
b6ff5bc764 Use ghcup's internal dir for 'ghcup run' 2022-07-11 19:43:48 +02:00
b8aeb1f935 Fix guide 2022-07-11 00:43:18 +02:00
b0ef0590a2 Merge branch 'pwsh' 2022-07-10 21:21:17 +02:00
256e1942f2 More stuff 2022-07-10 21:19:45 +02:00
aa71f0dfa1 Set wget 2022-07-10 21:05:51 +02:00
04d527c98a Add DisableCurl powershell switch 2022-07-10 20:58:30 +02:00
Arjun Kathuria
ca5c5550ab removes newline after set' function 2022-07-10 21:49:54 +05:30
7b59621179 Support wget in bootstrap script 2022-07-10 17:56:00 +02:00
9d59463ded Add GHCUP_CURL_OPTS to bootstrap script 2022-07-10 17:35:45 +02:00
Arjun Kathuria
3d49f79beb removes prettyShow from error case in BrickMain set' 2022-07-10 09:52:57 +05:30
Arjun Kathuria
e9740d13fc Updates userPrompt in BrickMain to a more efficient version 2022-07-10 09:50:58 +05:30
Arjun Kathuria
2bd5a8fe1a Removes redundant putPrompt function from Prompts module. 2022-07-10 09:45:39 +05:30
Arjun Kathuria
0acccae523 Removes GHCup.Types.Prompts module and stuffs it into GHCup.Types 2022-07-10 09:44:23 +05:30
Arjun Kathuria
9ceb66ef21 chore: fix a hlint warning 2022-06-28 22:10:02 +05:30
Arjun Kathuria
7cbe38b011 Behavior Enhancement: make user press "S" only once to set, asks to install AND set if tool uninstalled 2022-06-28 19:50:22 +05:30
Arjun Kathuria
3bbc1edb19 updates user prompt message for "set" uninstalled version in BrickMain 2022-06-28 19:49:00 +05:30
Arjun Kathuria
b8dac2d7cd Updates the Prompt module to use logInfo instead of putStrLn,
makes the prompt look prettier
2022-06-28 19:45:17 +05:30
Arjun Kathuria
0e1fd68d93 when setting an uninstalled tool in tui, asks user to install first 2022-06-25 13:45:07 +05:30
Arjun Kathuria
c7eceb2330 Adds GHCup.Prompt modules and its types to project 2022-06-25 13:44:25 +05:30
25 changed files with 606 additions and 230 deletions

View File

@@ -1,5 +1,36 @@
# Revision history for ghcup # Revision history for ghcup
## 0.1.18.1 -- 2022-08-06
* fix sdist and unbreak hackage, wrt [#399](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/399)
## 0.1.18.0 -- 2022-07-30
* Fix tui set wrt [#266](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/266) by Arjun Kathuria
- Ask the user to install the tool via prompt when setting an non-installed version
* improvements to safe (un-)installations
- bindists that don't support `make DESTDIR=/some/tmp/dir install` are now unsupported
- installed GHC files are now recorded to avoid use of `removePathForcibly`
- internally uses a newtype wrapper for user-input paths and restrict destructive operations to validated paths
* Add `--disable-ld-override` for darwin bindists wrt #391
* Allow passing bindist configure args wrt #377
* use of `TMPDIR` is dropped... now uses an internal tmp dir `~/.ghcup/tmp`
* improvements to error handling and warnings
* Require --isolate to have an absolute directory, fixes #367
* Fix mingw PATH handling wrt #371
* Add --mingw-path switch to `ghcup run`
* Fix `ghcup run` on windows, fixes #375
* Improve `ghcup compile <hls|ghc>`
- short hashes now work
- print the long hash in addition to the detected version
* Improve `ghcup compile hls`
- add `--git-describe-version` switch as an alternative to `--overwrite-version`
- Allow to build HLS from hackage (now is the default)
- Allow to run 'cabal update' automatically before the HLS build
- Fix parser and completer for 'ghcup compile hls --version'
* Improve `ghcup compile ghc`
- Allow to build from arbitrary GHC source dists
## 0.1.17.10 -- 2022-05-12 ## 0.1.17.10 -- 2022-05-12
* windows hotfix (hackage-only release) * windows hotfix (hackage-only release)

View File

@@ -17,6 +17,7 @@ import GHCup.Prelude ( decUTF8Safe )
import GHCup.Prelude.File import GHCup.Prelude.File
import GHCup.Prelude.Logger import GHCup.Prelude.Logger
import GHCup.Prelude.Process import GHCup.Prelude.Process
import GHCup.Prompts
import Brick import Brick
import Brick.Widgets.Border import Brick.Widgets.Border
@@ -52,6 +53,8 @@ import Text.PrettyPrint.HughesPJClass ( prettyShow )
import URI.ByteString import URI.ByteString
import qualified Data.Text as T import qualified Data.Text as T
import qualified Data.Text.Lazy.Builder as B
import qualified Data.Text.Lazy as L
import qualified Graphics.Vty as Vty import qualified Graphics.Vty as Vty
import qualified Data.Vector as V import qualified Data.Vector as V
import System.Environment (getExecutablePath) import System.Environment (getExecutablePath)
@@ -98,7 +101,7 @@ keyHandlers KeyBindings {..} =
[ (bQuit, const "Quit" , halt) [ (bQuit, const "Quit" , halt)
, (bInstall, const "Install" , withIOAction install') , (bInstall, const "Install" , withIOAction install')
, (bUninstall, const "Uninstall", withIOAction del') , (bUninstall, const "Uninstall", withIOAction del')
, (bSet, const "Set" , withIOAction ((liftIO .) . set')) , (bSet, const "Set" , withIOAction set')
, (bChangelog, const "ChangeLog", withIOAction changelog') , (bChangelog, const "ChangeLog", withIOAction changelog')
, ( bShowAllVersions , ( bShowAllVersions
, \BrickSettings {..} -> , \BrickSettings {..} ->
@@ -486,9 +489,12 @@ install' _ (_, ListResult {..}) = do
<> "Also check the logs in ~/.ghcup/logs" <> "Also check the logs in ~/.ghcup/logs"
set' :: BrickState -> (Int, ListResult) -> IO (Either String ()) set' :: (MonadReader AppState m, MonadIO m, MonadThrow m, MonadFail m, MonadMask m, MonadUnliftIO m)
set' _ (_, ListResult {..}) = do => BrickState
settings <- readIORef settings' -> (Int, ListResult)
-> m (Either String ())
set' bs input@(_, ListResult {..}) = do
settings <- liftIO $ readIORef settings'
let run = let run =
flip runReaderT settings flip runReaderT settings
@@ -504,7 +510,28 @@ set' _ (_, ListResult {..}) = do
) )
>>= \case >>= \case
VRight _ -> pure $ Right () VRight _ -> pure $ Right ()
VLeft e -> pure $ Left (prettyShow e) VLeft e -> case e of
(V (NotInstalled tool _)) -> do
promptAnswer <- getUserPromptResponse userPrompt
case promptAnswer of
PromptYes -> do
res <- install' bs input
case res of
(Left err) -> pure $ Left err
(Right _) -> do
logInfo "Setting now..."
set' bs input
PromptNo -> pure $ Left (prettyShow e)
where
userPrompt = L.toStrict . B.toLazyText . B.fromString $
"This Version of "
<> show tool
<> " you are trying to set is not installed.\n"
<> "Would you like to install it first? [Y/N]: "
_ -> pure $ Left (prettyShow e)
del' :: (MonadReader AppState m, MonadIO m, MonadFail m, MonadMask m, MonadUnliftIO m) del' :: (MonadReader AppState m, MonadIO m, MonadFail m, MonadMask m, MonadUnliftIO m)

View File

@@ -58,7 +58,7 @@ data ChangeLogOptions = ChangeLogOptions
--[ Parsers ]-- --[ Parsers ]--
--------------- ---------------
changelogP :: Parser ChangeLogOptions changelogP :: Parser ChangeLogOptions
changelogP = changelogP =
(\x y -> ChangeLogOptions x y) (\x y -> ChangeLogOptions x y)
@@ -71,15 +71,16 @@ changelogP =
"cabal" -> Right Cabal "cabal" -> Right Cabal
"ghcup" -> Right GHCup "ghcup" -> Right GHCup
"stack" -> Right Stack "stack" -> Right Stack
"hls" -> Right HLS
e -> Left e e -> Left e
) )
) )
(short 't' <> long "tool" <> metavar "<ghc|cabal|ghcup>" <> help (short 't' <> long "tool" <> metavar "<ghc|cabal|hls|ghcup>" <> help
"Open changelog for given tool (default: ghc)" "Open changelog for given tool (default: ghc)"
<> completer toolCompleter <> completer toolCompleter
) )
) )
<*> optional (toolVersionArgument Nothing Nothing) <*> optional (toolVersionTagArgument Nothing Nothing)
@@ -116,7 +117,8 @@ changelog ChangeLogOptions{..} runAppState runLogger = do
ver' = maybe ver' = maybe
(Right Latest) (Right Latest)
(\case (\case
ToolVersion tv -> Left (_tvVersion tv) -- FIXME: ugly sharing of ToolVersion GHCVersion tv -> Left (_tvVersion tv)
ToolVersion tv -> Left tv
ToolTag t -> Right t ToolTag t -> Right t
) )
clToolVer clToolVer

View File

@@ -70,20 +70,24 @@ import Control.Exception (evaluate)
--[ Types ]-- --[ Types ]--
------------- -------------
data ToolVersion = ToolVersion GHCTargetVersion -- target is ignored for cabal data ToolVersion = GHCVersion GHCTargetVersion
| ToolVersion Version
| ToolTag Tag | ToolTag Tag
-- a superset of ToolVersion -- a superset of ToolVersion
data SetToolVersion = SetToolVersion GHCTargetVersion data SetToolVersion = SetGHCVersion GHCTargetVersion
| SetToolVersion Version
| SetToolTag Tag | SetToolTag Tag
| SetRecommended | SetRecommended
| SetNext | SetNext
prettyToolVer :: ToolVersion -> String prettyToolVer :: ToolVersion -> String
prettyToolVer (ToolVersion v') = T.unpack $ tVerToText v' prettyToolVer (GHCVersion v') = T.unpack $ tVerToText v'
prettyToolVer (ToolVersion v') = T.unpack $ prettyVer v'
prettyToolVer (ToolTag t) = show t prettyToolVer (ToolTag t) = show t
toSetToolVer :: Maybe ToolVersion -> SetToolVersion toSetToolVer :: Maybe ToolVersion -> SetToolVersion
toSetToolVer (Just (GHCVersion v')) = SetGHCVersion v'
toSetToolVer (Just (ToolVersion v')) = SetToolVersion v' toSetToolVer (Just (ToolVersion v')) = SetToolVersion v'
toSetToolVer (Just (ToolTag t')) = SetToolTag t' toSetToolVer (Just (ToolTag t')) = SetToolTag t'
toSetToolVer Nothing = SetRecommended toSetToolVer Nothing = SetRecommended
@@ -96,10 +100,9 @@ toSetToolVer Nothing = SetRecommended
-------------- --------------
-- | same as toolVersionParser, except as an argument. toolVersionTagArgument :: Maybe ListCriteria -> Maybe Tool -> Parser ToolVersion
toolVersionArgument :: Maybe ListCriteria -> Maybe Tool -> Parser ToolVersion toolVersionTagArgument criteria tool =
toolVersionArgument criteria tool = argument (eitherReader (parser tool))
argument (eitherReader toolVersionEither)
(metavar (mv tool) (metavar (mv tool)
<> completer (tagCompleter (fromMaybe GHC tool) []) <> completer (tagCompleter (fromMaybe GHC tool) [])
<> foldMap (completer . versionCompleter criteria) tool) <> foldMap (completer . versionCompleter criteria) tool)
@@ -108,20 +111,19 @@ toolVersionArgument criteria tool =
mv (Just HLS) = "HLS_VERSION|TAG" mv (Just HLS) = "HLS_VERSION|TAG"
mv _ = "VERSION|TAG" mv _ = "VERSION|TAG"
parser (Just GHC) = ghcVersionTagEither
parser Nothing = ghcVersionTagEither
parser _ = toolVersionTagEither
versionParser :: Parser GHCTargetVersion
versionParser = option
(eitherReader tVersionEither)
(short 'v' <> long "version" <> metavar "VERSION" <> help "The target version"
)
versionParser' :: Maybe ListCriteria -> Maybe Tool -> Parser Version versionParser' :: Maybe ListCriteria -> Maybe Tool -> Parser Version
versionParser' criteria tool = argument versionParser' criteria tool = argument
(eitherReader (first show . version . T.pack)) (eitherReader (first show . version . T.pack))
(metavar "VERSION" <> foldMap (completer . versionCompleter criteria) tool) (metavar "VERSION" <> foldMap (completer . versionCompleter criteria) tool)
versionArgument :: Maybe ListCriteria -> Maybe Tool -> Parser GHCTargetVersion ghcVersionArgument :: Maybe ListCriteria -> Maybe Tool -> Parser GHCTargetVersion
versionArgument criteria tool = argument (eitherReader tVersionEither) (metavar "VERSION" <> foldMap (completer . versionCompleter criteria) tool) ghcVersionArgument criteria tool = argument (eitherReader ghcVersionEither)
(metavar "VERSION" <> foldMap (completer . versionCompleter criteria) tool)
-- https://github.com/pcapriotti/optparse-applicative/issues/148 -- https://github.com/pcapriotti/optparse-applicative/issues/148
@@ -230,9 +232,15 @@ isolateParser f = case isValid f && isAbsolute f of
True -> Right $ normalise f True -> Right $ normalise f
False -> Left "Please enter a valid filepath for isolate dir." False -> Left "Please enter a valid filepath for isolate dir."
toolVersionEither :: String -> Either String ToolVersion -- this accepts cross prefix
toolVersionEither s' = ghcVersionTagEither :: String -> Either String ToolVersion
second ToolTag (tagEither s') <|> second ToolVersion (tVersionEither s') ghcVersionTagEither s' =
second ToolTag (tagEither s') <|> second GHCVersion (ghcVersionEither s')
-- this ignores cross prefix
toolVersionTagEither :: String -> Either String ToolVersion
toolVersionTagEither s' =
second ToolTag (tagEither s') <|> second ToolVersion (toolVersionEither s')
tagEither :: String -> Either String Tag tagEither :: String -> Either String Tag
tagEither s' = case fmap toLower s' of tagEither s' = case fmap toLower s' of
@@ -244,10 +252,14 @@ tagEither s' = case fmap toLower s' of
other -> Left $ "Unknown tag " <> other other -> Left $ "Unknown tag " <> other
tVersionEither :: String -> Either String GHCTargetVersion ghcVersionEither :: String -> Either String GHCTargetVersion
tVersionEither = ghcVersionEither =
first (const "Not a valid version") . MP.parse ghcTargetVerP "" . T.pack first (const "Not a valid version") . MP.parse ghcTargetVerP "" . T.pack
toolVersionEither :: String -> Either String Version
toolVersionEither =
first (const "Not a valid version") . MP.parse version' "" . T.pack
toolParser :: String -> Either String Tool toolParser :: String -> Either String Tool
toolParser s' | t == T.pack "ghc" = Right GHC toolParser s' | t == T.pack "ghc" = Right GHC
@@ -665,7 +677,7 @@ fromVersion' SetRecommended tool = do
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
bimap mkTVer Just <$> getRecommended dls tool bimap mkTVer Just <$> getRecommended dls tool
?? TagNotFound Recommended tool ?? TagNotFound Recommended tool
fromVersion' (SetToolVersion v) tool = do fromVersion' (SetGHCVersion v) tool = do
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
let vi = getVersionInfo (_tvVersion v) tool dls let vi = getVersionInfo (_tvVersion v) tool dls
case pvp $ prettyVer (_tvVersion v) of -- need to be strict here case pvp $ prettyVer (_tvVersion v) of -- need to be strict here
@@ -677,6 +689,18 @@ fromVersion' (SetToolVersion v) tool = do
when (v' /= _tvVersion v) $ lift $ logWarn ("Assuming you meant version " <> prettyVer v') when (v' /= _tvVersion v) $ lift $ logWarn ("Assuming you meant version " <> prettyVer v')
pure (GHCTargetVersion (_tvTarget v) v', Just vi') pure (GHCTargetVersion (_tvTarget v) v', Just vi')
Nothing -> pure (v, vi) Nothing -> pure (v, vi)
fromVersion' (SetToolVersion v) tool = do
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
let vi = getVersionInfo v tool dls
case pvp $ prettyVer v of -- need to be strict here
Left _ -> pure (mkTVer v, vi)
Right pvpIn ->
lift (getLatestToolFor tool pvpIn dls) >>= \case
Just (pvp_, vi') -> do
v' <- lift $ pvpToVersion pvp_ ""
when (v' /= v) $ lift $ logWarn ("Assuming you meant version " <> prettyVer v')
pure (GHCTargetVersion mempty v', Just vi')
Nothing -> pure (mkTVer v, vi)
fromVersion' (SetToolTag Latest) tool = do fromVersion' (SetToolTag Latest) tool = do
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
bimap mkTVer Just <$> getLatest dls tool ?? TagNotFound Latest tool bimap mkTVer Just <$> getLatest dls tool ?? TagNotFound Latest tool

View File

@@ -401,7 +401,7 @@ hlsCompileOpts =
) )
) )
<*> some ( <*> some (
option (eitherReader toolVersionEither) option (eitherReader ghcVersionTagEither)
( long "ghc" <> metavar "GHC_VERSION|TAG" <> help "For which GHC version to compile for (can be specified multiple times)" ( long "ghc" <> metavar "GHC_VERSION|TAG" <> help "For which GHC version to compile for (can be specified multiple times)"
<> completer (tagCompleter GHC []) <> completer (tagCompleter GHC [])
<> completer (versionCompleter Nothing GHC)) <> completer (versionCompleter Nothing GHC))

View File

@@ -171,7 +171,7 @@ Examples:
ghcup install ghc 8.10.2 ghcup install ghc 8.10.2
# install GHC head fedora bindist # install GHC head fedora bindist
ghcup install ghc -u https://gitlab.haskell.org/api/v4/projects/1/jobs/artifacts/master/raw/ghc-x86_64-fedora27-linux.tar.xz?job=validate-x86_64-linux-fedora27 head|] ghcup install ghc -u 'https://gitlab.haskell.org/ghc/ghc/-/jobs/artifacts/master/raw/ghc-x86_64-linux-fedora33-release.tar.xz?job=x86_64-linux-fedora33-release' head|]
installOpts :: Maybe Tool -> Parser InstallOptions installOpts :: Maybe Tool -> Parser InstallOptions
@@ -196,7 +196,7 @@ installOpts tool =
<> completer (toolDlCompleter (fromMaybe GHC tool)) <> completer (toolDlCompleter (fromMaybe GHC tool))
) )
) )
<*> (Just <$> toolVersionArgument Nothing tool) <*> (Just <$> toolVersionTagArgument Nothing tool)
) )
<|> pure (Nothing, Nothing) <|> pure (Nothing, Nothing)
) )
@@ -546,4 +546,3 @@ install installCommand settings getAppState' runLogger = case installCommand of
logError $ T.pack $ prettyShow e logError $ T.pack $ prettyShow e
logError $ "Also check the logs in " <> T.pack (fromGHCupPath logsDir) logError $ "Also check the logs in " <> T.pack (fromGHCupPath logsDir)
pure $ ExitFailure 4 pure $ ExitFailure 4

View File

@@ -74,44 +74,44 @@ data PrefetchGHCOptions = PrefetchGHCOptions {
--[ Parsers ]-- --[ Parsers ]--
--------------- ---------------
prefetchP :: Parser PrefetchCommand prefetchP :: Parser PrefetchCommand
prefetchP = subparser prefetchP = subparser
( command ( command
"ghc" "ghc"
(info (info
(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/)" <> completer (bashCompleter "directory"))))
<*> optional (toolVersionArgument Nothing (Just GHC)) ) <*> optional (toolVersionTagArgument Nothing (Just GHC)) )
( progDesc "Download GHC assets for installation") ( progDesc "Download GHC assets for installation")
) )
<> <>
command command
"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/)" <> completer (bashCompleter "directory"))))
<*> ( optional (toolVersionArgument Nothing (Just Cabal)) <**> helper )) <*> ( optional (toolVersionTagArgument Nothing (Just Cabal)) <**> helper ))
( progDesc "Download cabal assets for installation") ( progDesc "Download cabal assets for installation")
) )
<> <>
command command
"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/)" <> completer (bashCompleter "directory"))))
<*> ( optional (toolVersionArgument Nothing (Just HLS)) <**> helper )) <*> ( optional (toolVersionTagArgument Nothing (Just HLS)) <**> helper ))
( progDesc "Download HLS assets for installation") ( progDesc "Download HLS assets for installation")
) )
<> <>
command command
"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/)" <> completer (bashCompleter "directory"))))
<*> ( optional (toolVersionArgument Nothing (Just Stack)) <**> helper )) <*> ( optional (toolVersionTagArgument Nothing (Just Stack)) <**> helper ))
( progDesc "Download stack assets for installation") ( progDesc "Download stack assets for installation")
) )
<> <>

View File

@@ -71,7 +71,7 @@ data RmOptions = RmOptions
--[ Parsers ]-- --[ Parsers ]--
--------------- ---------------
rmParser :: Parser (Either RmCommand RmOptions) rmParser :: Parser (Either RmCommand RmOptions)
rmParser = rmParser =
(Left <$> subparser (Left <$> subparser
@@ -103,7 +103,7 @@ rmParser =
rmOpts :: Maybe Tool -> Parser RmOptions rmOpts :: Maybe Tool -> Parser RmOptions
rmOpts tool = RmOptions <$> versionArgument (Just ListInstalled) tool rmOpts tool = RmOptions <$> ghcVersionArgument (Just ListInstalled) tool

View File

@@ -5,6 +5,7 @@
{-# LANGUAGE RankNTypes #-} {-# LANGUAGE RankNTypes #-}
{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE ViewPatterns #-}
module GHCup.OptParse.Run where module GHCup.OptParse.Run where
@@ -46,6 +47,7 @@ import qualified Data.Text as T
#ifndef IS_WINDOWS #ifndef IS_WINDOWS
import qualified System.Posix.Process as SPP import qualified System.Posix.Process as SPP
#endif #endif
import Data.Versions ( prettyVer, Version )
@@ -88,7 +90,7 @@ runOpts =
(short 'm' <> long "mingw-path" <> help "On windows, add mingw64 PATHs to environment (does nothing on unix)") (short 'm' <> long "mingw-path" <> help "On windows, add mingw64 PATHs to environment (does nothing on unix)")
<*> optional <*> optional
(option (option
(eitherReader toolVersionEither) (eitherReader ghcVersionTagEither)
(metavar "GHC_VERSION" <> long "ghc" <> help "The ghc version" (metavar "GHC_VERSION" <> long "ghc" <> help "The ghc version"
<> completer (tagCompleter GHC []) <> completer (tagCompleter GHC [])
<> (completer $ versionCompleter Nothing GHC) <> (completer $ versionCompleter Nothing GHC)
@@ -96,7 +98,7 @@ runOpts =
) )
<*> optional <*> optional
(option (option
(eitherReader toolVersionEither) (eitherReader toolVersionTagEither)
(metavar "CABAL_VERSION" <> long "cabal" <> help "The cabal version" (metavar "CABAL_VERSION" <> long "cabal" <> help "The cabal version"
<> completer (tagCompleter Cabal []) <> completer (tagCompleter Cabal [])
<> (completer $ versionCompleter Nothing Cabal) <> (completer $ versionCompleter Nothing Cabal)
@@ -104,7 +106,7 @@ runOpts =
) )
<*> optional <*> optional
(option (option
(eitherReader toolVersionEither) (eitherReader toolVersionTagEither)
(metavar "HLS_VERSION" <> long "hls" <> help "The HLS version" (metavar "HLS_VERSION" <> long "hls" <> help "The HLS version"
<> completer (tagCompleter HLS []) <> completer (tagCompleter HLS [])
<> (completer $ versionCompleter Nothing HLS) <> (completer $ versionCompleter Nothing HLS)
@@ -112,7 +114,7 @@ runOpts =
) )
<*> optional <*> optional
(option (option
(eitherReader toolVersionEither) (eitherReader toolVersionTagEither)
(metavar "STACK_VERSION" <> long "stack" <> help "The stack version" (metavar "STACK_VERSION" <> long "stack" <> help "The stack version"
<> completer (tagCompleter Stack []) <> completer (tagCompleter Stack [])
<> (completer $ versionCompleter Nothing Stack) <> (completer $ versionCompleter Nothing Stack)
@@ -217,7 +219,7 @@ runRUN appState action' = do
run :: forall m. run :: forall m .
( MonadFail m ( MonadFail m
, MonadMask m , MonadMask m
, MonadCatch m , MonadCatch m
@@ -233,12 +235,16 @@ run RunOptions{..} runAppState leanAppstate runLogger = do
r <- if not runQuick r <- if not runQuick
then runRUN runAppState $ do then runRUN runAppState $ do
toolchain <- liftE resolveToolchainFull toolchain <- liftE resolveToolchainFull
tmp <- liftIO $ createTmpDir toolchain
-- oh dear
r <- lift ask
tmp <- lift . lift . lift . flip runReaderT (fromAppState r) $ createTmpDir toolchain
liftE $ installToolChainFull toolchain tmp liftE $ installToolChainFull toolchain tmp
pure tmp pure tmp
else runLeanRUN leanAppstate $ do else runLeanRUN leanAppstate $ do
toolchain <- resolveToolchain toolchain <- resolveToolchain
tmp <- liftIO $ createTmpDir toolchain tmp <- lift $ createTmpDir toolchain
liftE $ installToolChain toolchain tmp liftE $ installToolChain toolchain tmp
pure tmp pure tmp
case r of case r of
@@ -268,17 +274,6 @@ run RunOptions{..} runAppState leanAppstate runLogger = do
where where
createTmpDir :: Toolchain -> IO FilePath
createTmpDir toolchain =
case runBinDir of
Just bindir -> do
createDirRecursive' bindir
canonicalizePath bindir
Nothing -> do
d <- predictableTmpDir toolchain
createDirRecursive' d
canonicalizePath d
-- TODO: doesn't work for cross -- TODO: doesn't work for cross
resolveToolchainFull :: ( MonadFail m resolveToolchainFull :: ( MonadFail m
, MonadThrow m , MonadThrow m
@@ -296,29 +291,33 @@ run RunOptions{..} runAppState leanAppstate runLogger = do
pure v pure v
cabalVer <- forM runCabalVer $ \ver -> do cabalVer <- forM runCabalVer $ \ver -> do
(v, _) <- liftE $ fromVersion (Just ver) Cabal (v, _) <- liftE $ fromVersion (Just ver) Cabal
pure v pure (_tvVersion v)
hlsVer <- forM runHLSVer $ \ver -> do hlsVer <- forM runHLSVer $ \ver -> do
(v, _) <- liftE $ fromVersion (Just ver) HLS (v, _) <- liftE $ fromVersion (Just ver) HLS
pure v pure (_tvVersion v)
stackVer <- forM runStackVer $ \ver -> do stackVer <- forM runStackVer $ \ver -> do
(v, _) <- liftE $ fromVersion (Just ver) Stack (v, _) <- liftE $ fromVersion (Just ver) Stack
pure v pure (_tvVersion v)
pure Toolchain{..} pure Toolchain{..}
resolveToolchain = do resolveToolchain = do
ghcVer <- case runGHCVer of ghcVer <- case runGHCVer of
Just (ToolVersion v) -> pure $ Just v Just (GHCVersion v) -> pure $ Just v
Just (ToolVersion v) -> pure $ Just (mkTVer v)
Nothing -> pure Nothing Nothing -> pure Nothing
_ -> fail "Internal error" _ -> fail "Internal error"
cabalVer <- case runCabalVer of cabalVer <- case runCabalVer of
Just (GHCVersion v) -> pure $ Just (_tvVersion v)
Just (ToolVersion v) -> pure $ Just v Just (ToolVersion v) -> pure $ Just v
Nothing -> pure Nothing Nothing -> pure Nothing
_ -> fail "Internal error" _ -> fail "Internal error"
hlsVer <- case runHLSVer of hlsVer <- case runHLSVer of
Just (GHCVersion v) -> pure $ Just (_tvVersion v)
Just (ToolVersion v) -> pure $ Just v Just (ToolVersion v) -> pure $ Just v
Nothing -> pure Nothing Nothing -> pure Nothing
_ -> fail "Internal error" _ -> fail "Internal error"
stackVer <- case runStackVer of stackVer <- case runStackVer of
Just (GHCVersion v) -> pure $ Just (_tvVersion v)
Just (ToolVersion v) -> pure $ Just v Just (ToolVersion v) -> pure $ Just v
Nothing -> pure Nothing Nothing -> pure Nothing
_ -> fail "Internal error" _ -> fail "Internal error"
@@ -353,35 +352,43 @@ run RunOptions{..} runAppState leanAppstate runLogger = do
, MergeFileTreeError , MergeFileTreeError
] (ResourceT (ReaderT AppState m)) () ] (ResourceT (ReaderT AppState m)) ()
installToolChainFull Toolchain{..} tmp = do installToolChainFull Toolchain{..} tmp = do
forM_ [(GHC,) <$> ghcVer, (Cabal,) <$> cabalVer, (HLS,) <$> hlsVer, (Stack,) <$> stackVer] $ \mt -> do case ghcVer of
isInstalled <- maybe (pure False) (\(tool, v) -> lift $ checkIfToolInstalled' tool v) mt Just v -> do
case mt of isInstalled <- lift $ checkIfToolInstalled' GHC v
Just (GHC, v) -> do unless isInstalled $ when (runInstTool' && isNothing (_tvTarget v)) $ void $ liftE $ installGHCBin
unless isInstalled $ when (runInstTool' && isNothing (_tvTarget v)) $ void $ liftE $ installGHCBin (_tvVersion v)
(_tvVersion v) GHCupInternal
GHCupInternal False
False []
[] setGHC' v tmp
setTool GHC v tmp _ -> pure ()
Just (Cabal, v) -> do case cabalVer of
unless isInstalled $ when runInstTool' $ void $ liftE $ installCabalBin Just v -> do
(_tvVersion v) isInstalled <- lift $ checkIfToolInstalled' Cabal (mkTVer v)
GHCupInternal unless isInstalled $ when runInstTool' $ void $ liftE $ installCabalBin
False v
setTool Cabal v tmp GHCupInternal
Just (Stack, v) -> do False
unless isInstalled $ when runInstTool' $ void $ liftE $ installStackBin setCabal' v tmp
(_tvVersion v) _ -> pure ()
GHCupInternal case stackVer of
False Just v -> do
setTool Stack v tmp isInstalled <- lift $ checkIfToolInstalled' Stack (mkTVer v)
Just (HLS, v) -> do unless isInstalled $ when runInstTool' $ void $ liftE $ installStackBin
unless isInstalled $ when runInstTool' $ void $ liftE $ installHLSBin v
(_tvVersion v) GHCupInternal
GHCupInternal False
False setStack' v tmp
setTool HLS v tmp _ -> pure ()
_ -> pure () case hlsVer of
Just v -> do
isInstalled <- lift $ checkIfToolInstalled' HLS (mkTVer v)
unless isInstalled $ when runInstTool' $ void $ liftE $ installHLSBin
v
GHCupInternal
False
setHLS' v tmp
_ -> pure ()
installToolChain :: ( MonadFail m installToolChain :: ( MonadFail m
, MonadThrow m , MonadThrow m
@@ -392,46 +399,47 @@ run RunOptions{..} runAppState leanAppstate runLogger = do
-> FilePath -> FilePath
-> Excepts '[NotInstalled] (ReaderT LeanAppState m) () -> Excepts '[NotInstalled] (ReaderT LeanAppState m) ()
installToolChain Toolchain{..} tmp = do installToolChain Toolchain{..} tmp = do
forM_ [(GHC,) <$> ghcVer, (Cabal,) <$> cabalVer, (HLS,) <$> hlsVer, (Stack,) <$> stackVer] $ \mt -> do case ghcVer of
case mt of Just v -> setGHC' v tmp
Just (GHC, v) -> setTool GHC v tmp _ -> pure ()
Just (Cabal, v) -> setTool Cabal v tmp case cabalVer of
Just (Stack, v) -> setTool Stack v tmp Just v -> setCabal' v tmp
Just (HLS, v) -> setTool HLS v tmp _ -> pure ()
_ -> pure () case stackVer of
Just v -> setStack' v tmp
_ -> pure ()
case hlsVer of
Just v -> setHLS' v tmp
_ -> pure ()
setTool tool v tmp = setGHC' v tmp = do
case tool of
GHC -> do
void $ liftE $ setGHC v SetGHC_XYZ (Just tmp) void $ liftE $ setGHC v SetGHC_XYZ (Just tmp)
void $ liftE $ setGHC v SetGHCOnly (Just tmp) void $ liftE $ setGHC v SetGHCOnly (Just tmp)
Cabal -> do setCabal' v tmp = do
bin <- liftE $ whereIsTool Cabal v bin <- liftE $ whereIsTool Cabal (mkTVer v)
cbin <- liftIO $ canonicalizePath bin cbin <- liftIO $ canonicalizePath bin
lift $ createLink (relativeSymlink tmp cbin) (tmp </> ("cabal" <.> exeExt)) lift $ createLink (relativeSymlink tmp cbin) (tmp </> ("cabal" <.> exeExt))
Stack -> do setStack' v tmp = do
bin <- liftE $ whereIsTool Stack v bin <- liftE $ whereIsTool Stack (mkTVer v)
cbin <- liftIO $ canonicalizePath bin cbin <- liftIO $ canonicalizePath bin
lift $ createLink (relativeSymlink tmp cbin) (tmp </> ("stack" <.> exeExt)) lift $ createLink (relativeSymlink tmp cbin) (tmp </> ("stack" <.> exeExt))
HLS -> do setHLS' v tmp = do
Dirs {..} <- getDirs Dirs {..} <- getDirs
let v' = _tvVersion v legacy <- isLegacyHLS v
legacy <- isLegacyHLS v'
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')) hlsWrapper <- liftE @_ @'[NotInstalled] $ hlsWrapperBinary v !? (NotInstalled HLS (mkTVer v))
cw <- liftIO $ canonicalizePath (binDir </> hlsWrapper) cw <- liftIO $ canonicalizePath (binDir </> hlsWrapper)
lift $ createLink (relativeSymlink tmp cw) (tmp </> takeFileName cw) lift $ createLink (relativeSymlink tmp cw) (tmp </> takeFileName cw)
hlsBins <- hlsServerBinaries v' Nothing >>= liftIO . traverse (canonicalizePath . (binDir </>)) hlsBins <- hlsServerBinaries v Nothing >>= liftIO . traverse (canonicalizePath . (binDir </>))
forM_ hlsBins $ \bin -> forM_ hlsBins $ \bin ->
lift $ createLink (relativeSymlink tmp bin) (tmp </> takeFileName bin) lift $ createLink (relativeSymlink tmp bin) (tmp </> takeFileName bin)
liftE $ setHLS (_tvVersion v) SetHLSOnly (Just tmp) liftE $ setHLS v SetHLSOnly (Just tmp)
else do else do
liftE $ setHLS (_tvVersion v) SetHLS_XYZ (Just tmp) liftE $ setHLS v SetHLS_XYZ (Just tmp)
liftE $ setHLS (_tvVersion v) SetHLSOnly (Just tmp) liftE $ setHLS v SetHLSOnly (Just tmp)
GHCup -> pure ()
addToPath path = do addToPath path = do
cEnv <- Map.fromList <$> getEnvironment cEnv <- Map.fromList <$> getEnvironment
let paths = ["PATH", "Path"] let paths = ["PATH", "Path"]
@@ -443,16 +451,38 @@ run RunOptions{..} runAppState leanAppstate runLogger = do
liftIO $ setEnv pathVar newPath liftIO $ setEnv pathVar newPath
return envWithNewPath return envWithNewPath
predictableTmpDir (Toolchain Nothing Nothing Nothing Nothing) = createTmpDir :: ( MonadUnliftIO m
liftIO (getTemporaryDirectory >>= \tmp -> pure (tmp </> "ghcup-none")) , MonadCatch m
, MonadThrow m
, MonadMask m
, MonadIO m
)
=> Toolchain
-> ReaderT LeanAppState m FilePath
createTmpDir toolchain =
case runBinDir of
Just bindir -> do
liftIO $ createDirRecursive' bindir
liftIO $ canonicalizePath bindir
Nothing -> do
d <- predictableTmpDir toolchain
liftIO $ createDirRecursive' d
liftIO $ canonicalizePath d
predictableTmpDir :: Monad m
=> Toolchain
-> ReaderT LeanAppState m FilePath
predictableTmpDir (Toolchain Nothing Nothing Nothing Nothing) = do
Dirs { tmpDir } <- getDirs
pure (fromGHCupPath tmpDir </> "ghcup-none")
predictableTmpDir Toolchain{..} = do predictableTmpDir Toolchain{..} = do
tmp <- getTemporaryDirectory Dirs { tmpDir } <- getDirs
pure $ tmp pure $ fromGHCupPath tmpDir
</> ("ghcup-" <> intercalate "_" </> ("ghcup-" <> intercalate "_"
( maybe [] ( (:[]) . ("ghc-" <>) . T.unpack . tVerToText) ghcVer ( maybe [] ( (:[]) . ("ghc-" <>) . T.unpack . tVerToText) ghcVer
<> maybe [] ( (:[]) . ("cabal-" <>) . T.unpack . tVerToText) cabalVer <> maybe [] ( (:[]) . ("cabal-" <>) . T.unpack . prettyVer) cabalVer
<> maybe [] ( (:[]) . ("hls-" <>) . T.unpack . tVerToText) hlsVer <> maybe [] ( (:[]) . ("hls-" <>) . T.unpack . prettyVer) hlsVer
<> maybe [] ( (:[]) . ("stack-" <>) . T.unpack . tVerToText) stackVer <> maybe [] ( (:[]) . ("stack-" <>) . T.unpack . prettyVer) stackVer
) )
) )
@@ -466,7 +496,7 @@ run RunOptions{..} runAppState leanAppstate runLogger = do
data Toolchain = Toolchain data Toolchain = Toolchain
{ ghcVer :: Maybe GHCTargetVersion { ghcVer :: Maybe GHCTargetVersion
, cabalVer :: Maybe GHCTargetVersion , cabalVer :: Maybe Version
, hlsVer :: Maybe GHCTargetVersion , hlsVer :: Maybe Version
, stackVer :: Maybe GHCTargetVersion , stackVer :: Maybe Version
} } deriving Show

View File

@@ -74,7 +74,7 @@ data SetOptions = SetOptions
--[ Parsers ]-- --[ Parsers ]--
--------------- ---------------
setParser :: Parser (Either SetCommand SetOptions) setParser :: Parser (Either SetCommand SetOptions)
setParser = setParser =
(Left <$> subparser (Left <$> subparser
@@ -82,7 +82,7 @@ setParser =
"ghc" "ghc"
( SetGHC ( SetGHC
<$> info <$> info
(setOpts (Just GHC) <**> helper) (setOpts GHC <**> helper)
( progDesc "Set GHC version" ( progDesc "Set GHC version"
<> footerDoc (Just $ text setGHCFooter) <> footerDoc (Just $ text setGHCFooter)
) )
@@ -91,7 +91,7 @@ setParser =
"cabal" "cabal"
( SetCabal ( SetCabal
<$> info <$> info
(setOpts (Just Cabal) <**> helper) (setOpts Cabal <**> helper)
( progDesc "Set Cabal version" ( progDesc "Set Cabal version"
<> footerDoc (Just $ text setCabalFooter) <> footerDoc (Just $ text setCabalFooter)
) )
@@ -100,7 +100,7 @@ setParser =
"hls" "hls"
( SetHLS ( SetHLS
<$> info <$> info
(setOpts (Just HLS) <**> helper) (setOpts HLS <**> helper)
( progDesc "Set haskell-language-server version" ( progDesc "Set haskell-language-server version"
<> footerDoc (Just $ text setHLSFooter) <> footerDoc (Just $ text setHLSFooter)
) )
@@ -109,14 +109,14 @@ setParser =
"stack" "stack"
( SetStack ( SetStack
<$> info <$> info
(setOpts (Just Stack) <**> helper) (setOpts Stack <**> helper)
( progDesc "Set stack version" ( progDesc "Set stack version"
<> footerDoc (Just $ text setStackFooter) <> footerDoc (Just $ text setStackFooter)
) )
) )
) )
) )
<|> (Right <$> setOpts Nothing) <|> (Right <$> setOpts GHC)
where where
setGHCFooter :: String setGHCFooter :: String
setGHCFooter = [s|Discussion: setGHCFooter = [s|Discussion:
@@ -137,22 +137,25 @@ setParser =
Sets the the current haskell-language-server version.|] Sets the the current haskell-language-server version.|]
setOpts :: Maybe Tool -> Parser SetOptions setOpts :: Tool -> Parser SetOptions
setOpts tool = SetOptions <$> setOpts tool = SetOptions <$>
(fromMaybe SetRecommended <$> (fromMaybe SetRecommended <$>
optional (setVersionArgument (Just ListInstalled) tool)) optional (setVersionArgument (Just ListInstalled) tool))
setVersionArgument :: Maybe ListCriteria -> Maybe Tool -> Parser SetToolVersion setVersionArgument :: Maybe ListCriteria -> Tool -> Parser SetToolVersion
setVersionArgument criteria tool = setVersionArgument criteria tool =
argument (eitherReader setEither) argument (eitherReader setEither)
(metavar "VERSION|TAG|next" (metavar "VERSION|TAG|next"
<> completer (tagCompleter (fromMaybe GHC tool) ["next"]) <> completer (tagCompleter tool ["next"])
<> foldMap (completer . versionCompleter criteria) tool) <> (completer . versionCompleter criteria) tool)
where where
setEither s' = setEither s' =
parseSet s' parseSet s'
<|> second SetToolTag (tagEither s') <|> second SetToolTag (tagEither s')
<|> second SetToolVersion (tVersionEither s') <|> se s'
se s' = case tool of
GHC -> second SetGHCVersion (ghcVersionEither s')
_ -> second SetToolVersion (toolVersionEither s')
parseSet s' = case fmap toLower s' of parseSet s' = case fmap toLower s' of
"next" -> Right SetNext "next" -> Right SetNext
other -> Left $ "Unknown tag/version " <> other other -> Left $ "Unknown tag/version " <> other
@@ -261,9 +264,9 @@ set setCommand runAppState runLeanAppState runLogger = case setCommand of
(Right sopts) -> do (Right sopts) -> do
runLogger (logWarn "This is an old-style command for setting GHC. Use 'ghcup set ghc' instead.") runLogger (logWarn "This is an old-style command for setting GHC. Use 'ghcup set ghc' instead.")
setGHC' sopts setGHC' sopts
(Left (SetGHC sopts)) -> setGHC' sopts (Left (SetGHC sopts)) -> setGHC' sopts
(Left (SetCabal sopts)) -> setCabal' sopts (Left (SetCabal sopts)) -> setCabal' sopts
(Left (SetHLS sopts)) -> setHLS' sopts (Left (SetHLS sopts)) -> setHLS' sopts
(Left (SetStack sopts)) -> setStack' sopts (Left (SetStack sopts)) -> setStack' sopts
where where
@@ -271,7 +274,7 @@ set setCommand runAppState runLeanAppState runLogger = case setCommand of
-> m ExitCode -> m ExitCode
setGHC' SetOptions{ sToolVer } = setGHC' SetOptions{ sToolVer } =
case sToolVer of case sToolVer of
(SetToolVersion v) -> runSetGHC runLeanAppState (liftE $ setGHC v SetGHCOnly Nothing >> pure v) (SetGHCVersion v) -> runSetGHC runLeanAppState (liftE $ setGHC v SetGHCOnly Nothing >> pure v)
_ -> runSetGHC runAppState (do _ -> runSetGHC runAppState (do
v <- liftE $ fst <$> fromVersion' sToolVer GHC v <- liftE $ fst <$> fromVersion' sToolVer GHC
liftE $ setGHC v SetGHCOnly Nothing liftE $ setGHC v SetGHCOnly Nothing
@@ -291,17 +294,17 @@ set setCommand runAppState runLeanAppState runLogger = case setCommand of
-> m ExitCode -> m ExitCode
setCabal' SetOptions{ sToolVer } = setCabal' SetOptions{ sToolVer } =
case sToolVer of case sToolVer of
(SetToolVersion v) -> runSetCabal runLeanAppState (liftE $ setCabal (_tvVersion v) >> pure v) (SetToolVersion v) -> runSetCabal runLeanAppState (liftE $ setCabal v >> pure (mkTVer v))
_ -> runSetCabal runAppState (do _ -> runSetCabal runAppState (do
v <- liftE $ fst <$> fromVersion' sToolVer Cabal v <- liftE $ fst <$> fromVersion' sToolVer Cabal
liftE $ setCabal (_tvVersion v) liftE $ setCabal (_tvVersion v)
pure v pure v
) )
>>= \case >>= \case
VRight GHCTargetVersion{..} -> do VRight v -> do
runLogger runLogger
$ logInfo $ $ logInfo $
"Cabal " <> prettyVer _tvVersion <> " successfully set as default version" "Cabal " <> prettyVer (_tvVersion v) <> " successfully set as default version"
pure ExitSuccess pure ExitSuccess
VLeft e -> do VLeft e -> do
runLogger $ logError $ T.pack $ prettyShow e runLogger $ logError $ T.pack $ prettyShow e
@@ -311,17 +314,17 @@ set setCommand runAppState runLeanAppState runLogger = case setCommand of
-> m ExitCode -> m ExitCode
setHLS' SetOptions{ sToolVer } = setHLS' SetOptions{ sToolVer } =
case sToolVer of case sToolVer of
(SetToolVersion v) -> runSetHLS runLeanAppState (liftE $ setHLS (_tvVersion v) SetHLSOnly Nothing >> pure v) (SetToolVersion v) -> runSetHLS runLeanAppState (liftE $ setHLS v SetHLSOnly Nothing >> pure (mkTVer v))
_ -> runSetHLS runAppState (do _ -> runSetHLS runAppState (do
v <- liftE $ fst <$> fromVersion' sToolVer HLS v <- liftE $ fst <$> fromVersion' sToolVer HLS
liftE $ setHLS (_tvVersion v) SetHLSOnly Nothing liftE $ setHLS (_tvVersion v) SetHLSOnly Nothing
pure v pure v
) )
>>= \case >>= \case
VRight GHCTargetVersion{..} -> do VRight v -> do
runLogger runLogger
$ logInfo $ $ logInfo $
"HLS " <> prettyVer _tvVersion <> " successfully set as default version" "HLS " <> prettyVer (_tvVersion v) <> " successfully set as default version"
pure ExitSuccess pure ExitSuccess
VLeft e -> do VLeft e -> do
runLogger $ logError $ T.pack $ prettyShow e runLogger $ logError $ T.pack $ prettyShow e
@@ -332,17 +335,17 @@ set setCommand runAppState runLeanAppState runLogger = case setCommand of
-> m ExitCode -> m ExitCode
setStack' SetOptions{ sToolVer } = setStack' SetOptions{ sToolVer } =
case sToolVer of case sToolVer of
(SetToolVersion v) -> runSetStack runLeanAppState (liftE $ setStack (_tvVersion v) >> pure v) (SetToolVersion v) -> runSetStack runLeanAppState (liftE $ setStack v >> pure (mkTVer v))
_ -> runSetStack runAppState (do _ -> runSetStack runAppState (do
v <- liftE $ fst <$> fromVersion' sToolVer Stack v <- liftE $ fst <$> fromVersion' sToolVer Stack
liftE $ setStack (_tvVersion v) liftE $ setStack (_tvVersion v)
pure v pure v
) )
>>= \case >>= \case
VRight GHCTargetVersion{..} -> do VRight v -> do
runLogger runLogger
$ logInfo $ $ logInfo $
"Stack " <> prettyVer _tvVersion <> " successfully set as default version" "Stack " <> prettyVer (_tvVersion v) <> " successfully set as default version"
pure ExitSuccess pure ExitSuccess
VLeft e -> do VLeft e -> do
runLogger $ logError $ T.pack $ prettyShow e runLogger $ logError $ T.pack $ prettyShow e

View File

@@ -75,14 +75,14 @@ data WhereisOptions = WhereisOptions {
--[ Parsers ]-- --[ Parsers ]--
--------------- ---------------
whereisP :: Parser WhereisCommand whereisP :: Parser WhereisCommand
whereisP = subparser whereisP = subparser
(commandGroup "Tools locations:" <> (commandGroup "Tools locations:" <>
command command
"ghc" "ghc"
(WhereisTool GHC <$> info (WhereisTool GHC <$> info
( optional (toolVersionArgument Nothing (Just GHC)) <**> helper ) ( optional (toolVersionTagArgument Nothing (Just GHC)) <**> helper )
( progDesc "Get GHC location" ( progDesc "Get GHC location"
<> footerDoc (Just $ text whereisGHCFooter )) <> footerDoc (Just $ text whereisGHCFooter ))
) )
@@ -90,7 +90,7 @@ whereisP = subparser
command command
"cabal" "cabal"
(WhereisTool Cabal <$> info (WhereisTool Cabal <$> info
( optional (toolVersionArgument Nothing (Just Cabal)) <**> helper ) ( optional (toolVersionTagArgument Nothing (Just Cabal)) <**> helper )
( progDesc "Get cabal location" ( progDesc "Get cabal location"
<> footerDoc (Just $ text whereisCabalFooter )) <> footerDoc (Just $ text whereisCabalFooter ))
) )
@@ -98,7 +98,7 @@ whereisP = subparser
command command
"hls" "hls"
(WhereisTool HLS <$> info (WhereisTool HLS <$> info
( optional (toolVersionArgument Nothing (Just HLS)) <**> helper ) ( optional (toolVersionTagArgument Nothing (Just HLS)) <**> helper )
( progDesc "Get HLS location" ( progDesc "Get HLS location"
<> footerDoc (Just $ text whereisHLSFooter )) <> footerDoc (Just $ text whereisHLSFooter ))
) )
@@ -106,7 +106,7 @@ whereisP = subparser
command command
"stack" "stack"
(WhereisTool Stack <$> info (WhereisTool Stack <$> info
( optional (toolVersionArgument Nothing (Just Stack)) <**> helper ) ( optional (toolVersionTagArgument Nothing (Just Stack)) <**> helper )
( progDesc "Get stack location" ( progDesc "Get stack location"
<> footerDoc (Just $ text whereisStackFooter )) <> footerDoc (Just $ text whereisStackFooter ))
) )
@@ -268,7 +268,7 @@ whereis :: ( Monad m
whereis whereisCommand whereisOptions runAppState leanAppstate runLogger = do whereis whereisCommand whereisOptions runAppState leanAppstate runLogger = do
Dirs{ .. } <- runReaderT getDirs leanAppstate Dirs{ .. } <- runReaderT getDirs leanAppstate
case (whereisCommand, whereisOptions) of case (whereisCommand, whereisOptions) of
(WhereisTool tool (Just (ToolVersion v)), WhereisOptions{..}) -> (WhereisTool tool (Just (GHCVersion v)), WhereisOptions{..}) ->
runLeanWhereIs leanAppstate (do runLeanWhereIs leanAppstate (do
loc <- liftE $ whereIsTool tool v loc <- liftE $ whereIsTool tool v
if directory if directory
@@ -282,6 +282,20 @@ whereis whereisCommand whereisOptions runAppState leanAppstate runLogger = do
VLeft e -> do VLeft e -> do
runLogger $ logError $ T.pack $ prettyShow e runLogger $ logError $ T.pack $ prettyShow e
pure $ ExitFailure 30 pure $ ExitFailure 30
(WhereisTool tool (Just (ToolVersion v)), WhereisOptions{..}) ->
runLeanWhereIs leanAppstate (do
loc <- liftE $ whereIsTool tool (mkTVer v)
if directory
then pure $ takeDirectory loc
else pure loc
)
>>= \case
VRight r -> do
liftIO $ putStr r
pure ExitSuccess
VLeft e -> do
runLogger $ logError $ T.pack $ prettyShow e
pure $ ExitFailure 30
(WhereisTool tool whereVer, WhereisOptions{..}) -> do (WhereisTool tool whereVer, WhereisOptions{..}) -> do
runWhereIs runAppState (do runWhereIs runAppState (do

View File

@@ -238,7 +238,7 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
| Just False <- optVerbose -> pure () | Just False <- optVerbose -> pure ()
| otherwise -> lookupEnv "GHCUP_SKIP_UPDATE_CHECK" >>= \case | 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
-- https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/283 -- https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/283
alreadyInstalling' <- alreadyInstalling optCommand newTool alreadyInstalling' <- alreadyInstalling optCommand newTool
@@ -279,7 +279,7 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
runAppState action' = do runAppState action' = do
s' <- liftIO appState s' <- liftIO appState
runReaderT action' s' runReaderT action' s'
----------------- -----------------
-- Run command -- -- Run command --
@@ -339,16 +339,16 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
alreadyInstalling (Install (Left (InstallHLS InstallOptions{..}))) (HLS, ver) = cmp' HLS instVer ver alreadyInstalling (Install (Left (InstallHLS InstallOptions{..}))) (HLS, ver) = cmp' HLS instVer ver
alreadyInstalling (Install (Left (InstallStack InstallOptions{..}))) (Stack, ver) = cmp' Stack instVer ver alreadyInstalling (Install (Left (InstallStack InstallOptions{..}))) (Stack, ver) = cmp' Stack instVer ver
alreadyInstalling (Compile (CompileGHC GHCCompileOptions{ ovewrwiteVer = Just over })) alreadyInstalling (Compile (CompileGHC GHCCompileOptions{ ovewrwiteVer = Just over }))
(GHC, ver) = cmp' GHC (Just $ ToolVersion (mkTVer over)) ver (GHC, ver) = cmp' GHC (Just $ GHCVersion (mkTVer over)) ver
alreadyInstalling (Compile (CompileGHC GHCCompileOptions{ targetGhc = GHC.SourceDist tver })) alreadyInstalling (Compile (CompileGHC GHCCompileOptions{ targetGhc = GHC.SourceDist tver }))
(GHC, ver) = cmp' GHC (Just $ ToolVersion (mkTVer tver)) ver (GHC, ver) = cmp' GHC (Just $ ToolVersion tver) ver
alreadyInstalling (Compile (CompileHLS HLSCompileOptions{ ovewrwiteVer = Right over })) alreadyInstalling (Compile (CompileHLS HLSCompileOptions{ ovewrwiteVer = Right over }))
(HLS, ver) = cmp' HLS (Just $ ToolVersion (mkTVer over)) ver (HLS, ver) = cmp' HLS (Just $ ToolVersion over) ver
alreadyInstalling (Compile (CompileHLS HLSCompileOptions{ targetHLS = HLS.SourceDist tver })) alreadyInstalling (Compile (CompileHLS HLSCompileOptions{ targetHLS = HLS.SourceDist tver }))
(HLS, ver) = cmp' HLS (Just $ ToolVersion (mkTVer tver)) ver (HLS, ver) = cmp' HLS (Just $ ToolVersion tver) ver
alreadyInstalling (Compile (CompileHLS HLSCompileOptions{ targetHLS = HLS.HackageDist tver })) alreadyInstalling (Compile (CompileHLS HLSCompileOptions{ targetHLS = HLS.HackageDist tver }))
(HLS, ver) = cmp' HLS (Just $ ToolVersion (mkTVer tver)) ver (HLS, ver) = cmp' HLS (Just $ ToolVersion tver) ver
alreadyInstalling (Upgrade _ _ _) (GHCup, _) = pure True alreadyInstalling (Upgrade {}) (GHCup, _) = pure True
alreadyInstalling _ _ = pure False alreadyInstalling _ _ = pure False
cmp' :: ( HasLog env cmp' :: ( HasLog env

View File

@@ -4,7 +4,7 @@ This is a more in-depth guide specific to GHCup. `ghcup --help` is your friend.
## Basic usage ## Basic usage
For the simple interactive TUI (not available on windows), run: For the simple, interactive, text-based user interface (TUI) (not available on windows), run:
```sh ```sh
ghcup tui ghcup tui
@@ -186,6 +186,51 @@ url-source:
# More on installation # More on installation
## Customisation of the installation scripts
The scripts offered to install GHCup are available here:
* [bootstrap-haskell](https://gitlab.haskell.org/haskell/ghcup-hs/-/blob/master/scripts/bootstrap/bootstrap-haskell#L7)
for Unix-like operating systems
* [bootstrap-haskell.ps1](https://gitlab.haskell.org/haskell/ghcup-hs/-/blob/master/scripts/bootstrap/bootstrap-haskell.ps1#L17)
for Windows (PowerShell). This will, in turn, run the final bootstrap script
(by default, that for the Unix-like operating systems).
The effect of the scripts can be customised by setting one or more
`BOOTSTRAP_HASKELL_*` environment variables (as set out in the first script)
and, in the case of Windows, by specifying parameters (as set out in the
PowerShell script).
For example, you can toggle:
* non-interactive installation
* a more verbose installation
* whether to install only GHCup (and, on Windows, MSYS2)
* not to trigger the upgrade of GHCup
* whether to install the latest version of HLS
* whether to install the latest version of Stack
* whether to respect the XDG Base Directory Specification
* whether to adjust (prepend) the PATH in `bashrc`
* on Windows, whether to adjust MINGW paths in `cabal.config`
You can also specify:
* the GHC version to install
* the Cabal version to install
* which downloader to use (the default is `curl`)
* the base URL for the download of the GHCup binary distribution
On Windows, you can also use the parameters to:
* toggle whether to overwrite a previous installation
* specify the GHCup installation root directory
* specify the Cabal root directory
* specify the directory of an existing installation of MSYS2 (for example,
the one supplied by Stack)
* specify the URL of the final bootstrap script
* toggle whether to run the final bootstrap script via `bash` (instead of in a
new MSYS2 shell)
## Installing custom bindists ## Installing custom bindists
There are a couple of good use cases to install custom bindists: There are a couple of good use cases to install custom bindists:
@@ -193,7 +238,8 @@ There are a couple of good use cases to install custom bindists:
1. manually built bindists (e.g. with patches) 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` - 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 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` - example specifying a branch (`master`): `ghcup install ghc -u 'https://gitlab.haskell.org/ghc/ghc/-/jobs/artifacts/master/raw/ghc-x86_64-linux-fedora33-release.tar.xz?job=x86_64-linux-fedora33-release' head`
- example specifying a job id (`1129565`): `ghcup install ghc -u ' https://gitlab.haskell.org/api/v4/projects/1/jobs/1129565/artifacts/ghc-x86_64-linux-alpine3_12-validate+fully_static.tar.xz' mr7847`
3. DWARF bindists 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` - 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`
@@ -257,6 +303,23 @@ To instruct cabal to run `cabal update` before building, run `ghcup compile hls
As always, check `ghcup compile hls --help`. As always, check `ghcup compile hls --help`.
#### Updating HLS for a new GHC version
First try to build from hackage with some tricks:
```sh
ghcup compile hls --version 1.7.0.0 --ghc 9.2.4 --cabal-update -- --allow-newer --index-state=2022-06-12T00:00:00Z
```
This augments the currently installed 1.7.0.0 official bindists in ghcup with new GHC versions support.
If that fails (since `--allow-newer` is quite brutal), you can install from HLS master branch (which may contain new fixes) like so:
```
ghcup compile hls --git-ref master --git-describe-version --ghc 8.10.7 --ghc 9.2.4 --cabal-update
```
This however will create a new HLS version in ghcup, e.g. `1.7.0.0-105-gdc682ba1`, for both 8.10.7 and 9.2.4. If you want to switch back to the official bindists, run `ghcup set hls 1.7.0.0`.
### Cross support ### Cross support
ghcup can compile and install a cross GHC for any target. However, this ghcup can compile and install a cross GHC for any target. However, this
@@ -284,24 +347,26 @@ You need to use the `--isolate` or `-i` flag followed by the directory path.
Examples: Examples:
1. install an isolated GHC version at location /home/user/isolated_dir/ghc/ 1. install an isolated GHC version at location /home/user/isolated_dir/ghc/
- `ghcup install ghc 8.10.5 --isolate /home/user/isolated_dir/ghc` - `ghcup install ghc 8.10.5 --isolate /home/user/isolated_dir/ghc`
2. isolated install Cabal at a location you desire 2. isolated install Cabal at a location you desire
- `ghcup install cabal --isolate /home/username/my_isolated_dir/` - `ghcup install cabal --isolate /home/username/my_isolated_dir/`
3. do an isolated install with a custom bindist 3. do an isolated install with a custom bindist
- `ghcup install ghc --isolate /home/username/my_isolated_dir/ -u 'https://gitlab.haskell.org/api/v4/projects/1/jobs/artifacts/master/raw/ghc-x86_64-fedora27-linux.tar.xz?job=validate-x86_64-linux-fedora27' head` - `ghcup install ghc --isolate /home/username/my_isolated_dir/ -u 'https://gitlab.haskell.org/ghc/ghc/-/jobs/artifacts/master/raw/ghc-x86_64-linux-fedora33-release.tar.xz?job=x86_64-linux-fedora33-release' head`
4. isolated install HLS 4. isolated install HLS
- `ghcup install hls --isolate /home/username/dir/hls/` - `ghcup install hls --isolate /home/username/dir/hls/`
5. you can even compile ghc to an isolated location. 5. you can even compile ghc to an isolated location.
- `ghcup compile ghc -j 4 -v 9.0.1 -b 8.10.5 -i /home/username/my/dir/ghc` - `ghcup compile ghc -j 4 -v 9.0.1 -b 8.10.5 -i /home/username/my/dir/ghc`
## Continuous integration ## Continuous integration
On windows, ghcup can be installed automatically on a CI runner non-interactively like so: On Windows, GHCup can be installed automatically on a CI runner
non-interactively, as below. The paramaters to the PowerShell script are
specified positionally, after `-ArgumentList`:
```ps ```ps
Set-ExecutionPolicy Bypass -Scope Process -Force;[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072;Invoke-Command -ScriptBlock ([ScriptBlock]::Create((Invoke-WebRequest https://www.haskell.org/ghcup/sh/bootstrap-haskell.ps1 -UseBasicParsing))) -ArgumentList $false,$true,$true,$false,$false,$false,$false,"C:\" Set-ExecutionPolicy Bypass -Scope Process -Force;[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072;Invoke-Command -ScriptBlock ([ScriptBlock]::Create((Invoke-WebRequest https://www.haskell.org/ghcup/sh/bootstrap-haskell.ps1 -UseBasicParsing))) -ArgumentList $false,$true,$true,$false,$false,$false,$false,"C:\"
@@ -313,12 +378,10 @@ On linux/darwin/freebsd, run the following on your runner:
curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | BOOTSTRAP_HASKELL_NONINTERACTIVE=1 BOOTSTRAP_HASKELL_MINIMAL=1 sh curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | BOOTSTRAP_HASKELL_NONINTERACTIVE=1 BOOTSTRAP_HASKELL_MINIMAL=1 sh
``` ```
This will just install `ghcup` and on windows additionally `msys2`. This will just install `ghcup` and on Windows additionally MSYS2.
For the full list of env variables and parameters to tweak the script behavior, see: See the installation scripts referred to above for the full list of environment
variables and, in the case of Windows, parameters to tweak the script behavior.
* [bootstrap-haskell for linux/darwin/freebsd](https://gitlab.haskell.org/haskell/ghcup-hs/-/blob/master/scripts/bootstrap/bootstrap-haskell#L7)
* [bootstrap-haskell.ps1 for windows](https://gitlab.haskell.org/haskell/ghcup-hs/-/blob/master/scripts/bootstrap/bootstrap-haskell.ps1#L17)
### github workflows ### github workflows
@@ -353,7 +416,7 @@ 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 ## ghcup run
@@ -367,3 +430,34 @@ ghcup run --ghc 8.10.7 --cabal latest --hls latest --stack latest --install -- c
``` ```
This will execute vscode with GHC set to 8.10.7 and all other tools to their latest version. This will execute vscode with GHC set to 8.10.7 and all other tools to their latest version.
# Troubleshooting
## Script immediately exits on windows
There are two possible reasons:
1. your company blocks the script (some have a whitelist)... ask your administrator
2. your Antivirus or Windows Defender interfere with the installation. Disable them temporarily.
## C compiler cannot create executables
### Darwin
You need to update your XCode command line tools, e.g. [like this](https://stackoverflow.com/questions/34617452/how-to-update-xcode-from-command-line).
## Certificate authority errors (curl)
If your certificates are outdated or improperly configured, curl may be unable
to download ghcup.
There are two known workarounds:
1. Tell curl to ignore certificate errors (dangerous): `curl -k https://gitlab.haskell.org/haskell/ghcup-hs/-/raw/master/scripts/bootstrap/bootstrap-haskell | GHCUP_CURL_OPTS="-k" sh`
2. Try to use wget instead: `wget -O /dev/stdout https://gitlab.haskell.org/haskell/ghcup-hs/-/raw/master/scripts/bootstrap/bootstrap-haskell | BOOTSTRAP_HASKELL_DOWNLOADER=wget sh`
On windows, you can disable curl like so:
```pwsh
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,$false,$false,$false,$false,$false,$false,"","","","",$true
```

View File

@@ -57,7 +57,7 @@ hide:
</section> </section>
<p id="help" class="ghcup-help"> <p id="help" class="ghcup-help">
Need help? Ask on Need help? Check the <a href="guide/#troubleshooting">Troubleshooting section</a> or ask on
<span> <span>
<a href="https://kiwiirc.com/nextclient/irc.libera.chat/?nick=Guest%7C?#haskell,#haskell-ghcup"> <a href="https://kiwiirc.com/nextclient/irc.libera.chat/?nick=Guest%7C?#haskell,#haskell-ghcup">
<img src="irc.svg" alt="" /> <img src="irc.svg" alt="" />

View File

@@ -55,7 +55,9 @@ GHCup supports the following tools, which are also known as the **Haskell Toolch
<table> <table>
<thead><tr><th>GHC Version</th><th>Tags</th></tr></thead> <thead><tr><th>GHC Version</th><th>Tags</th></tr></thead>
<tbody> <tbody>
<tr><td>9.2.3</td><td><span style="color:blue">latest</span>, base-4.16.2.0</td></tr> <tr><td>9.4.1</td><td><span style="color:blue">latest</span>, base-4.17.0.0</td></tr>
<tr><td>9.2.4</td><td>base-4.16.3.0</td></tr>
<tr><td>9.2.3</td><td>base-4.16.2.0</td></tr>
<tr><td>9.2.2</td><td>base-4.16.1.0</td></tr> <tr><td>9.2.2</td><td>base-4.16.1.0</td></tr>
<tr><td>9.2.1</td><td>base-4.16.0.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.2</td><td>base-4.15.1.0</td></tr>
@@ -208,6 +210,8 @@ The developers of the Haskell Language Server offer an [extension](https://githu
3. Make sure your project uses the GHC version installed from GHCup (otherwise HLS is likely to fail on launch): 3. Make sure your project uses the GHC version installed from GHCup (otherwise HLS is likely to fail on launch):
- instructions for [stack](https://docs.haskellstack.org/en/stable/yaml_configuration/#system-ghc) - instructions for [stack](https://docs.haskellstack.org/en/stable/yaml_configuration/#system-ghc)
On Linux, some users have reported an issue when VSCode is not launched from a terminal ("cannot find ghc version"). A solution is to [let HLS know about your GHCup on $PATH](https://github.com/haskell/vscode-haskell#stackcabalghc-can-not-be-found).
## Get help ## Get help
* [Libera IRC chat on #haskell-ghcup or #haskell](https://kiwiirc.com/nextclient/irc.libera.chat/?nick=Guest%7C?#haskell,#haskell-ghcup) * [Libera IRC chat on #haskell-ghcup or #haskell](https://kiwiirc.com/nextclient/irc.libera.chat/?nick=Guest%7C?#haskell,#haskell-ghcup)

View File

@@ -335,7 +335,7 @@ see the [Cabal user guide](https://cabal.readthedocs.io/en/stable/getting-starte
To learn Haskell, try any of those: 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/)) - A beginner friendly [4-lectures course](https://github.com/haskell-beginners-2022/course-plan) with exercises (by [Dmitrii Kovanikov](https://kodimensional.dev/))
- An in-depth university [CIS 194 Haskell course](https://www.cis.upenn.edu/~cis194/spring13/) including exercises (by [Brent Yorgey](https://byorgey.wordpress.com/)) - 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 ## Projects to contribute to

View File

@@ -1,6 +1,6 @@
cabal-version: 3.0 cabal-version: 3.0
name: ghcup name: ghcup
version: 0.1.18.0 version: 0.1.18.1
license: LGPL-3.0-only license: LGPL-3.0-only
license-file: LICENSE license-file: LICENSE
copyright: Julian Ospald 2020 copyright: Julian Ospald 2020
@@ -21,6 +21,8 @@ extra-doc-files:
README.md README.md
extra-source-files: extra-source-files:
cbits/dirutils.c
cbits/dirutils.h
data/build_mk/cross data/build_mk/cross
data/build_mk/default data/build_mk/default
test/golden/GHCupInfo.json test/golden/GHCupInfo.json
@@ -69,6 +71,7 @@ library
GHCup.Prelude.Process GHCup.Prelude.Process
GHCup.Prelude.String.QQ GHCup.Prelude.String.QQ
GHCup.Prelude.Version.QQ GHCup.Prelude.Version.QQ
GHCup.Prompts
GHCup.Requirements GHCup.Requirements
GHCup.Stack GHCup.Stack
GHCup.Types GHCup.Types
@@ -161,14 +164,13 @@ library
, terminal-progress-bar >=0.4.1 , terminal-progress-bar >=0.4.1
if os(windows) if os(windows)
cpp-options: -DIS_WINDOWS cpp-options: -DIS_WINDOWS
other-modules: other-modules:
GHCup.Prelude.File.Windows GHCup.Prelude.File.Windows
GHCup.Prelude.Windows GHCup.Prelude.Windows
-- GHCup.OptParse.Run uses this
exposed-modules:
GHCup.Prelude.Process.Windows
-- GHCup.OptParse.Run uses this
exposed-modules: GHCup.Prelude.Process.Windows
build-depends: build-depends:
, bzlib , bzlib
, process ^>=1.6.11.0 , process ^>=1.6.11.0
@@ -182,7 +184,10 @@ library
GHCup.Prelude.Posix GHCup.Prelude.Posix
GHCup.Prelude.Process.Posix GHCup.Prelude.Process.Posix
c-sources: cbits/dirutils.c include-dirs: cbits
includes: dirutils.h
install-includes: dirutils.h
c-sources: cbits/dirutils.c
build-depends: build-depends:
, bz2 >=0.5.0.5 && <1.1 , bz2 >=0.5.0.5 && <1.1
, terminal-size ^>=0.3.2.1 , terminal-size ^>=0.3.2.1
@@ -236,7 +241,7 @@ executable ghcup
, aeson-pretty ^>=0.8.8 , aeson-pretty ^>=0.8.8
, async ^>=2.2.3 , async ^>=2.2.3
, base >=4.12 && <5 , base >=4.12 && <5
, bytestring >=0.10 && <0.12 , bytestring >=0.10 && <0.12
, cabal-plan ^>=0.7.2 , cabal-plan ^>=0.7.2
, containers ^>=0.6 , containers ^>=0.6
, deepseq ^>=1.4 , deepseq ^>=1.4
@@ -313,11 +318,11 @@ test-suite ghcup-test
build-depends: build-depends:
, base >=4.12 && <5 , base >=4.12 && <5
, bytestring >=0.10 && <0.12 , bytestring >=0.10 && <0.12
, containers ^>=0.6 , containers ^>=0.6
, directory ^>=1.3.6.0 , directory ^>=1.3.6.0
, filepath ^>=1.4.2.1 , filepath ^>=1.4.2.1
, generic-arbitrary >=0.1.0 && < 0.2.1 || >=0.2.2 && <0.3 , generic-arbitrary >=0.1.0 && <0.2.1 || >=0.2.2 && <0.3
, ghcup , ghcup
, hspec >=2.7.10 && <2.10 , hspec >=2.7.10 && <2.10
, hspec-golden-aeson ^>=0.9 , hspec-golden-aeson ^>=0.9

View File

@@ -137,8 +137,8 @@ data AlreadyInstalled = AlreadyInstalled Tool Version
instance Pretty AlreadyInstalled where instance Pretty AlreadyInstalled where
pPrint (AlreadyInstalled tool ver') = pPrint (AlreadyInstalled tool ver') =
pPrint tool <+> text "-" <+> pPrint ver' <+> text "is already installed;" (pPrint tool <> text "-" <> pPrint ver') <+> text "is already installed;"
<+> text "if you really want to reinstall it, you may want to run 'ghcup install cabal --force" <+> (pPrint ver' <> text "'") <+> text "if you really want to reinstall it, you may want to run 'ghcup install" <+> pPrint tool <+> text "--force" <+> (pPrint ver' <> text "'")
-- | The Directory is supposed to be empty, but wasn't. -- | The Directory is supposed to be empty, but wasn't.

View File

@@ -301,8 +301,9 @@ installUnpackedGHC path inst ver forceInstall addConfArgs
| otherwise = do | otherwise = do
PlatformRequest {..} <- lift getPlatformReq PlatformRequest {..} <- lift getPlatformReq
let alpineArgs let ldOverride
| ver >= [vver|8.2.2|], Linux Alpine <- _rPlatform | ver >= [vver|8.2.2|]
, _rPlatform `elem` [Linux Alpine, Darwin]
= ["--disable-ld-override"] = ["--disable-ld-override"]
| otherwise | otherwise
= [] = []
@@ -310,7 +311,7 @@ installUnpackedGHC path inst ver forceInstall addConfArgs
lift $ logInfo "Installing GHC (this may take a while)" lift $ logInfo "Installing GHC (this may take a while)"
lEM $ execLogged "sh" lEM $ execLogged "sh"
("./configure" : ("--prefix=" <> fromInstallDir inst) ("./configure" : ("--prefix=" <> fromInstallDir inst)
: (alpineArgs <> (T.unpack <$> addConfArgs)) : (ldOverride <> (T.unpack <$> addConfArgs))
) )
(Just $ fromGHCupPath path) (Just $ fromGHCupPath path)
"ghc-configure" "ghc-configure"

28
lib/GHCup/Prompts.hs Normal file
View File

@@ -0,0 +1,28 @@
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE FlexibleContexts #-}
module GHCup.Prompts
( PromptQuestion,
PromptResponse (..),
getUserPromptResponse,
)
where
import Control.Monad.Reader
import qualified Data.Text.IO as TIO
import GHCup.Prelude.Logger
import GHCup.Types.Optics
import GHCup.Types (PromptQuestion, PromptResponse(..))
getUserPromptResponse :: ( HasLog env
, MonadReader env m
, MonadIO m)
=> PromptQuestion
-> m PromptResponse
getUserPromptResponse prompt = do
logInfo prompt
resp <- liftIO TIO.getLine
if resp `elem` ["YES", "yes", "y", "Y"]
then pure PromptYes
else pure PromptNo

View File

@@ -407,6 +407,9 @@ data AppState = AppState
instance NFData AppState instance NFData AppState
fromAppState :: AppState -> LeanAppState
fromAppState AppState {..} = LeanAppState {..}
data LeanAppState = LeanAppState data LeanAppState = LeanAppState
{ settings :: Settings { settings :: Settings
, dirs :: Dirs , dirs :: Dirs
@@ -654,3 +657,7 @@ isSafeDir (IsolateDirResolved _) = False
isSafeDir (GHCupDir _) = True isSafeDir (GHCupDir _) = True
isSafeDir (GHCupBinDir _) = False isSafeDir (GHCupBinDir _) = False
type PromptQuestion = Text
data PromptResponse = PromptYes | PromptNo
deriving (Show, Eq)

View File

@@ -12,10 +12,12 @@
# * BOOTSTRAP_HASKELL_VERBOSE - any nonzero value for more verbose installation # * BOOTSTRAP_HASKELL_VERBOSE - any nonzero value for more verbose installation
# * BOOTSTRAP_HASKELL_GHC_VERSION - the ghc version to install # * BOOTSTRAP_HASKELL_GHC_VERSION - the ghc version to install
# * BOOTSTRAP_HASKELL_CABAL_VERSION - the cabal version to install # * BOOTSTRAP_HASKELL_CABAL_VERSION - the cabal version to install
# * BOOTSTRAP_HASKELL_INSTALL_STACK - whether to install latest stack # * BOOTSTRAP_HASKELL_INSTALL_NO_STACK - disable installation of stack
# * BOOTSTRAP_HASKELL_INSTALL_NO_STACK_HOOK - disable installation stack ghcup hook
# * 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
# * BOOTSTRAP_HASKELL_DOWNLOADER - which downloader to use (default: curl)
# * GHCUP_BASE_URL - the base url for ghcup binary download (use this to overwrite https://downloads.haskell.org/~ghcup with a mirror) # * 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,10 +28,11 @@
plat="$(uname -s)" plat="$(uname -s)"
arch=$(uname -m) arch=$(uname -m)
ghver="0.1.17.8" ghver="0.1.18.0"
: "${GHCUP_BASE_URL:=https://downloads.haskell.org/~ghcup}" : "${GHCUP_BASE_URL:=https://downloads.haskell.org/~ghcup}"
export GHCUP_SKIP_UPDATE_CHECK=yes export GHCUP_SKIP_UPDATE_CHECK=yes
: "${BOOTSTRAP_HASKELL_DOWNLOADER:=curl}"
case "${plat}" in case "${plat}" in
MSYS*|MINGW*) MSYS*|MINGW*)
@@ -138,8 +141,12 @@ ecabal() {
} }
_ecabal() { _ecabal() {
# shellcheck disable=SC2086 if [ -n "${CABAL_BIN}" ] ; then
"${GHCUP_BIN}/cabal" "$@" "${CABAL_BIN}" "$@"
else
# shellcheck disable=SC2086
"${GHCUP_BIN}/cabal" "$@"
fi
} }
_done() { _done() {
@@ -322,11 +329,35 @@ download_ghcup() {
esac esac
case "${plat}" in case "${plat}" in
MSYS*|MINGW*) MSYS*|MINGW*)
edo curl -Lf "${_url}" > "${GHCUP_BIN}"/ghcup.exe case "${BOOTSTRAP_HASKELL_DOWNLOADER}" in
"curl")
# shellcheck disable=SC2086
edo curl -Lf ${GHCUP_CURL_OPTS} "${_url}" > "${GHCUP_BIN}"/ghcup.exe
;;
"wget")
# shellcheck disable=SC2086
edo wget -O /dev/stdout ${GHCUP_WGET_OPTS} "${_url}" > "${GHCUP_BIN}"/ghcup.exe
;;
*)
die "Unknown downloader: ${BOOTSTRAP_HASKELL_DOWNLOADER}"
;;
esac
edo chmod +x "${GHCUP_BIN}"/ghcup.exe edo chmod +x "${GHCUP_BIN}"/ghcup.exe
;; ;;
*) *)
edo curl -Lf "${_url}" > "${GHCUP_BIN}"/ghcup case "${BOOTSTRAP_HASKELL_DOWNLOADER}" in
"curl")
# shellcheck disable=SC2086
edo curl -Lf ${GHCUP_CURL_OPTS} "${_url}" > "${GHCUP_BIN}"/ghcup
;;
"wget")
# shellcheck disable=SC2086
edo wget -O /dev/stdout ${GHCUP_WGET_OPTS} "${_url}" > "${GHCUP_BIN}"/ghcup
;;
*)
die "Unknown downloader: ${BOOTSTRAP_HASKELL_DOWNLOADER}"
;;
esac
edo chmod +x "${GHCUP_BIN}"/ghcup edo chmod +x "${GHCUP_BIN}"/ghcup
;; ;;
esac esac
@@ -353,6 +384,17 @@ download_ghcup() {
# shellcheck disable=SC1090 # shellcheck disable=SC1090
edo . "${GHCUP_DIR}"/env edo . "${GHCUP_DIR}"/env
case "${BOOTSTRAP_HASKELL_DOWNLOADER}" in
"curl")
eghcup config set downloader Curl
;;
"wget")
eghcup config set downloader Wget
;;
*)
die "Unknown downloader: ${BOOTSTRAP_HASKELL_DOWNLOADER}"
;;
esac
eghcup upgrade eghcup upgrade
} }
@@ -618,7 +660,7 @@ ask_hls() {
warn "Do you want to install haskell-language-server (HLS)?" warn "Do you want to install haskell-language-server (HLS)?"
warn "HLS is a language-server that provides IDE-like functionality" warn "HLS is a language-server that provides IDE-like functionality"
warn "and can integrate with different editors, such as Vim, Emacs, VS Code, Atom, ..." warn "and can integrate with different editors, such as Vim, Emacs, VS Code, Atom, ..."
warn "Also see https://github.com/haskell/haskell-language-server/blob/master/README.md" warn "Also see https://haskell-language-server.readthedocs.io/en/stable/"
warn "" warn ""
warn "[Y] Yes [N] No [?] Help (default is \"N\")." warn "[Y] Yes [N] No [?] Help (default is \"N\")."
warn "" warn ""
@@ -651,40 +693,44 @@ ask_hls() {
} }
ask_stack() { ask_stack() {
if [ -n "${BOOTSTRAP_HASKELL_INSTALL_STACK}" ] ; then if [ -n "${BOOTSTRAP_HASKELL_INSTALL_NO_STACK}" ] ; then
return 0
elif [ -n "${BOOTSTRAP_HASKELL_INSTALL_NO_STACK_HOOK}" ] ; then
return 1 return 1
fi fi
if [ -z "${BOOTSTRAP_HASKELL_NONINTERACTIVE}" ] ; then if [ -z "${BOOTSTRAP_HASKELL_NONINTERACTIVE}" ] ; then
echo "-------------------------------------------------------------------------------" echo "-------------------------------------------------------------------------------"
warn "Do you want to install stack?" warn "Do you want to enable better integration of stack with GHCup?"
warn "Stack is a haskell build tool similar to cabal that is used by some projects." warn "This means that stack won't install its own GHC versions, but uses GHCup's."
warn "Also see https://docs.haskellstack.org/" warn "For more information see:"
warn " https://docs.haskellstack.org/en/stable/yaml_configuration/#ghc-installation-customisation-experimental"
warn "If you want to keep stacks vanilla behavior, answer 'No'."
warn "" warn ""
warn "[Y] Yes [N] No [?] Help (default is \"N\")." warn "[Y] Yes [N] No [?] Help (default is \"Y\")."
warn "" warn ""
while true; do while true; do
read -r stack_answer </dev/tty read -r stack_answer </dev/tty
case $stack_answer in case $stack_answer in
[Yy]*) [Yy]* | "")
return 2 ;;
[Nn]*)
return 1 ;; return 1 ;;
[Nn]* | "")
return 0 ;;
*) *)
echo "Possible choices are:" echo "Possible choices are:"
echo echo
echo "Y - Yes, install stack" echo "Y - Yes, enable better integration (default)"
echo "N - No, don't install anything more (default)" echo "N - No, keep stacks vanilla behavior"
echo echo
echo "Please make your choice and press ENTER." echo "Please make your choice and press ENTER."
;; ;;
esac esac
done done
else else
return 0 return 2
fi fi
unset stack_answer unset stack_answer
@@ -701,7 +747,7 @@ echo "This script can download and install the following binaries:"
echo " * ghcup - The Haskell toolchain installer" echo " * ghcup - The Haskell toolchain installer"
echo " * ghc - The Glasgow Haskell Compiler" echo " * ghc - The Glasgow Haskell Compiler"
echo " * cabal - The Cabal build tool for managing Haskell software" echo " * cabal - The Cabal build tool for managing Haskell software"
echo " * stack - (optional) A cross-platform program for developing Haskell projects" echo " * stack - A cross-platform program for developing Haskell projects (similar to cabal)"
echo " * hls - (optional) A language server for developers to integrate with their editor/IDE" echo " * hls - (optional) A language server for developers to integrate with their editor/IDE"
echo echo
if [ -z "${GHCUP_USE_XDG_DIRS}" ] ; then if [ -z "${GHCUP_USE_XDG_DIRS}" ] ; then
@@ -780,7 +826,7 @@ else # don't install ghc and cabal
# we'll remove it afterwards # we'll remove it afterwards
tmp_dir="$(mktemp -d)" tmp_dir="$(mktemp -d)"
eghcup --cache install cabal -i "${tmp_dir}" "${BOOTSTRAP_HASKELL_CABAL_VERSION}" eghcup --cache install cabal -i "${tmp_dir}" "${BOOTSTRAP_HASKELL_CABAL_VERSION}"
PATH="${tmp_dir}:$PATH" do_cabal_config_init $ask_cabal_config_init_answer CABAL_BIN="${tmp_dir}/cabal" do_cabal_config_init $ask_cabal_config_init_answer
rm "${tmp_dir}/cabal" rm "${tmp_dir}/cabal"
unset tmp_dir unset tmp_dir
;; ;;
@@ -798,7 +844,35 @@ esac
case $ask_stack_answer in case $ask_stack_answer in
1) 1)
_eghcup --cache install stack || warn "Stack installation failed, continuing anyway" _eghcup --cache install stack || die "Stack installation failed"
;;
2)
_eghcup --cache install stack || die "Stack installation failed"
edo mkdir -p "${STACK_ROOOT:-$HOME/.stack}"/hooks
hook_exe="${STACK_ROOOT:-$HOME/.stack}"/hooks/ghc-install.sh
hook_url="https://www.haskell.org/ghcup/sh/hooks/stack/ghc-install.sh"
if [ -e "${hook_exe}" ] ; then
warn "$hook_exe already exists, skipping hook installation."
warn "If you want to reinstall the hook, delete it manually and re-run"
warn "this script!"
else
case "${BOOTSTRAP_HASKELL_DOWNLOADER}" in
"curl")
# shellcheck disable=SC2086
edo curl -Lf ${GHCUP_CURL_OPTS} "${hook_url}" > "${hook_exe}"
;;
"wget")
# shellcheck disable=SC2086
edo wget -O /dev/stdout ${GHCUP_WGET_OPTS} "${hook_url}" > "${hook_exe}"
;;
*)
die "Unknown downloader: ${BOOTSTRAP_HASKELL_DOWNLOADER}"
;;
esac
edo chmod +x "${hook_exe}"
fi
;; ;;
*) ;; *) ;;
esac esac

View File

@@ -36,7 +36,9 @@ param (
# Instead of installing a new MSys2, use an existing installation # Instead of installing a new MSys2, use an existing installation
[string]$ExistingMsys2Dir, [string]$ExistingMsys2Dir,
# Specify the cabal root directory (default: '$InstallDir\cabal') # Specify the cabal root directory (default: '$InstallDir\cabal')
[string]$CabalDir [string]$CabalDir,
# Whether to disable use of curl.exe
[switch]$DisableCurl
) )
$Silent = !$Interactive $Silent = !$Interactive
@@ -425,7 +427,7 @@ if (!(Test-Path -Path ('{0}' -f $MsysDir))) {
$archive = 'msys2-x86_64-latest.sfx.exe' $archive = 'msys2-x86_64-latest.sfx.exe'
$archivePath = ('{0}\{1}' -f ([IO.Path]::GetTempPath()), "$archive") $archivePath = ('{0}\{1}' -f ([IO.Path]::GetTempPath()), "$archive")
if (Get-Command -Name 'curl.exe' -ErrorAction SilentlyContinue) { if ((Get-Command -Name 'curl.exe' -ErrorAction SilentlyContinue) -and !($DisableCurl)) {
Exec "curl.exe" '-o' "$archivePath" ('https://repo.msys2.org/distrib/{0}' -f "$archive") Exec "curl.exe" '-o' "$archivePath" ('https://repo.msys2.org/distrib/{0}' -f "$archive")
} else { } else {
Get-FileWCSynchronous -url ('https://repo.msys2.org/distrib/{0}' -f $archive) -destinationFolder ([IO.Path]::GetTempPath()) -includeStats Get-FileWCSynchronous -url ('https://repo.msys2.org/distrib/{0}' -f $archive) -destinationFolder ([IO.Path]::GetTempPath()) -includeStats
@@ -575,8 +577,8 @@ $Msys2Shell = ('{0}\msys2_shell.cmd' -f $MsysDir)
# The bootstrap script is always silent, since we ask relevant questions here # The bootstrap script is always silent, since we ask relevant questions here
$SilentExport = 'export BOOTSTRAP_HASKELL_NONINTERACTIVE=1 ;' $SilentExport = 'export BOOTSTRAP_HASKELL_NONINTERACTIVE=1 ;'
if ($InstallStack) { if (!($InstallStack)) {
$StackInstallExport = 'export BOOTSTRAP_HASKELL_INSTALL_STACK=1 ;' $StackInstallExport = 'export BOOTSTRAP_HASKELL_INSTALL_NO_STACK=1 ;'
} }
if ($InstallHLS) { if ($InstallHLS) {
@@ -591,10 +593,17 @@ if ($Minimal) {
$MinimalExport = 'export BOOTSTRAP_HASKELL_MINIMAL=1 ;' $MinimalExport = 'export BOOTSTRAP_HASKELL_MINIMAL=1 ;'
} }
if ((Get-Process -ID $PID).ProcessName.StartsWith("bootstrap-haskell") -Or $InBash) { if ($DisableCurl) {
Exec "$Bash" '-lc' ('{4} {6} {7} {8} {9} [ -n ''{1}'' ] && export GHCUP_MSYS2=$(cygpath -m ''{1}'') ; [ -n ''{2}'' ] && export GHCUP_INSTALL_BASE_PREFIX=$(cygpath -m ''{2}/'') ; export PATH=$(cygpath -u ''{3}/bin''):$PATH ; export CABAL_DIR=''{5}'' ; [[ ''{0}'' = https* ]] && curl --proto ''=https'' --tlsv1.2 -sSf {0} | bash || cat $(cygpath -m ''{0}'') | bash' -f $BootstrapUrl, $MsysDir, $GhcupBasePrefix, $GhcupDir, $SilentExport, $CabalDirFull, $StackInstallExport, $HLSInstallExport, $AdjustCabalConfigExport, $MinimalExport) $BootstrapDownloader = 'export BOOTSTRAP_HASKELL_DOWNLOADER=wget ;'
$DownloadScript = 'wget -O /dev/stdout'
} else { } else {
Exec "$Msys2Shell" '-mingw64' '-mintty' '-c' ('{4} {6} {7} {8} {9} [ -n ''{1}'' ] && export GHCUP_MSYS2=$(cygpath -m ''{1}'') ; [ -n ''{2}'' ] && export GHCUP_INSTALL_BASE_PREFIX=$(cygpath -m ''{2}/'') ; export PATH=$(cygpath -u ''{3}/bin''):$PATH ; export CABAL_DIR=''{5}'' ; trap ''echo Press any key to exit && read -n 1 && exit'' 2 ; [[ ''{0}'' = https* ]] && curl --proto ''=https'' --tlsv1.2 -sSf {0} | bash || cat $(cygpath -m ''{0}'') | bash ; echo ''Press any key to exit'' && read -n 1' -f $BootstrapUrl, $MsysDir, $GhcupBasePrefix, $GhcupDir, $SilentExport, $CabalDirFull, $StackInstallExport, $HLSInstallExport, $AdjustCabalConfigExport, $MinimalExport) $DownloadScript = 'curl --proto ''=https'' --tlsv1.2 -sSf'
}
if ((Get-Process -ID $PID).ProcessName.StartsWith("bootstrap-haskell") -Or $InBash) {
Exec "$Bash" '-lc' ('{4} {6} {7} {8} {9} {10} [ -n ''{1}'' ] && export GHCUP_MSYS2=$(cygpath -m ''{1}'') ; [ -n ''{2}'' ] && export GHCUP_INSTALL_BASE_PREFIX=$(cygpath -m ''{2}/'') ; export PATH=$(cygpath -u ''{3}/bin''):$PATH ; export CABAL_DIR=''{5}'' ; [[ ''{0}'' = https* ]] && {11} {0} | bash || cat $(cygpath -m ''{0}'') | bash' -f $BootstrapUrl, $MsysDir, $GhcupBasePrefix, $GhcupDir, $SilentExport, $CabalDirFull, $StackInstallExport, $HLSInstallExport, $AdjustCabalConfigExport, $MinimalExport, $BootstrapDownloader, $DownloadScript)
} else {
Exec "$Msys2Shell" '-mingw64' '-mintty' '-c' ('{4} {6} {7} {8} {9} {10} [ -n ''{1}'' ] && export GHCUP_MSYS2=$(cygpath -m ''{1}'') ; [ -n ''{2}'' ] && export GHCUP_INSTALL_BASE_PREFIX=$(cygpath -m ''{2}/'') ; export PATH=$(cygpath -u ''{3}/bin''):$PATH ; export CABAL_DIR=''{5}'' ; trap ''echo Press any key to exit && read -n 1 && exit'' 2 ; [[ ''{0}'' = https* ]] && {11} {0} | bash || cat $(cygpath -m ''{0}'') | bash ; echo ''Press any key to exit'' && read -n 1' -f $BootstrapUrl, $MsysDir, $GhcupBasePrefix, $GhcupDir, $SilentExport, $CabalDirFull, $StackInstallExport, $HLSInstallExport, $AdjustCabalConfigExport, $MinimalExport, $BootstrapDownloader, $DownloadScript)
} }

View File

@@ -0,0 +1,24 @@
#!/bin/sh
# !! KEEP THIS SCRIPT POSIX COMPLIANT !!
# see https://docs.haskellstack.org/en/stable/yaml_configuration/#ghc-installation-customisation-experimental
# for documentation about hooks
set -eu
case $HOOK_GHC_TYPE in
bindist)
ghcdir=$(ghcup whereis --directory ghc "$HOOK_GHC_VERSION" || ghcup run --ghc "$HOOK_GHC_VERSION" --install) || exit 3
printf "%s/ghc" "${ghcdir}"
;;
git)
# TODO: should be somewhat possible
>&2 echo "Hook doesn't support installing from source"
exit 1
;;
*)
>&2 echo "Unsupported GHC installation type: $HOOK_GHC_TYPE"
exit 2
;;
esac