Compare commits

..

1 Commits

Author SHA1 Message Date
1810bb27a8 Experimental nice thing 2020-03-24 18:05:12 +01:00
54 changed files with 843 additions and 5436 deletions

View File

@@ -1,78 +0,0 @@
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
.darwin:
tags:
- x86_64-darwin
.test_ghcup_version:
script:
- ./.gitlab/script/ghcup_version.sh
variables:
JSON_VERSION: "0.0.1"
.test_ghcup_version:linux:
extends:
- .test_ghcup_version
- .debian
before_script:
- ./.gitlab/before_script/linux/install_deps.sh
variables:
OS: "LINUX"
.test_ghcup_version:darwin:
extends:
- .test_ghcup_version
- .darwin
before_script:
- ./.gitlab/before_script/darwin/install_deps.sh
variables:
OS: "DARWIN"
after_script:
- BUILD_DIR=$CI_PROJECT_DIR
- echo "Cleaning $BUILD_DIR"
- cd $HOME
- rm -Rf "$BUILD_DIR"/*
- exit 0
######## linux ########
test:linux:recommended:
extends: .test_ghcup_version:linux
variables:
GHC_VERSION: "recommended"
test:linux:latest:
extends: .test_ghcup_version:linux
variables:
GHC_VERSION: "latest"
allow_failure: true
######## darwin ########
test:mac:recommended:
extends: .test_ghcup_version:darwin
variables:
GHC_VERSION: "recommended"
test:mac:latest:
extends: .test_ghcup_version:darwin
variables:
GHC_VERSION: "latest"
allow_failure: true

View File

@@ -1,14 +0,0 @@
#!/bin/sh
set -eux
. "$( cd "$(dirname "$0")" ; pwd -P )/../../ghcup_env"
curl -sSfL https://gitlab.haskell.org/haskell/ghcup/-/raw/master/ghcup > ./ghcup-legacy
chmod +x ghcup-legacy
./ghcup-legacy install ${GHC_VERSION}
./ghcup-legacy set ${GHC_VERSION}
./ghcup-legacy install-cabal
exit 0

View File

@@ -1,16 +0,0 @@
#!/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://gitlab.haskell.org/haskell/ghcup/-/raw/master/ghcup > ./ghcup-legacy
chmod +x ghcup-legacy
./ghcup-legacy install ${GHC_VERSION}
./ghcup-legacy set ${GHC_VERSION}
./ghcup-legacy install-cabal

View File

@@ -1,3 +0,0 @@
export GHCUP_INSTALL_BASE_PREFIX="$CI_PROJECT_DIR"
export PATH="$CI_PROJECT_DIR/.ghcup/bin:$CI_PROJECT_DIR/.local/bin:$PATH"

View File

@@ -1,75 +0,0 @@
#!/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 -fcurl
else
ecabal build
fi
cp "$(ecabal new-exec --enable-tests --verbose=0 --offline sh -- -c 'command -v ghcup')" .
cp "$(ecabal new-exec --enable-tests --verbose=0 --offline sh -- -c 'command -v ghcup-gen')" .
# testing
cp ./ghcup "$CI_PROJECT_DIR"/.local/bin/ghcup
cp ./ghcup-gen "$CI_PROJECT_DIR"/.local/bin/ghcup-gen
rm -rf "${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup
ghcup-gen check -f ghcup-${JSON_VERSION}.json
eghcup numeric-version
eghcup install ${GHC_VERSION}
eghcup set ${GHC_VERSION}
eghcup install-cabal
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

View File

@@ -1,25 +0,0 @@
jobs:
include:
- os: osx
osx_image: xcode10.1
language: generic
env: ARTIFACT=x86_64-apple-darwin-10.13-ghcup
- os: osx
osx_image: xcode11.3
language: generic
env: ARTIFACT=x86_64-apple-darwin-10.14-ghcup
script: ".travis/build.sh"
deploy:
provider: releases
api_key:
secure: GQESg4TcYf3PQJRRaZV/kWS0hsF+OFnH2+EcwpgnIcfx4+aogMyprdh745KtBXe1FlFN1luKHksFjqceqhcg/xcNyeCJiSnLWMn4D/i4WUperEHseRBi5yZZCB1AvOjIlHrE4DS3a8pyEm1GV3G7CKY5Fu8jBjof2SnyENfd7fofhjtNHWmeFS+jBn8HRDf1YaSRYxzTw6uHLrPLsybfgQZVl7babMu/38Ghin0f5pz5OlNokzDxaubIYQHOZ7st7YndHJtBWWql/KualBWbMILy88dUVQBnbqQLP2P8d1ME8ILUjJVqz33HiRU0JzlEJyWfbvEjcJ6iD8M6n4nXTaxfu3i2UhhGsQ6SSBNKssMP4tji8nkNpMqG59wLQ/zhcetEm71fKkgJNrIMNllkqlWSo5K74IqqP9kiLg/qm8ipOJjui0gPk8tZXKcV+ztX1d1OVCapoLfiDM5l/0LLQXaTOXOV1x3e5LLQ/w2doNiH3eh5CV4II9dRu7owpaiiMBHMssmT0pH99jEeF6giHLKtt3y7l2GWoRLPdhsZZ54gxsaBxZt9GuypmkbNcr97CEnAVaWij5v0CF3w4rAWqy/tAxQpIDJOIOQBgmwG5WrBAKyKrFvEpBL5a8BPcRWJDvqKC83QeWpvPrEVdgJevC6ZN1MKzrb2SiPOwC2Kerc=
file: $ARTIFACT
on:
repo: haskell/ghcup-hs
tags: true
skip_cleanup: true
draft: true

View File

@@ -1,22 +0,0 @@
#/bin/sh
set -ex
## install ghc via old ghcup
mkdir -p ~/.ghcup/bin
curl https://gitlab.haskell.org/haskell/ghcup/raw/master/ghcup > ~/.ghcup/bin/ghcup
chmod +x ~/.ghcup/bin/ghcup
export PATH="$HOME/.ghcup/bin:$PATH"
ghcup install 8.8.3
ghcup install-cabal 3.2.0.0
ghcup set 8.8.3
## install ghcup
cabal update
cabal build -fcurl
cp "$(cabal new-exec --verbose=0 --offline sh -- -c 'command -v ghcup')" "./${ARTIFACT}"

View File

@@ -1,24 +1,5 @@
# Revision history for ghcup # Revision history for ghcup
## 0.1.4 -- 2012-04-16 ## 0.1.0.0 -- YYYY-mm-dd
* 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
## 0.1.0
* First version. Released on an unsuspecting world. * First version. Released on an unsuspecting world.

View File

@@ -1,42 +0,0 @@
FROM alpine:edge
# ghc and cabal
RUN apk add --no-cache \
curl \
gcc \
g++ \
gmp-dev \
ncurses-dev \
libffi-dev \
make \
xz \
tar \
perl \
\
cabal \
ghc
# utils
RUN apk add --no-cache \
bash
## Package specific
RUN apk add --no-cache \
zlib \
zlib-dev \
zlib-static \
gmp \
gmp-dev \
openssl-dev \
openssl-libs-static \
xz \
xz-dev
RUN cabal v2-update
COPY . /app
WORKDIR /app
RUN chmod +x /app/docker/build.sh

View File

@@ -1,45 +0,0 @@
# HACKING
## Design decisions
### Using [Excepts](https://hackage.haskell.org/package/haskus-utils-variant-3.0/docs/Haskus-Utils-Variant-Excepts.html) as a beefed up ExceptT
This is an open variant, similar to [plucky](https://hackage.haskell.org/package/plucky) or [oops](https://github.com/i-am-tom/oops) and allows us to combine different error types. Maybe it is too much and it's a little bit [unergonomic](https://github.com/haskus/packages/issues/32) at times. If it really hurts maintenance, it will be removed. It was more of an experiment.
### No use of filepath or directory
Filepath and directory have two fundamental problems: 1. they use String as filepath (see [AFPP](https://gitlab.haskell.org/ghc/ghc/-/wikis/proposal/abstract-file-path) as to why this is wrong) and 2. they try very hard to be cross-platform at the expense of low-level correctness. Instead, we use the [hpath](https://github.com/hasufell/hpath) libraries for file and filepath related stuff, which also gives us stronger filepath types.
### No use of haskell-TLS
I consider haskell-TLS an interesting experiment, but not a battle-tested and peer-reviewed crypto implementation. There is little to no research about what the intricacies of using haskell for low-level crypto are and how vulnerable such binaries are. Instead, we use either curl the binary (for FreeBSD and mac) or http-io-streams, which works with OpenSSL bindings.
### Optics instead of lens
They're a little safer (less Monoid weirdness with view) and have better error messages. Consider the following wit lens
```
> view (_Just . to (++ "abc")) Nothing
""
```
vs optics
```
> view (_Just % to (++ "abc")) Nothing
<interactive>:2:1: error:
• An_AffineFold cannot be used as A_Getter
• In the expression: view (_Just % to (++ "abc")) Nothing
In an equation for it: it = view (_Just % to (++ "abc")) Nothing
```
### Strict and StrictData on by default
Kazu Yamamoto [explained it in his PR](https://github.com/yesodweb/wai/pull/752#issuecomment-501531386) very well. I like to agree with him. The instances where we need non-strict behavior, we annotate it.
## Code style and formatting
1. Brittany
2. mtl-style preferred
3. no overly pointfree style

View File

@@ -25,7 +25,7 @@ Follow the instructions at [https://www.haskell.org/ghcup/](https://www.haskell.
### Manual install ### Manual install
Download the binary for your platform at [https://downloads.haskell.org/~ghcup/](https://downloads.haskell.org/~ghcup/) Download the binary for your platform at [https://github.com/hasufell/ghcup-hs/releases](https://github.com/hasufell/ghcup-hs/releases)
and place it into your `PATH` anywhere. and place it into your `PATH` anywhere.
Then adjust your `PATH` in `~/.bashrc` (or similar, depending on your shell) like so: Then adjust your `PATH` in `~/.bashrc` (or similar, depending on your shell) like so:
@@ -45,16 +45,16 @@ Common use cases are:
ghcup list ghcup list
# install the recommended GHC version # install the recommended GHC version
ghcup install ghcup install ghc
# install a specific GHC version # install a specific GHC version
ghcup install 8.2.2 ghcup install ghc -v 8.2.2
# set the currently "active" GHC version # set the currently "active" GHC version
ghcup set 8.4.4 ghcup set -v 8.4.4
# install cabal-install # install cabal-install
ghcup install-cabal ghcup install cabal
# update ghcup itself # update ghcup itself
ghcup upgrade ghcup upgrade

View File

@@ -1,11 +0,0 @@
# RELEASING
1. update `GHCup.Version` module. `ghcupURL` must only be updated if we change the `_toolRequirements` type or the JSON representation of it. The version of the json represents the change increments. `ghcUpVer` is the current application version.
2. Add/fix downloads to `GHCupDownloads` module, then run `ghcup-gen gen` to generate the new json and validate it via `ghcup-gen check`.
3. Commit and git push with tag. Wait for tests to succeed.
4. Upload the new `ghcup-<ver>.json` to `webhost.haskell.org/ghcup/data/`.
5. Build ghcup releases for Linux (fully static), mac (with `-fcurl`) and FreeBSD (with `-fcurl`). Upload to `webhost.haskell.org/ghcup/bin/` and update symlinks.

28
TODO.md
View File

@@ -1,28 +0,0 @@
# TODOs and Remarks
## Now
* move out GHCup.Version module, bc it's not library-ish
## Maybe
* maybe: changelog Show the changelog of a GHC release (online)
* 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
* 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?

View File

@@ -832,64 +832,6 @@ ghc_883_32_musl = DownloadInfo
-----------------
--[ GHC 8.10.1 ]--
-----------------
ghc_8101_32_deb9 :: DownloadInfo
ghc_8101_32_deb9 = DownloadInfo
[uri|https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-i386-deb9-linux.tar.xz|]
(Just [rel|ghc-8.10.1|])
"8b53eef2c827b5f634d72920a93c0c9dd66ea288691a2bfe28def45d3c686ee2"
ghc_8101_64_deb9 :: DownloadInfo
ghc_8101_64_deb9 = DownloadInfo
[uri|https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-x86_64-deb9-linux.tar.xz|]
(Just [rel|ghc-8.10.1|])
"d1cf7886f27af070f3b7dbe1975a78b43ef2d32b86362cbe953e79464fe70761"
ghc_8101_64_deb10 :: DownloadInfo
ghc_8101_64_deb10 = DownloadInfo
[uri|https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-x86_64-deb10-linux.tar.xz|]
(Just [rel|ghc-8.10.1|])
"c1e31d798b013699b3c0de4fda27fb4cda47f572df0e75e3bd598a3012060615"
ghc_8101_64_fedora :: DownloadInfo
ghc_8101_64_fedora = DownloadInfo
[uri|https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-x86_64-fedora27-linux.tar.xz|]
(Just [rel|ghc-8.10.1|])
"3c4cd72b4806045779739e8f5d1658e30e57123d88c2c8966422cdbcae448470"
ghc_8101_64_centos :: DownloadInfo
ghc_8101_64_centos = DownloadInfo
[uri|https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-x86_64-centos7-linux.tar.xz|]
(Just [rel|ghc-8.10.1|])
"0618b94854edc6be5302489df905e627820b71be6b66c950f5e3088fe92df0a1"
ghc_8101_64_darwin :: DownloadInfo
ghc_8101_64_darwin = DownloadInfo
[uri|https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-x86_64-apple-darwin.tar.xz|]
(Just [rel|ghc-8.10.1|])
"65b1ca361093de4804a7e40b3e68178e1ef720f84f743641ec8d95e56a45b3a8"
ghc_8101_64_alpine :: DownloadInfo
ghc_8101_64_alpine = DownloadInfo
[uri|https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-x86_64-alpine3.10-linux-integer-simple.tar.xz|]
(Just [rel|ghc-8.10.1|])
"cb13b645d103e2fba2eb8dfcc4e5f2fbd9550c00c4df42f342b4210436dcb8a8"
--------------------- ---------------------
--[ Cabal-2.4.1.0 ]-- --[ Cabal-2.4.1.0 ]--
--------------------- ---------------------
@@ -953,64 +895,16 @@ cabal_3000_64_darwin = DownloadInfo
---------------------
--[ Cabal-3.2.0.0 ]--
---------------------
cabal_3200_32_linux :: DownloadInfo
cabal_3200_32_linux = DownloadInfo
[uri|https://downloads.haskell.org/cabal/cabal-install-3.2.0.0/cabal-install-3.2.0.0-i386-unknown-linux.tar.xz|]
Nothing
"2b3ac28549916de5f3379241797eaf60e84b6c001f2abbe73d9fadbbaf768e93"
cabal_3200_64_linux :: DownloadInfo
cabal_3200_64_linux = DownloadInfo
[uri|https://downloads.haskell.org/~cabal/cabal-install-3.2.0.0/cabal-install-3.2.0.0-x86_64-unknown-linux.tar.xz|]
Nothing
"32d1f7cf1065c37cb0ef99a66adb405f409b9763f14c0926f5424ae408c738ac"
cabal_3200_64_darwin :: DownloadInfo
cabal_3200_64_darwin = DownloadInfo
[uri|https://downloads.haskell.org/cabal/cabal-install-3.2.0.0/cabal-install-3.2.0.0-x86_64-apple-darwin17.7.0.tar.xz|]
Nothing
"9197c17d2ece0f934f5b33e323cfcaf486e4681952687bc3d249488ce3cbe0e9"
------------- -------------
--[ GHCup ]-- --[ GHCup ]--
------------- -------------
ghcup_013_32_linux :: DownloadInfo ghcup_010_64_linux :: DownloadInfo
ghcup_013_32_linux = DownloadInfo ghcup_010_64_linux = DownloadInfo
[uri|https://downloads.haskell.org/~ghcup/0.1.3/i386-linux-ghcup-0.1.3|] [uri|file:///home/maerwald/tmp/ghcup-exe|]
Nothing Nothing
"ff76a6130d6ea869a65bed127255bfa1ddf6aa1bd690df99d872467422c08be0" "558126339252788a3d44a3f910417277c7ab656f0796b68bdc58afe73296b8cd"
ghcup_013_64_linux :: DownloadInfo
ghcup_013_64_linux = DownloadInfo
[uri|https://downloads.haskell.org/~ghcup/0.1.3/x86_64-linux-ghcup-0.1.3|]
Nothing
"873f73b65cf5e399864b81ed597a0e14fa73e0c492429cd3a85fe0fdc585a4c8"
ghcup_013_64_freebsd :: DownloadInfo
ghcup_013_64_freebsd = DownloadInfo
[uri|https://downloads.haskell.org/~ghcup/0.1.3/x86_64-portbld-freebsd-ghcup-0.1.3|]
Nothing
"2daa775d6fa307cb8123fa45ba20e2acd244cdb8cfb3f2b3c8a1aa3f3571c46f"
ghcup_013_64_darwin10_13 :: DownloadInfo
ghcup_013_64_darwin10_13 = DownloadInfo
[uri|https://downloads.haskell.org/~ghcup/0.1.3/x86_64-apple-darwin-ghcup-0.1.3|]
Nothing
"a617b06619ec6e75d50dac53f36814c3cafd4dbeebe8cea46d9cd5842c0c94a9"
@@ -1526,7 +1420,7 @@ ghcupDownloads = M.fromList
) )
, ( [vver|8.6.5|] , ( [vver|8.6.5|]
, VersionInfo , VersionInfo
[] [Recommended]
(Just $ DownloadInfo (Just $ DownloadInfo
[uri|https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-src.tar.xz|] [uri|https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-src.tar.xz|]
(Just [rel|ghc-8.6.5|]) (Just [rel|ghc-8.6.5|])
@@ -1676,7 +1570,7 @@ ghcupDownloads = M.fromList
) )
, ( [vver|8.8.3|] , ( [vver|8.8.3|]
, VersionInfo , VersionInfo
[Recommended] [Latest]
(Just $ DownloadInfo (Just $ DownloadInfo
[uri|https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-src.tar.xz|] [uri|https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-src.tar.xz|]
(Just [rel|ghc-8.8.3|]) (Just [rel|ghc-8.8.3|])
@@ -1724,71 +1618,6 @@ ghcupDownloads = M.fromList
) )
] ]
) )
, ( [vver|8.10.1|]
, VersionInfo
[Latest]
(Just $ DownloadInfo
[uri|https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-src.tar.xz|]
(Just [rel|ghc-8.10.1|])
"4e3b07f83a266b3198310f19f71e371ebce97c769b14f0d688f4cbf2a2a1edf5"
)
$ M.fromList
[ ( A_64
, M.fromList
[ ( Linux UnknownLinux
, M.fromList [(Nothing, ghc_8101_64_fedora)]
)
, ( Linux Fedora
, M.fromList
[ (Nothing , ghc_8101_64_fedora)
, (Just [vers|27|], ghc_8101_64_fedora)
]
)
, ( Linux CentOS
, M.fromList
[ (Nothing , ghc_8101_64_centos)
, (Just [vers|7|], ghc_8101_64_centos)
]
)
, ( Linux AmazonLinux
, M.fromList [(Nothing, ghc_8101_64_centos)]
)
, ( Linux Ubuntu
, M.fromList
[ (Nothing , ghc_8101_64_fedora)
, (Just [vers|16.04|], ghc_8101_64_deb9)
, (Just [vers|18.04|], ghc_8101_64_deb9)
]
)
, (Linux Mint, M.fromList [(Nothing, ghc_8101_64_deb10)])
, ( Linux Debian
, M.fromList
[ (Nothing , ghc_8101_64_deb9)
, (Just [vers|9|] , ghc_8101_64_deb9)
, (Just [vers|10|], ghc_8101_64_deb10)
]
)
, (Darwin , M.fromList [(Nothing, ghc_8101_64_darwin)])
, (Linux Alpine, M.fromList [(Nothing, ghc_8101_64_alpine)])
]
)
, ( A_32
, M.fromList
[ ( Linux UnknownLinux
, M.fromList [(Nothing, ghc_8101_32_deb9)]
)
, (Linux Ubuntu, M.fromList [(Nothing, ghc_8101_32_deb9)])
, (Linux Mint , M.fromList [(Nothing, ghc_8101_32_deb9)])
, ( Linux Debian
, M.fromList
[ (Nothing , ghc_8101_32_deb9)
, (Just [vers|9|], ghc_8101_32_deb9)
]
)
]
)
]
)
] ]
) )
, ( Cabal , ( Cabal
@@ -1823,7 +1652,7 @@ ghcupDownloads = M.fromList
) )
, ( [vver|3.0.0.0|] , ( [vver|3.0.0.0|]
, VersionInfo , VersionInfo
[] [Recommended, Latest]
(Just $ DownloadInfo (Just $ DownloadInfo
[uri|https://github.com/haskell/cabal/archive/cabal-install-v3.0.0.0.tar.gz|] [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|]) (Just [rel|cabal-cabal-install-v3.0.0.0/cabal-install|])
@@ -1847,48 +1676,15 @@ ghcupDownloads = M.fromList
) )
] ]
) )
, ( [vver|3.2.0.0|]
, VersionInfo
[Recommended, Latest]
(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|])
"77202358bdf0b481c09326268ce18880df14194c5aaa840f99510bdd1a124b75"
)
$ M.fromList
[ ( A_64
, M.fromList
[ ( Linux UnknownLinux
, M.fromList [(Nothing, cabal_3200_64_linux)]
)
, (Darwin, M.fromList [(Nothing, cabal_3200_64_darwin)])
]
)
, ( A_32
, M.fromList
[ ( Linux UnknownLinux
, M.fromList [(Nothing, cabal_3200_32_linux)]
)
]
)
]
)
] ]
) )
, ( GHCup , ( GHCup
, M.fromList , M.fromList
[ ( [vver|0.1.3|] [ ( [vver|0.0.0|]
, VersionInfo [Recommended, Latest] Nothing $ M.fromList , VersionInfo [Recommended, Latest] Nothing $ M.fromList
[ ( A_64 [ ( A_64
, M.fromList , M.fromList
[ (Linux UnknownLinux, M.fromList [(Nothing, ghcup_013_64_linux)]) [(Linux UnknownLinux, M.fromList [(Nothing, ghcup_010_64_linux)])]
, (Darwin, M.fromList [(Nothing, ghcup_013_64_darwin10_13)])
, (FreeBSD, M.fromList [(Nothing, ghcup_013_64_freebsd)])
]
)
, ( A_32
, M.fromList
[(Linux UnknownLinux, M.fromList [(Nothing, ghcup_013_32_linux)])]
) )
] ]
) )

View File

@@ -1,11 +0,0 @@
module GHCupInfo where
import GHCupDownloads
import ToolRequirements
import GHCup.Types
ghcupInfo :: GHCupInfo
ghcupInfo = GHCupInfo { _toolRequirements = toolRequirements
, _ghcupDownloads = ghcupDownloads
}

View File

@@ -1,25 +1,20 @@
{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-} {-# LANGUAGE DataKinds #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeApplications #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE DuplicateRecordFields #-}
module Main where module Main where
import GHCup.Types
import GHCup.Types.JSON ( ) import GHCup.Types.JSON ( )
import GHCup.Utils.Logger import GHCup.Utils.Logger
import GHCupInfo import GHCupDownloads
import Data.Aeson ( eitherDecode, encode ) import Data.Aeson ( eitherDecode )
import Data.Aeson.Encode.Pretty import Data.Aeson.Encode.Pretty
#if !MIN_VERSION_base(4,13,0)
import Data.Semigroup ( (<>) ) import Data.Semigroup ( (<>) )
#endif
import Options.Applicative hiding ( style ) import Options.Applicative hiding ( style )
import System.Console.Pretty import System.Console.Pretty
import System.Exit import System.Exit
@@ -62,13 +57,10 @@ outputP = fileOutput <|> stdOutput
data GenJSONOpts = GenJSONOpts data GenJSONOpts = GenJSONOpts
{ output :: Maybe Output { output :: Maybe Output
, pretty :: Bool
} }
genJSONOpts :: Parser GenJSONOpts genJSONOpts :: Parser GenJSONOpts
genJSONOpts = GenJSONOpts <$> optional outputP <*> switch genJSONOpts = GenJSONOpts <$> optional outputP
(short 'p' <> long "pretty" <> help "Make JSON output pretty (human readable)"
)
data Input data Input
@@ -138,16 +130,14 @@ main = do
customExecParser (prefs showHelpOnError) (info (opts <**> helper) idm) customExecParser (prefs showHelpOnError) (info (opts <**> helper) idm)
>>= \Options {..} -> case optCommand of >>= \Options {..} -> case optCommand of
GenJSON gopts -> do GenJSON gopts -> do
let bs True = let
encodePretty' (defConfig { confIndent = Spaces 2 }) ghcupInfo bs = encodePretty' (defConfig { confIndent = Spaces 2 })
bs False = encode ghcupInfo ghcupDownloads
case gopts of case gopts of
GenJSONOpts { output = Nothing, pretty } -> GenJSONOpts { output = Nothing } -> L.hPutStr stdout bs
L.hPutStr stdout (bs pretty) GenJSONOpts { output = Just StdOutput } -> L.hPutStr stdout bs
GenJSONOpts { output = Just StdOutput, pretty } -> GenJSONOpts { output = Just (FileOutput file) } ->
L.hPutStr stdout (bs pretty) L.writeFile file bs
GenJSONOpts { output = Just (FileOutput file), pretty } ->
L.writeFile file (bs pretty)
ValidateJSON vopts -> case vopts of ValidateJSON vopts -> case vopts of
ValidateJSONOpts { input = Nothing } -> ValidateJSONOpts { input = Nothing } ->
L.getContents >>= valAndExit validate L.getContents >>= valAndExit validate
@@ -166,8 +156,9 @@ main = do
where where
valAndExit f contents = do valAndExit f contents = do
(GHCupInfo _ av) <- case eitherDecode contents of av <- case eitherDecode contents of
Right r -> pure r Right r -> pure r
Left e -> die (color Red $ show e) Left e -> die (color Red $ show e)
myLoggerT (LoggerConfig True (B.hPut stdout) (\_ -> pure ())) (f av) myLoggerT (LoggerConfig True (B.hPut stdout) (\_ -> pure ())) (f av)
>>= exitWith >>= exitWith

View File

@@ -1,94 +0,0 @@
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
module ToolRequirements where
import GHCup.Types
import GHCup.Utils.String.QQ
import qualified Data.Map as M
-- | Currently 'GHC' is used for both GHC and cabal to simplify
-- this, until we need actual separation.
toolRequirements :: ToolRequirements
toolRequirements = M.fromList
[ ( GHC
, M.fromList
[ ( Nothing
, M.fromList
[ ( Linux UnknownLinux
, M.fromList
[ ( Nothing
, Requirements
[]
[s|You need the following packages: curl g++ gcc gmp make ncurses realpath xz-utils. Consult your distro documentation on the exact names of those packages.|]
)
]
)
, ( Linux Alpine
, M.fromList
[ ( Nothing
, Requirements
[ "curl"
, "gcc"
, "g++"
, "gmp-dev"
, "ncurses-dev"
, "libffi-dev"
, "make"
, "xz"
, "tar"
, "perl"
]
""
)
]
)
, ( Linux Ubuntu
, M.fromList
[ ( Nothing
, Requirements
[ "build-essential"
, "curl"
, "libgmp-dev"
, "libffi-dev"
, "libncurses-dev"
, "libtinfo5"
]
""
)
]
)
, ( Darwin
, M.fromList
[ ( Nothing
, Requirements
[]
"On OS X, in the course of running ghcup you will be given a dialog box to install the command line tools. Accept and the requirements will be installed for you. You will then need to run the command again."
)
]
)
, ( FreeBSD
, M.fromList
[ ( Nothing
, Requirements
[ "curl"
, "gcc"
, "gmp"
, "gmake"
, "ncurses"
, "perl5"
, "libffi"
, "libiconv"
]
""
)
]
)
]
)
]
)
]

View File

@@ -1,4 +1,3 @@
{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-} {-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeApplications #-}
{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE OverloadedStrings #-}
@@ -13,17 +12,13 @@ module Main where
import GHCup import GHCup
import GHCup.Download import GHCup.Download
import GHCup.Errors import GHCup.Errors
import GHCup.Platform
import GHCup.Requirements
import GHCup.Types import GHCup.Types
import GHCup.Utils import GHCup.Utils
import GHCup.Utils.Logger import GHCup.Utils.Logger
import GHCup.Utils.Prelude import GHCup.Utils.Prelude
import GHCup.Version import GHCup.Version
#if !MIN_VERSION_base(4,13,0)
import Control.Monad.Fail ( MonadFail ) import Control.Monad.Fail ( MonadFail )
#endif
import Control.Monad.Logger import Control.Monad.Logger
import Control.Monad.Reader import Control.Monad.Reader
import Control.Monad.Trans.Resource import Control.Monad.Trans.Resource
@@ -32,6 +27,7 @@ import Data.Char
import Data.Either import Data.Either
import Data.Functor import Data.Functor
import Data.List ( intercalate ) import Data.List ( intercalate )
import Data.Semigroup ( (<>) )
import Data.String.Interpolate import Data.String.Interpolate
import Data.Text ( Text ) import Data.Text ( Text )
import Data.Versions import Data.Versions
@@ -73,21 +69,22 @@ data Options = Options
} }
data Command data Command
= Install InstallOptions = Install InstallCommand
| InstallCabal InstallOptions
| SetGHC SetGHCOptions | SetGHC SetGHCOptions
| List ListOptions | List ListOptions
| Rm RmOptions | Rm RmOptions
| DInfo | DInfo
| Compile CompileCommand | Compile CompileCommand
| Upgrade UpgradeOpts Bool | Upgrade UpgradeOpts
| NumericVersion | NumericVersion
| ToolRequirements
data ToolVersion = ToolVersion Version data ToolVersion = ToolVersion Version
| ToolTag Tag | ToolTag Tag
data InstallCommand = InstallGHC InstallOptions
| InstallCabal InstallOptions
data InstallOptions = InstallOptions data InstallOptions = InstallOptions
{ instVer :: Maybe ToolVersion { instVer :: Maybe ToolVersion
, instPlatform :: Maybe PlatformRequest , instPlatform :: Maybe PlatformRequest
@@ -113,10 +110,9 @@ data CompileCommand = CompileGHC CompileOptions
data CompileOptions = CompileOptions data CompileOptions = CompileOptions
{ targetVer :: Version { targetVer :: Version
, bootstrapGhc :: Either Version (Path Abs) , bootstrapVer :: Version
, jobs :: Maybe Int , jobs :: Maybe Int
, buildConfig :: Maybe (Path Abs) , buildConfig :: Maybe (Path Abs)
, patchDir :: Maybe (Path Abs)
} }
data UpgradeOpts = UpgradeInplace data UpgradeOpts = UpgradeInplace
@@ -130,11 +126,11 @@ opts =
Options Options
<$> switch <$> switch
(short 'v' <> long "verbose" <> help (short 'v' <> long "verbose" <> help
"Enable verbosity" "Whether to enable verbosity (default: False)"
) )
<*> switch <*> switch
(short 'c' <> long "cache" <> help (short 'c' <> long "cache" <> help
"Cache downloads in ~/.ghcup/cache" "Whether to cache downloads (default: False)"
) )
<*> (optional <*> (optional
(option (option
@@ -149,7 +145,7 @@ opts =
) )
<*> switch <*> switch
(short 'n' <> long "no-verify" <> help (short 'n' <> long "no-verify" <> help
"Skip tarball checksum verification" "Skip tarball checksum verification (default: False)"
) )
<*> com <*> com
where where
@@ -162,29 +158,11 @@ com =
subparser subparser
( command ( command
"install" "install"
((info ((Install <$> installOpts) <**> helper) ( Install
(progDesc "Install or update GHC") <$> (info (installP <**> helper)
) (progDesc "Install or update GHC/cabal")
)
) )
<> command
"set"
( SetGHC
<$> (info (setGHCOpts <**> helper)
(progDesc "Set currently active GHC version")
)
)
<> command
"rm"
( Rm
<$> (info (rmOpts <**> helper) (progDesc "Remove a GHC version"))
)
<> command
"install-cabal"
((info ((InstallCabal <$> installOpts) <**> helper)
(progDesc "Install or update cabal")
)
)
<> command <> command
"list" "list"
( List ( List
@@ -194,12 +172,12 @@ com =
) )
<> command <> command
"upgrade" "upgrade"
(info ((Upgrade <$> upgradeOptsP <*> ( Upgrade
switch <$> (info
(short 'f' <> long "force" <> help (upgradeOptsP <**> helper)
"Force update" (progDesc "Upgrade ghcup (per default in ~/.ghcup/bin/)")
) )
) <**> helper) (progDesc "Upgrade ghcup")) )
<> command <> command
"compile" "compile"
( Compile ( Compile
@@ -209,6 +187,25 @@ com =
) )
<> commandGroup "Main commands:" <> commandGroup "Main commands:"
) )
<|> subparser
( command
"set"
( SetGHC
<$> (info (setGHCOpts <**> helper)
(progDesc "Set the currently active GHC version")
)
)
<> command
"rm"
( Rm
<$> (info
(rmOpts <**> helper)
(progDesc "Remove a GHC version installed by ghcup")
)
)
<> commandGroup "GHC commands:"
<> hidden
)
<|> subparser <|> subparser
( command ( command
"debug-info" "debug-info"
@@ -218,22 +215,32 @@ com =
( (\_ -> NumericVersion) ( (\_ -> NumericVersion)
<$> (info (helper) (progDesc "Show the numeric version")) <$> (info (helper) (progDesc "Show the numeric version"))
) )
<> command
"tool-requirements"
( (\_ -> ToolRequirements)
<$> (info (helper)
(progDesc "Show the requirements for ghc/cabal")
)
)
<> commandGroup "Other commands:" <> commandGroup "Other commands:"
<> hidden <> hidden
) )
installP :: Parser InstallCommand
installP = subparser
( command
"ghc"
( InstallGHC
<$> (info (installOpts <**> helper) (progDesc "Install a GHC version"))
)
<> command
"cabal"
( InstallCabal
<$> (info (installOpts <**> helper)
(progDesc "Install or update a Cabal version")
)
)
)
installOpts :: Parser InstallOptions installOpts :: Parser InstallOptions
installOpts = installOpts =
(flip InstallOptions) InstallOptions
<$> (optional <$> optional toolVersionParser
<*> (optional
(option (option
(eitherReader platformParser) (eitherReader platformParser)
( short 'p' ( short 'p'
@@ -244,11 +251,10 @@ installOpts =
) )
) )
) )
<*> optional toolVersionArgument
setGHCOpts :: Parser SetGHCOptions setGHCOpts :: Parser SetGHCOptions
setGHCOpts = SetGHCOptions <$> optional toolVersionArgument setGHCOpts = SetGHCOptions <$> optional toolVersionParser
listOpts :: Parser ListOptions listOpts :: Parser ListOptions
listOpts = listOpts =
@@ -272,7 +278,7 @@ listOpts =
) )
rmOpts :: Parser RmOptions rmOpts :: Parser RmOptions
rmOpts = RmOptions <$> versionArgument rmOpts = RmOptions <$> versionParser
compileP :: Parser CompileCommand compileP :: Parser CompileCommand
@@ -306,16 +312,12 @@ compileOpts =
) )
<*> (option <*> (option
(eitherReader (eitherReader
(\x -> (bimap (const "Not a valid version") id . version . T.pack)
(bimap (const "Not a valid version") Left . version . T.pack $ x)
<|> (bimap show Right . parseAbs . E.encodeUtf8 . T.pack $ x)
)
) )
( short 'b' ( short 'b'
<> long "bootstrap-ghc" <> long "bootstrap-version"
<> metavar "BOOTSTRAP_GHC" <> metavar "BOOTSTRAP_VERSION"
<> help <> help "The GHC version to bootstrap with (must be installed)"
"The GHC version (or full path) to bootstrap with (must be installed)"
) )
) )
<*> optional <*> optional
@@ -338,19 +340,13 @@ compileOpts =
"Absolute path to build config file" "Absolute path to build config file"
) )
) )
<*> optional
(option
(eitherReader versionParser :: Parser Version
(\x -> versionParser = option
bimap show id . parseAbs . E.encodeUtf8 . T.pack $ x :: Either (eitherReader (bimap (const "Not a valid version") id . version . T.pack))
String (short 'v' <> long "version" <> metavar "VERSION" <> help "The target version"
(Path Abs) )
)
)
(short 'p' <> long "patchdir" <> metavar "PATCH_DIR" <> help
"Absolute path to patch directory (applied in order, uses -p1)"
)
)
toolVersionParser :: Parser ToolVersion toolVersionParser :: Parser ToolVersion
@@ -360,44 +356,16 @@ toolVersionParser = verP <|> toolP
toolP = toolP =
ToolTag ToolTag
<$> (option <$> (option
(eitherReader tagEither) (eitherReader
(\s' -> case fmap toLower s' of
"recommended" -> Right Recommended
"latest" -> Right Latest
other -> Left ([i|Unknown tag #{other}|])
)
)
(short 't' <> long "tag" <> metavar "TAG" <> help "The target tag") (short 't' <> long "tag" <> metavar "TAG" <> help "The target tag")
) )
-- | same as toolVersionParser, except as an argument.
toolVersionArgument :: Parser ToolVersion
toolVersionArgument =
argument (eitherReader toolVersionEither) (metavar "VERSION|TAG")
versionArgument :: Parser Version
versionArgument = argument
(eitherReader versionEither)
(metavar "VERSION")
versionParser :: Parser Version
versionParser = option
(eitherReader versionEither)
(short 'v' <> long "version" <> metavar "VERSION" <> help "The target version"
)
tagEither :: String -> Either String Tag
tagEither s' = case fmap toLower s' of
"recommended" -> Right Recommended
"latest" -> Right Latest
other -> Left ([i|Unknown tag #{other}|])
versionEither :: String -> Either String Version
versionEither s' =
-- 'version' is a bit too lax and will parse typoed tags
case readMaybe ((:[]) . head $ s') :: Maybe Int of
Just _ -> bimap (const "Not a valid version") id . version . T.pack $ s'
Nothing -> Left "Not a valid version"
toolVersionEither :: String -> Either String ToolVersion
toolVersionEither s' =
bimap id ToolTag (tagEither s') <|> bimap id ToolVersion (versionEither s')
toolParser :: String -> Either String Tool toolParser :: String -> Either String Tool
toolParser s' | t == T.pack "ghc" = Right GHC toolParser s' | t == T.pack "ghc" = Right GHC
@@ -592,15 +560,10 @@ main = do
@'[ AlreadyInstalled @'[ AlreadyInstalled
, BuildFailed , BuildFailed
, DigestError , DigestError
, DistroNotFound
, DownloadFailed
, GHCupSetError , GHCupSetError
, NoCompatibleArch
, NoCompatiblePlatform
, NoDownload , NoDownload
, NotFoundInPATH
, PatchFailed
, UnknownArchive , UnknownArchive
, DownloadFailed
] ]
let runCompileCabal = let runCompileCabal =
@@ -608,15 +571,11 @@ main = do
. flip runReaderT settings . flip runReaderT settings
. runResourceT . runResourceT
. runE . runE
@'[ BuildFailed @'[ UnknownArchive
, DigestError
, DistroNotFound
, DownloadFailed
, NoCompatibleArch
, NoCompatiblePlatform
, NoDownload , NoDownload
, PatchFailed , DigestError
, UnknownArchive , BuildFailed
, DownloadFailed
] ]
let runUpgrade = let runUpgrade =
@@ -629,13 +588,12 @@ main = do
, NoCompatiblePlatform , NoCompatiblePlatform
, NoCompatibleArch , NoCompatibleArch
, NoDownload , NoDownload
, NoUpdate
, FileDoesNotExistError , FileDoesNotExistError
, CopyError , CopyError
, DownloadFailed , DownloadFailed
] ]
(GHCupInfo treq dls) <- dls <-
( runLogger ( runLogger
. flip runReaderT settings . flip runReaderT settings
. runE @'[JSONError , DownloadFailed] . runE @'[JSONError , DownloadFailed]
@@ -651,7 +609,7 @@ main = do
runLogger $ checkForUpdates dls runLogger $ checkForUpdates dls
case optCommand of case optCommand of
Install (InstallOptions {..}) -> Install (InstallGHC InstallOptions {..}) ->
void void
$ (runInstTool $ do $ (runInstTool $ do
v <- liftE $ fromVersion dls instVer GHC v <- liftE $ fromVersion dls instVer GHC
@@ -674,7 +632,7 @@ Check the logs at ~/.ghcup/logs and the build directory #{tmpdir} for more clues
$(logError) [i|#{e}|] $(logError) [i|#{e}|]
$(logError) [i|Also check the logs in ~/.ghcup/logs|] $(logError) [i|Also check the logs in ~/.ghcup/logs|]
exitFailure exitFailure
InstallCabal (InstallOptions {..}) -> Install (InstallCabal InstallOptions {..}) ->
void void
$ (runInstTool $ do $ (runInstTool $ do
v <- liftE $ fromVersion dls instVer Cabal v <- liftE $ fromVersion dls instVer Cabal
@@ -699,8 +657,8 @@ Check the logs at ~/.ghcup/logs and the build directory #{tmpdir} for more clues
liftE $ setGHC v SetGHCOnly liftE $ setGHC v SetGHCOnly
) )
>>= \case >>= \case
VRight v -> VRight _ ->
runLogger $ $(logInfo) [i|GHC #{prettyVer v} successfully set as default version|] runLogger $ $(logInfo) ("GHC successfully set")
VLeft e -> VLeft e ->
runLogger ($(logError) [i|#{e}|]) >> exitFailure runLogger ($(logError) [i|#{e}|]) >> exitFailure
@@ -738,7 +696,7 @@ Check the logs at ~/.ghcup/logs and the build directory #{tmpdir} for more clues
void void
$ (runCompileGHC $ do $ (runCompileGHC $ do
liftE liftE
$ compileGHC dls targetVer bootstrapGhc jobs buildConfig patchDir $ compileGHC dls targetVer bootstrapVer jobs buildConfig
) )
>>= \case >>= \case
VRight _ -> VRight _ ->
@@ -759,7 +717,7 @@ Check the logs at ~/.ghcup/logs and the build directory #{tmpdir} for more clues
Compile (CompileCabal CompileOptions {..}) -> Compile (CompileCabal CompileOptions {..}) ->
void void
$ (runCompileCabal $ do $ (runCompileCabal $ do
liftE $ compileCabal dls targetVer bootstrapGhc jobs patchDir liftE $ compileCabal dls targetVer bootstrapVer jobs
) )
>>= \case >>= \case
VRight _ -> VRight _ ->
@@ -774,7 +732,7 @@ Check the logs at ~/.ghcup/logs and the build directory #{tmpdir} for more clues
VLeft e -> VLeft e ->
runLogger ($(logError) [i|#{e}|]) >> exitFailure runLogger ($(logError) [i|#{e}|]) >> exitFailure
Upgrade (uOpts) force -> do Upgrade (uOpts) -> do
target <- case uOpts of target <- case uOpts of
UpgradeInplace -> do UpgradeInplace -> do
efp <- liftIO $ getExecutablePath efp <- liftIO $ getExecutablePath
@@ -787,7 +745,7 @@ Check the logs at ~/.ghcup/logs and the build directory #{tmpdir} for more clues
void void
$ (runUpgrade $ do $ (runUpgrade $ do
liftE $ upgradeGHCup dls target force liftE $ upgradeGHCup dls target
) )
>>= \case >>= \case
VRight v' -> do VRight v' -> do
@@ -795,28 +753,10 @@ Check the logs at ~/.ghcup/logs and the build directory #{tmpdir} for more clues
runLogger runLogger
$ $(logInfo) $ $(logInfo)
[i|Successfully upgraded GHCup to version #{pretty_v}|] [i|Successfully upgraded GHCup to version #{pretty_v}|]
VLeft (V NoUpdate) ->
runLogger $ $(logWarn)
[i|No GHCup update available|]
VLeft e -> VLeft e ->
runLogger ($(logError) [i|#{e}|]) >> exitFailure runLogger ($(logError) [i|#{e}|]) >> exitFailure
NumericVersion -> T.hPutStr stdout (prettyPVP ghcUpVer) NumericVersion -> T.hPutStr stdout (prettyPVP ghcUpVer)
ToolRequirements -> (runLogger $ runE
@'[ NoCompatiblePlatform
, DistroNotFound
, NoToolRequirements
] $ do
platform <- liftE $ getPlatform
req <- (getCommonRequirements platform $ treq)
?? NoToolRequirements
liftIO $ T.hPutStr stdout (prettyRequirements req))
>>= \case
VRight r -> pure r
VLeft e ->
runLogger
($(logError) [i|Error getting tool requirements: #{e}|])
>> exitFailure
pure () pure ()

View File

@@ -1,202 +0,0 @@
#!/bin/sh
# safety subshell to avoid executing anything in case this script is not downloaded properly
(
: "${GHCUP_INSTALL_BASE_PREFIX:=$HOME}"
die() {
(>&2 printf "\\033[0;31m%s\\033[0m\\n" "$1")
exit 2
}
edo()
{
"$@" || die "\"$*\" failed!"
}
eghcup() {
if [ -z "${BOOTSTRAP_HASKELL_VERBOSE}" ] ; then
edo ghcup "$@"
else
edo ghcup --verbose "$@"
fi
}
download_ghcup() {
_plat="$(uname -s)"
_arch=$(uname -m)
case "${_plat}" in
"linux"|"Linux")
case "${_arch}" in
x86_64|amd64)
_url=https://downloads.haskell.org/~ghcup/0.1.3/x86_64-linux-ghcup-0.1.3
;;
i*86)
_url=https://downloads.haskell.org/~ghcup/0.1.3/i386-linux-ghcup-0.1.3
;;
*) die "Unknown architecture: ${_arch}"
;;
esac
;;
"FreeBSD"|"freebsd")
case "${_arch}" in
x86_64|amd64)
;;
i*86)
die "i386 currently not supported!"
;;
*) die "Unknown architecture: ${_arch}"
;;
esac
_url=https://downloads.haskell.org/~ghcup/0.1.3/x86_64-portbld-freebsd-ghcup-0.1.3
;;
"Darwin"|"darwin")
case "${_arch}" in
x86_64|amd64)
;;
i*86)
die "i386 currently not supported!"
;;
*) die "Unknown architecture: ${_arch}"
;;
esac
_url=https://downloads.haskell.org/~ghcup/0.1.3/x86_64-apple-darwin-ghcup-0.1.3 ;;
*) die "Unknown platform: ${_plat}"
;;
esac
edo curl -Lf "${_url}" > "${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup/bin/ghcup
unset _plat _arch _url
}
echo
echo "Welcome to Haskell!"
echo
echo "This will download and install the Glasgow Haskell Compiler (GHC)"
echo "and the Cabal build tool."
echo
echo "ghcup installs only into the following directory, which can be removed anytime:"
echo " $GHCUP_INSTALL_BASE_PREFIX/.ghcup"
echo
if [ -z "${BOOTSTRAP_HASKELL_NONINTERACTIVE}" ] ; then
printf "\\033[0;35m%s\\033[0m\\n" "Press ENTER to proceed"
printf "\\033[0;35m%s\\033[0m\\n" "or ctrl-c to abort."
printf "\\033[0;35m%s\\033[0m\\n" "Note that this script can be re-run at any given time."
echo
# Wait for user input to continue.
# shellcheck disable=SC2034
read -r answer </dev/tty
fi
edo mkdir -p "${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup/bin
if command -V "ghcup" >/dev/null 2>&1 ; then
if [ -z "${BOOTSTRAP_HASKELL_NO_UPGRADE}" ] ; then
eghcup upgrade
fi
else
download_ghcup
edo chmod +x "${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup/bin/ghcup
cat <<-EOF > "${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup/env || die "Failed to create env file"
export PATH="\$HOME/.cabal/bin:\${GHCUP_INSTALL_BASE_PREFIX:=\$HOME}/.ghcup/bin:\$PATH"
EOF
# shellcheck disable=SC1090
edo . "${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup/env
eghcup upgrade
fi
echo
echo "$(ghcup tool-requirements)"
echo
if [ -z "${BOOTSTRAP_HASKELL_NONINTERACTIVE}" ] ; then
printf "\\033[0;35m%s\\033[0m\\n" "Press ENTER to proceed"
printf "\\033[0;35m%s\\033[0m\\n" "or ctrl-c to abort."
printf "\\033[0;35m%s\\033[0m\\n" "Installation may take a while."
echo
# Wait for user input to continue.
# shellcheck disable=SC2034
read -r answer </dev/tty
fi
eghcup --cache install
eghcup set
eghcup --cache install-cabal
edo cabal new-update
printf "\\033[0;35m%s\\033[0m\\n" ""
printf "\\033[0;35m%s\\033[0m\\n" "Installation done!"
printf "\\033[0;35m%s\\033[0m\\n" ""
if [ -z "${BOOTSTRAP_HASKELL_NONINTERACTIVE}" ] ; then
echo "In order to run ghc and cabal, you need to adjust your PATH variable."
echo "You may want to source '$GHCUP_INSTALL_BASE_PREFIX/.ghcup/env' in your shell"
echo "configuration to do so (e.g. ~/.bashrc)."
case $SHELL in
*/zsh) # login shell is zsh
GHCUP_PROFILE_FILE="$HOME/.zshrc"
MY_SHELL="zsh" ;;
*/bash) # login shell is bash
if [ -f "$HOME/.bashrc" ] ; then # bashrc is not sourced by default, so assume it isn't if file does not exist
GHCUP_PROFILE_FILE="$HOME/.bashrc"
else
GHCUP_PROFILE_FILE="$HOME/.bash_profile"
fi
MY_SHELL="bash" ;;
*/sh) # login shell is sh, but might be a symlink to bash or zsh
if [ -n "${BASH}" ] ; then
if [ -f "$HOME/.bashrc" ] ; then # bashrc is not sourced by default, so assume it isn't if file does not exist
GHCUP_PROFILE_FILE="$HOME/.bashrc"
else
GHCUP_PROFILE_FILE="$HOME/.bash_profile"
fi
MY_SHELL="bash"
elif [ -n "${ZSH_VERSION}" ] ; then
GHCUP_PROFILE_FILE="$HOME/.zshrc"
MY_SHELL="zsh"
else
exit 0
fi
;;
*) exit 0 ;;
esac
printf "\\033[0;35m%s\\033[0m\\n" ""
printf "\\033[0;35m%s\\033[0m\\n" "Detected ${MY_SHELL} shell on your system..."
printf "\\033[0;35m%s\\033[0m\\n" "If you want ghcup to automatically add the required PATH variable to \"${GHCUP_PROFILE_FILE}\""
printf "\\033[0;35m%s\\033[0m\\n" "answer with YES, otherwise with NO and press ENTER."
printf "\\033[0;35m%s\\033[0m\\n" ""
while true; do
read -r next_answer </dev/tty
case $next_answer in
[Yy]*)
echo "[ -f \"\${GHCUP_INSTALL_BASE_PREFIX:=\$HOME}/.ghcup/env\" ] && source \"\${GHCUP_INSTALL_BASE_PREFIX:=\$HOME}/.ghcup/env\"" >> "${GHCUP_PROFILE_FILE}"
printf "\\033[0;35m%s\\033[0m\\n" "OK! ${GHCUP_PROFILE_FILE} has been modified. Restart your terminal for the changes to take effect,"
printf "\\033[0;35m%s\\033[0m\\n" "or type \"source ${GHCUP_INSTALL_BASE_PREFIX}/.ghcup/env\" to apply them in your current terminal session."
exit 0;;
[Nn]*)
exit 0;;
*)
echo "Please type YES or NO and press enter.";;
esac
done
fi
)
# vim: tabstop=4 shiftwidth=4 expandtab

