Compare commits

...

25 Commits

Author SHA1 Message Date
5cf297a4d2 Clarify stack postinstall message wrt #153 2021-07-11 15:09:16 +02:00
d86f84eef4 Improve logging with newlines 2021-07-11 14:34:05 +02:00
83458c6c1e Merge branch 'issue-163' 2021-07-11 13:51:27 +02:00
e8d79c9d38 Warn when powershell script is run as admin
Fixes #163
2021-07-09 22:29:10 +02:00
59e1eee8ce Update linux aarch64 ghcup binary
Partly addresses #160
2021-07-09 22:06:37 +02:00
57c8ffda35 Update hacking docs 2021-07-09 19:51:21 +02:00
171ebd213d Merge branch 'issue-175' 2021-07-07 20:47:44 +02:00
2a240cbd09 Make sure HLS and stack installation failures don't exit the entire script
Fixes #175
2021-07-07 20:08:12 +02:00
068fa3454c Update website 2021-07-04 22:15:56 +02:00
6b2bcbf2ce Merge branch 'issue-151' 2021-07-04 20:27:45 +02:00
19e46dac18 Avoid too many questions 2021-07-04 19:45:43 +02:00
e96c863120 Speed up installation wrt #151 2021-07-03 21:16:46 +02:00
a30b3c84d7 Loosen bound on versions wrt #164 2021-07-03 17:48:39 +02:00
0ad5dc4583 Fix CI 2021-07-03 16:51:58 +02:00
7189998f3b Cleanup rmGhcupDirs a bit 2021-07-03 11:25:49 +02:00
b6b24b8e0b Update CHANGELOG 2021-07-03 11:15:45 +02:00
8e820c6e89 Clean up and fix nuke command 2021-07-03 11:15:37 +02:00
c74784a37c Merge remote-tracking branch 'origin/merge-requests/101' 2021-07-03 11:15:09 +02:00
3d940cffcf Merge remote-tracking branch 'origin/merge-requests/102' 2021-07-02 14:37:19 +02:00
0df044b284 Merge remote-tracking branch 'origin/merge-requests/103' 2021-07-02 14:02:43 +02:00
f576b9fb20 Merge remote-tracking branch 'origin/merge-requests/104' 2021-07-02 14:01:58 +02:00
5e00264119 Update hashes 2021-07-02 13:56:03 +02:00
Tom Ellis
05eeba32fa Make it clear that Windows is supported 2021-07-01 13:43:24 +00:00
Tom Ellis
9f343c45e8 Fix typo 2021-06-25 20:06:18 +00:00
Colin Barrett
fa11ca665f Use GetFolderPath to get the Desktop location
On my system, for example, Desktop is backed up with OneDrive
2021-06-15 22:25:24 -04:00
18 changed files with 411 additions and 282 deletions

View File

@@ -7,7 +7,7 @@ variables:
GIT_SSL_NO_VERIFY: "1" GIT_SSL_NO_VERIFY: "1"
# Commit of ghc/ci-images repository from which to pull Docker images # Commit of ghc/ci-images repository from which to pull Docker images
DOCKER_REV: 1ac7f435c9312f10422a82d304194778378e2a1a DOCKER_REV: 8d0224e6b2a08157649651e69302380b2bd24e11
############################################################ ############################################################
# CI Step # CI Step
@@ -149,17 +149,19 @@ variables:
script: | script: |
set -Eeuo pipefail set -Eeuo pipefail
function runInNixShell() { function runInNixShell() {
time nix-shell .gitlab/shell.nix \ time nix-shell $CI_PROJECT_DIR/.gitlab/shell.nix \
-I nixpkgs=https://github.com/angerman/nixpkgs/archive/75f7281738b.tar.gz \ -I nixpkgs=https://github.com/angerman/nixpkgs/archive/75f7281738b.tar.gz \
--argstr system "aarch64-darwin" \ --argstr system "aarch64-darwin" \
--pure \ --pure \
--keep GHC_VERSION --keep CABAL_INSTALL_VERSION --keep BUILD_FLAVOUR \ --keep CI_PROJECT_DIR \
--keep BIN_DIST_PREP_TAR_COMP --keep CPUS --keep PROJECT_DIR \ --keep MACOSX_DEPLOYMENT_TARGET \
--keep CI_PROJECT_DIR --keep MAKE_ARGS --keep HADRIAN_ARGS --keep CABAL_CACHE \ --keep JSON_VERSION \
--keep LANG --keep CONFIGURE_ARGS --keep TEST_ENV --keep BIN_DIST_NAME \ --keep ARTIFACT \
--keep MACOSX_DEPLOYMENT_TARGET --keep ac_cv_func_clock_gettime --keep HACKAGE_INDEX_STATE \ --keep OS \
--keep CABAL_DIR --keep ARCH --keep OS --keep CABAL_VERSION --keep GHC_VERSION \ --keep ARCH \
--keep JSON_VERSION --ARTIFACT \ --keep CABAL_DIR \
--keep GHC_VERSION \
--keep CABAL_VERSION \
--run "$1" 2>&1 --run "$1" 2>&1
} }
runInNixShell ./.gitlab/before_script/darwin/install_deps.sh 2>&1 runInNixShell ./.gitlab/before_script/darwin/install_deps.sh 2>&1
@@ -219,6 +221,23 @@ test:linux:bootstrap_script:
CABAL_VERSION: "3.4.0.0" CABAL_VERSION: "3.4.0.0"
extends: extends:
- .debian - .debian
- .root_cleanup
needs: []
test:windows:bootstrap_powershell_script:
stage: test
script:
- ./bootstrap-haskell.ps1 -InstallDir $CI_PROJECT_DIR -BootstrapUrl $CI_PROJECT_DIR/bootstrap-haskell -InBash
after_script:
- "[Environment]::SetEnvironmentVariable('GHCUP_INSTALL_BASE_PREFIX', $null, [System.EnvironmentVariableTarget]::User)"
- "[Environment]::SetEnvironmentVariable('GHCUP_MSYS2', $null, [System.EnvironmentVariableTarget]::User)"
- "[Environment]::SetEnvironmentVariable('CABAL_DIR', $null, [System.EnvironmentVariableTarget]::User)"
- bash ./.gitlab/after_script.sh
variables:
GHC_VERSION: "8.10.5"
CABAL_VERSION: "3.4.0.0"
extends:
- .windows
needs: [] needs: []
######## linux test ######## ######## linux test ########
@@ -405,13 +424,9 @@ release:darwin:aarch64:
-I nixpkgs=https://github.com/angerman/nixpkgs/archive/75f7281738b.tar.gz \ -I nixpkgs=https://github.com/angerman/nixpkgs/archive/75f7281738b.tar.gz \
--argstr system "aarch64-darwin" \ --argstr system "aarch64-darwin" \
--pure \ --pure \
--keep GHC_VERSION --keep CABAL_INSTALL_VERSION --keep BUILD_FLAVOUR \
--keep BIN_DIST_PREP_TAR_COMP --keep CPUS --keep PROJECT_DIR \
--keep CI_PROJECT_DIR --keep MAKE_ARGS --keep HADRIAN_ARGS --keep CABAL_CACHE \ --keep CI_PROJECT_DIR --keep MAKE_ARGS --keep HADRIAN_ARGS --keep CABAL_CACHE \
--keep LANG --keep CONFIGURE_ARGS --keep TEST_ENV --keep BIN_DIST_NAME \ --keep MACOSX_DEPLOYMENT_TARGET \
--keep MACOSX_DEPLOYMENT_TARGET --keep ac_cv_func_clock_gettime --keep HACKAGE_INDEX_STATE \ --keep JSON_VERSION --keep ARTIFACT \
--keep CABAL_DIR --keep ARCH --keep OS --keep CABAL_VERSION --keep GHC_VERSION \
--keep JSON_VERSION --ARTIFACT \
--run "$1" 2>&1 --run "$1" 2>&1
} }
runInNixShell ./.gitlab/before_script/darwin/install_deps.sh 2>&1 runInNixShell ./.gitlab/before_script/darwin/install_deps.sh 2>&1

View File

@@ -19,4 +19,14 @@ fi
./ghcup-bin set ${GHC_VERSION} ./ghcup-bin set ${GHC_VERSION}
./ghcup-bin install-cabal ${CABAL_VERSION} ./ghcup-bin install-cabal ${CABAL_VERSION}
if [ $ARCH = 'ARM64' ] ; then
cabal update
mkdir vendored
cd vendored
cabal unpack network-3.1.2.1
cd network*
autoreconf -fi
cd ../..
fi
exit 0 exit 0

View File

