Compare commits
9 Commits
v0.1.17.6-
...
max_path
| Author | SHA1 | Date | |
|---|---|---|---|
|
92bd333552
|
|||
|
70a451b63e
|
|||
|
cfe6c47cd7
|
|||
|
8eeb32c495
|
|||
|
fdcd6822c4
|
|||
|
71390c84da
|
|||
|
84d01b1091
|
|||
|
8f9faaa39e
|
|||
|
0898244b2a
|
@@ -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 ( getDirs )
|
import GHCup.Types.Optics
|
||||||
import GHCup.Utils.Logger
|
import GHCup.Utils.Logger
|
||||||
import GHCup.Utils.String.QQ
|
import GHCup.Utils.String.QQ
|
||||||
|
|
||||||
@@ -187,14 +187,16 @@ runLeanRUN leanAppstate =
|
|||||||
@RunEffects
|
@RunEffects
|
||||||
|
|
||||||
runRUN :: MonadUnliftIO m
|
runRUN :: MonadUnliftIO m
|
||||||
=> (ReaderT AppState m (VEither RunEffects a) -> m (VEither RunEffects a))
|
=> IO AppState
|
||||||
-> Excepts RunEffects (ResourceT (ReaderT AppState m)) a
|
-> Excepts RunEffects (ResourceT (ReaderT AppState m)) a
|
||||||
-> m (VEither RunEffects a)
|
-> m (VEither RunEffects a)
|
||||||
runRUN runAppState =
|
runRUN appState action' = do
|
||||||
runAppState
|
s' <- liftIO appState
|
||||||
|
flip runReaderT s'
|
||||||
. runResourceT
|
. runResourceT
|
||||||
. runE
|
. runE
|
||||||
@RunEffects
|
@RunEffects
|
||||||
|
$ action'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -212,52 +214,77 @@ run :: forall m.
|
|||||||
, MonadUnliftIO m
|
, MonadUnliftIO m
|
||||||
)
|
)
|
||||||
=> RunOptions
|
=> RunOptions
|
||||||
-> (forall a. ReaderT AppState m (VEither RunEffects a) -> m (VEither RunEffects a))
|
-> IO AppState
|
||||||
-> LeanAppState
|
-> LeanAppState
|
||||||
-> (ReaderT LeanAppState m () -> m ())
|
-> (ReaderT LeanAppState m () -> m ())
|
||||||
-> m ExitCode
|
-> m ExitCode
|
||||||
run RunOptions{..} runAppState leanAppstate runLogger = runE @RunEffects ( do
|
run RunOptions{..} runAppState leanAppstate runLogger = do
|
||||||
toolchain <- Excepts resolveToolchain
|
r <- if or (fmap (maybe False isToolTag) [runGHCVer, runCabalVer, runHLSVer, runStackVer]) || runInstTool'
|
||||||
tmp <- case runBinDir of
|
then runRUN runAppState $ do
|
||||||
Just bindir -> do
|
toolchain <- liftE resolveToolchainFull
|
||||||
liftIO $ createDirRecursive' bindir
|
tmp <- case runBinDir of
|
||||||
liftIO $ canonicalizePath bindir
|
Just bindir -> do
|
||||||
Nothing -> do
|
liftIO $ createDirRecursive' bindir
|
||||||
d <- liftIO $ predictableTmpDir toolchain
|
liftIO $ canonicalizePath bindir
|
||||||
liftIO $ createDirRecursive' d
|
Nothing -> do
|
||||||
liftIO $ canonicalizePath d
|
d <- liftIO $ predictableTmpDir toolchain
|
||||||
Excepts $ installToolChain toolchain tmp
|
liftIO $ createDirRecursive' d
|
||||||
pure tmp
|
liftIO $ canonicalizePath d
|
||||||
) >>= \case
|
liftE $ installToolChainFull toolchain tmp
|
||||||
VRight tmp -> do
|
pure tmp
|
||||||
case runCOMMAND of
|
else runLeanRUN leanAppstate $ do
|
||||||
[] -> do
|
toolchain <- resolveToolchain
|
||||||
liftIO $ putStr tmp
|
tmp <- case runBinDir of
|
||||||
pure ExitSuccess
|
Just bindir -> do
|
||||||
(cmd:args) -> do
|
liftIO $ createDirRecursive' bindir
|
||||||
newEnv <- liftIO $ addToPath tmp
|
liftIO $ canonicalizePath bindir
|
||||||
|
Nothing -> do
|
||||||
|
d <- liftIO $ predictableTmpDir toolchain
|
||||||
|
liftIO $ createDirRecursive' d
|
||||||
|
liftIO $ canonicalizePath d
|
||||||
|
liftE $ installToolChain toolchain tmp
|
||||||
|
pure tmp
|
||||||
|
case r of
|
||||||
|
VRight tmp -> do
|
||||||
|
case runCOMMAND of
|
||||||
|
[] -> do
|
||||||
|
liftIO $ putStr tmp
|
||||||
|
pure ExitSuccess
|
||||||
|
(cmd:args) -> do
|
||||||
|
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
|
||||||
resolveToolchain
|
resolveToolchainFull :: ( MonadFail m
|
||||||
| or (fmap (maybe False isToolTag) [runGHCVer, runCabalVer, runHLSVer, runStackVer]) || runInstTool' = runRUN runAppState $ do
|
, MonadThrow m
|
||||||
|
, MonadIO m
|
||||||
|
, MonadCatch m
|
||||||
|
)
|
||||||
|
=> Excepts
|
||||||
|
'[ TagNotFound
|
||||||
|
, NextVerNotFound
|
||||||
|
, NoToolVersionSet
|
||||||
|
] (ResourceT (ReaderT AppState m)) Toolchain
|
||||||
|
resolveToolchainFull = do
|
||||||
ghcVer <- forM runGHCVer $ \ver -> do
|
ghcVer <- forM runGHCVer $ \ver -> do
|
||||||
(v, _) <- liftE $ fromVersion (Just ver) GHC
|
(v, _) <- liftE $ fromVersion (Just ver) GHC
|
||||||
pure v
|
pure v
|
||||||
@@ -271,7 +298,8 @@ run RunOptions{..} runAppState leanAppstate runLogger = runE @RunEffects ( do
|
|||||||
(v, _) <- liftE $ fromVersion (Just ver) Stack
|
(v, _) <- liftE $ fromVersion (Just ver) Stack
|
||||||
pure v
|
pure v
|
||||||
pure Toolchain{..}
|
pure Toolchain{..}
|
||||||
| otherwise = runLeanRUN leanAppstate $ do
|
|
||||||
|
resolveToolchain = do
|
||||||
ghcVer <- case runGHCVer of
|
ghcVer <- case runGHCVer of
|
||||||
Just (ToolVersion v) -> pure $ Just v
|
Just (ToolVersion v) -> pure $ Just v
|
||||||
Nothing -> pure Nothing
|
Nothing -> pure Nothing
|
||||||
@@ -290,8 +318,33 @@ run RunOptions{..} runAppState leanAppstate runLogger = runE @RunEffects ( do
|
|||||||
_ -> fail "Internal error"
|
_ -> fail "Internal error"
|
||||||
pure Toolchain{..}
|
pure Toolchain{..}
|
||||||
|
|
||||||
installToolChain Toolchain{..} tmp
|
installToolChainFull :: ( MonadFail m
|
||||||
| or (fmap (maybe False isToolTag) [runGHCVer, runCabalVer, runHLSVer, runStackVer]) || runInstTool' = runRUN runAppState $ do
|
, MonadThrow m
|
||||||
|
, MonadIO m
|
||||||
|
, MonadCatch m
|
||||||
|
)
|
||||||
|
=> 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
|
forM_ [(GHC,) <$> ghcVer, (Cabal,) <$> cabalVer, (HLS,) <$> hlsVer, (Stack,) <$> stackVer] $ \mt -> do
|
||||||
isInstalled <- maybe (pure False) (\(tool, v) -> lift $ checkIfToolInstalled' tool v) mt
|
isInstalled <- maybe (pure False) (\(tool, v) -> lift $ checkIfToolInstalled' tool v) mt
|
||||||
case mt of
|
case mt of
|
||||||
@@ -320,7 +373,16 @@ run RunOptions{..} runAppState leanAppstate runLogger = runE @RunEffects ( do
|
|||||||
False
|
False
|
||||||
setTool HLS v tmp
|
setTool HLS v tmp
|
||||||
_ -> pure ()
|
_ -> pure ()
|
||||||
| otherwise = runLeanRUN leanAppstate $ do
|
|
||||||
|
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
|
forM_ [(GHC,) <$> ghcVer, (Cabal,) <$> cabalVer, (HLS,) <$> hlsVer, (Stack,) <$> stackVer] $ \mt -> do
|
||||||
case mt of
|
case mt of
|
||||||
Just (GHC, v) -> setTool GHC v tmp
|
Just (GHC, v) -> setTool GHC v tmp
|
||||||
|
|||||||
@@ -315,7 +315,7 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
|
|||||||
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 runAppState leanAppstate runLogger
|
Run runCommand -> run runCommand appState leanAppstate runLogger
|
||||||
|
|
||||||
case res of
|
case res of
|
||||||
ExitSuccess -> pure ()
|
ExitSuccess -> pure ()
|
||||||
|
|||||||
@@ -181,6 +181,48 @@ _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
|
||||||
|
|
||||||
|
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
|
||||||
@@ -427,23 +469,23 @@ adjust_bashrc() {
|
|||||||
;;
|
;;
|
||||||
fish)
|
fish)
|
||||||
mkdir -p "${GHCUP_PROFILE_FILE%/*}"
|
mkdir -p "${GHCUP_PROFILE_FILE%/*}"
|
||||||
sed -i -e '/# ghcup-env$/ s/^#*/#/' "${GHCUP_PROFILE_FILE}"
|
sed -i -e '/# ghcup-env$/ s/^#*/#/' "$(posix_realpath "${GHCUP_PROFILE_FILE}")"
|
||||||
case $1 in
|
case $1 in
|
||||||
1)
|
1)
|
||||||
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}"
|
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}"
|
||||||
;;
|
;;
|
||||||
2)
|
2)
|
||||||
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}"
|
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}"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
bash)
|
bash)
|
||||||
sed -i -e '/# ghcup-env$/ s/^#*/#/' "${GHCUP_PROFILE_FILE}"
|
sed -i -e '/# ghcup-env$/ s/^#*/#/' "$(posix_realpath "${GHCUP_PROFILE_FILE}")"
|
||||||
echo "[ -f \"${GHCUP_DIR}/env\" ] && source \"${GHCUP_DIR}/env\" # ghcup-env" >> "${GHCUP_PROFILE_FILE}"
|
printf "\n%s" "[ -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
|
||||||
echo "[[ -f ~/.bashrc ]] && source ~/.bashrc # ghcup-env" >> "${HOME}/.bash_profile"
|
printf "\n%s" "[[ -f ~/.bashrc ]] && source ~/.bashrc # ghcup-env" >> "${HOME}/.bash_profile"
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
MSYS*|MINGW*)
|
MSYS*|MINGW*)
|
||||||
@@ -457,8 +499,8 @@ adjust_bashrc() {
|
|||||||
;;
|
;;
|
||||||
|
|
||||||
zsh)
|
zsh)
|
||||||
sed -i -e '/# ghcup-env$/ s/^#*/#/' "${GHCUP_PROFILE_FILE}"
|
sed -i -e '/# ghcup-env$/ s/^#*/#/' "$(posix_realpath "${GHCUP_PROFILE_FILE}")"
|
||||||
echo "[ -f \"${GHCUP_DIR}/env\" ] && source \"${GHCUP_DIR}/env\" # ghcup-env" >> "${GHCUP_PROFILE_FILE}"
|
printf "\n%s" "[ -f \"${GHCUP_DIR}/env\" ] && source \"${GHCUP_DIR}/env\" # ghcup-env" >> "${GHCUP_PROFILE_FILE}"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
echo
|
echo
|
||||||
|
|||||||
Reference in New Issue
Block a user