Compare commits

...

35 Commits

Author SHA1 Message Date
ec98826e6d Fix installStackBindist 2021-07-12 22:15:45 +02:00
1345ec938b Merge branch 'issue-173' 2021-07-12 17:09:46 +02:00
227f3acaa5 Implement 'whereis' subcommand, fixes #173 2021-07-12 17:09:18 +02:00
c20636f597 Fix adjust_bashrc on windows 2021-07-11 23:29:03 +02:00
c2d437150a Merge branch 'issue-118' 2021-07-11 22:22:03 +02:00
9ff1467612 Add user choice for prepend/append of PATH
Fixes #118
2021-07-11 22:08:19 +02:00
9218efd71a Update linux aarch64 and armv7 ghcup binaries, fixing #160 2021-07-11 19:35:46 +02:00
bcd244a92a Merge branch 'improve-logging' 2021-07-11 17:41:32 +02:00
7de552ed82 Merge branch 'issue-160-CI' 2021-07-11 16:12:01 +02:00
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
b862ca52a9 Update arm/aarch CI 2021-07-11 13:43:53 +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
21 changed files with 694 additions and 366 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
@@ -41,7 +41,7 @@ variables:
CABAL_DIR: "$CI_PROJECT_DIR/cabal" CABAL_DIR: "$CI_PROJECT_DIR/cabal"
.linux:armv7: .linux:armv7:
image: "arm32v7/fedora" image: "registry.gitlab.haskell.org/ghc/ci-images/armv7-linux-deb10:$DOCKER_REV"
tags: tags:
- armv7-linux - armv7-linux
variables: variables:
@@ -50,7 +50,7 @@ variables:
CABAL_DIR: "$CI_PROJECT_DIR/cabal" CABAL_DIR: "$CI_PROJECT_DIR/cabal"
.linux:aarch64: .linux:aarch64:
image: "arm64v8/fedora" image: "registry.gitlab.haskell.org/ghc/ci-images/aarch64-linux-deb10:$DOCKER_REV"
tags: tags:
- aarch64-linux - aarch64-linux
variables: variables:
@@ -124,14 +124,14 @@ variables:
- .test_ghcup_version - .test_ghcup_version
- .linux:armv7 - .linux:armv7
before_script: before_script:
- ./.gitlab/before_script/linux/install_deps_manual.sh - ./.gitlab/before_script/linux/install_deps.sh
.test_ghcup_version:aarch64: .test_ghcup_version:aarch64:
extends: extends:
- .test_ghcup_version - .test_ghcup_version
- .linux:aarch64 - .linux:aarch64
before_script: before_script:
- ./.gitlab/before_script/linux/install_deps_manual.sh - ./.gitlab/before_script/linux/install_deps.sh
.test_ghcup_version:darwin: .test_ghcup_version:darwin:
extends: extends:
@@ -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 ########
@@ -355,7 +374,7 @@ release:linux:armv7:
- .linux:armv7 - .linux:armv7
- .release_ghcup - .release_ghcup
before_script: before_script:
- ./.gitlab/before_script/linux/install_deps_manual.sh - ./.gitlab/before_script/linux/install_deps.sh
variables: variables:
ARTIFACT: "armv7-linux-ghcup" ARTIFACT: "armv7-linux-ghcup"
GHC_VERSION: "8.10.4" GHC_VERSION: "8.10.4"
@@ -368,7 +387,7 @@ release:linux:aarch64:
- .linux:aarch64 - .linux:aarch64
- .release_ghcup - .release_ghcup
before_script: before_script:
- ./.gitlab/before_script/linux/install_deps_manual.sh - ./.gitlab/before_script/linux/install_deps.sh
variables: variables:
ARTIFACT: "aarch64-linux-ghcup" ARTIFACT: "aarch64-linux-ghcup"
GHC_VERSION: "8.10.4" GHC_VERSION: "8.10.4"
@@ -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