@@ -104,35 +104,39 @@ if [ "${OS}" != "WINDOWS" ] ; then
fi fi
# test installing new ghc doesn't mess with currently set GHC if [ "${OS}" = "DARWIN" ] && [ "${ARCH}" = "ARM64" ] ; then
# https://gitlab.haskell.org/haskell/ghcup-hs/issues/7 echo
if [ "${OS}" = "LINUX" ] ; then else
eghcup --downloader=wget install 8.10.3 # test installing new ghc doesn't mess with currently set GHC
else # test wget a bit # https://gitlab.haskell.org/haskell/ghcup-hs/issues/7
eghcup install 8.10.3 if [ "${OS}" = "LINUX" ] ; then
fi eghcup --downloader=wget install 8.10.3
[ "$(ghc --numeric-version)" = "${ghc_ver}" ] else # test wget a bit
eghcup set 8.10.3 eghcup install 8.10.3
eghcup set 8.10.3 fi
[ "$(ghc --numeric-version)" = "8.10.3" ] [ "$(ghc --numeric-version)" = "${ghc_ver}" ]
eghcup set ${GHC_VERSION} eghcup set 8.10.3
[ "$(ghc --numeric-version)" = "${ghc_ver}" ] eghcup set 8.10.3
eghcup rm 8.10.3 [ "$(ghc --numeric-version)" = "8.10.3" ]
[ "$(ghc --numeric-version)" = "${ghc_ver}" ] eghcup set ${GHC_VERSION}
[ "$(ghc --numeric-version)" = "${ghc_ver}" ]
eghcup rm 8.10.3
[ "$(ghc --numeric-version)" = "${ghc_ver}" ]
if [ "${OS}" = "DARWIN" ] ; then if [ "${OS}" = "DARWIN" ] ; then
eghcup install hls
haskell-language-server-wrapper --version
eghcup install stack
stack --version
elif [ "${OS}" = "LINUX" ] ; then
if [ "${ARCH}" = "64" ] ; then
eghcup install hls eghcup install hls
haskell-language-server-wrapper --version haskell-language-server-wrapper --version
eghcup install stack eghcup install stack
stack --version stack --version
elif [ "${OS}" = "LINUX" ] ; then
if [ "${ARCH}" = "64" ] ; then
eghcup install hls
haskell-language-server-wrapper --version
eghcup install stack
stack --version
fi
fi fi
fi fi
@@ -150,3 +154,11 @@ fi
eghcup upgrade eghcup upgrade
eghcup upgrade -f eghcup upgrade -f
# nuke
eghcup nuke
if [ "${OS}" = "WINDOWS" ] ; then
[ ! -e "${GHCUP_INSTALL_BASE_PREFIX}/ghcup" ]
else
[ ! -e "${GHCUP_INSTALL_BASE_PREFIX}/.ghcup" ]
fi

View File