View File

@@ -1,5 +1,7 @@
packages: ./ghcup.cabal packages: ./ghcup.cabal
with-compiler: ghc-8.6.5
optimization: 2 optimization: 2
package streamly package streamly
@@ -13,4 +15,4 @@ package tar-bytestring
constraints: http-io-streams -brotli constraints: http-io-streams -brotli
allow-newer: base index-state: 2020-03-09T18:53:34Z

258
cabal.project.freeze Normal file
View File

@@ -0,0 +1,258 @@
constraints: any.Cabal ==2.4.0.1,
any.Glob ==0.10.0,
any.HsOpenSSL ==0.11.4.17,
HsOpenSSL -fast-bignum -homebrew-openssl -macports-openssl -old-locale,
any.IfElse ==0.85,
any.Only ==0.1,
any.QuickCheck ==2.13.2,
QuickCheck +templatehaskell,
any.StateVar ==1.2,
any.abstract-deque ==0.3,
abstract-deque -usecas,
any.abstract-par ==0.3.3,
any.aeson ==1.4.6.0,
aeson -bytestring-builder -cffi -developer -fast,
any.aeson-pretty ==0.8.8,
aeson-pretty -lib-only,
any.ansi-terminal ==0.10.3,
ansi-terminal -example,
any.ansi-wl-pprint ==0.6.9,
ansi-wl-pprint -example,
any.array ==0.5.3.0,
any.ascii-string ==1.0.1.4,
any.assoc ==1.0.1,
any.async ==2.2.2,
async -bench,
any.atomic-primops ==0.8.3,
atomic-primops -debug,
any.attoparsec ==0.13.2.3,
attoparsec -developer,
any.auto-update ==0.1.6,
any.base ==4.12.0.0,
any.base-compat ==0.11.1,
any.base-compat-batteries ==0.11.1,
any.base-orphans ==0.8.2,
any.base-prelude ==1.3,
any.base16-bytestring ==0.1.1.6,
any.base64-bytestring ==1.0.0.3,
any.bifunctors ==5.5.7,
bifunctors +semigroups +tagged,
any.binary ==0.8.6.0,
any.binary-orphans ==1.0.1,
any.blaze-builder ==0.4.1.0,
any.bytestring ==0.10.8.2,
any.bytestring-builder ==0.10.8.2.0,
bytestring-builder +bytestring_has_builder,
any.bytestring-handle ==0.1.0.6,
any.bzlib ==0.5.0.5,
any.cabal-doctest ==1.0.8,
any.case-insensitive ==1.2.1.0,
any.cassava ==0.5.2.0,
cassava -bytestring--lt-0_10_4,
any.cereal ==0.5.8.1,
cereal -bytestring-builder,
any.clock ==0.8,
clock -llvm,
any.cmdargs ==0.10.20,
cmdargs +quotation -testprog,
any.code-page ==0.2,
any.colour ==2.3.5,
any.comonad ==5.0.6,
comonad +containers +distributive +test-doctests,
any.conduit ==1.3.1.2,
any.conduit-extra ==1.3.4,
any.containers ==0.6.0.1,
any.contravariant ==1.5.2,
contravariant +semigroups +statevar +tagged,
any.criterion ==1.5.6.2,
criterion -embed-data-files -fast,
any.criterion-measurement ==0.1.2.0,
criterion-measurement -fast,
any.data-default-class ==0.1.2.0,
any.data-default-instances-base ==0.1.0.1,
any.deepseq ==1.4.4.0,
any.deferred-folds ==0.9.10.1,
any.dense-linear-algebra ==0.1.0.0,
any.directory ==1.3.3.0 || ==1.3.6.0,
any.distributive ==0.6.1,
distributive +semigroups +tagged,
any.dlist ==0.8.0.7,
any.easy-file ==0.2.2,
any.errors ==2.3.0,
any.exceptions ==0.10.4,
exceptions +transformers-0-4,
any.extra ==1.7,
any.fast-logger ==3.0.1,
any.filepath ==1.4.2.1,
any.focus ==1.0.1.3,
any.foldl ==1.4.6,
any.free ==5.1.3,
any.fusion-plugin-types ==0.1.0,
any.generics-sop ==0.5.0.0,
any.ghc-boot-th ==8.6.5,
any.ghc-prim ==0.5.3,
any.happy ==1.19.12,
happy +small_base,
any.hashable ==1.3.0.0,
hashable -examples +integer-gmp +sse2 -sse41,
any.haskell-src-exts ==1.23.0,
any.haskell-src-meta ==0.8.5,
any.haskus-utils-data ==1.2,
any.haskus-utils-types ==1.5,
any.haskus-utils-variant ==3.0,
any.heaps ==0.3.6.1,
any.hopenssl ==2.2.4,
hopenssl -link-libz,
any.hpath ==0.11.0,
any.hpath-directory ==0.13.2,
any.hpath-filepath ==0.10.4,
any.hpath-io ==0.13.1,
any.hpath-posix ==0.13.1,
any.hsc2hs ==0.68.6,
hsc2hs -in-ghc-tree,
any.http-io-streams ==0.1.2.0,
http-io-streams -brotli,
any.indexed-profunctors ==0.1,
any.integer-gmp ==1.0.2.0,
any.integer-logarithms ==1.0.3,
integer-logarithms -check-bounds +integer-gmp,
any.io-streams ==1.5.1.0,
io-streams -nointeractivetests,
any.js-flot ==0.8.3,
any.js-jquery ==3.3.1,
any.language-bash ==0.9.0,
any.lifted-base ==0.2.3.12,
any.list-t ==1.0.4,
any.lockfree-queue ==0.2.3.1,
any.lzma ==0.0.0.3,
any.math-functions ==0.3.3.0,
math-functions +system-erf +system-expm1,
any.megaparsec ==8.0.0,
megaparsec -dev,
any.microstache ==1.0.1.1,
any.mmorph ==1.1.3,
any.monad-control ==1.0.2.3,
any.monad-logger ==0.3.32,
monad-logger +template_haskell,
any.monad-loops ==0.4.3,
monad-loops +base4,
any.monad-par ==0.3.5,
monad-par -chaselev -newgeneric,
any.monad-par-extras ==0.3.3,
any.mono-traversable ==1.0.15.1,
any.mtl ==2.2.2,
any.mwc-random ==0.14.0.0,
any.network ==3.1.1.1,
any.network-uri ==2.6.3.0,
any.old-locale ==1.0.0.7,
any.old-time ==1.1.0.3,
any.openssl-streams ==1.2.2.0,
any.optics ==0.2,
any.optics-core ==0.2,
any.optics-extra ==0.2,
any.optics-th ==0.2,
any.optics-vl ==0.2,
any.optparse-applicative ==0.15.1.0,
any.parallel ==3.2.2.0,
any.parsec ==3.1.13.0,
any.parser-combinators ==1.2.1,
parser-combinators -dev,
any.pretty ==1.1.3.6,
any.pretty-terminal ==0.1.0.0,
any.prettyprinter ==1.6.1,
prettyprinter -buildreadme,
any.primitive ==0.7.0.1,
any.primitive-extras ==0.8,
any.primitive-unlifted ==0.1.3.0,
any.process ==1.6.5.0 || ==1.6.8.0,
any.profunctors ==5.5.2,
any.random ==1.1,
any.recursion-schemes ==5.1.3,
recursion-schemes +template-haskell,
any.regex-base ==0.94.0.0,
any.regex-posix ==0.96.0.0,
regex-posix -_regex-posix-clib,
any.resourcet ==1.2.3,
any.rts ==1.0,
any.safe ==0.3.18,
any.safe-exceptions ==0.1.7.0,
any.scientific ==0.3.6.2,
scientific -bytestring-builder -integer-simple,
any.semigroupoids ==5.3.4,
semigroupoids +comonad +containers +contravariant +distributive +doctests +tagged +unordered-containers,
any.semigroups ==0.19.1,
semigroups +binary +bytestring -bytestring-builder +containers +deepseq +hashable +tagged +template-haskell +text +transformers +unordered-containers,
any.sop-core ==0.5.0.0,
any.split ==0.2.3.4,
any.splitmix ==0.0.4,
splitmix -optimised-mixer +random,
any.statistics ==0.15.2.0,
any.stm ==2.5.0.0,
any.stm-chans ==3.0.0.4,
any.streaming-commons ==0.2.1.2,
streaming-commons -use-bytestring-builder,
any.streamly ==0.7.1,
streamly -debug -dev -examples -examples-sdl -fusion-plugin -has-llvm -inspection -no-charts -no-fusion -streamk,
any.streamly-bytestring ==0.1.2,
any.streamly-posix ==0.1.0.0,
any.strict-base ==0.4.0.0,
any.string-interpolate ==0.2.0.0,
any.syb ==0.7.1,
any.table-layout ==0.8.0.5,
any.tagged ==0.8.6,
tagged +deepseq +transformers,
any.tar-bytestring ==0.6.3.1,
any.tasty ==1.2.3,
tasty +clock,
any.tasty-quickcheck ==0.10.1.1,
any.template-haskell ==2.14.0.0,
any.terminal-progress-bar ==0.4.1,
any.terminal-size ==0.3.2.1,
any.text ==1.2.3.1,
any.text-conversions ==0.3.0,
any.text-short ==0.1.3,
text-short -asserts,
any.th-abstraction ==0.3.2.0,
any.th-expand-syns ==0.4.5.0,
any.th-lift ==0.8.1,
any.th-lift-instances ==0.1.14,
any.th-orphans ==0.13.9,
any.th-reify-many ==0.1.9,
any.these ==1.0.1,
these +aeson +assoc +quickcheck +semigroupoids,
any.time ==1.8.0.2 || ==1.9.3,
any.time-compat ==1.9.2.2,
time-compat -old-locale,
any.transformers ==0.5.6.2,
any.transformers-base ==0.4.5.2,
transformers-base +orphaninstances,
any.transformers-compat ==0.6.5,
transformers-compat -five +five-three -four +generic-deriving +mtl -three -two,
any.typed-process ==0.2.6.0,
any.unbounded-delays ==0.1.1.0,
any.unix ==2.7.2.2,
any.unix-bytestring ==0.3.7.3,
any.unix-compat ==0.5.2,
unix-compat -old-time,
any.unix-time ==0.4.7,
any.unliftio-core ==0.2.0.1,
any.unordered-containers ==0.2.10.0,
unordered-containers -debug,
any.uri-bytestring ==0.3.2.2,
uri-bytestring -lib-werror,
any.utf8-string ==1.0.1.1,
any.uuid-types ==1.0.3,
any.vector ==0.12.1.2,
vector +boundschecks -internalchecks -unsafechecks -wall,
any.vector-algorithms ==0.8.0.3,
vector-algorithms +bench +boundschecks -internalchecks -llvm +properties -unsafechecks,
any.vector-binary-instances ==0.2.5.1,
any.vector-builder ==0.3.8,
any.vector-th-unbox ==0.2.1.7,
any.versions ==3.5.3,
any.wcwidth ==0.0.2,
wcwidth -cli +split-base,
any.word8 ==0.1.3,
any.zlib ==0.6.2.1,
zlib -non-blocking-ffi -pkg-config,
any.zlib-bindings ==0.1.1.5