@@ -7,13 +7,60 @@ set -eux
mkdir -p "${TMPDIR}" mkdir -p "${TMPDIR}"
sudo apt-get update -y sudo apt-get update -y
sudo apt-get install -y libnuma-dev zlib1g-dev libgmp-dev libgmp10 libssl-dev liblzma-dev libbz2-dev git wget sudo apt-get install -y libnuma-dev zlib1g-dev libgmp-dev libgmp10 libssl-dev liblzma-dev libbz2-dev git wget lsb-release software-properties-common gnupg2 apt-transport-https
curl -sSfL https://downloads.haskell.org/~ghcup/x86_64-linux-ghcup > ./ghcup-bin case "${ARCH}" in
chmod +x ghcup-bin ARM*)
case "${ARCH}" in
"ARM")
ghc_url=https://downloads.haskell.org/~ghc/${GHC_VERSION}/ghc-${GHC_VERSION}-armv7-deb10-linux.tar.xz
cabal_url=home.smart-cactus.org/~ben/cabal-install-${CABAL_VERSION}-armv7-linux-bootstrapped.tar.xz
;;
"ARM64")
ghc_url=https://downloads.haskell.org/~ghc/${GHC_VERSION}/ghc-${GHC_VERSION}-aarch64-deb10-linux.tar.xz
cabal_url=https://downloads.haskell.org/~cabal/cabal-install-${CABAL_VERSION}/cabal-install-${CABAL_VERSION}-aarch64-ubuntu-18.04.tar.xz
;;
*)
exit 1 ;;
esac
./ghcup-bin upgrade -i -f mkdir -p "${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup/bin
./ghcup-bin install ${GHC_VERSION}
./ghcup-bin set ${GHC_VERSION} curl -O "${ghc_url}"
./ghcup-bin install-cabal ${CABAL_VERSION} tar -xf ghc-*.tar.*
cd ghc-${GHC_VERSION}
./configure --prefix="${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup/ghc/${GHC_VERSION}
make install
for i in "${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup/ghc/${GHC_VERSION}/bin/*-${GHC_VERSION} ; do
ln -s "${i}" "${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup/bin/${i##*/}
done
for x in "${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup/bin/*-${GHC_VERSION} ; do
ln -s ${x##*/} ${x%-${GHC_VERSION}}
done
cd ..
rm -rf ghc-${GHC_VERSION} ghc-*.tar.*
unset x i
mkdir cabal-install
cd cabal-install
curl -O "${cabal_url}"
tar -xf cabal-install-*
mv cabal "${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup/bin/cabal
cd ..
rm -rf cabal-install
;;
*)
url=https://downloads.haskell.org/~ghcup/x86_64-linux-ghcup
curl -sSfL "${url}" > ./ghcup-bin
chmod +x ghcup-bin
./ghcup-bin upgrade -i -f
./ghcup-bin install ${GHC_VERSION}
./ghcup-bin set ${GHC_VERSION}
./ghcup-bin install-cabal ${CABAL_VERSION}
;;
esac

View File

