Compare commits
97 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
15dd810d67
|
|||
|
b5ca01dc4f
|
|||
|
d662682fb5
|
|||
|
ff2b06a5e8
|
|||
|
aece305003
|
|||
|
ef8da9bcec
|
|||
|
3cd55beab1
|
|||
|
6766501858
|
|||
|
d5b41683ca
|
|||
|
ff8dbe111d
|
|||
|
28d4071fac
|
|||
|
31a523755f
|
|||
|
3d1d8f1af7
|
|||
|
167f6d0683
|
|||
|
8580487b61
|
|||
|
a8b1c33280
|
|||
|
fca2a4134b
|
|||
|
f90741f4d3
|
|||
|
ba4b45f7fb
|
|||
|
4767f3db5b
|
|||
|
709658462c
|
|||
|
c431c0ae00
|
|||
|
6f61b5dbef
|
|||
|
c42c4b64f9
|
|||
|
d3a36c2c9a
|
|||
|
6799e9616e
|
|||
|
|
e8d962ac44 | ||
|
ac1e145028
|
|||
|
2fdf121167
|
|||
|
dcca8b0bf2
|
|||
|
b1f891b005
|
|||
|
648dcc7287
|
|||
|
2175f7dd3d
|
|||
|
aff90a52f1
|
|||
|
0f14dee72a
|
|||
|
ae2031174e
|
|||
|
c163278c64
|
|||
|
d10133f06f
|
|||
|
4377fc663e
|
|||
|
487e236882
|
|||
|
|
8fc128e89b | ||
|
|
737f72f90f | ||
|
|
c3aab65521 | ||
|
|
972474f79a | ||
| bc64d2ade0 | |||
|
|
eddda55fe6 | ||
|
|
13aca91231 | ||
|
|
6011242eae | ||
|
|
cadb5086e1 | ||
|
|
10a30bbf38 | ||
|
|
6ac7a75bab | ||
|
bbd11bfa26
|
|||
|
75548fa02d
|
|||
|
fb6956009f
|
|||
|
e029117c3e
|
|||
|
bc7c01de90
|
|||
|
cfcd8a4c20
|
|||
|
5e17eb7ca7
|
|||
|
|
756727ffe2 | ||
|
6bc602dead
|
|||
|
056c79e813
|
|||
|
68bbf31a86
|
|||
|
b58f380e75
|
|||
|
48c54bf374
|
|||
|
51da1578f4
|
|||
|
|
488f25aed6 | ||
|
|
d60f58cf43 | ||
|
|
7a6a119829 | ||
|
|
f0fb019c70 | ||
|
|
0f98ec6b78 | ||
|
|
107fed6e60 | ||
|
|
59a9a770a5 | ||
|
|
20bcb26e3d | ||
|
d355c46250
|
|||
|
787c927de6
|
|||
|
d15ff7bc67
|
|||
|
7c5c35f1b0
|
|||
|
001b090bc6
|
|||
|
db8207f8b9
|
|||
|
e5918de7af
|
|||
|
d2346a543a
|
|||
|
c057b4ae5c
|
|||
|
b962bf4af9
|
|||
|
c54dc05d92
|
|||
|
8c72bf697e
|
|||
|
cc8cf3d12a
|
|||
|
9bdf6bde17
|
|||
|
8363495843
|
|||
|
bc80b1048f
|
|||
|
d61981bc1b
|
|||
|
4ccdc5dd6c
|
|||
|
3240118226
|
|||
|
254989d63d
|
|||
|
|
be82565775 | ||
|
|
f8d0243146 | ||
|
|
d7f82d643c | ||
|
|
15560a06b1 |
@@ -49,6 +49,7 @@ variables:
|
||||
OS: "LINUX"
|
||||
ARCH: "ARM"
|
||||
CABAL_DIR: "$CI_PROJECT_DIR/cabal"
|
||||
retry: 2
|
||||
|
||||
.linux:aarch64:
|
||||
image: "registry.gitlab.haskell.org/ghc/ci-images/aarch64-linux-deb10:$DOCKER_REV"
|
||||
@@ -75,7 +76,15 @@ variables:
|
||||
ARCH: "ARM64"
|
||||
CABAL_DIR: "$CI_PROJECT_DIR/cabal"
|
||||
|
||||
.freebsd:
|
||||
.freebsd13:
|
||||
tags:
|
||||
- x86_64-freebsd13
|
||||
variables:
|
||||
OS: "FREEBSD"
|
||||
ARCH: "64"
|
||||
CABAL_DIR: "$CI_PROJECT_DIR/cabal"
|
||||
|
||||
.freebsd12:
|
||||
tags:
|
||||
- x86_64-freebsd
|
||||
variables:
|
||||
@@ -90,6 +99,7 @@ variables:
|
||||
OS: "WINDOWS"
|
||||
ARCH: "64"
|
||||
CABAL_DIR: "$CI_PROJECT_DIR/cabal"
|
||||
retry: 2
|
||||
|
||||
.root_cleanup:
|
||||
after_script:
|
||||
@@ -99,11 +109,11 @@ variables:
|
||||
script:
|
||||
- bash ./.gitlab/script/ghcup_version.sh
|
||||
variables:
|
||||
JSON_VERSION: "0.0.7"
|
||||
JSON_VERSION: "0.0.6"
|
||||
artifacts:
|
||||
expire_in: 2 week
|
||||
paths:
|
||||
- golden
|
||||
- test/golden
|
||||
- dist-newstyle/cache/
|
||||
when: on_failure
|
||||
|
||||
@@ -173,10 +183,18 @@ variables:
|
||||
runInNixShell ./.gitlab/before_script/darwin/install_deps.sh 2>&1
|
||||
runInNixShell ./.gitlab/script/ghcup_version.sh 2>&1
|
||||
|
||||
.test_ghcup_version:freebsd:
|
||||
.test_ghcup_version:freebsd12:
|
||||
extends:
|
||||
- .test_ghcup_version
|
||||
- .freebsd
|
||||
- .freebsd12
|
||||
- .root_cleanup
|
||||
before_script:
|
||||
- ./.gitlab/before_script/freebsd/install_deps.sh
|
||||
|
||||
.test_ghcup_version:freebsd13:
|
||||
extends:
|
||||
- .test_ghcup_version
|
||||
- .freebsd13
|
||||
- .root_cleanup
|
||||
before_script:
|
||||
- ./.gitlab/before_script/freebsd/install_deps.sh
|
||||
@@ -207,7 +225,7 @@ variables:
|
||||
only:
|
||||
- tags
|
||||
variables:
|
||||
JSON_VERSION: "0.0.7"
|
||||
JSON_VERSION: "0.0.6"
|
||||
|
||||
######## stack test ########
|
||||
|
||||
@@ -240,7 +258,7 @@ test:linux:bootstrap_script:
|
||||
test:windows:bootstrap_powershell_script:
|
||||
stage: test
|
||||
script:
|
||||
- ./bootstrap-haskell.ps1 -InstallDir $CI_PROJECT_DIR -BootstrapUrl $CI_PROJECT_DIR/bootstrap-haskell -InBash
|
||||
- ./scripts/bootstrap/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)"
|
||||
@@ -263,6 +281,23 @@ test:linux:
|
||||
CABAL_VERSION: "3.4.0.0"
|
||||
needs: []
|
||||
|
||||
test:linux:hls:
|
||||
stage: test
|
||||
extends:
|
||||
- .test_ghcup_version
|
||||
- .debian
|
||||
variables:
|
||||
GHC_VERSION: "8.10.7"
|
||||
HLS_TARGET_VERSION: "1.4.0"
|
||||
CABAL_VERSION: "3.6.0.0"
|
||||
needs: []
|
||||
when: manual
|
||||
allow_failure: true
|
||||
before_script:
|
||||
- ./.gitlab/before_script/linux/install_deps.sh
|
||||
script:
|
||||
- ./.gitlab/script/ghcup_hls.sh
|
||||
|
||||
test:linux:cross-armv7:
|
||||
stage: test
|
||||
extends:
|
||||
@@ -355,9 +390,19 @@ test:mac:aarch64:
|
||||
|
||||
######## freebsd test ########
|
||||
|
||||
test:freebsd:
|
||||
test:freebsd12:
|
||||
stage: test
|
||||
extends: .test_ghcup_version:freebsd
|
||||
extends: .test_ghcup_version:freebsd12
|
||||
variables:
|
||||
GHC_VERSION: "8.10.4"
|
||||
CABAL_VERSION: "3.4.0.0"
|
||||
allow_failure: true # freebsd runners are unreliable
|
||||
when: manual
|
||||
needs: []
|
||||
|
||||
test:freebsd13:
|
||||
stage: test
|
||||
extends: .test_ghcup_version:freebsd13
|
||||
variables:
|
||||
GHC_VERSION: "8.10.4"
|
||||
CABAL_VERSION: "3.4.0.0"
|
||||
@@ -491,11 +536,26 @@ release:darwin:aarch64:
|
||||
|
||||
######## freebsd release ########
|
||||
|
||||
release:freebsd:
|
||||
release:freebsd12:
|
||||
stage: release
|
||||
needs: ["test:freebsd"]
|
||||
needs: ["test:freebsd12"]
|
||||
extends:
|
||||
- .freebsd
|
||||
- .freebsd12
|
||||
- .release_ghcup
|
||||
- .root_cleanup
|
||||
before_script:
|
||||
- ./.gitlab/before_script/freebsd/install_deps.sh
|
||||
variables:
|
||||
ARTIFACT: "x86_64-portbld-freebsd-ghcup"
|
||||
GHC_VERSION: "8.10.6"
|
||||
CABAL_VERSION: "3.4.0.0"
|
||||
allow_failure: true
|
||||
|
||||
release:freebsd13:
|
||||
stage: release
|
||||
needs: ["test:freebsd13"]
|
||||
extends:
|
||||
- .freebsd13
|
||||
- .release_ghcup
|
||||
- .root_cleanup
|
||||
before_script:
|
||||
|
||||
@@ -11,9 +11,9 @@ mkdir -p "${TMPDIR}"
|
||||
curl -sSfL https://downloads.haskell.org/~ghcup/x86_64-portbld-freebsd-ghcup > ./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}
|
||||
./ghcup-bin -v upgrade -i -f
|
||||
./ghcup-bin -v install ${GHC_VERSION}
|
||||
./ghcup-bin -v set ${GHC_VERSION}
|
||||
./ghcup-bin -v install-cabal ${CABAL_VERSION}
|
||||
|
||||
exit 0
|
||||
|
||||
@@ -7,67 +7,21 @@ set -eux
|
||||
mkdir -p "${TMPDIR}"
|
||||
|
||||
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 lsb-release software-properties-common gnupg2 apt-transport-https
|
||||
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 gcc autoconf automake build-essential
|
||||
|
||||
if [ "${CROSS}" = "arm-linux-gnueabihf" ] ; then
|
||||
sudo apt-get install -y autoconf build-essential gcc-arm-linux-gnueabihf
|
||||
sudo apt-get install -y gcc-arm-linux-gnueabihf
|
||||
sudo dpkg --add-architecture armhf
|
||||
sudo apt-get update -y
|
||||
sudo apt-get install -y libncurses-dev:armhf
|
||||
fi
|
||||
|
||||
case "${ARCH}" in
|
||||
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
|
||||
export BOOTSTRAP_HASKELL_NONINTERACTIVE=1
|
||||
export BOOTSTRAP_HASKELL_GHC_VERSION=$GHC_VERSION
|
||||
export BOOTSTRAP_HASKELL_CABAL_VERSION=$CABAL_VERSION
|
||||
export BOOTSTRAP_HASKELL_VERBOSE=1
|
||||
|
||||
mkdir -p "${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup/bin
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh
|
||||
|
||||
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
|
||||
|
||||
;;
|
||||
*)
|
||||
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 ${GHC_VERSION}
|
||||
./ghcup-bin set ghc ${GHC_VERSION}
|
||||
./ghcup-bin install cabal ${CABAL_VERSION}
|
||||
|
||||
;;
|
||||
esac
|
||||
rm "${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup/bin/ghcup
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
if [ "${OS}" = "WINDOWS" ] ; then
|
||||
export GHCUP_INSTALL_BASE_PREFIX="$CI_PROJECT_DIR"
|
||||
export PATH="$GHCUP_INSTALL_BASE_PREFIX/ghcup/bin:$CI_PROJECT_DIR/.local/bin:$PATH"
|
||||
export GHCUP_BIN="$CI_PROJECT_DIR/ghcup/bin"
|
||||
export PATH="$GHCUP_BIN:$CI_PROJECT_DIR/.local/bin:$PATH"
|
||||
export TMPDIR="$CI_PROJECT_DIR/tmp"
|
||||
else
|
||||
export GHCUP_INSTALL_BASE_PREFIX="$CI_PROJECT_DIR"
|
||||
export PATH="$CI_PROJECT_DIR/.ghcup/bin:$CI_PROJECT_DIR/.local/bin:/opt/llvm/bin:$PATH"
|
||||
export GHCUP_BIN="$CI_PROJECT_DIR/.ghcup/bin"
|
||||
export PATH="$GHCUP_BIN:$CI_PROJECT_DIR/.local/bin:/opt/llvm/bin:$PATH"
|
||||
export TMPDIR="$CI_PROJECT_DIR/tmp"
|
||||
fi
|
||||
|
||||
@@ -24,7 +24,7 @@ export BOOTSTRAP_HASKELL_NONINTERACTIVE=yes
|
||||
export BOOTSTRAP_HASKELL_GHC_VERSION=$GHC_VERSION
|
||||
export BOOTSTRAP_HASKELL_CABAL_VERSION=$CABAL_VERSION
|
||||
|
||||
./bootstrap-haskell
|
||||
./scripts/bootstrap/bootstrap-haskell
|
||||
|
||||
[ "$(ghc --numeric-version)" = "${GHC_VERSION}" ]
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ ecabal() {
|
||||
}
|
||||
|
||||
eghcup() {
|
||||
ghcup -v -c -s file://$CI_PROJECT_DIR/ghcup-${JSON_VERSION}.yaml "$@"
|
||||
ghcup -v -c -s file://$CI_PROJECT_DIR/data/metadata/ghcup-${JSON_VERSION}.yaml "$@"
|
||||
}
|
||||
|
||||
git describe --always
|
||||
|
||||
@@ -13,7 +13,7 @@ ecabal() {
|
||||
}
|
||||
|
||||
eghcup() {
|
||||
ghcup -v -c -s file://$CI_PROJECT_DIR/ghcup-${JSON_VERSION}.yaml "$@"
|
||||
ghcup -v -c -s file://$CI_PROJECT_DIR/data/metadata/ghcup-${JSON_VERSION}.yaml "$@"
|
||||
}
|
||||
|
||||
git describe --always
|
||||
|
||||
51
.gitlab/script/ghcup_hls.sh
Executable file
51
.gitlab/script/ghcup_hls.sh
Executable file
@@ -0,0 +1,51 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -eux
|
||||
|
||||
. "$( cd "$(dirname "$0")" ; pwd -P )/../ghcup_env"
|
||||
|
||||
mkdir -p "$CI_PROJECT_DIR"/.local/bin
|
||||
|
||||
CI_PROJECT_DIR=$(pwd)
|
||||
|
||||
ecabal() {
|
||||
cabal "$@"
|
||||
}
|
||||
|
||||
eghcup() {
|
||||
ghcup -v -c -s file://$CI_PROJECT_DIR/data/metadata/ghcup-${JSON_VERSION}.yaml "$@"
|
||||
}
|
||||
|
||||
git describe --always
|
||||
|
||||
### build
|
||||
|
||||
ecabal update
|
||||
|
||||
ecabal build -w ghc-${GHC_VERSION}
|
||||
cp "$(ecabal new-exec -w ghc-${GHC_VERSION} --verbose=0 --offline sh -- -c 'command -v ghcup')" "$CI_PROJECT_DIR"/.local/bin/ghcup
|
||||
|
||||
### cleanup
|
||||
|
||||
rm -rf "${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup
|
||||
|
||||
### manual cli based testing
|
||||
|
||||
eghcup --numeric-version
|
||||
|
||||
eghcup install ghc ${GHC_VERSION}
|
||||
eghcup set ghc ${GHC_VERSION}
|
||||
eghcup install cabal ${CABAL_VERSION}
|
||||
|
||||
cabal --version
|
||||
|
||||
eghcup debug-info
|
||||
|
||||
eghcup compile hls -j $(nproc) -v ${HLS_TARGET_VERSION} ${GHC_VERSION}
|
||||
|
||||
[ `$(eghcup whereis hls ${HLS_TARGET_VERSION}) --numeric-version` = "${HLS_TARGET_VERSION}" ] || [ `$(eghcup whereis hls ${HLS_TARGET_VERSION}) --numeric-version | sed 's/.0$//'` = "${HLS_TARGET_VERSION}" ]
|
||||
|
||||
# nuke
|
||||
eghcup nuke
|
||||
[ ! -e "${GHCUP_INSTALL_BASE_PREFIX}/.ghcup" ]
|
||||
|
||||
@@ -18,9 +18,9 @@ raw_eghcup() {
|
||||
|
||||
eghcup() {
|
||||
if [ "${OS}" = "WINDOWS" ] ; then
|
||||
ghcup -v -c -s file:/$CI_PROJECT_DIR/ghcup-${JSON_VERSION}.yaml "$@"
|
||||
ghcup -v -c -s file:/$CI_PROJECT_DIR/data/metadata/ghcup-${JSON_VERSION}.yaml "$@"
|
||||
else
|
||||
ghcup -v -c -s file://$CI_PROJECT_DIR/ghcup-${JSON_VERSION}.yaml "$@"
|
||||
ghcup -v -c -s file://$CI_PROJECT_DIR/data/metadata/ghcup-${JSON_VERSION}.yaml "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ rm -rf "${GHCUP_DIR}"
|
||||
### manual cli based testing
|
||||
|
||||
|
||||
ghcup-gen check -f ghcup-${JSON_VERSION}.yaml
|
||||
ghcup-gen check -f data/metadata/ghcup-${JSON_VERSION}.yaml
|
||||
|
||||
eghcup --numeric-version
|
||||
|
||||
@@ -101,6 +101,10 @@ eghcup install ghc ${GHC_VERSION}
|
||||
eghcup set ghc ${GHC_VERSION}
|
||||
eghcup install cabal ${CABAL_VERSION}
|
||||
[ `$(eghcup whereis cabal ${CABAL_VERSION}) --numeric-version` = "${CABAL_VERSION}" ]
|
||||
eghcup unset cabal
|
||||
"$GHCUP_BIN"/cabal --version && exit || echo yes
|
||||
eghcup set cabal ${CABAL_VERSION}
|
||||
[ `$(eghcup whereis cabal ${CABAL_VERSION}) --numeric-version` = "${CABAL_VERSION}" ]
|
||||
|
||||
cabal --version
|
||||
|
||||
@@ -151,9 +155,13 @@ else
|
||||
[ "$(ghc --numeric-version)" = "8.10.3" ]
|
||||
eghcup set ${GHC_VERSION}
|
||||
[ "$(ghc --numeric-version)" = "${ghc_ver}" ]
|
||||
eghcup unset ghc
|
||||
"$GHCUP_BIN"/ghc --numeric-version && exit || echo yes
|
||||
eghcup set ${GHC_VERSION}
|
||||
eghcup --offline rm 8.10.3
|
||||
[ "$(ghc --numeric-version)" = "${ghc_ver}" ]
|
||||
|
||||
|
||||
if [ "${OS}" = "DARWIN" ] ; then
|
||||
eghcup install hls
|
||||
$(eghcup whereis hls) --version
|
||||
@@ -164,18 +172,22 @@ else
|
||||
if [ "${ARCH}" = "64" ] ; then
|
||||
eghcup install hls
|
||||
haskell-language-server-wrapper --version
|
||||
eghcup unset hls
|
||||
"$GHCUP_BIN"/haskell-language-server-wrapper --version && exit || echo yes
|
||||
|
||||
eghcup install stack
|
||||
stack --version
|
||||
eghcup unset hls
|
||||
"$GHCUP_BIN"/stack --version && exit || echo yes
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# check that lazy loading works for 'whereis'
|
||||
cp "$CI_PROJECT_DIR/ghcup-${JSON_VERSION}.yaml" "$CI_PROJECT_DIR/ghcup-${JSON_VERSION}.yaml.bak"
|
||||
echo '**' > "$CI_PROJECT_DIR/ghcup-${JSON_VERSION}.yaml"
|
||||
cp "$CI_PROJECT_DIR/data/metadata/ghcup-${JSON_VERSION}.yaml" "$CI_PROJECT_DIR/data/metadata/ghcup-${JSON_VERSION}.yaml.bak"
|
||||
echo '**' > "$CI_PROJECT_DIR/data/metadata/ghcup-${JSON_VERSION}.yaml"
|
||||
eghcup whereis ghc $(ghc --numeric-version)
|
||||
mv -f "$CI_PROJECT_DIR/ghcup-${JSON_VERSION}.yaml.bak" "$CI_PROJECT_DIR/ghcup-${JSON_VERSION}.yaml"
|
||||
mv -f "$CI_PROJECT_DIR/data/metadata/ghcup-${JSON_VERSION}.yaml.bak" "$CI_PROJECT_DIR/data/metadata/ghcup-${JSON_VERSION}.yaml"
|
||||
|
||||
eghcup rm $(ghc --numeric-version)
|
||||
|
||||
|
||||
169
README.md
169
README.md
@@ -10,16 +10,18 @@ Similar in scope to [rustup](https://github.com/rust-lang-nursery/rustup.rs), [p
|
||||
[](https://app.element.io/#/room/#haskell-tooling:matrix.org)
|
||||
[](https://discord.gg/pKYf3zDQU7)
|
||||
[](https://gitter.im/haskell/ghcup?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
<a href="https://opencollective.com/ghcup#category-CONTRIBUTE"><img src="https://opencollective.com/webpack/donate/button@2x.png?color=blue" alt="Donate" width="150"></a>
|
||||
|
||||
* [Installation](#installation)
|
||||
* [Simple bootstrap](#simple-bootstrap)
|
||||
* [Supported platforms](#supported-platforms)
|
||||
* [Manual install](#manual-install)
|
||||
* [Vim integration](#vim-integration)
|
||||
* [Usage](#usage)
|
||||
* [Configuration](#configuration)
|
||||
* [GPG verification](#gpg-verification)
|
||||
* [Manpages](#manpages)
|
||||
* [Shell-completion](#shell-completion)
|
||||
* [Cross support](#cross-support)
|
||||
* [Compiling GHC from source](#compiling-ghc-from-source)
|
||||
* [XDG support](#xdg-support)
|
||||
* [Env variables](#env-variables)
|
||||
* [Installing custom bindists](#installing-custom-bindists)
|
||||
@@ -34,9 +36,59 @@ Similar in scope to [rustup](https://github.com/rust-lang-nursery/rustup.rs), [p
|
||||
|
||||
## Installation
|
||||
|
||||
### Simple bootstrap
|
||||
Most users should follow the instructions at [https://www.haskell.org/ghcup/](https://www.haskell.org/ghcup/).
|
||||
Advanced users may want to perform a [manual installation](#manual-install).
|
||||
|
||||
Follow the instructions at [https://www.haskell.org/ghcup/](https://www.haskell.org/ghcup/)
|
||||
### Supported platforms
|
||||
|
||||
This list may not be exhaustive and specifies support for bindists only.
|
||||
|
||||
| Platform | Architecture | ghcup | GHC | cabal | HLS | stack |
|
||||
| ------ | ------ | ------ | ------ | ------ | ------ | ------ |
|
||||
| Windows 7 | amd64 | ❔ | ✅ | ✅ | ✅ | ✅ |
|
||||
| Windows 10 | amd64 | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| Windows Server 2016 | amd64 | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| Windows Server 2019 | amd64 | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| Windows Server 2022 | amd64 | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| Windows WSL1 | amd64 | ❌ | ❔ | ❔ | ❔ | ❔ |
|
||||
| Windows WSL2 | amd64 | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| MacOS >=13 | amd64 | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| MacOS <13 | amd64 | ❌ | ❔ | ❔ | ❔ | ❔ |
|
||||
| MacOS | aarch64 | ✅ | ✅ | ✅ | ⚠️ | ❌ |
|
||||
| FreeBSD | amd64 | ✅ | ⚠️ | ✅ | ⚠️ | ❌ |
|
||||
| Linux generic | x86 | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| Linux generic | amd64 | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| Linux generic | aarch64 | ✅ | ⚠️ | ✅ | ⚠️ | ❌ |
|
||||
| Linux generic | armv7 | ✅ | ⚠️ | ✅ | ⚠️ | ❌ |
|
||||
|
||||
#### Windows 7
|
||||
|
||||
May or may not work, several issues:
|
||||
|
||||
* https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/140
|
||||
* https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/197
|
||||
|
||||
#### WSL1
|
||||
|
||||
Unsupported. GHC may or may not work. Upgrade to WSL2.
|
||||
|
||||
#### MacOS <13
|
||||
|
||||
Not supported. Would require separate binaries, since >=13 binaries are incompatible.
|
||||
Please upgrade.
|
||||
|
||||
#### MacOS aarch64
|
||||
|
||||
HLS bindists are still experimental. Stack is theoretically supported, but has no binaries yet.
|
||||
|
||||
#### FreeBSD
|
||||
|
||||
Lacks some upstream bindists and may need compat libs, since most bindists are built on FreeBSD-12.
|
||||
HLS bindists are experimental.
|
||||
|
||||
#### Linux ARMv7/AARCH64
|
||||
|
||||
Lower availability of bindists. HLS only has experimental ones. Stack not supported currently.
|
||||
|
||||
### Manual install
|
||||
|
||||
@@ -91,10 +143,38 @@ handles your haskell packages and can demand that [a specific version](https://c
|
||||
### Configuration
|
||||
|
||||
A configuration file can be put in `~/.ghcup/config.yaml`. The default config file
|
||||
explaining all possible configurations can be found in this repo: [config.yaml](./config.yaml).
|
||||
explaining all possible configurations can be found in this repo: [config.yaml](./data/config.yaml).
|
||||
|
||||
Partial configuration is fine. Command line options always override the config file settings.
|
||||
|
||||
### GPG verification
|
||||
|
||||
GHCup supports verifying the GPG signature of the metadata file. The metadata file then contains SHA256 hashes of all downloads, so
|
||||
this is cryptographically secure.
|
||||
|
||||
First, obtain the gpg key:
|
||||
|
||||
```sh
|
||||
gpg --batch --keyserver keys.openpgp.org --recv-keys 7784930957807690A66EBDBE3786C5262ECB4A3F
|
||||
```
|
||||
|
||||
Then verify the gpg key in one of these ways:
|
||||
|
||||
1. find out where I live and visit me to do offline key signing
|
||||
2. figure out my mobile phone number and call me to verify the fingerprint
|
||||
3. more boring: contact me on Libera IRC (`maerwald`) and verify the fingerprint
|
||||
|
||||
Once you've verified the key, you have to figure out if you trust me.
|
||||
|
||||
If you trust me, then you can configure gpg in `~/.ghcup/config.yaml`:
|
||||
|
||||
```yml
|
||||
gpg-setting: GPGLax # GPGStrict | GPGLax | GPGNone
|
||||
```
|
||||
|
||||
In `GPGStrict` mode, ghcup will fail if verification fails. In `GPGLax` mode it will just print a warning.
|
||||
You can also pass the mode via `ghcup --gpg <strict|lax|none>`.
|
||||
|
||||
### Manpages
|
||||
|
||||
For man pages to work you need [man-db](http://man-db.nongnu.org/) as your `man` provider, then issue `man ghc`. Manpages only work for the currently set ghc.
|
||||
@@ -102,14 +182,26 @@ For man pages to work you need [man-db](http://man-db.nongnu.org/) as your `man`
|
||||
|
||||
### Shell-completion
|
||||
|
||||
Shell completions are in `shell-completions`.
|
||||
Shell completions are in [scripts/shell-completions](./scripts/shell-completions) directory of this repository.
|
||||
|
||||
For bash: install `shell-completions/bash`
|
||||
as e.g. `/etc/bash_completion.d/ghcup` (depending on distro)
|
||||
and make sure your bashrc sources the startup script
|
||||
(`/usr/share/bash-completion/bash_completion` on some distros).
|
||||
|
||||
### Cross support
|
||||
### Compiling GHC from source
|
||||
|
||||
Compiling from source is supported for both source tarballs and arbitrary git refs. See `ghcup compile ghc --help`
|
||||
for a list of all available options.
|
||||
|
||||
If you need to overwrite the existing `build.mk`, check the default files
|
||||
in [data/build_mk](./data/build_mk), copy them somewhere, adjust them and
|
||||
pass `--config path/to/build.mk` to `ghcup compile ghc`.
|
||||
Common `build.mk` options are explained [here](https://gitlab.haskell.org/ghc/ghc/-/wikis/building/using#build-configuration).
|
||||
|
||||
Make sure your system meets all the [prerequisites](https://gitlab.haskell.org/ghc/ghc/-/wikis/building/preparation).
|
||||
|
||||
#### Cross support
|
||||
|
||||
ghcup can compile and install a cross GHC for any target. However, this
|
||||
requires that the build host has a complete cross toolchain and various
|
||||
@@ -143,6 +235,7 @@ This is the complete list of env variables that change GHCup behavior:
|
||||
* `GHCUP_INSTALL_BASE_PREFIX`: the base of ghcup (default: `$HOME`)
|
||||
* `GHCUP_CURL_OPTS`: additional options that can be passed to curl
|
||||
* `GHCUP_WGET_OPTS`: additional options that can be passed to wget
|
||||
* `GHCUP_GPG_OPTS`: additional options that can be passed to gpg
|
||||
* `GHCUP_SKIP_UPDATE_CHECK`: Skip the (possibly annoying) update check when you run a command
|
||||
* `CC`/`LD` etc.: full environment is passed to the build system when compiling GHC via GHCup
|
||||
|
||||
@@ -241,14 +334,15 @@ jobs:
|
||||
name: Install ghcup on windows
|
||||
run: Set-ExecutionPolicy Bypass -Scope Process -Force;[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072;Invoke-Command -ScriptBlock ([ScriptBlock]::Create((Invoke-WebRequest https://www.haskell.org/ghcup/sh/bootstrap-haskell.ps1 -UseBasicParsing))) -ArgumentList $false,$true,$true,$false,$false,$false,$false,"C:\"
|
||||
|
||||
- if: matrix.os == 'windows-latest'
|
||||
name: Add ghcup to PATH
|
||||
run: echo "/c/ghcup/bin" >> $GITHUB_PATH
|
||||
shell: bash
|
||||
|
||||
- if: matrix.os != 'windows-latest'
|
||||
name: Install ghcup on non-windows
|
||||
run: curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | BOOTSTRAP_HASKELL_NONINTERACTIVE=1 BOOTSTRAP_HASKELL_MINIMAL=1 sh
|
||||
|
||||
- if: matrix.os == 'windows-latest'
|
||||
run: echo "/c/ghcup/bin" >> $GITHUB_PATH
|
||||
shell: bash
|
||||
|
||||
- name: Install ghc/cabal
|
||||
run: |
|
||||
ghcup install ghc ${{ matrix.ghc }}
|
||||
@@ -266,50 +360,6 @@ jobs:
|
||||
- name: Run tests
|
||||
run: cabal test
|
||||
shell: bash
|
||||
|
||||
- name: Run benches
|
||||
run: cabal bench
|
||||
shell: bash
|
||||
|
||||
build-stack:
|
||||
name: Stack ${{ matrix.stack }} ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, macOS-latest, windows-latest]
|
||||
stack: ['latest']
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- if: matrix.os == 'windows-latest'
|
||||
name: Install ghcup on windows
|
||||
run: Set-ExecutionPolicy Bypass -Scope Process -Force;[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072;Invoke-Command -ScriptBlock ([ScriptBlock]::Create((Invoke-WebRequest https://www.haskell.org/ghcup/sh/bootstrap-haskell.ps1 -UseBasicParsing))) -ArgumentList $false,$true,$true,$false,$false,$false,$false,"C:\"
|
||||
|
||||
- if: matrix.os != 'windows-latest'
|
||||
name: Install ghcup on non-windows
|
||||
run: curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | BOOTSTRAP_HASKELL_NONINTERACTIVE=1 BOOTSTRAP_HASKELL_MINIMAL=1 sh
|
||||
|
||||
- if: matrix.os == 'windows-latest'
|
||||
run: echo "/c/ghcup/bin" >> $GITHUB_PATH
|
||||
shell: bash
|
||||
|
||||
- name: Install stack
|
||||
run: ghcup install stack ${{ matrix.stack }}
|
||||
shell: bash
|
||||
|
||||
- name: Build
|
||||
run: stack build
|
||||
shell: bash
|
||||
|
||||
- name: Run tests
|
||||
run: stack test
|
||||
shell: bash
|
||||
|
||||
- name: Run benches
|
||||
run: stack bench
|
||||
shell: bash
|
||||
```
|
||||
|
||||
### Tips and tricks
|
||||
@@ -387,8 +437,13 @@ In addition this script can also install `cabal-install`.
|
||||
|
||||
## Known users
|
||||
|
||||
* Github action [haskell/actions/setup](https://github.com/haskell/actions/tree/main/setup)
|
||||
* [vabal](https://github.com/Franciman/vabal)
|
||||
* Github actions:
|
||||
- [actions/virtual-environments](https://github.com/actions/virtual-environments)
|
||||
- [haskell/actions/setup](https://github.com/haskell/actions/tree/main/setup)
|
||||
* mirrors:
|
||||
- [sjtug](https://mirror.sjtu.edu.cn/docs/ghcup)
|
||||
* tools:
|
||||
- [vabal](https://github.com/Franciman/vabal)
|
||||
|
||||
## Known problems
|
||||
|
||||
|
||||
19
RELEASING.md
19
RELEASING.md
@@ -1,19 +0,0 @@
|
||||
# RELEASING
|
||||
|
||||
1. update `GHCup.Version` module. `ghcupURL` must only be updated if we change the `_toolRequirements` type or the YAML representation of it. The version of the YAML represents the change increments. `ghcUpVer` is the current application version.
|
||||
|
||||
2. Update version in ghcup.cabal
|
||||
|
||||
3. Add ChangeLog entry
|
||||
|
||||
4. Add/fix downloads in `ghcup-<ver>.yaml`, then verify with `ghcup-gen check -f ghcup-<ver>.yaml`
|
||||
|
||||
5. Commit and git push with tag. Wait for tests to succeed and release artifacts to build.
|
||||
|
||||
6. Download release artifacts and upload them `downloads.haskell.org/ghcup`
|
||||
|
||||
7. Add release artifacts to yaml file (see point 4.)
|
||||
|
||||
8. Upload the final `ghcup-<ver>.yaml` to `webhost.haskell.org/ghcup/data/`.
|
||||
|
||||
9. Update bootstrap-haskell and symlinks on `downloads.haskell.org/ghcup`
|
||||
@@ -11,21 +11,23 @@
|
||||
module Main where
|
||||
|
||||
import GHCup.Types
|
||||
import GHCup.Types.Optics
|
||||
import GHCup.Errors
|
||||
import GHCup.Platform
|
||||
import GHCup.Utils.Dirs
|
||||
import GHCup.Utils.Logger
|
||||
import GHCup.Types.JSON ( )
|
||||
|
||||
import Control.Monad.Trans.Reader ( runReaderT )
|
||||
import Control.Monad.IO.Class
|
||||
import Data.Char ( toLower )
|
||||
import Data.Maybe
|
||||
#if !MIN_VERSION_base(4,13,0)
|
||||
import Data.Semigroup ( (<>) )
|
||||
#endif
|
||||
import Options.Applicative hiding ( style )
|
||||
import Haskus.Utils.Variant.Excepts
|
||||
import System.Console.Pretty
|
||||
import System.Environment
|
||||
import System.Exit
|
||||
import System.IO ( stderr )
|
||||
import Text.Regex.Posix
|
||||
@@ -114,12 +116,14 @@ com = subparser
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
let loggerConfig = LoggerConfig { lcPrintDebug = True
|
||||
, colorOutter = T.hPutStr stderr
|
||||
, rawOutter = \_ -> pure ()
|
||||
no_color <- isJust <$> lookupEnv "NO_COLOR"
|
||||
let loggerConfig = LoggerConfig { lcPrintDebug = True
|
||||
, consoleOutter = T.hPutStr stderr
|
||||
, fileOutter = \_ -> pure ()
|
||||
, fancyColors = not no_color
|
||||
}
|
||||
dirs <- liftIO getAllDirs
|
||||
let leanAppstate = LeanAppState (Settings True False Never Curl True GHCupURL False) dirs defaultKeyBindings loggerConfig
|
||||
let leanAppstate = LeanAppState (Settings True False Never Curl True GHCupURL False GPGNone False) dirs defaultKeyBindings loggerConfig
|
||||
|
||||
pfreq <- (
|
||||
flip runReaderT leanAppstate . runE @'[NoCompatiblePlatform, NoCompatibleArch, DistroNotFound] $ platformRequest
|
||||
@@ -129,7 +133,7 @@ main = do
|
||||
flip runReaderT leanAppstate $ logError $ T.pack $ prettyShow e
|
||||
liftIO $ exitWith (ExitFailure 2)
|
||||
|
||||
let appstate = AppState (Settings True False Never Curl True GHCupURL False) dirs defaultKeyBindings (GHCupInfo mempty mempty mempty) pfreq loggerConfig
|
||||
let appstate = AppState (Settings True False Never Curl True GHCupURL False GPGNone False) dirs defaultKeyBindings (GHCupInfo mempty mempty mempty) pfreq loggerConfig
|
||||
|
||||
_ <- customExecParser (prefs showHelpOnError) (info (opts <**> helper) idm)
|
||||
>>= \Options {..} -> case optCommand of
|
||||
|
||||
@@ -15,6 +15,7 @@ import GHCup.Errors
|
||||
import GHCup.Types
|
||||
import GHCup.Types.Optics
|
||||
import GHCup.Utils
|
||||
import GHCup.Utils.Logger
|
||||
import GHCup.Utils.Version.QQ
|
||||
|
||||
import Codec.Archive
|
||||
@@ -229,6 +230,7 @@ validateTarballs (TarballFilter etool versionRegex) dls gt = do
|
||||
downloadAll ref dli = do
|
||||
r <- runResourceT
|
||||
. runE @'[DigestError
|
||||
, GPGError
|
||||
, DownloadFailed
|
||||
, UnknownArchive
|
||||
, ArchiveResult
|
||||
@@ -237,7 +239,7 @@ validateTarballs (TarballFilter etool versionRegex) dls gt = do
|
||||
case etool of
|
||||
Right (Just GHCup) -> do
|
||||
tmpUnpack <- lift mkGhcupTmpDir
|
||||
_ <- liftE $ download (_dlUri dli) (Just (_dlHash dli)) tmpUnpack Nothing False
|
||||
_ <- liftE $ download (_dlUri dli) Nothing (Just (_dlHash dli)) tmpUnpack Nothing False
|
||||
pure Nothing
|
||||
Right _ -> do
|
||||
p <- liftE $ downloadCached dli Nothing
|
||||
@@ -247,7 +249,7 @@ validateTarballs (TarballFilter etool versionRegex) dls gt = do
|
||||
$ p
|
||||
Left ShimGen -> do
|
||||
tmpUnpack <- lift mkGhcupTmpDir
|
||||
_ <- liftE $ download (_dlUri dli) (Just (_dlHash dli)) tmpUnpack Nothing False
|
||||
_ <- liftE $ download (_dlUri dli) Nothing (Just (_dlHash dli)) tmpUnpack Nothing False
|
||||
pure Nothing
|
||||
case r of
|
||||
VRight (Just basePath) -> do
|
||||
|
||||
@@ -13,9 +13,9 @@ module BrickMain where
|
||||
import GHCup
|
||||
import GHCup.Download
|
||||
import GHCup.Errors
|
||||
import GHCup.Types.Optics hiding ( getGHCupInfo )
|
||||
import GHCup.Types hiding ( LeanAppState(..) )
|
||||
import GHCup.Utils
|
||||
import GHCup.Utils.Logger
|
||||
import GHCup.Utils.Prelude ( decUTF8Safe )
|
||||
import GHCup.Utils.File
|
||||
|
||||
@@ -43,7 +43,6 @@ import Data.Vector ( Vector
|
||||
import Data.Versions hiding ( str )
|
||||
import Haskus.Utils.Variant.Excepts
|
||||
import Prelude hiding ( appendFile )
|
||||
import System.Environment
|
||||
import System.Exit
|
||||
import System.IO.Unsafe
|
||||
import Text.PrettyPrint.HughesPJClass ( prettyShow )
|
||||
@@ -429,6 +428,7 @@ install' _ (_, ListResult {..}) = do
|
||||
, BuildFailed
|
||||
, TagNotFound
|
||||
, DigestError
|
||||
, GPGError
|
||||
, DownloadFailed
|
||||
, DirNotEmpty
|
||||
, NoUpdate
|
||||
@@ -440,19 +440,19 @@ install' _ (_, ListResult {..}) = do
|
||||
case lTool of
|
||||
GHC -> do
|
||||
let vi = getVersionInfo lVer GHC dls
|
||||
liftE $ installGHCBin lVer Nothing $> vi
|
||||
liftE $ installGHCBin lVer Nothing False $> vi
|
||||
Cabal -> do
|
||||
let vi = getVersionInfo lVer Cabal dls
|
||||
liftE $ installCabalBin lVer Nothing $> vi
|
||||
liftE $ installCabalBin lVer Nothing False $> vi
|
||||
GHCup -> do
|
||||
let vi = snd <$> getLatest dls GHCup
|
||||
liftE $ upgradeGHCup Nothing False $> vi
|
||||
HLS -> do
|
||||
let vi = getVersionInfo lVer HLS dls
|
||||
liftE $ installHLSBin lVer Nothing $> vi
|
||||
liftE $ installHLSBin lVer Nothing False $> vi
|
||||
Stack -> do
|
||||
let vi = getVersionInfo lVer Stack dls
|
||||
liftE $ installStackBin lVer Nothing $> vi
|
||||
liftE $ installStackBin lVer Nothing False $> vi
|
||||
)
|
||||
>>= \case
|
||||
VRight vi -> do
|
||||
@@ -536,9 +536,10 @@ settings' :: IORef AppState
|
||||
{-# NOINLINE settings' #-}
|
||||
settings' = unsafePerformIO $ do
|
||||
dirs <- getAllDirs
|
||||
let loggerConfig = LoggerConfig { lcPrintDebug = False
|
||||
, colorOutter = \_ -> pure ()
|
||||
, rawOutter = \_ -> pure ()
|
||||
let loggerConfig = LoggerConfig { lcPrintDebug = False
|
||||
, consoleOutter = \_ -> pure ()
|
||||
, fileOutter = \_ -> pure ()
|
||||
, fancyColors = True
|
||||
}
|
||||
newIORef $ AppState (Settings { cache = True
|
||||
, noVerify = False
|
||||
@@ -547,6 +548,8 @@ settings' = unsafePerformIO $ do
|
||||
, verbose = False
|
||||
, urlSource = GHCupURL
|
||||
, noNetwork = False
|
||||
, gpgSetting = GPGNone
|
||||
, noColor = False
|
||||
, ..
|
||||
})
|
||||
dirs
|
||||
@@ -562,13 +565,11 @@ brickMain :: AppState
|
||||
brickMain s = do
|
||||
writeIORef settings' s
|
||||
|
||||
no_color <- isJust <$> lookupEnv "NO_COLOR"
|
||||
|
||||
eAppData <- getAppData (Just $ ghcupInfo s)
|
||||
case eAppData of
|
||||
Right ad ->
|
||||
defaultMain
|
||||
(app (defaultAttributes no_color) (dimAttributes no_color))
|
||||
(app (defaultAttributes (noColor $ settings s)) (dimAttributes (noColor $ settings s)))
|
||||
(BrickState ad
|
||||
defaultAppSettings
|
||||
(constructList ad defaultAppSettings Nothing)
|
||||
@@ -591,7 +592,7 @@ getGHCupInfo = do
|
||||
|
||||
r <-
|
||||
flip runReaderT settings
|
||||
. runE @'[JSONError , DownloadFailed , FileDoesNotExistError]
|
||||
. runE @'[DigestError, GPGError, JSONError , DownloadFailed , FileDoesNotExistError]
|
||||
$ liftE
|
||||
$ getDownloadsF
|
||||
|
||||
|
||||
@@ -57,6 +57,7 @@ import Data.Void
|
||||
import GHC.IO.Encoding
|
||||
import Haskus.Utils.Variant.Excepts
|
||||
import Language.Haskell.TH
|
||||
import Language.Haskell.TH.Syntax ( Quasi(qAddDependentFile) )
|
||||
import Options.Applicative hiding ( style )
|
||||
import Options.Applicative.Help.Pretty ( text )
|
||||
import Prelude hiding ( appendFile )
|
||||
@@ -86,21 +87,23 @@ import qualified Text.Megaparsec.Char as MPC
|
||||
data Options = Options
|
||||
{
|
||||
-- global options
|
||||
optVerbose :: Maybe Bool
|
||||
, optCache :: Maybe Bool
|
||||
, optUrlSource :: Maybe URI
|
||||
, optNoVerify :: Maybe Bool
|
||||
, optKeepDirs :: Maybe KeepDirs
|
||||
optVerbose :: Maybe Bool
|
||||
, optCache :: Maybe Bool
|
||||
, optUrlSource :: Maybe URI
|
||||
, optNoVerify :: Maybe Bool
|
||||
, optKeepDirs :: Maybe KeepDirs
|
||||
, optsDownloader :: Maybe Downloader
|
||||
, optNoNetwork :: Maybe Bool
|
||||
, optNoNetwork :: Maybe Bool
|
||||
, optGpg :: Maybe GPGSetting
|
||||
-- commands
|
||||
, optCommand :: Command
|
||||
, optCommand :: Command
|
||||
}
|
||||
|
||||
data Command
|
||||
= Install (Either InstallCommand InstallOptions)
|
||||
| InstallCabalLegacy InstallOptions
|
||||
| Set (Either SetCommand SetOptions)
|
||||
| UnSet UnsetCommand
|
||||
| List ListOptions
|
||||
| Rm (Either RmCommand RmOptions)
|
||||
| DInfo
|
||||
@@ -140,6 +143,7 @@ data InstallOptions = InstallOptions
|
||||
, instBindist :: Maybe URI
|
||||
, instSet :: Bool
|
||||
, isolateDir :: Maybe FilePath
|
||||
, forceInstall :: Bool
|
||||
}
|
||||
|
||||
data SetCommand = SetGHC SetOptions
|
||||
@@ -147,6 +151,11 @@ data SetCommand = SetGHC SetOptions
|
||||
| SetHLS SetOptions
|
||||
| SetStack SetOptions
|
||||
|
||||
data UnsetCommand = UnsetGHC UnsetOptions
|
||||
| UnsetCabal UnsetOptions
|
||||
| UnsetHLS UnsetOptions
|
||||
| UnsetStack UnsetOptions
|
||||
|
||||
-- a superset of ToolVersion
|
||||
data SetToolVersion = SetToolVersion GHCTargetVersion
|
||||
| SetToolTag Tag
|
||||
@@ -157,6 +166,10 @@ data SetOptions = SetOptions
|
||||
{ sToolVer :: SetToolVersion
|
||||
}
|
||||
|
||||
data UnsetOptions = UnsetOptions
|
||||
{ sToolVer :: Maybe Text -- target platform triple
|
||||
}
|
||||
|
||||
data ListOptions = ListOptions
|
||||
{ loTool :: Maybe Tool
|
||||
, lCriteria :: Maybe ListCriteria
|
||||
@@ -174,6 +187,7 @@ data RmOptions = RmOptions
|
||||
|
||||
|
||||
data CompileCommand = CompileGHC GHCCompileOptions
|
||||
| CompileHLS HLSCompileOptions
|
||||
|
||||
data ConfigCommand = ShowConfig | SetConfig String String | InitConfig
|
||||
|
||||
@@ -192,6 +206,18 @@ data GHCCompileOptions = GHCCompileOptions
|
||||
, isolateDir :: Maybe FilePath
|
||||
}
|
||||
|
||||
data HLSCompileOptions = HLSCompileOptions
|
||||
{ targetHLS :: Either Version GitBranch
|
||||
, jobs :: Maybe Int
|
||||
, setCompile :: Bool
|
||||
, ovewrwiteVer :: Maybe Version
|
||||
, isolateDir :: Maybe FilePath
|
||||
, cabalProject :: Maybe FilePath
|
||||
, cabalProjectLocal :: Maybe FilePath
|
||||
, patchDir :: Maybe FilePath
|
||||
, targetGHCs :: [ToolVersion]
|
||||
}
|
||||
|
||||
data UpgradeOpts = UpgradeInplace
|
||||
| UpgradeAt FilePath
|
||||
| UpgradeGHCupDir
|
||||
@@ -308,6 +334,13 @@ opts =
|
||||
<> hidden
|
||||
))
|
||||
<*> invertableSwitch "offline" 'o' False (help "Don't do any network calls, trying cached assets and failing if missing.")
|
||||
<*> optional (option
|
||||
(eitherReader gpgParser)
|
||||
( long "gpg"
|
||||
<> metavar "<strict|lax|none>"
|
||||
<> help
|
||||
"GPG verification (default: none)"
|
||||
))
|
||||
<*> com
|
||||
where
|
||||
parseUri s' =
|
||||
@@ -335,7 +368,7 @@ com =
|
||||
( Install
|
||||
<$> info
|
||||
(installParser <**> helper)
|
||||
( progDesc "Install or update GHC/cabal/HLS"
|
||||
( progDesc "Install or update GHC/cabal/HLS/stack"
|
||||
<> footerDoc (Just $ text installToolFooter)
|
||||
)
|
||||
)
|
||||
@@ -347,11 +380,19 @@ com =
|
||||
<> footerDoc (Just $ text setFooter)
|
||||
)
|
||||
)
|
||||
<> command
|
||||
"unset"
|
||||
(info
|
||||
(UnSet <$> unsetParser <**> helper)
|
||||
( progDesc "Unset currently active GHC/cabal version"
|
||||
<> footerDoc (Just $ text unsetFooter)
|
||||
)
|
||||
)
|
||||
<> command
|
||||
"rm"
|
||||
(info
|
||||
(Rm <$> rmParser <**> helper)
|
||||
( progDesc "Remove a GHC/cabal/HLS version"
|
||||
( progDesc "Remove a GHC/cabal/HLS/stack version"
|
||||
<> footerDoc (Just $ text rmFooter)
|
||||
)
|
||||
)
|
||||
@@ -451,20 +492,24 @@ com =
|
||||
installToolFooter = [s|Discussion:
|
||||
Installs GHC or cabal. When no command is given, installs GHC
|
||||
with the specified version/tag.
|
||||
It is recommended to always specify a subcommand (ghc/cabal/hls).|]
|
||||
It is recommended to always specify a subcommand (ghc/cabal/hls/stack).|]
|
||||
|
||||
setFooter :: String
|
||||
setFooter = [s|Discussion:
|
||||
Sets the currently active GHC or cabal version. When no command is given,
|
||||
defaults to setting GHC with the specified version/tag (if no tag
|
||||
is given, sets GHC to 'recommended' version).
|
||||
It is recommended to always specify a subcommand (ghc/cabal/hls).|]
|
||||
It is recommended to always specify a subcommand (ghc/cabal/hls/stack).|]
|
||||
|
||||
unsetFooter :: String
|
||||
unsetFooter = [s|Discussion:
|
||||
Unsets the currently active GHC or cabal version.|]
|
||||
|
||||
rmFooter :: String
|
||||
rmFooter = [s|Discussion:
|
||||
Remove the given GHC or cabal version. When no command is given,
|
||||
defaults to removing GHC with the specified version.
|
||||
It is recommended to always specify a subcommand (ghc/cabal/hls).|]
|
||||
It is recommended to always specify a subcommand (ghc/cabal/hls/stack).|]
|
||||
|
||||
changeLogFooter :: String
|
||||
changeLogFooter = [s|Discussion:
|
||||
@@ -545,7 +590,7 @@ installParser =
|
||||
( InstallHLS
|
||||
<$> info
|
||||
(installOpts (Just HLS) <**> helper)
|
||||
( progDesc "Install haskell-languge-server"
|
||||
( progDesc "Install haskell-language-server"
|
||||
<> footerDoc (Just $ text installHLSFooter)
|
||||
)
|
||||
)
|
||||
@@ -601,7 +646,7 @@ Examples:
|
||||
|
||||
installOpts :: Maybe Tool -> Parser InstallOptions
|
||||
installOpts tool =
|
||||
(\p (u, v) b is -> InstallOptions v p u b is)
|
||||
(\p (u, v) b is f -> InstallOptions v p u b is f)
|
||||
<$> optional
|
||||
(option
|
||||
(eitherReader platformParser)
|
||||
@@ -639,6 +684,9 @@ installOpts tool =
|
||||
<> help "install in an isolated dir instead of the default one"
|
||||
)
|
||||
)
|
||||
<*> switch
|
||||
(short 'f' <> long "force" <> help "Force install")
|
||||
|
||||
|
||||
|
||||
setParser :: Parser (Either SetCommand SetOptions)
|
||||
@@ -702,12 +750,74 @@ setParser =
|
||||
setHLSFooter = [s|Discussion:
|
||||
Sets the the current haskell-language-server version.|]
|
||||
|
||||
unsetParser :: Parser UnsetCommand
|
||||
unsetParser =
|
||||
(subparser
|
||||
( command
|
||||
"ghc"
|
||||
( UnsetGHC
|
||||
<$> info
|
||||
(unsetOpts <**> helper)
|
||||
( progDesc "Unset GHC version"
|
||||
<> footerDoc (Just $ text unsetGHCFooter)
|
||||
)
|
||||
)
|
||||
<> command
|
||||
"cabal"
|
||||
( UnsetCabal
|
||||
<$> info
|
||||
(unsetOpts <**> helper)
|
||||
( progDesc "Unset Cabal version"
|
||||
<> footerDoc (Just $ text unsetCabalFooter)
|
||||
)
|
||||
)
|
||||
<> command
|
||||
"hls"
|
||||
( UnsetHLS
|
||||
<$> info
|
||||
(unsetOpts <**> helper)
|
||||
( progDesc "Unset haskell-language-server version"
|
||||
<> footerDoc (Just $ text unsetHLSFooter)
|
||||
)
|
||||
)
|
||||
<> command
|
||||
"stack"
|
||||
( UnsetStack
|
||||
<$> info
|
||||
(unsetOpts <**> helper)
|
||||
( progDesc "Unset stack version"
|
||||
<> footerDoc (Just $ text unsetStackFooter)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
where
|
||||
unsetGHCFooter :: String
|
||||
unsetGHCFooter = [s|Discussion:
|
||||
Unsets the the current GHC version. That means there won't
|
||||
be a ~/.ghcup/bin/ghc anymore.|]
|
||||
|
||||
unsetCabalFooter :: String
|
||||
unsetCabalFooter = [s|Discussion:
|
||||
Unsets the the current Cabal version.|]
|
||||
|
||||
unsetStackFooter :: String
|
||||
unsetStackFooter = [s|Discussion:
|
||||
Unsets the the current Stack version.|]
|
||||
|
||||
unsetHLSFooter :: String
|
||||
unsetHLSFooter = [s|Discussion:
|
||||
Unsets the the current haskell-language-server version.|]
|
||||
|
||||
|
||||
setOpts :: Maybe Tool -> Parser SetOptions
|
||||
setOpts tool = SetOptions <$>
|
||||
(fromMaybe SetRecommended <$>
|
||||
optional (setVersionArgument (Just ListInstalled) tool))
|
||||
|
||||
unsetOpts :: Parser UnsetOptions
|
||||
unsetOpts = UnsetOptions . fmap T.pack <$> optional (argument str (metavar "TRIPLE"))
|
||||
|
||||
listOpts :: Parser ListOptions
|
||||
listOpts =
|
||||
ListOptions
|
||||
@@ -798,6 +908,15 @@ compileP = subparser
|
||||
<> footerDoc (Just $ text compileFooter)
|
||||
)
|
||||
)
|
||||
<> command
|
||||
"hls"
|
||||
( CompileHLS
|
||||
<$> info
|
||||
(hlsCompileOpts <**> helper)
|
||||
( progDesc "Compile HLS from source"
|
||||
<> footerDoc (Just $ text compileHLSFooter)
|
||||
)
|
||||
)
|
||||
)
|
||||
where
|
||||
compileFooter = [s|Discussion:
|
||||
@@ -822,6 +941,14 @@ Examples:
|
||||
# build cross compiler
|
||||
ghcup compile ghc -j 4 -v 8.4.2 -b 8.2.2 -x armv7-unknown-linux-gnueabihf --config $(pwd)/build.mk -- --enable-unregisterised|]
|
||||
|
||||
compileHLSFooter = [s|Discussion:
|
||||
Compiles and installs the specified HLS version.
|
||||
The last argument is a list of GHC versions to compile for.
|
||||
These need to be available in PATH prior to compilation.
|
||||
|
||||
Examples:
|
||||
ghcup compile hls -v 1.4.0 -j 12 8.10.5 8.10.7 9.0.1|]
|
||||
|
||||
configP :: Parser ConfigCommand
|
||||
configP = subparser
|
||||
( command "init" initP
|
||||
@@ -1045,7 +1172,7 @@ ghcCompileOpts =
|
||||
(option
|
||||
str
|
||||
(short 'p' <> long "patchdir" <> metavar "PATCH_DIR" <> help
|
||||
"Absolute path to patch directory (applied in order, uses -p1)"
|
||||
"Absolute path to patch directory (applies all .patch and .diff files in order using -p1)"
|
||||
)
|
||||
)
|
||||
<*> optional
|
||||
@@ -1091,6 +1218,78 @@ ghcCompileOpts =
|
||||
)
|
||||
)
|
||||
|
||||
hlsCompileOpts :: Parser HLSCompileOptions
|
||||
hlsCompileOpts =
|
||||
HLSCompileOptions
|
||||
<$> ((Left <$> option
|
||||
(eitherReader
|
||||
(first (const "Not a valid version") . version . T.pack)
|
||||
)
|
||||
(short 'v' <> long "version" <> metavar "VERSION" <> help
|
||||
"The tool version to compile"
|
||||
)
|
||||
) <|>
|
||||
(Right <$> (GitBranch <$> option
|
||||
str
|
||||
(short 'g' <> long "git-ref" <> metavar "GIT_REFERENCE" <> help
|
||||
"The git commit/branch/ref to build from"
|
||||
) <*>
|
||||
optional (option str (short 'r' <> long "repository" <> metavar "GIT_REPOSITORY" <> help "The git repository to build from (defaults to GHC upstream)"))
|
||||
)))
|
||||
<*> optional
|
||||
(option
|
||||
(eitherReader (readEither @Int))
|
||||
(short 'j' <> long "jobs" <> metavar "JOBS" <> help
|
||||
"How many jobs to use for make"
|
||||
)
|
||||
)
|
||||
<*> flag
|
||||
False
|
||||
True
|
||||
(long "set" <> help
|
||||
"Set as active version after install"
|
||||
)
|
||||
<*> optional
|
||||
(option
|
||||
(eitherReader
|
||||
(first (const "Not a valid version") . version . T.pack)
|
||||
)
|
||||
(short 'o' <> long "overwrite-version" <> metavar "OVERWRITE_VERSION" <> help
|
||||
"Allows to overwrite the finally installed VERSION with a different one, e.g. when you build 8.10.4 with your own patches, you might want to set this to '8.10.4-p1'"
|
||||
)
|
||||
)
|
||||
<*> optional
|
||||
(option
|
||||
(eitherReader isolateParser)
|
||||
( short 'i'
|
||||
<> long "isolate"
|
||||
<> metavar "DIR"
|
||||
<> help "install in an isolated directory instead of the default one, no symlinks to this installation will be made"
|
||||
)
|
||||
)
|
||||
<*> optional
|
||||
(option
|
||||
str
|
||||
(long "cabal-project" <> metavar "CABAL_PROJECT" <> help
|
||||
"If relative, specifies the path to cabal.project inside the unpacked HLS tarball/checkout. If absolute, will copy the file over."
|
||||
)
|
||||
)
|
||||
<*> optional
|
||||
(option
|
||||
(eitherReader absolutePathParser)
|
||||
(long "cabal-project-local" <> metavar "CABAL_PROJECT_LOCAL" <> help
|
||||
"Absolute path to a cabal.project.local to be used for the build. Will be copied over."
|
||||
)
|
||||
)
|
||||
<*> optional
|
||||
(option
|
||||
(eitherReader absolutePathParser)
|
||||
(short 'p' <> long "patchdir" <> metavar "PATCH_DIR" <> help
|
||||
"Absolute path to patch directory (applies all .patch and .diff files in order using -p1)"
|
||||
)
|
||||
)
|
||||
<*> some (toolVersionArgument Nothing (Just GHC))
|
||||
|
||||
|
||||
toolVersionParser :: Parser ToolVersion
|
||||
toolVersionParser = verP' <|> toolP
|
||||
@@ -1106,9 +1305,13 @@ toolVersionParser = verP' <|> toolP
|
||||
toolVersionArgument :: Maybe ListCriteria -> Maybe Tool -> Parser ToolVersion
|
||||
toolVersionArgument criteria tool =
|
||||
argument (eitherReader toolVersionEither)
|
||||
(metavar "VERSION|TAG"
|
||||
(metavar (mv tool)
|
||||
<> completer (tagCompleter (fromMaybe GHC tool) [])
|
||||
<> foldMap (completer . versionCompleter criteria) tool)
|
||||
where
|
||||
mv (Just GHC) = "GHC_VERSION|TAG"
|
||||
mv (Just HLS) = "HLS_VERSION|TAG"
|
||||
mv _ = "VERSION|TAG"
|
||||
|
||||
|
||||
setVersionArgument :: Maybe ListCriteria -> Maybe Tool -> Parser SetToolVersion
|
||||
@@ -1135,12 +1338,13 @@ tagCompleter :: Tool -> [String] -> Completer
|
||||
tagCompleter tool add = listIOCompleter $ do
|
||||
dirs' <- liftIO getAllDirs
|
||||
let loggerConfig = LoggerConfig
|
||||
{ lcPrintDebug = False
|
||||
, colorOutter = mempty
|
||||
, rawOutter = mempty
|
||||
{ lcPrintDebug = False
|
||||
, consoleOutter = mempty
|
||||
, fileOutter = mempty
|
||||
, fancyColors = False
|
||||
}
|
||||
let appState = LeanAppState
|
||||
(Settings True False Never Curl False GHCupURL True)
|
||||
(Settings True False Never Curl False GHCupURL True GPGNone False)
|
||||
dirs'
|
||||
defaultKeyBindings
|
||||
loggerConfig
|
||||
@@ -1161,11 +1365,12 @@ versionCompleter :: Maybe ListCriteria -> Tool -> Completer
|
||||
versionCompleter criteria tool = listIOCompleter $ do
|
||||
dirs' <- liftIO getAllDirs
|
||||
let loggerConfig = LoggerConfig
|
||||
{ lcPrintDebug = False
|
||||
, colorOutter = mempty
|
||||
, rawOutter = mempty
|
||||
{ lcPrintDebug = False
|
||||
, consoleOutter = mempty
|
||||
, fileOutter = mempty
|
||||
, fancyColors = False
|
||||
}
|
||||
let settings = Settings True False Never Curl False GHCupURL True
|
||||
let settings = Settings True False Never Curl False GHCupURL True GPGNone False
|
||||
let leanAppState = LeanAppState
|
||||
settings
|
||||
dirs'
|
||||
@@ -1252,6 +1457,13 @@ downloaderParser s' | t == T.pack "curl" = Right Curl
|
||||
| otherwise = Left ("Unknown downloader value: " <> s')
|
||||
where t = T.toLower (T.pack s')
|
||||
|
||||
gpgParser :: String -> Either String GPGSetting
|
||||
gpgParser s' | t == T.pack "strict" = Right GPGStrict
|
||||
| t == T.pack "lax" = Right GPGLax
|
||||
| t == T.pack "none" = Right GPGNone
|
||||
| otherwise = Left ("Unknown gpg setting value: " <> s')
|
||||
where t = T.toLower (T.pack s')
|
||||
|
||||
|
||||
platformParser :: String -> Either String PlatformRequest
|
||||
platformParser s' = case MP.parse (platformP <* MP.eof) "" (T.pack s') of
|
||||
@@ -1310,8 +1522,14 @@ isolateParser f = case isValid f of
|
||||
True -> Right $ normalise f
|
||||
False -> Left "Please enter a valid filepath for isolate dir."
|
||||
|
||||
absolutePathParser :: FilePath -> Either String FilePath
|
||||
absolutePathParser f = case isValid f && isAbsolute f of
|
||||
True -> Right $ normalise f
|
||||
False -> Left "Please enter a valid absolute filepath."
|
||||
|
||||
toSettings :: Options -> IO (Settings, KeyBindings)
|
||||
toSettings options = do
|
||||
noColor <- isJust <$> lookupEnv "NO_COLOR"
|
||||
userConf <- runE @'[ JSONError ] ghcupConfigFile >>= \case
|
||||
VRight r -> pure r
|
||||
VLeft (V (JSONDecodeError e)) -> do
|
||||
@@ -1319,10 +1537,10 @@ toSettings options = do
|
||||
pure defaultUserSettings
|
||||
_ -> do
|
||||
die "Unexpected error!"
|
||||
pure $ mergeConf options userConf
|
||||
pure $ mergeConf options userConf noColor
|
||||
where
|
||||
mergeConf :: Options -> UserSettings -> (Settings, KeyBindings)
|
||||
mergeConf Options{..} UserSettings{..} =
|
||||
mergeConf :: Options -> UserSettings -> Bool -> (Settings, KeyBindings)
|
||||
mergeConf Options{..} UserSettings{..} noColor =
|
||||
let cache = fromMaybe (fromMaybe False uCache) optCache
|
||||
noVerify = fromMaybe (fromMaybe False uNoVerify) optNoVerify
|
||||
verbose = fromMaybe (fromMaybe False uVerbose) optVerbose
|
||||
@@ -1331,6 +1549,7 @@ toSettings options = do
|
||||
keyBindings = maybe defaultKeyBindings mergeKeys uKeyBindings
|
||||
urlSource = maybe (fromMaybe GHCupURL uUrlSource) OwnSource optUrlSource
|
||||
noNetwork = fromMaybe (fromMaybe False uNoNetwork) optNoNetwork
|
||||
gpgSetting = fromMaybe (fromMaybe GPGNone uGPGSetting) optGpg
|
||||
in (Settings {..}, keyBindings)
|
||||
#if defined(INTERNAL_DOWNLOADER)
|
||||
defaultDownloader = Internal
|
||||
@@ -1366,7 +1585,8 @@ updateSettings config settings = do
|
||||
verbose' = fromMaybe verbose uVerbose
|
||||
urlSource' = fromMaybe urlSource uUrlSource
|
||||
noNetwork' = fromMaybe noNetwork uNoNetwork
|
||||
in Settings cache' noVerify' keepDirs' downloader' verbose' urlSource' noNetwork'
|
||||
gpgSetting' = fromMaybe gpgSetting uGPGSetting
|
||||
in Settings cache' noVerify' keepDirs' downloader' verbose' urlSource' noNetwork' gpgSetting' noColor
|
||||
|
||||
upgradeOptsP :: Parser UpgradeOpts
|
||||
upgradeOptsP =
|
||||
@@ -1391,7 +1611,7 @@ describe_result = $( LitE . StringL <$>
|
||||
runIO (do
|
||||
CapturedProcess{..} <- do
|
||||
dirs <- liftIO getAllDirs
|
||||
let settings = AppState (Settings True False Never Curl False GHCupURL False)
|
||||
let settings = AppState (Settings True False Never Curl False GHCupURL False GPGNone False)
|
||||
dirs
|
||||
defaultKeyBindings
|
||||
flip runReaderT settings $ executeOut "git" ["describe"] Nothing
|
||||
@@ -1402,14 +1622,14 @@ describe_result = $( LitE . StringL <$>
|
||||
)
|
||||
|
||||
plan_json :: String
|
||||
plan_json = $( LitE . StringL <$>
|
||||
runIO (handleIO (\_ -> pure "") $ do
|
||||
plan_json = $( do
|
||||
(fp, c) <- runIO (handleIO (\_ -> pure ("", "")) $ do
|
||||
fp <- findPlanJson (ProjectRelativeToDir ".")
|
||||
c <- B.readFile fp
|
||||
(Just res) <- pure $ decodeStrict' @Value c
|
||||
pure $ T.unpack $ decUTF8Safe' $ encodePretty res
|
||||
)
|
||||
)
|
||||
pure (fp, T.unpack $ decUTF8Safe' $ encodePretty res))
|
||||
when (not . null $ fp ) $ qAddDependentFile fp
|
||||
pure . LitE . StringL $ c)
|
||||
|
||||
formatConfig :: UserSettings -> String
|
||||
formatConfig settings
|
||||
@@ -1471,17 +1691,19 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
|
||||
|
||||
-- logger interpreter
|
||||
logfile <- flip runReaderT dirs initGHCupFileLogging
|
||||
no_color <- isJust <$> lookupEnv "NO_COLOR"
|
||||
let loggerConfig = LoggerConfig
|
||||
{ lcPrintDebug = verbose settings
|
||||
, colorOutter = T.hPutStr stderr
|
||||
, rawOutter =
|
||||
, consoleOutter = T.hPutStr stderr
|
||||
, fileOutter =
|
||||
case optCommand of
|
||||
Nuke -> \_ -> pure ()
|
||||
_ -> T.appendFile logfile
|
||||
, fancyColors = not no_color
|
||||
}
|
||||
let leanAppstate = LeanAppState settings dirs keybindings loggerConfig
|
||||
let runLogger = flip runReaderT leanAppstate
|
||||
let siletRunLogger = flip runReaderT (leanAppstate { loggerConfig = loggerConfig { colorOutter = \_ -> pure () } } :: LeanAppState)
|
||||
let siletRunLogger = flip runReaderT (leanAppstate { loggerConfig = loggerConfig { consoleOutter = \_ -> pure () } } :: LeanAppState)
|
||||
|
||||
|
||||
-------------------------
|
||||
@@ -1501,7 +1723,7 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
|
||||
|
||||
ghcupInfo <-
|
||||
( flip runReaderT leanAppstate
|
||||
. runE @'[JSONError , DownloadFailed, FileDoesNotExistError]
|
||||
. runE @'[DigestError, GPGError, JSONError , DownloadFailed, FileDoesNotExistError]
|
||||
$ liftE
|
||||
$ getDownloadsF
|
||||
)
|
||||
@@ -1574,6 +1796,7 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
|
||||
, BuildFailed
|
||||
, TagNotFound
|
||||
, DigestError
|
||||
, GPGError
|
||||
, DownloadFailed
|
||||
, TarDirDoesNotExist
|
||||
, NextVerNotFound
|
||||
@@ -1606,6 +1829,11 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
|
||||
, NoToolVersionSet
|
||||
]
|
||||
|
||||
runUnsetGHC =
|
||||
runAppState
|
||||
. runE
|
||||
@'[ NotInstalled ]
|
||||
|
||||
let
|
||||
runLeanSetCabal =
|
||||
runLeanAppState
|
||||
@@ -1664,6 +1892,7 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
|
||||
@'[ AlreadyInstalled
|
||||
, BuildFailed
|
||||
, DigestError
|
||||
, GPGError
|
||||
, DownloadFailed
|
||||
, GHCupSetError
|
||||
, NoDownload
|
||||
@@ -1676,6 +1905,29 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
|
||||
, ArchiveResult
|
||||
]
|
||||
|
||||
let runCompileHLS =
|
||||
runAppState
|
||||
. runResourceT
|
||||
. runE
|
||||
@'[ AlreadyInstalled
|
||||
, BuildFailed
|
||||
, DigestError
|
||||
, GPGError
|
||||
, DownloadFailed
|
||||
, GHCupSetError
|
||||
, NoDownload
|
||||
, NotFoundInPATH
|
||||
, PatchFailed
|
||||
, UnknownArchive
|
||||
, TarDirDoesNotExist
|
||||
, TagNotFound
|
||||
, NextVerNotFound
|
||||
, NoToolVersionSet
|
||||
, NotInstalled
|
||||
, DirNotEmpty
|
||||
, ArchiveResult
|
||||
]
|
||||
|
||||
let
|
||||
runLeanWhereIs =
|
||||
-- Don't use runLeanAppState here, which is disabled on windows.
|
||||
@@ -1702,6 +1954,7 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
|
||||
. runResourceT
|
||||
. runE
|
||||
@'[ DigestError
|
||||
, GPGError
|
||||
, NoDownload
|
||||
, NoUpdate
|
||||
, FileDoesNotExistError
|
||||
@@ -1718,6 +1971,7 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
|
||||
, NoToolVersionSet
|
||||
, NoDownload
|
||||
, DigestError
|
||||
, GPGError
|
||||
, DownloadFailed
|
||||
, JSONError
|
||||
, FileDoesNotExistError
|
||||
@@ -1732,7 +1986,10 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
|
||||
(case instBindist of
|
||||
Nothing -> runInstTool instPlatform $ do
|
||||
(v, vi) <- liftE $ fromVersion instVer GHC
|
||||
liftE $ installGHCBin (_tvVersion v) isolateDir
|
||||
liftE $ installGHCBin
|
||||
(_tvVersion v)
|
||||
isolateDir
|
||||
forceInstall
|
||||
when instSet $ void $ liftE $ setGHC v SetGHCOnly
|
||||
pure vi
|
||||
Just uri -> do
|
||||
@@ -1740,9 +1997,10 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
|
||||
runInstTool' s'{ settings = settings {noVerify = True}} instPlatform $ do
|
||||
(v, vi) <- liftE $ fromVersion instVer GHC
|
||||
liftE $ installGHCBindist
|
||||
(DownloadInfo uri (Just $ RegexDir "ghc-.*") "")
|
||||
(_tvVersion v)
|
||||
isolateDir
|
||||
(DownloadInfo uri (Just $ RegexDir "ghc-.*") "")
|
||||
(_tvVersion v)
|
||||
isolateDir
|
||||
forceInstall
|
||||
when instSet $ void $ liftE $ setGHC v SetGHCOnly
|
||||
pure vi
|
||||
)
|
||||
@@ -1754,8 +2012,12 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
|
||||
pure ExitSuccess
|
||||
VLeft (V (AlreadyInstalled _ v)) -> do
|
||||
runLogger $ logWarn $
|
||||
"GHC ver " <> prettyVer v <> " already installed; if you really want to reinstall it, you may want to run 'ghcup rm ghc " <> prettyVer v <> "' first"
|
||||
"GHC ver " <> prettyVer v <> " already installed; if you really want to reinstall it, you may want to run 'ghcup install ghc --force " <> prettyVer v <> "'"
|
||||
pure ExitSuccess
|
||||
VLeft (V (DirNotEmpty fp)) -> do
|
||||
runLogger $ logWarn $
|
||||
"Install directory " <> T.pack fp <> " is not empty. Use 'ghcup install ghc --isolate " <> T.pack fp <> " --force ..." <> "' to install regardless."
|
||||
pure $ ExitFailure 3
|
||||
VLeft err@(V (BuildFailed tmpdir _)) -> do
|
||||
case keepDirs settings of
|
||||
Never -> runLogger $ (logError $ T.pack $ prettyShow err)
|
||||
@@ -1774,16 +2036,20 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
|
||||
(case instBindist of
|
||||
Nothing -> runInstTool instPlatform $ do
|
||||
(v, vi) <- liftE $ fromVersion instVer Cabal
|
||||
liftE $ installCabalBin (_tvVersion v) isolateDir
|
||||
liftE $ installCabalBin
|
||||
(_tvVersion v)
|
||||
isolateDir
|
||||
forceInstall
|
||||
pure vi
|
||||
Just uri -> do
|
||||
s' <- appState
|
||||
runInstTool' s'{ settings = settings { noVerify = True}} instPlatform $ do
|
||||
(v, vi) <- liftE $ fromVersion instVer Cabal
|
||||
liftE $ installCabalBindist
|
||||
(DownloadInfo uri Nothing "")
|
||||
(_tvVersion v)
|
||||
isolateDir
|
||||
liftE $ installCabalBindist
|
||||
(DownloadInfo uri Nothing "")
|
||||
(_tvVersion v)
|
||||
isolateDir
|
||||
forceInstall
|
||||
pure vi
|
||||
)
|
||||
>>= \case
|
||||
@@ -1794,8 +2060,12 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
|
||||
pure ExitSuccess
|
||||
VLeft (V (AlreadyInstalled _ v)) -> do
|
||||
runLogger $ logWarn $
|
||||
"Cabal ver " <> prettyVer v <> " already installed; if you really want to reinstall it, you may want to run 'ghcup rm cabal " <> prettyVer v <> "' first"
|
||||
"Cabal ver " <> prettyVer v <> " already installed; if you really want to reinstall it, you may want to run 'ghcup install cabal --force " <> prettyVer v <> "'"
|
||||
pure ExitSuccess
|
||||
VLeft (V (FileAlreadyExistsError fp)) -> do
|
||||
runLogger $ logWarn $
|
||||
"File " <> T.pack fp <> " already exists. Use 'ghcup install cabal --isolate " <> T.pack fp <> " --force ..." <> "' if you want to overwrite."
|
||||
pure $ ExitFailure 3
|
||||
VLeft e -> do
|
||||
runLogger $ do
|
||||
logError $ T.pack $ prettyShow e
|
||||
@@ -1806,16 +2076,20 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
|
||||
(case instBindist of
|
||||
Nothing -> runInstTool instPlatform $ do
|
||||
(v, vi) <- liftE $ fromVersion instVer HLS
|
||||
liftE $ installHLSBin (_tvVersion v) isolateDir
|
||||
liftE $ installHLSBin
|
||||
(_tvVersion v)
|
||||
isolateDir
|
||||
forceInstall
|
||||
pure vi
|
||||
Just uri -> do
|
||||
s' <- appState
|
||||
runInstTool' s'{ settings = settings { noVerify = True}} instPlatform $ do
|
||||
(v, vi) <- liftE $ fromVersion instVer HLS
|
||||
liftE $ installHLSBindist
|
||||
(DownloadInfo uri Nothing "")
|
||||
(_tvVersion v)
|
||||
isolateDir
|
||||
(DownloadInfo uri Nothing "")
|
||||
(_tvVersion v)
|
||||
isolateDir
|
||||
forceInstall
|
||||
pure vi
|
||||
)
|
||||
>>= \case
|
||||
@@ -1828,10 +2102,14 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
|
||||
runLogger $ logWarn $
|
||||
"HLS ver "
|
||||
<> prettyVer v
|
||||
<> " already installed; if you really want to reinstall it, you may want to run 'ghcup rm hls "
|
||||
<> " already installed; if you really want to reinstall it, you may want to run 'ghcup install hls --force "
|
||||
<> prettyVer v
|
||||
<> "' first"
|
||||
<> "'"
|
||||
pure ExitSuccess
|
||||
VLeft (V (FileAlreadyExistsError fp)) -> do
|
||||
runLogger $ logWarn $
|
||||
"File " <> T.pack fp <> " already exists. Use 'ghcup install hls --isolate " <> T.pack fp <> " --force ..." <> "' if you want to overwrite."
|
||||
pure $ ExitFailure 3
|
||||
VLeft e -> do
|
||||
runLogger $ do
|
||||
logError $ T.pack $ prettyShow e
|
||||
@@ -1842,16 +2120,20 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
|
||||
(case instBindist of
|
||||
Nothing -> runInstTool instPlatform $ do
|
||||
(v, vi) <- liftE $ fromVersion instVer Stack
|
||||
liftE $ installStackBin (_tvVersion v) isolateDir
|
||||
liftE $ installStackBin
|
||||
(_tvVersion v)
|
||||
isolateDir
|
||||
forceInstall
|
||||
pure vi
|
||||
Just uri -> do
|
||||
s' <- appState
|
||||
runInstTool' s'{ settings = settings { noVerify = True}} instPlatform $ do
|
||||
(v, vi) <- liftE $ fromVersion instVer Stack
|
||||
liftE $ installStackBindist
|
||||
(DownloadInfo uri Nothing "")
|
||||
(_tvVersion v)
|
||||
isolateDir
|
||||
(DownloadInfo uri Nothing "")
|
||||
(_tvVersion v)
|
||||
isolateDir
|
||||
forceInstall
|
||||
pure vi
|
||||
)
|
||||
>>= \case
|
||||
@@ -1862,8 +2144,12 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
|
||||
pure ExitSuccess
|
||||
VLeft (V (AlreadyInstalled _ v)) -> do
|
||||
runLogger $ logWarn $
|
||||
"Stack ver " <> prettyVer v <> " already installed; if you really want to reinstall it, you may want to run 'ghcup rm stack " <> prettyVer v <> "' first"
|
||||
"Stack ver " <> prettyVer v <> " already installed; if you really want to reinstall it, you may want to run 'ghcup install stack --force " <> prettyVer v <> "'"
|
||||
pure ExitSuccess
|
||||
VLeft (V (FileAlreadyExistsError fp)) -> do
|
||||
runLogger $ logWarn $
|
||||
"File " <> T.pack fp <> " already exists. Use 'ghcup install stack --isolate " <> T.pack fp <> " --force ..." <> "' if you want to overwrite."
|
||||
pure $ ExitFailure 3
|
||||
VLeft e -> do
|
||||
runLogger $ do
|
||||
logError $ T.pack $ prettyShow e
|
||||
@@ -2031,10 +2317,31 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
|
||||
Set (Left (SetHLS sopts)) -> setHLS' sopts
|
||||
Set (Left (SetStack sopts)) -> setStack' sopts
|
||||
|
||||
UnSet (UnsetGHC (UnsetOptions triple)) -> runUnsetGHC (unsetGHC triple)
|
||||
>>= \case
|
||||
VRight _ -> do
|
||||
runLogger $ logInfo "GHC successfully unset"
|
||||
pure ExitSuccess
|
||||
VLeft e -> do
|
||||
runLogger $ logError $ T.pack $ prettyShow e
|
||||
pure $ ExitFailure 14
|
||||
UnSet (UnsetCabal (UnsetOptions _)) -> do
|
||||
runAppState unsetCabal
|
||||
runLogger $ logInfo "Cabal successfully unset"
|
||||
pure ExitSuccess
|
||||
UnSet (UnsetHLS (UnsetOptions _)) -> do
|
||||
runAppState unsetHLS
|
||||
runLogger $ logInfo "HLS successfully unset"
|
||||
pure ExitSuccess
|
||||
UnSet (UnsetStack (UnsetOptions _)) -> do
|
||||
runAppState unsetStack
|
||||
runLogger $ logInfo "Stack successfully unset"
|
||||
pure ExitSuccess
|
||||
|
||||
List ListOptions {..} ->
|
||||
runListGHC (do
|
||||
l <- listVersions loTool lCriteria
|
||||
liftIO $ printListResult lRawFormat l
|
||||
liftIO $ printListResult no_color lRawFormat l
|
||||
pure ExitSuccess
|
||||
)
|
||||
|
||||
@@ -2056,6 +2363,53 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
|
||||
runLogger $ logError $ T.pack $ prettyShow e
|
||||
pure $ ExitFailure 8
|
||||
|
||||
Compile (CompileHLS HLSCompileOptions { .. }) -> do
|
||||
runCompileHLS (do
|
||||
case targetHLS of
|
||||
Left targetVer -> do
|
||||
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||
let vi = getVersionInfo targetVer HLS dls
|
||||
forM_ (_viPreCompile =<< vi) $ \msg -> do
|
||||
lift $ logInfo msg
|
||||
lift $ logInfo
|
||||
"...waiting for 5 seconds, you can still abort..."
|
||||
liftIO $ threadDelay 5000000 -- for compilation, give the user a sec to intervene
|
||||
Right _ -> pure ()
|
||||
ghcs <- liftE $ forM targetGHCs (\ghc -> fmap (_tvVersion . fst) . fromVersion (Just ghc) $ GHC)
|
||||
targetVer <- liftE $ compileHLS
|
||||
targetHLS
|
||||
ghcs
|
||||
jobs
|
||||
ovewrwiteVer
|
||||
isolateDir
|
||||
cabalProject
|
||||
cabalProjectLocal
|
||||
patchDir
|
||||
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||
let vi = getVersionInfo targetVer HLS dls
|
||||
when setCompile $ void $ liftE $
|
||||
setHLS targetVer
|
||||
pure (vi, targetVer)
|
||||
)
|
||||
>>= \case
|
||||
VRight (vi, tv) -> do
|
||||
runLogger $ logInfo
|
||||
"HLS successfully compiled and installed"
|
||||
forM_ (_viPostInstall =<< vi) $ \msg ->
|
||||
runLogger $ logInfo msg
|
||||
putStr (T.unpack $ prettyVer tv)
|
||||
pure ExitSuccess
|
||||
VLeft err@(V (BuildFailed tmpdir _)) -> do
|
||||
case keepDirs settings of
|
||||
Never -> runLogger $ logError $ T.pack $ prettyShow err
|
||||
_ -> runLogger $ (logError $ T.pack (prettyShow err) <> "\n" <>
|
||||
"Check the logs at " <> T.pack logsDir <> " and the build directory "
|
||||
<> T.pack tmpdir <> " for more clues." <> "\n" <>
|
||||
"Make sure to clean up " <> T.pack tmpdir <> " afterwards.")
|
||||
pure $ ExitFailure 9
|
||||
VLeft e -> do
|
||||
runLogger $ logError $ T.pack $ prettyShow e
|
||||
pure $ ExitFailure 9
|
||||
Compile (CompileGHC GHCCompileOptions { hadrian = True, crossTarget = Just _ }) -> do
|
||||
runLogger $ logError "Hadrian cross compile support is not yet implemented!"
|
||||
pure $ ExitFailure 9
|
||||
@@ -2098,8 +2452,12 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
|
||||
pure ExitSuccess
|
||||
VLeft (V (AlreadyInstalled _ v)) -> do
|
||||
runLogger $ logWarn $
|
||||
"GHC ver " <> prettyVer v <> " already installed; if you really want to reinstall it, you may want to run 'ghcup rm ghc " <> prettyVer v <> "' first"
|
||||
"GHC ver " <> prettyVer v <> " already installed; if you really want to reinstall it, you may want to run 'ghcup install ghc --force " <> prettyVer v <> "'"
|
||||
pure ExitSuccess
|
||||
VLeft (V (DirNotEmpty fp)) -> do
|
||||
runLogger $ logWarn $
|
||||
"Install directory " <> T.pack fp <> " is not empty. Use 'ghcup install ghc --isolate " <> T.pack fp <> " --force ..." <> "' to install regardless."
|
||||
pure $ ExitFailure 3
|
||||
VLeft err@(V (BuildFailed tmpdir _)) -> do
|
||||
case keepDirs settings of
|
||||
Never -> runLogger $ logError $ T.pack $ prettyShow err
|
||||
@@ -2454,9 +2812,8 @@ fromVersion' (SetToolTag t') tool =
|
||||
throwE $ TagNotFound t' tool
|
||||
|
||||
|
||||
printListResult :: Bool -> [ListResult] -> IO ()
|
||||
printListResult raw lr = do
|
||||
no_color <- isJust <$> lookupEnv "NO_COLOR"
|
||||
printListResult :: Bool -> Bool -> [ListResult] -> IO ()
|
||||
printListResult no_color raw lr = do
|
||||
|
||||
let
|
||||
color | raw || no_color = flip const
|
||||
|
||||
@@ -8,11 +8,6 @@ package ghcup
|
||||
tests: True
|
||||
flags: +tui
|
||||
|
||||
source-repository-package
|
||||
type: git
|
||||
location: https://github.com/bgamari/terminal-size
|
||||
tag: 34ea816bd63f75f800eedac12c6908c6f3736036
|
||||
|
||||
source-repository-package
|
||||
type: git
|
||||
location: https://github.com/hasufell/libarchive
|
||||
|
||||
9
data/build_mk/cross
Normal file
9
data/build_mk/cross
Normal file
@@ -0,0 +1,9 @@
|
||||
V=0
|
||||
BUILD_MAN = NO
|
||||
BUILD_SPHINX_HTML = NO
|
||||
BUILD_SPHINX_PDF = NO
|
||||
HADDOCK_DOCS = NO
|
||||
ifneq "$(BuildFlavour)" ""
|
||||
include mk/flavours/$(BuildFlavour).mk
|
||||
endif
|
||||
Stage1Only = YES
|
||||
8
data/build_mk/default
Normal file
8
data/build_mk/default
Normal file
@@ -0,0 +1,8 @@
|
||||
V=0
|
||||
BUILD_MAN = NO
|
||||
BUILD_SPHINX_HTML = NO
|
||||
BUILD_SPHINX_PDF = NO
|
||||
HADDOCK_DOCS = YES
|
||||
ifneq "$(BuildFlavour)" ""
|
||||
include mk/flavours/$(BuildFlavour).mk
|
||||
endif
|
||||
@@ -8,6 +8,10 @@ verbose: False
|
||||
keep-dirs: Errors # Always | Never | Errors
|
||||
# Which downloader to use
|
||||
downloader: Curl # Curl | Wget | Internal
|
||||
# whether to run in offline mode
|
||||
no-network: False
|
||||
# whether/how to do gpg verification
|
||||
gpg-setting: GPGNone # GPGStrict | GPGLax | GPGNone
|
||||
|
||||
# TUI key bindings,
|
||||
# see https://hackage.haskell.org/package/vty-5.31/docs/Graphics-Vty-Input-Events.html#t:Key
|
||||
@@ -72,7 +72,6 @@ toolRequirements:
|
||||
'( >= 7 && < 8 )':
|
||||
distroPKGs:
|
||||
- gcc
|
||||
- gcc-c++
|
||||
- gmp
|
||||
- gmp-devel
|
||||
- make
|
||||
@@ -83,7 +82,6 @@ toolRequirements:
|
||||
unknown_versioning:
|
||||
distroPKGs:
|
||||
- gcc
|
||||
- gcc-c++
|
||||
- gmp
|
||||
- gmp-devel
|
||||
- make
|
||||
@@ -96,7 +94,6 @@ toolRequirements:
|
||||
unknown_versioning:
|
||||
distroPKGs:
|
||||
- gcc
|
||||
- gcc-c++
|
||||
- gmp
|
||||
- gmp-devel
|
||||
- make
|
||||
@@ -111,14 +108,15 @@ toolRequirements:
|
||||
- binutils-gold
|
||||
- curl
|
||||
- gcc
|
||||
- g++
|
||||
- gmp-dev
|
||||
- ncurses-dev
|
||||
- libc-dev
|
||||
- libffi-dev
|
||||
- make
|
||||
- xz
|
||||
- tar
|
||||
- musl-dev
|
||||
- ncurses-dev
|
||||
- perl
|
||||
- tar
|
||||
- xz
|
||||
notes: ''
|
||||
Linux_UnknownLinux:
|
||||
unknown_versioning:
|
||||
@@ -1598,6 +1596,11 @@ ghcupDownloads:
|
||||
dlHash: f10941f16e4fbd98580ab5241b9271bb0851304560c4d5ca127e3b0e20e3076f
|
||||
viPostRemove: *ghc-post-remove
|
||||
viPreCompile: *ghc-pre-compile
|
||||
viPostInstall: &ghc-8105-post-install |
|
||||
GHC 8.10.5 and 8.10.6 have several issues on Darwin, e.g.
|
||||
https://gitlab.haskell.org/ghc/ghc/-/issues/19950
|
||||
Consider upgrading to 8.10.7 via
|
||||
ghcup install ghc --set 8.10.7
|
||||
viArch:
|
||||
A_64:
|
||||
Linux_Debian:
|
||||
@@ -1698,6 +1701,7 @@ ghcupDownloads:
|
||||
dlHash: 43afba72a533408b42c1492bd047b5e37e5f7204e41a5cedd3182cc841610ce9
|
||||
viPostRemove: *ghc-post-remove
|
||||
viPreCompile: *ghc-pre-compile
|
||||
viPostInstall: *ghc-8105-post-install
|
||||
viArch:
|
||||
A_64:
|
||||
Linux_Debian:
|
||||
@@ -2172,7 +2176,6 @@ ghcupDownloads:
|
||||
3.4.0.0:
|
||||
viTags:
|
||||
- Recommended
|
||||
- Latest
|
||||
viChangeLog: https://github.com/haskell/cabal/blob/master/release-notes/cabal-install-3.4.0.0.md
|
||||
viArch:
|
||||
A_64:
|
||||
@@ -2221,8 +2224,52 @@ ghcupDownloads:
|
||||
unknown_versioning:
|
||||
dlUri: https://downloads.haskell.org/~ghcup/unofficial-bindists/cabal/3.4.0.0/cabal-install-3.4.0.0-armv7-linux-bootstrapped.tar.xz
|
||||
dlHash: 16c0d1eaba24bed14f3e152970179a45d9f9bb5cc839b2c210ad06eb7d4826ed
|
||||
3.6.0.0:
|
||||
viTags:
|
||||
- Latest
|
||||
viChangeLog: https://github.com/haskell/cabal/blob/master/release-notes/cabal-install-3.6.0.0.md
|
||||
viArch:
|
||||
A_64:
|
||||
Linux_UnknownLinux:
|
||||
unknown_versioning:
|
||||
dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.6.0.0/cabal-install-3.6.0.0-x86_64-linux.tar.xz
|
||||
dlHash: bfcb7350966dafe95051b5fc9fcb989c5708ab9e78191e71fc04647061668a11
|
||||
Linux_Alpine:
|
||||
unknown_versioning:
|
||||
dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.6.0.0/cabal-install-3.6.0.0-x86_64-linux-alpine.tar.xz
|
||||
dlHash: 3203d71b7ee87fc9dce74b452ae07f420afe8817b5e6f84e54798442f4ccdda8
|
||||
Darwin:
|
||||
unknown_versioning:
|
||||
dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.6.0.0/cabal-install-3.6.0.0-x86_64-darwin.tar.xz
|
||||
dlHash: 8e1367a4a1fc86ff0fd82ee057320a7b974595ba7999457b42035467ba06190c
|
||||
FreeBSD:
|
||||
'( >= 12 && < 13 )':
|
||||
dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.6.0.0/cabal-install-3.6.0.0-x86_64-freebsd.tar.xz
|
||||
dlHash: 56b5b37396c16a29f164a6963f24bd88f09e1d37448542ed61a683325f0a868b
|
||||
'( >= 13 )':
|
||||
dlUri: https://downloads.haskell.org/~ghcup/unofficial-bindists/cabal/3.6.0.0/cabal-install-3.6.0.0-x86_64-freebsd13.tar.xz
|
||||
dlHash: a283aa498702a3e286aa08e004c2a389538cbb47ec7096a25682fb7d57f6bb7f
|
||||
Windows:
|
||||
unknown_versioning:
|
||||
dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.6.0.0/cabal-install-3.6.0.0-x86_64-windows.zip
|
||||
dlSubdir:
|
||||
dlHash: 8222b49b6eac3d06aaa390bc688f467e8f949a38943567f46246f8320fd72ded
|
||||
A_ARM64:
|
||||
Linux_UnknownLinux:
|
||||
unknown_versioning:
|
||||
dlUri: https://downloads.haskell.org/~cabal/cabal-install-3.6.0.0/cabal-install-3.6.0.0-aarch64-linux-deb10.tar.xz
|
||||
dlHash: 534f71cd4e1d9758dc73066cc5733c5838874710aeb3aa88541de6c6d042d9ec
|
||||
Darwin:
|
||||
unknown_versioning:
|
||||
dlUri: https://downloads.haskell.org/~ghcup/unofficial-bindists/cabal/3.6.0.0/cabal-install-3.6.0.0-aarch64-darwin-big-sur.tar.xz
|
||||
dlHash: 7acf740946d996ede835edf68887e6b2f1e16d1b95e94054d266463f38d136d9
|
||||
A_ARM:
|
||||
Linux_UnknownLinux:
|
||||
unknown_versioning:
|
||||
dlUri: https://downloads.haskell.org/~ghcup/unofficial-bindists/cabal/3.6.0.0/cabal-install-3.6.0.0-armv7-linux.tar.xz
|
||||
dlHash: 11b5ca042a8bf45971224f2127a3e9d6b803f09210042ca80a254bea06f01a2e
|
||||
GHCup:
|
||||
0.1.16.2:
|
||||
0.1.17:
|
||||
viTags:
|
||||
- Recommended
|
||||
- Latest
|
||||
@@ -2232,46 +2279,47 @@ ghcupDownloads:
|
||||
A_64:
|
||||
Linux_UnknownLinux:
|
||||
unknown_versioning: &ghcup-64
|
||||
dlUri: https://downloads.haskell.org/~ghcup/0.1.16.2/x86_64-linux-ghcup-0.1.16.2
|
||||
dlHash: d5e43b95ce1d42263376e414f7eb7c5dd440271c7c6cd9bad446fdeff3823893
|
||||
dlUri: https://downloads.haskell.org/~ghcup/0.1.17/x86_64-linux-ghcup-0.1.17
|
||||
dlHash: 1eaa33af4180f97edf02822d6d711ce618d9828fe9ebbf042d198fe6c1c9d153
|
||||
Darwin:
|
||||
unknown_versioning:
|
||||
dlUri: https://downloads.haskell.org/~ghcup/0.1.16.2/x86_64-apple-darwin-ghcup-0.1.16.2
|
||||
dlHash: a334620ccce7705211b2142882dde544003e6030af4b91a44c890542a90f879f
|
||||
dlUri: https://downloads.haskell.org/~ghcup/0.1.17/x86_64-apple-darwin-ghcup-0.1.17
|
||||
dlHash: a3d4ed12f8631c0537d8d9531cc5518bc6f90edcee3326e5d4e0efb72c8dfc6f
|
||||
FreeBSD:
|
||||
unknown_versioning:
|
||||
dlUri: https://downloads.haskell.org/~ghcup/0.1.16.2/x86_64-portbld-freebsd-ghcup-0.1.16.2
|
||||
dlHash: 92359592a5694375e53b22628920086bf4bbf0faff5be018a0ed3e745a6426a9
|
||||
dlUri: https://downloads.haskell.org/~ghcup/0.1.17/x86_64-portbld-freebsd-ghcup-0.1.17
|
||||
dlHash: 83012de837773f3aa26182c607c2da85ee6ff3b0092becb78907700f407a27fb
|
||||
Windows:
|
||||
unknown_versioning:
|
||||
dlUri: https://downloads.haskell.org/~ghcup/0.1.16.2/x86_64-mingw64-ghcup-0.1.16.2.exe
|
||||
dlHash: ec78872a84213968c490675127b9aad2285980b747c68207801ae824b98c7948
|
||||
dlUri: https://downloads.haskell.org/~ghcup/0.1.17/x86_64-mingw64-ghcup-0.1.17.exe
|
||||
dlHash: 40bda6050c800fa69af51d2e668426ca73b4179214bfeef329b795484991d258
|
||||
Linux_Alpine:
|
||||
unknown_versioning: *ghcup-64
|
||||
A_32:
|
||||
Linux_UnknownLinux:
|
||||
unknown_versioning: &ghcup-32
|
||||
dlUri: https://downloads.haskell.org/~ghcup/0.1.16.2/i386-linux-ghcup-0.1.16.2
|
||||
dlHash: 01968ca6decac7b6e8ba6e2c817870d3fa47289a6507e0c1ab563f7b6eec0e38
|
||||
dlUri: https://downloads.haskell.org/~ghcup/0.1.17/i386-linux-ghcup-0.1.17
|
||||
dlHash: d0f887b13a2c7a11477dc54cb90b446ef0ebe1d2a6bfbf60ccd4b37fc5de70cc
|
||||
Linux_Alpine:
|
||||
unknown_versioning: *ghcup-32
|
||||
A_ARM64:
|
||||
Linux_UnknownLinux:
|
||||
unknown_versioning:
|
||||
dlUri: https://downloads.haskell.org/~ghcup/0.1.16.2/aarch64-linux-ghcup-0.1.16.2
|
||||
dlHash: 0bdbfc724e0ddabb266156eea83c2c4e19c6ed79dd06db0c29b7d69df8d9fa8c
|
||||
dlUri: https://downloads.haskell.org/~ghcup/0.1.17/aarch64-linux-ghcup-0.1.17
|
||||
dlHash: be67cf8800ae305c5ba210b645f4fce8751763f3eac3db399f6efca145b7ab38
|
||||
Darwin:
|
||||
unknown_versioning:
|
||||
dlUri: https://downloads.haskell.org/~ghcup/0.1.16.2/aarch64-apple-darwin-ghcup-0.1.16.2
|
||||
dlHash: 8854e991a2ba1350abda59dab96ce50ae7729d1ce99399d67929ef31e90f1da5
|
||||
dlUri: https://downloads.haskell.org/~ghcup/0.1.17/aarch64-apple-darwin-ghcup-0.1.17
|
||||
dlHash: b1be8c55838bd0d972e42b02b71bdf47fbbf67be1456e0de2d7d346620538539
|
||||
A_ARM:
|
||||
Linux_UnknownLinux:
|
||||
unknown_versioning:
|
||||
dlUri: https://downloads.haskell.org/~ghcup/0.1.16.2/armv7-linux-ghcup-0.1.16.2
|
||||
dlHash: 983ebb5b584bfa600704216a63f94b40d36a02573834e90ef1042c8472d9ad57
|
||||
dlUri: https://downloads.haskell.org/~ghcup/0.1.17/armv7-linux-ghcup-0.1.17
|
||||
dlHash: fe54ded2fafff4f8d82e511229f257f4c3b87b14c796f9b5b0ea35c359c26cb0
|
||||
HLS:
|
||||
1.1.0:
|
||||
viTags: []
|
||||
viTags:
|
||||
- old
|
||||
viChangeLog: https://github.com/haskell/haskell-language-server/blob/master/ChangeLog.md#110
|
||||
viPostInstall: &hls-post-install |
|
||||
This is just the server part of your LSP configuration. Consult the README on how to
|
||||
@@ -2294,7 +2342,8 @@ ghcupDownloads:
|
||||
Linux_Alpine:
|
||||
unknown_versioning: *hls-110-64
|
||||
1.2.0:
|
||||
viTags: []
|
||||
viTags:
|
||||
- old
|
||||
viChangeLog: https://github.com/haskell/haskell-language-server/blob/master/ChangeLog.md#120
|
||||
viPostInstall: *hls-post-install
|
||||
viArch:
|
||||
@@ -2314,9 +2363,7 @@ ghcupDownloads:
|
||||
Linux_Alpine:
|
||||
unknown_versioning: *hls-120-64
|
||||
1.3.0:
|
||||
viTags:
|
||||
- Recommended
|
||||
- Latest
|
||||
viTags: []
|
||||
viChangeLog: https://github.com/haskell/haskell-language-server/blob/master/ChangeLog.md#130
|
||||
viPostInstall: *hls-post-install
|
||||
viArch:
|
||||
@@ -2335,6 +2382,50 @@ ghcupDownloads:
|
||||
dlHash: 46aac7be888e29a9907cf56698c1ce1475c148b5e6cc099513e9ef74a0520dcf
|
||||
Linux_Alpine:
|
||||
unknown_versioning: *hls-130-64
|
||||
1.4.0:
|
||||
viTags:
|
||||
- Recommended
|
||||
- Latest
|
||||
viChangeLog: https://github.com/haskell/haskell-language-server/blob/master/ChangeLog.md#140
|
||||
viPostInstall: *hls-post-install
|
||||
viSourceDL:
|
||||
dlUri: https://downloads.haskell.org/ghcup/src/haskell-language-server/1.4.0/haskell-language-server-1.4.0.tar.gz
|
||||
dlSubdir: haskell-language-server-1.4.0
|
||||
dlHash: c5d7dbf7fae9aa3ed2c1184b49e82d8ac623ca786494ef6602cfe11735d28db0
|
||||
viArch:
|
||||
A_64:
|
||||
Linux_UnknownLinux:
|
||||
unknown_versioning: &hls-140-64
|
||||
dlUri: https://github.com/haskell/haskell-language-server/releases/download/1.4.0/haskell-language-server-Linux-1.4.0.tar.gz
|
||||
dlHash: f93c114441911ccce55649702adc9553cb4c9f953c37878321d2806a3525fee8
|
||||
Darwin:
|
||||
unknown_versioning:
|
||||
dlUri: https://github.com/haskell/haskell-language-server/releases/download/1.4.0/haskell-language-server-macOS-1.4.0.tar.gz
|
||||
dlHash: a7f0ac6be93ffb08cc239e5f5fead99b061061825f99566c1be33ee60cab62a4
|
||||
FreeBSD:
|
||||
unknown_versioning:
|
||||
dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/haskell-language-server/1.4.0/haskell-language-server-freebsd-1.4.0.tar.gz
|
||||
dlHash: 6b2ad2398ed8c3964dea017e3d5e553b54c10ba1373d7653d2edd019854f4da2
|
||||
Windows:
|
||||
unknown_versioning:
|
||||
dlUri: https://github.com/haskell/haskell-language-server/releases/download/1.4.0/haskell-language-server-Windows-1.4.0.tar.gz
|
||||
dlHash: 0ec77cee750037b7a0ede817b46a913a702821f4098c6a858bcb686cb30f7efd
|
||||
Linux_Alpine:
|
||||
unknown_versioning: *hls-140-64
|
||||
A_ARM64:
|
||||
Linux_UnknownLinux:
|
||||
unknown_versioning:
|
||||
dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/haskell-language-server/1.4.0/haskell-language-server-linux-aarch64-1.4.0.tar.gz
|
||||
dlHash: 8ad97e2bf1c538e637edec194e1cd9939019955bb749cb470f34bbe5a067b001
|
||||
Darwin:
|
||||
unknown_versioning:
|
||||
dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/haskell-language-server/1.4.0/haskell-language-server-macOS-aarch64-1.4.0.tar.gz
|
||||
dlHash: 70c6fe38e987ba44c1e19173486c01f666ffb30a74cd5a7968296a5aba4c2dd0
|
||||
A_ARM:
|
||||
Linux_UnknownLinux:
|
||||
unknown_versioning:
|
||||
dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/haskell-language-server/1.4.0/haskell-language-server-linux-armv7-1.4.0.tar.gz
|
||||
dlHash: 4a921fbca06b02f3b1c0930cec5e65e9362b603e7715680ec7b150f18bd703d6
|
||||
Stack:
|
||||
2.5.1:
|
||||
viTags:
|
||||
@@ -1,5 +1,19 @@
|
||||
# Revision history for ghcup
|
||||
|
||||
## 0.1.17 -- 2021-09-20
|
||||
|
||||
* Add `--force` option to install/compile wrt [#210](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/210) by Arjun Kathuria
|
||||
* Implement compiling HLS from source wrt [#201](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/201)
|
||||
* Implement experimental GPG verification of the metadata file (see README) wrt [#263](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/236)
|
||||
* Add `ghcup unset` command wrt [#145](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/145)
|
||||
* Add `ghcup whereis bindir` etc wrt [#221](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/221)
|
||||
* Greatly reduce dependency footprint wrt [#212](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/212)
|
||||
* Add `ghcup --plan-json`
|
||||
* Improve `--patchdir` option for GHC compilation wrt [#226](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/226)
|
||||
* Try to improve logging and failure modes, especially during downloads
|
||||
* Add descriptive warnings when HLS and GHC versions are incompatible
|
||||
* Improve curl header parsing wrt [#213](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/213)
|
||||
|
||||
## 0.1.16.2 -- 2021-08-12
|
||||
|
||||
* Add isolated installations wrt [#141](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/141) by Arjun Kathuria
|
||||
21
docs/RELEASING.md
Normal file
21
docs/RELEASING.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# RELEASING
|
||||
|
||||
1. Update version in `ghcup.cabal` and `boostrap-haskell` (`ghver` variable at the top of the script)
|
||||
|
||||
2. Update `GHCup.Version` module. `ghcupURL` must only be updated if we change the `GHCupInfo` type or the YAML representation of it. The version of the YAML represents the change increments. `ghcUpVer` is the current application version, read from `ghcup.cabal`.
|
||||
|
||||
3. Add ChangeLog entry
|
||||
|
||||
4. Add/fix downloads in `ghcup-<ver>.yaml` (under `data/metadata`), then verify with `ghcup-gen check -f ghcup-<ver>.yaml` and possibly (example only) `ghcup-gen check-tarballs -f ghcup-<ver>.yaml -u 'ghc-8.10.7'`. Generally, new GHC/cabal/stack/hls versions are only added to the latest yaml file. New GHCup versions are added to all (great care must be taken here to not break the parser... e.g. ARM platforms don't parse in all older formats).
|
||||
|
||||
5. Commit and git push with tag. Wait for tests to succeed and release artifacts to build.
|
||||
|
||||
6. Download release artifacts and upload them `downloads.haskell.org/ghcup` along with checksum files (`sha256sum --tag * > SHA256SUMS && gpg --detach-sign -u <your-email> SHA256SUMS`)
|
||||
|
||||
7. Add ghcup release artifacts to ALL yaml files (see point 4.)
|
||||
|
||||
8. Upload the final `ghcup-<ver>.yaml` to `webhost.haskell.org/ghcup/data/`.
|
||||
|
||||
9. Update `bootstrap-haskell` and `bootstrap-haskell.ps1` to `webhost.haskell.org/ghcup/sh/`
|
||||
|
||||
10. Update the ghcup symlinks at `downloads.haskell.org/ghcup`
|
||||
2494
ghcup-0.0.7.yaml
2494
ghcup-0.0.7.yaml
File diff suppressed because it is too large
Load Diff
59
ghcup.cabal
59
ghcup.cabal
@@ -1,30 +1,33 @@
|
||||
cabal-version: 3.0
|
||||
name: ghcup
|
||||
version: 0.1.16.2
|
||||
license: LGPL-3.0-only
|
||||
license-file: LICENSE
|
||||
copyright: Julian Ospald 2020
|
||||
maintainer: hasufell@posteo.de
|
||||
author: Julian Ospald
|
||||
homepage: https://gitlab.haskell.org/haskell/ghcup-hs
|
||||
bug-reports: https://gitlab.haskell.org/haskell/ghcup-hs/issues
|
||||
synopsis: ghc toolchain installer
|
||||
cabal-version: 3.0
|
||||
name: ghcup
|
||||
version: 0.1.17
|
||||
license: LGPL-3.0-only
|
||||
license-file: LICENSE
|
||||
copyright: Julian Ospald 2020
|
||||
maintainer: hasufell@posteo.de
|
||||
author: Julian Ospald
|
||||
homepage: https://gitlab.haskell.org/haskell/ghcup-hs
|
||||
bug-reports: https://gitlab.haskell.org/haskell/ghcup-hs/issues
|
||||
synopsis: ghc toolchain installer
|
||||
description:
|
||||
A rewrite of the shell script ghcup, for providing
|
||||
a more stable user experience and exposing an API.
|
||||
|
||||
category: System
|
||||
build-type: Simple
|
||||
category: System
|
||||
build-type: Simple
|
||||
extra-doc-files:
|
||||
CHANGELOG.md
|
||||
config.yaml
|
||||
ghcup-0.0.4.yaml
|
||||
ghcup-0.0.5.yaml
|
||||
ghcup-0.0.6.yaml
|
||||
ghcup-0.0.7.yaml
|
||||
HACKING.md
|
||||
data/config.yaml
|
||||
data/metadata/ghcup-0.0.4.yaml
|
||||
data/metadata/ghcup-0.0.5.yaml
|
||||
data/metadata/ghcup-0.0.6.yaml
|
||||
docs/CHANGELOG.md
|
||||
docs/HACKING.md
|
||||
docs/RELEASING.md
|
||||
README.md
|
||||
RELEASING.md
|
||||
|
||||
extra-source-files:
|
||||
data/build_mk/cross
|
||||
data/build_mk/default
|
||||
|
||||
source-repository head
|
||||
type: git
|
||||
@@ -96,9 +99,9 @@ library
|
||||
, base16-bytestring >=0.1.1.6 && <1.1
|
||||
, binary ^>=0.8.6.0
|
||||
, bytestring ^>=0.10
|
||||
, Cabal
|
||||
, case-insensitive ^>=1.2.1.0
|
||||
, casing ^>=0.1.4.1
|
||||
, concurrent-output ^>=1.10.11
|
||||
, containers ^>=0.6
|
||||
, cryptohash-sha256 ^>=0.11.101.0
|
||||
, deepseq ^>=1.4.4.0
|
||||
@@ -107,6 +110,7 @@ library
|
||||
, filepath ^>=1.4.2.1
|
||||
, haskus-utils-types ^>=1.5
|
||||
, haskus-utils-variant >=3.0 && <3.2
|
||||
, HsYAML-aeson ^>=0.2.0.0
|
||||
, libarchive ^>=3.0.0.0
|
||||
, lzma-static ^>=5.2.5.3
|
||||
, megaparsec >=8.0.0 && <9.1
|
||||
@@ -132,7 +136,6 @@ library
|
||||
, vector ^>=0.12
|
||||
, versions >=4.0.1 && <5.1
|
||||
, word8 ^>=0.1.3
|
||||
, HsYAML-aeson ^>=0.2.0.0
|
||||
, zlib ^>=0.6.2.2
|
||||
|
||||
if (flag(internal-downloader) && !os(windows))
|
||||
@@ -154,7 +157,11 @@ library
|
||||
, Win32 ^>=2.10
|
||||
|
||||
else
|
||||
other-modules: GHCup.Utils.File.Posix
|
||||
other-modules:
|
||||
GHCup.Utils.File.Posix
|
||||
System.Console.Terminal.Common
|
||||
System.Console.Terminal.Posix
|
||||
|
||||
build-depends:
|
||||
, bz2 >=0.5.0.5 && <1.1
|
||||
, unix ^>=2.7
|
||||
@@ -194,6 +201,7 @@ executable ghcup
|
||||
, filepath ^>=1.4.2.1
|
||||
, ghcup
|
||||
, haskus-utils-variant >=3.0 && <3.2
|
||||
, HsYAML-aeson ^>=0.2.0.0
|
||||
, libarchive ^>=3.0.0.0
|
||||
, megaparsec >=8.0.0 && <9.1
|
||||
, mtl ^>=2.2
|
||||
@@ -208,7 +216,6 @@ executable ghcup
|
||||
, uri-bytestring ^>=0.3.2.2
|
||||
, utf8-string ^>=1.0
|
||||
, versions >=4.0.1 && <5.1
|
||||
, HsYAML-aeson ^>=0.2.0.0
|
||||
|
||||
if flag(internal-downloader)
|
||||
cpp-options: -DINTERNAL_DOWNLOADER
|
||||
@@ -256,6 +263,7 @@ executable ghcup-gen
|
||||
, filepath ^>=1.4.2.1
|
||||
, ghcup
|
||||
, haskus-utils-variant >=3.0 && <3.2
|
||||
, HsYAML-aeson ^>=0.2.0.0
|
||||
, libarchive ^>=3.0.0.0
|
||||
, mtl ^>=2.2
|
||||
, optics ^>=0.4
|
||||
@@ -268,7 +276,6 @@ executable ghcup-gen
|
||||
, text ^>=1.2.4.0
|
||||
, transformers ^>=0.5
|
||||
, versions >=4.0.1 && <5.1
|
||||
, HsYAML-aeson ^>=0.2.0.0
|
||||
|
||||
test-suite ghcup-test
|
||||
type: exitcode-stdio-1.0
|
||||
|
||||
513
lib/GHCup.hs
513
lib/GHCup.hs
@@ -34,6 +34,7 @@ import GHCup.Types.JSON ( )
|
||||
import GHCup.Types.Optics
|
||||
import GHCup.Utils
|
||||
import GHCup.Utils.File
|
||||
import GHCup.Utils.Logger
|
||||
import GHCup.Utils.Prelude
|
||||
import GHCup.Utils.String.QQ
|
||||
import GHCup.Utils.Version.QQ
|
||||
@@ -63,11 +64,17 @@ import Data.Text ( Text )
|
||||
import Data.Time.Clock
|
||||
import Data.Time.Format.ISO8601
|
||||
import Data.Versions
|
||||
import Distribution.Types.Version hiding ( Version )
|
||||
import Distribution.Types.PackageId
|
||||
import Distribution.Types.PackageDescription
|
||||
import Distribution.Types.GenericPackageDescription
|
||||
import Distribution.PackageDescription.Parsec
|
||||
import GHC.IO.Exception
|
||||
import Haskus.Utils.Variant.Excepts
|
||||
import Language.Haskell.TH
|
||||
import Language.Haskell.TH.Syntax ( Quasi(qAddDependentFile) )
|
||||
import Optics
|
||||
import Prelude hiding ( abs
|
||||
, readFile
|
||||
, writeFile
|
||||
)
|
||||
import Safe hiding ( at )
|
||||
@@ -82,6 +89,7 @@ import Text.PrettyPrint.HughesPJClass ( prettyShow )
|
||||
import Text.Regex.Posix
|
||||
|
||||
import qualified Crypto.Hash.SHA256 as SHA256
|
||||
import qualified Data.List.NonEmpty as NE
|
||||
import qualified Data.ByteString.Base16 as B16
|
||||
import qualified Data.ByteString as B
|
||||
import qualified Data.ByteString.Lazy as BL
|
||||
@@ -120,6 +128,7 @@ fetchToolBindist :: ( MonadFail m
|
||||
-> Maybe FilePath
|
||||
-> Excepts
|
||||
'[ DigestError
|
||||
, GPGError
|
||||
, DownloadFailed
|
||||
, NoDownload
|
||||
]
|
||||
@@ -147,6 +156,7 @@ fetchGHCSrc :: ( MonadFail m
|
||||
-> Maybe FilePath
|
||||
-> Excepts
|
||||
'[ DigestError
|
||||
, GPGError
|
||||
, DownloadFailed
|
||||
, NoDownload
|
||||
]
|
||||
@@ -183,10 +193,12 @@ installGHCBindist :: ( MonadFail m
|
||||
=> DownloadInfo -- ^ where/how to download
|
||||
-> Version -- ^ the version to install
|
||||
-> Maybe FilePath -- ^ isolated filepath if user passed any
|
||||
-> Bool -- ^ Force install
|
||||
-> Excepts
|
||||
'[ AlreadyInstalled
|
||||
, BuildFailed
|
||||
, DigestError
|
||||
, GPGError
|
||||
, DownloadFailed
|
||||
, NoDownload
|
||||
, NotInstalled
|
||||
@@ -197,15 +209,26 @@ installGHCBindist :: ( MonadFail m
|
||||
]
|
||||
m
|
||||
()
|
||||
installGHCBindist dlinfo ver isoFilepath = do
|
||||
installGHCBindist dlinfo ver isoFilepath forceInstall = do
|
||||
let tver = mkTVer ver
|
||||
|
||||
lift $ logDebug $ "Requested to install GHC with " <> prettyVer ver
|
||||
|
||||
case isoFilepath of
|
||||
-- we only care for already installed errors in regular (non-isolated) installs
|
||||
Nothing -> whenM (lift $ ghcInstalled tver) (throwE $ AlreadyInstalled GHC ver)
|
||||
_ -> pure ()
|
||||
regularGHCInstalled <- lift $ checkIfToolInstalled GHC ver
|
||||
|
||||
if
|
||||
| not forceInstall
|
||||
, regularGHCInstalled
|
||||
, Nothing <- isoFilepath -> do
|
||||
throwE $ AlreadyInstalled GHC ver
|
||||
|
||||
| forceInstall
|
||||
, regularGHCInstalled
|
||||
, Nothing <- isoFilepath -> do
|
||||
lift $ logInfo "Removing the currently installed GHC version first!"
|
||||
liftE $ rmGHCVer tver
|
||||
|
||||
| otherwise -> pure ()
|
||||
|
||||
-- download (or use cached version)
|
||||
dl <- liftE $ downloadCached dlinfo Nothing
|
||||
@@ -214,13 +237,13 @@ installGHCBindist dlinfo ver isoFilepath = do
|
||||
ghcdir <- lift $ ghcupGHCDir tver
|
||||
|
||||
toolchainSanityChecks
|
||||
|
||||
|
||||
case isoFilepath of
|
||||
Just isoDir -> do -- isolated install
|
||||
lift $ logInfo $ "isolated installing GHC to " <> T.pack isoDir
|
||||
liftE $ installPackedGHC dl (view dlSubdir dlinfo) isoDir ver
|
||||
liftE $ installPackedGHC dl (view dlSubdir dlinfo) isoDir ver forceInstall
|
||||
Nothing -> do -- regular install
|
||||
liftE $ installPackedGHC dl (view dlSubdir dlinfo) ghcdir ver
|
||||
liftE $ installPackedGHC dl (view dlSubdir dlinfo) ghcdir ver forceInstall
|
||||
|
||||
-- make symlinks & stuff when regular install,
|
||||
liftE $ postGHCInstall tver
|
||||
@@ -248,11 +271,13 @@ installPackedGHC :: ( MonadMask m
|
||||
, HasLog env
|
||||
, MonadIO m
|
||||
, MonadUnliftIO m
|
||||
, MonadFail m
|
||||
)
|
||||
=> FilePath -- ^ Path to the packed GHC bindist
|
||||
-> Maybe TarDir -- ^ Subdir of the archive
|
||||
-> FilePath -- ^ Path to install to
|
||||
-> Version -- ^ The GHC version
|
||||
-> Bool -- ^ Force install
|
||||
-> Excepts
|
||||
'[ BuildFailed
|
||||
, UnknownArchive
|
||||
@@ -260,10 +285,11 @@ installPackedGHC :: ( MonadMask m
|
||||
, DirNotEmpty
|
||||
, ArchiveResult
|
||||
] m ()
|
||||
installPackedGHC dl msubdir inst ver = do
|
||||
installPackedGHC dl msubdir inst ver forceInstall = do
|
||||
PlatformRequest {..} <- lift getPlatformReq
|
||||
|
||||
liftE $ installDestSanityCheck inst
|
||||
unless forceInstall
|
||||
(liftE $ installDestSanityCheck inst)
|
||||
|
||||
-- unpack
|
||||
tmpUnpack <- lift mkGhcupTmpDir
|
||||
@@ -274,7 +300,7 @@ installPackedGHC dl msubdir inst ver = do
|
||||
workdir <- maybe (pure tmpUnpack)
|
||||
(liftE . intoSubdir tmpUnpack)
|
||||
msubdir
|
||||
|
||||
|
||||
liftE $ runBuildAction tmpUnpack
|
||||
(Just inst)
|
||||
(installUnpackedGHC workdir inst ver)
|
||||
@@ -364,10 +390,12 @@ installGHCBin :: ( MonadFail m
|
||||
)
|
||||
=> Version -- ^ the version to install
|
||||
-> Maybe FilePath -- ^ isolated install filepath, if user passed any
|
||||
-> Bool -- ^ force install
|
||||
-> Excepts
|
||||
'[ AlreadyInstalled
|
||||
, BuildFailed
|
||||
, DigestError
|
||||
, GPGError
|
||||
, DownloadFailed
|
||||
, NoDownload
|
||||
, NotInstalled
|
||||
@@ -378,9 +406,9 @@ installGHCBin :: ( MonadFail m
|
||||
]
|
||||
m
|
||||
()
|
||||
installGHCBin ver isoFilepath = do
|
||||
installGHCBin ver isoFilepath forceInstall = do
|
||||
dlinfo <- liftE $ getDownloadInfo GHC ver
|
||||
installGHCBindist dlinfo ver isoFilepath
|
||||
installGHCBindist dlinfo ver isoFilepath forceInstall
|
||||
|
||||
|
||||
-- | Like 'installCabalBin', except takes the 'DownloadInfo' as
|
||||
@@ -400,10 +428,12 @@ installCabalBindist :: ( MonadMask m
|
||||
=> DownloadInfo
|
||||
-> Version
|
||||
-> Maybe FilePath -- ^ isolated install filepath, if user provides any.
|
||||
-> Bool -- ^ Force install
|
||||
-> Excepts
|
||||
'[ AlreadyInstalled
|
||||
, CopyError
|
||||
, DigestError
|
||||
, GPGError
|
||||
, DownloadFailed
|
||||
, NoDownload
|
||||
, NotInstalled
|
||||
@@ -414,25 +444,30 @@ installCabalBindist :: ( MonadMask m
|
||||
]
|
||||
m
|
||||
()
|
||||
installCabalBindist dlinfo ver isoFilepath = do
|
||||
installCabalBindist dlinfo ver isoFilepath forceInstall = do
|
||||
lift $ logDebug $ "Requested to install cabal version " <> prettyVer ver
|
||||
|
||||
PlatformRequest {..} <- lift getPlatformReq
|
||||
Dirs {..} <- lift getDirs
|
||||
|
||||
case isoFilepath of
|
||||
Nothing -> -- for regular install check if any previous versions installed
|
||||
whenM
|
||||
(lift (cabalInstalled ver) >>= \a -> liftIO $
|
||||
handleIO (\_ -> pure False)
|
||||
$ fmap (\x -> a && x)
|
||||
-- ignore when the installation is a legacy cabal (binary, not symlink)
|
||||
$ pathIsLink (binDir </> "cabal" <> exeExt)
|
||||
)
|
||||
(throwE $ AlreadyInstalled Cabal ver)
|
||||
-- check if we already have a regular cabal already installed
|
||||
regularCabalInstalled <- lift $ checkIfToolInstalled Cabal ver
|
||||
|
||||
_ -> pure () -- check isn't required in isolated installs
|
||||
if
|
||||
| not forceInstall
|
||||
, regularCabalInstalled
|
||||
, Nothing <- isoFilepath -> do
|
||||
throwE $ AlreadyInstalled Cabal ver
|
||||
|
||||
| forceInstall
|
||||
, regularCabalInstalled
|
||||
, Nothing <- isoFilepath -> do
|
||||
lift $ logInfo "Removing the currently installed version first!"
|
||||
liftE $ rmCabalVer ver
|
||||
|
||||
| otherwise -> pure ()
|
||||
|
||||
|
||||
-- download (or use cached version)
|
||||
dl <- liftE $ downloadCached dlinfo Nothing
|
||||
|
||||
@@ -447,23 +482,24 @@ installCabalBindist dlinfo ver isoFilepath = do
|
||||
case isoFilepath of
|
||||
Just isoDir -> do -- isolated install
|
||||
lift $ logInfo $ "isolated installing Cabal to " <> T.pack isoDir
|
||||
liftE $ installCabalUnpacked workdir isoDir Nothing
|
||||
liftE $ installCabalUnpacked workdir isoDir Nothing forceInstall
|
||||
|
||||
Nothing -> do -- regular install
|
||||
liftE $ installCabalUnpacked workdir binDir (Just ver)
|
||||
liftE $ installCabalUnpacked workdir binDir (Just ver) forceInstall
|
||||
|
||||
-- create symlink if this is the latest version for regular installs
|
||||
cVers <- lift $ fmap rights getInstalledCabals
|
||||
let lInstCabal = headMay . reverse . sort $ cVers
|
||||
when (maybe True (ver >=) lInstCabal) $ liftE $ setCabal ver
|
||||
|
||||
-- | Install an unpacked cabal distribution.
|
||||
installCabalUnpacked :: (MonadReader env m, HasLog env, MonadCatch m, MonadIO m)
|
||||
|
||||
-- | Install an unpacked cabal distribution.Symbol
|
||||
installCabalUnpacked :: (MonadCatch m, HasLog env, MonadIO m, MonadReader env m)
|
||||
=> FilePath -- ^ Path to the unpacked cabal bindist (where the executable resides)
|
||||
-> FilePath -- ^ Path to install to
|
||||
-> Maybe Version -- ^ Nothing for isolated install
|
||||
-> Bool -- ^ Force Install
|
||||
-> Excepts '[CopyError, FileAlreadyExistsError] m ()
|
||||
installCabalUnpacked path inst mver' = do
|
||||
installCabalUnpacked path inst mver' forceInstall = do
|
||||
lift $ logInfo "Installing cabal"
|
||||
let cabalFile = "cabal"
|
||||
liftIO $ createDirRecursive' inst
|
||||
@@ -472,7 +508,8 @@ installCabalUnpacked path inst mver' = do
|
||||
<> exeExt
|
||||
let destPath = inst </> destFileName
|
||||
|
||||
liftE $ throwIfFileAlreadyExists destPath
|
||||
unless forceInstall -- Overwrite it when it IS a force install
|
||||
(liftE $ throwIfFileAlreadyExists destPath)
|
||||
|
||||
handleIO (throwE . CopyError . show) $ liftIO $ copyFile
|
||||
(path </> cabalFile <> exeExt)
|
||||
@@ -497,10 +534,12 @@ installCabalBin :: ( MonadMask m
|
||||
)
|
||||
=> Version
|
||||
-> Maybe FilePath -- isolated install Path, if user provided any
|
||||
-> Bool -- force install
|
||||
-> Excepts
|
||||
'[ AlreadyInstalled
|
||||
, CopyError
|
||||
, DigestError
|
||||
, GPGError
|
||||
, DownloadFailed
|
||||
, NoDownload
|
||||
, NotInstalled
|
||||
@@ -511,9 +550,9 @@ installCabalBin :: ( MonadMask m
|
||||
]
|
||||
m
|
||||
()
|
||||
installCabalBin ver isoFilepath = do
|
||||
installCabalBin ver isoFilepath forceInstall = do
|
||||
dlinfo <- liftE $ getDownloadInfo Cabal ver
|
||||
installCabalBindist dlinfo ver isoFilepath
|
||||
installCabalBindist dlinfo ver isoFilepath forceInstall
|
||||
|
||||
|
||||
-- | Like 'installHLSBin, except takes the 'DownloadInfo' as
|
||||
@@ -533,10 +572,12 @@ installHLSBindist :: ( MonadMask m
|
||||
=> DownloadInfo
|
||||
-> Version
|
||||
-> Maybe FilePath -- ^ isolated install path, if user passed any
|
||||
-> Bool -- ^ Force install
|
||||
-> Excepts
|
||||
'[ AlreadyInstalled
|
||||
, CopyError
|
||||
, DigestError
|
||||
, GPGError
|
||||
, DownloadFailed
|
||||
, NoDownload
|
||||
, NotInstalled
|
||||
@@ -547,20 +588,28 @@ installHLSBindist :: ( MonadMask m
|
||||
]
|
||||
m
|
||||
()
|
||||
installHLSBindist dlinfo ver isoFilepath = do
|
||||
installHLSBindist dlinfo ver isoFilepath forceInstall = do
|
||||
lift $ logDebug $ "Requested to install hls version " <> prettyVer ver
|
||||
|
||||
PlatformRequest {..} <- lift getPlatformReq
|
||||
Dirs {..} <- lift getDirs
|
||||
|
||||
case isoFilepath of
|
||||
Nothing ->
|
||||
-- we only check for already installed in regular (non-isolated) installs
|
||||
whenM (lift (hlsInstalled ver))
|
||||
(throwE $ AlreadyInstalled HLS ver)
|
||||
regularHLSInstalled <- lift $ checkIfToolInstalled HLS ver
|
||||
|
||||
_ -> pure ()
|
||||
if
|
||||
| not forceInstall
|
||||
, regularHLSInstalled
|
||||
, Nothing <- isoFilepath -> do -- regular install
|
||||
throwE $ AlreadyInstalled HLS ver
|
||||
|
||||
| forceInstall
|
||||
, regularHLSInstalled
|
||||
, Nothing <- isoFilepath -> do -- regular forced install
|
||||
lift $ logInfo "Removing the currently installed version of HLS before force installing!"
|
||||
liftE $ rmHLSVer ver
|
||||
|
||||
| otherwise -> pure ()
|
||||
|
||||
-- download (or use cached version)
|
||||
dl <- liftE $ downloadCached dlinfo Nothing
|
||||
|
||||
@@ -575,15 +624,12 @@ installHLSBindist dlinfo ver isoFilepath = do
|
||||
case isoFilepath of
|
||||
Just isoDir -> do
|
||||
lift $ logInfo $ "isolated installing HLS to " <> T.pack isoDir
|
||||
liftE $ installHLSUnpacked workdir isoDir Nothing
|
||||
liftE $ installHLSUnpacked workdir isoDir Nothing forceInstall
|
||||
|
||||
Nothing -> do
|
||||
liftE $ installHLSUnpacked workdir binDir (Just ver)
|
||||
liftE $ installHLSUnpacked workdir binDir (Just ver) forceInstall
|
||||
|
||||
-- create symlink if this is the latest version in a regular install
|
||||
hlsVers <- lift $ fmap rights getInstalledHLSs
|
||||
let lInstHLS = headMay . reverse . sort $ hlsVers
|
||||
when (maybe True (ver >=) lInstHLS) $ liftE $ setHLS ver
|
||||
liftE $ installHLSPostInst isoFilepath ver
|
||||
|
||||
|
||||
-- | Install an unpacked hls distribution.
|
||||
@@ -591,8 +637,9 @@ installHLSUnpacked :: (MonadReader env m, MonadFail m, HasLog env, MonadCatch m,
|
||||
=> FilePath -- ^ Path to the unpacked hls bindist (where the executable resides)
|
||||
-> FilePath -- ^ Path to install to
|
||||
-> Maybe Version -- ^ Nothing for isolated install
|
||||
-> Bool -- ^ is it a force install
|
||||
-> Excepts '[CopyError, FileAlreadyExistsError] m ()
|
||||
installHLSUnpacked path inst mver' = do
|
||||
installHLSUnpacked path inst mver' forceInstall = do
|
||||
lift $ logInfo "Installing HLS"
|
||||
liftIO $ createDirRecursive' inst
|
||||
|
||||
@@ -611,7 +658,8 @@ installHLSUnpacked path inst mver' = do
|
||||
let srcPath = path </> f
|
||||
let destPath = inst </> toF
|
||||
|
||||
liftE $ throwIfFileAlreadyExists destPath
|
||||
unless forceInstall -- if it is a force install, overwrite it.
|
||||
(liftE $ throwIfFileAlreadyExists destPath)
|
||||
|
||||
handleIO (throwE . CopyError . show) $ liftIO $ copyFile
|
||||
srcPath
|
||||
@@ -626,7 +674,8 @@ installHLSUnpacked path inst mver' = do
|
||||
srcWrapperPath = path </> wrapper <> exeExt
|
||||
destWrapperPath = inst </> toF
|
||||
|
||||
liftE $ throwIfFileAlreadyExists destWrapperPath
|
||||
unless forceInstall
|
||||
(liftE $ throwIfFileAlreadyExists destWrapperPath)
|
||||
|
||||
handleIO (throwE . CopyError . show) $ liftIO $ copyFile
|
||||
srcWrapperPath
|
||||
@@ -634,6 +683,21 @@ installHLSUnpacked path inst mver' = do
|
||||
|
||||
lift $ chmod_755 destWrapperPath
|
||||
|
||||
|
||||
installHLSPostInst :: (MonadReader env m, HasDirs env, HasLog env, MonadIO m, MonadCatch m, MonadMask m, MonadFail m, MonadUnliftIO m)
|
||||
=> Maybe FilePath
|
||||
-> Version
|
||||
-> Excepts '[NotInstalled] m ()
|
||||
installHLSPostInst isoFilepath ver =
|
||||
case isoFilepath of
|
||||
Just _ -> pure ()
|
||||
Nothing -> do
|
||||
-- create symlink if this is the latest version in a regular install
|
||||
hlsVers <- lift $ fmap rights getInstalledHLSs
|
||||
let lInstHLS = headMay . reverse . sort $ hlsVers
|
||||
when (maybe True (ver >=) lInstHLS) $ liftE $ setHLS ver
|
||||
|
||||
|
||||
-- | Installs hls binaries @haskell-language-server-\<ghcver\>@
|
||||
-- into @~\/.ghcup\/bin/@, as well as @haskell-languager-server-wrapper@.
|
||||
installHLSBin :: ( MonadMask m
|
||||
@@ -650,11 +714,13 @@ installHLSBin :: ( MonadMask m
|
||||
, MonadFail m
|
||||
)
|
||||
=> Version
|
||||
-> Maybe FilePath
|
||||
-> Maybe FilePath -- isolated install Dir (if any)
|
||||
-> Bool -- force install
|
||||
-> Excepts
|
||||
'[ AlreadyInstalled
|
||||
, CopyError
|
||||
, DigestError
|
||||
, GPGError
|
||||
, DownloadFailed
|
||||
, NoDownload
|
||||
, NotInstalled
|
||||
@@ -665,9 +731,174 @@ installHLSBin :: ( MonadMask m
|
||||
]
|
||||
m
|
||||
()
|
||||
installHLSBin ver isoFilepath = do
|
||||
installHLSBin ver isoFilepath forceInstall = do
|
||||
dlinfo <- liftE $ getDownloadInfo HLS ver
|
||||
installHLSBindist dlinfo ver isoFilepath
|
||||
installHLSBindist dlinfo ver isoFilepath forceInstall
|
||||
|
||||
|
||||
compileHLS :: ( MonadMask m
|
||||
, MonadCatch m
|
||||
, MonadReader env m
|
||||
, HasDirs env
|
||||
, HasSettings env
|
||||
, HasPlatformReq env
|
||||
, HasGHCupInfo env
|
||||
, HasLog env
|
||||
, MonadResource m
|
||||
, MonadIO m
|
||||
, MonadUnliftIO m
|
||||
, MonadFail m
|
||||
)
|
||||
=> Either Version GitBranch
|
||||
-> [Version]
|
||||
-> Maybe Int
|
||||
-> Maybe Version
|
||||
-> Maybe FilePath
|
||||
-> Maybe FilePath
|
||||
-> Maybe FilePath
|
||||
-> Maybe FilePath
|
||||
-> Excepts '[ NoDownload
|
||||
, GPGError
|
||||
, DownloadFailed
|
||||
, DigestError
|
||||
, UnknownArchive
|
||||
, TarDirDoesNotExist
|
||||
, ArchiveResult
|
||||
, BuildFailed
|
||||
, NotInstalled
|
||||
] m Version
|
||||
compileHLS targetHLS ghcs jobs ov isolateDir cabalProject cabalProjectLocal patchdir = do
|
||||
PlatformRequest { .. } <- lift getPlatformReq
|
||||
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||
Dirs { .. } <- lift getDirs
|
||||
|
||||
(workdir, tver) <- case targetHLS of
|
||||
-- unpack from version tarball
|
||||
Left tver -> do
|
||||
lift $ logDebug $ "Requested to compile: " <> prettyVer tver
|
||||
|
||||
-- download source tarball
|
||||
dlInfo <-
|
||||
preview (ix HLS % ix tver % viSourceDL % _Just) dls
|
||||
?? NoDownload
|
||||
dl <- liftE $ downloadCached dlInfo Nothing
|
||||
|
||||
-- unpack
|
||||
tmpUnpack <- lift mkGhcupTmpDir
|
||||
liftE $ unpackToDir tmpUnpack dl
|
||||
liftE $ catchWarn $ lEM @_ @'[ProcessError] $ darwinNotarization _rPlatform tmpUnpack
|
||||
|
||||
workdir <- maybe (pure tmpUnpack)
|
||||
(liftE . intoSubdir tmpUnpack)
|
||||
(view dlSubdir dlInfo)
|
||||
|
||||
pure (workdir, tver)
|
||||
|
||||
-- clone from git
|
||||
Right GitBranch{..} -> do
|
||||
tmpUnpack <- lift mkGhcupTmpDir
|
||||
let git args = execLogged "git" ("--no-pager":args) (Just tmpUnpack) "git" Nothing
|
||||
tver <- reThrowAll @_ @'[ProcessError] DownloadFailed $ do
|
||||
let rep = fromMaybe "https://github.com/haskell/haskell-language-server.git" repo
|
||||
lift $ logInfo $ "Fetching git repo " <> T.pack rep <> " at ref " <> T.pack ref <> " (this may take a while)"
|
||||
lEM $ git [ "init" ]
|
||||
lEM $ git [ "remote"
|
||||
, "add"
|
||||
, "origin"
|
||||
, fromString rep ]
|
||||
|
||||
let fetch_args =
|
||||
[ "fetch"
|
||||
, "--depth"
|
||||
, "1"
|
||||
, "--quiet"
|
||||
, "origin"
|
||||
, fromString ref ]
|
||||
lEM $ git fetch_args
|
||||
|
||||
lEM $ git [ "checkout", "FETCH_HEAD" ]
|
||||
(Just gpd) <- parseGenericPackageDescriptionMaybe <$> liftIO (B.readFile (tmpUnpack </> "haskell-language-server.cabal"))
|
||||
pure . (\c -> Version Nothing c [] Nothing)
|
||||
. NE.fromList . fmap (NE.fromList . (:[]) . digits . fromIntegral)
|
||||
. versionNumbers
|
||||
. pkgVersion
|
||||
. package
|
||||
. packageDescription
|
||||
$ gpd
|
||||
|
||||
liftE $ catchWarn $ lEM @_ @'[ProcessError] $ darwinNotarization _rPlatform tmpUnpack
|
||||
lift $ logInfo $ "Git version " <> T.pack ref <> " corresponds to HLS version " <> prettyVer tver
|
||||
|
||||
pure (tmpUnpack, tver)
|
||||
|
||||
-- the version that's installed may differ from the
|
||||
-- compiled version, so the user can overwrite it
|
||||
let installVer = fromMaybe tver ov
|
||||
|
||||
liftE $ runBuildAction
|
||||
workdir
|
||||
Nothing
|
||||
(reThrowAll @_ @'[PatchFailed, ProcessError, FileAlreadyExistsError, CopyError] @'[BuildFailed] (BuildFailed workdir) $ do
|
||||
let installDir = workdir </> "out"
|
||||
liftIO $ createDirRecursive' installDir
|
||||
|
||||
-- apply patches
|
||||
forM_ patchdir (\dir -> liftE $ applyPatches dir workdir)
|
||||
|
||||
-- set up project files
|
||||
cp <- case cabalProject of
|
||||
Just cp
|
||||
| isAbsolute cp -> do
|
||||
handleIO (throwE . CopyError . show) $ liftIO $ copyFile cp (workdir </> "cabal.project")
|
||||
pure "cabal.project"
|
||||
| otherwise -> pure (takeFileName cp)
|
||||
Nothing -> pure "cabal.project"
|
||||
forM_ cabalProjectLocal $ \cpl -> handleIO (throwE . CopyError . show) $ liftIO $ copyFile cpl (workdir </> cp <.> "local")
|
||||
|
||||
artifacts <- forM (sort ghcs) $ \ghc -> do
|
||||
let ghcInstallDir = installDir </> T.unpack (prettyVer ghc)
|
||||
liftIO $ createDirRecursive' installDir
|
||||
lift $ logInfo $ "Building HLS " <> prettyVer installVer <> " for GHC version " <> prettyVer ghc
|
||||
liftE $ lEM @_ @'[ProcessError] $
|
||||
execLogged "cabal" ( [ "v2-install"
|
||||
, "-w"
|
||||
, "ghc-" <> T.unpack (prettyVer ghc)
|
||||
, "--install-method=copy"
|
||||
] ++
|
||||
maybe [] (\j -> ["--jobs=" <> show j]) jobs ++
|
||||
[ "--overwrite-policy=always"
|
||||
, "--disable-profiling"
|
||||
, "--disable-tests"
|
||||
, "--enable-split-sections"
|
||||
, "--enable-executable-stripping"
|
||||
, "--enable-executable-static"
|
||||
, "--installdir=" <> ghcInstallDir
|
||||
, "--project-file=" <> cp
|
||||
, "exe:haskell-language-server"
|
||||
, "exe:haskell-language-server-wrapper"]
|
||||
)
|
||||
(Just workdir) "cabal" Nothing
|
||||
pure ghcInstallDir
|
||||
|
||||
forM_ artifacts $ \artifact -> do
|
||||
liftIO $ renameFile (artifact </> "haskell-language-server" <.> exeExt)
|
||||
(installDir </> "haskell-language-server-" <> takeFileName artifact <.> exeExt)
|
||||
liftIO $ renameFile (artifact </> "haskell-language-server-wrapper" <.> exeExt)
|
||||
(installDir </> "haskell-language-server-wrapper" <.> exeExt)
|
||||
liftIO $ rmPathForcibly artifact
|
||||
|
||||
case isolateDir of
|
||||
Just isoDir -> do
|
||||
lift $ logInfo $ "isolated installing HLS to " <> T.pack isoDir
|
||||
liftE $ installHLSUnpacked installDir isoDir Nothing True
|
||||
Nothing -> do
|
||||
liftE $ installHLSUnpacked installDir binDir (Just installVer) True
|
||||
)
|
||||
|
||||
liftE $ installHLSPostInst isolateDir installVer
|
||||
|
||||
pure installVer
|
||||
|
||||
|
||||
|
||||
-- | Installs stack into @~\/.ghcup\/bin/stack-\<ver\>@ and
|
||||
@@ -687,11 +918,13 @@ installStackBin :: ( MonadMask m
|
||||
, MonadFail m
|
||||
)
|
||||
=> Version
|
||||
-> Maybe FilePath
|
||||
-> Maybe FilePath -- ^ isolate install Dir (if any)
|
||||
-> Bool -- ^ Force install
|
||||
-> Excepts
|
||||
'[ AlreadyInstalled
|
||||
, CopyError
|
||||
, DigestError
|
||||
, GPGError
|
||||
, DownloadFailed
|
||||
, NoDownload
|
||||
, NotInstalled
|
||||
@@ -702,9 +935,9 @@ installStackBin :: ( MonadMask m
|
||||
]
|
||||
m
|
||||
()
|
||||
installStackBin ver isoFilepath = do
|
||||
installStackBin ver isoFilepath forceInstall = do
|
||||
dlinfo <- liftE $ getDownloadInfo Stack ver
|
||||
installStackBindist dlinfo ver isoFilepath
|
||||
installStackBindist dlinfo ver isoFilepath forceInstall
|
||||
|
||||
|
||||
-- | Like 'installStackBin', except takes the 'DownloadInfo' as
|
||||
@@ -723,11 +956,13 @@ installStackBindist :: ( MonadMask m
|
||||
)
|
||||
=> DownloadInfo
|
||||
-> Version
|
||||
-> Maybe FilePath
|
||||
-> Maybe FilePath -- ^ isolate install Dir (if any)
|
||||
-> Bool -- ^ Force install
|
||||
-> Excepts
|
||||
'[ AlreadyInstalled
|
||||
, CopyError
|
||||
, DigestError
|
||||
, GPGError
|
||||
, DownloadFailed
|
||||
, NoDownload
|
||||
, NotInstalled
|
||||
@@ -738,18 +973,27 @@ installStackBindist :: ( MonadMask m
|
||||
]
|
||||
m
|
||||
()
|
||||
installStackBindist dlinfo ver isoFilepath = do
|
||||
installStackBindist dlinfo ver isoFilepath forceInstall = do
|
||||
lift $ logDebug $ "Requested to install stack version " <> prettyVer ver
|
||||
|
||||
PlatformRequest {..} <- lift getPlatformReq
|
||||
Dirs {..} <- lift getDirs
|
||||
|
||||
case isoFilepath of
|
||||
Nothing -> -- check previous versions in case of regular installs
|
||||
whenM (lift (stackInstalled ver))
|
||||
(throwE $ AlreadyInstalled Stack ver)
|
||||
regularStackInstalled <- lift $ checkIfToolInstalled Stack ver
|
||||
|
||||
_ -> pure () -- don't do shit for isolates
|
||||
if
|
||||
| not forceInstall
|
||||
, regularStackInstalled
|
||||
, Nothing <- isoFilepath -> do
|
||||
throwE $ AlreadyInstalled Stack ver
|
||||
|
||||
| forceInstall
|
||||
, regularStackInstalled
|
||||
, Nothing <- isoFilepath -> do
|
||||
lift $ logInfo "Removing the currently installed version of Stack first!"
|
||||
liftE $ rmStackVer ver
|
||||
|
||||
| otherwise -> pure ()
|
||||
|
||||
-- download (or use cached version)
|
||||
dl <- liftE $ downloadCached dlinfo Nothing
|
||||
@@ -765,9 +1009,9 @@ installStackBindist dlinfo ver isoFilepath = do
|
||||
case isoFilepath of
|
||||
Just isoDir -> do -- isolated install
|
||||
lift $ logInfo $ "isolated installing Stack to " <> T.pack isoDir
|
||||
liftE $ installStackUnpacked workdir isoDir Nothing
|
||||
liftE $ installStackUnpacked workdir isoDir Nothing forceInstall
|
||||
Nothing -> do -- regular install
|
||||
liftE $ installStackUnpacked workdir binDir (Just ver)
|
||||
liftE $ installStackUnpacked workdir binDir (Just ver) forceInstall
|
||||
|
||||
-- create symlink if this is the latest version and a regular install
|
||||
sVers <- lift $ fmap rights getInstalledStacks
|
||||
@@ -780,8 +1024,9 @@ installStackUnpacked :: (MonadReader env m, HasLog env, MonadCatch m, MonadIO m)
|
||||
=> FilePath -- ^ Path to the unpacked stack bindist (where the executable resides)
|
||||
-> FilePath -- ^ Path to install to
|
||||
-> Maybe Version -- ^ Nothing for isolated installs
|
||||
-> Bool -- ^ Force install
|
||||
-> Excepts '[CopyError, FileAlreadyExistsError] m ()
|
||||
installStackUnpacked path inst mver' = do
|
||||
installStackUnpacked path inst mver' forceInstall = do
|
||||
lift $ logInfo "Installing stack"
|
||||
let stackFile = "stack"
|
||||
liftIO $ createDirRecursive' inst
|
||||
@@ -790,7 +1035,8 @@ installStackUnpacked path inst mver' = do
|
||||
<> exeExt
|
||||
destPath = inst </> destFileName
|
||||
|
||||
liftE $ throwIfFileAlreadyExists destPath
|
||||
unless forceInstall
|
||||
(liftE $ throwIfFileAlreadyExists destPath)
|
||||
|
||||
handleIO (throwE . CopyError . show) $ liftIO $ copyFile
|
||||
(path </> stackFile <> exeExt)
|
||||
@@ -867,6 +1113,8 @@ setGHC ver sghc = do
|
||||
-- create symlink for share dir
|
||||
when (isNothing . _tvTarget $ ver) $ lift $ symlinkShareDir ghcdir verS
|
||||
|
||||
when (sghc == SetGHCOnly) $ lift warnAboutHlsCompatibility
|
||||
|
||||
pure ver
|
||||
|
||||
where
|
||||
@@ -905,6 +1153,17 @@ setGHC ver sghc = do
|
||||
$ createDirectoryLink targetF fullF
|
||||
_ -> pure ()
|
||||
|
||||
unsetGHC :: ( MonadReader env m
|
||||
, HasDirs env
|
||||
, HasLog env
|
||||
, MonadThrow m
|
||||
, MonadFail m
|
||||
, MonadIO m
|
||||
, MonadMask m
|
||||
)
|
||||
=> Maybe Text
|
||||
-> Excepts '[NotInstalled] m ()
|
||||
unsetGHC = rmPlain
|
||||
|
||||
|
||||
-- | Set the @~\/.ghcup\/bin\/cabal@ symlink.
|
||||
@@ -912,7 +1171,6 @@ setCabal :: ( MonadMask m
|
||||
, MonadReader env m
|
||||
, HasDirs env
|
||||
, HasLog env
|
||||
, MonadThrow m
|
||||
, MonadFail m
|
||||
, MonadIO m
|
||||
, MonadUnliftIO m)
|
||||
@@ -936,18 +1194,24 @@ setCabal ver = do
|
||||
|
||||
pure ()
|
||||
|
||||
|
||||
unsetCabal :: ( MonadMask m
|
||||
, MonadReader env m
|
||||
, HasDirs env
|
||||
, MonadIO m)
|
||||
=> m ()
|
||||
unsetCabal = do
|
||||
Dirs {..} <- getDirs
|
||||
let cabalbin = binDir </> "cabal" <> exeExt
|
||||
hideError doesNotExistErrorType $ rmLink cabalbin
|
||||
|
||||
|
||||
-- | Set the haskell-language-server symlinks.
|
||||
setHLS :: ( MonadCatch m
|
||||
, MonadReader env m
|
||||
setHLS :: ( MonadReader env m
|
||||
, HasDirs env
|
||||
, HasLog env
|
||||
, MonadThrow m
|
||||
, MonadFail m
|
||||
, MonadIO m
|
||||
, MonadMask m
|
||||
, MonadFail m
|
||||
, MonadUnliftIO m
|
||||
)
|
||||
=> Version
|
||||
@@ -977,9 +1241,26 @@ setHLS ver = do
|
||||
|
||||
lift $ createLink destL wrapper
|
||||
|
||||
lift warnAboutHlsCompatibility
|
||||
|
||||
pure ()
|
||||
|
||||
|
||||
unsetHLS :: ( MonadMask m
|
||||
, MonadReader env m
|
||||
, HasDirs env
|
||||
, MonadIO m)
|
||||
=> m ()
|
||||
unsetHLS = do
|
||||
Dirs {..} <- getDirs
|
||||
let wrapper = binDir </> "haskell-language-server-wrapper" <> exeExt
|
||||
bins <- liftIO $ handleIO (\_ -> pure []) $ findFiles'
|
||||
binDir
|
||||
(MP.chunk "haskell-language-server-" <* pvp' <* MP.chunk (T.pack exeExt) <* MP.eof)
|
||||
forM_ bins (hideError doesNotExistErrorType . rmLink . (binDir </>))
|
||||
hideError doesNotExistErrorType $ rmLink wrapper
|
||||
|
||||
|
||||
-- | Set the @~\/.ghcup\/bin\/stack@ symlink.
|
||||
setStack :: ( MonadMask m
|
||||
, MonadReader env m
|
||||
@@ -1009,6 +1290,42 @@ setStack ver = do
|
||||
pure ()
|
||||
|
||||
|
||||
unsetStack :: ( MonadMask m
|
||||
, MonadReader env m
|
||||
, HasDirs env
|
||||
, MonadIO m)
|
||||
=> m ()
|
||||
unsetStack = do
|
||||
Dirs {..} <- getDirs
|
||||
let stackbin = binDir </> "stack" <> exeExt
|
||||
hideError doesNotExistErrorType $ rmLink stackbin
|
||||
|
||||
|
||||
-- | Warn if the installed and set HLS is not compatible with the installed and
|
||||
-- set GHC version.
|
||||
warnAboutHlsCompatibility :: ( MonadReader env m
|
||||
, HasDirs env
|
||||
, HasLog env
|
||||
, MonadThrow m
|
||||
, MonadCatch m
|
||||
, MonadIO m
|
||||
)
|
||||
=> m ()
|
||||
warnAboutHlsCompatibility = do
|
||||
supportedGHC <- hlsGHCVersions
|
||||
currentGHC <- fmap _tvVersion <$> ghcSet Nothing
|
||||
currentHLS <- hlsSet
|
||||
|
||||
case (currentGHC, currentHLS) of
|
||||
(Just gv, Just hv) | gv `notElem` supportedGHC -> do
|
||||
logWarn $
|
||||
"GHC " <> T.pack (prettyShow gv) <> " is not compatible with " <>
|
||||
"Haskell Language Server " <> T.pack (prettyShow hv) <> "." <> "\n" <>
|
||||
"Haskell IDE support may not work until this is fixed." <> "\n" <>
|
||||
"Install a different HLS version, or install and set one of the following GHCs:" <> "\n" <>
|
||||
T.pack (prettyShow supportedGHC)
|
||||
|
||||
_ -> return ()
|
||||
|
||||
------------------
|
||||
--[ List tools ]--
|
||||
@@ -1782,6 +2099,7 @@ compileGHC :: ( MonadMask m
|
||||
'[ AlreadyInstalled
|
||||
, BuildFailed
|
||||
, DigestError
|
||||
, GPGError
|
||||
, DownloadFailed
|
||||
, GHCupSetError
|
||||
, NoDownload
|
||||
@@ -1907,6 +2225,7 @@ compileGHC targetGhc ov bstrap jobs mbuildConfig patchdir aargs buildFlavour had
|
||||
(Just $ RegexDir "ghc-.*")
|
||||
ghcdir
|
||||
(tver ^. tvVersion)
|
||||
False -- not a force install, since we already overwrite when compiling.
|
||||
|
||||
liftIO $ B.writeFile (ghcdir </> ghcUpSrcBuiltFile) bmk
|
||||
|
||||
@@ -1922,26 +2241,12 @@ compileGHC targetGhc ov bstrap jobs mbuildConfig patchdir aargs buildFlavour had
|
||||
pure tver
|
||||
|
||||
where
|
||||
defaultConf = case targetGhc of
|
||||
Left (GHCTargetVersion (Just _) _) -> [s|
|
||||
V=0
|
||||
BUILD_MAN = NO
|
||||
BUILD_SPHINX_HTML = NO
|
||||
BUILD_SPHINX_PDF = NO
|
||||
HADDOCK_DOCS = NO
|
||||
ifneq "$(BuildFlavour)" ""
|
||||
include mk/flavours/$(BuildFlavour).mk
|
||||
endif
|
||||
Stage1Only = YES|]
|
||||
_ -> [s|
|
||||
V=0
|
||||
BUILD_MAN = NO
|
||||
BUILD_SPHINX_HTML = NO
|
||||
BUILD_SPHINX_PDF = NO
|
||||
HADDOCK_DOCS = YES
|
||||
ifneq "$(BuildFlavour)" ""
|
||||
include mk/flavours/$(BuildFlavour).mk
|
||||
endif|]
|
||||
defaultConf =
|
||||
let cross_mk = $(LitE . StringL <$> (qAddDependentFile "data/build_mk/cross" >> runIO (readFile "data/build_mk/cross")))
|
||||
default_mk = $(LitE . StringL <$> (qAddDependentFile "data/build_mk/default" >> runIO (readFile "data/build_mk/default")))
|
||||
in case targetGhc of
|
||||
Left (GHCTargetVersion (Just _) _) -> cross_mk
|
||||
_ -> default_mk
|
||||
|
||||
compileHadrianBindist :: ( MonadReader env m
|
||||
, HasDirs env
|
||||
@@ -2242,6 +2547,8 @@ upgradeGHCup :: ( MonadMask m
|
||||
-> Excepts
|
||||
'[ CopyError
|
||||
, DigestError
|
||||
, GPGError
|
||||
, GPGError
|
||||
, DownloadFailed
|
||||
, NoDownload
|
||||
, NoUpdate
|
||||
@@ -2258,7 +2565,7 @@ upgradeGHCup mtarget force' = do
|
||||
dli <- liftE $ getDownloadInfo GHCup latestVer
|
||||
tmp <- lift withGHCupTmpDir
|
||||
let fn = "ghcup" <> exeExt
|
||||
p <- liftE $ download (_dlUri dli) (Just (_dlHash dli)) tmp (Just fn) False
|
||||
p <- liftE $ download (_dlUri dli) Nothing (Just (_dlHash dli)) tmp (Just fn) False
|
||||
let destDir = takeDirectory destFile
|
||||
destFile = fromMaybe (binDir </> fn) mtarget
|
||||
lift $ logDebug $ "mkdir -p " <> T.pack destDir
|
||||
@@ -2367,6 +2674,22 @@ whereIsTool tool ver@GHCTargetVersion {..} = do
|
||||
currentRunningExecPath <- liftIO getExecutablePath
|
||||
liftIO $ canonicalizePath currentRunningExecPath
|
||||
|
||||
-- | Doesn't work for cross GHC.
|
||||
checkIfToolInstalled :: ( MonadIO m
|
||||
, MonadReader env m
|
||||
, HasDirs env
|
||||
, MonadCatch m) =>
|
||||
Tool ->
|
||||
Version ->
|
||||
m Bool
|
||||
|
||||
checkIfToolInstalled tool ver =
|
||||
case tool of
|
||||
Cabal -> cabalInstalled ver
|
||||
HLS -> hlsInstalled ver
|
||||
Stack -> stackInstalled ver
|
||||
GHC -> ghcInstalled $ mkTVer ver
|
||||
_ -> pure False
|
||||
|
||||
throwIfFileAlreadyExists :: ( MonadIO m ) =>
|
||||
FilePath ->
|
||||
|
||||
@@ -35,6 +35,7 @@ import GHCup.Types.Optics
|
||||
import GHCup.Types.JSON ( )
|
||||
import GHCup.Utils.Dirs
|
||||
import GHCup.Utils.File
|
||||
import GHCup.Utils.Logger
|
||||
import GHCup.Utils.Prelude
|
||||
import GHCup.Version
|
||||
|
||||
@@ -114,7 +115,7 @@ getDownloadsF :: ( FromJSONKey Tool
|
||||
, MonadMask m
|
||||
)
|
||||
=> Excepts
|
||||
'[JSONError , DownloadFailed , FileDoesNotExistError]
|
||||
'[DigestError, GPGError, JSONError , DownloadFailed , FileDoesNotExistError]
|
||||
m
|
||||
GHCupInfo
|
||||
getDownloadsF = do
|
||||
@@ -165,25 +166,24 @@ getBase :: ( MonadReader env m
|
||||
, MonadMask m
|
||||
)
|
||||
=> URI
|
||||
-> Excepts '[JSONError] m GHCupInfo
|
||||
-> Excepts '[GPGError, DigestError, JSONError, FileDoesNotExistError] m GHCupInfo
|
||||
getBase uri = do
|
||||
Settings { noNetwork } <- lift getSettings
|
||||
Settings { noNetwork, downloader } <- lift getSettings
|
||||
|
||||
-- try to download yaml... usually this writes it into cache dir,
|
||||
-- but in some cases not (e.g. when using file://), so we honour
|
||||
-- the return filepath, if any
|
||||
mYaml <- if noNetwork && view (uriSchemeL' % schemeBSL') uri /= "file" -- for file://, let it fall through
|
||||
then pure Nothing
|
||||
else handleIO (\e -> warnCache (displayException e) >> pure Nothing)
|
||||
. catchE @_ @_ @'[] (\e@(DownloadFailed _) -> warnCache (prettyShow e) >> pure Nothing)
|
||||
. reThrowAll @_ @_ @'[DownloadFailed] DownloadFailed
|
||||
else handleIO (\e -> lift (warnCache (displayException e) downloader) >> pure Nothing)
|
||||
. catchE @_ @_ @'[] (\e@(DownloadFailed _) -> lift (warnCache (prettyShow e) downloader) >> pure Nothing)
|
||||
. fmap Just
|
||||
. smartDl
|
||||
$ uri
|
||||
|
||||
-- if we didn't get a filepath from the download, use the cached yaml
|
||||
actualYaml <- maybe (lift $ yamlFromCache uri) pure mYaml
|
||||
yamlContents <- liftIO $ L.readFile actualYaml
|
||||
yamlContents <- liftIOException doesNotExistErrorType (FileDoesNotExistError actualYaml) $ liftIO $ L.readFile actualYaml
|
||||
lift $ logDebug $ "Decoding yaml at: " <> T.pack actualYaml
|
||||
|
||||
liftE
|
||||
@@ -201,9 +201,19 @@ getBase uri = do
|
||||
handleIO (\e -> logWarn $ "Couldn't remove file " <> T.pack efp <> ", error was: " <> T.pack (displayException e))
|
||||
(hideError doesNotExistErrorType $ rmFile efp)
|
||||
liftIO $ hideError doesNotExistErrorType $ setAccessTime fp (posixSecondsToUTCTime (fromIntegral @Int 0))
|
||||
warnCache s = do
|
||||
lift $ logWarn "Could not get download info, trying cached version (this may not be recent!)"
|
||||
lift $ logDebug $ "Error was: " <> T.pack s
|
||||
|
||||
warnCache :: (MonadReader env m, HasLog env, MonadMask m, MonadCatch m, MonadIO m) => FilePath -> Downloader -> m ()
|
||||
warnCache s downloader' = do
|
||||
let tryDownloder = case downloader' of
|
||||
Curl -> "Wget"
|
||||
Wget -> "Curl"
|
||||
#if defined(INTERNAL_DOWNLOADER)
|
||||
Internal -> "Curl"
|
||||
#endif
|
||||
logWarn $ "Could not get download info, trying cached version (this may not be recent!)" <> "\n" <>
|
||||
"If this problem persists, consider switching downloader via: " <> "\n " <>
|
||||
"ghcup config set downloader " <> tryDownloder
|
||||
logDebug $ "Error was: " <> T.pack s
|
||||
|
||||
-- First check if the json file is in the ~/.ghcup/cache dir
|
||||
-- and check it's access time. If it has been accessed within the
|
||||
@@ -224,6 +234,7 @@ getBase uri = do
|
||||
-> Excepts
|
||||
'[ DownloadFailed
|
||||
, DigestError
|
||||
, GPGError
|
||||
]
|
||||
m1
|
||||
FilePath
|
||||
@@ -235,7 +246,7 @@ getBase uri = do
|
||||
Dirs { cacheDir } <- lift getDirs
|
||||
|
||||
-- for local files, let's short-circuit and ignore access time
|
||||
if | scheme == "file" -> liftE $ download uri' Nothing cacheDir Nothing True
|
||||
if | scheme == "file" -> liftE $ download uri' Nothing Nothing cacheDir Nothing True
|
||||
| e -> do
|
||||
accessTime <- liftIO $ getAccessTime json_file
|
||||
|
||||
@@ -248,7 +259,7 @@ getBase uri = do
|
||||
where
|
||||
dlWithMod modTime json_file = do
|
||||
let (dir, fn) = splitFileName json_file
|
||||
f <- liftE $ download uri' Nothing dir (Just fn) True
|
||||
f <- liftE $ download uri' (Just $ over pathL' (<> ".sig") uri') Nothing dir (Just fn) True
|
||||
liftIO $ setModificationTime f modTime
|
||||
liftIO $ setAccessTime f modTime
|
||||
pure f
|
||||
@@ -312,16 +323,17 @@ download :: ( MonadReader env m
|
||||
, MonadIO m
|
||||
)
|
||||
=> URI
|
||||
-> Maybe URI -- ^ URI for gpg sig
|
||||
-> Maybe T.Text -- ^ expected hash
|
||||
-> FilePath -- ^ destination dir (ignored for file:// scheme)
|
||||
-> Maybe FilePath -- ^ optional filename
|
||||
-> Bool -- ^ whether to read an write etags
|
||||
-> Excepts '[DigestError , DownloadFailed] m FilePath
|
||||
download uri eDigest dest mfn etags
|
||||
-> Excepts '[DigestError , DownloadFailed, GPGError] m FilePath
|
||||
download uri gpgUri eDigest dest mfn etags
|
||||
| scheme == "https" = dl
|
||||
| scheme == "http" = dl
|
||||
| scheme == "file" = do
|
||||
let destFile' = T.unpack . decUTF8Safe $ path
|
||||
let destFile' = T.unpack . decUTF8Safe $ view pathL' uri
|
||||
lift $ logDebug $ "using local file: " <> T.pack destFile'
|
||||
forM_ eDigest (liftE . flip checkDigest destFile')
|
||||
pure destFile'
|
||||
@@ -330,115 +342,179 @@ download uri eDigest dest mfn etags
|
||||
where
|
||||
scheme = view (uriSchemeL' % schemeBSL') uri
|
||||
dl = do
|
||||
destFile <- liftE . reThrowAll @_ @_ @'[DownloadFailed] DownloadFailed $ getDestFile
|
||||
lift $ logInfo $ "downloading: " <> uri' <> " as file " <> T.pack destFile
|
||||
baseDestFile <- liftE . reThrowAll @_ @_ @'[DownloadFailed] DownloadFailed $ getDestFile uri mfn
|
||||
lift $ logInfo $ "downloading: " <> (decUTF8Safe . serializeURIRef') uri <> " as file " <> T.pack baseDestFile
|
||||
|
||||
-- destination dir must exist
|
||||
liftIO $ createDirRecursive' dest
|
||||
|
||||
|
||||
-- download
|
||||
flip onException
|
||||
(lift $ hideError doesNotExistErrorType $ recycleFile destFile)
|
||||
$ catchAllE @_ @'[ProcessError, DownloadFailed, UnsupportedScheme]
|
||||
(\e ->
|
||||
lift (hideError doesNotExistErrorType $ recycleFile destFile)
|
||||
>> (throwE . DownloadFailed $ e)
|
||||
(lift $ hideError doesNotExistErrorType $ recycleFile (tmpFile baseDestFile))
|
||||
$ catchAllE @_ @'[GPGError, ProcessError, DownloadFailed, UnsupportedScheme, DigestError] @'[DigestError, DownloadFailed, GPGError]
|
||||
(\e' -> do
|
||||
lift $ hideError doesNotExistErrorType $ recycleFile (tmpFile baseDestFile)
|
||||
case e' of
|
||||
V e@GPGError {} -> throwE e
|
||||
V e@DigestError {} -> throwE e
|
||||
_ -> throwE (DownloadFailed e')
|
||||
) $ do
|
||||
Settings{ downloader, noNetwork } <- lift getSettings
|
||||
Settings{ downloader, noNetwork, gpgSetting } <- lift getSettings
|
||||
when noNetwork $ throwE (DownloadFailed (V NoNetwork :: V '[NoNetwork]))
|
||||
case downloader of
|
||||
Curl -> do
|
||||
o' <- liftIO getCurlOpts
|
||||
if etags
|
||||
then do
|
||||
dh <- liftIO $ emptySystemTempFile "curl-header"
|
||||
flip finally (try @_ @SomeException $ rmFile dh) $
|
||||
flip finally (try @_ @SomeException $ rmFile (destFile <.> "tmp")) $ do
|
||||
metag <- lift $ readETag destFile
|
||||
liftE $ lEM @_ @'[ProcessError] $ exec "curl"
|
||||
(o' ++ (if etags then ["--dump-header", dh] else [])
|
||||
++ maybe [] (\t -> ["-H", "If-None-Match: " <> T.unpack t]) metag
|
||||
++ ["-fL", "-o", destFile <.> "tmp", T.unpack uri']) Nothing Nothing
|
||||
headers <- liftIO $ T.readFile dh
|
||||
|
||||
-- this nonsense is necessary, because some older versions of curl would overwrite
|
||||
-- the destination file when 304 is returned
|
||||
case fmap T.words . listToMaybe . fmap T.strip . T.lines . getLastHeader $ headers of
|
||||
Just (http':sc:_)
|
||||
| sc == "304"
|
||||
, T.pack "HTTP" `T.isPrefixOf` http' -> lift $ logDebug "Status code was 304, not overwriting"
|
||||
| T.pack "HTTP" `T.isPrefixOf` http' -> do
|
||||
lift $ logDebug $ "Status code was " <> sc <> ", overwriting"
|
||||
liftIO $ copyFile (destFile <.> "tmp") destFile
|
||||
_ -> liftE $ throwE @_ @'[DownloadFailed] (DownloadFailed (toVariantAt @0 (MalformedHeaders headers)
|
||||
:: V '[MalformedHeaders]))
|
||||
|
||||
lift $ writeEtags destFile (parseEtags headers)
|
||||
else
|
||||
liftE $ lEM @_ @'[ProcessError] $ exec "curl"
|
||||
(o' ++ ["-fL", "-o", destFile, T.unpack uri']) Nothing Nothing
|
||||
Wget -> do
|
||||
destFileTemp <- liftIO $ emptySystemTempFile "wget-tmp"
|
||||
flip finally (try @_ @SomeException $ rmFile destFileTemp) $ do
|
||||
o' <- liftIO getWgetOpts
|
||||
if etags
|
||||
then do
|
||||
metag <- lift $ readETag destFile
|
||||
let opts = o' ++ maybe [] (\t -> ["--header", "If-None-Match: " <> T.unpack t]) metag
|
||||
++ ["-q", "-S", "-O", destFileTemp , T.unpack uri']
|
||||
CapturedProcess {_exitCode, _stdErr} <- lift $ executeOut "wget" opts Nothing
|
||||
case _exitCode of
|
||||
ExitSuccess -> do
|
||||
liftIO $ copyFile destFileTemp destFile
|
||||
lift $ writeEtags destFile (parseEtags (decUTF8Safe' _stdErr))
|
||||
ExitFailure i'
|
||||
| i' == 8
|
||||
, Just _ <- find (T.pack "304 Not Modified" `T.isInfixOf`) . T.lines . decUTF8Safe' $ _stdErr
|
||||
-> do
|
||||
lift $ logDebug "Not modified, skipping download"
|
||||
lift $ writeEtags destFile (parseEtags (decUTF8Safe' _stdErr))
|
||||
| otherwise -> throwE (NonZeroExit i' "wget" opts)
|
||||
else do
|
||||
let opts = o' ++ ["-O", destFileTemp , T.unpack uri']
|
||||
liftE $ lEM @_ @'[ProcessError] $ exec "wget" opts Nothing Nothing
|
||||
liftIO $ copyFile destFileTemp destFile
|
||||
downloadAction <- case downloader of
|
||||
Curl -> do
|
||||
o' <- liftIO getCurlOpts
|
||||
if etags
|
||||
then pure $ curlEtagsDL o'
|
||||
else pure $ curlDL o'
|
||||
Wget -> do
|
||||
o' <- liftIO getWgetOpts
|
||||
if etags
|
||||
then pure $ wgetEtagsDL o'
|
||||
else pure $ wgetDL o'
|
||||
#if defined(INTERNAL_DOWNLOADER)
|
||||
Internal -> do
|
||||
(https, host, fullPath, port) <- liftE $ uriToQuadruple uri
|
||||
if etags
|
||||
then do
|
||||
metag <- lift $ readETag destFile
|
||||
let addHeaders = maybe mempty (\etag -> M.fromList [ (mk . E.encodeUtf8 . T.pack $ "If-None-Match"
|
||||
, E.encodeUtf8 etag)]) metag
|
||||
liftE
|
||||
$ catchE @HTTPNotModified @'[DownloadFailed] @'[] (\(HTTPNotModified etag) -> lift $ writeEtags destFile (pure $ Just etag))
|
||||
$ do
|
||||
r <- downloadToFile https host fullPath port destFile addHeaders
|
||||
lift $ writeEtags destFile (pure $ decUTF8Safe <$> getHeader r "etag")
|
||||
else void $ liftE $ catchE @HTTPNotModified
|
||||
@'[DownloadFailed]
|
||||
(\e@(HTTPNotModified _) ->
|
||||
throwE @_ @'[DownloadFailed] (DownloadFailed (toVariantAt @0 e :: V '[HTTPNotModified])))
|
||||
$ downloadToFile https host fullPath port destFile mempty
|
||||
Internal -> do
|
||||
if etags
|
||||
then pure (\fp -> liftE . internalEtagsDL fp)
|
||||
else pure (\fp -> liftE . internalDL fp)
|
||||
#endif
|
||||
liftE $ downloadAction baseDestFile uri
|
||||
case (gpgUri, gpgSetting) of
|
||||
(_, GPGNone) -> pure ()
|
||||
(Just gpgUri', _) -> do
|
||||
gpgDestFile <- liftE . reThrowAll @_ @_ @'[DownloadFailed] DownloadFailed $ getDestFile gpgUri' Nothing
|
||||
liftE $ flip onException
|
||||
(lift $ hideError doesNotExistErrorType $ recycleFile (tmpFile gpgDestFile))
|
||||
$ catchAllE @_ @'[GPGError, ProcessError, UnsupportedScheme, DownloadFailed] @'[GPGError]
|
||||
(\e -> if gpgSetting == GPGStrict then throwE (GPGError e) else lift $ logWarn $ T.pack (prettyShow (GPGError e))
|
||||
) $ do
|
||||
o' <- liftIO getGpgOpts
|
||||
lift $ logDebug $ "downloading: " <> (decUTF8Safe . serializeURIRef') gpgUri' <> " as file " <> T.pack gpgDestFile
|
||||
liftE $ downloadAction gpgDestFile gpgUri'
|
||||
lift $ logInfo $ "verifying signature of: " <> T.pack baseDestFile
|
||||
let args = o' ++ ["--batch", "--verify", "--quiet", "--no-tty", gpgDestFile, baseDestFile]
|
||||
cp <- lift $ executeOut "gpg" args Nothing
|
||||
case cp of
|
||||
CapturedProcess { _exitCode = ExitFailure i, _stdErr } -> do
|
||||
lift $ logDebug $ decUTF8Safe' _stdErr
|
||||
throwE (GPGError @'[ProcessError] (V (NonZeroExit i "gpg" args)))
|
||||
CapturedProcess { _stdErr } -> lift $ logDebug $ decUTF8Safe' _stdErr
|
||||
_ -> pure ()
|
||||
|
||||
forM_ eDigest (liftE . flip checkDigest destFile)
|
||||
pure destFile
|
||||
forM_ eDigest (liftE . flip checkDigest baseDestFile)
|
||||
pure baseDestFile
|
||||
|
||||
curlDL :: (MonadCatch m, MonadMask m, MonadIO m) => [String] -> FilePath -> URI -> Excepts '[ProcessError, DownloadFailed, UnsupportedScheme] m ()
|
||||
curlDL o' destFile (decUTF8Safe . serializeURIRef' -> uri') = do
|
||||
let destFileTemp = tmpFile destFile
|
||||
flip finally (try @_ @SomeException $ rmFile destFileTemp) $ do
|
||||
liftE $ lEM @_ @'[ProcessError] $ exec "curl"
|
||||
(o' ++ ["-fL", "-o", destFileTemp, T.unpack uri']) Nothing Nothing
|
||||
liftIO $ renameFile destFileTemp destFile
|
||||
|
||||
curlEtagsDL :: (MonadReader env m, HasLog env, MonadCatch m, MonadMask m, MonadIO m)
|
||||
=> [String] -> FilePath -> URI -> Excepts '[ProcessError, DownloadFailed, UnsupportedScheme] m ()
|
||||
curlEtagsDL o' destFile (decUTF8Safe . serializeURIRef' -> uri') = do
|
||||
let destFileTemp = tmpFile destFile
|
||||
dh <- liftIO $ emptySystemTempFile "curl-header"
|
||||
flip finally (try @_ @SomeException $ rmFile dh) $
|
||||
flip finally (try @_ @SomeException $ rmFile destFileTemp) $ do
|
||||
metag <- lift $ readETag destFile
|
||||
liftE $ lEM @_ @'[ProcessError] $ exec "curl"
|
||||
(o' ++ (if etags then ["--dump-header", dh] else [])
|
||||
++ maybe [] (\t -> ["-H", "If-None-Match: " <> T.unpack t]) metag
|
||||
++ ["-fL", "-o", destFileTemp, T.unpack uri']) Nothing Nothing
|
||||
headers <- liftIO $ T.readFile dh
|
||||
|
||||
-- this nonsense is necessary, because some older versions of curl would overwrite
|
||||
-- the destination file when 304 is returned
|
||||
case fmap T.words . listToMaybe . fmap T.strip . T.lines . getLastHeader $ headers of
|
||||
Just (http':sc:_)
|
||||
| sc == "304"
|
||||
, T.pack "HTTP" `T.isPrefixOf` http' -> lift $ logDebug "Status code was 304, not overwriting"
|
||||
| T.pack "HTTP" `T.isPrefixOf` http' -> do
|
||||
lift $ logDebug $ "Status code was " <> sc <> ", overwriting"
|
||||
liftIO $ renameFile destFileTemp destFile
|
||||
_ -> liftE $ throwE @_ @'[DownloadFailed] (DownloadFailed (toVariantAt @0 (MalformedHeaders headers)
|
||||
:: V '[MalformedHeaders]))
|
||||
|
||||
lift $ writeEtags destFile (parseEtags headers)
|
||||
|
||||
wgetDL :: (MonadCatch m, MonadMask m, MonadIO m) => [String] -> FilePath -> URI -> Excepts '[ProcessError, DownloadFailed, UnsupportedScheme] m ()
|
||||
wgetDL o' destFile (decUTF8Safe . serializeURIRef' -> uri') = do
|
||||
let destFileTemp = tmpFile destFile
|
||||
flip finally (try @_ @SomeException $ rmFile destFileTemp) $ do
|
||||
let opts = o' ++ ["-O", destFileTemp , T.unpack uri']
|
||||
liftE $ lEM @_ @'[ProcessError] $ exec "wget" opts Nothing Nothing
|
||||
liftIO $ renameFile destFileTemp destFile
|
||||
|
||||
|
||||
wgetEtagsDL :: (MonadReader env m, HasLog env, MonadCatch m, MonadMask m, MonadIO m)
|
||||
=> [String] -> FilePath -> URI -> Excepts '[ProcessError, DownloadFailed, UnsupportedScheme] m ()
|
||||
wgetEtagsDL o' destFile (decUTF8Safe . serializeURIRef' -> uri') = do
|
||||
let destFileTemp = tmpFile destFile
|
||||
flip finally (try @_ @SomeException $ rmFile destFileTemp) $ do
|
||||
metag <- lift $ readETag destFile
|
||||
let opts = o' ++ maybe [] (\t -> ["--header", "If-None-Match: " <> T.unpack t]) metag
|
||||
++ ["-q", "-S", "-O", destFileTemp , T.unpack uri']
|
||||
CapturedProcess {_exitCode, _stdErr} <- lift $ executeOut "wget" opts Nothing
|
||||
case _exitCode of
|
||||
ExitSuccess -> do
|
||||
liftIO $ renameFile destFileTemp destFile
|
||||
lift $ writeEtags destFile (parseEtags (decUTF8Safe' _stdErr))
|
||||
ExitFailure i'
|
||||
| i' == 8
|
||||
, Just _ <- find (T.pack "304 Not Modified" `T.isInfixOf`) . T.lines . decUTF8Safe' $ _stdErr
|
||||
-> do
|
||||
lift $ logDebug "Not modified, skipping download"
|
||||
lift $ writeEtags destFile (parseEtags (decUTF8Safe' _stdErr))
|
||||
| otherwise -> throwE (NonZeroExit i' "wget" opts)
|
||||
|
||||
#if defined(INTERNAL_DOWNLOADER)
|
||||
internalDL :: (MonadCatch m, MonadMask m, MonadIO m)
|
||||
=> FilePath -> URI -> Excepts '[DownloadFailed, UnsupportedScheme] m ()
|
||||
internalDL destFile uri' = do
|
||||
let destFileTemp = tmpFile destFile
|
||||
flip finally (try @_ @SomeException $ rmFile destFileTemp) $ do
|
||||
(https, host, fullPath, port) <- liftE $ uriToQuadruple uri'
|
||||
void $ liftE $ catchE @HTTPNotModified
|
||||
@'[DownloadFailed]
|
||||
(\e@(HTTPNotModified _) ->
|
||||
throwE @_ @'[DownloadFailed] (DownloadFailed (toVariantAt @0 e :: V '[HTTPNotModified])))
|
||||
$ downloadToFile https host fullPath port destFileTemp mempty
|
||||
liftIO $ renameFile destFileTemp destFile
|
||||
|
||||
|
||||
internalEtagsDL :: (MonadReader env m, HasLog env, MonadCatch m, MonadMask m, MonadIO m)
|
||||
=> FilePath -> URI -> Excepts '[DownloadFailed, UnsupportedScheme] m ()
|
||||
internalEtagsDL destFile uri' = do
|
||||
let destFileTemp = tmpFile destFile
|
||||
flip finally (try @_ @SomeException $ rmFile destFileTemp) $ do
|
||||
(https, host, fullPath, port) <- liftE $ uriToQuadruple uri'
|
||||
metag <- lift $ readETag destFile
|
||||
let addHeaders = maybe mempty (\etag -> M.fromList [ (mk . E.encodeUtf8 . T.pack $ "If-None-Match"
|
||||
, E.encodeUtf8 etag)]) metag
|
||||
liftE
|
||||
$ catchE @HTTPNotModified @'[DownloadFailed] @'[] (\(HTTPNotModified etag) -> lift $ writeEtags destFile (pure $ Just etag))
|
||||
$ do
|
||||
r <- downloadToFile https host fullPath port destFileTemp addHeaders
|
||||
liftIO $ renameFile destFileTemp destFile
|
||||
lift $ writeEtags destFile (pure $ decUTF8Safe <$> getHeader r "etag")
|
||||
#endif
|
||||
|
||||
|
||||
-- Manage to find a file we can write the body into.
|
||||
getDestFile :: Monad m => Excepts '[NoUrlBase] m FilePath
|
||||
getDestFile =
|
||||
case mfn of
|
||||
getDestFile :: Monad m => URI -> Maybe FilePath -> Excepts '[NoUrlBase] m FilePath
|
||||
getDestFile uri' mfn' =
|
||||
let path = view pathL' uri'
|
||||
in case mfn' of
|
||||
Just fn -> pure (dest </> fn)
|
||||
Nothing
|
||||
| let urlBase = T.unpack (decUTF8Safe (urlBaseName path))
|
||||
, not (null urlBase) -> pure (dest </> urlBase)
|
||||
-- TODO: remove this once we use hpath again
|
||||
| otherwise -> throwE $ NoUrlBase uri'
|
||||
|
||||
path = view pathL' uri
|
||||
uri' = decUTF8Safe (serializeURIRef' uri)
|
||||
| otherwise -> throwE $ NoUrlBase (decUTF8Safe . serializeURIRef' $ uri')
|
||||
|
||||
parseEtags :: (MonadReader env m, HasLog env, MonadIO m, MonadThrow m) => T.Text -> m (Maybe T.Text)
|
||||
parseEtags stderr = do
|
||||
@@ -499,14 +575,14 @@ downloadCached :: ( MonadReader env m
|
||||
)
|
||||
=> DownloadInfo
|
||||
-> Maybe FilePath -- ^ optional filename
|
||||
-> Excepts '[DigestError , DownloadFailed] m FilePath
|
||||
-> Excepts '[DigestError , DownloadFailed, GPGError] m FilePath
|
||||
downloadCached dli mfn = do
|
||||
Settings{ cache } <- lift getSettings
|
||||
case cache of
|
||||
True -> downloadCached' dli mfn Nothing
|
||||
False -> do
|
||||
tmp <- lift withGHCupTmpDir
|
||||
liftE $ download (_dlUri dli) (Just (_dlHash dli)) tmp mfn False
|
||||
liftE $ download (_dlUri dli) Nothing (Just (_dlHash dli)) tmp mfn False
|
||||
|
||||
|
||||
downloadCached' :: ( MonadReader env m
|
||||
@@ -521,7 +597,7 @@ downloadCached' :: ( MonadReader env m
|
||||
=> DownloadInfo
|
||||
-> Maybe FilePath -- ^ optional filename
|
||||
-> Maybe FilePath -- ^ optional destination dir (default: cacheDir)
|
||||
-> Excepts '[DigestError , DownloadFailed] m FilePath
|
||||
-> Excepts '[DigestError , DownloadFailed, GPGError] m FilePath
|
||||
downloadCached' dli mfn mDestDir = do
|
||||
Dirs { cacheDir } <- lift getDirs
|
||||
let destDir = fromMaybe cacheDir mDestDir
|
||||
@@ -532,7 +608,7 @@ downloadCached' dli mfn mDestDir = do
|
||||
| fileExists -> do
|
||||
liftE $ checkDigest (view dlHash dli) cachfile
|
||||
pure cachfile
|
||||
| otherwise -> liftE $ download (_dlUri dli) (Just (_dlHash dli)) destDir mfn False
|
||||
| otherwise -> liftE $ download (_dlUri dli) Nothing (Just (_dlHash dli)) destDir mfn False
|
||||
|
||||
|
||||
|
||||
@@ -561,7 +637,7 @@ checkDigest eDigest file = do
|
||||
lift $ logInfo $ "verifying digest of: " <> T.pack p'
|
||||
c <- liftIO $ L.readFile file
|
||||
cDigest <- throwEither . E.decodeUtf8' . B16.encode . SHA256.hashlazy $ c
|
||||
when ((cDigest /= eDigest) && verify) $ throwE (DigestError cDigest eDigest)
|
||||
when ((cDigest /= eDigest) && verify) $ throwE (DigestError file cDigest eDigest)
|
||||
|
||||
|
||||
-- | Get additional curl args from env. This is an undocumented option.
|
||||
@@ -579,6 +655,12 @@ getWgetOpts =
|
||||
Just r -> pure $ splitOn " " r
|
||||
Nothing -> pure []
|
||||
|
||||
-- | Get additional gpg args from env. This is an undocumented option.
|
||||
getGpgOpts :: IO [String]
|
||||
getGpgOpts =
|
||||
lookupEnv "GHCUP_GPG_OPTS" >>= \case
|
||||
Just r -> pure $ splitOn " " r
|
||||
Nothing -> pure []
|
||||
|
||||
-- | Get the url base name.
|
||||
--
|
||||
@@ -600,3 +682,7 @@ urlBaseName = snd . B.breakEnd (== _slash) . urlDecode False
|
||||
-- "HTTP/1.1 304 Not Modified\n"
|
||||
getLastHeader :: T.Text -> T.Text
|
||||
getLastHeader = T.unlines . lastDef [] . filter (\x -> not (null x)) . splitOn [""] . fmap T.stripEnd . T.lines
|
||||
|
||||
|
||||
tmpFile :: FilePath -> FilePath
|
||||
tmpFile = (<.> "tmp")
|
||||
|
||||
@@ -188,12 +188,22 @@ instance Pretty TarDirDoesNotExist where
|
||||
text "Tar directory does not exist:" <+> pPrint dir
|
||||
|
||||
-- | File digest verification failed.
|
||||
data DigestError = DigestError Text Text
|
||||
data DigestError = DigestError FilePath Text Text
|
||||
deriving Show
|
||||
|
||||
instance Pretty DigestError where
|
||||
pPrint (DigestError currentDigest expectedDigest) =
|
||||
text "Digest error: expected" <+> text (T.unpack expectedDigest) <+> text "but got" <+> pPrint currentDigest
|
||||
pPrint (DigestError fp currentDigest expectedDigest) =
|
||||
text "Digest error for" <+> text (fp <> ": expected")
|
||||
<+> text (T.unpack expectedDigest) <+> text "but got" <+> pPrint currentDigest <+> text
|
||||
"\nConsider removing the file in case it's cached and try again."
|
||||
|
||||
-- | File digest verification failed.
|
||||
data GPGError = forall xs . (ToVariantMaybe DownloadFailed xs, PopVariant DownloadFailed xs, Show (V xs), Pretty (V xs)) => GPGError (V xs)
|
||||
|
||||
deriving instance Show GPGError
|
||||
|
||||
instance Pretty GPGError where
|
||||
pPrint (GPGError reason) = text "GPG verify failed:" <+> pPrint reason
|
||||
|
||||
-- | Unexpected HTTP status.
|
||||
data HTTPStatusError = HTTPStatusError Int (M.Map (CI ByteString) ByteString)
|
||||
@@ -285,31 +295,37 @@ instance Pretty HadrianNotFound where
|
||||
-------------------------
|
||||
|
||||
-- | A download failed. The underlying error is encapsulated.
|
||||
data DownloadFailed = forall x xs . (Show x, Show (V xs), Pretty x, Pretty (V xs)) => DownloadFailed (V (x ': xs))
|
||||
data DownloadFailed = forall xs . (ToVariantMaybe DownloadFailed xs, PopVariant DownloadFailed xs, Show (V xs), Pretty (V xs)) => DownloadFailed (V xs)
|
||||
|
||||
instance Pretty DownloadFailed where
|
||||
pPrint (DownloadFailed reason) =
|
||||
text "Download failed:" <+> pPrint reason
|
||||
case reason of
|
||||
VMaybe (_ :: DownloadFailed) -> pPrint reason
|
||||
_ -> text "Download failed:" <+> pPrint reason
|
||||
|
||||
deriving instance Show DownloadFailed
|
||||
|
||||
|
||||
-- | A build failed.
|
||||
data BuildFailed = forall es . (Pretty (V es), Show (V es)) => BuildFailed FilePath (V es)
|
||||
data BuildFailed = forall es . (ToVariantMaybe BuildFailed es, PopVariant BuildFailed es, Pretty (V es), Show (V es)) => BuildFailed FilePath (V es)
|
||||
|
||||
instance Pretty BuildFailed where
|
||||
pPrint (BuildFailed path reason) =
|
||||
text "BuildFailed failed in dir" <+> text (path <> ":") <+> pPrint reason
|
||||
case reason of
|
||||
VMaybe (_ :: BuildFailed) -> pPrint reason
|
||||
_ -> text "BuildFailed failed in dir" <+> text (path <> ":") <+> pPrint reason
|
||||
|
||||
deriving instance Show BuildFailed
|
||||
|
||||
|
||||
-- | Setting the current GHC version failed.
|
||||
data GHCupSetError = forall es . (Show (V es), Pretty (V es)) => GHCupSetError (V es)
|
||||
data GHCupSetError = forall es . (ToVariantMaybe GHCupSetError es, PopVariant GHCupSetError es, Show (V es), Pretty (V es)) => GHCupSetError (V es)
|
||||
|
||||
instance Pretty GHCupSetError where
|
||||
pPrint (GHCupSetError reason) =
|
||||
text "Setting the current GHC version failed:" <+> pPrint reason
|
||||
case reason of
|
||||
VMaybe (_ :: GHCupSetError) -> pPrint reason
|
||||
_ -> text "Setting the current GHC version failed:" <+> pPrint reason
|
||||
|
||||
deriving instance Show GHCupSetError
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import GHCup.Types
|
||||
import GHCup.Types.Optics
|
||||
import GHCup.Types.JSON ( )
|
||||
import GHCup.Utils.File
|
||||
import GHCup.Utils.Logger
|
||||
import GHCup.Utils.Prelude
|
||||
import GHCup.Utils.String.QQ
|
||||
|
||||
@@ -138,7 +139,6 @@ getLinuxDistro = do
|
||||
| hasWord name ["exherbo"] -> Exherbo
|
||||
| hasWord name ["gentoo"] -> Gentoo
|
||||
| hasWord name ["amazonlinux", "Amazon Linux"] -> AmazonLinux
|
||||
| hasWord name ["solus"] -> Solus
|
||||
| otherwise -> UnknownLinux
|
||||
pure (distro, parsedVer)
|
||||
where
|
||||
|
||||
@@ -60,9 +60,10 @@ getCommonRequirements pr tr =
|
||||
prettyRequirements :: Requirements -> T.Text
|
||||
prettyRequirements Requirements {..} =
|
||||
let d = if not . null $ _distroPKGs
|
||||
then
|
||||
"\n Please install the following distro packages: "
|
||||
<> T.intercalate " " _distroPKGs
|
||||
then "\n Please ensure the following distro packages "
|
||||
<> "are installed before continuing (you can exit ghcup "
|
||||
<> "and return at any time): "
|
||||
<> T.intercalate " " _distroPKGs
|
||||
else ""
|
||||
n = if not . T.null $ _notes then "\n Note: " <> _notes else ""
|
||||
in "System requirements " <> d <> n
|
||||
|
||||
@@ -223,7 +223,6 @@ data LinuxDistro = Debian
|
||||
| RedHat
|
||||
| Alpine
|
||||
| AmazonLinux
|
||||
| Solus
|
||||
-- rolling
|
||||
| Gentoo
|
||||
| Exherbo
|
||||
@@ -243,7 +242,6 @@ distroToString CentOS = "centos"
|
||||
distroToString RedHat = "redhat"
|
||||
distroToString Alpine = "alpine"
|
||||
distroToString AmazonLinux = "amazon"
|
||||
distroToString Solus = "solus"
|
||||
distroToString Gentoo = "gentoo"
|
||||
distroToString Exherbo = "exherbo"
|
||||
distroToString UnknownLinux = "unknown"
|
||||
@@ -303,11 +301,12 @@ data UserSettings = UserSettings
|
||||
, uKeyBindings :: Maybe UserKeyBindings
|
||||
, uUrlSource :: Maybe URLSource
|
||||
, uNoNetwork :: Maybe Bool
|
||||
, uGPGSetting :: Maybe GPGSetting
|
||||
}
|
||||
deriving (Show, GHC.Generic)
|
||||
|
||||
defaultUserSettings :: UserSettings
|
||||
defaultUserSettings = UserSettings Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing
|
||||
defaultUserSettings = UserSettings Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing
|
||||
|
||||
fromSettings :: Settings -> Maybe KeyBindings -> UserSettings
|
||||
fromSettings Settings{..} Nothing =
|
||||
@@ -320,6 +319,7 @@ fromSettings Settings{..} Nothing =
|
||||
, uNoNetwork = Just noNetwork
|
||||
, uKeyBindings = Nothing
|
||||
, uUrlSource = Just urlSource
|
||||
, uGPGSetting = Just gpgSetting
|
||||
}
|
||||
fromSettings Settings{..} (Just KeyBindings{..}) =
|
||||
let ukb = UserKeyBindings
|
||||
@@ -342,6 +342,7 @@ fromSettings Settings{..} (Just KeyBindings{..}) =
|
||||
, uNoNetwork = Just noNetwork
|
||||
, uKeyBindings = Just ukb
|
||||
, uUrlSource = Just urlSource
|
||||
, uGPGSetting = Just gpgSetting
|
||||
}
|
||||
|
||||
data UserKeyBindings = UserKeyBindings
|
||||
@@ -415,6 +416,8 @@ data Settings = Settings
|
||||
, verbose :: Bool
|
||||
, urlSource :: URLSource
|
||||
, noNetwork :: Bool
|
||||
, gpgSetting :: GPGSetting
|
||||
, noColor :: Bool -- this also exists in LoggerConfig
|
||||
}
|
||||
deriving (Show, GHC.Generic)
|
||||
|
||||
@@ -448,6 +451,13 @@ data Downloader = Curl
|
||||
|
||||
instance NFData Downloader
|
||||
|
||||
data GPGSetting = GPGStrict
|
||||
| GPGLax
|
||||
| GPGNone
|
||||
deriving (Eq, Show, Ord, GHC.Generic)
|
||||
|
||||
instance NFData GPGSetting
|
||||
|
||||
data DebugInfo = DebugInfo
|
||||
{ diBaseDir :: FilePath
|
||||
, diBinDir :: FilePath
|
||||
@@ -567,11 +577,12 @@ data LogLevel = Warn
|
||||
deriving (Eq, Ord, Show)
|
||||
|
||||
data LoggerConfig = LoggerConfig
|
||||
{ lcPrintDebug :: Bool -- ^ whether to print debug in colorOutter
|
||||
, colorOutter :: T.Text -> IO () -- ^ how to write the color output
|
||||
, rawOutter :: T.Text -> IO () -- ^ how to write the full raw output
|
||||
{ lcPrintDebug :: Bool -- ^ whether to print debug in colorOutter
|
||||
, consoleOutter :: T.Text -> IO () -- ^ how to write the console output
|
||||
, fileOutter :: T.Text -> IO () -- ^ how to write the file output
|
||||
, fancyColors :: Bool
|
||||
}
|
||||
deriving Show
|
||||
|
||||
instance NFData LoggerConfig where
|
||||
rnf (LoggerConfig !lcPrintDebug !_ !_) = rnf lcPrintDebug
|
||||
rnf (LoggerConfig !lcPrintDebug !_ !_ !fancyColors) = rnf (lcPrintDebug, fancyColors)
|
||||
|
||||
@@ -24,6 +24,8 @@ module GHCup.Types.JSON where
|
||||
import GHCup.Types
|
||||
import GHCup.Utils.MegaParsec
|
||||
import GHCup.Utils.Prelude
|
||||
import GHCup.Utils.Logger () -- TH is broken shite and needs GHCup.Utils.Logger for linking, although we don't depend on the file.
|
||||
-- This is due to the boot file.
|
||||
|
||||
import Control.Applicative ( (<|>) )
|
||||
import Data.Aeson
|
||||
@@ -54,6 +56,7 @@ deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''Tool
|
||||
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''GlobalTool
|
||||
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''KeepDirs
|
||||
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''Downloader
|
||||
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''GPGSetting
|
||||
|
||||
instance ToJSON Tag where
|
||||
toJSON Latest = String "Latest"
|
||||
|
||||
@@ -23,12 +23,9 @@ import GHCup.Types
|
||||
|
||||
import Control.Monad.Reader
|
||||
import Data.ByteString ( ByteString )
|
||||
import Data.Text ( Text )
|
||||
import Optics
|
||||
import URI.ByteString
|
||||
import System.Console.Pretty
|
||||
|
||||
import qualified Data.Text as T
|
||||
|
||||
makePrisms ''Tool
|
||||
makePrisms ''Architecture
|
||||
@@ -117,80 +114,6 @@ getDirs :: ( MonadReader env m
|
||||
getDirs = gets @"dirs"
|
||||
|
||||
|
||||
logInfo :: ( MonadReader env m
|
||||
, LabelOptic' "loggerConfig" A_Lens env LoggerConfig
|
||||
, MonadIO m
|
||||
)
|
||||
=> Text
|
||||
-> m ()
|
||||
logInfo = logInternal Info
|
||||
|
||||
logWarn :: ( MonadReader env m
|
||||
, LabelOptic' "loggerConfig" A_Lens env LoggerConfig
|
||||
, MonadIO m
|
||||
)
|
||||
=> Text
|
||||
-> m ()
|
||||
logWarn = logInternal Warn
|
||||
|
||||
logDebug :: ( MonadReader env m
|
||||
, LabelOptic' "loggerConfig" A_Lens env LoggerConfig
|
||||
, MonadIO m
|
||||
)
|
||||
=> Text
|
||||
-> m ()
|
||||
logDebug = logInternal Debug
|
||||
|
||||
logError :: ( MonadReader env m
|
||||
, LabelOptic' "loggerConfig" A_Lens env LoggerConfig
|
||||
, MonadIO m
|
||||
)
|
||||
=> Text
|
||||
-> m ()
|
||||
logError = logInternal Error
|
||||
|
||||
|
||||
logInternal :: ( MonadReader env m
|
||||
, LabelOptic' "loggerConfig" A_Lens env LoggerConfig
|
||||
, MonadIO m
|
||||
) => LogLevel
|
||||
-> Text
|
||||
-> m ()
|
||||
logInternal logLevel msg = do
|
||||
LoggerConfig {..} <- gets @"loggerConfig"
|
||||
let style' = case logLevel of
|
||||
Debug -> style Bold . color Blue
|
||||
Info -> style Bold . color Green
|
||||
Warn -> style Bold . color Yellow
|
||||
Error -> style Bold . color Red
|
||||
let l = case logLevel of
|
||||
Debug -> style' "[ Debug ]"
|
||||
Info -> style' "[ Info ]"
|
||||
Warn -> style' "[ Warn ]"
|
||||
Error -> style' "[ Error ]"
|
||||
let strs = T.split (== '\n') msg
|
||||
let out = case strs of
|
||||
[] -> T.empty
|
||||
(x:xs) ->
|
||||
foldr (\a b -> a <> "\n" <> b) mempty
|
||||
. ((l <> " " <> x) :)
|
||||
. fmap (\line' -> style' "[ ... ] " <> line' )
|
||||
$ xs
|
||||
|
||||
when (lcPrintDebug || (not lcPrintDebug && (logLevel /= Debug)))
|
||||
$ liftIO $ colorOutter out
|
||||
|
||||
-- raw output
|
||||
let lr = case logLevel of
|
||||
Debug -> "Debug:"
|
||||
Info -> "Info:"
|
||||
Warn -> "Warn:"
|
||||
Error -> "Error:"
|
||||
let outr = lr <> " " <> msg <> "\n"
|
||||
liftIO $ rawOutter outr
|
||||
|
||||
|
||||
|
||||
getLogCleanup :: ( MonadReader env m
|
||||
, LabelOptic' "logCleanup" A_Lens env (IO ())
|
||||
)
|
||||
|
||||
@@ -35,6 +35,7 @@ import GHCup.Types.Optics
|
||||
import GHCup.Types.JSON ( )
|
||||
import GHCup.Utils.Dirs
|
||||
import GHCup.Utils.File
|
||||
import GHCup.Utils.Logger
|
||||
import GHCup.Utils.MegaParsec
|
||||
import GHCup.Utils.Prelude
|
||||
import GHCup.Utils.String.QQ
|
||||
@@ -176,7 +177,7 @@ rmMajorSymlinks tv@GHCTargetVersion{..} = do
|
||||
forM_ files $ \f -> do
|
||||
let f_xy = f <> "-" <> T.unpack v' <> exeExt
|
||||
let fullF = binDir </> f_xy
|
||||
lift $ logDebug "rm -f #{fullF}"
|
||||
lift $ logDebug ("rm -f " <> T.pack fullF)
|
||||
lift $ hideError doesNotExistErrorType $ rmLink fullF
|
||||
|
||||
|
||||
@@ -250,7 +251,6 @@ getInstalledGHCs = do
|
||||
-- | Get all installed cabals, by matching on @~\/.ghcup\/bin/cabal-*@.
|
||||
getInstalledCabals :: ( MonadReader env m
|
||||
, HasDirs env
|
||||
, HasLog env
|
||||
, MonadIO m
|
||||
, MonadCatch m
|
||||
)
|
||||
@@ -268,7 +268,7 @@ getInstalledCabals = do
|
||||
|
||||
|
||||
-- | Whether the given cabal version is installed.
|
||||
cabalInstalled :: (HasLog env, MonadIO m, MonadReader env m, HasDirs env, MonadCatch m) => Version -> m Bool
|
||||
cabalInstalled :: (MonadIO m, MonadReader env m, HasDirs env, MonadCatch m) => Version -> m Bool
|
||||
cabalInstalled ver = do
|
||||
vers <- fmap rights getInstalledCabals
|
||||
pure $ elem ver vers
|
||||
@@ -475,7 +475,7 @@ hlsGHCVersions = do
|
||||
. splitOn "~"
|
||||
)
|
||||
bins
|
||||
pure . rights . concat . maybeToList $ vers
|
||||
pure . sortBy (flip compare) . rights . concat . maybeToList $ vers
|
||||
|
||||
|
||||
-- | Get all server binaries for an hls version, if any.
|
||||
@@ -791,7 +791,12 @@ applyPatches :: (MonadReader env m, HasDirs env, HasLog env, MonadIO m)
|
||||
-> FilePath -- ^ dir to apply patches in
|
||||
-> Excepts '[PatchFailed] m ()
|
||||
applyPatches pdir ddir = do
|
||||
patches <- (fmap . fmap) (pdir </>) $ liftIO $ listDirectory pdir
|
||||
patches <- (fmap . fmap) (pdir </>) $ liftIO $ findFiles
|
||||
pdir
|
||||
(makeRegexOpts compExtended
|
||||
execBlank
|
||||
([s|.+\.(patch|diff)$|] :: ByteString)
|
||||
)
|
||||
forM_ (sort patches) $ \patch' -> do
|
||||
lift $ logInfo $ "Applying patch " <> T.pack patch'
|
||||
fmap (either (const Nothing) Just)
|
||||
@@ -829,6 +834,8 @@ getChangeLog dls tool (Right tag) =
|
||||
-- 2. the install destination, depending on whether the build failed
|
||||
runBuildAction :: ( Pretty (V e)
|
||||
, Show (V e)
|
||||
, PopVariant BuildFailed e
|
||||
, ToVariantMaybe BuildFailed e
|
||||
, MonadReader env m
|
||||
, HasDirs env
|
||||
, HasSettings env
|
||||
@@ -836,6 +843,8 @@ runBuildAction :: ( Pretty (V e)
|
||||
, MonadMask m
|
||||
, HasLog env
|
||||
, MonadUnliftIO m
|
||||
, MonadFail m
|
||||
, MonadCatch m
|
||||
)
|
||||
=> FilePath -- ^ build directory (cleaned up depending on Settings)
|
||||
-> Maybe FilePath -- ^ dir to *always* clean up on exception
|
||||
@@ -1025,7 +1034,7 @@ ensureGlobalTools :: ( MonadMask m
|
||||
, MonadUnliftIO m
|
||||
, MonadFail m
|
||||
)
|
||||
=> Excepts '[DigestError , DownloadFailed, NoDownload] m ()
|
||||
=> Excepts '[GPGError, DigestError , DownloadFailed, NoDownload] m ()
|
||||
ensureGlobalTools = do
|
||||
#if defined(IS_WINDOWS)
|
||||
(GHCupInfo _ _ gTools) <- lift getGHCupInfo
|
||||
@@ -1033,12 +1042,12 @@ ensureGlobalTools = do
|
||||
shimDownload <- liftE $ lE @_ @'[NoDownload]
|
||||
$ maybe (Left NoDownload) Right $ Map.lookup ShimGen gTools
|
||||
let dl = downloadCached' shimDownload (Just "gs.exe") Nothing
|
||||
void $ (\(DigestError _ _) -> do
|
||||
void $ (\(DigestError _ _ _) -> do
|
||||
lift $ logWarn "Digest doesn't match, redownloading gs.exe..."
|
||||
lift $ logDebug "rm -f #{shimDownload}"
|
||||
lift $ logDebug ("rm -f " <> T.pack (cacheDir dirs </> "gs.exe"))
|
||||
lift $ hideError doesNotExistErrorType $ recycleFile (cacheDir dirs </> "gs.exe")
|
||||
liftE @'[DigestError , DownloadFailed] $ dl
|
||||
) `catchE` (liftE @'[DigestError , DownloadFailed] dl)
|
||||
liftE @'[GPGError, DigestError , DownloadFailed] $ dl
|
||||
) `catchE` (liftE @'[GPGError, DigestError , DownloadFailed] dl)
|
||||
pure ()
|
||||
#else
|
||||
pure ()
|
||||
|
||||
@@ -38,6 +38,7 @@ import GHCup.Types
|
||||
import GHCup.Types.JSON ( )
|
||||
import GHCup.Types.Optics
|
||||
import GHCup.Utils.MegaParsec
|
||||
import GHCup.Utils.Logger
|
||||
import GHCup.Utils.Prelude
|
||||
|
||||
import Control.Exception.Safe
|
||||
|
||||
@@ -9,6 +9,8 @@ import GHCup.Utils.Prelude
|
||||
|
||||
import Control.Monad.Reader
|
||||
import Data.Maybe
|
||||
import Data.Text ( Text )
|
||||
import Data.Void
|
||||
import GHC.IO.Exception
|
||||
import Optics hiding ((<|), (|>))
|
||||
import System.Directory
|
||||
@@ -16,7 +18,9 @@ import System.FilePath
|
||||
import Text.PrettyPrint.HughesPJClass hiding ( (<>) )
|
||||
import Text.Regex.Posix
|
||||
|
||||
import qualified Data.Text as T
|
||||
import qualified Data.ByteString.Lazy as BL
|
||||
import qualified Text.Megaparsec as MP
|
||||
|
||||
|
||||
|
||||
@@ -28,11 +32,11 @@ data ProcessError = NonZeroExit Int FilePath [String]
|
||||
|
||||
instance Pretty ProcessError where
|
||||
pPrint (NonZeroExit e exe args) =
|
||||
text "Process " <+> pPrint exe <+> text " with arguments " <+> text (show args) <+> text " failed with exit code " <+> text (show e) <+> "."
|
||||
text "Process" <+> pPrint exe <+> text "with arguments" <+> pPrint args <+> text "failed with exit code" <+> text (show e <> ".")
|
||||
pPrint (PTerminated exe args) =
|
||||
text "Process " <+> pPrint exe <+> text " with arguments " <+> text (show args) <+> text " terminated."
|
||||
text "Process" <+> pPrint exe <+> text "with arguments" <+> pPrint args <+> text "terminated."
|
||||
pPrint (PStopped exe args) =
|
||||
text "Process " <+> pPrint exe <+> text " with arguments " <+> text (show args) <+> text " stopped."
|
||||
text "Process" <+> pPrint exe <+> text "with arguments" <+> pPrint args <+> text "stopped."
|
||||
pPrint (NoSuchPid exe args) =
|
||||
text "Could not find PID for process running " <+> pPrint exe <+> text " with arguments " <+> text (show args) <+> text "."
|
||||
|
||||
@@ -101,6 +105,11 @@ findFiles path regex = do
|
||||
contents <- listDirectory path
|
||||
pure $ filter (match regex) contents
|
||||
|
||||
findFiles' :: FilePath -> MP.Parsec Void Text a -> IO [FilePath]
|
||||
findFiles' path parser = do
|
||||
contents <- listDirectory path
|
||||
pure $ filter (\fp -> either (const False) (const True) $ MP.parse parser "" (T.pack fp)) contents
|
||||
|
||||
|
||||
checkFileAlreadyExists :: (MonadIO m) => FilePath -> m Bool
|
||||
checkFileAlreadyExists fp = liftIO $ doesFileExist fp
|
||||
|
||||
5
lib/GHCup/Utils/File/Common.hs-boot
Normal file
5
lib/GHCup/Utils/File/Common.hs-boot
Normal file
@@ -0,0 +1,5 @@
|
||||
module GHCup.Utils.File.Common where
|
||||
|
||||
import Text.Regex.Posix
|
||||
|
||||
findFiles :: FilePath -> Regex -> IO [FilePath]
|
||||
@@ -17,6 +17,7 @@ module GHCup.Utils.File.Posix where
|
||||
|
||||
import GHCup.Utils.File.Common
|
||||
import GHCup.Utils.Prelude
|
||||
import GHCup.Utils.Logger
|
||||
import GHCup.Types
|
||||
import GHCup.Types.Optics
|
||||
|
||||
@@ -34,8 +35,7 @@ import Data.Sequence ( Seq, (|>) )
|
||||
import Data.List
|
||||
import Data.Word8
|
||||
import GHC.IO.Exception
|
||||
import System.Console.Pretty hiding ( Pretty )
|
||||
import System.Console.Regions
|
||||
import System.Console.Terminal.Common
|
||||
import System.IO.Error
|
||||
import System.FilePath
|
||||
import System.Directory
|
||||
@@ -51,6 +51,7 @@ import qualified Data.Sequence as Sq
|
||||
import qualified Data.Text as T
|
||||
import qualified Data.Text.Encoding as E
|
||||
import qualified System.Posix.Process as SPP
|
||||
import qualified System.Console.Terminal.Posix as TP
|
||||
import qualified Data.ByteString as BS
|
||||
import qualified Data.ByteString.Lazy as BL
|
||||
import qualified "unix-bytestring" System.Posix.IO.ByteString
|
||||
@@ -87,9 +88,9 @@ execLogged exe args chdir lfile env = do
|
||||
let logfile = logsDir </> lfile <> ".log"
|
||||
liftIO $ bracket (openFd logfile WriteOnly (Just newFilePerms) defaultFileFlags{ append = True })
|
||||
closeFd
|
||||
(action verbose)
|
||||
(action verbose noColor)
|
||||
where
|
||||
action verbose fd = do
|
||||
action verbose no_color fd = do
|
||||
actionWithPipes $ \(stdoutRead, stdoutWrite) -> do
|
||||
-- start the thread that logs to stdout
|
||||
pState <- newEmptyMVar
|
||||
@@ -100,7 +101,7 @@ execLogged exe args chdir lfile env = do
|
||||
$ EX.finally
|
||||
(if verbose
|
||||
then tee fd stdoutRead
|
||||
else printToRegion fd stdoutRead 6 pState
|
||||
else printToRegion fd stdoutRead 6 pState no_color
|
||||
)
|
||||
(putMVar done ())
|
||||
|
||||
@@ -137,46 +138,57 @@ execLogged exe args chdir lfile env = do
|
||||
|
||||
-- Reads fdIn and logs the output in a continous scrolling area
|
||||
-- of 'size' terminal lines. Also writes to a log file.
|
||||
printToRegion :: Fd -> Fd -> Int -> MVar Bool -> IO ()
|
||||
printToRegion fileFd fdIn size pState = do
|
||||
void $ displayConsoleRegions $ do
|
||||
rs <-
|
||||
liftIO
|
||||
. fmap Sq.fromList
|
||||
. sequence
|
||||
. replicate size
|
||||
. openConsoleRegion
|
||||
$ Linear
|
||||
flip runStateT mempty
|
||||
$ handle
|
||||
(\(ex :: SomeException) -> do
|
||||
ps <- liftIO $ takeMVar pState
|
||||
when ps (forM_ rs (liftIO . closeConsoleRegion))
|
||||
throw ex
|
||||
)
|
||||
$ readTilEOF (lineAction rs) fdIn
|
||||
printToRegion :: Fd -> Fd -> Int -> MVar Bool -> Bool -> IO ()
|
||||
printToRegion fileFd fdIn size pState no_color = do
|
||||
-- init region
|
||||
forM_ [1..size] $ \_ -> BS.putStr "\n"
|
||||
|
||||
void $ flip runStateT mempty
|
||||
$ do
|
||||
handle
|
||||
(\(ex :: SomeException) -> do
|
||||
ps <- liftIO $ takeMVar pState
|
||||
when ps (liftIO $ BS.putStr (pos1 <> moveLineUp size <> clearScreen))
|
||||
throw ex
|
||||
) $ readTilEOF lineAction fdIn
|
||||
|
||||
where
|
||||
clearScreen :: ByteString
|
||||
clearScreen = "\x1b[0J"
|
||||
clearLine :: ByteString
|
||||
clearLine = "\x1b[2K"
|
||||
moveLineUp :: Int -> ByteString
|
||||
moveLineUp n = "\x1b[" <> E.encodeUtf8 (T.pack (show n)) <> "A"
|
||||
moveLineDown :: Int -> ByteString
|
||||
moveLineDown n = "\x1b[" <> E.encodeUtf8 (T.pack (show n)) <> "B"
|
||||
pos1 :: ByteString
|
||||
pos1 = "\r"
|
||||
overwriteNthLine :: Int -> ByteString -> ByteString
|
||||
overwriteNthLine n str = pos1 <> moveLineUp n <> clearLine <> str <> moveLineDown n <> pos1
|
||||
|
||||
blue :: ByteString -> ByteString
|
||||
blue bs
|
||||
| no_color = bs
|
||||
| otherwise = "\x1b[0;34m" <> bs <> "\x1b[0m"
|
||||
|
||||
-- action to perform line by line
|
||||
-- TODO: do this with vty for efficiency
|
||||
lineAction :: (MonadMask m, MonadIO m)
|
||||
=> Seq ConsoleRegion
|
||||
-> ByteString
|
||||
=> ByteString
|
||||
-> StateT (Seq ByteString) m ()
|
||||
lineAction rs = \bs' -> do
|
||||
lineAction = \bs' -> do
|
||||
void $ liftIO $ SPIB.fdWrite fileFd (bs' <> "\n")
|
||||
modify (swapRegs bs')
|
||||
regs <- get
|
||||
liftIO $ forM_ (Sq.zip regs rs) $ \(bs, r) -> setConsoleRegion r $ do
|
||||
w <- consoleWidth
|
||||
return
|
||||
. T.pack
|
||||
. color Blue
|
||||
. T.unpack
|
||||
. decUTF8Safe
|
||||
. trim w
|
||||
. (\b -> "[ " <> E.encodeUtf8 (T.pack lfile) <> " ] " <> b)
|
||||
$ bs
|
||||
liftIO TP.size >>= \case
|
||||
Nothing -> pure ()
|
||||
Just (Window _ w) -> do
|
||||
regs <- get
|
||||
liftIO $ forM_ (Sq.zip regs (Sq.fromList [0..(Sq.length regs - 1)])) $ \(bs, i) -> do
|
||||
BS.putStr
|
||||
. overwriteNthLine (size - i)
|
||||
. trim w
|
||||
. blue
|
||||
. (\b -> "[ " <> E.encodeUtf8 (T.pack lfile) <> " ] " <> b)
|
||||
$ bs
|
||||
|
||||
swapRegs :: a -> Seq a -> Seq a
|
||||
swapRegs bs = \regs -> if
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
{-# LANGUAGE FlexibleContexts #-}
|
||||
{-# LANGUAGE QuasiQuotes #-}
|
||||
{-# LANGUAGE DataKinds #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
|
||||
{-|
|
||||
Module : GHCup.Utils.Logger
|
||||
@@ -16,21 +18,97 @@ module GHCup.Utils.Logger where
|
||||
|
||||
import GHCup.Types
|
||||
import GHCup.Types.Optics
|
||||
import GHCup.Utils.File
|
||||
import {-# SOURCE #-} GHCup.Utils.File.Common
|
||||
import GHCup.Utils.String.QQ
|
||||
|
||||
import Control.Exception.Safe
|
||||
import Control.Monad
|
||||
import Control.Monad.IO.Class
|
||||
import Control.Monad.Reader
|
||||
import Data.Text ( Text )
|
||||
import Optics
|
||||
import Prelude hiding ( appendFile )
|
||||
import System.Console.Pretty
|
||||
import System.FilePath
|
||||
import System.IO.Error
|
||||
import Text.Regex.Posix
|
||||
|
||||
import qualified Data.ByteString as B
|
||||
import GHCup.Utils.Prelude
|
||||
import qualified Data.Text as T
|
||||
|
||||
logInfo :: ( MonadReader env m
|
||||
, LabelOptic' "loggerConfig" A_Lens env LoggerConfig
|
||||
, MonadIO m
|
||||
)
|
||||
=> Text
|
||||
-> m ()
|
||||
logInfo = logInternal Info
|
||||
|
||||
logWarn :: ( MonadReader env m
|
||||
, LabelOptic' "loggerConfig" A_Lens env LoggerConfig
|
||||
, MonadIO m
|
||||
)
|
||||
=> Text
|
||||
-> m ()
|
||||
logWarn = logInternal Warn
|
||||
|
||||
logDebug :: ( MonadReader env m
|
||||
, LabelOptic' "loggerConfig" A_Lens env LoggerConfig
|
||||
, MonadIO m
|
||||
)
|
||||
=> Text
|
||||
-> m ()
|
||||
logDebug = logInternal Debug
|
||||
|
||||
logError :: ( MonadReader env m
|
||||
, LabelOptic' "loggerConfig" A_Lens env LoggerConfig
|
||||
, MonadIO m
|
||||
)
|
||||
=> Text
|
||||
-> m ()
|
||||
logError = logInternal Error
|
||||
|
||||
|
||||
logInternal :: ( MonadReader env m
|
||||
, LabelOptic' "loggerConfig" A_Lens env LoggerConfig
|
||||
, MonadIO m
|
||||
) => LogLevel
|
||||
-> Text
|
||||
-> m ()
|
||||
logInternal logLevel msg = do
|
||||
LoggerConfig {..} <- gets @"loggerConfig"
|
||||
let color' c = if fancyColors then color c else id
|
||||
let style' = case logLevel of
|
||||
Debug -> style Bold . color' Blue
|
||||
Info -> style Bold . color' Green
|
||||
Warn -> style Bold . color' Yellow
|
||||
Error -> style Bold . color' Red
|
||||
let l = case logLevel of
|
||||
Debug -> style' "[ Debug ]"
|
||||
Info -> style' "[ Info ]"
|
||||
Warn -> style' "[ Warn ]"
|
||||
Error -> style' "[ Error ]"
|
||||
let strs = T.split (== '\n') msg
|
||||
let out = case strs of
|
||||
[] -> T.empty
|
||||
(x:xs) ->
|
||||
foldr (\a b -> a <> "\n" <> b) mempty
|
||||
. ((l <> " " <> x) :)
|
||||
. fmap (\line' -> style' "[ ... ] " <> line' )
|
||||
$ xs
|
||||
|
||||
when (lcPrintDebug || (not lcPrintDebug && (logLevel /= Debug)))
|
||||
$ liftIO $ consoleOutter out
|
||||
|
||||
-- raw output
|
||||
let lr = case logLevel of
|
||||
Debug -> "Debug:"
|
||||
Info -> "Info:"
|
||||
Warn -> "Warn:"
|
||||
Error -> "Error:"
|
||||
let outr = lr <> " " <> msg <> "\n"
|
||||
liftIO $ fileOutter outr
|
||||
|
||||
|
||||
initGHCupFileLogging :: ( MonadReader env m
|
||||
|
||||
21
lib/GHCup/Utils/Logger.hs-boot
Normal file
21
lib/GHCup/Utils/Logger.hs-boot
Normal file
@@ -0,0 +1,21 @@
|
||||
{-# LANGUAGE FlexibleContexts #-}
|
||||
{-# LANGUAGE QuasiQuotes #-}
|
||||
{-# LANGUAGE DataKinds #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
|
||||
module GHCup.Utils.Logger where
|
||||
|
||||
import GHCup.Types
|
||||
|
||||
import Control.Monad.IO.Class
|
||||
import Control.Monad.Reader
|
||||
import Data.Text ( Text )
|
||||
import Optics
|
||||
|
||||
logWarn :: ( MonadReader env m
|
||||
, LabelOptic' "loggerConfig" A_Lens env LoggerConfig
|
||||
, MonadIO m
|
||||
)
|
||||
=> Text
|
||||
-> m ()
|
||||
|
||||
@@ -23,6 +23,7 @@ module GHCup.Utils.Prelude where
|
||||
import GHCup.Types
|
||||
#endif
|
||||
import GHCup.Types.Optics
|
||||
import {-# SOURCE #-} GHCup.Utils.Logger
|
||||
|
||||
import Control.Applicative
|
||||
import Control.Exception.Safe
|
||||
|
||||
@@ -24,8 +24,11 @@ import qualified Data.List.NonEmpty as NE
|
||||
import qualified Data.Text as T
|
||||
|
||||
-- | This reflects the API version of the YAML.
|
||||
--
|
||||
-- Note that when updating this, CI requires that the file exsists AND the same file exists at
|
||||
-- 'https://www.haskell.org/ghcup/exp/ghcup-<ver>.yaml' with some newlines added.
|
||||
ghcupURL :: URI
|
||||
ghcupURL = [uri|https://www.haskell.org/ghcup/data/ghcup-0.0.7.yaml|]
|
||||
ghcupURL = [uri|https://www.haskell.org/ghcup/data/ghcup-0.0.6.yaml|]
|
||||
|
||||
-- | The current ghcup version.
|
||||
ghcUpVer :: PVP
|
||||
|
||||
43
lib/System/Console/Terminal/Common.hs
Normal file
43
lib/System/Console/Terminal/Common.hs
Normal file
@@ -0,0 +1,43 @@
|
||||
{-# LANGUAGE CPP #-}
|
||||
{-# LANGUAGE DeriveDataTypeable #-}
|
||||
{-# LANGUAGE DeriveTraversable #-}
|
||||
|
||||
#if __GLASGOW_HASKELL__ >= 702
|
||||
#define LANGUAGE_DeriveGeneric
|
||||
{-# LANGUAGE DeriveGeneric #-}
|
||||
#endif
|
||||
|
||||
module System.Console.Terminal.Common
|
||||
( Window(..)
|
||||
) where
|
||||
|
||||
import Data.Data (Typeable, Data)
|
||||
|
||||
#if __GLASGOW_HASKELL__ < 710
|
||||
import Data.Foldable (Foldable)
|
||||
import Data.Traversable (Traversable)
|
||||
#endif
|
||||
|
||||
#ifdef LANGUAGE_DeriveGeneric
|
||||
import GHC.Generics
|
||||
( Generic
|
||||
#if __GLASGOW_HASKELL__ >= 706
|
||||
, Generic1
|
||||
#endif
|
||||
)
|
||||
#endif
|
||||
|
||||
-- | Terminal window width and height
|
||||
data Window a = Window
|
||||
{ height :: !a
|
||||
, width :: !a
|
||||
} deriving
|
||||
( Show, Eq, Read, Data, Typeable
|
||||
, Foldable, Functor, Traversable
|
||||
#ifdef LANGUAGE_DeriveGeneric
|
||||
, Generic
|
||||
#if __GLASGOW_HASKELL__ >= 706
|
||||
, Generic1
|
||||
#endif
|
||||
#endif
|
||||
)
|
||||
65
lib/System/Console/Terminal/Posix.hsc
Normal file
65
lib/System/Console/Terminal/Posix.hsc
Normal file
@@ -0,0 +1,65 @@
|
||||
{-# LANGUAGE CApiFFI #-}
|
||||
|
||||
module System.Console.Terminal.Posix
|
||||
( size, fdSize, hSize
|
||||
) where
|
||||
|
||||
import System.Console.Terminal.Common
|
||||
import Control.Exception (catch)
|
||||
import Data.Typeable (cast)
|
||||
import Foreign
|
||||
import Foreign.C.Error
|
||||
import Foreign.C.Types
|
||||
import GHC.IO.FD (FD(FD, fdFD))
|
||||
import GHC.IO.Handle.Internals (withHandle_)
|
||||
import GHC.IO.Handle.Types (Handle, Handle__(Handle__, haDevice))
|
||||
#if defined(__GLASGOW_HASKELL__) && (__GLASGOW_HASKELL__ < 706)
|
||||
import Prelude hiding (catch)
|
||||
#endif
|
||||
import System.Posix.Types (Fd(Fd))
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
#let alignment t = "%lu", (unsigned long)offsetof(struct {char x__; t (y__); }, y__)
|
||||
|
||||
|
||||
-- Interesting part of @struct winsize@
|
||||
data CWin = CWin CUShort CUShort
|
||||
|
||||
instance Storable CWin where
|
||||
sizeOf _ = (#size struct winsize)
|
||||
alignment _ = (#alignment struct winsize)
|
||||
peek ptr = do
|
||||
row <- (#peek struct winsize, ws_row) ptr
|
||||
col <- (#peek struct winsize, ws_col) ptr
|
||||
return $ CWin row col
|
||||
poke ptr (CWin row col) = do
|
||||
(#poke struct winsize, ws_row) ptr row
|
||||
(#poke struct winsize, ws_col) ptr col
|
||||
|
||||
|
||||
fdSize :: Integral n => Fd -> IO (Maybe (Window n))
|
||||
fdSize (Fd fd) = with (CWin 0 0) $ \ws -> do
|
||||
_ <- throwErrnoIfMinus1 "ioctl" $
|
||||
ioctl fd (#const TIOCGWINSZ) ws
|
||||
CWin row col <- peek ws
|
||||
return . Just $ Window (fromIntegral row) (fromIntegral col)
|
||||
`catch`
|
||||
handler
|
||||
where
|
||||
handler :: IOError -> IO (Maybe (Window h))
|
||||
handler _ = return Nothing
|
||||
|
||||
foreign import capi "sys/ioctl.h ioctl"
|
||||
ioctl :: CInt -> CULong -> Ptr CWin -> IO CInt
|
||||
|
||||
size :: Integral n => IO (Maybe (Window n))
|
||||
size = fdSize (Fd (#const STDOUT_FILENO))
|
||||
|
||||
hSize :: Integral n => Handle -> IO (Maybe (Window n))
|
||||
hSize h = withHandle_ "hSize" h $ \Handle__ { haDevice = dev } ->
|
||||
case cast dev of
|
||||
Nothing -> return Nothing
|
||||
Just FD { fdFD = fd } -> fdSize (Fd fd)
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
plat="$(uname -s)"
|
||||
arch=$(uname -m)
|
||||
ghver="0.1.16.2"
|
||||
ghver="0.1.17"
|
||||
base_url="https://downloads.haskell.org/~ghcup"
|
||||
|
||||
export GHCUP_SKIP_UPDATE_CHECK=yes
|
||||
@@ -52,41 +52,57 @@ esac
|
||||
|
||||
|
||||
die() {
|
||||
(>&2 printf "\\033[0;31m%s\\033[0m\\n" "$1")
|
||||
if [ -n "${NO_COLOR}" ] ; then
|
||||
(>&2 printf "%s\\n" "$1")
|
||||
else
|
||||
(>&2 printf "\\033[0;31m%s\\033[0m\\n" "$1")
|
||||
fi
|
||||
exit 2
|
||||
}
|
||||
|
||||
warn() {
|
||||
case "${plat}" in
|
||||
MSYS*|MINGW*)
|
||||
echo -e "\\033[0;35m$1\\033[0m"
|
||||
;;
|
||||
*)
|
||||
printf "\\033[0;35m%s\\033[0m\\n" "$1"
|
||||
;;
|
||||
esac
|
||||
if [ -n "${NO_COLOR}" ] ; then
|
||||
printf "%s\\n" "$1"
|
||||
else
|
||||
case "${plat}" in
|
||||
MSYS*|MINGW*)
|
||||
echo -e "\\033[0;35m$1\\033[0m"
|
||||
;;
|
||||
*)
|
||||
printf "\\033[0;35m%s\\033[0m\\n" "$1"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
}
|
||||
|
||||
yellow() {
|
||||
case "${plat}" in
|
||||
MSYS*|MINGW*)
|
||||
echo -e "\\033[0;33m$1\\033[0m"
|
||||
;;
|
||||
*)
|
||||
printf "\\033[0;33m%s\\033[0m\\n" "$1"
|
||||
;;
|
||||
esac
|
||||
if [ -n "${NO_COLOR}" ] ; then
|
||||
printf "%s\\n" "$1"
|
||||
else
|
||||
case "${plat}" in
|
||||
MSYS*|MINGW*)
|
||||
echo -e "\\033[0;33m$1\\033[0m"
|
||||
;;
|
||||
*)
|
||||
printf "\\033[0;33m%s\\033[0m\\n" "$1"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
}
|
||||
|
||||
green() {
|
||||
case "${plat}" in
|
||||
MSYS*|MINGW*)
|
||||
echo -e "\\033[0;32m$1\\033[0m"
|
||||
;;
|
||||
*)
|
||||
printf "\\033[0;32m%s\\033[0m\\n" "$1"
|
||||
;;
|
||||
esac
|
||||
if [ -n "${NO_COLOR}" ] ; then
|
||||
printf "%s\\n" "$1"
|
||||
else
|
||||
case "${plat}" in
|
||||
MSYS*|MINGW*)
|
||||
echo -e "\\033[0;32m$1\\033[0m"
|
||||
;;
|
||||
*)
|
||||
printf "\\033[0;32m%s\\033[0m\\n" "$1"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
}
|
||||
|
||||
edo() {
|
||||
@@ -100,7 +116,7 @@ eghcup() {
|
||||
_eghcup() {
|
||||
if [ -n "${BOOTSTRAP_HASKELL_YAML}" ] ; then
|
||||
args="-s ${BOOTSTRAP_HASKELL_YAML}"
|
||||
fi
|
||||
fi
|
||||
if [ -z "${BOOTSTRAP_HASKELL_VERBOSE}" ] ; then
|
||||
"${GHCUP_BIN}/ghcup" ${args} "$@"
|
||||
else
|
||||
@@ -176,7 +192,15 @@ download_ghcup() {
|
||||
_url=${base_url}/${ghver}/armv7-linux-ghcup-${ghver}
|
||||
;;
|
||||
aarch64|arm64|armv8l)
|
||||
_url=${base_url}/${ghver}/aarch64-linux-ghcup-${ghver}
|
||||
# we could be in a 32bit docker container, in which
|
||||
# case uname doesn't give us what we want
|
||||
if [ "$(getconf LONG_BIT)" = "32" ] ; then
|
||||
_url=${base_url}/${ghver}/armv7-linux-ghcup-${ghver}
|
||||
elif [ "$(getconf LONG_BIT)" = "64" ] ; then
|
||||
_url=${base_url}/${ghver}/aarch64-linux-ghcup-${ghver}
|
||||
else
|
||||
die "Unknown long bit size: $(getconf LONG_BIT)"
|
||||
fi
|
||||
;;
|
||||
*) die "Unknown architecture: ${arch}"
|
||||
;;
|
||||
@@ -293,16 +317,7 @@ ask_bashrc() {
|
||||
|
||||
read -r bashrc_answer </dev/tty
|
||||
else
|
||||
# On windows .bashrc isn't an important user config, so we adjust it
|
||||
# always. On other platforms, let's be a bit more conservative.
|
||||
case "${plat}" in
|
||||
MSYS*|MINGW*)
|
||||
return 1
|
||||
;;
|
||||
*)
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
return 0
|
||||
fi
|
||||
case $bashrc_answer in
|
||||
[Pp]* | "")
|
||||
@@ -406,7 +421,7 @@ warn_path() {
|
||||
echo
|
||||
[ -n "$1" ] && warn "$1"
|
||||
yellow "In order to run ghc and cabal, you need to adjust your PATH variable."
|
||||
yellow "To do so, you may want run 'source $GHCUP_DIR/env' in your current terminal"
|
||||
yellow "To do so, you may want to run 'source $GHCUP_DIR/env' in your current terminal"
|
||||
yellow "session as well as your shell configuration (e.g. ~/.bashrc)."
|
||||
|
||||
}
|
||||
@@ -678,4 +693,3 @@ _done
|
||||
)
|
||||
|
||||
# vim: tabstop=4 shiftwidth=4 expandtab
|
||||
|
||||
19
stack.yaml
19
stack.yaml
@@ -4,24 +4,21 @@ packages:
|
||||
- .
|
||||
|
||||
extra-deps:
|
||||
- git: https://github.com/bgamari/terminal-size
|
||||
commit: 34ea816bd63f75f800eedac12c6908c6f3736036
|
||||
|
||||
- git: https://github.com/hasufell/libarchive
|
||||
commit: 8587aab78dd515928024ecd82c8f215e06db85cd
|
||||
|
||||
- brick-0.64@sha256:f03fa14607c22cf48af99e24c44f79a0fb073f7ec229f15e969fed9ff73c93f6,16530
|
||||
- IfElse-0.85@sha256:6939b94acc6a55f545f63a168a349dd2fbe4b9a7cca73bf60282db5cc6aa47d2,445
|
||||
- ascii-string-1.0.1.4@sha256:fa34f1d9ba57e8e89c0d4c9cef5e01ba32cb2d4373d13f92dcc0b531a6c6749b,2582
|
||||
- base16-bytestring-0.1.1.7@sha256:0021256a9628971c08da95cb8f4d0d72192f3bb8a7b30b55c080562d17c43dd3,2231
|
||||
- brick-0.64@sha256:f03fa14607c22cf48af99e24c44f79a0fb073f7ec229f15e969fed9ff73c93f6,16530
|
||||
- brotli-0.0.0.0@sha256:2bf383a4cd308745740986be0b18381c5a0784393fe69b91456aacb2d603de46,2964
|
||||
- brotli-streams-0.0.0.0@sha256:1af1e22f67b8bfd6ad0d05e61825e7a178d738f689ebbb21c1aab5f1bbcae176,2331
|
||||
- chs-cabal-0.1.1.0@sha256:20ec6a9fb5ab6991f1a4adf157c537bd5d3b98d08d3c09c387c954c7c50bd011,1153
|
||||
- chs-deps-0.1.0.0@sha256:0cdada6d2c682c41b20331b8c63c2ecfc7e806928585195fd544c9d41f3074fd,2496
|
||||
- composition-prelude-3.0.0.2@sha256:1ffed216bd28d810fce0b5be83a661e2a892696d73b3f8de5c0f5edb9b5f0090,1216
|
||||
- haskus-utils-data-1.3@sha256:f62c4e49021b463185d043f7b69c727b63af641a71d7edd582d9f4f98e80e500,1466
|
||||
- haskus-utils-data-1.4@sha256:bfa94363b94b14779edd6834fbd59dbb847c3d7b8f48e3844f456ffdc077da4a,1466
|
||||
- haskus-utils-types-1.5.1@sha256:991c472f4e751e2f0d7aab6ad4220ef151d6160876dcf0511bbf876bbd432020,1298
|
||||
- haskus-utils-variant-3.0@sha256:8d51e45d3b664e61ccc25a58b37c0ccc4ee7537138b9fee21cd15c356906dd34,2159
|
||||
- haskus-utils-variant-3.1@sha256:e602dd23e068c98d03c1027af20503addef8df6368577622453f44ccabea2a5b,2159
|
||||
- hpath-filepath-0.10.4@sha256:e9e44fb5fdbade7f30b5b5451257dbee15b6ef1aae4060034d73008bb3b5d878,1269
|
||||
- hpath-posix-0.13.3@sha256:abe472cf16bccd3a8b8814865ed3551a728fde0f3a2baea2acc03023bec6c565,1615
|
||||
- hspec-2.7.10@sha256:c9e82c90086acebac576552a06f3cabd249bba048edd1667c7fae0b1313d5bce,1712
|
||||
@@ -30,11 +27,11 @@ extra-deps:
|
||||
- hspec-golden-aeson-0.9.0.0@sha256:aa17274114026661ba4dfc9c60c230673c8f408bd86482fd611d2d5cb6aff996,2179
|
||||
- http-io-streams-0.1.6.0@sha256:53f5bab177efb52cd65ec396fd04ed59b93e5f919fb3700cd7dacd6cfce6f06d,3582
|
||||
- lzma-static-5.2.5.3@sha256:2758ee58c35992fcf7db78e98684c357a16a82fa2a4e7c352a6c210c08c555d8,7308
|
||||
- os-release-1.0.1@sha256:1281c62081f438fc3f0874d3bae6a4887d5964ac25261ba06e29d368ab173467,2716
|
||||
- optics-0.4@sha256:9fb69bf0195b8d8f1f8cd0098000946868b8a3c3ffb51e5b64f79fc600c3eb4c,6568
|
||||
- optics-core-0.4@sha256:59e04aebca536bd011ae50c781937f45af4c1456af1eb9fb578f9a69eee293cd,4995
|
||||
- optics-extra-0.4@sha256:b9914f38aa7d5c92f231060d9168447f9f5a367c07df9bf47a003e3e786d5e05,3432
|
||||
- optics-th-0.4@sha256:7c838b5b1d6998133bf8f0641c36197ed6cb468dc69515e1952f33f0bbe8e11d,2009
|
||||
- os-release-1.0.1@sha256:1281c62081f438fc3f0874d3bae6a4887d5964ac25261ba06e29d368ab173467,2716
|
||||
- primitive-0.7.1.0@sha256:29de6bfd0cf8ba023ceb806203dfbec0e51e3524e75ffe41056f70b4229c6f0f,2728
|
||||
- regex-posix-clib-2.7
|
||||
- streamly-0.7.3@sha256:ad2a488fe802692ed47cab9fd0416c2904aac9e51cf2d8aafd1c3a40064c42f5,27421
|
||||
@@ -63,3 +60,11 @@ ghc-options:
|
||||
"$locals": -O2
|
||||
streamly: -O2 -fspec-constr-recursive=16 -fmax-worker-args=16
|
||||
ghcup: -O2 -fspec-constr-recursive=16 -fmax-worker-args=16
|
||||
|
||||
build:
|
||||
test: true
|
||||
test-arguments:
|
||||
no-run-tests: true
|
||||
bench: true
|
||||
benchmark-opts:
|
||||
no-run-benchmarks: true
|
||||
|
||||
@@ -13,4 +13,5 @@ import Test.Hspec
|
||||
|
||||
spec :: Spec
|
||||
spec = do
|
||||
roundtripAndGoldenSpecs (Proxy @GHCupInfo)
|
||||
roundtripAndGoldenSpecsWithSettings (defaultSettings { goldenDirectoryOption = CustomDirectoryName "test/golden" }) (Proxy @GHCupInfo)
|
||||
|
||||
|
||||
@@ -174,7 +174,17 @@ span.code {
|
||||
line-height: 2rem;
|
||||
}
|
||||
|
||||
#help {
|
||||
margin-bottom: 0px !important;
|
||||
}
|
||||
|
||||
#collective {
|
||||
margin-top: 1em !important;
|
||||
margin-bottom: 0px !important;
|
||||
}
|
||||
|
||||
#about {
|
||||
margin-top: 0.5em !important;
|
||||
font-size: 16px;
|
||||
line-height: 2em;
|
||||
}
|
||||
|
||||
@@ -137,9 +137,14 @@
|
||||
|
||||
</div>
|
||||
|
||||
<p>
|
||||
<p id="help">
|
||||
Need help? Ask on <a href="https://kiwiirc.com/nextclient/irc.libera.chat/?nick=Guest%7C?#haskell,#haskell-ghcup"><img src="irc.svg" height="18px" alt="" />IRC</a>, <a href="https://discord.gg/pKYf3zDQU7"><img src="Discord-Logo-Black.svg" height="18px" alt="" />Discord</a>, <a href="https://app.element.io/#/room/#haskell-tooling:matrix.org"><img src="Matrix_logo.svg" height="25px" alt="" style="top:5px;position:relative;" /></a> or <a href="https://gitlab.haskell.org/haskell/ghcup-hs/issues">report a bug <img src="Octicons-bug.svg" height="18px" alt="" /></a>.
|
||||
</p>
|
||||
<p id="collective">
|
||||
<a id="collective" href="https://opencollective.com/ghcup#category-CONTRIBUTE" target="_blank">
|
||||
<img src="https://opencollective.com/webpack/donate/button@2x.png?color=blue" width=200 />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<p id="about">
|
||||
<img src="haskell-logo.svg" alt="" />
|
||||
|
||||
Reference in New Issue
Block a user