View File

@@ -1,14 +0,0 @@
#!/bin/sh
set -ex
cd /app
cabal v2-update
cabal v2-install \
--install-method=copy \
--overwrite-policy=always \
--installdir="/bin" \
--ghc-options='-optl-static'

File diff suppressed because it is too large Load Diff

View File

@@ -1,13 +1,13 @@
cabal-version: 3.0 cabal-version: 3.0
name: ghcup name: ghcup
version: 0.1.4 version: 0.1.0.0
synopsis: ghc toolchain installer as an exe/library synopsis: ghc toolchain installer as an exe/library
description: description:
A rewrite of the shell script ghcup, for providing A rewrite of the shell script ghcup, for providing
a more stable user experience and exposing an API. a more stable user experience and exposing an API.
homepage: https://gitlab.haskell.org/haskell/ghcup-hs homepage: https://github.com/hasufell/ghcup-hs
bug-reports: https://gitlab.haskell.org/haskell/ghcup-hs/issues bug-reports: https://github.com/hasufell/ghcup-hs/issues
license: LGPL-3.0-only license: LGPL-3.0-only
license-file: LICENSE license-file: LICENSE
author: Julian Ospald author: Julian Ospald
@@ -19,15 +19,10 @@ extra-source-files: CHANGELOG.md
source-repository head source-repository head
type: git type: git
location: https://gitlab.haskell.org/haskell/ghcup-hs.git location: https://github.com/hasufell/ghcup-hs
flag Curl
description: Use curl instead of http-io-streams for download
default: False
manual: True
common HsOpenSSL common HsOpenSSL
build-depends: HsOpenSSL >=0.11.4.18 build-depends: HsOpenSSL >=0.11
common aeson common aeson
build-depends: aeson >=1.4 build-depends: aeson >=1.4
@@ -47,17 +42,14 @@ common attoparsec
common base common base
build-depends: base >=4.12 && <5 build-depends: base >=4.12 && <5
common base16-bytestring
build-depends: base16-bytestring >= 0.1.1.6
common binary common binary
build-depends: binary >=0.8.6.0 build-depends: binary >=0.8.6.0
common bytestring common bytestring
build-depends: bytestring >=0.10 build-depends: bytestring >=0.10
common bz2 common bzlib
build-depends: bz2 >=0.5.0.5 build-depends: bzlib >=0.5.0.5
common case-insensitive common case-insensitive
build-depends: case-insensitive >=1.2.1.0 build-depends: case-insensitive >=1.2.1.0
@@ -68,9 +60,6 @@ common concurrent-output
common containers common containers
build-depends: containers >=0.6 build-depends: containers >=0.6
common cryptohash-sha256
build-depends: cryptohash-sha256 >= 0.11.101.0
common generics-sop common generics-sop
build-depends: generics-sop >=0.5 build-depends: generics-sop >=0.5
@@ -80,11 +69,14 @@ common haskus-utils-types
common haskus-utils-variant common haskus-utils-variant
build-depends: haskus-utils-variant >=3.0 build-depends: haskus-utils-variant >=3.0
common hopenssl
build-depends: hopenssl >=2.2.4
common hpath common hpath
build-depends: hpath >=0.11 build-depends: hpath >=0.11
common hpath-directory common hpath-directory
build-depends: hpath-directory >=0.13.3 build-depends: hpath-directory >=0.13.2
common hpath-filepath common hpath-filepath
build-depends: hpath-filepath >=0.10.3 build-depends: hpath-filepath >=0.10.3
@@ -93,7 +85,7 @@ common hpath-io
build-depends: hpath-io >=0.13.1 build-depends: hpath-io >=0.13.1
common hpath-posix common hpath-posix
build-depends: hpath-posix >=0.13.2 build-depends: hpath-posix >=0.11.1
common http-io-streams common http-io-streams
build-depends: http-io-streams >=0.1.2.0 build-depends: http-io-streams >=0.1.2.0
@@ -226,26 +218,28 @@ library
import: import:
config config
, base , base
, base16-bytestring , HsOpenSSL
, aeson , aeson
, ascii-string , ascii-string
, async , async
, attoparsec , attoparsec
, binary , binary
, bytestring , bytestring
, bz2 , bzlib
, case-insensitive , case-insensitive
, concurrent-output , concurrent-output
, containers , containers
, cryptohash-sha256
, generics-sop , generics-sop
, haskus-utils-types , haskus-utils-types
, haskus-utils-variant , haskus-utils-variant
, hopenssl
, hpath , hpath
, hpath-directory , hpath-directory
, hpath-filepath , hpath-filepath
, hpath-io , hpath-io
, hpath-posix , hpath-posix
, http-io-streams
, io-streams
, language-bash , language-bash
, lzma , lzma
, monad-logger , monad-logger
@@ -265,6 +259,7 @@ library
, string-interpolate , string-interpolate
, tar-bytestring , tar-bytestring
, template-haskell , template-haskell
, terminal-progress-bar
, text , text
, time , time
, transformers , transformers
@@ -277,13 +272,13 @@ library
, word8 , word8
, zlib , zlib
-- deps
-- cabal-fmt: expand lib
exposed-modules: exposed-modules:
GHCup GHCup
GHCup.Download GHCup.Download
GHCup.Download.Utils
GHCup.Errors GHCup.Errors
GHCup.Platform GHCup.Platform
GHCup.Requirements
GHCup.Types GHCup.Types
GHCup.Types.JSON GHCup.Types.JSON
GHCup.Types.Optics GHCup.Types.Optics
@@ -301,16 +296,6 @@ library
-- other-extensions: -- other-extensions:
hs-source-dirs: lib hs-source-dirs: lib
if !flag(curl)
import:
, HsOpenSSL
, http-io-streams
, io-streams
, terminal-progress-bar
exposed-modules: GHCup.Download.IOStreams
else
cpp-options: -DCURL
executable ghcup executable ghcup
import: import:
config config
@@ -318,20 +303,20 @@ executable ghcup
, bytestring , bytestring
, containers , containers
, haskus-utils-variant , haskus-utils-variant
, hpath
, hpath-io
, megaparsec
, monad-logger , monad-logger
, megaparsec
, mtl , mtl
, optparse-applicative , optparse-applicative
, text
, versions
, hpath
, hpath-io
, pretty-terminal , pretty-terminal
, resourcet , resourcet
, string-interpolate , string-interpolate
, table-layout , table-layout
, text
, uri-bytestring , uri-bytestring
, utf8-string , utf8-string
, versions
-- --
main-is: Main.hs main-is: Main.hs
@@ -350,29 +335,27 @@ executable ghcup-gen
, aeson-pretty , aeson-pretty
, bytestring , bytestring
, containers , containers
, safe-exceptions
, haskus-utils-variant , haskus-utils-variant
, hpath
, monad-logger , monad-logger
, mtl , mtl
, optics , optics
, optparse-applicative , optparse-applicative
, text
, versions
, hpath
, pretty-terminal , pretty-terminal
, resourcet , resourcet
, safe-exceptions
, string-interpolate , string-interpolate
, table-layout , table-layout
, text
, transformers , transformers
, uri-bytestring , uri-bytestring
, utf8-string , utf8-string
, versions
-- --
main-is: Main.hs main-is: Main.hs
other-modules: other-modules:
GHCupDownloads GHCupDownloads
GHCupInfo
ToolRequirements
Validate Validate
-- other-extensions: -- other-extensions:

View File

@@ -1,4 +1,3 @@
{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-} {-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleContexts #-}
@@ -29,11 +28,10 @@ import GHCup.Version
import Control.Applicative import Control.Applicative
import Control.Exception.Safe import Control.Exception.Safe
import Control.Monad import Control.Monad
#if !MIN_VERSION_base(4,13,0)
import Control.Monad.Fail ( MonadFail ) import Control.Monad.Fail ( MonadFail )
#endif
import Control.Monad.Logger import Control.Monad.Logger
import Control.Monad.Reader import Control.Monad.Reader
import Control.Monad.Trans.Class ( lift )
import Control.Monad.Trans.Resource import Control.Monad.Trans.Resource
hiding ( throwM ) hiding ( throwM )
import Data.ByteString ( ByteString ) import Data.ByteString ( ByteString )
@@ -53,7 +51,8 @@ import Prelude hiding ( abs
) )
import System.IO.Error import System.IO.Error
import System.Posix.FilePath ( getSearchPath ) import System.Posix.FilePath ( getSearchPath )
import System.Posix.Files.ByteString import System.Posix.RawFilePath.Directory.Errors
( hideError )
import qualified Data.ByteString as B import qualified Data.ByteString as B
import qualified Data.Map.Strict as Map import qualified Data.Map.Strict as Map
@@ -97,16 +96,14 @@ installGHCBin bDls ver mpfReq = do
whenM (liftIO $ toolAlreadyInstalled GHC ver) whenM (liftIO $ toolAlreadyInstalled GHC ver)
$ (throwE $ AlreadyInstalled GHC ver) $ (throwE $ AlreadyInstalled GHC ver)
Settings {..} <- lift ask Settings {..} <- lift ask
pfreq@(PlatformRequest {..}) <- maybe (liftE $ platformRequest) pure mpfReq
-- download (or use cached version) -- download (or use cached version)
dlinfo <- lE $ getDownloadInfo GHC ver pfreq bDls dlinfo <- liftE $ getDownloadInfo bDls GHC ver mpfReq
dl <- liftE $ downloadCached dlinfo Nothing dl <- liftE $ downloadCached dlinfo Nothing
-- unpack -- unpack
tmpUnpack <- lift mkGhcupTmpDir tmpUnpack <- lift mkGhcupTmpDir
liftE $ unpackToDir tmpUnpack dl liftE $ unpackToDir tmpUnpack dl
void $ liftIO $ darwinNotarization _rPlatform tmpUnpack
-- prepare paths -- prepare paths
ghcdir <- liftIO $ ghcupGHCDir ver ghcdir <- liftIO $ ghcupGHCDir ver
@@ -173,16 +170,14 @@ installCabalBin :: ( MonadMask m
installCabalBin bDls ver mpfReq = do installCabalBin bDls ver mpfReq = do
lift $ $(logDebug) [i|Requested to install cabal version #{ver}|] 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) -- download (or use cached version)
dlinfo <- lE $ getDownloadInfo Cabal ver pfreq bDls dlinfo <- liftE $ getDownloadInfo bDls Cabal ver mpfReq
dl <- liftE $ downloadCached dlinfo Nothing dl <- liftE $ downloadCached dlinfo Nothing
-- unpack -- unpack
tmpUnpack <- lift withGHCupTmpDir tmpUnpack <- lift withGHCupTmpDir
liftE $ unpackToDir tmpUnpack dl liftE $ unpackToDir tmpUnpack dl
void $ liftIO $ darwinNotarization _rPlatform tmpUnpack
-- prepare paths -- prepare paths
bindir <- liftIO ghcupBinDir bindir <- liftIO ghcupBinDir
@@ -228,7 +223,7 @@ installCabalBin bDls ver mpfReq = do
setGHC :: (MonadLogger m, MonadThrow m, MonadFail m, MonadIO m) setGHC :: (MonadLogger m, MonadThrow m, MonadFail m, MonadIO m)
=> Version => Version
-> SetGHC -> SetGHC
-> Excepts '[NotInstalled] m Version -> Excepts '[NotInstalled] m ()
setGHC ver sghc = do setGHC ver sghc = do
let verBS = verToBS ver let verBS = verToBS ver
ghcdir <- liftIO $ ghcupGHCDir ver ghcdir <- liftIO $ ghcupGHCDir ver
@@ -247,6 +242,7 @@ setGHC ver sghc = do
-- for ghc tools (ghc, ghci, haddock, ...) -- for ghc tools (ghc, ghci, haddock, ...)
verfiles <- ghcToolFiles ver verfiles <- ghcToolFiles ver
forM_ verfiles $ \file -> do forM_ verfiles $ \file -> do
liftIO $ hideError doesNotExistErrorType $ deleteFile (bindir </> file)
targetFile <- case sghc of targetFile <- case sghc of
SetGHCOnly -> pure file SetGHCOnly -> pure file
SetGHC_XY -> do SetGHC_XY -> do
@@ -265,7 +261,7 @@ setGHC ver sghc = do
-- create symlink for share dir -- create symlink for share dir
lift $ symlinkShareDir ghcdir verBS lift $ symlinkShareDir ghcdir verBS
pure ver pure ()
where where
@@ -375,10 +371,6 @@ rmGHCVer ver = do
if exists if exists
then do then do
-- this isn't atomic, order matters -- this isn't atomic, order matters
when isSetGHC $ do
lift $ $(logInfo) [i|Removing ghc symlinks|]
liftE $ rmPlain ver
lift $ $(logInfo) [i|Removing directory recursively: #{d'}|] lift $ $(logInfo) [i|Removing directory recursively: #{d'}|]
liftIO $ deleteDirRecursive dir liftIO $ deleteDirRecursive dir
@@ -392,6 +384,11 @@ rmGHCVer ver = do
(mj, mi) <- getGHCMajor ver (mj, mi) <- getGHCMajor ver
getGHCForMajor mj mi >>= mapM_ (\v -> liftE $ setGHC v SetGHC_XY) getGHCForMajor mj mi >>= mapM_ (\v -> liftE $ setGHC v SetGHC_XY)
when isSetGHC $ do
lift $ $(logInfo) [i|Removing ghc symlinks|]
liftE $ rmPlain ver
liftIO liftIO
$ ghcupBaseDir $ ghcupBaseDir
>>= hideError doesNotExistErrorType >>= hideError doesNotExistErrorType
@@ -438,29 +435,23 @@ compileGHC :: ( MonadMask m
, MonadFail m , MonadFail m
) )
=> GHCupDownloads => GHCupDownloads
-> Version -- ^ version to install -> Version -- ^ version to install
-> Either Version (Path Abs) -- ^ version to bootstrap with -> Version -- ^ version to bootstrap with
-> Maybe Int -- ^ jobs -> Maybe Int -- ^ jobs
-> Maybe (Path Abs) -- ^ build config -> Maybe (Path Abs) -- ^ build config
-> Maybe (Path Abs)
-> Excepts -> Excepts
'[ AlreadyInstalled '[ AlreadyInstalled
, BuildFailed , BuildFailed
, DigestError , DigestError
, DistroNotFound
, DownloadFailed , DownloadFailed
, GHCupSetError , GHCupSetError
, NoCompatibleArch
, NoCompatiblePlatform
, NoDownload , NoDownload
, NotFoundInPATH
, PatchFailed
, UnknownArchive , UnknownArchive
] ]
m m
() ()
compileGHC dls tver bstrap jobs mbuildConfig patchdir = do compileGHC dls tver bver jobs mbuildConfig = do
lift $ $(logDebug) [i|Requested to compile: #{tver} with #{bstrap}|] lift $ $(logDebug) [i|Requested to compile: #{tver} with #{bver}|]
whenM (liftIO $ toolAlreadyInstalled GHC tver) whenM (liftIO $ toolAlreadyInstalled GHC tver)
(throwE $ AlreadyInstalled GHC tver) (throwE $ AlreadyInstalled GHC tver)
@@ -471,12 +462,8 @@ compileGHC dls tver bstrap jobs mbuildConfig patchdir = do
-- unpack -- unpack
tmpUnpack <- lift mkGhcupTmpDir tmpUnpack <- lift mkGhcupTmpDir
liftE $ unpackToDir tmpUnpack dl liftE $ unpackToDir tmpUnpack dl
(PlatformRequest {..}) <- liftE $ platformRequest
void $ liftIO $ darwinNotarization _rPlatform tmpUnpack
bghc <- case bstrap of bghc <- parseRel ("ghc-" <> verToBS bver)
Right g -> pure $ Right g
Left bver -> Left <$> parseRel ("ghc-" <> verToBS bver)
let workdir = maybe id (flip (</>)) (view dlSubdir dlInfo) $ tmpUnpack let workdir = maybe id (flip (</>)) (view dlSubdir dlInfo) $ tmpUnpack
ghcdir <- liftIO $ ghcupGHCDir tver ghcdir <- liftIO $ ghcupGHCDir tver
@@ -508,32 +495,23 @@ HADDOCK_DOCS = YES
GhcWithLlvmCodeGen = YES|] GhcWithLlvmCodeGen = YES|]
compile :: (MonadCatch m, MonadLogger m, MonadIO m) compile :: (MonadCatch m, MonadLogger m, MonadIO m)
=> Either (Path Rel) (Path Abs) => Path Rel
-> Path Abs -> Path Abs
-> Path Abs -> Path Abs
-> Excepts -> Excepts
'[ FileDoesNotExistError '[NoDownload , FileDoesNotExistError , ProcessError]
, PatchFailed
, ProcessError
, NotFoundInPATH
]
m m
() ()
compile bghc ghcdir workdir = do compile bghc ghcdir workdir = do
lift $ $(logInfo) [i|configuring build|] lift $ $(logInfo) [i|configuring build|]
forM_ patchdir $ \dir -> liftE $ applyPatches dir workdir
-- force ld.bfd for build (others seem to misbehave, like lld from FreeBSD) -- force ld.bfd for build (others seem to misbehave, like lld from FreeBSD)
newEnv <- addToCurrentEnv [("LD", "ld.bfd")] newEnv <- addToCurrentEnv [("LD", "ld.bfd")]
if if
| tver >= [vver|8.8.0|] -> do | tver >= [vver|8.8.0|] -> do
bghcPath <- case bghc of spaths <- catMaybes . fmap parseAbs <$> liftIO getSearchPath
Right ghc' -> pure ghc' bghcPath <- (liftIO $ searchPath spaths bghc) !? NoDownload
Left bver -> do
spaths <- catMaybes . fmap parseAbs <$> liftIO getSearchPath
(liftIO $ searchPath spaths bver) !? NotFoundInPATH bver
lEM $ liftIO $ execLogged lEM $ liftIO $ execLogged
"./configure" "./configure"
False False
@@ -545,9 +523,7 @@ GhcWithLlvmCodeGen = YES|]
lEM $ liftIO $ execLogged lEM $ liftIO $ execLogged
"./configure" "./configure"
False False
[ "--prefix=" <> toFilePath ghcdir ["--prefix=" <> toFilePath ghcdir, "--with-ghc=" <> toFilePath bghc]
, "--with-ghc=" <> either toFilePath toFilePath bghc
]
[rel|ghc-conf|] [rel|ghc-conf|]
(Just workdir) (Just workdir)
(Just newEnv) (Just newEnv)
@@ -560,7 +536,9 @@ GhcWithLlvmCodeGen = YES|]
Nothing -> Nothing ->
liftIO $ writeFile (build_mk workdir) (Just newFilePerms) defaultConf liftIO $ writeFile (build_mk workdir) (Just newFilePerms) defaultConf
lift $ $(logInfo) [i|Building (this may take a while)...|] lift
$ $(logInfo)
[i|Building (this may take a while)... Run 'tail -f ~/.ghcup/logs/ghc-make.log' to see the progress.|]
lEM $ liftIO $ make (maybe [] (\j -> ["-j" <> fS (show j)]) jobs) lEM $ liftIO $ make (maybe [] (\j -> ["-j" <> fS (show j)]) jobs)
(Just workdir) (Just workdir)
@@ -582,24 +560,19 @@ compileCabal :: ( MonadReader Settings m
) )
=> GHCupDownloads => GHCupDownloads
-> Version -- ^ version to install -> Version -- ^ version to install
-> Either Version (Path Abs) -- ^ version to bootstrap with -> Version -- ^ GHC version to build with
-> Maybe Int -> Maybe Int
-> Maybe (Path Abs)
-> Excepts -> Excepts
'[ BuildFailed '[ BuildFailed
, DigestError , DigestError
, DistroNotFound
, DownloadFailed , DownloadFailed
, NoCompatibleArch
, NoCompatiblePlatform
, NoDownload , NoDownload
, PatchFailed
, UnknownArchive , UnknownArchive
] ]
m m
() ()
compileCabal dls tver bghc jobs patchdir = do compileCabal dls tver bver jobs = do
lift $ $(logDebug) [i|Requested to compile: #{tver} with ghc-#{bghc}|] lift $ $(logDebug) [i|Requested to compile: #{tver} with ghc-#{bver}|]
-- download source tarball -- download source tarball
dlInfo <- preview (ix Cabal % ix tver % viSourceDL % _Just) dls ?? NoDownload dlInfo <- preview (ix Cabal % ix tver % viSourceDL % _Just) dls ?? NoDownload
@@ -608,8 +581,6 @@ compileCabal dls tver bghc jobs patchdir = do
-- unpack -- unpack
tmpUnpack <- lift mkGhcupTmpDir tmpUnpack <- lift mkGhcupTmpDir
liftE $ unpackToDir tmpUnpack dl liftE $ unpackToDir tmpUnpack dl
(PlatformRequest {..}) <- liftE $ platformRequest
void $ liftIO $ darwinNotarization _rPlatform tmpUnpack
let workdir = maybe id (flip (</>)) (view dlSubdir dlInfo) $ tmpUnpack let workdir = maybe id (flip (</>)) (view dlSubdir dlInfo) $ tmpUnpack
@@ -621,33 +592,22 @@ compileCabal dls tver bghc jobs patchdir = do
pure () pure ()
where where
compile :: (MonadThrow m, MonadLogger m, MonadIO m) compile :: (MonadLogger m, MonadIO m)
=> Path Abs => Path Abs
-> Excepts '[ProcessError , PatchFailed] m () -> Excepts '[ProcessError] m ()
compile workdir = do compile workdir = do
lift $ $(logInfo) [i|Building (this may take a while)...|] lift
$ $(logInfo)
forM_ patchdir $ \dir -> liftE $ applyPatches dir workdir [i|Building (this may take a while)... Run 'tail -f ~/.ghcup/logs/cabal-bootstrap.log' to see the progress.|]
ghcEnv <- case bghc of
Right path -> do
-- recover the version from /foo/ghc-6.5.4
bn <- basename path
let dn = toFilePath $ dirname path
let ver = snd . B.break (== _hyphen) . toFilePath $ bn
pure
[ ("GHC" , toFilePath path)
, ("GHC_PKG", dn <> "/" <> "ghc-pkg" <> ver)
]
Left bver -> do
let v' = verToBS bver
pure [("GHC", "ghc-" <> v'), ("GHC_PKG", "ghc-pkg-" <> v')]
let v' = verToBS bver
cabal_bin <- liftIO $ ghcupBinDir cabal_bin <- liftIO $ ghcupBinDir
newEnv <- lift newEnv <- lift $ addToCurrentEnv
$ addToCurrentEnv (("PREFIX", toFilePath cabal_bin) : ghcEnv) [ ("GHC" , "ghc-" <> v')
lift $ $(logDebug) [i|Environment: #{newEnv}|] , ("GHC_PKG", "ghc-pkg-" <> v')
, ("GHC_VER", v')
, ("PREFIX" , toFilePath cabal_bin)
]
lEM $ liftIO $ execLogged "./bootstrap.sh" lEM $ liftIO $ execLogged "./bootstrap.sh"
False False
@@ -674,8 +634,6 @@ upgradeGHCup :: ( MonadMask m
) )
=> GHCupDownloads => GHCupDownloads
-> Maybe (Path Abs) -- ^ full file destination to write ghcup into -> Maybe (Path Abs) -- ^ full file destination to write ghcup into
-> Bool -- ^ whether to force update regardless
-- of currently installed version
-> Excepts -> Excepts
'[ CopyError '[ CopyError
, DigestError , DigestError
@@ -684,38 +642,23 @@ upgradeGHCup :: ( MonadMask m
, NoCompatibleArch , NoCompatibleArch
, NoCompatiblePlatform , NoCompatiblePlatform
, NoDownload , NoDownload
, NoUpdate
] ]
m m
Version Version
upgradeGHCup dls mtarget force = do upgradeGHCup dls mtarget = do
lift $ $(logInfo) [i|Upgrading GHCup...|] lift $ $(logInfo) [i|Upgrading GHCup...|]
let latestVer = fromJust $ getLatest dls GHCup let latestVer = fromJust $ getLatest dls GHCup
when (not force && (latestVer <= pvpToVersion ghcUpVer)) $ throwE NoUpdate dli <- liftE $ getDownloadInfo dls GHCup latestVer Nothing
pfreq <- liftE platformRequest tmp <- lift withGHCupTmpDir
dli <- lE $ getDownloadInfo GHCup latestVer pfreq dls
tmp <- lift withGHCupTmpDir
let fn = [rel|ghcup|] let fn = [rel|ghcup|]
p <- liftE $ download dli tmp (Just fn) p <- liftE $ download dli tmp (Just fn)
let fileMode' =
newFilePerms
`unionFileModes` ownerExecuteMode
`unionFileModes` groupExecuteMode
`unionFileModes` otherExecuteMode
case mtarget of case mtarget of
Nothing -> do Nothing -> do
dest <- liftIO $ ghcupBinDir dest <- liftIO $ ghcupBinDir
liftIO $ hideError NoSuchThing $ deleteFile (dest </> fn)
handleIO (throwE . CopyError . show) $ liftIO $ copyFile p handleIO (throwE . CopyError . show) $ liftIO $ copyFile p
(dest </> fn) (dest </> fn)
Overwrite Overwrite
liftIO $ setFileMode (toFilePath (dest </> fn)) fileMode' Just fullDest -> liftIO $ copyFile p fullDest Overwrite
Just fullDest -> do
liftIO $ hideError NoSuchThing $ deleteFile fullDest
handleIO (throwE . CopyError . show) $ liftIO $ copyFile p
fullDest
Overwrite
liftIO $ setFileMode (toFilePath fullDest) fileMode'
pure latestVer pure latestVer
@@ -731,7 +674,7 @@ postGHCInstall :: (MonadLogger m, MonadThrow m, MonadFail m, MonadIO m)
=> Version => Version
-> Excepts '[NotInstalled] m () -> Excepts '[NotInstalled] m ()
postGHCInstall ver = do postGHCInstall ver = do
void $ liftE $ setGHC ver SetGHC_XYZ liftE $ setGHC ver SetGHC_XYZ
-- Create ghc-x.y symlinks. This may not be the current -- Create ghc-x.y symlinks. This may not be the current
-- version, create it regardless. -- version, create it regardless.

View File

@@ -1,4 +1,3 @@
{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-} {-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleContexts #-}
@@ -11,69 +10,75 @@
module GHCup.Download where module GHCup.Download where
#if !defined(CURL)
import GHCup.Download.IOStreams
import GHCup.Download.Utils
#endif
import GHCup.Errors import GHCup.Errors
import GHCup.Platform
import GHCup.Types import GHCup.Types
import GHCup.Types.JSON ( ) import GHCup.Types.JSON ( )
import GHCup.Types.Optics import GHCup.Types.Optics
import GHCup.Utils import GHCup.Utils
import GHCup.Utils.File import GHCup.Utils.File
import GHCup.Utils.Prelude import GHCup.Utils.Prelude
import GHCup.Version
import Control.Applicative import Control.Applicative
import Control.Exception.Safe import Control.Exception.Safe
import Control.Monad import Control.Monad
#if !MIN_VERSION_base(4,13,0)
import Control.Monad.Fail ( MonadFail ) import Control.Monad.Fail ( MonadFail )
#endif
import Control.Monad.Logger import Control.Monad.Logger
import Control.Monad.Reader import Control.Monad.Reader
import Control.Monad.Trans.Class ( lift )
import Control.Monad.Trans.Resource import Control.Monad.Trans.Resource
hiding ( throwM ) hiding ( throwM )
import Data.Aeson import Data.Aeson
#if !defined(CURL)
import Data.ByteString ( ByteString ) import Data.ByteString ( ByteString )
import Data.ByteString.Builder
import Data.CaseInsensitive ( CI ) import Data.CaseInsensitive ( CI )
#endif import Data.IORef
import Data.Maybe import Data.Maybe
import Data.String.Interpolate import Data.String.Interpolate
import Data.Text.Read
import Data.Time.Clock import Data.Time.Clock
import Data.Time.Clock.POSIX import Data.Time.Clock.POSIX
#if !defined(CURL)
import Data.Time.Format import Data.Time.Format
#endif
import Data.Versions import Data.Versions
import GHC.IO.Exception import GHC.IO.Exception
import HPath import HPath
import HPath.IO as HIO import HPath.IO as HIO
import Haskus.Utils.Variant.Excepts import Haskus.Utils.Variant.Excepts
import Network.Http.Client hiding ( URL )
import OpenSSL.Digest
import Optics import Optics
import Prelude hiding ( abs import Prelude hiding ( abs
, readFile , readFile
, writeFile , writeFile
) )
import System.IO.Error import System.IO.Error
import "unix" System.Posix.IO.ByteString
hiding ( fdWrite )
import "unix-bytestring" System.Posix.IO.ByteString
( fdWrite )
import System.Posix.RawFilePath.Directory.Errors
( hideError )
import System.ProgressBar
import URI.ByteString import URI.ByteString
import URI.ByteString.QQ
import qualified Crypto.Hash.SHA256 as SHA256 import qualified Data.Binary.Builder as B
import qualified Data.ByteString.Base16 as B16 import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as L import qualified Data.ByteString.Lazy as L
#if !defined(CURL)
import qualified Data.CaseInsensitive as CI import qualified Data.CaseInsensitive as CI
import qualified Data.Map.Strict as M import qualified Data.Map.Strict as M
import qualified Data.Text as T import qualified Data.Text as T
#endif
import qualified Data.Text.Encoding as E import qualified Data.Text.Encoding as E
import qualified System.IO.Streams as Streams
import qualified System.Posix.Files.ByteString as PF import qualified System.Posix.Files.ByteString as PF
import qualified System.Posix.RawFilePath.Directory import qualified System.Posix.RawFilePath.Directory
as RD as RD
ghcupURL :: URI
ghcupURL = [uri|https://www.haskell.org/ghcup/data/ghcup-0.0.1.json|]
@@ -93,7 +98,7 @@ getDownloads :: ( FromJSONKey Tool
, MonadFail m , MonadFail m
) )
=> URLSource => URLSource
-> Excepts '[JSONError , DownloadFailed] m GHCupInfo -> Excepts '[JSONError , DownloadFailed] m GHCupDownloads
getDownloads urlSource = do getDownloads urlSource = do
lift $ $(logDebug) [i|Receiving download info from: #{urlSource}|] lift $ $(logDebug) [i|Receiving download info from: #{urlSource}|]
case urlSource of case urlSource of
@@ -125,7 +130,6 @@ getDownloads urlSource = do
, UnsupportedScheme , UnsupportedScheme
, NoLocationHeader , NoLocationHeader
, TooManyRedirs , TooManyRedirs
, ProcessError
] ]
m1 m1
L.ByteString L.ByteString
@@ -154,7 +158,7 @@ getDownloads urlSource = do
pure bs pure bs
else liftIO $ readFile json_file else liftIO $ readFile json_file
Nothing -> do Nothing -> do
lift $ $(logDebug) [i|Unable to get/parse Last-Modified header|] lift $ $(logWarn) [i|Unable to get/parse Last-Modified header|]
liftIO $ deleteFile json_file liftIO $ deleteFile json_file
liftE $ downloadBS uri' liftE $ downloadBS uri'
else -- access in less than 5 minutes, re-use file else -- access in less than 5 minutes, re-use file
@@ -167,14 +171,11 @@ getDownloads urlSource = do
liftIO $ writeFileWithModTime modTime json_file bs liftIO $ writeFileWithModTime modTime json_file bs
pure bs pure bs
Nothing -> do Nothing -> do
lift $ $(logDebug) [i|Unable to get/parse Last-Modified header|] lift $ $(logWarn) [i|Unable to get/parse Last-Modified header|]
liftE $ downloadBS uri' liftE $ downloadBS uri'
where where
getModTime = do getModTime = do
#if defined(CURL)
pure Nothing
#else
headers <- headers <-
handleIO (\_ -> pure mempty) handleIO (\_ -> pure mempty)
$ liftE $ liftE
@@ -186,6 +187,7 @@ getDownloads urlSource = do
) )
pure $ parseModifiedHeader headers pure $ parseModifiedHeader headers
parseModifiedHeader :: (M.Map (CI ByteString) ByteString) -> Maybe UTCTime parseModifiedHeader :: (M.Map (CI ByteString) ByteString) -> Maybe UTCTime
parseModifiedHeader headers = parseModifiedHeader headers =
(M.lookup (CI.mk "Last-Modified") headers) >>= \h -> parseTimeM (M.lookup (CI.mk "Last-Modified") headers) >>= \h -> parseTimeM
@@ -194,8 +196,6 @@ getDownloads urlSource = do
"%a, %d %b %Y %H:%M:%S %Z" "%a, %d %b %Y %H:%M:%S %Z"
(T.unpack . E.decodeUtf8 $ h) (T.unpack . E.decodeUtf8 $ h)
#endif
writeFileWithModTime :: UTCTime -> Path Abs -> L.ByteString -> IO () writeFileWithModTime :: UTCTime -> Path Abs -> L.ByteString -> IO ()
writeFileWithModTime utctime path content = do writeFileWithModTime utctime path content = do
let mod_time = utcTimeToPOSIXSeconds utctime let mod_time = utcTimeToPOSIXSeconds utctime
@@ -203,13 +203,43 @@ getDownloads urlSource = do
setModificationTimeHiRes path mod_time setModificationTimeHiRes path mod_time
getDownloadInfo :: Tool
getDownloadInfo :: (MonadLogger m, MonadCatch m, MonadIO m)
=> GHCupDownloads
-> Tool
-> Version -> Version
-> Maybe PlatformRequest
-> Excepts
'[ DistroNotFound
, NoCompatiblePlatform
, NoCompatibleArch
, NoDownload
]
m
DownloadInfo
getDownloadInfo bDls t v mpfReq = do
(PlatformRequest arch' plat ver) <- case mpfReq of
Just x -> pure x
Nothing -> do
(PlatformResult rp rv) <- liftE getPlatform
ar <- lE getArchitecture
pure $ PlatformRequest ar rp rv
lE $ getDownloadInfo' t v arch' plat ver bDls
getDownloadInfo' :: Tool
-> Version
-- ^ tool version -- ^ tool version
-> PlatformRequest -> Architecture
-> GHCupDownloads -- ^ user arch
-> Either NoDownload DownloadInfo -> Platform
getDownloadInfo t v (PlatformRequest a p mv) dls = maybe -- ^ user platform
-> Maybe Versioning
-- ^ optional version of the platform
-> GHCupDownloads
-> Either NoDownload DownloadInfo
getDownloadInfo' t v a p mv dls = maybe
(Left NoDownload) (Left NoDownload)
Right Right
(with_distro <|> without_distro_ver <|> without_distro) (with_distro <|> without_distro_ver <|> without_distro)
@@ -259,25 +289,25 @@ download dli dest mfn
let uri' = E.decodeUtf8 (serializeURIRef' (view dlUri dli)) let uri' = E.decodeUtf8 (serializeURIRef' (view dlUri dli))
lift $ $(logInfo) [i|downloading: #{uri'}|] lift $ $(logInfo) [i|downloading: #{uri'}|]
(https, host, fullPath, port) <- reThrowAll DownloadFailed
$ uriToQuadruple (view dlUri dli)
-- destination dir must exist -- destination dir must exist
liftIO $ hideError AlreadyExists $ createDirRecursive newDirPerms dest liftIO $ hideError AlreadyExists $ createDirRecursive newDirPerms dest
destFile <- getDestFile destFile <- getDestFile
-- download -- download
fd <- liftIO $ createRegularFileFd newFilePerms destFile
let stepper = fdWrite fd
flip onException flip onException
(liftIO $ hideError doesNotExistErrorType $ deleteFile destFile) (liftIO $ hideError doesNotExistErrorType $ deleteFile destFile)
$ catchAllE @_ @'[ProcessError, DownloadFailed, UnsupportedScheme] $ flip finally (liftIO $ closeFd fd)
$ catchAllE
(\e -> (\e ->
(liftIO $ hideError doesNotExistErrorType $ deleteFile destFile) (liftIO $ hideError doesNotExistErrorType $ deleteFile destFile)
>> (throwE . DownloadFailed $ e) >> (throwE . DownloadFailed $ e)
) $ do )
#if defined(CURL) $ downloadInternal True https host fullPath port stepper
liftE $ lEM @_ @'[ProcessError] $ liftIO $ exec "curl" True
["-fL", "-o", toFilePath destFile , serializeURIRef' $ view dlUri dli] Nothing Nothing
#else
(https, host, fullPath, port) <- liftE $ uriToQuadruple (view dlUri dli)
liftE $ downloadToFile https host fullPath port destFile
#endif
liftE $ checkDigest dli destFile liftE $ checkDigest dli destFile
pure destFile pure destFile
@@ -326,8 +356,6 @@ downloadCached dli mfn = do
------------------ ------------------
-- | This is used for downloading the JSON. -- | This is used for downloading the JSON.
downloadBS :: (MonadCatch m, MonadIO m) downloadBS :: (MonadCatch m, MonadIO m)
=> URI => URI
@@ -338,7 +366,6 @@ downloadBS :: (MonadCatch m, MonadIO m)
, UnsupportedScheme , UnsupportedScheme
, NoLocationHeader , NoLocationHeader
, TooManyRedirs , TooManyRedirs
, ProcessError
] ]
m m
L.ByteString L.ByteString
@@ -356,19 +383,221 @@ downloadBS uri'
where where
scheme = view (uriSchemeL' % schemeBSL') uri' scheme = view (uriSchemeL' % schemeBSL') uri'
path = view pathL' uri' path = view pathL' uri'
#if defined(CURL)
dl _ = do
let exe = [rel|curl|]
args = ["-sSfL", serializeURIRef' uri']
liftIO (executeOut exe args Nothing) >>= \case
CapturedProcess ExitSuccess stdout _ -> do
pure $ L.fromStrict stdout
CapturedProcess (ExitFailure i') _ _ -> throwE $ NonZeroExit i' (toFilePath exe) args
#else
dl https = do dl https = do
(_, host', fullPath', port') <- liftE $ uriToQuadruple uri' (_, host', fullPath', port') <- liftE $ uriToQuadruple uri'
liftE $ downloadBS' https host' fullPath' port' liftE $ downloadBS' https host' fullPath' port'
#endif
-- | Load the result of this download into memory at once.
downloadBS' :: MonadIO m
=> Bool -- ^ https?
-> ByteString -- ^ host (e.g. "www.example.com")
-> ByteString -- ^ path (e.g. "/my/file") including query
-> Maybe Int -- ^ optional port (e.g. 3000)
-> Excepts
'[ HTTPStatusError
, URIParseError
, UnsupportedScheme
, NoLocationHeader
, TooManyRedirs
]
m
(L.ByteString)
downloadBS' https host path port = do
bref <- liftIO $ newIORef (mempty :: Builder)
let stepper bs = modifyIORef bref (<> byteString bs)
downloadInternal False https host path port stepper
liftIO (readIORef bref <&> toLazyByteString)
downloadInternal :: MonadIO m
=> Bool -- ^ whether to show a progress bar
-> Bool -- ^ https?
-> ByteString -- ^ host
-> ByteString -- ^ path with query
-> Maybe Int -- ^ optional port
-> (ByteString -> IO a) -- ^ the consuming step function
-> Excepts
'[ HTTPStatusError
, URIParseError
, UnsupportedScheme
, NoLocationHeader
, TooManyRedirs
]
m
()
downloadInternal = go (5 :: Int)
where
go redirs progressBar https host path port consumer = do
r <- liftIO $ withConnection' https host port action
veitherToExcepts r >>= \case
Just r' ->
if redirs > 0 then followRedirectURL r' else throwE TooManyRedirs
Nothing -> pure ()
where
action c = do
let q = buildRequest1 $ http GET path
sendRequest c q emptyBody
receiveResponse
c
(\r i' -> runE $ do
let scode = getStatusCode r
if
| scode >= 200 && scode < 300 -> downloadStream r i' >> pure Nothing
| scode >= 300 && scode < 400 -> case getHeader r "Location" of
Just r' -> pure $ Just $ r'
Nothing -> throwE NoLocationHeader
| otherwise -> throwE $ HTTPStatusError scode
)
followRedirectURL bs = case parseURI strictURIParserOptions bs of
Right uri' -> do
(https', host', fullPath', port') <- liftE $ uriToQuadruple uri'
go (redirs - 1) progressBar https' host' fullPath' port' consumer
Left e -> throwE e
downloadStream r i' = do
let size = case getHeader r "Content-Length" of
Just x' -> case decimal $ E.decodeUtf8 x' of
Left _ -> 0
Right (r', _) -> r'
Nothing -> 0
mpb <- if progressBar
then Just <$> (liftIO $ newProgressBar defStyle 10 (Progress 0 size ()))
else pure Nothing
outStream <- liftIO $ Streams.makeOutputStream
(\case
Just bs -> do
forM_ mpb $ \pb -> incProgress pb (BS.length bs)
void $ consumer bs
Nothing -> pure ()
)
liftIO $ Streams.connect i' outStream
getHead :: (MonadCatch m, MonadIO m)
=> URI
-> Excepts
'[ HTTPStatusError
, URIParseError
, UnsupportedScheme
, NoLocationHeader
, TooManyRedirs
]
m
(M.Map (CI ByteString) ByteString)
getHead uri' | scheme == "https" = head' True
| scheme == "http" = head' False
| otherwise = throwE UnsupportedScheme
where
scheme = view (uriSchemeL' % schemeBSL') uri'
head' https = do
(_, host', fullPath', port') <- liftE $ uriToQuadruple uri'
liftE $ headInternal https host' fullPath' port'
headInternal :: MonadIO m
=> Bool -- ^ https?
-> ByteString -- ^ host
-> ByteString -- ^ path with query
-> Maybe Int -- ^ optional port
-> Excepts
'[ HTTPStatusError
, URIParseError
, UnsupportedScheme
, TooManyRedirs
, NoLocationHeader
]
m
(M.Map (CI ByteString) ByteString)
headInternal = go (5 :: Int)
where
go redirs https host path port = do
r <- liftIO $ withConnection' https host port action
veitherToExcepts r >>= \case
Left r' ->
if redirs > 0 then followRedirectURL r' else throwE TooManyRedirs
Right hs -> pure hs
where
action c = do
let q = buildRequest1 $ http HEAD path
sendRequest c q emptyBody
unsafeReceiveResponse
c
(\r _ -> runE $ do
let scode = getStatusCode r
if
| scode >= 200 && scode < 300 -> do
let headers = getHeaderMap r
pure $ Right $ headers
| scode >= 300 && scode < 400 -> case getHeader r "Location" of
Just r' -> pure $ Left $ r'
Nothing -> throwE NoLocationHeader
| otherwise -> throwE $ HTTPStatusError scode
)
followRedirectURL bs = case parseURI strictURIParserOptions bs of
Right uri' -> do
(https', host', fullPath', port') <- liftE $ uriToQuadruple uri'
go (redirs - 1) https' host' fullPath' port'
Left e -> throwE e
withConnection' :: Bool
-> ByteString
-> Maybe Int
-> (Connection -> IO a)
-> IO a
withConnection' https host port action = bracket acquire closeConnection action
where
acquire = case https of
True -> do
ctx <- baselineContextSSL
openConnectionSSL ctx host (fromIntegral $ fromMaybe 443 port)
False -> openConnection host (fromIntegral $ fromMaybe 80 port)
-- | Extracts from a URI type: (https?, host, path+query, port)
uriToQuadruple :: Monad m
=> URI
-> Excepts
'[UnsupportedScheme]
m
(Bool, ByteString, ByteString, Maybe Int)
uriToQuadruple URI {..} = do
let scheme = view schemeBSL' uriScheme
host <-
preview (_Just % authorityHostL' % hostBSL') uriAuthority
?? UnsupportedScheme
https <- if
| scheme == "https" -> pure True
| scheme == "http" -> pure False
| otherwise -> throwE UnsupportedScheme
let queryBS =
BS.intercalate "&"
. fmap (\(x, y) -> encodeQuery x <> "=" <> encodeQuery y)
$ (queryPairs uriQuery)
port =
preview (_Just % authorityPortL' % _Just % portNumberL') uriAuthority
fullpath = if BS.null queryBS then uriPath else uriPath <> "?" <> queryBS
pure (https, host, fullpath, port)
where encodeQuery = L.toStrict . B.toLazyByteString . urlEncodeQuery
checkDigest :: (MonadIO m, MonadLogger m, MonadReader Settings m) checkDigest :: (MonadIO m, MonadLogger m, MonadReader Settings m)
@@ -381,7 +610,6 @@ checkDigest dli file = do
let p' = toFilePath file let p' = toFilePath file
lift $ $(logInfo) [i|verifying digest of: #{p'}|] lift $ $(logInfo) [i|verifying digest of: #{p'}|]
c <- liftIO $ readFile file c <- liftIO $ readFile file
let cDigest = E.decodeUtf8 . B16.encode . SHA256.hashlazy $ c let cDigest = E.decodeUtf8 . toHex . digest (digestByName "sha256") $ c
eDigest = view dlHash dli eDigest = view dlHash dli
when ((cDigest /= eDigest) && verify) $ throwE (DigestError cDigest eDigest) when ((cDigest /= eDigest) && verify) $ throwE (DigestError cDigest eDigest)

View File

@@ -1,254 +0,0 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
module GHCup.Download.IOStreams where
import GHCup.Download.Utils
import GHCup.Errors
import GHCup.Types.Optics
import GHCup.Types.JSON ( )
import GHCup.Utils.File
import GHCup.Utils.Prelude
import Control.Applicative
import Control.Exception.Safe
import Control.Monad
import Control.Monad.Reader
import Data.ByteString ( ByteString )
import Data.ByteString.Builder
import Data.CaseInsensitive ( CI )
import Data.IORef
import Data.Maybe
import Data.Text.Read
import HPath
import HPath.IO as HIO
import Haskus.Utils.Variant.Excepts
import Network.Http.Client hiding ( URL )
import Optics
import Prelude hiding ( abs
, readFile
, writeFile
)
import "unix" System.Posix.IO.ByteString
hiding ( fdWrite )
import "unix-bytestring" System.Posix.IO.ByteString
( fdWrite )
import System.ProgressBar
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
----------------------------
--[ Low-level (non-curl) ]--
----------------------------
-- | Load the result of this download into memory at once.
downloadBS' :: MonadIO m
=> Bool -- ^ https?
-> ByteString -- ^ host (e.g. "www.example.com")
-> ByteString -- ^ path (e.g. "/my/file") including query
-> Maybe Int -- ^ optional port (e.g. 3000)
-> Excepts
'[ HTTPStatusError
, URIParseError
, UnsupportedScheme
, NoLocationHeader
, TooManyRedirs
]
m
(L.ByteString)
downloadBS' https host path port = do
bref <- liftIO $ newIORef (mempty :: Builder)
let stepper bs = modifyIORef bref (<> byteString bs)
downloadInternal False https host path port stepper
liftIO (readIORef bref <&> toLazyByteString)
downloadToFile :: (MonadMask m, MonadIO m)
=> Bool -- ^ https?
-> ByteString -- ^ host (e.g. "www.example.com")
-> ByteString -- ^ path (e.g. "/my/file") including query
-> Maybe Int -- ^ optional port (e.g. 3000)
-> Path Abs -- ^ destination file to create and write to
-> Excepts '[DownloadFailed] m ()
downloadToFile https host fullPath port destFile = do
fd <- liftIO $ createRegularFileFd newFilePerms destFile
let stepper = fdWrite fd
flip finally (liftIO $ closeFd fd)
$ reThrowAll DownloadFailed $ downloadInternal True https host fullPath port stepper
downloadInternal :: MonadIO m
=> Bool -- ^ whether to show a progress bar
-> Bool -- ^ https?
-> ByteString -- ^ host
-> ByteString -- ^ path with query
-> Maybe Int -- ^ optional port
-> (ByteString -> IO a) -- ^ the consuming step function
-> Excepts
'[ HTTPStatusError
, URIParseError
, UnsupportedScheme
, NoLocationHeader
, TooManyRedirs
]
m
()
downloadInternal = go (5 :: Int)
where
go redirs progressBar https host path port consumer = do
r <- liftIO $ withConnection' https host port action
veitherToExcepts r >>= \case
Just r' ->
if redirs > 0 then followRedirectURL r' else throwE TooManyRedirs
Nothing -> pure ()
where
action c = do
let q = buildRequest1 $ http GET path
sendRequest c q emptyBody
receiveResponse
c
(\r i' -> runE $ do
let scode = getStatusCode r
if
| scode >= 200 && scode < 300 -> downloadStream r i' >> pure Nothing
| scode >= 300 && scode < 400 -> case getHeader r "Location" of
Just r' -> pure $ Just $ r'
Nothing -> throwE NoLocationHeader
| otherwise -> throwE $ HTTPStatusError scode
)
followRedirectURL bs = case parseURI strictURIParserOptions bs of
Right uri' -> do
(https', host', fullPath', port') <- liftE $ uriToQuadruple uri'
go (redirs - 1) progressBar https' host' fullPath' port' consumer
Left e -> throwE e
downloadStream r i' = do
let size = case getHeader r "Content-Length" of
Just x' -> case decimal $ E.decodeUtf8 x' of
Left _ -> 0
Right (r', _) -> r'
Nothing -> 0
mpb <- if progressBar
then Just <$> (liftIO $ newProgressBar defStyle 10 (Progress 0 size ()))
else pure Nothing
outStream <- liftIO $ Streams.makeOutputStream
(\case
Just bs -> do
forM_ mpb $ \pb -> incProgress pb (BS.length bs)
void $ consumer bs
Nothing -> pure ()
)
liftIO $ Streams.connect i' outStream
getHead :: (MonadCatch m, MonadIO m)
=> URI
-> Excepts
'[ HTTPStatusError
, URIParseError
, UnsupportedScheme
, NoLocationHeader
, TooManyRedirs
, ProcessError
]
m
(M.Map (CI ByteString) ByteString)
getHead uri' | scheme == "https" = head' True
| scheme == "http" = head' False
| otherwise = throwE UnsupportedScheme
where
scheme = view (uriSchemeL' % schemeBSL') uri'
head' https = do
(_, host', fullPath', port') <- liftE $ uriToQuadruple uri'
liftE $ headInternal https host' fullPath' port'
headInternal :: MonadIO m
=> Bool -- ^ https?
-> ByteString -- ^ host
-> ByteString -- ^ path with query
-> Maybe Int -- ^ optional port
-> Excepts
'[ HTTPStatusError
, URIParseError
, UnsupportedScheme
, TooManyRedirs
, NoLocationHeader
]
m
(M.Map (CI ByteString) ByteString)
headInternal = go (5 :: Int)
where
go redirs https host path port = do
r <- liftIO $ withConnection' https host port action
veitherToExcepts r >>= \case
Left r' ->
if redirs > 0 then followRedirectURL r' else throwE TooManyRedirs
Right hs -> pure hs
where
action c = do
let q = buildRequest1 $ http HEAD path
sendRequest c q emptyBody
unsafeReceiveResponse
c
(\r _ -> runE $ do
let scode = getStatusCode r
if
| scode >= 200 && scode < 300 -> do
let headers = getHeaderMap r
pure $ Right $ headers
| scode >= 300 && scode < 400 -> case getHeader r "Location" of
Just r' -> pure $ Left $ r'
Nothing -> throwE NoLocationHeader
| otherwise -> throwE $ HTTPStatusError scode
)
followRedirectURL bs = case parseURI strictURIParserOptions bs of
Right uri' -> do
(https', host', fullPath', port') <- liftE $ uriToQuadruple uri'
go (redirs - 1) https' host' fullPath' port'
Left e -> throwE e
withConnection' :: Bool
-> ByteString
-> Maybe Int
-> (Connection -> IO a)
-> IO a
withConnection' https host port action = bracket acquire closeConnection action
where
acquire = case https of
True -> do
ctx <- baselineContextSSL
openConnectionSSL ctx host (fromIntegral $ fromMaybe 443 port)
False -> openConnection host (fromIntegral $ fromMaybe 80 port)