@@ -1,64 +0,0 @@
#!/bin/sh
set -eux
. "$( cd "$(dirname "$0")" ; pwd -P )/../../ghcup_env"
mkdir -p "${TMPDIR}"
ednf() {
case "${ARCH}" in
"ARM")
sudo dnf -y --forcearch armv7hl "$@"
;;
"ARM64")
sudo dnf -y --forcearch aarch64 "$@"
;;
*) exit 1 ;;
esac
}
ednf update
ednf install gcc gcc-c++ gmp gmp-devel make ncurses ncurses-devel xz xz-devel perl zlib zlib-devel openssl-devel openssl-libs openssl libffi libffi-devel lbzip2 lbzip2-utils bzip2-devel
if [ "${ARCH}" = "ARM64" ] ; then
ednf install numactl numactl-libs numactl-devel
fi
ednf install bash wget curl git tar
ednf install llvm9.0 llvm9.0-devel llvm9.0-libs llvm9.0-static
case "${ARCH}" in
"ARM")
ghc_url=https://downloads.haskell.org/~ghc/${GHC_VERSION}/ghc-${GHC_VERSION}-armv7-deb10-linux.tar.xz
cabal_url=home.smart-cactus.org/~ben/cabal-install-${CABAL_VERSION}-armv7-linux-bootstrapped.tar.xz
;;
"ARM64")
ghc_url=https://downloads.haskell.org/~ghc/${GHC_VERSION}/ghc-${GHC_VERSION}-aarch64-deb10-linux.tar.xz
cabal_url=https://downloads.haskell.org/~cabal/cabal-install-${CABAL_VERSION}/cabal-install-${CABAL_VERSION}-aarch64-ubuntu-18.04.tar.xz
;;
*) exit 1 ;;
esac
mkdir -p "${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup/bin
curl -O "${ghc_url}"
tar -xf ghc-*.tar.*
cd ghc-${GHC_VERSION}
./configure --prefix="${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup/ghc/${GHC_VERSION}
make install
for i in "${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup/ghc/${GHC_VERSION}/bin/*-${GHC_VERSION} ; do
ln -s "${i}" "${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup/bin/${i##*/}
done
for x in "${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup/bin/*-${GHC_VERSION} ; do
ln -s ${x##*/} ${x%-${GHC_VERSION}}
done
cd ..
rm -rf ghc-${GHC_VERSION} ghc-*.tar.*
unset x i
mkdir cabal-install
cd cabal-install
curl -O "${cabal_url}"
tar -xf cabal-install-*
mv cabal "${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup/bin/cabal
cd ..
rm -rf cabal-install

View File

@@ -4,6 +4,6 @@ if [ "${OS}" = "WINDOWS" ] ; then
export TMPDIR="$CI_PROJECT_DIR/tmp" export TMPDIR="$CI_PROJECT_DIR/tmp"
else else
export GHCUP_INSTALL_BASE_PREFIX="$CI_PROJECT_DIR" export GHCUP_INSTALL_BASE_PREFIX="$CI_PROJECT_DIR"
export PATH="$CI_PROJECT_DIR/.ghcup/bin:$CI_PROJECT_DIR/.local/bin:$PATH" export PATH="$CI_PROJECT_DIR/.ghcup/bin:$CI_PROJECT_DIR/.local/bin:/opt/llvm/bin:$PATH"
export TMPDIR="$CI_PROJECT_DIR/tmp" export TMPDIR="$CI_PROJECT_DIR/tmp"
fi fi

View File

@@ -84,8 +84,10 @@ ghcup-gen check -f ghcup-${JSON_VERSION}.yaml
eghcup --numeric-version eghcup --numeric-version
eghcup install ${GHC_VERSION} eghcup install ${GHC_VERSION}
[ `$(eghcup whereis ghc ${GHC_VERSION}) --numeric-version` = "${GHC_VERSION}" ]
eghcup set ${GHC_VERSION} eghcup set ${GHC_VERSION}
eghcup install-cabal ${CABAL_VERSION} eghcup install-cabal ${CABAL_VERSION}
[ `$(eghcup whereis cabal ${CABAL_VERSION}) --numeric-version` = "${CABAL_VERSION}" ]
cabal --version cabal --version
@@ -104,35 +106,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 $(eghcup whereis hls) --version
eghcup install stack eghcup install stack
stack --version $(eghcup whereis 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 +156,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

@@ -100,6 +100,7 @@ data Command
| Rm (Either RmCommand RmOptions) | Rm (Either RmCommand RmOptions)
| DInfo | DInfo
| Compile CompileCommand | Compile CompileCommand
| Whereis WhereisOptions WhereisCommand
| Upgrade UpgradeOpts Bool | Upgrade UpgradeOpts Bool
| ToolRequirements | ToolRequirements
| ChangeLog ChangeLogOptions | ChangeLog ChangeLogOptions
@@ -190,6 +191,13 @@ data ChangeLogOptions = ChangeLogOptions
} }
data WhereisCommand = WhereisTool Tool (Maybe ToolVersion)
data WhereisOptions = WhereisOptions {
directory :: Bool
}
-- https://github.com/pcapriotti/optparse-applicative/issues/148 -- https://github.com/pcapriotti/optparse-applicative/issues/148
-- | A switch that can be enabled using --foo and disabled using --no-foo. -- | A switch that can be enabled using --foo and disabled using --no-foo.
@@ -335,6 +343,17 @@ com =
<$> info (compileP <**> helper) <$> info (compileP <**> helper)
(progDesc "Compile a tool from source") (progDesc "Compile a tool from source")
) )
<> command
"whereis"
(info
( (Whereis
<$> (WhereisOptions <$> switch (short 'd' <> long "directory" <> help "return directory of the binary instead of the binary location"))
<*> whereisP
) <**> helper
)
(progDesc "Find a tools location"
<> footerDoc ( Just $ text whereisFooter ))
)
<> commandGroup "Main commands:" <> commandGroup "Main commands:"
) )
<|> subparser <|> subparser
@@ -402,6 +421,23 @@ com =
By default returns the URI of the ChangeLog of the latest GHC release. By default returns the URI of the ChangeLog of the latest GHC release.
Pass '-o' to automatically open via xdg-open.|] Pass '-o' to automatically open via xdg-open.|]
whereisFooter :: String
whereisFooter = [s|Discussion:
Finds the location of a tool. For GHC, this is the ghc binary, that
usually resides in a self-contained "~/.ghcup/ghc/<ghcver>" directory.
For cabal/stack/hls this the binary usually at "~/.ghcup/bin/<tool>-<ver>".
Examples:
# outputs ~/.ghcup/ghc/8.10.5/bin/ghc.exe
ghcup whereis ghc 8.10.5
# outputs ~/.ghcup/ghc/8.10.5/bin/
ghcup whereis --directory ghc 8.10.5
# outputs ~/.ghcup/bin/cabal-3.4.0.0
ghcup whereis cabal 3.4.0.0
# outputs ~/.ghcup/bin/
ghcup whereis --directory cabal 3.4.0.0|]
installCabalFooter :: String installCabalFooter :: String
installCabalFooter = [s|Discussion: installCabalFooter = [s|Discussion:
Installs the specified cabal-install version (or a recommended default one) Installs the specified cabal-install version (or a recommended default one)
@@ -706,6 +742,86 @@ Examples:
ghcup compile ghc -j 4 -v 8.4.2 -b 8.2.2 -x armv7-unknown-linux-gnueabihf --config $(pwd)/build.mk -- --enable-unregisterised|] ghcup compile ghc -j 4 -v 8.4.2 -b 8.2.2 -x armv7-unknown-linux-gnueabihf --config $(pwd)/build.mk -- --enable-unregisterised|]
whereisP :: Parser WhereisCommand
whereisP = subparser
( command
"ghc"
(WhereisTool GHC <$> info
( optional (toolVersionArgument Nothing (Just GHC)) <**> helper )
( progDesc "Get GHC location"
<> footerDoc (Just $ text whereisGHCFooter ))
)
<>
command
"cabal"
(WhereisTool Cabal <$> info
( optional (toolVersionArgument Nothing (Just Cabal)) <**> helper )
( progDesc "Get cabal location"
<> footerDoc (Just $ text whereisCabalFooter ))
)
<>
command
"hls"
(WhereisTool HLS <$> info
( optional (toolVersionArgument Nothing (Just HLS)) <**> helper )
( progDesc "Get HLS location"
<> footerDoc (Just $ text whereisHLSFooter ))
)
<>
command
"stack"
(WhereisTool Stack <$> info
( optional (toolVersionArgument Nothing (Just Stack)) <**> helper )
( progDesc "Get stack location"
<> footerDoc (Just $ text whereisStackFooter ))
)
<>
command
"ghcup"
(WhereisTool GHCup <$> info ( (pure Nothing) <**> helper ) ( progDesc "Get ghcup location" ))
)
where
whereisGHCFooter = [s|Discussion:
Finds the location of a GHC executable, which usually resides in
a self-contained "~/.ghcup/ghc/<ghcver>" directory.
Examples:
# outputs ~/.ghcup/ghc/8.10.5/bin/ghc.exe
ghcup whereis ghc 8.10.5
# outputs ~/.ghcup/ghc/8.10.5/bin/
ghcup whereis --directory ghc 8.10.5 |]
whereisCabalFooter = [s|Discussion:
Finds the location of a Cabal executable, which usually resides in
"~/.ghcup/bin/".
Examples:
# outputs ~/.ghcup/bin/cabal-3.4.0.0
ghcup whereis cabal 3.4.0.0
# outputs ~/.ghcup/bin
ghcup whereis --directory cabal 3.4.0.0|]
whereisHLSFooter = [s|Discussion:
Finds the location of a HLS executable, which usually resides in
"~/.ghcup/bin/".
Examples:
# outputs ~/.ghcup/bin/haskell-language-server-wrapper-1.2.0
ghcup whereis hls 1.2.0
# outputs ~/.ghcup/bin/
ghcup whereis --directory hls 1.2.0|]
whereisStackFooter = [s|Discussion:
Finds the location of a stack executable, which usually resides in
"~/.ghcup/bin/".
Examples:
# outputs ~/.ghcup/bin/stack-2.7.1
ghcup whereis stack 2.7.1
# outputs ~/.ghcup/bin/
ghcup whereis --directory stack 2.7.1|]
ghcCompileOpts :: Parser GHCCompileOptions ghcCompileOpts :: Parser GHCCompileOptions
ghcCompileOpts = ghcCompileOpts =
GHCCompileOptions GHCCompileOptions
@@ -1113,7 +1229,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 () }
@@ -1262,6 +1381,17 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
#endif #endif
] ]
let
runWhereIs =
runLogger
. flip runReaderT appstate
. runE
@'[ NotInstalled
, NoToolVersionSet
, NextVerNotFound
, TagNotFound
]
let runUpgrade = let runUpgrade =
runLogger runLogger
. flip runReaderT appstate . flip runReaderT appstate
@@ -1625,6 +1755,22 @@ Make sure to clean up #{tmpdir} afterwards.|])
runLogger $ $(logError) $ T.pack $ prettyShow e runLogger $ $(logError) $ T.pack $ prettyShow e
pure $ ExitFailure 9 pure $ ExitFailure 9
Whereis WhereisOptions{..} (WhereisTool tool whereVer) ->
runWhereIs (do
(v, _) <- liftE $ fromVersion whereVer tool
loc <- liftE $ whereIsTool tool v
if directory
then pure $ takeDirectory loc
else pure loc
)
>>= \case
VRight r -> do
putStr r
pure ExitSuccess
VLeft e -> do
runLogger $ $(logError) $ T.pack $ prettyShow e
pure $ ExitFailure 30
Upgrade uOpts force -> do Upgrade uOpts force -> do
target <- case uOpts of target <- case uOpts of
UpgradeInplace -> Just <$> liftIO getExecutablePath UpgradeInplace -> Just <$> liftIO getExecutablePath
@@ -1703,31 +1849,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