@@ -44,9 +44,6 @@
# unconditionally add the MacOSX.sdk and TargetConditional.h # unconditionally add the MacOSX.sdk and TargetConditional.h
export NIX_CFLAGS_COMPILE+=" -isystem /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include" export NIX_CFLAGS_COMPILE+=" -isystem /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include"
# Use an architecture specific home, so cabal for different architectures don't confuse each other.
export HOME="$HOME/$(uname -m)-home"
mkdir -p $HOME
''; '';
nativeBuildInputs = (with pkgs; [ nativeBuildInputs = (with pkgs; [
@@ -81,6 +78,7 @@
which which
wget wget
curl
file file
xz xz

View File

@@ -1,5 +1,9 @@
# Revision history for ghcup # Revision history for ghcup
## 0.1.16 -- ????-??-??
* Add 'nuke' subcommand wrt [#135](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/135), implemented by Arjun Kathuria
## 0.1.15.2 -- 2021-06-13 ## 0.1.15.2 -- 2021-06-13
* Remove legacy handling of cabal binary and be more graceful about binaries not installed by ghcup (e.g. stack) * Remove legacy handling of cabal binary and be more graceful about binaries not installed by ghcup (e.g. stack)

View File

@@ -69,3 +69,7 @@ yaml files: `ghcup-<yaml-ver>.yaml`.
Most of the `Version` parameters to functions had to be replaced with Most of the `Version` parameters to functions had to be replaced with
that and ensured the logic is consistent for cross and non-cross that and ensured the logic is consistent for cross and non-cross
installs. installs.
2. This refactor added windows support wrt [#130](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/130).
The major changes here were switching `hpath` library out for `filepath`/`directory` (sadly) and
introducing a non-unix way of handling processes via the `process` library. It also introduced considerable
amounts of CPP wrt file handling, installation etc.

View File

@@ -1,5 +1,5 @@
`ghcup` makes it easy to install specific versions of `ghc` on GNU/Linux, `ghcup` makes it easy to install specific versions of `ghc` on GNU/Linux,
macOS (aka Darwin) and FreeBSD and can also bootstrap a fresh Haskell developer environment from scratch. macOS (aka Darwin), FreeBSD and Windows and can also bootstrap a fresh Haskell developer environment from scratch.
It follows the unix UNIX philosophy of [do one thing and do it well](https://en.wikipedia.org/wiki/Unix_philosophy#Do_One_Thing_and_Do_It_Well). It follows the unix UNIX philosophy of [do one thing and do it well](https://en.wikipedia.org/wiki/Unix_philosophy#Do_One_Thing_and_Do_It_Well).
Similar in scope to [rustup](https://github.com/rust-lang-nursery/rustup.rs), [pyenv](https://github.com/pyenv/pyenv) and [jenv](http://www.jenv.be). Similar in scope to [rustup](https://github.com/rust-lang-nursery/rustup.rs), [pyenv](https://github.com/pyenv/pyenv) and [jenv](http://www.jenv.be).
@@ -85,7 +85,7 @@ handles your haskell packages and can demand that [a specific version](https://c
A configuration file can be put in `~/.ghcup/config.yaml`. The default config file A configuration file can be put in `~/.ghcup/config.yaml`. The default config file
explaining all possible configurations can be found in this repo: [config.yaml](./config.yaml). explaining all possible configurations can be found in this repo: [config.yaml](./config.yaml).
Partial configuration is fine. Command line options always overwrite the config file settings. Partial configuration is fine. Command line options always override the config file settings.
### Manpages ### Manpages

View File

@@ -1113,7 +1113,10 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
let loggerConfig = LoggerConfig let loggerConfig = LoggerConfig
{ lcPrintDebug = verbose settings { lcPrintDebug = verbose settings
, colorOutter = B.hPut stderr , colorOutter = B.hPut stderr
, rawOutter = B.appendFile logfile , rawOutter =
case optCommand of
Nuke -> \_ -> pure ()
_ -> B.appendFile logfile
} }
let runLogger = myLoggerT loggerConfig let runLogger = myLoggerT loggerConfig
let siletRunLogger = myLoggerT loggerConfig { colorOutter = \_ -> pure () } let siletRunLogger = myLoggerT loggerConfig { colorOutter = \_ -> pure () }
@@ -1703,31 +1706,27 @@ Make sure to clean up #{tmpdir} afterwards.|])
Nuke -> Nuke ->
runRm (do runRm (do
lift $ runLogger $ $logWarn "WARNING: This will remove GHCup and all installed components from your system." lift $ $logWarn "WARNING: This will remove GHCup and all installed components from your system."
lift $ runLogger $ $logWarn "Waiting 10 seconds before commencing, if you want to cancel it, now would be the time." lift $ $logWarn "Waiting 10 seconds before commencing, if you want to cancel it, now would be the time."
liftIO $ threadDelay 10000000 -- wait 10s liftIO $ threadDelay 10000000 -- wait 10s
lift $ runLogger $ $logInfo "Initiating Nuclear Sequence 🚀🚀🚀" lift $ $logInfo "Initiating Nuclear Sequence 🚀🚀🚀"
lift $ runLogger $ $logInfo "Nuking in 3...2...1" lift $ $logInfo "Nuking in 3...2...1"
lInstalled <- lift $ listVersions Nothing (Just ListInstalled)
lInstalled <- lift $ runLogger . flip runReaderT appstate $ listVersions Nothing (Just ListInstalled)
forM_ lInstalled (liftE . rmTool) forM_ lInstalled (liftE . rmTool)
leftOverFiles <- lift $ runLogger $ runReaderT rmGhcupDirs appstate lift rmGhcupDirs
pure leftOverFiles
) >>= \case ) >>= \case
VRight leftOverFiles -> do VRight leftOverFiles
| null leftOverFiles -> do
case length leftOverFiles of
0 -> do
runLogger $ $logInfo "Nuclear Annihilation complete!" runLogger $ $logInfo "Nuclear Annihilation complete!"
pure ExitSuccess pure ExitSuccess
_ -> do | otherwise -> do
runLogger $ $logWarn "These Directories/Files have survived Nuclear Annihilation, you may remove them manually." runLogger $ $logWarn "These Files have survived Nuclear Annihilation, you may remove them manually."
forM_ leftOverFiles (runLogger . $logDebug . T.pack) forM_ leftOverFiles putStrLn
pure ExitSuccess pure ExitSuccess
VLeft e -> do VLeft e -> do

View File

@@ -210,6 +210,90 @@ download_ghcup() {
eghcup upgrade eghcup upgrade
} }
adjust_bashrc() {
case $SHELL in
*/zsh) # login shell is zsh
GHCUP_PROFILE_FILE="$HOME/.zshrc"
MY_SHELL="zsh" ;;
*/bash) # login shell is bash
GHCUP_PROFILE_FILE="$HOME/.bashrc"
MY_SHELL="bash" ;;
*/sh) # login shell is sh, but might be a symlink to bash or zsh
if [ -n "${BASH}" ] ; then
GHCUP_PROFILE_FILE="$HOME/.bashrc"
MY_SHELL="bash"
elif [ -n "${ZSH_VERSION}" ] ; then
GHCUP_PROFILE_FILE="$HOME/.zshrc"
MY_SHELL="zsh"
else
return
fi
;;
*/fish) # login shell is fish
GHCUP_PROFILE_FILE="$HOME/.config/fish/config.fish"
MY_SHELL="fish" ;;
*) return ;;
esac
warn ""
warn "Detected ${MY_SHELL} shell on your system..."
warn "If you want ghcup to automatically add the required PATH variable to \"${GHCUP_PROFILE_FILE}\""
warn ""
warn "[Y] Yes [N] No [?] Help (default is \"Y\")."
warn ""
while true; do
if [ -z "${BOOTSTRAP_HASKELL_NONINTERACTIVE}" ] ; then
read -r next_answer </dev/tty
else
next_answer="yes"
fi
case $next_answer in
[Nn]*)
return ;;
[Yy]* | "")
case $MY_SHELL in
"") break ;;
fish)
mkdir -p "${GHCUP_PROFILE_FILE%/*}"
sed -i -e '/# ghcup-env$/ s/^#*/#/' "${GHCUP_PROFILE_FILE}"
echo "set -q GHCUP_INSTALL_BASE_PREFIX[1]; or set GHCUP_INSTALL_BASE_PREFIX \$HOME ; test -f $GHCUP_DIR/env ; and set -gx PATH \$HOME/.cabal/bin $GHCUP_BIN \$PATH # ghcup-env" >> "${GHCUP_PROFILE_FILE}"
break ;;
bash)
sed -i -e '/# ghcup-env$/ s/^#*/#/' "${GHCUP_PROFILE_FILE}"
echo "[ -f \"${GHCUP_DIR}/env\" ] && source \"${GHCUP_DIR}/env\" # ghcup-env" >> "${GHCUP_PROFILE_FILE}"
case "${plat}" in
"Darwin"|"darwin")
if ! grep -q "ghcup-env" "${HOME}/.bash_profile" ; then
echo "[[ -f ~/.bashrc ]] && source ~/.bashrc # ghcup-env" >> "${HOME}/.bash_profile"
fi
;;
esac
break ;;
zsh)
sed -i -e '/# ghcup-env$/ s/^#*/#/' "${GHCUP_PROFILE_FILE}"
echo "[ -f \"${GHCUP_DIR}/env\" ] && source \"${GHCUP_DIR}/env\" # ghcup-env" >> "${GHCUP_PROFILE_FILE}"
break ;;
esac
warn "OK! ${GHCUP_PROFILE_FILE} has been modified. Restart your terminal for the changes to take effect,"
warn "or type \"source ${GHCUP_DIR}/env\" to apply them in your current terminal session."
return
;;
*)
echo "Possible choices are:"
echo
echo "Y - Yes, update my \"${GHCUP_PROFILE_FILE}\" (default)"
echo "N - No, don't mess with my configuration"
echo
echo "Please make your choice and press ENTER."
;;
esac
done
}
echo echo
echo "Welcome to Haskell!" echo "Welcome to Haskell!"
@@ -317,6 +401,7 @@ esac
edo cabal new-update edo cabal new-update
if [ -z "${BOOTSTRAP_HASKELL_NONINTERACTIVE}" ] ; then if [ -z "${BOOTSTRAP_HASKELL_NONINTERACTIVE}" ] ; then
warn "Do you want to install haskell-language-server (HLS) now?" warn "Do you want to install haskell-language-server (HLS) now?"
warn "HLS is a language-server that provides IDE-like functionality" warn "HLS is a language-server that provides IDE-like functionality"
@@ -331,7 +416,7 @@ if [ -z "${BOOTSTRAP_HASKELL_NONINTERACTIVE}" ] ; then
case $hls_answer in case $hls_answer in
[Yy]*) [Yy]*)
eghcup --cache install hls || warn "HLS installation failed, continuing anyway" _eghcup --cache install hls || warn "HLS installation failed, continuing anyway"
break ;; break ;;
[Nn]* | "") [Nn]* | "")
break ;; break ;;
@@ -358,7 +443,7 @@ if [ -z "${BOOTSTRAP_HASKELL_NONINTERACTIVE}" ] ; then
case $stack_answer in case $stack_answer in
[Yy]*) [Yy]*)
eghcup --cache install stack || warn "Stack installation failed, continuing anyway" _eghcup --cache install stack || warn "Stack installation failed, continuing anyway"
break ;; break ;;
[Nn]* | "") [Nn]* | "")
break ;; break ;;
@@ -372,89 +457,24 @@ if [ -z "${BOOTSTRAP_HASKELL_NONINTERACTIVE}" ] ; then
;; ;;
esac esac
done done
fi
echo "In order to run ghc and cabal, you need to adjust your PATH variable." # short-circuit script based on platform
echo "You may want to source '$GHCUP_DIR/env' in your shell" case "${plat}" in
echo "configuration to do so (e.g. ~/.bashrc)." MSYS*|MINGW*)
# For windows we always adjust bashrc, since it's inside msys2
adjust_bashrc
;;
*)
if [ -z "${BOOTSTRAP_HASKELL_NONINTERACTIVE}" ] ; then
echo "In order to run ghc and cabal, you need to adjust your PATH variable."
echo "You may want to source '$GHCUP_DIR/env' in your shell"
echo "configuration to do so (e.g. ~/.bashrc)."
case $SHELL in adjust_bashrc
*/zsh) # login shell is zsh
GHCUP_PROFILE_FILE="$HOME/.zshrc"
MY_SHELL="zsh" ;;
*/bash) # login shell is bash
GHCUP_PROFILE_FILE="$HOME/.bashrc"
MY_SHELL="bash" ;;
*/sh) # login shell is sh, but might be a symlink to bash or zsh
if [ -n "${BASH}" ] ; then
GHCUP_PROFILE_FILE="$HOME/.bashrc"
MY_SHELL="bash"
elif [ -n "${ZSH_VERSION}" ] ; then
GHCUP_PROFILE_FILE="$HOME/.zshrc"
MY_SHELL="zsh"
else
_done
fi fi
;; ;;
*/fish) # login shell is fish esac
GHCUP_PROFILE_FILE="$HOME/.config/fish/config.fish"
MY_SHELL="fish" ;;
*) _done ;;
esac
warn ""
warn "Detected ${MY_SHELL} shell on your system..."
warn "If you want ghcup to automatically add the required PATH variable to \"${GHCUP_PROFILE_FILE}\""
warn ""
warn "[Y] Yes [N] No [?] Help (default is \"Y\")."
warn ""
while true; do
read -r next_answer </dev/tty
case $next_answer in
[Nn]*)
_done ;;
[Yy]* | "")
case $MY_SHELL in
"") break ;;
fish)
mkdir -p "${GHCUP_PROFILE_FILE%/*}"
sed -i -e '/# ghcup-env$/ s/^#*/#/' "${GHCUP_PROFILE_FILE}"
echo "set -q GHCUP_INSTALL_BASE_PREFIX[1]; or set GHCUP_INSTALL_BASE_PREFIX \$HOME ; test -f $GHCUP_DIR/env ; and set -gx PATH \$HOME/.cabal/bin $GHCUP_BIN \$PATH # ghcup-env" >> "${GHCUP_PROFILE_FILE}"
break ;;
bash)
sed -i -e '/# ghcup-env$/ s/^#*/#/' "${GHCUP_PROFILE_FILE}"
echo "[ -f \"${GHCUP_DIR}/env\" ] && source \"${GHCUP_DIR}/env\" # ghcup-env" >> "${GHCUP_PROFILE_FILE}"
case "${plat}" in
"Darwin"|"darwin")
if ! grep -q "ghcup-env" "${HOME}/.bash_profile" ; then
echo "[[ -f ~/.bashrc ]] && source ~/.bashrc # ghcup-env" >> "${HOME}/.bash_profile"
fi
;;
esac
break ;;
zsh)
sed -i -e '/# ghcup-env$/ s/^#*/#/' "${GHCUP_PROFILE_FILE}"
echo "[ -f \"${GHCUP_DIR}/env\" ] && source \"${GHCUP_DIR}/env\" # ghcup-env" >> "${GHCUP_PROFILE_FILE}"
break ;;
esac
warn "OK! ${GHCUP_PROFILE_FILE} has been modified. Restart your terminal for the changes to take effect,"
warn "or type \"source ${GHCUP_DIR}/env\" to apply them in your current terminal session."
_done
;;
*)
echo "Possible choices are:"
echo
echo "Y - Yes, update my \"${GHCUP_PROFILE_FILE}\" (default)"
echo "N - No, don't mess with my configuration"
echo
echo "Please make your choice and press ENTER."
;;
esac
done
fi
_done _done