View File

@@ -1,64 +0,0 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
module GHCup.Download.Utils where
import GHCup.Errors
import GHCup.Types.Optics
import GHCup.Types.JSON ( )
import GHCup.Utils.Prelude
import Control.Applicative
import Control.Monad
import Data.ByteString ( ByteString )
import Data.Maybe
import Haskus.Utils.Variant.Excepts
import Optics
import Prelude hiding ( abs
, readFile
, writeFile
)
import URI.ByteString
import qualified Data.Binary.Builder as B
import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as L
-- | Extracts from a URI type: (https?, host, path+query, port)
uriToQuadruple :: Monad m
=> URI
-> Excepts
'[UnsupportedScheme]
m
(Bool, ByteString, ByteString, Maybe Int)
uriToQuadruple URI {..} = do
let scheme = view schemeBSL' uriScheme
host <-
preview (_Just % authorityHostL' % hostBSL') uriAuthority
?? UnsupportedScheme
https <- if
| scheme == "https" -> pure True
| scheme == "http" -> pure False
| otherwise -> throwE UnsupportedScheme
let queryBS =
BS.intercalate "&"
. fmap (\(x, y) -> encodeQuery x <> "=" <> encodeQuery y)
$ (queryPairs uriQuery)
port =
preview (_Just % authorityPortL' % _Just % portNumberL') uriAuthority
fullpath = if BS.null queryBS then uriPath else uriPath <> "?" <> queryBS
pure (https, host, fullpath, port)
where encodeQuery = L.toStrict . B.toLazyByteString . urlEncodeQuery