@@ -201,15 +201,124 @@ download_ghcup() {
;; ;;
esac esac
edo mkdir -p "${GHCUP_DIR}" edo mkdir -p "${GHCUP_DIR}"
# we may overwrite this in adjust_bashrc
cat <<-EOF > "${GHCUP_DIR}"/env || die "Failed to create env file" cat <<-EOF > "${GHCUP_DIR}"/env || die "Failed to create env file"
export PATH="\$HOME/.cabal/bin:${GHCUP_BIN}:\$PATH" export PATH="\$HOME/.cabal/bin:${GHCUP_BIN}:\$PATH"
EOF EOF
# shellcheck disable=SC1090 # shellcheck disable=SC1090
edo . "${GHCUP_DIR}"/env edo . "${GHCUP_DIR}"/env
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 "Do you want ghcup to automatically add the required PATH variable to \"${GHCUP_PROFILE_FILE}\"?"
warn ""
warn "[P] Yes, prepend [A] Yes, append [N] No [?] Help (default is \"P\")."
warn ""
while true; do
if [ -z "${BOOTSTRAP_HASKELL_NONINTERACTIVE}" ] ; then
read -r next_answer </dev/tty
else
next_answer="prepend"
fi
case $next_answer in
[Pp]* | "")
cat <<-EOF > "${GHCUP_DIR}"/env || die "Failed to create env file"
export PATH="\$HOME/.cabal/bin:${GHCUP_BIN}:\$PATH"
EOF
;;
[Aa]*)
cat <<-EOF > "${GHCUP_DIR}"/env || die "Failed to create env file"
export PATH="\$HOME/.cabal/bin:\$PATH:${GHCUP_BIN}"
EOF
;;
*) ;;
esac
case $next_answer in
[Nn]*)
return ;;
[Pp]* | [Aa]* | "")
case $MY_SHELL in
"") break ;;
fish)
mkdir -p "${GHCUP_PROFILE_FILE%/*}"
sed -i -e '/# ghcup-env$/ s/^#*/#/' "${GHCUP_PROFILE_FILE}"
case $next_answer in
[Pp]* | "")
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}"
;;
[Aa]*)
echo "set -q GHCUP_INSTALL_BASE_PREFIX[1]; or set GHCUP_INSTALL_BASE_PREFIX \$HOME ; set -gx PATH \$HOME/.cabal/bin \$PATH $GHCUP_BIN # ghcup-env" >> "${GHCUP_PROFILE_FILE}"
;;
esac
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 "P - Yes, prepend to PATH, taking precedence (default)"
echo "A - Yes, append to PATH"
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 +426,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 +441,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 +468,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 +482,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-r1
dlHash: d91b7a5416f292f2cf813824eb419f76ad9976d258cee3581123cb6eb01db9a7 dlHash: d853372440f3d43babbb868fad399811241760f2233829c92403fcbea8c547ec
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
@@ -2069,8 +2069,8 @@ ghcupDownloads:
A_ARM: A_ARM:
Linux_UnknownLinux: Linux_UnknownLinux:
unknown_versioning: unknown_versioning:
dlUri: https://downloads.haskell.org/~ghcup/0.1.15.2/armv7-linux-ghcup-0.1.15.2 dlUri: https://downloads.haskell.org/~ghcup/0.1.15.2/armv7-linux-ghcup-0.1.15.2-r1
dlHash: 03a4af5ed895ada1dd21f4cc3f64dc9078a5bf4268313021d004c04bea7f9c2e dlHash: f8add9b39e1f7d0f03904dc69a8683259972a4472432c1ade27d918c39a4a874
HLS: HLS:
1.1.0: 1.1.0:
viTags: [] viTags: []
@@ -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)
@@ -585,7 +586,7 @@ installStackBindist dlinfo ver = do
, settings , settings
} <- lift ask } <- lift ask
whenM (lift (hlsInstalled ver)) whenM (lift (stackInstalled ver))
(throwE $ AlreadyInstalled Stack ver) (throwE $ AlreadyInstalled Stack ver)
-- download (or use cached version) -- download (or use cached version)
@@ -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
@@ -1888,3 +1880,49 @@ postGHCInstall ver@GHCTargetVersion {..} = do
$ getMajorMinorV _tvVersion $ getMajorMinorV _tvVersion
forM_ v' $ \(mj, mi) -> lift (getGHCForMajor mj mi _tvTarget) forM_ v' $ \(mj, mi) -> lift (getGHCForMajor mj mi _tvTarget)
>>= mapM_ (\v -> liftE $ setGHC v SetGHC_XY) >>= mapM_ (\v -> liftE $ setGHC v SetGHC_XY)
-- | Reports the binary location of a given tool:
--
-- * for GHC, this reports: @~\/.ghcup\/ghc\/\<ver\>\/bin\/ghc@
-- * for cabal, this reports @~\/.ghcup\/bin\/cabal-\<ver\>@
-- * for hls, this reports @~\/.ghcup\/bin\/haskell-language-server-wrapper-\<ver\>@
-- * for stack, this reports @~\/.ghcup\/bin\/stack-\<ver\>@
-- * for ghcup, this reports the location of the currently running executable
whereIsTool :: ( MonadReader AppState m
, MonadLogger m
, MonadThrow m
, MonadFail m
, MonadIO m
, MonadCatch m
, MonadMask m
, MonadUnliftIO m
)
=> Tool
-> GHCTargetVersion
-> Excepts '[NotInstalled] m FilePath
whereIsTool tool ver@GHCTargetVersion {..} = do
AppState { dirs } <- lift ask
case tool of
GHC -> do
whenM (lift $ fmap not $ ghcInstalled ver)
$ throwE (NotInstalled GHC ver)
bdir <- lift $ ghcupGHCDir ver
pure (bdir </> "bin" </> "ghc" <> exeExt)
Cabal -> do
whenM (lift $ fmap not $ cabalInstalled _tvVersion)
$ throwE (NotInstalled Cabal (GHCTargetVersion Nothing _tvVersion))
pure (binDir dirs </> "cabal-" <> T.unpack (prettyVer _tvVersion) <> exeExt)
HLS -> do
whenM (lift $ fmap not $ hlsInstalled _tvVersion)
$ throwE (NotInstalled HLS (GHCTargetVersion Nothing _tvVersion))
pure (binDir dirs </> "haskell-language-server-wrapper-" <> T.unpack (prettyVer _tvVersion) <> exeExt)
Stack -> do
whenM (lift $ fmap not $ stackInstalled _tvVersion)
$ throwE (NotInstalled Stack (GHCTargetVersion Nothing _tvVersion))
pure (binDir dirs </> "stack-" <> T.unpack (prettyVer _tvVersion) <> exeExt)
GHCup -> do
currentRunningExecPath <- liftIO getExecutablePath
liftIO $ canonicalizePath currentRunningExecPath

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>