View File

@@ -13,20 +13,24 @@
* hls - (optional) A language server for developers to integrate with their editor/IDE" * hls - (optional) A language server for developers to integrate with their editor/IDE"
#> #>
param ( param (
# Run a non-interactive installation # Run an interactive installation
[switch]$Silent, [switch]$Interactive,
# Specify the install root (default: 'C:\') # Specify the install root (default: 'C:\')
[string]$InstallDir, [string]$InstallDir,
# 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,
# Perform a quick installation, omitting some expensive operations (you may have to install dependencies yourself later)
[bool]$Quick,
# Overwrite (or rather backup) a previous install # Overwrite (or rather backup) a previous install
[bool]$Overwrite [switch]$Overwrite,
# Specify the bootstrap url (default: 'https://www.haskell.org/ghcup/sh/bootstrap-haskell')
[string]$BootstrapUrl,
# Run the final bootstrap script via 'bash' instead of a full newly spawned msys2 shell
[switch]$InBash
) )
$Silent = !$Interactive
function Print-Msg { function Print-Msg {
param ( [Parameter(Mandatory=$true, HelpMessage='String to output')][string]$msg, [string]$color = "Green" ) param ( [Parameter(Mandatory=$true, HelpMessage='String to output')][string]$msg, [string]$color = "Green" )
Write-Host ('{0}' -f $msg) -ForegroundColor $color Write-Host ('{0}' -f $msg) -ForegroundColor $color
@@ -146,12 +150,41 @@ function Exec
$ErrorActionPreference = 'Stop' $ErrorActionPreference = 'Stop'
$elevated = ([Security.Principal.WindowsPrincipal] `
[Security.Principal.WindowsIdentity]::GetCurrent()
).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
if ($elevated) {
Print-Msg -color Yellow -msg ('This script should not be run as administrator/elevated. Waiting 10s before continuing anyway...')
Start-Sleep -s 10
}
$GhcupBasePrefixEnv = [System.Environment]::GetEnvironmentVariable('GHCUP_INSTALL_BASE_PREFIX', 'user') $GhcupBasePrefixEnv = [System.Environment]::GetEnvironmentVariable('GHCUP_INSTALL_BASE_PREFIX', 'user')
if ($GhcupBasePrefixEnv) { if ($GhcupBasePrefixEnv) {
$defaultGhcupBasePrefix = $GhcupBasePrefixEnv $defaultGhcupBasePrefix = $GhcupBasePrefixEnv
} else { } else {
$defaultGhcupBasePrefix = 'C:\' $partitions = Get-CimInstance win32_logicaldisk
$defaultGhcupBasePrefix = $null
foreach ($p in $partitions){
try {
if ($p."FreeSpace" -lt 5368709120) { # at least 5 GB are needed
throw ("Not enough free space on {0}" -f $p."DeviceId")
}
$null = New-Item -Path ('{0}\' -f $p."DeviceId") -Name "ghcup.test" -ItemType "directory" -Force
$defaultGhcupBasePrefix = ('{0}\' -f $p."DeviceId")
Remove-Item -LiteralPath ('{0}\ghcup.test' -f $p."DeviceId")
break
} catch {
Print-Msg -color Yellow -msg ("{0} not writable or not enough disk space, trying next device" -f $p."DeviceId")
}
}
if ($defaultGhcupBasePrefix) {
Print-Msg -color Green -msg ("Picked {0} as default Install prefix!" -f $defaultGhcupBasePrefix)
} else {
Print-Msg -color Red -msg "Couldn't find a writable partition with at least 5GB free disk space!"
Exit 1
}
} }
if ($Silent -and !($InstallDir)) { if ($Silent -and !($InstallDir)) {
@@ -194,7 +227,9 @@ $null = [Environment]::SetEnvironmentVariable("GHCUP_INSTALL_BASE_PREFIX", $Ghcu
$GhcupDir = ('{0}\ghcup' -f $GhcupBasePrefix) $GhcupDir = ('{0}\ghcup' -f $GhcupBasePrefix)
$MsysDir = ('{0}\msys64' -f $GhcupDir) $MsysDir = ('{0}\msys64' -f $GhcupDir)
$Bash = ('{0}\usr\bin\bash' -f $MsysDir) $Bash = ('{0}\usr\bin\bash' -f $MsysDir)
$BootstrapUrl = 'https://www.haskell.org/ghcup/sh/bootstrap-haskell' if (!($BootstrapUrl)) {
$BootstrapUrl = 'https://www.haskell.org/ghcup/sh/bootstrap-haskell'
}
$GhcupMsys2 = [System.Environment]::GetEnvironmentVariable('GHCUP_MSYS2', 'user') $GhcupMsys2 = [System.Environment]::GetEnvironmentVariable('GHCUP_MSYS2', 'user')
Print-Msg -msg 'Preparing for GHCup installation...' Print-Msg -msg 'Preparing for GHCup installation...'
@@ -268,20 +303,8 @@ if (!(Test-Path -Path ('{0}' -f $MsysDir))) {
Print-Msg -msg 'Upgrading full system twice...' Print-Msg -msg 'Upgrading full system twice...'
Exec "$Bash" '-lc' 'pacman --noconfirm -Syuu' Exec "$Bash" '-lc' 'pacman --noconfirm -Syuu'
if ($Quick) { Print-Msg -msg 'Installing Dependencies...'
$ghcBuildDeps = $Quick Exec "$Bash" '-lc' 'pacman --noconfirm -S --needed curl mingw-w64-x86_64-pkgconf'
} elseif (!($Silent)) {
$ghcBuildDeps = $Host.UI.PromptForChoice('Install Dependencies'
, 'Install a standard set of mingw64 packages to be able to build various haskell packages requiring unix libraries? (recommended, however this might take a while... if you skip this, you might have to do it manually later)'
, [System.Management.Automation.Host.ChoiceDescription[]] @('&Yes'
'&No'), 0)
} else {
$ghcBuildDeps = 0
}
if ($ghcBuildDeps -eq 0) {
Print-Msg -msg 'Installing Dependencies...'
Exec "$Bash" '-lc' 'pacman --noconfirm -S --needed git tar curl wget base-devel gettext binutils autoconf make libtool automake pkgconf python p7zip patch unzip'
}
Print-Msg -msg 'Updating SSL root certificate authorities...' Print-Msg -msg 'Updating SSL root certificate authorities...'
Exec "$Bash" '-lc' 'pacman --noconfirm -S ca-certificates' Exec "$Bash" '-lc' 'pacman --noconfirm -S ca-certificates'
@@ -319,8 +342,11 @@ if (!(Test-Path -Path ('{0}' -f $MsysDir))) {
} }
Print-Msg -msg 'Creating shortcuts...' Print-Msg -msg 'Creating shortcuts...'
Create-Shortcut -SourceExe ('{0}\msys2_shell.cmd' -f $MsysDir) -ArgumentsToSourceExe '-mingw64' -DestinationPath ('{0}\Desktop\Mingw haskell shell.lnk' -f $HOME) $DesktopDir = [Environment]::GetFolderPath("Desktop")
Create-Shortcut -SourceExe 'https://www.msys2.org/docs/package-management' -ArgumentsToSourceExe '' -DestinationPath ('{0}\Desktop\Mingw package management docs.url' -f $HOME) $GhcInstArgs = '-mingw64 -mintty -c "pacman --noconfirm -S --needed base-devel gettext autoconf make libtool automake python p7zip patch unzip"'
Create-Shortcut -SourceExe ('{0}\msys2_shell.cmd' -f $MsysDir) -ArgumentsToSourceExe $GhcInstArgs -DestinationPath ('{0}\Install GHC dev dependencies.lnk' -f $DesktopDir)
Create-Shortcut -SourceExe ('{0}\msys2_shell.cmd' -f $MsysDir) -ArgumentsToSourceExe '-mingw64' -DestinationPath ('{0}\Mingw haskell shell.lnk' -f $DesktopDir)
Create-Shortcut -SourceExe 'https://www.msys2.org/docs/package-management' -ArgumentsToSourceExe '' -DestinationPath ('{0}\Mingw package management docs.url' -f $DesktopDir)
Print-Msg -msg ('Adding {0}\bin to Users Path...' -f $GhcupDir) Print-Msg -msg ('Adding {0}\bin to Users Path...' -f $GhcupDir)
Add-EnvPath -Path ('{0}\bin' -f ([System.IO.Path]::GetFullPath("$GhcupDir"))) -Container 'User' Add-EnvPath -Path ('{0}\bin' -f ([System.IO.Path]::GetFullPath("$GhcupDir"))) -Container 'User'
@@ -368,10 +394,10 @@ if ($Silent) {
$SilentExport = '' $SilentExport = ''
} }
if ((Get-Process -ID $PID).ProcessName.StartsWith("bootstrap-haskell")) { if ((Get-Process -ID $PID).ProcessName.StartsWith("bootstrap-haskell") -Or $InBash) {
Exec "$Bash" '-lc' ('{4} [ -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}'' ; curl --proto ''=https'' --tlsv1.2 -sSf {0} | bash' -f $BootstrapUrl, $MsysDir, $GhcupBasePrefix, $GhcupDir, $SilentExport, $CabalDirFull) Exec "$Bash" '-lc' ('{4} [ -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)
} else { } else {
Exec "$Msys2Shell" '-mingw64' '-mintty' '-c' ('{4} [ -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 ; curl --proto =https --tlsv1.2 -sSf -k {0} | bash ; echo ''Press any key to exit'' && read -n 1' -f $BootstrapUrl, $MsysDir, $GhcupBasePrefix, $GhcupDir, $SilentExport, $CabalDirFull) Exec "$Msys2Shell" '-mingw64' '-mintty' '-c' ('{4} [ -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)
} }
@@ -399,3 +425,7 @@ if ((Get-Process -ID $PID).ProcessName.StartsWith("bootstrap-haskell")) {
# E5VhEwLBnwzWrvLKtdEclhgUCo5Tq87QMXVdgX4aRmunl4ZE+Q== # E5VhEwLBnwzWrvLKtdEclhgUCo5Tq87QMXVdgX4aRmunl4ZE+Q==
# SIG # End signature block # SIG # End signature block

View File

@@ -1,5 +1,7 @@
packages: ./ghcup.cabal packages: ./ghcup.cabal
optional-packages: ./vendored/*/*.cabal
optimization: 2 optimization: 2
package ghcup package ghcup

View File

@@ -1,8 +1,8 @@
--- ---
globalTools: globalTools:
ShimGen: ShimGen:
dlUri: https://downloads.haskell.org/~ghcup/shimgen/gs.exe dlUri: https://downloads.haskell.org/~ghcup/shimgen/shim-2.exe
dlHash: 9ce8b7dad7ff4e5017dbd63d6f6f3d16412b889560cb6ccd3903dbcab0bf4f0d dlHash: 7c55e201f71860c5babea886007c8fa44b861abf50d1c07e5677eb0bda387a70
toolRequirements: toolRequirements:
GHC: GHC:
unknown_version: unknown_version:
@@ -2060,8 +2060,8 @@ ghcupDownloads:
A_ARM64: A_ARM64:
Linux_UnknownLinux: Linux_UnknownLinux:
unknown_versioning: unknown_versioning:
dlUri: https://downloads.haskell.org/~ghcup/0.1.15.2/aarch64-linux-ghcup-0.1.15.2 dlUri: https://downloads.haskell.org/~ghcup/0.1.15.2/aarch64-linux-ghcup-0.1.15.2-r2
dlHash: d91b7a5416f292f2cf813824eb419f76ad9976d258cee3581123cb6eb01db9a7 dlHash: d67702f7c9e3586e85ed7c1bd09b7544da55bd1d3b4a961a07018348f78cf76b
Darwin: Darwin:
unknown_versioning: unknown_versioning:
dlUri: https://downloads.haskell.org/~ghcup/0.1.15.2/aarch64-apple-darwin-ghcup-0.1.15.2 dlUri: https://downloads.haskell.org/~ghcup/0.1.15.2/aarch64-apple-darwin-ghcup-0.1.15.2
@@ -2107,7 +2107,7 @@ ghcupDownloads:
Darwin: Darwin:
unknown_versioning: unknown_versioning:
dlUri: https://github.com/haskell/haskell-language-server/releases/download/1.2.0/haskell-language-server-macOS-1.2.0.tar.gz dlUri: https://github.com/haskell/haskell-language-server/releases/download/1.2.0/haskell-language-server-macOS-1.2.0.tar.gz
dlHash: 43d2ef356fb8cbd8e27acf70f94c079157258916bb1220751547584513584aaa dlHash: a310d8a3e9c5c4218210f750682c74a0f82ad0f59995adde0dbe775115b1e357
Windows: Windows:
unknown_versioning: unknown_versioning:
dlUri: https://github.com/haskell/haskell-language-server/releases/download/1.2.0/haskell-language-server-Windows-1.2.0.tar.gz dlUri: https://github.com/haskell/haskell-language-server/releases/download/1.2.0/haskell-language-server-Windows-1.2.0.tar.gz
@@ -2120,8 +2120,17 @@ ghcupDownloads:
- old - old
viChangeLog: https://github.com/commercialhaskell/stack/blob/master/ChangeLog.md#v251 viChangeLog: https://github.com/commercialhaskell/stack/blob/master/ChangeLog.md#v251
viPostInstall: &stack-post | viPostInstall: &stack-post |
Stack manages GHC versions internally by default. In order to make it use ghcup installed GHC versions have a look at the options 'system-ghc', 'compiler-check' and 'compiler': https://docs.haskellstack.org/en/stable/yaml_configuration/#system-ghc Stack manages GHC versions internally by default. In order to make it use ghcup installed
Additionally, you should upgrade stack only through ghcup. GHC versions you can run the following commands:
stack config set install-ghc false --global
stack config set system-ghc true --global
On windows, you may find the following config options useful too:
skip-msys, extra-path, extra-include-dirs, extra-lib-dirs
Also check out: https://docs.haskellstack.org/en/stable/yaml_configuration
!!! Additionally, you should upgrade stack only through ghcup and not use 'stack upgrade' !!!
viArch: viArch:
A_64: A_64:
Linux_UnknownLinux: Linux_UnknownLinux:

View File

@@ -43,9 +43,7 @@ flag internal-downloader
manual: True manual: True
flag tar flag tar
description: description: Use tar-bytestring instead of libarchive.
Use tar-bytestring instead of libarchive.
default: False default: False
manual: True manual: True
@@ -142,7 +140,7 @@ library
, uri-bytestring ^>=0.3.2.2 , uri-bytestring ^>=0.3.2.2
, utf8-string ^>=1.0 , utf8-string ^>=1.0
, vector ^>=0.12 , vector ^>=0.12
, versions ^>=4.0.1 , versions >=4.0.1 && <5.1
, word8 ^>=0.1.3 , word8 ^>=0.1.3
, yaml ^>=0.11.4.0 , yaml ^>=0.11.4.0
, zip ^>=1.7.1 , zip ^>=1.7.1
@@ -226,7 +224,7 @@ executable ghcup
, text ^>=1.2.4.0 , text ^>=1.2.4.0
, uri-bytestring ^>=0.3.2.2 , uri-bytestring ^>=0.3.2.2
, utf8-string ^>=1.0 , utf8-string ^>=1.0
, versions ^>=4.0.1 , versions >=4.0.1 && <5.1
if flag(internal-downloader) if flag(internal-downloader)
cpp-options: -DINTERNAL_DOWNLOADER cpp-options: -DINTERNAL_DOWNLOADER
@@ -294,7 +292,7 @@ executable ghcup-gen
, text ^>=1.2.4.0 , text ^>=1.2.4.0
, transformers ^>=0.5 , transformers ^>=0.5
, uri-bytestring ^>=0.3.2.2 , uri-bytestring ^>=0.3.2.2
, versions ^>=4.0.1 , versions >=4.0.1 && <5.1
, yaml ^>=0.11.4.0 , yaml ^>=0.11.4.0
if flag(tar) if flag(tar)
@@ -338,4 +336,4 @@ test-suite ghcup-test
, quickcheck-arbitrary-adt ^>=0.3.1.0 , quickcheck-arbitrary-adt ^>=0.3.1.0
, text ^>=1.2.4.0 , text ^>=1.2.4.0
, uri-bytestring ^>=0.3.2.2 , uri-bytestring ^>=0.3.2.2
, versions ^>=4.0.1 , versions >=4.0.1 && <5.1

View File

@@ -42,6 +42,7 @@ import GHCup.Version
import Codec.Archive ( ArchiveResult ) import Codec.Archive ( ArchiveResult )
#endif #endif
import Control.Applicative import Control.Applicative
import Control.Exception ( evaluate )
import Control.Exception.Safe import Control.Exception.Safe
import Control.Monad import Control.Monad
#if !MIN_VERSION_base(4,13,0) #if !MIN_VERSION_base(4,13,0)
@@ -1295,7 +1296,7 @@ rmGhcup = do
let ghcupFilename = "ghcup" <> exeExt let ghcupFilename = "ghcup" <> exeExt
let ghcupFilepath = binDir </> ghcupFilename let ghcupFilepath = binDir </> ghcupFilename
currentRunningExecPath <- liftIO $ getExecutablePath currentRunningExecPath <- liftIO getExecutablePath
-- if paths do no exist, warn user, and continue to compare them, as is, -- if paths do no exist, warn user, and continue to compare them, as is,
-- which should eventually fail and result in a non-standard install warning -- which should eventually fail and result in a non-standard install warning
@@ -1305,29 +1306,25 @@ rmGhcup = do
(liftIO $ canonicalizePath currentRunningExecPath) (liftIO $ canonicalizePath currentRunningExecPath)
p2 <- handleIO' doesNotExistErrorType p2 <- handleIO' doesNotExistErrorType
(handlePathNotPresent ghcupFilename) (handlePathNotPresent ghcupFilepath)
(liftIO $ canonicalizePath ghcupFilename) (liftIO $ canonicalizePath ghcupFilepath)
let areEqualPaths = equalFilePath p1 p2 let areEqualPaths = equalFilePath p1 p2
if areEqualPaths unless areEqualPaths $ $logWarn $ nonStandardInstallLocationMsg currentRunningExecPath
then
do
#if defined(IS_WINDOWS) #if defined(IS_WINDOWS)
-- since it doesn't seem possible to delete a running exec in windows -- since it doesn't seem possible to delete a running exec in windows
-- we move it to temp dir, to be deleted at next reboot -- we move it to temp dir, to be deleted at next reboot
tempDir <- liftIO $ getTemporaryDirectory tempDir <- liftIO $ getTemporaryDirectory
let tempFilepath = tempDir </> ghcupFilename let tempFilepath = tempDir </> ghcupFilename
hideError UnsupportedOperation $ hideError UnsupportedOperation $
liftIO $ hideError NoSuchThing $ liftIO $ hideError NoSuchThing $
Win32.moveFileEx ghcupFilepath (Just tempFilepath) 1 Win32.moveFileEx ghcupFilepath (Just tempFilepath) Win32.mOVEFILE_REPLACE_EXISTING
#else #else
-- delete it. -- delete it.
hideError doesNotExistErrorType $ liftIO $ rmFile ghcupFilepath hideError doesNotExistErrorType $ liftIO $ rmFile ghcupFilepath
#endif #endif
else
$logWarn $
nonStandardInstallLocationMsg currentRunningExecPath
where where
handlePathNotPresent fp _err = do handlePathNotPresent fp _err = do
@@ -1348,86 +1345,73 @@ rmTool :: ( MonadReader AppState m
-> Excepts '[NotInstalled ] m () -> Excepts '[NotInstalled ] m ()
rmTool ListResult {lVer, lTool, lCross} = do rmTool ListResult {lVer, lTool, lCross} = do
-- appstate <- ask
case lTool of case lTool of
GHC -> do GHC ->
let ghcTargetVersion = GHCTargetVersion lCross lVer let ghcTargetVersion = GHCTargetVersion lCross lVer
rmGHCVer ghcTargetVersion in rmGHCVer ghcTargetVersion
HLS -> rmHLSVer lVer
Cabal -> rmCabalVer lVer
Stack -> rmStackVer lVer
GHCup -> lift rmGhcup
HLS -> do
rmHLSVer lVer
Cabal -> do
rmCabalVer lVer
Stack -> do
rmStackVer lVer
GHCup -> do
lift rmGhcup
rmGhcupDirs :: ( MonadReader AppState m rmGhcupDirs :: ( MonadReader AppState m
, MonadIO m , MonadIO m
, MonadLogger m , MonadLogger m
, MonadCatch m , MonadCatch m
, MonadMask m ) , MonadMask m )
=> m [FilePath] => m [FilePath]
rmGhcupDirs = do rmGhcupDirs = do
dirs@Dirs Dirs
{ baseDir { baseDir
, binDir , binDir
, logsDir , logsDir
, cacheDir , cacheDir
, confDir } <- asks dirs } <- asks dirs
let envFilePath = baseDir </> "env" let envFilePath = baseDir </> "env"
confFilePath <- getConfigFilePath confFilePath <- getConfigFilePath
-- remove env File rmEnvFile envFilePath
rmEnvFile envFilePath
-- remove the configFile file
rmConfFile confFilePath rmConfFile confFilePath
rmDir cacheDir
rmDir logsDir
rmBinDir binDir
#if defined(IS_WINDOWS)
rmDir (baseDir </> "msys64")
#endif
-- remove entire cache Dir liftIO $ removeEmptyDirsRecursive baseDir
rmCacheDir cacheDir
-- remove entire logs Dir -- report files in baseDir that are left-over after
rmLogsDir logsDir -- the standard location deletions above
hideErrorDef [doesNotExistErrorType] [] $ reportRemainingFiles baseDir
-- remove bin directory conditionally
rmBinDir binDir
-- report files in baseDir that are left-over after the standard location deletions above
reportRemainingFiles baseDir
where where
rmEnvFile :: (MonadCatch m, MonadLogger m, MonadIO m) => FilePath -> m ()
rmEnvFile enFilePath = do rmEnvFile enFilePath = do
$logInfo "Removing Ghcup Environment File" $logInfo "Removing Ghcup Environment File"
hideError doesNotExistErrorType $ liftIO $ deleteFile enFilePath hideError doesNotExistErrorType $ liftIO $ deleteFile enFilePath
rmConfFile :: (MonadCatch m, MonadLogger m, MonadIO m) => FilePath -> m ()
rmConfFile confFilePath = do rmConfFile confFilePath = do
$logInfo "removing Ghcup Config File" $logInfo "removing Ghcup Config File"
hideError doesNotExistErrorType $ liftIO $ deleteFile confFilePath hideError doesNotExistErrorType $ liftIO $ deleteFile confFilePath
rmCacheDir cacheDir = do rmDir :: (MonadLogger m, MonadIO m, MonadCatch m) => FilePath -> m ()
$logInfo "removing ghcup cache Dir" rmDir dir = do
contents <- liftIO $ listDirectory cacheDir $logInfo [i|removing #{dir}|]
forM_ contents deleteFile contents <- hideErrorDef [doesNotExistErrorType] []
removeDirIfEmptyOrIsSymlink cacheDir $ liftIO
(getDirectoryContentsRecursive dir >>= evaluate)
rmLogsDir logsDir = do forM_ contents (liftIO . deleteFile . (dir </>))
$logInfo "removing ghcup logs Dir"
contents <- liftIO $ listDirectory logsDir
forM_ contents deleteFile
removeDirIfEmptyOrIsSymlink logsDir
rmBinDir :: (MonadCatch m, MonadIO m) => FilePath -> m ()
rmBinDir binDir = do rmBinDir binDir = do
#if !defined(IS_WINDOWS) #if !defined(IS_WINDOWS)
isXDGStyle <- liftIO $ useXDG isXDGStyle <- liftIO useXDG
if not isXDGStyle if not isXDGStyle
then removeDirIfEmptyOrIsSymlink binDir then removeDirIfEmptyOrIsSymlink binDir
else pure () else pure ()
@@ -1435,11 +1419,12 @@ rmGhcupDirs = do
removeDirIfEmptyOrIsSymlink binDir removeDirIfEmptyOrIsSymlink binDir
#endif #endif
reportRemainingFiles ghcupDir = do reportRemainingFiles :: MonadIO m => FilePath -> m [FilePath]
remainingFiles <- liftIO $ getDirectoryContentsRecursive ghcupDir reportRemainingFiles dir = do
remainingFiles <- liftIO $ getDirectoryContentsRecursive dir
let normalizedFilePaths = fmap normalise remainingFiles let normalizedFilePaths = fmap normalise remainingFiles
let sortedByDepthRemainingFiles = reverse $ sortBy compareFn normalizedFilePaths let sortedByDepthRemainingFiles = sortBy (flip compareFn) normalizedFilePaths
remainingFilesAbsolute <- makePathsAbsolute sortedByDepthRemainingFiles let remainingFilesAbsolute = fmap (dir </>) sortedByDepthRemainingFiles
pure remainingFilesAbsolute pure remainingFilesAbsolute
@@ -1450,17 +1435,22 @@ rmGhcupDirs = do
compareFn :: FilePath -> FilePath -> Ordering compareFn :: FilePath -> FilePath -> Ordering
compareFn fp1 fp2 = compare (calcDepth fp1) (calcDepth fp2) compareFn fp1 fp2 = compare (calcDepth fp1) (calcDepth fp2)
makePathsAbsolute :: (MonadIO m) => [FilePath] -> m [FilePath] removeEmptyDirsRecursive :: FilePath -> IO ()
makePathsAbsolute paths = liftIO $ removeEmptyDirsRecursive fp = do
traverse (makeAbsolute . normalise) paths cs <- listDirectory fp >>= filterM doesDirectoryExist . fmap (fp </>)
forM_ cs removeEmptyDirsRecursive
hideError InappropriateType $ removeDirIfEmptyOrIsSymlink fp
-- we expect only files inside cache/log dir -- we expect only files inside cache/log dir
-- we report remaining files/dirs later, -- we report remaining files/dirs later,
-- hence the force/quiet mode in these delete functions below. -- hence the force/quiet mode in these delete functions below.
deleteFile :: FilePath -> IO ()
deleteFile filepath = do deleteFile filepath = do
hideError InappropriateType $ rmFile filepath hideError InappropriateType $ rmFile filepath
removeDirIfEmptyOrIsSymlink :: (MonadCatch m, MonadIO m) => FilePath -> m ()
removeDirIfEmptyOrIsSymlink filepath = removeDirIfEmptyOrIsSymlink filepath =
hideError UnsatisfiedConstraints $ hideError UnsatisfiedConstraints $
handleIO' InappropriateType handleIO' InappropriateType
@@ -1473,6 +1463,8 @@ rmGhcupDirs = do
then liftIO $ deleteFile fp then liftIO $ deleteFile fp
else liftIO $ ioError e else liftIO $ ioError e
------------------ ------------------
--[ Debug info ]-- --[ Debug info ]--
------------------ ------------------
@@ -1813,14 +1805,14 @@ upgradeGHCup :: ( MonadMask m
] ]
m m
Version Version
upgradeGHCup mtarget force = do upgradeGHCup mtarget force' = do
AppState { dirs = Dirs {..} AppState { dirs = Dirs {..}
, pfreq , pfreq
, ghcupInfo = GHCupInfo { _ghcupDownloads = dls } , ghcupInfo = GHCupInfo { _ghcupDownloads = dls }
, settings } <- lift ask , settings } <- lift ask
lift $ $(logInfo) [i|Upgrading GHCup...|] lift $ $(logInfo) [i|Upgrading GHCup...|]
let latestVer = fromJust $ fst <$> getLatest dls GHCup let latestVer = fromJust $ fst <$> getLatest dls GHCup
when (not force && (latestVer <= pvpToVersion ghcUpVer)) $ throwE NoUpdate when (not force' && (latestVer <= pvpToVersion ghcUpVer)) $ throwE NoUpdate
dli <- lE $ getDownloadInfo GHCup latestVer pfreq dls dli <- lE $ getDownloadInfo GHCup latestVer pfreq dls
tmp <- lift withGHCupTmpDir tmp <- lift withGHCupTmpDir
let fn = "ghcup" <> exeExt let fn = "ghcup" <> exeExt

View File

@@ -20,6 +20,7 @@ import GHCup.Utils.String.QQ
import Control.Monad import Control.Monad
import Control.Monad.IO.Class import Control.Monad.IO.Class
import Control.Monad.Logger import Control.Monad.Logger
import Data.Char ( ord )
import Prelude hiding ( appendFile ) import Prelude hiding ( appendFile )
import System.Console.Pretty import System.Console.Pretty
import System.FilePath import System.FilePath
@@ -43,20 +44,33 @@ myLoggerT LoggerConfig {..} loggingt = runLoggingT loggingt mylogger
mylogger :: Loc -> LogSource -> LogLevel -> LogStr -> IO () mylogger :: Loc -> LogSource -> LogLevel -> LogStr -> IO ()
mylogger _ _ level str' = do mylogger _ _ level str' = do
-- color output -- color output
let style' = case level of
LevelDebug -> style Bold . color Blue
LevelInfo -> style Bold . color Green
LevelWarn -> style Bold . color Yellow
LevelError -> style Bold . color Red
LevelOther _ -> id
let l = case level of let l = case level of
LevelDebug -> toLogStr (style Bold $ color Blue "[ Debug ]") LevelDebug -> toLogStr (style' "[ Debug ]")
LevelInfo -> toLogStr (style Bold $ color Green "[ Info ]") LevelInfo -> toLogStr (style' "[ Info ]")
LevelWarn -> toLogStr (style Bold $ color Yellow "[ Warn ]") LevelWarn -> toLogStr (style' "[ Warn ]")
LevelError -> toLogStr (style Bold $ color Red "[ Error ]") LevelError -> toLogStr (style' "[ Error ]")
LevelOther t -> toLogStr "[ " <> toLogStr t <> toLogStr " ]" LevelOther t -> toLogStr "[ " <> toLogStr t <> toLogStr " ]"
let out = fromLogStr (l <> toLogStr " " <> str' <> toLogStr "\n") let strs = fmap toLogStr . B.split (fromIntegral $ ord '\n') . fromLogStr $ str'
let out = case strs of
[] -> B.empty
(x:xs) -> fromLogStr
. foldr (\a b -> a <> toLogStr "\n" <> b) mempty
. ((l <> toLogStr " " <> x) :)
. fmap (\line' -> toLogStr (style' "[ ... ] ") <> line' )
$ xs
when (lcPrintDebug || (not lcPrintDebug && (level /= LevelDebug))) when (lcPrintDebug || (not lcPrintDebug && (level /= LevelDebug)))
$ colorOutter out $ colorOutter out
-- raw output -- raw output
let lr = case level of let lr = case level of
LevelDebug -> toLogStr "Debug: " LevelDebug -> toLogStr "Debug:"
LevelInfo -> toLogStr "Info:" LevelInfo -> toLogStr "Info:"
LevelWarn -> toLogStr "Warn:" LevelWarn -> toLogStr "Warn:"
LevelError -> toLogStr "Error:" LevelError -> toLogStr "Error:"

View File

@@ -190,14 +190,14 @@ hideError :: (MonadIO m, MonadCatch m) => IOErrorType -> m () -> m ()
hideError err = handleIO (\e -> if err == ioeGetErrorType e then pure () else liftIO . ioError $ e) hideError err = handleIO (\e -> if err == ioeGetErrorType e then pure () else liftIO . ioError $ e)
hideErrorDef :: [IOErrorType] -> a -> IO a -> IO a hideErrorDef :: (MonadIO m, MonadCatch m) => [IOErrorType] -> a -> m a -> m a
hideErrorDef errs def = hideErrorDef errs def =
handleIO (\e -> if ioeGetErrorType e `elem` errs then pure def else ioError e) handleIO (\e -> if ioeGetErrorType e `elem` errs then pure def else liftIO $ ioError e)
hideErrorDefM :: [IOErrorType] -> IO a -> IO a -> IO a hideErrorDefM :: (MonadIO m, MonadCatch m) => [IOErrorType] -> m a -> m a -> m a
hideErrorDefM errs def = hideErrorDefM errs def =
handleIO (\e -> if ioeGetErrorType e `elem` errs then def else ioError e) handleIO (\e -> if ioeGetErrorType e `elem` errs then def else liftIO $ ioError e)
-- TODO: does this work? -- TODO: does this work?
@@ -334,12 +334,13 @@ copyDirectoryRecursive srcDir destDir = do
in doCopy src dest in doCopy src dest
| (srcBase, srcFile) <- srcFiles ] | (srcBase, srcFile) <- srcFiles ]
-- | List all the files in a directory and all subdirectories.
-- -- | List all the files in a directory and all subdirectories.
-- The order places files in sub-directories after all the files in their --
-- parent directories. The list is generated lazily so is not well defined if -- The order places files in sub-directories after all the files in their
-- the source directory structure changes before the list is used. -- parent directories. The list is generated lazily so is not well defined if
-- -- the source directory structure changes before the list is used.
--
getDirectoryContentsRecursive :: FilePath -> IO [FilePath] getDirectoryContentsRecursive :: FilePath -> IO [FilePath]
getDirectoryContentsRecursive topdir = recurseDirectories [""] getDirectoryContentsRecursive topdir = recurseDirectories [""]
where where

View File

@@ -132,13 +132,17 @@ hr {
margin-bottom: 2em; margin-bottom: 2em;
} }
#platform-instructions-linux > div > pre, span.code {
#platform-instructions-mac > div > pre, font-family: 'Lucida Console', monospace;
#platform-instructions-freebsd > div > pre, }
#platform-instructions-win32 > div > pre,
#platform-instructions-win64 > div > pre, #platform-instructions-linux div > pre,
#platform-instructions-default > div > div > pre, #platform-instructions-mac div > pre,
#platform-instructions-unknown > div > div > pre { #platform-instructions-freebsd div > pre,
#platform-instructions-win32 div > pre,
#platform-instructions-win64 div > pre,
#platform-instructions-default div > div > pre,
#platform-instructions-unknown div > div > pre {
background-color: #515151; background-color: #515151;
color: white; color: white;
margin-left: auto; margin-left: auto;

View File

@@ -44,23 +44,40 @@
<div id="platform-instructions-win32" class="instructions"> <div id="platform-instructions-win32" class="instructions">
<p> <p>
To install Haskell,<br/>run the following in a powershell session (as a non-admin user). To install Haskell,<br/>run the following in a powershell session (as a non-admin user).
<div class="command-button"><pre><span class='ghcup-command' id="ghcup-command-powershell">Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; Invoke-WebRequest -UseBasicParsing https://www.haskell.org/ghcup/sh/bootstrap-haskell.ps1 | Invoke-Expression</span></span></pre><button class="tooltip" onclick="copyToClipboardPowershell()"><img src="copy.svg" alt="" /><span class="tooltiptext">Copy to clipboard</span></button></div> <div>
<div class="command-button"><pre><span class='ghcup-command' id="ghcup-command-powershell">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</span></span></pre><button class="tooltip" onclick="copyToClipboardPowershell()"><img src="copy.svg" alt="" /><span class="tooltiptext">Copy to clipboard</span></button>
</div>
<p class="other-help">If you want to run an interactive installation, change <span class='code'>$false</span> to <span class='code'>$true</span> at the end of the script.</p>
</div>
<p>If you're a Windows Subsystem 2 for Linux user run the following in your terminal, then follow the onscreen instructions to install Haskell. <p>If you're a Windows Subsystem 2 for Linux user run the following in your terminal, then follow the onscreen instructions to install Haskell.
</p> </p>
<div class="command-button"><pre><span class='ghcup-command'>curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh</span></pre><button class="tooltip" onclick="copyToClipboard()"><img src="copy.svg" alt="" /><span class="tooltiptext">Copy to clipboard</span></button></div> <div>
<div class="command-button"><pre><span class='ghcup-command'>curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh</span></pre><button class="tooltip" onclick="copyToClipboard()"><img src="copy.svg" alt="" /><span class="tooltiptext">Copy to clipboard</span></button>
</div>
<p class="other-help">WSL1 does not work with ghcup, follow <a href="https://docs.microsoft.com/en-us/windows/wsl/install-win10">the instructions here</a> to upgrade to WSL2 if needed.</p>
</div>
</p> </p>
<p class="other-help">WSL1 does not work with ghcup, follow <a href="https://docs.microsoft.com/en-us/windows/wsl/install-win10">the instructions here</a> to upgrade to WSL2 if needed.</br>You appear to be running Windows 32-bit. If not, <a class="default-platform-button" href="#">display all supported installers</a>.</p> <hr/>
<p class="other-help">You appear to be running Windows 32-bit. If not, <a class="default-platform-button" href="#">display all supported installers</a>.</p>
</div> </div>
<div id="platform-instructions-win64" class="instructions" style="display: none;"> <div id="platform-instructions-win64" class="instructions" style="display: none;">
<p> <p>
To install Haskell,<br/>run the following in a powershell session (as a non-admin user). To install Haskell,<br/>run the following in a powershell session (as a non-admin user).
<div class="command-button"><pre><span class='ghcup-command'>Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; Invoke-WebRequest -UseBasicParsing https://www.haskell.org/ghcup/sh/bootstrap-haskell.ps1 | Invoke-Expression</span></span></pre><button class="tooltip" onclick="copyToClipboardPowershell()"><img src="copy.svg" alt="" /><span class="tooltiptext">Copy to clipboard</span></button></div> <div>
<div class="command-button"><pre><span class='ghcup-command'>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</span></span></pre><button class="tooltip" onclick="copyToClipboardPowershell()"><img src="copy.svg" alt="" /><span class="tooltiptext">Copy to clipboard</span></button>
</div>
<p class="other-help">If you want to run an interactive installation, change <span class='code'>$false</span> to <span class='code'>$true</span> at the end of the script.</p>
</div>
</p> </p>
<p>If you're a Windows Subsystem 2 for Linux user run the following in your terminal, then follow the onscreen instructions to install Haskell. <p>If you're a Windows Subsystem 2 for Linux user run the following in your terminal, then follow the onscreen instructions to install Haskell.
</p> </p>
<div class="command-button"><pre><span class='ghcup-command'>curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh</span></pre><button class="tooltip" onclick="copyToClipboard()"><img src="copy.svg" alt="" /><span class="tooltiptext">Copy to clipboard</span></button></div> <div>
<p class="other-help">WSL1 does not work with ghcup, follow <a href="https://docs.microsoft.com/en-us/windows/wsl/install-win10">the instructions here</a> to upgrade to WSL2 if needed.</br>You appear to be running Windows 64-bit. If not, <a class="default-platform-button" href="#">display all supported installers</a>.</p> <div class="command-button"><pre><span class='ghcup-command'>curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh</span></pre><button class="tooltip" onclick="copyToClipboard()"><img src="copy.svg" alt="" /><span class="tooltiptext">Copy to clipboard</span></button>
</div>
<p class="other-help">WSL1 does not work with ghcup, follow <a href="https://docs.microsoft.com/en-us/windows/wsl/install-win10">the instructions here</a> to upgrade to WSL2 if needed.</p>
</div>
<p class="other-help">You appear to be running Windows 64-bit. If not, <a class="default-platform-button" href="#">display all supported installers</a>.</p>
</div> </div>
<div id="platform-instructions-unknown" class="instructions" style="display: none;"> <div id="platform-instructions-unknown" class="instructions" style="display: none;">
@@ -92,7 +109,7 @@
<div> <div>
<p> <p>
If you are running Windows,<br/>run the following in a powershell session (as a non-admin user). If you are running Windows,<br/>run the following in a powershell session (as a non-admin user).
<div class="command-button"><pre><span class='ghcup-command'>Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; Invoke-WebRequest -UseBasicParsing https://www.haskell.org/ghcup/sh/bootstrap-haskell.ps1 | Invoke-Expression</span></span></pre><button class="tooltip" onclick="copyToClipboardPowershell()"><img src="copy.svg" alt="" /><span class="tooltiptext">Copy to clipboard</span></button></div> <div class="command-button"><pre><span class='ghcup-command'>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</span></span></pre><button class="tooltip" onclick="copyToClipboardPowershell()"><img src="copy.svg" alt="" /><span class="tooltiptext">Copy to clipboard</span></button></div>
</p> </p>
</div> </div>
@@ -111,7 +128,7 @@
<div> <div>
<p> <p>
If you are running Windows,<br/>run the following in a powershell session (as a non-admin user). If you are running Windows,<br/>run the following in a powershell session (as a non-admin user).
<div class="command-button"><pre><span class='ghcup-command'>Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; Invoke-WebRequest -UseBasicParsing https://www.haskell.org/ghcup/sh/bootstrap-haskell.ps1 | Invoke-Expression</span></span></pre><button class="tooltip" onclick="copyToClipboardPowershell()"><img src="copy.svg" alt="" /><span class="tooltiptext">Copy to clipboard</span></button></div> <div class="command-button"><pre><span class='ghcup-command'>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</span></span></pre><button class="tooltip" onclick="copyToClipboardPowershell()"><img src="copy.svg" alt="" /><span class="tooltiptext">Copy to clipboard</span></button></div>
</p> </p>
</div> </div>