View File

@@ -30,10 +30,6 @@ data NoCompatiblePlatform = NoCompatiblePlatform String -- the platform we got
data NoDownload = NoDownload data NoDownload = NoDownload
deriving Show deriving Show
-- | No update available or necessary.
data NoUpdate = NoUpdate
deriving Show
-- | The Architecture is unknown and unsupported. -- | The Architecture is unknown and unsupported.
data NoCompatibleArch = NoCompatibleArch String data NoCompatibleArch = NoCompatibleArch String
deriving Show deriving Show
@@ -67,10 +63,6 @@ data AlreadyInstalled = AlreadyInstalled Tool Version
data NotInstalled = NotInstalled Tool Version data NotInstalled = NotInstalled Tool Version
deriving Show deriving Show
-- | An executable was expected to be in PATH, but was not found.
data NotFoundInPATH = NotFoundInPATH (Path Rel)
deriving Show
-- | JSON decoding failed. -- | JSON decoding failed.
data JSONError = JSONDecodeError String data JSONError = JSONDecodeError String
deriving Show deriving Show
@@ -96,13 +88,6 @@ data NoLocationHeader = NoLocationHeader
data TooManyRedirs = TooManyRedirs data TooManyRedirs = TooManyRedirs
deriving Show deriving Show
-- | A patch could not be applied.
data PatchFailed = PatchFailed
deriving Show
-- | The tool requirements could not be found.
data NoToolRequirements = NoToolRequirements
deriving Show
------------------------- -------------------------

