Compare commits
59 Commits
a7fd36beeb
...
v0.1.5-alp
| Author | SHA1 | Date | |
|---|---|---|---|
| bc0cd22433 | |||
| ed4ff15f96 | |||
| 1d623723a2 | |||
| 931080244f | |||
| 27e2e7f848 | |||
| 8b638c7ecb | |||
| acd370611f | |||
| e1b5a89cee | |||
| 5edebd57d9 | |||
| bcaccaaf31 | |||
| 818a5d2d85 | |||
| 13acce07d4 | |||
| 4ed5e21b7f | |||
| 86aab6bb59 | |||
| 7f5cb64b18 | |||
| 6c12eb16eb | |||
| e637f90fae | |||
| 5b33c3f491 | |||
| 1842ed464f | |||
| 296bbdd561 | |||
| 27ead1be7c | |||
| 5184609dba | |||
| 5d94d0bf75 | |||
| 72bcfa9270 | |||
| fafff9dadd | |||
| e3c20d53a8 | |||
| 8b7dc68491 | |||
| 7742fe08b5 | |||
| a773da037c | |||
| dfeb814dcc | |||
| 0623c7b1b1 | |||
| 62005f83a4 | |||
| eaafd77a7e | |||
| 9d9e415a09 | |||
| 6c1ae585b7 | |||
| 793aad7b6c | |||
| fd7807a66e | |||
| 879bd061dd | |||
| 75632b2cf1 | |||
| b65b9dc5e1 | |||
| 31d70e34e9 | |||
| 84de282655 | |||
| 997dcadf89 | |||
| b2312629ce | |||
| 3d10f964c6 | |||
| 404038edcb | |||
| ea4f9ceab1 | |||
| 5c481ea94e | |||
| 1ccaf4ba91 | |||
| b532511cd5 | |||
| b3105b439c | |||
| 2b6cb5f1a8 | |||
| f4242b10e7 | |||
| ad4d185ead | |||
| b18aafe2c4 | |||
| 340196bf9d | |||
| 883226aa70 | |||
| 0d393612a7 | |||
| 5635f6cc4e |
14
.bash-completion
Normal file
14
.bash-completion
Normal file
@@ -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
|
||||
197
.gitlab-ci.yml
Normal file
197
.gitlab-ci.yml
Normal file
@@ -0,0 +1,197 @@
|
||||
variables:
|
||||
GIT_SSL_NO_VERIFY: "1"
|
||||
|
||||
# Commit of ghc/ci-images repository from which to pull Docker images
|
||||
DOCKER_REV: cefaee3c742af193e0f7783f87edb0d35374515c
|
||||
|
||||
############################################################
|
||||
# CI Step
|
||||
############################################################
|
||||
|
||||
.debian:
|
||||
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.2"
|
||||
|
||||
.test_ghcup_version:linux:
|
||||
extends:
|
||||
- .test_ghcup_version
|
||||
- .debian
|
||||
before_script:
|
||||
- ./.gitlab/before_script/linux/install_deps.sh
|
||||
|
||||
.test_ghcup_version:darwin:
|
||||
extends:
|
||||
- .test_ghcup_version
|
||||
- .darwin
|
||||
- .root_cleanup
|
||||
before_script:
|
||||
- ./.gitlab/before_script/darwin/install_deps.sh
|
||||
|
||||
.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 test ########
|
||||
|
||||
test:linux:recommended:
|
||||
extends: .test_ghcup_version:linux
|
||||
variables:
|
||||
GHC_VERSION: "8.6.5"
|
||||
CABAL_VERSION: "3.2.0.0"
|
||||
|
||||
test:linux:latest:
|
||||
extends: .test_ghcup_version:linux
|
||||
variables:
|
||||
GHC_VERSION: "8.8.3"
|
||||
CABAL_VERSION: "3.2.0.0"
|
||||
allow_failure: true
|
||||
|
||||
|
||||
######## darwin test ########
|
||||
|
||||
test:mac:recommended:
|
||||
extends: .test_ghcup_version:darwin
|
||||
variables:
|
||||
GHC_VERSION: "8.6.5"
|
||||
CABAL_VERSION: "3.2.0.0"
|
||||
|
||||
test:mac:latest:
|
||||
extends: .test_ghcup_version:darwin
|
||||
variables:
|
||||
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: "x86_64-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"
|
||||
|
||||
14
.gitlab/before_script/darwin/install_deps.sh
Executable file
14
.gitlab/before_script/darwin/install_deps.sh
Executable file
@@ -0,0 +1,14 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -eux
|
||||
|
||||
. "$( cd "$(dirname "$0")" ; pwd -P )/../../ghcup_env"
|
||||
|
||||
curl -sSfL https://downloads.haskell.org/~ghcup/x86_64-apple-darwin-ghcup > ./ghcup-bin
|
||||
chmod +x ghcup-bin
|
||||
|
||||
./ghcup-bin install ${GHC_VERSION}
|
||||
./ghcup-bin set ${GHC_VERSION}
|
||||
./ghcup-bin install-cabal ${CABAL_VERSION}
|
||||
|
||||
exit 0
|
||||
23
.gitlab/before_script/freebsd/install_deps.sh
Executable file
23
.gitlab/before_script/freebsd/install_deps.sh
Executable file
@@ -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
|
||||
60
.gitlab/before_script/linux/alpine/install_deps.sh
Executable file
60
.gitlab/before_script/linux/alpine/install_deps.sh
Executable file
@@ -0,0 +1,60 @@
|
||||
#!/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
|
||||
|
||||
## Package specific
|
||||
apk add --no-cache \
|
||||
zlib \
|
||||
zlib-dev \
|
||||
zlib-static \
|
||||
gmp \
|
||||
gmp-dev \
|
||||
openssl-dev \
|
||||
openssl-libs-static \
|
||||
xz \
|
||||
xz-dev
|
||||
|
||||
|
||||
|
||||
16
.gitlab/before_script/linux/install_deps.sh
Executable file
16
.gitlab/before_script/linux/install_deps.sh
Executable file
@@ -0,0 +1,16 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -eux
|
||||
|
||||
sudo apt-get update -y
|
||||
sudo apt-get install -y libnuma-dev zlib1g-dev libgmp-dev libgmp10 libssl-dev liblzma-dev
|
||||
|
||||
. "$( cd "$(dirname "$0")" ; pwd -P )/../../ghcup_env"
|
||||
|
||||
curl -sSfL https://downloads.haskell.org/~ghcup/x86_64-linux-ghcup > ./ghcup-bin
|
||||
chmod +x ghcup-bin
|
||||
|
||||
./ghcup-bin install ${GHC_VERSION}
|
||||
./ghcup-bin set ${GHC_VERSION}
|
||||
./ghcup-bin install-cabal ${CABAL_VERSION}
|
||||
|
||||
3
.gitlab/ghcup_env
Normal file
3
.gitlab/ghcup_env
Normal file
@@ -0,0 +1,3 @@
|
||||
export GHCUP_INSTALL_BASE_PREFIX="$CI_PROJECT_DIR"
|
||||
export PATH="$CI_PROJECT_DIR/.ghcup/bin:$CI_PROJECT_DIR/.local/bin:$PATH"
|
||||
|
||||
26
.gitlab/script/ghcup_release.sh
Executable file
26
.gitlab/script/ghcup_release.sh
Executable file
@@ -0,0 +1,26 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -eux
|
||||
|
||||
. "$( cd "$(dirname "$0")" ; pwd -P )/../ghcup_env"
|
||||
|
||||
mkdir -p "$CI_PROJECT_DIR"/.local/bin
|
||||
|
||||
ecabal() {
|
||||
cabal --store-dir="$(pwd)"/.store "$@"
|
||||
}
|
||||
|
||||
# build
|
||||
ecabal update
|
||||
|
||||
if [ "${OS}" = "LINUX" ] ; then
|
||||
ecabal build -w ghc-${GHC_VERSION} -fcurl --ghc-options='-split-sections -optl-static'
|
||||
else
|
||||
ecabal build -w ghc-${GHC_VERSION} -fcurl
|
||||
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}
|
||||
|
||||
87
.gitlab/script/ghcup_version.sh
Executable file
87
.gitlab/script/ghcup_version.sh
Executable file
@@ -0,0 +1,87 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -eux
|
||||
|
||||
. "$( cd "$(dirname "$0")" ; pwd -P )/../ghcup_env"
|
||||
|
||||
mkdir -p "$CI_PROJECT_DIR"/.local/bin
|
||||
|
||||
ecabal() {
|
||||
cabal --store-dir="$(pwd)"/.store "$@"
|
||||
}
|
||||
|
||||
eghcup() {
|
||||
ghcup -v -c -s file://$(pwd)/ghcup-${JSON_VERSION}.json "$@"
|
||||
}
|
||||
|
||||
|
||||
### build
|
||||
|
||||
ecabal update
|
||||
|
||||
if [ "${OS}" = "DARWIN" ] ; then
|
||||
ecabal build -w ghc-${GHC_VERSION} -fcurl
|
||||
else
|
||||
ecabal build -w ghc-${GHC_VERSION}
|
||||
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')" .
|
||||
|
||||
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
|
||||
|
||||
# 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 ${CABAL_VERSION}
|
||||
|
||||
cabal --version
|
||||
|
||||
eghcup debug-info
|
||||
|
||||
eghcup list
|
||||
eghcup list -t ghc
|
||||
eghcup list -t cabal
|
||||
|
||||
ghc_ver=$(ghc --numeric-version)
|
||||
ghc --version
|
||||
ghci --version
|
||||
ghc-$(ghc --numeric-version) --version
|
||||
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
|
||||
[ "$(ghc --numeric-version)" = "${ghc_ver}" ]
|
||||
eghcup set 8.4.4
|
||||
eghcup set 8.4.4
|
||||
[ "$(ghc --numeric-version)" = "8.4.4" ]
|
||||
eghcup set ${GHC_VERSION}
|
||||
[ "$(ghc --numeric-version)" = "${ghc_ver}" ]
|
||||
eghcup rm 8.4.4
|
||||
[ "$(ghc --numeric-version)" = "${ghc_ver}" ]
|
||||
|
||||
eghcup rm $(ghc --numeric-version)
|
||||
|
||||
eghcup upgrade
|
||||
eghcup upgrade -f
|
||||
|
||||
@@ -15,10 +15,11 @@ script: ".travis/build.sh"
|
||||
deploy:
|
||||
provider: releases
|
||||
api_key:
|
||||
secure: GEQR+HIwMUql+tFU0LoKCCzG+IG1s5XVA4yp8xMFk0IPsNjHEMh6djYgNqsS6MnujzRulinZe69RyJMZHW3UbtVKWd1D5nsCKmAVfnU8VRbubaL55Bz7C2WI9UCYtKY0isVIQu3KkY+0a6LhdjSkbatO2hl9v0nFmN28q/RpEzsJTI4kyVhmCBflH4fL/QvXzfLuyOae7qsiZBVQXEhmySYktKifNMANSI1aU+kyZ3JgykqZogMK+g/fmcxxTe9MPYMsRQxae/xqdf87IQpmK8v9BRShvF0wq1gO8NY+/fEemAVIHi5CYhPgiLntUD/HFr6AT04LcHnaGryDn/PhkvHuDuZ4INYgBrdNMeGVTjT93N7OtXyh7c+AP3/51E8nM0SkSWCeP4P2fMMksdeOnKtPbhzlqgEM9tbRMILOj1LcjcqurU5ku+WEwZ7d1osTyNug7FVCO5Vb0q3NYnDF4UPXc/d5/2SB+SjJSMxRc52+BiKskHmOa96TXirL3eo6KVNaokQRKvbLw1fEjZvqYJuhPWBRDMalyYjc77poj4kzfVL9CYjtP7h6N5wFR7AtPsMz2n2fQf7J3N4+oqHK+83fOPGyy4FYPZojKNw+L2X/XYrfVscsY/1KbBjULgGIrdr4euYz+rRrTHixUYIvGclKOx+g3SHAOXFWhXlldvI=
|
||||
secure: GQESg4TcYf3PQJRRaZV/kWS0hsF+OFnH2+EcwpgnIcfx4+aogMyprdh745KtBXe1FlFN1luKHksFjqceqhcg/xcNyeCJiSnLWMn4D/i4WUperEHseRBi5yZZCB1AvOjIlHrE4DS3a8pyEm1GV3G7CKY5Fu8jBjof2SnyENfd7fofhjtNHWmeFS+jBn8HRDf1YaSRYxzTw6uHLrPLsybfgQZVl7babMu/38Ghin0f5pz5OlNokzDxaubIYQHOZ7st7YndHJtBWWql/KualBWbMILy88dUVQBnbqQLP2P8d1ME8ILUjJVqz33HiRU0JzlEJyWfbvEjcJ6iD8M6n4nXTaxfu3i2UhhGsQ6SSBNKssMP4tji8nkNpMqG59wLQ/zhcetEm71fKkgJNrIMNllkqlWSo5K74IqqP9kiLg/qm8ipOJjui0gPk8tZXKcV+ztX1d1OVCapoLfiDM5l/0LLQXaTOXOV1x3e5LLQ/w2doNiH3eh5CV4II9dRu7owpaiiMBHMssmT0pH99jEeF6giHLKtt3y7l2GWoRLPdhsZZ54gxsaBxZt9GuypmkbNcr97CEnAVaWij5v0CF3w4rAWqy/tAxQpIDJOIOQBgmwG5WrBAKyKrFvEpBL5a8BPcRWJDvqKC83QeWpvPrEVdgJevC6ZN1MKzrb2SiPOwC2Kerc=
|
||||
file: $ARTIFACT
|
||||
on:
|
||||
repo: hasufell/ghcup-hs
|
||||
repo: haskell/ghcup-hs
|
||||
tags: true
|
||||
skip_cleanup: true
|
||||
draft: true
|
||||
|
||||
|
||||
15
CHANGELOG.md
15
CHANGELOG.md
@@ -1,5 +1,20 @@
|
||||
# Revision history for ghcup
|
||||
|
||||
## 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
|
||||
|
||||
## 0.1.3 -- 2020-04-15
|
||||
|
||||
* Fix lesser bug when skipping ghcup update
|
||||
|
||||
## 0.1.2 -- 2020-04-15
|
||||
|
||||
* Fix bug when removing the set GHC version
|
||||
* Fix use of undocumented `GHCUP_INSTALL_BASE_PREFIX` variable
|
||||
* skip upgrade if ghcup is already latest version
|
||||
|
||||
## 0.1.1 -- 2020-04-15
|
||||
|
||||
* fix awful fdopendir bug on mac bug by updating hpath-posix
|
||||
|
||||
@@ -68,6 +68,12 @@ 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.
|
||||
|
||||
### Bash-completion
|
||||
|
||||
Depending on your distro and setup, install `.bash-completion` from this repo
|
||||
as e.g. `/etc/bash_completion.d/ghcup` and make sure your bashrc sources the
|
||||
startup script (`/usr/share/bash-completion/bash_completion` on some distros).
|
||||
|
||||
## Design goals
|
||||
|
||||
1. simplicity
|
||||
@@ -142,3 +148,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?
|
||||
|
||||
21
TODO.md
21
TODO.md
@@ -2,30 +2,39 @@
|
||||
|
||||
## Now
|
||||
|
||||
* ghcup migration
|
||||
* update static links
|
||||
* 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
|
||||
|
||||
* releases, update download info and bootstrap-haskell
|
||||
|
||||
## 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
|
||||
|
||||
@@ -27,9 +27,12 @@ import Haskus.Utils.Variant.Excepts
|
||||
import Optics
|
||||
import System.Exit
|
||||
import System.IO
|
||||
import Text.ParserCombinators.ReadP
|
||||
|
||||
import qualified Data.ByteString as B
|
||||
import qualified Data.Map.Strict as M
|
||||
import qualified Data.Text as T
|
||||
import qualified Data.Version as V
|
||||
|
||||
|
||||
data ValidationError = InternalError String
|
||||
@@ -61,8 +64,9 @@ validate dls = do
|
||||
forM_ (M.toList $ _viArch vi) $ \(arch, pspecs) -> do
|
||||
checkHasRequiredPlatforms t v arch (M.keys pspecs)
|
||||
|
||||
checkGHCisSemver
|
||||
checkGHCVerIsValid
|
||||
forM_ (M.toList dls) $ \(t, _) -> checkMandatoryTags t
|
||||
_ <- checkGHCHasBaseVersion
|
||||
|
||||
-- exit
|
||||
e <- liftIO $ readIORef ref
|
||||
@@ -85,7 +89,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,26 +109,40 @@ 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
|
||||
checkGHCVerIsValid = do
|
||||
let ghcVers = toListOf (ix GHC % to M.keys % folded) dls
|
||||
forM_ ghcVers $ \v -> case semver (prettyVer v) of
|
||||
Left _ -> do
|
||||
lift $ $(logError) [i|GHC version #{v} is not valid semver|]
|
||||
addError
|
||||
Right _ -> pure ()
|
||||
forM_ ghcVers $ \v ->
|
||||
case [ x | (x,"") <- readP_to_S V.parseVersion (T.unpack . prettyVer $ v) ] of
|
||||
[_] -> pure ()
|
||||
_ -> do
|
||||
lift $ $(logError) [i|GHC version #{v} is not valid |]
|
||||
addError
|
||||
|
||||
-- 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 +179,7 @@ validateTarballs dls = do
|
||||
|
||||
where
|
||||
downloadAll dli = do
|
||||
let settings = Settings True False
|
||||
let settings = Settings True False Never
|
||||
let runLogger = myLoggerT LoggerConfig { lcPrintDebug = True
|
||||
, colorOutter = B.hPut stderr
|
||||
, rawOutter = (\_ -> pure ())
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -31,10 +31,10 @@ download_ghcup() {
|
||||
"linux"|"Linux")
|
||||
case "${_arch}" in
|
||||
x86_64|amd64)
|
||||
_url=https://downloads.haskell.org/~ghcup/x86_64-linux-ghcup
|
||||
_url=https://downloads.haskell.org/~ghcup/0.1.4/x86_64-linux-ghcup-0.1.4
|
||||
;;
|
||||
i*86)
|
||||
_url=https://downloads.haskell.org/~ghcup/i386-linux-ghcup
|
||||
_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/x86_64-portbld-freebsd-ghcup
|
||||
_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/x86_64-apple-darwin-ghcup ;;
|
||||
_url=https://downloads.haskell.org/~ghcup/0.1.4/x86_64-apple-darwin-ghcup-0.1.4 ;;
|
||||
*) die "Unknown platform: ${_plat}"
|
||||
;;
|
||||
esac
|
||||
@@ -108,6 +108,7 @@ else
|
||||
EOF
|
||||
# shellcheck disable=SC1090
|
||||
edo . "${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup/env
|
||||
eghcup upgrade
|
||||
fi
|
||||
|
||||
echo
|
||||
|
||||
2180
ghcup-0.0.1.json
2180
ghcup-0.0.1.json
File diff suppressed because one or more lines are too long
2251
ghcup-0.0.2.json
Normal file
2251
ghcup-0.0.2.json
Normal file
File diff suppressed because it is too large
Load Diff
22
ghcup.cabal
22
ghcup.cabal
@@ -1,13 +1,13 @@
|
||||
cabal-version: 3.0
|
||||
name: ghcup
|
||||
version: 0.1.1
|
||||
version: 0.1.4
|
||||
synopsis: ghc toolchain installer as an exe/library
|
||||
description:
|
||||
A rewrite of the shell script ghcup, for providing
|
||||
a more stable user experience and exposing an API.
|
||||
|
||||
homepage: https://github.com/hasufell/ghcup-hs
|
||||
bug-reports: https://github.com/hasufell/ghcup-hs/issues
|
||||
homepage: https://gitlab.haskell.org/haskell/ghcup-hs
|
||||
bug-reports: https://gitlab.haskell.org/haskell/ghcup-hs/issues
|
||||
license: LGPL-3.0-only
|
||||
license-file: LICENSE
|
||||
author: Julian Ospald
|
||||
@@ -19,7 +19,7 @@ extra-source-files: CHANGELOG.md
|
||||
|
||||
source-repository head
|
||||
type: git
|
||||
location: https://github.com/hasufell/ghcup-hs
|
||||
location: https://gitlab.haskell.org/haskell/ghcup-hs.git
|
||||
|
||||
flag Curl
|
||||
description: Use curl instead of http-io-streams for download
|
||||
@@ -41,9 +41,6 @@ common ascii-string
|
||||
common async
|
||||
build-depends: async >=0.8
|
||||
|
||||
common attoparsec
|
||||
build-depends: attoparsec >=0.13
|
||||
|
||||
common base
|
||||
build-depends: base >=4.12 && <5
|
||||
|
||||
@@ -230,7 +227,6 @@ library
|
||||
, aeson
|
||||
, ascii-string
|
||||
, async
|
||||
, attoparsec
|
||||
, binary
|
||||
, bytestring
|
||||
, bz2
|
||||
@@ -248,6 +244,7 @@ library
|
||||
, hpath-posix
|
||||
, language-bash
|
||||
, lzma
|
||||
, megaparsec
|
||||
, monad-logger
|
||||
, mtl
|
||||
, optics
|
||||
@@ -279,6 +276,9 @@ library
|
||||
|
||||
exposed-modules:
|
||||
GHCup
|
||||
GHCup.Data.GHCupDownloads
|
||||
GHCup.Data.GHCupInfo
|
||||
GHCup.Data.ToolRequirements
|
||||
GHCup.Download
|
||||
GHCup.Download.Utils
|
||||
GHCup.Errors
|
||||
@@ -292,6 +292,7 @@ library
|
||||
GHCup.Utils.Dirs
|
||||
GHCup.Utils.File
|
||||
GHCup.Utils.Logger
|
||||
GHCup.Utils.MegaParsec
|
||||
GHCup.Utils.Prelude
|
||||
GHCup.Utils.String.QQ
|
||||
GHCup.Utils.Version.QQ
|
||||
@@ -326,8 +327,10 @@ executable ghcup
|
||||
, optparse-applicative
|
||||
, pretty-terminal
|
||||
, resourcet
|
||||
, safe
|
||||
, string-interpolate
|
||||
, table-layout
|
||||
, template-haskell
|
||||
, text
|
||||
, uri-bytestring
|
||||
, utf8-string
|
||||
@@ -370,9 +373,6 @@ executable ghcup-gen
|
||||
--
|
||||
main-is: Main.hs
|
||||
other-modules:
|
||||
GHCupDownloads
|
||||
GHCupInfo
|
||||
ToolRequirements
|
||||
Validate
|
||||
|
||||
-- other-extensions:
|
||||
|
||||
304
lib/GHCup.hs
304
lib/GHCup.hs
@@ -9,6 +9,7 @@
|
||||
{-# LANGUAGE TemplateHaskell #-}
|
||||
{-# LANGUAGE TypeApplications #-}
|
||||
{-# LANGUAGE TypeFamilies #-}
|
||||
{-# LANGUAGE ViewPatterns #-}
|
||||
|
||||
module GHCup where
|
||||
|
||||
@@ -40,6 +41,7 @@ import Data.ByteString ( ByteString )
|
||||
import Data.List
|
||||
import Data.Maybe
|
||||
import Data.String.Interpolate
|
||||
import Data.Text ( Text )
|
||||
import Data.Versions
|
||||
import Data.Word8
|
||||
import GHC.IO.Exception
|
||||
@@ -52,11 +54,14 @@ import Prelude hiding ( abs
|
||||
, writeFile
|
||||
)
|
||||
import System.IO.Error
|
||||
import System.Posix.Env.ByteString ( getEnvironment )
|
||||
import System.Posix.FilePath ( getSearchPath )
|
||||
import System.Posix.Files.ByteString
|
||||
|
||||
import qualified Data.ByteString as B
|
||||
import qualified Data.ByteString.Lazy as BL
|
||||
import qualified Data.Map.Strict as Map
|
||||
import qualified Data.Text as T
|
||||
import qualified Data.Text.Encoding as E
|
||||
|
||||
|
||||
@@ -93,45 +98,34 @@ installGHCBin :: ( MonadFail m
|
||||
m
|
||||
()
|
||||
installGHCBin bDls ver mpfReq = do
|
||||
let tver = (mkTVer ver)
|
||||
lift $ $(logDebug) [i|Requested to install GHC with #{ver}|]
|
||||
whenM (liftIO $ toolAlreadyInstalled GHC ver)
|
||||
whenM (liftIO $ ghcInstalled tver)
|
||||
$ (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
|
||||
|
||||
-- prepare paths
|
||||
ghcdir <- liftIO $ ghcupGHCDir ver
|
||||
ghcdir <- liftIO $ ghcupGHCDir tver
|
||||
|
||||
-- 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
|
||||
liftE $ runBuildAction tmpUnpack (Just ghcdir) (installGHC' workdir ghcdir)
|
||||
|
||||
-- only clean up dir if the build succeeded
|
||||
liftIO $ deleteDirRecursive tmpUnpack
|
||||
|
||||
liftE $ postGHCInstall ver
|
||||
liftE $ postGHCInstall tver
|
||||
|
||||
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
|
||||
@@ -172,15 +166,15 @@ installCabalBin :: ( MonadMask m
|
||||
()
|
||||
installCabalBin bDls ver mpfReq = do
|
||||
lift $ $(logDebug) [i|Requested to install cabal version #{ver}|]
|
||||
Settings {..} <- lift ask
|
||||
Settings {..} <- lift ask
|
||||
pfreq@(PlatformRequest {..}) <- maybe (liftE $ platformRequest) pure mpfReq
|
||||
|
||||
-- download (or use cached version)
|
||||
dlinfo <- lE $ getDownloadInfo Cabal ver pfreq bDls
|
||||
dl <- liftE $ downloadCached dlinfo Nothing
|
||||
dlinfo <- lE $ getDownloadInfo Cabal ver pfreq bDls
|
||||
dl <- liftE $ downloadCached dlinfo Nothing
|
||||
|
||||
-- unpack
|
||||
tmpUnpack <- lift withGHCupTmpDir
|
||||
tmpUnpack <- lift withGHCupTmpDir
|
||||
liftE $ unpackToDir tmpUnpack dl
|
||||
void $ liftIO $ darwinNotarization _rPlatform tmpUnpack
|
||||
|
||||
@@ -194,7 +188,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
|
||||
@@ -226,11 +220,11 @@ installCabalBin bDls ver mpfReq = do
|
||||
-- Additionally creates a ~/.ghcup/share -> ~/.ghcup/ghc/<ver>/share symlink
|
||||
-- for `SetGHCOnly` constructor.
|
||||
setGHC :: (MonadLogger m, MonadThrow m, MonadFail m, MonadIO m)
|
||||
=> Version
|
||||
=> GHCTargetVersion
|
||||
-> SetGHC
|
||||
-> Excepts '[NotInstalled] m ()
|
||||
-> Excepts '[NotInstalled] m GHCTargetVersion
|
||||
setGHC ver sghc = do
|
||||
let verBS = verToBS ver
|
||||
let verBS = verToBS (_tvVersion ver)
|
||||
ghcdir <- liftIO $ ghcupGHCDir ver
|
||||
|
||||
-- symlink destination
|
||||
@@ -240,20 +234,18 @@ setGHC ver sghc = do
|
||||
-- first delete the old symlinks (this fixes compatibility issues
|
||||
-- with old ghcup)
|
||||
case sghc of
|
||||
SetGHCOnly -> liftE $ rmPlain ver
|
||||
SetGHCOnly -> liftE $ rmPlain (_tvTarget ver)
|
||||
SetGHC_XY -> lift $ rmMajorSymlinks ver
|
||||
SetGHC_XYZ -> lift $ rmMinorSymlinks ver
|
||||
|
||||
-- for ghc tools (ghc, ghci, haddock, ...)
|
||||
verfiles <- ghcToolFiles ver
|
||||
forM_ verfiles $ \file -> do
|
||||
liftIO $ hideError doesNotExistErrorType $ deleteFile (bindir </> file)
|
||||
targetFile <- case sghc of
|
||||
SetGHCOnly -> pure file
|
||||
SetGHC_XY -> do
|
||||
major' <-
|
||||
(\(mj, mi) -> E.encodeUtf8 $ intToText mj <> "." <> intToText mi)
|
||||
<$> getGHCMajor ver
|
||||
major' <- (\(mj, mi) -> E.encodeUtf8 $ intToText mj <> "." <> intToText mi)
|
||||
<$> getMajorMinorV (_tvVersion ver)
|
||||
parseRel (toFilePath file <> B.singleton _hyphen <> major')
|
||||
SetGHC_XYZ -> parseRel (toFilePath file <> B.singleton _hyphen <> verBS)
|
||||
|
||||
@@ -264,9 +256,9 @@ setGHC ver sghc = do
|
||||
liftIO $ createSymlink fullF destL
|
||||
|
||||
-- create symlink for share dir
|
||||
lift $ symlinkShareDir ghcdir verBS
|
||||
when (isNothing . _tvTarget $ ver) $ lift $ symlinkShareDir ghcdir verBS
|
||||
|
||||
pure ()
|
||||
pure ver
|
||||
|
||||
where
|
||||
|
||||
@@ -304,27 +296,41 @@ data ListCriteria = ListInstalled
|
||||
data ListResult = ListResult
|
||||
{ lTool :: Tool
|
||||
, lVer :: Version
|
||||
, lCross :: Maybe Text -- ^ currently only for GHC
|
||||
, 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 :: (MonadThrow m, 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
|
||||
@@ -332,21 +338,75 @@ listVersions av lt criteria = case lt of
|
||||
pure (ghcvers <> cabalvers <> ghcupvers)
|
||||
|
||||
where
|
||||
strayGHCs :: (MonadThrow m, MonadLogger m, MonadIO m)
|
||||
=> Map.Map Version [Tag]
|
||||
-> m [ListResult]
|
||||
strayGHCs avTools = do
|
||||
ghcs <- getInstalledGHCs
|
||||
fmap catMaybes $ forM ghcs $ \case
|
||||
Right tver@GHCTargetVersion{ _tvTarget = Nothing, .. } -> do
|
||||
case Map.lookup _tvVersion avTools of
|
||||
Just _ -> pure Nothing
|
||||
Nothing -> do
|
||||
lSet <- fmap (maybe False (\(GHCTargetVersion _ v ) -> v == _tvVersion)) $ ghcSet Nothing
|
||||
fromSrc <- liftIO $ ghcSrcInstalled tver
|
||||
pure $ Just $ ListResult
|
||||
{ lTool = GHC
|
||||
, lVer = _tvVersion
|
||||
, lCross = Nothing
|
||||
, lTag = []
|
||||
, lInstalled = True
|
||||
, lStray = maybe True (const False) (Map.lookup _tvVersion avTools)
|
||||
, ..
|
||||
}
|
||||
Right tver@GHCTargetVersion{ .. } -> do
|
||||
lSet <- fmap (maybe False (\(GHCTargetVersion _ v ) -> v == _tvVersion)) $ ghcSet _tvTarget
|
||||
fromSrc <- liftIO $ ghcSrcInstalled tver
|
||||
pure $ Just $ ListResult
|
||||
{ lTool = GHC
|
||||
, lVer = _tvVersion
|
||||
, lCross = _tvTarget
|
||||
, lTag = []
|
||||
, lInstalled = True
|
||||
, lStray = True -- NOTE: cross currently cannot be installed via bindist
|
||||
, ..
|
||||
}
|
||||
Left e -> do
|
||||
$(logWarn)
|
||||
[i|Could not parse version of stray directory #{toFilePath e}|]
|
||||
pure Nothing
|
||||
|
||||
-- NOTE: this are not cross ones, because no bindists
|
||||
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, .. }
|
||||
let tver = mkTVer v
|
||||
lSet <- fmap (maybe False (\(GHCTargetVersion _ v') -> v' == v)) $ ghcSet Nothing
|
||||
lInstalled <- ghcInstalled tver
|
||||
fromSrc <- ghcSrcInstalled tver
|
||||
pure ListResult { lVer = v, lCross = Nothing , 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
|
||||
, lCross = Nothing
|
||||
, 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
|
||||
, lCross = Nothing
|
||||
, lTool = t
|
||||
, fromSrc = False
|
||||
, lStray = False
|
||||
, ..
|
||||
}
|
||||
|
||||
|
||||
filter' :: [ListResult] -> [ListResult]
|
||||
@@ -364,10 +424,10 @@ listVersions av lt criteria = case lt of
|
||||
|
||||
-- | This function may throw and crash in various ways.
|
||||
rmGHCVer :: (MonadThrow m, MonadLogger m, MonadIO m, MonadFail m)
|
||||
=> Version
|
||||
=> GHCTargetVersion
|
||||
-> Excepts '[NotInstalled] m ()
|
||||
rmGHCVer ver = do
|
||||
isSetGHC <- fmap (maybe False (== ver)) $ ghcSet
|
||||
isSetGHC <- fmap (maybe False (== ver)) $ ghcSet (_tvTarget ver)
|
||||
dir <- liftIO $ ghcupGHCDir ver
|
||||
let d' = toFilePath dir
|
||||
exists <- liftIO $ doesDirectoryExist dir
|
||||
@@ -376,6 +436,10 @@ rmGHCVer ver = do
|
||||
if exists
|
||||
then do
|
||||
-- this isn't atomic, order matters
|
||||
when isSetGHC $ do
|
||||
lift $ $(logInfo) [i|Removing ghc symlinks|]
|
||||
liftE $ rmPlain (_tvTarget ver)
|
||||
|
||||
lift $ $(logInfo) [i|Removing directory recursively: #{d'}|]
|
||||
liftIO $ deleteDirRecursive dir
|
||||
|
||||
@@ -386,20 +450,15 @@ rmGHCVer ver = do
|
||||
-- first remove
|
||||
lift $ rmMajorSymlinks ver
|
||||
-- then fix them (e.g. with an earlier version)
|
||||
(mj, mi) <- getGHCMajor ver
|
||||
getGHCForMajor mj mi >>= mapM_ (\v -> liftE $ setGHC v SetGHC_XY)
|
||||
|
||||
|
||||
when isSetGHC $ do
|
||||
lift $ $(logInfo) [i|Removing ghc symlinks|]
|
||||
liftE $ rmPlain ver
|
||||
(mj, mi) <- getMajorMinorV (_tvVersion ver)
|
||||
getGHCForMajor mj mi (_tvTarget ver) >>= mapM_ (\v -> liftE $ setGHC v SetGHC_XY)
|
||||
|
||||
liftIO
|
||||
$ ghcupBaseDir
|
||||
>>= hideError doesNotExistErrorType
|
||||
. deleteFile
|
||||
. (</> [rel|share|])
|
||||
else throwE (NotInstalled GHC ver)
|
||||
else throwE (NotInstalled GHC (ver ^. tvVersion % to prettyVer))
|
||||
|
||||
|
||||
|
||||
@@ -440,11 +499,12 @@ compileGHC :: ( MonadMask m
|
||||
, MonadFail m
|
||||
)
|
||||
=> GHCupDownloads
|
||||
-> Version -- ^ version to install
|
||||
-> GHCTargetVersion -- ^ version to install
|
||||
-> Either Version (Path Abs) -- ^ version to bootstrap with
|
||||
-> Maybe Int -- ^ jobs
|
||||
-> Maybe (Path Abs) -- ^ build config
|
||||
-> Maybe (Path Abs)
|
||||
-> Maybe (Path Abs) -- ^ patch directory
|
||||
-> [Text] -- ^ additional args to ./configure
|
||||
-> Excepts
|
||||
'[ AlreadyInstalled
|
||||
, BuildFailed
|
||||
@@ -461,13 +521,15 @@ compileGHC :: ( MonadMask m
|
||||
]
|
||||
m
|
||||
()
|
||||
compileGHC dls tver bstrap jobs mbuildConfig patchdir = do
|
||||
compileGHC dls tver bstrap jobs mbuildConfig patchdir aargs = do
|
||||
lift $ $(logDebug) [i|Requested to compile: #{tver} with #{bstrap}|]
|
||||
whenM (liftIO $ toolAlreadyInstalled GHC tver)
|
||||
(throwE $ AlreadyInstalled GHC tver)
|
||||
whenM (liftIO $ ghcInstalled tver)
|
||||
(throwE $ AlreadyInstalled GHC (tver ^. tvVersion))
|
||||
|
||||
-- download source tarball
|
||||
dlInfo <- preview (ix GHC % ix tver % viSourceDL % _Just) dls ?? NoDownload
|
||||
dlInfo <-
|
||||
preview (ix GHC % ix (tver ^. tvVersion) % viSourceDL % _Just) dls
|
||||
?? NoDownload
|
||||
dl <- liftE $ downloadCached dlInfo Nothing
|
||||
|
||||
-- unpack
|
||||
@@ -482,32 +544,29 @@ 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 ()
|
||||
|
||||
where
|
||||
defaultConf = [s|
|
||||
defaultConf = case _tvTarget tver of
|
||||
Nothing -> [s|
|
||||
V=0
|
||||
BUILD_MAN = NO
|
||||
BUILD_SPHINX_HTML = NO
|
||||
BUILD_SPHINX_PDF = NO
|
||||
HADDOCK_DOCS = YES
|
||||
GhcWithLlvmCodeGen = YES|]
|
||||
HADDOCK_DOCS = YES|]
|
||||
Just _ -> [s|
|
||||
V=0
|
||||
BUILD_MAN = NO
|
||||
BUILD_SPHINX_HTML = NO
|
||||
BUILD_SPHINX_PDF = NO
|
||||
HADDOCK_DOCS = NO
|
||||
Stage1Only = YES|]
|
||||
|
||||
compile :: (MonadCatch m, MonadLogger m, MonadIO m)
|
||||
=> Either (Path Rel) (Path Abs)
|
||||
@@ -515,6 +574,7 @@ GhcWithLlvmCodeGen = YES|]
|
||||
-> Path Abs
|
||||
-> Excepts
|
||||
'[ FileDoesNotExistError
|
||||
, InvalidBuildConfig
|
||||
, PatchFailed
|
||||
, ProcessError
|
||||
, NotFoundInPATH
|
||||
@@ -523,14 +583,14 @@ GhcWithLlvmCodeGen = YES|]
|
||||
()
|
||||
compile bghc ghcdir workdir = do
|
||||
lift $ $(logInfo) [i|configuring build|]
|
||||
liftE $ checkBuildConfig
|
||||
|
||||
forM_ patchdir $ \dir -> liftE $ applyPatches dir workdir
|
||||
|
||||
-- force ld.bfd for build (others seem to misbehave, like lld from FreeBSD)
|
||||
newEnv <- addToCurrentEnv [("LD", "ld.bfd")]
|
||||
cEnv <- liftIO $ getEnvironment
|
||||
|
||||
if
|
||||
| tver >= [vver|8.8.0|] -> do
|
||||
| (_tvVersion tver) >= [vver|8.8.0|] -> do
|
||||
bghcPath <- case bghc of
|
||||
Right ghc' -> pure ghc'
|
||||
Left bver -> do
|
||||
@@ -539,20 +599,32 @@ GhcWithLlvmCodeGen = YES|]
|
||||
lEM $ liftIO $ execLogged
|
||||
"./configure"
|
||||
False
|
||||
["--prefix=" <> toFilePath ghcdir]
|
||||
( ["--prefix=" <> toFilePath ghcdir]
|
||||
++ (maybe mempty
|
||||
(\x -> ["--target=" <> E.encodeUtf8 x])
|
||||
(_tvTarget tver)
|
||||
)
|
||||
++ fmap E.encodeUtf8 aargs
|
||||
)
|
||||
[rel|ghc-conf|]
|
||||
(Just workdir)
|
||||
(Just (("GHC", toFilePath bghcPath) : newEnv))
|
||||
(Just (("GHC", toFilePath bghcPath) : cEnv))
|
||||
| otherwise -> do
|
||||
lEM $ liftIO $ execLogged
|
||||
"./configure"
|
||||
False
|
||||
[ "--prefix=" <> toFilePath ghcdir
|
||||
, "--with-ghc=" <> either toFilePath toFilePath bghc
|
||||
]
|
||||
( [ "--prefix=" <> toFilePath ghcdir
|
||||
, "--with-ghc=" <> either toFilePath toFilePath bghc
|
||||
]
|
||||
++ (maybe mempty
|
||||
(\x -> ["--target=" <> E.encodeUtf8 x])
|
||||
(_tvTarget tver)
|
||||
)
|
||||
++ fmap E.encodeUtf8 aargs
|
||||
)
|
||||
[rel|ghc-conf|]
|
||||
(Just workdir)
|
||||
(Just newEnv)
|
||||
(Just cEnv)
|
||||
|
||||
case mbuildConfig of
|
||||
Just bc -> liftIOException
|
||||
@@ -575,6 +647,30 @@ GhcWithLlvmCodeGen = YES|]
|
||||
|
||||
build_mk workdir = workdir </> [rel|mk/build.mk|]
|
||||
|
||||
checkBuildConfig :: (MonadCatch m, MonadIO m)
|
||||
=> Excepts
|
||||
'[FileDoesNotExistError , InvalidBuildConfig]
|
||||
m
|
||||
()
|
||||
checkBuildConfig = do
|
||||
c <- case mbuildConfig of
|
||||
Just bc -> do
|
||||
BL.toStrict <$> liftIOException doesNotExistErrorType
|
||||
(FileDoesNotExistError $ toFilePath bc)
|
||||
(liftIO $ readFile bc)
|
||||
Nothing -> pure defaultConf
|
||||
let lines' = fmap T.strip . T.lines $ decUTF8Safe c
|
||||
|
||||
-- for cross, we need Stage1Only
|
||||
case _tvTarget tver of
|
||||
Just _ -> when (not $ elem "Stage1Only = YES" lines') $ throwE
|
||||
(InvalidBuildConfig
|
||||
[s|Cross compiling needs to be a Stage1 build, add "Stage1Only = YES" to your config!|]
|
||||
)
|
||||
Nothing -> pure ()
|
||||
|
||||
|
||||
|
||||
|
||||
compileCabal :: ( MonadReader Settings m
|
||||
, MonadResource m
|
||||
@@ -615,7 +711,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
|
||||
@@ -676,6 +776,8 @@ upgradeGHCup :: ( MonadMask m
|
||||
)
|
||||
=> GHCupDownloads
|
||||
-> Maybe (Path Abs) -- ^ full file destination to write ghcup into
|
||||
-> Bool -- ^ whether to force update regardless
|
||||
-- of currently installed version
|
||||
-> Excepts
|
||||
'[ CopyError
|
||||
, DigestError
|
||||
@@ -684,12 +786,14 @@ upgradeGHCup :: ( MonadMask m
|
||||
, NoCompatibleArch
|
||||
, NoCompatiblePlatform
|
||||
, NoDownload
|
||||
, NoUpdate
|
||||
]
|
||||
m
|
||||
Version
|
||||
upgradeGHCup dls mtarget = do
|
||||
upgradeGHCup dls mtarget force = do
|
||||
lift $ $(logInfo) [i|Upgrading GHCup...|]
|
||||
let latestVer = fromJust $ getLatest dls GHCup
|
||||
when (not force && (latestVer <= pvpToVersion ghcUpVer)) $ throwE NoUpdate
|
||||
pfreq <- liftE platformRequest
|
||||
dli <- lE $ getDownloadInfo GHCup latestVer pfreq dls
|
||||
tmp <- lift withGHCupTmpDir
|
||||
@@ -726,12 +830,12 @@ upgradeGHCup dls mtarget = do
|
||||
-- | Creates ghc-x.y.z and ghc-x.y symlinks. This is used for
|
||||
-- both installing from source and bindist.
|
||||
postGHCInstall :: (MonadLogger m, MonadThrow m, MonadFail m, MonadIO m)
|
||||
=> Version
|
||||
=> GHCTargetVersion
|
||||
-> Excepts '[NotInstalled] m ()
|
||||
postGHCInstall ver = do
|
||||
liftE $ setGHC ver SetGHC_XYZ
|
||||
postGHCInstall ver@GHCTargetVersion{..} = do
|
||||
void $ liftE $ setGHC ver SetGHC_XYZ
|
||||
|
||||
-- Create ghc-x.y symlinks. This may not be the current
|
||||
-- version, create it regardless.
|
||||
(mj, mi) <- liftIO $ getGHCMajor ver
|
||||
getGHCForMajor mj mi >>= mapM_ (\v -> liftE $ setGHC v SetGHC_XY)
|
||||
(mj, mi) <- getMajorMinorV _tvVersion
|
||||
getGHCForMajor mj mi _tvTarget >>= mapM_ (\v -> liftE $ setGHC v SetGHC_XY)
|
||||
|
||||
@@ -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_010_32_linux :: DownloadInfo
|
||||
ghcup_010_32_linux = DownloadInfo
|
||||
[uri|https://downloads.haskell.org/~ghcup/i386-linux-ghcup|]
|
||||
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
|
||||
"ce95fd3044ea249c2ea02e122112a787d710cc4be2dcf1e78d8c68b540a70920"
|
||||
"057cc1cc39abdacd92cb1d4fb44c850fd9c5398a36b893286248ac5c38bc0c70"
|
||||
|
||||
|
||||
ghcup_010_64_linux :: DownloadInfo
|
||||
ghcup_010_64_linux = DownloadInfo
|
||||
[uri|https://downloads.haskell.org/~ghcup/x86_64-linux-ghcup|]
|
||||
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
|
||||
"9281da4d8db628bbfbf1d3f3b748a2556f828cc60308559bc87c5d657cb06bdf"
|
||||
"78d69ed4c9a810a445af89ea25e4217a632799ecb427b06cd2320ffb574f555e"
|
||||
|
||||
|
||||
ghcup_010_64_freebsd :: DownloadInfo
|
||||
ghcup_010_64_freebsd = DownloadInfo
|
||||
[uri|https://downloads.haskell.org/~ghcup/x86_64-portbld-freebsd-ghcup|]
|
||||
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
|
||||
"992a375cc4d296a9ceed3712b8bb329a0ac605a614b5a9b8a5f3dba05183d2a5"
|
||||
"cda0b959f053abc04ab0a1b9919a505b8c9304e2898a291f527a370cb0e00731"
|
||||
|
||||
|
||||
ghcup_010_64_darwin10_13 :: DownloadInfo
|
||||
ghcup_010_64_darwin10_13 = DownloadInfo
|
||||
[uri|https://downloads.haskell.org/~ghcup/x86_64-apple-darwin-ghcup|]
|
||||
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
|
||||
"adeaa6943611cf68c0c8224037788eac2a84a9136c59685eaea28ed16f3953c7"
|
||||
"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.0|]
|
||||
, VersionInfo [Recommended, Latest] Nothing $ M.fromList
|
||||
[ ( A_64
|
||||
, M.fromList
|
||||
[ (Linux UnknownLinux, M.fromList [(Nothing, ghcup_010_64_linux)])
|
||||
, (Darwin, M.fromList [(Nothing, ghcup_010_64_darwin10_13)])
|
||||
, (FreeBSD, M.fromList [(Nothing, ghcup_010_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_010_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,7 +1,7 @@
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE QuasiQuotes #-}
|
||||
|
||||
module ToolRequirements where
|
||||
module GHCup.Data.ToolRequirements where
|
||||
|
||||
import GHCup.Types
|
||||
import GHCup.Utils.String.QQ
|
||||
@@ -192,7 +192,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 +256,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
|
||||
@@ -371,17 +371,17 @@ downloadBS uri'
|
||||
#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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -30,6 +30,10 @@ data NoCompatiblePlatform = NoCompatiblePlatform String -- the platform we got
|
||||
data NoDownload = NoDownload
|
||||
deriving Show
|
||||
|
||||
-- | No update available or necessary.
|
||||
data NoUpdate = NoUpdate
|
||||
deriving Show
|
||||
|
||||
-- | The Architecture is unknown and unsupported.
|
||||
data NoCompatibleArch = NoCompatibleArch String
|
||||
deriving Show
|
||||
@@ -60,7 +64,7 @@ data AlreadyInstalled = AlreadyInstalled Tool Version
|
||||
|
||||
-- | The tool is not installed. Some operations rely on a tool
|
||||
-- to be installed (such as setting the current GHC version).
|
||||
data NotInstalled = NotInstalled Tool Version
|
||||
data NotInstalled = NotInstalled Tool Text
|
||||
deriving Show
|
||||
|
||||
-- | An executable was expected to be in PATH, but was not found.
|
||||
@@ -100,6 +104,9 @@ data PatchFailed = PatchFailed
|
||||
data NoToolRequirements = NoToolRequirements
|
||||
deriving Show
|
||||
|
||||
data InvalidBuildConfig = InvalidBuildConfig Text
|
||||
deriving Show
|
||||
|
||||
|
||||
-------------------------
|
||||
--[ High-level errors ]--
|
||||
|
||||
@@ -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,4 +1,5 @@
|
||||
{-# LANGUAGE DeriveGeneric #-}
|
||||
{-# LANGUAGE DeriveGeneric #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
|
||||
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
|
||||
@@ -139,10 +143,17 @@ data URLSource = GHCupURL
|
||||
data Settings = Settings
|
||||
{ cache :: Bool
|
||||
, noVerify :: Bool
|
||||
, keepDirs :: KeepDirs
|
||||
}
|
||||
deriving Show
|
||||
|
||||
|
||||
data KeepDirs = Always
|
||||
| Errors
|
||||
| Never
|
||||
deriving (Eq, Show, Ord)
|
||||
|
||||
|
||||
data DebugInfo = DebugInfo
|
||||
{ diBaseDir :: Path Abs
|
||||
, diBinDir :: Path Abs
|
||||
@@ -172,3 +183,23 @@ data PlatformRequest = PlatformRequest
|
||||
, _rVersion :: Maybe Versioning
|
||||
}
|
||||
deriving (Eq, Show)
|
||||
|
||||
|
||||
-- | A GHC identified by the target platform triple
|
||||
-- and the version.
|
||||
data GHCTargetVersion = GHCTargetVersion
|
||||
{ _tvTarget :: Maybe Text
|
||||
, _tvVersion :: Version
|
||||
}
|
||||
deriving (Ord, Eq, Show)
|
||||
|
||||
|
||||
mkTVer :: Version -> GHCTargetVersion
|
||||
mkTVer = GHCTargetVersion Nothing
|
||||
|
||||
|
||||
-- | Assembles a path of the form: <target-triple>-<version>
|
||||
prettyTVer :: GHCTargetVersion -> Text
|
||||
prettyTVer (GHCTargetVersion (Just t) v') = t <> "-" <> prettyVer v'
|
||||
prettyTVer (GHCTargetVersion Nothing v') = prettyVer v'
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -19,6 +19,8 @@ makeLenses ''DownloadInfo
|
||||
makeLenses ''Tag
|
||||
makeLenses ''VersionInfo
|
||||
|
||||
makeLenses ''GHCTargetVersion
|
||||
|
||||
makeLenses ''GHCupInfo
|
||||
|
||||
uriSchemeL' :: Lens' (URIRef Absolute) Scheme
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE QuasiQuotes #-}
|
||||
{-# LANGUAGE TemplateHaskell #-}
|
||||
{-# LANGUAGE ViewPatterns #-}
|
||||
|
||||
|
||||
module GHCup.Utils
|
||||
@@ -15,10 +16,13 @@ where
|
||||
|
||||
import GHCup.Errors
|
||||
import GHCup.Types
|
||||
import GHCup.Types.Optics
|
||||
import GHCup.Types.JSON ( )
|
||||
import GHCup.Utils.Dirs
|
||||
import GHCup.Utils.File
|
||||
import GHCup.Utils.MegaParsec
|
||||
import GHCup.Utils.Prelude
|
||||
import GHCup.Utils.String.QQ
|
||||
|
||||
import Control.Applicative
|
||||
import Control.Exception.Safe
|
||||
@@ -28,11 +32,12 @@ import Control.Monad.Fail ( MonadFail )
|
||||
#endif
|
||||
import Control.Monad.Logger
|
||||
import Control.Monad.Reader
|
||||
import Data.Attoparsec.ByteString
|
||||
import Data.ByteString ( ByteString )
|
||||
import Data.Either
|
||||
import Data.List
|
||||
import Data.Maybe
|
||||
import Data.String.Interpolate
|
||||
import Data.Text ( Text )
|
||||
import Data.Versions
|
||||
import Data.Word8
|
||||
import GHC.IO.Exception
|
||||
@@ -50,6 +55,7 @@ import System.Posix.FilePath ( getSearchPath
|
||||
, takeFileName
|
||||
)
|
||||
import System.Posix.Files.ByteString ( readSymbolicLink )
|
||||
import Text.Regex.Posix
|
||||
import URI.ByteString
|
||||
|
||||
import qualified Codec.Archive.Tar as Tar
|
||||
@@ -59,7 +65,7 @@ import qualified Codec.Compression.Lzma as Lzma
|
||||
import qualified Data.ByteString as B
|
||||
import qualified Data.Map.Strict as Map
|
||||
import qualified Data.Text.Encoding as E
|
||||
|
||||
import qualified Text.Megaparsec as MP
|
||||
|
||||
|
||||
|
||||
@@ -72,62 +78,69 @@ import qualified Data.Text.Encoding as E
|
||||
|
||||
-- | The symlink destination of a ghc tool.
|
||||
ghcLinkDestination :: ByteString -- ^ the tool, such as 'ghc', 'haddock' etc.
|
||||
-> Version
|
||||
-> GHCTargetVersion
|
||||
-> ByteString
|
||||
ghcLinkDestination tool ver = "../ghc/" <> verToBS ver <> "/bin/" <> tool
|
||||
|
||||
|
||||
-- | Extract the version part of the result of `ghcLinkDestination`.
|
||||
ghcLinkVersion :: MonadThrow m => ByteString -> m Version
|
||||
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
|
||||
ghcLinkDestination tool ver =
|
||||
"../ghc/" <> E.encodeUtf8 (prettyTVer ver) <> "/bin/" <> tool
|
||||
|
||||
|
||||
-- e.g. ghc-8.6.5
|
||||
rmMinorSymlinks :: (MonadIO m, MonadLogger m) => Version -> m ()
|
||||
rmMinorSymlinks ver = do
|
||||
rmMinorSymlinks :: (MonadIO m, MonadLogger m) => GHCTargetVersion -> m ()
|
||||
rmMinorSymlinks GHCTargetVersion {..} = do
|
||||
bindir <- liftIO $ ghcupBinDir
|
||||
files <- liftIO $ getDirsFiles' bindir
|
||||
let myfiles =
|
||||
filter (\x -> ("-" <> verToBS ver) `B.isSuffixOf` toFilePath x) files
|
||||
forM_ myfiles $ \f -> do
|
||||
|
||||
files <- liftIO $ findFiles'
|
||||
bindir
|
||||
( maybe mempty (\x -> MP.chunk (x <> "-")) _tvTarget
|
||||
*> parseUntil1 (MP.chunk $ prettyVer _tvVersion)
|
||||
*> (MP.chunk $ prettyVer _tvVersion)
|
||||
*> MP.eof
|
||||
)
|
||||
|
||||
forM_ files $ \f -> do
|
||||
let fullF = (bindir </> f)
|
||||
$(logDebug) [i|rm -f #{toFilePath fullF}|]
|
||||
liftIO $ hideError doesNotExistErrorType $ deleteFile fullF
|
||||
|
||||
-- E.g. ghc, if this version is the set one.
|
||||
-- This reads `ghcupGHCDir`.
|
||||
|
||||
-- Removes the set ghc version for the given target, if any.
|
||||
rmPlain :: (MonadLogger m, MonadThrow m, MonadFail m, MonadIO m)
|
||||
=> Version
|
||||
=> Maybe Text -- ^ target
|
||||
-> Excepts '[NotInstalled] m ()
|
||||
rmPlain ver = do
|
||||
files <- liftE $ ghcToolFiles ver
|
||||
bindir <- liftIO $ ghcupBinDir
|
||||
forM_ files $ \f -> do
|
||||
let fullF = (bindir </> f)
|
||||
lift $ $(logDebug) [i|rm -f #{toFilePath fullF}|]
|
||||
liftIO $ hideError doesNotExistErrorType $ deleteFile fullF
|
||||
-- old ghcup
|
||||
let hdc_file = (bindir </> [rel|haddock-ghc|])
|
||||
lift $ $(logDebug) [i|rm -f #{toFilePath hdc_file}|]
|
||||
liftIO $ hideError doesNotExistErrorType $ deleteFile hdc_file
|
||||
rmPlain target = do
|
||||
mtv <- ghcSet target
|
||||
forM_ mtv $ \tv -> do
|
||||
files <- liftE $ ghcToolFiles tv
|
||||
bindir <- liftIO $ ghcupBinDir
|
||||
forM_ files $ \f -> do
|
||||
let fullF = (bindir </> f)
|
||||
lift $ $(logDebug) [i|rm -f #{toFilePath fullF}|]
|
||||
liftIO $ hideError doesNotExistErrorType $ deleteFile fullF
|
||||
-- old ghcup
|
||||
let hdc_file = (bindir </> [rel|haddock-ghc|])
|
||||
lift $ $(logDebug) [i|rm -f #{toFilePath hdc_file}|]
|
||||
liftIO $ hideError doesNotExistErrorType $ deleteFile hdc_file
|
||||
|
||||
|
||||
-- e.g. ghc-8.6
|
||||
rmMajorSymlinks :: (MonadLogger m, MonadIO m) => Version -> m ()
|
||||
rmMajorSymlinks ver = do
|
||||
(mj, mi) <- liftIO $ getGHCMajor ver
|
||||
let v' = E.encodeUtf8 $ intToText mj <> "." <> intToText mi
|
||||
rmMajorSymlinks :: (MonadThrow m, MonadLogger m, MonadIO m)
|
||||
=> GHCTargetVersion
|
||||
-> m ()
|
||||
rmMajorSymlinks GHCTargetVersion {..} = do
|
||||
(mj, mi) <- getMajorMinorV _tvVersion
|
||||
let v' = intToText mj <> "." <> intToText mi
|
||||
|
||||
bindir <- liftIO ghcupBinDir
|
||||
|
||||
files <- liftIO $ getDirsFiles' bindir
|
||||
let myfiles = filter (\x -> ("-" <> v') `B.isSuffixOf` toFilePath x) files
|
||||
forM_ myfiles $ \f -> do
|
||||
files <- liftIO $ findFiles'
|
||||
bindir
|
||||
( maybe mempty (\x -> MP.chunk (x <> "-")) _tvTarget
|
||||
*> parseUntil1 (MP.chunk v')
|
||||
*> MP.chunk v'
|
||||
*> MP.eof
|
||||
)
|
||||
|
||||
forM_ files $ \f -> do
|
||||
let fullF = (bindir </> f)
|
||||
$(logDebug) [i|rm -f #{toFilePath fullF}|]
|
||||
liftIO $ hideError doesNotExistErrorType $ deleteFile fullF
|
||||
@@ -140,33 +153,60 @@ rmMajorSymlinks ver = do
|
||||
-----------------------------------
|
||||
|
||||
|
||||
toolAlreadyInstalled :: Tool -> Version -> IO Bool
|
||||
toolAlreadyInstalled tool ver = case tool of
|
||||
GHC -> ghcInstalled ver
|
||||
Cabal -> cabalInstalled ver
|
||||
GHCup -> pure True
|
||||
|
||||
|
||||
ghcInstalled :: Version -> IO Bool
|
||||
ghcInstalled :: GHCTargetVersion -> IO Bool
|
||||
ghcInstalled ver = do
|
||||
ghcdir <- ghcupGHCDir ver
|
||||
doesDirectoryExist ghcdir
|
||||
|
||||
|
||||
ghcSrcInstalled :: Version -> IO Bool
|
||||
ghcSrcInstalled :: GHCTargetVersion -> IO Bool
|
||||
ghcSrcInstalled ver = do
|
||||
ghcdir <- ghcupGHCDir ver
|
||||
doesFileExist (ghcdir </> ghcUpSrcBuiltFile)
|
||||
|
||||
|
||||
ghcSet :: (MonadIO m, MonadThrow m) => m (Maybe Version)
|
||||
ghcSet = do
|
||||
ghcBin <- (</> [rel|ghc|]) <$> liftIO ghcupBinDir
|
||||
ghcSet :: (MonadThrow m, MonadIO m)
|
||||
=> Maybe Text -- ^ the target of the GHC version, if any
|
||||
-- (e.g. armv7-unknown-linux-gnueabihf)
|
||||
-> m (Maybe GHCTargetVersion)
|
||||
ghcSet mtarget = do
|
||||
ghc <- parseRel $ E.encodeUtf8 (maybe "ghc" (<> "-ghc") mtarget)
|
||||
ghcBin <- (</> ghc) <$> liftIO ghcupBinDir
|
||||
|
||||
-- link destination is of the form ../ghc/<ver>/bin/ghc
|
||||
liftIO $ handleIO' NoSuchThing (\_ -> pure $ Nothing) $ do
|
||||
link <- readSymbolicLink $ toFilePath ghcBin
|
||||
Just <$> ghcLinkVersion link
|
||||
where
|
||||
ghcLinkVersion :: MonadThrow m => ByteString -> m GHCTargetVersion
|
||||
ghcLinkVersion bs = do
|
||||
t <- throwEither $ E.decodeUtf8' bs
|
||||
throwEither $ MP.parse parser "" t
|
||||
where
|
||||
parser =
|
||||
MP.chunk "../ghc/"
|
||||
*> (do
|
||||
r <- parseUntil1 (MP.chunk "/")
|
||||
rest <- MP.getInput
|
||||
MP.setInput r
|
||||
x <- ghcTargetVerP
|
||||
MP.setInput rest
|
||||
pure x
|
||||
)
|
||||
<* MP.chunk "/bin/"
|
||||
<* ghcTargetBinP "ghc"
|
||||
<* MP.eof
|
||||
|
||||
|
||||
-- | Get all installed GHCs by reading ~/.ghcup/ghc/<dir>.
|
||||
-- If a dir cannot be parsed, returns left.
|
||||
getInstalledGHCs :: MonadIO m => m [Either (Path Rel) GHCTargetVersion]
|
||||
getInstalledGHCs = do
|
||||
ghcdir <- liftIO $ ghcupGHCBaseDir
|
||||
fs <- liftIO $ hideErrorDef [NoSuchThing] [] $ getDirsFiles' ghcdir
|
||||
forM fs $ \f -> case parseGHCupGHCDir f of
|
||||
Right r -> pure $ Right r
|
||||
Left _ -> pure $ Left f
|
||||
|
||||
|
||||
cabalInstalled :: Version -> IO Bool
|
||||
@@ -179,7 +219,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
|
||||
|
||||
@@ -190,32 +230,49 @@ cabalSet = do
|
||||
-----------------------------------------
|
||||
|
||||
|
||||
-- | We assume GHC is in semver format. I hope it is.
|
||||
getGHCMajor :: MonadThrow m => Version -> m (Int, Int)
|
||||
getGHCMajor ver = do
|
||||
SemVer {..} <- throwEither (semver $ prettyVer ver)
|
||||
pure (fromIntegral _svMajor, fromIntegral _svMinor)
|
||||
getMajorMinorV :: MonadThrow m => Version -> m (Int, Int)
|
||||
getMajorMinorV Version {..} = case _vChunks of
|
||||
([Digits x] : [Digits y] : _) -> pure (fromIntegral x, fromIntegral y)
|
||||
_ -> throwM $ ParseError "Could not parse X.Y from version"
|
||||
|
||||
|
||||
matchMajor :: Version -> Int -> Int -> Bool
|
||||
matchMajor v' major' minor' = case getMajorMinorV v' of
|
||||
Just (x, y) -> x == major' && y == minor'
|
||||
Nothing -> False
|
||||
|
||||
|
||||
-- | Get the latest installed full GHC version that satisfies X.Y.
|
||||
-- This reads `ghcupGHCBaseDir`.
|
||||
getGHCForMajor :: (MonadIO m, MonadThrow m)
|
||||
=> Int -- ^ major version component
|
||||
-> Int -- ^ minor version component
|
||||
-> m (Maybe Version)
|
||||
getGHCForMajor major' minor' = do
|
||||
p <- liftIO $ ghcupGHCBaseDir
|
||||
ghcs <- liftIO $ getDirsFiles' p
|
||||
semvers <- forM ghcs $ throwEither . semver . E.decodeUtf8 . toFilePath
|
||||
mapM (throwEither . version)
|
||||
. fmap prettySemVer
|
||||
=> Int -- ^ major version component
|
||||
-> Int -- ^ minor version component
|
||||
-> Maybe Text -- ^ the target triple
|
||||
-> m (Maybe GHCTargetVersion)
|
||||
getGHCForMajor major' minor' mt = do
|
||||
ghcs <- rights <$> getInstalledGHCs
|
||||
|
||||
pure
|
||||
. lastMay
|
||||
. sort
|
||||
. sortBy (\x y -> compare (_tvVersion x) (_tvVersion y))
|
||||
. filter
|
||||
(\SemVer {..} ->
|
||||
fromIntegral _svMajor == major' && fromIntegral _svMinor == minor'
|
||||
(\GHCTargetVersion {..} ->
|
||||
_tvTarget == mt && matchMajor _tvVersion major' minor'
|
||||
)
|
||||
$ semvers
|
||||
$ ghcs
|
||||
|
||||
|
||||
-- | 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 -> matchMajor v major' minor'))
|
||||
. preview (ix GHC % to Map.keys)
|
||||
$ dls
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -232,8 +289,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 +316,27 @@ 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
|
||||
|
||||
|
||||
|
||||
@@ -298,12 +362,12 @@ urlBaseName = parseRel . snd . B.breakEnd (== _slash) . urlDecode False
|
||||
|
||||
|
||||
-- Get tool files from '~/.ghcup/bin/ghc/<ver>/bin/*'
|
||||
-- while ignoring *-<ver> symlinks.
|
||||
-- while ignoring *-<ver> symlinks and accounting for cross triple prefix.
|
||||
--
|
||||
-- Returns unversioned relative files, e.g.:
|
||||
-- ["hsc2hs","haddock","hpc","runhaskell","ghc","ghc-pkg","ghci","runghc","hp2ps"]
|
||||
ghcToolFiles :: (MonadThrow m, MonadFail m, MonadIO m)
|
||||
=> Version
|
||||
=> GHCTargetVersion
|
||||
-> Excepts '[NotInstalled] m [Path Rel]
|
||||
ghcToolFiles ver = do
|
||||
ghcdir <- liftIO $ ghcupGHCDir ver
|
||||
@@ -311,18 +375,28 @@ ghcToolFiles ver = do
|
||||
|
||||
-- fail if ghc is not installed
|
||||
whenM (fmap not $ liftIO $ doesDirectoryExist ghcdir)
|
||||
(throwE (NotInstalled GHC ver))
|
||||
(throwE (NotInstalled GHC (prettyTVer ver)))
|
||||
|
||||
files <- liftIO $ getDirsFiles' bindir
|
||||
files <- liftIO $ getDirsFiles' bindir
|
||||
-- figure out the <ver> suffix, because this might not be `Version` for
|
||||
-- alpha/rc releases, but x.y.a.somedate.
|
||||
|
||||
-- for cross, this won't be "ghc", but e.g.
|
||||
-- "armv7-unknown-linux-gnueabihf-ghc"
|
||||
[ghcbin] <- liftIO $ findFiles
|
||||
bindir
|
||||
(makeRegexOpts compExtended
|
||||
execBlank
|
||||
([s|^([a-zA-Z0-9_-]*[a-zA-Z0-9_]-)?ghc$|] :: ByteString)
|
||||
)
|
||||
|
||||
(Just symver) <-
|
||||
(B.stripPrefix "ghc-" . takeFileName)
|
||||
<$> (liftIO $ readSymbolicLink $ toFilePath (bindir </> [rel|ghc|]))
|
||||
(B.stripPrefix (toFilePath ghcbin <> "-") . takeFileName)
|
||||
<$> (liftIO $ readSymbolicLink $ toFilePath (bindir </> ghcbin))
|
||||
when (B.null symver)
|
||||
(throwIO $ userError $ "Fatal: ghc symlink target is broken")
|
||||
|
||||
pure $ filter (\x -> not $ symver `B.isSuffixOf` toFilePath x) files
|
||||
pure . filter (\x -> not $ symver `B.isSuffixOf` toFilePath x) $ files
|
||||
|
||||
|
||||
-- | This file, when residing in ~/.ghcup/ghc/<ver>/ signals that
|
||||
@@ -368,3 +442,47 @@ 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
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE QuasiQuotes #-}
|
||||
{-# LANGUAGE ViewPatterns #-}
|
||||
|
||||
module GHCup.Utils.Dirs where
|
||||
|
||||
|
||||
import GHCup.Types
|
||||
import GHCup.Types.JSON ( )
|
||||
import GHCup.Utils.MegaParsec
|
||||
import GHCup.Utils.Prelude
|
||||
|
||||
import Control.Applicative
|
||||
@@ -13,7 +16,6 @@ import Control.Monad
|
||||
import Control.Monad.Reader
|
||||
import Control.Monad.Trans.Resource
|
||||
import Data.Maybe
|
||||
import Data.Versions
|
||||
import HPath
|
||||
import HPath.IO
|
||||
import Optics
|
||||
@@ -27,8 +29,10 @@ import System.Posix.Env.ByteString ( getEnv
|
||||
import System.Posix.Temp.ByteString ( mkdtemp )
|
||||
|
||||
import qualified Data.ByteString.UTF8 as UTF8
|
||||
import qualified Data.Text.Encoding as E
|
||||
import qualified System.Posix.FilePath as FP
|
||||
import qualified System.Posix.User as PU
|
||||
import qualified Text.Megaparsec as MP
|
||||
|
||||
|
||||
|
||||
@@ -37,24 +41,38 @@ import qualified System.Posix.User as PU
|
||||
-------------------------
|
||||
|
||||
|
||||
-- | ~/.ghcup by default
|
||||
ghcupBaseDir :: IO (Path Abs)
|
||||
ghcupBaseDir = do
|
||||
getEnv "GHCUP_INSTALL_BASE_PREFIX" >>= \case
|
||||
bdir <- getEnv "GHCUP_INSTALL_BASE_PREFIX" >>= \case
|
||||
Just r -> parseAbs r
|
||||
Nothing -> do
|
||||
home <- liftIO getHomeDirectory
|
||||
pure (home </> [rel|.ghcup|])
|
||||
Nothing -> liftIO getHomeDirectory
|
||||
pure (bdir </> [rel|.ghcup|])
|
||||
|
||||
|
||||
-- | ~/.ghcup/ghc by default.
|
||||
ghcupGHCBaseDir :: IO (Path Abs)
|
||||
ghcupGHCBaseDir = ghcupBaseDir <&> (</> [rel|ghc|])
|
||||
|
||||
ghcupGHCDir :: Version -> IO (Path Abs)
|
||||
|
||||
-- | Gets '~/.ghcup/ghc/<ghcupGHCDir>'.
|
||||
-- The dir may be of the form
|
||||
-- * armv7-unknown-linux-gnueabihf-8.8.3
|
||||
-- * 8.8.4
|
||||
ghcupGHCDir :: GHCTargetVersion -> IO (Path Abs)
|
||||
ghcupGHCDir ver = do
|
||||
ghcbasedir <- ghcupGHCBaseDir
|
||||
verdir <- parseRel (verToBS ver)
|
||||
verdir <- parseRel $ E.encodeUtf8 (prettyTVer ver)
|
||||
pure (ghcbasedir </> verdir)
|
||||
|
||||
|
||||
-- | See 'ghcupToolParser'.
|
||||
parseGHCupGHCDir :: MonadThrow m => Path Rel -> m GHCTargetVersion
|
||||
parseGHCupGHCDir (toFilePath -> f) = do
|
||||
fp <- throwEither $ E.decodeUtf8' f
|
||||
throwEither $ MP.parse ghcTargetVerP "" fp
|
||||
|
||||
|
||||
ghcupBinDir :: IO (Path Abs)
|
||||
ghcupBinDir = ghcupBaseDir <&> (</> [rel|bin|])
|
||||
|
||||
|
||||
@@ -18,6 +18,8 @@ import Data.Foldable
|
||||
import Data.Functor
|
||||
import Data.IORef
|
||||
import Data.Maybe
|
||||
import Data.Text ( Text )
|
||||
import Data.Void
|
||||
import GHC.Foreign ( peekCStringLen )
|
||||
import GHC.IO.Encoding ( getLocaleEncoding )
|
||||
import GHC.IO.Exception
|
||||
@@ -39,12 +41,12 @@ import "unix" System.Posix.IO.ByteString
|
||||
hiding ( openFd )
|
||||
import System.Posix.Process ( ProcessStatus(..) )
|
||||
import System.Posix.Types
|
||||
import Text.Regex.Posix
|
||||
|
||||
|
||||
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
|
||||
@@ -53,12 +55,14 @@ import qualified Streamly.Internal.Memory.ArrayStream
|
||||
import qualified Streamly.FileSystem.Handle as FH
|
||||
import qualified Streamly.Internal.Data.Unfold as SU
|
||||
import qualified Streamly.Prelude as S
|
||||
import qualified Text.Megaparsec as MP
|
||||
import qualified Data.ByteString as BS
|
||||
import qualified Data.ByteString.Lazy as L
|
||||
import qualified "unix-bytestring" System.Posix.IO.ByteString
|
||||
as SPIB
|
||||
|
||||
|
||||
|
||||
-- | Bool signals whether the regions should be cleaned.
|
||||
data StopThread = StopThread Bool
|
||||
deriving Show
|
||||
@@ -201,6 +205,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 +213,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 +374,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)
|
||||
@@ -383,3 +385,27 @@ searchPath paths needle = go paths
|
||||
if p == toFilePath needle
|
||||
then isExecutable (basedir </> needle)
|
||||
else pure False
|
||||
|
||||
|
||||
findFiles :: Path Abs -> Regex -> IO [Path Rel]
|
||||
findFiles path regex = do
|
||||
dirStream <- openDirStream (toFilePath path)
|
||||
f <-
|
||||
(fmap . fmap) snd
|
||||
. S.toList
|
||||
. S.filter (\(_, p) -> match regex p)
|
||||
$ dirContentsStream dirStream
|
||||
pure $ join $ fmap parseRel f
|
||||
|
||||
|
||||
findFiles' :: Path Abs -> MP.Parsec Void Text () -> IO [Path Rel]
|
||||
findFiles' path parser = do
|
||||
dirStream <- openDirStream (toFilePath path)
|
||||
f <-
|
||||
(fmap . fmap) snd
|
||||
. S.toList
|
||||
. S.filter (\(_, p) -> case E.decodeUtf8' p of
|
||||
Left _ -> False
|
||||
Right p' -> isJust $ MP.parseMaybe parser p')
|
||||
$ dirContentsStream dirStream
|
||||
pure $ join $ fmap parseRel f
|
||||
|
||||
87
lib/GHCup/Utils/MegaParsec.hs
Normal file
87
lib/GHCup/Utils/MegaParsec.hs
Normal file
@@ -0,0 +1,87 @@
|
||||
{-# LANGUAGE CPP #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
|
||||
module GHCup.Utils.MegaParsec where
|
||||
|
||||
import GHCup.Types
|
||||
|
||||
import Control.Applicative
|
||||
import Control.Monad
|
||||
#if !MIN_VERSION_base(4,13,0)
|
||||
import Control.Monad.Fail ( MonadFail )
|
||||
#endif
|
||||
import Data.Functor
|
||||
import Data.Maybe
|
||||
import Data.Text ( Text )
|
||||
import Data.Versions
|
||||
import Data.Void
|
||||
|
||||
import qualified Data.Text as T
|
||||
import qualified Text.Megaparsec as MP
|
||||
|
||||
|
||||
choice' :: (MonadFail f, MP.MonadParsec e s f) => [f a] -> f a
|
||||
choice' [] = fail "Empty list"
|
||||
choice' [x ] = x
|
||||
choice' (x : xs) = MP.try x <|> choice' xs
|
||||
|
||||
|
||||
parseUntil :: MP.Parsec Void Text a -> MP.Parsec Void Text Text
|
||||
parseUntil p = do
|
||||
(MP.try (MP.lookAhead p) $> mempty)
|
||||
<|> (do
|
||||
c <- T.singleton <$> MP.anySingle
|
||||
c2 <- parseUntil p
|
||||
pure (c `mappend` c2)
|
||||
)
|
||||
|
||||
parseUntil1 :: MP.Parsec Void Text a -> MP.Parsec Void Text Text
|
||||
parseUntil1 p = do
|
||||
i1 <- MP.getOffset
|
||||
t <- parseUntil p
|
||||
i2 <- MP.getOffset
|
||||
if i1 == i2 then fail "empty parse" else pure t
|
||||
|
||||
|
||||
|
||||
-- | Parses e.g.
|
||||
-- * armv7-unknown-linux-gnueabihf-ghc
|
||||
-- * armv7-unknown-linux-gnueabihf-ghci
|
||||
ghcTargetBinP :: Text -> MP.Parsec Void Text (Maybe Text, Text)
|
||||
ghcTargetBinP t =
|
||||
(,)
|
||||
<$> ( MP.try
|
||||
(Just <$> (parseUntil1 (MP.chunk "-" *> MP.chunk t)) <* MP.chunk "-"
|
||||
)
|
||||
<|> (flip const Nothing <$> mempty)
|
||||
)
|
||||
<*> (MP.chunk t <* MP.eof)
|
||||
|
||||
|
||||
-- | Extracts target triple and version from e.g.
|
||||
-- * armv7-unknown-linux-gnueabihf-8.8.3
|
||||
-- * armv7-unknown-linux-gnueabihf-8.8.3
|
||||
ghcTargetVerP :: MP.Parsec Void Text GHCTargetVersion
|
||||
ghcTargetVerP =
|
||||
(\x y -> GHCTargetVersion x y)
|
||||
<$> (MP.try (Just <$> (parseUntil1 (MP.chunk "-" *> verP)) <* MP.chunk "-")
|
||||
<|> (flip const Nothing <$> mempty)
|
||||
)
|
||||
<*> (version' <* MP.eof)
|
||||
where
|
||||
verP :: MP.Parsec Void Text Text
|
||||
verP = do
|
||||
v <- version'
|
||||
let startsWithDigists =
|
||||
and
|
||||
. take 3
|
||||
. join
|
||||
. (fmap . fmap)
|
||||
(\case
|
||||
(Digits _) -> True
|
||||
(Str _) -> False
|
||||
)
|
||||
$ (_vChunks v)
|
||||
if startsWithDigists && not (isJust (_vEpoch v))
|
||||
then pure $ prettyVer v
|
||||
else fail "Oh"
|
||||
@@ -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?
|
||||
@@ -221,6 +218,12 @@ throwEither a = case a of
|
||||
Right r -> pure r
|
||||
|
||||
|
||||
throwEither' :: (Exception a, MonadThrow m) => a -> Either x b -> m b
|
||||
throwEither' e eth = case eth of
|
||||
Left _ -> throwM e
|
||||
Right r -> pure r
|
||||
|
||||
|
||||
verToBS :: Version -> ByteString
|
||||
verToBS = E.encodeUtf8 . prettyVer
|
||||
|
||||
@@ -240,3 +243,19 @@ addToCurrentEnv :: MonadIO m
|
||||
addToCurrentEnv adds = do
|
||||
cEnv <- liftIO $ getEnvironment
|
||||
pure (adds ++ cEnv)
|
||||
|
||||
|
||||
pvpToVersion :: PVP -> Version
|
||||
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.0|]
|
||||
ghcUpVer = [pver|0.1.4|]
|
||||
|
||||
numericVer :: String
|
||||
numericVer = T.unpack . prettyPVP $ ghcUpVer
|
||||
|
||||
208
www/LICENSE
Normal file
208
www/LICENSE
Normal file
@@ -0,0 +1,208 @@
|
||||
The ghcup website, excluding ghcup, fonts, bootstrap-haskell script are subject
|
||||
to the license below. Design, javascript and css are used from the rustup
|
||||
project: https://github.com/rust-lang/rustup.rs/tree/master/www
|
||||
|
||||
|
||||
|
||||
===============================================================================
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
1
www/copy.svg
Normal file
1
www/copy.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" focusable="false" width="1.66em" height="2em" style="-ms-transform: rotate(360deg); -webkit-transform: rotate(360deg); transform: rotate(360deg);" preserveAspectRatio="xMidYMid meet" viewBox="0 0 14 16"><path fill-rule="evenodd" d="M2 13h4v1H2v-1zm5-6H2v1h5V7zm2 3V8l-3 3l3 3v-2h5v-2H9zM4.5 9H2v1h2.5V9zM2 12h2.5v-1H2v1zm9 1h1v2c-.02.28-.11.52-.3.7c-.19.18-.42.28-.7.3H1c-.55 0-1-.45-1-1V4c0-.55.45-1 1-1h3c0-1.11.89-2 2-2c1.11 0 2 .89 2 2h3c.55 0 1 .45 1 1v5h-1V6H1v9h10v-2zM2 5h8c0-.55-.45-1-1-1H8c-.55 0-1-.45-1-1s-.45-1-1-1s-1 .45-1 1s-.45 1-1 1H3c-.55 0-1 .45-1 1z" fill="#626262"/></svg>
|
||||
|
After Width: | Height: | Size: 696 B |
BIN
www/fonts/FiraSans-Light.woff
Normal file
BIN
www/fonts/FiraSans-Light.woff
Normal file
Binary file not shown.
BIN
www/fonts/FiraSans-Medium.woff
Normal file
BIN
www/fonts/FiraSans-Medium.woff
Normal file
Binary file not shown.
BIN
www/fonts/FiraSans-Regular.woff
Normal file
BIN
www/fonts/FiraSans-Regular.woff
Normal file
Binary file not shown.
BIN
www/fonts/Inconsolata-Regular.ttf
Normal file
BIN
www/fonts/Inconsolata-Regular.ttf
Normal file
Binary file not shown.
92
www/fonts/OFL.txt
Normal file
92
www/fonts/OFL.txt
Normal file
@@ -0,0 +1,92 @@
|
||||
Copyright (c) 2011, Raph Levien (firstname.lastname@gmail.com), Copyright (c) 2012, Cyreal (cyreal.org)
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
http://scripts.sil.org/OFL
|
||||
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||
BIN
www/fonts/WorkSans-Medium.ttf
Normal file
BIN
www/fonts/WorkSans-Medium.ttf
Normal file
Binary file not shown.
240
www/ghcup.css
Normal file
240
www/ghcup.css
Normal file
@@ -0,0 +1,240 @@
|
||||
@font-face {
|
||||
font-family: 'Fira Sans';
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
src: local('Fira Sans Light'), url("fonts/FiraSans-Light.woff") format('woff');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Fira Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Fira Sans'), url("fonts/FiraSans-Regular.woff") format('woff');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Fira Sans';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
src: local('Fira Sans Medium'), url("fonts/FiraSans-Medium.woff") format('woff');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Work Sans';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
src: local('Work Sans Medium'), url("fonts/WorkSans-Medium.ttf") format('ttf');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Inconsolata';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Inconsolata Regular'), url("fonts/Inconsolata-Regular.ttf") format('ttf');
|
||||
}
|
||||
|
||||
body {
|
||||
margin-top: 2em;
|
||||
background-color: white;
|
||||
color: #515151;
|
||||
font-family: "Fira Sans","Helvetica Neue",Helvetica,Arial,sans-serif;
|
||||
font-weight: 300;
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
pre {
|
||||
font-family: Inconsolata,Menlo,Monaco,Consolas,"Courier New",monospace;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
body#idx #pitch > a {
|
||||
font-weight: 500;
|
||||
line-height: 2em;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #428bca;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: rgb(42, 100, 150);
|
||||
}
|
||||
|
||||
body#idx > * {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
text-align: center;
|
||||
width: 37em;
|
||||
}
|
||||
|
||||
body#idx > #pitch {
|
||||
width: 30rem;
|
||||
}
|
||||
|
||||
#pitch em {
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
body#idx p {
|
||||
margin-top: 2em;
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
|
||||
body#idx p.other-help {
|
||||
font-size: 0.6em;
|
||||
}
|
||||
|
||||
.instructions {
|
||||
background-color: rgb(250, 250, 250);
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
border-radius: 3px;
|
||||
border: 1px solid rgb(204, 204, 204);
|
||||
box-shadow: 0px 1px 4px 0px rgb(204, 204, 204);
|
||||
}
|
||||
|
||||
.instructions > * {
|
||||
width: 55rem;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.instructions div.command-button {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.instructions div.command-button button {
|
||||
color: white;
|
||||
/* border: none; */
|
||||
background-color: rgb(242, 242, 242);
|
||||
border-width: 2px;
|
||||
border-style: solid;
|
||||
border-radius: 3px;
|
||||
|
||||
margin-left: 1rem;
|
||||
margin-right: auto;
|
||||
margin-top: 25px;
|
||||
margin-bottom: 25px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.instructions div.command-button button:hover {
|
||||
background: rgb(232, 232, 232);
|
||||
}
|
||||
|
||||
.instructions div.command-button button:focus {
|
||||
background: rgb(222, 222, 222);
|
||||
}
|
||||
|
||||
hr {
|
||||
margin-top: 2em;
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
|
||||
#platform-instructions-linux > div > pre,
|
||||
#platform-instructions-mac > div > pre,
|
||||
#platform-instructions-freebsd > div > pre,
|
||||
#platform-instructions-win32 > pre,
|
||||
#platform-instructions-win64 > pre,
|
||||
#platform-instructions-default > div > div > pre,
|
||||
#platform-instructions-unknown > div > div > pre {
|
||||
background-color: #515151;
|
||||
color: white;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
padding-top: 1rem;
|
||||
padding-bottom: 1rem;
|
||||
padding-right: 1rem;
|
||||
text-align: center;
|
||||
border-radius: 3px;
|
||||
box-shadow: inset 0px 0px 20px 0px #333333;
|
||||
}
|
||||
|
||||
#platform-instructions-win32 a.windows-download,
|
||||
#platform-instructions-win64 a.windows-download,
|
||||
#platform-instructions-default a.windows-download,
|
||||
#platform-instructions-unknown a.windows-download {
|
||||
display: block;
|
||||
padding-top: 0.4rem;
|
||||
padding-bottom: 0.6rem;
|
||||
font-family: "Work Sans", "Fira Sans","Helvetica Neue",Helvetica,Arial,sans-serif;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.1rem;
|
||||
}
|
||||
|
||||
/* This is the box that prints navigator.platform, navigator.appVersion values */
|
||||
#platform-instructions-unknown > div:first-of-type {
|
||||
font-size: 16px;
|
||||
line-height: 2rem;
|
||||
}
|
||||
|
||||
#about {
|
||||
font-size: 16px;
|
||||
line-height: 2em;
|
||||
}
|
||||
|
||||
#about > img {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
transform: translateY(11px);
|
||||
}
|
||||
|
||||
#platform-button {
|
||||
background-color: #515151;
|
||||
color: white;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
.ghcup-command:before {
|
||||
color: #999;
|
||||
content: " $ ";
|
||||
}
|
||||
|
||||
/* Tooltip container */
|
||||
.tooltip {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
/* border-bottom: 1px dotted black; [> If you want dots under the hoverable text <] */
|
||||
}
|
||||
|
||||
/* Tooltip text */
|
||||
.tooltip .tooltiptext {
|
||||
visibility: hidden;
|
||||
width: 120px;
|
||||
background-color: #555;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
padding: 5px 0;
|
||||
border-radius: 6px;
|
||||
|
||||
/* Position the tooltip text */
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
bottom: 125%;
|
||||
left: 50%;
|
||||
margin-left: -60px;
|
||||
|
||||
/* Fade in tooltip */
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
|
||||
/* Tooltip arrow */
|
||||
.tooltip .tooltiptext::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 50%;
|
||||
margin-left: -5px;
|
||||
border-width: 5px;
|
||||
border-style: solid;
|
||||
border-color: #555 transparent transparent transparent;
|
||||
}
|
||||
|
||||
/* Show the tooltip text when you mouse over the tooltip container */
|
||||
.tooltip:hover .tooltiptext {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
166
www/ghcup.js
Normal file
166
www/ghcup.js
Normal file
@@ -0,0 +1,166 @@
|
||||
var platforms = ["default", "unknown", "win32", "win64", "linux", "freebsd", "mac"];
|
||||
var platform_override = null;
|
||||
|
||||
function detect_platform() {
|
||||
"use strict";
|
||||
|
||||
if (platform_override !== null) {
|
||||
return platforms[platform_override];
|
||||
}
|
||||
|
||||
var os = "unknown";
|
||||
|
||||
if (navigator.platform == "Linux x86_64") {os = "linux";}
|
||||
if (navigator.platform == "Linux i686") {os = "linux";}
|
||||
if (navigator.platform == "Linux i686 on x86_64") {os = "linux";}
|
||||
if (navigator.platform == "Linux aarch64") {os = "linux";}
|
||||
if (navigator.platform == "Linux armv6l") {os = "linux";}
|
||||
if (navigator.platform == "Linux armv7l") {os = "linux";}
|
||||
if (navigator.platform == "Linux armv8l") {os = "linux";}
|
||||
if (navigator.platform == "Linux ppc64") {os = "linux";}
|
||||
if (navigator.platform == "Linux mips") {os = "linux";}
|
||||
if (navigator.platform == "Linux mips64") {os = "linux";}
|
||||
if (navigator.platform == "Mac") {os = "mac";}
|
||||
if (navigator.platform == "Win32") {os = "win32";}
|
||||
if (navigator.platform == "Win64" ||
|
||||
navigator.userAgent.indexOf("WOW64") != -1 ||
|
||||
navigator.userAgent.indexOf("Win64") != -1) { os = "win64"; }
|
||||
if (navigator.platform == "FreeBSD x86_64") {os = "freebsd";}
|
||||
if (navigator.platform == "FreeBSD amd64") {os = "freebsd";}
|
||||
// if (navigator.platform == "NetBSD x86_64") {os = "unix";}
|
||||
// if (navigator.platform == "NetBSD amd64") {os = "unix";}
|
||||
|
||||
// I wish I knew by now, but I don't. Try harder.
|
||||
if (os == "unknown") {
|
||||
if (navigator.appVersion.indexOf("Win")!=-1) {os = "win32";}
|
||||
if (navigator.appVersion.indexOf("Mac")!=-1) {os = "mac";}
|
||||
if (navigator.appVersion.indexOf("FreeBSD")!=-1) {os = "freebsd";}
|
||||
}
|
||||
|
||||
// Firefox Quantum likes to hide platform and appVersion but oscpu works
|
||||
if (navigator.oscpu) {
|
||||
if (navigator.oscpu.indexOf("Win32")!=-1) {os = "win32";}
|
||||
if (navigator.oscpu.indexOf("Win64")!=-1) {os = "win64";}
|
||||
if (navigator.oscpu.indexOf("Mac")!=-1) {os = "mac";}
|
||||
if (navigator.oscpu.indexOf("Linux")!=-1) {os = "linux";}
|
||||
if (navigator.oscpu.indexOf("FreeBSD")!=-1) {os = "freebsd";}
|
||||
// if (navigator.oscpu.indexOf("NetBSD")!=-1) {os = "unix";}
|
||||
}
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
function adjust_for_platform() {
|
||||
"use strict";
|
||||
|
||||
var platform = detect_platform();
|
||||
|
||||
platforms.forEach(function (platform_elem) {
|
||||
var platform_div = document.getElementById("platform-instructions-" + platform_elem);
|
||||
platform_div.style.display = "none";
|
||||
if (platform == platform_elem) {
|
||||
platform_div.style.display = "block";
|
||||
}
|
||||
});
|
||||
|
||||
adjust_platform_specific_instrs(platform);
|
||||
}
|
||||
|
||||
function adjust_platform_specific_instrs(platform) {
|
||||
var platform_specific = document.getElementsByClassName("platform-specific");
|
||||
for (var el of platform_specific) {
|
||||
var el_is_not_win = el.className.indexOf("not-win") !== -1;
|
||||
var el_is_inline = el.tagName.toLowerCase() == "span";
|
||||
var el_visible_style = "block";
|
||||
if (el_is_inline) {
|
||||
el_visible_style = "inline";
|
||||
}
|
||||
if (platform == "win64" || platform == "win32") {
|
||||
if (el_is_not_win) {
|
||||
el.style.display = "none";
|
||||
} else {
|
||||
el.style.display = el_visible_style;
|
||||
}
|
||||
} else {
|
||||
if (el_is_not_win) {
|
||||
el.style.display = el_visible_style;
|
||||
} else {
|
||||
el.style.display = "none";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function cycle_platform() {
|
||||
if (platform_override == null) {
|
||||
platform_override = 0;
|
||||
} else {
|
||||
platform_override = (platform_override + 1) % platforms.length;
|
||||
}
|
||||
adjust_for_platform();
|
||||
}
|
||||
|
||||
function set_up_cycle_button() {
|
||||
var cycle_button = document.getElementById("platform-button");
|
||||
cycle_button.onclick = cycle_platform;
|
||||
|
||||
var key="test";
|
||||
var idx=0;
|
||||
var unlocked=false;
|
||||
|
||||
document.onkeypress = function(event) {
|
||||
if (event.key == "n" && unlocked) {
|
||||
cycle_platform();
|
||||
}
|
||||
|
||||
if (event.key == key[idx]) {
|
||||
idx += 1;
|
||||
|
||||
if (idx == key.length) {
|
||||
cycle_button.style.display = "block";
|
||||
unlocked = true;
|
||||
cycle_platform();
|
||||
}
|
||||
} else if (event.key == key[0]) {
|
||||
idx = 1;
|
||||
} else {
|
||||
idx = 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function go_to_default_platform() {
|
||||
platform_override = 0;
|
||||
adjust_for_platform();
|
||||
}
|
||||
|
||||
function set_up_default_platform_buttons() {
|
||||
var defaults_buttons = document.getElementsByClassName('default-platform-button');
|
||||
for (var i = 0; i < defaults_buttons.length; i++) {
|
||||
defaults_buttons[i].onclick = go_to_default_platform;
|
||||
}
|
||||
}
|
||||
|
||||
function fill_in_bug_report_values() {
|
||||
var nav_plat = document.getElementById("nav-plat");
|
||||
var nav_app = document.getElementById("nav-app");
|
||||
nav_plat.textContent = navigator.platform;
|
||||
nav_app.textContent = navigator.appVersion;
|
||||
}
|
||||
|
||||
function copyToClipboard() {
|
||||
const text = document.getElementsByClassName("ghcup-command").item(0).innerText;
|
||||
const el = document.createElement('textarea');
|
||||
el.value = text;
|
||||
document.body.appendChild(el);
|
||||
el.select();
|
||||
document.execCommand('copy');
|
||||
document.body.removeChild(el);
|
||||
}
|
||||
|
||||
(function () {
|
||||
adjust_for_platform();
|
||||
set_up_cycle_button();
|
||||
set_up_default_platform_buttons();
|
||||
fill_in_bug_report_values();
|
||||
}());
|
||||
66
www/haskell-logo.svg
Normal file
66
www/haskell-logo.svg
Normal file
@@ -0,0 +1,66 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="109"
|
||||
height="80"
|
||||
viewBox="0 0 109.00001 80"
|
||||
version="1.1"
|
||||
id="svg14"
|
||||
sodipodi:docname="haskell-logo.svg"
|
||||
inkscape:version="0.92.3 (2405546, 2018-03-11)">
|
||||
<metadata
|
||||
id="metadata20">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs18" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1916"
|
||||
inkscape:window-height="1033"
|
||||
id="namedview16"
|
||||
showgrid="false"
|
||||
inkscape:zoom="2.0159478"
|
||||
inkscape:cx="298.15447"
|
||||
inkscape:cy="-2.7202801"
|
||||
inkscape:window-x="1366"
|
||||
inkscape:window-y="22"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg14" />
|
||||
<path
|
||||
d="M 1.842,77.722 26.586,40.63 1.842,3.537 H 20.4 L 45.144,40.63 20.4,77.722 Z m 0,0"
|
||||
id="path8"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#453a62" />
|
||||
<path
|
||||
d="M 26.586,77.722 51.33,40.63 26.586,3.537 H 45.144 L 94.63,77.722 H 76.074 L 60.61,54.54 45.143,77.722 Z m 0,0"
|
||||
id="path10"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#5e5086" />
|
||||
<path
|
||||
d="M 86.384,56.085 78.136,43.72 h 28.868 V 56.086 H 86.384 Z M 74.012,37.54 65.764,25.175 h 41.24 V 37.54 Z m 0,0"
|
||||
id="path12"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#8f4e8b" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.1 KiB |
177
www/index.html
Normal file
177
www/index.html
Normal file
@@ -0,0 +1,177 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>ghcup - The Haskell (GHC) toolchain installer</title>
|
||||
<meta name="keywords" content="Haskell, Haskell programming language, ghc, ghcup">
|
||||
<meta name="description" content="The Haskell (GHC) toolchain installer">
|
||||
|
||||
<link rel="stylesheet" href="normalize.css">
|
||||
<link rel="stylesheet" href="ghcup.css">
|
||||
|
||||
</head>
|
||||
|
||||
<body id="idx">
|
||||
|
||||
<script id='html-content' type="text/html">
|
||||
<a id="platform-button" style="display: none;" href="#">
|
||||
click or press "n" to cycle platforms
|
||||
</a>
|
||||
|
||||
<p id="pitch">
|
||||
<em>ghcup</em> is an installer for<br/>
|
||||
the general purpose language <a href="https://www.haskell.org/">Haskell</a>
|
||||
</p>
|
||||
|
||||
<div id="platform-instructions-linux" class="instructions" style="display: none;">
|
||||
<p>Run the following in your terminal (as a user other than root), then follow the onscreen instructions.</p>
|
||||
<div class="command-button"><pre><span class='ghcup-command'>curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh</span></pre><button class="tooltip" onclick="copyToClipboard()"><img src="copy.svg" alt="" /><span class="tooltiptext">Copy to clipboard</span></button></div>
|
||||
<p class="other-help">If you don't like curl | sh, see <a href="https://gitlab.haskell.org/haskell/ghcup-hs#manual-install">other installation methods</a>.<br/>You appear to be running Linux. If not, <a class="default-platform-button" href="#">display all supported installers</a>.</p>
|
||||
</div>
|
||||
|
||||
<div id="platform-instructions-mac" class="instructions" style="display: none;">
|
||||
<p>Run the following in your terminal (as a user other than root), then follow the onscreen instructions.</p>
|
||||
<div class="command-button"><pre><span class='ghcup-command'>curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh</span></pre><button class="tooltip" onclick="copyToClipboard()"><img src="copy.svg" alt="" /><span class="tooltiptext">Copy to clipboard</span></button></div>
|
||||
<p class="other-help">If you don't like curl | sh, see <a href="https://gitlab.haskell.org/haskell/ghcup-hs#manual-install">other installation methods</a>.<br/>You appear to be running macOS. If not, <a class="default-platform-button" href="#">display all supported installers</a>.</p>
|
||||
</div>
|
||||
|
||||
<div id="platform-instructions-freebsd" class="instructions" style="display: none;">
|
||||
<p>Run the following in your terminal (as a user other than root), then follow the onscreen instructions.</p>
|
||||
<div class="command-button"><pre><span class='ghcup-command'>curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh</span></pre><button class="tooltip" onclick="copyToClipboard()"><img src="copy.svg" alt="" /><span class="tooltiptext">Copy to clipboard</span></button></div>
|
||||
<p class="other-help">If you don't like curl | sh, see <a href="https://gitlab.haskell.org/haskell/ghcup-hs#manual-install">other installation methods</a>.<br/>You appear to be running FreeBSD. If not, <a class="default-platform-button" href="#">display all supported installers</a>.</p>
|
||||
</div>
|
||||
|
||||
<div id="platform-instructions-win32" class="instructions">
|
||||
<p>
|
||||
To install Haskell, follow the instructions on
|
||||
<a class="windows-download" href="https://www.haskell.org/platform/#windows">Haskell Platform</a>
|
||||
</p>
|
||||
<p class="other-help">You appear to be running Windows 32-bit. If not, <a class="default-platform-button" href="#">display all supported installers</a>.</p>
|
||||
</div>
|
||||
|
||||
<div id="platform-instructions-win64" class="instructions" style="display: none;">
|
||||
<p>
|
||||
To install Haskell, follow the instructions on
|
||||
<a class="windows-download" href="https://www.haskell.org/platform/#windows">Haskell Platform</a>
|
||||
</p>
|
||||
<p class="other-help">You appear to be running Windows 64-bit. If not, <a class="default-platform-button" href="#">display all supported installers</a>.</p>
|
||||
</div>
|
||||
|
||||
<div id="platform-instructions-unknown" class="instructions" style="display: none;">
|
||||
<!-- unrecognized platform: ask for help -->
|
||||
<p>I don't recognize your platform.</p>
|
||||
<p>
|
||||
ghcup runs on Linux, macOS and FreeBSD. If
|
||||
you are on one of these platforms and are seeing this then please
|
||||
<a href="https://gitlab.haskell.org/haskell/ghcup-hs/issues">report an issue</a>,
|
||||
along with the following values:
|
||||
</p>
|
||||
|
||||
<div>
|
||||
<div>navigator.platform:</div>
|
||||
<div id="nav-plat"></div>
|
||||
<div>navigator.appVersion:</div>
|
||||
<div id="nav-app"></div>
|
||||
</div>
|
||||
|
||||
<!-- duplicate the default cross-platform instructions -->
|
||||
<div>
|
||||
<p>If you are running Linux, macOS or FreeBSD,<br/>run the following in your terminal (as a user other than root), then follow the onscreen instructions.</p>
|
||||
<div class="command-button"><pre><span class='ghcup-command'>curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh</span></pre><button class="tooltip" onclick="copyToClipboard()"><img src="copy.svg" alt="" /><span class="tooltiptext">Copy to clipboard</span></button></div>
|
||||
<p class="other-help">If you don't like curl | sh, see <a href="https://gitlab.haskell.org/haskell/ghcup-hs#manual-install">other installation methods</a>.</p>
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
|
||||
<div>
|
||||
<p>
|
||||
If you are running Windows,<br/>follow the instructions on
|
||||
<a class="windows-download" href="https://www.haskell.org/platform/#windows">Haskell Platform</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="platform-instructions-default" class="instructions">
|
||||
<div>
|
||||
<p>To install Haskell, if you are running Linux, macOS or FreeBSD,<br/>run the following
|
||||
in your terminal (as a user other than root), then follow the onscreen instructions.</p>
|
||||
<div class="command-button"><pre><span class='ghcup-command'>curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh</span></pre><button class="tooltip" onclick="copyToClipboard()"><img src="copy.svg" alt="" /><span class="tooltiptext">Copy to clipboard</span></button></div>
|
||||
<p class="other-help">If you don't like curl | sh, see <a href="https://gitlab.haskell.org/haskell/ghcup-hs#manual-install">other installation methods</a>.</p>
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
|
||||
<div>
|
||||
<p>
|
||||
If you are running Windows,<br/>follow the instructions on
|
||||
<a class="windows-download" href="https://www.haskell.org/platform/#windows">Haskell Platform</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<p>
|
||||
Need help? <a href="http://webchat.freenode.net/?randomnick=1&channels=%23haskell&uio=d4">Ask on #haskell</a> or <a href="https://gitlab.haskell.org/haskell/ghcup-hs/issues">report a bug</a>.
|
||||
</p>
|
||||
|
||||
<p id="about">
|
||||
<img src="haskell-logo.svg" alt="" />
|
||||
ghcup is a haskell.org hosted project.
|
||||
<br/>
|
||||
<a href="https://www.haskell.org/downloads/">other installation options</a>
|
||||
·
|
||||
<a href="https://gitlab.haskell.org/haskell/ghcup-hs">about ghcup</a>
|
||||
·
|
||||
<a href="https://github.com/rust-lang/rustup.rs/tree/master/www">web design from rustup</a>
|
||||
</p>
|
||||
</script>
|
||||
<script>
|
||||
document.write(document.getElementById("html-content").innerHTML);
|
||||
</script>
|
||||
<script type="text/javascript" src="ghcup.js"></script>
|
||||
|
||||
<noscript>
|
||||
<p id="pitch">
|
||||
<em>ghcup</em> is an installer for<br/>
|
||||
the general purpose language <a href="https://www.haskell.org/">Haskell</a>
|
||||
</p>
|
||||
|
||||
<div id="platform-instructions-default" class="instructions">
|
||||
<div>
|
||||
<p>To install Haskell, if you are running Linux, macOS or FreeBSD,<br/>run the following
|
||||
in your terminal (as a user other than root), then follow the onscreen instructions.</p>
|
||||
<pre><span class='ghcup-command'>curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh</span></pre>
|
||||
<p class="other-help">If you don't like curl | sh, see <a href="https://gitlab.haskell.org/haskell/ghcup-hs#manual-install">other installation methods</a>.</p>
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
|
||||
<div>
|
||||
<p>
|
||||
If you are running Windows,<br/>follow the instructions on
|
||||
<a class="windows-download" href="https://www.haskell.org/platform/#windows">Haskell Platform</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<p>
|
||||
Need help? <a href="http://webchat.freenode.net/?randomnick=1&channels=%23haskell&uio=d4">Ask on #haskell</a>.
|
||||
</p>
|
||||
|
||||
<p id="about">
|
||||
<img src="haskell-logo.svg" alt="" />
|
||||
ghcup is a haskell.org hosted project.
|
||||
<br/>
|
||||
<a href="https://www.haskell.org/downloads/">other installation options</a>
|
||||
·
|
||||
<a href="https://gitlab.haskell.org/haskell/ghcup-hs">about ghcup</a>
|
||||
·
|
||||
<a href="https://github.com/rust-lang/rustup.rs/tree/master/www">web design from rustup</a>
|
||||
</p>
|
||||
|
||||
</noscript>
|
||||
</body>
|
||||
</html>
|
||||
427
www/normalize.css
vendored
Normal file
427
www/normalize.css
vendored
Normal file
@@ -0,0 +1,427 @@
|
||||
/*! normalize.css v3.0.2 | MIT License | git.io/normalize */
|
||||
|
||||
/**
|
||||
* 1. Set default font family to sans-serif.
|
||||
* 2. Prevent iOS text size adjust after orientation change, without disabling
|
||||
* user zoom.
|
||||
*/
|
||||
|
||||
html {
|
||||
font-family: sans-serif; /* 1 */
|
||||
-ms-text-size-adjust: 100%; /* 2 */
|
||||
-webkit-text-size-adjust: 100%; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove default margin.
|
||||
*/
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* HTML5 display definitions
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Correct `block` display not defined for any HTML5 element in IE 8/9.
|
||||
* Correct `block` display not defined for `details` or `summary` in IE 10/11
|
||||
* and Firefox.
|
||||
* Correct `block` display not defined for `main` in IE 11.
|
||||
*/
|
||||
|
||||
article,
|
||||
aside,
|
||||
details,
|
||||
figcaption,
|
||||
figure,
|
||||
footer,
|
||||
header,
|
||||
hgroup,
|
||||
main,
|
||||
menu,
|
||||
nav,
|
||||
section,
|
||||
summary {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct `inline-block` display not defined in IE 8/9.
|
||||
* 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
|
||||
*/
|
||||
|
||||
audio,
|
||||
canvas,
|
||||
progress,
|
||||
video {
|
||||
display: inline-block; /* 1 */
|
||||
vertical-align: baseline; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent modern browsers from displaying `audio` without controls.
|
||||
* Remove excess height in iOS 5 devices.
|
||||
*/
|
||||
|
||||
audio:not([controls]) {
|
||||
display: none;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address `[hidden]` styling not present in IE 8/9/10.
|
||||
* Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.
|
||||
*/
|
||||
|
||||
[hidden],
|
||||
template {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Links
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove the gray background color from active links in IE 10.
|
||||
*/
|
||||
|
||||
a {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Improve readability when focused and also mouse hovered in all browsers.
|
||||
*/
|
||||
|
||||
a:active,
|
||||
a:hover {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
/* Text-level semantics
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Address styling not present in IE 8/9/10/11, Safari, and Chrome.
|
||||
*/
|
||||
|
||||
abbr[title] {
|
||||
border-bottom: 1px dotted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
|
||||
*/
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address styling not present in Safari and Chrome.
|
||||
*/
|
||||
|
||||
dfn {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address variable `h1` font-size and margin within `section` and `article`
|
||||
* contexts in Firefox 4+, Safari, and Chrome.
|
||||
*/
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
margin: 0.67em 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address styling not present in IE 8/9.
|
||||
*/
|
||||
|
||||
mark {
|
||||
background: #ff0;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address inconsistent and variable font size in all browsers.
|
||||
*/
|
||||
|
||||
small {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent `sub` and `sup` affecting `line-height` in all browsers.
|
||||
*/
|
||||
|
||||
sub,
|
||||
sup {
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
/* Embedded content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove border when inside `a` element in IE 8/9/10.
|
||||
*/
|
||||
|
||||
img {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct overflow not hidden in IE 9/10/11.
|
||||
*/
|
||||
|
||||
svg:not(:root) {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Grouping content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Address margin not present in IE 8/9 and Safari.
|
||||
*/
|
||||
|
||||
figure {
|
||||
margin: 1em 40px;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address differences between Firefox and other browsers.
|
||||
*/
|
||||
|
||||
hr {
|
||||
-moz-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Contain overflow in all browsers.
|
||||
*/
|
||||
|
||||
pre {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address odd `em`-unit font size rendering in all browsers.
|
||||
*/
|
||||
|
||||
code,
|
||||
kbd,
|
||||
pre,
|
||||
samp {
|
||||
font-family: monospace, monospace;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
/* Forms
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Known limitation: by default, Chrome and Safari on OS X allow very limited
|
||||
* styling of `select`, unless a `border` property is set.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 1. Correct color not being inherited.
|
||||
* Known issue: affects color of disabled elements.
|
||||
* 2. Correct font properties not being inherited.
|
||||
* 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
|
||||
*/
|
||||
|
||||
button,
|
||||
input,
|
||||
optgroup,
|
||||
select,
|
||||
textarea {
|
||||
color: inherit; /* 1 */
|
||||
font: inherit; /* 2 */
|
||||
margin: 0; /* 3 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Address `overflow` set to `hidden` in IE 8/9/10/11.
|
||||
*/
|
||||
|
||||
button {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address inconsistent `text-transform` inheritance for `button` and `select`.
|
||||
* All other form control elements do not inherit `text-transform` values.
|
||||
* Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
|
||||
* Correct `select` style inheritance in Firefox.
|
||||
*/
|
||||
|
||||
button,
|
||||
select {
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
|
||||
* and `video` controls.
|
||||
* 2. Correct inability to style clickable `input` types in iOS.
|
||||
* 3. Improve usability and consistency of cursor style between image-type
|
||||
* `input` and others.
|
||||
*/
|
||||
|
||||
button,
|
||||
html input[type="button"], /* 1 */
|
||||
input[type="reset"],
|
||||
input[type="submit"] {
|
||||
-webkit-appearance: button; /* 2 */
|
||||
cursor: pointer; /* 3 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-set default cursor for disabled elements.
|
||||
*/
|
||||
|
||||
button[disabled],
|
||||
html input[disabled] {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove inner padding and border in Firefox 4+.
|
||||
*/
|
||||
|
||||
button::-moz-focus-inner,
|
||||
input::-moz-focus-inner {
|
||||
border: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address Firefox 4+ setting `line-height` on `input` using `!important` in
|
||||
* the UA stylesheet.
|
||||
*/
|
||||
|
||||
input {
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
/**
|
||||
* It's recommended that you don't attempt to style these elements.
|
||||
* Firefox's implementation doesn't respect box-sizing, padding, or width.
|
||||
*
|
||||
* 1. Address box sizing set to `content-box` in IE 8/9/10.
|
||||
* 2. Remove excess padding in IE 8/9/10.
|
||||
*/
|
||||
|
||||
input[type="checkbox"],
|
||||
input[type="radio"] {
|
||||
box-sizing: border-box; /* 1 */
|
||||
padding: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Fix the cursor style for Chrome's increment/decrement buttons. For certain
|
||||
* `font-size` values of the `input`, it causes the cursor style of the
|
||||
* decrement button to change from `default` to `text`.
|
||||
*/
|
||||
|
||||
input[type="number"]::-webkit-inner-spin-button,
|
||||
input[type="number"]::-webkit-outer-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Address `appearance` set to `searchfield` in Safari and Chrome.
|
||||
* 2. Address `box-sizing` set to `border-box` in Safari and Chrome
|
||||
* (include `-moz` to future-proof).
|
||||
*/
|
||||
|
||||
input[type="search"] {
|
||||
-webkit-appearance: textfield; /* 1 */
|
||||
-moz-box-sizing: content-box;
|
||||
-webkit-box-sizing: content-box; /* 2 */
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove inner padding and search cancel button in Safari and Chrome on OS X.
|
||||
* Safari (but not Chrome) clips the cancel button when the search input has
|
||||
* padding (and `textfield` appearance).
|
||||
*/
|
||||
|
||||
input[type="search"]::-webkit-search-cancel-button,
|
||||
input[type="search"]::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define consistent border, margin, and padding.
|
||||
*/
|
||||
|
||||
fieldset {
|
||||
border: 1px solid #c0c0c0;
|
||||
margin: 0 2px;
|
||||
padding: 0.35em 0.625em 0.75em;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct `color` not being inherited in IE 8/9/10/11.
|
||||
* 2. Remove padding so people aren't caught out if they zero out fieldsets.
|
||||
*/
|
||||
|
||||
legend {
|
||||
border: 0; /* 1 */
|
||||
padding: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove default vertical scrollbar in IE 8/9/10/11.
|
||||
*/
|
||||
|
||||
textarea {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't inherit the `font-weight` (applied by a rule above).
|
||||
* NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
|
||||
*/
|
||||
|
||||
optgroup {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Tables
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove most spacing between table cells.
|
||||
*/
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
td,
|
||||
th {
|
||||
padding: 0;
|
||||
}
|
||||
Reference in New Issue
Block a user