Compare commits
46 Commits
879bd061dd
...
34b9ea7d20
Author | SHA1 | Date |
---|---|---|
Julian Ospald | 34b9ea7d20 | |
Julian Ospald | 0ff7ebb1fd | |
Julian Ospald | f83dcbc430 | |
Julian Ospald | 56e4a6b15f | |
Julian Ospald | ee9b2ec30d | |
Julian Ospald | 640cf1e2c1 | |
Julian Ospald | 56c439d716 | |
Julian Ospald | 1ed6e49a81 | |
Julian Ospald | fad9f83e6a | |
Julian Ospald | 2e28b0d00f | |
Julian Ospald | ed4ff15f96 | |
Julian Ospald | 1d623723a2 | |
Julian Ospald | 931080244f | |
Julian Ospald | 27e2e7f848 | |
Julian Ospald | 8b638c7ecb | |
Julian Ospald | acd370611f | |
Julian Ospald | e1b5a89cee | |
Julian Ospald | 5edebd57d9 | |
Julian Ospald | bcaccaaf31 | |
Julian Ospald | 818a5d2d85 | |
Julian Ospald | 13acce07d4 | |
Julian Ospald | 4ed5e21b7f | |
Julian Ospald | 86aab6bb59 | |
Julian Ospald | 7f5cb64b18 | |
Julian Ospald | 6c12eb16eb | |
Julian Ospald | e637f90fae | |
Julian Ospald | 5b33c3f491 | |
Julian Ospald | 1842ed464f | |
Julian Ospald | 296bbdd561 | |
Julian Ospald | 27ead1be7c | |
Julian Ospald | 5184609dba | |
Julian Ospald | 5d94d0bf75 | |
Julian Ospald | 72bcfa9270 | |
Julian Ospald | fafff9dadd | |
Julian Ospald | e3c20d53a8 | |
Julian Ospald | 8b7dc68491 | |
Julian Ospald | 7742fe08b5 | |
Julian Ospald | a773da037c | |
Julian Ospald | dfeb814dcc | |
Julian Ospald | 0623c7b1b1 | |
Julian Ospald | 62005f83a4 | |
Julian Ospald | eaafd77a7e | |
Julian Ospald | 9d9e415a09 | |
Julian Ospald | 6c1ae585b7 | |
Julian Ospald | 793aad7b6c | |
Julian Ospald | fd7807a66e |
153
.gitlab-ci.yml
153
.gitlab-ci.yml
|
@ -12,16 +12,52 @@ variables:
|
|||
image: "registry.gitlab.haskell.org/ghc/ci-images/x86_64-linux-deb9:$DOCKER_REV"
|
||||
tags:
|
||||
- x86_64-linux
|
||||
variables:
|
||||
OS: "LINUX"
|
||||
|
||||
.alpine:64bit:
|
||||
image: "alpine:edge"
|
||||
tags:
|
||||
- x86_64-linux
|
||||
variables:
|
||||
OS: "LINUX"
|
||||
BIT: "64"
|
||||
|
||||
.alpine:32bit:
|
||||
image: "i386/alpine:edge"
|
||||
tags:
|
||||
- x86_64-linux
|
||||
variables:
|
||||
OS: "LINUX"
|
||||
BIT: "32"
|
||||
|
||||
.darwin:
|
||||
tags:
|
||||
- x86_64-darwin
|
||||
variables:
|
||||
OS: "DARWIN"
|
||||
|
||||
.freebsd:
|
||||
tags:
|
||||
- x86_64-freebsd
|
||||
variables:
|
||||
OS: "FREEBSD"
|
||||
|
||||
.root_cleanup:
|
||||
after_script:
|
||||
- BUILD_DIR=$CI_PROJECT_DIR
|
||||
- echo "Cleaning $BUILD_DIR"
|
||||
- cd $HOME
|
||||
- test -n "$BUILD_DIR"
|
||||
- shopt -s extglob
|
||||
- rm -Rf "$BUILD_DIR"/!(out)
|
||||
- exit 0
|
||||
|
||||
.test_ghcup_version:
|
||||
script:
|
||||
- ./.gitlab/script/ghcup_version.sh
|
||||
variables:
|
||||
JSON_VERSION: "0.0.1"
|
||||
JSON_VERSION: "0.0.2"
|
||||
|
||||
.test_ghcup_version:linux:
|
||||
extends:
|
||||
|
@ -29,50 +65,133 @@ variables:
|
|||
- .debian
|
||||
before_script:
|
||||
- ./.gitlab/before_script/linux/install_deps.sh
|
||||
variables:
|
||||
OS: "LINUX"
|
||||
|
||||
.test_ghcup_version:darwin:
|
||||
extends:
|
||||
- .test_ghcup_version
|
||||
- .darwin
|
||||
- .root_cleanup
|
||||
before_script:
|
||||
- ./.gitlab/before_script/darwin/install_deps.sh
|
||||
variables:
|
||||
OS: "DARWIN"
|
||||
after_script:
|
||||
- BUILD_DIR=$CI_PROJECT_DIR
|
||||
- echo "Cleaning $BUILD_DIR"
|
||||
- cd $HOME
|
||||
- rm -Rf "$BUILD_DIR"/*
|
||||
- exit 0
|
||||
|
||||
.test_ghcup_version:freebsd:
|
||||
extends:
|
||||
- .test_ghcup_version
|
||||
- .freebsd
|
||||
- .root_cleanup
|
||||
before_script:
|
||||
- ./.gitlab/before_script/freebsd/install_deps.sh
|
||||
|
||||
.release_ghcup:
|
||||
script:
|
||||
- ./.gitlab/script/ghcup_release.sh
|
||||
artifacts:
|
||||
expire_in: 2 week
|
||||
paths:
|
||||
- out
|
||||
only:
|
||||
- tags
|
||||
|
||||
######## linux ########
|
||||
######## linux test ########
|
||||
|
||||
test:linux:recommended:
|
||||
extends: .test_ghcup_version:linux
|
||||
variables:
|
||||
GHC_VERSION: "recommended"
|
||||
GHC_VERSION: "8.6.5"
|
||||
CABAL_VERSION: "3.2.0.0"
|
||||
|
||||
test:linux:latest:
|
||||
extends: .test_ghcup_version:linux
|
||||
variables:
|
||||
GHC_VERSION: "latest"
|
||||
GHC_VERSION: "8.8.3"
|
||||
CABAL_VERSION: "3.2.0.0"
|
||||
allow_failure: true
|
||||
|
||||
|
||||
######## darwin ########
|
||||
######## darwin test ########
|
||||
|
||||
test:mac:recommended:
|
||||
extends: .test_ghcup_version:darwin
|
||||
variables:
|
||||
GHC_VERSION: "recommended"
|
||||
GHC_VERSION: "8.6.5"
|
||||
CABAL_VERSION: "3.2.0.0"
|
||||
|
||||
test:mac:latest:
|
||||
extends: .test_ghcup_version:darwin
|
||||
variables:
|
||||
GHC_VERSION: "latest"
|
||||
GHC_VERSION: "8.8.3"
|
||||
CABAL_VERSION: "3.2.0.0"
|
||||
allow_failure: true
|
||||
|
||||
|
||||
######## freebsd test ########
|
||||
|
||||
test:freebsd:recommended:
|
||||
extends: .test_ghcup_version:freebsd
|
||||
variables:
|
||||
GHC_VERSION: "8.6.5"
|
||||
CABAL_VERSION: "3.2.0.0"
|
||||
|
||||
test:freebsd:latest:
|
||||
extends: .test_ghcup_version:freebsd
|
||||
variables:
|
||||
GHC_VERSION: "8.8.3"
|
||||
CABAL_VERSION: "3.2.0.0"
|
||||
allow_failure: true
|
||||
|
||||
|
||||
######## linux release ########
|
||||
|
||||
release:linux:64bit:
|
||||
extends:
|
||||
- .alpine:64bit
|
||||
- .release_ghcup
|
||||
before_script:
|
||||
- ./.gitlab/before_script/linux/alpine/install_deps.sh
|
||||
variables:
|
||||
ARTIFACT: "x86_64-linux-ghcup"
|
||||
GHC_VERSION: "8.8.3"
|
||||
CABAL_VERSION: "3.2.0.0"
|
||||
|
||||
|
||||
release:linux:32bit:
|
||||
extends:
|
||||
- .alpine:32bit
|
||||
- .release_ghcup
|
||||
before_script:
|
||||
- ./.gitlab/before_script/linux/alpine/install_deps.sh
|
||||
variables:
|
||||
ARTIFACT: "i386-linux-ghcup"
|
||||
GHC_VERSION: "8.8.3"
|
||||
CABAL_VERSION: "3.2.0.0"
|
||||
|
||||
|
||||
######## darwin release ########
|
||||
|
||||
release:darwin:
|
||||
extends:
|
||||
- .darwin
|
||||
- .release_ghcup
|
||||
- .root_cleanup
|
||||
before_script:
|
||||
- ./.gitlab/before_script/darwin/install_deps.sh
|
||||
variables:
|
||||
ARTIFACT: "x86_64-apple-darwin-ghcup"
|
||||
GHC_VERSION: "8.8.3"
|
||||
CABAL_VERSION: "3.2.0.0"
|
||||
MACOSX_DEPLOYMENT_TARGET: "10.7"
|
||||
|
||||
|
||||
######## freebsd release ########
|
||||
|
||||
release:freebsd:
|
||||
extends:
|
||||
- .freebsd
|
||||
- .release_ghcup
|
||||
- .root_cleanup
|
||||
before_script:
|
||||
- ./.gitlab/before_script/freebsd/install_deps.sh
|
||||
variables:
|
||||
ARTIFACT: "x86_64-portbld-freebsd-ghcup"
|
||||
GHC_VERSION: "8.6.5"
|
||||
|
||||
|
|
|
@ -4,11 +4,11 @@ set -eux
|
|||
|
||||
. "$( cd "$(dirname "$0")" ; pwd -P )/../../ghcup_env"
|
||||
|
||||
curl -sSfL https://gitlab.haskell.org/haskell/ghcup/-/raw/master/ghcup > ./ghcup-legacy
|
||||
chmod +x ghcup-legacy
|
||||
curl -sSfL https://downloads.haskell.org/~ghcup/x86_64-apple-darwin-ghcup > ./ghcup-bin
|
||||
chmod +x ghcup-bin
|
||||
|
||||
./ghcup-legacy install ${GHC_VERSION}
|
||||
./ghcup-legacy set ${GHC_VERSION}
|
||||
./ghcup-legacy install-cabal
|
||||
./ghcup-bin install ${GHC_VERSION}
|
||||
./ghcup-bin set ${GHC_VERSION}
|
||||
./ghcup-bin install-cabal ${CABAL_VERSION}
|
||||
|
||||
exit 0
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -eux
|
||||
|
||||
# pkg install --force --yes --no-repo-update curl gcc gmp gmake ncurses perl5 libffi libiconv
|
||||
|
||||
. "$( cd "$(dirname "$0")" ; pwd -P )/../../ghcup_env"
|
||||
|
||||
curl -sSfL https://downloads.haskell.org/~ghcup/x86_64-portbld-freebsd-ghcup > ./ghcup-bin
|
||||
chmod +x ghcup-bin
|
||||
|
||||
mkdir -p "${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup/bin
|
||||
# ./ghcup-bin install ${GHC_VERSION}
|
||||
# ./ghcup-bin install-cabal ${CABAL_VERSION}
|
||||
# ./ghcup-bin set ${GHC_VERSION}
|
||||
|
||||
# install cabal-3.2.0.0
|
||||
curl -sSfL -o cabal-install-3.2.0.0-x86_64-portbld-freebsd.tar.xz 'https://hasufell.de/d/d3e215db133e4fcaa61e/files/?p=/cabal-install-3.2.0.0-x86_64-portbld-freebsd.tar.xz&dl=1'
|
||||
tar xf cabal-install-3.2.0.0-x86_64-portbld-freebsd.tar.xz
|
||||
cp cabal "${GHCUP_INSTALL_BASE_PREFIX}/.ghcup/bin/cabal"
|
||||
chmod +x "${GHCUP_INSTALL_BASE_PREFIX}/.ghcup/bin/cabal"
|
||||
|
||||
exit 0
|
|
@ -0,0 +1,61 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -eux
|
||||
|
||||
. "$( cd "$(dirname "$0")" ; pwd -P )/../../../ghcup_env"
|
||||
|
||||
apk add --no-cache \
|
||||
curl \
|
||||
gcc \
|
||||
g++ \
|
||||
gmp-dev \
|
||||
ncurses-dev \
|
||||
libffi-dev \
|
||||
make \
|
||||
xz \
|
||||
tar \
|
||||
perl
|
||||
|
||||
ln -s libncurses.so /usr/lib/libtinfo.so
|
||||
ln -s libncursesw.so.6 /usr/lib/libtinfow.so.6
|
||||
if [ "${BIT}" = "32" ] ; then
|
||||
curl -sSfL https://downloads.haskell.org/~ghcup/0.1.4/i386-linux-ghcup-0.1.4 > ./ghcup-bin
|
||||
else
|
||||
curl -sSfL https://downloads.haskell.org/~ghcup/0.1.4/x86_64-linux-ghcup-0.1.4 > ./ghcup-bin
|
||||
fi
|
||||
chmod +x ghcup-bin
|
||||
./ghcup-bin upgrade
|
||||
./ghcup-bin install ${GHC_VERSION}
|
||||
# ./ghcup-bin install-cabal ${CABAL_VERSION}
|
||||
# install cabal-3.2.0.0
|
||||
if [ "${BIT}" = "32" ] ; then
|
||||
curl -sSfL -o cabal-install-3.2.0.0-i386-alpine-linux-musl.tar.xz 'https://hasufell.de/d/d3e215db133e4fcaa61e/files/?p=/cabal-install-3.2.0.0-i386-alpine-linux-musl.tar.xz&dl=1'
|
||||
tar xf cabal-install-3.2.0.0-i386-alpine-linux-musl.tar.xz
|
||||
cp cabal-install-3.2.0.0-i386-alpine-linux-musl "${GHCUP_INSTALL_BASE_PREFIX}/.ghcup/bin/cabal"
|
||||
else
|
||||
curl -sSfL -o cabal-install-3.2.0.0-x86_64-alpine-linux-musl.tar.xz 'https://hasufell.de/d/d3e215db133e4fcaa61e/files/?p=/cabal-install-3.2.0.0-x86_64-alpine-linux-musl.tar.xz&dl=1'
|
||||
tar xf cabal-install-3.2.0.0-x86_64-alpine-linux-musl.tar.xz
|
||||
cp cabal-install-3.2.0.0-x86_64-alpine-linux-musl "${GHCUP_INSTALL_BASE_PREFIX}/.ghcup/bin/cabal"
|
||||
fi
|
||||
chmod +x "${GHCUP_INSTALL_BASE_PREFIX}/.ghcup/bin/cabal"
|
||||
|
||||
|
||||
# utils
|
||||
apk add --no-cache \
|
||||
bash \
|
||||
git
|
||||
|
||||
## Package specific
|
||||
apk add --no-cache \
|
||||
zlib \
|
||||
zlib-dev \
|
||||
zlib-static \
|
||||
gmp \
|
||||
gmp-dev \
|
||||
openssl-dev \
|
||||
openssl-libs-static \
|
||||
xz \
|
||||
xz-dev
|
||||
|
||||
|
||||
|
|
@ -3,14 +3,14 @@
|
|||
set -eux
|
||||
|
||||
sudo apt-get update -y
|
||||
sudo apt-get install -y libnuma-dev zlib1g-dev libgmp-dev libgmp10 libssl-dev liblzma-dev
|
||||
sudo apt-get install -y libnuma-dev zlib1g-dev libgmp-dev libgmp10 libssl-dev liblzma-dev git wget
|
||||
|
||||
. "$( cd "$(dirname "$0")" ; pwd -P )/../../ghcup_env"
|
||||
|
||||
curl -sSfL https://gitlab.haskell.org/haskell/ghcup/-/raw/master/ghcup > ./ghcup-legacy
|
||||
chmod +x ghcup-legacy
|
||||
curl -sSfL https://downloads.haskell.org/~ghcup/x86_64-linux-ghcup > ./ghcup-bin
|
||||
chmod +x ghcup-bin
|
||||
|
||||
./ghcup-legacy install ${GHC_VERSION}
|
||||
./ghcup-legacy set ${GHC_VERSION}
|
||||
./ghcup-legacy install-cabal
|
||||
./ghcup-bin install ${GHC_VERSION}
|
||||
./ghcup-bin set ${GHC_VERSION}
|
||||
./ghcup-bin install-cabal ${CABAL_VERSION}
|
||||
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -eux
|
||||
|
||||
. "$( cd "$(dirname "$0")" ; pwd -P )/../ghcup_env"
|
||||
|
||||
mkdir -p "$CI_PROJECT_DIR"/.local/bin
|
||||
|
||||
ecabal() {
|
||||
cabal --store-dir="$(pwd)"/.store "$@"
|
||||
}
|
||||
|
||||
git describe
|
||||
|
||||
# build
|
||||
ecabal update
|
||||
|
||||
if [ "${OS}" = "LINUX" ] ; then
|
||||
ecabal build -w ghc-${GHC_VERSION} --ghc-options='-split-sections -optl-static'
|
||||
elif [ "${OS}" = "FREEBSD" ] ; then
|
||||
ecabal build -w ghc-${GHC_VERSION} --ghc-options='-split-sections'
|
||||
else
|
||||
ecabal build -w ghc-${GHC_VERSION}
|
||||
fi
|
||||
|
||||
mkdir out
|
||||
cp "$(ecabal new-exec -w ghc-${GHC_VERSION} --verbose=0 --offline sh -- -c 'command -v ghcup')" .
|
||||
ver=$(./ghcup --numeric-version)
|
||||
cp ghcup out/${ARTIFACT}-${ver}
|
||||
|
|
@ -14,32 +14,45 @@ eghcup() {
|
|||
ghcup -v -c -s file://$(pwd)/ghcup-${JSON_VERSION}.json "$@"
|
||||
}
|
||||
|
||||
# build
|
||||
git describe
|
||||
|
||||
### build
|
||||
|
||||
ecabal update
|
||||
|
||||
if [ "${OS}" = "DARWIN" ] ; then
|
||||
ecabal build -fcurl
|
||||
ecabal build -w ghc-${GHC_VERSION}
|
||||
else
|
||||
ecabal build
|
||||
ecabal build -w ghc-${GHC_VERSION} -finternal-downloader
|
||||
fi
|
||||
|
||||
cp "$(ecabal new-exec --enable-tests --verbose=0 --offline sh -- -c 'command -v ghcup')" .
|
||||
cp "$(ecabal new-exec --enable-tests --verbose=0 --offline sh -- -c 'command -v ghcup-gen')" .
|
||||
|
||||
|
||||
# testing
|
||||
|
||||
cp ./ghcup "$CI_PROJECT_DIR"/.local/bin/ghcup
|
||||
cp ./ghcup-gen "$CI_PROJECT_DIR"/.local/bin/ghcup-gen
|
||||
|
||||
### cleanup
|
||||
|
||||
rm -rf "${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup
|
||||
|
||||
|
||||
### manual cli based testing
|
||||
|
||||
|
||||
ghcup-gen check -f ghcup-${JSON_VERSION}.json
|
||||
|
||||
eghcup numeric-version
|
||||
eghcup --numeric-version
|
||||
|
||||
# TODO: rm once we have tarballs
|
||||
if [ "${OS}" = "FREEBSD" ] ; then
|
||||
GHC_VERSION=8.6.3
|
||||
CABAL_VERSION=2.4.1.0
|
||||
fi
|
||||
|
||||
eghcup install ${GHC_VERSION}
|
||||
eghcup set ${GHC_VERSION}
|
||||
eghcup install-cabal
|
||||
eghcup install-cabal ${CABAL_VERSION}
|
||||
|
||||
cabal --version
|
||||
|
||||
|
@ -58,7 +71,11 @@ ghci-$(ghc --numeric-version) --version
|
|||
|
||||
# test installing new ghc doesn't mess with currently set GHC
|
||||
# https://gitlab.haskell.org/haskell/ghcup-hs/issues/7
|
||||
eghcup install 8.4.4
|
||||
if [ "${OS}" = "DARWIN" ] ; then
|
||||
eghcup install 8.4.4
|
||||
else # test wget a bit
|
||||
eghcup --downloader=wget install 8.4.4
|
||||
fi
|
||||
[ "$(ghc --numeric-version)" = "${ghc_ver}" ]
|
||||
eghcup set 8.4.4
|
||||
eghcup set 8.4.4
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Revision history for ghcup
|
||||
|
||||
## 0.1.4 -- 2012-04-16
|
||||
## 0.1.4 -- 2020-04-16
|
||||
|
||||
* build on all platforms with curl (as a binary), wrt https://gitlab.haskell.org/haskell/ghcup-hs/issues/6
|
||||
* Fix unlinking of ghc symlinks after new installation, wrt https://gitlab.haskell.org/haskell/ghcup-hs/issues/7
|
||||
|
|
12
HACKING.md
12
HACKING.md
|
@ -43,3 +43,15 @@ Kazu Yamamoto [explained it in his PR](https://github.com/yesodweb/wai/pull/752#
|
|||
1. Brittany
|
||||
2. mtl-style preferred
|
||||
3. no overly pointfree style
|
||||
|
||||
## Code structure
|
||||
|
||||
Main functionality is in `GHCup` module. Utility functions are
|
||||
organised tree-ish in `GHCup.Utils` and `GHCup.Utils.*`.
|
||||
|
||||
Anything dealing with ghcup specific directories is in
|
||||
`GHCup.Utils.Dirs`.
|
||||
|
||||
Download information on where to fetch bindists from is in
|
||||
`GHCup.Data.GHCupDownloads`.
|
||||
|
||||
|
|
12
README.md
12
README.md
|
@ -68,6 +68,15 @@ handles your haskell packages and can demand that [a specific version](https://c
|
|||
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.
|
||||
`MANPATH` may be required to be unset.
|
||||
|
||||
### Shell-completion
|
||||
|
||||
Shell completions are in `shell-completions`.
|
||||
|
||||
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).
|
||||
|
||||
## Design goals
|
||||
|
||||
1. simplicity
|
||||
|
@ -142,3 +151,6 @@ ghcup is not a reimplementation of stack. The only common part is automatic inst
|
|||
|
||||
Consider using [Chocolatey](https://chocolatey.org/search?q=ghc) or [ghcups](https://github.com/kakkun61/ghcups).
|
||||
|
||||
3. Why the haskell reimplementation?
|
||||
|
||||
Why not?
|
||||
|
|
|
@ -4,8 +4,11 @@
|
|||
|
||||
2. Add/fix downloads to `GHCupDownloads` module, then run `ghcup-gen gen` to generate the new json and validate it via `ghcup-gen check`.
|
||||
|
||||
3. Commit and git push with tag. Wait for tests to succeed.
|
||||
3. Commit and git push with tag. Wait for tests to succeed and release artifacts to build.
|
||||
|
||||
4. Upload the new `ghcup-<ver>.json` to `webhost.haskell.org/ghcup/data/`.
|
||||
4. Download release artifacts and upload them `downloads.haskell.org/ghcup`
|
||||
|
||||
5. Add release artifacts to GHCupDownloads (see point 2.)
|
||||
|
||||
6. Upload the final `ghcup-<ver>.json` to `webhost.haskell.org/ghcup/data/`.
|
||||
|
||||
5. Build ghcup releases for Linux (fully static), mac (with `-fcurl`) and FreeBSD (with `-fcurl`). Upload to `webhost.haskell.org/ghcup/bin/` and update symlinks.
|
||||
|
|
20
TODO.md
20
TODO.md
|
@ -2,27 +2,39 @@
|
|||
|
||||
## Now
|
||||
|
||||
* move out GHCup.Version module, bc it's not library-ish
|
||||
* try to run exe before upgrade (backup to ~/.ghcup/bin/ghcup.old)
|
||||
* allow to build 8.8
|
||||
* curl DL does not cache json
|
||||
* explain environment variables
|
||||
* add --keep=<always|error> option
|
||||
|
||||
* allow to switch to curl/wget at runtime
|
||||
|
||||
* cross support
|
||||
* installing multiple versions of the same
|
||||
|
||||
* proper test suite
|
||||
* add more logging
|
||||
|
||||
|
||||
## Maybe
|
||||
|
||||
* maybe: changelog Show the changelog of a GHC release (online)
|
||||
* version ranges in json
|
||||
* sign the JSON? (Or check gpg keys?)
|
||||
* testing (especially distro detection -> unit tests)
|
||||
|
||||
## Later
|
||||
|
||||
* i386 support
|
||||
* add support for RC/alpha/HEAD versions
|
||||
|
||||
## Cleanups
|
||||
|
||||
* too many decodeutf8
|
||||
* avoid alternative for IO
|
||||
* use plucky or oops instead of Excepts
|
||||
|
||||
## Questions
|
||||
|
||||
* move out GHCup.Version module, bc it's not library-ish?
|
||||
* mirror support
|
||||
* interactive handling when distro doesn't exist and we know the tarball is incompatible?
|
||||
* ghcup-with wrapper to execute a command with a given ghc in PATH?
|
||||
|
|
|
@ -10,10 +10,10 @@
|
|||
|
||||
module Main where
|
||||
|
||||
import GHCup.Data.GHCupInfo
|
||||
import GHCup.Types
|
||||
import GHCup.Types.JSON ( )
|
||||
import GHCup.Utils.Logger
|
||||
import GHCupInfo
|
||||
|
||||
import Data.Aeson ( eitherDecode, encode )
|
||||
import Data.Aeson.Encode.Pretty
|
||||
|
|
|
@ -63,6 +63,7 @@ validate dls = do
|
|||
|
||||
checkGHCisSemver
|
||||
forM_ (M.toList dls) $ \(t, _) -> checkMandatoryTags t
|
||||
_ <- checkGHCHasBaseVersion
|
||||
|
||||
-- exit
|
||||
e <- liftIO $ readIORef ref
|
||||
|
@ -85,7 +86,7 @@ validate dls = do
|
|||
[i|FreeBSD missing for #{t} #{v'} #{arch}|]
|
||||
|
||||
checkUniqueTags tool = do
|
||||
let allTags = join $ fmap snd $ availableToolVersions dls tool
|
||||
let allTags = join $ M.elems $ availableToolVersions dls tool
|
||||
let nonUnique =
|
||||
fmap fst
|
||||
. filter (\(_, b) -> not b)
|
||||
|
@ -105,8 +106,10 @@ validate dls = do
|
|||
lift $ $(logError) [i|Tags not unique for #{tool}: #{xs}|]
|
||||
addError
|
||||
where
|
||||
isUniqueTag Latest = True
|
||||
isUniqueTag Recommended = True
|
||||
isUniqueTag Latest = True
|
||||
isUniqueTag Recommended = True
|
||||
isUniqueTag (Base _) = False
|
||||
isUniqueTag (UnknownTag _) = False
|
||||
|
||||
checkGHCisSemver = do
|
||||
let ghcVers = toListOf (ix GHC % to M.keys % folded) dls
|
||||
|
@ -118,13 +121,24 @@ validate dls = do
|
|||
|
||||
-- a tool must have at least one of each mandatory tags
|
||||
checkMandatoryTags tool = do
|
||||
let allTags = join $ fmap snd $ availableToolVersions dls tool
|
||||
let allTags = join $ M.elems $ availableToolVersions dls tool
|
||||
forM_ [Latest, Recommended] $ \t -> case elem t allTags of
|
||||
False -> do
|
||||
lift $ $(logError) [i|Tag #{t} missing from #{tool}|]
|
||||
addError
|
||||
True -> pure ()
|
||||
|
||||
-- all GHC versions must have a base tag
|
||||
checkGHCHasBaseVersion = do
|
||||
let allTags = M.toList $ availableToolVersions dls GHC
|
||||
forM allTags $ \(ver, tags) -> case any isBase tags of
|
||||
False -> do
|
||||
lift $ $(logError) [i|Base tag missing from GHC ver #{ver}|]
|
||||
addError
|
||||
True -> pure ()
|
||||
|
||||
isBase (Base _) = True
|
||||
isBase _ = False
|
||||
|
||||
validateTarballs :: ( Monad m
|
||||
, MonadLogger m
|
||||
|
@ -161,7 +175,7 @@ validateTarballs dls = do
|
|||
|
||||
where
|
||||
downloadAll dli = do
|
||||
let settings = Settings True False
|
||||
let settings = Settings True False Never Curl
|
||||
let runLogger = myLoggerT LoggerConfig { lcPrintDebug = True
|
||||
, colorOutter = B.hPut stderr
|
||||
, rawOutter = (\_ -> pure ())
|
||||
|
|
|
@ -17,6 +17,7 @@ import GHCup.Platform
|
|||
import GHCup.Requirements
|
||||
import GHCup.Types
|
||||
import GHCup.Utils
|
||||
import GHCup.Utils.File
|
||||
import GHCup.Utils.Logger
|
||||
import GHCup.Utils.Prelude
|
||||
import GHCup.Version
|
||||
|
@ -31,7 +32,9 @@ import Data.Bifunctor
|
|||
import Data.Char
|
||||
import Data.Either
|
||||
import Data.Functor
|
||||
import Data.List ( intercalate )
|
||||
import Data.List ( intercalate, sort )
|
||||
import Data.List.NonEmpty (NonEmpty ((:|)))
|
||||
import Data.Maybe
|
||||
import Data.String.Interpolate
|
||||
import Data.Text ( Text )
|
||||
import Data.Versions
|
||||
|
@ -40,8 +43,11 @@ import GHC.IO.Encoding
|
|||
import Haskus.Utils.Variant.Excepts
|
||||
import HPath
|
||||
import HPath.IO
|
||||
import Language.Haskell.TH
|
||||
import Options.Applicative hiding ( style )
|
||||
import Options.Applicative.Help.Pretty ( text )
|
||||
import Prelude hiding ( appendFile )
|
||||
import Safe
|
||||
import System.Console.Pretty
|
||||
import System.Environment
|
||||
import System.Exit
|
||||
|
@ -68,6 +74,8 @@ data Options = Options
|
|||
, optCache :: Bool
|
||||
, optUrlSource :: Maybe URI
|
||||
, optNoVerify :: Bool
|
||||
, optKeepDirs :: KeepDirs
|
||||
, optsDownloader :: Downloader
|
||||
-- commands
|
||||
, optCommand :: Command
|
||||
}
|
||||
|
@ -81,12 +89,16 @@ data Command
|
|||
| DInfo
|
||||
| Compile CompileCommand
|
||||
| Upgrade UpgradeOpts Bool
|
||||
| NumericVersion
|
||||
| ToolRequirements
|
||||
| ChangeLog ChangeLogOptions
|
||||
|
||||
data ToolVersion = ToolVersion Version
|
||||
| ToolTag Tag
|
||||
|
||||
prettyToolVer :: ToolVersion -> String
|
||||
prettyToolVer (ToolVersion v') = T.unpack $ prettyVer v'
|
||||
prettyToolVer (ToolTag t) = show t
|
||||
|
||||
|
||||
data InstallOptions = InstallOptions
|
||||
{ instVer :: Maybe ToolVersion
|
||||
|
@ -98,8 +110,9 @@ data SetGHCOptions = SetGHCOptions
|
|||
}
|
||||
|
||||
data ListOptions = ListOptions
|
||||
{ lTool :: Maybe Tool
|
||||
, lCriteria :: Maybe ListCriteria
|
||||
{ lTool :: Maybe Tool
|
||||
, lCriteria :: Maybe ListCriteria
|
||||
, lRawFormat :: Bool
|
||||
}
|
||||
|
||||
data RmOptions = RmOptions
|
||||
|
@ -124,17 +137,19 @@ data UpgradeOpts = UpgradeInplace
|
|||
| UpgradeGHCupDir
|
||||
deriving Show
|
||||
|
||||
data ChangeLogOptions = ChangeLogOptions
|
||||
{ clOpen :: Bool
|
||||
, clTool :: Maybe Tool
|
||||
, clToolVer :: Maybe ToolVersion
|
||||
}
|
||||
|
||||
|
||||
opts :: Parser Options
|
||||
opts =
|
||||
Options
|
||||
<$> switch
|
||||
(short 'v' <> long "verbose" <> help
|
||||
"Enable verbosity"
|
||||
)
|
||||
<$> switch (short 'v' <> long "verbose" <> help "Enable verbosity")
|
||||
<*> switch
|
||||
(short 'c' <> long "cache" <> help
|
||||
"Cache downloads in ~/.ghcup/cache"
|
||||
(short 'c' <> long "cache" <> help "Cache downloads in ~/.ghcup/cache"
|
||||
)
|
||||
<*> (optional
|
||||
(option
|
||||
|
@ -151,6 +166,31 @@ opts =
|
|||
(short 'n' <> long "no-verify" <> help
|
||||
"Skip tarball checksum verification"
|
||||
)
|
||||
<*> option
|
||||
(eitherReader keepOnParser)
|
||||
( long "keep"
|
||||
<> metavar "<always|errors|never>"
|
||||
<> help
|
||||
"Keep build directories? (default: never)"
|
||||
<> value Never
|
||||
<> hidden
|
||||
)
|
||||
<*> option
|
||||
(eitherReader downloaderParser)
|
||||
( long "downloader"
|
||||
#if defined(INTERNAL_DOWNLOADER)
|
||||
<> metavar "<internal|curl|wget>"
|
||||
<> help
|
||||
"Downloader to use (default: internal)"
|
||||
<> value Internal
|
||||
#else
|
||||
<> metavar "<curl|wget>"
|
||||
<> help
|
||||
"Downloader to use (default: curl)"
|
||||
<> value Curl
|
||||
#endif
|
||||
<> hidden
|
||||
)
|
||||
<*> com
|
||||
where
|
||||
parseUri s' =
|
||||
|
@ -162,15 +202,21 @@ com =
|
|||
subparser
|
||||
( command
|
||||
"install"
|
||||
((info ((Install <$> installOpts) <**> helper)
|
||||
(progDesc "Install or update GHC")
|
||||
((info
|
||||
((Install <$> installOpts) <**> helper)
|
||||
( progDesc "Install or update GHC"
|
||||
<> footerDoc (Just $ text installFooter)
|
||||
)
|
||||
)
|
||||
)
|
||||
<> command
|
||||
"set"
|
||||
( SetGHC
|
||||
<$> (info (setGHCOpts <**> helper)
|
||||
(progDesc "Set currently active GHC version")
|
||||
<$> (info
|
||||
(setGHCOpts <**> helper)
|
||||
( progDesc "Set currently active GHC version"
|
||||
<> footerDoc (Just $ text setFooter)
|
||||
)
|
||||
)
|
||||
)
|
||||
<> command
|
||||
|
@ -181,8 +227,11 @@ com =
|
|||
|
||||
<> command
|
||||
"install-cabal"
|
||||
((info ((InstallCabal <$> installOpts) <**> helper)
|
||||
(progDesc "Install or update cabal")
|
||||
((info
|
||||
((InstallCabal <$> installOpts) <**> helper)
|
||||
( progDesc "Install or update cabal"
|
||||
<> footerDoc (Just $ text installCabalFooter)
|
||||
)
|
||||
)
|
||||
)
|
||||
<> command
|
||||
|
@ -194,12 +243,14 @@ com =
|
|||
)
|
||||
<> command
|
||||
"upgrade"
|
||||
(info ((Upgrade <$> upgradeOptsP <*>
|
||||
switch
|
||||
(short 'f' <> long "force" <> help
|
||||
"Force update"
|
||||
)
|
||||
) <**> helper) (progDesc "Upgrade ghcup"))
|
||||
(info
|
||||
( (Upgrade <$> upgradeOptsP <*> switch
|
||||
(short 'f' <> long "force" <> help "Force update")
|
||||
)
|
||||
<**> helper
|
||||
)
|
||||
(progDesc "Upgrade ghcup")
|
||||
)
|
||||
<> command
|
||||
"compile"
|
||||
( Compile
|
||||
|
@ -213,11 +264,6 @@ com =
|
|||
( command
|
||||
"debug-info"
|
||||
((\_ -> DInfo) <$> (info (helper) (progDesc "Show debug info")))
|
||||
<> command
|
||||
"numeric-version"
|
||||
( (\_ -> NumericVersion)
|
||||
<$> (info (helper) (progDesc "Show the numeric version"))
|
||||
)
|
||||
<> command
|
||||
"tool-requirements"
|
||||
( (\_ -> ToolRequirements)
|
||||
|
@ -225,9 +271,35 @@ com =
|
|||
(progDesc "Show the requirements for ghc/cabal")
|
||||
)
|
||||
)
|
||||
<> command
|
||||
"changelog"
|
||||
((info (fmap ChangeLog changelogP <**> helper)
|
||||
(progDesc "Find/show changelog"
|
||||
<> footerDoc (Just $ text changeLogFooter)
|
||||
)
|
||||
)
|
||||
)
|
||||
<> commandGroup "Other commands:"
|
||||
<> hidden
|
||||
)
|
||||
where
|
||||
installFooter = [i|Discussion:
|
||||
Installs the specified GHC version (or a recommended default one) into
|
||||
a self-contained "~/.ghcup/ghc/<ghcver>" directory
|
||||
and symlinks the ghc binaries to "~/.ghcup/bin/<binary>-<ghcver>".|]
|
||||
setFooter = [i|Discussion:
|
||||
Sets the the current GHC version by creating non-versioned
|
||||
symlinks for all ghc binaries of the specified version in
|
||||
"~/.ghcup/bin/<binary>".|]
|
||||
installCabalFooter = [i|Discussion:
|
||||
Installs the specified cabal-install version (or a recommended default one)
|
||||
into "~/.ghcup/bin", so it can be overwritten by later
|
||||
"cabal install cabal-install", which installs into "~/.cabal/bin" by
|
||||
default. Make sure to set up your PATH appropriately, so the cabal
|
||||
installation takes precedence.|]
|
||||
changeLogFooter = [i|Discussion:
|
||||
By default returns the URI of the ChangeLog of the latest GHC release.
|
||||
Pass '-o' to automatically open via xdg-open.|]
|
||||
|
||||
|
||||
installOpts :: Parser InstallOptions
|
||||
|
@ -270,27 +342,75 @@ listOpts =
|
|||
)
|
||||
)
|
||||
)
|
||||
<*> switch
|
||||
(short 'r' <> long "raw-format" <> help "More machine-parsable format"
|
||||
)
|
||||
|
||||
rmOpts :: Parser RmOptions
|
||||
rmOpts = RmOptions <$> versionArgument
|
||||
|
||||
|
||||
changelogP :: Parser ChangeLogOptions
|
||||
changelogP =
|
||||
(\x y -> ChangeLogOptions x y)
|
||||
<$> switch (short 'o' <> long "open" <> help "xdg-open the changelog url")
|
||||
<*> (optional
|
||||
(option
|
||||
(eitherReader
|
||||
(\s' -> case fmap toLower s' of
|
||||
"ghc" -> Right GHC
|
||||
"cabal" -> Right Cabal
|
||||
"ghcup" -> Right GHCup
|
||||
e -> Left $ e
|
||||
)
|
||||
)
|
||||
(short 't' <> long "tool" <> metavar "<ghc|cabal|ghcup>" <> help
|
||||
"Open changelog for given tool (default: ghc)"
|
||||
)
|
||||
)
|
||||
)
|
||||
<*> optional toolVersionArgument
|
||||
|
||||
compileP :: Parser CompileCommand
|
||||
compileP = subparser
|
||||
( command
|
||||
"ghc"
|
||||
( CompileGHC
|
||||
<$> (info (compileOpts <**> helper) (progDesc "Compile GHC from source")
|
||||
<$> (info
|
||||
(compileOpts <**> helper)
|
||||
( progDesc "Compile GHC from source"
|
||||
<> footerDoc (Just $ text compileFooter)
|
||||
)
|
||||
)
|
||||
)
|
||||
<> command
|
||||
"cabal"
|
||||
( CompileCabal
|
||||
<$> (info (compileOpts <**> helper)
|
||||
(progDesc "Compile Cabal from source")
|
||||
<$> (info
|
||||
(compileOpts <**> helper)
|
||||
( progDesc "Compile Cabal from source"
|
||||
<> footerDoc (Just $ text compileCabalFooter)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
where
|
||||
compileFooter = [i|Discussion:
|
||||
Compiles and installs the specified GHC version into
|
||||
a self-contained "~/.ghcup/ghc/<ghcver>" directory
|
||||
and symlinks the ghc binaries to "~/.ghcup/bin/<binary>-<ghcver>".
|
||||
|
||||
Examples:
|
||||
ghcup compile ghc -j 4 -v 8.4.2 -b 8.2.2
|
||||
ghcup compile ghc -j 4 -v 8.4.2 -b /usr/bin/ghc-8.2.2|]
|
||||
compileCabalFooter = [i|Discussion:
|
||||
Compiles and installs the specified Cabal version
|
||||
into "~/.ghcup/bin".
|
||||
|
||||
Examples:
|
||||
ghcup compile cabal -j 4 -v 3.2.0.0 -b 8.6.5
|
||||
ghcup compile cabal -j 4 -v 3.2.0.0 -b /usr/bin/ghc-8.6.5|]
|
||||
|
||||
|
||||
|
||||
compileOpts :: Parser CompileOptions
|
||||
|
@ -371,9 +491,7 @@ toolVersionArgument =
|
|||
|
||||
|
||||
versionArgument :: Parser Version
|
||||
versionArgument = argument
|
||||
(eitherReader versionEither)
|
||||
(metavar "VERSION")
|
||||
versionArgument = argument (eitherReader versionEither) (metavar "VERSION")
|
||||
|
||||
versionParser :: Parser Version
|
||||
versionParser = option
|
||||
|
@ -385,14 +503,17 @@ tagEither :: String -> Either String Tag
|
|||
tagEither s' = case fmap toLower s' of
|
||||
"recommended" -> Right Recommended
|
||||
"latest" -> Right Latest
|
||||
('b':'a':'s':'e':'-':ver') -> case pvp (T.pack ver') of
|
||||
Right x -> Right (Base x)
|
||||
Left _ -> Left [i|Invalid PVP version for base #{ver'}|]
|
||||
other -> Left ([i|Unknown tag #{other}|])
|
||||
|
||||
versionEither :: String -> Either String Version
|
||||
versionEither s' =
|
||||
-- 'version' is a bit too lax and will parse typoed tags
|
||||
case readMaybe ((:[]) . head $ s') :: Maybe Int of
|
||||
Just _ -> bimap (const "Not a valid version") id . version . T.pack $ s'
|
||||
Nothing -> Left "Not a valid version"
|
||||
case readMaybe ((: []) . head $ s') :: Maybe Int of
|
||||
Just _ -> bimap (const "Not a valid version") id . version . T.pack $ s'
|
||||
Nothing -> Left "Not a valid version"
|
||||
|
||||
toolVersionEither :: String -> Either String ToolVersion
|
||||
toolVersionEither s' =
|
||||
|
@ -413,6 +534,24 @@ criteriaParser s' | t == T.pack "installed" = Right ListInstalled
|
|||
where t = T.toLower (T.pack s')
|
||||
|
||||
|
||||
keepOnParser :: String -> Either String KeepDirs
|
||||
keepOnParser s' | t == T.pack "always" = Right Always
|
||||
| t == T.pack "errors" = Right Errors
|
||||
| t == T.pack "never" = Right Never
|
||||
| otherwise = Left ("Unknown keep value: " <> s')
|
||||
where t = T.toLower (T.pack s')
|
||||
|
||||
|
||||
downloaderParser :: String -> Either String Downloader
|
||||
downloaderParser s' | t == T.pack "curl" = Right Curl
|
||||
| t == T.pack "wget" = Right Wget
|
||||
#if defined(INTERNAL_DOWNLOADER)
|
||||
| t == T.pack "internal" = Right Internal
|
||||
#endif
|
||||
| otherwise = Left ("Unknown downloader 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
|
||||
Right r -> pure r
|
||||
|
@ -488,8 +627,10 @@ platformParser s' = case MP.parse (platformP <* MP.eof) "" (T.pack s') of
|
|||
|
||||
toSettings :: Options -> Settings
|
||||
toSettings Options {..} =
|
||||
let cache = optCache
|
||||
noVerify = optNoVerify
|
||||
let cache = optCache
|
||||
noVerify = optNoVerify
|
||||
keepDirs = optKeepDirs
|
||||
downloader = optsDownloader
|
||||
in Settings { .. }
|
||||
|
||||
|
||||
|
@ -518,13 +659,55 @@ upgradeOptsP =
|
|||
|
||||
|
||||
|
||||
describe_result :: String
|
||||
describe_result = $( (LitE . StringL) <$>
|
||||
runIO (do
|
||||
CapturedProcess{..} <- executeOut [rel|git|] ["describe"] Nothing
|
||||
case _exitCode of
|
||||
ExitSuccess -> pure . T.unpack . decUTF8Safe $ _stdOut
|
||||
ExitFailure _ -> pure numericVer
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
let versionHelp = infoOption
|
||||
( ("The GHCup Haskell installer, version " <>)
|
||||
$ (head . lines $ describe_result)
|
||||
)
|
||||
(long "version" <> help "Show version" <> hidden)
|
||||
let numericVersionHelp = infoOption
|
||||
numericVer
|
||||
( long "numeric-version"
|
||||
<> help "Show the numeric version (for use in scripts)"
|
||||
<> hidden
|
||||
)
|
||||
let listCommands = infoOption
|
||||
"install set rm install-cabal list upgrade compile debug-info tool-requirements changelog"
|
||||
( long "list-commands"
|
||||
<> help "List available commands for shell completion"
|
||||
<> internal
|
||||
)
|
||||
|
||||
customExecParser (prefs showHelpOnError) (info (opts <**> helper) idm)
|
||||
let main_footer = [i|Discussion:
|
||||
ghcup installs the Glasgow Haskell Compiler from the official
|
||||
release channels, enabling you to easily switch between different
|
||||
versions. It maintains a self-contained ~/.ghcup directory.
|
||||
|
||||
ENV variables:
|
||||
* TMPDIR: where ghcup does the work (unpacking, building, ...)
|
||||
* GHCUP_INSTALL_BASE_PREFIX: the base of ghcup (default: $HOME)
|
||||
|
||||
Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
|
||||
|
||||
customExecParser
|
||||
(prefs showHelpOnError)
|
||||
(info (opts <**> helper <**> versionHelp <**> numericVersionHelp <**> listCommands)
|
||||
(footerDoc (Just $ text main_footer))
|
||||
)
|
||||
>>= \opt@Options {..} -> do
|
||||
let settings = toSettings opt
|
||||
let settings@Settings{..} = toSettings opt
|
||||
|
||||
-- create ~/.ghcup dir
|
||||
ghcdir <- ghcupBaseDir
|
||||
|
@ -570,10 +753,7 @@ main = do
|
|||
, TagNotFound
|
||||
]
|
||||
|
||||
let runListGHC =
|
||||
runLogger
|
||||
. flip runReaderT settings
|
||||
. runE @'[FileDoesNotExistError]
|
||||
let runListGHC = runE @'[] . runLogger
|
||||
|
||||
let runRmGHC =
|
||||
runLogger . flip runReaderT settings . runE @'[NotInstalled]
|
||||
|
@ -638,141 +818,175 @@ main = do
|
|||
(GHCupInfo treq dls) <-
|
||||
( runLogger
|
||||
. flip runReaderT settings
|
||||
. runE @'[JSONError , DownloadFailed]
|
||||
. runE @'[JSONError , DownloadFailed, FileDoesNotExistError]
|
||||
$ liftE
|
||||
$ getDownloads (maybe GHCupURL OwnSource optUrlSource)
|
||||
$ getDownloadsF (maybe GHCupURL OwnSource optUrlSource)
|
||||
)
|
||||
>>= \case
|
||||
VRight r -> pure r
|
||||
VLeft e ->
|
||||
VLeft e -> do
|
||||
runLogger
|
||||
($(logError) [i|Error fetching download info: #{e}|])
|
||||
>> exitFailure
|
||||
($(logError) [i|Error fetching download info: #{e}|])
|
||||
exitWith (ExitFailure 2)
|
||||
runLogger $ checkForUpdates dls
|
||||
|
||||
case optCommand of
|
||||
res <- case optCommand of
|
||||
Install (InstallOptions {..}) ->
|
||||
void
|
||||
$ (runInstTool $ do
|
||||
v <- liftE $ fromVersion dls instVer GHC
|
||||
liftE $ installGHCBin dls v instPlatform
|
||||
)
|
||||
(runInstTool $ do
|
||||
v <- liftE $ fromVersion dls instVer GHC
|
||||
liftE $ installGHCBin dls v instPlatform
|
||||
)
|
||||
>>= \case
|
||||
VRight _ ->
|
||||
VRight _ -> do
|
||||
runLogger $ $(logInfo) ("GHC installation successful")
|
||||
VLeft (V (AlreadyInstalled _ v)) ->
|
||||
pure ExitSuccess
|
||||
VLeft (V (AlreadyInstalled _ v)) -> do
|
||||
runLogger $ $(logWarn)
|
||||
[i|GHC ver #{prettyVer v} already installed|]
|
||||
VLeft (V (BuildFailed tmpdir e)) ->
|
||||
runLogger
|
||||
($(logError) [i|Build failed with #{e}
|
||||
Check the logs at ~/.ghcup/logs and the build directory #{tmpdir} for more clues.|]
|
||||
)
|
||||
>> exitFailure
|
||||
pure ExitSuccess
|
||||
VLeft (V (BuildFailed tmpdir e)) -> do
|
||||
case keepDirs of
|
||||
Never -> runLogger ($(logError) [i|Build failed with #{e}|])
|
||||
_ -> runLogger ($(logError) [i|Build failed with #{e}
|
||||
Check the logs at ~/.ghcup/logs and the build directory #{tmpdir} for more clues.
|
||||
Make sure to clean up #{tmpdir} afterwards.|])
|
||||
pure $ ExitFailure 3
|
||||
VLeft (V NoDownload) -> do
|
||||
|
||||
runLogger $ do
|
||||
case instVer of
|
||||
Just iver -> $(logError) [i|No available GHC version for #{prettyToolVer iver}|]
|
||||
Nothing -> $(logError) [i|No available recommended GHC version|]
|
||||
pure $ ExitFailure 3
|
||||
VLeft e -> do
|
||||
runLogger $ do
|
||||
$(logError) [i|#{e}|]
|
||||
$(logError) [i|Also check the logs in ~/.ghcup/logs|]
|
||||
exitFailure
|
||||
pure $ ExitFailure 3
|
||||
InstallCabal (InstallOptions {..}) ->
|
||||
void
|
||||
$ (runInstTool $ do
|
||||
v <- liftE $ fromVersion dls instVer Cabal
|
||||
liftE $ installCabalBin dls v instPlatform
|
||||
)
|
||||
(runInstTool $ do
|
||||
v <- liftE $ fromVersion dls instVer Cabal
|
||||
liftE $ installCabalBin dls v instPlatform
|
||||
)
|
||||
>>= \case
|
||||
VRight _ ->
|
||||
VRight _ -> do
|
||||
runLogger $ $(logInfo) ("Cabal installation successful")
|
||||
VLeft (V (AlreadyInstalled _ v)) ->
|
||||
pure ExitSuccess
|
||||
VLeft (V (AlreadyInstalled _ v)) -> do
|
||||
runLogger $ $(logWarn)
|
||||
[i|Cabal ver #{prettyVer v} already installed|]
|
||||
pure ExitSuccess
|
||||
VLeft (V NoDownload) -> do
|
||||
|
||||
runLogger $ do
|
||||
case instVer of
|
||||
Just iver -> $(logError) [i|No available Cabal version for #{prettyToolVer iver}|]
|
||||
Nothing -> $(logError) [i|No available recommended Cabal version|]
|
||||
pure $ ExitFailure 4
|
||||
VLeft e -> do
|
||||
runLogger $ do
|
||||
$(logError) [i|#{e}|]
|
||||
$(logError) [i|Also check the logs in ~/.ghcup/logs|]
|
||||
exitFailure
|
||||
pure $ ExitFailure 4
|
||||
|
||||
SetGHC (SetGHCOptions {..}) ->
|
||||
void
|
||||
$ (runSetGHC $ do
|
||||
v <- liftE $ fromVersion dls ghcVer GHC
|
||||
liftE $ setGHC v SetGHCOnly
|
||||
)
|
||||
(runSetGHC $ do
|
||||
v <- liftE $ fromVersion dls ghcVer GHC
|
||||
liftE $ setGHC v SetGHCOnly
|
||||
)
|
||||
>>= \case
|
||||
VRight v ->
|
||||
runLogger $ $(logInfo) [i|GHC #{prettyVer v} successfully set as default version|]
|
||||
VLeft e ->
|
||||
runLogger ($(logError) [i|#{e}|]) >> exitFailure
|
||||
VRight v -> do
|
||||
runLogger
|
||||
$ $(logInfo)
|
||||
[i|GHC #{prettyVer v} successfully set as default version|]
|
||||
pure ExitSuccess
|
||||
VLeft e -> do
|
||||
runLogger ($(logError) [i|#{e}|])
|
||||
pure $ ExitFailure 5
|
||||
|
||||
List (ListOptions {..}) ->
|
||||
void
|
||||
$ (runListGHC $ do
|
||||
liftIO $ listVersions dls lTool lCriteria
|
||||
)
|
||||
(runListGHC $ do
|
||||
l <- listVersions dls lTool lCriteria
|
||||
pure l
|
||||
)
|
||||
>>= \case
|
||||
VRight r -> liftIO $ printListResult r
|
||||
VLeft e ->
|
||||
runLogger ($(logError) [i|#{e}|]) >> exitFailure
|
||||
VRight r -> do
|
||||
liftIO $ printListResult lRawFormat r
|
||||
pure ExitSuccess
|
||||
VLeft e -> do
|
||||
runLogger ($(logError) [i|#{e}|])
|
||||
pure $ ExitFailure 6
|
||||
|
||||
Rm (RmOptions {..}) ->
|
||||
void
|
||||
$ (runRmGHC $ do
|
||||
liftE $ rmGHCVer ghcVer
|
||||
)
|
||||
(runRmGHC $ do
|
||||
liftE $ rmGHCVer ghcVer
|
||||
)
|
||||
>>= \case
|
||||
VRight _ -> pure ()
|
||||
VLeft e ->
|
||||
runLogger ($(logError) [i|#{e}|]) >> exitFailure
|
||||
VRight _ -> pure ExitSuccess
|
||||
VLeft e -> do
|
||||
runLogger ($(logError) [i|#{e}|])
|
||||
pure $ ExitFailure 7
|
||||
|
||||
DInfo -> do
|
||||
void
|
||||
$ (runDebugInfo $ do
|
||||
liftE $ getDebugInfo
|
||||
)
|
||||
DInfo ->
|
||||
do
|
||||
(runDebugInfo $ liftE $ getDebugInfo)
|
||||
>>= \case
|
||||
VRight dinfo -> putStrLn $ show dinfo
|
||||
VLeft e ->
|
||||
runLogger ($(logError) [i|#{e}|]) >> exitFailure
|
||||
VRight dinfo -> do
|
||||
putStrLn $ prettyDebugInfo dinfo
|
||||
pure ExitSuccess
|
||||
VLeft e -> do
|
||||
runLogger ($(logError) [i|#{e}|])
|
||||
pure $ ExitFailure 8
|
||||
|
||||
Compile (CompileGHC CompileOptions {..}) ->
|
||||
void
|
||||
$ (runCompileGHC $ do
|
||||
liftE
|
||||
$ compileGHC dls targetVer bootstrapGhc jobs buildConfig patchDir
|
||||
)
|
||||
(runCompileGHC $ liftE $ compileGHC dls
|
||||
targetVer
|
||||
bootstrapGhc
|
||||
jobs
|
||||
buildConfig
|
||||
patchDir
|
||||
)
|
||||
>>= \case
|
||||
VRight _ ->
|
||||
VRight _ -> do
|
||||
runLogger $ $(logInfo)
|
||||
("GHC successfully compiled and installed")
|
||||
VLeft (V (AlreadyInstalled _ v)) ->
|
||||
pure ExitSuccess
|
||||
VLeft (V (AlreadyInstalled _ v)) -> do
|
||||
runLogger $ $(logWarn)
|
||||
[i|GHC ver #{prettyVer v} already installed|]
|
||||
VLeft (V (BuildFailed tmpdir e)) ->
|
||||
runLogger
|
||||
($(logError) [i|Build failed with #{e}
|
||||
Check the logs at ~/.ghcup/logs and the build directory #{tmpdir} for more clues.|]
|
||||
)
|
||||
>> exitFailure
|
||||
VLeft e ->
|
||||
runLogger ($(logError) [i|#{e}|]) >> exitFailure
|
||||
pure ExitSuccess
|
||||
VLeft (V (BuildFailed tmpdir e)) -> do
|
||||
case keepDirs of
|
||||
Never -> runLogger ($(logError) [i|Build failed with #{e}|])
|
||||
_ -> runLogger ($(logError) [i|Build failed with #{e}
|
||||
Check the logs at ~/.ghcup/logs and the build directory #{tmpdir} for more clues.
|
||||
Make sure to clean up #{tmpdir} afterwards.|])
|
||||
pure $ ExitFailure 9
|
||||
VLeft e -> do
|
||||
runLogger ($(logError) [i|#{e}|])
|
||||
pure $ ExitFailure 9
|
||||
|
||||
Compile (CompileCabal CompileOptions {..}) ->
|
||||
void
|
||||
$ (runCompileCabal $ do
|
||||
liftE $ compileCabal dls targetVer bootstrapGhc jobs patchDir
|
||||
)
|
||||
(runCompileCabal $ do
|
||||
liftE $ compileCabal dls targetVer bootstrapGhc jobs patchDir
|
||||
)
|
||||
>>= \case
|
||||
VRight _ ->
|
||||
runLogger $ $(logInfo)
|
||||
("Cabal successfully compiled and installed")
|
||||
VLeft (V (BuildFailed tmpdir e)) ->
|
||||
VRight _ -> do
|
||||
runLogger
|
||||
($(logError) [i|Build failed with #{e}
|
||||
Check the logs at ~/.ghcup/logs and the build directory #{tmpdir} for more clues.|]
|
||||
)
|
||||
>> exitFailure
|
||||
VLeft e ->
|
||||
runLogger ($(logError) [i|#{e}|]) >> exitFailure
|
||||
($(logInfo)
|
||||
"Cabal successfully compiled and installed"
|
||||
)
|
||||
pure ExitSuccess
|
||||
VLeft (V (BuildFailed tmpdir e)) -> do
|
||||
case keepDirs of
|
||||
Never -> runLogger ($(logError) [i|Build failed with #{e}|])
|
||||
_ -> runLogger ($(logError) [i|Build failed with #{e}
|
||||
Check the logs at ~/.ghcup/logs and the build directory #{tmpdir} for more clues.
|
||||
Make sure to clean up #{tmpdir} afterwards.|])
|
||||
pure $ ExitFailure 10
|
||||
VLeft e -> do
|
||||
runLogger ($(logError) [i|#{e}|])
|
||||
pure $ ExitFailure 10
|
||||
|
||||
Upgrade (uOpts) force -> do
|
||||
target <- case uOpts of
|
||||
|
@ -785,38 +999,74 @@ Check the logs at ~/.ghcup/logs and the build directory #{tmpdir} for more clues
|
|||
bdir <- liftIO $ ghcupBinDir
|
||||
pure (Just (bdir </> [rel|ghcup|]))
|
||||
|
||||
void
|
||||
$ (runUpgrade $ do
|
||||
liftE $ upgradeGHCup dls target force
|
||||
)
|
||||
>>= \case
|
||||
VRight v' -> do
|
||||
let pretty_v = prettyVer v'
|
||||
runLogger
|
||||
$ $(logInfo)
|
||||
[i|Successfully upgraded GHCup to version #{pretty_v}|]
|
||||
VLeft (V NoUpdate) ->
|
||||
runLogger $ $(logWarn)
|
||||
[i|No GHCup update available|]
|
||||
VLeft e ->
|
||||
runLogger ($(logError) [i|#{e}|]) >> exitFailure
|
||||
(runUpgrade $ (liftE $ upgradeGHCup dls target force)) >>= \case
|
||||
VRight v' -> do
|
||||
let pretty_v = prettyVer v'
|
||||
runLogger $ $(logInfo)
|
||||
[i|Successfully upgraded GHCup to version #{pretty_v}|]
|
||||
pure ExitSuccess
|
||||
VLeft (V NoUpdate) -> do
|
||||
runLogger $ $(logWarn) [i|No GHCup update available|]
|
||||
pure ExitSuccess
|
||||
VLeft e -> do
|
||||
runLogger ($(logError) [i|#{e}|])
|
||||
pure $ ExitFailure 11
|
||||
|
||||
NumericVersion -> T.hPutStr stdout (prettyPVP ghcUpVer)
|
||||
ToolRequirements -> (runLogger $ runE
|
||||
@'[ NoCompatiblePlatform
|
||||
, DistroNotFound
|
||||
, NoToolRequirements
|
||||
] $ do
|
||||
platform <- liftE $ getPlatform
|
||||
req <- (getCommonRequirements platform $ treq)
|
||||
?? NoToolRequirements
|
||||
liftIO $ T.hPutStr stdout (prettyRequirements req))
|
||||
>>= \case
|
||||
VRight r -> pure r
|
||||
VLeft e ->
|
||||
runLogger
|
||||
($(logError) [i|Error getting tool requirements: #{e}|])
|
||||
>> exitFailure
|
||||
ToolRequirements ->
|
||||
( runLogger
|
||||
$ runE
|
||||
@'[NoCompatiblePlatform , DistroNotFound , NoToolRequirements]
|
||||
$ do
|
||||
platform <- liftE $ getPlatform
|
||||
req <-
|
||||
(getCommonRequirements platform $ treq)
|
||||
?? NoToolRequirements
|
||||
liftIO $ T.hPutStr stdout (prettyRequirements req)
|
||||
)
|
||||
>>= \case
|
||||
VRight _ -> pure ExitSuccess
|
||||
VLeft e -> do
|
||||
runLogger
|
||||
($(logError)
|
||||
[i|Error getting tool requirements: #{e}|]
|
||||
)
|
||||
pure $ ExitFailure 12
|
||||
|
||||
ChangeLog (ChangeLogOptions {..}) -> do
|
||||
let tool = fromMaybe GHC clTool
|
||||
ver' = maybe
|
||||
(Right Latest)
|
||||
(\case
|
||||
ToolVersion tv -> Left tv
|
||||
ToolTag t -> Right t
|
||||
)
|
||||
clToolVer
|
||||
muri = getChangeLog dls tool ver'
|
||||
case muri of
|
||||
Nothing -> do
|
||||
runLogger
|
||||
($(logWarn)
|
||||
[i|Could not find ChangeLog for #{tool}, version #{either (T.unpack . prettyVer) show ver'}|]
|
||||
)
|
||||
pure ExitSuccess
|
||||
Just uri -> do
|
||||
let uri' = T.unpack . decUTF8Safe . serializeURIRef' $ uri
|
||||
if clOpen
|
||||
then
|
||||
exec "xdg-open"
|
||||
True
|
||||
[serializeURIRef' uri]
|
||||
Nothing
|
||||
Nothing
|
||||
>>= \case
|
||||
Right _ -> pure ExitSuccess
|
||||
Left e -> runLogger ($(logError) [i|#{e}|])
|
||||
>> pure (ExitFailure 13)
|
||||
else putStrLn uri' >> pure ExitSuccess
|
||||
|
||||
case res of
|
||||
ExitSuccess -> pure ()
|
||||
ef@(ExitFailure _) -> exitWith ef
|
||||
pure ()
|
||||
|
||||
|
||||
|
@ -827,47 +1077,115 @@ fromVersion :: Monad m
|
|||
-> Excepts '[TagNotFound] m Version
|
||||
fromVersion av Nothing tool =
|
||||
getRecommended av tool ?? TagNotFound Recommended tool
|
||||
fromVersion _ (Just (ToolVersion v)) _ = pure v
|
||||
fromVersion av (Just (ToolVersion v)) _ = do
|
||||
case pvp $ prettyVer v of
|
||||
Left _ -> pure v
|
||||
Right (PVP (major' :|[minor'])) ->
|
||||
case getLatestGHCFor (fromIntegral major') (fromIntegral minor') av of
|
||||
Just v' -> pure v'
|
||||
Nothing -> pure v
|
||||
Right _ -> pure v
|
||||
fromVersion av (Just (ToolTag Latest)) tool =
|
||||
getLatest av tool ?? TagNotFound Latest tool
|
||||
fromVersion av (Just (ToolTag Recommended)) tool =
|
||||
getRecommended av tool ?? TagNotFound Recommended tool
|
||||
fromVersion av (Just (ToolTag (Base pvp''))) GHC =
|
||||
getLatestBaseVersion av pvp'' ?? TagNotFound (Base pvp'') GHC
|
||||
fromVersion _ (Just (ToolTag t')) tool =
|
||||
throwE $ TagNotFound t' tool
|
||||
|
||||
|
||||
printListResult :: [ListResult] -> IO ()
|
||||
printListResult lr = do
|
||||
printListResult :: Bool -> [ListResult] -> IO ()
|
||||
printListResult raw lr = do
|
||||
-- https://gitlab.haskell.org/ghc/ghc/issues/8118
|
||||
setLocaleEncoding utf8
|
||||
|
||||
let
|
||||
formatted =
|
||||
gridString
|
||||
[ column expand left def def
|
||||
, column expand left def def
|
||||
, column expand left def def
|
||||
, column expand left def def
|
||||
, column expand left def def
|
||||
]
|
||||
( (if raw then [] else [column expand left def def])
|
||||
++ [ column expand left def def
|
||||
, column expand left def def
|
||||
, column expand left def def
|
||||
, column expand left def def
|
||||
]
|
||||
)
|
||||
. (\x -> if raw
|
||||
then x
|
||||
else [color Green "", "Tool", "Version", "Tags", "Notes"] : x
|
||||
)
|
||||
$ fmap
|
||||
(\ListResult {..} ->
|
||||
[ if
|
||||
| lSet -> (color Green "✔✔")
|
||||
| lInstalled -> (color Green "✓")
|
||||
| otherwise -> (color Red "✗")
|
||||
, fmap toLower . show $ lTool
|
||||
, T.unpack . prettyVer $ lVer
|
||||
, intercalate "," $ ((fmap . fmap) toLower . fmap show $ lTag)
|
||||
, if fromSrc then (color Blue "compiled") else mempty
|
||||
]
|
||||
let marks = if
|
||||
| lSet -> (color Green "✔✔")
|
||||
| lInstalled -> (color Green "✓")
|
||||
| otherwise -> (color Red "✗")
|
||||
in (if raw then [] else [marks])
|
||||
++ [ fmap toLower . show $ lTool
|
||||
, T.unpack . prettyVer $ lVer
|
||||
, intercalate "," $ (fmap printTag $ sort lTag)
|
||||
, intercalate ","
|
||||
$ (if fromSrc then [color' Blue "compiled"] else mempty)
|
||||
++ (if lStray then [color' Blue "stray"] else mempty)
|
||||
]
|
||||
)
|
||||
lr
|
||||
putStrLn $ formatted
|
||||
where
|
||||
printTag Recommended = color' Green "recommended"
|
||||
printTag Latest = color' Yellow "latest"
|
||||
printTag (Base pvp'') = "base-" ++ T.unpack (prettyPVP pvp'')
|
||||
printTag (UnknownTag t ) = t
|
||||
color' = case raw of
|
||||
True -> flip const
|
||||
False -> color
|
||||
|
||||
|
||||
checkForUpdates :: (MonadFail m, MonadLogger m) => GHCupDownloads -> m ()
|
||||
checkForUpdates :: (MonadThrow m, MonadIO m, MonadFail m, MonadLogger m)
|
||||
=> GHCupDownloads
|
||||
-> m ()
|
||||
checkForUpdates dls = do
|
||||
forM_ (getLatest dls GHCup) $ \l -> do
|
||||
(Right ghc_ver) <- pure $ version $ prettyPVP ghcUpVer
|
||||
when (l > ghc_ver)
|
||||
$ $(logWarn)
|
||||
[i|New GHCup version available: #{prettyVer l}. To upgrade, run 'ghcup upgrade'|]
|
||||
|
||||
forM_ (getLatest dls GHC) $ \l -> do
|
||||
mghc_ver <- latestInstalled GHC
|
||||
forM mghc_ver $ \ghc_ver ->
|
||||
when (l > ghc_ver)
|
||||
$ $(logWarn)
|
||||
[i|New GHC version available: #{prettyVer l}. To upgrade, run 'ghcup install #{prettyVer l}'|]
|
||||
|
||||
forM_ (getLatest dls Cabal) $ \l -> do
|
||||
mcabal_ver <- latestInstalled Cabal
|
||||
forM mcabal_ver $ \cabal_ver ->
|
||||
when (l > cabal_ver)
|
||||
$ $(logWarn)
|
||||
[i|New Cabal version available: #{prettyVer l}. To upgrade, run 'ghcup install-cabal #{prettyVer l}'|]
|
||||
|
||||
where
|
||||
latestInstalled tool = (fmap lVer . lastMay)
|
||||
<$> (listVersions dls (Just tool) (Just ListInstalled))
|
||||
|
||||
|
||||
prettyDebugInfo :: DebugInfo -> String
|
||||
prettyDebugInfo DebugInfo {..} = [i|Debug Info
|
||||
==========
|
||||
GHCup base dir: #{toFilePath diBaseDir}
|
||||
GHCup bin dir: #{toFilePath diBinDir}
|
||||
GHCup GHC directory: #{toFilePath diGHCDir}
|
||||
GHCup cache directory: #{toFilePath diCacheDir}
|
||||
Architecture: #{prettyArch diArch}
|
||||
Platform: #{prettyPlatform diPlatform}
|
||||
Version: #{describe_result}|]
|
||||
where
|
||||
prettyArch :: Architecture -> String
|
||||
prettyArch A_64 = "amd64"
|
||||
prettyArch A_32 = "i386"
|
||||
prettyPlatform :: PlatformResult -> String
|
||||
prettyPlatform PlatformResult { _platform = plat, _distroVersion = Just v' }
|
||||
= show plat <> ", " <> show v'
|
||||
prettyPlatform PlatformResult { _platform = plat, _distroVersion = Nothing }
|
||||
= show plat
|
||||
|
||||
|
|
|
@ -31,10 +31,10 @@ download_ghcup() {
|
|||
"linux"|"Linux")
|
||||
case "${_arch}" in
|
||||
x86_64|amd64)
|
||||
_url=https://downloads.haskell.org/~ghcup/0.1.3/x86_64-linux-ghcup-0.1.3
|
||||
_url=https://downloads.haskell.org/~ghcup/0.1.4/x86_64-linux-ghcup-0.1.4
|
||||
;;
|
||||
i*86)
|
||||
_url=https://downloads.haskell.org/~ghcup/0.1.3/i386-linux-ghcup-0.1.3
|
||||
_url=https://downloads.haskell.org/~ghcup/0.1.4/i386-linux-ghcup-0.1.4
|
||||
;;
|
||||
*) die "Unknown architecture: ${_arch}"
|
||||
;;
|
||||
|
@ -50,7 +50,7 @@ download_ghcup() {
|
|||
*) die "Unknown architecture: ${_arch}"
|
||||
;;
|
||||
esac
|
||||
_url=https://downloads.haskell.org/~ghcup/0.1.3/x86_64-portbld-freebsd-ghcup-0.1.3
|
||||
_url=https://downloads.haskell.org/~ghcup/0.1.4/x86_64-portbld-freebsd-ghcup-0.1.4
|
||||
;;
|
||||
"Darwin"|"darwin")
|
||||
case "${_arch}" in
|
||||
|
@ -62,7 +62,7 @@ download_ghcup() {
|
|||
*) die "Unknown architecture: ${_arch}"
|
||||
;;
|
||||
esac
|
||||
_url=https://downloads.haskell.org/~ghcup/0.1.3/x86_64-apple-darwin-ghcup-0.1.3 ;;
|
||||
_url=https://downloads.haskell.org/~ghcup/0.1.4/x86_64-apple-darwin-ghcup-0.1.4 ;;
|
||||
*) die "Unknown platform: ${_plat}"
|
||||
;;
|
||||
esac
|
||||
|
|
|
@ -170,6 +170,7 @@
|
|||
"dlSubdir": "ghc-8.6.2",
|
||||
"dlUri": "https://downloads.haskell.org/~ghc/8.6.2/ghc-8.6.2-src.tar.xz"
|
||||
},
|
||||
"viChangeLog": "https://downloads.haskell.org/ghc/8.6.2/docs/html/users_guide/8.6.2-notes.html",
|
||||
"viTags": []
|
||||
},
|
||||
"8.0.2": {
|
||||
|
@ -264,6 +265,7 @@
|
|||
"dlSubdir": "ghc-8.0.2",
|
||||
"dlUri": "https://downloads.haskell.org/~ghc/8.0.2/ghc-8.0.2-src.tar.xz"
|
||||
},
|
||||
"viChangeLog": "https://downloads.haskell.org/ghc/8.0.2/docs/html/users_guide/8.0.1-notes.html",
|
||||
"viTags": []
|
||||
},
|
||||
"8.6.4": {
|
||||
|
@ -377,6 +379,7 @@
|
|||
"dlSubdir": "ghc-8.6.4",
|
||||
"dlUri": "https://downloads.haskell.org/~ghc/8.6.4/ghc-8.6.4-src.tar.xz"
|
||||
},
|
||||
"viChangeLog": "https://downloads.haskell.org/ghc/8.6.4/docs/html/users_guide/8.6.4-notes.html",
|
||||
"viTags": []
|
||||
},
|
||||
"8.4.1": {
|
||||
|
@ -482,6 +485,7 @@
|
|||
"dlSubdir": "ghc-8.4.1",
|
||||
"dlUri": "https://downloads.haskell.org/~ghc/8.4.1/ghc-8.4.1-src.tar.xz"
|
||||
},
|
||||
"viChangeLog": "https://downloads.haskell.org/ghc/8.4.1/docs/html/users_guide/8.4.1-notes.html",
|
||||
"viTags": []
|
||||
},
|
||||
"8.6.3": {
|
||||
|
@ -616,6 +620,7 @@
|
|||
"dlSubdir": "ghc-8.6.3",
|
||||
"dlUri": "https://downloads.haskell.org/~ghc/8.6.3/ghc-8.6.3-src.tar.xz"
|
||||
},
|
||||
"viChangeLog": "https://downloads.haskell.org/ghc/8.6.3/docs/html/users_guide/8.6.3-notes.html",
|
||||
"viTags": []
|
||||
},
|
||||
"8.10.1": {
|
||||
|
@ -756,6 +761,7 @@
|
|||
"dlSubdir": "ghc-8.10.1",
|
||||
"dlUri": "https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-src.tar.xz"
|
||||
},
|
||||
"viChangeLog": "https://downloads.haskell.org/ghc/8.10.1/docs/html/users_guide/8.10.1-notes.html",
|
||||
"viTags": [
|
||||
"Latest"
|
||||
]
|
||||
|
@ -885,6 +891,7 @@
|
|||
"dlSubdir": "ghc-8.6.5",
|
||||
"dlUri": "https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-src.tar.xz"
|
||||
},
|
||||
"viChangeLog": "https://downloads.haskell.org/ghc/8.6.5/docs/html/users_guide/8.6.5-notes.html",
|
||||
"viTags": []
|
||||
},
|
||||
"8.4.2": {
|
||||
|
@ -1005,6 +1012,7 @@
|
|||
"dlSubdir": "ghc-8.4.2",
|
||||
"dlUri": "https://downloads.haskell.org/~ghc/8.4.2/ghc-8.4.2-src.tar.xz"
|
||||
},
|
||||
"viChangeLog": "https://downloads.haskell.org/ghc/8.4.2/docs/html/users_guide/8.4.2-notes.html",
|
||||
"viTags": []
|
||||
},
|
||||
"8.8.1": {
|
||||
|
@ -1132,6 +1140,7 @@
|
|||
"dlSubdir": "ghc-8.8.1",
|
||||
"dlUri": "https://downloads.haskell.org/~ghc/8.8.1/ghc-8.8.1-src.tar.xz"
|
||||
},
|
||||
"viChangeLog": "https://downloads.haskell.org/ghc/8.8.1/docs/html/users_guide/8.8.1-notes.html",
|
||||
"viTags": []
|
||||
},
|
||||
"8.4.3": {
|
||||
|
@ -1245,6 +1254,7 @@
|
|||
"dlSubdir": "ghc-8.4.3",
|
||||
"dlUri": "https://downloads.haskell.org/~ghc/8.4.3/ghc-8.4.3-src.tar.xz"
|
||||
},
|
||||
"viChangeLog": "https://downloads.haskell.org/ghc/8.4.3/docs/html/users_guide/8.4.3-notes.html",
|
||||
"viTags": []
|
||||
},
|
||||
"8.6.1": {
|
||||
|
@ -1365,6 +1375,7 @@
|
|||
"dlSubdir": "ghc-8.6.1",
|
||||
"dlUri": "https://downloads.haskell.org/~ghc/8.6.1/ghc-8.6.1-src.tar.xz"
|
||||
},
|
||||
"viChangeLog": "https://downloads.haskell.org/ghc/8.6.1/docs/html/users_guide/8.6.1-notes.html",
|
||||
"viTags": []
|
||||
},
|
||||
"8.8.2": {
|
||||
|
@ -1492,6 +1503,7 @@
|
|||
"dlSubdir": "ghc-8.8.2",
|
||||
"dlUri": "https://downloads.haskell.org/~ghc/8.8.2/ghc-8.8.2-src.tar.xz"
|
||||
},
|
||||
"viChangeLog": "https://downloads.haskell.org/ghc/8.8.2/docs/html/users_guide/8.8.2-notes.html",
|
||||
"viTags": []
|
||||
},
|
||||
"7.10.3": {
|
||||
|
@ -1618,6 +1630,7 @@
|
|||
"dlSubdir": "ghc-7.10.3",
|
||||
"dlUri": "https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-src.tar.xz"
|
||||
},
|
||||
"viChangeLog": "https://downloads.haskell.org/ghc/7.10.3/docs/html/users_guide/release-7-10-1.html",
|
||||
"viTags": []
|
||||
},
|
||||
"8.2.2": {
|
||||
|
@ -1722,6 +1735,7 @@
|
|||
"dlSubdir": "ghc-8.2.2",
|
||||
"dlUri": "https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-src.tar.xz"
|
||||
},
|
||||
"viChangeLog": "https://downloads.haskell.org/ghc/8.2.2/docs/html/users_guide/8.2.2-notes.html",
|
||||
"viTags": []
|
||||
},
|
||||
"8.4.4": {
|
||||
|
@ -1856,6 +1870,7 @@
|
|||
"dlSubdir": "ghc-8.4.4",
|
||||
"dlUri": "https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-src.tar.xz"
|
||||
},
|
||||
"viChangeLog": "https://downloads.haskell.org/ghc/8.4.4/docs/html/users_guide/8.4.4-notes.html",
|
||||
"viTags": []
|
||||
},
|
||||
"8.8.3": {
|
||||
|
@ -1943,7 +1958,7 @@
|
|||
"A_32": {
|
||||
"Linux_Alpine": {
|
||||
"unknown_versioning": {
|
||||
"dlHash": "23779adb4cf4b314d0f8c66ee215ba6e74154c0768a573780475943544020bec",
|
||||
"dlHash": "7a5f41646d06777e75636291a1855d60a0984552bbdf33c3d107565d302f38a4",
|
||||
"dlSubdir": "ghc-8.8.3",
|
||||
"dlUri": "https://github.com/redneb/ghc-alt-libc/releases/download/ghc-8.8.3-musl/ghc-8.8.3-i386-unknown-linux-musl.tar.xz"
|
||||
}
|
||||
|
@ -1983,6 +1998,7 @@
|
|||
"dlSubdir": "ghc-8.8.3",
|
||||
"dlUri": "https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-src.tar.xz"
|
||||
},
|
||||
"viChangeLog": "https://downloads.haskell.org/ghc/8.8.3/docs/html/users_guide/8.8.3-notes.html",
|
||||
"viTags": [
|
||||
"Recommended"
|
||||
]
|
||||
|
@ -2022,6 +2038,7 @@
|
|||
"dlSubdir": "cabal-cabal-install-v3.0.0.0/cabal-install",
|
||||
"dlUri": "https://github.com/haskell/cabal/archive/cabal-install-v3.0.0.0.tar.gz"
|
||||
},
|
||||
"viChangeLog": "https://downloads.haskell.org/~cabal/cabal-install-3.0.0.0/changelog",
|
||||
"viTags": []
|
||||
},
|
||||
"3.2.0.0": {
|
||||
|
@ -2057,6 +2074,7 @@
|
|||
"dlSubdir": "cabal-cabal-install-v3.2.0.0/cabal-install",
|
||||
"dlUri": "https://github.com/haskell/cabal/archive/cabal-install-v3.2.0.0.tar.gz"
|
||||
},
|
||||
"viChangeLog": "https://downloads.haskell.org/~cabal/cabal-install-3.2.0.0/changelog",
|
||||
"viTags": [
|
||||
"Recommended",
|
||||
"Latest"
|
||||
|
@ -2109,46 +2127,48 @@
|
|||
"dlSubdir": "cabal-cabal-install-v2.4.1.0/cabal-install",
|
||||
"dlUri": "https://github.com/haskell/cabal/archive/cabal-install-v2.4.1.0.tar.gz"
|
||||
},
|
||||
"viChangeLog": "https://downloads.haskell.org/~cabal/cabal-install-2.4.1.0/changelog",
|
||||
"viTags": []
|
||||
}
|
||||
},
|
||||
"GHCup": {
|
||||
"0.1.3": {
|
||||
"0.1.4": {
|
||||
"viArch": {
|
||||
"A_64": {
|
||||
"FreeBSD": {
|
||||
"unknown_versioning": {
|
||||
"dlHash": "2daa775d6fa307cb8123fa45ba20e2acd244cdb8cfb3f2b3c8a1aa3f3571c46f",
|
||||
"dlHash": "cda0b959f053abc04ab0a1b9919a505b8c9304e2898a291f527a370cb0e00731",
|
||||
"dlSubdir": null,
|
||||
"dlUri": "https://downloads.haskell.org/~ghcup/0.1.3/x86_64-portbld-freebsd-ghcup-0.1.3"
|
||||
"dlUri": "https://downloads.haskell.org/~ghcup/0.1.4/x86_64-portbld-freebsd-ghcup-0.1.4"
|
||||
}
|
||||
},
|
||||
"Darwin": {
|
||||
"unknown_versioning": {
|
||||
"dlHash": "a617b06619ec6e75d50dac53f36814c3cafd4dbeebe8cea46d9cd5842c0c94a9",
|
||||
"dlHash": "2422b79933ae037237ccb8f836417b90b3111d7931beb7ae8b9e33a1945c641e",
|
||||
"dlSubdir": null,
|
||||
"dlUri": "https://downloads.haskell.org/~ghcup/0.1.3/x86_64-apple-darwin-ghcup-0.1.3"
|
||||
"dlUri": "https://downloads.haskell.org/~ghcup/0.1.4/x86_64-apple-darwin-ghcup-0.1.4"
|
||||
}
|
||||
},
|
||||
"Linux_UnknownLinux": {
|
||||
"unknown_versioning": {
|
||||
"dlHash": "873f73b65cf5e399864b81ed597a0e14fa73e0c492429cd3a85fe0fdc585a4c8",
|
||||
"dlHash": "78d69ed4c9a810a445af89ea25e4217a632799ecb427b06cd2320ffb574f555e",
|
||||
"dlSubdir": null,
|
||||
"dlUri": "https://downloads.haskell.org/~ghcup/0.1.3/x86_64-linux-ghcup-0.1.3"
|
||||
"dlUri": "https://downloads.haskell.org/~ghcup/0.1.4/x86_64-linux-ghcup-0.1.4"
|
||||
}
|
||||
}
|
||||
},
|
||||
"A_32": {
|
||||
"Linux_UnknownLinux": {
|
||||
"unknown_versioning": {
|
||||
"dlHash": "ff76a6130d6ea869a65bed127255bfa1ddf6aa1bd690df99d872467422c08be0",
|
||||
"dlHash": "057cc1cc39abdacd92cb1d4fb44c850fd9c5398a36b893286248ac5c38bc0c70",
|
||||
"dlSubdir": null,
|
||||
"dlUri": "https://downloads.haskell.org/~ghcup/0.1.3/i386-linux-ghcup-0.1.3"
|
||||
"dlUri": "https://downloads.haskell.org/~ghcup/0.1.4/i386-linux-ghcup-0.1.4"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"viSourceDL": null,
|
||||
"viChangeLog": "https://gitlab.haskell.org/haskell/ghcup-hs/-/blob/master/CHANGELOG.md",
|
||||
"viTags": [
|
||||
"Recommended",
|
||||
"Latest"
|
||||
|
|
File diff suppressed because it is too large
Load Diff
21
ghcup.cabal
21
ghcup.cabal
|
@ -21,8 +21,8 @@ source-repository head
|
|||
type: git
|
||||
location: https://gitlab.haskell.org/haskell/ghcup-hs.git
|
||||
|
||||
flag Curl
|
||||
description: Use curl instead of http-io-streams for download
|
||||
flag internal-downloader
|
||||
description: Compile the internal downloader, which links against OpenSSL
|
||||
default: False
|
||||
manual: True
|
||||
|
||||
|
@ -279,6 +279,9 @@ library
|
|||
|
||||
exposed-modules:
|
||||
GHCup
|
||||
GHCup.Data.GHCupDownloads
|
||||
GHCup.Data.GHCupInfo
|
||||
GHCup.Data.ToolRequirements
|
||||
GHCup.Download
|
||||
GHCup.Download.Utils
|
||||
GHCup.Errors
|
||||
|
@ -301,15 +304,14 @@ library
|
|||
-- other-extensions:
|
||||
hs-source-dirs: lib
|
||||
|
||||
if !flag(curl)
|
||||
if flag(internal-downloader)
|
||||
import:
|
||||
, HsOpenSSL
|
||||
, http-io-streams
|
||||
, io-streams
|
||||
, terminal-progress-bar
|
||||
exposed-modules: GHCup.Download.IOStreams
|
||||
else
|
||||
cpp-options: -DCURL
|
||||
cpp-options: -DINTERNAL_DOWNLOADER
|
||||
|
||||
executable ghcup
|
||||
import:
|
||||
|
@ -326,8 +328,10 @@ executable ghcup
|
|||
, optparse-applicative
|
||||
, pretty-terminal
|
||||
, resourcet
|
||||
, safe
|
||||
, string-interpolate
|
||||
, table-layout
|
||||
, template-haskell
|
||||
, text
|
||||
, uri-bytestring
|
||||
, utf8-string
|
||||
|
@ -342,6 +346,10 @@ executable ghcup
|
|||
hs-source-dirs: app/ghcup
|
||||
default-language: Haskell2010
|
||||
|
||||
if flag(internal-downloader)
|
||||
cpp-options: -DINTERNAL_DOWNLOADER
|
||||
|
||||
|
||||
executable ghcup-gen
|
||||
import:
|
||||
config
|
||||
|
@ -370,9 +378,6 @@ executable ghcup-gen
|
|||
--
|
||||
main-is: Main.hs
|
||||
other-modules:
|
||||
GHCupDownloads
|
||||
GHCupInfo
|
||||
ToolRequirements
|
||||
Validate
|
||||
|
||||
-- other-extensions:
|
||||
|
|
127
lib/GHCup.hs
127
lib/GHCup.hs
|
@ -9,6 +9,7 @@
|
|||
{-# LANGUAGE TemplateHaskell #-}
|
||||
{-# LANGUAGE TypeApplications #-}
|
||||
{-# LANGUAGE TypeFamilies #-}
|
||||
{-# LANGUAGE ViewPatterns #-}
|
||||
|
||||
module GHCup where
|
||||
|
||||
|
@ -96,15 +97,15 @@ installGHCBin bDls ver mpfReq = do
|
|||
lift $ $(logDebug) [i|Requested to install GHC with #{ver}|]
|
||||
whenM (liftIO $ toolAlreadyInstalled GHC ver)
|
||||
$ (throwE $ AlreadyInstalled GHC ver)
|
||||
Settings {..} <- lift ask
|
||||
Settings {..} <- lift ask
|
||||
pfreq@(PlatformRequest {..}) <- maybe (liftE $ platformRequest) pure mpfReq
|
||||
|
||||
-- download (or use cached version)
|
||||
dlinfo <- lE $ getDownloadInfo GHC ver pfreq bDls
|
||||
dl <- liftE $ downloadCached dlinfo Nothing
|
||||
dlinfo <- lE $ getDownloadInfo GHC ver pfreq bDls
|
||||
dl <- liftE $ downloadCached dlinfo Nothing
|
||||
|
||||
-- unpack
|
||||
tmpUnpack <- lift mkGhcupTmpDir
|
||||
tmpUnpack <- lift mkGhcupTmpDir
|
||||
liftE $ unpackToDir tmpUnpack dl
|
||||
void $ liftIO $ darwinNotarization _rPlatform tmpUnpack
|
||||
|
||||
|
@ -114,24 +115,12 @@ installGHCBin bDls ver mpfReq = do
|
|||
-- the subdir of the archive where we do the work
|
||||
let workdir = maybe tmpUnpack (tmpUnpack </>) (view dlSubdir dlinfo)
|
||||
|
||||
-- Be careful about cleanup. We must catch both pure exceptions
|
||||
-- as well as async ones.
|
||||
flip onException
|
||||
(liftIO $ hideError doesNotExistErrorType $ deleteDirRecursive ghcdir)
|
||||
$ catchAllE
|
||||
(\es -> do
|
||||
liftIO (hideError doesNotExistErrorType $ deleteDirRecursive ghcdir)
|
||||
>> throwE (BuildFailed workdir es)
|
||||
)
|
||||
$ installGHC' workdir ghcdir
|
||||
|
||||
-- only clean up dir if the build succeeded
|
||||
liftIO $ deleteDirRecursive tmpUnpack
|
||||
liftE $ runBuildAction tmpUnpack (Just ghcdir) (installGHC' workdir ghcdir)
|
||||
|
||||
liftE $ postGHCInstall ver
|
||||
|
||||
where
|
||||
-- | Install an unpacked GHC distribution. This only deals with the GHC build system and nothing else.
|
||||
-- | Install an unpacked GHC distribution. This only deals with the GHC build system and nothing else.
|
||||
installGHC' :: (MonadLogger m, MonadIO m)
|
||||
=> Path Abs -- ^ Path to the unpacked GHC bindist (where the configure script resides)
|
||||
-> Path Abs -- ^ Path to install to
|
||||
|
@ -194,7 +183,7 @@ installCabalBin bDls ver mpfReq = do
|
|||
pure ()
|
||||
|
||||
where
|
||||
-- | Install an unpacked cabal distribution.
|
||||
-- | Install an unpacked cabal distribution.
|
||||
installCabal' :: (MonadLogger m, MonadCatch m, MonadIO m)
|
||||
=> Path Abs -- ^ Path to the unpacked cabal bindist (where the executable resides)
|
||||
-> Path Abs -- ^ Path to install to
|
||||
|
@ -305,25 +294,38 @@ data ListResult = ListResult
|
|||
, lVer :: Version
|
||||
, lTag :: [Tag]
|
||||
, lInstalled :: Bool
|
||||
, lSet :: Bool
|
||||
, fromSrc :: Bool
|
||||
, lSet :: Bool -- ^ currently active version
|
||||
, fromSrc :: Bool -- ^ compiled from source
|
||||
, lStray :: Bool -- ^ not in download info
|
||||
}
|
||||
deriving Show
|
||||
deriving (Eq, Ord, Show)
|
||||
|
||||
|
||||
availableToolVersions :: GHCupDownloads -> Tool -> [(Version, [Tag])]
|
||||
availableToolVersions av tool = toListOf
|
||||
(ix tool % to (fmap (\(v, vi) -> (v, (_viTags vi))) . Map.toList) % folded)
|
||||
availableToolVersions :: GHCupDownloads -> Tool -> Map.Map Version [Tag]
|
||||
availableToolVersions av tool = view
|
||||
(at tool % non Map.empty % to (fmap (_viTags)))
|
||||
av
|
||||
|
||||
|
||||
listVersions :: GHCupDownloads
|
||||
-- | List all versions from the download info, as well as stray
|
||||
-- versions.
|
||||
listVersions :: (MonadLogger m, MonadIO m)
|
||||
=> GHCupDownloads
|
||||
-> Maybe Tool
|
||||
-> Maybe ListCriteria
|
||||
-> IO [ListResult]
|
||||
-> m [ListResult]
|
||||
listVersions av lt criteria = case lt of
|
||||
Just t -> do
|
||||
filter' <$> forM (availableToolVersions av t) (toListResult t)
|
||||
-- get versions from GHCupDownloads
|
||||
let avTools = availableToolVersions av t
|
||||
lr <- filter' <$> forM (Map.toList avTools) (liftIO . toListResult t)
|
||||
|
||||
case t of
|
||||
-- append stray GHCs
|
||||
GHC -> do
|
||||
slr <- strayGHCs avTools
|
||||
pure $ (sort (slr ++ lr))
|
||||
_ -> pure lr
|
||||
Nothing -> do
|
||||
ghcvers <- listVersions av (Just GHC) criteria
|
||||
cabalvers <- listVersions av (Just Cabal) criteria
|
||||
|
@ -331,21 +333,60 @@ listVersions av lt criteria = case lt of
|
|||
pure (ghcvers <> cabalvers <> ghcupvers)
|
||||
|
||||
where
|
||||
strayGHCs :: (MonadLogger m, MonadIO m)
|
||||
=> Map.Map Version [Tag]
|
||||
-> m [ListResult]
|
||||
strayGHCs avTools = do
|
||||
ghcdir <- liftIO $ ghcupGHCBaseDir
|
||||
fs <- liftIO $ liftIO $ hideErrorDef [NoSuchThing] [] $ getDirsFiles' ghcdir
|
||||
fmap catMaybes $ forM fs $ \(toFilePath -> f) -> do
|
||||
case version . decUTF8Safe $ f of
|
||||
Right v' -> do
|
||||
case Map.lookup v' avTools of
|
||||
Just _ -> pure Nothing
|
||||
Nothing -> do
|
||||
lSet <- fmap (maybe False (== v')) $ ghcSet
|
||||
fromSrc <- liftIO $ ghcSrcInstalled v'
|
||||
pure $ Just $ ListResult
|
||||
{ lTool = GHC
|
||||
, lVer = v'
|
||||
, lTag = []
|
||||
, lInstalled = True
|
||||
, lStray = maybe True (const False) (Map.lookup v' avTools)
|
||||
, ..
|
||||
}
|
||||
Left e -> do
|
||||
$(logWarn)
|
||||
[i|Could not parse version of stray directory #{toFilePath ghcdir}/#{f}: #{e}|]
|
||||
pure Nothing
|
||||
|
||||
toListResult :: Tool -> (Version, [Tag]) -> IO ListResult
|
||||
toListResult t (v, tags) = case t of
|
||||
GHC -> do
|
||||
lSet <- fmap (maybe False (== v)) $ ghcSet
|
||||
lInstalled <- ghcInstalled v
|
||||
fromSrc <- ghcSrcInstalled v
|
||||
pure ListResult { lVer = v, lTag = tags, lTool = t, .. }
|
||||
pure ListResult { lVer = v, lTag = tags, lTool = t, lStray = False, .. }
|
||||
Cabal -> do
|
||||
lSet <- fmap (== v) $ cabalSet
|
||||
let lInstalled = lSet
|
||||
pure ListResult { lVer = v, lTag = tags, lTool = t, fromSrc = False, .. }
|
||||
pure ListResult { lVer = v
|
||||
, lTag = tags
|
||||
, lTool = t
|
||||
, fromSrc = False
|
||||
, lStray = False
|
||||
, ..
|
||||
}
|
||||
GHCup -> do
|
||||
let lSet = prettyPVP ghcUpVer == prettyVer v
|
||||
let lInstalled = lSet
|
||||
pure ListResult { lVer = v, lTag = tags, lTool = t, fromSrc = False, .. }
|
||||
pure ListResult { lVer = v
|
||||
, lTag = tags
|
||||
, lTool = t
|
||||
, fromSrc = False
|
||||
, lStray = False
|
||||
, ..
|
||||
}
|
||||
|
||||
|
||||
filter' :: [ListResult] -> [ListResult]
|
||||
|
@ -480,20 +521,10 @@ compileGHC dls tver bstrap jobs mbuildConfig patchdir = do
|
|||
let workdir = maybe id (flip (</>)) (view dlSubdir dlInfo) $ tmpUnpack
|
||||
ghcdir <- liftIO $ ghcupGHCDir tver
|
||||
|
||||
-- Be careful about cleanup. We must catch both pure exceptions
|
||||
-- as well as async ones.
|
||||
flip onException
|
||||
(liftIO $ hideError doesNotExistErrorType $ deleteDirRecursive ghcdir)
|
||||
$ catchAllE
|
||||
(\es ->
|
||||
liftIO (hideError doesNotExistErrorType $ deleteDirRecursive ghcdir)
|
||||
>> throwE (BuildFailed workdir es)
|
||||
)
|
||||
$ compile bghc ghcdir workdir
|
||||
markSrcBuilt ghcdir workdir
|
||||
|
||||
-- only clean up dir if the build succeeded
|
||||
liftIO $ deleteDirRecursive tmpUnpack
|
||||
liftE $ runBuildAction
|
||||
tmpUnpack
|
||||
(Just ghcdir)
|
||||
(compile bghc ghcdir workdir >> markSrcBuilt ghcdir workdir)
|
||||
|
||||
reThrowAll GHCupSetError $ postGHCInstall tver
|
||||
pure ()
|
||||
|
@ -613,7 +644,11 @@ compileCabal dls tver bghc jobs patchdir = do
|
|||
|
||||
let workdir = maybe id (flip (</>)) (view dlSubdir dlInfo) $ tmpUnpack
|
||||
|
||||
reThrowAll (BuildFailed workdir) $ compile workdir
|
||||
|
||||
liftE $ runBuildAction
|
||||
tmpUnpack
|
||||
Nothing
|
||||
(compile workdir)
|
||||
|
||||
-- only clean up dir if the build succeeded
|
||||
liftIO $ deleteDirRecursive tmpUnpack
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
{-# LANGUAGE QuasiQuotes #-}
|
||||
|
||||
|
||||
module GHCupDownloads where
|
||||
module GHCup.Data.GHCupDownloads where
|
||||
|
||||
import GHCup.Types
|
||||
import GHCup.Utils.Version.QQ
|
||||
|
@ -827,7 +827,7 @@ ghc_883_32_musl :: DownloadInfo
|
|||
ghc_883_32_musl = DownloadInfo
|
||||
[uri|https://github.com/redneb/ghc-alt-libc/releases/download/ghc-8.8.3-musl/ghc-8.8.3-i386-unknown-linux-musl.tar.xz|]
|
||||
(Just [rel|ghc-8.8.3|])
|
||||
"23779adb4cf4b314d0f8c66ee215ba6e74154c0768a573780475943544020bec"
|
||||
"7a5f41646d06777e75636291a1855d60a0984552bbdf33c3d107565d302f38a4"
|
||||
|
||||
|
||||
|
||||
|
@ -951,6 +951,24 @@ cabal_3000_64_darwin = DownloadInfo
|
|||
Nothing
|
||||
"d4857e068560515e4cbb0e8ca124c370e07892f2a28804d87152834e5fe2b845"
|
||||
|
||||
cabal_3000_64_freebsd :: DownloadInfo
|
||||
cabal_3000_64_freebsd = DownloadInfo
|
||||
[uri|https://hasufell.de/d/d3e215db133e4fcaa61e/files/?p=/cabal-install-3.0.0.0-x86_64-portbld-freebsd.tar.xz&dl=1|]
|
||||
Nothing
|
||||
"d97b6469ed612a1367ad1032d0722469ee5277668879694d7d4336233b937516"
|
||||
|
||||
cabal_3000_32_alpine :: DownloadInfo
|
||||
cabal_3000_32_alpine = DownloadInfo
|
||||
[uri|https://hasufell.de/d/d3e215db133e4fcaa61e/files/?p=/cabal-install-3.0.0.0-i386-alpine-linux-musl.tar.xz&dl=1|]
|
||||
Nothing
|
||||
"a4191cd5a645b00e6a9c53abe6f3cb91fe700de7d7c520c9cb36ce8ec5c9919a"
|
||||
|
||||
cabal_3000_64_alpine :: DownloadInfo
|
||||
cabal_3000_64_alpine = DownloadInfo
|
||||
[uri|https://hasufell.de/d/d3e215db133e4fcaa61e/files/?p=/cabal-install-3.0.0.0-x86_64-alpine-linux-musl.tar.xz&dl=1|]
|
||||
Nothing
|
||||
"7b35e5986aba4a40fc37141cbde26612bfc916e95a2d2ff35a413612d8c7cd3a"
|
||||
|
||||
|
||||
|
||||
---------------------
|
||||
|
@ -976,6 +994,24 @@ cabal_3200_64_darwin = DownloadInfo
|
|||
Nothing
|
||||
"9197c17d2ece0f934f5b33e323cfcaf486e4681952687bc3d249488ce3cbe0e9"
|
||||
|
||||
cabal_3200_64_freebsd :: DownloadInfo
|
||||
cabal_3200_64_freebsd = DownloadInfo
|
||||
[uri|https://hasufell.de/d/d3e215db133e4fcaa61e/files/?p=/cabal-install-3.2.0.0-x86_64-portbld-freebsd.tar.xz&dl=1|]
|
||||
Nothing
|
||||
"e4dc00ab7fef51354e7624dd03e49c6bb684887fc95acb9b33bc52f357a5ef8c"
|
||||
|
||||
cabal_3200_32_alpine :: DownloadInfo
|
||||
cabal_3200_32_alpine = DownloadInfo
|
||||
[uri|https://hasufell.de/d/d3e215db133e4fcaa61e/files/?p=/cabal-install-3.2.0.0-i386-alpine-linux-musl.tar.xz&dl=1|]
|
||||
Nothing
|
||||
"4aaa52fbc337ae1ef855a2aa2808186580b21ec36883aafec7473e7d899bc5ec"
|
||||
|
||||
cabal_3200_64_alpine :: DownloadInfo
|
||||
cabal_3200_64_alpine = DownloadInfo
|
||||
[uri|https://hasufell.de/d/d3e215db133e4fcaa61e/files/?p=/cabal-install-3.2.0.0-x86_64-alpine-linux-musl.tar.xz&dl=1|]
|
||||
Nothing
|
||||
"c1f3c21a5307cea8d2a0bd9a2eab9f56f3dd90e947ae64e231f909024980992b"
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -984,32 +1020,32 @@ cabal_3200_64_darwin = DownloadInfo
|
|||
-------------
|
||||
|
||||
|
||||
ghcup_013_32_linux :: DownloadInfo
|
||||
ghcup_013_32_linux = DownloadInfo
|
||||
[uri|https://downloads.haskell.org/~ghcup/0.1.3/i386-linux-ghcup-0.1.3|]
|
||||
ghcup_014_32_linux :: DownloadInfo
|
||||
ghcup_014_32_linux = DownloadInfo
|
||||
[uri|https://downloads.haskell.org/~ghcup/0.1.4/i386-linux-ghcup-0.1.4|]
|
||||
Nothing
|
||||
"ff76a6130d6ea869a65bed127255bfa1ddf6aa1bd690df99d872467422c08be0"
|
||||
"057cc1cc39abdacd92cb1d4fb44c850fd9c5398a36b893286248ac5c38bc0c70"
|
||||
|
||||
|
||||
ghcup_013_64_linux :: DownloadInfo
|
||||
ghcup_013_64_linux = DownloadInfo
|
||||
[uri|https://downloads.haskell.org/~ghcup/0.1.3/x86_64-linux-ghcup-0.1.3|]
|
||||
ghcup_014_64_linux :: DownloadInfo
|
||||
ghcup_014_64_linux = DownloadInfo
|
||||
[uri|https://downloads.haskell.org/~ghcup/0.1.4/x86_64-linux-ghcup-0.1.4|]
|
||||
Nothing
|
||||
"873f73b65cf5e399864b81ed597a0e14fa73e0c492429cd3a85fe0fdc585a4c8"
|
||||
"78d69ed4c9a810a445af89ea25e4217a632799ecb427b06cd2320ffb574f555e"
|
||||
|
||||
|
||||
ghcup_013_64_freebsd :: DownloadInfo
|
||||
ghcup_013_64_freebsd = DownloadInfo
|
||||
[uri|https://downloads.haskell.org/~ghcup/0.1.3/x86_64-portbld-freebsd-ghcup-0.1.3|]
|
||||
ghcup_014_64_freebsd :: DownloadInfo
|
||||
ghcup_014_64_freebsd = DownloadInfo
|
||||
[uri|https://downloads.haskell.org/~ghcup/0.1.4/x86_64-portbld-freebsd-ghcup-0.1.4|]
|
||||
Nothing
|
||||
"2daa775d6fa307cb8123fa45ba20e2acd244cdb8cfb3f2b3c8a1aa3f3571c46f"
|
||||
"cda0b959f053abc04ab0a1b9919a505b8c9304e2898a291f527a370cb0e00731"
|
||||
|
||||
|
||||
ghcup_013_64_darwin10_13 :: DownloadInfo
|
||||
ghcup_013_64_darwin10_13 = DownloadInfo
|
||||
[uri|https://downloads.haskell.org/~ghcup/0.1.3/x86_64-apple-darwin-ghcup-0.1.3|]
|
||||
ghcup_014_64_darwin10_13 :: DownloadInfo
|
||||
ghcup_014_64_darwin10_13 = DownloadInfo
|
||||
[uri|https://downloads.haskell.org/~ghcup/0.1.4/x86_64-apple-darwin-ghcup-0.1.4|]
|
||||
Nothing
|
||||
"a617b06619ec6e75d50dac53f36814c3cafd4dbeebe8cea46d9cd5842c0c94a9"
|
||||
"2422b79933ae037237ccb8f836417b90b3111d7931beb7ae8b9e33a1945c641e"
|
||||
|
||||
|
||||
|
||||
|
@ -1026,7 +1062,10 @@ ghcupDownloads = M.fromList
|
|||
, M.fromList
|
||||
[ ( [vver|7.10.3|]
|
||||
, VersionInfo
|
||||
[]
|
||||
[Base [pver|4.8.2.0|]]
|
||||
(Just
|
||||
[uri|https://downloads.haskell.org/ghc/7.10.3/docs/html/users_guide/release-7-10-1.html|]
|
||||
)
|
||||
(Just $ DownloadInfo
|
||||
[uri|https://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-src.tar.xz|]
|
||||
(Just [rel|ghc-7.10.3|])
|
||||
|
@ -1069,7 +1108,10 @@ ghcupDownloads = M.fromList
|
|||
)
|
||||
, ( [vver|8.0.2|]
|
||||
, VersionInfo
|
||||
[]
|
||||
[Base [pver|4.9.1.0|]]
|
||||
(Just
|
||||
[uri|https://downloads.haskell.org/ghc/8.0.2/docs/html/users_guide/8.0.1-notes.html|]
|
||||
)
|
||||
(Just $ DownloadInfo
|
||||
[uri|https://downloads.haskell.org/~ghc/8.0.2/ghc-8.0.2-src.tar.xz|]
|
||||
(Just [rel|ghc-8.0.2|])
|
||||
|
@ -1112,7 +1154,10 @@ ghcupDownloads = M.fromList
|
|||
)
|
||||
, ( [vver|8.2.2|]
|
||||
, VersionInfo
|
||||
[]
|
||||
[Base [pver|4.10.1.0|]]
|
||||
(Just
|
||||
[uri|https://downloads.haskell.org/ghc/8.2.2/docs/html/users_guide/8.2.2-notes.html|]
|
||||
)
|
||||
(Just $ DownloadInfo
|
||||
[uri|https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-src.tar.xz|]
|
||||
(Just [rel|ghc-8.2.2|])
|
||||
|
@ -1161,7 +1206,10 @@ ghcupDownloads = M.fromList
|
|||
)
|
||||
, ( [vver|8.4.1|]
|
||||
, VersionInfo
|
||||
[]
|
||||
[Base [pver|4.11.0.0|]]
|
||||
(Just
|
||||
[uri|https://downloads.haskell.org/ghc/8.4.1/docs/html/users_guide/8.4.1-notes.html|]
|
||||
)
|
||||
(Just $ DownloadInfo
|
||||
[uri|https://downloads.haskell.org/~ghc/8.4.1/ghc-8.4.1-src.tar.xz|]
|
||||
(Just [rel|ghc-8.4.1|])
|
||||
|
@ -1197,7 +1245,10 @@ ghcupDownloads = M.fromList
|
|||
)
|
||||
, ( [vver|8.4.2|]
|
||||
, VersionInfo
|
||||
[]
|
||||
[Base [pver|4.11.1.0|]]
|
||||
(Just
|
||||
[uri|https://downloads.haskell.org/ghc/8.4.2/docs/html/users_guide/8.4.2-notes.html|]
|
||||
)
|
||||
(Just $ DownloadInfo
|
||||
[uri|https://downloads.haskell.org/~ghc/8.4.2/ghc-8.4.2-src.tar.xz|]
|
||||
(Just [rel|ghc-8.4.2|])
|
||||
|
@ -1244,7 +1295,10 @@ ghcupDownloads = M.fromList
|
|||
)
|
||||
, ( [vver|8.4.3|]
|
||||
, VersionInfo
|
||||
[]
|
||||
[Base [pver|4.11.1.0|]]
|
||||
(Just
|
||||
[uri|https://downloads.haskell.org/ghc/8.4.3/docs/html/users_guide/8.4.3-notes.html|]
|
||||
)
|
||||
(Just $ DownloadInfo
|
||||
[uri|https://downloads.haskell.org/~ghc/8.4.3/ghc-8.4.3-src.tar.xz|]
|
||||
(Just [rel|ghc-8.4.3|])
|
||||
|
@ -1290,7 +1344,10 @@ ghcupDownloads = M.fromList
|
|||
)
|
||||
, ( [vver|8.4.4|]
|
||||
, VersionInfo
|
||||
[]
|
||||
[Base [pver|4.11.1.0|]]
|
||||
(Just
|
||||
[uri|https://downloads.haskell.org/ghc/8.4.4/docs/html/users_guide/8.4.4-notes.html|]
|
||||
)
|
||||
(Just $ DownloadInfo
|
||||
[uri|https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-src.tar.xz|]
|
||||
(Just [rel|ghc-8.4.4|])
|
||||
|
@ -1341,7 +1398,10 @@ ghcupDownloads = M.fromList
|
|||
)
|
||||
, ( [vver|8.6.1|]
|
||||
, VersionInfo
|
||||
[]
|
||||
[Base [pver|4.12.0.0|]]
|
||||
(Just
|
||||
[uri|https://downloads.haskell.org/ghc/8.6.1/docs/html/users_guide/8.6.1-notes.html|]
|
||||
)
|
||||
(Just $ DownloadInfo
|
||||
[uri|https://downloads.haskell.org/~ghc/8.6.1/ghc-8.6.1-src.tar.xz|]
|
||||
(Just [rel|ghc-8.6.1|])
|
||||
|
@ -1388,7 +1448,10 @@ ghcupDownloads = M.fromList
|
|||
)
|
||||
, ( [vver|8.6.2|]
|
||||
, VersionInfo
|
||||
[]
|
||||
[Base [pver|4.12.0.0|]]
|
||||
(Just
|
||||
[uri|https://downloads.haskell.org/ghc/8.6.2/docs/html/users_guide/8.6.2-notes.html|]
|
||||
)
|
||||
(Just $ DownloadInfo
|
||||
[uri|https://downloads.haskell.org/~ghc/8.6.2/ghc-8.6.2-src.tar.xz|]
|
||||
(Just [rel|ghc-8.6.2|])
|
||||
|
@ -1429,7 +1492,10 @@ ghcupDownloads = M.fromList
|
|||
)
|
||||
, ( [vver|8.6.3|]
|
||||
, VersionInfo
|
||||
[]
|
||||
[Base [pver|4.12.0.0|]]
|
||||
(Just
|
||||
[uri|https://downloads.haskell.org/ghc/8.6.3/docs/html/users_guide/8.6.3-notes.html|]
|
||||
)
|
||||
(Just $ DownloadInfo
|
||||
[uri|https://downloads.haskell.org/~ghc/8.6.3/ghc-8.6.3-src.tar.xz|]
|
||||
(Just [rel|ghc-8.6.3|])
|
||||
|
@ -1480,7 +1546,10 @@ ghcupDownloads = M.fromList
|
|||
)
|
||||
, ( [vver|8.6.4|]
|
||||
, VersionInfo
|
||||
[]
|
||||
[Base [pver|4.12.0.0|]]
|
||||
(Just
|
||||
[uri|https://downloads.haskell.org/ghc/8.6.4/docs/html/users_guide/8.6.4-notes.html|]
|
||||
)
|
||||
(Just $ DownloadInfo
|
||||
[uri|https://downloads.haskell.org/~ghc/8.6.4/ghc-8.6.4-src.tar.xz|]
|
||||
(Just [rel|ghc-8.6.4|])
|
||||
|
@ -1526,7 +1595,10 @@ ghcupDownloads = M.fromList
|
|||
)
|
||||
, ( [vver|8.6.5|]
|
||||
, VersionInfo
|
||||
[]
|
||||
[Base [pver|4.12.0.0|]]
|
||||
(Just
|
||||
[uri|https://downloads.haskell.org/ghc/8.6.5/docs/html/users_guide/8.6.5-notes.html|]
|
||||
)
|
||||
(Just $ DownloadInfo
|
||||
[uri|https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-src.tar.xz|]
|
||||
(Just [rel|ghc-8.6.5|])
|
||||
|
@ -1576,7 +1648,10 @@ ghcupDownloads = M.fromList
|
|||
)
|
||||
, ( [vver|8.8.1|]
|
||||
, VersionInfo
|
||||
[]
|
||||
[Base [pver|4.13.0.0|]]
|
||||
(Just
|
||||
[uri|https://downloads.haskell.org/ghc/8.8.1/docs/html/users_guide/8.8.1-notes.html|]
|
||||
)
|
||||
(Just $ DownloadInfo
|
||||
[uri|https://downloads.haskell.org/~ghc/8.8.1/ghc-8.8.1-src.tar.xz|]
|
||||
(Just [rel|ghc-8.8.1|])
|
||||
|
@ -1626,7 +1701,10 @@ ghcupDownloads = M.fromList
|
|||
)
|
||||
, ( [vver|8.8.2|]
|
||||
, VersionInfo
|
||||
[]
|
||||
[Base [pver|4.13.0.0|]]
|
||||
(Just
|
||||
[uri|https://downloads.haskell.org/ghc/8.8.2/docs/html/users_guide/8.8.2-notes.html|]
|
||||
)
|
||||
(Just $ DownloadInfo
|
||||
[uri|https://downloads.haskell.org/~ghc/8.8.2/ghc-8.8.2-src.tar.xz|]
|
||||
(Just [rel|ghc-8.8.2|])
|
||||
|
@ -1676,7 +1754,10 @@ ghcupDownloads = M.fromList
|
|||
)
|
||||
, ( [vver|8.8.3|]
|
||||
, VersionInfo
|
||||
[Recommended]
|
||||
[Recommended, Base [pver|4.13.0.0|]]
|
||||
(Just
|
||||
[uri|https://downloads.haskell.org/ghc/8.8.3/docs/html/users_guide/8.8.3-notes.html|]
|
||||
)
|
||||
(Just $ DownloadInfo
|
||||
[uri|https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-src.tar.xz|]
|
||||
(Just [rel|ghc-8.8.3|])
|
||||
|
@ -1726,7 +1807,10 @@ ghcupDownloads = M.fromList
|
|||
)
|
||||
, ( [vver|8.10.1|]
|
||||
, VersionInfo
|
||||
[Latest]
|
||||
[Latest, Base [pver|4.14.0.0|]]
|
||||
(Just
|
||||
[uri|https://downloads.haskell.org/ghc/8.10.1/docs/html/users_guide/8.10.1-notes.html|]
|
||||
)
|
||||
(Just $ DownloadInfo
|
||||
[uri|https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-src.tar.xz|]
|
||||
(Just [rel|ghc-8.10.1|])
|
||||
|
@ -1796,6 +1880,9 @@ ghcupDownloads = M.fromList
|
|||
[ ( [vver|2.4.1.0|]
|
||||
, VersionInfo
|
||||
[]
|
||||
(Just
|
||||
[uri|https://downloads.haskell.org/~cabal/cabal-install-2.4.1.0/changelog|]
|
||||
)
|
||||
(Just $ DownloadInfo
|
||||
[uri|https://github.com/haskell/cabal/archive/cabal-install-v2.4.1.0.tar.gz|]
|
||||
(Just [rel|cabal-cabal-install-v2.4.1.0/cabal-install|])
|
||||
|
@ -1824,6 +1911,9 @@ ghcupDownloads = M.fromList
|
|||
, ( [vver|3.0.0.0|]
|
||||
, VersionInfo
|
||||
[]
|
||||
(Just
|
||||
[uri|https://downloads.haskell.org/~cabal/cabal-install-3.0.0.0/changelog|]
|
||||
)
|
||||
(Just $ DownloadInfo
|
||||
[uri|https://github.com/haskell/cabal/archive/cabal-install-v3.0.0.0.tar.gz|]
|
||||
(Just [rel|cabal-cabal-install-v3.0.0.0/cabal-install|])
|
||||
|
@ -1835,7 +1925,9 @@ ghcupDownloads = M.fromList
|
|||
[ ( Linux UnknownLinux
|
||||
, M.fromList [(Nothing, cabal_3000_64_linux)]
|
||||
)
|
||||
, (Darwin, M.fromList [(Nothing, cabal_3000_64_darwin)])
|
||||
, (Linux Alpine, M.fromList [(Nothing, cabal_3000_64_alpine)])
|
||||
, (Darwin , M.fromList [(Nothing, cabal_3000_64_darwin)])
|
||||
, (FreeBSD, M.fromList [(Nothing, cabal_3000_64_freebsd)])
|
||||
]
|
||||
)
|
||||
, ( A_32
|
||||
|
@ -1843,6 +1935,7 @@ ghcupDownloads = M.fromList
|
|||
[ ( Linux UnknownLinux
|
||||
, M.fromList [(Nothing, cabal_3000_32_linux)]
|
||||
)
|
||||
, (Linux Alpine, M.fromList [(Nothing, cabal_3000_32_alpine)])
|
||||
]
|
||||
)
|
||||
]
|
||||
|
@ -1850,6 +1943,9 @@ ghcupDownloads = M.fromList
|
|||
, ( [vver|3.2.0.0|]
|
||||
, VersionInfo
|
||||
[Recommended, Latest]
|
||||
(Just
|
||||
[uri|https://downloads.haskell.org/~cabal/cabal-install-3.2.0.0/changelog|]
|
||||
)
|
||||
(Just $ DownloadInfo
|
||||
[uri|https://github.com/haskell/cabal/archive/cabal-install-v3.2.0.0.tar.gz|]
|
||||
(Just [rel|cabal-cabal-install-v3.2.0.0/cabal-install|])
|
||||
|
@ -1861,7 +1957,9 @@ ghcupDownloads = M.fromList
|
|||
[ ( Linux UnknownLinux
|
||||
, M.fromList [(Nothing, cabal_3200_64_linux)]
|
||||
)
|
||||
, (Darwin, M.fromList [(Nothing, cabal_3200_64_darwin)])
|
||||
, (Linux Alpine, M.fromList [(Nothing, cabal_3200_64_alpine)])
|
||||
, (Darwin , M.fromList [(Nothing, cabal_3200_64_darwin)])
|
||||
, (FreeBSD, M.fromList [(Nothing, cabal_3200_64_freebsd)])
|
||||
]
|
||||
)
|
||||
, ( A_32
|
||||
|
@ -1869,6 +1967,7 @@ ghcupDownloads = M.fromList
|
|||
[ ( Linux UnknownLinux
|
||||
, M.fromList [(Nothing, cabal_3200_32_linux)]
|
||||
)
|
||||
, (Linux Alpine, M.fromList [(Nothing, cabal_3200_32_alpine)])
|
||||
]
|
||||
)
|
||||
]
|
||||
|
@ -1877,20 +1976,31 @@ ghcupDownloads = M.fromList
|
|||
)
|
||||
, ( GHCup
|
||||
, M.fromList
|
||||
[ ( [vver|0.1.3|]
|
||||
, VersionInfo [Recommended, Latest] Nothing $ M.fromList
|
||||
[ ( A_64
|
||||
, M.fromList
|
||||
[ (Linux UnknownLinux, M.fromList [(Nothing, ghcup_013_64_linux)])
|
||||
, (Darwin, M.fromList [(Nothing, ghcup_013_64_darwin10_13)])
|
||||
, (FreeBSD, M.fromList [(Nothing, ghcup_013_64_freebsd)])
|
||||
[ ( [vver|0.1.4|]
|
||||
, VersionInfo
|
||||
[Recommended, Latest]
|
||||
(Just
|
||||
[uri|https://gitlab.haskell.org/haskell/ghcup-hs/-/blob/master/CHANGELOG.md|]
|
||||
)
|
||||
Nothing
|
||||
$ M.fromList
|
||||
[ ( A_64
|
||||
, M.fromList
|
||||
[ ( Linux UnknownLinux
|
||||
, M.fromList [(Nothing, ghcup_014_64_linux)]
|
||||
)
|
||||
, (Darwin , M.fromList [(Nothing, ghcup_014_64_darwin10_13)])
|
||||
, (FreeBSD, M.fromList [(Nothing, ghcup_014_64_freebsd)])
|
||||
]
|
||||
)
|
||||
, ( A_32
|
||||
, M.fromList
|
||||
[ ( Linux UnknownLinux
|
||||
, M.fromList [(Nothing, ghcup_014_32_linux)]
|
||||
)
|
||||
]
|
||||
)
|
||||
]
|
||||
)
|
||||
, ( A_32
|
||||
, M.fromList
|
||||
[(Linux UnknownLinux, M.fromList [(Nothing, ghcup_013_32_linux)])]
|
||||
)
|
||||
]
|
||||
)
|
||||
]
|
||||
)
|
|
@ -1,7 +1,7 @@
|
|||
module GHCupInfo where
|
||||
module GHCup.Data.GHCupInfo where
|
||||
|
||||
import GHCupDownloads
|
||||
import ToolRequirements
|
||||
import GHCup.Data.GHCupDownloads
|
||||
import GHCup.Data.ToolRequirements
|
||||
import GHCup.Types
|
||||
|
||||
|
|
@ -1,10 +1,11 @@
|
|||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE QuasiQuotes #-}
|
||||
|
||||
module ToolRequirements where
|
||||
module GHCup.Data.ToolRequirements where
|
||||
|
||||
import GHCup.Types
|
||||
import GHCup.Utils.String.QQ
|
||||
import GHCup.Utils.Version.QQ
|
||||
|
||||
import qualified Data.Map as M
|
||||
|
||||
|
@ -61,6 +62,35 @@ toolRequirements = M.fromList
|
|||
)
|
||||
]
|
||||
)
|
||||
, ( Linux CentOS
|
||||
, M.fromList
|
||||
[ ( Nothing
|
||||
, Requirements
|
||||
[ "gcc"
|
||||
, "gcc-c++"
|
||||
, "gmp"
|
||||
, "make"
|
||||
, "ncurses"
|
||||
, "ncurses-compat-libs"
|
||||
, "xz"
|
||||
, "perl"
|
||||
]
|
||||
""
|
||||
),
|
||||
( Just [vers|7|]
|
||||
, Requirements
|
||||
[ "gcc"
|
||||
, "gcc-c++"
|
||||
, "gmp"
|
||||
, "make"
|
||||
, "ncurses"
|
||||
, "xz"
|
||||
, "perl"
|
||||
]
|
||||
""
|
||||
)
|
||||
]
|
||||
)
|
||||
, ( Darwin
|
||||
, M.fromList
|
||||
[ ( Nothing
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
module GHCup.Download where
|
||||
|
||||
#if !defined(CURL)
|
||||
#if defined(INTERNAL_DOWNLOADER)
|
||||
import GHCup.Download.IOStreams
|
||||
import GHCup.Download.Utils
|
||||
#endif
|
||||
|
@ -35,7 +35,7 @@ import Control.Monad.Reader
|
|||
import Control.Monad.Trans.Resource
|
||||
hiding ( throwM )
|
||||
import Data.Aeson
|
||||
#if !defined(CURL)
|
||||
#if defined(INTERNAL_DOWNLOADER)
|
||||
import Data.ByteString ( ByteString )
|
||||
import Data.CaseInsensitive ( CI )
|
||||
#endif
|
||||
|
@ -43,10 +43,11 @@ import Data.Maybe
|
|||
import Data.String.Interpolate
|
||||
import Data.Time.Clock
|
||||
import Data.Time.Clock.POSIX
|
||||
#if !defined(CURL)
|
||||
#if defined(INTERNAL_DOWNLOADER)
|
||||
import Data.Time.Format
|
||||
#endif
|
||||
import Data.Versions
|
||||
import Data.Word8
|
||||
import GHC.IO.Exception
|
||||
import HPath
|
||||
import HPath.IO as HIO
|
||||
|
@ -57,12 +58,14 @@ import Prelude hiding ( abs
|
|||
, writeFile
|
||||
)
|
||||
import System.IO.Error
|
||||
import System.Posix.Env.ByteString ( getEnv )
|
||||
import URI.ByteString
|
||||
|
||||
import qualified Crypto.Hash.SHA256 as SHA256
|
||||
import qualified Data.ByteString as BS
|
||||
import qualified Data.ByteString.Base16 as B16
|
||||
import qualified Data.ByteString.Lazy as L
|
||||
#if !defined(CURL)
|
||||
#if defined(INTERNAL_DOWNLOADER)
|
||||
import qualified Data.CaseInsensitive as CI
|
||||
import qualified Data.Map.Strict as M
|
||||
import qualified Data.Text as T
|
||||
|
@ -82,6 +85,48 @@ import qualified System.Posix.RawFilePath.Directory
|
|||
------------------
|
||||
|
||||
|
||||
-- | Like 'getDownloads', but tries to fall back to
|
||||
-- cached ~/.ghcup/cache/ghcup-<format-ver>.json
|
||||
getDownloadsF :: ( FromJSONKey Tool
|
||||
, FromJSONKey Version
|
||||
, FromJSON VersionInfo
|
||||
, MonadIO m
|
||||
, MonadCatch m
|
||||
, MonadLogger m
|
||||
, MonadThrow m
|
||||
, MonadFail m
|
||||
, MonadReader Settings m
|
||||
)
|
||||
=> URLSource
|
||||
-> Excepts
|
||||
'[JSONError , DownloadFailed , FileDoesNotExistError]
|
||||
m
|
||||
GHCupInfo
|
||||
getDownloadsF urlSource = do
|
||||
case urlSource of
|
||||
GHCupURL ->
|
||||
liftE
|
||||
$ handleIO (\_ -> readFromCache)
|
||||
$ catchE @_ @'[JSONError , FileDoesNotExistError]
|
||||
(\(DownloadFailed _) -> readFromCache)
|
||||
$ getDownloads urlSource
|
||||
(OwnSource _) -> liftE $ getDownloads urlSource
|
||||
(OwnSpec _) -> liftE $ getDownloads urlSource
|
||||
where
|
||||
readFromCache = do
|
||||
lift $ $(logWarn)
|
||||
[i|Could not get download info, trying cached version (this may not be recent!)|]
|
||||
let path = view pathL' ghcupURL
|
||||
cacheDir <- liftIO $ ghcupCacheDir
|
||||
json_file <- (cacheDir </>) <$> urlBaseName path
|
||||
bs <-
|
||||
handleIO' NoSuchThing
|
||||
(\_ -> throwE $ FileDoesNotExistError (toFilePath json_file))
|
||||
$ liftIO
|
||||
$ readFile json_file
|
||||
lE' JSONDecodeError $ eitherDecode' bs
|
||||
|
||||
|
||||
-- | Downloads the download information! But only if we need to ;P
|
||||
getDownloads :: ( FromJSONKey Tool
|
||||
, FromJSONKey Version
|
||||
|
@ -91,6 +136,7 @@ getDownloads :: ( FromJSONKey Tool
|
|||
, MonadLogger m
|
||||
, MonadThrow m
|
||||
, MonadFail m
|
||||
, MonadReader Settings m
|
||||
)
|
||||
=> URLSource
|
||||
-> Excepts '[JSONError , DownloadFailed] m GHCupInfo
|
||||
|
@ -116,7 +162,12 @@ getDownloads urlSource = do
|
|||
--
|
||||
-- Always save the local file with the mod time of the remote file.
|
||||
smartDl :: forall m1
|
||||
. (MonadCatch m1, MonadIO m1, MonadFail m1, MonadLogger m1)
|
||||
. ( MonadCatch m1
|
||||
, MonadIO m1
|
||||
, MonadFail m1
|
||||
, MonadLogger m1
|
||||
, MonadReader Settings m1
|
||||
)
|
||||
=> URI
|
||||
-> Excepts
|
||||
'[ FileDoesNotExistError
|
||||
|
@ -148,31 +199,38 @@ getDownloads urlSource = do
|
|||
Just modTime -> do
|
||||
fileMod <- liftIO $ getModificationTime json_file
|
||||
if modTime > fileMod
|
||||
then do
|
||||
bs <- liftE $ downloadBS uri'
|
||||
liftIO $ writeFileWithModTime modTime json_file bs
|
||||
pure bs
|
||||
then dlWithMod modTime json_file
|
||||
else liftIO $ readFile json_file
|
||||
Nothing -> do
|
||||
lift $ $(logDebug) [i|Unable to get/parse Last-Modified header|]
|
||||
liftIO $ deleteFile json_file
|
||||
liftE $ downloadBS uri'
|
||||
dlWithoutMod json_file
|
||||
else -- access in less than 5 minutes, re-use file
|
||||
liftIO $ readFile json_file
|
||||
else do
|
||||
liftIO $ createDirIfMissing newDirPerms cacheDir
|
||||
getModTime >>= \case
|
||||
Just modTime -> do
|
||||
bs <- liftE $ downloadBS uri'
|
||||
liftIO $ writeFileWithModTime modTime json_file bs
|
||||
pure bs
|
||||
Just modTime -> dlWithMod modTime json_file
|
||||
Nothing -> do
|
||||
-- although we don't know last-modified, we still save
|
||||
-- it to a file, so we might use it in offline mode
|
||||
lift $ $(logDebug) [i|Unable to get/parse Last-Modified header|]
|
||||
liftE $ downloadBS uri'
|
||||
dlWithoutMod json_file
|
||||
|
||||
where
|
||||
dlWithMod modTime json_file = do
|
||||
bs <- liftE $ downloadBS uri'
|
||||
liftIO $ writeFileWithModTime modTime json_file bs
|
||||
pure bs
|
||||
dlWithoutMod json_file = do
|
||||
bs <- liftE $ downloadBS uri'
|
||||
liftIO $ hideError doesNotExistErrorType $ deleteFile json_file
|
||||
liftIO $ writeFileL json_file (Just newFilePerms) bs
|
||||
liftIO $ setModificationTime json_file (fromIntegral @Int 0)
|
||||
pure bs
|
||||
|
||||
|
||||
getModTime = do
|
||||
#if defined(CURL)
|
||||
#if !defined(INTERNAL_DOWNLOADER)
|
||||
pure Nothing
|
||||
#else
|
||||
headers <-
|
||||
|
@ -192,7 +250,7 @@ getDownloads urlSource = do
|
|||
True
|
||||
defaultTimeLocale
|
||||
"%a, %d %b %Y %H:%M:%S %Z"
|
||||
(T.unpack . E.decodeUtf8 $ h)
|
||||
(T.unpack . decUTF8Safe $ h)
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -256,7 +314,7 @@ download dli dest mfn
|
|||
liftIO $ copyFile fromFile destFile Strict
|
||||
pure destFile
|
||||
dl = do
|
||||
let uri' = E.decodeUtf8 (serializeURIRef' (view dlUri dli))
|
||||
let uri' = decUTF8Safe (serializeURIRef' (view dlUri dli))
|
||||
lift $ $(logInfo) [i|downloading: #{uri'}|]
|
||||
|
||||
-- destination dir must exist
|
||||
|
@ -271,12 +329,19 @@ download dli dest mfn
|
|||
(liftIO $ hideError doesNotExistErrorType $ deleteFile destFile)
|
||||
>> (throwE . DownloadFailed $ e)
|
||||
) $ do
|
||||
#if defined(CURL)
|
||||
liftE $ lEM @_ @'[ProcessError] $ liftIO $ exec "curl" True
|
||||
["-fL", "-o", toFilePath destFile , serializeURIRef' $ view dlUri dli] Nothing Nothing
|
||||
#else
|
||||
(https, host, fullPath, port) <- liftE $ uriToQuadruple (view dlUri dli)
|
||||
liftE $ downloadToFile https host fullPath port destFile
|
||||
lift getDownloader >>= \case
|
||||
Curl -> do
|
||||
o' <- liftIO getCurlOpts
|
||||
liftE $ lEM @_ @'[ProcessError] $ liftIO $ exec "curl" True
|
||||
(o' ++ ["-fL", "-o", toFilePath destFile, serializeURIRef' $ view dlUri dli]) Nothing Nothing
|
||||
Wget -> do
|
||||
o' <- liftIO getWgetOpts
|
||||
liftE $ lEM @_ @'[ProcessError] $ liftIO $ exec "wget" True
|
||||
(o' ++ ["-O", toFilePath destFile , serializeURIRef' $ view dlUri dli]) Nothing Nothing
|
||||
#if defined(INTERNAL_DOWNLOADER)
|
||||
Internal -> do
|
||||
(https, host, fullPath, port) <- liftE $ uriToQuadruple (view dlUri dli)
|
||||
liftE $ downloadToFile https host fullPath port destFile
|
||||
#endif
|
||||
|
||||
liftE $ checkDigest dli destFile
|
||||
|
@ -329,7 +394,7 @@ downloadCached dli mfn = do
|
|||
|
||||
|
||||
-- | This is used for downloading the JSON.
|
||||
downloadBS :: (MonadCatch m, MonadIO m)
|
||||
downloadBS :: (MonadReader Settings m, MonadCatch m, MonadIO m, MonadLogger m)
|
||||
=> URI
|
||||
-> Excepts
|
||||
'[ FileDoesNotExistError
|
||||
|
@ -356,32 +421,63 @@ downloadBS uri'
|
|||
where
|
||||
scheme = view (uriSchemeL' % schemeBSL') uri'
|
||||
path = view pathL' uri'
|
||||
#if defined(CURL)
|
||||
dl _ = do
|
||||
let exe = [rel|curl|]
|
||||
args = ["-sSfL", serializeURIRef' uri']
|
||||
liftIO (executeOut exe args Nothing) >>= \case
|
||||
CapturedProcess ExitSuccess stdout _ -> do
|
||||
pure $ L.fromStrict stdout
|
||||
CapturedProcess (ExitFailure i') _ _ -> throwE $ NonZeroExit i' (toFilePath exe) args
|
||||
#else
|
||||
#if defined(INTERNAL_DOWNLOADER)
|
||||
dl https = do
|
||||
(_, host', fullPath', port') <- liftE $ uriToQuadruple uri'
|
||||
liftE $ downloadBS' https host' fullPath' port'
|
||||
#else
|
||||
dl _ = do
|
||||
#endif
|
||||
lift $ $(logDebug) [i|downloading: #{serializeURIRef' uri'}|]
|
||||
lift getDownloader >>= \case
|
||||
Curl -> do
|
||||
o' <- liftIO getCurlOpts
|
||||
let exe = [rel|curl|]
|
||||
args = o' ++ ["-sSfL", serializeURIRef' uri']
|
||||
liftIO (executeOut exe args Nothing) >>= \case
|
||||
CapturedProcess ExitSuccess stdout _ -> do
|
||||
pure $ L.fromStrict stdout
|
||||
CapturedProcess (ExitFailure i') _ _ -> throwE $ NonZeroExit i' (toFilePath exe) args
|
||||
Wget -> do
|
||||
o' <- liftIO getWgetOpts
|
||||
let exe = [rel|wget|]
|
||||
args = o' ++ ["-qO-", serializeURIRef' uri']
|
||||
liftIO (executeOut exe args Nothing) >>= \case
|
||||
CapturedProcess ExitSuccess stdout _ -> do
|
||||
pure $ L.fromStrict stdout
|
||||
CapturedProcess (ExitFailure i') _ _ -> throwE $ NonZeroExit i' (toFilePath exe) args
|
||||
#if defined(INTERNAL_DOWNLOADER)
|
||||
Internal -> do
|
||||
(_, host', fullPath', port') <- liftE $ uriToQuadruple uri'
|
||||
liftE $ downloadBS' https host' fullPath' port'
|
||||
#endif
|
||||
|
||||
|
||||
checkDigest :: (MonadIO m, MonadLogger m, MonadReader Settings m)
|
||||
checkDigest :: (MonadIO m, MonadThrow m, MonadLogger m, MonadReader Settings m)
|
||||
=> DownloadInfo
|
||||
-> Path Abs
|
||||
-> Excepts '[DigestError] m ()
|
||||
checkDigest dli file = do
|
||||
verify <- lift ask <&> (not . noVerify)
|
||||
when verify $ do
|
||||
let p' = toFilePath file
|
||||
p' <- toFilePath <$> basename file
|
||||
lift $ $(logInfo) [i|verifying digest of: #{p'}|]
|
||||
c <- liftIO $ readFile file
|
||||
let cDigest = E.decodeUtf8 . B16.encode . SHA256.hashlazy $ c
|
||||
eDigest = view dlHash dli
|
||||
cDigest <- throwEither . E.decodeUtf8' . B16.encode . SHA256.hashlazy $ c
|
||||
let eDigest = view dlHash dli
|
||||
when ((cDigest /= eDigest) && verify) $ throwE (DigestError cDigest eDigest)
|
||||
|
||||
|
||||
-- | Get additional curl args from env. This is an undocumented option.
|
||||
getCurlOpts :: IO [ByteString]
|
||||
getCurlOpts =
|
||||
getEnv "GHCUP_CURL_OPTS" >>= \case
|
||||
Just r -> pure $ BS.split _space r
|
||||
Nothing -> pure []
|
||||
|
||||
|
||||
-- | Get additional wget args from env. This is an undocumented option.
|
||||
getWgetOpts :: IO [ByteString]
|
||||
getWgetOpts =
|
||||
getEnv "GHCUP_WGET_OPTS" >>= \case
|
||||
Just r -> pure $ BS.split _space r
|
||||
Nothing -> pure []
|
||||
|
||||
|
|
|
@ -47,7 +47,6 @@ import URI.ByteString
|
|||
import qualified Data.ByteString as BS
|
||||
import qualified Data.ByteString.Lazy as L
|
||||
import qualified Data.Map.Strict as M
|
||||
import qualified Data.Text.Encoding as E
|
||||
import qualified System.IO.Streams as Streams
|
||||
|
||||
|
||||
|
@ -146,7 +145,7 @@ downloadInternal = go (5 :: Int)
|
|||
|
||||
downloadStream r i' = do
|
||||
let size = case getHeader r "Content-Length" of
|
||||
Just x' -> case decimal $ E.decodeUtf8 x' of
|
||||
Just x' -> case decimal $ decUTF8Safe x' of
|
||||
Left _ -> 0
|
||||
Right (r', _) -> r'
|
||||
Nothing -> 0
|
||||
|
|
|
@ -39,7 +39,6 @@ import System.Info
|
|||
import Text.Regex.Posix
|
||||
|
||||
import qualified Data.Text as T
|
||||
import qualified Data.Text.Encoding as E
|
||||
|
||||
--------------------------
|
||||
--[ Platform detection ]--
|
||||
|
@ -84,13 +83,13 @@ getPlatform = do
|
|||
( either (const Nothing) Just
|
||||
. versioning
|
||||
. getMajorVersion
|
||||
. E.decodeUtf8
|
||||
. decUTF8Safe
|
||||
)
|
||||
<$> getDarwinVersion
|
||||
pure $ PlatformResult { _platform = Darwin, _distroVersion = ver }
|
||||
"freebsd" -> do
|
||||
ver <-
|
||||
(either (const Nothing) Just . versioning . E.decodeUtf8)
|
||||
(either (const Nothing) Just . versioning . decUTF8Safe)
|
||||
<$> getFreeBSDVersion
|
||||
pure $ PlatformResult { _platform = FreeBSD, _distroVersion = ver }
|
||||
what -> throwE $ NoCompatiblePlatform what
|
||||
|
@ -159,7 +158,7 @@ getLinuxDistro = do
|
|||
(Just _) <- findExecutable lsb_release_cmd
|
||||
name <- fmap _stdOut $ executeOut lsb_release_cmd ["-si"] Nothing
|
||||
ver <- fmap _stdOut $ executeOut lsb_release_cmd ["-sr"] Nothing
|
||||
pure (E.decodeUtf8 name, Just $ E.decodeUtf8 ver)
|
||||
pure (decUTF8Safe name, Just $ decUTF8Safe ver)
|
||||
|
||||
try_lsb_release :: IO (Text, Maybe Text)
|
||||
try_lsb_release = do
|
||||
|
@ -169,7 +168,7 @@ getLinuxDistro = do
|
|||
|
||||
try_redhat_release :: IO (Text, Maybe Text)
|
||||
try_redhat_release = do
|
||||
t <- fmap lBS2sT $ readFile redhat_release
|
||||
t <- fmap decUTF8Safe' $ readFile redhat_release
|
||||
let nameRegex n =
|
||||
makeRegexOpts compIgnoreCase
|
||||
execBlank
|
||||
|
@ -192,4 +191,4 @@ getLinuxDistro = do
|
|||
try_debian_version :: IO (Text, Maybe Text)
|
||||
try_debian_version = do
|
||||
ver <- readFile debian_version
|
||||
pure (T.pack "debian", Just $ lBS2sT ver)
|
||||
pure (T.pack "debian", Just . decUTF8Safe' $ ver)
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
{-# LANGUAGE CPP #-}
|
||||
{-# LANGUAGE DeriveGeneric #-}
|
||||
|
||||
module GHCup.Types where
|
||||
|
@ -70,9 +71,10 @@ data Tool = GHC
|
|||
-- | All necessary information of a tool version, including
|
||||
-- source download and per-architecture downloads.
|
||||
data VersionInfo = VersionInfo
|
||||
{ _viTags :: [Tag] -- ^ version specific tag
|
||||
, _viSourceDL :: Maybe DownloadInfo -- ^ source tarball
|
||||
, _viArch :: ArchitectureSpec -- ^ descend for binary downloads per arch
|
||||
{ _viTags :: [Tag] -- ^ version specific tag
|
||||
, _viChangeLog :: Maybe URI
|
||||
, _viSourceDL :: Maybe DownloadInfo -- ^ source tarball
|
||||
, _viArch :: ArchitectureSpec -- ^ descend for binary downloads per arch
|
||||
}
|
||||
deriving (Eq, Show)
|
||||
|
||||
|
@ -80,7 +82,9 @@ data VersionInfo = VersionInfo
|
|||
-- | A tag. These are currently attached to a version of a tool.
|
||||
data Tag = Latest
|
||||
| Recommended
|
||||
deriving (Ord, Eq, Show)
|
||||
| Base PVP
|
||||
| UnknownTag String -- ^ used for upwardscompat
|
||||
deriving (Ord, Eq, Show) -- FIXME: manual JSON instance
|
||||
|
||||
|
||||
data Architecture = A_64
|
||||
|
@ -137,12 +141,26 @@ data URLSource = GHCupURL
|
|||
|
||||
|
||||
data Settings = Settings
|
||||
{ cache :: Bool
|
||||
, noVerify :: Bool
|
||||
{ cache :: Bool
|
||||
, noVerify :: Bool
|
||||
, keepDirs :: KeepDirs
|
||||
, downloader :: Downloader
|
||||
}
|
||||
deriving Show
|
||||
|
||||
|
||||
data KeepDirs = Always
|
||||
| Errors
|
||||
| Never
|
||||
deriving (Eq, Show, Ord)
|
||||
|
||||
data Downloader = Curl
|
||||
| Wget
|
||||
#if defined(INTERNAL_DOWNLOADER)
|
||||
| Internal
|
||||
#endif
|
||||
deriving (Eq, Show, Ord)
|
||||
|
||||
data DebugInfo = DebugInfo
|
||||
{ diBaseDir :: Path Abs
|
||||
, diBinDir :: Path Abs
|
||||
|
|
|
@ -37,14 +37,27 @@ deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''Tool
|
|||
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''VSep
|
||||
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''VUnit
|
||||
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''VersionInfo
|
||||
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''Tag
|
||||
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''DownloadInfo
|
||||
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''GHCupInfo
|
||||
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''Requirements
|
||||
|
||||
instance ToJSON Tag where
|
||||
toJSON Latest = String "Latest"
|
||||
toJSON Recommended = String "Recommended"
|
||||
toJSON (Base pvp'') = String ("base-" <> prettyPVP pvp'')
|
||||
toJSON (UnknownTag x) = String (T.pack x)
|
||||
|
||||
instance FromJSON Tag where
|
||||
parseJSON = withText "Tag" $ \t -> case T.unpack t of
|
||||
"Latest" -> pure Latest
|
||||
"Recommended" -> pure Recommended
|
||||
('b':'a':'s':'e':'-':ver') -> case pvp (T.pack ver') of
|
||||
Right x -> pure $ Base x
|
||||
Left e -> fail . show $ e
|
||||
x -> pure (UnknownTag x)
|
||||
|
||||
instance ToJSON URI where
|
||||
toJSON = toJSON . decodeUtf8 . serializeURIRef'
|
||||
toJSON = toJSON . decUTF8Safe . serializeURIRef'
|
||||
|
||||
instance FromJSON URI where
|
||||
parseJSON = withText "URL" $ \t ->
|
||||
|
@ -143,6 +156,14 @@ instance FromJSONKey Version where
|
|||
Right x -> pure x
|
||||
Left e -> fail $ "Failure in Version (FromJSONKey)" <> show e
|
||||
|
||||
instance ToJSON PVP where
|
||||
toJSON = toJSON . prettyPVP
|
||||
|
||||
instance FromJSON PVP where
|
||||
parseJSON = withText "PVP" $ \t -> case pvp t of
|
||||
Right x -> pure x
|
||||
Left e -> fail $ "Failure in PVP (FromJSON)" <> show e
|
||||
|
||||
instance ToJSONKey Tool where
|
||||
toJSONKey = genericToJSONKey defaultJSONKeyOptions
|
||||
|
||||
|
@ -151,7 +172,7 @@ instance FromJSONKey Tool where
|
|||
|
||||
instance ToJSON (Path Rel) where
|
||||
toJSON p = case and . fmap isAscii . BS.unpack $ fp of
|
||||
True -> toJSON . E.decodeUtf8 $ fp
|
||||
True -> toJSON . decUTF8Safe $ fp
|
||||
False -> String "/not/a/valid/path"
|
||||
where fp = toFilePath p
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ where
|
|||
|
||||
import GHCup.Errors
|
||||
import GHCup.Types
|
||||
import GHCup.Types.Optics
|
||||
import GHCup.Types.JSON ( )
|
||||
import GHCup.Utils.Dirs
|
||||
import GHCup.Utils.File
|
||||
|
@ -83,9 +84,11 @@ ghcLinkVersion = either (throwM . ParseError) pure . parseOnly parser
|
|||
where
|
||||
parser = string "../ghc/" *> verParser <* string "/bin/ghc"
|
||||
verParser = many1' (notWord8 _slash) >>= \t ->
|
||||
case version $ E.decodeUtf8 $ B.pack t of
|
||||
Left e -> fail $ show e
|
||||
Right r -> pure r
|
||||
case
|
||||
version (decUTF8Safe $ B.pack t)
|
||||
of
|
||||
Left e -> fail $ show e
|
||||
Right r -> pure r
|
||||
|
||||
|
||||
-- e.g. ghc-8.6.5
|
||||
|
@ -159,7 +162,7 @@ ghcSrcInstalled ver = do
|
|||
doesFileExist (ghcdir </> ghcUpSrcBuiltFile)
|
||||
|
||||
|
||||
ghcSet :: (MonadIO m, MonadThrow m) => m (Maybe Version)
|
||||
ghcSet :: (MonadIO m) => m (Maybe Version)
|
||||
ghcSet = do
|
||||
ghcBin <- (</> [rel|ghc|]) <$> liftIO ghcupBinDir
|
||||
|
||||
|
@ -179,7 +182,7 @@ cabalSet = do
|
|||
cabalbin <- (</> [rel|cabal|]) <$> liftIO ghcupBinDir
|
||||
mc <- liftIO $ executeOut cabalbin ["--numeric-version"] Nothing
|
||||
let reportedVer = fst . B.spanEnd (== _lf) . _stdOut $ mc
|
||||
case version (E.decodeUtf8 reportedVer) of
|
||||
case version $ decUTF8Safe reportedVer of
|
||||
Left e -> throwM e
|
||||
Right r -> pure r
|
||||
|
||||
|
@ -206,7 +209,8 @@ getGHCForMajor :: (MonadIO m, MonadThrow m)
|
|||
getGHCForMajor major' minor' = do
|
||||
p <- liftIO $ ghcupGHCBaseDir
|
||||
ghcs <- liftIO $ getDirsFiles' p
|
||||
semvers <- forM ghcs $ throwEither . semver . E.decodeUtf8 . toFilePath
|
||||
semvers <- forM ghcs $ \ghc ->
|
||||
throwEither . semver =<< (throwEither . E.decodeUtf8' . toFilePath $ ghc)
|
||||
mapM (throwEither . version)
|
||||
. fmap prettySemVer
|
||||
. lastMay
|
||||
|
@ -218,6 +222,23 @@ getGHCForMajor major' minor' = do
|
|||
$ semvers
|
||||
|
||||
|
||||
-- | Get the latest available ghc for X.Y major version.
|
||||
getLatestGHCFor :: Int -- ^ major version component
|
||||
-> Int -- ^ minor version component
|
||||
-> GHCupDownloads
|
||||
-> Maybe Version
|
||||
getLatestGHCFor major' minor' dls = do
|
||||
join . fmap
|
||||
(lastMay . filter
|
||||
(\v -> case semver $ prettyVer v of
|
||||
Right SemVer{..} -> fromIntegral _svMajor == major' && fromIntegral _svMinor == minor'
|
||||
Left _ -> False
|
||||
)
|
||||
)
|
||||
. preview (ix GHC % to Map.keys) $ dls
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
-----------------
|
||||
|
@ -232,8 +253,9 @@ unpackToDir :: (MonadLogger m, MonadIO m, MonadThrow m)
|
|||
-> Path Abs -- ^ archive path
|
||||
-> Excepts '[UnknownArchive] m ()
|
||||
unpackToDir dest av = do
|
||||
let fp = E.decodeUtf8 (toFilePath av)
|
||||
lift $ $(logInfo) [i|Unpacking: #{fp}|]
|
||||
fp <- (decUTF8Safe . toFilePath) <$> basename av
|
||||
let dfp = decUTF8Safe . toFilePath $ dest
|
||||
lift $ $(logInfo) [i|Unpacking: #{fp} to #{dfp}|]
|
||||
fn <- toFilePath <$> basename av
|
||||
let untar = Tar.unpack (toFilePath dest) . Tar.read
|
||||
|
||||
|
@ -258,21 +280,25 @@ unpackToDir dest av = do
|
|||
------------
|
||||
|
||||
|
||||
-- | Get the tool versions that have this tag.
|
||||
getTagged :: GHCupDownloads -> Tool -> Tag -> [Version]
|
||||
getTagged av tool tag = toListOf
|
||||
( ix tool
|
||||
% to (Map.filter (\VersionInfo {..} -> elem tag _viTags))
|
||||
% to Map.keys
|
||||
% folded
|
||||
-- | Get the tool version that has this tag. If multiple have it,
|
||||
-- picks the greatest version.
|
||||
getTagged :: Tag -> AffineFold (Map.Map Version VersionInfo) (Version, VersionInfo)
|
||||
getTagged tag =
|
||||
( to (Map.filter (\VersionInfo {..} -> elem tag _viTags))
|
||||
% to Map.toDescList
|
||||
% _head
|
||||
)
|
||||
av
|
||||
|
||||
getLatest :: GHCupDownloads -> Tool -> Maybe Version
|
||||
getLatest av tool = headOf folded $ getTagged av tool Latest
|
||||
getLatest av tool = headOf (ix tool % getTagged Latest % to fst) $ av
|
||||
|
||||
getRecommended :: GHCupDownloads -> Tool -> Maybe Version
|
||||
getRecommended av tool = headOf folded $ getTagged av tool Recommended
|
||||
getRecommended av tool = headOf (ix tool % getTagged Recommended % to fst) $ av
|
||||
|
||||
|
||||
-- | Gets the latest GHC with a given base version.
|
||||
getLatestBaseVersion :: GHCupDownloads -> PVP -> Maybe Version
|
||||
getLatestBaseVersion av pvpVer = headOf (ix GHC % getTagged (Base pvpVer) % to fst) av
|
||||
|
||||
|
||||
|
||||
|
@ -285,6 +311,10 @@ getCache :: MonadReader Settings m => m Bool
|
|||
getCache = ask <&> cache
|
||||
|
||||
|
||||
getDownloader :: MonadReader Settings m => m Downloader
|
||||
getDownloader = ask <&> downloader
|
||||
|
||||
|
||||
|
||||
-------------
|
||||
--[ Other ]--
|
||||
|
@ -368,3 +398,52 @@ darwinNotarization Darwin path = exec
|
|||
Nothing
|
||||
Nothing
|
||||
darwinNotarization _ _ = pure $ Right ()
|
||||
|
||||
|
||||
getChangeLog :: GHCupDownloads -> Tool -> Either Version Tag -> Maybe URI
|
||||
getChangeLog dls tool (Left v') =
|
||||
preview (ix tool % ix v' % viChangeLog % _Just) dls
|
||||
getChangeLog dls tool (Right tag) = preview
|
||||
( ix tool
|
||||
% getTagged tag
|
||||
% to snd
|
||||
% viChangeLog
|
||||
% _Just
|
||||
) dls
|
||||
|
||||
|
||||
-- | Execute a build action while potentially cleaning up:
|
||||
--
|
||||
-- 1. the build directory, depending on the KeepDirs setting
|
||||
-- 2. the install destination, depending on whether the build failed
|
||||
runBuildAction :: (Show (V e), MonadReader Settings m, MonadIO m, MonadMask m)
|
||||
=> Path Abs -- ^ build directory
|
||||
-> Maybe (Path Abs) -- ^ install location (e.g. for GHC)
|
||||
-> Excepts e m ()
|
||||
-> Excepts '[BuildFailed] m ()
|
||||
runBuildAction bdir instdir action = do
|
||||
Settings {..} <- lift ask
|
||||
flip
|
||||
onException
|
||||
(do
|
||||
forM_ instdir $ \dir ->
|
||||
liftIO $ hideError doesNotExistErrorType $ deleteDirRecursive dir
|
||||
when (keepDirs == Never)
|
||||
$ liftIO
|
||||
$ hideError doesNotExistErrorType
|
||||
$ deleteDirRecursive bdir
|
||||
)
|
||||
$ catchAllE
|
||||
(\es -> do
|
||||
forM_ instdir $ \dir ->
|
||||
liftIO $ hideError doesNotExistErrorType $ deleteDirRecursive dir
|
||||
when (keepDirs == Never)
|
||||
$ liftIO
|
||||
$ hideError doesNotExistErrorType
|
||||
$ deleteDirRecursive bdir
|
||||
throwE (BuildFailed bdir es)
|
||||
)
|
||||
$ action
|
||||
|
||||
when (keepDirs == Never || keepDirs == Errors) $ liftIO $ deleteDirRecursive
|
||||
bdir
|
||||
|
|
|
@ -43,8 +43,6 @@ import System.Posix.Types
|
|||
|
||||
import qualified Control.Exception as EX
|
||||
import qualified Data.Text as T
|
||||
import qualified Data.Text.Encoding as E
|
||||
import qualified Data.Text.Encoding.Error as E
|
||||
import qualified System.Posix.Process.ByteString
|
||||
as SPPB
|
||||
import Streamly.External.Posix.DirStream
|
||||
|
@ -201,6 +199,7 @@ execLogged exe spath args lfile chdir env = do
|
|||
lineAction ref rs bs' = do
|
||||
modifyIORef' ref (swapRegs bs')
|
||||
regs <- readIORef ref
|
||||
void $ SPIB.fdWrite fileFd (bs' <> "\n")
|
||||
forM (zip regs rs) $ \(bs, r) -> do
|
||||
setConsoleRegion r $ do
|
||||
w <- consoleWidth
|
||||
|
@ -208,12 +207,10 @@ execLogged exe spath args lfile chdir env = do
|
|||
. T.pack
|
||||
. color Blue
|
||||
. T.unpack
|
||||
. E.decodeUtf8With E.lenientDecode
|
||||
. decUTF8Safe
|
||||
. trim w
|
||||
. (\b -> "[ " <> toFilePath lfile <> " ] " <> b)
|
||||
$ bs
|
||||
SPIB.fdWrite fileFd (bs <> "\n")
|
||||
|
||||
|
||||
swapRegs bs regs | length regs < size = regs ++ [bs]
|
||||
| otherwise = tail regs ++ [bs]
|
||||
|
@ -371,8 +368,7 @@ searchPath paths needle = go paths
|
|||
where
|
||||
go [] = pure Nothing
|
||||
go (x : xs) =
|
||||
hideErrorDefM PermissionDenied (go xs)
|
||||
$ hideErrorDefM NoSuchThing (go xs)
|
||||
hideErrorDefM [InappropriateType, PermissionDenied, NoSuchThing] (go xs)
|
||||
$ do
|
||||
dirStream <- openDirStream (toFilePath x)
|
||||
S.findM (\(_, p) -> isMatch x p) (dirContentsStream dirStream)
|
||||
|
|
|
@ -29,6 +29,7 @@ import qualified Data.ByteString.Lazy as L
|
|||
import qualified Data.Strict.Maybe as S
|
||||
import qualified Data.Text as T
|
||||
import qualified Data.Text.Encoding as E
|
||||
import qualified Data.Text.Encoding.Error as E
|
||||
import qualified Data.Text.Lazy as TL
|
||||
import qualified Data.Text.Lazy.Builder as B
|
||||
import qualified Data.Text.Lazy.Builder.Int as B
|
||||
|
@ -87,10 +88,6 @@ whileM_ ~action = void . whileM action
|
|||
guardM :: (Monad m, Alternative m) => m Bool -> m ()
|
||||
guardM ~f = guard =<< f
|
||||
|
||||
lBS2sT :: L.ByteString -> Text
|
||||
lBS2sT = TL.toStrict . TLE.decodeUtf8
|
||||
|
||||
|
||||
|
||||
handleIO' :: (MonadIO m, MonadCatch m)
|
||||
=> IOErrorType
|
||||
|
@ -168,14 +165,14 @@ liftIOException errType ex =
|
|||
. lift
|
||||
|
||||
|
||||
hideErrorDef :: IOErrorType -> a -> IO a -> IO a
|
||||
hideErrorDef err def =
|
||||
handleIO (\e -> if err == ioeGetErrorType e then pure def else ioError e)
|
||||
hideErrorDef :: [IOErrorType] -> a -> IO a -> IO a
|
||||
hideErrorDef errs def =
|
||||
handleIO (\e -> if ioeGetErrorType e `elem` errs then pure def else ioError e)
|
||||
|
||||
|
||||
hideErrorDefM :: IOErrorType -> IO a -> IO a -> IO a
|
||||
hideErrorDefM err def =
|
||||
handleIO (\e -> if err == ioeGetErrorType e then def else ioError e)
|
||||
hideErrorDefM :: [IOErrorType] -> IO a -> IO a -> IO a
|
||||
hideErrorDefM errs def =
|
||||
handleIO (\e -> if ioeGetErrorType e `elem` errs then def else ioError e)
|
||||
|
||||
|
||||
-- TODO: does this work?
|
||||
|
@ -243,4 +240,16 @@ addToCurrentEnv adds = do
|
|||
|
||||
|
||||
pvpToVersion :: PVP -> Version
|
||||
pvpToVersion = either (\_ -> error "Couldn't convert PVP to Version") id . version . prettyPVP
|
||||
pvpToVersion =
|
||||
either (\_ -> error "Couldn't convert PVP to Version") id
|
||||
. version
|
||||
. prettyPVP
|
||||
|
||||
|
||||
-- | Safe 'decodeUtf8With'. Replaces an invalid input byte with
|
||||
-- the Unicode replacement character U+FFFD.
|
||||
decUTF8Safe :: ByteString -> Text
|
||||
decUTF8Safe = E.decodeUtf8With E.lenientDecode
|
||||
|
||||
decUTF8Safe' :: L.ByteString -> Text
|
||||
decUTF8Safe' = TL.toStrict . TLE.decodeUtf8With E.lenientDecode
|
||||
|
|
|
@ -9,9 +9,14 @@ import Data.Versions
|
|||
import URI.ByteString
|
||||
import URI.ByteString.QQ
|
||||
|
||||
import qualified Data.Text as T
|
||||
|
||||
-- | This reflects the API version of the JSON.
|
||||
ghcupURL :: URI
|
||||
ghcupURL = [uri|https://www.haskell.org/ghcup/data/ghcup-0.0.1.json|]
|
||||
ghcupURL = [uri|https://www.haskell.org/ghcup/data/ghcup-0.0.2.json|]
|
||||
|
||||
ghcUpVer :: PVP
|
||||
ghcUpVer = [pver|0.1.4|]
|
||||
|
||||
numericVer :: String
|
||||
numericVer = T.unpack . prettyPVP $ ghcUpVer
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
_ghcup()
|
||||
{
|
||||
local CMDLINE
|
||||
local IFS=$'\n'
|
||||
CMDLINE=(--bash-completion-index $COMP_CWORD)
|
||||
|
||||
for arg in ${COMP_WORDS[@]}; do
|
||||
CMDLINE=(${CMDLINE[@]} --bash-completion-word $arg)
|
||||
done
|
||||
|
||||
COMPREPLY=( $(ghcup "${CMDLINE[@]}") )
|
||||
}
|
||||
|
||||
complete -o filenames -F _ghcup ghcup
|
|
@ -0,0 +1,19 @@
|
|||
function _ghcup
|
||||
set -l cl (commandline --tokenize --current-process)
|
||||
# Hack around fish issue #3934
|
||||
set -l cn (commandline --tokenize --cut-at-cursor --current-process)
|
||||
set -l cn (count $cn)
|
||||
set -l tmpline --bash-completion-enriched --bash-completion-index $cn
|
||||
for arg in $cl
|
||||
set tmpline $tmpline --bash-completion-word $arg
|
||||
end
|
||||
for opt in (ghcup $tmpline)
|
||||
if test -d $opt
|
||||
echo -E "$opt/"
|
||||
else
|
||||
echo -E "$opt"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
complete --no-files --command ghcup --arguments '(_ghcup)'
|
|
@ -0,0 +1,32 @@
|
|||
#compdef ghcup
|
||||
|
||||
local request
|
||||
local completions
|
||||
local word
|
||||
local index=$((CURRENT - 1))
|
||||
|
||||
request=(--bash-completion-enriched --bash-completion-index $index)
|
||||
for arg in ${words[@]}; do
|
||||
request=(${request[@]} --bash-completion-word $arg)
|
||||
done
|
||||
|
||||
IFS=$'\n' completions=($( ghcup "${request[@]}" ))
|
||||
|
||||
for word in $completions; do
|
||||
local -a parts
|
||||
|
||||
# Split the line at a tab if there is one.
|
||||
IFS=$'\t' parts=($( echo $word ))
|
||||
|
||||
if [[ -n $parts[2] ]]; then
|
||||
if [[ $word[1] == "-" ]]; then
|
||||
local desc=("$parts[1] ($parts[2])")
|
||||
compadd -d desc -- $parts[1]
|
||||
else
|
||||
local desc=($(print -f "%-019s -- %s" $parts[1] $parts[2]))
|
||||
compadd -l -d desc -- $parts[1]
|
||||
fi
|
||||
else
|
||||
compadd -f -- $word
|
||||
fi
|
||||
done
|
Loading…
Reference in New Issue