View File

@@ -22,6 +22,7 @@ import Control.Exception.Safe
import Control.Monad import Control.Monad
import Control.Monad.Logger import Control.Monad.Logger
import Control.Monad.Reader import Control.Monad.Reader
import Control.Monad.Trans.Class ( lift )
import Data.ByteString ( ByteString ) import Data.ByteString ( ByteString )
import Data.Foldable import Data.Foldable
import Data.Maybe import Data.Maybe
@@ -46,21 +47,6 @@ import qualified Data.Text.Encoding as E
-------------------------- --------------------------
-- | Get the full platform request, consisting of architecture, distro, ...
platformRequest :: (MonadLogger m, MonadCatch m, MonadIO m)
=> Excepts
'[ NoCompatiblePlatform
, NoCompatibleArch
, DistroNotFound
]
m
PlatformRequest
platformRequest = do
(PlatformResult rp rv) <- liftE getPlatform
ar <- lE getArchitecture
pure $ PlatformRequest ar rp rv
getArchitecture :: Either NoCompatibleArch Architecture getArchitecture :: Either NoCompatibleArch Architecture
getArchitecture = case arch of getArchitecture = case arch of
"x86_64" -> Right A_64 "x86_64" -> Right A_64
@@ -79,30 +65,16 @@ getPlatform = do
"linux" -> do "linux" -> do
(distro, ver) <- liftE getLinuxDistro (distro, ver) <- liftE getLinuxDistro
pure $ PlatformResult { _platform = Linux distro, _distroVersion = ver } pure $ PlatformResult { _platform = Linux distro, _distroVersion = ver }
"darwin" -> do -- TODO: these are not verified
ver <- "darwin" ->
( either (const Nothing) Just pure $ PlatformResult { _platform = Darwin, _distroVersion = Nothing }
. versioning
. getMajorVersion
. E.decodeUtf8
)
<$> getDarwinVersion
pure $ PlatformResult { _platform = Darwin, _distroVersion = ver }
"freebsd" -> do "freebsd" -> do
ver <- ver <- getFreeBSDVersion
(either (const Nothing) Just . versioning . E.decodeUtf8)
<$> getFreeBSDVersion
pure $ PlatformResult { _platform = FreeBSD, _distroVersion = ver } pure $ PlatformResult { _platform = FreeBSD, _distroVersion = ver }
what -> throwE $ NoCompatiblePlatform what what -> throwE $ NoCompatiblePlatform what
lift $ $(logDebug) [i|Identified Platform as: #{pfr}|] lift $ $(logDebug) [i|Identified Platform as: #{pfr}|]
pure pfr pure pfr
where where getFreeBSDVersion = pure Nothing
getMajorVersion = T.intercalate "." . take 2 . T.split (== '.')
getFreeBSDVersion =
liftIO $ fmap _stdOut $ executeOut [rel|freebsd-version|] [] Nothing
getDarwinVersion = liftIO $ fmap _stdOut $ executeOut [rel|sw_vers|]
["-productVersion"]
Nothing
getLinuxDistro :: (MonadCatch m, MonadIO m) getLinuxDistro :: (MonadCatch m, MonadIO m)

View File

@@ -1,46 +0,0 @@
{-# LANGUAGE OverloadedStrings #-}
module GHCup.Requirements where
import GHCup.Types
import GHCup.Types.JSON ( )
import GHCup.Types.Optics
import Control.Applicative
import Data.Maybe
import Optics
import Prelude hiding ( abs
, readFile
, writeFile
)
import qualified Data.Text as T
-- | Get the requirements. Right now this combines GHC and cabal
-- and doesn't do fine-grained distinction. However, the 'ToolRequirements'
-- type allows it.
getCommonRequirements :: PlatformResult
-> ToolRequirements
-> Maybe Requirements
getCommonRequirements pr tr =
preview (ix GHC % ix Nothing % ix (_platform pr) % ix (_distroVersion pr)) tr
<|> preview (ix GHC % ix Nothing % ix (_platform pr) % ix Nothing) tr
<|> preview
( ix GHC
% ix Nothing
% ix (set _Linux UnknownLinux $ _platform pr)
% ix Nothing
)
tr
prettyRequirements :: Requirements -> T.Text
prettyRequirements Requirements {..} =
let d = if not . null $ _distroPKGs
then
"\n Install the following distro packages: "
<> T.intercalate " " _distroPKGs
else ""
n = if not . T.null $ _notes then "\n Note: " <> _notes else ""
in "System requirements " <> d <> n

View File

@@ -12,39 +12,6 @@ import qualified GHC.Generics as GHC
--------------------
--[ GHCInfo Tree ]--
--------------------
data GHCupInfo = GHCupInfo
{ _toolRequirements :: ToolRequirements
, _ghcupDownloads :: GHCupDownloads
}
deriving (Show, GHC.Generic)
-------------------------
--[ Requirements Tree ]--
-------------------------
type ToolRequirements = Map Tool ToolReqVersionSpec
type ToolReqVersionSpec = Map (Maybe Version) PlatformReqSpec
type PlatformReqSpec = Map Platform PlatformReqVersionSpec
type PlatformReqVersionSpec = Map (Maybe Versioning) Requirements
data Requirements = Requirements
{ _distroPKGs :: [Text]
, _notes :: Text
}
deriving (Show, GHC.Generic)
--------------------- ---------------------
--[ Download Tree ]-- --[ Download Tree ]--
@@ -132,7 +99,7 @@ data DownloadInfo = DownloadInfo
-- | Where to fetch GHCupDownloads from. -- | Where to fetch GHCupDownloads from.
data URLSource = GHCupURL data URLSource = GHCupURL
| OwnSource URI | OwnSource URI
| OwnSpec GHCupInfo | OwnSpec GHCupDownloads
deriving Show deriving Show

View File

@@ -18,6 +18,7 @@ import GHCup.Utils.Prelude
import Data.Aeson import Data.Aeson
import Data.Aeson.TH import Data.Aeson.TH
import Data.Aeson.Types import Data.Aeson.Types
import Data.Text.Encoding ( decodeUtf8 )
import Data.Text.Encoding as E import Data.Text.Encoding as E
import Data.Versions import Data.Versions
import Data.Word8 import Data.Word8
@@ -39,8 +40,6 @@ deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''VUnit
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''VersionInfo deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''VersionInfo
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''Tag deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''Tag
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''DownloadInfo deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''DownloadInfo
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''GHCupInfo
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''Requirements
instance ToJSON URI where instance ToJSON URI where
@@ -71,11 +70,11 @@ instance FromJSONKey Versioning where
instance ToJSONKey (Maybe Versioning) where instance ToJSONKey (Maybe Versioning) where
toJSONKey = toJSONKeyText $ \case toJSONKey = toJSONKeyText $ \case
Just x -> prettyV x Just x -> prettyV x
Nothing -> T.pack "unknown_versioning" Nothing -> T.pack "unknown_version"
instance FromJSONKey (Maybe Versioning) where instance FromJSONKey (Maybe Versioning) where
fromJSONKey = FromJSONKeyTextParser $ \t -> fromJSONKey = FromJSONKeyTextParser $ \t ->
if t == T.pack "unknown_versioning" then pure Nothing else pure $ just t if t == T.pack "unknown_version" then pure Nothing else pure $ just t
where where
just t = case versioning t of just t = case versioning t of
Right x -> pure x Right x -> pure x
@@ -114,19 +113,6 @@ instance ToJSONKey Architecture where
instance FromJSONKey Architecture where instance FromJSONKey Architecture where
fromJSONKey = genericFromJSONKey defaultJSONKeyOptions fromJSONKey = genericFromJSONKey defaultJSONKeyOptions
instance ToJSONKey (Maybe Version) where
toJSONKey = toJSONKeyText $ \case
Just x -> prettyVer x
Nothing -> T.pack "unknown_version"
instance FromJSONKey (Maybe Version) where
fromJSONKey = FromJSONKeyTextParser $ \t ->
if t == T.pack "unknown_version" then pure Nothing else pure $ just t
where
just t = case version t of
Right x -> pure x
Left e -> fail $ "Failure in (Maybe Version) (FromJSONKey)" <> show e
instance ToJSON Version where instance ToJSON Version where
toJSON = toJSON . prettyVer toJSON = toJSON . prettyVer

View File

@@ -19,7 +19,6 @@ makeLenses ''DownloadInfo
makeLenses ''Tag makeLenses ''Tag
makeLenses ''VersionInfo makeLenses ''VersionInfo
makeLenses ''GHCupInfo
uriSchemeL' :: Lens' (URIRef Absolute) Scheme uriSchemeL' :: Lens' (URIRef Absolute) Scheme
uriSchemeL' = lensVL uriSchemeL uriSchemeL' = lensVL uriSchemeL

View File

@@ -1,4 +1,3 @@
{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-} {-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE OverloadedStrings #-}
@@ -23,11 +22,10 @@ import GHCup.Utils.Prelude
import Control.Applicative import Control.Applicative
import Control.Exception.Safe import Control.Exception.Safe
import Control.Monad import Control.Monad
#if !MIN_VERSION_base(4,13,0)
import Control.Monad.Fail ( MonadFail ) import Control.Monad.Fail ( MonadFail )
#endif
import Control.Monad.Logger import Control.Monad.Logger
import Control.Monad.Reader import Control.Monad.Reader
import Control.Monad.Trans.Class ( lift )
import Data.Attoparsec.ByteString import Data.Attoparsec.ByteString
import Data.ByteString ( ByteString ) import Data.ByteString ( ByteString )
import Data.List import Data.List
@@ -297,7 +295,7 @@ urlBaseName :: MonadThrow m
urlBaseName = parseRel . snd . B.breakEnd (== _slash) . urlDecode False urlBaseName = parseRel . snd . B.breakEnd (== _slash) . urlDecode False
-- Get tool files from '~/.ghcup/bin/ghc/<ver>/bin/*' -- Get tool files from ~/.ghcup/bin/ghc/<ver>/bin/*
-- while ignoring *-<ver> symlinks. -- while ignoring *-<ver> symlinks.
-- --
-- Returns unversioned relative files, e.g.: -- Returns unversioned relative files, e.g.:
@@ -338,33 +336,3 @@ make args workdir = do
has_gmake <- isJust <$> searchPath spaths [rel|gmake|] has_gmake <- isJust <$> searchPath spaths [rel|gmake|]
let mymake = if has_gmake then "gmake" else "make" let mymake = if has_gmake then "gmake" else "make"
execLogged mymake True args [rel|ghc-make|] workdir Nothing execLogged mymake True args [rel|ghc-make|] workdir Nothing
-- | Try to apply patches in order. Fails with 'PatchFailed'
-- on first failure.
applyPatches :: (MonadLogger m, MonadIO m)
=> Path Abs -- ^ dir containing patches
-> Path Abs -- ^ dir to apply patches in
-> Excepts '[PatchFailed] m ()
applyPatches pdir ddir = do
patches <- liftIO $ getDirsFiles pdir
forM_ (sort patches) $ \patch' -> do
lift $ $(logInfo) [i|Applying patch #{patch'}|]
(fmap (either (const Nothing) Just) $ liftIO $ exec
"patch"
True
["-p1", "-i", toFilePath patch']
(Just ddir)
Nothing
)
!? PatchFailed
darwinNotarization :: Platform -> Path Abs -> IO (Either ProcessError ())
darwinNotarization Darwin path = exec
"xattr"
True
["-r", "-d", "com.apple.quarantine", toFilePath path]
Nothing
Nothing
darwinNotarization _ _ = pure $ Right ()

View File

@@ -39,10 +39,11 @@ import qualified System.Posix.User as PU
ghcupBaseDir :: IO (Path Abs) ghcupBaseDir :: IO (Path Abs)
ghcupBaseDir = do ghcupBaseDir = do
bdir <- getEnv "GHCUP_INSTALL_BASE_PREFIX" >>= \case getEnv "GHCUP_INSTALL_BASE_PREFIX" >>= \case
Just r -> parseAbs r Just r -> parseAbs r
Nothing -> liftIO getHomeDirectory Nothing -> do
pure (bdir </> [rel|.ghcup|]) home <- liftIO getHomeDirectory
pure (home </> [rel|.ghcup|])
ghcupGHCBaseDir :: IO (Path Abs) ghcupGHCBaseDir :: IO (Path Abs)
ghcupGHCBaseDir = ghcupBaseDir <&> (</> [rel|ghc|]) ghcupGHCBaseDir = ghcupBaseDir <&> (</> [rel|ghc|])

View File

@@ -6,9 +6,10 @@ module GHCup.Utils.File where
import GHCup.Utils.Dirs import GHCup.Utils.Dirs
import GHCup.Utils.Prelude import GHCup.Utils.Prelude
import GHCup.Utils.String.QQ
import Control.Concurrent import Control.Concurrent
import Control.Exception ( evaluate ) import Control.Concurrent.MVar
import Control.Exception.Safe import Control.Exception.Safe
import Control.Monad import Control.Monad
import Data.ByteString ( ByteString ) import Data.ByteString ( ByteString )
@@ -18,6 +19,8 @@ import Data.Foldable
import Data.Functor import Data.Functor
import Data.IORef import Data.IORef
import Data.Maybe import Data.Maybe
import Data.Word8
import GHC.Conc hiding ( threadWaitRead )
import GHC.Foreign ( peekCStringLen ) import GHC.Foreign ( peekCStringLen )
import GHC.IO.Encoding ( getLocaleEncoding ) import GHC.IO.Encoding ( getLocaleEncoding )
import GHC.IO.Exception import GHC.IO.Exception
@@ -27,6 +30,7 @@ import Optics
import Streamly import Streamly
import Streamly.External.ByteString import Streamly.External.ByteString
import Streamly.External.ByteString.Lazy import Streamly.External.ByteString.Lazy
import System.Console.Concurrent
import System.Console.Pretty import System.Console.Pretty
import System.Console.Regions import System.Console.Regions
import System.IO import System.IO
@@ -44,7 +48,6 @@ import System.Posix.Types
import qualified Control.Exception as EX import qualified Control.Exception as EX
import qualified Data.Text as T import qualified Data.Text as T
import qualified Data.Text.Encoding as E import qualified Data.Text.Encoding as E
import qualified Data.Text.Encoding.Error as E
import qualified System.Posix.Process.ByteString import qualified System.Posix.Process.ByteString
as SPPB as SPPB
import Streamly.External.Posix.DirStream import Streamly.External.Posix.DirStream
@@ -59,7 +62,6 @@ import qualified "unix-bytestring" System.Posix.IO.ByteString
as SPIB as SPIB
-- | Bool signals whether the regions should be cleaned.
data StopThread = StopThread Bool data StopThread = StopThread Bool
deriving Show deriving Show
@@ -147,8 +149,8 @@ execLogged exe spath args lfile chdir env = do
done <- newEmptyMVar done <- newEmptyMVar
tid <- tid <-
forkIO forkIO
$ EX.handle (\(_ :: StopThread) -> pure ()) $ EX.handle (\(e :: StopThread) -> pure ())
$ EX.handle (\(_ :: IOException) -> pure ()) $ EX.handle (\(e :: IOException) -> pure ())
$ flip finally (putMVar done ()) $ flip finally (putMVar done ())
$ printToRegion fd stdoutRead 6 $ printToRegion fd stdoutRead 6
@@ -185,36 +187,32 @@ execLogged exe spath args lfile chdir env = do
ref <- newIORef ([] :: [ByteString]) ref <- newIORef ([] :: [ByteString])
displayConsoleRegions $ do displayConsoleRegions $ do
rs <- sequence . replicate size . openConsoleRegion $ Linear rs <- sequence . replicate size . openConsoleRegion $ Linear
flip finally (readTilEOF (lineAction ref rs) fdIn) -- make sure the last few lines don't get cut off EX.handle
$ handle (\(StopThread b) -> do
(\(StopThread b) -> do when b (forM_ rs closeConsoleRegion)
when b (forM_ rs closeConsoleRegion) EX.throw (StopThread b)
EX.throw (StopThread b) )
$ readForever
(\bs -> do
modifyIORef' ref (swapRegs bs)
regs <- readIORef ref
forM (zip regs rs) $ \(bs, r) -> do
setConsoleRegion r $ do
w <- consoleWidth
return
. T.pack
. color Blue
. T.unpack
. E.decodeUtf8
. trim w
. (\b -> "[ " <> toFilePath lfile <> " ] " <> b)
$ bs
SPIB.fdWrite fileFd (bs <> "\n")
) )
$ do fdIn
hideError eofErrorType $ readTilEOF (lineAction ref rs) fdIn
-- wait for explicit stop from the parent to signal what cleanup to run
forever (threadDelay 5000)
where where
-- action to perform line by line
lineAction ref rs bs' = do
modifyIORef' ref (swapRegs bs')
regs <- readIORef ref
forM (zip regs rs) $ \(bs, r) -> do
setConsoleRegion r $ do
w <- consoleWidth
return
. T.pack
. color Blue
. T.unpack
. E.decodeUtf8With E.lenientDecode
. trim w
. (\b -> "[ " <> toFilePath lfile <> " ] " <> b)
$ bs
SPIB.fdWrite fileFd (bs <> "\n")
swapRegs bs regs | length regs < size = regs ++ [bs] swapRegs bs regs | length regs < size = regs ++ [bs]
| otherwise = tail regs ++ [bs] | otherwise = tail regs ++ [bs]
@@ -224,16 +222,18 @@ execLogged exe spath args lfile chdir env = do
-- read an entire line from the file descriptor (removes the newline char) -- read an entire line from the file descriptor (removes the newline char)
readLine fd' = do readLine fd' = do
threadWaitRead fd'
bs <- SPIB.fdRead fd' 1 bs <- SPIB.fdRead fd' 1
if if
| bs == "\n" -> pure "" | bs == "\n" -> pure ""
| bs == "" -> pure "" | bs == "" -> pure ""
| otherwise -> fmap (bs <>) $ readLine fd' | otherwise -> fmap (bs <>) $ readLine fd'
readTilEOF action' fd' = do readForever action' fd' = do
bs <- readLine fd' bs <- readLine fd'
void $ action' bs if not $ BS.null bs
readTilEOF action' fd' then action' bs >> readForever action' fd'
else readForever action' fd'
-- | Capture the stdout and stderr of the given action, which -- | Capture the stdout and stderr of the given action, which
@@ -242,7 +242,7 @@ execLogged exe spath args lfile chdir env = do
captureOutStreams :: IO a captureOutStreams :: IO a
-- ^ the action to execute in a subprocess -- ^ the action to execute in a subprocess
-> IO CapturedProcess -> IO CapturedProcess
captureOutStreams action = do captureOutStreams action =
actionWithPipes $ \(parentStdoutRead, childStdoutWrite) -> actionWithPipes $ \(parentStdoutRead, childStdoutWrite) ->
actionWithPipes $ \(parentStderrRead, childStderrWrite) -> do actionWithPipes $ \(parentStderrRead, childStderrWrite) -> do
pid <- SPPB.forkProcess $ do pid <- SPPB.forkProcess $ do
@@ -257,61 +257,23 @@ captureOutStreams action = do
closeFd parentStderrRead closeFd parentStderrRead
-- execute the action -- execute the action
a <- action void $ action
void $ evaluate a
-- close everything we don't need -- close everything we don't need
closeFd childStdoutWrite closeFd childStdoutWrite
closeFd childStderrWrite closeFd childStderrWrite
-- start thread that writes the output SPPB.getProcessStatus True True pid >>= \case
refOut <- newIORef BS.empty
refErr <- newIORef BS.empty
done <- newEmptyMVar
_ <-
forkIO
$ EX.handle (\(_ :: StopThread) -> pure ())
$ EX.handle (\(_ :: IOException) -> pure ())
$ flip finally (putMVar done ())
$ writeStds parentStdoutRead parentStderrRead refOut refErr
status <- SPPB.getProcessStatus True True pid
takeMVar done
case status of
-- readFd will take care of closing the fd -- readFd will take care of closing the fd
Just (SPPB.Exited es) -> do Just (SPPB.Exited es) -> do
stdout' <- readIORef refOut stdout' <- L.toStrict <$> readFd parentStdoutRead
stderr' <- readIORef refErr stderr' <- L.toStrict <$> readFd parentStderrRead
pure $ CapturedProcess { _exitCode = es pure $ CapturedProcess { _exitCode = es
, _stdOut = stdout' , _stdOut = stdout'
, _stdErr = stderr' , _stdErr = stderr'
} }
_ -> throwIO $ userError $ ("No such PID " ++ show pid) _ -> throwIO $ userError $ ("No such PID " ++ show pid)
where
writeStds pout perr rout rerr = do
doneOut <- newEmptyMVar
void
$ forkIO
$ hideError eofErrorType
$ flip finally (putMVar doneOut ())
$ readTilEOF (\x -> modifyIORef' rout (<> x)) pout
doneErr <- newEmptyMVar
void
$ forkIO
$ hideError eofErrorType
$ flip finally (putMVar doneErr ())
$ readTilEOF (\x -> modifyIORef' rerr (<> x)) perr
takeMVar doneOut
takeMVar doneErr
readTilEOF ~action' fd' = do
bs <- SPIB.fdRead fd' 512
void $ action' bs
readTilEOF action' fd'
actionWithPipes :: ((Fd, Fd) -> IO b) -> IO b actionWithPipes :: ((Fd, Fd) -> IO b) -> IO b
actionWithPipes a = actionWithPipes a =

View File

@@ -17,6 +17,7 @@ import Control.Monad.IO.Class
import Control.Monad.Trans.Class ( lift ) import Control.Monad.Trans.Class ( lift )
import Data.Bifunctor import Data.Bifunctor
import Data.ByteString ( ByteString ) import Data.ByteString ( ByteString )
import Data.Monoid ( (<>) )
import Data.String import Data.String
import Data.Text ( Text ) import Data.Text ( Text )
import Data.Versions import Data.Versions
@@ -240,7 +241,3 @@ addToCurrentEnv :: MonadIO m
addToCurrentEnv adds = do addToCurrentEnv adds = do
cEnv <- liftIO $ getEnvironment cEnv <- liftIO $ getEnvironment
pure (adds ++ cEnv) pure (adds ++ cEnv)
pvpToVersion :: PVP -> Version
pvpToVersion = either (\_ -> error "Couldn't convert PVP to Version") id . version . prettyPVP

View File

@@ -1,5 +1,4 @@
{-# OPTIONS_GHC -Wno-orphans #-} {-# OPTIONS_GHC -Wno-orphans #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveLift #-} {-# LANGUAGE DeriveLift #-}
{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FlexibleInstances #-}
@@ -12,12 +11,11 @@ module GHCup.Utils.Version.QQ where
import Data.Data import Data.Data
import Data.Text ( Text ) import Data.Text ( Text )
import Data.Versions import Data.Versions
#if !MIN_VERSION_base(4,13,0)
import GHC.Base import GHC.Base
#endif
import Language.Haskell.TH import Language.Haskell.TH
import Language.Haskell.TH.Quote ( QuasiQuoter(..) ) import Language.Haskell.TH.Quote ( QuasiQuoter(..) )
import Language.Haskell.TH.Syntax ( Lift import Language.Haskell.TH.Syntax ( Exp(..)
, Lift
, dataToExpQ , dataToExpQ
) )
import qualified Data.Text as T import qualified Data.Text as T
@@ -35,15 +33,12 @@ deriving instance Data Mess
deriving instance Lift Mess deriving instance Lift Mess
deriving instance Data PVP deriving instance Data PVP
deriving instance Lift PVP deriving instance Lift PVP
deriving instance Lift (NonEmpty Word)
deriving instance Lift VSep deriving instance Lift VSep
deriving instance Data VSep deriving instance Data VSep
deriving instance Lift VUnit deriving instance Lift VUnit
deriving instance Data VUnit deriving instance Data VUnit
#if !MIN_VERSION_base(4,13,0)
deriving instance Lift (NonEmpty Word)
instance Lift Text instance Lift Text
#endif
qq :: (Text -> Q Exp) -> QuasiQuoter qq :: (Text -> Q Exp) -> QuasiQuoter
qq quoteExp' = QuasiQuoter qq quoteExp' = QuasiQuoter

View File

@@ -6,12 +6,6 @@ module GHCup.Version where
import GHCup.Utils.Version.QQ import GHCup.Utils.Version.QQ
import Data.Versions import Data.Versions
import URI.ByteString
import URI.ByteString.QQ
-- | This reflects the API version of the JSON.
ghcupURL :: URI
ghcupURL = [uri|https://www.haskell.org/ghcup/data/ghcup-0.0.1.json|]
ghcUpVer :: PVP ghcUpVer :: PVP
ghcUpVer = [pver|0.1.4|] ghcUpVer = [pver|0.0.0|]

39
stack.yaml Normal file
View File

@@ -0,0 +1,39 @@
resolver: lts-14.27
packages:
- .
extra-deps:
- IfElse-0.85@sha256:6939b94acc6a55f545f63a168a349dd2fbe4b9a7cca73bf60282db5cc6aa47d2
- ascii-string-1.0.1.3
- brotli-0.0.0.0@sha256:448061ceabdcaa752bbaf208f255bbb7e90bbcf8ea8a913d26ffa7887636823b
- brotli-streams-0.0.0.0@sha256:c75a1d5d33420cbc9399c315e9b50a1976a5370f4fa8a40c71e11d011c2fedd6
- case-insensitive-1.2.1.0
- data-default-instances-base-0.1.0.1@sha256:985a13d7103e45a65f06f277b735ef025636014f0d29dd6de998bc7628e09be9
- fusion-plugin-types-0.1.0@sha256:0f11bbc445ab8ae3dbbb3d5d2ea198bdb1ac020518b7f4f7579035dc89182438
- generics-sop-0.5.0.0
- haskus-utils-data-1.2@sha256:48f62aa23d84b94edd0338379d3b3d74a34d3c2dbabf8c448a774a89ca70ea5d
- haskus-utils-types-1.5
- haskus-utils-variant-3.0
- hpath-0.11.0
- hpath-directory-0.13.2
- hpath-filepath-0.10.4
- hpath-io-0.13.1
- hpath-posix-0.13.1
- http-io-streams-0.1.2.0
- indexed-profunctors-0.1@sha256:ddf618d0d4c58319c1e735e746bc69a1021f13b6f475dc9614b80af03432e6d4
- language-bash-0.9.0
- optics-0.2
- optics-core-0.2@sha256:cfdf39871553769b59fcc54863a3521d262ea25d8d05d0f41ab87296c560cfa6
- optics-extra-0.2@sha256:211ce1dfd1b3ffd95c1158d8c8beb53cbd17c4d477169e226b1831607f6789eb
- optics-th-0.2@sha256:b4f6c5a3f134c697837190ed6da969dd284aefe79e43c3ef793093b607bb83b9
- optics-vl-0.2
- optparse-applicative-0.15.1.0
- pretty-terminal-0.1.0.0
- sop-core-0.5.0.0@sha256:8734ab38b8c84837094eec657da0b58942e481e20166131f34cf6c7fe9787b07
- streamly-0.7.1
- streamly-bytestring-0.1.2
- streamly-posix-0.1.0.0
- strict-base-0.4.0.0
- string-interpolate-0.2.0.0
- table-layout-0.8.0.5
- tar-bytestring-0.6.3.0
- time-1.9.3

View File

@@ -1,208 +0,0 @@
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.

View File

@@ -1 +0,0 @@
<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>

Before

Width:  |  Height:  |  Size: 696 B

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,92 +0,0 @@
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.

Binary file not shown.

View File

@@ -1,240 +0,0 @@
@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;
}

View File

@@ -1,166 +0,0 @@
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();
}());

View File

@@ -1,66 +0,0 @@
<?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>

Before

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -1,177 +0,0 @@
<!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>
&nbsp;&middot;&nbsp;
<a href="https://gitlab.haskell.org/haskell/ghcup-hs">about ghcup</a>
&nbsp;&middot;&nbsp;
<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&amp;channels=%23haskell&amp;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>
&nbsp;&middot;&nbsp;
<a href="https://gitlab.haskell.org/haskell/ghcup-hs">about ghcup</a>
&nbsp;&middot;&nbsp;
<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
View File

@@ -1,427 +0,0 @@
/*! 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;
}