Compare commits
225 Commits
issue-364
...
readDirEnt
| Author | SHA1 | Date | |
|---|---|---|---|
|
6d3e8d65e1
|
|||
|
895e4b3f18
|
|||
|
20f0505120
|
|||
|
31e83cac5e
|
|||
|
d3a1115b99
|
|||
|
6d46849fec
|
|||
|
53e324bfee
|
|||
|
2e39b7b603
|
|||
|
048932bf50
|
|||
|
69d325bf90
|
|||
|
3d1b8859cd
|
|||
|
db89ca9942
|
|||
|
bba009d98c
|
|||
|
9d954ea174
|
|||
|
da9c9049d2
|
|||
|
a4c00d2c56
|
|||
|
|
b30f565871 | ||
|
|
fa378a1d34 | ||
|
|
119efb1ff4 | ||
|
1fb4101b49
|
|||
|
ec8333b223
|
|||
|
54b979aa0b
|
|||
|
ba274307c0
|
|||
|
|
a623d0809d | ||
|
e00899d176
|
|||
|
a38ca1954b
|
|||
|
3f5a19c63e
|
|||
|
525e9672e8
|
|||
|
070c6e1cf1
|
|||
|
195fd00e0a
|
|||
|
733d014c19
|
|||
|
16039769d5
|
|||
|
5eeb8ca9fc
|
|||
|
317a06bbc3
|
|||
|
f693adcd7c
|
|||
|
ac88d2bd50
|
|||
|
a427146de5
|
|||
|
a16bcddeaa
|
|||
|
74edf1fc07
|
|||
|
1e32639873
|
|||
|
0704d2640a
|
|||
|
26a6368d79
|
|||
|
54af66d115
|
|||
|
850799c21a
|
|||
| d4834d7541 | |||
|
2895dd9d13
|
|||
|
eb9a0b66c4
|
|||
|
8d0432b961
|
|||
|
ab2c01d1c9
|
|||
|
fffaa65b7f
|
|||
|
703be0a706
|
|||
|
4be97ffd7c
|
|||
|
009f9211a9
|
|||
|
109187eb6f
|
|||
|
e881705323
|
|||
|
ea06c155a7
|
|||
|
d4732e15a7
|
|||
|
db6f784a1f
|
|||
|
82e3837dd9
|
|||
|
957c5918b8
|
|||
|
9d4c923649
|
|||
|
24c36ef856
|
|||
|
2783b8f693
|
|||
|
d5a680e3c6
|
|||
|
d1075987de
|
|||
|
e116a2392e
|
|||
|
7dd6f1f4a4
|
|||
|
4d82c37539
|
|||
|
801b1edfa7
|
|||
|
c1b67e1787
|
|||
|
70dd106549
|
|||
|
b098aa4e65
|
|||
|
74b784fcfb
|
|||
|
673db344d6
|
|||
|
5594a19c02
|
|||
|
|
a5bc13fe50 | ||
|
a5f2067d76
|
|||
|
be8fa57be1
|
|||
|
6ad9963889
|
|||
|
bcddb05b1d
|
|||
|
f7d2033e25
|
|||
|
6ce7649cfe
|
|||
|
cb0d8b80c3
|
|||
|
95869f9560
|
|||
|
e8586cf993
|
|||
|
d195a3f86c
|
|||
|
b171afa09d
|
|||
|
5cf49bffac
|
|||
|
5659de8516
|
|||
|
0cd2b6d549
|
|||
|
ae092de4b6
|
|||
|
a7e6e7c27d
|
|||
|
175a301a0d
|
|||
|
823458910b
|
|||
|
2abcb46199
|
|||
|
75b891147a
|
|||
|
de208f004e
|
|||
|
ecb0676fea
|
|||
|
957867ff1c
|
|||
|
b1b21f000d
|
|||
|
fbbafc33be
|
|||
|
4a46de4c49
|
|||
|
77419ea41d
|
|||
|
043500e8e8
|
|||
|
e924ad8278
|
|||
|
010db93b93
|
|||
|
9fdc6eebe8
|
|||
|
7c8d013b6e
|
|||
|
96eb0c3532
|
|||
|
94c01ee362
|
|||
|
4297a46f13
|
|||
|
c07e1bbc8f
|
|||
|
9ee2df3841
|
|||
|
3c5505d222
|
|||
|
|
70df740f9d | ||
|
|
761f3253c3 | ||
|
787edc17af
|
|||
|
9902adab6d
|
|||
|
156b4724f3
|
|||
|
e9575aba5c
|
|||
|
81c7f6a32a
|
|||
|
|
ab97c80b80 | ||
|
|
04369673ef | ||
|
|
63dfdc2da6 | ||
|
14de382129
|
|||
|
d97c10dbe6
|
|||
|
|
8420bf093e | ||
|
|
5e28074522 | ||
|
c842c41a78
|
|||
|
8b93eaad59
|
|||
|
2cba97cf1c
|
|||
|
7d74178295
|
|||
|
c37bef55e9
|
|||
|
837ba8b46a
|
|||
|
|
c25e73408a | ||
|
|
71c3172cf5 | ||
|
|
1f2855a107 | ||
|
|
d949c4375e | ||
|
|
22f0081303 | ||
|
5562be18e3
|
|||
|
6baa891424
|
|||
|
a544feffb3
|
|||
|
3b6bb0df46
|
|||
|
60299b6bb8
|
|||
|
4d20f4e07c
|
|||
|
5f6b5f845d
|
|||
|
b0fecce0d1
|
|||
|
|
27c06ddde7 | ||
|
3154d2839b
|
|||
|
|
511d8d5ed8 | ||
|
fe22405ee1
|
|||
|
ea828cd13a
|
|||
|
00fa70b9de
|
|||
|
823275363c
|
|||
|
2f299ee48d
|
|||
|
284fe1b3b6
|
|||
|
35bda8d67a
|
|||
|
7a2a5074fa
|
|||
|
ce239ab88e
|
|||
|
f3c703d655
|
|||
|
b6ff5bc764
|
|||
|
b8aeb1f935
|
|||
|
9673d28d3e
|
|||
|
99a51d67a1
|
|||
|
b0ef0590a2
|
|||
|
256e1942f2
|
|||
|
aa71f0dfa1
|
|||
|
04d527c98a
|
|||
|
|
ca5c5550ab | ||
|
7b59621179
|
|||
|
9d59463ded
|
|||
|
|
3d49f79beb | ||
|
|
e9740d13fc | ||
|
|
2bd5a8fe1a | ||
|
|
0acccae523 | ||
|
974112016e
|
|||
|
9fb2889696
|
|||
|
63f22b28d7
|
|||
|
9a72fa13d5
|
|||
|
86a8a32032
|
|||
|
13e01ab453
|
|||
|
873dd77a6f
|
|||
|
544c618473
|
|||
|
a264cb088e
|
|||
|
1a43fddca9
|
|||
|
|
9ceb66ef21 | ||
|
|
7cbe38b011 | ||
|
|
3bbc1edb19 | ||
|
|
b8dac2d7cd | ||
|
bdfb1a3a9b
|
|||
|
9b8b3e8126
|
|||
|
d657c17df4
|
|||
|
|
0e1fd68d93 | ||
|
|
c7eceb2330 | ||
|
|
e143c06697 | ||
|
|
29da21f5dc | ||
|
028696d4be
|
|||
|
4022edb12e
|
|||
|
fde5044194
|
|||
|
3af1286ab7
|
|||
|
bcff46d3d4
|
|||
|
d1c72cdff4
|
|||
|
565bb59f45
|
|||
|
aae3f31c50
|
|||
|
0ce9b5d352
|
|||
|
bf0e5b37ca
|
|||
|
fe620835be
|
|||
|
c7dc77e6bc
|
|||
|
05c72a3de6
|
|||
|
0653844931
|
|||
|
7661046bcb
|
|||
|
16888a12d4
|
|||
|
9f7df33692
|
|||
|
b7007aa100
|
|||
|
03dfd0cba0
|
|||
|
0e64d1f22f
|
|||
|
c7774450bf
|
|||
|
9375255452
|
|||
|
b8b3a16589
|
|||
|
e1d86c77d0
|
|||
|
001d33eabb
|
|||
|
9ccf29903e
|
|||
|
2a2ace603b
|
|||
|
25f9ac71ca
|
|||
|
61e2801838
|
26
.cirrus.yml
Normal file
26
.cirrus.yml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
freebsd_instance:
|
||||||
|
image_family: freebsd-13-1
|
||||||
|
|
||||||
|
build_task:
|
||||||
|
name: build
|
||||||
|
env:
|
||||||
|
GHC_VER: 9.2.4
|
||||||
|
CABAL_VER: 3.8.1.0
|
||||||
|
ARTIFACT: "x86_64-portbld-freebsd-ghcup"
|
||||||
|
ARCH: 64
|
||||||
|
RUNNER_OS: FreeBSD
|
||||||
|
DISTRO: na
|
||||||
|
GITHUB_WORKSPACE: ${CIRRUS_WORKING_DIR}
|
||||||
|
JSON_VERSION: "0.0.7"
|
||||||
|
CIRRUS_CLONE_SUBMODULES: true
|
||||||
|
AWS_ACCESS_KEY_ID: ENCRYPTED[6ed6287e2dd78ab5f84b22232c5245834ab042bd8ba443883aaf4b4d1ecc0481add1fdfad5ae6f6a8cfb418e6f19b2fc]
|
||||||
|
AWS_SECRET_ACCESS_KEY: ENCRYPTED[16f3cda2954c7cee99444e6788eb5997382aa4ce1477e7523fef2586077541f43b5c816156961fc6b4677259679875a7]
|
||||||
|
S3_HOST: ENCRYPTED[ce961780a33159f7d1d8046956b5ac6ebc3bfc8149428e5f538576cda51d9f3d0c35b79cdd1e325793639ff6e31f889d]
|
||||||
|
install_script: pkg install -y ghc hs-cabal-install git bash misc/compat10x misc/compat11x misc/compat12x gmake llvm14
|
||||||
|
script:
|
||||||
|
- tzsetup Etc/GMT
|
||||||
|
- adjkerntz -a
|
||||||
|
- bash .github/scripts/build.sh
|
||||||
|
- bash .github/scripts/test.sh
|
||||||
|
binaries_artifacts:
|
||||||
|
path: "out/*"
|
||||||
4946
.github/ghc-8.10.3-linux.alpine.files
vendored
Normal file
4946
.github/ghc-8.10.3-linux.alpine.files
vendored
Normal file
File diff suppressed because it is too large
Load Diff
8734
.github/ghc-8.10.3-linux.files
vendored
Normal file
8734
.github/ghc-8.10.3-linux.files
vendored
Normal file
File diff suppressed because it is too large
Load Diff
10321
.github/ghc-8.10.3-windows.files
vendored
Normal file
10321
.github/ghc-8.10.3-windows.files
vendored
Normal file
File diff suppressed because it is too large
Load Diff
37
.github/ghcup-run.files
vendored
Normal file
37
.github/ghcup-run.files
vendored
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
.
|
||||||
|
./cabal
|
||||||
|
./ghc
|
||||||
|
./ghc-8.10.7
|
||||||
|
./ghc-pkg
|
||||||
|
./ghc-pkg-8.10.7
|
||||||
|
./ghci
|
||||||
|
./ghci-8.10.7
|
||||||
|
./haddock
|
||||||
|
./haddock-8.10.7
|
||||||
|
./haskell-language-server-8.10.6
|
||||||
|
./haskell-language-server-8.10.6~1.6.1.0
|
||||||
|
./haskell-language-server-8.10.7
|
||||||
|
./haskell-language-server-8.10.7~1.6.1.0
|
||||||
|
./haskell-language-server-8.6.5
|
||||||
|
./haskell-language-server-8.6.5~1.6.1.0
|
||||||
|
./haskell-language-server-8.8.4
|
||||||
|
./haskell-language-server-8.8.4~1.6.1.0
|
||||||
|
./haskell-language-server-9.0.1
|
||||||
|
./haskell-language-server-9.0.1~1.6.1.0
|
||||||
|
./haskell-language-server-9.0.2
|
||||||
|
./haskell-language-server-9.0.2~1.6.1.0
|
||||||
|
./haskell-language-server-9.2.1
|
||||||
|
./haskell-language-server-9.2.1~1.6.1.0
|
||||||
|
./haskell-language-server-wrapper
|
||||||
|
./haskell-language-server-wrapper-1.6.1.0
|
||||||
|
./hp2ps
|
||||||
|
./hp2ps-8.10.7
|
||||||
|
./hpc
|
||||||
|
./hpc-8.10.7
|
||||||
|
./hsc2hs
|
||||||
|
./hsc2hs-8.10.7
|
||||||
|
./runghc
|
||||||
|
./runghc-8.10.7
|
||||||
|
./runhaskell
|
||||||
|
./runhaskell-8.10.7
|
||||||
|
./stack
|
||||||
31
.github/ghcup-run.files.alpine
vendored
Normal file
31
.github/ghcup-run.files.alpine
vendored
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
.
|
||||||
|
./cabal
|
||||||
|
./ghc
|
||||||
|
./ghc-8.10.7
|
||||||
|
./ghc-pkg
|
||||||
|
./ghc-pkg-8.10.7
|
||||||
|
./ghci
|
||||||
|
./ghci-8.10.7
|
||||||
|
./haddock
|
||||||
|
./haddock-8.10.7
|
||||||
|
./haskell-language-server-8.10.7
|
||||||
|
./haskell-language-server-8.10.7~1.6.1.0
|
||||||
|
./haskell-language-server-8.8.4
|
||||||
|
./haskell-language-server-8.8.4~1.6.1.0
|
||||||
|
./haskell-language-server-9.0.2
|
||||||
|
./haskell-language-server-9.0.2~1.6.1.0
|
||||||
|
./haskell-language-server-9.2.1
|
||||||
|
./haskell-language-server-9.2.1~1.6.1.0
|
||||||
|
./haskell-language-server-wrapper
|
||||||
|
./haskell-language-server-wrapper-1.6.1.0
|
||||||
|
./hp2ps
|
||||||
|
./hp2ps-8.10.7
|
||||||
|
./hpc
|
||||||
|
./hpc-8.10.7
|
||||||
|
./hsc2hs
|
||||||
|
./hsc2hs-8.10.7
|
||||||
|
./runghc
|
||||||
|
./runghc-8.10.7
|
||||||
|
./runhaskell
|
||||||
|
./runhaskell-8.10.7
|
||||||
|
./stack
|
||||||
81
.github/ghcup-run.files.windows
vendored
Normal file
81
.github/ghcup-run.files.windows
vendored
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
.
|
||||||
|
./cabal.exe
|
||||||
|
./cabal.shim
|
||||||
|
./ghc-8.10.7.exe
|
||||||
|
./ghc-8.10.7.shim
|
||||||
|
./ghc-pkg-8.10.7.exe
|
||||||
|
./ghc-pkg-8.10.7.shim
|
||||||
|
./ghc-pkg.exe
|
||||||
|
./ghc-pkg.shim
|
||||||
|
./ghc.exe
|
||||||
|
./ghc.shim
|
||||||
|
./ghci-8.10.7.exe
|
||||||
|
./ghci-8.10.7.shim
|
||||||
|
./ghci.exe
|
||||||
|
./ghci.shim
|
||||||
|
./ghcii-8.10.7.sh-8.10.7.exe
|
||||||
|
./ghcii-8.10.7.sh-8.10.7.shim
|
||||||
|
./ghcii-8.10.7.sh.exe
|
||||||
|
./ghcii-8.10.7.sh.shim
|
||||||
|
./ghcii.sh-8.10.7.exe
|
||||||
|
./ghcii.sh-8.10.7.shim
|
||||||
|
./ghcii.sh.exe
|
||||||
|
./ghcii.sh.shim
|
||||||
|
./haddock-8.10.7.exe
|
||||||
|
./haddock-8.10.7.shim
|
||||||
|
./haddock.exe
|
||||||
|
./haddock.shim
|
||||||
|
./haskell-language-server-8.10.6.exe
|
||||||
|
./haskell-language-server-8.10.6.shim
|
||||||
|
./haskell-language-server-8.10.6~1.6.1.0.exe
|
||||||
|
./haskell-language-server-8.10.6~1.6.1.0.shim
|
||||||
|
./haskell-language-server-8.10.7.exe
|
||||||
|
./haskell-language-server-8.10.7.shim
|
||||||
|
./haskell-language-server-8.10.7~1.6.1.0.exe
|
||||||
|
./haskell-language-server-8.10.7~1.6.1.0.shim
|
||||||
|
./haskell-language-server-8.6.5.exe
|
||||||
|
./haskell-language-server-8.6.5.shim
|
||||||
|
./haskell-language-server-8.6.5~1.6.1.0.exe
|
||||||
|
./haskell-language-server-8.6.5~1.6.1.0.shim
|
||||||
|
./haskell-language-server-8.8.4.exe
|
||||||
|
./haskell-language-server-8.8.4.shim
|
||||||
|
./haskell-language-server-8.8.4~1.6.1.0.exe
|
||||||
|
./haskell-language-server-8.8.4~1.6.1.0.shim
|
||||||
|
./haskell-language-server-9.0.1.exe
|
||||||
|
./haskell-language-server-9.0.1.shim
|
||||||
|
./haskell-language-server-9.0.1~1.6.1.0.exe
|
||||||
|
./haskell-language-server-9.0.1~1.6.1.0.shim
|
||||||
|
./haskell-language-server-9.0.2.exe
|
||||||
|
./haskell-language-server-9.0.2.shim
|
||||||
|
./haskell-language-server-9.0.2~1.6.1.0.exe
|
||||||
|
./haskell-language-server-9.0.2~1.6.1.0.shim
|
||||||
|
./haskell-language-server-9.2.1.exe
|
||||||
|
./haskell-language-server-9.2.1.shim
|
||||||
|
./haskell-language-server-9.2.1~1.6.1.0.exe
|
||||||
|
./haskell-language-server-9.2.1~1.6.1.0.shim
|
||||||
|
./haskell-language-server-wrapper-1.6.1.0.exe
|
||||||
|
./haskell-language-server-wrapper-1.6.1.0.shim
|
||||||
|
./haskell-language-server-wrapper.exe
|
||||||
|
./haskell-language-server-wrapper.shim
|
||||||
|
./hp2ps-8.10.7.exe
|
||||||
|
./hp2ps-8.10.7.shim
|
||||||
|
./hp2ps.exe
|
||||||
|
./hp2ps.shim
|
||||||
|
./hpc-8.10.7.exe
|
||||||
|
./hpc-8.10.7.shim
|
||||||
|
./hpc.exe
|
||||||
|
./hpc.shim
|
||||||
|
./hsc2hs-8.10.7.exe
|
||||||
|
./hsc2hs-8.10.7.shim
|
||||||
|
./hsc2hs.exe
|
||||||
|
./hsc2hs.shim
|
||||||
|
./runghc-8.10.7.exe
|
||||||
|
./runghc-8.10.7.shim
|
||||||
|
./runghc.exe
|
||||||
|
./runghc.shim
|
||||||
|
./runhaskell-8.10.7.exe
|
||||||
|
./runhaskell-8.10.7.shim
|
||||||
|
./runhaskell.exe
|
||||||
|
./runhaskell.shim
|
||||||
|
./stack.exe
|
||||||
|
./stack.shim
|
||||||
18
.github/scripts/bootstrap.sh
vendored
Normal file
18
.github/scripts/bootstrap.sh
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -eux
|
||||||
|
|
||||||
|
. .github/scripts/env.sh
|
||||||
|
|
||||||
|
mkdir -p "$CI_PROJECT_DIR"/.local/bin
|
||||||
|
|
||||||
|
git describe --always
|
||||||
|
|
||||||
|
### build
|
||||||
|
|
||||||
|
./scripts/bootstrap/bootstrap-haskell
|
||||||
|
|
||||||
|
[ "$(ghc --numeric-version)" = "${BOOTSTRAP_HASKELL_GHC_VERSION}" ]
|
||||||
|
# https://github.com/actions/runner-images/issues/7061
|
||||||
|
[ "$(ghcup config | grep --color=never meta-mode)" = "meta-mode: Lax" ]
|
||||||
|
|
||||||
27
.github/scripts/brew.sh
vendored
Normal file
27
.github/scripts/brew.sh
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -eux
|
||||||
|
|
||||||
|
. .github/scripts/env.sh
|
||||||
|
|
||||||
|
if [ -e "$HOME/.brew" ] ; then
|
||||||
|
(
|
||||||
|
cd "$HOME/.brew"
|
||||||
|
git fetch --depth 1
|
||||||
|
git reset --hard origin/master
|
||||||
|
)
|
||||||
|
else
|
||||||
|
git clone --depth=1 https://github.com/Homebrew/brew "$HOME/.brew"
|
||||||
|
fi
|
||||||
|
export PATH="$HOME/.brew/bin:$HOME/.brew/sbin:$PATH"
|
||||||
|
|
||||||
|
mkdir -p $CI_PROJECT_DIR/.brew_cache
|
||||||
|
export HOMEBREW_CACHE=$CI_PROJECT_DIR/.brew_cache
|
||||||
|
mkdir -p $CI_PROJECT_DIR/.brew_logs
|
||||||
|
export HOMEBREW_LOGS=$CI_PROJECT_DIR/.brew_logs
|
||||||
|
mkdir -p /private/tmp/.brew_tmp
|
||||||
|
export HOMEBREW_TEMP=/private/tmp/.brew_tmp
|
||||||
|
|
||||||
|
brew update
|
||||||
|
brew install ${1+"$@"}
|
||||||
|
|
||||||
35
.github/scripts/build.sh
vendored
Normal file
35
.github/scripts/build.sh
vendored
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -eux
|
||||||
|
|
||||||
|
. .github/scripts/common.sh
|
||||||
|
|
||||||
|
git_describe
|
||||||
|
|
||||||
|
# ensure ghcup
|
||||||
|
install_ghcup
|
||||||
|
|
||||||
|
# ensure cabal-cache
|
||||||
|
download_cabal_cache "$HOME/.local/bin/cabal-cache"
|
||||||
|
|
||||||
|
# install toolchain (if necessary)
|
||||||
|
ghcup -v install ghc --set --force "$GHC_VER"
|
||||||
|
ghcup -v install cabal --force "$CABAL_VER"
|
||||||
|
ghc --version
|
||||||
|
cabal --version
|
||||||
|
GHC="ghc-${GHC_VER}"
|
||||||
|
|
||||||
|
# build
|
||||||
|
ecabal update
|
||||||
|
build_with_cache --project-file=cabal.project.release -w "${GHC}" --enable-tests
|
||||||
|
|
||||||
|
# set up artifacts
|
||||||
|
mkdir -p out
|
||||||
|
binary=$(cabal --project-file=cabal.project.release list-bin ghcup)
|
||||||
|
binary_test=$(cabal --project-file=cabal.project.release list-bin ghcup-test)
|
||||||
|
ver=$("${binary}" --numeric-version)
|
||||||
|
strip_binary "${binary}"
|
||||||
|
cp "${binary}" "out/${ARTIFACT}-${ver}${ext}"
|
||||||
|
cp "${binary_test}" "out/test-${ARTIFACT}-${ver}${ext}"
|
||||||
|
cp ./dist-newstyle/cache/plan.json "out/${ARTIFACT}.plan.json"
|
||||||
|
|
||||||
149
.github/scripts/common.sh
vendored
Normal file
149
.github/scripts/common.sh
vendored
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
. .github/scripts/env.sh
|
||||||
|
|
||||||
|
ecabal() {
|
||||||
|
cabal "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
nonfatal() {
|
||||||
|
"$@" || "$* failed"
|
||||||
|
}
|
||||||
|
|
||||||
|
sync_from() {
|
||||||
|
if [ "${RUNNER_OS}" != "Windows" ] ; then
|
||||||
|
cabal_store_path="$(dirname "$(cabal help user-config | tail -n 1 | xargs)")/store"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cabal-cache sync-from-archive \
|
||||||
|
--host-name-override=${S3_HOST} \
|
||||||
|
--host-port-override=443 \
|
||||||
|
--host-ssl-override=True \
|
||||||
|
--region us-west-2 \
|
||||||
|
$([ "${RUNNER_OS}" != "Windows" ] && echo --store-path="$cabal_store_path") \
|
||||||
|
--archive-uri "s3://ghcup-hs/${RUNNER_OS}-${ARCH}-${DISTRO}"
|
||||||
|
}
|
||||||
|
|
||||||
|
sync_to() {
|
||||||
|
if [ "${RUNNER_OS}" != "Windows" ] ; then
|
||||||
|
cabal_store_path="$(dirname "$(cabal help user-config | tail -n 1 | xargs)")/store"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cabal-cache sync-to-archive \
|
||||||
|
--host-name-override=${S3_HOST} \
|
||||||
|
--host-port-override=443 \
|
||||||
|
--host-ssl-override=True \
|
||||||
|
--region us-west-2 \
|
||||||
|
$([ "${RUNNER_OS}" != "Windows" ] && echo --store-path="$cabal_store_path") \
|
||||||
|
--archive-uri "s3://ghcup-hs/${RUNNER_OS}-${ARCH}-${DISTRO}"
|
||||||
|
}
|
||||||
|
|
||||||
|
raw_eghcup() {
|
||||||
|
"$GHCUP_BIN/ghcup${ext}" -v -c "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
eghcup() {
|
||||||
|
if [ "${OS}" = "Windows" ] ; then
|
||||||
|
"$GHCUP_BIN/ghcup${ext}" -c -s "file:/$CI_PROJECT_DIR/data/metadata/ghcup-${JSON_VERSION}.yaml" "$@"
|
||||||
|
else
|
||||||
|
"$GHCUP_BIN/ghcup${ext}" -c -s "file://$CI_PROJECT_DIR/data/metadata/ghcup-${JSON_VERSION}.yaml" "$@"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
sha_sum() {
|
||||||
|
if [ "${OS}" = "FreeBSD" ] ; then
|
||||||
|
sha256 "$@"
|
||||||
|
else
|
||||||
|
sha256sum "$@"
|
||||||
|
fi
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
git_describe() {
|
||||||
|
git config --global --get-all safe.directory | grep '^\*$' || git config --global --add safe.directory "*"
|
||||||
|
git describe --always
|
||||||
|
}
|
||||||
|
|
||||||
|
download_cabal_cache() {
|
||||||
|
(
|
||||||
|
set -e
|
||||||
|
mkdir -p "$HOME/.local/bin"
|
||||||
|
dest="$HOME/.local/bin/cabal-cache"
|
||||||
|
url=""
|
||||||
|
exe=""
|
||||||
|
cd /tmp
|
||||||
|
case "${RUNNER_OS}" in
|
||||||
|
"Linux")
|
||||||
|
case "${ARCH}" in
|
||||||
|
"32") url=https://downloads.haskell.org/~ghcup/unofficial-bindists/cabal-cache/experimental5/i386-linux-cabal-cache
|
||||||
|
;;
|
||||||
|
"64") url=https://downloads.haskell.org/~ghcup/unofficial-bindists/cabal-cache/experimental5/x86_64-linux-cabal-cache
|
||||||
|
;;
|
||||||
|
"ARM64") url=https://downloads.haskell.org/~ghcup/unofficial-bindists/cabal-cache/experimental5/aarch64-linux-cabal-cache
|
||||||
|
;;
|
||||||
|
"ARM") url=https://downloads.haskell.org/~ghcup/unofficial-bindists/cabal-cache/experimental5/armv7-linux-cabal-cache
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
"FreeBSD")
|
||||||
|
url=https://downloads.haskell.org/~ghcup/unofficial-bindists/cabal-cache/experimental5/x86_64-portbld-freebsd-cabal-cache
|
||||||
|
;;
|
||||||
|
"Windows")
|
||||||
|
exe=".exe"
|
||||||
|
url=https://downloads.haskell.org/~ghcup/unofficial-bindists/cabal-cache/experimental5/x86_64-mingw64-cabal-cache
|
||||||
|
;;
|
||||||
|
"macOS")
|
||||||
|
case "${ARCH}" in
|
||||||
|
"ARM64") url=https://downloads.haskell.org/~ghcup/unofficial-bindists/cabal-cache/experimental5/aarch64-apple-darwin-cabal-cache
|
||||||
|
;;
|
||||||
|
"64") url=https://downloads.haskell.org/~ghcup/unofficial-bindists/cabal-cache/experimental5/x86_64-apple-darwin-cabal-cache
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ -n "${url}" ] ; then
|
||||||
|
case "${url##*.}" in
|
||||||
|
"gz")
|
||||||
|
curl -L -o - "${url}" | gunzip > cabal-cache${exe}
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
curl -o cabal-cache${exe} -L "${url}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
sha_sum cabal-cache${exe}
|
||||||
|
mv "cabal-cache${exe}" "${dest}${exe}"
|
||||||
|
chmod +x "${dest}${exe}"
|
||||||
|
fi
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
build_with_cache() {
|
||||||
|
ecabal configure "$@"
|
||||||
|
ecabal build --dependencies-only "$@" --dry-run
|
||||||
|
sync_from
|
||||||
|
ecabal build --dependencies-only "$@" || sync_to
|
||||||
|
sync_to
|
||||||
|
ecabal build "$@"
|
||||||
|
sync_to
|
||||||
|
}
|
||||||
|
|
||||||
|
install_ghcup() {
|
||||||
|
curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | BOOTSTRAP_HASKELL_NONINTERACTIVE=1 BOOTSTRAP_HASKELL_MINIMAL=1 BOOTSTRAP_HASKELL_INSTALL_NO_STACK=yes sh
|
||||||
|
}
|
||||||
|
|
||||||
|
strip_binary() {
|
||||||
|
(
|
||||||
|
set -e
|
||||||
|
local binary=$1
|
||||||
|
case "$(uname -s)" in
|
||||||
|
"Darwin"|"darwin")
|
||||||
|
;;
|
||||||
|
MSYS_*|MINGW*)
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
strip -s "${binary}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
)
|
||||||
|
}
|
||||||
30
.github/scripts/env.sh
vendored
Normal file
30
.github/scripts/env.sh
vendored
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
if [ "${RUNNER_OS}" = "Windows" ] ; then
|
||||||
|
ext=".exe"
|
||||||
|
else
|
||||||
|
ext=''
|
||||||
|
fi
|
||||||
|
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
export TZ=Asia/Singapore
|
||||||
|
|
||||||
|
export OS="$RUNNER_OS"
|
||||||
|
export PATH="$HOME/.local/bin:$PATH"
|
||||||
|
|
||||||
|
if [ "${RUNNER_OS}" = "Windows" ] ; then
|
||||||
|
# on windows use pwd to get unix style path
|
||||||
|
CI_PROJECT_DIR="$(pwd)"
|
||||||
|
export CI_PROJECT_DIR
|
||||||
|
export GHCUP_INSTALL_BASE_PREFIX="/c"
|
||||||
|
export GHCUP_BIN="$GHCUP_INSTALL_BASE_PREFIX/ghcup/bin"
|
||||||
|
export PATH="$GHCUP_BIN:$PATH"
|
||||||
|
export CABAL_DIR="C:\\Users\\runneradmin\\AppData\\Roaming\\cabal"
|
||||||
|
else
|
||||||
|
export CI_PROJECT_DIR="${GITHUB_WORKSPACE}"
|
||||||
|
export GHCUP_INSTALL_BASE_PREFIX="$CI_PROJECT_DIR"
|
||||||
|
export GHCUP_BIN="$GHCUP_INSTALL_BASE_PREFIX/.ghcup/bin"
|
||||||
|
export PATH="$GHCUP_BIN:$PATH"
|
||||||
|
export CABAL_DIR="$CI_PROJECT_DIR/cabal"
|
||||||
|
export CABAL_CACHE="$CI_PROJECT_DIR/cabal-cache"
|
||||||
|
fi
|
||||||
72
.github/scripts/hls.sh
vendored
Normal file
72
.github/scripts/hls.sh
vendored
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -eux
|
||||||
|
|
||||||
|
. .github/scripts/common.sh
|
||||||
|
|
||||||
|
mkdir -p "$CI_PROJECT_DIR"/.local/bin
|
||||||
|
|
||||||
|
### build
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if [ "${OS}" = "Windows" ] ; then
|
||||||
|
GHCUP_DIR="${GHCUP_INSTALL_BASE_PREFIX}"/ghcup
|
||||||
|
else
|
||||||
|
GHCUP_DIR="${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -rf "${GHCUP_DIR}"
|
||||||
|
mkdir -p "${GHCUP_BIN}"
|
||||||
|
|
||||||
|
ls -lah out
|
||||||
|
find out
|
||||||
|
cp "out/${ARTIFACT}"-* "$GHCUP_BIN/ghcup${ext}"
|
||||||
|
chmod +x "$GHCUP_BIN/ghcup${ext}"
|
||||||
|
echo "$PATH"
|
||||||
|
|
||||||
|
"$GHCUP_BIN/ghcup${ext}" --version
|
||||||
|
eghcup --version
|
||||||
|
sha_sum "$GHCUP_BIN/ghcup${ext}"
|
||||||
|
sha_sum "$(raw_eghcup --offline whereis ghcup)"
|
||||||
|
|
||||||
|
git_describe
|
||||||
|
|
||||||
|
eghcup install ghc "${GHC_VERSION}"
|
||||||
|
eghcup install cabal "${CABAL_VERSION}"
|
||||||
|
|
||||||
|
ecabal update
|
||||||
|
|
||||||
|
if ! command -v cabal-cache ; then
|
||||||
|
download_cabal_cache "$HOME/.local/bin/cabal-cache"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! cabal-cache version ; then
|
||||||
|
build_cabal_cache "$HOME/.local/bin"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
eghcup debug-info
|
||||||
|
|
||||||
|
(
|
||||||
|
cd /tmp
|
||||||
|
git clone --depth 1 --branch "${HLS_TARGET_VERSION}" \
|
||||||
|
https://github.com/haskell/haskell-language-server.git \
|
||||||
|
"haskell-language-server-${HLS_TARGET_VERSION}"
|
||||||
|
cd "haskell-language-server-${HLS_TARGET_VERSION}/"
|
||||||
|
ecabal configure -w "ghc-${GHC_VERSION}" --disable-profiling --disable-tests --jobs="$(nproc)"
|
||||||
|
ecabal build --dependencies-only -w "ghc-${GHC_VERSION}" --disable-profiling --disable-tests --jobs="$(nproc)" --dry-run
|
||||||
|
sync_from
|
||||||
|
ecabal build --dependencies-only -w "ghc-${GHC_VERSION}" --disable-profiling --disable-tests --jobs="$(nproc)" || sync_to
|
||||||
|
sync_to
|
||||||
|
)
|
||||||
|
|
||||||
|
eghcup -v compile hls -j "$(nproc)" -g "${HLS_TARGET_VERSION}" --ghc "${GHC_VERSION}"
|
||||||
|
|
||||||
|
[ "$($(eghcup whereis hls "${HLS_TARGET_VERSION}") --numeric-version)" = "${HLS_TARGET_VERSION}" ] ||
|
||||||
|
[ "$($(eghcup whereis hls "${HLS_TARGET_VERSION}") --numeric-version | sed 's/.0$//')" = "${HLS_TARGET_VERSION}" ]
|
||||||
|
|
||||||
|
# nuke
|
||||||
|
eghcup nuke
|
||||||
|
[ ! -e "${GHCUP_DIR}" ]
|
||||||
|
|
||||||
262
.github/scripts/test.sh
vendored
Normal file
262
.github/scripts/test.sh
vendored
Normal file
@@ -0,0 +1,262 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -eux
|
||||||
|
|
||||||
|
. .github/scripts/common.sh
|
||||||
|
|
||||||
|
|
||||||
|
if [ "${OS}" = "Windows" ] ; then
|
||||||
|
GHCUP_DIR="${GHCUP_INSTALL_BASE_PREFIX}"/ghcup
|
||||||
|
else
|
||||||
|
GHCUP_DIR="${GHCUP_INSTALL_BASE_PREFIX}"/.ghcup
|
||||||
|
fi
|
||||||
|
|
||||||
|
git_describe
|
||||||
|
|
||||||
|
rm -rf "${GHCUP_DIR}"
|
||||||
|
mkdir -p "${GHCUP_BIN}"
|
||||||
|
|
||||||
|
cp "out/${ARTIFACT}"-* "$GHCUP_BIN/ghcup${ext}"
|
||||||
|
cp "out/test-${ARTIFACT}"-* "ghcup-test${ext}"
|
||||||
|
chmod +x "$GHCUP_BIN/ghcup${ext}"
|
||||||
|
chmod +x "ghcup-test${ext}"
|
||||||
|
|
||||||
|
"$GHCUP_BIN/ghcup${ext}" --version
|
||||||
|
eghcup --version
|
||||||
|
sha_sum "$GHCUP_BIN/ghcup${ext}"
|
||||||
|
sha_sum "$(raw_eghcup --offline whereis ghcup)"
|
||||||
|
|
||||||
|
### Haskell test suite
|
||||||
|
|
||||||
|
./ghcup-test${ext}
|
||||||
|
rm ghcup-test${ext}
|
||||||
|
|
||||||
|
### manual cli based testing
|
||||||
|
|
||||||
|
eghcup --numeric-version
|
||||||
|
|
||||||
|
eghcup install ghc ${GHC_VER}
|
||||||
|
eghcup unset ghc ${GHC_VER}
|
||||||
|
ls -lah "$(eghcup whereis -d ghc ${GHC_VER})"
|
||||||
|
[ "`$(eghcup whereis ghc ${GHC_VER}) --numeric-version`" = "${GHC_VER}" ]
|
||||||
|
[ "`eghcup run --ghc ${GHC_VER} -- ghc --numeric-version`" = "${GHC_VER}" ]
|
||||||
|
[ "`ghcup run --ghc ${GHC_VER} -- ghc -e 'Control.Monad.join (Control.Monad.fmap System.IO.putStr System.Environment.getExecutablePath)'`" = "`$(ghcup whereis ghc ${GHC_VER}) -e 'Control.Monad.join (Control.Monad.fmap System.IO.putStr System.Environment.getExecutablePath)'`" ]
|
||||||
|
eghcup set ghc ${GHC_VER}
|
||||||
|
eghcup install cabal ${CABAL_VER}
|
||||||
|
[ "`$(eghcup whereis cabal ${CABAL_VER}) --numeric-version`" = "${CABAL_VER}" ]
|
||||||
|
eghcup unset cabal
|
||||||
|
"$GHCUP_BIN"/cabal --version && exit 1 || echo yes
|
||||||
|
|
||||||
|
# make sure no cabal is set when running 'ghcup run' to check that PATH propagages properly
|
||||||
|
# https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/375
|
||||||
|
[ "`eghcup run --cabal ${CABAL_VER} -- cabal --numeric-version`" = "${CABAL_VER}" ]
|
||||||
|
eghcup set cabal ${CABAL_VER}
|
||||||
|
|
||||||
|
[ "`$(eghcup whereis cabal ${CABAL_VER}) --numeric-version`" = "${CABAL_VER}" ]
|
||||||
|
|
||||||
|
if [ "${OS}" != "FreeBSD" ] ; then
|
||||||
|
if [ "${ARCH}" = "64" ] && [ "${DISTRO}" != "Alpine" ] ; then
|
||||||
|
eghcup run --ghc 8.10.7 --cabal 3.4.1.0 --hls 1.6.1.0 --stack 2.7.3 --install --bindir "$(pwd)/.bin"
|
||||||
|
if [ "${OS}" = "Windows" ] ; then
|
||||||
|
cat "$( cd "$(dirname "$0")" ; pwd -P )/../ghcup-run.files.windows" | sort > expected.txt
|
||||||
|
elif [ "${DISTRO}" = "Alpine" ] ; then
|
||||||
|
cat "$( cd "$(dirname "$0")" ; pwd -P )/../ghcup-run.files.alpine" | sort > expected.txt
|
||||||
|
else
|
||||||
|
cat "$( cd "$(dirname "$0")" ; pwd -P )/../ghcup-run.files" | sort > expected.txt
|
||||||
|
fi
|
||||||
|
(cd ".bin" && find . | sort) > actual.txt
|
||||||
|
diff --strip-trailing-cr -w -u actual.txt expected.txt
|
||||||
|
rm actual.txt expected.txt
|
||||||
|
rm -rf .bin
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
cabal --version
|
||||||
|
|
||||||
|
eghcup debug-info
|
||||||
|
|
||||||
|
# also test etags
|
||||||
|
eghcup list
|
||||||
|
eghcup list -t ghc
|
||||||
|
eghcup list -t cabal
|
||||||
|
|
||||||
|
ghc_ver=$(ghc --numeric-version)
|
||||||
|
ghc --version
|
||||||
|
ghc-${ghc_ver} --version
|
||||||
|
if [ "${OS}" != "Windows" ] ; then
|
||||||
|
ghci --version
|
||||||
|
ghci-${ghc_ver} --version
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
if [ "${OS}" = "macOS" ] && [ "${ARCH}" = "ARM64" ] ; then
|
||||||
|
# missing bindists
|
||||||
|
echo
|
||||||
|
elif [ "${OS}" = "FreeBSD" ] ; then
|
||||||
|
# not enough space
|
||||||
|
echo
|
||||||
|
else
|
||||||
|
# test installing new ghc doesn't mess with currently set GHC
|
||||||
|
# https://gitlab.haskell.org/haskell/ghcup-hs/issues/7
|
||||||
|
if [ "${OS}" = "Linux" ] ; then
|
||||||
|
eghcup --downloader=wget prefetch ghc 8.10.3
|
||||||
|
eghcup --offline install ghc 8.10.3
|
||||||
|
if [ "${ARCH}" = "64" ] ; then
|
||||||
|
if [ "${DISTRO}" = "Alpine" ] ; then
|
||||||
|
(cat "$( cd "$(dirname "$0")" ; pwd -P )/../ghc-8.10.3-linux.alpine.files" | sort) > expected.txt
|
||||||
|
else
|
||||||
|
(cat "$( cd "$(dirname "$0")" ; pwd -P )/../ghc-8.10.3-linux.files" | sort) > expected.txt
|
||||||
|
fi
|
||||||
|
(cd "${GHCUP_DIR}/ghc/8.10.3/" && find . | sort) > actual.txt
|
||||||
|
# ignore docs
|
||||||
|
sed -i '/share\/doc/d' actual.txt
|
||||||
|
sed -i '/share\/doc/d' expected.txt
|
||||||
|
diff --strip-trailing-cr -w -u actual.txt expected.txt
|
||||||
|
rm actual.txt expected.txt
|
||||||
|
fi
|
||||||
|
elif [ "${OS}" = "Windows" ] ; then
|
||||||
|
eghcup prefetch ghc 8.10.3
|
||||||
|
eghcup --offline install ghc 8.10.3
|
||||||
|
(cat "$( cd "$(dirname "$0")" ; pwd -P )/../ghc-8.10.3-windows.files" | sort) > expected.txt
|
||||||
|
(cd "${GHCUP_DIR}/ghc/8.10.3/" && find . | sort) > actual.txt
|
||||||
|
diff --strip-trailing-cr -w -u actual.txt expected.txt
|
||||||
|
rm actual.txt expected.txt
|
||||||
|
else
|
||||||
|
eghcup prefetch ghc 8.10.3
|
||||||
|
eghcup --offline install ghc 8.10.3
|
||||||
|
fi
|
||||||
|
[ "$(ghc --numeric-version)" = "${ghc_ver}" ]
|
||||||
|
eghcup --offline set 8.10.3
|
||||||
|
eghcup set 8.10.3
|
||||||
|
[ "$(ghc --numeric-version)" = "8.10.3" ]
|
||||||
|
eghcup set ${GHC_VER}
|
||||||
|
[ "$(ghc --numeric-version)" = "${ghc_ver}" ]
|
||||||
|
eghcup unset ghc
|
||||||
|
"$GHCUP_BIN"/ghc --numeric-version && exit 1 || echo yes
|
||||||
|
eghcup set ${GHC_VER}
|
||||||
|
eghcup --offline rm 8.10.3
|
||||||
|
[ "$(ghc --numeric-version)" = "${ghc_ver}" ]
|
||||||
|
|
||||||
|
|
||||||
|
ls -lah "$GHCUP_BIN"
|
||||||
|
|
||||||
|
if [ "${OS}" = "macOS" ] ; then
|
||||||
|
eghcup install hls
|
||||||
|
$(eghcup whereis hls) --version
|
||||||
|
|
||||||
|
eghcup install stack
|
||||||
|
$(eghcup whereis stack) --version
|
||||||
|
elif [ "${OS}" = "Linux" ] ; then
|
||||||
|
if [ "${ARCH}" = "64" ] && [ "${DISTRO}" != "Alpine" ] ; then
|
||||||
|
eghcup install hls
|
||||||
|
haskell-language-server-wrapper --version
|
||||||
|
eghcup unset hls
|
||||||
|
"$GHCUP_BIN"/haskell-language-server-wrapper --version && exit 1 || echo yes
|
||||||
|
|
||||||
|
eghcup install stack
|
||||||
|
stack --version
|
||||||
|
eghcup unset stack
|
||||||
|
"$GHCUP_BIN"/stack --version && exit 1 || echo yes
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# check that lazy loading works for 'whereis'
|
||||||
|
cp "$CI_PROJECT_DIR/data/metadata/ghcup-${JSON_VERSION}.yaml" "$CI_PROJECT_DIR/data/metadata/ghcup-${JSON_VERSION}.yaml.bak"
|
||||||
|
echo '**' > "$CI_PROJECT_DIR/data/metadata/ghcup-${JSON_VERSION}.yaml"
|
||||||
|
eghcup whereis ghc $(ghc --numeric-version)
|
||||||
|
mv -f "$CI_PROJECT_DIR/data/metadata/ghcup-${JSON_VERSION}.yaml.bak" "$CI_PROJECT_DIR/data/metadata/ghcup-${JSON_VERSION}.yaml"
|
||||||
|
|
||||||
|
eghcup rm $(ghc --numeric-version)
|
||||||
|
|
||||||
|
# https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/116
|
||||||
|
if [ "${OS}" = "Linux" ] ; then
|
||||||
|
if [ "${ARCH}" = "64" ] ; then
|
||||||
|
eghcup install cabal -u https://downloads.haskell.org/~ghcup/unofficial-bindists/cabal/3.7.0.0-pre20220407/cabal-install-3.7-x86_64-linux-alpine.tar.xz 3.4.0.0-rc4
|
||||||
|
eghcup rm cabal 3.4.0.0-rc4
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
eghcup gc -c
|
||||||
|
|
||||||
|
# test etags
|
||||||
|
rm -f "${GHCUP_DIR}/cache/ghcup-${JSON_VERSION}.yaml"
|
||||||
|
raw_eghcup -s https://www.haskell.org/ghcup/data/ghcup-${JSON_VERSION}.yaml list
|
||||||
|
# snapshot yaml and etags file
|
||||||
|
etag=$(cat "${GHCUP_DIR}/cache/ghcup-${JSON_VERSION}.yaml.etags")
|
||||||
|
sha=$(sha_sum "${GHCUP_DIR}/cache/ghcup-${JSON_VERSION}.yaml")
|
||||||
|
# invalidate access time timer, which is 5minutes, so we re-download
|
||||||
|
touch -a -m -t '199901010101' "${GHCUP_DIR}/cache/ghcup-${JSON_VERSION}.yaml"
|
||||||
|
# redownload same file with some newlines added
|
||||||
|
raw_eghcup -s https://www.haskell.org/ghcup/exp/ghcup-${JSON_VERSION}.yaml list
|
||||||
|
# snapshot new yaml and etags file
|
||||||
|
etag2=$(cat "${GHCUP_DIR}/cache/ghcup-${JSON_VERSION}.yaml.etags")
|
||||||
|
sha2=$(sha_sum "${GHCUP_DIR}/cache/ghcup-${JSON_VERSION}.yaml")
|
||||||
|
# compare
|
||||||
|
[ "${etag}" != "${etag2}" ]
|
||||||
|
[ "${sha}" != "${sha2}" ]
|
||||||
|
# invalidate access time timer, which is 5minutes, but don't expect a re-download
|
||||||
|
touch -a -m -t '199901010101' "${GHCUP_DIR}/cache/ghcup-${JSON_VERSION}.yaml"
|
||||||
|
# this time, we expect the same hash and etag
|
||||||
|
raw_eghcup -s https://www.haskell.org/ghcup/exp/ghcup-${JSON_VERSION}.yaml list
|
||||||
|
etag3=$(cat "${GHCUP_DIR}/cache/ghcup-${JSON_VERSION}.yaml.etags")
|
||||||
|
sha3=$(sha_sum "${GHCUP_DIR}/cache/ghcup-${JSON_VERSION}.yaml")
|
||||||
|
[ "${etag2}" = "${etag3}" ]
|
||||||
|
[ "${sha2}" = "${sha3}" ]
|
||||||
|
|
||||||
|
# test isolated installs
|
||||||
|
if [ "${DISTRO}" != "Alpine" ] ; then
|
||||||
|
eghcup install ghc -i "$(pwd)/isolated" 8.10.5
|
||||||
|
[ "$(isolated/bin/ghc --numeric-version)" = "8.10.5" ]
|
||||||
|
! eghcup install ghc -i "$(pwd)/isolated" 8.10.5
|
||||||
|
if [ "${ARCH}" = "64" ] ; then
|
||||||
|
if [ "${OS}" = "Linux" ] || [ "${OS}" = "Windows" ] ; then
|
||||||
|
eghcup install cabal -i "$(pwd)/isolated" 3.4.0.0
|
||||||
|
[ "$(isolated/cabal --numeric-version)" = "3.4.0.0" ]
|
||||||
|
eghcup install stack -i "$(pwd)/isolated" 2.7.3
|
||||||
|
[ "$(isolated/stack --numeric-version)" = "2.7.3" ]
|
||||||
|
eghcup install hls -i "$(pwd)/isolated" 1.3.0
|
||||||
|
[ "$(isolated/haskell-language-server-wrapper --numeric-version)" = "1.3.0" ] ||
|
||||||
|
[ "$(isolated/haskell-language-server-wrapper --numeric-version)" = "1.3.0.0" ]
|
||||||
|
|
||||||
|
# test that isolated installs don't clean up target directory
|
||||||
|
cat <<EOF > "${GHCUP_BIN}/gmake"
|
||||||
|
#!/bin/bash
|
||||||
|
exit 1
|
||||||
|
EOF
|
||||||
|
chmod +x "${GHCUP_BIN}/gmake"
|
||||||
|
mkdir isolated_tainted/
|
||||||
|
touch isolated_tainted/lol
|
||||||
|
|
||||||
|
! eghcup install ghc -i "$(pwd)/isolated_tainted" 8.10.5 --force
|
||||||
|
[ -e "$(pwd)/isolated_tainted/lol" ]
|
||||||
|
rm "${GHCUP_BIN}/gmake"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
eghcup upgrade
|
||||||
|
eghcup upgrade -f
|
||||||
|
|
||||||
|
# restore old ghcup, because we want to test nuke
|
||||||
|
cp "out/${ARTIFACT}"-* "$GHCUP_BIN/ghcup${ext}"
|
||||||
|
chmod +x "$GHCUP_BIN/ghcup${ext}"
|
||||||
|
|
||||||
|
# test that doing fishy symlinks into GHCup dir doesn't cause weird stuff on 'ghcup nuke'
|
||||||
|
mkdir no_nuke/
|
||||||
|
mkdir no_nuke/bar
|
||||||
|
echo 'foo' > no_nuke/file
|
||||||
|
echo 'bar' > no_nuke/bar/file
|
||||||
|
ln -s "$CI_PROJECT_DIR"/no_nuke/ "${GHCUP_DIR}"/cache/no_nuke
|
||||||
|
ln -s "$CI_PROJECT_DIR"/no_nuke/ "${GHCUP_DIR}"/logs/no_nuke
|
||||||
|
|
||||||
|
# nuke
|
||||||
|
eghcup nuke
|
||||||
|
[ ! -e "${GHCUP_DIR}" ]
|
||||||
|
|
||||||
|
# make sure nuke doesn't resolve symlinks
|
||||||
|
[ -e "$CI_PROJECT_DIR"/no_nuke/file ]
|
||||||
|
[ -e "$CI_PROJECT_DIR"/no_nuke/bar/file ]
|
||||||
|
|
||||||
55
.github/workflows/bootstrap.yaml
vendored
Normal file
55
.github/workflows/bootstrap.yaml
vendored
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
name: Bootstrap tests
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
tags:
|
||||||
|
- 'v*'
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
bootstrap:
|
||||||
|
name: bootstrap
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
env:
|
||||||
|
BOOTSTRAP_HASKELL_CABAL_VERSION: 3.6.2.0
|
||||||
|
BOOTSTRAP_HASKELL_GHC_VERSION: 8.10.7
|
||||||
|
BOOTSTRAP_HASKELL_NONINTERACTIVE: yes
|
||||||
|
ARCH: 64
|
||||||
|
JSON_VERSION: "0.0.7"
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- os: ubuntu-latest
|
||||||
|
DISTRO: Ubuntu
|
||||||
|
- os: macOS-10.15
|
||||||
|
DISTRO: na
|
||||||
|
- os: windows-latest
|
||||||
|
DISTRO: na
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: 'true'
|
||||||
|
|
||||||
|
- if: runner.os == 'Linux'
|
||||||
|
name: Run bootstrap
|
||||||
|
run: |
|
||||||
|
sudo apt-get install -y libnuma-dev zlib1g-dev libgmp-dev libgmp10 libssl-dev liblzma-dev libbz2-dev git wget lsb-release software-properties-common gnupg2 apt-transport-https gcc autoconf automake build-essential curl gzip
|
||||||
|
sh ./.github/scripts/bootstrap.sh
|
||||||
|
env:
|
||||||
|
DISTRO: ${{ matrix.DISTRO }}
|
||||||
|
|
||||||
|
- if: runner.os == 'macOS'
|
||||||
|
name: Run bootstrap
|
||||||
|
run: sh ./.github/scripts/bootstrap.sh
|
||||||
|
env:
|
||||||
|
DISTRO: ${{ matrix.DISTRO }}
|
||||||
|
|
||||||
|
- if: runner.os == 'Windows'
|
||||||
|
name: Run bootstrap
|
||||||
|
run: ./scripts/bootstrap/bootstrap-haskell.ps1 -InstallDir ${GITHUB_WORKSPACE} -BootstrapUrl ${GITHUB_WORKSPACE}/bootstrap-haskell -InBash
|
||||||
|
shell: pwsh
|
||||||
37
.github/workflows/cache.yaml
vendored
Normal file
37
.github/workflows/cache.yaml
vendored
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
name: Cache eviction
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
key:
|
||||||
|
description: Which cache to evict
|
||||||
|
required: true
|
||||||
|
default: '/'
|
||||||
|
type: choice
|
||||||
|
options:
|
||||||
|
- FreeBSD-64-na
|
||||||
|
- Linux-32-Alpine
|
||||||
|
- Linux-64-Alpine
|
||||||
|
- Linux-64-Ubuntu
|
||||||
|
- Linux-ARM-Ubuntu
|
||||||
|
- Linux-ARM64-Ubuntu
|
||||||
|
- Windows-64-na
|
||||||
|
- macOS-64-na
|
||||||
|
- macOS-ARM64-na
|
||||||
|
- /
|
||||||
|
jobs:
|
||||||
|
evict:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Remove from S3
|
||||||
|
uses: vitorsgomes/s3-rm-action@master
|
||||||
|
with:
|
||||||
|
args: --recursive
|
||||||
|
env:
|
||||||
|
AWS_S3_ENDPOINT: https://${{ secrets.S3_HOST }}
|
||||||
|
AWS_S3_BUCKET: ghcup-hs
|
||||||
|
AWS_REGION: us-west-2
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||||
|
PATH_TO_DELETE: ${{ github.event.inputs.key }}
|
||||||
109
.github/workflows/docker.yaml
vendored
Normal file
109
.github/workflows/docker.yaml
vendored
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
name: Docker image builds
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 0 * * *'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
docker-alpine32:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v2
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
- name: Login to Docker Hub
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
- name: Build and push (alpine 32bit)
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
with:
|
||||||
|
context: ./docker/alpine32
|
||||||
|
push: true
|
||||||
|
tags: hasufell/i386-alpine-haskell:3.12
|
||||||
|
platforms: |
|
||||||
|
linux/i386
|
||||||
|
linux/amd64
|
||||||
|
|
||||||
|
docker-alpine:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v2
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
- name: Login to Docker Hub
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
- name: Build and push (alpine 64bit)
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
with:
|
||||||
|
context: ./docker/alpine64
|
||||||
|
push: true
|
||||||
|
tags: hasufell/alpine-haskell:3.12
|
||||||
|
platforms: linux/amd64
|
||||||
|
|
||||||
|
docker-arm32:
|
||||||
|
runs-on: [self-hosted, Linux, ARM64, aarch32-linux]
|
||||||
|
steps:
|
||||||
|
- uses: docker://arm64v8/ubuntu:focal
|
||||||
|
name: Cleanup (aarch64 linux)
|
||||||
|
with:
|
||||||
|
args: "find . -mindepth 1 -maxdepth 1 -exec rm -rf -- {} +"
|
||||||
|
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
|
||||||
|
- name: Login to Docker Hub
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Build and push
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
with:
|
||||||
|
context: ./docker/arm32v7
|
||||||
|
push: true
|
||||||
|
tags: hasufell/arm32v7-ubuntu-haskell:focal
|
||||||
|
platforms: linux/arm
|
||||||
|
|
||||||
|
docker-aarch:
|
||||||
|
runs-on: [self-hosted, Linux, ARM64]
|
||||||
|
steps:
|
||||||
|
- uses: docker://arm64v8/ubuntu:focal
|
||||||
|
name: Cleanup (aarch64 linux)
|
||||||
|
with:
|
||||||
|
args: "find . -mindepth 1 -maxdepth 1 -exec rm -rf -- {} +"
|
||||||
|
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
|
||||||
|
- name: Login to Docker Hub
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Build and push
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
with:
|
||||||
|
context: ./docker/arm64v8/
|
||||||
|
push: true
|
||||||
|
tags: hasufell/arm64v8-ubuntu-haskell:focal
|
||||||
|
platforms: linux/arm64
|
||||||
26
.github/workflows/hlint.yaml
vendored
Normal file
26
.github/workflows/hlint.yaml
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
name: Hlint
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
tags:
|
||||||
|
- 'v*'
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
hlint:
|
||||||
|
name: hlint
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
JSON_VERSION: "0.0.7"
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: 'true'
|
||||||
|
|
||||||
|
- name: Run hlint
|
||||||
|
run: curl -sSL https://raw.github.com/ndmitchell/hlint/master/misc/run.sh | sh -s -- -r lib/ test/
|
||||||
33
.github/workflows/mkdocs.yaml
vendored
Normal file
33
.github/workflows/mkdocs.yaml
vendored
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
name: MkDocs
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
tags:
|
||||||
|
- 'v*'
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
mkdocs:
|
||||||
|
name: mkdocs
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
JSON_VERSION: "0.0.7"
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: 'true'
|
||||||
|
|
||||||
|
- name: Install mkdocs deps
|
||||||
|
run: |
|
||||||
|
sudo apt-get update -y
|
||||||
|
sudo apt-get install -y python3-pip
|
||||||
|
sudo pip3 install mkdocs
|
||||||
|
|
||||||
|
- name: Run mkdocs
|
||||||
|
run: |
|
||||||
|
mkdocs build
|
||||||
581
.github/workflows/release.yaml
vendored
581
.github/workflows/release.yaml
vendored
@@ -1,109 +1,514 @@
|
|||||||
name: Create Release
|
name: Build and release
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
tags:
|
tags:
|
||||||
- 'v*'
|
- 'v*'
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
schedule:
|
||||||
|
- cron: '0 2 * * *'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
draft_release:
|
build-linux:
|
||||||
name: Draft Release
|
name: Build linux binary
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Create Release
|
|
||||||
id: create_release
|
|
||||||
uses: actions/create-release@v1
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
with:
|
|
||||||
tag_name: ${{ github.ref }}
|
|
||||||
release_name: Release ${{ github.ref }}
|
|
||||||
body: |
|
|
||||||
Changes in this Release
|
|
||||||
- First Change
|
|
||||||
- Second Change
|
|
||||||
draft: true
|
|
||||||
prerelease: false
|
|
||||||
|
|
||||||
release-mac:
|
|
||||||
name: Create Release
|
|
||||||
needs: draft_release
|
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
env:
|
env:
|
||||||
MACOSX_DEPLOYMENT_TARGET: 10.13
|
CABAL_VER: 3.8.1.0
|
||||||
|
JSON_VERSION: "0.0.7"
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||||
|
S3_HOST: ${{ secrets.S3_HOST }}
|
||||||
strategy:
|
strategy:
|
||||||
|
fail-fast: true
|
||||||
matrix:
|
matrix:
|
||||||
os:
|
include:
|
||||||
- macOS-10.15
|
- os: ubuntu-latest
|
||||||
|
ARTIFACT: "i386-linux-ghcup"
|
||||||
|
GHC_VER: 8.10.7
|
||||||
|
ARCH: 32
|
||||||
|
- os: ubuntu-latest
|
||||||
|
ARTIFACT: "x86_64-linux-ghcup"
|
||||||
|
GHC_VER: 8.10.7
|
||||||
|
ARCH: 64
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- uses: haskell/actions/setup@v1.2
|
|
||||||
with:
|
with:
|
||||||
ghc-version: 8.10.7
|
submodules: 'true'
|
||||||
cabal-version: 3.6.2.0
|
|
||||||
|
|
||||||
- name: create ~/.local/bin
|
- if: matrix.ARCH == '32'
|
||||||
run: mkdir -p "$HOME/.local/bin"
|
name: Run build (32 bit linux)
|
||||||
shell: bash
|
uses: docker://hasufell/i386-alpine-haskell:3.12
|
||||||
|
with:
|
||||||
- name: Add ~/.local/bin to PATH
|
args: sh .github/scripts/build.sh
|
||||||
run: echo "$HOME/.local/bin" >> $GITHUB_PATH
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
- name: Update cabal cache
|
|
||||||
run: cabal update
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
- name: Install cabal dependencies
|
|
||||||
run: cabal build --only-dependencies --constraint="zlib +bundled-c-zlib" --constraint="lzma +static" -ftui
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: cabal build --constraint="zlib +bundled-c-zlib" --constraint="lzma +static" -ftui
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
- name: Install
|
|
||||||
run: cp "$(cabal list-bin exe:ghcup)" ~/.local/bin/ghcup
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
- name: Strip
|
|
||||||
run: strip ~/.local/bin/ghcup
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
- name: Run tests
|
|
||||||
run: cabal test --constraint="zlib +bundled-c-zlib" --constraint="lzma +static" all
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
- name: Install git
|
|
||||||
run: brew install git
|
|
||||||
|
|
||||||
- name: set HOME
|
|
||||||
run: echo "HOME=$HOME" >> $GITHUB_ENV
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
- name: Set ASSET_PATH
|
|
||||||
run: echo "ASSET_PATH=$HOME/.local/bin/ghcup" >> $GITHUB_ENV
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
- name: Upload Release Asset
|
|
||||||
id: upload-release-asset
|
|
||||||
uses: actions/upload-release-asset@v1
|
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
ARTIFACT: ${{ matrix.ARTIFACT }}
|
||||||
|
ARCH: ${{ matrix.ARCH }}
|
||||||
|
GHC_VER: ${{ matrix.GHC_VER }}
|
||||||
|
DISTRO: Alpine
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ env.AWS_SECRET_ACCESS_KEY }}
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ env.AWS_ACCESS_KEY_ID }}
|
||||||
|
S3_HOST: ${{ env.S3_HOST }}
|
||||||
|
|
||||||
|
- if: matrix.ARCH == '64'
|
||||||
|
name: Run build (64 bit linux)
|
||||||
|
uses: docker://hasufell/alpine-haskell:3.12
|
||||||
with:
|
with:
|
||||||
upload_url: ${{ needs.draft_release.outputs.upload_url }}
|
args: sh .github/scripts/build.sh
|
||||||
asset_path: ${{ env.ASSET_PATH }}
|
env:
|
||||||
asset_name: ghcup-${{ matrix.os }}
|
ARTIFACT: ${{ matrix.ARTIFACT }}
|
||||||
asset_content_type: application/octet-stream
|
ARCH: ${{ matrix.ARCH }}
|
||||||
|
GHC_VER: ${{ matrix.GHC_VER }}
|
||||||
|
DISTRO: Alpine
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ env.AWS_SECRET_ACCESS_KEY }}
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ env.AWS_ACCESS_KEY_ID }}
|
||||||
|
S3_HOST: ${{ env.S3_HOST }}
|
||||||
|
|
||||||
- if: always()
|
- if: always()
|
||||||
uses: actions/upload-artifact@v2
|
name: Upload artifact
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: plan.json
|
name: artifacts
|
||||||
path: ./dist-newstyle/cache/plan.json
|
path: |
|
||||||
|
./out/*
|
||||||
|
|
||||||
|
|
||||||
|
build-arm:
|
||||||
|
name: Build ARM binary
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
env:
|
||||||
|
CABAL_VER: 3.8.1.0
|
||||||
|
JSON_VERSION: "0.0.7"
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||||
|
S3_HOST: ${{ secrets.S3_HOST }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: true
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- os: [self-hosted, Linux, ARM64, aarch32-linux]
|
||||||
|
ARTIFACT: "armv7-linux-ghcup"
|
||||||
|
GHC_VER: 9.2.2
|
||||||
|
ARCH: ARM
|
||||||
|
- os: [self-hosted, Linux, ARM64]
|
||||||
|
ARTIFACT: "aarch64-linux-ghcup"
|
||||||
|
GHC_VER: 9.2.5
|
||||||
|
ARCH: ARM64
|
||||||
|
steps:
|
||||||
|
- uses: docker://arm64v8/ubuntu:focal
|
||||||
|
name: Cleanup (aarch64 linux)
|
||||||
|
with:
|
||||||
|
args: "find . -mindepth 1 -maxdepth 1 -exec rm -rf -- {} +"
|
||||||
|
|
||||||
|
- name: git config
|
||||||
|
run: |
|
||||||
|
git config --global --get-all safe.directory | grep '^\*$' || git config --global --add safe.directory "*"
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: 'true'
|
||||||
|
|
||||||
|
- if: matrix.ARCH == 'ARM'
|
||||||
|
uses: docker://hasufell/arm32v7-ubuntu-haskell:focal
|
||||||
|
name: Run build (armv7 linux)
|
||||||
|
with:
|
||||||
|
args: sh .github/scripts/build.sh
|
||||||
|
env:
|
||||||
|
ARTIFACT: ${{ matrix.ARTIFACT }}
|
||||||
|
ARCH: ${{ matrix.ARCH }}
|
||||||
|
GHC_VER: ${{ matrix.GHC_VER }}
|
||||||
|
DISTRO: Ubuntu
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ env.AWS_SECRET_ACCESS_KEY }}
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ env.AWS_ACCESS_KEY_ID }}
|
||||||
|
S3_HOST: ${{ env.S3_HOST }}
|
||||||
|
|
||||||
|
- if: matrix.ARCH == 'ARM64'
|
||||||
|
uses: docker://hasufell/arm64v8-ubuntu-haskell:focal
|
||||||
|
name: Run build (aarch64 linux)
|
||||||
|
with:
|
||||||
|
args: sh .github/scripts/build.sh
|
||||||
|
env:
|
||||||
|
ARTIFACT: ${{ matrix.ARTIFACT }}
|
||||||
|
ARCH: ${{ matrix.ARCH }}
|
||||||
|
GHC_VER: ${{ matrix.GHC_VER }}
|
||||||
|
DISTRO: Ubuntu
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ env.AWS_SECRET_ACCESS_KEY }}
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ env.AWS_ACCESS_KEY_ID }}
|
||||||
|
S3_HOST: ${{ env.S3_HOST }}
|
||||||
|
|
||||||
|
- if: always()
|
||||||
|
name: Upload artifact
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: artifacts
|
||||||
|
path: |
|
||||||
|
./out/*
|
||||||
|
|
||||||
|
build-macwin:
|
||||||
|
name: Build binary (Mac/Win)
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
env:
|
||||||
|
CABAL_VER: 3.8.1.0
|
||||||
|
MACOSX_DEPLOYMENT_TARGET: 10.13
|
||||||
|
JSON_VERSION: "0.0.7"
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||||
|
S3_HOST: ${{ secrets.S3_HOST }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- os: [self-hosted, macOS, ARM64]
|
||||||
|
ARTIFACT: "aarch64-apple-darwin-ghcup"
|
||||||
|
GHC_VER: 9.2.5
|
||||||
|
ARCH: ARM64
|
||||||
|
- os: macOS-10.15
|
||||||
|
ARTIFACT: "x86_64-apple-darwin-ghcup"
|
||||||
|
GHC_VER: 9.2.5
|
||||||
|
ARCH: 64
|
||||||
|
- os: windows-latest
|
||||||
|
ARTIFACT: "x86_64-mingw64-ghcup"
|
||||||
|
GHC_VER: 8.10.7
|
||||||
|
ARCH: 64
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: 'true'
|
||||||
|
|
||||||
|
- if: matrix.ARCH == 'ARM64' && runner.os == 'macOS'
|
||||||
|
name: Run build
|
||||||
|
run: |
|
||||||
|
bash .github/scripts/brew.sh git coreutils llvm@11 autoconf automake
|
||||||
|
export PATH="$HOME/.brew/bin:$HOME/.brew/sbin:$HOME/.brew/opt/llvm@11/bin:$PATH"
|
||||||
|
export CC="$HOME/.brew/opt/llvm@11/bin/clang"
|
||||||
|
export CXX="$HOME/.brew/opt/llvm@11/bin/clang++"
|
||||||
|
export LD=ld
|
||||||
|
export AR="$HOME/.brew/opt/llvm@11/bin/llvm-ar"
|
||||||
|
export RANLIB="$HOME/.brew/opt/llvm@11/bin/llvm-ranlib"
|
||||||
|
bash .github/scripts/build.sh
|
||||||
|
env:
|
||||||
|
ARTIFACT: ${{ matrix.ARTIFACT }}
|
||||||
|
ARCH: ${{ matrix.ARCH }}
|
||||||
|
GHC_VER: ${{ matrix.GHC_VER }}
|
||||||
|
DISTRO: na
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ env.AWS_SECRET_ACCESS_KEY }}
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ env.AWS_ACCESS_KEY_ID }}
|
||||||
|
S3_HOST: ${{ env.S3_HOST }}
|
||||||
|
HOMEBREW_CHANGE_ARCH_TO_ARM: 1
|
||||||
|
|
||||||
|
- if: matrix.ARCH == '64' && runner.os == 'macOS'
|
||||||
|
name: Run build (windows/mac)
|
||||||
|
run: |
|
||||||
|
bash .github/scripts/brew.sh coreutils
|
||||||
|
export PATH="$HOME/.brew/bin:$HOME/.brew/sbin:$PATH"
|
||||||
|
bash .github/scripts/build.sh
|
||||||
|
env:
|
||||||
|
ARTIFACT: ${{ matrix.ARTIFACT }}
|
||||||
|
ARCH: ${{ matrix.ARCH }}
|
||||||
|
GHC_VER: ${{ matrix.GHC_VER }}
|
||||||
|
DISTRO: na
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ env.AWS_SECRET_ACCESS_KEY }}
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ env.AWS_ACCESS_KEY_ID }}
|
||||||
|
S3_HOST: ${{ env.S3_HOST }}
|
||||||
|
HOMEBREW_CHANGE_ARCH_TO_ARM: 1
|
||||||
|
|
||||||
|
- if: runner.os == 'Windows'
|
||||||
|
name: Run build (windows/mac)
|
||||||
|
run: |
|
||||||
|
bash .github/scripts/brew.sh git coreutils autoconf automake
|
||||||
|
bash .github/scripts/build.sh
|
||||||
|
env:
|
||||||
|
ARTIFACT: ${{ matrix.ARTIFACT }}
|
||||||
|
ARCH: ${{ matrix.ARCH }}
|
||||||
|
GHC_VER: ${{ matrix.GHC_VER }}
|
||||||
|
DISTRO: na
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ env.AWS_SECRET_ACCESS_KEY }}
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ env.AWS_ACCESS_KEY_ID }}
|
||||||
|
S3_HOST: ${{ env.S3_HOST }}
|
||||||
|
HOMEBREW_CHANGE_ARCH_TO_ARM: 1
|
||||||
|
|
||||||
|
- if: always()
|
||||||
|
name: Upload artifact
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: artifacts
|
||||||
|
path: |
|
||||||
|
./out/*
|
||||||
|
|
||||||
|
test-linux:
|
||||||
|
name: Test linux
|
||||||
|
needs: "build-linux"
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
env:
|
||||||
|
CABAL_VER: 3.8.1.0
|
||||||
|
JSON_VERSION: "0.0.7"
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- os: ubuntu-latest
|
||||||
|
ARTIFACT: "i386-linux-ghcup"
|
||||||
|
GHC_VER: 8.10.7
|
||||||
|
ARCH: 32
|
||||||
|
DISTRO: Alpine
|
||||||
|
- os: ubuntu-latest
|
||||||
|
ARTIFACT: "x86_64-linux-ghcup"
|
||||||
|
GHC_VER: 8.10.7
|
||||||
|
ARCH: 64
|
||||||
|
DISTRO: Alpine
|
||||||
|
- os: ubuntu-latest
|
||||||
|
ARTIFACT: "x86_64-linux-ghcup"
|
||||||
|
GHC_VER: 8.10.7
|
||||||
|
ARCH: 64
|
||||||
|
DISTRO: Ubuntu
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: 'true'
|
||||||
|
|
||||||
|
- uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: artifacts
|
||||||
|
path: ./out
|
||||||
|
|
||||||
|
- if: matrix.ARCH == '32' && matrix.DISTRO == 'Alpine'
|
||||||
|
name: Run test (32 bit linux Alpine)
|
||||||
|
uses: docker://hasufell/i386-alpine-haskell:3.12
|
||||||
|
with:
|
||||||
|
args: sh .github/scripts/test.sh
|
||||||
|
env:
|
||||||
|
ARTIFACT: ${{ matrix.ARTIFACT }}
|
||||||
|
ARCH: ${{ matrix.ARCH }}
|
||||||
|
GHC_VER: ${{ matrix.GHC_VER }}
|
||||||
|
DISTRO: ${{ matrix.DISTRO }}
|
||||||
|
|
||||||
|
- if: matrix.ARCH == '64' && matrix.DISTRO == 'Alpine'
|
||||||
|
name: Run test (64 bit linux Alpine)
|
||||||
|
uses: docker://hasufell/alpine-haskell:3.12
|
||||||
|
with:
|
||||||
|
args: sh .github/scripts/test.sh
|
||||||
|
env:
|
||||||
|
ARTIFACT: ${{ matrix.ARTIFACT }}
|
||||||
|
ARCH: ${{ matrix.ARCH }}
|
||||||
|
GHC_VER: ${{ matrix.GHC_VER }}
|
||||||
|
DISTRO: ${{ matrix.DISTRO }}
|
||||||
|
|
||||||
|
- if: matrix.DISTRO != 'Alpine'
|
||||||
|
name: Run test (64 bit linux)
|
||||||
|
run: |
|
||||||
|
sudo apt-get install -y libnuma-dev zlib1g-dev libgmp-dev libgmp10 libssl-dev liblzma-dev libbz2-dev git wget lsb-release software-properties-common gnupg2 apt-transport-https gcc autoconf automake build-essential curl gzip
|
||||||
|
sh .github/scripts/test.sh
|
||||||
|
env:
|
||||||
|
ARTIFACT: ${{ matrix.ARTIFACT }}
|
||||||
|
ARCH: ${{ matrix.ARCH }}
|
||||||
|
GHC_VER: ${{ matrix.GHC_VER }}
|
||||||
|
DISTRO: ${{ matrix.DISTRO }}
|
||||||
|
|
||||||
|
- if: failure()
|
||||||
|
name: Upload artifact
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: testfiles
|
||||||
|
path: |
|
||||||
|
./test/golden/unix/GHCupInfo*json
|
||||||
|
|
||||||
|
test-arm:
|
||||||
|
name: Test ARM
|
||||||
|
needs: "build-arm"
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
env:
|
||||||
|
CABAL_VER: 3.8.1.0
|
||||||
|
JSON_VERSION: "0.0.7"
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- os: [self-hosted, Linux, ARM64, aarch32-linux]
|
||||||
|
ARTIFACT: "armv7-linux-ghcup"
|
||||||
|
GHC_VER: 9.2.2
|
||||||
|
ARCH: ARM
|
||||||
|
DISTRO: Ubuntu
|
||||||
|
- os: [self-hosted, Linux, ARM64]
|
||||||
|
ARTIFACT: "aarch64-linux-ghcup"
|
||||||
|
GHC_VER: 9.2.5
|
||||||
|
ARCH: ARM64
|
||||||
|
DISTRO: Ubuntu
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: docker://arm64v8/ubuntu:focal
|
||||||
|
name: Cleanup (aarch64 linux)
|
||||||
|
with:
|
||||||
|
args: "find . -mindepth 1 -maxdepth 1 -exec rm -rf -- {} +"
|
||||||
|
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: 'true'
|
||||||
|
|
||||||
|
- uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: artifacts
|
||||||
|
path: ./out
|
||||||
|
|
||||||
|
- if: matrix.ARCH == 'ARM'
|
||||||
|
uses: docker://hasufell/arm32v7-ubuntu-haskell:focal
|
||||||
|
name: Run test (armv7 linux)
|
||||||
|
with:
|
||||||
|
args: sh .github/scripts/test.sh
|
||||||
|
env:
|
||||||
|
ARTIFACT: ${{ matrix.ARTIFACT }}
|
||||||
|
ARCH: ${{ matrix.ARCH }}
|
||||||
|
GHC_VER: ${{ matrix.GHC_VER }}
|
||||||
|
DISTRO: Ubuntu
|
||||||
|
|
||||||
|
- if: matrix.ARCH == 'ARM64'
|
||||||
|
uses: docker://hasufell/arm64v8-ubuntu-haskell:focal
|
||||||
|
name: Run test (aarch64 linux)
|
||||||
|
with:
|
||||||
|
args: sh .github/scripts/test.sh
|
||||||
|
env:
|
||||||
|
ARTIFACT: ${{ matrix.ARTIFACT }}
|
||||||
|
ARCH: ${{ matrix.ARCH }}
|
||||||
|
GHC_VER: ${{ matrix.GHC_VER }}
|
||||||
|
DISTRO: Ubuntu
|
||||||
|
|
||||||
|
- if: failure()
|
||||||
|
name: Upload artifact
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: testfiles
|
||||||
|
path: |
|
||||||
|
./test/golden/unix/GHCupInfo*json
|
||||||
|
|
||||||
|
test-macwin:
|
||||||
|
name: Test Mac/Win
|
||||||
|
needs: "build-macwin"
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
env:
|
||||||
|
CABAL_VER: 3.8.1.0
|
||||||
|
MACOSX_DEPLOYMENT_TARGET: 10.13
|
||||||
|
JSON_VERSION: "0.0.7"
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- os: [self-hosted, macOS, ARM64]
|
||||||
|
ARTIFACT: "aarch64-apple-darwin-ghcup"
|
||||||
|
GHC_VER: 9.2.5
|
||||||
|
ARCH: ARM64
|
||||||
|
DISTRO: na
|
||||||
|
- os: macOS-10.15
|
||||||
|
ARTIFACT: "x86_64-apple-darwin-ghcup"
|
||||||
|
GHC_VER: 9.2.5
|
||||||
|
ARCH: 64
|
||||||
|
DISTRO: na
|
||||||
|
- os: windows-latest
|
||||||
|
ARTIFACT: "x86_64-mingw64-ghcup"
|
||||||
|
GHC_VER: 8.10.7
|
||||||
|
ARCH: 64
|
||||||
|
DISTRO: na
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: 'true'
|
||||||
|
|
||||||
|
- uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: artifacts
|
||||||
|
path: ./out
|
||||||
|
|
||||||
|
- if: runner.os == 'macOS'
|
||||||
|
name: Run test
|
||||||
|
run: |
|
||||||
|
bash .github/scripts/brew.sh coreutils
|
||||||
|
export PATH="$HOME/.brew/bin:$HOME/.brew/sbin:$PATH"
|
||||||
|
bash .github/scripts/test.sh
|
||||||
|
env:
|
||||||
|
ARTIFACT: ${{ matrix.ARTIFACT }}
|
||||||
|
ARCH: ${{ matrix.ARCH }}
|
||||||
|
GHC_VER: ${{ matrix.GHC_VER }}
|
||||||
|
DISTRO: ${{ matrix.DISTRO }}
|
||||||
|
HOMEBREW_CHANGE_ARCH_TO_ARM: 1
|
||||||
|
|
||||||
|
- if: runner.os != 'macOS'
|
||||||
|
name: Run test
|
||||||
|
run: bash .github/scripts/test.sh
|
||||||
|
env:
|
||||||
|
ARTIFACT: ${{ matrix.ARTIFACT }}
|
||||||
|
ARCH: ${{ matrix.ARCH }}
|
||||||
|
GHC_VER: ${{ matrix.GHC_VER }}
|
||||||
|
DISTRO: ${{ matrix.DISTRO }}
|
||||||
|
HOMEBREW_CHANGE_ARCH_TO_ARM: 1
|
||||||
|
|
||||||
|
- if: failure() && runner.os == 'Windows'
|
||||||
|
name: Upload artifact
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: testfiles
|
||||||
|
path: |
|
||||||
|
./test/golden/windows/GHCupInfo*json
|
||||||
|
|
||||||
|
- if: failure() && runner.os != 'Windows'
|
||||||
|
name: Upload artifact
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: testfiles
|
||||||
|
path: |
|
||||||
|
./test/golden/unix/GHCupInfo*json
|
||||||
|
hls:
|
||||||
|
name: hls
|
||||||
|
needs: build-linux
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
GHC_VERSION: "8.10.7"
|
||||||
|
HLS_TARGET_VERSION: "1.8.0.0"
|
||||||
|
CABAL_VERSION: "3.8.1.0"
|
||||||
|
JSON_VERSION: "0.0.7"
|
||||||
|
ARTIFACT: "x86_64-linux-ghcup"
|
||||||
|
DISTRO: Ubuntu
|
||||||
|
ARCH: 64
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||||
|
S3_HOST: ${{ secrets.S3_HOST }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: 'true'
|
||||||
|
|
||||||
|
- uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: artifacts
|
||||||
|
path: ./out
|
||||||
|
|
||||||
|
- name: Run hls build
|
||||||
|
run: |
|
||||||
|
sudo apt-get install -y libnuma-dev zlib1g-dev libgmp-dev libgmp10 libssl-dev liblzma-dev libbz2-dev git wget lsb-release software-properties-common gnupg2 apt-transport-https gcc autoconf automake build-essential curl gzip
|
||||||
|
sh .github/scripts/hls.sh
|
||||||
|
|
||||||
|
release:
|
||||||
|
name: release
|
||||||
|
needs: ["test-linux", "test-arm", "test-macwin", "hls"]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: startsWith(github.ref, 'refs/tags/v')
|
||||||
|
steps:
|
||||||
|
- name: Download artifacts
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: artifacts
|
||||||
|
path: ./out
|
||||||
|
|
||||||
|
- name: Release
|
||||||
|
uses: softprops/action-gh-release@v1
|
||||||
|
with:
|
||||||
|
draft: true
|
||||||
|
files: |
|
||||||
|
./out/*
|
||||||
|
|||||||
28
.github/workflows/shellcheck.yaml
vendored
Normal file
28
.github/workflows/shellcheck.yaml
vendored
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
name: Shellcheck
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
tags:
|
||||||
|
- 'v*'
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
shellcheck:
|
||||||
|
name: shellcheck
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
JSON_VERSION: "0.0.7"
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: 'true'
|
||||||
|
|
||||||
|
- name: Run shellcheck
|
||||||
|
uses: docker://koalaman/shellcheck-alpine
|
||||||
|
with:
|
||||||
|
args: shellcheck scripts/bootstrap/bootstrap-haskell
|
||||||
@@ -6,20 +6,10 @@ set -eux
|
|||||||
|
|
||||||
mkdir -p "$CI_PROJECT_DIR"/.local/bin
|
mkdir -p "$CI_PROJECT_DIR"/.local/bin
|
||||||
|
|
||||||
ecabal() {
|
|
||||||
cabal "$@"
|
|
||||||
}
|
|
||||||
|
|
||||||
eghcup() {
|
|
||||||
ghcup -v -c -s file://$(pwd)/ghcup-${JSON_VERSION}.yaml "$@"
|
|
||||||
}
|
|
||||||
|
|
||||||
git describe --always
|
git describe --always
|
||||||
|
|
||||||
### build
|
### build
|
||||||
|
|
||||||
ecabal update
|
|
||||||
|
|
||||||
export BOOTSTRAP_HASKELL_NONINTERACTIVE=yes
|
export BOOTSTRAP_HASKELL_NONINTERACTIVE=yes
|
||||||
export BOOTSTRAP_HASKELL_GHC_VERSION=$GHC_VERSION
|
export BOOTSTRAP_HASKELL_GHC_VERSION=$GHC_VERSION
|
||||||
export BOOTSTRAP_HASKELL_CABAL_VERSION=$CABAL_VERSION
|
export BOOTSTRAP_HASKELL_CABAL_VERSION=$CABAL_VERSION
|
||||||
|
|||||||
@@ -97,17 +97,23 @@ rm -rf "${GHCUP_DIR}"
|
|||||||
eghcup --numeric-version
|
eghcup --numeric-version
|
||||||
|
|
||||||
eghcup install ghc ${GHC_VERSION}
|
eghcup install ghc ${GHC_VERSION}
|
||||||
|
eghcup unset ghc ${GHC_VERSION}
|
||||||
ls -lah "$(eghcup whereis -d ghc ${GHC_VERSION})"
|
ls -lah "$(eghcup whereis -d ghc ${GHC_VERSION})"
|
||||||
[ "`$(eghcup whereis ghc ${GHC_VERSION}) --numeric-version`" = "${GHC_VERSION}" ]
|
[ "`$(eghcup whereis ghc ${GHC_VERSION}) --numeric-version`" = "${GHC_VERSION}" ]
|
||||||
[ "`eghcup run --ghc ${GHC_VERSION} -- ghc --numeric-version`" = "${GHC_VERSION}" ]
|
[ "`eghcup run --ghc ${GHC_VERSION} -- ghc --numeric-version`" = "${GHC_VERSION}" ]
|
||||||
|
[ "`ghcup run --ghc ${GHC_VERSION} -- ghc -e 'Control.Monad.join (Control.Monad.fmap System.IO.putStr System.Environment.getExecutablePath)'`" = "`$(ghcup whereis ghc ${GHC_VERSION}) -e 'Control.Monad.join (Control.Monad.fmap System.IO.putStr System.Environment.getExecutablePath)'`" ]
|
||||||
eghcup set ghc ${GHC_VERSION}
|
eghcup set ghc ${GHC_VERSION}
|
||||||
eghcup install cabal ${CABAL_VERSION}
|
eghcup install cabal ${CABAL_VERSION}
|
||||||
[ "`$(eghcup whereis cabal ${CABAL_VERSION}) --numeric-version`" = "${CABAL_VERSION}" ]
|
[ "`$(eghcup whereis cabal ${CABAL_VERSION}) --numeric-version`" = "${CABAL_VERSION}" ]
|
||||||
eghcup unset cabal
|
eghcup unset cabal
|
||||||
"$GHCUP_BIN"/cabal --version && exit 1 || echo yes
|
"$GHCUP_BIN"/cabal --version && exit 1 || echo yes
|
||||||
eghcup set cabal ${CABAL_VERSION}
|
|
||||||
[ "`$(eghcup whereis cabal ${CABAL_VERSION}) --numeric-version`" = "${CABAL_VERSION}" ]
|
# make sure no cabal is set when running 'ghcup run' to check that PATH propagages properly
|
||||||
|
# https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/375
|
||||||
[ "`eghcup run --cabal ${CABAL_VERSION} -- cabal --numeric-version`" = "${CABAL_VERSION}" ]
|
[ "`eghcup run --cabal ${CABAL_VERSION} -- cabal --numeric-version`" = "${CABAL_VERSION}" ]
|
||||||
|
eghcup set cabal ${CABAL_VERSION}
|
||||||
|
|
||||||
|
[ "`$(eghcup whereis cabal ${CABAL_VERSION}) --numeric-version`" = "${CABAL_VERSION}" ]
|
||||||
|
|
||||||
if [ "${OS}" != "FREEBSD" ] ; then
|
if [ "${OS}" != "FREEBSD" ] ; then
|
||||||
if [ "${ARCH}" = "64" ] ; then
|
if [ "${ARCH}" = "64" ] ; then
|
||||||
|
|||||||
25
.travis.yml
25
.travis.yml
@@ -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: "hT2od8Iy04tdFVuonPSWv0NX5hZDmv4al8Q0GbIWmviUetROuM7c6/MCHUcgyiw6H2L3pmH4F24GBYWpKBT3ZMbxrKXhZOZ3KPLXzlnuRlm1qymKqqwsJs3466bMftaiBr16rx1VpAuditN4A32oSmTFcQAJc84Bxn2WZ4t8hk9muS8YPyLhqg3/NxT6ob8dzNp9eS2cA0WODMb/fMzaMruRtepSK8JvuXb/SnTvaDcl9plmPzEa+eW54jwVsDps8ZpQMQlTtGIjYHIwTQ36/iLH4LoAvD7OEnB7qf753LOzmI/bvlB75xYGsLxe1qgpzPMjuG3AK0jb2KGSZCzyAyrbBFSQMIyC1gNKMtab3CohnA9WdQqAT1xrzPzA9zNw516G5Fn/z+t9Ek1f6L2OYO2hJfweNhWh+ChAIsOags2QBpqc0qjkwUS4wqxCWBdyVfgPTUoGelvjCfjQgypgIyLEHFvXt9rlj+kd97FY7nG3vxZrsvWTKKKT551OqUYX5zWTyvGR71jKyNst/p93Pg3DkRy31gHrGnG9zfNgN5tWxJqDd/suR/BAFTp0VtkFb8fR3ct7WMVeJXtE2+bKqxO5Fnocs1VjEm8pKPk7glnp0muu08kaO0h54wiSOCbk1RvO1KZtHue4wKWrHcI18dwW2WtzoBQ4P1lOSkS81UY="
|
|
||||||
file: $ARTIFACT
|
|
||||||
on:
|
|
||||||
repo: hasufell/ghcup-hs
|
|
||||||
tags: true
|
|
||||||
skip_cleanup: true
|
|
||||||
draft: true
|
|
||||||
58
CHANGELOG.md
58
CHANGELOG.md
@@ -1,5 +1,63 @@
|
|||||||
# Revision history for ghcup
|
# Revision history for ghcup
|
||||||
|
|
||||||
|
## 0.1.19.0 -- 2023-1-13
|
||||||
|
|
||||||
|
* restore proper support for FreeBSD and Linux armv7
|
||||||
|
* integrate with [errors.haskell.org](https://errors.haskell.org/index.html), wrt [#434](https://github.com/haskell/ghcup-hs/issues/434)
|
||||||
|
* allow to overwrite distro detection via config wrt [#421](https://github.com/haskell/ghcup-hs/issues/421)
|
||||||
|
- this is particularly useful for e.g. Ubuntu derivates, where ghcup doesn't pick the optimal bindist, also see the [GHCup documentation on overriding distro detection](https://www.haskell.org/ghcup/guide/#overriding-distro-detection)
|
||||||
|
* Add proper support for mirrors wrt [#357](https://github.com/haskell/ghcup-hs/issues/357)
|
||||||
|
* fix a (harmless) bug in `ghcup nuke` on windows
|
||||||
|
* improvements to `ghcup add-release-channel` wrt [#708](https://github.com/haskell/ghcup-hs/issues/708)
|
||||||
|
* fix building newer GHC from source wrt [#433](https://github.com/haskell/ghcup-hs/issues/433)
|
||||||
|
* Fix `ghcup install hls -u` on windows
|
||||||
|
* Fix failure with `--isolate=dir --force`
|
||||||
|
* Add `--metadata-fetching-mode` arg, fixes [#440](https://github.com/haskell/ghcup-hs/issues/440)
|
||||||
|
* Add content-length property to downloads
|
||||||
|
* [Fix a grave bug on armv7](https://github.com/haskell/ghcup-hs/commit/78ee956df2618862f421178a565c82548ff7e578) during installation wrt [#415](https://github.com/haskell/ghcup-hs/issues/415)
|
||||||
|
* improve many warning/error messages (contributions by @taylorfausak)
|
||||||
|
* some minor optimization in `ghcup whereis ghcup`
|
||||||
|
* improve `--keep=always` to not clean up directories in certain circumstances
|
||||||
|
|
||||||
|
## 0.1.18.1 -- 2022-08-06
|
||||||
|
|
||||||
|
* fix sdist and unbreak hackage, wrt [#399](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/399)
|
||||||
|
|
||||||
|
## 0.1.18.0 -- 2022-07-30
|
||||||
|
|
||||||
|
* Fix tui set wrt [#266](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/266) by Arjun Kathuria
|
||||||
|
- Ask the user to install the tool via prompt when setting an non-installed version
|
||||||
|
* improvements to safe (un-)installations
|
||||||
|
- bindists that don't support `make DESTDIR=/some/tmp/dir install` are now unsupported
|
||||||
|
- installed GHC files are now recorded to avoid use of `removePathForcibly`
|
||||||
|
- internally uses a newtype wrapper for user-input paths and restrict destructive operations to validated paths
|
||||||
|
* Add `--disable-ld-override` for darwin bindists wrt #391
|
||||||
|
* Allow passing bindist configure args wrt #377
|
||||||
|
* use of `TMPDIR` is dropped... now uses an internal tmp dir `~/.ghcup/tmp`
|
||||||
|
* improvements to error handling and warnings
|
||||||
|
* Require --isolate to have an absolute directory, fixes #367
|
||||||
|
* Fix mingw PATH handling wrt #371
|
||||||
|
* Add --mingw-path switch to `ghcup run`
|
||||||
|
* Fix `ghcup run` on windows, fixes #375
|
||||||
|
* Improve `ghcup compile <hls|ghc>`
|
||||||
|
- short hashes now work
|
||||||
|
- print the long hash in addition to the detected version
|
||||||
|
* Improve `ghcup compile hls`
|
||||||
|
- add `--git-describe-version` switch as an alternative to `--overwrite-version`
|
||||||
|
- Allow to build HLS from hackage (now is the default)
|
||||||
|
- Allow to run 'cabal update' automatically before the HLS build
|
||||||
|
- Fix parser and completer for 'ghcup compile hls --version'
|
||||||
|
* Improve `ghcup compile ghc`
|
||||||
|
- Allow to build from arbitrary GHC source dists
|
||||||
|
|
||||||
|
## 0.1.17.10 -- 2022-05-12
|
||||||
|
|
||||||
|
* windows hotfix (hackage-only release)
|
||||||
|
|
||||||
|
## 0.1.17.9 -- 2022-05-12
|
||||||
|
|
||||||
|
* broken sdist (hackage-only release)
|
||||||
|
|
||||||
## 0.1.17.8 -- 2022-05-11
|
## 0.1.17.8 -- 2022-05-11
|
||||||
|
|
||||||
* Fix a serious (but hard to trigger) bug when combining `--isolate <DIR>` with `--force`, please make sure to upgrade or avoid `--force`
|
* Fix a serious (but hard to trigger) bug when combining `--isolate <DIR>` with `--force`, please make sure to upgrade or avoid `--force`
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
[](https://gitter.im/haskell/ghcup?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
[](https://gitter.im/haskell/ghcup?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||||
<a href="https://opencollective.com/ghcup#category-CONTRIBUTE"><img src="https://opencollective.com/webpack/donate/button@2x.png?color=blue" alt="Donate" width="150"></a>
|
<a href="https://opencollective.com/ghcup#category-CONTRIBUTE"><img src="https://opencollective.com/webpack/donate/button@2x.png?color=blue" alt="Donate" width="150"></a>
|
||||||
|
|
||||||
GHCup is an installer for the general purpose language [Haskell](https://www.haskell.org/).
|
GHCup is the main installer for the general purpose language [Haskell](https://www.haskell.org/).
|
||||||
|
|
||||||
Visit the [documentation](https://www.haskell.org/ghcup/) for installation instructions.
|
Visit the [documentation](https://www.haskell.org/ghcup/) for installation instructions.
|
||||||
|
|
||||||
|
|||||||
@@ -13,10 +13,12 @@ import GHCup.Errors
|
|||||||
import GHCup.Types.Optics ( getDirs )
|
import GHCup.Types.Optics ( getDirs )
|
||||||
import GHCup.Types hiding ( LeanAppState(..) )
|
import GHCup.Types hiding ( LeanAppState(..) )
|
||||||
import GHCup.Utils
|
import GHCup.Utils
|
||||||
|
import GHCup.OptParse.Common (logGHCPostRm)
|
||||||
import GHCup.Prelude ( decUTF8Safe )
|
import GHCup.Prelude ( decUTF8Safe )
|
||||||
import GHCup.Prelude.File
|
import GHCup.Prelude.File
|
||||||
import GHCup.Prelude.Logger
|
import GHCup.Prelude.Logger
|
||||||
import GHCup.Prelude.Process
|
import GHCup.Prelude.Process
|
||||||
|
import GHCup.Prompts
|
||||||
|
|
||||||
import Brick
|
import Brick
|
||||||
import Brick.Widgets.Border
|
import Brick.Widgets.Border
|
||||||
@@ -52,6 +54,8 @@ import Text.PrettyPrint.HughesPJClass ( prettyShow )
|
|||||||
import URI.ByteString
|
import URI.ByteString
|
||||||
|
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
|
import qualified Data.Text.Lazy.Builder as B
|
||||||
|
import qualified Data.Text.Lazy as L
|
||||||
import qualified Graphics.Vty as Vty
|
import qualified Graphics.Vty as Vty
|
||||||
import qualified Data.Vector as V
|
import qualified Data.Vector as V
|
||||||
import System.Environment (getExecutablePath)
|
import System.Environment (getExecutablePath)
|
||||||
@@ -91,14 +95,14 @@ data BrickState = BrickState
|
|||||||
keyHandlers :: KeyBindings
|
keyHandlers :: KeyBindings
|
||||||
-> [ ( Vty.Key
|
-> [ ( Vty.Key
|
||||||
, BrickSettings -> String
|
, BrickSettings -> String
|
||||||
, BrickState -> EventM n (Next BrickState)
|
, BrickState -> EventM String BrickState ()
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
keyHandlers KeyBindings {..} =
|
keyHandlers KeyBindings {..} =
|
||||||
[ (bQuit, const "Quit" , halt)
|
[ (bQuit, const "Quit" , \_ -> halt)
|
||||||
, (bInstall, const "Install" , withIOAction install')
|
, (bInstall, const "Install" , withIOAction install')
|
||||||
, (bUninstall, const "Uninstall", withIOAction del')
|
, (bUninstall, const "Uninstall", withIOAction del')
|
||||||
, (bSet, const "Set" , withIOAction ((liftIO .) . set'))
|
, (bSet, const "Set" , withIOAction set')
|
||||||
, (bChangelog, const "ChangeLog", withIOAction changelog')
|
, (bChangelog, const "ChangeLog", withIOAction changelog')
|
||||||
, ( bShowAllVersions
|
, ( bShowAllVersions
|
||||||
, \BrickSettings {..} ->
|
, \BrickSettings {..} ->
|
||||||
@@ -110,14 +114,14 @@ keyHandlers KeyBindings {..} =
|
|||||||
if showAllTools then "Don't show all tools" else "Show all tools"
|
if showAllTools then "Don't show all tools" else "Show all tools"
|
||||||
, hideShowHandler showAllVersions (not . showAllTools)
|
, hideShowHandler showAllVersions (not . showAllTools)
|
||||||
)
|
)
|
||||||
, (bUp, const "Up", \BrickState {..} -> continue BrickState{ appState = moveCursor 1 appState Up, .. })
|
, (bUp, const "Up", \BrickState {..} -> put BrickState{ appState = moveCursor 1 appState Up, .. })
|
||||||
, (bDown, const "Down", \BrickState {..} -> continue BrickState{ appState = moveCursor 1 appState Down, .. })
|
, (bDown, const "Down", \BrickState {..} -> put BrickState{ appState = moveCursor 1 appState Down, .. })
|
||||||
]
|
]
|
||||||
where
|
where
|
||||||
hideShowHandler f p BrickState{..} =
|
hideShowHandler f p BrickState{..} =
|
||||||
let newAppSettings = appSettings { showAllVersions = f appSettings , showAllTools = p appSettings }
|
let newAppSettings = appSettings { showAllVersions = f appSettings , showAllTools = p appSettings }
|
||||||
newInternalState = constructList appData newAppSettings (Just appState)
|
newInternalState = constructList appData newAppSettings (Just appState)
|
||||||
in continue (BrickState appData newAppSettings newInternalState appKeys)
|
in put (BrickState appData newAppSettings newInternalState appKeys)
|
||||||
|
|
||||||
|
|
||||||
showKey :: Vty.Key -> String
|
showKey :: Vty.Key -> String
|
||||||
@@ -138,7 +142,7 @@ ui dimAttrs BrickState{ appSettings = as@BrickSettings{}, ..}
|
|||||||
|
|
||||||
where
|
where
|
||||||
footer =
|
footer =
|
||||||
withAttr "help"
|
withAttr (attrName "help")
|
||||||
. txtWrap
|
. txtWrap
|
||||||
. T.pack
|
. T.pack
|
||||||
. foldr1 (\x y -> x <> " " <> y)
|
. foldr1 (\x y -> x <> " " <> y)
|
||||||
@@ -153,9 +157,9 @@ ui dimAttrs BrickState{ appSettings = as@BrickSettings{}, ..}
|
|||||||
renderList' = withDefAttr listAttr . drawListElements renderItem True
|
renderList' = withDefAttr listAttr . drawListElements renderItem True
|
||||||
renderItem _ b listResult@ListResult{..} =
|
renderItem _ b listResult@ListResult{..} =
|
||||||
let marks = if
|
let marks = if
|
||||||
| lSet -> (withAttr "set" $ str "✔✔")
|
| lSet -> (withAttr (attrName "set") $ str "✔✔")
|
||||||
| lInstalled -> (withAttr "installed" $ str "✓ ")
|
| lInstalled -> (withAttr (attrName "installed") $ str "✓ ")
|
||||||
| otherwise -> (withAttr "not-installed" $ str "✗ ")
|
| otherwise -> (withAttr (attrName "not-installed") $ str "✗ ")
|
||||||
ver = case lCross of
|
ver = case lCross of
|
||||||
Nothing -> T.unpack . prettyVer $ lVer
|
Nothing -> T.unpack . prettyVer $ lVer
|
||||||
Just c -> T.unpack (c <> "-" <> prettyVer lVer)
|
Just c -> T.unpack (c <> "-" <> prettyVer lVer)
|
||||||
@@ -163,13 +167,13 @@ ui dimAttrs BrickState{ appSettings = as@BrickSettings{}, ..}
|
|||||||
| lNoBindist && not lInstalled
|
| lNoBindist && not lInstalled
|
||||||
&& not b -- TODO: overloading dim and active ignores active
|
&& not b -- TODO: overloading dim and active ignores active
|
||||||
-- so we hack around it here
|
-- so we hack around it here
|
||||||
= updateAttrMap (const dimAttrs) . withAttr "no-bindist"
|
= updateAttrMap (const dimAttrs) . withAttr (attrName "no-bindist")
|
||||||
| otherwise = id
|
| otherwise = id
|
||||||
hooray
|
hooray
|
||||||
| elem Latest lTag && not lInstalled =
|
| elem Latest lTag && not lInstalled =
|
||||||
withAttr "hooray"
|
withAttr (attrName "hooray")
|
||||||
| otherwise = id
|
| otherwise = id
|
||||||
active = if b then putCursor "GHCup" (Location (0,0)) . forceAttr "active" else id
|
active = if b then putCursor "GHCup" (Location (0,0)) . forceAttr (attrName "active") else id
|
||||||
in hooray $ active $ dim
|
in hooray $ active $ dim
|
||||||
( marks
|
( marks
|
||||||
<+> padLeft (Pad 2)
|
<+> padLeft (Pad 2)
|
||||||
@@ -191,9 +195,9 @@ ui dimAttrs BrickState{ appSettings = as@BrickSettings{}, ..}
|
|||||||
<+> vLimit 1 (fill ' ')
|
<+> vLimit 1 (fill ' ')
|
||||||
)
|
)
|
||||||
|
|
||||||
printTag Recommended = Just $ withAttr "recommended" $ str "recommended"
|
printTag Recommended = Just $ withAttr (attrName "recommended") $ str "recommended"
|
||||||
printTag Latest = Just $ withAttr "latest" $ str "latest"
|
printTag Latest = Just $ withAttr (attrName "latest") $ str "latest"
|
||||||
printTag Prerelease = Just $ withAttr "prerelease" $ str "prerelease"
|
printTag Prerelease = Just $ withAttr (attrName "prerelease") $ str "prerelease"
|
||||||
printTag (Base pvp'') = Just $ str ("base-" ++ T.unpack (prettyPVP pvp''))
|
printTag (Base pvp'') = Just $ str ("base-" ++ T.unpack (prettyPVP pvp''))
|
||||||
printTag Old = Nothing
|
printTag Old = Nothing
|
||||||
printTag (UnknownTag t) = Just $ str t
|
printTag (UnknownTag t) = Just $ str t
|
||||||
@@ -205,10 +209,10 @@ ui dimAttrs BrickState{ appSettings = as@BrickSettings{}, ..}
|
|||||||
printTool Stack = str "Stack"
|
printTool Stack = str "Stack"
|
||||||
|
|
||||||
printNotes ListResult {..} =
|
printNotes ListResult {..} =
|
||||||
(if hlsPowered then [withAttr "hls-powered" $ str "hls-powered"] else mempty
|
(if hlsPowered then [withAttr (attrName "hls-powered") $ str "hls-powered"] else mempty
|
||||||
)
|
)
|
||||||
++ (if fromSrc then [withAttr "compiled" $ str "compiled"] else mempty)
|
++ (if fromSrc then [withAttr (attrName "compiled") $ str "compiled"] else mempty)
|
||||||
++ (if lStray then [withAttr "stray" $ str "stray"] else mempty)
|
++ (if lStray then [withAttr (attrName "stray") $ str "stray"] else mempty)
|
||||||
|
|
||||||
-- | Draws the list elements.
|
-- | Draws the list elements.
|
||||||
--
|
--
|
||||||
@@ -238,8 +242,8 @@ ui dimAttrs BrickState{ appSettings = as@BrickSettings{}, ..}
|
|||||||
selItemAttr = if foc
|
selItemAttr = if foc
|
||||||
then withDefAttr listSelectedFocusedAttr
|
then withDefAttr listSelectedFocusedAttr
|
||||||
else withDefAttr listSelectedAttr
|
else withDefAttr listSelectedAttr
|
||||||
makeVisible = if isSelected then visible . selItemAttr else id
|
makeVisible' = if isSelected then visible . selItemAttr else id
|
||||||
in addSeparator $ makeVisible elemWidget
|
in addSeparator $ makeVisible' elemWidget
|
||||||
|
|
||||||
in render
|
in render
|
||||||
$ viewport "GHCup" Vertical
|
$ viewport "GHCup" Vertical
|
||||||
@@ -254,8 +258,8 @@ minHSize s' = hLimit s' . vLimit 1 . (<+> fill ' ')
|
|||||||
app :: AttrMap -> AttrMap -> App BrickState e String
|
app :: AttrMap -> AttrMap -> App BrickState e String
|
||||||
app attrs dimAttrs =
|
app attrs dimAttrs =
|
||||||
App { appDraw = \st -> [ui dimAttrs st]
|
App { appDraw = \st -> [ui dimAttrs st]
|
||||||
, appHandleEvent = eventHandler
|
, appHandleEvent = \be -> get >>= \s -> eventHandler s be
|
||||||
, appStartEvent = return
|
, appStartEvent = return ()
|
||||||
, appAttrMap = const attrs
|
, appAttrMap = const attrs
|
||||||
, appChooseCursor = showFirstCursor
|
, appChooseCursor = showFirstCursor
|
||||||
}
|
}
|
||||||
@@ -263,18 +267,18 @@ app attrs dimAttrs =
|
|||||||
defaultAttributes :: Bool -> AttrMap
|
defaultAttributes :: Bool -> AttrMap
|
||||||
defaultAttributes no_color = attrMap
|
defaultAttributes no_color = attrMap
|
||||||
Vty.defAttr
|
Vty.defAttr
|
||||||
[ ("active" , Vty.defAttr `withBackColor` Vty.blue)
|
[ (attrName "active" , Vty.defAttr `withBackColor` Vty.blue)
|
||||||
, ("not-installed", Vty.defAttr `withForeColor` Vty.red)
|
, (attrName "not-installed", Vty.defAttr `withForeColor` Vty.red)
|
||||||
, ("set" , Vty.defAttr `withForeColor` Vty.green)
|
, (attrName "set" , Vty.defAttr `withForeColor` Vty.green)
|
||||||
, ("installed" , Vty.defAttr `withForeColor` Vty.green)
|
, (attrName "installed" , Vty.defAttr `withForeColor` Vty.green)
|
||||||
, ("recommended" , Vty.defAttr `withForeColor` Vty.green)
|
, (attrName "recommended" , Vty.defAttr `withForeColor` Vty.green)
|
||||||
, ("hls-powered" , Vty.defAttr `withForeColor` Vty.green)
|
, (attrName "hls-powered" , Vty.defAttr `withForeColor` Vty.green)
|
||||||
, ("latest" , Vty.defAttr `withForeColor` Vty.yellow)
|
, (attrName "latest" , Vty.defAttr `withForeColor` Vty.yellow)
|
||||||
, ("prerelease" , Vty.defAttr `withForeColor` Vty.red)
|
, (attrName "prerelease" , Vty.defAttr `withForeColor` Vty.red)
|
||||||
, ("compiled" , Vty.defAttr `withForeColor` Vty.blue)
|
, (attrName "compiled" , Vty.defAttr `withForeColor` Vty.blue)
|
||||||
, ("stray" , Vty.defAttr `withForeColor` Vty.blue)
|
, (attrName "stray" , Vty.defAttr `withForeColor` Vty.blue)
|
||||||
, ("help" , Vty.defAttr `withStyle` Vty.italic)
|
, (attrName "help" , Vty.defAttr `withStyle` Vty.italic)
|
||||||
, ("hooray" , Vty.defAttr `withForeColor` Vty.brightWhite)
|
, (attrName "hooray" , Vty.defAttr `withForeColor` Vty.brightWhite)
|
||||||
]
|
]
|
||||||
where
|
where
|
||||||
withForeColor | no_color = const
|
withForeColor | no_color = const
|
||||||
@@ -288,31 +292,31 @@ defaultAttributes no_color = attrMap
|
|||||||
dimAttributes :: Bool -> AttrMap
|
dimAttributes :: Bool -> AttrMap
|
||||||
dimAttributes no_color = attrMap
|
dimAttributes no_color = attrMap
|
||||||
(Vty.defAttr `Vty.withStyle` Vty.dim)
|
(Vty.defAttr `Vty.withStyle` Vty.dim)
|
||||||
[ ("active" , Vty.defAttr `withBackColor` Vty.blue) -- has no effect ??
|
[ (attrName "active" , Vty.defAttr `withBackColor` Vty.blue) -- has no effect ??
|
||||||
, ("no-bindist", Vty.defAttr `Vty.withStyle` Vty.dim)
|
, (attrName "no-bindist", Vty.defAttr `Vty.withStyle` Vty.dim)
|
||||||
]
|
]
|
||||||
where
|
where
|
||||||
withBackColor | no_color = \attr _ -> attr `Vty.withStyle` Vty.reverseVideo
|
withBackColor | no_color = \attr _ -> attr `Vty.withStyle` Vty.reverseVideo
|
||||||
| otherwise = Vty.withBackColor
|
| otherwise = Vty.withBackColor
|
||||||
|
|
||||||
eventHandler :: BrickState -> BrickEvent n e -> EventM n (Next BrickState)
|
eventHandler :: BrickState -> BrickEvent String e -> EventM String BrickState ()
|
||||||
eventHandler st@BrickState{..} ev = do
|
eventHandler st@BrickState{..} ev = do
|
||||||
AppState { keyBindings = kb } <- liftIO $ readIORef settings'
|
AppState { keyBindings = kb } <- liftIO $ readIORef settings'
|
||||||
case ev of
|
case ev of
|
||||||
(MouseDown _ Vty.BScrollUp _ _) ->
|
(MouseDown _ Vty.BScrollUp _ _) ->
|
||||||
continue (BrickState { appState = moveCursor 1 appState Up, .. })
|
put (BrickState { appState = moveCursor 1 appState Up, .. })
|
||||||
(MouseDown _ Vty.BScrollDown _ _) ->
|
(MouseDown _ Vty.BScrollDown _ _) ->
|
||||||
continue (BrickState { appState = moveCursor 1 appState Down, .. })
|
put (BrickState { appState = moveCursor 1 appState Down, .. })
|
||||||
(VtyEvent (Vty.EvResize _ _)) -> continue st
|
(VtyEvent (Vty.EvResize _ _)) -> put st
|
||||||
(VtyEvent (Vty.EvKey Vty.KUp _)) ->
|
(VtyEvent (Vty.EvKey Vty.KUp _)) ->
|
||||||
continue BrickState{ appState = moveCursor 1 appState Up, .. }
|
put BrickState{ appState = moveCursor 1 appState Up, .. }
|
||||||
(VtyEvent (Vty.EvKey Vty.KDown _)) ->
|
(VtyEvent (Vty.EvKey Vty.KDown _)) ->
|
||||||
continue BrickState{ appState = moveCursor 1 appState Down, .. }
|
put BrickState{ appState = moveCursor 1 appState Down, .. }
|
||||||
(VtyEvent (Vty.EvKey key _)) ->
|
(VtyEvent (Vty.EvKey key _)) ->
|
||||||
case find (\(key', _, _) -> key' == key) (keyHandlers kb) of
|
case find (\(key', _, _) -> key' == key) (keyHandlers kb) of
|
||||||
Nothing -> continue st
|
Nothing -> put st
|
||||||
Just (_, _, handler) -> handler st
|
Just (_, _, handler) -> handler st
|
||||||
_ -> continue st
|
_ -> put st
|
||||||
|
|
||||||
|
|
||||||
moveCursor :: Int -> BrickInternalState -> Direction -> BrickInternalState
|
moveCursor :: Int -> BrickInternalState -> Direction -> BrickInternalState
|
||||||
@@ -325,13 +329,14 @@ moveCursor steps ais@BrickInternalState{..} direction =
|
|||||||
|
|
||||||
-- | Suspend the current UI and run an IO action in terminal. If the
|
-- | Suspend the current UI and run an IO action in terminal. If the
|
||||||
-- IO action returns a Left value, then it's thrown as userError.
|
-- IO action returns a Left value, then it's thrown as userError.
|
||||||
withIOAction :: (BrickState
|
withIOAction :: Ord n
|
||||||
|
=> (BrickState
|
||||||
-> (Int, ListResult)
|
-> (Int, ListResult)
|
||||||
-> ReaderT AppState IO (Either String a))
|
-> ReaderT AppState IO (Either String a))
|
||||||
-> BrickState
|
-> BrickState
|
||||||
-> EventM n (Next BrickState)
|
-> EventM n BrickState ()
|
||||||
withIOAction action as = case listSelectedElement' (appState as) of
|
withIOAction action as = case listSelectedElement' (appState as) of
|
||||||
Nothing -> continue as
|
Nothing -> put as
|
||||||
Just (ix, e) -> do
|
Just (ix, e) -> do
|
||||||
suspendAndResume $ do
|
suspendAndResume $ do
|
||||||
settings <- readIORef settings'
|
settings <- readIORef settings'
|
||||||
@@ -430,6 +435,7 @@ install' _ (_, ListResult {..}) = do
|
|||||||
, BuildFailed
|
, BuildFailed
|
||||||
, TagNotFound
|
, TagNotFound
|
||||||
, DigestError
|
, DigestError
|
||||||
|
, ContentLengthError
|
||||||
, GPGError
|
, GPGError
|
||||||
, DownloadFailed
|
, DownloadFailed
|
||||||
, DirNotEmpty
|
, DirNotEmpty
|
||||||
@@ -437,7 +443,7 @@ install' _ (_, ListResult {..}) = do
|
|||||||
, TarDirDoesNotExist
|
, TarDirDoesNotExist
|
||||||
, FileAlreadyExistsError
|
, FileAlreadyExistsError
|
||||||
, ProcessError
|
, ProcessError
|
||||||
, GHCupShadowed
|
, ToolShadowed
|
||||||
, UninstallFailed
|
, UninstallFailed
|
||||||
, MergeFileTreeError
|
, MergeFileTreeError
|
||||||
]
|
]
|
||||||
@@ -449,7 +455,7 @@ install' _ (_, ListResult {..}) = do
|
|||||||
case lTool of
|
case lTool of
|
||||||
GHC -> do
|
GHC -> do
|
||||||
let vi = getVersionInfo lVer GHC dls
|
let vi = getVersionInfo lVer GHC dls
|
||||||
liftE $ installGHCBin lVer GHCupInternal False $> (vi, dirs, ce)
|
liftE $ installGHCBin lVer GHCupInternal False [] $> (vi, dirs, ce)
|
||||||
Cabal -> do
|
Cabal -> do
|
||||||
let vi = getVersionInfo lVer Cabal dls
|
let vi = getVersionInfo lVer Cabal dls
|
||||||
liftE $ installCabalBin lVer GHCupInternal False $> (vi, dirs, ce)
|
liftE $ installCabalBin lVer GHCupInternal False $> (vi, dirs, ce)
|
||||||
@@ -482,13 +488,16 @@ install' _ (_, ListResult {..}) = do
|
|||||||
pure $ Right ()
|
pure $ Right ()
|
||||||
VLeft (V (AlreadyInstalled _ _)) -> pure $ Right ()
|
VLeft (V (AlreadyInstalled _ _)) -> pure $ Right ()
|
||||||
VLeft (V NoUpdate) -> pure $ Right ()
|
VLeft (V NoUpdate) -> pure $ Right ()
|
||||||
VLeft e -> pure $ Left $ prettyShow e <> "\n"
|
VLeft e -> pure $ Left $ prettyHFError e <> "\n"
|
||||||
<> "Also check the logs in ~/.ghcup/logs"
|
<> "Also check the logs in ~/.ghcup/logs"
|
||||||
|
|
||||||
|
|
||||||
set' :: BrickState -> (Int, ListResult) -> IO (Either String ())
|
set' :: (MonadReader AppState m, MonadIO m, MonadThrow m, MonadFail m, MonadMask m, MonadUnliftIO m)
|
||||||
set' _ (_, ListResult {..}) = do
|
=> BrickState
|
||||||
settings <- readIORef settings'
|
-> (Int, ListResult)
|
||||||
|
-> m (Either String ())
|
||||||
|
set' bs input@(_, ListResult {..}) = do
|
||||||
|
settings <- liftIO $ readIORef settings'
|
||||||
|
|
||||||
let run =
|
let run =
|
||||||
flip runReaderT settings
|
flip runReaderT settings
|
||||||
@@ -504,7 +513,28 @@ set' _ (_, ListResult {..}) = do
|
|||||||
)
|
)
|
||||||
>>= \case
|
>>= \case
|
||||||
VRight _ -> pure $ Right ()
|
VRight _ -> pure $ Right ()
|
||||||
VLeft e -> pure $ Left (prettyShow e)
|
VLeft e -> case e of
|
||||||
|
(V (NotInstalled tool _)) -> do
|
||||||
|
promptAnswer <- getUserPromptResponse userPrompt
|
||||||
|
case promptAnswer of
|
||||||
|
PromptYes -> do
|
||||||
|
res <- install' bs input
|
||||||
|
case res of
|
||||||
|
(Left err) -> pure $ Left err
|
||||||
|
(Right _) -> do
|
||||||
|
logInfo "Setting now..."
|
||||||
|
set' bs input
|
||||||
|
|
||||||
|
PromptNo -> pure $ Left (prettyHFError e)
|
||||||
|
where
|
||||||
|
userPrompt = L.toStrict . B.toLazyText . B.fromString $
|
||||||
|
"This Version of "
|
||||||
|
<> show tool
|
||||||
|
<> " you are trying to set is not installed.\n"
|
||||||
|
<> "Would you like to install it first? [Y/N]: "
|
||||||
|
|
||||||
|
_ -> pure $ Left (prettyHFError e)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
del' :: (MonadReader AppState m, MonadIO m, MonadFail m, MonadMask m, MonadUnliftIO m)
|
del' :: (MonadReader AppState m, MonadIO m, MonadFail m, MonadMask m, MonadUnliftIO m)
|
||||||
@@ -527,10 +557,11 @@ del' _ (_, ListResult {..}) = do
|
|||||||
)
|
)
|
||||||
>>= \case
|
>>= \case
|
||||||
VRight vi -> do
|
VRight vi -> do
|
||||||
|
logGHCPostRm (mkTVer lVer)
|
||||||
forM_ (_viPostRemove =<< vi) $ \msg ->
|
forM_ (_viPostRemove =<< vi) $ \msg ->
|
||||||
logInfo msg
|
logInfo msg
|
||||||
pure $ Right ()
|
pure $ Right ()
|
||||||
VLeft e -> pure $ Left (prettyShow e)
|
VLeft e -> pure $ Left (prettyHFError e)
|
||||||
|
|
||||||
|
|
||||||
changelog' :: (MonadReader AppState m, MonadIO m)
|
changelog' :: (MonadReader AppState m, MonadIO m)
|
||||||
@@ -550,7 +581,7 @@ changelog' _ (_, ListResult {..}) = do
|
|||||||
Windows -> "start"
|
Windows -> "start"
|
||||||
exec cmd [T.unpack $ decUTF8Safe $ serializeURIRef' uri] Nothing Nothing >>= \case
|
exec cmd [T.unpack $ decUTF8Safe $ serializeURIRef' uri] Nothing Nothing >>= \case
|
||||||
Right _ -> pure $ Right ()
|
Right _ -> pure $ Right ()
|
||||||
Left e -> pure $ Left $ prettyShow e
|
Left e -> pure $ Left $ prettyHFError e
|
||||||
|
|
||||||
|
|
||||||
settings' :: IORef AppState
|
settings' :: IORef AppState
|
||||||
@@ -603,12 +634,12 @@ getGHCupInfo = do
|
|||||||
|
|
||||||
r <-
|
r <-
|
||||||
flip runReaderT settings
|
flip runReaderT settings
|
||||||
. runE @'[DigestError, GPGError, JSONError , DownloadFailed , FileDoesNotExistError]
|
. runE @'[DigestError, ContentLengthError, GPGError, JSONError , DownloadFailed , FileDoesNotExistError]
|
||||||
$ liftE getDownloadsF
|
$ liftE getDownloadsF
|
||||||
|
|
||||||
case r of
|
case r of
|
||||||
VRight a -> pure $ Right a
|
VRight a -> pure $ Right a
|
||||||
VLeft e -> pure $ Left (prettyShow e)
|
VLeft e -> pure $ Left (prettyHFError e)
|
||||||
|
|
||||||
|
|
||||||
getAppData :: Maybe GHCupInfo
|
getAppData :: Maybe GHCupInfo
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
module GHCup.OptParse (
|
module GHCup.OptParse (
|
||||||
module GHCup.OptParse.Common
|
module GHCup.OptParse.Common
|
||||||
, module GHCup.OptParse.Install
|
, module GHCup.OptParse.Install
|
||||||
|
, module GHCup.OptParse.Test
|
||||||
, module GHCup.OptParse.Set
|
, module GHCup.OptParse.Set
|
||||||
, module GHCup.OptParse.UnSet
|
, module GHCup.OptParse.UnSet
|
||||||
, module GHCup.OptParse.Rm
|
, module GHCup.OptParse.Rm
|
||||||
@@ -31,6 +32,7 @@ module GHCup.OptParse (
|
|||||||
|
|
||||||
import GHCup.OptParse.Common
|
import GHCup.OptParse.Common
|
||||||
import GHCup.OptParse.Install
|
import GHCup.OptParse.Install
|
||||||
|
import GHCup.OptParse.Test
|
||||||
import GHCup.OptParse.Set
|
import GHCup.OptParse.Set
|
||||||
import GHCup.OptParse.UnSet
|
import GHCup.OptParse.UnSet
|
||||||
import GHCup.OptParse.Rm
|
import GHCup.OptParse.Rm
|
||||||
@@ -67,13 +69,14 @@ import URI.ByteString
|
|||||||
import qualified Data.ByteString.UTF8 as UTF8
|
import qualified Data.ByteString.UTF8 as UTF8
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
data Options = Options
|
data Options = Options
|
||||||
{
|
{
|
||||||
-- global options
|
-- global options
|
||||||
optVerbose :: Maybe Bool
|
optVerbose :: Maybe Bool
|
||||||
, optCache :: Maybe Bool
|
, optCache :: Maybe Bool
|
||||||
, optMetaCache :: Maybe Integer
|
, optMetaCache :: Maybe Integer
|
||||||
|
, optMetaMode :: Maybe MetaMode
|
||||||
|
, optPlatform :: Maybe PlatformRequest
|
||||||
, optUrlSource :: Maybe URI
|
, optUrlSource :: Maybe URI
|
||||||
, optNoVerify :: Maybe Bool
|
, optNoVerify :: Maybe Bool
|
||||||
, optKeepDirs :: Maybe KeepDirs
|
, optKeepDirs :: Maybe KeepDirs
|
||||||
@@ -86,6 +89,7 @@ data Options = Options
|
|||||||
|
|
||||||
data Command
|
data Command
|
||||||
= Install (Either InstallCommand InstallOptions)
|
= Install (Either InstallCommand InstallOptions)
|
||||||
|
| Test TestCommand
|
||||||
| InstallCabalLegacy InstallOptions
|
| InstallCabalLegacy InstallOptions
|
||||||
| Set (Either SetCommand SetOptions)
|
| Set (Either SetCommand SetOptions)
|
||||||
| UnSet UnsetCommand
|
| UnSet UnsetCommand
|
||||||
@@ -107,6 +111,7 @@ data Command
|
|||||||
| Prefetch PrefetchCommand
|
| Prefetch PrefetchCommand
|
||||||
| GC GCOptions
|
| GC GCOptions
|
||||||
| Run RunOptions
|
| Run RunOptions
|
||||||
|
| PrintAppErrors
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -115,7 +120,18 @@ opts =
|
|||||||
Options
|
Options
|
||||||
<$> invertableSwitch "verbose" (Just 'v') False (help "Enable verbosity (default: disabled)")
|
<$> invertableSwitch "verbose" (Just 'v') False (help "Enable verbosity (default: disabled)")
|
||||||
<*> invertableSwitch "cache" (Just 'c') False (help "Cache downloads in ~/.ghcup/cache (default: disabled)")
|
<*> invertableSwitch "cache" (Just 'c') False (help "Cache downloads in ~/.ghcup/cache (default: disabled)")
|
||||||
<*> optional (option auto (long "metadata-caching" <> help "How long the yaml metadata caching interval is (in seconds), 0 to disable" <> internal))
|
<*> optional (option auto (long "metadata-caching" <> metavar "SEC" <> help "How long the yaml metadata caching interval is (in seconds), 0 to disable"))
|
||||||
|
<*> optional (option auto (long "metadata-fetching-mode" <> metavar "<Strict|Lax>" <> help "Whether to fail on metadata download failure (Strict) or fall back to cached version (Lax (default))"))
|
||||||
|
<*> optional
|
||||||
|
(option
|
||||||
|
(eitherReader platformParser)
|
||||||
|
( short 'p'
|
||||||
|
<> long "platform"
|
||||||
|
<> metavar "PLATFORM"
|
||||||
|
<> help
|
||||||
|
"Override for platform (triple matching ghc tarball names), e.g. x86_64-fedora27-linux"
|
||||||
|
)
|
||||||
|
)
|
||||||
<*> optional
|
<*> optional
|
||||||
(option
|
(option
|
||||||
(eitherReader parseUri)
|
(eitherReader parseUri)
|
||||||
@@ -192,6 +208,14 @@ com =
|
|||||||
<> footerDoc (Just $ text installToolFooter)
|
<> footerDoc (Just $ text installToolFooter)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
<> command
|
||||||
|
"test"
|
||||||
|
(info
|
||||||
|
(Test <$> testParser <**> helper)
|
||||||
|
( progDesc "Run tests for a tool (if any) [EXPERIMENTAL!]"
|
||||||
|
<> footerDoc (Just $ text testFooter)
|
||||||
|
)
|
||||||
|
)
|
||||||
<> command
|
<> command
|
||||||
"set"
|
"set"
|
||||||
(info
|
(info
|
||||||
@@ -329,3 +353,10 @@ com =
|
|||||||
<> commandGroup "Nuclear Commands:"
|
<> commandGroup "Nuclear Commands:"
|
||||||
<> hidden
|
<> hidden
|
||||||
)
|
)
|
||||||
|
<|> subparser
|
||||||
|
(command
|
||||||
|
"print-app-errors"
|
||||||
|
(info (pure PrintAppErrors <**> helper)
|
||||||
|
(progDesc ""))
|
||||||
|
<> internal
|
||||||
|
)
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ module GHCup.OptParse.ChangeLog where
|
|||||||
|
|
||||||
|
|
||||||
import GHCup.Types
|
import GHCup.Types
|
||||||
|
import GHCup.Errors
|
||||||
import GHCup.OptParse.Common
|
import GHCup.OptParse.Common
|
||||||
import GHCup.Prelude
|
import GHCup.Prelude
|
||||||
import GHCup.Prelude.Logger
|
import GHCup.Prelude.Logger
|
||||||
@@ -58,7 +59,7 @@ data ChangeLogOptions = ChangeLogOptions
|
|||||||
--[ Parsers ]--
|
--[ Parsers ]--
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
|
||||||
changelogP :: Parser ChangeLogOptions
|
changelogP :: Parser ChangeLogOptions
|
||||||
changelogP =
|
changelogP =
|
||||||
(\x y -> ChangeLogOptions x y)
|
(\x y -> ChangeLogOptions x y)
|
||||||
@@ -71,15 +72,16 @@ changelogP =
|
|||||||
"cabal" -> Right Cabal
|
"cabal" -> Right Cabal
|
||||||
"ghcup" -> Right GHCup
|
"ghcup" -> Right GHCup
|
||||||
"stack" -> Right Stack
|
"stack" -> Right Stack
|
||||||
|
"hls" -> Right HLS
|
||||||
e -> Left e
|
e -> Left e
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
(short 't' <> long "tool" <> metavar "<ghc|cabal|ghcup>" <> help
|
(short 't' <> long "tool" <> metavar "<ghc|cabal|hls|ghcup>" <> help
|
||||||
"Open changelog for given tool (default: ghc)"
|
"Open changelog for given tool (default: ghc)"
|
||||||
<> completer toolCompleter
|
<> completer toolCompleter
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
<*> optional (toolVersionArgument Nothing Nothing)
|
<*> optional (toolVersionTagArgument Nothing Nothing)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -116,7 +118,8 @@ changelog ChangeLogOptions{..} runAppState runLogger = do
|
|||||||
ver' = maybe
|
ver' = maybe
|
||||||
(Right Latest)
|
(Right Latest)
|
||||||
(\case
|
(\case
|
||||||
ToolVersion tv -> Left (_tvVersion tv) -- FIXME: ugly sharing of ToolVersion
|
GHCVersion tv -> Left (_tvVersion tv)
|
||||||
|
ToolVersion tv -> Left tv
|
||||||
ToolTag t -> Right t
|
ToolTag t -> Right t
|
||||||
)
|
)
|
||||||
clToolVer
|
clToolVer
|
||||||
@@ -146,6 +149,6 @@ changelog ChangeLogOptions{..} runAppState runLogger = do
|
|||||||
Nothing
|
Nothing
|
||||||
>>= \case
|
>>= \case
|
||||||
Right _ -> pure ExitSuccess
|
Right _ -> pure ExitSuccess
|
||||||
Left e -> logError (T.pack $ prettyShow e)
|
Left e -> logError (T.pack $ prettyHFError e)
|
||||||
>> pure (ExitFailure 13)
|
>> pure (ExitFailure 13)
|
||||||
else liftIO $ putStrLn uri' >> pure ExitSuccess
|
else liftIO $ putStrLn uri' >> pure ExitSuccess
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import Control.DeepSeq
|
|||||||
import Control.Concurrent
|
import Control.Concurrent
|
||||||
import Control.Concurrent.Async
|
import Control.Concurrent.Async
|
||||||
import Control.Exception.Safe
|
import Control.Exception.Safe
|
||||||
|
import Control.Monad.Identity (Identity(..))
|
||||||
#if !MIN_VERSION_base(4,13,0)
|
#if !MIN_VERSION_base(4,13,0)
|
||||||
import Control.Monad.Fail ( MonadFail )
|
import Control.Monad.Fail ( MonadFail )
|
||||||
#endif
|
#endif
|
||||||
@@ -64,26 +65,31 @@ import qualified Text.Megaparsec as MP
|
|||||||
import qualified System.FilePath.Posix as FP
|
import qualified System.FilePath.Posix as FP
|
||||||
import GHCup.Version
|
import GHCup.Version
|
||||||
import Control.Exception (evaluate)
|
import Control.Exception (evaluate)
|
||||||
|
import qualified Cabal.Config as CC
|
||||||
|
|
||||||
|
|
||||||
-------------
|
-------------
|
||||||
--[ Types ]--
|
--[ Types ]--
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
data ToolVersion = ToolVersion GHCTargetVersion -- target is ignored for cabal
|
data ToolVersion = GHCVersion GHCTargetVersion
|
||||||
|
| ToolVersion Version
|
||||||
| ToolTag Tag
|
| ToolTag Tag
|
||||||
|
|
||||||
-- a superset of ToolVersion
|
-- a superset of ToolVersion
|
||||||
data SetToolVersion = SetToolVersion GHCTargetVersion
|
data SetToolVersion = SetGHCVersion GHCTargetVersion
|
||||||
|
| SetToolVersion Version
|
||||||
| SetToolTag Tag
|
| SetToolTag Tag
|
||||||
| SetRecommended
|
| SetRecommended
|
||||||
| SetNext
|
| SetNext
|
||||||
|
|
||||||
prettyToolVer :: ToolVersion -> String
|
prettyToolVer :: ToolVersion -> String
|
||||||
prettyToolVer (ToolVersion v') = T.unpack $ tVerToText v'
|
prettyToolVer (GHCVersion v') = T.unpack $ tVerToText v'
|
||||||
|
prettyToolVer (ToolVersion v') = T.unpack $ prettyVer v'
|
||||||
prettyToolVer (ToolTag t) = show t
|
prettyToolVer (ToolTag t) = show t
|
||||||
|
|
||||||
toSetToolVer :: Maybe ToolVersion -> SetToolVersion
|
toSetToolVer :: Maybe ToolVersion -> SetToolVersion
|
||||||
|
toSetToolVer (Just (GHCVersion v')) = SetGHCVersion v'
|
||||||
toSetToolVer (Just (ToolVersion v')) = SetToolVersion v'
|
toSetToolVer (Just (ToolVersion v')) = SetToolVersion v'
|
||||||
toSetToolVer (Just (ToolTag t')) = SetToolTag t'
|
toSetToolVer (Just (ToolTag t')) = SetToolTag t'
|
||||||
toSetToolVer Nothing = SetRecommended
|
toSetToolVer Nothing = SetRecommended
|
||||||
@@ -96,10 +102,9 @@ toSetToolVer Nothing = SetRecommended
|
|||||||
--------------
|
--------------
|
||||||
|
|
||||||
|
|
||||||
-- | same as toolVersionParser, except as an argument.
|
toolVersionTagArgument :: Maybe ListCriteria -> Maybe Tool -> Parser ToolVersion
|
||||||
toolVersionArgument :: Maybe ListCriteria -> Maybe Tool -> Parser ToolVersion
|
toolVersionTagArgument criteria tool =
|
||||||
toolVersionArgument criteria tool =
|
argument (eitherReader (parser tool))
|
||||||
argument (eitherReader toolVersionEither)
|
|
||||||
(metavar (mv tool)
|
(metavar (mv tool)
|
||||||
<> completer (tagCompleter (fromMaybe GHC tool) [])
|
<> completer (tagCompleter (fromMaybe GHC tool) [])
|
||||||
<> foldMap (completer . versionCompleter criteria) tool)
|
<> foldMap (completer . versionCompleter criteria) tool)
|
||||||
@@ -108,20 +113,19 @@ toolVersionArgument criteria tool =
|
|||||||
mv (Just HLS) = "HLS_VERSION|TAG"
|
mv (Just HLS) = "HLS_VERSION|TAG"
|
||||||
mv _ = "VERSION|TAG"
|
mv _ = "VERSION|TAG"
|
||||||
|
|
||||||
|
parser (Just GHC) = ghcVersionTagEither
|
||||||
|
parser Nothing = ghcVersionTagEither
|
||||||
|
parser _ = toolVersionTagEither
|
||||||
|
|
||||||
versionParser :: Parser GHCTargetVersion
|
|
||||||
versionParser = option
|
|
||||||
(eitherReader tVersionEither)
|
|
||||||
(short 'v' <> long "version" <> metavar "VERSION" <> help "The target version"
|
|
||||||
)
|
|
||||||
|
|
||||||
versionParser' :: Maybe ListCriteria -> Maybe Tool -> Parser Version
|
versionParser' :: Maybe ListCriteria -> Maybe Tool -> Parser Version
|
||||||
versionParser' criteria tool = argument
|
versionParser' criteria tool = argument
|
||||||
(eitherReader (first show . version . T.pack))
|
(eitherReader (first show . version . T.pack))
|
||||||
(metavar "VERSION" <> foldMap (completer . versionCompleter criteria) tool)
|
(metavar "VERSION" <> foldMap (completer . versionCompleter criteria) tool)
|
||||||
|
|
||||||
versionArgument :: Maybe ListCriteria -> Maybe Tool -> Parser GHCTargetVersion
|
ghcVersionArgument :: Maybe ListCriteria -> Maybe Tool -> Parser GHCTargetVersion
|
||||||
versionArgument criteria tool = argument (eitherReader tVersionEither) (metavar "VERSION" <> foldMap (completer . versionCompleter criteria) tool)
|
ghcVersionArgument criteria tool = argument (eitherReader ghcVersionEither)
|
||||||
|
(metavar "VERSION" <> foldMap (completer . versionCompleter criteria) tool)
|
||||||
|
|
||||||
|
|
||||||
-- https://github.com/pcapriotti/optparse-applicative/issues/148
|
-- https://github.com/pcapriotti/optparse-applicative/issues/148
|
||||||
@@ -226,13 +230,19 @@ absolutePathParser f = case isValid f && isAbsolute f of
|
|||||||
False -> Left "Please enter a valid absolute filepath."
|
False -> Left "Please enter a valid absolute filepath."
|
||||||
|
|
||||||
isolateParser :: FilePath -> Either String FilePath
|
isolateParser :: FilePath -> Either String FilePath
|
||||||
isolateParser f = case isValid f of
|
isolateParser f = case isValid f && isAbsolute f of
|
||||||
True -> Right $ normalise f
|
True -> Right $ normalise f
|
||||||
False -> Left "Please enter a valid filepath for isolate dir."
|
False -> Left "Please enter a valid filepath for isolate dir."
|
||||||
|
|
||||||
toolVersionEither :: String -> Either String ToolVersion
|
-- this accepts cross prefix
|
||||||
toolVersionEither s' =
|
ghcVersionTagEither :: String -> Either String ToolVersion
|
||||||
second ToolTag (tagEither s') <|> second ToolVersion (tVersionEither s')
|
ghcVersionTagEither s' =
|
||||||
|
second ToolTag (tagEither s') <|> second GHCVersion (ghcVersionEither s')
|
||||||
|
|
||||||
|
-- this ignores cross prefix
|
||||||
|
toolVersionTagEither :: String -> Either String ToolVersion
|
||||||
|
toolVersionTagEither s' =
|
||||||
|
second ToolTag (tagEither s') <|> second ToolVersion (toolVersionEither s')
|
||||||
|
|
||||||
tagEither :: String -> Either String Tag
|
tagEither :: String -> Either String Tag
|
||||||
tagEither s' = case fmap toLower s' of
|
tagEither s' = case fmap toLower s' of
|
||||||
@@ -244,10 +254,14 @@ tagEither s' = case fmap toLower s' of
|
|||||||
other -> Left $ "Unknown tag " <> other
|
other -> Left $ "Unknown tag " <> other
|
||||||
|
|
||||||
|
|
||||||
tVersionEither :: String -> Either String GHCTargetVersion
|
ghcVersionEither :: String -> Either String GHCTargetVersion
|
||||||
tVersionEither =
|
ghcVersionEither =
|
||||||
first (const "Not a valid version") . MP.parse ghcTargetVerP "" . T.pack
|
first (const "Not a valid version") . MP.parse ghcTargetVerP "" . T.pack
|
||||||
|
|
||||||
|
toolVersionEither :: String -> Either String Version
|
||||||
|
toolVersionEither =
|
||||||
|
first (const "Not a valid version") . MP.parse version' "" . T.pack
|
||||||
|
|
||||||
|
|
||||||
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
|
||||||
@@ -440,9 +454,11 @@ tagCompleter tool add = listIOCompleter $ do
|
|||||||
pure $ nub $ (add ++) $ fmap tagToString allTags
|
pure $ nub $ (add ++) $ fmap tagToString allTags
|
||||||
VLeft _ -> pure (nub $ ["recommended", "latest"] ++ add)
|
VLeft _ -> pure (nub $ ["recommended", "latest"] ++ add)
|
||||||
|
|
||||||
|
|
||||||
versionCompleter :: Maybe ListCriteria -> Tool -> Completer
|
versionCompleter :: Maybe ListCriteria -> Tool -> Completer
|
||||||
versionCompleter criteria tool = listIOCompleter $ do
|
versionCompleter criteria tool = versionCompleter' criteria tool (const True)
|
||||||
|
|
||||||
|
versionCompleter' :: Maybe ListCriteria -> Tool -> (Version -> Bool) -> Completer
|
||||||
|
versionCompleter' criteria tool filter' = listIOCompleter $ do
|
||||||
dirs' <- liftIO getAllDirs
|
dirs' <- liftIO getAllDirs
|
||||||
let loggerConfig = LoggerConfig
|
let loggerConfig = LoggerConfig
|
||||||
{ lcPrintDebug = False
|
{ lcPrintDebug = False
|
||||||
@@ -471,7 +487,7 @@ versionCompleter criteria tool = listIOCompleter $ do
|
|||||||
runEnv = flip runReaderT appState
|
runEnv = flip runReaderT appState
|
||||||
|
|
||||||
installedVersions <- runEnv $ listVersions (Just tool) criteria
|
installedVersions <- runEnv $ listVersions (Just tool) criteria
|
||||||
return $ T.unpack . prettyVer . lVer <$> installedVersions
|
return $ fmap (T.unpack . prettyVer) . filter filter' . fmap lVer $ installedVersions
|
||||||
|
|
||||||
|
|
||||||
toolDlCompleter :: Tool -> Completer
|
toolDlCompleter :: Tool -> Completer
|
||||||
@@ -663,7 +679,7 @@ fromVersion' SetRecommended tool = do
|
|||||||
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||||
bimap mkTVer Just <$> getRecommended dls tool
|
bimap mkTVer Just <$> getRecommended dls tool
|
||||||
?? TagNotFound Recommended tool
|
?? TagNotFound Recommended tool
|
||||||
fromVersion' (SetToolVersion v) tool = do
|
fromVersion' (SetGHCVersion v) tool = do
|
||||||
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||||
let vi = getVersionInfo (_tvVersion v) tool dls
|
let vi = getVersionInfo (_tvVersion v) tool dls
|
||||||
case pvp $ prettyVer (_tvVersion v) of -- need to be strict here
|
case pvp $ prettyVer (_tvVersion v) of -- need to be strict here
|
||||||
@@ -675,6 +691,18 @@ fromVersion' (SetToolVersion v) tool = do
|
|||||||
when (v' /= _tvVersion v) $ lift $ logWarn ("Assuming you meant version " <> prettyVer v')
|
when (v' /= _tvVersion v) $ lift $ logWarn ("Assuming you meant version " <> prettyVer v')
|
||||||
pure (GHCTargetVersion (_tvTarget v) v', Just vi')
|
pure (GHCTargetVersion (_tvTarget v) v', Just vi')
|
||||||
Nothing -> pure (v, vi)
|
Nothing -> pure (v, vi)
|
||||||
|
fromVersion' (SetToolVersion v) tool = do
|
||||||
|
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||||
|
let vi = getVersionInfo v tool dls
|
||||||
|
case pvp $ prettyVer v of -- need to be strict here
|
||||||
|
Left _ -> pure (mkTVer v, vi)
|
||||||
|
Right pvpIn ->
|
||||||
|
lift (getLatestToolFor tool pvpIn dls) >>= \case
|
||||||
|
Just (pvp_, vi') -> do
|
||||||
|
v' <- lift $ pvpToVersion pvp_ ""
|
||||||
|
when (v' /= v) $ lift $ logWarn ("Assuming you meant version " <> prettyVer v')
|
||||||
|
pure (GHCTargetVersion mempty v', Just vi')
|
||||||
|
Nothing -> pure (mkTVer v, vi)
|
||||||
fromVersion' (SetToolTag Latest) tool = do
|
fromVersion' (SetToolTag Latest) tool = do
|
||||||
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||||
bimap mkTVer Just <$> getLatest dls tool ?? TagNotFound Latest tool
|
bimap mkTVer Just <$> getLatest dls tool ?? TagNotFound Latest tool
|
||||||
@@ -763,3 +791,12 @@ checkForUpdates = do
|
|||||||
pure $ catMaybes (ghcup:otherTools)
|
pure $ catMaybes (ghcup:otherTools)
|
||||||
where
|
where
|
||||||
forMM a f = fmap join $ forM a f
|
forMM a f = fmap join $ forM a f
|
||||||
|
|
||||||
|
|
||||||
|
logGHCPostRm :: (MonadReader env m, HasLog env, MonadIO m) => GHCTargetVersion -> m ()
|
||||||
|
logGHCPostRm ghcVer = do
|
||||||
|
cabalStore <- liftIO $ handleIO (\_ -> if isWindows then pure "C:\\cabal\\store" else pure "~/.cabal/store")
|
||||||
|
(runIdentity . CC.cfgStoreDir <$> CC.readConfig)
|
||||||
|
let storeGhcDir = cabalStore </> ("ghc-" <> T.unpack (prettyVer $ _tvVersion ghcVer))
|
||||||
|
logInfo $ T.pack $ "After removing GHC you might also want to clean up your cabal store at: " <> storeGhcDir
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ module GHCup.OptParse.Compile where
|
|||||||
|
|
||||||
|
|
||||||
import GHCup
|
import GHCup
|
||||||
|
import qualified GHCup.GHC as GHC
|
||||||
|
import qualified GHCup.HLS as HLS
|
||||||
import GHCup.Errors
|
import GHCup.Errors
|
||||||
import GHCup.Types
|
import GHCup.Types
|
||||||
import GHCup.Types.Optics
|
import GHCup.Types.Optics
|
||||||
@@ -30,18 +32,18 @@ import Control.Monad.Trans.Resource
|
|||||||
import Data.Bifunctor
|
import Data.Bifunctor
|
||||||
import Data.Functor
|
import Data.Functor
|
||||||
import Data.Maybe
|
import Data.Maybe
|
||||||
import Data.Versions ( Version, prettyVer, version )
|
import Data.Versions ( Version, prettyVer, version, pvp )
|
||||||
|
import qualified Data.Versions as V
|
||||||
import Data.Text ( Text )
|
import Data.Text ( Text )
|
||||||
import Haskus.Utils.Variant.Excepts
|
import Haskus.Utils.Variant.Excepts
|
||||||
import Options.Applicative hiding ( style )
|
import Options.Applicative hiding ( style )
|
||||||
import Options.Applicative.Help.Pretty ( text )
|
import Options.Applicative.Help.Pretty ( text )
|
||||||
import Prelude hiding ( appendFile )
|
import Prelude hiding ( appendFile )
|
||||||
import System.Exit
|
import System.Exit
|
||||||
import Text.PrettyPrint.HughesPJClass ( prettyShow )
|
|
||||||
|
|
||||||
import URI.ByteString hiding ( uriParser )
|
import URI.ByteString hiding ( uriParser )
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import Control.Exception.Safe (MonadMask)
|
import Control.Exception.Safe (MonadMask, displayException)
|
||||||
import System.FilePath (isPathSeparator)
|
import System.FilePath (isPathSeparator)
|
||||||
import Text.Read (readEither)
|
import Text.Read (readEither)
|
||||||
|
|
||||||
@@ -64,7 +66,7 @@ data CompileCommand = CompileGHC GHCCompileOptions
|
|||||||
|
|
||||||
|
|
||||||
data GHCCompileOptions = GHCCompileOptions
|
data GHCCompileOptions = GHCCompileOptions
|
||||||
{ targetGhc :: Either Version GitBranch
|
{ targetGhc :: GHC.GHCVer Version
|
||||||
, bootstrapGhc :: Either Version FilePath
|
, bootstrapGhc :: Either Version FilePath
|
||||||
, jobs :: Maybe Int
|
, jobs :: Maybe Int
|
||||||
, buildConfig :: Maybe FilePath
|
, buildConfig :: Maybe FilePath
|
||||||
@@ -78,11 +80,13 @@ data GHCCompileOptions = GHCCompileOptions
|
|||||||
, isolateDir :: Maybe FilePath
|
, isolateDir :: Maybe FilePath
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
data HLSCompileOptions = HLSCompileOptions
|
data HLSCompileOptions = HLSCompileOptions
|
||||||
{ targetHLS :: Either Version GitBranch
|
{ targetHLS :: HLS.HLSVer
|
||||||
, jobs :: Maybe Int
|
, jobs :: Maybe Int
|
||||||
, setCompile :: Bool
|
, setCompile :: Bool
|
||||||
, ovewrwiteVer :: Maybe Version
|
, updateCabal :: Bool
|
||||||
|
, ovewrwiteVer :: Either Bool Version
|
||||||
, isolateDir :: Maybe FilePath
|
, isolateDir :: Maybe FilePath
|
||||||
, cabalProject :: Maybe (Either FilePath URI)
|
, cabalProject :: Maybe (Either FilePath URI)
|
||||||
, cabalProjectLocal :: Maybe URI
|
, cabalProjectLocal :: Maybe URI
|
||||||
@@ -145,20 +149,22 @@ Examples:
|
|||||||
|
|
||||||
compileHLSFooter = [s|Discussion:
|
compileHLSFooter = [s|Discussion:
|
||||||
Compiles and installs the specified HLS version.
|
Compiles and installs the specified HLS version.
|
||||||
The last argument is a list of GHC versions to compile for.
|
The --ghc arguments are necessary to specify which GHC version to build for/against.
|
||||||
These need to be available in PATH prior to compilation.
|
These need to be available in PATH prior to compilation.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
# compile 1.4.0 for ghc 8.10.5 and 8.10.7
|
# compile 1.7.0.0 from hackage for 8.10.7, running 'cabal update' before the build
|
||||||
ghcup compile hls -v 1.4.0 -j 12 --ghc 8.10.5 --ghc 8.10.7
|
ghcup compile hls --version 1.7.0.0 --ghc 8.10.7 --cabal-update
|
||||||
# compile from master for ghc 8.10.7, linking everything dynamically
|
# compile from master for ghc 9.2.3 using 'git describe' to name the binary and ignore the pinned index state
|
||||||
ghcup compile hls -g master -j 12 --ghc 8.10.7 -- --ghc-options='-dynamic'|]
|
ghcup compile hls -g master --git-describe-version --ghc 9.2.3 -- --index-state=@(date '+%s')
|
||||||
|
# compile a specific commit for ghc 9.2.3 and set a specifc version for the binary name
|
||||||
|
ghcup compile hls -g a32db0b -o 1.7.0.0-p1 --ghc 9.2.3|]
|
||||||
|
|
||||||
|
|
||||||
ghcCompileOpts :: Parser GHCCompileOptions
|
ghcCompileOpts :: Parser GHCCompileOptions
|
||||||
ghcCompileOpts =
|
ghcCompileOpts =
|
||||||
GHCCompileOptions
|
GHCCompileOptions
|
||||||
<$> ((Left <$> option
|
<$> ((GHC.SourceDist <$> option
|
||||||
(eitherReader
|
(eitherReader
|
||||||
(first (const "Not a valid version") . version . T.pack)
|
(first (const "Not a valid version") . version . T.pack)
|
||||||
)
|
)
|
||||||
@@ -167,7 +173,7 @@ ghcCompileOpts =
|
|||||||
<> (completer $ versionCompleter Nothing GHC)
|
<> (completer $ versionCompleter Nothing GHC)
|
||||||
)
|
)
|
||||||
) <|>
|
) <|>
|
||||||
(Right <$> (GitBranch <$> option
|
(GHC.GitDist <$> (GitBranch <$> option
|
||||||
str
|
str
|
||||||
(short 'g' <> long "git-ref" <> metavar "GIT_REFERENCE" <> help
|
(short 'g' <> long "git-ref" <> metavar "GIT_REFERENCE" <> help
|
||||||
"The git commit/branch/ref to build from"
|
"The git commit/branch/ref to build from"
|
||||||
@@ -176,7 +182,18 @@ ghcCompileOpts =
|
|||||||
short 'r' <> long "repository" <> metavar "GIT_REPOSITORY" <> help "The git repository to build from (defaults to GHC upstream)"
|
short 'r' <> long "repository" <> metavar "GIT_REPOSITORY" <> help "The git repository to build from (defaults to GHC upstream)"
|
||||||
<> completer (gitFileUri ["https://gitlab.haskell.org/ghc/ghc.git"])
|
<> completer (gitFileUri ["https://gitlab.haskell.org/ghc/ghc.git"])
|
||||||
))
|
))
|
||||||
)))
|
))
|
||||||
|
<|>
|
||||||
|
(
|
||||||
|
GHC.RemoteDist <$> (option
|
||||||
|
(eitherReader uriParser)
|
||||||
|
(long "remote-source-dist" <> metavar "URI" <> help
|
||||||
|
"URI (https/http/file) to a GHC source distribution"
|
||||||
|
<> completer fileUri
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
<*> option
|
<*> option
|
||||||
(eitherReader
|
(eitherReader
|
||||||
(\x ->
|
(\x ->
|
||||||
@@ -232,7 +249,7 @@ ghcCompileOpts =
|
|||||||
"Build cross-compiler for this platform"
|
"Build cross-compiler for this platform"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
<*> many (argument str (metavar "CONFIGURE_ARGS" <> help "Additional arguments to configure, prefix with '-- ' (longopts)"))
|
<*> many (argument str (metavar "CONFIGURE_ARGS" <> help "Additional arguments to compile configure, prefix with '-- ' (longopts)"))
|
||||||
<*> fmap (fromMaybe False) (invertableSwitch "set" Nothing False (help "Set as active version after install"))
|
<*> fmap (fromMaybe False) (invertableSwitch "set" Nothing False (help "Set as active version after install"))
|
||||||
<*> optional
|
<*> optional
|
||||||
(option
|
(option
|
||||||
@@ -268,24 +285,46 @@ ghcCompileOpts =
|
|||||||
hlsCompileOpts :: Parser HLSCompileOptions
|
hlsCompileOpts :: Parser HLSCompileOptions
|
||||||
hlsCompileOpts =
|
hlsCompileOpts =
|
||||||
HLSCompileOptions
|
HLSCompileOptions
|
||||||
<$> ((Left <$> option
|
<$> ((HLS.HackageDist <$> option
|
||||||
(eitherReader
|
(eitherReader
|
||||||
(first (const "Not a valid version") . version . T.pack)
|
((>>= first displayException . V.version . V.prettyPVP) . first (const "Not a valid PVP version") . pvp . T.pack)
|
||||||
)
|
)
|
||||||
(short 'v' <> long "version" <> metavar "VERSION" <> help
|
(short 'v' <> long "version" <> metavar "VERSION" <> help
|
||||||
"The tool version to compile"
|
"The version to compile (pulled from hackage)"
|
||||||
<> (completer $ versionCompleter Nothing HLS)
|
<> (completer $ versionCompleter' Nothing HLS (either (const False) (const True) . V.pvp . V.prettyVer))
|
||||||
)
|
)
|
||||||
) <|>
|
)
|
||||||
(Right <$> (GitBranch <$> option
|
<|>
|
||||||
|
(HLS.GitDist <$> (GitBranch <$> option
|
||||||
str
|
str
|
||||||
(short 'g' <> long "git-ref" <> metavar "GIT_REFERENCE" <> help
|
(short 'g' <> long "git-ref" <> metavar "GIT_REFERENCE" <> help
|
||||||
"The git commit/branch/ref to build from"
|
"The git commit/branch/ref to build from (accepts anything 'git checkout' accepts)"
|
||||||
) <*>
|
) <*>
|
||||||
optional (option str (short 'r' <> long "repository" <> metavar "GIT_REPOSITORY" <> help "The git repository to build from (defaults to HLS upstream)"
|
optional (option str (short 'r' <> long "repository" <> metavar "GIT_REPOSITORY" <> help "The git repository to build from (defaults to HLS upstream)"
|
||||||
<> completer (gitFileUri ["https://github.com/haskell/haskell-language-server.git"])
|
<> completer (gitFileUri ["https://github.com/haskell/haskell-language-server.git"])
|
||||||
))
|
))
|
||||||
)))
|
))
|
||||||
|
<|>
|
||||||
|
(HLS.SourceDist <$> (option
|
||||||
|
(eitherReader
|
||||||
|
(first (const "Not a valid version") . version . T.pack)
|
||||||
|
)
|
||||||
|
(long "source-dist" <> metavar "VERSION" <> help
|
||||||
|
"The version to compile (pulled from packaged git sources)"
|
||||||
|
<> (completer $ versionCompleter Nothing HLS)
|
||||||
|
)
|
||||||
|
))
|
||||||
|
<|>
|
||||||
|
(
|
||||||
|
HLS.RemoteDist <$> (option
|
||||||
|
(eitherReader uriParser)
|
||||||
|
(long "remote-source-dist" <> metavar "URI" <> help
|
||||||
|
"URI (https/http/file) to a HLS source distribution"
|
||||||
|
<> completer fileUri
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
<*> optional
|
<*> optional
|
||||||
(option
|
(option
|
||||||
(eitherReader (readEither @Int))
|
(eitherReader (readEither @Int))
|
||||||
@@ -295,8 +334,10 @@ hlsCompileOpts =
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
<*> fmap (fromMaybe True) (invertableSwitch "set" Nothing True (help "Don't set as active version after install"))
|
<*> fmap (fromMaybe True) (invertableSwitch "set" Nothing True (help "Don't set as active version after install"))
|
||||||
<*> optional
|
<*> switch (long "cabal-update" <> help "Run 'cabal update' before the build")
|
||||||
(option
|
<*>
|
||||||
|
(
|
||||||
|
(Right <$> option
|
||||||
(eitherReader
|
(eitherReader
|
||||||
(first (const "Not a valid version") . version . T.pack)
|
(first (const "Not a valid version") . version . T.pack)
|
||||||
)
|
)
|
||||||
@@ -305,6 +346,14 @@ hlsCompileOpts =
|
|||||||
<> (completer $ versionCompleter Nothing HLS)
|
<> (completer $ versionCompleter Nothing HLS)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
<|>
|
||||||
|
(Left <$> (switch
|
||||||
|
(long "git-describe-version"
|
||||||
|
<> help "Use the output of 'git describe' (if building from git) as the VERSION component of the installed binary."
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
<*> optional
|
<*> optional
|
||||||
(option
|
(option
|
||||||
(eitherReader isolateParser)
|
(eitherReader isolateParser)
|
||||||
@@ -351,7 +400,7 @@ hlsCompileOpts =
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
<*> some (
|
<*> some (
|
||||||
option (eitherReader toolVersionEither)
|
option (eitherReader ghcVersionTagEither)
|
||||||
( long "ghc" <> metavar "GHC_VERSION|TAG" <> help "For which GHC version to compile for (can be specified multiple times)"
|
( long "ghc" <> metavar "GHC_VERSION|TAG" <> help "For which GHC version to compile for (can be specified multiple times)"
|
||||||
<> completer (tagCompleter GHC [])
|
<> completer (tagCompleter GHC [])
|
||||||
<> completer (versionCompleter Nothing GHC))
|
<> completer (versionCompleter Nothing GHC))
|
||||||
@@ -370,6 +419,7 @@ hlsCompileOpts =
|
|||||||
type GHCEffects = '[ AlreadyInstalled
|
type GHCEffects = '[ AlreadyInstalled
|
||||||
, BuildFailed
|
, BuildFailed
|
||||||
, DigestError
|
, DigestError
|
||||||
|
, ContentLengthError
|
||||||
, GPGError
|
, GPGError
|
||||||
, DownloadFailed
|
, DownloadFailed
|
||||||
, GHCupSetError
|
, GHCupSetError
|
||||||
@@ -393,6 +443,7 @@ type GHCEffects = '[ AlreadyInstalled
|
|||||||
type HLSEffects = '[ AlreadyInstalled
|
type HLSEffects = '[ AlreadyInstalled
|
||||||
, BuildFailed
|
, BuildFailed
|
||||||
, DigestError
|
, DigestError
|
||||||
|
, ContentLengthError
|
||||||
, GPGError
|
, GPGError
|
||||||
, DownloadFailed
|
, DownloadFailed
|
||||||
, GHCupSetError
|
, GHCupSetError
|
||||||
@@ -457,7 +508,7 @@ compile compileCommand settings Dirs{..} runAppState runLogger = do
|
|||||||
(CompileHLS HLSCompileOptions { .. }) -> do
|
(CompileHLS HLSCompileOptions { .. }) -> do
|
||||||
runCompileHLS runAppState (do
|
runCompileHLS runAppState (do
|
||||||
case targetHLS of
|
case targetHLS of
|
||||||
Left targetVer -> do
|
HLS.SourceDist targetVer -> do
|
||||||
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||||
let vi = getVersionInfo targetVer HLS dls
|
let vi = getVersionInfo targetVer HLS dls
|
||||||
forM_ (_viPreCompile =<< vi) $ \msg -> do
|
forM_ (_viPreCompile =<< vi) $ \msg -> do
|
||||||
@@ -465,7 +516,7 @@ compile compileCommand settings Dirs{..} runAppState runLogger = do
|
|||||||
lift $ logInfo
|
lift $ logInfo
|
||||||
"...waiting for 5 seconds, you can still abort..."
|
"...waiting for 5 seconds, you can still abort..."
|
||||||
liftIO $ threadDelay 5000000 -- for compilation, give the user a sec to intervene
|
liftIO $ threadDelay 5000000 -- for compilation, give the user a sec to intervene
|
||||||
Right _ -> pure ()
|
_ -> pure ()
|
||||||
ghcs <- liftE $ forM targetGHCs (\ghc -> fmap (_tvVersion . fst) . fromVersion (Just ghc) $ GHC)
|
ghcs <- liftE $ forM targetGHCs (\ghc -> fmap (_tvVersion . fst) . fromVersion (Just ghc) $ GHC)
|
||||||
targetVer <- liftE $ compileHLS
|
targetVer <- liftE $ compileHLS
|
||||||
targetHLS
|
targetHLS
|
||||||
@@ -475,6 +526,7 @@ compile compileCommand settings Dirs{..} runAppState runLogger = do
|
|||||||
(maybe GHCupInternal IsolateDir isolateDir)
|
(maybe GHCupInternal IsolateDir isolateDir)
|
||||||
cabalProject
|
cabalProject
|
||||||
cabalProjectLocal
|
cabalProjectLocal
|
||||||
|
updateCabal
|
||||||
patches
|
patches
|
||||||
cabalArgs
|
cabalArgs
|
||||||
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||||
@@ -493,14 +545,14 @@ compile compileCommand settings Dirs{..} runAppState runLogger = do
|
|||||||
pure ExitSuccess
|
pure ExitSuccess
|
||||||
VLeft err@(V (BuildFailed tmpdir _)) -> do
|
VLeft err@(V (BuildFailed tmpdir _)) -> do
|
||||||
case keepDirs settings of
|
case keepDirs settings of
|
||||||
Never -> runLogger $ logError $ T.pack $ prettyShow err
|
Never -> runLogger $ logError $ T.pack $ prettyHFError err
|
||||||
_ -> runLogger (logError $ T.pack (prettyShow err) <> "\n" <>
|
_ -> runLogger (logError $ T.pack (prettyHFError err) <> "\n" <>
|
||||||
"Check the logs at " <> T.pack (fromGHCupPath logsDir) <> " and the build directory "
|
"Check the logs at " <> T.pack (fromGHCupPath logsDir) <> " and the build directory "
|
||||||
<> T.pack tmpdir <> " for more clues." <> "\n" <>
|
<> T.pack tmpdir <> " for more clues." <> "\n" <>
|
||||||
"Make sure to clean up " <> T.pack tmpdir <> " afterwards.")
|
"Make sure to clean up " <> T.pack tmpdir <> " afterwards.")
|
||||||
pure $ ExitFailure 9
|
pure $ ExitFailure 9
|
||||||
VLeft e -> do
|
VLeft e -> do
|
||||||
runLogger $ logError $ T.pack $ prettyShow e
|
runLogger $ logError $ T.pack $ prettyHFError e
|
||||||
pure $ ExitFailure 9
|
pure $ ExitFailure 9
|
||||||
(CompileGHC GHCCompileOptions { hadrian = True, crossTarget = Just _ }) -> do
|
(CompileGHC GHCCompileOptions { hadrian = True, crossTarget = Just _ }) -> do
|
||||||
runLogger $ logError "Hadrian cross compile support is not yet implemented!"
|
runLogger $ logError "Hadrian cross compile support is not yet implemented!"
|
||||||
@@ -508,7 +560,7 @@ compile compileCommand settings Dirs{..} runAppState runLogger = do
|
|||||||
(CompileGHC GHCCompileOptions {..}) ->
|
(CompileGHC GHCCompileOptions {..}) ->
|
||||||
runCompileGHC runAppState (do
|
runCompileGHC runAppState (do
|
||||||
case targetGhc of
|
case targetGhc of
|
||||||
Left targetVer -> do
|
GHC.SourceDist targetVer -> do
|
||||||
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||||
let vi = getVersionInfo targetVer GHC dls
|
let vi = getVersionInfo targetVer GHC dls
|
||||||
forM_ (_viPreCompile =<< vi) $ \msg -> do
|
forM_ (_viPreCompile =<< vi) $ \msg -> do
|
||||||
@@ -516,9 +568,12 @@ compile compileCommand settings Dirs{..} runAppState runLogger = do
|
|||||||
lift $ logInfo
|
lift $ logInfo
|
||||||
"...waiting for 5 seconds, you can still abort..."
|
"...waiting for 5 seconds, you can still abort..."
|
||||||
liftIO $ threadDelay 5000000 -- for compilation, give the user a sec to intervene
|
liftIO $ threadDelay 5000000 -- for compilation, give the user a sec to intervene
|
||||||
Right _ -> pure ()
|
_ -> pure ()
|
||||||
targetVer <- liftE $ compileGHC
|
targetVer <- liftE $ compileGHC
|
||||||
(first (GHCTargetVersion crossTarget) targetGhc)
|
((\case
|
||||||
|
GHC.SourceDist v -> GHC.SourceDist $ GHCTargetVersion crossTarget v
|
||||||
|
GHC.GitDist g -> GHC.GitDist g
|
||||||
|
GHC.RemoteDist r -> GHC.RemoteDist r) targetGhc)
|
||||||
ovewrwiteVer
|
ovewrwiteVer
|
||||||
bootstrapGhc
|
bootstrapGhc
|
||||||
jobs
|
jobs
|
||||||
@@ -552,12 +607,12 @@ compile compileCommand settings Dirs{..} runAppState runLogger = do
|
|||||||
pure $ ExitFailure 3
|
pure $ ExitFailure 3
|
||||||
VLeft err@(V (BuildFailed tmpdir _)) -> do
|
VLeft err@(V (BuildFailed tmpdir _)) -> do
|
||||||
case keepDirs settings of
|
case keepDirs settings of
|
||||||
Never -> runLogger $ logError $ T.pack $ prettyShow err
|
Never -> runLogger $ logError $ T.pack $ prettyHFError err
|
||||||
_ -> runLogger (logError $ T.pack (prettyShow err) <> "\n" <>
|
_ -> runLogger (logError $ T.pack (prettyHFError err) <> "\n" <>
|
||||||
"Check the logs at " <> T.pack (fromGHCupPath logsDir) <> " and the build directory "
|
"Check the logs at " <> T.pack (fromGHCupPath logsDir) <> " and the build directory "
|
||||||
<> T.pack tmpdir <> " for more clues." <> "\n" <>
|
<> T.pack tmpdir <> " for more clues." <> "\n" <>
|
||||||
"Make sure to clean up " <> T.pack tmpdir <> " afterwards.")
|
"Make sure to clean up " <> T.pack tmpdir <> " afterwards.")
|
||||||
pure $ ExitFailure 9
|
pure $ ExitFailure 9
|
||||||
VLeft e -> do
|
VLeft e -> do
|
||||||
runLogger $ logError $ T.pack $ prettyShow e
|
runLogger $ logError $ T.pack $ prettyHFError e
|
||||||
pure $ ExitFailure 9
|
pure $ ExitFailure 9
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ data ConfigCommand
|
|||||||
--[ Parsers ]--
|
--[ Parsers ]--
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
|
||||||
configP :: Parser ConfigCommand
|
configP :: Parser ConfigCommand
|
||||||
configP = subparser
|
configP = subparser
|
||||||
( command "init" initP
|
( command "init" initP
|
||||||
@@ -120,18 +120,38 @@ formatConfig :: UserSettings -> String
|
|||||||
formatConfig = UTF8.toString . Y.encode
|
formatConfig = UTF8.toString . Y.encode
|
||||||
|
|
||||||
|
|
||||||
updateSettings :: UserSettings -> Settings -> Settings
|
updateSettings :: UserSettings -> UserSettings -> UserSettings
|
||||||
updateSettings UserSettings{..} Settings{..} =
|
updateSettings usl usr =
|
||||||
let cache' = fromMaybe cache uCache
|
let cache' = uCache usl <|> uCache usr
|
||||||
metaCache' = fromMaybe metaCache uMetaCache
|
metaCache' = uMetaCache usl <|> uMetaCache usr
|
||||||
noVerify' = fromMaybe noVerify uNoVerify
|
metaMode' = uMetaMode usl <|> uMetaMode usr
|
||||||
keepDirs' = fromMaybe keepDirs uKeepDirs
|
noVerify' = uNoVerify usl <|> uNoVerify usr
|
||||||
downloader' = fromMaybe downloader uDownloader
|
verbose' = uVerbose usl <|> uVerbose usr
|
||||||
verbose' = fromMaybe verbose uVerbose
|
keepDirs' = uKeepDirs usl <|> uKeepDirs usr
|
||||||
urlSource' = fromMaybe urlSource uUrlSource
|
downloader' = uDownloader usl <|> uDownloader usr
|
||||||
noNetwork' = fromMaybe noNetwork uNoNetwork
|
urlSource' = uUrlSource usl <|> uUrlSource usr
|
||||||
gpgSetting' = fromMaybe gpgSetting uGPGSetting
|
noNetwork' = uNoNetwork usl <|> uNoNetwork usr
|
||||||
in Settings cache' metaCache' noVerify' keepDirs' downloader' verbose' urlSource' noNetwork' gpgSetting' noColor
|
gpgSetting' = uGPGSetting usl <|> uGPGSetting usr
|
||||||
|
platformOverride' = uPlatformOverride usl <|> uPlatformOverride usr
|
||||||
|
mirrors' = uMirrors usl <|> uMirrors usr
|
||||||
|
in UserSettings cache' metaCache' metaMode' noVerify' verbose' keepDirs' downloader' (updateKeyBindings (uKeyBindings usl) (uKeyBindings usr)) urlSource' noNetwork' gpgSetting' platformOverride' mirrors'
|
||||||
|
where
|
||||||
|
updateKeyBindings :: Maybe UserKeyBindings -> Maybe UserKeyBindings -> Maybe UserKeyBindings
|
||||||
|
updateKeyBindings Nothing Nothing = Nothing
|
||||||
|
updateKeyBindings (Just kbl) Nothing = Just kbl
|
||||||
|
updateKeyBindings Nothing (Just kbr) = Just kbr
|
||||||
|
updateKeyBindings (Just kbl) (Just kbr) =
|
||||||
|
Just $ UserKeyBindings {
|
||||||
|
kUp = kUp kbl <|> kUp kbr
|
||||||
|
, kDown = kDown kbl <|> kDown kbr
|
||||||
|
, kQuit = kQuit kbl <|> kQuit kbr
|
||||||
|
, kInstall = kInstall kbl <|> kInstall kbr
|
||||||
|
, kUninstall = kUninstall kbl <|> kUninstall kbr
|
||||||
|
, kSet = kSet kbl <|> kSet kbr
|
||||||
|
, kChangelog = kChangelog kbl <|> kChangelog kbr
|
||||||
|
, kShowAll = kShowAll kbl <|> kShowAll kbr
|
||||||
|
, kShowAllTools = kShowAllTools kbl <|> kShowAllTools kbr
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -148,10 +168,11 @@ config :: forall m. ( Monad m
|
|||||||
)
|
)
|
||||||
=> ConfigCommand
|
=> ConfigCommand
|
||||||
-> Settings
|
-> Settings
|
||||||
|
-> UserSettings
|
||||||
-> KeyBindings
|
-> KeyBindings
|
||||||
-> (ReaderT LeanAppState m () -> m ())
|
-> (ReaderT LeanAppState m () -> m ())
|
||||||
-> m ExitCode
|
-> m ExitCode
|
||||||
config configCommand settings keybindings runLogger = case configCommand of
|
config configCommand settings userConf keybindings runLogger = case configCommand of
|
||||||
InitConfig -> do
|
InitConfig -> do
|
||||||
path <- getConfigFilePath
|
path <- getConfigFilePath
|
||||||
liftIO $ writeFile path $ formatConfig $ fromSettings settings (Just keybindings)
|
liftIO $ writeFile path $ formatConfig $ fromSettings settings (Just keybindings)
|
||||||
@@ -187,16 +208,22 @@ config configCommand settings keybindings runLogger = case configCommand of
|
|||||||
AddSource xs -> do
|
AddSource xs -> do
|
||||||
doConfig (defaultUserSettings { uUrlSource = Just $ AddSource (xs <> [Right uri]) })
|
doConfig (defaultUserSettings { uUrlSource = Just $ AddSource (xs <> [Right uri]) })
|
||||||
pure ExitSuccess
|
pure ExitSuccess
|
||||||
_ -> do
|
GHCupURL -> do
|
||||||
doConfig (defaultUserSettings { uUrlSource = Just $ AddSource [Right uri] })
|
doConfig (defaultUserSettings { uUrlSource = Just $ AddSource [Right uri] })
|
||||||
pure ExitSuccess
|
pure ExitSuccess
|
||||||
|
OwnSource xs -> do
|
||||||
|
doConfig (defaultUserSettings { uUrlSource = Just $ OwnSource (xs <> [Right uri]) })
|
||||||
|
pure ExitSuccess
|
||||||
|
OwnSpec spec -> do
|
||||||
|
doConfig (defaultUserSettings { uUrlSource = Just $ OwnSource ([Left spec, Right uri]) })
|
||||||
|
pure ExitSuccess
|
||||||
|
|
||||||
where
|
where
|
||||||
doConfig :: MonadIO m => UserSettings -> m ()
|
doConfig :: MonadIO m => UserSettings -> m ()
|
||||||
doConfig usersettings = do
|
doConfig usersettings = do
|
||||||
let settings' = updateSettings usersettings settings
|
let settings' = updateSettings usersettings userConf
|
||||||
path <- liftIO getConfigFilePath
|
path <- liftIO getConfigFilePath
|
||||||
liftIO $ writeFile path $ formatConfig $ fromSettings settings' (Just keybindings)
|
liftIO $ writeFile path $ formatConfig $ settings'
|
||||||
runLogger $ logDebug $ T.pack $ show settings'
|
runLogger $ logDebug $ T.pack $ show settings'
|
||||||
pure ()
|
pure ()
|
||||||
|
|
||||||
|
|||||||
@@ -115,5 +115,5 @@ dinfo runAppState runLogger = do
|
|||||||
liftIO $ putStrLn $ prettyDebugInfo di
|
liftIO $ putStrLn $ prettyDebugInfo di
|
||||||
pure ExitSuccess
|
pure ExitSuccess
|
||||||
VLeft e -> do
|
VLeft e -> do
|
||||||
runLogger $ logError $ T.pack $ prettyShow e
|
runLogger $ logError $ T.pack $ prettyHFError e
|
||||||
pure $ ExitFailure 8
|
pure $ ExitFailure 8
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ import Haskus.Utils.Variant.Excepts
|
|||||||
import Options.Applicative hiding ( style )
|
import Options.Applicative hiding ( style )
|
||||||
import Prelude hiding ( appendFile )
|
import Prelude hiding ( appendFile )
|
||||||
import System.Exit
|
import System.Exit
|
||||||
import Text.PrettyPrint.HughesPJClass ( prettyShow )
|
|
||||||
|
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import Control.Exception.Safe (MonadMask)
|
import Control.Exception.Safe (MonadMask)
|
||||||
@@ -139,5 +138,5 @@ gc GCOptions{..} runAppState runLogger = runGC runAppState (do
|
|||||||
VRight _ -> do
|
VRight _ -> do
|
||||||
pure ExitSuccess
|
pure ExitSuccess
|
||||||
VLeft e -> do
|
VLeft e -> do
|
||||||
runLogger $ logError $ T.pack $ prettyShow e
|
runLogger $ logError $ T.pack $ prettyHFError e
|
||||||
pure $ ExitFailure 27
|
pure $ ExitFailure 27
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
{-# LANGUAGE DuplicateRecordFields #-}
|
{-# LANGUAGE DuplicateRecordFields #-}
|
||||||
{-# LANGUAGE ViewPatterns #-}
|
{-# LANGUAGE ViewPatterns #-}
|
||||||
|
{-# LANGUAGE TypeOperators #-}
|
||||||
|
|
||||||
module GHCup.OptParse.Install where
|
module GHCup.OptParse.Install where
|
||||||
|
|
||||||
@@ -19,6 +20,7 @@ import GHCup
|
|||||||
import GHCup.Errors
|
import GHCup.Errors
|
||||||
import GHCup.Types
|
import GHCup.Types
|
||||||
import GHCup.Utils.Dirs
|
import GHCup.Utils.Dirs
|
||||||
|
import GHCup.Prelude
|
||||||
import GHCup.Prelude.Logger
|
import GHCup.Prelude.Logger
|
||||||
import GHCup.Prelude.String.QQ
|
import GHCup.Prelude.String.QQ
|
||||||
|
|
||||||
@@ -31,13 +33,11 @@ import Control.Monad.Trans.Resource
|
|||||||
import Data.Either
|
import Data.Either
|
||||||
import Data.Functor
|
import Data.Functor
|
||||||
import Data.Maybe
|
import Data.Maybe
|
||||||
import Data.Versions hiding ( str )
|
|
||||||
import Haskus.Utils.Variant.Excepts
|
import Haskus.Utils.Variant.Excepts
|
||||||
import Options.Applicative hiding ( style )
|
import Options.Applicative hiding ( style )
|
||||||
import Options.Applicative.Help.Pretty ( text )
|
import Options.Applicative.Help.Pretty ( text )
|
||||||
import Prelude hiding ( appendFile )
|
import Prelude hiding ( appendFile )
|
||||||
import System.Exit
|
import System.Exit
|
||||||
import Text.PrettyPrint.HughesPJClass ( prettyShow )
|
|
||||||
import URI.ByteString hiding ( uriParser )
|
import URI.ByteString hiding ( uriParser )
|
||||||
|
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
@@ -65,11 +65,11 @@ data InstallCommand = InstallGHC InstallOptions
|
|||||||
|
|
||||||
data InstallOptions = InstallOptions
|
data InstallOptions = InstallOptions
|
||||||
{ instVer :: Maybe ToolVersion
|
{ instVer :: Maybe ToolVersion
|
||||||
, instPlatform :: Maybe PlatformRequest
|
|
||||||
, instBindist :: Maybe URI
|
, instBindist :: Maybe URI
|
||||||
, instSet :: Bool
|
, instSet :: Bool
|
||||||
, isolateDir :: Maybe FilePath
|
, isolateDir :: Maybe FilePath
|
||||||
, forceInstall :: Bool
|
, forceInstall :: Bool
|
||||||
|
, addConfArgs :: [T.Text]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -169,23 +169,13 @@ Examples:
|
|||||||
ghcup install ghc 8.10.2
|
ghcup install ghc 8.10.2
|
||||||
|
|
||||||
# install GHC head fedora bindist
|
# install GHC head fedora bindist
|
||||||
ghcup install ghc -u https://gitlab.haskell.org/api/v4/projects/1/jobs/artifacts/master/raw/ghc-x86_64-fedora27-linux.tar.xz?job=validate-x86_64-linux-fedora27 head|]
|
ghcup install ghc -u 'https://gitlab.haskell.org/ghc/ghc/-/jobs/artifacts/master/raw/ghc-x86_64-linux-fedora33-release.tar.xz?job=x86_64-linux-fedora33-release' head|]
|
||||||
|
|
||||||
|
|
||||||
installOpts :: Maybe Tool -> Parser InstallOptions
|
installOpts :: Maybe Tool -> Parser InstallOptions
|
||||||
installOpts tool =
|
installOpts tool =
|
||||||
(\p (u, v) b is f -> InstallOptions v p u b is f)
|
(\(u, v) b is f -> InstallOptions v u b is f)
|
||||||
<$> optional
|
<$> ( ( (,)
|
||||||
(option
|
|
||||||
(eitherReader platformParser)
|
|
||||||
( short 'p'
|
|
||||||
<> long "platform"
|
|
||||||
<> metavar "PLATFORM"
|
|
||||||
<> help
|
|
||||||
"Override for platform (triple matching ghc tarball names), e.g. x86_64-fedora27-linux"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
<*> ( ( (,)
|
|
||||||
<$> optional
|
<$> optional
|
||||||
(option
|
(option
|
||||||
(eitherReader uriParser)
|
(eitherReader uriParser)
|
||||||
@@ -194,7 +184,7 @@ installOpts tool =
|
|||||||
<> completer (toolDlCompleter (fromMaybe GHC tool))
|
<> completer (toolDlCompleter (fromMaybe GHC tool))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
<*> (Just <$> toolVersionArgument Nothing tool)
|
<*> (Just <$> toolVersionTagArgument Nothing tool)
|
||||||
)
|
)
|
||||||
<|> pure (Nothing, Nothing)
|
<|> pure (Nothing, Nothing)
|
||||||
)
|
)
|
||||||
@@ -212,6 +202,7 @@ installOpts tool =
|
|||||||
)
|
)
|
||||||
<*> switch
|
<*> switch
|
||||||
(short 'f' <> long "force" <> help "Force install (THIS IS UNSAFE, only use it in Dockerfiles or CI)")
|
(short 'f' <> long "force" <> help "Force install (THIS IS UNSAFE, only use it in Dockerfiles or CI)")
|
||||||
|
<*> many (argument str (metavar "CONFIGURE_ARGS" <> help "Additional arguments to bindist configure, prefix with '-- ' (longopts)"))
|
||||||
where
|
where
|
||||||
setDefault = case tool of
|
setDefault = case tool of
|
||||||
Nothing -> False
|
Nothing -> False
|
||||||
@@ -251,6 +242,7 @@ type InstallEffects = '[ AlreadyInstalled
|
|||||||
, BuildFailed
|
, BuildFailed
|
||||||
, TagNotFound
|
, TagNotFound
|
||||||
, DigestError
|
, DigestError
|
||||||
|
, ContentLengthError
|
||||||
, GPGError
|
, GPGError
|
||||||
, DownloadFailed
|
, DownloadFailed
|
||||||
, TarDirDoesNotExist
|
, TarDirDoesNotExist
|
||||||
@@ -260,125 +252,49 @@ type InstallEffects = '[ AlreadyInstalled
|
|||||||
, ProcessError
|
, ProcessError
|
||||||
, UninstallFailed
|
, UninstallFailed
|
||||||
, MergeFileTreeError
|
, MergeFileTreeError
|
||||||
|
, InstallSetError
|
||||||
, (AlreadyInstalled, ())
|
|
||||||
, (UnknownArchive, ())
|
|
||||||
, (ArchiveResult, ())
|
|
||||||
, (FileDoesNotExistError, ())
|
|
||||||
, (CopyError, ())
|
|
||||||
, (NotInstalled, ())
|
|
||||||
, (UninstallFailed, ())
|
|
||||||
, (MergeFileTreeError, ())
|
|
||||||
, (DirNotEmpty, ())
|
|
||||||
, (NoDownload, ())
|
|
||||||
, (BuildFailed, ())
|
|
||||||
, (TagNotFound, ())
|
|
||||||
, (DigestError, ())
|
|
||||||
, (GPGError, ())
|
|
||||||
, (DownloadFailed, ())
|
|
||||||
, (TarDirDoesNotExist, ())
|
|
||||||
, (NextVerNotFound, ())
|
|
||||||
, (NoToolVersionSet, ())
|
|
||||||
, (FileAlreadyExistsError, ())
|
|
||||||
, (ProcessError, ())
|
|
||||||
|
|
||||||
, (AlreadyInstalled, NotInstalled)
|
|
||||||
, (UnknownArchive, NotInstalled)
|
|
||||||
, (ArchiveResult, NotInstalled)
|
|
||||||
, (FileDoesNotExistError, NotInstalled)
|
|
||||||
, (CopyError, NotInstalled)
|
|
||||||
, (NotInstalled, NotInstalled)
|
|
||||||
, (DirNotEmpty, NotInstalled)
|
|
||||||
, (NoDownload, NotInstalled)
|
|
||||||
, (NotInstalled, NotInstalled)
|
|
||||||
, (UninstallFailed, NotInstalled)
|
|
||||||
, (MergeFileTreeError, NotInstalled)
|
|
||||||
, (BuildFailed, NotInstalled)
|
|
||||||
, (TagNotFound, NotInstalled)
|
|
||||||
, (DigestError, NotInstalled)
|
|
||||||
, (GPGError, NotInstalled)
|
|
||||||
, (DownloadFailed, NotInstalled)
|
|
||||||
, (TarDirDoesNotExist, NotInstalled)
|
|
||||||
, (NextVerNotFound, NotInstalled)
|
|
||||||
, (NoToolVersionSet, NotInstalled)
|
|
||||||
, (FileAlreadyExistsError, NotInstalled)
|
|
||||||
, (ProcessError, NotInstalled)
|
|
||||||
|
|
||||||
, ((), NotInstalled)
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
runInstTool :: AppState
|
runInstTool :: AppState
|
||||||
-> Maybe PlatformRequest
|
|
||||||
-> Excepts InstallEffects (ResourceT (ReaderT AppState IO)) a
|
-> Excepts InstallEffects (ResourceT (ReaderT AppState IO)) a
|
||||||
-> IO (VEither InstallEffects a)
|
-> IO (VEither InstallEffects a)
|
||||||
runInstTool appstate' mInstPlatform =
|
runInstTool appstate' =
|
||||||
flip runReaderT (maybe appstate' (\x -> appstate'{ pfreq = x } :: AppState) mInstPlatform)
|
flip runReaderT appstate'
|
||||||
. runResourceT
|
. runResourceT
|
||||||
. runE
|
. runE
|
||||||
@InstallEffects
|
@InstallEffects
|
||||||
|
|
||||||
|
|
||||||
type InstallGHCEffects = '[ TagNotFound
|
type InstallGHCEffects = '[ AlreadyInstalled
|
||||||
, NextVerNotFound
|
, ArchiveResult
|
||||||
, NoToolVersionSet
|
|
||||||
, BuildFailed
|
, BuildFailed
|
||||||
|
, CopyError
|
||||||
|
, DigestError
|
||||||
|
, ContentLengthError
|
||||||
, DirNotEmpty
|
, DirNotEmpty
|
||||||
, AlreadyInstalled
|
, DownloadFailed
|
||||||
, UninstallFailed
|
, FileAlreadyExistsError
|
||||||
|
, FileDoesNotExistError
|
||||||
|
, GPGError
|
||||||
, MergeFileTreeError
|
, MergeFileTreeError
|
||||||
|
, NextVerNotFound
|
||||||
, (AlreadyInstalled, NotInstalled)
|
, NoDownload
|
||||||
, (UnknownArchive, NotInstalled)
|
, NoToolVersionSet
|
||||||
, (ArchiveResult, NotInstalled)
|
, NotInstalled
|
||||||
, (FileDoesNotExistError, NotInstalled)
|
, ProcessError
|
||||||
, (CopyError, NotInstalled)
|
, TagNotFound
|
||||||
, (NotInstalled, NotInstalled)
|
, TarDirDoesNotExist
|
||||||
, (DirNotEmpty, NotInstalled)
|
, UninstallFailed
|
||||||
, (NoDownload, NotInstalled)
|
, UnknownArchive
|
||||||
, (UninstallFailed, NotInstalled)
|
, InstallSetError
|
||||||
, (MergeFileTreeError, NotInstalled)
|
|
||||||
, (BuildFailed, NotInstalled)
|
|
||||||
, (TagNotFound, NotInstalled)
|
|
||||||
, (DigestError, NotInstalled)
|
|
||||||
, (GPGError, NotInstalled)
|
|
||||||
, (DownloadFailed, NotInstalled)
|
|
||||||
, (TarDirDoesNotExist, NotInstalled)
|
|
||||||
, (NextVerNotFound, NotInstalled)
|
|
||||||
, (NoToolVersionSet, NotInstalled)
|
|
||||||
, (FileAlreadyExistsError, NotInstalled)
|
|
||||||
, (ProcessError, NotInstalled)
|
|
||||||
|
|
||||||
, (AlreadyInstalled, ())
|
|
||||||
, (UnknownArchive, ())
|
|
||||||
, (ArchiveResult, ())
|
|
||||||
, (FileDoesNotExistError, ())
|
|
||||||
, (CopyError, ())
|
|
||||||
, (NotInstalled, ())
|
|
||||||
, (DirNotEmpty, ())
|
|
||||||
, (NoDownload, ())
|
|
||||||
, (UninstallFailed, ())
|
|
||||||
, (MergeFileTreeError, ())
|
|
||||||
, (BuildFailed, ())
|
|
||||||
, (TagNotFound, ())
|
|
||||||
, (DigestError, ())
|
|
||||||
, (GPGError, ())
|
|
||||||
, (DownloadFailed, ())
|
|
||||||
, (TarDirDoesNotExist, ())
|
|
||||||
, (NextVerNotFound, ())
|
|
||||||
, (NoToolVersionSet, ())
|
|
||||||
, (FileAlreadyExistsError, ())
|
|
||||||
, (ProcessError, ())
|
|
||||||
|
|
||||||
, ((), NotInstalled)
|
|
||||||
]
|
]
|
||||||
|
|
||||||
runInstGHC :: AppState
|
runInstGHC :: AppState
|
||||||
-> Maybe PlatformRequest
|
|
||||||
-> Excepts InstallGHCEffects (ResourceT (ReaderT AppState IO)) a
|
-> Excepts InstallGHCEffects (ResourceT (ReaderT AppState IO)) a
|
||||||
-> IO (VEither InstallGHCEffects a)
|
-> IO (VEither InstallGHCEffects a)
|
||||||
runInstGHC appstate' mInstPlatform =
|
runInstGHC appstate' =
|
||||||
flip runReaderT (maybe appstate' (\x -> appstate'{ pfreq = x } :: AppState) mInstPlatform)
|
flip runReaderT appstate'
|
||||||
. runResourceT
|
. runResourceT
|
||||||
. runE
|
. runE
|
||||||
@InstallGHCEffects
|
@InstallGHCEffects
|
||||||
@@ -403,25 +319,27 @@ install installCommand settings getAppState' runLogger = case installCommand of
|
|||||||
installGHC InstallOptions{..} = do
|
installGHC InstallOptions{..} = do
|
||||||
s'@AppState{ dirs = Dirs{ .. } } <- liftIO getAppState'
|
s'@AppState{ dirs = Dirs{ .. } } <- liftIO getAppState'
|
||||||
(case instBindist of
|
(case instBindist of
|
||||||
Nothing -> runInstGHC s' instPlatform $ do
|
Nothing -> runInstGHC s' $ do
|
||||||
(v, vi) <- liftE $ fromVersion instVer GHC
|
(v, vi) <- liftE $ fromVersion instVer GHC
|
||||||
void $ liftE $ sequenceE (installGHCBin
|
liftE $ runBothE' (installGHCBin
|
||||||
(_tvVersion v)
|
(_tvVersion v)
|
||||||
(maybe GHCupInternal IsolateDir isolateDir)
|
(maybe GHCupInternal IsolateDir isolateDir)
|
||||||
forceInstall
|
forceInstall
|
||||||
|
addConfArgs
|
||||||
)
|
)
|
||||||
$ when instSet $ when (isNothing isolateDir) $ void $ setGHC v SetGHCOnly Nothing
|
$ when instSet $ when (isNothing isolateDir) $ liftE $ void $ setGHC v SetGHCOnly Nothing
|
||||||
pure vi
|
pure vi
|
||||||
Just uri -> do
|
Just uri -> do
|
||||||
runInstGHC s'{ settings = settings {noVerify = True}} instPlatform $ do
|
runInstGHC s'{ settings = settings {noVerify = True}} $ do
|
||||||
(v, vi) <- liftE $ fromVersion instVer GHC
|
(v, vi) <- liftE $ fromVersion instVer GHC
|
||||||
void $ liftE $ sequenceE (installGHCBindist
|
liftE $ runBothE' (installGHCBindist
|
||||||
(DownloadInfo uri (Just $ RegexDir "ghc-.*") "")
|
(DownloadInfo uri (Just $ RegexDir "ghc-.*") "" Nothing)
|
||||||
(_tvVersion v)
|
(_tvVersion v)
|
||||||
(maybe GHCupInternal IsolateDir isolateDir)
|
(maybe GHCupInternal IsolateDir isolateDir)
|
||||||
forceInstall
|
forceInstall
|
||||||
|
addConfArgs
|
||||||
)
|
)
|
||||||
$ when instSet $ when (isNothing isolateDir) $ void $ setGHC v SetGHCOnly Nothing
|
$ when instSet $ when (isNothing isolateDir) $ liftE $ void $ setGHC v SetGHCOnly Nothing
|
||||||
pure vi
|
pure vi
|
||||||
)
|
)
|
||||||
>>= \case
|
>>= \case
|
||||||
@@ -431,42 +349,40 @@ install installCommand settings getAppState' runLogger = case installCommand of
|
|||||||
runLogger $ logInfo msg
|
runLogger $ logInfo msg
|
||||||
pure ExitSuccess
|
pure ExitSuccess
|
||||||
|
|
||||||
VLeft (V (AlreadyInstalled _ v, ())) -> do
|
VLeft e@(V (AlreadyInstalled _ _)) -> do
|
||||||
runLogger $ logWarn $
|
runLogger $ logWarn $ T.pack $ prettyHFError e
|
||||||
"GHC ver " <> prettyVer v <> " already installed, remove it first to reinstall"
|
|
||||||
pure ExitSuccess
|
pure ExitSuccess
|
||||||
VLeft (V (AlreadyInstalled _ v)) -> do
|
VLeft e@(V (AlreadyInstalled _ _)) -> do
|
||||||
runLogger $ logWarn $
|
runLogger $ logWarn $ T.pack $ prettyHFError e
|
||||||
"GHC ver " <> prettyVer v <> " already installed, remove it first to reinstall"
|
|
||||||
pure ExitSuccess
|
pure ExitSuccess
|
||||||
|
|
||||||
VLeft (V (DirNotEmpty fp)) -> do
|
VLeft (V (DirNotEmpty fp)) -> do
|
||||||
runLogger $ logError $
|
runLogger $ logError $
|
||||||
"Install directory " <> T.pack fp <> " is not empty."
|
"Install directory " <> T.pack fp <> " is not empty."
|
||||||
pure $ ExitFailure 3
|
pure $ ExitFailure 3
|
||||||
VLeft (V (DirNotEmpty fp, ())) -> do
|
VLeft (V (DirNotEmpty fp)) -> do
|
||||||
runLogger $ logError $
|
runLogger $ logError $
|
||||||
"Install directory " <> T.pack fp <> " is not empty."
|
"Install directory " <> T.pack fp <> " is not empty."
|
||||||
pure $ ExitFailure 3
|
pure $ ExitFailure 3
|
||||||
|
|
||||||
VLeft err@(V (BuildFailed tmpdir _)) -> do
|
VLeft err@(V (BuildFailed tmpdir _)) -> do
|
||||||
case keepDirs settings of
|
case keepDirs settings of
|
||||||
Never -> runLogger (logError $ T.pack $ prettyShow err)
|
Never -> runLogger (logError $ T.pack $ prettyHFError err)
|
||||||
_ -> runLogger (logError $ T.pack (prettyShow err) <> "\n" <>
|
_ -> runLogger (logError $ T.pack (prettyHFError err) <> "\n" <>
|
||||||
"Check the logs at " <> T.pack (fromGHCupPath logsDir) <> " and the build directory " <> T.pack tmpdir <> " for more clues." <> "\n" <>
|
"Check the logs at " <> T.pack (fromGHCupPath logsDir) <> " and the build directory " <> T.pack tmpdir <> " for more clues." <> "\n" <>
|
||||||
"Make sure to clean up " <> T.pack tmpdir <> " afterwards.")
|
"Make sure to clean up " <> T.pack tmpdir <> " afterwards.")
|
||||||
pure $ ExitFailure 3
|
pure $ ExitFailure 3
|
||||||
VLeft err@(V (BuildFailed tmpdir _, ())) -> do
|
VLeft err@(V (BuildFailed tmpdir _)) -> do
|
||||||
case keepDirs settings of
|
case keepDirs settings of
|
||||||
Never -> runLogger (logError $ T.pack $ prettyShow err)
|
Never -> runLogger (logError $ T.pack $ prettyHFError err)
|
||||||
_ -> runLogger (logError $ T.pack (prettyShow err) <> "\n" <>
|
_ -> runLogger (logError $ T.pack (prettyHFError err) <> "\n" <>
|
||||||
"Check the logs at " <> T.pack (fromGHCupPath logsDir) <> " and the build directory " <> T.pack tmpdir <> " for more clues." <> "\n" <>
|
"Check the logs at " <> T.pack (fromGHCupPath logsDir) <> " and the build directory " <> T.pack tmpdir <> " for more clues." <> "\n" <>
|
||||||
"Make sure to clean up " <> T.pack tmpdir <> " afterwards.")
|
"Make sure to clean up " <> T.pack tmpdir <> " afterwards.")
|
||||||
pure $ ExitFailure 3
|
pure $ ExitFailure 3
|
||||||
|
|
||||||
VLeft e -> do
|
VLeft e -> do
|
||||||
runLogger $ do
|
runLogger $ do
|
||||||
logError $ T.pack $ prettyShow e
|
logError $ T.pack $ prettyHFError e
|
||||||
logError $ "Also check the logs in " <> T.pack (fromGHCupPath logsDir)
|
logError $ "Also check the logs in " <> T.pack (fromGHCupPath logsDir)
|
||||||
pure $ ExitFailure 3
|
pure $ ExitFailure 3
|
||||||
|
|
||||||
@@ -475,23 +391,23 @@ install installCommand settings getAppState' runLogger = case installCommand of
|
|||||||
installCabal InstallOptions{..} = do
|
installCabal InstallOptions{..} = do
|
||||||
s'@AppState{ dirs = Dirs{ .. } } <- liftIO getAppState'
|
s'@AppState{ dirs = Dirs{ .. } } <- liftIO getAppState'
|
||||||
(case instBindist of
|
(case instBindist of
|
||||||
Nothing -> runInstTool s' instPlatform $ do
|
Nothing -> runInstTool s' $ do
|
||||||
(_tvVersion -> v, vi) <- liftE $ fromVersion instVer Cabal
|
(_tvVersion -> v, vi) <- liftE $ fromVersion instVer Cabal
|
||||||
void $ liftE $ sequenceE (installCabalBin
|
liftE $ runBothE' (installCabalBin
|
||||||
v
|
v
|
||||||
(maybe GHCupInternal IsolateDir isolateDir)
|
(maybe GHCupInternal IsolateDir isolateDir)
|
||||||
forceInstall
|
forceInstall
|
||||||
) $ when instSet $ when (isNothing isolateDir) $ void $ setCabal v
|
) $ when instSet $ when (isNothing isolateDir) $ liftE $ setCabal v
|
||||||
pure vi
|
pure vi
|
||||||
Just uri -> do
|
Just uri -> do
|
||||||
runInstTool s'{ settings = settings { noVerify = True}} instPlatform $ do
|
runInstTool s'{ settings = settings { noVerify = True}} $ do
|
||||||
(_tvVersion -> v, vi) <- liftE $ fromVersion instVer Cabal
|
(_tvVersion -> v, vi) <- liftE $ fromVersion instVer Cabal
|
||||||
void $ liftE $ sequenceE (installCabalBindist
|
liftE $ runBothE' (installCabalBindist
|
||||||
(DownloadInfo uri Nothing "")
|
(DownloadInfo uri Nothing "" Nothing)
|
||||||
v
|
v
|
||||||
(maybe GHCupInternal IsolateDir isolateDir)
|
(maybe GHCupInternal IsolateDir isolateDir)
|
||||||
forceInstall
|
forceInstall
|
||||||
) $ when instSet $ when (isNothing isolateDir) $ void $ setCabal v
|
) $ when instSet $ when (isNothing isolateDir) $ liftE $ setCabal v
|
||||||
pure vi
|
pure vi
|
||||||
)
|
)
|
||||||
>>= \case
|
>>= \case
|
||||||
@@ -500,25 +416,23 @@ install installCommand settings getAppState' runLogger = case installCommand of
|
|||||||
forM_ (_viPostInstall =<< vi) $ \msg ->
|
forM_ (_viPostInstall =<< vi) $ \msg ->
|
||||||
runLogger $ logInfo msg
|
runLogger $ logInfo msg
|
||||||
pure ExitSuccess
|
pure ExitSuccess
|
||||||
VLeft (V (AlreadyInstalled _ v)) -> do
|
VLeft e@(V (AlreadyInstalled _ _)) -> do
|
||||||
runLogger $ logWarn $
|
runLogger $ logWarn $ T.pack $ prettyHFError e
|
||||||
"Cabal ver " <> prettyVer v <> " already installed; if you really want to reinstall it, you may want to run 'ghcup install cabal --force " <> prettyVer v <> "'"
|
|
||||||
pure ExitSuccess
|
pure ExitSuccess
|
||||||
VLeft (V (FileAlreadyExistsError fp)) -> do
|
VLeft (V (FileAlreadyExistsError fp)) -> do
|
||||||
runLogger $ logWarn $
|
runLogger $ logWarn $
|
||||||
"File " <> T.pack fp <> " already exists. Use 'ghcup install cabal --isolate " <> T.pack fp <> " --force ..." <> "' if you want to overwrite."
|
"File " <> T.pack fp <> " already exists. Use 'ghcup install cabal --isolate " <> T.pack fp <> " --force ..." <> "' if you want to overwrite."
|
||||||
pure $ ExitFailure 3
|
pure $ ExitFailure 3
|
||||||
VLeft (V (AlreadyInstalled _ v, ())) -> do
|
VLeft e@(V (AlreadyInstalled _ _)) -> do
|
||||||
runLogger $ logWarn $
|
runLogger $ logWarn $ T.pack $ prettyHFError e
|
||||||
"Cabal ver " <> prettyVer v <> " already installed; if you really want to reinstall it, you may want to run 'ghcup install cabal --force " <> prettyVer v <> "'"
|
|
||||||
pure ExitSuccess
|
pure ExitSuccess
|
||||||
VLeft (V (FileAlreadyExistsError fp, ())) -> do
|
VLeft (V (FileAlreadyExistsError fp)) -> do
|
||||||
runLogger $ logWarn $
|
runLogger $ logWarn $
|
||||||
"File " <> T.pack fp <> " already exists. Use 'ghcup install cabal --isolate " <> T.pack fp <> " --force ..." <> "' if you want to overwrite."
|
"File " <> T.pack fp <> " already exists. Use 'ghcup install cabal --isolate " <> T.pack fp <> " --force ..." <> "' if you want to overwrite."
|
||||||
pure $ ExitFailure 3
|
pure $ ExitFailure 3
|
||||||
VLeft e -> do
|
VLeft e -> do
|
||||||
runLogger $ do
|
runLogger $ do
|
||||||
logError $ T.pack $ prettyShow e
|
logError $ T.pack $ prettyHFError e
|
||||||
logError $ "Also check the logs in " <> T.pack (fromGHCupPath logsDir)
|
logError $ "Also check the logs in " <> T.pack (fromGHCupPath logsDir)
|
||||||
pure $ ExitFailure 4
|
pure $ ExitFailure 4
|
||||||
|
|
||||||
@@ -526,24 +440,24 @@ install installCommand settings getAppState' runLogger = case installCommand of
|
|||||||
installHLS InstallOptions{..} = do
|
installHLS InstallOptions{..} = do
|
||||||
s'@AppState{ dirs = Dirs{ .. } } <- liftIO getAppState'
|
s'@AppState{ dirs = Dirs{ .. } } <- liftIO getAppState'
|
||||||
(case instBindist of
|
(case instBindist of
|
||||||
Nothing -> runInstTool s' instPlatform $ do
|
Nothing -> runInstTool s' $ do
|
||||||
(_tvVersion -> v, vi) <- liftE $ fromVersion instVer HLS
|
(_tvVersion -> v, vi) <- liftE $ fromVersion instVer HLS
|
||||||
void $ liftE $ sequenceE (installHLSBin
|
liftE $ runBothE' (installHLSBin
|
||||||
v
|
v
|
||||||
(maybe GHCupInternal IsolateDir isolateDir)
|
(maybe GHCupInternal IsolateDir isolateDir)
|
||||||
forceInstall
|
forceInstall
|
||||||
) $ when instSet $ when (isNothing isolateDir) $ void $ setHLS v SetHLSOnly Nothing
|
) $ when instSet $ when (isNothing isolateDir) $ liftE $ setHLS v SetHLSOnly Nothing
|
||||||
pure vi
|
pure vi
|
||||||
Just uri -> do
|
Just uri -> do
|
||||||
runInstTool s'{ settings = settings { noVerify = True}} instPlatform $ do
|
runInstTool s'{ settings = settings { noVerify = True}} $ do
|
||||||
(_tvVersion -> v, vi) <- liftE $ fromVersion instVer HLS
|
(_tvVersion -> v, vi) <- liftE $ fromVersion instVer HLS
|
||||||
-- TODO: support legacy
|
-- TODO: support legacy
|
||||||
void $ liftE $ sequenceE (installHLSBindist
|
liftE $ runBothE' (installHLSBindist
|
||||||
(DownloadInfo uri (Just $ RegexDir "haskell-language-server-*") "")
|
(DownloadInfo uri (if isWindows then Nothing else Just (RegexDir "haskell-language-server-*")) "" Nothing)
|
||||||
v
|
v
|
||||||
(maybe GHCupInternal IsolateDir isolateDir)
|
(maybe GHCupInternal IsolateDir isolateDir)
|
||||||
forceInstall
|
forceInstall
|
||||||
) $ when instSet $ when (isNothing isolateDir) $ void $ setHLS v SetHLSOnly Nothing
|
) $ when instSet $ when (isNothing isolateDir) $ liftE $ setHLS v SetHLSOnly Nothing
|
||||||
pure vi
|
pure vi
|
||||||
)
|
)
|
||||||
>>= \case
|
>>= \case
|
||||||
@@ -552,33 +466,23 @@ install installCommand settings getAppState' runLogger = case installCommand of
|
|||||||
forM_ (_viPostInstall =<< vi) $ \msg ->
|
forM_ (_viPostInstall =<< vi) $ \msg ->
|
||||||
runLogger $ logInfo msg
|
runLogger $ logInfo msg
|
||||||
pure ExitSuccess
|
pure ExitSuccess
|
||||||
VLeft (V (AlreadyInstalled _ v)) -> do
|
VLeft e@(V (AlreadyInstalled _ _)) -> do
|
||||||
runLogger $ logWarn $
|
runLogger $ logWarn $ T.pack $ prettyHFError e
|
||||||
"HLS ver "
|
|
||||||
<> prettyVer v
|
|
||||||
<> " already installed; if you really want to reinstall it, you may want to run 'ghcup install hls --force "
|
|
||||||
<> prettyVer v
|
|
||||||
<> "'"
|
|
||||||
pure ExitSuccess
|
pure ExitSuccess
|
||||||
VLeft (V (FileAlreadyExistsError fp)) -> do
|
VLeft (V (FileAlreadyExistsError fp)) -> do
|
||||||
runLogger $ logWarn $
|
runLogger $ logWarn $
|
||||||
"File " <> T.pack fp <> " already exists. Use 'ghcup install hls --isolate " <> T.pack fp <> " --force ..." <> "' if you want to overwrite."
|
"File " <> T.pack fp <> " already exists. Use 'ghcup install hls --isolate " <> T.pack fp <> " --force ..." <> "' if you want to overwrite."
|
||||||
pure $ ExitFailure 3
|
pure $ ExitFailure 3
|
||||||
VLeft (V (AlreadyInstalled _ v, ())) -> do
|
VLeft e@(V (AlreadyInstalled _ _)) -> do
|
||||||
runLogger $ logWarn $
|
runLogger $ logWarn $ T.pack $ prettyHFError e
|
||||||
"HLS ver "
|
|
||||||
<> prettyVer v
|
|
||||||
<> " already installed; if you really want to reinstall it, you may want to run 'ghcup install hls --force "
|
|
||||||
<> prettyVer v
|
|
||||||
<> "'"
|
|
||||||
pure ExitSuccess
|
pure ExitSuccess
|
||||||
VLeft (V (FileAlreadyExistsError fp, ())) -> do
|
VLeft (V (FileAlreadyExistsError fp)) -> do
|
||||||
runLogger $ logWarn $
|
runLogger $ logWarn $
|
||||||
"File " <> T.pack fp <> " already exists. Use 'ghcup install hls --isolate " <> T.pack fp <> " --force ..." <> "' if you want to overwrite."
|
"File " <> T.pack fp <> " already exists. Use 'ghcup install hls --isolate " <> T.pack fp <> " --force ..." <> "' if you want to overwrite."
|
||||||
pure $ ExitFailure 3
|
pure $ ExitFailure 3
|
||||||
VLeft e -> do
|
VLeft e -> do
|
||||||
runLogger $ do
|
runLogger $ do
|
||||||
logError $ T.pack $ prettyShow e
|
logError $ T.pack $ prettyHFError e
|
||||||
logError $ "Also check the logs in " <> T.pack (fromGHCupPath logsDir)
|
logError $ "Also check the logs in " <> T.pack (fromGHCupPath logsDir)
|
||||||
pure $ ExitFailure 4
|
pure $ ExitFailure 4
|
||||||
|
|
||||||
@@ -586,23 +490,23 @@ install installCommand settings getAppState' runLogger = case installCommand of
|
|||||||
installStack InstallOptions{..} = do
|
installStack InstallOptions{..} = do
|
||||||
s'@AppState{ dirs = Dirs{ .. } } <- liftIO getAppState'
|
s'@AppState{ dirs = Dirs{ .. } } <- liftIO getAppState'
|
||||||
(case instBindist of
|
(case instBindist of
|
||||||
Nothing -> runInstTool s' instPlatform $ do
|
Nothing -> runInstTool s' $ do
|
||||||
(_tvVersion -> v, vi) <- liftE $ fromVersion instVer Stack
|
(_tvVersion -> v, vi) <- liftE $ fromVersion instVer Stack
|
||||||
void $ liftE $ sequenceE (installStackBin
|
liftE $ runBothE' (installStackBin
|
||||||
v
|
v
|
||||||
(maybe GHCupInternal IsolateDir isolateDir)
|
(maybe GHCupInternal IsolateDir isolateDir)
|
||||||
forceInstall
|
forceInstall
|
||||||
) $ when instSet $ when (isNothing isolateDir) $ void $ setStack v
|
) $ when instSet $ when (isNothing isolateDir) $ liftE $ setStack v
|
||||||
pure vi
|
pure vi
|
||||||
Just uri -> do
|
Just uri -> do
|
||||||
runInstTool s'{ settings = settings { noVerify = True}} instPlatform $ do
|
runInstTool s'{ settings = settings { noVerify = True}} $ do
|
||||||
(_tvVersion -> v, vi) <- liftE $ fromVersion instVer Stack
|
(_tvVersion -> v, vi) <- liftE $ fromVersion instVer Stack
|
||||||
void $ liftE $ sequenceE (installStackBindist
|
liftE $ runBothE' (installStackBindist
|
||||||
(DownloadInfo uri Nothing "")
|
(DownloadInfo uri Nothing "" Nothing)
|
||||||
v
|
v
|
||||||
(maybe GHCupInternal IsolateDir isolateDir)
|
(maybe GHCupInternal IsolateDir isolateDir)
|
||||||
forceInstall
|
forceInstall
|
||||||
) $ when instSet $ when (isNothing isolateDir) $ void $ setStack v
|
) $ when instSet $ when (isNothing isolateDir) $ liftE $ setStack v
|
||||||
pure vi
|
pure vi
|
||||||
)
|
)
|
||||||
>>= \case
|
>>= \case
|
||||||
@@ -611,25 +515,22 @@ install installCommand settings getAppState' runLogger = case installCommand of
|
|||||||
forM_ (_viPostInstall =<< vi) $ \msg ->
|
forM_ (_viPostInstall =<< vi) $ \msg ->
|
||||||
runLogger $ logInfo msg
|
runLogger $ logInfo msg
|
||||||
pure ExitSuccess
|
pure ExitSuccess
|
||||||
VLeft (V (AlreadyInstalled _ v)) -> do
|
VLeft e@(V (AlreadyInstalled _ _)) -> do
|
||||||
runLogger $ logWarn $
|
runLogger $ logWarn $ T.pack $ prettyHFError e
|
||||||
"Stack ver " <> prettyVer v <> " already installed; if you really want to reinstall it, you may want to run 'ghcup install stack --force " <> prettyVer v <> "'"
|
|
||||||
pure ExitSuccess
|
pure ExitSuccess
|
||||||
VLeft (V (FileAlreadyExistsError fp)) -> do
|
VLeft (V (FileAlreadyExistsError fp)) -> do
|
||||||
runLogger $ logWarn $
|
runLogger $ logWarn $
|
||||||
"File " <> T.pack fp <> " already exists. Use 'ghcup install stack --isolate " <> T.pack fp <> " --force ..." <> "' if you want to overwrite."
|
"File " <> T.pack fp <> " already exists. Use 'ghcup install stack --isolate " <> T.pack fp <> " --force ..." <> "' if you want to overwrite."
|
||||||
pure $ ExitFailure 3
|
pure $ ExitFailure 3
|
||||||
VLeft (V (AlreadyInstalled _ v, ())) -> do
|
VLeft e@(V (AlreadyInstalled _ _)) -> do
|
||||||
runLogger $ logWarn $
|
runLogger $ logWarn $ T.pack $ prettyHFError e
|
||||||
"Stack ver " <> prettyVer v <> " already installed; if you really want to reinstall it, you may want to run 'ghcup install stack --force " <> prettyVer v <> "'"
|
|
||||||
pure ExitSuccess
|
pure ExitSuccess
|
||||||
VLeft (V (FileAlreadyExistsError fp, ())) -> do
|
VLeft (V (FileAlreadyExistsError fp)) -> do
|
||||||
runLogger $ logWarn $
|
runLogger $ logWarn $
|
||||||
"File " <> T.pack fp <> " already exists. Use 'ghcup install stack --isolate " <> T.pack fp <> " --force ..." <> "' if you want to overwrite."
|
"File " <> T.pack fp <> " already exists. Use 'ghcup install stack --isolate " <> T.pack fp <> " --force ..." <> "' if you want to overwrite."
|
||||||
pure $ ExitFailure 3
|
pure $ ExitFailure 3
|
||||||
VLeft e -> do
|
VLeft e -> do
|
||||||
runLogger $ do
|
runLogger $ do
|
||||||
logError $ T.pack $ prettyShow e
|
logError $ T.pack $ prettyHFError e
|
||||||
logError $ "Also check the logs in " <> T.pack (fromGHCupPath logsDir)
|
logError $ "Also check the logs in " <> T.pack (fromGHCupPath logsDir)
|
||||||
pure $ ExitFailure 4
|
pure $ ExitFailure 4
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ import Haskus.Utils.Variant.Excepts
|
|||||||
import Options.Applicative hiding ( style )
|
import Options.Applicative hiding ( style )
|
||||||
import Prelude hiding ( appendFile )
|
import Prelude hiding ( appendFile )
|
||||||
import System.Exit
|
import System.Exit
|
||||||
import Text.PrettyPrint.HughesPJClass ( prettyShow )
|
|
||||||
|
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import Control.Exception.Safe (MonadMask)
|
import Control.Exception.Safe (MonadMask)
|
||||||
@@ -95,5 +94,5 @@ nuke appState runLogger = do
|
|||||||
pure ExitSuccess
|
pure ExitSuccess
|
||||||
|
|
||||||
VLeft e -> do
|
VLeft e -> do
|
||||||
runLogger $ logError $ T.pack $ prettyShow e
|
runLogger $ logError $ T.pack $ prettyHFError e
|
||||||
pure $ ExitFailure 15
|
pure $ ExitFailure 15
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ import Haskus.Utils.Variant.Excepts
|
|||||||
import Options.Applicative hiding ( style )
|
import Options.Applicative hiding ( style )
|
||||||
import Prelude hiding ( appendFile )
|
import Prelude hiding ( appendFile )
|
||||||
import System.Exit
|
import System.Exit
|
||||||
import Text.PrettyPrint.HughesPJClass ( prettyShow )
|
|
||||||
|
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import Control.Exception.Safe (MonadMask)
|
import Control.Exception.Safe (MonadMask)
|
||||||
@@ -74,44 +73,44 @@ data PrefetchGHCOptions = PrefetchGHCOptions {
|
|||||||
--[ Parsers ]--
|
--[ Parsers ]--
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
|
||||||
prefetchP :: Parser PrefetchCommand
|
prefetchP :: Parser PrefetchCommand
|
||||||
prefetchP = subparser
|
prefetchP = subparser
|
||||||
( command
|
( command
|
||||||
"ghc"
|
"ghc"
|
||||||
(info
|
(info
|
||||||
(PrefetchGHC
|
(PrefetchGHC
|
||||||
<$> (PrefetchGHCOptions
|
<$> (PrefetchGHCOptions
|
||||||
<$> ( switch (short 's' <> long "source" <> help "Download source tarball instead of bindist") <**> helper )
|
<$> ( switch (short 's' <> long "source" <> help "Download source tarball instead of bindist") <**> helper )
|
||||||
<*> optional (option str (short 'd' <> long "directory" <> help "directory to download into (default: ~/.ghcup/cache/)" <> completer (bashCompleter "directory"))))
|
<*> optional (option str (short 'd' <> long "directory" <> help "directory to download into (default: ~/.ghcup/cache/)" <> completer (bashCompleter "directory"))))
|
||||||
<*> optional (toolVersionArgument Nothing (Just GHC)) )
|
<*> optional (toolVersionTagArgument Nothing (Just GHC)) )
|
||||||
( progDesc "Download GHC assets for installation")
|
( progDesc "Download GHC assets for installation")
|
||||||
)
|
)
|
||||||
<>
|
<>
|
||||||
command
|
command
|
||||||
"cabal"
|
"cabal"
|
||||||
(info
|
(info
|
||||||
(PrefetchCabal
|
(PrefetchCabal
|
||||||
<$> fmap PrefetchOptions (optional (option str (short 'd' <> long "directory" <> help "directory to download into (default: ~/.ghcup/cache/)" <> completer (bashCompleter "directory"))))
|
<$> fmap PrefetchOptions (optional (option str (short 'd' <> long "directory" <> help "directory to download into (default: ~/.ghcup/cache/)" <> completer (bashCompleter "directory"))))
|
||||||
<*> ( optional (toolVersionArgument Nothing (Just Cabal)) <**> helper ))
|
<*> ( optional (toolVersionTagArgument Nothing (Just Cabal)) <**> helper ))
|
||||||
( progDesc "Download cabal assets for installation")
|
( progDesc "Download cabal assets for installation")
|
||||||
)
|
)
|
||||||
<>
|
<>
|
||||||
command
|
command
|
||||||
"hls"
|
"hls"
|
||||||
(info
|
(info
|
||||||
(PrefetchHLS
|
(PrefetchHLS
|
||||||
<$> fmap PrefetchOptions (optional (option str (short 'd' <> long "directory" <> help "directory to download into (default: ~/.ghcup/cache/)" <> completer (bashCompleter "directory"))))
|
<$> fmap PrefetchOptions (optional (option str (short 'd' <> long "directory" <> help "directory to download into (default: ~/.ghcup/cache/)" <> completer (bashCompleter "directory"))))
|
||||||
<*> ( optional (toolVersionArgument Nothing (Just HLS)) <**> helper ))
|
<*> ( optional (toolVersionTagArgument Nothing (Just HLS)) <**> helper ))
|
||||||
( progDesc "Download HLS assets for installation")
|
( progDesc "Download HLS assets for installation")
|
||||||
)
|
)
|
||||||
<>
|
<>
|
||||||
command
|
command
|
||||||
"stack"
|
"stack"
|
||||||
(info
|
(info
|
||||||
(PrefetchStack
|
(PrefetchStack
|
||||||
<$> fmap PrefetchOptions (optional (option str (short 'd' <> long "directory" <> help "directory to download into (default: ~/.ghcup/cache/)" <> completer (bashCompleter "directory"))))
|
<$> fmap PrefetchOptions (optional (option str (short 'd' <> long "directory" <> help "directory to download into (default: ~/.ghcup/cache/)" <> completer (bashCompleter "directory"))))
|
||||||
<*> ( optional (toolVersionArgument Nothing (Just Stack)) <**> helper ))
|
<*> ( optional (toolVersionTagArgument Nothing (Just Stack)) <**> helper ))
|
||||||
( progDesc "Download stack assets for installation")
|
( progDesc "Download stack assets for installation")
|
||||||
)
|
)
|
||||||
<>
|
<>
|
||||||
@@ -153,6 +152,7 @@ type PrefetchEffects = '[ TagNotFound
|
|||||||
, NoToolVersionSet
|
, NoToolVersionSet
|
||||||
, NoDownload
|
, NoDownload
|
||||||
, DigestError
|
, DigestError
|
||||||
|
, ContentLengthError
|
||||||
, GPGError
|
, GPGError
|
||||||
, DownloadFailed
|
, DownloadFailed
|
||||||
, JSONError
|
, JSONError
|
||||||
@@ -215,5 +215,5 @@ prefetch prefetchCommand runAppState runLogger =
|
|||||||
VRight _ -> do
|
VRight _ -> do
|
||||||
pure ExitSuccess
|
pure ExitSuccess
|
||||||
VLeft e -> do
|
VLeft e -> do
|
||||||
runLogger $ logError $ T.pack $ prettyShow e
|
runLogger $ logError $ T.pack $ prettyHFError e
|
||||||
pure $ ExitFailure 15
|
pure $ ExitFailure 15
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ import Haskus.Utils.Variant.Excepts
|
|||||||
import Options.Applicative hiding ( style )
|
import Options.Applicative hiding ( style )
|
||||||
import Prelude hiding ( appendFile )
|
import Prelude hiding ( appendFile )
|
||||||
import System.Exit
|
import System.Exit
|
||||||
import Text.PrettyPrint.HughesPJClass ( prettyShow )
|
|
||||||
|
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import Control.Exception.Safe (MonadMask)
|
import Control.Exception.Safe (MonadMask)
|
||||||
@@ -71,7 +70,7 @@ data RmOptions = RmOptions
|
|||||||
--[ Parsers ]--
|
--[ Parsers ]--
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
|
||||||
rmParser :: Parser (Either RmCommand RmOptions)
|
rmParser :: Parser (Either RmCommand RmOptions)
|
||||||
rmParser =
|
rmParser =
|
||||||
(Left <$> subparser
|
(Left <$> subparser
|
||||||
@@ -103,7 +102,7 @@ rmParser =
|
|||||||
|
|
||||||
|
|
||||||
rmOpts :: Maybe Tool -> Parser RmOptions
|
rmOpts :: Maybe Tool -> Parser RmOptions
|
||||||
rmOpts tool = RmOptions <$> versionArgument (Just ListInstalled) tool
|
rmOpts tool = RmOptions <$> ghcVersionArgument (Just ListInstalled) tool
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -175,11 +174,11 @@ rm rmCommand runAppState runLogger = case rmCommand of
|
|||||||
)
|
)
|
||||||
>>= \case
|
>>= \case
|
||||||
VRight vi -> do
|
VRight vi -> do
|
||||||
forM_ (_viPostRemove =<< vi) $ \msg ->
|
runLogger $ logGHCPostRm ghcVer
|
||||||
runLogger $ logInfo msg
|
postRmLog vi
|
||||||
pure ExitSuccess
|
pure ExitSuccess
|
||||||
VLeft e -> do
|
VLeft e -> do
|
||||||
runLogger $ logError $ T.pack $ prettyShow e
|
runLogger $ logError $ T.pack $ prettyHFError e
|
||||||
pure $ ExitFailure 7
|
pure $ ExitFailure 7
|
||||||
|
|
||||||
rmCabal' tv =
|
rmCabal' tv =
|
||||||
@@ -191,11 +190,10 @@ rm rmCommand runAppState runLogger = case rmCommand of
|
|||||||
)
|
)
|
||||||
>>= \case
|
>>= \case
|
||||||
VRight vi -> do
|
VRight vi -> do
|
||||||
forM_ (_viPostRemove =<< vi) $ \msg ->
|
postRmLog vi
|
||||||
runLogger $ logInfo msg
|
|
||||||
pure ExitSuccess
|
pure ExitSuccess
|
||||||
VLeft e -> do
|
VLeft e -> do
|
||||||
runLogger $ logError $ T.pack $ prettyShow e
|
runLogger $ logError $ T.pack $ prettyHFError e
|
||||||
pure $ ExitFailure 15
|
pure $ ExitFailure 15
|
||||||
|
|
||||||
rmHLS' tv =
|
rmHLS' tv =
|
||||||
@@ -207,11 +205,10 @@ rm rmCommand runAppState runLogger = case rmCommand of
|
|||||||
)
|
)
|
||||||
>>= \case
|
>>= \case
|
||||||
VRight vi -> do
|
VRight vi -> do
|
||||||
forM_ (_viPostRemove =<< vi) $ \msg ->
|
postRmLog vi
|
||||||
runLogger $ logInfo msg
|
|
||||||
pure ExitSuccess
|
pure ExitSuccess
|
||||||
VLeft e -> do
|
VLeft e -> do
|
||||||
runLogger $ logError $ T.pack $ prettyShow e
|
runLogger $ logError $ T.pack $ prettyHFError e
|
||||||
pure $ ExitFailure 15
|
pure $ ExitFailure 15
|
||||||
|
|
||||||
rmStack' tv =
|
rmStack' tv =
|
||||||
@@ -223,10 +220,12 @@ rm rmCommand runAppState runLogger = case rmCommand of
|
|||||||
)
|
)
|
||||||
>>= \case
|
>>= \case
|
||||||
VRight vi -> do
|
VRight vi -> do
|
||||||
forM_ (_viPostRemove =<< vi) $ \msg ->
|
postRmLog vi
|
||||||
runLogger $ logInfo msg
|
|
||||||
pure ExitSuccess
|
pure ExitSuccess
|
||||||
VLeft e -> do
|
VLeft e -> do
|
||||||
runLogger $ logError $ T.pack $ prettyShow e
|
runLogger $ logError $ T.pack $ prettyHFError e
|
||||||
pure $ ExitFailure 15
|
pure $ ExitFailure 15
|
||||||
|
|
||||||
|
postRmLog vi =
|
||||||
|
forM_ (_viPostRemove =<< vi) $ \msg ->
|
||||||
|
runLogger $ logInfo msg
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
{-# LANGUAGE RankNTypes #-}
|
{-# LANGUAGE RankNTypes #-}
|
||||||
{-# LANGUAGE FlexibleContexts #-}
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
{-# LANGUAGE TypeFamilies #-}
|
{-# LANGUAGE TypeFamilies #-}
|
||||||
|
{-# LANGUAGE ViewPatterns #-}
|
||||||
module GHCup.OptParse.Run where
|
module GHCup.OptParse.Run where
|
||||||
|
|
||||||
|
|
||||||
@@ -18,6 +19,7 @@ import GHCup.Prelude
|
|||||||
import GHCup.Prelude.File
|
import GHCup.Prelude.File
|
||||||
#ifdef IS_WINDOWS
|
#ifdef IS_WINDOWS
|
||||||
import GHCup.Prelude.Process
|
import GHCup.Prelude.Process
|
||||||
|
import GHCup.Prelude.Process.Windows ( execNoMinGW )
|
||||||
#endif
|
#endif
|
||||||
import GHCup.Prelude.Logger
|
import GHCup.Prelude.Logger
|
||||||
import GHCup.Prelude.String.QQ
|
import GHCup.Prelude.String.QQ
|
||||||
@@ -38,13 +40,13 @@ import Prelude hiding ( appendFile )
|
|||||||
import System.FilePath
|
import System.FilePath
|
||||||
import System.Environment
|
import System.Environment
|
||||||
import System.Exit
|
import System.Exit
|
||||||
import Text.PrettyPrint.HughesPJClass ( prettyShow )
|
|
||||||
|
|
||||||
import qualified Data.Map.Strict as Map
|
import qualified Data.Map.Strict as Map
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
#ifndef IS_WINDOWS
|
#ifndef IS_WINDOWS
|
||||||
import qualified System.Posix.Process as SPP
|
import qualified System.Posix.Process as SPP
|
||||||
#endif
|
#endif
|
||||||
|
import Data.Versions ( prettyVer, Version )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -58,6 +60,7 @@ import qualified System.Posix.Process as SPP
|
|||||||
data RunOptions = RunOptions
|
data RunOptions = RunOptions
|
||||||
{ runAppendPATH :: Bool
|
{ runAppendPATH :: Bool
|
||||||
, runInstTool' :: Bool
|
, runInstTool' :: Bool
|
||||||
|
, runMinGWPath :: Bool
|
||||||
, runGHCVer :: Maybe ToolVersion
|
, runGHCVer :: Maybe ToolVersion
|
||||||
, runCabalVer :: Maybe ToolVersion
|
, runCabalVer :: Maybe ToolVersion
|
||||||
, runHLSVer :: Maybe ToolVersion
|
, runHLSVer :: Maybe ToolVersion
|
||||||
@@ -82,9 +85,11 @@ runOpts =
|
|||||||
(short 'a' <> long "append" <> help "Append bin/ dir to PATH instead of prepending (this means that e.g. a system installation may take precedence)")
|
(short 'a' <> long "append" <> help "Append bin/ dir to PATH instead of prepending (this means that e.g. a system installation may take precedence)")
|
||||||
<*> switch
|
<*> switch
|
||||||
(short 'i' <> long "install" <> help "Install the tool, if missing")
|
(short 'i' <> long "install" <> help "Install the tool, if missing")
|
||||||
|
<*> switch
|
||||||
|
(short 'm' <> long "mingw-path" <> help "On windows, add mingw64 PATHs to environment (does nothing on unix)")
|
||||||
<*> optional
|
<*> optional
|
||||||
(option
|
(option
|
||||||
(eitherReader toolVersionEither)
|
(eitherReader ghcVersionTagEither)
|
||||||
(metavar "GHC_VERSION" <> long "ghc" <> help "The ghc version"
|
(metavar "GHC_VERSION" <> long "ghc" <> help "The ghc version"
|
||||||
<> completer (tagCompleter GHC [])
|
<> completer (tagCompleter GHC [])
|
||||||
<> (completer $ versionCompleter Nothing GHC)
|
<> (completer $ versionCompleter Nothing GHC)
|
||||||
@@ -92,7 +97,7 @@ runOpts =
|
|||||||
)
|
)
|
||||||
<*> optional
|
<*> optional
|
||||||
(option
|
(option
|
||||||
(eitherReader toolVersionEither)
|
(eitherReader toolVersionTagEither)
|
||||||
(metavar "CABAL_VERSION" <> long "cabal" <> help "The cabal version"
|
(metavar "CABAL_VERSION" <> long "cabal" <> help "The cabal version"
|
||||||
<> completer (tagCompleter Cabal [])
|
<> completer (tagCompleter Cabal [])
|
||||||
<> (completer $ versionCompleter Nothing Cabal)
|
<> (completer $ versionCompleter Nothing Cabal)
|
||||||
@@ -100,7 +105,7 @@ runOpts =
|
|||||||
)
|
)
|
||||||
<*> optional
|
<*> optional
|
||||||
(option
|
(option
|
||||||
(eitherReader toolVersionEither)
|
(eitherReader toolVersionTagEither)
|
||||||
(metavar "HLS_VERSION" <> long "hls" <> help "The HLS version"
|
(metavar "HLS_VERSION" <> long "hls" <> help "The HLS version"
|
||||||
<> completer (tagCompleter HLS [])
|
<> completer (tagCompleter HLS [])
|
||||||
<> (completer $ versionCompleter Nothing HLS)
|
<> (completer $ versionCompleter Nothing HLS)
|
||||||
@@ -108,7 +113,7 @@ runOpts =
|
|||||||
)
|
)
|
||||||
<*> optional
|
<*> optional
|
||||||
(option
|
(option
|
||||||
(eitherReader toolVersionEither)
|
(eitherReader toolVersionTagEither)
|
||||||
(metavar "STACK_VERSION" <> long "stack" <> help "The stack version"
|
(metavar "STACK_VERSION" <> long "stack" <> help "The stack version"
|
||||||
<> completer (tagCompleter Stack [])
|
<> completer (tagCompleter Stack [])
|
||||||
<> (completer $ versionCompleter Nothing Stack)
|
<> (completer $ versionCompleter Nothing Stack)
|
||||||
@@ -171,6 +176,7 @@ type RunEffects = '[ AlreadyInstalled
|
|||||||
, BuildFailed
|
, BuildFailed
|
||||||
, TagNotFound
|
, TagNotFound
|
||||||
, DigestError
|
, DigestError
|
||||||
|
, ContentLengthError
|
||||||
, GPGError
|
, GPGError
|
||||||
, DownloadFailed
|
, DownloadFailed
|
||||||
, TarDirDoesNotExist
|
, TarDirDoesNotExist
|
||||||
@@ -213,7 +219,7 @@ runRUN appState action' = do
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
run :: forall m.
|
run :: forall m .
|
||||||
( MonadFail m
|
( MonadFail m
|
||||||
, MonadMask m
|
, MonadMask m
|
||||||
, MonadCatch m
|
, MonadCatch m
|
||||||
@@ -229,12 +235,16 @@ run RunOptions{..} runAppState leanAppstate runLogger = do
|
|||||||
r <- if not runQuick
|
r <- if not runQuick
|
||||||
then runRUN runAppState $ do
|
then runRUN runAppState $ do
|
||||||
toolchain <- liftE resolveToolchainFull
|
toolchain <- liftE resolveToolchainFull
|
||||||
tmp <- liftIO $ createTmpDir toolchain
|
|
||||||
|
-- oh dear
|
||||||
|
r <- lift ask
|
||||||
|
tmp <- lift . lift . lift . flip runReaderT (fromAppState r) $ createTmpDir toolchain
|
||||||
|
|
||||||
liftE $ installToolChainFull toolchain tmp
|
liftE $ installToolChainFull toolchain tmp
|
||||||
pure tmp
|
pure tmp
|
||||||
else runLeanRUN leanAppstate $ do
|
else runLeanRUN leanAppstate $ do
|
||||||
toolchain <- resolveToolchain
|
toolchain <- resolveToolchain
|
||||||
tmp <- liftIO $ createTmpDir toolchain
|
tmp <- lift $ createTmpDir toolchain
|
||||||
liftE $ installToolChain toolchain tmp
|
liftE $ installToolChain toolchain tmp
|
||||||
pure tmp
|
pure tmp
|
||||||
case r of
|
case r of
|
||||||
@@ -244,35 +254,26 @@ run RunOptions{..} runAppState leanAppstate runLogger = do
|
|||||||
liftIO $ putStr tmp
|
liftIO $ putStr tmp
|
||||||
pure ExitSuccess
|
pure ExitSuccess
|
||||||
(cmd:args) -> do
|
(cmd:args) -> do
|
||||||
newEnv <- liftIO $ addToPath tmp
|
newEnv <- liftIO $ addToPath tmp runAppendPATH
|
||||||
#ifndef IS_WINDOWS
|
#ifndef IS_WINDOWS
|
||||||
void $ liftIO $ SPP.executeFile cmd True args (Just newEnv)
|
void $ liftIO $ SPP.executeFile cmd True args (Just newEnv)
|
||||||
pure ExitSuccess
|
pure ExitSuccess
|
||||||
#else
|
#else
|
||||||
r' <- runLeanRUN leanAppstate $ liftE $ lEM @_ @'[ProcessError] $ exec cmd args Nothing (Just newEnv)
|
r' <- if runMinGWPath
|
||||||
|
then runLeanRUN leanAppstate $ liftE $ lEM @_ @'[ProcessError] $ exec cmd args Nothing (Just newEnv)
|
||||||
|
else runLeanRUN leanAppstate $ liftE $ lEM @_ @'[ProcessError] $ execNoMinGW cmd args Nothing (Just newEnv)
|
||||||
case r' of
|
case r' of
|
||||||
VRight _ -> pure ExitSuccess
|
VRight _ -> pure ExitSuccess
|
||||||
VLeft e -> do
|
VLeft e -> do
|
||||||
runLogger $ logError $ T.pack $ prettyShow e
|
runLogger $ logError $ T.pack $ prettyHFError e
|
||||||
pure $ ExitFailure 28
|
pure $ ExitFailure 28
|
||||||
#endif
|
#endif
|
||||||
VLeft e -> do
|
VLeft e -> do
|
||||||
runLogger $ logError $ T.pack $ prettyShow e
|
runLogger $ logError $ T.pack $ prettyHFError e
|
||||||
pure $ ExitFailure 27
|
pure $ ExitFailure 27
|
||||||
|
|
||||||
where
|
where
|
||||||
|
|
||||||
createTmpDir :: Toolchain -> IO FilePath
|
|
||||||
createTmpDir toolchain =
|
|
||||||
case runBinDir of
|
|
||||||
Just bindir -> do
|
|
||||||
createDirRecursive' bindir
|
|
||||||
canonicalizePath bindir
|
|
||||||
Nothing -> do
|
|
||||||
d <- predictableTmpDir toolchain
|
|
||||||
createDirRecursive' d
|
|
||||||
canonicalizePath d
|
|
||||||
|
|
||||||
-- TODO: doesn't work for cross
|
-- TODO: doesn't work for cross
|
||||||
resolveToolchainFull :: ( MonadFail m
|
resolveToolchainFull :: ( MonadFail m
|
||||||
, MonadThrow m
|
, MonadThrow m
|
||||||
@@ -290,29 +291,33 @@ run RunOptions{..} runAppState leanAppstate runLogger = do
|
|||||||
pure v
|
pure v
|
||||||
cabalVer <- forM runCabalVer $ \ver -> do
|
cabalVer <- forM runCabalVer $ \ver -> do
|
||||||
(v, _) <- liftE $ fromVersion (Just ver) Cabal
|
(v, _) <- liftE $ fromVersion (Just ver) Cabal
|
||||||
pure v
|
pure (_tvVersion v)
|
||||||
hlsVer <- forM runHLSVer $ \ver -> do
|
hlsVer <- forM runHLSVer $ \ver -> do
|
||||||
(v, _) <- liftE $ fromVersion (Just ver) HLS
|
(v, _) <- liftE $ fromVersion (Just ver) HLS
|
||||||
pure v
|
pure (_tvVersion v)
|
||||||
stackVer <- forM runStackVer $ \ver -> do
|
stackVer <- forM runStackVer $ \ver -> do
|
||||||
(v, _) <- liftE $ fromVersion (Just ver) Stack
|
(v, _) <- liftE $ fromVersion (Just ver) Stack
|
||||||
pure v
|
pure (_tvVersion v)
|
||||||
pure Toolchain{..}
|
pure Toolchain{..}
|
||||||
|
|
||||||
resolveToolchain = do
|
resolveToolchain = do
|
||||||
ghcVer <- case runGHCVer of
|
ghcVer <- case runGHCVer of
|
||||||
Just (ToolVersion v) -> pure $ Just v
|
Just (GHCVersion v) -> pure $ Just v
|
||||||
|
Just (ToolVersion v) -> pure $ Just (mkTVer v)
|
||||||
Nothing -> pure Nothing
|
Nothing -> pure Nothing
|
||||||
_ -> fail "Internal error"
|
_ -> fail "Internal error"
|
||||||
cabalVer <- case runCabalVer of
|
cabalVer <- case runCabalVer of
|
||||||
|
Just (GHCVersion v) -> pure $ Just (_tvVersion v)
|
||||||
Just (ToolVersion v) -> pure $ Just v
|
Just (ToolVersion v) -> pure $ Just v
|
||||||
Nothing -> pure Nothing
|
Nothing -> pure Nothing
|
||||||
_ -> fail "Internal error"
|
_ -> fail "Internal error"
|
||||||
hlsVer <- case runHLSVer of
|
hlsVer <- case runHLSVer of
|
||||||
|
Just (GHCVersion v) -> pure $ Just (_tvVersion v)
|
||||||
Just (ToolVersion v) -> pure $ Just v
|
Just (ToolVersion v) -> pure $ Just v
|
||||||
Nothing -> pure Nothing
|
Nothing -> pure Nothing
|
||||||
_ -> fail "Internal error"
|
_ -> fail "Internal error"
|
||||||
stackVer <- case runStackVer of
|
stackVer <- case runStackVer of
|
||||||
|
Just (GHCVersion v) -> pure $ Just (_tvVersion v)
|
||||||
Just (ToolVersion v) -> pure $ Just v
|
Just (ToolVersion v) -> pure $ Just v
|
||||||
Nothing -> pure Nothing
|
Nothing -> pure Nothing
|
||||||
_ -> fail "Internal error"
|
_ -> fail "Internal error"
|
||||||
@@ -338,6 +343,7 @@ run RunOptions{..} runAppState leanAppstate runLogger = do
|
|||||||
, DownloadFailed
|
, DownloadFailed
|
||||||
, DirNotEmpty
|
, DirNotEmpty
|
||||||
, DigestError
|
, DigestError
|
||||||
|
, ContentLengthError
|
||||||
, BuildFailed
|
, BuildFailed
|
||||||
, ArchiveResult
|
, ArchiveResult
|
||||||
, AlreadyInstalled
|
, AlreadyInstalled
|
||||||
@@ -347,34 +353,43 @@ run RunOptions{..} runAppState leanAppstate runLogger = do
|
|||||||
, MergeFileTreeError
|
, MergeFileTreeError
|
||||||
] (ResourceT (ReaderT AppState m)) ()
|
] (ResourceT (ReaderT AppState m)) ()
|
||||||
installToolChainFull Toolchain{..} tmp = do
|
installToolChainFull Toolchain{..} tmp = do
|
||||||
forM_ [(GHC,) <$> ghcVer, (Cabal,) <$> cabalVer, (HLS,) <$> hlsVer, (Stack,) <$> stackVer] $ \mt -> do
|
case ghcVer of
|
||||||
isInstalled <- maybe (pure False) (\(tool, v) -> lift $ checkIfToolInstalled' tool v) mt
|
Just v -> do
|
||||||
case mt of
|
isInstalled <- lift $ checkIfToolInstalled' GHC v
|
||||||
Just (GHC, v) -> do
|
unless isInstalled $ when (runInstTool' && isNothing (_tvTarget v)) $ void $ liftE $ installGHCBin
|
||||||
unless isInstalled $ when (runInstTool' && isNothing (_tvTarget v)) $ void $ liftE $ installGHCBin
|
(_tvVersion v)
|
||||||
(_tvVersion v)
|
GHCupInternal
|
||||||
GHCupInternal
|
False
|
||||||
False
|
[]
|
||||||
setTool GHC v tmp
|
setGHC' v tmp
|
||||||
Just (Cabal, v) -> do
|
_ -> pure ()
|
||||||
unless isInstalled $ when runInstTool' $ void $ liftE $ installCabalBin
|
case cabalVer of
|
||||||
(_tvVersion v)
|
Just v -> do
|
||||||
GHCupInternal
|
isInstalled <- lift $ checkIfToolInstalled' Cabal (mkTVer v)
|
||||||
False
|
unless isInstalled $ when runInstTool' $ void $ liftE $ installCabalBin
|
||||||
setTool Cabal v tmp
|
v
|
||||||
Just (Stack, v) -> do
|
GHCupInternal
|
||||||
unless isInstalled $ when runInstTool' $ void $ liftE $ installStackBin
|
False
|
||||||
(_tvVersion v)
|
setCabal' v tmp
|
||||||
GHCupInternal
|
_ -> pure ()
|
||||||
False
|
case stackVer of
|
||||||
setTool Stack v tmp
|
Just v -> do
|
||||||
Just (HLS, v) -> do
|
isInstalled <- lift $ checkIfToolInstalled' Stack (mkTVer v)
|
||||||
unless isInstalled $ when runInstTool' $ void $ liftE $ installHLSBin
|
unless isInstalled $ when runInstTool' $ void $ liftE $ installStackBin
|
||||||
(_tvVersion v)
|
v
|
||||||
GHCupInternal
|
GHCupInternal
|
||||||
False
|
False
|
||||||
setTool HLS v tmp
|
setStack' v tmp
|
||||||
_ -> pure ()
|
_ -> pure ()
|
||||||
|
case hlsVer of
|
||||||
|
Just v -> do
|
||||||
|
isInstalled <- lift $ checkIfToolInstalled' HLS (mkTVer v)
|
||||||
|
unless isInstalled $ when runInstTool' $ void $ liftE $ installHLSBin
|
||||||
|
v
|
||||||
|
GHCupInternal
|
||||||
|
False
|
||||||
|
setHLS' v tmp
|
||||||
|
_ -> pure ()
|
||||||
|
|
||||||
installToolChain :: ( MonadFail m
|
installToolChain :: ( MonadFail m
|
||||||
, MonadThrow m
|
, MonadThrow m
|
||||||
@@ -385,67 +400,79 @@ run RunOptions{..} runAppState leanAppstate runLogger = do
|
|||||||
-> FilePath
|
-> FilePath
|
||||||
-> Excepts '[NotInstalled] (ReaderT LeanAppState m) ()
|
-> Excepts '[NotInstalled] (ReaderT LeanAppState m) ()
|
||||||
installToolChain Toolchain{..} tmp = do
|
installToolChain Toolchain{..} tmp = do
|
||||||
forM_ [(GHC,) <$> ghcVer, (Cabal,) <$> cabalVer, (HLS,) <$> hlsVer, (Stack,) <$> stackVer] $ \mt -> do
|
case ghcVer of
|
||||||
case mt of
|
Just v -> setGHC' v tmp
|
||||||
Just (GHC, v) -> setTool GHC v tmp
|
_ -> pure ()
|
||||||
Just (Cabal, v) -> setTool Cabal v tmp
|
case cabalVer of
|
||||||
Just (Stack, v) -> setTool Stack v tmp
|
Just v -> setCabal' v tmp
|
||||||
Just (HLS, v) -> setTool HLS v tmp
|
_ -> pure ()
|
||||||
_ -> pure ()
|
case stackVer of
|
||||||
|
Just v -> setStack' v tmp
|
||||||
|
_ -> pure ()
|
||||||
|
case hlsVer of
|
||||||
|
Just v -> setHLS' v tmp
|
||||||
|
_ -> pure ()
|
||||||
|
|
||||||
setTool tool v tmp =
|
setGHC' v tmp = do
|
||||||
case tool of
|
|
||||||
GHC -> do
|
|
||||||
void $ liftE $ setGHC v SetGHC_XYZ (Just tmp)
|
void $ liftE $ setGHC v SetGHC_XYZ (Just tmp)
|
||||||
void $ liftE $ setGHC v SetGHCOnly (Just tmp)
|
void $ liftE $ setGHC v SetGHCOnly (Just tmp)
|
||||||
Cabal -> do
|
setCabal' v tmp = do
|
||||||
bin <- liftE $ whereIsTool Cabal v
|
bin <- liftE $ whereIsTool Cabal (mkTVer v)
|
||||||
cbin <- liftIO $ canonicalizePath bin
|
cbin <- liftIO $ canonicalizePath bin
|
||||||
lift $ createLink (relativeSymlink tmp cbin) (tmp </> ("cabal" <.> exeExt))
|
lift $ createLink (relativeSymlink tmp cbin) (tmp </> ("cabal" <.> exeExt))
|
||||||
Stack -> do
|
setStack' v tmp = do
|
||||||
bin <- liftE $ whereIsTool Stack v
|
bin <- liftE $ whereIsTool Stack (mkTVer v)
|
||||||
cbin <- liftIO $ canonicalizePath bin
|
cbin <- liftIO $ canonicalizePath bin
|
||||||
lift $ createLink (relativeSymlink tmp cbin) (tmp </> ("stack" <.> exeExt))
|
lift $ createLink (relativeSymlink tmp cbin) (tmp </> ("stack" <.> exeExt))
|
||||||
HLS -> do
|
setHLS' v tmp = do
|
||||||
Dirs {..} <- getDirs
|
Dirs {..} <- getDirs
|
||||||
let v' = _tvVersion v
|
legacy <- isLegacyHLS v
|
||||||
legacy <- isLegacyHLS v'
|
|
||||||
if legacy
|
if legacy
|
||||||
then do
|
then do
|
||||||
-- TODO: factor this out
|
-- TODO: factor this out
|
||||||
hlsWrapper <- liftE @_ @'[NotInstalled] $ hlsWrapperBinary v' !? (NotInstalled HLS (mkTVer v'))
|
hlsWrapper <- liftE @_ @'[NotInstalled] $ hlsWrapperBinary v !? (NotInstalled HLS (mkTVer v))
|
||||||
cw <- liftIO $ canonicalizePath (binDir </> hlsWrapper)
|
cw <- liftIO $ canonicalizePath (binDir </> hlsWrapper)
|
||||||
lift $ createLink (relativeSymlink tmp cw) (tmp </> takeFileName cw)
|
lift $ createLink (relativeSymlink tmp cw) (tmp </> takeFileName cw)
|
||||||
hlsBins <- hlsServerBinaries v' Nothing >>= liftIO . traverse (canonicalizePath . (binDir </>))
|
hlsBins <- hlsServerBinaries v Nothing >>= liftIO . traverse (canonicalizePath . (binDir </>))
|
||||||
forM_ hlsBins $ \bin ->
|
forM_ hlsBins $ \bin ->
|
||||||
lift $ createLink (relativeSymlink tmp bin) (tmp </> takeFileName bin)
|
lift $ createLink (relativeSymlink tmp bin) (tmp </> takeFileName bin)
|
||||||
liftE $ setHLS (_tvVersion v) SetHLSOnly (Just tmp)
|
liftE $ setHLS v SetHLSOnly (Just tmp)
|
||||||
else do
|
else do
|
||||||
liftE $ setHLS (_tvVersion v) SetHLS_XYZ (Just tmp)
|
liftE $ setHLS v SetHLS_XYZ (Just tmp)
|
||||||
liftE $ setHLS (_tvVersion v) SetHLSOnly (Just tmp)
|
liftE $ setHLS v SetHLSOnly (Just tmp)
|
||||||
GHCup -> pure ()
|
|
||||||
|
|
||||||
addToPath path = do
|
|
||||||
cEnv <- Map.fromList <$> getEnvironment
|
|
||||||
let paths = ["PATH", "Path"]
|
|
||||||
curPaths = (\x -> maybe [] splitSearchPath (Map.lookup x cEnv)) =<< paths
|
|
||||||
newPath = intercalate [searchPathSeparator] (if runAppendPATH then (curPaths ++ [path]) else (path : curPaths))
|
|
||||||
envWithoutPath = foldr (\x y -> Map.delete x y) cEnv paths
|
|
||||||
pathVar = if isWindows then "Path" else "PATH"
|
|
||||||
envWithNewPath = Map.toList $ Map.insert pathVar newPath envWithoutPath
|
|
||||||
liftIO $ setEnv pathVar newPath
|
|
||||||
return envWithNewPath
|
|
||||||
|
|
||||||
predictableTmpDir (Toolchain Nothing Nothing Nothing Nothing) =
|
createTmpDir :: ( MonadUnliftIO m
|
||||||
liftIO (getTemporaryDirectory >>= \tmp -> pure (tmp </> "ghcup-none"))
|
, MonadCatch m
|
||||||
|
, MonadThrow m
|
||||||
|
, MonadMask m
|
||||||
|
, MonadIO m
|
||||||
|
)
|
||||||
|
=> Toolchain
|
||||||
|
-> ReaderT LeanAppState m FilePath
|
||||||
|
createTmpDir toolchain =
|
||||||
|
case runBinDir of
|
||||||
|
Just bindir -> do
|
||||||
|
liftIO $ createDirRecursive' bindir
|
||||||
|
liftIO $ canonicalizePath bindir
|
||||||
|
Nothing -> do
|
||||||
|
d <- predictableTmpDir toolchain
|
||||||
|
liftIO $ createDirRecursive' d
|
||||||
|
liftIO $ canonicalizePath d
|
||||||
|
|
||||||
|
predictableTmpDir :: Monad m
|
||||||
|
=> Toolchain
|
||||||
|
-> ReaderT LeanAppState m FilePath
|
||||||
|
predictableTmpDir (Toolchain Nothing Nothing Nothing Nothing) = do
|
||||||
|
Dirs { tmpDir } <- getDirs
|
||||||
|
pure (fromGHCupPath tmpDir </> "ghcup-none")
|
||||||
predictableTmpDir Toolchain{..} = do
|
predictableTmpDir Toolchain{..} = do
|
||||||
tmp <- getTemporaryDirectory
|
Dirs { tmpDir } <- getDirs
|
||||||
pure $ tmp
|
pure $ fromGHCupPath tmpDir
|
||||||
</> ("ghcup-" <> intercalate "_"
|
</> ("ghcup-" <> intercalate "_"
|
||||||
( maybe [] ( (:[]) . ("ghc-" <>) . T.unpack . tVerToText) ghcVer
|
( maybe [] ( (:[]) . ("ghc-" <>) . T.unpack . tVerToText) ghcVer
|
||||||
<> maybe [] ( (:[]) . ("cabal-" <>) . T.unpack . tVerToText) cabalVer
|
<> maybe [] ( (:[]) . ("cabal-" <>) . T.unpack . prettyVer) cabalVer
|
||||||
<> maybe [] ( (:[]) . ("hls-" <>) . T.unpack . tVerToText) hlsVer
|
<> maybe [] ( (:[]) . ("hls-" <>) . T.unpack . prettyVer) hlsVer
|
||||||
<> maybe [] ( (:[]) . ("stack-" <>) . T.unpack . tVerToText) stackVer
|
<> maybe [] ( (:[]) . ("stack-" <>) . T.unpack . prettyVer) stackVer
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -459,7 +486,7 @@ run RunOptions{..} runAppState leanAppstate runLogger = do
|
|||||||
|
|
||||||
data Toolchain = Toolchain
|
data Toolchain = Toolchain
|
||||||
{ ghcVer :: Maybe GHCTargetVersion
|
{ ghcVer :: Maybe GHCTargetVersion
|
||||||
, cabalVer :: Maybe GHCTargetVersion
|
, cabalVer :: Maybe Version
|
||||||
, hlsVer :: Maybe GHCTargetVersion
|
, hlsVer :: Maybe Version
|
||||||
, stackVer :: Maybe GHCTargetVersion
|
, stackVer :: Maybe Version
|
||||||
}
|
} deriving Show
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ import Options.Applicative hiding ( style )
|
|||||||
import Options.Applicative.Help.Pretty ( text )
|
import Options.Applicative.Help.Pretty ( text )
|
||||||
import Prelude hiding ( appendFile )
|
import Prelude hiding ( appendFile )
|
||||||
import System.Exit
|
import System.Exit
|
||||||
import Text.PrettyPrint.HughesPJClass ( prettyShow )
|
|
||||||
|
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import Data.Bifunctor (second)
|
import Data.Bifunctor (second)
|
||||||
@@ -74,7 +73,7 @@ data SetOptions = SetOptions
|
|||||||
--[ Parsers ]--
|
--[ Parsers ]--
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
|
||||||
setParser :: Parser (Either SetCommand SetOptions)
|
setParser :: Parser (Either SetCommand SetOptions)
|
||||||
setParser =
|
setParser =
|
||||||
(Left <$> subparser
|
(Left <$> subparser
|
||||||
@@ -82,7 +81,7 @@ setParser =
|
|||||||
"ghc"
|
"ghc"
|
||||||
( SetGHC
|
( SetGHC
|
||||||
<$> info
|
<$> info
|
||||||
(setOpts (Just GHC) <**> helper)
|
(setOpts GHC <**> helper)
|
||||||
( progDesc "Set GHC version"
|
( progDesc "Set GHC version"
|
||||||
<> footerDoc (Just $ text setGHCFooter)
|
<> footerDoc (Just $ text setGHCFooter)
|
||||||
)
|
)
|
||||||
@@ -91,7 +90,7 @@ setParser =
|
|||||||
"cabal"
|
"cabal"
|
||||||
( SetCabal
|
( SetCabal
|
||||||
<$> info
|
<$> info
|
||||||
(setOpts (Just Cabal) <**> helper)
|
(setOpts Cabal <**> helper)
|
||||||
( progDesc "Set Cabal version"
|
( progDesc "Set Cabal version"
|
||||||
<> footerDoc (Just $ text setCabalFooter)
|
<> footerDoc (Just $ text setCabalFooter)
|
||||||
)
|
)
|
||||||
@@ -100,7 +99,7 @@ setParser =
|
|||||||
"hls"
|
"hls"
|
||||||
( SetHLS
|
( SetHLS
|
||||||
<$> info
|
<$> info
|
||||||
(setOpts (Just HLS) <**> helper)
|
(setOpts HLS <**> helper)
|
||||||
( progDesc "Set haskell-language-server version"
|
( progDesc "Set haskell-language-server version"
|
||||||
<> footerDoc (Just $ text setHLSFooter)
|
<> footerDoc (Just $ text setHLSFooter)
|
||||||
)
|
)
|
||||||
@@ -109,14 +108,14 @@ setParser =
|
|||||||
"stack"
|
"stack"
|
||||||
( SetStack
|
( SetStack
|
||||||
<$> info
|
<$> info
|
||||||
(setOpts (Just Stack) <**> helper)
|
(setOpts Stack <**> helper)
|
||||||
( progDesc "Set stack version"
|
( progDesc "Set stack version"
|
||||||
<> footerDoc (Just $ text setStackFooter)
|
<> footerDoc (Just $ text setStackFooter)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
<|> (Right <$> setOpts Nothing)
|
<|> (Right <$> setOpts GHC)
|
||||||
where
|
where
|
||||||
setGHCFooter :: String
|
setGHCFooter :: String
|
||||||
setGHCFooter = [s|Discussion:
|
setGHCFooter = [s|Discussion:
|
||||||
@@ -137,22 +136,25 @@ setParser =
|
|||||||
Sets the the current haskell-language-server version.|]
|
Sets the the current haskell-language-server version.|]
|
||||||
|
|
||||||
|
|
||||||
setOpts :: Maybe Tool -> Parser SetOptions
|
setOpts :: Tool -> Parser SetOptions
|
||||||
setOpts tool = SetOptions <$>
|
setOpts tool = SetOptions <$>
|
||||||
(fromMaybe SetRecommended <$>
|
(fromMaybe SetRecommended <$>
|
||||||
optional (setVersionArgument (Just ListInstalled) tool))
|
optional (setVersionArgument (Just ListInstalled) tool))
|
||||||
|
|
||||||
setVersionArgument :: Maybe ListCriteria -> Maybe Tool -> Parser SetToolVersion
|
setVersionArgument :: Maybe ListCriteria -> Tool -> Parser SetToolVersion
|
||||||
setVersionArgument criteria tool =
|
setVersionArgument criteria tool =
|
||||||
argument (eitherReader setEither)
|
argument (eitherReader setEither)
|
||||||
(metavar "VERSION|TAG|next"
|
(metavar "VERSION|TAG|next"
|
||||||
<> completer (tagCompleter (fromMaybe GHC tool) ["next"])
|
<> completer (tagCompleter tool ["next"])
|
||||||
<> foldMap (completer . versionCompleter criteria) tool)
|
<> (completer . versionCompleter criteria) tool)
|
||||||
where
|
where
|
||||||
setEither s' =
|
setEither s' =
|
||||||
parseSet s'
|
parseSet s'
|
||||||
<|> second SetToolTag (tagEither s')
|
<|> second SetToolTag (tagEither s')
|
||||||
<|> second SetToolVersion (tVersionEither s')
|
<|> se s'
|
||||||
|
se s' = case tool of
|
||||||
|
GHC -> second SetGHCVersion (ghcVersionEither s')
|
||||||
|
_ -> second SetToolVersion (toolVersionEither s')
|
||||||
parseSet s' = case fmap toLower s' of
|
parseSet s' = case fmap toLower s' of
|
||||||
"next" -> Right SetNext
|
"next" -> Right SetNext
|
||||||
other -> Left $ "Unknown tag/version " <> other
|
other -> Left $ "Unknown tag/version " <> other
|
||||||
@@ -257,22 +259,19 @@ set :: forall m env.
|
|||||||
-> m (VEither eff GHCTargetVersion))
|
-> m (VEither eff GHCTargetVersion))
|
||||||
-> (ReaderT LeanAppState m () -> m ())
|
-> (ReaderT LeanAppState m () -> m ())
|
||||||
-> m ExitCode
|
-> m ExitCode
|
||||||
set setCommand runAppState runLeanAppState runLogger = case setCommand of
|
set setCommand runAppState _ runLogger = case setCommand of
|
||||||
(Right sopts) -> do
|
(Right sopts) -> do
|
||||||
runLogger (logWarn "This is an old-style command for setting GHC. Use 'ghcup set ghc' instead.")
|
runLogger (logWarn "This is an old-style command for setting GHC. Use 'ghcup set ghc' instead.")
|
||||||
setGHC' sopts
|
setGHC' sopts
|
||||||
(Left (SetGHC sopts)) -> setGHC' sopts
|
(Left (SetGHC sopts)) -> setGHC' sopts
|
||||||
(Left (SetCabal sopts)) -> setCabal' sopts
|
(Left (SetCabal sopts)) -> setCabal' sopts
|
||||||
(Left (SetHLS sopts)) -> setHLS' sopts
|
(Left (SetHLS sopts)) -> setHLS' sopts
|
||||||
(Left (SetStack sopts)) -> setStack' sopts
|
(Left (SetStack sopts)) -> setStack' sopts
|
||||||
|
|
||||||
where
|
where
|
||||||
setGHC' :: SetOptions
|
setGHC' :: SetOptions
|
||||||
-> m ExitCode
|
-> m ExitCode
|
||||||
setGHC' SetOptions{ sToolVer } =
|
setGHC' SetOptions{ sToolVer } = runSetGHC runAppState (do
|
||||||
case sToolVer of
|
|
||||||
(SetToolVersion v) -> runSetGHC runLeanAppState (liftE $ setGHC v SetGHCOnly Nothing >> pure v)
|
|
||||||
_ -> runSetGHC runAppState (do
|
|
||||||
v <- liftE $ fst <$> fromVersion' sToolVer GHC
|
v <- liftE $ fst <$> fromVersion' sToolVer GHC
|
||||||
liftE $ setGHC v SetGHCOnly Nothing
|
liftE $ setGHC v SetGHCOnly Nothing
|
||||||
)
|
)
|
||||||
@@ -283,67 +282,58 @@ set setCommand runAppState runLeanAppState runLogger = case setCommand of
|
|||||||
"GHC " <> prettyVer _tvVersion <> " successfully set as default version" <> maybe "" (" for cross target " <>) _tvTarget
|
"GHC " <> prettyVer _tvVersion <> " successfully set as default version" <> maybe "" (" for cross target " <>) _tvTarget
|
||||||
pure ExitSuccess
|
pure ExitSuccess
|
||||||
VLeft e -> do
|
VLeft e -> do
|
||||||
runLogger $ logError $ T.pack $ prettyShow e
|
runLogger $ logError $ T.pack $ prettyHFError e
|
||||||
pure $ ExitFailure 5
|
pure $ ExitFailure 5
|
||||||
|
|
||||||
|
|
||||||
setCabal' :: SetOptions
|
setCabal' :: SetOptions
|
||||||
-> m ExitCode
|
-> m ExitCode
|
||||||
setCabal' SetOptions{ sToolVer } =
|
setCabal' SetOptions{ sToolVer } = runSetCabal runAppState (do
|
||||||
case sToolVer of
|
|
||||||
(SetToolVersion v) -> runSetCabal runLeanAppState (liftE $ setCabal (_tvVersion v) >> pure v)
|
|
||||||
_ -> runSetCabal runAppState (do
|
|
||||||
v <- liftE $ fst <$> fromVersion' sToolVer Cabal
|
v <- liftE $ fst <$> fromVersion' sToolVer Cabal
|
||||||
liftE $ setCabal (_tvVersion v)
|
liftE $ setCabal (_tvVersion v)
|
||||||
pure v
|
pure v
|
||||||
)
|
)
|
||||||
>>= \case
|
>>= \case
|
||||||
VRight GHCTargetVersion{..} -> do
|
VRight v -> do
|
||||||
runLogger
|
runLogger
|
||||||
$ logInfo $
|
$ logInfo $
|
||||||
"Cabal " <> prettyVer _tvVersion <> " successfully set as default version"
|
"Cabal " <> prettyVer (_tvVersion v) <> " successfully set as default version"
|
||||||
pure ExitSuccess
|
pure ExitSuccess
|
||||||
VLeft e -> do
|
VLeft e -> do
|
||||||
runLogger $ logError $ T.pack $ prettyShow e
|
runLogger $ logError $ T.pack $ prettyHFError e
|
||||||
pure $ ExitFailure 14
|
pure $ ExitFailure 14
|
||||||
|
|
||||||
setHLS' :: SetOptions
|
setHLS' :: SetOptions
|
||||||
-> m ExitCode
|
-> m ExitCode
|
||||||
setHLS' SetOptions{ sToolVer } =
|
setHLS' SetOptions{ sToolVer } = runSetHLS runAppState (do
|
||||||
case sToolVer of
|
|
||||||
(SetToolVersion v) -> runSetHLS runLeanAppState (liftE $ setHLS (_tvVersion v) SetHLSOnly Nothing >> pure v)
|
|
||||||
_ -> runSetHLS runAppState (do
|
|
||||||
v <- liftE $ fst <$> fromVersion' sToolVer HLS
|
v <- liftE $ fst <$> fromVersion' sToolVer HLS
|
||||||
liftE $ setHLS (_tvVersion v) SetHLSOnly Nothing
|
liftE $ setHLS (_tvVersion v) SetHLSOnly Nothing
|
||||||
pure v
|
pure v
|
||||||
)
|
)
|
||||||
>>= \case
|
>>= \case
|
||||||
VRight GHCTargetVersion{..} -> do
|
VRight v -> do
|
||||||
runLogger
|
runLogger
|
||||||
$ logInfo $
|
$ logInfo $
|
||||||
"HLS " <> prettyVer _tvVersion <> " successfully set as default version"
|
"HLS " <> prettyVer (_tvVersion v) <> " successfully set as default version"
|
||||||
pure ExitSuccess
|
pure ExitSuccess
|
||||||
VLeft e -> do
|
VLeft e -> do
|
||||||
runLogger $ logError $ T.pack $ prettyShow e
|
runLogger $ logError $ T.pack $ prettyHFError e
|
||||||
pure $ ExitFailure 14
|
pure $ ExitFailure 14
|
||||||
|
|
||||||
|
|
||||||
setStack' :: SetOptions
|
setStack' :: SetOptions
|
||||||
-> m ExitCode
|
-> m ExitCode
|
||||||
setStack' SetOptions{ sToolVer } =
|
setStack' SetOptions{ sToolVer } = runSetStack runAppState (do
|
||||||
case sToolVer of
|
|
||||||
(SetToolVersion v) -> runSetStack runLeanAppState (liftE $ setStack (_tvVersion v) >> pure v)
|
|
||||||
_ -> runSetStack runAppState (do
|
|
||||||
v <- liftE $ fst <$> fromVersion' sToolVer Stack
|
v <- liftE $ fst <$> fromVersion' sToolVer Stack
|
||||||
liftE $ setStack (_tvVersion v)
|
liftE $ setStack (_tvVersion v)
|
||||||
pure v
|
pure v
|
||||||
)
|
)
|
||||||
>>= \case
|
>>= \case
|
||||||
VRight GHCTargetVersion{..} -> do
|
VRight v -> do
|
||||||
runLogger
|
runLogger
|
||||||
$ logInfo $
|
$ logInfo $
|
||||||
"Stack " <> prettyVer _tvVersion <> " successfully set as default version"
|
"Stack " <> prettyVer (_tvVersion v) <> " successfully set as default version"
|
||||||
pure ExitSuccess
|
pure ExitSuccess
|
||||||
VLeft e -> do
|
VLeft e -> do
|
||||||
runLogger $ logError $ T.pack $ prettyShow e
|
runLogger $ logError $ T.pack $ prettyHFError e
|
||||||
pure $ ExitFailure 14
|
pure $ ExitFailure 14
|
||||||
|
|||||||
188
app/ghcup/GHCup/OptParse/Test.hs
Normal file
188
app/ghcup/GHCup/OptParse/Test.hs
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
{-# LANGUAGE CPP #-}
|
||||||
|
{-# LANGUAGE DataKinds #-}
|
||||||
|
{-# LANGUAGE TypeApplications #-}
|
||||||
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
|
{-# LANGUAGE TemplateHaskell #-}
|
||||||
|
{-# LANGUAGE QuasiQuotes #-}
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
{-# LANGUAGE DuplicateRecordFields #-}
|
||||||
|
{-# LANGUAGE ViewPatterns #-}
|
||||||
|
{-# LANGUAGE TypeOperators #-}
|
||||||
|
|
||||||
|
module GHCup.OptParse.Test where
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import GHCup.OptParse.Common
|
||||||
|
|
||||||
|
import GHCup
|
||||||
|
import GHCup.Errors
|
||||||
|
import GHCup.Types
|
||||||
|
import GHCup.Utils.Dirs
|
||||||
|
import GHCup.Prelude.Logger
|
||||||
|
import GHCup.Prelude.String.QQ
|
||||||
|
|
||||||
|
import Codec.Archive
|
||||||
|
#if !MIN_VERSION_base(4,13,0)
|
||||||
|
import Control.Monad.Fail ( MonadFail )
|
||||||
|
#endif
|
||||||
|
import Control.Monad.Reader
|
||||||
|
import Control.Monad.Trans.Resource
|
||||||
|
import Data.Functor
|
||||||
|
import Data.Maybe
|
||||||
|
import Haskus.Utils.Variant.Excepts
|
||||||
|
import Options.Applicative hiding ( style )
|
||||||
|
import Options.Applicative.Help.Pretty ( text )
|
||||||
|
import Prelude hiding ( appendFile )
|
||||||
|
import System.Exit
|
||||||
|
import URI.ByteString hiding ( uriParser )
|
||||||
|
|
||||||
|
import qualified Data.Text as T
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
----------------
|
||||||
|
--[ Commands ]--
|
||||||
|
----------------
|
||||||
|
|
||||||
|
|
||||||
|
data TestCommand = TestGHC TestOptions
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---------------
|
||||||
|
--[ Options ]--
|
||||||
|
---------------
|
||||||
|
|
||||||
|
|
||||||
|
data TestOptions = TestOptions
|
||||||
|
{ testVer :: Maybe ToolVersion
|
||||||
|
, testBindist :: Maybe URI
|
||||||
|
, addMakeArgs :: [T.Text]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---------------
|
||||||
|
--[ Footers ]--
|
||||||
|
---------------
|
||||||
|
|
||||||
|
testFooter :: String
|
||||||
|
testFooter = [s|Discussion:
|
||||||
|
Runs test suites from the test bindist.|]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---------------
|
||||||
|
--[ Parsers ]--
|
||||||
|
---------------
|
||||||
|
|
||||||
|
testParser :: Parser TestCommand
|
||||||
|
testParser =
|
||||||
|
subparser
|
||||||
|
( command
|
||||||
|
"ghc"
|
||||||
|
( TestGHC
|
||||||
|
<$> info
|
||||||
|
(testOpts (Just GHC) <**> helper)
|
||||||
|
( progDesc "Test GHC"
|
||||||
|
<> footerDoc (Just $ text testGHCFooter)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
where
|
||||||
|
testGHCFooter :: String
|
||||||
|
testGHCFooter = [s|Discussion:
|
||||||
|
Runs the GHC test suite from the test bindist.|]
|
||||||
|
|
||||||
|
|
||||||
|
testOpts :: Maybe Tool -> Parser TestOptions
|
||||||
|
testOpts tool =
|
||||||
|
(\(u, v) args -> TestOptions v u args)
|
||||||
|
<$> ( ( (,)
|
||||||
|
<$> optional
|
||||||
|
(option
|
||||||
|
(eitherReader uriParser)
|
||||||
|
(short 'u' <> long "url" <> metavar "BINDIST_URL" <> help
|
||||||
|
"Install the specified version from this bindist"
|
||||||
|
<> completer (toolDlCompleter (fromMaybe GHC tool))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
<*> (Just <$> toolVersionTagArgument Nothing tool)
|
||||||
|
)
|
||||||
|
<|> pure (Nothing, Nothing)
|
||||||
|
)
|
||||||
|
<*> many (argument str (metavar "MAKE_ARGS" <> help "Additional arguments to 'make', prefix with '-- ' (longopts)"))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---------------------------
|
||||||
|
--[ Effect interpreters ]--
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
|
||||||
|
type TestGHCEffects = [ DigestError
|
||||||
|
, ContentLengthError
|
||||||
|
, GPGError
|
||||||
|
, DownloadFailed
|
||||||
|
, NoDownload
|
||||||
|
, ArchiveResult
|
||||||
|
, TarDirDoesNotExist
|
||||||
|
, UnknownArchive
|
||||||
|
, TestFailed
|
||||||
|
, NextVerNotFound
|
||||||
|
, TagNotFound
|
||||||
|
, NoToolVersionSet
|
||||||
|
]
|
||||||
|
|
||||||
|
runTestGHC :: AppState
|
||||||
|
-> Excepts TestGHCEffects (ResourceT (ReaderT AppState IO)) a
|
||||||
|
-> IO (VEither TestGHCEffects a)
|
||||||
|
runTestGHC appstate' =
|
||||||
|
flip runReaderT appstate'
|
||||||
|
. runResourceT
|
||||||
|
. runE
|
||||||
|
@TestGHCEffects
|
||||||
|
|
||||||
|
|
||||||
|
-------------------
|
||||||
|
--[ Entrypoints ]--
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
|
||||||
|
test :: TestCommand -> Settings -> IO AppState -> (ReaderT LeanAppState IO () -> IO ()) -> IO ExitCode
|
||||||
|
test testCommand settings getAppState' runLogger = case testCommand of
|
||||||
|
(TestGHC iopts) -> go iopts
|
||||||
|
where
|
||||||
|
go :: TestOptions -> IO ExitCode
|
||||||
|
go TestOptions{..} = do
|
||||||
|
s'@AppState{ dirs = Dirs{ .. } } <- liftIO getAppState'
|
||||||
|
(case testBindist of
|
||||||
|
Nothing -> runTestGHC s' $ do
|
||||||
|
(v, vi) <- liftE $ fromVersion testVer GHC
|
||||||
|
liftE $ testGHCVer (_tvVersion v) addMakeArgs
|
||||||
|
pure vi
|
||||||
|
Just uri -> do
|
||||||
|
runTestGHC s'{ settings = settings {noVerify = True}} $ do
|
||||||
|
(v, vi) <- liftE $ fromVersion testVer GHC
|
||||||
|
liftE $ testGHCBindist (DownloadInfo uri (Just $ RegexDir ".*/.*") "" Nothing) (_tvVersion v) addMakeArgs
|
||||||
|
pure vi
|
||||||
|
)
|
||||||
|
>>= \case
|
||||||
|
VRight _ -> do
|
||||||
|
runLogger $ logInfo "GHC test successful"
|
||||||
|
pure ExitSuccess
|
||||||
|
VLeft e -> do
|
||||||
|
runLogger $ do
|
||||||
|
logError $ T.pack $ prettyHFError e
|
||||||
|
logError $ "Also check the logs in " <> T.pack (fromGHCupPath logsDir)
|
||||||
|
pure $ ExitFailure 3
|
||||||
|
|
||||||
@@ -23,7 +23,6 @@ import Haskus.Utils.Variant.Excepts
|
|||||||
import Options.Applicative hiding ( style )
|
import Options.Applicative hiding ( style )
|
||||||
import Prelude hiding ( appendFile )
|
import Prelude hiding ( appendFile )
|
||||||
import System.Exit
|
import System.Exit
|
||||||
import Text.PrettyPrint.HughesPJClass ( prettyShow )
|
|
||||||
|
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import qualified Data.Text.IO as T
|
import qualified Data.Text.IO as T
|
||||||
@@ -118,5 +117,5 @@ toolRequirements ToolReqOpts{..} runAppState runLogger = runToolRequirements run
|
|||||||
>>= \case
|
>>= \case
|
||||||
VRight _ -> pure ExitSuccess
|
VRight _ -> pure ExitSuccess
|
||||||
VLeft e -> do
|
VLeft e -> do
|
||||||
runLogger $ logError $ T.pack $ prettyShow e
|
runLogger $ logError $ T.pack $ prettyHFError e
|
||||||
pure $ ExitFailure 12
|
pure $ ExitFailure 12
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ import Options.Applicative hiding ( style )
|
|||||||
import Options.Applicative.Help.Pretty ( text )
|
import Options.Applicative.Help.Pretty ( text )
|
||||||
import Prelude hiding ( appendFile )
|
import Prelude hiding ( appendFile )
|
||||||
import System.Exit
|
import System.Exit
|
||||||
import Text.PrettyPrint.HughesPJClass ( prettyShow )
|
|
||||||
|
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import Control.Exception.Safe (MonadMask)
|
import Control.Exception.Safe (MonadMask)
|
||||||
@@ -189,7 +188,7 @@ unset unsetCommand runLeanAppState runLogger = case unsetCommand of
|
|||||||
runLogger $ logInfo "GHC successfully unset"
|
runLogger $ logInfo "GHC successfully unset"
|
||||||
pure ExitSuccess
|
pure ExitSuccess
|
||||||
VLeft e -> do
|
VLeft e -> do
|
||||||
runLogger $ logError $ T.pack $ prettyShow e
|
runLogger $ logError $ T.pack $ prettyHFError e
|
||||||
pure $ ExitFailure 14
|
pure $ ExitFailure 14
|
||||||
(UnsetCabal (UnsetOptions _)) -> do
|
(UnsetCabal (UnsetOptions _)) -> do
|
||||||
void $ runLeanAppState (VRight <$> unsetCabal)
|
void $ runLeanAppState (VRight <$> unsetCabal)
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ import Haskus.Utils.Variant.Excepts
|
|||||||
import Options.Applicative hiding ( style )
|
import Options.Applicative hiding ( style )
|
||||||
import Prelude hiding ( appendFile )
|
import Prelude hiding ( appendFile )
|
||||||
import System.Exit
|
import System.Exit
|
||||||
import Text.PrettyPrint.HughesPJClass ( prettyShow )
|
|
||||||
|
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import Control.Exception.Safe (MonadMask)
|
import Control.Exception.Safe (MonadMask)
|
||||||
@@ -88,13 +87,14 @@ upgradeOptsP =
|
|||||||
|
|
||||||
|
|
||||||
type UpgradeEffects = '[ DigestError
|
type UpgradeEffects = '[ DigestError
|
||||||
|
, ContentLengthError
|
||||||
, GPGError
|
, GPGError
|
||||||
, NoDownload
|
, NoDownload
|
||||||
, NoUpdate
|
, NoUpdate
|
||||||
, FileDoesNotExistError
|
, FileDoesNotExistError
|
||||||
, CopyError
|
, CopyError
|
||||||
, DownloadFailed
|
, DownloadFailed
|
||||||
, GHCupShadowed
|
, ToolShadowed
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@@ -151,5 +151,5 @@ upgrade uOpts force' fatal Dirs{..} runAppState runLogger = do
|
|||||||
runLogger $ logWarn "No GHCup update available"
|
runLogger $ logWarn "No GHCup update available"
|
||||||
pure ExitSuccess
|
pure ExitSuccess
|
||||||
VLeft e -> do
|
VLeft e -> do
|
||||||
runLogger $ logError $ T.pack $ prettyShow e
|
runLogger $ logError $ T.pack $ prettyHFError e
|
||||||
pure $ ExitFailure 11
|
pure $ ExitFailure 11
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ import Haskus.Utils.Variant.Excepts
|
|||||||
import Options.Applicative hiding ( style )
|
import Options.Applicative hiding ( style )
|
||||||
import Options.Applicative.Help.Pretty ( text )
|
import Options.Applicative.Help.Pretty ( text )
|
||||||
import Prelude hiding ( appendFile )
|
import Prelude hiding ( appendFile )
|
||||||
|
import System.Environment
|
||||||
import System.Exit
|
import System.Exit
|
||||||
import Text.PrettyPrint.HughesPJClass ( prettyShow )
|
|
||||||
|
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import Control.Exception.Safe (MonadMask)
|
import Control.Exception.Safe (MonadMask)
|
||||||
@@ -75,14 +75,14 @@ data WhereisOptions = WhereisOptions {
|
|||||||
--[ Parsers ]--
|
--[ Parsers ]--
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
|
||||||
whereisP :: Parser WhereisCommand
|
whereisP :: Parser WhereisCommand
|
||||||
whereisP = subparser
|
whereisP = subparser
|
||||||
(commandGroup "Tools locations:" <>
|
(commandGroup "Tools locations:" <>
|
||||||
command
|
command
|
||||||
"ghc"
|
"ghc"
|
||||||
(WhereisTool GHC <$> info
|
(WhereisTool GHC <$> info
|
||||||
( optional (toolVersionArgument Nothing (Just GHC)) <**> helper )
|
( optional (toolVersionTagArgument Nothing (Just GHC)) <**> helper )
|
||||||
( progDesc "Get GHC location"
|
( progDesc "Get GHC location"
|
||||||
<> footerDoc (Just $ text whereisGHCFooter ))
|
<> footerDoc (Just $ text whereisGHCFooter ))
|
||||||
)
|
)
|
||||||
@@ -90,7 +90,7 @@ whereisP = subparser
|
|||||||
command
|
command
|
||||||
"cabal"
|
"cabal"
|
||||||
(WhereisTool Cabal <$> info
|
(WhereisTool Cabal <$> info
|
||||||
( optional (toolVersionArgument Nothing (Just Cabal)) <**> helper )
|
( optional (toolVersionTagArgument Nothing (Just Cabal)) <**> helper )
|
||||||
( progDesc "Get cabal location"
|
( progDesc "Get cabal location"
|
||||||
<> footerDoc (Just $ text whereisCabalFooter ))
|
<> footerDoc (Just $ text whereisCabalFooter ))
|
||||||
)
|
)
|
||||||
@@ -98,7 +98,7 @@ whereisP = subparser
|
|||||||
command
|
command
|
||||||
"hls"
|
"hls"
|
||||||
(WhereisTool HLS <$> info
|
(WhereisTool HLS <$> info
|
||||||
( optional (toolVersionArgument Nothing (Just HLS)) <**> helper )
|
( optional (toolVersionTagArgument Nothing (Just HLS)) <**> helper )
|
||||||
( progDesc "Get HLS location"
|
( progDesc "Get HLS location"
|
||||||
<> footerDoc (Just $ text whereisHLSFooter ))
|
<> footerDoc (Just $ text whereisHLSFooter ))
|
||||||
)
|
)
|
||||||
@@ -106,7 +106,7 @@ whereisP = subparser
|
|||||||
command
|
command
|
||||||
"stack"
|
"stack"
|
||||||
(WhereisTool Stack <$> info
|
(WhereisTool Stack <$> info
|
||||||
( optional (toolVersionArgument Nothing (Just Stack)) <**> helper )
|
( optional (toolVersionTagArgument Nothing (Just Stack)) <**> helper )
|
||||||
( progDesc "Get stack location"
|
( progDesc "Get stack location"
|
||||||
<> footerDoc (Just $ text whereisStackFooter ))
|
<> footerDoc (Just $ text whereisStackFooter ))
|
||||||
)
|
)
|
||||||
@@ -268,7 +268,14 @@ whereis :: ( Monad m
|
|||||||
whereis whereisCommand whereisOptions runAppState leanAppstate runLogger = do
|
whereis whereisCommand whereisOptions runAppState leanAppstate runLogger = do
|
||||||
Dirs{ .. } <- runReaderT getDirs leanAppstate
|
Dirs{ .. } <- runReaderT getDirs leanAppstate
|
||||||
case (whereisCommand, whereisOptions) of
|
case (whereisCommand, whereisOptions) of
|
||||||
(WhereisTool tool (Just (ToolVersion v)), WhereisOptions{..}) ->
|
(WhereisTool GHCup _, WhereisOptions{..}) -> do
|
||||||
|
loc <- liftIO (getExecutablePath >>= canonicalizePath )
|
||||||
|
if directory
|
||||||
|
then liftIO $ putStr $ takeDirectory loc
|
||||||
|
else liftIO $ putStr loc
|
||||||
|
pure ExitSuccess
|
||||||
|
|
||||||
|
(WhereisTool tool (Just (GHCVersion v)), WhereisOptions{..}) ->
|
||||||
runLeanWhereIs leanAppstate (do
|
runLeanWhereIs leanAppstate (do
|
||||||
loc <- liftE $ whereIsTool tool v
|
loc <- liftE $ whereIsTool tool v
|
||||||
if directory
|
if directory
|
||||||
@@ -280,7 +287,21 @@ whereis whereisCommand whereisOptions runAppState leanAppstate runLogger = do
|
|||||||
liftIO $ putStr r
|
liftIO $ putStr r
|
||||||
pure ExitSuccess
|
pure ExitSuccess
|
||||||
VLeft e -> do
|
VLeft e -> do
|
||||||
runLogger $ logError $ T.pack $ prettyShow e
|
runLogger $ logError $ T.pack $ prettyHFError e
|
||||||
|
pure $ ExitFailure 30
|
||||||
|
(WhereisTool tool (Just (ToolVersion v)), WhereisOptions{..}) ->
|
||||||
|
runLeanWhereIs leanAppstate (do
|
||||||
|
loc <- liftE $ whereIsTool tool (mkTVer v)
|
||||||
|
if directory
|
||||||
|
then pure $ takeDirectory loc
|
||||||
|
else pure loc
|
||||||
|
)
|
||||||
|
>>= \case
|
||||||
|
VRight r -> do
|
||||||
|
liftIO $ putStr r
|
||||||
|
pure ExitSuccess
|
||||||
|
VLeft e -> do
|
||||||
|
runLogger $ logError $ T.pack $ prettyHFError e
|
||||||
pure $ ExitFailure 30
|
pure $ ExitFailure 30
|
||||||
|
|
||||||
(WhereisTool tool whereVer, WhereisOptions{..}) -> do
|
(WhereisTool tool whereVer, WhereisOptions{..}) -> do
|
||||||
@@ -296,7 +317,7 @@ whereis whereisCommand whereisOptions runAppState leanAppstate runLogger = do
|
|||||||
liftIO $ putStr r
|
liftIO $ putStr r
|
||||||
pure ExitSuccess
|
pure ExitSuccess
|
||||||
VLeft e -> do
|
VLeft e -> do
|
||||||
runLogger $ logError $ T.pack $ prettyShow e
|
runLogger $ logError $ T.pack $ prettyHFError e
|
||||||
pure $ ExitFailure 30
|
pure $ ExitFailure 30
|
||||||
|
|
||||||
(WhereisBaseDir, _) -> do
|
(WhereisBaseDir, _) -> do
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ module Main where
|
|||||||
import BrickMain ( brickMain )
|
import BrickMain ( brickMain )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
import qualified GHCup.GHC as GHC
|
||||||
|
import qualified GHCup.HLS as HLS
|
||||||
import GHCup.OptParse
|
import GHCup.OptParse
|
||||||
|
|
||||||
import GHCup.Download
|
import GHCup.Download
|
||||||
@@ -61,7 +63,7 @@ import qualified GHCup.Types as Types
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
toSettings :: Options -> IO (Settings, KeyBindings)
|
toSettings :: Options -> IO (Settings, KeyBindings, UserSettings)
|
||||||
toSettings options = do
|
toSettings options = do
|
||||||
noColor <- isJust <$> lookupEnv "NO_COLOR"
|
noColor <- isJust <$> lookupEnv "NO_COLOR"
|
||||||
userConf <- runE @'[ JSONError ] ghcupConfigFile >>= \case
|
userConf <- runE @'[ JSONError ] ghcupConfigFile >>= \case
|
||||||
@@ -71,12 +73,13 @@ toSettings options = do
|
|||||||
pure defaultUserSettings
|
pure defaultUserSettings
|
||||||
_ -> do
|
_ -> do
|
||||||
die "Unexpected error!"
|
die "Unexpected error!"
|
||||||
pure $ mergeConf options userConf noColor
|
pure $ (\(s', k) -> (s', k, userConf)) $ mergeConf options userConf noColor
|
||||||
where
|
where
|
||||||
mergeConf :: Options -> UserSettings -> Bool -> (Settings, KeyBindings)
|
mergeConf :: Options -> UserSettings -> Bool -> (Settings, KeyBindings)
|
||||||
mergeConf Options{..} UserSettings{..} noColor =
|
mergeConf Options{..} UserSettings{..} noColor =
|
||||||
let cache = fromMaybe (fromMaybe (Types.cache defaultSettings) uCache) optCache
|
let cache = fromMaybe (fromMaybe (Types.cache defaultSettings) uCache) optCache
|
||||||
metaCache = fromMaybe (fromMaybe (Types.metaCache defaultSettings) uMetaCache) optMetaCache
|
metaCache = fromMaybe (fromMaybe (Types.metaCache defaultSettings) uMetaCache) optMetaCache
|
||||||
|
metaMode = fromMaybe (fromMaybe (Types.metaMode defaultSettings) uMetaMode) optMetaMode
|
||||||
noVerify = fromMaybe (fromMaybe (Types.noVerify defaultSettings) uNoVerify) optNoVerify
|
noVerify = fromMaybe (fromMaybe (Types.noVerify defaultSettings) uNoVerify) optNoVerify
|
||||||
verbose = fromMaybe (fromMaybe (Types.verbose defaultSettings) uVerbose) optVerbose
|
verbose = fromMaybe (fromMaybe (Types.verbose defaultSettings) uVerbose) optVerbose
|
||||||
keepDirs = fromMaybe (fromMaybe (Types.keepDirs defaultSettings) uKeepDirs) optKeepDirs
|
keepDirs = fromMaybe (fromMaybe (Types.keepDirs defaultSettings) uKeepDirs) optKeepDirs
|
||||||
@@ -85,6 +88,8 @@ toSettings options = do
|
|||||||
urlSource = maybe (fromMaybe (Types.urlSource defaultSettings) uUrlSource) (OwnSource . (:[]) . Right) optUrlSource
|
urlSource = maybe (fromMaybe (Types.urlSource defaultSettings) uUrlSource) (OwnSource . (:[]) . Right) optUrlSource
|
||||||
noNetwork = fromMaybe (fromMaybe (Types.noNetwork defaultSettings) uNoNetwork) optNoNetwork
|
noNetwork = fromMaybe (fromMaybe (Types.noNetwork defaultSettings) uNoNetwork) optNoNetwork
|
||||||
gpgSetting = fromMaybe (fromMaybe (Types.gpgSetting defaultSettings) uGPGSetting) optGpg
|
gpgSetting = fromMaybe (fromMaybe (Types.gpgSetting defaultSettings) uGPGSetting) optGpg
|
||||||
|
platformOverride = optPlatform <|> (uPlatformOverride <|> Types.platformOverride defaultSettings)
|
||||||
|
mirrors = fromMaybe (Types.mirrors defaultSettings) uMirrors
|
||||||
in (Settings {..}, keyBindings)
|
in (Settings {..}, keyBindings)
|
||||||
#if defined(INTERNAL_DOWNLOADER)
|
#if defined(INTERNAL_DOWNLOADER)
|
||||||
defaultDownloader = Internal
|
defaultDownloader = Internal
|
||||||
@@ -158,7 +163,7 @@ ENV variables:
|
|||||||
* GHCUP_INSTALL_BASE_PREFIX: the base of ghcup (default: $HOME)
|
* GHCUP_INSTALL_BASE_PREFIX: the base of ghcup (default: $HOME)
|
||||||
* GHCUP_USE_XDG_DIRS: set to anything to use XDG style directories
|
* GHCUP_USE_XDG_DIRS: set to anything to use XDG style directories
|
||||||
|
|
||||||
Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
|
Report bugs at <https://github.com/haskell/ghcup-hs/issues>|]
|
||||||
|
|
||||||
customExecParser
|
customExecParser
|
||||||
(prefs showHelpOnError)
|
(prefs showHelpOnError)
|
||||||
@@ -171,7 +176,7 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
|
|||||||
-- create ~/.ghcup dir
|
-- create ~/.ghcup dir
|
||||||
ensureDirectories dirs
|
ensureDirectories dirs
|
||||||
|
|
||||||
(settings, keybindings) <- toSettings opt
|
(settings, keybindings, userConf) <- toSettings opt
|
||||||
|
|
||||||
-- logger interpreter
|
-- logger interpreter
|
||||||
logfile <- runReaderT initGHCupFileLogging dirs
|
logfile <- runReaderT initGHCupFileLogging dirs
|
||||||
@@ -196,25 +201,25 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
|
|||||||
|
|
||||||
|
|
||||||
let appState = do
|
let appState = do
|
||||||
pfreq <- (
|
pfreq <- case platformOverride settings of
|
||||||
runLogger . runE @'[NoCompatiblePlatform, NoCompatibleArch, DistroNotFound] . liftE $ platformRequest
|
Just pfreq' -> return pfreq'
|
||||||
) >>= \case
|
Nothing -> (runLogger . runE @'[NoCompatiblePlatform, NoCompatibleArch, DistroNotFound] . liftE $ platformRequest) >>= \case
|
||||||
VRight r -> pure r
|
VRight r -> pure r
|
||||||
VLeft e -> do
|
VLeft e -> do
|
||||||
runLogger
|
runLogger
|
||||||
(logError $ T.pack $ prettyShow e)
|
(logError $ T.pack $ prettyHFError e)
|
||||||
exitWith (ExitFailure 2)
|
exitWith (ExitFailure 2)
|
||||||
|
|
||||||
ghcupInfo <-
|
ghcupInfo <-
|
||||||
( flip runReaderT leanAppstate
|
( flip runReaderT leanAppstate
|
||||||
. runE @'[DigestError, GPGError, JSONError , DownloadFailed, FileDoesNotExistError]
|
. runE @'[DigestError, ContentLengthError, GPGError, JSONError , DownloadFailed, FileDoesNotExistError]
|
||||||
$ liftE getDownloadsF
|
$ liftE getDownloadsF
|
||||||
)
|
)
|
||||||
>>= \case
|
>>= \case
|
||||||
VRight r -> pure r
|
VRight r -> pure r
|
||||||
VLeft e -> do
|
VLeft e -> do
|
||||||
runLogger
|
runLogger
|
||||||
(logError $ T.pack $ prettyShow e)
|
(logError $ T.pack $ prettyHFError e)
|
||||||
exitWith (ExitFailure 2)
|
exitWith (ExitFailure 2)
|
||||||
let s' = AppState settings dirs keybindings ghcupInfo pfreq loggerConfig
|
let s' = AppState settings dirs keybindings ghcupInfo pfreq loggerConfig
|
||||||
|
|
||||||
@@ -236,7 +241,7 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
|
|||||||
| Just False <- optVerbose -> pure ()
|
| Just False <- optVerbose -> pure ()
|
||||||
| otherwise -> lookupEnv "GHCUP_SKIP_UPDATE_CHECK" >>= \case
|
| otherwise -> lookupEnv "GHCUP_SKIP_UPDATE_CHECK" >>= \case
|
||||||
Nothing -> void . flip runReaderT s' . runE @'[TagNotFound, NextVerNotFound, NoToolVersionSet] $ do
|
Nothing -> void . flip runReaderT s' . runE @'[TagNotFound, NextVerNotFound, NoToolVersionSet] $ do
|
||||||
newTools <- lift checkForUpdates
|
newTools <- lift checkForUpdates
|
||||||
forM_ newTools $ \newTool@(t, l) -> do
|
forM_ newTools $ \newTool@(t, l) -> do
|
||||||
-- https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/283
|
-- https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/283
|
||||||
alreadyInstalling' <- alreadyInstalling optCommand newTool
|
alreadyInstalling' <- alreadyInstalling optCommand newTool
|
||||||
@@ -250,7 +255,7 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
|
|||||||
logWarn ("New "
|
logWarn ("New "
|
||||||
<> T.pack (prettyShow t)
|
<> T.pack (prettyShow t)
|
||||||
<> " version available. "
|
<> " version available. "
|
||||||
<> "To upgrade, run 'ghcup install "
|
<> "If you want to install this latest version, run 'ghcup install "
|
||||||
<> T.pack (prettyShow t)
|
<> T.pack (prettyShow t)
|
||||||
<> " "
|
<> " "
|
||||||
<> prettyVer l
|
<> prettyVer l
|
||||||
@@ -262,7 +267,7 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
|
|||||||
VRight _ -> pure ()
|
VRight _ -> pure ()
|
||||||
VLeft e -> do
|
VLeft e -> do
|
||||||
runLogger
|
runLogger
|
||||||
(logError $ T.pack $ prettyShow e)
|
(logError $ T.pack $ prettyHFError e)
|
||||||
exitWith (ExitFailure 30)
|
exitWith (ExitFailure 30)
|
||||||
pure s'
|
pure s'
|
||||||
|
|
||||||
@@ -277,7 +282,7 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
|
|||||||
runAppState action' = do
|
runAppState action' = do
|
||||||
s' <- liftIO appState
|
s' <- liftIO appState
|
||||||
runReaderT action' s'
|
runReaderT action' s'
|
||||||
|
|
||||||
|
|
||||||
-----------------
|
-----------------
|
||||||
-- Run command --
|
-- Run command --
|
||||||
@@ -291,13 +296,14 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
|
|||||||
#endif
|
#endif
|
||||||
Install installCommand -> install installCommand settings appState runLogger
|
Install installCommand -> install installCommand settings appState runLogger
|
||||||
InstallCabalLegacy iopts -> install (Left (InstallCabal iopts)) settings appState runLogger
|
InstallCabalLegacy iopts -> install (Left (InstallCabal iopts)) settings appState runLogger
|
||||||
|
Test testCommand -> test testCommand settings appState runLogger
|
||||||
Set setCommand -> set setCommand runAppState runLeanAppState runLogger
|
Set setCommand -> set setCommand runAppState runLeanAppState runLogger
|
||||||
UnSet unsetCommand -> unset unsetCommand runLeanAppState runLogger
|
UnSet unsetCommand -> unset unsetCommand runLeanAppState runLogger
|
||||||
List lo -> list lo no_color runAppState
|
List lo -> list lo no_color runAppState
|
||||||
Rm rmCommand -> rm rmCommand runAppState runLogger
|
Rm rmCommand -> rm rmCommand runAppState runLogger
|
||||||
DInfo -> dinfo runAppState runLogger
|
DInfo -> dinfo runAppState runLogger
|
||||||
Compile compileCommand -> compile compileCommand settings dirs runAppState runLogger
|
Compile compileCommand -> compile compileCommand settings dirs runAppState runLogger
|
||||||
Config configCommand -> config configCommand settings keybindings runLogger
|
Config configCommand -> config configCommand settings userConf keybindings runLogger
|
||||||
Whereis whereisOptions
|
Whereis whereisOptions
|
||||||
whereisCommand -> whereis whereisCommand whereisOptions runAppState leanAppstate runLogger
|
whereisCommand -> whereis whereisCommand whereisOptions runAppState leanAppstate runLogger
|
||||||
Upgrade uOpts force' fatal -> upgrade uOpts force' fatal dirs runAppState runLogger
|
Upgrade uOpts force' fatal -> upgrade uOpts force' fatal dirs runAppState runLogger
|
||||||
@@ -307,6 +313,7 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
|
|||||||
Prefetch pfCom -> prefetch pfCom runAppState runLogger
|
Prefetch pfCom -> prefetch pfCom runAppState runLogger
|
||||||
GC gcOpts -> gc gcOpts runAppState runLogger
|
GC gcOpts -> gc gcOpts runAppState runLogger
|
||||||
Run runCommand -> run runCommand appState leanAppstate runLogger
|
Run runCommand -> run runCommand appState leanAppstate runLogger
|
||||||
|
PrintAppErrors -> putStrLn allHFError >> pure ExitSuccess
|
||||||
|
|
||||||
case res of
|
case res of
|
||||||
ExitSuccess -> pure ()
|
ExitSuccess -> pure ()
|
||||||
@@ -337,14 +344,16 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
|
|||||||
alreadyInstalling (Install (Left (InstallHLS InstallOptions{..}))) (HLS, ver) = cmp' HLS instVer ver
|
alreadyInstalling (Install (Left (InstallHLS InstallOptions{..}))) (HLS, ver) = cmp' HLS instVer ver
|
||||||
alreadyInstalling (Install (Left (InstallStack InstallOptions{..}))) (Stack, ver) = cmp' Stack instVer ver
|
alreadyInstalling (Install (Left (InstallStack InstallOptions{..}))) (Stack, ver) = cmp' Stack instVer ver
|
||||||
alreadyInstalling (Compile (CompileGHC GHCCompileOptions{ ovewrwiteVer = Just over }))
|
alreadyInstalling (Compile (CompileGHC GHCCompileOptions{ ovewrwiteVer = Just over }))
|
||||||
(GHC, ver) = cmp' GHC (Just $ ToolVersion (mkTVer over)) ver
|
(GHC, ver) = cmp' GHC (Just $ GHCVersion (mkTVer over)) ver
|
||||||
alreadyInstalling (Compile (CompileGHC GHCCompileOptions{ targetGhc = Left tver }))
|
alreadyInstalling (Compile (CompileGHC GHCCompileOptions{ targetGhc = GHC.SourceDist tver }))
|
||||||
(GHC, ver) = cmp' GHC (Just $ ToolVersion (mkTVer tver)) ver
|
(GHC, ver) = cmp' GHC (Just $ ToolVersion tver) ver
|
||||||
alreadyInstalling (Compile (CompileHLS HLSCompileOptions{ ovewrwiteVer = Just over }))
|
alreadyInstalling (Compile (CompileHLS HLSCompileOptions{ ovewrwiteVer = Right over }))
|
||||||
(HLS, ver) = cmp' HLS (Just $ ToolVersion (mkTVer over)) ver
|
(HLS, ver) = cmp' HLS (Just $ ToolVersion over) ver
|
||||||
alreadyInstalling (Compile (CompileHLS HLSCompileOptions{ targetHLS = Left tver }))
|
alreadyInstalling (Compile (CompileHLS HLSCompileOptions{ targetHLS = HLS.SourceDist tver }))
|
||||||
(HLS, ver) = cmp' HLS (Just $ ToolVersion (mkTVer tver)) ver
|
(HLS, ver) = cmp' HLS (Just $ ToolVersion tver) ver
|
||||||
alreadyInstalling (Upgrade _ _ _) (GHCup, _) = pure True
|
alreadyInstalling (Compile (CompileHLS HLSCompileOptions{ targetHLS = HLS.HackageDist tver }))
|
||||||
|
(HLS, ver) = cmp' HLS (Just $ ToolVersion tver) ver
|
||||||
|
alreadyInstalling (Upgrade {}) (GHCup, _) = pure True
|
||||||
alreadyInstalling _ _ = pure False
|
alreadyInstalling _ _ = pure False
|
||||||
|
|
||||||
cmp' :: ( HasLog env
|
cmp' :: ( HasLog env
|
||||||
|
|||||||
@@ -5,16 +5,9 @@ optional-packages: ./vendored/*/*.cabal
|
|||||||
optimization: 2
|
optimization: 2
|
||||||
|
|
||||||
package ghcup
|
package ghcup
|
||||||
tests: True
|
|
||||||
flags: +tui
|
flags: +tui
|
||||||
|
|
||||||
source-repository-package
|
|
||||||
type: git
|
|
||||||
location: https://github.com/bgamari/terminal-size.git
|
|
||||||
tag: 34ea816bd63f75f800eedac12c6908c6f3736036
|
|
||||||
|
|
||||||
constraints: http-io-streams -brotli,
|
constraints: http-io-streams -brotli,
|
||||||
any.Cabal ==3.6.2.0,
|
|
||||||
any.aeson >= 2.0.1.0
|
any.aeson >= 2.0.1.0
|
||||||
|
|
||||||
package libarchive
|
package libarchive
|
||||||
@@ -29,6 +22,8 @@ package cabal-plan
|
|||||||
package aeson
|
package aeson
|
||||||
flags: +ordered-keymap
|
flags: +ordered-keymap
|
||||||
|
|
||||||
allow-newer: base, ghc-prim, template-haskell, language-c
|
package streamly
|
||||||
|
flags: +use-unliftio
|
||||||
|
|
||||||
|
|
||||||
with-compiler: ghc-8.10.7
|
with-compiler: ghc-8.10.7
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
active-repositories: hackage.haskell.org:merge
|
active-repositories: hackage.haskell.org:merge
|
||||||
constraints: any.Cabal ==3.6.2.0,
|
constraints: any.Cabal ==3.6.3.0,
|
||||||
Cabal -bundled-binary-generic,
|
Cabal -bundled-binary-generic,
|
||||||
|
any.Cabal-syntax ==3.8.1.0,
|
||||||
any.HUnit ==1.6.2.0,
|
any.HUnit ==1.6.2.0,
|
||||||
any.HsOpenSSL ==0.11.7.2,
|
any.HsOpenSSL ==0.11.7.4,
|
||||||
HsOpenSSL -fast-bignum -homebrew-openssl -macports-openssl -use-pkg-config,
|
HsOpenSSL -fast-bignum -homebrew-openssl -macports-openssl -use-pkg-config,
|
||||||
any.OneTuple ==0.3.1,
|
any.OneTuple ==0.3.1,
|
||||||
any.QuickCheck ==2.14.2,
|
any.QuickCheck ==2.14.2,
|
||||||
@@ -10,13 +11,13 @@ constraints: any.Cabal ==3.6.2.0,
|
|||||||
any.StateVar ==1.2.2,
|
any.StateVar ==1.2.2,
|
||||||
any.abstract-deque ==0.3,
|
any.abstract-deque ==0.3,
|
||||||
abstract-deque -usecas,
|
abstract-deque -usecas,
|
||||||
any.aeson ==2.0.3.0,
|
any.aeson ==2.1.1.0,
|
||||||
aeson -cffi +ordered-keymap,
|
aeson -cffi +ordered-keymap,
|
||||||
any.aeson-pretty ==0.8.9,
|
any.aeson-pretty ==0.8.9,
|
||||||
aeson-pretty +lib-only,
|
aeson-pretty +lib-only,
|
||||||
any.alex ==3.2.7.1,
|
any.alex ==3.2.7.1,
|
||||||
any.ansi-terminal ==0.11.1,
|
any.ansi-terminal ==0.11.4,
|
||||||
ansi-terminal -example,
|
ansi-terminal -example +win32-2-13-1,
|
||||||
any.ansi-wl-pprint ==0.6.9,
|
any.ansi-wl-pprint ==0.6.9,
|
||||||
ansi-wl-pprint -example,
|
ansi-wl-pprint -example,
|
||||||
any.array ==0.5.4.0,
|
any.array ==0.5.4.0,
|
||||||
@@ -28,23 +29,27 @@ constraints: any.Cabal ==3.6.2.0,
|
|||||||
any.attoparsec ==0.14.4,
|
any.attoparsec ==0.14.4,
|
||||||
attoparsec -developer,
|
attoparsec -developer,
|
||||||
any.base ==4.14.3.0,
|
any.base ==4.14.3.0,
|
||||||
any.base-compat ==0.12.1,
|
any.base-compat ==0.12.2,
|
||||||
any.base-compat-batteries ==0.12.1,
|
any.base-compat-batteries ==0.12.2,
|
||||||
any.base-orphans ==0.8.6,
|
any.base-orphans ==0.8.7,
|
||||||
any.base16-bytestring ==1.0.2.0,
|
any.base16-bytestring ==1.0.2.0,
|
||||||
any.base64-bytestring ==1.2.1.0,
|
any.base64-bytestring ==1.2.1.0,
|
||||||
any.bifunctors ==5.5.11,
|
any.bifunctors ==5.5.14,
|
||||||
bifunctors +semigroups +tagged,
|
bifunctors +semigroups +tagged,
|
||||||
|
any.bimap ==0.5.0,
|
||||||
any.binary ==0.8.8.0,
|
any.binary ==0.8.8.0,
|
||||||
|
any.binary-instances ==1.0.3,
|
||||||
|
any.binary-orphans ==1.0.3,
|
||||||
any.blaze-builder ==0.4.2.2,
|
any.blaze-builder ==0.4.2.2,
|
||||||
any.brick ==0.64.2,
|
any.brick ==1.5,
|
||||||
brick -demos,
|
brick -demos,
|
||||||
any.bytestring ==0.10.12.0,
|
any.bytestring ==0.10.12.0,
|
||||||
any.bz2 ==1.0.1.0,
|
any.bz2 ==1.0.1.0,
|
||||||
bz2 -cross +with-bzlib,
|
bz2 -cross +with-bzlib,
|
||||||
any.c2hs ==0.28.8,
|
any.c2hs ==0.28.8,
|
||||||
c2hs +base3 -regression,
|
c2hs +base3 -regression,
|
||||||
any.cabal-plan ==0.7.2.1,
|
any.cabal-install-parsers ==0.5,
|
||||||
|
any.cabal-plan ==0.7.2.3,
|
||||||
cabal-plan -_ -exe -license-report,
|
cabal-plan -_ -exe -license-report,
|
||||||
any.call-stack ==0.4.0,
|
any.call-stack ==0.4.0,
|
||||||
any.case-insensitive ==1.2.1.0,
|
any.case-insensitive ==1.2.1.0,
|
||||||
@@ -52,14 +57,12 @@ constraints: any.Cabal ==3.6.2.0,
|
|||||||
any.chs-cabal ==0.1.1.1,
|
any.chs-cabal ==0.1.1.1,
|
||||||
any.chs-deps ==0.1.0.0,
|
any.chs-deps ==0.1.0.0,
|
||||||
chs-deps -cross,
|
chs-deps -cross,
|
||||||
any.clock ==0.8.3,
|
|
||||||
clock -llvm,
|
|
||||||
any.colour ==2.3.6,
|
any.colour ==2.3.6,
|
||||||
any.comonad ==5.0.8,
|
any.comonad ==5.0.8,
|
||||||
comonad +containers +distributive +indexed-traversable,
|
comonad +containers +distributive +indexed-traversable,
|
||||||
any.composition-prelude ==3.0.0.2,
|
any.composition-prelude ==3.0.0.2,
|
||||||
composition-prelude -development,
|
composition-prelude -development,
|
||||||
any.config-ini ==0.2.4.0,
|
any.config-ini ==0.2.5.0,
|
||||||
config-ini -enable-doctests,
|
config-ini -enable-doctests,
|
||||||
any.containers ==0.6.5.1,
|
any.containers ==0.6.5.1,
|
||||||
any.contravariant ==1.5.5,
|
any.contravariant ==1.5.5,
|
||||||
@@ -69,6 +72,7 @@ constraints: any.Cabal ==3.6.2.0,
|
|||||||
any.cryptohash-sha1 ==0.11.101.0,
|
any.cryptohash-sha1 ==0.11.101.0,
|
||||||
any.cryptohash-sha256 ==0.11.102.1,
|
any.cryptohash-sha256 ==0.11.102.1,
|
||||||
cryptohash-sha256 -exe +use-cbits,
|
cryptohash-sha256 -exe +use-cbits,
|
||||||
|
any.data-array-byte ==0.1.0.1,
|
||||||
any.data-clist ==0.2,
|
any.data-clist ==0.2,
|
||||||
any.data-fix ==0.3.2,
|
any.data-fix ==0.3.2,
|
||||||
any.deepseq ==1.4.4.0,
|
any.deepseq ==1.4.4.0,
|
||||||
@@ -80,93 +84,91 @@ constraints: any.Cabal ==3.6.2.0,
|
|||||||
dlist -werror,
|
dlist -werror,
|
||||||
any.exceptions ==0.10.4,
|
any.exceptions ==0.10.4,
|
||||||
any.filepath ==1.4.2.1,
|
any.filepath ==1.4.2.1,
|
||||||
any.free ==5.1.7,
|
any.free ==5.1.10,
|
||||||
any.fusion-plugin-types ==0.1.0,
|
any.fusion-plugin-types ==0.1.0,
|
||||||
any.generic-arbitrary ==0.2.0,
|
any.generic-arbitrary ==0.2.2,
|
||||||
any.ghc ==8.10.7,
|
any.generically ==0.1,
|
||||||
any.ghc-boot ==8.10.7,
|
|
||||||
any.ghc-boot-th ==8.10.7,
|
any.ghc-boot-th ==8.10.7,
|
||||||
any.ghc-byteorder ==4.11.0.0.10,
|
any.ghc-byteorder ==4.11.0.0.10,
|
||||||
any.ghc-heap ==8.10.7,
|
|
||||||
any.ghc-prim ==0.6.1,
|
any.ghc-prim ==0.6.1,
|
||||||
any.ghci ==8.10.7,
|
|
||||||
any.happy ==1.20.0,
|
any.happy ==1.20.0,
|
||||||
any.hashable ==1.4.0.2,
|
any.hashable ==1.4.2.0,
|
||||||
hashable +containers +integer-gmp -random-initial-seed,
|
hashable +integer-gmp -random-initial-seed,
|
||||||
|
any.haskell-lexer ==1.1.1,
|
||||||
any.haskus-utils-data ==1.4,
|
any.haskus-utils-data ==1.4,
|
||||||
any.haskus-utils-types ==1.5.1,
|
any.haskus-utils-types ==1.5.1,
|
||||||
any.haskus-utils-variant ==3.2.1,
|
any.haskus-utils-variant ==3.2.1,
|
||||||
any.heaps ==0.4,
|
any.heaps ==0.4,
|
||||||
any.hpc ==0.6.1.0,
|
|
||||||
any.hsc2hs ==0.68.8,
|
any.hsc2hs ==0.68.8,
|
||||||
hsc2hs -in-ghc-tree,
|
hsc2hs -in-ghc-tree,
|
||||||
any.hspec ==2.9.4,
|
any.hspec ==2.10.8,
|
||||||
any.hspec-core ==2.9.4,
|
any.hspec-core ==2.10.8,
|
||||||
any.hspec-discover ==2.9.4,
|
any.hspec-discover ==2.10.8,
|
||||||
any.hspec-expectations ==0.8.2,
|
any.hspec-expectations ==0.8.2,
|
||||||
any.hspec-golden-aeson ==0.9.0.0,
|
any.hspec-golden-aeson ==0.9.0.0,
|
||||||
any.http-io-streams ==0.1.6.0,
|
any.http-io-streams ==0.1.6.1,
|
||||||
http-io-streams -brotli +fast-xor,
|
http-io-streams -brotli +fast-xor,
|
||||||
any.indexed-profunctors ==0.1.1,
|
any.indexed-profunctors ==0.1.1,
|
||||||
any.indexed-traversable ==0.1.2,
|
any.indexed-traversable ==0.1.2,
|
||||||
any.indexed-traversable-instances ==0.1.1,
|
any.indexed-traversable-instances ==0.1.1.1,
|
||||||
any.integer-gmp ==1.0.3.0,
|
any.integer-gmp ==1.0.3.0,
|
||||||
any.integer-logarithms ==1.0.3.1,
|
any.integer-logarithms ==1.0.3.1,
|
||||||
integer-logarithms -check-bounds +integer-gmp,
|
integer-logarithms -check-bounds +integer-gmp,
|
||||||
any.io-streams ==1.5.2.1,
|
any.io-streams ==1.5.2.2,
|
||||||
io-streams +network -nointeractivetests +zlib,
|
io-streams +network -nointeractivetests +zlib,
|
||||||
any.language-c ==0.9.0.1,
|
any.language-c ==0.9.2,
|
||||||
language-c -allwarnings +iecfpextension +usebytestrings,
|
language-c -allwarnings +iecfpextension +usebytestrings,
|
||||||
any.libarchive ==3.0.3.2,
|
any.libarchive ==3.0.3.2,
|
||||||
libarchive -cross -low-memory +no-exe -system-libarchive,
|
libarchive -cross -low-memory +no-exe -system-libarchive,
|
||||||
any.libyaml-streamly ==0.2.1,
|
any.libyaml-streamly ==0.2.1,
|
||||||
libyaml-streamly -no-unicode -system-libyaml,
|
libyaml-streamly -no-unicode -system-libyaml,
|
||||||
any.lockfree-queue ==0.2.3.1,
|
any.lockfree-queue ==0.2.4,
|
||||||
any.lzma-static ==5.2.5.4,
|
any.lukko ==0.1.1.3,
|
||||||
any.megaparsec ==9.2.0,
|
lukko +ofd-locking,
|
||||||
|
any.lzma-static ==5.2.5.5,
|
||||||
|
any.megaparsec ==9.2.1,
|
||||||
megaparsec -dev,
|
megaparsec -dev,
|
||||||
any.microlens ==0.4.12.0,
|
any.microlens ==0.4.13.1,
|
||||||
any.microlens-mtl ==0.2.0.1,
|
any.microlens-mtl ==0.2.0.3,
|
||||||
any.microlens-th ==0.4.3.10,
|
any.microlens-th ==0.4.3.11,
|
||||||
any.monad-control ==1.0.3.1,
|
|
||||||
any.mtl ==2.2.2,
|
any.mtl ==2.2.2,
|
||||||
any.network ==3.1.2.7,
|
any.network ==3.1.2.7,
|
||||||
network -devel,
|
network -devel,
|
||||||
any.network-uri ==2.6.4.1,
|
any.network-uri ==2.6.4.2,
|
||||||
any.openssl-streams ==1.2.3.0,
|
any.openssl-streams ==1.2.3.0,
|
||||||
any.optics ==0.4,
|
any.optics ==0.4.2,
|
||||||
any.optics-core ==0.4,
|
any.optics-core ==0.4.1,
|
||||||
optics-core -explicit-generic-labels,
|
optics-core -explicit-generic-labels,
|
||||||
any.optics-extra ==0.4,
|
any.optics-extra ==0.4.2.1,
|
||||||
any.optics-th ==0.4,
|
any.optics-th ==0.4.1,
|
||||||
any.optparse-applicative ==0.17.0.0,
|
any.optparse-applicative ==0.17.0.0,
|
||||||
optparse-applicative +process,
|
optparse-applicative +process,
|
||||||
any.os-release ==1.0.2.1,
|
any.os-release ==1.0.2.1,
|
||||||
os-release -devel,
|
os-release -devel,
|
||||||
any.parallel ==3.2.2.0,
|
any.parallel ==3.2.2.0,
|
||||||
any.parsec ==3.1.14.0,
|
any.parsec ==3.1.16.1,
|
||||||
any.parser-combinators ==1.3.0,
|
any.parser-combinators ==1.3.0,
|
||||||
parser-combinators -dev,
|
parser-combinators -dev,
|
||||||
any.polyparse ==1.13,
|
any.polyparse ==1.13,
|
||||||
any.pretty ==1.1.3.6,
|
any.pretty ==1.1.3.6,
|
||||||
any.pretty-terminal ==0.1.0.0,
|
any.pretty-terminal ==0.1.0.0,
|
||||||
any.primitive ==0.7.3.0,
|
any.primitive ==0.7.4.0,
|
||||||
any.process ==1.6.13.2,
|
any.process ==1.6.13.2,
|
||||||
any.profunctors ==5.6.2,
|
any.profunctors ==5.6.2,
|
||||||
any.quickcheck-arbitrary-adt ==0.3.1.0,
|
any.quickcheck-arbitrary-adt ==0.3.1.0,
|
||||||
any.quickcheck-io ==0.2.0,
|
any.quickcheck-io ==0.2.0,
|
||||||
any.random ==1.2.1,
|
any.random ==1.2.1.1,
|
||||||
any.recursion-schemes ==5.2.2.2,
|
any.recursion-schemes ==5.2.2.3,
|
||||||
recursion-schemes +template-haskell,
|
recursion-schemes +template-haskell,
|
||||||
any.regex-base ==0.94.0.2,
|
any.regex-base ==0.94.0.2,
|
||||||
any.regex-posix ==0.96.0.1,
|
any.regex-posix ==0.96.0.1,
|
||||||
regex-posix -_regex-posix-clib,
|
regex-posix -_regex-posix-clib,
|
||||||
any.resourcet ==1.2.4.3,
|
any.resourcet ==1.2.6,
|
||||||
any.retry ==0.8.1.2,
|
any.retry ==0.8.1.2,
|
||||||
retry -lib-werror,
|
retry -lib-werror,
|
||||||
any.rts ==1.0.1,
|
any.rts ==1.0.1,
|
||||||
any.safe ==0.3.19,
|
any.safe ==0.3.19,
|
||||||
any.safe-exceptions ==0.1.7.2,
|
any.safe-exceptions ==0.1.7.3,
|
||||||
any.scientific ==0.3.7.0,
|
any.scientific ==0.3.7.0,
|
||||||
scientific -bytestring-builder -integer-simple,
|
scientific -bytestring-builder -integer-simple,
|
||||||
any.semialign ==1.2.0.1,
|
any.semialign ==1.2.0.1,
|
||||||
@@ -174,32 +176,36 @@ constraints: any.Cabal ==3.6.2.0,
|
|||||||
any.semigroupoids ==5.3.7,
|
any.semigroupoids ==5.3.7,
|
||||||
semigroupoids +comonad +containers +contravariant +distributive +tagged +unordered-containers,
|
semigroupoids +comonad +containers +contravariant +distributive +tagged +unordered-containers,
|
||||||
any.setenv ==0.1.1.3,
|
any.setenv ==0.1.1.3,
|
||||||
any.split ==0.2.3.4,
|
any.split ==0.2.3.5,
|
||||||
any.splitmix ==0.1.0.4,
|
any.splitmix ==0.1.0.4,
|
||||||
splitmix -optimised-mixer,
|
splitmix -optimised-mixer,
|
||||||
any.stm ==2.5.0.1,
|
any.stm ==2.5.0.1,
|
||||||
any.streamly ==0.8.2,
|
any.streamly ==0.8.3,
|
||||||
streamly -debug -dev -fusion-plugin -has-llvm -inspection -limit-build-mem -no-fusion +opt -streamk -streamly-core -use-c-malloc -use-unliftio,
|
streamly -debug -dev -fusion-plugin -has-llvm -inspection -limit-build-mem -no-fusion +opt -streamk -streamly-core -use-c-malloc +use-unliftio,
|
||||||
any.strict ==0.4.0.1,
|
any.strict ==0.4.0.1,
|
||||||
strict +assoc,
|
strict +assoc,
|
||||||
any.strict-base ==0.4.0.0,
|
any.strict-base ==0.4.0.0,
|
||||||
any.tagged ==0.8.6.1,
|
any.tagged ==0.8.6.1,
|
||||||
tagged +deepseq +transformers,
|
tagged +deepseq +transformers,
|
||||||
any.tagsoup ==0.14.8,
|
any.tagsoup ==0.14.8,
|
||||||
|
any.tar ==0.5.1.1,
|
||||||
|
tar -old-bytestring -old-time,
|
||||||
any.template-haskell ==2.16.0.0,
|
any.template-haskell ==2.16.0.0,
|
||||||
any.temporary ==1.3,
|
any.temporary ==1.3,
|
||||||
any.terminal-progress-bar ==0.4.1,
|
any.terminal-progress-bar ==0.4.1,
|
||||||
any.terminal-size ==0.3.2.1,
|
any.terminal-size ==0.3.3,
|
||||||
any.terminfo ==0.4.1.4,
|
any.terminfo ==0.4.1.4,
|
||||||
any.text ==1.2.4.1,
|
any.text ==2.0.1,
|
||||||
|
text -developer +simdutf,
|
||||||
|
any.text-binary ==0.2.1.1,
|
||||||
any.text-short ==0.1.5,
|
any.text-short ==0.1.5,
|
||||||
text-short -asserts,
|
text-short -asserts,
|
||||||
any.text-zipper ==0.11,
|
any.text-zipper ==0.12,
|
||||||
any.tf-random ==0.5,
|
any.tf-random ==0.5,
|
||||||
any.th-abstraction ==0.4.3.0,
|
any.th-abstraction ==0.4.5.0,
|
||||||
any.th-compat ==0.1.3,
|
any.th-compat ==0.1.4,
|
||||||
any.th-lift ==0.8.2,
|
any.th-lift ==0.8.2,
|
||||||
any.th-lift-instances ==0.1.19,
|
any.th-lift-instances ==0.1.20,
|
||||||
any.these ==1.1.1.1,
|
any.these ==1.1.1.1,
|
||||||
these +assoc,
|
these +assoc,
|
||||||
any.time ==1.9.3,
|
any.time ==1.9.3,
|
||||||
@@ -208,16 +214,16 @@ constraints: any.Cabal ==3.6.2.0,
|
|||||||
any.transformers ==0.5.6.2,
|
any.transformers ==0.5.6.2,
|
||||||
any.transformers-base ==0.4.6,
|
any.transformers-base ==0.4.6,
|
||||||
transformers-base +orphaninstances,
|
transformers-base +orphaninstances,
|
||||||
any.transformers-compat ==0.7.1,
|
any.transformers-compat ==0.7.2,
|
||||||
transformers-compat -five +five-three -four +generic-deriving +mtl -three -two,
|
transformers-compat -five +five-three -four +generic-deriving +mtl -three -two,
|
||||||
any.unicode-data ==0.3.0,
|
any.unicode-data ==0.3.1,
|
||||||
unicode-data -ucd2haskell,
|
unicode-data -ucd2haskell,
|
||||||
any.unix ==2.7.2.2,
|
any.unix ==2.7.2.2,
|
||||||
any.unix-bytestring ==0.3.7.6,
|
any.unix-bytestring ==0.3.7.8,
|
||||||
any.unix-compat ==0.5.4,
|
any.unix-compat ==0.6,
|
||||||
unix-compat -old-time,
|
unix-compat -old-time,
|
||||||
any.unliftio-core ==0.2.0.1,
|
any.unliftio-core ==0.2.0.1,
|
||||||
any.unordered-containers ==0.2.17.0,
|
any.unordered-containers ==0.2.19.1,
|
||||||
unordered-containers -debug,
|
unordered-containers -debug,
|
||||||
any.uri-bytestring ==0.3.3.1,
|
any.uri-bytestring ==0.3.3.1,
|
||||||
uri-bytestring -lib-werror,
|
uri-bytestring -lib-werror,
|
||||||
@@ -225,15 +231,16 @@ constraints: any.Cabal ==3.6.2.0,
|
|||||||
any.uuid-types ==1.0.5,
|
any.uuid-types ==1.0.5,
|
||||||
any.vector ==0.12.3.1,
|
any.vector ==0.12.3.1,
|
||||||
vector +boundschecks -internalchecks -unsafechecks -wall,
|
vector +boundschecks -internalchecks -unsafechecks -wall,
|
||||||
any.versions ==5.0.3,
|
any.vector-binary-instances ==0.2.5.2,
|
||||||
any.vty ==5.33,
|
any.versions ==5.0.4,
|
||||||
|
any.vty ==5.37,
|
||||||
any.witherable ==0.4.2,
|
any.witherable ==0.4.2,
|
||||||
any.word-wrap ==0.5,
|
any.word-wrap ==0.5,
|
||||||
any.word8 ==0.1.3,
|
any.word8 ==0.1.3,
|
||||||
any.xor ==0.0.1.1,
|
any.xor ==0.0.1.1,
|
||||||
any.yaml-streamly ==0.12.1,
|
any.yaml-streamly ==0.12.1,
|
||||||
yaml-streamly +no-examples +no-exe,
|
yaml-streamly +no-examples +no-exe,
|
||||||
any.zlib ==0.6.2.3,
|
any.zlib ==0.6.3.0,
|
||||||
zlib -bundled-c-zlib -non-blocking-ffi -pkg-config,
|
zlib -bundled-c-zlib -non-blocking-ffi -pkg-config,
|
||||||
any.zlib-bindings ==0.1.1.5
|
any.zlib-bindings ==0.1.1.5
|
||||||
index-state: hackage.haskell.org 2022-03-15T16:43:02Z
|
index-state: hackage.haskell.org 2023-01-12T04:22:48Z
|
||||||
|
|||||||
@@ -1,34 +0,0 @@
|
|||||||
packages: ./ghcup.cabal
|
|
||||||
|
|
||||||
optional-packages: ./vendored/*/*.cabal
|
|
||||||
|
|
||||||
optimization: 2
|
|
||||||
|
|
||||||
package ghcup
|
|
||||||
tests: True
|
|
||||||
flags: +tui
|
|
||||||
|
|
||||||
source-repository-package
|
|
||||||
type: git
|
|
||||||
location: https://github.com/bgamari/terminal-size.git
|
|
||||||
tag: 34ea816bd63f75f800eedac12c6908c6f3736036
|
|
||||||
|
|
||||||
constraints: http-io-streams -brotli,
|
|
||||||
any.Cabal ==3.6.2.0,
|
|
||||||
any.aeson >= 2.0.1.0
|
|
||||||
|
|
||||||
package libarchive
|
|
||||||
flags: -system-libarchive
|
|
||||||
|
|
||||||
package aeson-pretty
|
|
||||||
flags: +lib-only
|
|
||||||
|
|
||||||
package cabal-plan
|
|
||||||
flags: -exe
|
|
||||||
|
|
||||||
package aeson
|
|
||||||
flags: +ordered-keymap
|
|
||||||
|
|
||||||
allow-newer: base, ghc-prim, template-haskell, language-c
|
|
||||||
|
|
||||||
with-compiler: ghc-9.0.2
|
|
||||||
@@ -1,239 +0,0 @@
|
|||||||
active-repositories: hackage.haskell.org:merge
|
|
||||||
constraints: any.Cabal ==3.6.2.0,
|
|
||||||
Cabal -bundled-binary-generic,
|
|
||||||
any.HUnit ==1.6.2.0,
|
|
||||||
any.HsOpenSSL ==0.11.7.2,
|
|
||||||
HsOpenSSL -fast-bignum -homebrew-openssl -macports-openssl -use-pkg-config,
|
|
||||||
any.OneTuple ==0.3.1,
|
|
||||||
any.QuickCheck ==2.14.2,
|
|
||||||
QuickCheck -old-random +templatehaskell,
|
|
||||||
any.StateVar ==1.2.2,
|
|
||||||
any.abstract-deque ==0.3,
|
|
||||||
abstract-deque -usecas,
|
|
||||||
any.aeson ==2.0.3.0,
|
|
||||||
aeson -cffi +ordered-keymap,
|
|
||||||
any.aeson-pretty ==0.8.9,
|
|
||||||
aeson-pretty +lib-only,
|
|
||||||
any.alex ==3.2.7.1,
|
|
||||||
any.ansi-terminal ==0.11.1,
|
|
||||||
ansi-terminal -example,
|
|
||||||
any.ansi-wl-pprint ==0.6.9,
|
|
||||||
ansi-wl-pprint -example,
|
|
||||||
any.array ==0.5.4.0,
|
|
||||||
any.assoc ==1.0.2,
|
|
||||||
any.async ==2.2.4,
|
|
||||||
async -bench,
|
|
||||||
any.atomic-primops ==0.8.4,
|
|
||||||
atomic-primops -debug,
|
|
||||||
any.attoparsec ==0.14.4,
|
|
||||||
attoparsec -developer,
|
|
||||||
any.base ==4.15.1.0,
|
|
||||||
any.base-compat ==0.12.1,
|
|
||||||
any.base-compat-batteries ==0.12.1,
|
|
||||||
any.base-orphans ==0.8.6,
|
|
||||||
any.base16-bytestring ==1.0.2.0,
|
|
||||||
any.base64-bytestring ==1.2.1.0,
|
|
||||||
any.bifunctors ==5.5.11,
|
|
||||||
bifunctors +semigroups +tagged,
|
|
||||||
any.binary ==0.8.8.0,
|
|
||||||
any.blaze-builder ==0.4.2.2,
|
|
||||||
any.brick ==0.64.2,
|
|
||||||
brick -demos,
|
|
||||||
any.bytestring ==0.10.12.1,
|
|
||||||
any.bz2 ==1.0.1.0,
|
|
||||||
bz2 -cross +with-bzlib,
|
|
||||||
any.c2hs ==0.28.8,
|
|
||||||
c2hs +base3 -regression,
|
|
||||||
any.cabal-plan ==0.7.2.1,
|
|
||||||
cabal-plan -_ -exe -license-report,
|
|
||||||
any.call-stack ==0.4.0,
|
|
||||||
any.case-insensitive ==1.2.1.0,
|
|
||||||
any.casing ==0.1.4.1,
|
|
||||||
any.chs-cabal ==0.1.1.1,
|
|
||||||
any.chs-deps ==0.1.0.0,
|
|
||||||
chs-deps -cross,
|
|
||||||
any.clock ==0.8.3,
|
|
||||||
clock -llvm,
|
|
||||||
any.colour ==2.3.6,
|
|
||||||
any.comonad ==5.0.8,
|
|
||||||
comonad +containers +distributive +indexed-traversable,
|
|
||||||
any.composition-prelude ==3.0.0.2,
|
|
||||||
composition-prelude -development,
|
|
||||||
any.config-ini ==0.2.4.0,
|
|
||||||
config-ini -enable-doctests,
|
|
||||||
any.containers ==0.6.4.1,
|
|
||||||
any.contravariant ==1.5.5,
|
|
||||||
contravariant +semigroups +statevar +tagged,
|
|
||||||
any.cpphs ==1.20.9.1,
|
|
||||||
cpphs -old-locale,
|
|
||||||
any.cryptohash-sha1 ==0.11.101.0,
|
|
||||||
any.cryptohash-sha256 ==0.11.102.1,
|
|
||||||
cryptohash-sha256 -exe +use-cbits,
|
|
||||||
any.data-clist ==0.2,
|
|
||||||
any.data-fix ==0.3.2,
|
|
||||||
any.deepseq ==1.4.5.0,
|
|
||||||
any.directory ==1.3.6.2,
|
|
||||||
any.disk-free-space ==0.1.0.1,
|
|
||||||
any.distributive ==0.6.2.1,
|
|
||||||
distributive +semigroups +tagged,
|
|
||||||
any.dlist ==1.0,
|
|
||||||
dlist -werror,
|
|
||||||
any.exceptions ==0.10.4,
|
|
||||||
any.filepath ==1.4.2.1,
|
|
||||||
any.free ==5.1.7,
|
|
||||||
any.fusion-plugin-types ==0.1.0,
|
|
||||||
any.generic-arbitrary ==0.2.0,
|
|
||||||
any.ghc ==9.0.2,
|
|
||||||
any.ghc-bignum ==1.1,
|
|
||||||
any.ghc-boot ==9.0.2,
|
|
||||||
any.ghc-boot-th ==9.0.2,
|
|
||||||
any.ghc-byteorder ==4.11.0.0.10,
|
|
||||||
any.ghc-heap ==9.0.2,
|
|
||||||
any.ghc-prim ==0.7.0,
|
|
||||||
any.ghci ==9.0.2,
|
|
||||||
any.happy ==1.20.0,
|
|
||||||
any.hashable ==1.4.0.2,
|
|
||||||
hashable +containers +integer-gmp -random-initial-seed,
|
|
||||||
any.haskus-utils-data ==1.4,
|
|
||||||
any.haskus-utils-types ==1.5.1,
|
|
||||||
any.haskus-utils-variant ==3.2.1,
|
|
||||||
any.heaps ==0.4,
|
|
||||||
any.hpc ==0.6.1.0,
|
|
||||||
any.hsc2hs ==0.68.8,
|
|
||||||
hsc2hs -in-ghc-tree,
|
|
||||||
any.hspec ==2.9.4,
|
|
||||||
any.hspec-core ==2.9.4,
|
|
||||||
any.hspec-discover ==2.9.4,
|
|
||||||
any.hspec-expectations ==0.8.2,
|
|
||||||
any.hspec-golden-aeson ==0.9.0.0,
|
|
||||||
any.http-io-streams ==0.1.6.0,
|
|
||||||
http-io-streams -brotli +fast-xor,
|
|
||||||
any.indexed-profunctors ==0.1.1,
|
|
||||||
any.indexed-traversable ==0.1.2,
|
|
||||||
any.indexed-traversable-instances ==0.1.1,
|
|
||||||
any.integer-logarithms ==1.0.3.1,
|
|
||||||
integer-logarithms -check-bounds +integer-gmp,
|
|
||||||
any.io-streams ==1.5.2.1,
|
|
||||||
io-streams +network -nointeractivetests +zlib,
|
|
||||||
any.language-c ==0.9.0.1,
|
|
||||||
language-c -allwarnings +iecfpextension +usebytestrings,
|
|
||||||
any.libarchive ==3.0.3.2,
|
|
||||||
libarchive -cross -low-memory +no-exe -system-libarchive,
|
|
||||||
any.libyaml-streamly ==0.2.1,
|
|
||||||
libyaml-streamly -no-unicode -system-libyaml,
|
|
||||||
any.lockfree-queue ==0.2.3.1,
|
|
||||||
any.lzma-static ==5.2.5.4,
|
|
||||||
any.megaparsec ==9.2.0,
|
|
||||||
megaparsec -dev,
|
|
||||||
any.microlens ==0.4.12.0,
|
|
||||||
any.microlens-mtl ==0.2.0.1,
|
|
||||||
any.microlens-th ==0.4.3.10,
|
|
||||||
any.monad-control ==1.0.3.1,
|
|
||||||
any.mtl ==2.2.2,
|
|
||||||
any.network ==3.1.2.7,
|
|
||||||
network -devel,
|
|
||||||
any.network-uri ==2.6.4.1,
|
|
||||||
any.openssl-streams ==1.2.3.0,
|
|
||||||
any.optics ==0.4,
|
|
||||||
any.optics-core ==0.4,
|
|
||||||
optics-core -explicit-generic-labels,
|
|
||||||
any.optics-extra ==0.4,
|
|
||||||
any.optics-th ==0.4,
|
|
||||||
any.optparse-applicative ==0.17.0.0,
|
|
||||||
optparse-applicative +process,
|
|
||||||
any.os-release ==1.0.2.1,
|
|
||||||
os-release -devel,
|
|
||||||
any.parallel ==3.2.2.0,
|
|
||||||
any.parsec ==3.1.14.0,
|
|
||||||
any.parser-combinators ==1.3.0,
|
|
||||||
parser-combinators -dev,
|
|
||||||
any.polyparse ==1.13,
|
|
||||||
any.pretty ==1.1.3.6,
|
|
||||||
any.pretty-terminal ==0.1.0.0,
|
|
||||||
any.primitive ==0.7.3.0,
|
|
||||||
any.process ==1.6.13.2,
|
|
||||||
any.profunctors ==5.6.2,
|
|
||||||
any.quickcheck-arbitrary-adt ==0.3.1.0,
|
|
||||||
any.quickcheck-io ==0.2.0,
|
|
||||||
any.random ==1.2.1,
|
|
||||||
any.recursion-schemes ==5.2.2.2,
|
|
||||||
recursion-schemes +template-haskell,
|
|
||||||
any.regex-base ==0.94.0.2,
|
|
||||||
any.regex-posix ==0.96.0.1,
|
|
||||||
regex-posix -_regex-posix-clib,
|
|
||||||
any.resourcet ==1.2.4.3,
|
|
||||||
any.retry ==0.8.1.2,
|
|
||||||
retry -lib-werror,
|
|
||||||
any.rts ==1.0.2,
|
|
||||||
any.safe ==0.3.19,
|
|
||||||
any.safe-exceptions ==0.1.7.2,
|
|
||||||
any.scientific ==0.3.7.0,
|
|
||||||
scientific -bytestring-builder -integer-simple,
|
|
||||||
any.semialign ==1.2.0.1,
|
|
||||||
semialign +semigroupoids,
|
|
||||||
any.semigroupoids ==5.3.7,
|
|
||||||
semigroupoids +comonad +containers +contravariant +distributive +tagged +unordered-containers,
|
|
||||||
any.setenv ==0.1.1.3,
|
|
||||||
any.split ==0.2.3.4,
|
|
||||||
any.splitmix ==0.1.0.4,
|
|
||||||
splitmix -optimised-mixer,
|
|
||||||
any.stm ==2.5.0.0,
|
|
||||||
any.streamly ==0.8.2,
|
|
||||||
streamly -debug -dev -fusion-plugin -has-llvm -inspection -limit-build-mem -no-fusion +opt -streamk -streamly-core -use-c-malloc -use-unliftio,
|
|
||||||
any.strict ==0.4.0.1,
|
|
||||||
strict +assoc,
|
|
||||||
any.strict-base ==0.4.0.0,
|
|
||||||
any.tagged ==0.8.6.1,
|
|
||||||
tagged +deepseq +transformers,
|
|
||||||
any.tagsoup ==0.14.8,
|
|
||||||
any.template-haskell ==2.17.0.0,
|
|
||||||
any.temporary ==1.3,
|
|
||||||
any.terminal-progress-bar ==0.4.1,
|
|
||||||
any.terminal-size ==0.3.2.1,
|
|
||||||
any.terminfo ==0.4.1.5,
|
|
||||||
any.text ==1.2.5.0,
|
|
||||||
any.text-short ==0.1.5,
|
|
||||||
text-short -asserts,
|
|
||||||
any.text-zipper ==0.11,
|
|
||||||
any.tf-random ==0.5,
|
|
||||||
any.th-abstraction ==0.4.3.0,
|
|
||||||
any.th-compat ==0.1.3,
|
|
||||||
any.th-lift ==0.8.2,
|
|
||||||
any.th-lift-instances ==0.1.19,
|
|
||||||
any.these ==1.1.1.1,
|
|
||||||
these +assoc,
|
|
||||||
any.time ==1.9.3,
|
|
||||||
any.time-compat ==1.9.6.1,
|
|
||||||
time-compat -old-locale,
|
|
||||||
any.transformers ==0.5.6.2,
|
|
||||||
any.transformers-base ==0.4.6,
|
|
||||||
transformers-base +orphaninstances,
|
|
||||||
any.transformers-compat ==0.7.1,
|
|
||||||
transformers-compat -five +five-three -four +generic-deriving +mtl -three -two,
|
|
||||||
any.unicode-data ==0.3.0,
|
|
||||||
unicode-data -ucd2haskell,
|
|
||||||
any.unix ==2.7.2.2,
|
|
||||||
any.unix-bytestring ==0.3.7.6,
|
|
||||||
any.unix-compat ==0.5.4,
|
|
||||||
unix-compat -old-time,
|
|
||||||
any.unliftio-core ==0.2.0.1,
|
|
||||||
any.unordered-containers ==0.2.17.0,
|
|
||||||
unordered-containers -debug,
|
|
||||||
any.uri-bytestring ==0.3.3.1,
|
|
||||||
uri-bytestring -lib-werror,
|
|
||||||
any.utf8-string ==1.0.2,
|
|
||||||
any.uuid-types ==1.0.5,
|
|
||||||
any.vector ==0.12.3.1,
|
|
||||||
vector +boundschecks -internalchecks -unsafechecks -wall,
|
|
||||||
any.versions ==5.0.3,
|
|
||||||
any.vty ==5.33,
|
|
||||||
any.witherable ==0.4.2,
|
|
||||||
any.word-wrap ==0.5,
|
|
||||||
any.word8 ==0.1.3,
|
|
||||||
any.xor ==0.0.1.1,
|
|
||||||
any.yaml-streamly ==0.12.1,
|
|
||||||
yaml-streamly +no-examples +no-exe,
|
|
||||||
any.zlib ==0.6.2.3,
|
|
||||||
zlib -bundled-c-zlib -non-blocking-ffi -pkg-config,
|
|
||||||
any.zlib-bindings ==0.1.1.5
|
|
||||||
index-state: hackage.haskell.org 2022-03-15T16:43:02Z
|
|
||||||
@@ -2,22 +2,11 @@ packages: ./ghcup.cabal
|
|||||||
|
|
||||||
optional-packages: ./vendored/*/*.cabal
|
optional-packages: ./vendored/*/*.cabal
|
||||||
|
|
||||||
optimization: 2
|
|
||||||
|
|
||||||
package ghcup
|
package ghcup
|
||||||
tests: True
|
|
||||||
flags: +tui
|
flags: +tui
|
||||||
|
|
||||||
source-repository-package
|
|
||||||
type: git
|
|
||||||
location: https://github.com/bgamari/terminal-size.git
|
|
||||||
tag: 34ea816bd63f75f800eedac12c6908c6f3736036
|
|
||||||
|
|
||||||
constraints: http-io-streams -brotli,
|
constraints: http-io-streams -brotli,
|
||||||
any.Cabal ==3.6.2.0,
|
any.aeson >= 2.0.1.0
|
||||||
any.aeson >= 2.0.1.0,
|
|
||||||
-- https://github.com/typeable/generic-arbitrary/issues/14
|
|
||||||
any.generic-arbitrary < 0.2.1
|
|
||||||
|
|
||||||
package libarchive
|
package libarchive
|
||||||
flags: -system-libarchive
|
flags: -system-libarchive
|
||||||
@@ -34,4 +23,3 @@ package aeson
|
|||||||
package streamly
|
package streamly
|
||||||
flags: +use-unliftio
|
flags: +use-unliftio
|
||||||
|
|
||||||
allow-newer: base, ghc-prim, template-haskell, language-c
|
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
-- windows picks weird version
|
-- windows picks weird version
|
||||||
constraints: any.hsc2hs ==0.68.7
|
constraints: any.hsc2hs ==0.68.8
|
||||||
|
|||||||
50
cabal.project.release
Normal file
50
cabal.project.release
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
packages: ./ghcup.cabal
|
||||||
|
|
||||||
|
optional-packages: ./vendored/*/*.cabal
|
||||||
|
|
||||||
|
optimization: 2
|
||||||
|
|
||||||
|
if os(linux)
|
||||||
|
package ghcup
|
||||||
|
flags: +tui
|
||||||
|
if arch(x86_64) || arch(i386)
|
||||||
|
package *
|
||||||
|
ghc-options: -split-sections -optl-static
|
||||||
|
elif os(darwin)
|
||||||
|
constraints: zlib +bundled-c-zlib,
|
||||||
|
lzma +static
|
||||||
|
package ghcup
|
||||||
|
flags: +tui
|
||||||
|
elif os(mingw32)
|
||||||
|
constraints: zlib +bundled-c-zlib,
|
||||||
|
lzma +static,
|
||||||
|
text -simdutf
|
||||||
|
package ghcup
|
||||||
|
flags: -tui
|
||||||
|
elif os(freebsd)
|
||||||
|
constraints: zlib +bundled-c-zlib,
|
||||||
|
zip +disable-zstd
|
||||||
|
package *
|
||||||
|
ghc-options: -split-sections -pgmc clang++14
|
||||||
|
package ghcup
|
||||||
|
flags: +tui
|
||||||
|
|
||||||
|
constraints: http-io-streams -brotli,
|
||||||
|
any.aeson >= 2.0.1.0,
|
||||||
|
any.hsc2hs ==0.68.8
|
||||||
|
|
||||||
|
package libarchive
|
||||||
|
flags: -system-libarchive
|
||||||
|
|
||||||
|
package aeson-pretty
|
||||||
|
flags: +lib-only
|
||||||
|
|
||||||
|
package cabal-plan
|
||||||
|
flags: -exe
|
||||||
|
|
||||||
|
package aeson
|
||||||
|
flags: +ordered-keymap
|
||||||
|
|
||||||
|
package streamly
|
||||||
|
flags: +use-unliftio
|
||||||
|
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
#ifndef POSIXPATHS_CBITS_DIRUTILS_H
|
#ifndef POSIXPATHS_CBITS_DIRUTILS_H
|
||||||
#define POSIXPATHS_CBITS_DIRUTILS_H
|
#define POSIXPATHS_CBITS_DIRUTILS_H
|
||||||
|
|
||||||
|
#include <HsFFI.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|||||||
@@ -40,6 +40,12 @@ key-bindings:
|
|||||||
# of the file. These usually are in '~/.ghcup/cache/ghcup-<ver>.yaml'.
|
# of the file. These usually are in '~/.ghcup/cache/ghcup-<ver>.yaml'.
|
||||||
meta-cache: 300 # in seconds
|
meta-cache: 300 # in seconds
|
||||||
|
|
||||||
|
# When trying to download ghcup metadata, this option decides what to do
|
||||||
|
# when the download fails:
|
||||||
|
# 1. Lax: use existing ~/.ghcup/cache/ghcup-<ver>.yaml as fallback (default)
|
||||||
|
# 2. Strict: fail hard
|
||||||
|
meta-mode: Lax # Strict | Lax
|
||||||
|
|
||||||
# Where to get GHC/cabal/hls download info/versions from. For more detailed explanation
|
# Where to get GHC/cabal/hls download info/versions from. For more detailed explanation
|
||||||
# check the 'URLSource' type in the code.
|
# check the 'URLSource' type in the code.
|
||||||
url-source:
|
url-source:
|
||||||
@@ -75,3 +81,41 @@ url-source:
|
|||||||
# AddSource:
|
# AddSource:
|
||||||
# - Right: "file:///home/jule/git/ghcup-hs/ghcup-prereleases.yaml"
|
# - Right: "file:///home/jule/git/ghcup-hs/ghcup-prereleases.yaml"
|
||||||
# - Right: "file:///home/jule/git/ghcup-hs/ghcup-custom.yaml"
|
# - Right: "file:///home/jule/git/ghcup-hs/ghcup-custom.yaml"
|
||||||
|
|
||||||
|
# This is a way to override platform detection, e.g. when you're running
|
||||||
|
# a Ubuntu derivate based on 18.04, you could do:
|
||||||
|
#
|
||||||
|
# platform-override:
|
||||||
|
# arch: A_64
|
||||||
|
# platform:
|
||||||
|
# contents: Ubuntu
|
||||||
|
# tag: Linux
|
||||||
|
# version: '18.04'
|
||||||
|
platform-override: null
|
||||||
|
|
||||||
|
# Support for mirrors. Currently there are 3 hosts you can mirror:
|
||||||
|
# - github.com (for stack and some older HLS versions)
|
||||||
|
# - raw.githubusercontent.com (for the yaml metadata)
|
||||||
|
# - downloads.haskell.org (for everything else)
|
||||||
|
#
|
||||||
|
# E.g. when we have 'https://raw.githubusercontent.com/haskell/ghcup-metadata/master/ghcup-0.0.7.yaml'
|
||||||
|
# and the following mirror config
|
||||||
|
#
|
||||||
|
# "raw.githubusercontent.com":
|
||||||
|
# authority:
|
||||||
|
# host: "mirror.sjtu.edu.cn"
|
||||||
|
# pathPrefix: "ghcup/yaml"
|
||||||
|
#
|
||||||
|
# Then the resulting url will be 'https://mirror.sjtu.edu.cn/ghcup/yaml/haskell/ghcup-metadata/master/ghcup-0.0.7.yaml'
|
||||||
|
mirrors:
|
||||||
|
"github.com":
|
||||||
|
authority:
|
||||||
|
host: "mirror.sjtu.edu.cn"
|
||||||
|
"raw.githubusercontent.com":
|
||||||
|
authority:
|
||||||
|
host: "mirror.sjtu.edu.cn"
|
||||||
|
pathPrefix: "ghcup/yaml"
|
||||||
|
"downloads.haskell.org":
|
||||||
|
authority:
|
||||||
|
host: "mirror.sjtu.edu.cn"
|
||||||
|
|
||||||
|
|||||||
Submodule data/metadata updated: 7d8f7eaf66...9e14e6c736
71
docker/alpine32/Dockerfile
Normal file
71
docker/alpine32/Dockerfile
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
FROM --platform=linux/i386 i386/alpine:3.12
|
||||||
|
|
||||||
|
ENV LANG C.UTF-8
|
||||||
|
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
curl \
|
||||||
|
gcc \
|
||||||
|
g++ \
|
||||||
|
binutils \
|
||||||
|
binutils-gold \
|
||||||
|
coreutils \
|
||||||
|
bsd-compat-headers \
|
||||||
|
gmp-dev \
|
||||||
|
ncurses-dev \
|
||||||
|
libffi-dev \
|
||||||
|
make \
|
||||||
|
xz \
|
||||||
|
tar \
|
||||||
|
perl \
|
||||||
|
bash \
|
||||||
|
diffutils \
|
||||||
|
git \
|
||||||
|
gzip \
|
||||||
|
gnupg && \
|
||||||
|
apk add --no-cache \
|
||||||
|
zlib \
|
||||||
|
zlib-dev \
|
||||||
|
zlib-static \
|
||||||
|
bzip2 \
|
||||||
|
bzip2-dev \
|
||||||
|
bzip2-static \
|
||||||
|
gmp \
|
||||||
|
gmp-dev \
|
||||||
|
openssl-dev \
|
||||||
|
openssl-libs-static \
|
||||||
|
xz \
|
||||||
|
xz-dev \
|
||||||
|
ncurses-static
|
||||||
|
|
||||||
|
ARG GHCUP_VERSION=0.1.18.0
|
||||||
|
ARG GPG_KEY=7784930957807690A66EBDBE3786C5262ECB4A3F
|
||||||
|
|
||||||
|
# install ghcup
|
||||||
|
RUN gpg --batch --keyserver keys.openpgp.org --recv-keys $GPG_KEY && \
|
||||||
|
curl -sSfL -O https://downloads.haskell.org/~ghcup/$GHCUP_VERSION/i386-linux-ghcup-$GHCUP_VERSION && \
|
||||||
|
curl -sSfL -O https://downloads.haskell.org/~ghcup/$GHCUP_VERSION/SHA256SUMS && \
|
||||||
|
curl -sSfL -O https://downloads.haskell.org/~ghcup/$GHCUP_VERSION/SHA256SUMS.sig && \
|
||||||
|
gpg --verify SHA256SUMS.sig SHA256SUMS && \
|
||||||
|
sha256sum -c --ignore-missing SHA256SUMS && \
|
||||||
|
mv i386-linux-ghcup-$GHCUP_VERSION /usr/bin/ghcup && \
|
||||||
|
chmod +x /usr/bin/ghcup && \
|
||||||
|
rm -rf SHA256SUMS SHA256SUMS.sig
|
||||||
|
|
||||||
|
ARG GHC=8.10.7
|
||||||
|
ARG CABAL_INSTALL=3.6.2.0
|
||||||
|
ARG STACK=2.9.1
|
||||||
|
|
||||||
|
ENV GHCUP_CURL_OPTS="--silent"
|
||||||
|
ENV NO_COLOR=1
|
||||||
|
|
||||||
|
# install haskell toolchain
|
||||||
|
RUN ghcup config set gpg-setting GPGStrict && \
|
||||||
|
ghcup --verbose install ghc --isolate=/usr --force ${GHC} && \
|
||||||
|
ghcup --verbose install cabal --isolate=/usr/bin --force ${CABAL_INSTALL} && \
|
||||||
|
find "/usr/lib/ghc-${GHC}/" \( -name "*_p.a" -o -name "*.p_hi" \) -type f -delete && \
|
||||||
|
rm -r "/usr/share/doc/ghc-${GHC}" && \
|
||||||
|
rm -rf /tmp/ghcup* && \
|
||||||
|
ghcup gc -p -s -c -t
|
||||||
|
|
||||||
|
ENV PATH /root/.cabal/bin:/root/.ghcup:/root/.local/bin:$PATH
|
||||||
|
|
||||||
71
docker/alpine64/Dockerfile
Normal file
71
docker/alpine64/Dockerfile
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
FROM alpine:3.12
|
||||||
|
|
||||||
|
ENV LANG C.UTF-8
|
||||||
|
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
curl \
|
||||||
|
gcc \
|
||||||
|
g++ \
|
||||||
|
binutils \
|
||||||
|
binutils-gold \
|
||||||
|
coreutils \
|
||||||
|
bsd-compat-headers \
|
||||||
|
gmp-dev \
|
||||||
|
ncurses-dev \
|
||||||
|
libffi-dev \
|
||||||
|
make \
|
||||||
|
xz \
|
||||||
|
tar \
|
||||||
|
perl \
|
||||||
|
bash \
|
||||||
|
diffutils \
|
||||||
|
git \
|
||||||
|
gzip \
|
||||||
|
gnupg && \
|
||||||
|
apk add --no-cache \
|
||||||
|
zlib \
|
||||||
|
zlib-dev \
|
||||||
|
zlib-static \
|
||||||
|
bzip2 \
|
||||||
|
bzip2-dev \
|
||||||
|
bzip2-static \
|
||||||
|
gmp \
|
||||||
|
gmp-dev \
|
||||||
|
openssl-dev \
|
||||||
|
openssl-libs-static \
|
||||||
|
xz \
|
||||||
|
xz-dev \
|
||||||
|
ncurses-static
|
||||||
|
|
||||||
|
ARG GHCUP_VERSION=0.1.18.0
|
||||||
|
ARG GPG_KEY=7784930957807690A66EBDBE3786C5262ECB4A3F
|
||||||
|
|
||||||
|
# install ghcup
|
||||||
|
RUN gpg --batch --keyserver keys.openpgp.org --recv-keys $GPG_KEY && \
|
||||||
|
curl -sSfL -O https://downloads.haskell.org/~ghcup/$GHCUP_VERSION/x86_64-linux-ghcup-$GHCUP_VERSION && \
|
||||||
|
curl -sSfL -O https://downloads.haskell.org/~ghcup/$GHCUP_VERSION/SHA256SUMS && \
|
||||||
|
curl -sSfL -O https://downloads.haskell.org/~ghcup/$GHCUP_VERSION/SHA256SUMS.sig && \
|
||||||
|
gpg --verify SHA256SUMS.sig SHA256SUMS && \
|
||||||
|
sha256sum -c --ignore-missing SHA256SUMS && \
|
||||||
|
mv x86_64-linux-ghcup-$GHCUP_VERSION /usr/bin/ghcup && \
|
||||||
|
chmod +x /usr/bin/ghcup && \
|
||||||
|
rm -rf SHA256SUMS SHA256SUMS.sig
|
||||||
|
|
||||||
|
ARG GHC=8.10.7
|
||||||
|
ARG CABAL_INSTALL=3.6.2.0
|
||||||
|
ARG STACK=2.9.1
|
||||||
|
|
||||||
|
ENV GHCUP_CURL_OPTS="--silent"
|
||||||
|
ENV NO_COLOR=1
|
||||||
|
|
||||||
|
# install haskell toolchain
|
||||||
|
RUN ghcup config set gpg-setting GPGStrict && \
|
||||||
|
ghcup --verbose install ghc --isolate=/usr --force ${GHC} && \
|
||||||
|
ghcup --verbose install cabal --isolate=/usr/bin --force ${CABAL_INSTALL} && \
|
||||||
|
find "/usr/lib/ghc-${GHC}/" \( -name "*_p.a" -o -name "*.p_hi" \) -type f -delete && \
|
||||||
|
rm -r "/usr/share/doc/ghc-${GHC}" && \
|
||||||
|
rm -rf /tmp/ghcup* && \
|
||||||
|
ghcup gc -p -s -c -t
|
||||||
|
|
||||||
|
ENV PATH /root/.cabal/bin:/root/.ghcup:/root/.local/bin:$PATH
|
||||||
|
|
||||||
64
docker/arm32v7/Dockerfile
Normal file
64
docker/arm32v7/Dockerfile
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
FROM arm32v7/ubuntu:focal
|
||||||
|
|
||||||
|
ENV LANG C.UTF-8
|
||||||
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
ENV TZ=Asia/Singapore
|
||||||
|
|
||||||
|
COPY update_opt.sh /usr/bin/update_opt.sh
|
||||||
|
RUN chmod +x /usr/bin/update_opt.sh
|
||||||
|
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get install -y --no-install-recommends \
|
||||||
|
ca-certificates \
|
||||||
|
curl \
|
||||||
|
dirmngr \
|
||||||
|
g++ \
|
||||||
|
git \
|
||||||
|
gnupg \
|
||||||
|
libsqlite3-dev \
|
||||||
|
libtinfo-dev \
|
||||||
|
libgmp-dev \
|
||||||
|
make \
|
||||||
|
netbase \
|
||||||
|
openssh-client \
|
||||||
|
xz-utils \
|
||||||
|
zlib1g-dev \
|
||||||
|
libnuma-dev libgmp10 libssl-dev liblzma-dev libbz2-dev wget lsb-release software-properties-common apt-transport-https gcc autoconf automake build-essential gzip patchelf tree \
|
||||||
|
llvm-9 clang-9 && \
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
RUN update_opt.sh 9 1
|
||||||
|
|
||||||
|
ARG GHCUP_VERSION=0.1.17.8
|
||||||
|
ARG GPG_KEY=7784930957807690A66EBDBE3786C5262ECB4A3F
|
||||||
|
|
||||||
|
# install ghcup
|
||||||
|
RUN gpg --batch --keyserver keys.openpgp.org --recv-keys $GPG_KEY && \
|
||||||
|
curl -sSfL -O https://downloads.haskell.org/~ghcup/$GHCUP_VERSION/armv7-linux-ghcup-$GHCUP_VERSION && \
|
||||||
|
curl -sSfL -O https://downloads.haskell.org/~ghcup/$GHCUP_VERSION/SHA256SUMS && \
|
||||||
|
curl -sSfL -O https://downloads.haskell.org/~ghcup/$GHCUP_VERSION/SHA256SUMS.sig && \
|
||||||
|
gpg --verify SHA256SUMS.sig SHA256SUMS && \
|
||||||
|
sha256sum -c --ignore-missing SHA256SUMS && \
|
||||||
|
mv armv7-linux-ghcup-$GHCUP_VERSION /usr/bin/ghcup && \
|
||||||
|
chmod +x /usr/bin/ghcup && \
|
||||||
|
rm -rf SHA256SUMS SHA256SUMS.sig
|
||||||
|
|
||||||
|
ARG GHC=8.10.7
|
||||||
|
ARG CABAL_INSTALL=3.6.2.0
|
||||||
|
ARG STACK=2.9.1
|
||||||
|
|
||||||
|
ENV GHCUP_CURL_OPTS="--silent"
|
||||||
|
ENV NO_COLOR=1
|
||||||
|
|
||||||
|
# install haskell toolchain
|
||||||
|
RUN ghcup config set gpg-setting GPGStrict && \
|
||||||
|
ghcup --verbose install ghc --isolate=/usr --force ${GHC} && \
|
||||||
|
ghcup --verbose install cabal --isolate=/usr/bin --force ${CABAL_INSTALL} && \
|
||||||
|
find "/usr/lib/ghc-${GHC}/" \( -name "*_p.a" -o -name "*.p_hi" \) -type f -delete && \
|
||||||
|
rm -r "/usr/share/doc/ghc-${GHC}" && \
|
||||||
|
rm -rf /tmp/ghcup* && \
|
||||||
|
ghcup gc -p -s -c -t
|
||||||
|
|
||||||
|
ENV PATH /root/.cabal/bin:/root/.ghcup/bin:/root/.local/bin:$PATH
|
||||||
|
|
||||||
|
CMD ["ghci"]
|
||||||
36
docker/arm32v7/update_opt.sh
Executable file
36
docker/arm32v7/update_opt.sh
Executable file
@@ -0,0 +1,36 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# update_alternatives.sh
|
||||||
|
|
||||||
|
update_alternatives() {
|
||||||
|
local version=${1}
|
||||||
|
local priority=${2}
|
||||||
|
local master=${3}
|
||||||
|
local slaves=${4}
|
||||||
|
local path=${5}
|
||||||
|
local cmdln
|
||||||
|
|
||||||
|
cmdln="--verbose --install ${path}${master} ${master} ${path}${master}-${version} ${priority}"
|
||||||
|
for slave in ${slaves}; do
|
||||||
|
cmdln="${cmdln} --slave ${path}${slave} ${slave} ${path}${slave}-${version}"
|
||||||
|
done
|
||||||
|
update-alternatives ${cmdln}
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ ${#} -ne 2 ]]; then
|
||||||
|
echo usage: "${0}" clang_version priority
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
version=${1}
|
||||||
|
priority=${2}
|
||||||
|
path="/usr/bin/"
|
||||||
|
|
||||||
|
master="llvm-config"
|
||||||
|
slaves="llvm-addr2line llvm-ar llvm-as llvm-bcanalyzer llvm-bitcode-strip llvm-cat llvm-cfi-verify llvm-cov llvm-c-test llvm-cvtres llvm-cxxdump llvm-cxxfilt llvm-cxxmap llvm-debuginfod llvm-debuginfod-find llvm-diff llvm-dis llvm-dlltool llvm-dwarfdump llvm-dwarfutil llvm-dwp llvm-exegesis llvm-extract llvm-gsymutil llvm-ifs llvm-install-name-tool llvm-jitlink llvm-jitlink-executor llvm-lib llvm-libtool-darwin llvm-link llvm-lipo llvm-lto llvm-lto2 llvm-mc llvm-mca llvm-ml llvm-modextract llvm-mt llvm-nm llvm-objcopy llvm-objdump llvm-omp-device-info llvm-opt-report llvm-otool llvm-pdbutil llvm-PerfectShuffle llvm-profdata llvm-profgen llvm-ranlib llvm-rc llvm-readelf llvm-readobj llvm-reduce llvm-remark-size-diff llvm-rtdyld llvm-sim llvm-size llvm-split llvm-stress llvm-strings llvm-strip llvm-symbolizer llvm-tapi-diff llvm-tblgen llvm-tli-checker llvm-undname llvm-windres llvm-xray"
|
||||||
|
|
||||||
|
update_alternatives "${version}" "${priority}" "${master}" "${slaves}" "${path}"
|
||||||
|
|
||||||
|
master="clang"
|
||||||
|
slaves="analyze-build asan_symbolize bugpoint c-index-test clang++ clang-apply-replacements clang-change-namespace clang-check clang-cl clang-cpp clangd clang-doc clang-extdef-mapping clang-format clang-format-diff clang-include-fixer clang-linker-wrapper clang-move clang-nvlink-wrapper clang-offload-bundler clang-offload-packager clang-offload-wrapper clang-pseudo clang-query clang-refactor clang-rename clang-reorder-fields clang-repl clang-scan-deps clang-tidy count diagtool dsymutil FileCheck find-all-symbols git-clang-format hmaptool hwasan_symbolize intercept-build ld64.lld ld.lld llc lld lldb lldb-argdumper lldb-instr lldb-server lldb-vscode lld-link lli lli-child-target modularize not obj2yaml opt pp-trace run-clang-tidy sancov sanstats scan-build scan-build-py scan-view split-file UnicodeNameMappingGenerator verify-uselistorder wasm-ld yaml2obj yaml-bench"
|
||||||
|
|
||||||
|
update_alternatives "${version}" "${priority}" "${master}" "${slaves}" "${path}"
|
||||||
64
docker/arm64v8/Dockerfile
Normal file
64
docker/arm64v8/Dockerfile
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
FROM arm64v8/ubuntu:focal
|
||||||
|
|
||||||
|
ENV LANG C.UTF-8
|
||||||
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
ENV TZ=Asia/Singapore
|
||||||
|
|
||||||
|
COPY update_opt.sh /usr/bin/update_opt.sh
|
||||||
|
RUN chmod +x /usr/bin/update_opt.sh
|
||||||
|
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get install -y --no-install-recommends \
|
||||||
|
ca-certificates \
|
||||||
|
curl \
|
||||||
|
dirmngr \
|
||||||
|
g++ \
|
||||||
|
git \
|
||||||
|
gnupg \
|
||||||
|
libsqlite3-dev \
|
||||||
|
libtinfo-dev \
|
||||||
|
libgmp-dev \
|
||||||
|
make \
|
||||||
|
netbase \
|
||||||
|
openssh-client \
|
||||||
|
xz-utils \
|
||||||
|
zlib1g-dev \
|
||||||
|
libnuma-dev libgmp10 libssl-dev liblzma-dev libbz2-dev wget lsb-release software-properties-common apt-transport-https gcc autoconf automake build-essential gzip patchelf tree \
|
||||||
|
llvm-9 clang-9 && \
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
RUN update_opt.sh 9 1
|
||||||
|
|
||||||
|
ARG GHCUP_VERSION=0.1.18.0
|
||||||
|
ARG GPG_KEY=7784930957807690A66EBDBE3786C5262ECB4A3F
|
||||||
|
|
||||||
|
# install ghcup
|
||||||
|
RUN gpg --batch --keyserver keys.openpgp.org --recv-keys $GPG_KEY && \
|
||||||
|
curl -sSfL -O https://downloads.haskell.org/~ghcup/$GHCUP_VERSION/aarch64-linux-ghcup-$GHCUP_VERSION && \
|
||||||
|
curl -sSfL -O https://downloads.haskell.org/~ghcup/$GHCUP_VERSION/SHA256SUMS && \
|
||||||
|
curl -sSfL -O https://downloads.haskell.org/~ghcup/$GHCUP_VERSION/SHA256SUMS.sig && \
|
||||||
|
gpg --verify SHA256SUMS.sig SHA256SUMS && \
|
||||||
|
sha256sum -c --ignore-missing SHA256SUMS && \
|
||||||
|
mv aarch64-linux-ghcup-$GHCUP_VERSION /usr/bin/ghcup && \
|
||||||
|
chmod +x /usr/bin/ghcup && \
|
||||||
|
rm -rf SHA256SUMS SHA256SUMS.sig
|
||||||
|
|
||||||
|
ARG GHC=8.10.7
|
||||||
|
ARG CABAL_INSTALL=3.6.2.0
|
||||||
|
ARG STACK=2.9.1
|
||||||
|
|
||||||
|
ENV GHCUP_CURL_OPTS="--silent"
|
||||||
|
ENV NO_COLOR=1
|
||||||
|
|
||||||
|
# install haskell toolchain
|
||||||
|
RUN ghcup config set gpg-setting GPGStrict && \
|
||||||
|
ghcup --verbose install ghc --isolate=/usr --force ${GHC} && \
|
||||||
|
ghcup --verbose install cabal --isolate=/usr/bin --force ${CABAL_INSTALL} && \
|
||||||
|
find "/usr/lib/ghc-${GHC}/" \( -name "*_p.a" -o -name "*.p_hi" \) -type f -delete && \
|
||||||
|
rm -r "/usr/share/doc/ghc-${GHC}" && \
|
||||||
|
rm -rf /tmp/ghcup* && \
|
||||||
|
ghcup gc -p -s -c -t
|
||||||
|
|
||||||
|
ENV PATH /root/.cabal/bin:/root/.ghcup/bin:/root/.local/bin:$PATH
|
||||||
|
|
||||||
|
CMD ["ghci"]
|
||||||
36
docker/arm64v8/update_opt.sh
Executable file
36
docker/arm64v8/update_opt.sh
Executable file
@@ -0,0 +1,36 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# update_alternatives.sh
|
||||||
|
|
||||||
|
update_alternatives() {
|
||||||
|
local version=${1}
|
||||||
|
local priority=${2}
|
||||||
|
local master=${3}
|
||||||
|
local slaves=${4}
|
||||||
|
local path=${5}
|
||||||
|
local cmdln
|
||||||
|
|
||||||
|
cmdln="--verbose --install ${path}${master} ${master} ${path}${master}-${version} ${priority}"
|
||||||
|
for slave in ${slaves}; do
|
||||||
|
cmdln="${cmdln} --slave ${path}${slave} ${slave} ${path}${slave}-${version}"
|
||||||
|
done
|
||||||
|
update-alternatives ${cmdln}
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ ${#} -ne 2 ]]; then
|
||||||
|
echo usage: "${0}" clang_version priority
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
version=${1}
|
||||||
|
priority=${2}
|
||||||
|
path="/usr/bin/"
|
||||||
|
|
||||||
|
master="llvm-config"
|
||||||
|
slaves="llvm-addr2line llvm-ar llvm-as llvm-bcanalyzer llvm-bitcode-strip llvm-cat llvm-cfi-verify llvm-cov llvm-c-test llvm-cvtres llvm-cxxdump llvm-cxxfilt llvm-cxxmap llvm-debuginfod llvm-debuginfod-find llvm-diff llvm-dis llvm-dlltool llvm-dwarfdump llvm-dwarfutil llvm-dwp llvm-exegesis llvm-extract llvm-gsymutil llvm-ifs llvm-install-name-tool llvm-jitlink llvm-jitlink-executor llvm-lib llvm-libtool-darwin llvm-link llvm-lipo llvm-lto llvm-lto2 llvm-mc llvm-mca llvm-ml llvm-modextract llvm-mt llvm-nm llvm-objcopy llvm-objdump llvm-omp-device-info llvm-opt-report llvm-otool llvm-pdbutil llvm-PerfectShuffle llvm-profdata llvm-profgen llvm-ranlib llvm-rc llvm-readelf llvm-readobj llvm-reduce llvm-remark-size-diff llvm-rtdyld llvm-sim llvm-size llvm-split llvm-stress llvm-strings llvm-strip llvm-symbolizer llvm-tapi-diff llvm-tblgen llvm-tli-checker llvm-undname llvm-windres llvm-xray"
|
||||||
|
|
||||||
|
update_alternatives "${version}" "${priority}" "${master}" "${slaves}" "${path}"
|
||||||
|
|
||||||
|
master="clang"
|
||||||
|
slaves="analyze-build asan_symbolize bugpoint c-index-test clang++ clang-apply-replacements clang-change-namespace clang-check clang-cl clang-cpp clangd clang-doc clang-extdef-mapping clang-format clang-format-diff clang-include-fixer clang-linker-wrapper clang-move clang-nvlink-wrapper clang-offload-bundler clang-offload-packager clang-offload-wrapper clang-pseudo clang-query clang-refactor clang-rename clang-reorder-fields clang-repl clang-scan-deps clang-tidy count diagtool dsymutil FileCheck find-all-symbols git-clang-format hmaptool hwasan_symbolize intercept-build ld64.lld ld.lld llc lld lldb lldb-argdumper lldb-instr lldb-server lldb-vscode lld-link lli lli-child-target modularize not obj2yaml opt pp-trace run-clang-tidy sancov sanstats scan-build scan-build-py scan-view split-file UnicodeNameMappingGenerator verify-uselistorder wasm-ld yaml2obj yaml-bench"
|
||||||
|
|
||||||
|
update_alternatives "${version}" "${priority}" "${master}" "${slaves}" "${path}"
|
||||||
@@ -42,8 +42,8 @@ All you wanted to know about GHCup.
|
|||||||
|
|
||||||
## How to help
|
## How to help
|
||||||
|
|
||||||
* if you want to contribute code or documentation, check out the [issue tracker](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues) and the [Development guide](./dev.md)
|
* if you want to contribute code or documentation, check out the [issue tracker](https://github.com/haskell/ghcup-hs/issues) and the [Development guide](./dev.md)
|
||||||
* if you want to propose features or write user feedback, feel free to [open a ticket](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/new?issue)
|
* if you want to propose features or write user feedback, feel free to [open a ticket](https://github.com/haskell/ghcup-hs/issues/new)
|
||||||
* if you want to donate to the project, visit our [opencollective](https://opencollective.com/ghcup#category-CONTRIBUTE) page
|
* if you want to donate to the project, visit our [opencollective](https://opencollective.com/ghcup#category-CONTRIBUTE) page
|
||||||
|
|
||||||
## Design goals
|
## Design goals
|
||||||
@@ -60,6 +60,29 @@ All you wanted to know about GHCup.
|
|||||||
3. handling cabal projects
|
3. handling cabal projects
|
||||||
4. being a stack alternative
|
4. being a stack alternative
|
||||||
|
|
||||||
|
## Distribution policies
|
||||||
|
|
||||||
|
Like most Linux distros and other distribution channels, GHCup also
|
||||||
|
follows certain policies. These are as follows:
|
||||||
|
|
||||||
|
1. The end-user experience is our primary concern
|
||||||
|
- ghcup in CI systems as a use case is a first class citizen
|
||||||
|
2. We strive to collaborate with all maintainers of all the tools we support and maintain a good relationship
|
||||||
|
3. We may fix build system or other distribution bugs in upstream bindists
|
||||||
|
- these are always communicated upstream
|
||||||
|
4. We may even patch source code of supported tools in very rare cases if that is required to ensure that the end-user experience does not break
|
||||||
|
- we'll first try to upstream any such required patch and request a new release to avoid downstream patching
|
||||||
|
- patches will be communicated to the maintainers either way and we'll strive to get their review
|
||||||
|
- they will also be communicated to the end-user
|
||||||
|
- they will be uploaded along with the bindist
|
||||||
|
- we will avoid maintaining long-running downstream patches (currently zero)
|
||||||
|
5. We may add bindists for platforms that upstream does not support
|
||||||
|
- this is currently the case for GHC for e.g. Alpine and possibly FreeBSD in the future
|
||||||
|
- this is currently also the case for stack on darwin M1
|
||||||
|
- we don't guarantee for unofficial bindists that the test suite passes at the moment (this may change in the future)
|
||||||
|
6. We GPG sign all the GHCup metadata as well as the unofficial bindists
|
||||||
|
- any trust issues relating to missing checksums or GPG signatures is a bug and given high priority
|
||||||
|
|
||||||
## How
|
## How
|
||||||
|
|
||||||
Installs a specified GHC version into `~/.ghcup/ghc/<ver>`, and places `ghc-<ver>` symlinks in `~/.ghcup/bin/`.
|
Installs a specified GHC version into `~/.ghcup/ghc/<ver>`, and places `ghc-<ver>` symlinks in `~/.ghcup/bin/`.
|
||||||
@@ -74,13 +97,16 @@ cabal-install/HLS/stack are installed in `~/.ghcup/bin/<tool>-<ver>` and have un
|
|||||||
|
|
||||||
## Known users
|
## Known users
|
||||||
|
|
||||||
* Github actions:
|
* CI:
|
||||||
- [actions/virtual-environments](https://github.com/actions/virtual-environments)
|
- [Github actions/virtual-environments](https://github.com/actions/virtual-environments)
|
||||||
- [haskell/actions/setup](https://github.com/haskell/actions/tree/main/setup)
|
- [Github haskell/actions/setup](https://github.com/haskell/actions/tree/main/setup)
|
||||||
|
- [haskell-ci](https://github.com/haskell-CI/haskell-ci)
|
||||||
* mirrors:
|
* mirrors:
|
||||||
- [sjtug](https://mirror.sjtu.edu.cn/docs/ghcup)
|
- [sjtug](https://mirror.sjtu.edu.cn/docs/ghcup)
|
||||||
* tools:
|
* tools:
|
||||||
- [vabal](https://github.com/Franciman/vabal)
|
- [vscode-haskell](https://github.com/haskell/vscode-haskell)
|
||||||
|
- [nvim-lsp-installer](https://github.com/williamboman/nvim-lsp-installer)
|
||||||
|
- [vabal](https://github.com/Franciman/vabal)
|
||||||
|
|
||||||
## Known problems
|
## Known problems
|
||||||
|
|
||||||
@@ -152,6 +178,11 @@ Windows 7 and Powershell 2.0 aren't well supported at the moment, also see:
|
|||||||
|
|
||||||
## FAQ
|
## FAQ
|
||||||
|
|
||||||
|
### Is ghcup really the main installer?
|
||||||
|
|
||||||
|
This is based on the Haskell survey results from 2022, which show that more
|
||||||
|
than half of survey participants use GHCup: https://taylor.fausak.me/2022/11/18/haskell-survey-results/
|
||||||
|
|
||||||
### Why reimplement stack?
|
### Why reimplement stack?
|
||||||
|
|
||||||
GHCup is not a reimplementation of stack. The only common part is automatic installation of GHC,
|
GHCup is not a reimplementation of stack. The only common part is automatic installation of GHC,
|
||||||
|
|||||||
@@ -69,9 +69,9 @@ Head over to: [https://github.com/haskell/ghcup-metadata#adding-a-new-ghc-versio
|
|||||||
|
|
||||||
### Adding a new CLI command
|
### Adding a new CLI command
|
||||||
|
|
||||||
An example illustration on how to deal with [optparse-applicative](https://hackage.haskell.org/package/optparse-applicative) can be seen here: [https://gitlab.haskell.org/haskell/ghcup-hs/-/commit/c19dd5ee8b2edbaf0336af143f1c75b6f4843e26](https://gitlab.haskell.org/haskell/ghcup-hs/-/commit/c19dd5ee8b2edbaf0336af143f1c75b6f4843e26)
|
An example illustration on how to deal with [optparse-applicative](https://hackage.haskell.org/package/optparse-applicative) can be seen here: [https://github.com/haskell/ghcup-hs/commit/c19dd5ee8b2edbaf0336af143f1c75b6f4843e26](https://github.com/haskell/ghcup-hs/commit/c19dd5ee8b2edbaf0336af143f1c75b6f4843e26)
|
||||||
|
|
||||||
Every subcommand now lives in its own module under [GHCup.OptParse.MyCommand](https://gitlab.haskell.org/haskell/ghcup-hs/-/tree/master/app/ghcup/GHCup/OptParse).
|
Every subcommand now lives in its own module under [GHCup.OptParse.MyCommand](https://github.com/haskell/ghcup-hs/tree/master/app/ghcup/GHCup/OptParse).
|
||||||
|
|
||||||
## Major refactors
|
## Major refactors
|
||||||
|
|
||||||
|
|||||||
250
docs/guide.md
250
docs/guide.md
@@ -4,7 +4,7 @@ This is a more in-depth guide specific to GHCup. `ghcup --help` is your friend.
|
|||||||
|
|
||||||
## Basic usage
|
## Basic usage
|
||||||
|
|
||||||
For the simple interactive TUI (not available on windows), run:
|
For the simple, interactive, text-based user interface (TUI) (not available on windows), run:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
ghcup tui
|
ghcup tui
|
||||||
@@ -50,7 +50,7 @@ For man pages to work you need [man-db](http://man-db.nongnu.org/) as your `man`
|
|||||||
|
|
||||||
## Shell-completion
|
## Shell-completion
|
||||||
|
|
||||||
Shell completions are in [scripts/shell-completions](https://gitlab.haskell.org/haskell/ghcup-hs/-/tree/master/scripts/shell-completions) directory of this repository.
|
Shell completions are in [scripts/shell-completions](https://github.com/haskell/ghcup-hs/tree/master/scripts/shell-completions) directory of this repository.
|
||||||
|
|
||||||
For bash: install `shell-completions/bash`
|
For bash: install `shell-completions/bash`
|
||||||
as e.g. `/etc/bash_completion.d/ghcup` (depending on distro)
|
as e.g. `/etc/bash_completion.d/ghcup` (depending on distro)
|
||||||
@@ -67,10 +67,24 @@ and make sure your bashrc sources the startup script
|
|||||||
# Configuration
|
# Configuration
|
||||||
|
|
||||||
A configuration file can be put in `~/.ghcup/config.yaml`. The default config file
|
A configuration file can be put in `~/.ghcup/config.yaml`. The default config file
|
||||||
explaining all possible configurations can be found in this repo: [config.yaml](https://gitlab.haskell.org/haskell/ghcup-hs/-/blob/master/data/config.yaml).
|
explaining all possible configurations can be found in this repo: [config.yaml](https://github.com/haskell/ghcup-hs/blob/master/data/config.yaml).
|
||||||
|
|
||||||
Partial configuration is fine. Command line options always override the config file settings.
|
Partial configuration is fine. Command line options always override the config file settings.
|
||||||
|
|
||||||
|
## Overriding distro detection
|
||||||
|
|
||||||
|
If you're running e.g. an Ubuntu derivate based on 18.04 and ghcup is picking bindists that
|
||||||
|
don't work well, you could do this in `config.yaml`:
|
||||||
|
|
||||||
|
```yml
|
||||||
|
platform-override:
|
||||||
|
arch: A_64
|
||||||
|
platform:
|
||||||
|
contents: Ubuntu
|
||||||
|
tag: Linux
|
||||||
|
version: '18.04'
|
||||||
|
```
|
||||||
|
|
||||||
## Env variables
|
## Env variables
|
||||||
|
|
||||||
This is the complete list of env variables that change GHCup behavior:
|
This is the complete list of env variables that change GHCup behavior:
|
||||||
@@ -83,6 +97,10 @@ This is the complete list of env variables that change GHCup behavior:
|
|||||||
* `GHCUP_SKIP_UPDATE_CHECK`: Skip the (possibly annoying) update check when you run a command
|
* `GHCUP_SKIP_UPDATE_CHECK`: Skip the (possibly annoying) update check when you run a command
|
||||||
* `CC`/`LD` etc.: full environment is passed to the build system when compiling GHC via GHCup
|
* `CC`/`LD` etc.: full environment is passed to the build system when compiling GHC via GHCup
|
||||||
|
|
||||||
|
On windows, there's additionally:
|
||||||
|
|
||||||
|
* `GHCUP_MSYS2`: Has to point to the root of an existing MSYS2 installation (when installed by GHCup, that's e.g. `C:\ghcup\msys64`). GHCup bootstrap takes care of this usually.
|
||||||
|
|
||||||
### XDG support
|
### XDG support
|
||||||
|
|
||||||
To enable XDG style directories, set the environment variable `GHCUP_USE_XDG_DIRS` to anything.
|
To enable XDG style directories, set the environment variable `GHCUP_USE_XDG_DIRS` to anything.
|
||||||
@@ -133,7 +151,7 @@ url-source:
|
|||||||
OwnSource: "https://some-url/ghcup-0.0.6.yaml"
|
OwnSource: "https://some-url/ghcup-0.0.6.yaml"
|
||||||
```
|
```
|
||||||
|
|
||||||
See [config.yaml](https://gitlab.haskell.org/haskell/ghcup-hs/-/blob/master/data/config.yaml)
|
See [config.yaml](https://github.com/haskell/ghcup-hs/blob/master/data/config.yaml)
|
||||||
for more options.
|
for more options.
|
||||||
|
|
||||||
Alternatively you can do it via a cli switch:
|
Alternatively you can do it via a cli switch:
|
||||||
@@ -184,8 +202,97 @@ url-source:
|
|||||||
- "https://raw.githubusercontent.com/haskell/ghcup-metadata/master/ghcup-prereleases-0.0.7.yaml"
|
- "https://raw.githubusercontent.com/haskell/ghcup-metadata/master/ghcup-prereleases-0.0.7.yaml"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Stack integration
|
||||||
|
|
||||||
|
Stack manages GHC versions internally by default. In order to make it use ghcup installed
|
||||||
|
GHC versions there are two strategies.
|
||||||
|
|
||||||
|
### Strategy 1: System GHC (works on all stack versions)
|
||||||
|
|
||||||
|
You can instruct stack to use "system" GHC versions (whatever is in PATH). To do so,
|
||||||
|
run the following commands:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
stack config set install-ghc false --global
|
||||||
|
stack config set system-ghc true --global
|
||||||
|
```
|
||||||
|
|
||||||
|
### Strategy 2: Stack hooks (new, recommended)
|
||||||
|
|
||||||
|
Since stack 2.9.1 you can customize the installation logic of GHC completely, see [https://docs.haskellstack.org/en/stable/yaml_configuration/#ghc-installation-customisation](https://docs.haskellstack.org/en/stable/yaml_configuration/#ghc-installation-customisation).
|
||||||
|
|
||||||
|
We can use this to simply invoke ghcup whenever stack is trying to install/discover a GHC versions. This
|
||||||
|
is done via placing a shell script at `~/.stack/hooks/ghc-install.sh` and making it executable.
|
||||||
|
|
||||||
|
The ghcup bootstrap script asks you during installation whether you want to install this shell script. You can also
|
||||||
|
install/update it manually like so:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
mkdir -p ~/.stack/hooks/
|
||||||
|
curl https://raw.githubusercontent.com/haskell/ghcup-hs/master/scripts/hooks/stack/ghc-install.sh \
|
||||||
|
> ~/.stack/hooks/ghc-install.sh
|
||||||
|
chmod +x ~/.stack/hooks/ghc-install.sh
|
||||||
|
# hooks are only run when 'system-ghc: false'
|
||||||
|
stack config set system-ghc false --global
|
||||||
|
```
|
||||||
|
|
||||||
|
By default, when the hook fails for whatever reason, stack will fall back to its own installation logic. To disable
|
||||||
|
this, run `stack config set install-ghc false --global`.
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
|
||||||
|
On windows, you may find the following config options useful too:
|
||||||
|
`skip-msys`, `extra-path`, `extra-include-dirs`, `extra-lib-dirs`.
|
||||||
|
|
||||||
|
Also check out: [https://docs.haskellstack.org/en/stable/yaml_configuration](https://docs.haskellstack.org/en/stable/yaml_configuration)
|
||||||
|
|
||||||
# More on installation
|
# More on installation
|
||||||
|
|
||||||
|
## Customisation of the installation scripts
|
||||||
|
|
||||||
|
The scripts offered to install GHCup are available here:
|
||||||
|
|
||||||
|
* [bootstrap-haskell](https://github.com/haskell/ghcup-hs/blob/master/scripts/bootstrap/bootstrap-haskell#L7)
|
||||||
|
for Unix-like operating systems
|
||||||
|
* [bootstrap-haskell.ps1](https://github.com/haskell/ghcup-hs/blob/master/scripts/bootstrap/bootstrap-haskell.ps1)
|
||||||
|
for Windows (PowerShell). This will, in turn, run the final bootstrap script
|
||||||
|
(by default, that for the Unix-like operating systems).
|
||||||
|
|
||||||
|
The effect of the scripts can be customised by setting one or more
|
||||||
|
`BOOTSTRAP_HASKELL_*` environment variables (as set out in the first script)
|
||||||
|
and, in the case of Windows, by specifying parameters (as set out in the
|
||||||
|
PowerShell script).
|
||||||
|
|
||||||
|
For example, you can toggle:
|
||||||
|
|
||||||
|
* non-interactive installation
|
||||||
|
* a more verbose installation
|
||||||
|
* whether to install only GHCup (and, on Windows, MSYS2)
|
||||||
|
* not to trigger the upgrade of GHCup
|
||||||
|
* whether to install the latest version of HLS
|
||||||
|
* whether to install the latest version of Stack
|
||||||
|
* whether to respect the XDG Base Directory Specification
|
||||||
|
* whether to adjust (prepend) the PATH in `bashrc`
|
||||||
|
* on Windows, whether to adjust MINGW paths in `cabal.config`
|
||||||
|
|
||||||
|
You can also specify:
|
||||||
|
|
||||||
|
* the GHC version to install
|
||||||
|
* the Cabal version to install
|
||||||
|
* which downloader to use (the default is `curl`)
|
||||||
|
* the base URL for the download of the GHCup binary distribution
|
||||||
|
|
||||||
|
On Windows, you can also use the parameters to:
|
||||||
|
|
||||||
|
* toggle whether to overwrite a previous installation
|
||||||
|
* specify the GHCup installation root directory
|
||||||
|
* specify the Cabal root directory
|
||||||
|
* specify the directory of an existing installation of MSYS2 (for example,
|
||||||
|
the one supplied by Stack)
|
||||||
|
* specify the URL of the final bootstrap script
|
||||||
|
* toggle whether to run the final bootstrap script via `bash` (instead of in a
|
||||||
|
new MSYS2 shell)
|
||||||
|
|
||||||
## Installing custom bindists
|
## Installing custom bindists
|
||||||
|
|
||||||
There are a couple of good use cases to install custom bindists:
|
There are a couple of good use cases to install custom bindists:
|
||||||
@@ -193,7 +300,8 @@ There are a couple of good use cases to install custom bindists:
|
|||||||
1. manually built bindists (e.g. with patches)
|
1. manually built bindists (e.g. with patches)
|
||||||
- example: `ghcup install ghc -u 'file:///home/mearwald/tmp/ghc-eff-patches/ghc-8.10.2-x86_64-deb10-linux.tar.xz' 8.10.2-eff`
|
- example: `ghcup install ghc -u 'file:///home/mearwald/tmp/ghc-eff-patches/ghc-8.10.2-x86_64-deb10-linux.tar.xz' 8.10.2-eff`
|
||||||
2. GHC head CI bindists
|
2. GHC head CI bindists
|
||||||
- example: `ghcup install ghc -u 'https://gitlab.haskell.org/api/v4/projects/1/jobs/artifacts/master/raw/ghc-x86_64-fedora27-linux.tar.xz?job=validate-x86_64-linux-fedora27' head`
|
- example specifying a branch (`master`): `ghcup install ghc -u 'https://gitlab.haskell.org/ghc/ghc/-/jobs/artifacts/master/raw/ghc-x86_64-linux-fedora33-release.tar.xz?job=x86_64-linux-fedora33-release' head`
|
||||||
|
- example specifying a job id (`1129565`): `ghcup install ghc -u ' https://gitlab.haskell.org/api/v4/projects/1/jobs/1129565/artifacts/ghc-x86_64-linux-alpine3_12-validate+fully_static.tar.xz' mr7847`
|
||||||
3. DWARF bindists
|
3. DWARF bindists
|
||||||
- example: `ghcup install ghc -u 'https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-x86_64-deb10-linux-dwarf.tar.xz' 8.10.2-dwarf`
|
- example: `ghcup install ghc -u 'https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-x86_64-deb10-linux-dwarf.tar.xz' 8.10.2-dwarf`
|
||||||
|
|
||||||
@@ -202,18 +310,78 @@ and produce the binaries `ghc-8.10.2-eff` and `ghc-head` respectively.
|
|||||||
GHCup always needs to know which version the bindist corresponds to (this is not automatically
|
GHCup always needs to know which version the bindist corresponds to (this is not automatically
|
||||||
detected).
|
detected).
|
||||||
|
|
||||||
## Compiling GHC from source
|
## Compiling from source
|
||||||
|
|
||||||
|
### GHC
|
||||||
|
|
||||||
Compiling from source is supported for both source tarballs and arbitrary git refs. See `ghcup compile ghc --help`
|
Compiling from source is supported for both source tarballs and arbitrary git refs. See `ghcup compile ghc --help`
|
||||||
for a list of all available options.
|
for a list of all available options.
|
||||||
|
|
||||||
If you need to overwrite the existing `build.mk`, check the default files
|
If you need to overwrite the existing `build.mk`, check the default files
|
||||||
in [data/build_mk](https://gitlab.haskell.org/haskell/ghcup-hs/-/tree/master/data/build_mk), copy them somewhere, adjust them and
|
in [data/build_mk](https://github.com/haskell/ghcup-hs/tree/master/data/build_mk), copy them somewhere, adjust them and
|
||||||
pass `--config path/to/build.mk` to `ghcup compile ghc`.
|
pass `--config path/to/build.mk` to `ghcup compile ghc`.
|
||||||
Common `build.mk` options are explained [here](https://gitlab.haskell.org/ghc/ghc/-/wikis/building/using#build-configuration).
|
Common `build.mk` options are explained [here](https://gitlab.haskell.org/ghc/ghc/-/wikis/building/using#build-configuration).
|
||||||
|
|
||||||
Make sure your system meets all the [prerequisites](https://gitlab.haskell.org/ghc/ghc/-/wikis/building/preparation).
|
Make sure your system meets all the [prerequisites](https://gitlab.haskell.org/ghc/ghc/-/wikis/building/preparation).
|
||||||
|
|
||||||
|
### HLS
|
||||||
|
|
||||||
|
There are 3 main ways to compile HLS from source.
|
||||||
|
|
||||||
|
1. from hackage (should have up to date version bounds)
|
||||||
|
- `ghcup compile hls --version 1.7.0.0 --ghc 9.2.3`
|
||||||
|
2. from git (allows to build latest sources and PRs)
|
||||||
|
- `ghcup compile hls --git-ref master --ghc 9.2.3`
|
||||||
|
- `ghcup compile hls --git-ref a32db0b --ghc 9.2.3`
|
||||||
|
- `ghcup compile hls --git-ref 1.7.0.0 --ghc 9.2.3`
|
||||||
|
3. from source distribution that's packaged during release from the corresponding git sources
|
||||||
|
- `ghcup compile hls --source-dist 1.7.0.0 --ghc 9.2.3`
|
||||||
|
|
||||||
|
All these use `cabal v2-install` under the hood, so all build components are cached.
|
||||||
|
You can pass arbitrary arguments to cabal, e.g. set the index state like so:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
ghcup compile hls --git-ref master --ghc 9.2.3 -- --index-state=2022-06-12T00:00:00Z --allow-newer
|
||||||
|
```
|
||||||
|
|
||||||
|
You can pass `--ghc <ver>` multiple times to install for many GHCs at once.
|
||||||
|
|
||||||
|
When building from git sources, ghcup will auto-detect the HLS version that the git commit corresponds to
|
||||||
|
from the `haskell-language-server.cabal` file. This version might not have been updated since the last release.
|
||||||
|
If you want to avoid overwriting the existing installed HLS version, you can instruct ghcup to use `git describe`
|
||||||
|
to set the HLS version instead:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
ghcup compile hls --git-ref master --ghc 9.2.3 --git-describe-version
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also set the version explicitly:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
ghcup compile hls --git-ref master --ghc 9.2.3 --overwrite-version 1.7.0.0-p1
|
||||||
|
```
|
||||||
|
|
||||||
|
To instruct cabal to run `cabal update` before building, run `ghcup compile hls --version 1.7.0.0 --ghc 9.2.3 --cabal-update`
|
||||||
|
|
||||||
|
As always, check `ghcup compile hls --help`.
|
||||||
|
|
||||||
|
#### Updating HLS for a new GHC version
|
||||||
|
|
||||||
|
First try to build from hackage with some tricks:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
ghcup compile hls --version 1.7.0.0 --ghc 9.2.4 --cabal-update -- --allow-newer --index-state=2022-06-12T00:00:00Z
|
||||||
|
```
|
||||||
|
|
||||||
|
This augments the currently installed 1.7.0.0 official bindists in ghcup with new GHC versions support.
|
||||||
|
|
||||||
|
If that fails (since `--allow-newer` is quite brutal), you can install from HLS master branch (which may contain new fixes) like so:
|
||||||
|
```
|
||||||
|
ghcup compile hls --git-ref master --git-describe-version --ghc 8.10.7 --ghc 9.2.4 --cabal-update
|
||||||
|
```
|
||||||
|
|
||||||
|
This however will create a new HLS version in ghcup, e.g. `1.7.0.0-105-gdc682ba1`, for both 8.10.7 and 9.2.4. If you want to switch back to the official bindists, run `ghcup set hls 1.7.0.0`.
|
||||||
|
|
||||||
### Cross support
|
### Cross support
|
||||||
|
|
||||||
ghcup can compile and install a cross GHC for any target. However, this
|
ghcup can compile and install a cross GHC for any target. However, this
|
||||||
@@ -241,41 +409,43 @@ You need to use the `--isolate` or `-i` flag followed by the directory path.
|
|||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
1. install an isolated GHC version at location /home/user/isolated_dir/ghc/
|
1. install an isolated GHC version at location /home/user/isolated_dir/ghc/
|
||||||
- `ghcup install ghc 8.10.5 --isolate /home/user/isolated_dir/ghc`
|
- `ghcup install ghc 8.10.5 --isolate /home/user/isolated_dir/ghc`
|
||||||
|
|
||||||
2. isolated install Cabal at a location you desire
|
2. isolated install Cabal at a location you desire
|
||||||
- `ghcup install cabal --isolate /home/username/my_isolated_dir/`
|
- `ghcup install cabal --isolate /home/username/my_isolated_dir/`
|
||||||
|
|
||||||
3. do an isolated install with a custom bindist
|
3. do an isolated install with a custom bindist
|
||||||
- `ghcup install ghc --isolate /home/username/my_isolated_dir/ -u 'https://gitlab.haskell.org/api/v4/projects/1/jobs/artifacts/master/raw/ghc-x86_64-fedora27-linux.tar.xz?job=validate-x86_64-linux-fedora27' head`
|
- `ghcup install ghc --isolate /home/username/my_isolated_dir/ -u 'https://gitlab.haskell.org/ghc/ghc/-/jobs/artifacts/master/raw/ghc-x86_64-linux-fedora33-release.tar.xz?job=x86_64-linux-fedora33-release' head`
|
||||||
|
|
||||||
4. isolated install HLS
|
4. isolated install HLS
|
||||||
- `ghcup install hls --isolate /home/username/dir/hls/`
|
- `ghcup install hls --isolate /home/username/dir/hls/`
|
||||||
|
|
||||||
5. you can even compile ghc to an isolated location.
|
5. you can even compile ghc to an isolated location.
|
||||||
- `ghcup compile ghc -j 4 -v 9.0.1 -b 8.10.5 -i /home/username/my/dir/ghc`
|
- `ghcup compile ghc -j 4 -v 9.0.1 -b 8.10.5 -i /home/username/my/dir/ghc`
|
||||||
|
|
||||||
## Continuous integration
|
## Continuous integration
|
||||||
|
|
||||||
On windows, ghcup can be installed automatically on a CI runner non-interactively like so:
|
On Windows, GHCup can be installed automatically on a CI runner
|
||||||
|
non-interactively, as below. The paramaters to the PowerShell script are
|
||||||
|
specified positionally, after `-ArgumentList`:
|
||||||
|
|
||||||
```ps
|
```ps
|
||||||
Set-ExecutionPolicy Bypass -Scope Process -Force;[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072;Invoke-Command -ScriptBlock ([ScriptBlock]::Create((Invoke-WebRequest https://www.haskell.org/ghcup/sh/bootstrap-haskell.ps1 -UseBasicParsing))) -ArgumentList $false,$true,$true,$false,$false,$false,$false,"C:\"
|
$ErrorActionPreference = 'Stop';Set-ExecutionPolicy Bypass -Scope Process -Force;[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072;try { Invoke-Command -ScriptBlock ([ScriptBlock]::Create((Invoke-WebRequest https://www.haskell.org/ghcup/sh/bootstrap-haskell.ps1 -UseBasicParsing))) -ArgumentList $false,$true,$true,$false,$false,$false,$false,"C:\" } catch { Write-Error $_ }
|
||||||
```
|
```
|
||||||
|
|
||||||
|
`$ErrorActionPreference = 'Stop'` here acts like `set -e` and stops execution if ghcup installation fails.
|
||||||
|
|
||||||
On linux/darwin/freebsd, run the following on your runner:
|
On linux/darwin/freebsd, run the following on your runner:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | BOOTSTRAP_HASKELL_NONINTERACTIVE=1 BOOTSTRAP_HASKELL_MINIMAL=1 sh
|
curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | BOOTSTRAP_HASKELL_NONINTERACTIVE=1 BOOTSTRAP_HASKELL_MINIMAL=1 sh
|
||||||
```
|
```
|
||||||
|
|
||||||
This will just install `ghcup` and on windows additionally `msys2`.
|
This will just install `ghcup` and on Windows additionally MSYS2.
|
||||||
|
|
||||||
For the full list of env variables and parameters to tweak the script behavior, see:
|
See the installation scripts referred to above for the full list of environment
|
||||||
|
variables and, in the case of Windows, parameters to tweak the script behavior.
|
||||||
* [bootstrap-haskell for linux/darwin/freebsd](https://gitlab.haskell.org/haskell/ghcup-hs/-/blob/master/scripts/bootstrap/bootstrap-haskell#L7)
|
|
||||||
* [bootstrap-haskell.ps1 for windows](https://gitlab.haskell.org/haskell/ghcup-hs/-/blob/master/scripts/bootstrap/bootstrap-haskell.ps1#L17)
|
|
||||||
|
|
||||||
### github workflows
|
### github workflows
|
||||||
|
|
||||||
@@ -287,10 +457,11 @@ GHCup itself is also pre-installed on all platforms, but may use non-standard in
|
|||||||
GHCup supports verifying the GPG signature of the metadata file. The metadata file then contains SHA256 hashes of all downloads, so
|
GHCup supports verifying the GPG signature of the metadata file. The metadata file then contains SHA256 hashes of all downloads, so
|
||||||
this is cryptographically secure.
|
this is cryptographically secure.
|
||||||
|
|
||||||
First, obtain the gpg key:
|
First, obtain the gpg keys:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
gpg --batch --keyserver keys.openpgp.org --recv-keys 7784930957807690A66EBDBE3786C5262ECB4A3F
|
gpg --batch --keyserver keys.openpgp.org --recv-keys 7784930957807690A66EBDBE3786C5262ECB4A3F
|
||||||
|
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys FE5AB6C91FEA597C3B31180B73EDE9E8CFBAEF01
|
||||||
```
|
```
|
||||||
|
|
||||||
Then verify the gpg key in one of these ways:
|
Then verify the gpg key in one of these ways:
|
||||||
@@ -309,7 +480,7 @@ gpg-setting: GPGLax # GPGStrict | GPGLax | GPGNone
|
|||||||
|
|
||||||
In `GPGStrict` mode, ghcup will fail if verification fails. In `GPGLax` mode it will just print a warning.
|
In `GPGStrict` mode, ghcup will fail if verification fails. In `GPGLax` mode it will just print a warning.
|
||||||
You can also pass the mode via `ghcup --gpg <strict|lax|none>`.
|
You can also pass the mode via `ghcup --gpg <strict|lax|none>`.
|
||||||
|
|
||||||
# Tips and tricks
|
# Tips and tricks
|
||||||
|
|
||||||
## ghcup run
|
## ghcup run
|
||||||
@@ -323,3 +494,34 @@ ghcup run --ghc 8.10.7 --cabal latest --hls latest --stack latest --install -- c
|
|||||||
```
|
```
|
||||||
|
|
||||||
This will execute vscode with GHC set to 8.10.7 and all other tools to their latest version.
|
This will execute vscode with GHC set to 8.10.7 and all other tools to their latest version.
|
||||||
|
|
||||||
|
# Troubleshooting
|
||||||
|
|
||||||
|
## Script immediately exits on windows
|
||||||
|
|
||||||
|
There are two possible reasons:
|
||||||
|
|
||||||
|
1. your company blocks the script (some have a whitelist)... ask your administrator
|
||||||
|
2. your Antivirus or Windows Defender interfere with the installation. Disable them temporarily.
|
||||||
|
|
||||||
|
## C compiler cannot create executables
|
||||||
|
|
||||||
|
### Darwin
|
||||||
|
|
||||||
|
You need to update your XCode command line tools, e.g. [like this](https://stackoverflow.com/questions/34617452/how-to-update-xcode-from-command-line).
|
||||||
|
|
||||||
|
## Certificate authority errors (curl)
|
||||||
|
|
||||||
|
If your certificates are outdated or improperly configured, curl may be unable
|
||||||
|
to download ghcup.
|
||||||
|
|
||||||
|
There are two known workarounds:
|
||||||
|
|
||||||
|
1. Tell curl to ignore certificate errors (dangerous): `curl -k https://raw.githubusercontent.com/haskell/ghcup-hs/master/scripts/bootstrap/bootstrap-haskell | GHCUP_CURL_OPTS="-k" sh`
|
||||||
|
2. Try to use wget instead: `wget -O /dev/stdout https://raw.githubusercontent.com/haskell/ghcup-hs/master/scripts/bootstrap/bootstrap-haskell | BOOTSTRAP_HASKELL_DOWNLOADER=wget sh`
|
||||||
|
|
||||||
|
On windows, you can disable curl like so:
|
||||||
|
|
||||||
|
```pwsh
|
||||||
|
Set-ExecutionPolicy Bypass -Scope Process -Force;[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072;try { Invoke-Command -ScriptBlock ([ScriptBlock]::Create((Invoke-WebRequest https://www.haskell.org/ghcup/sh/bootstrap-haskell.ps1 -UseBasicParsing))) -ArgumentList $true,$false,$false,$false,$false,$false,$false,"","","","",$true } catch { Write-Error $_ }
|
||||||
|
```
|
||||||
|
|||||||
@@ -13,10 +13,10 @@ hide:
|
|||||||
<h1>GHCup</h1>
|
<h1>GHCup</h1>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<p class="ghcup-intro">GHCup is an installer for the general purpose language <a href="https://www.haskell.org">Haskell</a>.</p>
|
<p class="ghcup-intro">GHCup is the main installer for the general purpose language <a href="https://www.haskell.org">Haskell</a>.</p>
|
||||||
|
|
||||||
<div class="text-center main-buttons">
|
<div class="text-center main-buttons">
|
||||||
<a href="install/" class="btn btn-primary" role="button">Getting Started</a>
|
<a href="install/" class="btn btn-primary" role="button">Installation</a>
|
||||||
<a href="steps/" class="btn btn-primary" role="button">First steps</a>
|
<a href="steps/" class="btn btn-primary" role="button">First steps</a>
|
||||||
<a href="guide/" class="btn btn-primary" role="button">User Guide</a>
|
<a href="guide/" class="btn btn-primary" role="button">User Guide</a>
|
||||||
</div>
|
</div>
|
||||||
@@ -35,7 +35,7 @@ hide:
|
|||||||
<span>
|
<span>
|
||||||
</span>
|
</span>
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
<a href="https://gitlab.haskell.org/haskell/ghcup-hs/-/blob/master/scripts/bootstrap/bootstrap-haskell" target="_blank">What does this do?</a> <b> · </b> <a href="https://www.haskell.org/ghcup/install/#manual-install">I don't like curl | sh</a> <div class="show-all-platforms"><b> · </b> <a class="show-all-platforms-button" href="#">Show all platforms</a></div></p>
|
<a href="https://github.com/haskell/ghcup-hs/blob/master/scripts/bootstrap/bootstrap-haskell" target="_blank">What does this do?</a> <b> · </b> <a href="https://www.haskell.org/ghcup/install/#manual-installation">I don't like curl | sh</a> <div class="show-all-platforms"><b> · </b> <a class="show-all-platforms-button" href="#">Show all platforms</a></div></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -45,19 +45,19 @@ hide:
|
|||||||
|
|
||||||
<div class="command-button">
|
<div class="command-button">
|
||||||
<pre>
|
<pre>
|
||||||
<span class="ghcup-command" id="ghcup-command-windows">Set-ExecutionPolicy Bypass -Scope Process -Force;[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072;Invoke-Command -ScriptBlock ([ScriptBlock]::Create((Invoke-WebRequest https://www.haskell.org/ghcup/sh/bootstrap-haskell.ps1 -UseBasicParsing))) -ArgumentList $true
|
<span class="ghcup-command" id="ghcup-command-windows">Set-ExecutionPolicy Bypass -Scope Process -Force;[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; try { Invoke-Command -ScriptBlock ([ScriptBlock]::Create((Invoke-WebRequest https://www.haskell.org/ghcup/sh/bootstrap-haskell.ps1 -UseBasicParsing))) -ArgumentList $true } catch { Write-Error $_ }
|
||||||
</span>
|
</span>
|
||||||
</pre>
|
</pre>
|
||||||
<button class="btn" onclick="copyToClipboardWin()" id="ghcup-windows-button"><i class="fa fa-copy"></i></button>
|
<button class="btn" onclick="copyToClipboardWin()" id="ghcup-windows-button"><i class="fa fa-copy"></i></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
<a href="https://gitlab.haskell.org/haskell/ghcup-hs/-/blob/master/scripts/bootstrap/bootstrap-haskell.ps1" target="_blank">What does this do?</a> <b> · </b> <a href="https://www.haskell.org/ghcup/install/#manual-install">I don't like curl | sh</a> <div class="show-all-platforms"><b> · </b> <a class="show-all-platforms-button" href="#">Show all platforms</a></div></p>
|
<a href="https://github.com/haskell/ghcup-hs/blob/master/scripts/bootstrap/bootstrap-haskell.ps1" target="_blank">What does this do?</a> <b> · </b> <a href="https://www.haskell.org/ghcup/install/#manual-installation">I don't like curl | sh</a> <div class="show-all-platforms"><b> · </b> <a class="show-all-platforms-button" href="#">Show all platforms</a></div></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<p id="help" class="ghcup-help">
|
<p id="help" class="ghcup-help">
|
||||||
Need help? Ask on
|
Need help? Check the <a href="guide/#troubleshooting">Troubleshooting section</a> or ask on
|
||||||
<span>
|
<span>
|
||||||
<a href="https://kiwiirc.com/nextclient/irc.libera.chat/?nick=Guest%7C?#haskell,#haskell-ghcup">
|
<a href="https://kiwiirc.com/nextclient/irc.libera.chat/?nick=Guest%7C?#haskell,#haskell-ghcup">
|
||||||
<img src="irc.svg" alt="" />
|
<img src="irc.svg" alt="" />
|
||||||
@@ -77,7 +77,7 @@ hide:
|
|||||||
</span>
|
</span>
|
||||||
or
|
or
|
||||||
<span>
|
<span>
|
||||||
<a href="https://gitlab.haskell.org/haskell/ghcup-hs/issues">
|
<a href="https://github.com/haskell/ghcup-hs/issues">
|
||||||
report a bug
|
report a bug
|
||||||
<img src="Octicons-bug.svg" alt="" />
|
<img src="Octicons-bug.svg" alt="" />
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
148
docs/install.md
148
docs/install.md
@@ -1,10 +1,10 @@
|
|||||||
# Getting started
|
# Installation
|
||||||
|
|
||||||
GHCup makes it easy to install specific versions of GHC on GNU/Linux,
|
GHCup makes it easy to install specific versions of GHC on GNU/Linux,
|
||||||
macOS (aka Darwin), FreeBSD and Windows and can also bootstrap a fresh [Haskell developer environment](./install/#supported-tools) from scratch.
|
macOS (aka Darwin), FreeBSD and Windows and can also bootstrap a fresh [Haskell developer environment](./#supported-tools) from scratch.
|
||||||
It follows the UNIX philosophy of [do one thing and do it well](https://en.wikipedia.org/wiki/Unix_philosophy#Do_One_Thing_and_Do_It_Well). Similar in scope to [rustup](https://github.com/rust-lang-nursery/rustup.rs), [pyenv](https://github.com/pyenv/pyenv) and [jenv](http://www.jenv.be).
|
It follows the UNIX philosophy of [do one thing and do it well](https://en.wikipedia.org/wiki/Unix_philosophy#Do_One_Thing_and_Do_It_Well). Similar in scope to [rustup](https://github.com/rust-lang-nursery/rustup.rs), [pyenv](https://github.com/pyenv/pyenv) and [jenv](http://www.jenv.be).
|
||||||
|
|
||||||
## Installation
|
## How to install
|
||||||
|
|
||||||
The following commands will download the `ghcup` binary into `~/.ghcup/bin` (or `C:\ghcup\bin` on windows) and then
|
The following commands will download the `ghcup` binary into `~/.ghcup/bin` (or `C:\ghcup\bin` on windows) and then
|
||||||
run it to interactively install the [Haskell Toolchain](#supported-tools). These commands should be run as **non-root/non-admin
|
run it to interactively install the [Haskell Toolchain](#supported-tools). These commands should be run as **non-root/non-admin
|
||||||
@@ -19,12 +19,12 @@ curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh
|
|||||||
For Windows, run this in a PowerShell session:
|
For Windows, run this in a PowerShell session:
|
||||||
|
|
||||||
```psh
|
```psh
|
||||||
Set-ExecutionPolicy Bypass -Scope Process -Force;[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072;Invoke-Command -ScriptBlock ([ScriptBlock]::Create((Invoke-WebRequest https://www.haskell.org/ghcup/sh/bootstrap-haskell.ps1 -UseBasicParsing))) -ArgumentList $true
|
Set-ExecutionPolicy Bypass -Scope Process -Force;[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; try { Invoke-Command -ScriptBlock ([ScriptBlock]::Create((Invoke-WebRequest https://www.haskell.org/ghcup/sh/bootstrap-haskell.ps1 -UseBasicParsing))) -ArgumentList $true } catch { Write-Error $_ }
|
||||||
```
|
```
|
||||||
|
|
||||||
There's also a [youtube video](https://www.youtube.com/watch?v=bB4fmQiUYPw) explaining installation on windows.
|
There's also a [youtube video](https://www.youtube.com/watch?v=bB4fmQiUYPw) explaining installation on windows.
|
||||||
|
|
||||||
If you want to know what these scripts do, check out the [source code at the repository](https://gitlab.haskell.org/haskell/ghcup-hs/-/tree/master/scripts/bootstrap). Advanced users may want to perform a [manual installation](#manual-install) and GPG verify the binaries.
|
If you want to know what these scripts do, check out the [source code at the repository](https://github.com/haskell/ghcup-hs/tree/master/scripts/bootstrap). Advanced users may want to perform a [manual installation](#manual-installation) and GPG verify the binaries.
|
||||||
|
|
||||||
### Which versions get installed?
|
### Which versions get installed?
|
||||||
|
|
||||||
@@ -34,6 +34,53 @@ GHCup has two main channels for every tool: **recommended** and **latest**. By d
|
|||||||
|
|
||||||
Also see [tags and shortcuts](../guide/#tags-and-shortcuts) for more information.
|
Also see [tags and shortcuts](../guide/#tags-and-shortcuts) for more information.
|
||||||
|
|
||||||
|
## System requirements
|
||||||
|
|
||||||
|
### Linux Debian
|
||||||
|
|
||||||
|
The following distro packages are required: `build-essential curl libffi-dev libffi6 libgmp-dev libgmp10 libncurses-dev libncurses5 libtinfo5`
|
||||||
|
|
||||||
|
### Linux Ubuntu
|
||||||
|
|
||||||
|
The following distro packages are required: `build-essential curl libffi-dev libffi6 libgmp-dev libgmp10 libncurses-dev libncurses5 libtinfo5`
|
||||||
|
|
||||||
|
### Linux Fedora
|
||||||
|
|
||||||
|
The following distro packages are required: `gcc gcc-c++ gmp gmp-devel make ncurses ncurses-compat-libs xz perl`
|
||||||
|
|
||||||
|
### Linux Mageia
|
||||||
|
|
||||||
|
The following distro packages are required: `curl gcc gcc-c++ gmp libffi-devel libffi7 libgmp-devel libgmp10 make libncurses-devel libncurses5 xz perl`
|
||||||
|
|
||||||
|
### Linux CentOS
|
||||||
|
|
||||||
|
The following distro packages are required: `gcc gcc-c++ gmp gmp-devel make ncurses ncurses-compat-libs xz perl`
|
||||||
|
|
||||||
|
### Linux Alpine
|
||||||
|
|
||||||
|
The following distro packages are required: `binutils-gold curl gcc g++ gmp-dev libc-dev libffi-dev make musl-dev ncurses-dev perl tar xz`
|
||||||
|
|
||||||
|
### Linux VoidLinux
|
||||||
|
|
||||||
|
The following distro packages are required: `gcc gmp curl coreutils xz ncurses make ncurses-libtinfo-libs perl tar`
|
||||||
|
|
||||||
|
### Linux (generic)
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
### Darwin
|
||||||
|
|
||||||
|
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.
|
||||||
|
On Darwin M1 you might also need a working llvm installed (e.g. via brew) and have the toolchain exposed in PATH.
|
||||||
|
|
||||||
|
### FreeBSD
|
||||||
|
|
||||||
|
The following distro packages are required: `curl gcc gmp gmake ncurses perl5 libffi libiconv`
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
|
||||||
|
On Windows, msys2 should already have been set up during the installation, so most users should just proceed. If you are installing manually, make sure to have a working mingw64 toolchain and shell.
|
||||||
|
|
||||||
## Next steps
|
## Next steps
|
||||||
|
|
||||||
1. Follow the [First steps guide](../steps) on how to build a "Hello world" program, use `ghc`, run an interactive REPL and create a Haskell project
|
1. Follow the [First steps guide](../steps) on how to build a "Hello world" program, use `ghc`, run an interactive REPL and create a Haskell project
|
||||||
@@ -55,11 +102,17 @@ GHCup supports the following tools, which are also known as the **Haskell Toolch
|
|||||||
<table>
|
<table>
|
||||||
<thead><tr><th>GHC Version</th><th>Tags</th></tr></thead>
|
<thead><tr><th>GHC Version</th><th>Tags</th></tr></thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr><td>9.2.2</td><td><span style="color:blue">latest</span>, base-4.16.1.0</td></tr>
|
<tr><td>9.4.3</td><td><span style="color:blue">latest</span>, base-4.17.0.0</td></tr>
|
||||||
|
<tr><td>9.4.2</td><td>base-4.17.0.0</td></tr>
|
||||||
|
<tr><td>9.4.1</td><td>base-4.17.0.0</td></tr>
|
||||||
|
<tr><td>9.2.5</td><td><span style="color:green">recommended</span>, base-4.16.4.0</td></tr>
|
||||||
|
<tr><td>9.2.4</td><td>base-4.16.3.0</td></tr>
|
||||||
|
<tr><td>9.2.3</td><td>base-4.16.2.0</td></tr>
|
||||||
|
<tr><td>9.2.2</td><td>base-4.16.1.0</td></tr>
|
||||||
<tr><td>9.2.1</td><td>base-4.16.0.0</td></tr>
|
<tr><td>9.2.1</td><td>base-4.16.0.0</td></tr>
|
||||||
<tr><td>9.0.2</td><td>base-4.15.1.0</td></tr>
|
<tr><td>9.0.2</td><td>base-4.15.1.0</td></tr>
|
||||||
<tr><td>9.0.1</td><td>base-4.15.0.0</td></tr>
|
<tr><td>9.0.1</td><td>base-4.15.0.0</td></tr>
|
||||||
<tr><td>8.10.7</td><td><span style="color:green">recommended</span>, base-4.14.3.0</td></tr>
|
<tr><td>8.10.7</td><td>base-4.14.3.0</td></tr>
|
||||||
<tr><td>8.10.6</td><td>base-4.14.3.0</td></tr>
|
<tr><td>8.10.6</td><td>base-4.14.3.0</td></tr>
|
||||||
<tr><td>8.10.5</td><td>base-4.14.2.0</td></tr>
|
<tr><td>8.10.5</td><td>base-4.14.2.0</td></tr>
|
||||||
<tr><td>8.10.4</td><td>base-4.14.1.0</td></tr>
|
<tr><td>8.10.4</td><td>base-4.14.1.0</td></tr>
|
||||||
@@ -90,7 +143,8 @@ GHCup supports the following tools, which are also known as the **Haskell Toolch
|
|||||||
<table>
|
<table>
|
||||||
<thead><tr><th>Cabal Version</th><th>Tags</th></tr></thead>
|
<thead><tr><th>Cabal Version</th><th>Tags</th></tr></thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr><td>3.6.2.0</td><td><span style="color:blue">latest</span>, <span style="color:green">recommended</span></td></tr>
|
<tr><td>3.8.1.0</td><td><span style="color:blue">latest</span></td></tr>
|
||||||
|
<tr><td>3.6.2.0</td><td><span style="color:green">recommended</span></td></tr>
|
||||||
<tr><td>3.6.0.0</td><td></td></tr>
|
<tr><td>3.6.0.0</td><td></td></tr>
|
||||||
<tr><td>3.4.1.0</td><td></td></tr>
|
<tr><td>3.4.1.0</td><td></td></tr>
|
||||||
<tr><td>3.4.0.0</td><td></td></tr>
|
<tr><td>3.4.0.0</td><td></td></tr>
|
||||||
@@ -105,7 +159,8 @@ GHCup supports the following tools, which are also known as the **Haskell Toolch
|
|||||||
<table>
|
<table>
|
||||||
<thead><tr><th>HLS Version</th><th>Tags</th></tr></thead>
|
<thead><tr><th>HLS Version</th><th>Tags</th></tr></thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr><td>1.7.0.0</td><td><span style="color:blue">latest</span>, <span style="color:green">recommended</span></td></tr>
|
<tr><td>1.8.0.0</td><td><span style="color:blue">latest</span>, <span style="color:green">recommended</span></td></tr>
|
||||||
|
<tr><td>1.7.0.0</td><td></td></tr>
|
||||||
<tr><td>1.6.1.0</td><td></td></tr>
|
<tr><td>1.6.1.0</td><td></td></tr>
|
||||||
<tr><td>1.6.0.0</td><td></td></tr>
|
<tr><td>1.6.0.0</td><td></td></tr>
|
||||||
<tr><td>1.5.1</td><td></td></tr>
|
<tr><td>1.5.1</td><td></td></tr>
|
||||||
@@ -122,7 +177,8 @@ GHCup supports the following tools, which are also known as the **Haskell Toolch
|
|||||||
<table>
|
<table>
|
||||||
<thead><tr><th>Stack Version</th><th>Tags</th></tr></thead>
|
<thead><tr><th>Stack Version</th><th>Tags</th></tr></thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr><td>2.7.5</td><td><span style="color:blue">latest</span>, <span style="color:green">recommended</span></td></tr>
|
<tr><td>2.9.1</td><td><span style="color:blue">latest</span>, <span style="color:green">recommended</span></td></tr>
|
||||||
|
<tr><td>2.7.5</td><td></td></tr>
|
||||||
<tr><td>2.7.3</td><td></td></tr>
|
<tr><td>2.7.3</td><td></td></tr>
|
||||||
<tr><td>2.7.1</td><td></td></tr>
|
<tr><td>2.7.1</td><td></td></tr>
|
||||||
<tr><td>2.5.1</td><td></td></tr>
|
<tr><td>2.5.1</td><td></td></tr>
|
||||||
@@ -182,12 +238,14 @@ HLS bindists are experimental.
|
|||||||
|
|
||||||
Lower availability of bindists. Stack and HLS binaries are experimental.
|
Lower availability of bindists. Stack and HLS binaries are experimental.
|
||||||
|
|
||||||
## Manual install
|
## Manual installation
|
||||||
|
|
||||||
|
### Unix
|
||||||
|
|
||||||
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://downloads.haskell.org/~ghcup/](https://downloads.haskell.org/~ghcup/)
|
||||||
and place it into your `PATH` anywhere.
|
and place it into your `PATH` anywhere.
|
||||||
|
|
||||||
If you want to GPG verify the binaries, import the following key first: `7784930957807690A66EBDBE3786C5262ECB4A3F`.
|
If you want to GPG verify the binaries, import the following keys first: `7784930957807690A66EBDBE3786C5262ECB4A3F` and `FE5AB6C91FEA597C3B31180B73EDE9E8CFBAEF01`.
|
||||||
|
|
||||||
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:
|
||||||
|
|
||||||
@@ -195,14 +253,78 @@ Then adjust your `PATH` in `~/.bashrc` (or similar, depending on your shell) lik
|
|||||||
export PATH="$HOME/.cabal/bin:$HOME/.ghcup/bin:$PATH"
|
export PATH="$HOME/.cabal/bin:$HOME/.ghcup/bin:$PATH"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
|
||||||
|
1. Install ghcup binary
|
||||||
|
- choose a base directory for installation, e.g. `C:\` that has sufficient space
|
||||||
|
- then create the directory, e.g. `C:\ghcup\bin`
|
||||||
|
- download the binary: https://downloads.haskell.org/~ghcup/x86_64-mingw64-ghcup.exe
|
||||||
|
- place it as `ghcup.exe` into e.g. `C:\ghcup\bin`
|
||||||
|
2. Install MSYS2
|
||||||
|
- download https://repo.msys2.org/distrib/msys2-x86_64-latest.exe and execute it
|
||||||
|
- remember the installation destination you choose (default is `C:\msys64`)
|
||||||
|
- finish the installation
|
||||||
|
* Add environment variables and update `Path`
|
||||||
|
- open search bar and type in "Edit the system environment variables", then open it
|
||||||
|
- click on "Environment Variables..." at the near bottom
|
||||||
|
- in the upper half, select `Path` variable and double click on it
|
||||||
|
- in the new window, click "New", type in `C:\ghcup\bin` (depending on step 1.) and press enter
|
||||||
|
- click "OK" at the bottom
|
||||||
|
- in the upper half, click on "New..."
|
||||||
|
- enter `GHCUP_MSYS2` under "Variable name" and the installation destination from step 2. under "Variable value"
|
||||||
|
- click "OK" at the bottom
|
||||||
|
- in the upper half, click on "New..."
|
||||||
|
- enter `GHCUP_INSTALL_BASE_PREFIX` under "Variable name" and based on the installation destination from step 1. enter the device directory (default `C:\`)
|
||||||
|
- click "OK" at the bottom
|
||||||
|
- in the upper half, click on "New..."
|
||||||
|
- enter `CABAL_DIR` under "Variable name" and based on the installation destination from step 1. enter the device directory + `cabal` subdir (default `C:\cabal`)
|
||||||
|
- click "OK" at the bottom
|
||||||
|
- click "OK" at the bottom
|
||||||
|
- click "OK" at the bottom
|
||||||
|
3. Install tools
|
||||||
|
- open powershell
|
||||||
|
- run `ghcup install ghc --set recommended`
|
||||||
|
- run `ghcup install cabal latest`
|
||||||
|
- run `ghcup install stack latest`
|
||||||
|
- run `ghcup install hls latest`
|
||||||
|
- run `cabal update`
|
||||||
|
4. Update msys2
|
||||||
|
- run `ghcup run -m -- pacman --noconfirm -Syuu`
|
||||||
|
- run `ghcup run -m -- pacman --noconfirm -Syuu`
|
||||||
|
- run `ghcup run -m -- pacman --noconfirm -S --needed curl autoconf mingw-w64-x86_64-pkgconf`
|
||||||
|
- run `ghcup run -m -- pacman --noconfirm -S ca-certificates`
|
||||||
|
5. Update cabal config
|
||||||
|
- go to e.g. `C:\cabal` (based on device you picked in 1.)
|
||||||
|
- open file `config`
|
||||||
|
- uncomment `extra-include-dirs` (the `-- `) and add the value (depending on installation destination you chose in 2.), e.g. `C:\msys64\mingw64\include`... so the final line should be `extra-include-dirs: C:\msys64\mingw64\include`
|
||||||
|
- uncomment `extra-lib-dirs` and do the same, adding `C:\msys64\mingw64\lib`
|
||||||
|
- uncomment `extra-prog-path` and set it to `C:\ghcup\bin, C:\cabal\bin, C:\msys64\mingw64\bin, C:\msys64\usr\bin`, depending on your install destinations from 1. and 2.
|
||||||
|
6. Set up msys2 shell
|
||||||
|
- run `ghcup run -m -- sed -i -e 's/db_home:.*$/db_home: windows/' /etc/nsswitch.conf` to make the HOME in your msys2 shell match the one from windows
|
||||||
|
- make a desktop shortcut from `C:\msys64\msys2_shell.cmd`, which will allow you to start a proper msys2 shell
|
||||||
|
- run `ghcup run -m -- sed -i -e 's/#MSYS2_PATH_TYPE=.*/MSYS2_PATH_TYPE=inherit/' /c/msys64/msys2.ini`
|
||||||
|
- run `ghcup run -m -- sed -i -e 's/rem set MSYS2_PATH_TYPE=inherit/set MSYS2_PATH_TYPE=inherit/' /c/msys64/msys2_shell.cmd`
|
||||||
|
|
||||||
|
All set. You can run `cabal init` now in an empty directory to start a project.
|
||||||
|
|
||||||
## Vim integration
|
## Vim integration
|
||||||
|
|
||||||
See [ghcup.vim](https://github.com/hasufell/ghcup.vim).
|
See [ghcup.vim](https://github.com/hasufell/ghcup.vim).
|
||||||
|
|
||||||
|
## VSCode integration
|
||||||
|
The developers of the Haskell Language Server offer an [extension](https://github.com/haskell/vscode-haskell) tightly integrated with the [Haskell Language Server](https://github.com/haskell/haskell-language-server). To get started:
|
||||||
|
|
||||||
|
1. Install GHCup. During installation, opt in to install the Haskell Language Server (HLS).
|
||||||
|
2. Install the extension (from VSCode: Ctrl + P and then `ext install haskell.haskell`).
|
||||||
|
3. Make sure your project uses the GHC version installed from GHCup (otherwise HLS is likely to fail on launch):
|
||||||
|
- instructions for [stack](https://docs.haskellstack.org/en/stable/yaml_configuration/#system-ghc)
|
||||||
|
|
||||||
|
On Linux, some users have reported an issue when VSCode is not launched from a terminal ("cannot find ghc version"). A solution is to [let HLS know about your GHCup on $PATH](https://github.com/haskell/vscode-haskell#stackcabalghc-can-not-be-found).
|
||||||
|
|
||||||
## Get help
|
## Get help
|
||||||
|
|
||||||
* [Libera IRC chat on #haskell-ghcup or #haskell](https://kiwiirc.com/nextclient/irc.libera.chat/?nick=Guest%7C?#haskell,#haskell-ghcup)
|
* [Libera IRC chat on #haskell-ghcup or #haskell](https://kiwiirc.com/nextclient/irc.libera.chat/?nick=Guest%7C?#haskell,#haskell-ghcup)
|
||||||
* [GHCup issue tracker](https://gitlab.haskell.org/haskell/ghcup-hs/issues)
|
* [GHCup issue tracker](https://github.com/haskell/ghcup-hs/issues/new)
|
||||||
* [Matrix](https://app.element.io/#/room/#haskell-tooling:matrix.org)
|
* [Matrix](https://app.element.io/#/room/#haskell-tooling:matrix.org)
|
||||||
* [Discord](https://discord.gg/pKYf3zDQU7)
|
* [Discord](https://discord.gg/pKYf3zDQU7)
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 40 KiB |
File diff suppressed because it is too large
Load Diff
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 40 KiB |
@@ -177,7 +177,7 @@ A more thorough introduction to GHCi can be found in the
|
|||||||
### Using external packages in ghci
|
### Using external packages in ghci
|
||||||
|
|
||||||
By default, GHCi can only load and use packages that are
|
By default, GHCi can only load and use packages that are
|
||||||
[included with the GHC installation](https://downloads.haskell.org/ghc/latest/docs/html/users_guide/9.2.2-notes.html#included-libraries).
|
[included with the GHC installation](https://downloads.haskell.org/ghc/9.4.2/docs/users_guide/9.4.2-notes.html#included-libraries).
|
||||||
|
|
||||||
However, users of the [cabal-install](https://www.haskell.org/cabal) and
|
However, users of the [cabal-install](https://www.haskell.org/cabal) and
|
||||||
[stack](http://haskellstack.org) build tools can download and load external packages
|
[stack](http://haskellstack.org) build tools can download and load external packages
|
||||||
@@ -335,7 +335,7 @@ see the [Cabal user guide](https://cabal.readthedocs.io/en/stable/getting-starte
|
|||||||
|
|
||||||
To learn Haskell, try any of those:
|
To learn Haskell, try any of those:
|
||||||
|
|
||||||
- A beginner friendly [4-lectures course](https://github.com/haskell-beginners-2022/course-plan) with exercises (by [Kowainik](https://kowainik.github.io/))
|
- A beginner friendly [4-lectures course](https://github.com/haskell-beginners-2022/course-plan) with exercises (by [Dmitrii Kovanikov](https://kodimensional.dev/))
|
||||||
- An in-depth university [CIS 194 Haskell course](https://www.cis.upenn.edu/~cis194/spring13/) including exercises (by [Brent Yorgey](https://byorgey.wordpress.com/))
|
- An in-depth university [CIS 194 Haskell course](https://www.cis.upenn.edu/~cis194/spring13/) including exercises (by [Brent Yorgey](https://byorgey.wordpress.com/))
|
||||||
|
|
||||||
## Projects to contribute to
|
## Projects to contribute to
|
||||||
@@ -343,7 +343,7 @@ To learn Haskell, try any of those:
|
|||||||
* [https://github.com/haskell/haskell-language-server](https://github.com/haskell/haskell-language-server)
|
* [https://github.com/haskell/haskell-language-server](https://github.com/haskell/haskell-language-server)
|
||||||
* [https://github.com/haskell/cabal](https://github.com/haskell/cabal)
|
* [https://github.com/haskell/cabal](https://github.com/haskell/cabal)
|
||||||
* [https://github.com/commercialhaskell/stack](https://github.com/commercialhaskell/stack)
|
* [https://github.com/commercialhaskell/stack](https://github.com/commercialhaskell/stack)
|
||||||
* [https://gitlab.haskell.org/haskell/ghcup-hs](https://gitlab.haskell.org/haskell/ghcup-hs)
|
* [https://github.com/haskell/ghcup-hs](https://github.com/haskell/ghcup-hs)
|
||||||
* [https://github.com/jgm/pandoc](https://github.com/jgm/pandoc)
|
* [https://github.com/jgm/pandoc](https://github.com/jgm/pandoc)
|
||||||
* [https://github.com/simonmichael/hledger](https://github.com/simonmichael/hledger)
|
* [https://github.com/simonmichael/hledger](https://github.com/simonmichael/hledger)
|
||||||
* [https://github.com/koalaman/shellcheck](https://github.com/koalaman/shellcheck)
|
* [https://github.com/koalaman/shellcheck](https://github.com/koalaman/shellcheck)
|
||||||
|
|||||||
130
ghcup.cabal
130
ghcup.cabal
@@ -1,13 +1,13 @@
|
|||||||
cabal-version: 3.0
|
cabal-version: 2.4
|
||||||
name: ghcup
|
name: ghcup
|
||||||
version: 0.1.18.0
|
version: 0.1.19.0
|
||||||
license: LGPL-3.0-only
|
license: LGPL-3.0-only
|
||||||
license-file: LICENSE
|
license-file: LICENSE
|
||||||
copyright: Julian Ospald 2020
|
copyright: Julian Ospald 2020
|
||||||
maintainer: hasufell@posteo.de
|
maintainer: hasufell@posteo.de
|
||||||
author: Julian Ospald
|
author: Julian Ospald
|
||||||
homepage: https://gitlab.haskell.org/haskell/ghcup-hs
|
homepage: https://github.com/haskell/ghcup-hs
|
||||||
bug-reports: https://gitlab.haskell.org/haskell/ghcup-hs/issues
|
bug-reports: https://github.com/haskell/ghcup-hs/issues/
|
||||||
synopsis: ghc toolchain installer
|
synopsis: ghc toolchain installer
|
||||||
description:
|
description:
|
||||||
A rewrite of the shell script ghcup, for providing
|
A rewrite of the shell script ghcup, for providing
|
||||||
@@ -21,13 +21,18 @@ extra-doc-files:
|
|||||||
README.md
|
README.md
|
||||||
|
|
||||||
extra-source-files:
|
extra-source-files:
|
||||||
|
cbits/dirutils.c
|
||||||
|
cbits/dirutils.h
|
||||||
data/build_mk/cross
|
data/build_mk/cross
|
||||||
data/build_mk/default
|
data/build_mk/default
|
||||||
test/golden/GHCupInfo.json
|
test/data/dir/.keep
|
||||||
|
test/data/file
|
||||||
|
test/golden/unix/GHCupInfo.json
|
||||||
|
test/golden/windows/GHCupInfo.json
|
||||||
|
|
||||||
source-repository head
|
source-repository head
|
||||||
type: git
|
type: git
|
||||||
location: https://gitlab.haskell.org/haskell/ghcup-hs.git
|
location: https://github.com/haskell/ghcup-hs.git
|
||||||
|
|
||||||
flag tui
|
flag tui
|
||||||
description:
|
description:
|
||||||
@@ -69,6 +74,7 @@ library
|
|||||||
GHCup.Prelude.Process
|
GHCup.Prelude.Process
|
||||||
GHCup.Prelude.String.QQ
|
GHCup.Prelude.String.QQ
|
||||||
GHCup.Prelude.Version.QQ
|
GHCup.Prelude.Version.QQ
|
||||||
|
GHCup.Prompts
|
||||||
GHCup.Requirements
|
GHCup.Requirements
|
||||||
GHCup.Stack
|
GHCup.Stack
|
||||||
GHCup.Types
|
GHCup.Types
|
||||||
@@ -108,8 +114,8 @@ library
|
|||||||
, base >=4.12 && <5
|
, base >=4.12 && <5
|
||||||
, base16-bytestring >=0.1.1.6 && <1.1
|
, base16-bytestring >=0.1.1.6 && <1.1
|
||||||
, binary ^>=0.8.6.0
|
, binary ^>=0.8.6.0
|
||||||
, bytestring ^>=0.10
|
, bytestring >=0.10 && <0.12
|
||||||
, Cabal ^>=3.6.2.0
|
, Cabal ^>=3.0.0.0 || ^>=3.2.0.0 || ^>=3.4.0.0 || ^>=3.6.0.0
|
||||||
, case-insensitive ^>=1.2.1.0
|
, case-insensitive ^>=1.2.1.0
|
||||||
, casing ^>=0.1.4.1
|
, casing ^>=0.1.4.1
|
||||||
, containers ^>=0.6
|
, containers ^>=0.6
|
||||||
@@ -137,9 +143,9 @@ library
|
|||||||
, split ^>=0.2.3.4
|
, split ^>=0.2.3.4
|
||||||
, streamly ^>=0.8.2
|
, streamly ^>=0.8.2
|
||||||
, strict-base ^>=0.4
|
, strict-base ^>=0.4
|
||||||
, template-haskell >=2.7 && <2.18
|
, template-haskell >=2.7 && <2.20
|
||||||
, temporary ^>=1.3
|
, temporary ^>=1.3
|
||||||
, text ^>=1.2.4.0
|
, text ^>=2.0
|
||||||
, time ^>=1.9.3
|
, time ^>=1.9.3
|
||||||
, transformers ^>=0.5
|
, transformers ^>=0.5
|
||||||
, unliftio-core ^>=0.2.0.1
|
, unliftio-core ^>=0.2.0.1
|
||||||
@@ -155,41 +161,45 @@ library
|
|||||||
exposed-modules: GHCup.Download.IOStreams
|
exposed-modules: GHCup.Download.IOStreams
|
||||||
cpp-options: -DINTERNAL_DOWNLOADER
|
cpp-options: -DINTERNAL_DOWNLOADER
|
||||||
build-depends:
|
build-depends:
|
||||||
, HsOpenSSL >=0.11.4.18
|
, HsOpenSSL >=0.11.7.2
|
||||||
, http-io-streams >=0.1.2.0
|
, http-io-streams >=0.1.2.0
|
||||||
, io-streams >=1.5.2.1
|
, io-streams >=1.5.2.1
|
||||||
, terminal-progress-bar >=0.4.1
|
, terminal-progress-bar >=0.4.1
|
||||||
|
|
||||||
if os(windows)
|
if os(windows)
|
||||||
cpp-options: -DIS_WINDOWS
|
cpp-options: -DIS_WINDOWS
|
||||||
other-modules:
|
other-modules:
|
||||||
GHCup.Prelude.File.Windows
|
GHCup.Prelude.File.Windows
|
||||||
GHCup.Prelude.Process.Windows
|
|
||||||
GHCup.Prelude.Windows
|
GHCup.Prelude.Windows
|
||||||
|
|
||||||
|
-- GHCup.OptParse.Run uses this
|
||||||
|
exposed-modules: GHCup.Prelude.Process.Windows
|
||||||
build-depends:
|
build-depends:
|
||||||
, bzlib
|
, bzlib
|
||||||
, process ^>=1.6.11.0
|
, process ^>=1.6.11.0
|
||||||
, Win32 ^>=2.10
|
, Win32 >=2.10
|
||||||
|
|
||||||
else
|
else
|
||||||
other-modules:
|
other-modules:
|
||||||
GHCup.Prelude.File.Posix
|
GHCup.Prelude.File.Posix
|
||||||
GHCup.Prelude.File.Posix.Foreign
|
GHCup.Prelude.File.Posix.Foreign
|
||||||
GHCup.Prelude.File.Posix.Traversals
|
|
||||||
GHCup.Prelude.Posix
|
GHCup.Prelude.Posix
|
||||||
GHCup.Prelude.Process.Posix
|
GHCup.Prelude.Process.Posix
|
||||||
|
|
||||||
c-sources: cbits/dirutils.c
|
exposed-modules: GHCup.Prelude.File.Posix.Traversals
|
||||||
|
include-dirs: cbits
|
||||||
|
includes: dirutils.h
|
||||||
|
install-includes: dirutils.h
|
||||||
|
c-sources: cbits/dirutils.c
|
||||||
build-depends:
|
build-depends:
|
||||||
, bz2 >=0.5.0.5 && <1.1
|
, bz2 >=0.5.0.5 && <1.1
|
||||||
, terminal-size ^>=0.3.2.1
|
, terminal-size ^>=0.3.3
|
||||||
, unix ^>=2.7
|
, unix ^>=2.7
|
||||||
, unix-bytestring ^>=0.3.7.3
|
, unix-bytestring ^>=0.3.7.3
|
||||||
|
|
||||||
if (flag(tui) && !os(windows))
|
if (flag(tui) && !os(windows))
|
||||||
cpp-options: -DBRICK
|
cpp-options: -DBRICK
|
||||||
build-depends: vty >=5.28.2 && <5.34
|
build-depends: vty ^>=5.37
|
||||||
|
|
||||||
executable ghcup
|
executable ghcup
|
||||||
main-is: Main.hs
|
main-is: Main.hs
|
||||||
@@ -208,6 +218,7 @@ executable ghcup
|
|||||||
GHCup.OptParse.Rm
|
GHCup.OptParse.Rm
|
||||||
GHCup.OptParse.Run
|
GHCup.OptParse.Run
|
||||||
GHCup.OptParse.Set
|
GHCup.OptParse.Set
|
||||||
|
GHCup.OptParse.Test
|
||||||
GHCup.OptParse.ToolRequirements
|
GHCup.OptParse.ToolRequirements
|
||||||
GHCup.OptParse.UnSet
|
GHCup.OptParse.UnSet
|
||||||
GHCup.OptParse.Upgrade
|
GHCup.OptParse.Upgrade
|
||||||
@@ -230,38 +241,40 @@ executable ghcup
|
|||||||
-fwarn-incomplete-record-updates -threaded
|
-fwarn-incomplete-record-updates -threaded
|
||||||
|
|
||||||
build-depends:
|
build-depends:
|
||||||
, aeson >=1.4
|
, aeson >=1.4
|
||||||
, aeson-pretty ^>=0.8.8
|
, aeson-pretty ^>=0.8.8
|
||||||
, async ^>=2.2.3
|
, async ^>=2.2.3
|
||||||
, base >=4.12 && <5
|
, base >=4.12 && <5
|
||||||
, bytestring ^>=0.10
|
, bytestring >=0.10 && <0.12
|
||||||
, cabal-plan ^>=0.7.2
|
, cabal-install-parsers >=0.4.5
|
||||||
, containers ^>=0.6
|
, cabal-plan ^>=0.7.2
|
||||||
, deepseq ^>=1.4
|
, containers ^>=0.6
|
||||||
, directory ^>=1.3.6.0
|
, deepseq ^>=1.4
|
||||||
, filepath ^>=1.4.2.1
|
, directory ^>=1.3.6.0
|
||||||
|
, filepath ^>=1.4.2.1
|
||||||
, ghcup
|
, ghcup
|
||||||
, haskus-utils-variant ^>=3.2.1
|
, haskus-utils-types ^>=1.5
|
||||||
, libarchive ^>=3.0.3.0
|
, haskus-utils-variant ^>=3.2.1
|
||||||
, megaparsec >=8.0.0 && <9.3
|
, libarchive ^>=3.0.3.0
|
||||||
, mtl ^>=2.2
|
, megaparsec >=8.0.0 && <9.3
|
||||||
, optparse-applicative >=0.15.1.0 && <0.18
|
, mtl ^>=2.2
|
||||||
, pretty ^>=1.1.3.1
|
, optparse-applicative >=0.15.1.0 && <0.18
|
||||||
, pretty-terminal ^>=0.1.0.0
|
, pretty ^>=1.1.3.1
|
||||||
, process ^>=1.6.11.0
|
, pretty-terminal ^>=0.1.0.0
|
||||||
, resourcet ^>=1.2.2
|
, process ^>=1.6.11.0
|
||||||
, safe ^>=0.3.18
|
, resourcet ^>=1.2.2
|
||||||
, safe-exceptions ^>=0.1
|
, safe ^>=0.3.18
|
||||||
, tagsoup ^>=0.14
|
, safe-exceptions ^>=0.1
|
||||||
, template-haskell >=2.7 && <2.18
|
, tagsoup ^>=0.14
|
||||||
, temporary ^>=1.3
|
, template-haskell >=2.7 && <2.20
|
||||||
, text ^>=1.2.4.0
|
, temporary ^>=1.3
|
||||||
, unordered-containers ^>=0.2
|
, text ^>=2.0
|
||||||
, uri-bytestring ^>=0.3.2.2
|
, unordered-containers ^>=0.2
|
||||||
, utf8-string ^>=1.0
|
, uri-bytestring ^>=0.3.2.2
|
||||||
, vector ^>=0.12
|
, utf8-string ^>=1.0
|
||||||
, versions >=4.0.1 && <5.1
|
, vector ^>=0.12
|
||||||
, yaml-streamly ^>=0.12.0
|
, versions >=4.0.1 && <5.1
|
||||||
|
, yaml-streamly ^>=0.12.0
|
||||||
|
|
||||||
if flag(internal-downloader)
|
if flag(internal-downloader)
|
||||||
cpp-options: -DINTERNAL_DOWNLOADER
|
cpp-options: -DINTERNAL_DOWNLOADER
|
||||||
@@ -270,10 +283,10 @@ executable ghcup
|
|||||||
cpp-options: -DBRICK
|
cpp-options: -DBRICK
|
||||||
other-modules: BrickMain
|
other-modules: BrickMain
|
||||||
build-depends:
|
build-depends:
|
||||||
, brick ^>=0.64
|
, brick ^>=1.5
|
||||||
, transformers ^>=0.5
|
, transformers ^>=0.5
|
||||||
, unix ^>=2.7
|
, unix ^>=2.7
|
||||||
, vty >=5.28.2 && <5.34
|
, vty ^>=5.37
|
||||||
|
|
||||||
if os(windows)
|
if os(windows)
|
||||||
cpp-options: -DIS_WINDOWS
|
cpp-options: -DIS_WINDOWS
|
||||||
@@ -291,6 +304,7 @@ test-suite ghcup-test
|
|||||||
hs-source-dirs: test
|
hs-source-dirs: test
|
||||||
other-modules:
|
other-modules:
|
||||||
GHCup.ArbitraryTypes
|
GHCup.ArbitraryTypes
|
||||||
|
GHCup.Prelude.File.Posix.TraversalsSpec
|
||||||
GHCup.Types.JSONSpec
|
GHCup.Types.JSONSpec
|
||||||
GHCup.Utils.FileSpec
|
GHCup.Utils.FileSpec
|
||||||
Spec
|
Spec
|
||||||
@@ -310,17 +324,23 @@ test-suite ghcup-test
|
|||||||
|
|
||||||
build-depends:
|
build-depends:
|
||||||
, base >=4.12 && <5
|
, base >=4.12 && <5
|
||||||
, bytestring ^>=0.10
|
, bytestring >=0.10 && <0.12
|
||||||
, containers ^>=0.6
|
, containers ^>=0.6
|
||||||
, directory ^>=1.3.6.0
|
, directory ^>=1.3.6.0
|
||||||
, filepath ^>=1.4.2.1
|
, filepath ^>=1.4.2.1
|
||||||
, generic-arbitrary >=0.1.0 && <0.3
|
, generic-arbitrary >=0.1.0 && <0.2.1 || >=0.2.2 && <0.3
|
||||||
, ghcup
|
, ghcup
|
||||||
, hspec >=2.7.10 && <2.10
|
, hspec >=2.7.10 && <2.11
|
||||||
, hspec-golden-aeson ^>=0.9
|
, hspec-golden-aeson ^>=0.9
|
||||||
, QuickCheck ^>=2.14.1
|
, QuickCheck ^>=2.14.1
|
||||||
, quickcheck-arbitrary-adt ^>=0.3.1.0
|
, quickcheck-arbitrary-adt ^>=0.3.1.0
|
||||||
, streamly ^>=0.8.2
|
, streamly ^>=0.8.2
|
||||||
, text ^>=1.2.4.0
|
, text ^>=2.0
|
||||||
, uri-bytestring ^>=0.3.2.2
|
, uri-bytestring ^>=0.3.2.2
|
||||||
, versions >=4.0.1 && <5.1
|
, versions >=4.0.1 && <5.1
|
||||||
|
|
||||||
|
if os(windows)
|
||||||
|
cpp-options: -DIS_WINDOWS
|
||||||
|
|
||||||
|
else
|
||||||
|
build-depends: unix ^>=2.7
|
||||||
|
|||||||
36
lib/GHCup.hs
36
lib/GHCup.hs
@@ -33,8 +33,8 @@ module GHCup (
|
|||||||
|
|
||||||
|
|
||||||
import GHCup.Cabal
|
import GHCup.Cabal
|
||||||
import GHCup.GHC
|
import GHCup.GHC hiding ( GHCVer(..) )
|
||||||
import GHCup.HLS
|
import GHCup.HLS hiding ( HLSVer(..) )
|
||||||
import GHCup.Stack
|
import GHCup.Stack
|
||||||
import GHCup.List
|
import GHCup.List
|
||||||
import GHCup.Download
|
import GHCup.Download
|
||||||
@@ -73,6 +73,7 @@ import Prelude hiding ( abs
|
|||||||
import System.Environment
|
import System.Environment
|
||||||
import System.FilePath
|
import System.FilePath
|
||||||
import System.IO.Error
|
import System.IO.Error
|
||||||
|
import System.IO.Temp
|
||||||
import Text.Regex.Posix
|
import Text.Regex.Posix
|
||||||
|
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
@@ -104,6 +105,7 @@ fetchToolBindist :: ( MonadFail m
|
|||||||
-> Maybe FilePath
|
-> Maybe FilePath
|
||||||
-> Excepts
|
-> Excepts
|
||||||
'[ DigestError
|
'[ DigestError
|
||||||
|
, ContentLengthError
|
||||||
, GPGError
|
, GPGError
|
||||||
, DownloadFailed
|
, DownloadFailed
|
||||||
, NoDownload
|
, NoDownload
|
||||||
@@ -132,6 +134,7 @@ rmTool :: ( MonadReader env m
|
|||||||
=> ListResult
|
=> ListResult
|
||||||
-> Excepts '[NotInstalled, UninstallFailed] m ()
|
-> Excepts '[NotInstalled, UninstallFailed] m ()
|
||||||
rmTool ListResult {lVer, lTool, lCross} = do
|
rmTool ListResult {lVer, lTool, lCross} = do
|
||||||
|
logInfo $ "removing " <> T.pack (show lTool) <> " version " <> prettyVer lVer
|
||||||
case lTool of
|
case lTool of
|
||||||
GHC ->
|
GHC ->
|
||||||
let ghcTargetVersion = GHCTargetVersion lCross lVer
|
let ghcTargetVersion = GHCTargetVersion lCross lVer
|
||||||
@@ -205,9 +208,8 @@ rmGhcupDirs = do
|
|||||||
| isWindows = removeDirIfEmptyOrIsSymlink binDir
|
| isWindows = removeDirIfEmptyOrIsSymlink binDir
|
||||||
| otherwise = do
|
| otherwise = do
|
||||||
isXDGStyle <- liftIO useXDG
|
isXDGStyle <- liftIO useXDG
|
||||||
if not isXDGStyle
|
when (not isXDGStyle) $
|
||||||
then removeDirIfEmptyOrIsSymlink binDir
|
removeDirIfEmptyOrIsSymlink binDir
|
||||||
else pure ()
|
|
||||||
|
|
||||||
reportRemainingFiles :: (MonadMask m, MonadIO m) => FilePath -> m [FilePath]
|
reportRemainingFiles :: (MonadMask m, MonadIO m) => FilePath -> m [FilePath]
|
||||||
reportRemainingFiles dir = do
|
reportRemainingFiles dir = do
|
||||||
@@ -286,12 +288,13 @@ upgradeGHCup :: ( MonadMask m
|
|||||||
-> Excepts
|
-> Excepts
|
||||||
'[ CopyError
|
'[ CopyError
|
||||||
, DigestError
|
, DigestError
|
||||||
|
, ContentLengthError
|
||||||
, GPGError
|
, GPGError
|
||||||
, GPGError
|
, GPGError
|
||||||
, DownloadFailed
|
, DownloadFailed
|
||||||
, NoDownload
|
, NoDownload
|
||||||
, NoUpdate
|
, NoUpdate
|
||||||
, GHCupShadowed
|
, ToolShadowed
|
||||||
]
|
]
|
||||||
m
|
m
|
||||||
Version
|
Version
|
||||||
@@ -306,7 +309,7 @@ upgradeGHCup mtarget force' fatal = do
|
|||||||
dli <- liftE $ getDownloadInfo GHCup latestVer
|
dli <- liftE $ getDownloadInfo GHCup latestVer
|
||||||
tmp <- fromGHCupPath <$> lift withGHCupTmpDir
|
tmp <- fromGHCupPath <$> lift withGHCupTmpDir
|
||||||
let fn = "ghcup" <> exeExt
|
let fn = "ghcup" <> exeExt
|
||||||
p <- liftE $ download (_dlUri dli) Nothing (Just (_dlHash dli)) tmp (Just fn) False
|
p <- liftE $ download (_dlUri dli) Nothing (Just (_dlHash dli)) (_dlCSize dli) tmp (Just fn) False
|
||||||
let destDir = takeDirectory destFile
|
let destDir = takeDirectory destFile
|
||||||
destFile = fromMaybe (binDir </> fn) mtarget
|
destFile = fromMaybe (binDir </> fn) mtarget
|
||||||
lift $ logDebug $ "mkdir -p " <> T.pack destDir
|
lift $ logDebug $ "mkdir -p " <> T.pack destDir
|
||||||
@@ -322,17 +325,9 @@ upgradeGHCup mtarget force' fatal = do
|
|||||||
liftIO (isShadowed destFile) >>= \case
|
liftIO (isShadowed destFile) >>= \case
|
||||||
Nothing -> pure ()
|
Nothing -> pure ()
|
||||||
Just pa
|
Just pa
|
||||||
| fatal -> throwE (GHCupShadowed pa destFile latestVer)
|
| fatal -> throwE (ToolShadowed GHCup pa destFile latestVer)
|
||||||
| otherwise ->
|
| otherwise ->
|
||||||
lift $ logWarn $ "ghcup is shadowed by "
|
lift $ logWarn $ T.pack $ prettyHFError (ToolShadowed GHCup pa destFile latestVer)
|
||||||
<> T.pack pa
|
|
||||||
<> ". The upgrade will not be in effect, unless you remove "
|
|
||||||
<> T.pack pa
|
|
||||||
<> " or make sure "
|
|
||||||
<> T.pack destDir
|
|
||||||
<> " comes before "
|
|
||||||
<> T.pack (takeDirectory pa)
|
|
||||||
<> " in PATH."
|
|
||||||
|
|
||||||
pure latestVer
|
pure latestVer
|
||||||
|
|
||||||
@@ -372,11 +367,12 @@ rmGhcup = do
|
|||||||
if isWindows
|
if isWindows
|
||||||
then do
|
then do
|
||||||
-- since it doesn't seem possible to delete a running exe on windows
|
-- since it doesn't seem possible to delete a running exe on windows
|
||||||
-- we move it to temp dir, to be deleted at next reboot
|
-- we move it to system temp dir, to be deleted at next reboot
|
||||||
tempFilepath <- mkGhcupTmpDir
|
tmp <- liftIO $ getCanonicalTemporaryDirectory >>= \t -> createTempDirectory t "ghcup"
|
||||||
|
logDebug $ "mv " <> T.pack ghcupFilepath <> " " <> T.pack (tmp </> "ghcup")
|
||||||
hideError UnsupportedOperation $
|
hideError UnsupportedOperation $
|
||||||
liftIO $ hideError NoSuchThing $
|
liftIO $ hideError NoSuchThing $
|
||||||
moveFile ghcupFilepath (fromGHCupPath tempFilepath </> "ghcup")
|
moveFile ghcupFilepath (tmp </> "ghcup")
|
||||||
else
|
else
|
||||||
-- delete it.
|
-- delete it.
|
||||||
hideError doesNotExistErrorType $ rmFile ghcupFilepath
|
hideError doesNotExistErrorType $ rmFile ghcupFilepath
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ installCabalBindist :: ( MonadMask m
|
|||||||
'[ AlreadyInstalled
|
'[ AlreadyInstalled
|
||||||
, CopyError
|
, CopyError
|
||||||
, DigestError
|
, DigestError
|
||||||
|
, ContentLengthError
|
||||||
, GPGError
|
, GPGError
|
||||||
, DownloadFailed
|
, DownloadFailed
|
||||||
, NoDownload
|
, NoDownload
|
||||||
@@ -183,6 +184,7 @@ installCabalBin :: ( MonadMask m
|
|||||||
'[ AlreadyInstalled
|
'[ AlreadyInstalled
|
||||||
, CopyError
|
, CopyError
|
||||||
, DigestError
|
, DigestError
|
||||||
|
, ContentLengthError
|
||||||
, GPGError
|
, GPGError
|
||||||
, DownloadFailed
|
, DownloadFailed
|
||||||
, NoDownload
|
, NoDownload
|
||||||
@@ -230,6 +232,10 @@ setCabal ver = do
|
|||||||
let destL = targetFile
|
let destL = targetFile
|
||||||
lift $ createLink destL cabalbin
|
lift $ createLink destL cabalbin
|
||||||
|
|
||||||
|
liftIO (isShadowed cabalbin) >>= \case
|
||||||
|
Nothing -> pure ()
|
||||||
|
Just pa -> lift $ logWarn $ T.pack $ prettyHFError (ToolShadowed Cabal pa cabalbin ver)
|
||||||
|
|
||||||
pure ()
|
pure ()
|
||||||
|
|
||||||
unsetCabal :: ( MonadMask m
|
unsetCabal :: ( MonadMask m
|
||||||
|
|||||||
@@ -75,7 +75,6 @@ import System.Exit
|
|||||||
import System.FilePath
|
import System.FilePath
|
||||||
import System.IO.Error
|
import System.IO.Error
|
||||||
import System.IO.Temp
|
import System.IO.Temp
|
||||||
import Text.PrettyPrint.HughesPJClass ( prettyShow )
|
|
||||||
import URI.ByteString
|
import URI.ByteString
|
||||||
|
|
||||||
import qualified Crypto.Hash.SHA256 as SHA256
|
import qualified Crypto.Hash.SHA256 as SHA256
|
||||||
@@ -114,7 +113,7 @@ getDownloadsF :: ( FromJSONKey Tool
|
|||||||
, MonadMask m
|
, MonadMask m
|
||||||
)
|
)
|
||||||
=> Excepts
|
=> Excepts
|
||||||
'[DigestError, GPGError, JSONError , DownloadFailed , FileDoesNotExistError]
|
'[DigestError, ContentLengthError, GPGError, JSONError , DownloadFailed , FileDoesNotExistError]
|
||||||
m
|
m
|
||||||
GHCupInfo
|
GHCupInfo
|
||||||
getDownloadsF = do
|
getDownloadsF = do
|
||||||
@@ -162,17 +161,21 @@ getBase :: ( MonadReader env m
|
|||||||
, MonadMask m
|
, MonadMask m
|
||||||
)
|
)
|
||||||
=> URI
|
=> URI
|
||||||
-> Excepts '[GPGError, DigestError, JSONError, FileDoesNotExistError] m GHCupInfo
|
-> Excepts '[DownloadFailed, GPGError, DigestError, ContentLengthError, JSONError, FileDoesNotExistError] m GHCupInfo
|
||||||
getBase uri = do
|
getBase uri = do
|
||||||
Settings { noNetwork, downloader } <- lift getSettings
|
Settings { noNetwork, downloader, metaMode } <- lift getSettings
|
||||||
|
|
||||||
-- try to download yaml... usually this writes it into cache dir,
|
-- try to download yaml... usually this writes it into cache dir,
|
||||||
-- but in some cases not (e.g. when using file://), so we honour
|
-- but in some cases not (e.g. when using file://), so we honour
|
||||||
-- the return filepath, if any
|
-- the return filepath, if any
|
||||||
mYaml <- if noNetwork && view (uriSchemeL' % schemeBSL') uri /= "file" -- for file://, let it fall through
|
mYaml <- if noNetwork && view (uriSchemeL' % schemeBSL') uri /= "file" -- for file://, let it fall through
|
||||||
then pure Nothing
|
then pure Nothing
|
||||||
else handleIO (\e -> lift (warnCache (displayException e) downloader) >> pure Nothing)
|
else handleIO (\e -> case metaMode of
|
||||||
. catchE @_ @_ @'[] (\e@(DownloadFailed _) -> lift (warnCache (prettyShow e) downloader) >> pure Nothing)
|
Strict -> throwIO e
|
||||||
|
Lax -> lift (warnCache (displayException e) downloader) >> pure Nothing)
|
||||||
|
. catchE @_ @_ @'[DownloadFailed] (\e@(DownloadFailed _) -> case metaMode of
|
||||||
|
Strict -> throwE e
|
||||||
|
Lax -> lift (warnCache (prettyHFError e) downloader) >> pure Nothing)
|
||||||
. fmap Just
|
. fmap Just
|
||||||
. smartDl
|
. smartDl
|
||||||
$ uri
|
$ uri
|
||||||
@@ -184,7 +187,7 @@ getBase uri = do
|
|||||||
liftE
|
liftE
|
||||||
. onE_ (onError actualYaml)
|
. onE_ (onError actualYaml)
|
||||||
. lEM' @_ @_ @'[JSONError] (\(displayException -> e) -> JSONDecodeError $ unlines [e, "Consider removing " <> actualYaml <> " manually."])
|
. lEM' @_ @_ @'[JSONError] (\(displayException -> e) -> JSONDecodeError $ unlines [e, "Consider removing " <> actualYaml <> " manually."])
|
||||||
. liftIO
|
. liftIO
|
||||||
. Y.decodeFileEither
|
. Y.decodeFileEither
|
||||||
$ actualYaml
|
$ actualYaml
|
||||||
where
|
where
|
||||||
@@ -229,6 +232,7 @@ getBase uri = do
|
|||||||
-> Excepts
|
-> Excepts
|
||||||
'[ DownloadFailed
|
'[ DownloadFailed
|
||||||
, DigestError
|
, DigestError
|
||||||
|
, ContentLengthError
|
||||||
, GPGError
|
, GPGError
|
||||||
]
|
]
|
||||||
m1
|
m1
|
||||||
@@ -242,7 +246,7 @@ getBase uri = do
|
|||||||
Settings { metaCache } <- lift getSettings
|
Settings { metaCache } <- lift getSettings
|
||||||
|
|
||||||
-- for local files, let's short-circuit and ignore access time
|
-- for local files, let's short-circuit and ignore access time
|
||||||
if | scheme == "file" -> liftE $ download uri' Nothing Nothing (fromGHCupPath cacheDir) Nothing True
|
if | scheme == "file" -> liftE $ download uri' Nothing Nothing Nothing (fromGHCupPath cacheDir) Nothing True
|
||||||
| e -> do
|
| e -> do
|
||||||
accessTime <- fmap utcTimeToPOSIXSeconds $ liftIO $ getAccessTime json_file
|
accessTime <- fmap utcTimeToPOSIXSeconds $ liftIO $ getAccessTime json_file
|
||||||
let sinceLastAccess = utcTimeToPOSIXSeconds currentTime - accessTime
|
let sinceLastAccess = utcTimeToPOSIXSeconds currentTime - accessTime
|
||||||
@@ -258,7 +262,7 @@ getBase uri = do
|
|||||||
where
|
where
|
||||||
dlWithMod modTime json_file = do
|
dlWithMod modTime json_file = do
|
||||||
let (dir, fn) = splitFileName json_file
|
let (dir, fn) = splitFileName json_file
|
||||||
f <- liftE $ download uri' (Just $ over pathL' (<> ".sig") uri') Nothing dir (Just fn) True
|
f <- liftE $ download uri' (Just $ over pathL' (<> ".sig") uri') Nothing Nothing dir (Just fn) True
|
||||||
liftIO $ setModificationTime f modTime
|
liftIO $ setModificationTime f modTime
|
||||||
liftIO $ setAccessTime f modTime
|
liftIO $ setAccessTime f modTime
|
||||||
pure f
|
pure f
|
||||||
@@ -324,23 +328,26 @@ download :: ( MonadReader env m
|
|||||||
=> URI
|
=> URI
|
||||||
-> Maybe URI -- ^ URI for gpg sig
|
-> Maybe URI -- ^ URI for gpg sig
|
||||||
-> Maybe T.Text -- ^ expected hash
|
-> Maybe T.Text -- ^ expected hash
|
||||||
|
-> Maybe Integer -- ^ expected content length
|
||||||
-> FilePath -- ^ destination dir (ignored for file:// scheme)
|
-> FilePath -- ^ destination dir (ignored for file:// scheme)
|
||||||
-> Maybe FilePath -- ^ optional filename
|
-> Maybe FilePath -- ^ optional filename
|
||||||
-> Bool -- ^ whether to read an write etags
|
-> Bool -- ^ whether to read an write etags
|
||||||
-> Excepts '[DigestError , DownloadFailed, GPGError] m FilePath
|
-> Excepts '[DigestError, ContentLengthError, DownloadFailed, GPGError] m FilePath
|
||||||
download uri gpgUri eDigest dest mfn etags
|
download rawUri gpgUri eDigest eCSize dest mfn etags
|
||||||
| scheme == "https" = dl
|
| scheme == "https" = liftE dl
|
||||||
| scheme == "http" = dl
|
| scheme == "http" = liftE dl
|
||||||
| scheme == "file" = do
|
| scheme == "file" = do
|
||||||
let destFile' = T.unpack . decUTF8Safe $ view pathL' uri
|
let destFile' = T.unpack . decUTF8Safe $ view pathL' rawUri
|
||||||
lift $ logDebug $ "using local file: " <> T.pack destFile'
|
lift $ logDebug $ "using local file: " <> T.pack destFile'
|
||||||
forM_ eDigest (liftE . flip checkDigest destFile')
|
forM_ eDigest (liftE . flip checkDigest destFile')
|
||||||
pure destFile'
|
pure destFile'
|
||||||
| otherwise = throwE $ DownloadFailed (variantFromValue UnsupportedScheme)
|
| otherwise = throwE $ DownloadFailed (variantFromValue UnsupportedScheme)
|
||||||
|
|
||||||
where
|
where
|
||||||
scheme = view (uriSchemeL' % schemeBSL') uri
|
scheme = view (uriSchemeL' % schemeBSL') rawUri
|
||||||
dl = do
|
dl = do
|
||||||
|
Settings{ mirrors } <- lift getSettings
|
||||||
|
let uri = applyMirrors mirrors rawUri
|
||||||
baseDestFile <- liftE . reThrowAll @_ @_ @'[DownloadFailed] DownloadFailed $ getDestFile uri mfn
|
baseDestFile <- liftE . reThrowAll @_ @_ @'[DownloadFailed] DownloadFailed $ getDestFile uri mfn
|
||||||
lift $ logInfo $ "downloading: " <> (decUTF8Safe . serializeURIRef') uri <> " as file " <> T.pack baseDestFile
|
lift $ logInfo $ "downloading: " <> (decUTF8Safe . serializeURIRef') uri <> " as file " <> T.pack baseDestFile
|
||||||
|
|
||||||
@@ -351,7 +358,7 @@ download uri gpgUri eDigest dest mfn etags
|
|||||||
-- download
|
-- download
|
||||||
flip onException
|
flip onException
|
||||||
(lift $ hideError doesNotExistErrorType $ recycleFile (tmpFile baseDestFile))
|
(lift $ hideError doesNotExistErrorType $ recycleFile (tmpFile baseDestFile))
|
||||||
$ catchAllE @_ @'[GPGError, ProcessError, DownloadFailed, UnsupportedScheme, DigestError] @'[DigestError, DownloadFailed, GPGError]
|
$ catchAllE @_ @'[GPGError, ProcessError, DownloadFailed, UnsupportedScheme, DigestError, ContentLengthError] @'[DigestError, ContentLengthError, DownloadFailed, GPGError]
|
||||||
(\e' -> do
|
(\e' -> do
|
||||||
lift $ hideError doesNotExistErrorType $ recycleFile (tmpFile baseDestFile)
|
lift $ hideError doesNotExistErrorType $ recycleFile (tmpFile baseDestFile)
|
||||||
case e' of
|
case e' of
|
||||||
@@ -386,7 +393,7 @@ download uri gpgUri eDigest dest mfn etags
|
|||||||
liftE $ flip onException
|
liftE $ flip onException
|
||||||
(lift $ hideError doesNotExistErrorType $ recycleFile (tmpFile gpgDestFile))
|
(lift $ hideError doesNotExistErrorType $ recycleFile (tmpFile gpgDestFile))
|
||||||
$ catchAllE @_ @'[GPGError, ProcessError, UnsupportedScheme, DownloadFailed] @'[GPGError]
|
$ catchAllE @_ @'[GPGError, ProcessError, UnsupportedScheme, DownloadFailed] @'[GPGError]
|
||||||
(\e -> if gpgSetting == GPGStrict then throwE (GPGError e) else lift $ logWarn $ T.pack (prettyShow (GPGError e))
|
(\e -> if gpgSetting == GPGStrict then throwE (GPGError e) else lift $ logWarn $ T.pack (prettyHFError (GPGError e))
|
||||||
) $ do
|
) $ do
|
||||||
o' <- liftIO getGpgOpts
|
o' <- liftIO getGpgOpts
|
||||||
lift $ logDebug $ "downloading: " <> (decUTF8Safe . serializeURIRef') gpgUri' <> " as file " <> T.pack gpgDestFile
|
lift $ logDebug $ "downloading: " <> (decUTF8Safe . serializeURIRef') gpgUri' <> " as file " <> T.pack gpgDestFile
|
||||||
@@ -401,19 +408,37 @@ download uri gpgUri eDigest dest mfn etags
|
|||||||
CapturedProcess { _stdErr } -> lift $ logDebug $ decUTF8Safe' _stdErr
|
CapturedProcess { _stdErr } -> lift $ logDebug $ decUTF8Safe' _stdErr
|
||||||
_ -> pure ()
|
_ -> pure ()
|
||||||
|
|
||||||
|
forM_ eCSize (liftE . flip checkCSize baseDestFile)
|
||||||
forM_ eDigest (liftE . flip checkDigest baseDestFile)
|
forM_ eDigest (liftE . flip checkDigest baseDestFile)
|
||||||
pure baseDestFile
|
pure baseDestFile
|
||||||
|
|
||||||
curlDL :: (MonadCatch m, MonadMask m, MonadIO m) => [String] -> FilePath -> URI -> Excepts '[ProcessError, DownloadFailed, UnsupportedScheme] m ()
|
curlDL :: ( MonadCatch m
|
||||||
|
, MonadMask m
|
||||||
|
, MonadIO m
|
||||||
|
)
|
||||||
|
=> [String]
|
||||||
|
-> FilePath
|
||||||
|
-> URI
|
||||||
|
-> Excepts '[ProcessError, DownloadFailed, UnsupportedScheme] m ()
|
||||||
curlDL o' destFile (decUTF8Safe . serializeURIRef' -> uri') = do
|
curlDL o' destFile (decUTF8Safe . serializeURIRef' -> uri') = do
|
||||||
let destFileTemp = tmpFile destFile
|
let destFileTemp = tmpFile destFile
|
||||||
flip finally (try @_ @SomeException $ rmFile destFileTemp) $ do
|
flip finally (try @_ @SomeException $ rmFile destFileTemp) $ do
|
||||||
liftE $ lEM @_ @'[ProcessError] $ exec "curl"
|
liftE $ lEM @_ @'[ProcessError] $ exec "curl"
|
||||||
(o' ++ ["-fL", "-o", destFileTemp, T.unpack uri']) Nothing Nothing
|
(o' ++ ["-fL", "-o", destFileTemp, T.unpack uri']
|
||||||
|
++ maybe [] (\s -> ["--max-filesize", show s]) eCSize
|
||||||
|
) Nothing Nothing
|
||||||
liftIO $ renameFile destFileTemp destFile
|
liftIO $ renameFile destFileTemp destFile
|
||||||
|
|
||||||
curlEtagsDL :: (MonadReader env m, HasLog env, MonadCatch m, MonadMask m, MonadIO m)
|
curlEtagsDL :: ( MonadReader env m
|
||||||
=> [String] -> FilePath -> URI -> Excepts '[ProcessError, DownloadFailed, UnsupportedScheme] m ()
|
, HasLog env
|
||||||
|
, MonadCatch m
|
||||||
|
, MonadMask m
|
||||||
|
, MonadIO m
|
||||||
|
)
|
||||||
|
=> [String]
|
||||||
|
-> FilePath
|
||||||
|
-> URI
|
||||||
|
-> Excepts '[ProcessError, DownloadFailed, UnsupportedScheme] m ()
|
||||||
curlEtagsDL o' destFile (decUTF8Safe . serializeURIRef' -> uri') = do
|
curlEtagsDL o' destFile (decUTF8Safe . serializeURIRef' -> uri') = do
|
||||||
let destFileTemp = tmpFile destFile
|
let destFileTemp = tmpFile destFile
|
||||||
dh <- liftIO $ emptySystemTempFile "curl-header"
|
dh <- liftIO $ emptySystemTempFile "curl-header"
|
||||||
@@ -440,7 +465,14 @@ download uri gpgUri eDigest dest mfn etags
|
|||||||
|
|
||||||
lift $ writeEtags destFile (parseEtags headers)
|
lift $ writeEtags destFile (parseEtags headers)
|
||||||
|
|
||||||
wgetDL :: (MonadCatch m, MonadMask m, MonadIO m) => [String] -> FilePath -> URI -> Excepts '[ProcessError, DownloadFailed, UnsupportedScheme] m ()
|
wgetDL :: ( MonadCatch m
|
||||||
|
, MonadMask m
|
||||||
|
, MonadIO m
|
||||||
|
)
|
||||||
|
=> [String]
|
||||||
|
-> FilePath
|
||||||
|
-> URI
|
||||||
|
-> Excepts '[ProcessError, DownloadFailed, UnsupportedScheme] m ()
|
||||||
wgetDL o' destFile (decUTF8Safe . serializeURIRef' -> uri') = do
|
wgetDL o' destFile (decUTF8Safe . serializeURIRef' -> uri') = do
|
||||||
let destFileTemp = tmpFile destFile
|
let destFileTemp = tmpFile destFile
|
||||||
flip finally (try @_ @SomeException $ rmFile destFileTemp) $ do
|
flip finally (try @_ @SomeException $ rmFile destFileTemp) $ do
|
||||||
@@ -449,8 +481,16 @@ download uri gpgUri eDigest dest mfn etags
|
|||||||
liftIO $ renameFile destFileTemp destFile
|
liftIO $ renameFile destFileTemp destFile
|
||||||
|
|
||||||
|
|
||||||
wgetEtagsDL :: (MonadReader env m, HasLog env, MonadCatch m, MonadMask m, MonadIO m)
|
wgetEtagsDL :: ( MonadReader env m
|
||||||
=> [String] -> FilePath -> URI -> Excepts '[ProcessError, DownloadFailed, UnsupportedScheme] m ()
|
, HasLog env
|
||||||
|
, MonadCatch m
|
||||||
|
, MonadMask m
|
||||||
|
, MonadIO m
|
||||||
|
)
|
||||||
|
=> [String]
|
||||||
|
-> FilePath
|
||||||
|
-> URI
|
||||||
|
-> Excepts '[ProcessError, DownloadFailed, UnsupportedScheme] m ()
|
||||||
wgetEtagsDL o' destFile (decUTF8Safe . serializeURIRef' -> uri') = do
|
wgetEtagsDL o' destFile (decUTF8Safe . serializeURIRef' -> uri') = do
|
||||||
let destFileTemp = tmpFile destFile
|
let destFileTemp = tmpFile destFile
|
||||||
flip finally (try @_ @SomeException $ rmFile destFileTemp) $ do
|
flip finally (try @_ @SomeException $ rmFile destFileTemp) $ do
|
||||||
@@ -471,7 +511,10 @@ download uri gpgUri eDigest dest mfn etags
|
|||||||
| otherwise -> throwE (NonZeroExit i' "wget" opts)
|
| otherwise -> throwE (NonZeroExit i' "wget" opts)
|
||||||
|
|
||||||
#if defined(INTERNAL_DOWNLOADER)
|
#if defined(INTERNAL_DOWNLOADER)
|
||||||
internalDL :: (MonadCatch m, MonadMask m, MonadIO m)
|
internalDL :: ( MonadCatch m
|
||||||
|
, MonadMask m
|
||||||
|
, MonadIO m
|
||||||
|
)
|
||||||
=> FilePath -> URI -> Excepts '[DownloadFailed, UnsupportedScheme] m ()
|
=> FilePath -> URI -> Excepts '[DownloadFailed, UnsupportedScheme] m ()
|
||||||
internalDL destFile uri' = do
|
internalDL destFile uri' = do
|
||||||
let destFileTemp = tmpFile destFile
|
let destFileTemp = tmpFile destFile
|
||||||
@@ -481,11 +524,16 @@ download uri gpgUri eDigest dest mfn etags
|
|||||||
@'[DownloadFailed]
|
@'[DownloadFailed]
|
||||||
(\e@(HTTPNotModified _) ->
|
(\e@(HTTPNotModified _) ->
|
||||||
throwE @_ @'[DownloadFailed] (DownloadFailed (toVariantAt @0 e :: V '[HTTPNotModified])))
|
throwE @_ @'[DownloadFailed] (DownloadFailed (toVariantAt @0 e :: V '[HTTPNotModified])))
|
||||||
$ downloadToFile https host fullPath port destFileTemp mempty
|
$ downloadToFile https host fullPath port destFileTemp mempty eCSize
|
||||||
liftIO $ renameFile destFileTemp destFile
|
liftIO $ renameFile destFileTemp destFile
|
||||||
|
|
||||||
|
|
||||||
internalEtagsDL :: (MonadReader env m, HasLog env, MonadCatch m, MonadMask m, MonadIO m)
|
internalEtagsDL :: ( MonadReader env m
|
||||||
|
, HasLog env
|
||||||
|
, MonadCatch m
|
||||||
|
, MonadMask m
|
||||||
|
, MonadIO m
|
||||||
|
)
|
||||||
=> FilePath -> URI -> Excepts '[DownloadFailed, UnsupportedScheme] m ()
|
=> FilePath -> URI -> Excepts '[DownloadFailed, UnsupportedScheme] m ()
|
||||||
internalEtagsDL destFile uri' = do
|
internalEtagsDL destFile uri' = do
|
||||||
let destFileTemp = tmpFile destFile
|
let destFileTemp = tmpFile destFile
|
||||||
@@ -497,7 +545,7 @@ download uri gpgUri eDigest dest mfn etags
|
|||||||
liftE
|
liftE
|
||||||
$ catchE @HTTPNotModified @'[DownloadFailed] @'[] (\(HTTPNotModified etag) -> lift $ writeEtags destFile (pure $ Just etag))
|
$ catchE @HTTPNotModified @'[DownloadFailed] @'[] (\(HTTPNotModified etag) -> lift $ writeEtags destFile (pure $ Just etag))
|
||||||
$ do
|
$ do
|
||||||
r <- downloadToFile https host fullPath port destFileTemp addHeaders
|
r <- downloadToFile https host fullPath port destFileTemp addHeaders eCSize
|
||||||
liftIO $ renameFile destFileTemp destFile
|
liftIO $ renameFile destFileTemp destFile
|
||||||
lift $ writeEtags destFile (pure $ decUTF8Safe <$> getHeader r "etag")
|
lift $ writeEtags destFile (pure $ decUTF8Safe <$> getHeader r "etag")
|
||||||
#endif
|
#endif
|
||||||
@@ -505,7 +553,7 @@ download uri gpgUri eDigest dest mfn etags
|
|||||||
|
|
||||||
-- Manage to find a file we can write the body into.
|
-- Manage to find a file we can write the body into.
|
||||||
getDestFile :: Monad m => URI -> Maybe FilePath -> Excepts '[NoUrlBase] m FilePath
|
getDestFile :: Monad m => URI -> Maybe FilePath -> Excepts '[NoUrlBase] m FilePath
|
||||||
getDestFile uri' mfn' =
|
getDestFile uri' mfn' =
|
||||||
let path = view pathL' uri'
|
let path = view pathL' uri'
|
||||||
in case mfn' of
|
in case mfn' of
|
||||||
Just fn -> pure (dest </> fn)
|
Just fn -> pure (dest </> fn)
|
||||||
@@ -574,14 +622,14 @@ downloadCached :: ( MonadReader env m
|
|||||||
)
|
)
|
||||||
=> DownloadInfo
|
=> DownloadInfo
|
||||||
-> Maybe FilePath -- ^ optional filename
|
-> Maybe FilePath -- ^ optional filename
|
||||||
-> Excepts '[DigestError , DownloadFailed, GPGError] m FilePath
|
-> Excepts '[DigestError, ContentLengthError, DownloadFailed, GPGError] m FilePath
|
||||||
downloadCached dli mfn = do
|
downloadCached dli mfn = do
|
||||||
Settings{ cache } <- lift getSettings
|
Settings{ cache } <- lift getSettings
|
||||||
case cache of
|
case cache of
|
||||||
True -> downloadCached' dli mfn Nothing
|
True -> downloadCached' dli mfn Nothing
|
||||||
False -> do
|
False -> do
|
||||||
tmp <- lift withGHCupTmpDir
|
tmp <- lift withGHCupTmpDir
|
||||||
liftE $ download (_dlUri dli) Nothing (Just (_dlHash dli)) (fromGHCupPath tmp) mfn False
|
liftE $ download (_dlUri dli) Nothing (Just (_dlHash dli)) (_dlCSize dli) (fromGHCupPath tmp) mfn False
|
||||||
|
|
||||||
|
|
||||||
downloadCached' :: ( MonadReader env m
|
downloadCached' :: ( MonadReader env m
|
||||||
@@ -596,7 +644,7 @@ downloadCached' :: ( MonadReader env m
|
|||||||
=> DownloadInfo
|
=> DownloadInfo
|
||||||
-> Maybe FilePath -- ^ optional filename
|
-> Maybe FilePath -- ^ optional filename
|
||||||
-> Maybe FilePath -- ^ optional destination dir (default: cacheDir)
|
-> Maybe FilePath -- ^ optional destination dir (default: cacheDir)
|
||||||
-> Excepts '[DigestError , DownloadFailed, GPGError] m FilePath
|
-> Excepts '[DigestError, ContentLengthError, DownloadFailed, GPGError] m FilePath
|
||||||
downloadCached' dli mfn mDestDir = do
|
downloadCached' dli mfn mDestDir = do
|
||||||
Dirs { cacheDir } <- lift getDirs
|
Dirs { cacheDir } <- lift getDirs
|
||||||
let destDir = fromMaybe (fromGHCupPath cacheDir) mDestDir
|
let destDir = fromMaybe (fromGHCupPath cacheDir) mDestDir
|
||||||
@@ -605,9 +653,10 @@ downloadCached' dli mfn mDestDir = do
|
|||||||
fileExists <- liftIO $ doesFileExist cachfile
|
fileExists <- liftIO $ doesFileExist cachfile
|
||||||
if
|
if
|
||||||
| fileExists -> do
|
| fileExists -> do
|
||||||
|
forM_ (view dlCSize dli) $ \s -> liftE $ checkCSize s cachfile
|
||||||
liftE $ checkDigest (view dlHash dli) cachfile
|
liftE $ checkDigest (view dlHash dli) cachfile
|
||||||
pure cachfile
|
pure cachfile
|
||||||
| otherwise -> liftE $ download (_dlUri dli) Nothing (Just (_dlHash dli)) destDir mfn False
|
| otherwise -> liftE $ download (_dlUri dli) Nothing (Just (_dlHash dli)) (_dlCSize dli) destDir mfn False
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -638,6 +687,25 @@ checkDigest eDigest file = do
|
|||||||
cDigest <- throwEither . E.decodeUtf8' . B16.encode . SHA256.hashlazy $ c
|
cDigest <- throwEither . E.decodeUtf8' . B16.encode . SHA256.hashlazy $ c
|
||||||
when ((cDigest /= eDigest) && verify) $ throwE (DigestError file cDigest eDigest)
|
when ((cDigest /= eDigest) && verify) $ throwE (DigestError file cDigest eDigest)
|
||||||
|
|
||||||
|
checkCSize :: ( MonadReader env m
|
||||||
|
, HasDirs env
|
||||||
|
, HasSettings env
|
||||||
|
, MonadIO m
|
||||||
|
, MonadThrow m
|
||||||
|
, HasLog env
|
||||||
|
)
|
||||||
|
=> Integer
|
||||||
|
-> FilePath
|
||||||
|
-> Excepts '[ContentLengthError] m ()
|
||||||
|
checkCSize eCSize file = do
|
||||||
|
Settings{ noVerify } <- lift getSettings
|
||||||
|
let verify = not noVerify
|
||||||
|
when verify $ do
|
||||||
|
let p' = takeFileName file
|
||||||
|
lift $ logInfo $ "verifying content length of: " <> T.pack p'
|
||||||
|
cSize <- liftIO $ getFileSize file
|
||||||
|
when ((eCSize /= cSize) && verify) $ throwE (ContentLengthError (Just file) (Just cSize) eCSize)
|
||||||
|
|
||||||
|
|
||||||
-- | Get additional curl args from env. This is an undocumented option.
|
-- | Get additional curl args from env. This is an undocumented option.
|
||||||
getCurlOpts :: IO [String]
|
getCurlOpts :: IO [String]
|
||||||
@@ -685,3 +753,17 @@ getLastHeader = T.unlines . lastDef [] . filter (\x -> not (null x)) . splitOn [
|
|||||||
|
|
||||||
tmpFile :: FilePath -> FilePath
|
tmpFile :: FilePath -> FilePath
|
||||||
tmpFile = (<.> "tmp")
|
tmpFile = (<.> "tmp")
|
||||||
|
|
||||||
|
|
||||||
|
applyMirrors :: DownloadMirrors -> URI -> URI
|
||||||
|
applyMirrors (DM ms) uri@(URI { uriAuthority = Just (Authority { authorityHost = Host host }) }) =
|
||||||
|
case M.lookup (decUTF8Safe host) ms of
|
||||||
|
Nothing -> uri
|
||||||
|
Just (DownloadMirror auth (Just prefix)) ->
|
||||||
|
uri { uriAuthority = Just auth
|
||||||
|
, uriPath = E.encodeUtf8 $ T.pack ("/" <> T.unpack prefix <> (T.unpack . decUTF8Safe . uriPath $ uri))
|
||||||
|
}
|
||||||
|
Just (DownloadMirror auth Nothing) ->
|
||||||
|
uri { uriAuthority = Just auth }
|
||||||
|
applyMirrors _ uri = uri
|
||||||
|
|
||||||
|
|||||||
@@ -17,14 +17,12 @@ import Control.Exception.Safe
|
|||||||
import Control.Monad
|
import Control.Monad
|
||||||
import Control.Monad.Reader
|
import Control.Monad.Reader
|
||||||
import Data.ByteString ( ByteString )
|
import Data.ByteString ( ByteString )
|
||||||
import Data.ByteString.Builder
|
|
||||||
import Data.CaseInsensitive ( CI, original, mk )
|
import Data.CaseInsensitive ( CI, original, mk )
|
||||||
import Data.IORef
|
import Data.IORef
|
||||||
import Data.Maybe
|
import Data.Maybe
|
||||||
import Data.Text.Read
|
import Data.Text.Read
|
||||||
import Haskus.Utils.Variant.Excepts
|
import Haskus.Utils.Variant.Excepts
|
||||||
import Network.Http.Client hiding ( URL )
|
import Network.Http.Client hiding ( URL )
|
||||||
import Optics
|
|
||||||
import Prelude hiding ( abs
|
import Prelude hiding ( abs
|
||||||
, readFile
|
, readFile
|
||||||
, writeFile
|
, writeFile
|
||||||
@@ -33,7 +31,6 @@ import System.ProgressBar
|
|||||||
import URI.ByteString
|
import URI.ByteString
|
||||||
|
|
||||||
import qualified Data.ByteString as BS
|
import qualified Data.ByteString as BS
|
||||||
import qualified Data.ByteString.Lazy as L
|
|
||||||
import qualified Data.Map.Strict as M
|
import qualified Data.Map.Strict as M
|
||||||
import qualified System.IO.Streams as Streams
|
import qualified System.IO.Streams as Streams
|
||||||
|
|
||||||
@@ -46,27 +43,6 @@ import qualified System.IO.Streams as Streams
|
|||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
|
|
||||||
-- | 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)
|
|
||||||
void $ downloadInternal False https host path port stepper (pure ()) mempty
|
|
||||||
liftIO (readIORef bref <&> toLazyByteString)
|
|
||||||
|
|
||||||
|
|
||||||
downloadToFile :: (MonadMask m, MonadIO m)
|
downloadToFile :: (MonadMask m, MonadIO m)
|
||||||
=> Bool -- ^ https?
|
=> Bool -- ^ https?
|
||||||
@@ -75,8 +51,9 @@ downloadToFile :: (MonadMask m, MonadIO m)
|
|||||||
-> Maybe Int -- ^ optional port (e.g. 3000)
|
-> Maybe Int -- ^ optional port (e.g. 3000)
|
||||||
-> FilePath -- ^ destination file to create and write to
|
-> FilePath -- ^ destination file to create and write to
|
||||||
-> M.Map (CI ByteString) ByteString -- ^ additional headers
|
-> M.Map (CI ByteString) ByteString -- ^ additional headers
|
||||||
|
-> Maybe Integer -- ^ expected content length
|
||||||
-> Excepts '[DownloadFailed, HTTPNotModified] m Response
|
-> Excepts '[DownloadFailed, HTTPNotModified] m Response
|
||||||
downloadToFile https host fullPath port destFile addHeaders = do
|
downloadToFile https host fullPath port destFile addHeaders eCSize = do
|
||||||
let stepper = BS.appendFile destFile
|
let stepper = BS.appendFile destFile
|
||||||
setup = BS.writeFile destFile mempty
|
setup = BS.writeFile destFile mempty
|
||||||
catchAllE (\case
|
catchAllE (\case
|
||||||
@@ -84,7 +61,7 @@ downloadToFile https host fullPath port destFile addHeaders = do
|
|||||||
| i == 304
|
| i == 304
|
||||||
, Just e <- M.lookup (mk "etag") headers -> throwE $ HTTPNotModified (decUTF8Safe e)
|
, Just e <- M.lookup (mk "etag") headers -> throwE $ HTTPNotModified (decUTF8Safe e)
|
||||||
v -> throwE $ DownloadFailed v
|
v -> throwE $ DownloadFailed v
|
||||||
) $ downloadInternal True https host fullPath port stepper setup addHeaders
|
) $ downloadInternal True https host fullPath port stepper setup addHeaders eCSize
|
||||||
|
|
||||||
|
|
||||||
downloadInternal :: MonadIO m
|
downloadInternal :: MonadIO m
|
||||||
@@ -96,19 +73,21 @@ downloadInternal :: MonadIO m
|
|||||||
-> (ByteString -> IO a) -- ^ the consuming step function
|
-> (ByteString -> IO a) -- ^ the consuming step function
|
||||||
-> IO a -- ^ setup action
|
-> IO a -- ^ setup action
|
||||||
-> M.Map (CI ByteString) ByteString -- ^ additional headers
|
-> M.Map (CI ByteString) ByteString -- ^ additional headers
|
||||||
|
-> Maybe Integer
|
||||||
-> Excepts
|
-> Excepts
|
||||||
'[ HTTPStatusError
|
'[ HTTPStatusError
|
||||||
, URIParseError
|
, URIParseError
|
||||||
, UnsupportedScheme
|
, UnsupportedScheme
|
||||||
, NoLocationHeader
|
, NoLocationHeader
|
||||||
, TooManyRedirs
|
, TooManyRedirs
|
||||||
|
, ContentLengthError
|
||||||
]
|
]
|
||||||
m
|
m
|
||||||
Response
|
Response
|
||||||
downloadInternal = go (5 :: Int)
|
downloadInternal = go (5 :: Int)
|
||||||
|
|
||||||
where
|
where
|
||||||
go redirs progressBar https host path port consumer setup addHeaders = do
|
go redirs progressBar https host path port consumer setup addHeaders eCSize = do
|
||||||
r <- liftIO $ withConnection' https host port action
|
r <- liftIO $ withConnection' https host port action
|
||||||
veitherToExcepts r >>= \case
|
veitherToExcepts r >>= \case
|
||||||
Right r' ->
|
Right r' ->
|
||||||
@@ -138,25 +117,39 @@ downloadInternal = go (5 :: Int)
|
|||||||
followRedirectURL bs = case parseURI strictURIParserOptions bs of
|
followRedirectURL bs = case parseURI strictURIParserOptions bs of
|
||||||
Right uri' -> do
|
Right uri' -> do
|
||||||
(https', host', fullPath', port') <- liftE $ uriToQuadruple uri'
|
(https', host', fullPath', port') <- liftE $ uriToQuadruple uri'
|
||||||
go (redirs - 1) progressBar https' host' fullPath' port' consumer setup addHeaders
|
go (redirs - 1) progressBar https' host' fullPath' port' consumer setup addHeaders eCSize
|
||||||
Left e -> throwE e
|
Left e -> throwE e
|
||||||
|
|
||||||
downloadStream r i' = do
|
downloadStream r i' = do
|
||||||
void setup
|
void setup
|
||||||
let size = case getHeader r "Content-Length" of
|
let size = case getHeader r "Content-Length" of
|
||||||
Just x' -> case decimal $ decUTF8Safe x' of
|
Just x' -> case decimal $ decUTF8Safe x' of
|
||||||
Left _ -> 0
|
Left _ -> Nothing
|
||||||
Right (r', _) -> r'
|
Right (r', _) -> Just r'
|
||||||
Nothing -> 0
|
Nothing -> Nothing
|
||||||
|
|
||||||
(mpb :: Maybe (ProgressBar ())) <- if progressBar
|
forM_ size $ \s -> forM_ eCSize $ \es -> when (es /= s) $ throwIO (ContentLengthError Nothing (Just s) es)
|
||||||
then Just <$> newProgressBar defStyle 10 (Progress 0 size ())
|
let size' = eCSize <|> size
|
||||||
else pure Nothing
|
|
||||||
|
(mpb :: Maybe (ProgressBar ())) <- case (progressBar, size') of
|
||||||
|
(True, Just size'') -> Just <$> newProgressBar defStyle 10 (Progress 0 (fromInteger size'') ())
|
||||||
|
_ -> pure Nothing
|
||||||
|
|
||||||
|
ior <- liftIO $ newIORef 0
|
||||||
|
|
||||||
outStream <- liftIO $ Streams.makeOutputStream
|
outStream <- liftIO $ Streams.makeOutputStream
|
||||||
(\case
|
(\case
|
||||||
Just bs -> do
|
Just bs -> do
|
||||||
forM_ mpb $ \pb -> incProgress pb (BS.length bs)
|
let len = BS.length bs
|
||||||
|
forM_ mpb $ \pb -> incProgress pb len
|
||||||
|
|
||||||
|
-- check we don't exceed size
|
||||||
|
forM_ size' $ \s -> do
|
||||||
|
cs <- readIORef ior
|
||||||
|
when ((cs + toInteger len) > s) $ throwIO (ContentLengthError Nothing (Just (cs + toInteger len)) s)
|
||||||
|
|
||||||
|
modifyIORef ior (+ toInteger len)
|
||||||
|
|
||||||
void $ consumer bs
|
void $ consumer bs
|
||||||
Nothing -> pure ()
|
Nothing -> pure ()
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
{-# LANGUAGE StandaloneDeriving #-}
|
{-# LANGUAGE StandaloneDeriving #-}
|
||||||
{-# LANGUAGE TypeOperators #-}
|
{-# LANGUAGE TypeOperators #-}
|
||||||
{-# LANGUAGE FlexibleInstances #-}
|
{-# LANGUAGE FlexibleInstances #-}
|
||||||
|
{-# LANGUAGE RankNTypes #-}
|
||||||
|
|
||||||
{-|
|
{-|
|
||||||
Module : GHCup.Errors
|
Module : GHCup.Errors
|
||||||
@@ -34,9 +35,153 @@ import URI.ByteString
|
|||||||
|
|
||||||
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
|
||||||
|
import Data.Data (Proxy(..))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
allHFError :: String
|
||||||
|
allHFError = unlines allErrors
|
||||||
|
where
|
||||||
|
format p = "GHCup-" <> show (eBase p) <> " " <> eDesc p
|
||||||
|
format'' e p = "GHCup-" <> show (eNum e) <> " " <> eDesc p
|
||||||
|
format' e _ = "GHCup-" <> show (eNum e) <> " " <> prettyShow e
|
||||||
|
format''' e _ str' = "GHCup-" <> show (eNum e) <> " " <> str'
|
||||||
|
allErrors =
|
||||||
|
[ "# low level errors (1 to 500)"
|
||||||
|
, let proxy = Proxy :: Proxy NoCompatiblePlatform in format proxy
|
||||||
|
, let proxy = Proxy :: Proxy NoDownload in format proxy
|
||||||
|
, let proxy = Proxy :: Proxy NoUpdate in format proxy
|
||||||
|
, let proxy = Proxy :: Proxy DistroNotFound in format proxy
|
||||||
|
, let proxy = Proxy :: Proxy UnknownArchive in format proxy
|
||||||
|
, let proxy = Proxy :: Proxy UnsupportedScheme in format proxy
|
||||||
|
, let proxy = Proxy :: Proxy CopyError in format proxy
|
||||||
|
, let proxy = Proxy :: Proxy MergeFileTreeError in format proxy
|
||||||
|
, let proxy = Proxy :: Proxy TagNotFound in format proxy
|
||||||
|
, let proxy = Proxy :: Proxy NextVerNotFound in format proxy
|
||||||
|
, let proxy = Proxy :: Proxy AlreadyInstalled in format proxy
|
||||||
|
, let proxy = Proxy :: Proxy DirNotEmpty in format proxy
|
||||||
|
, let proxy = Proxy :: Proxy NotInstalled in format proxy
|
||||||
|
, let proxy = Proxy :: Proxy UninstallFailed in format proxy
|
||||||
|
, let proxy = Proxy :: Proxy NotFoundInPATH in format proxy
|
||||||
|
, let proxy = Proxy :: Proxy JSONError in format proxy
|
||||||
|
, let proxy = Proxy :: Proxy FileDoesNotExistError in format proxy
|
||||||
|
, let proxy = Proxy :: Proxy FileAlreadyExistsError in format proxy
|
||||||
|
, let proxy = Proxy :: Proxy TarDirDoesNotExist in format proxy
|
||||||
|
, let proxy = Proxy :: Proxy DigestError in format proxy
|
||||||
|
, let proxy = Proxy :: Proxy GPGError in format proxy
|
||||||
|
, let proxy = Proxy :: Proxy HTTPStatusError in format proxy
|
||||||
|
, let proxy = Proxy :: Proxy MalformedHeaders in format proxy
|
||||||
|
, let proxy = Proxy :: Proxy HTTPNotModified in format proxy
|
||||||
|
, let proxy = Proxy :: Proxy NoLocationHeader in format proxy
|
||||||
|
, let proxy = Proxy :: Proxy TooManyRedirs in format proxy
|
||||||
|
, let proxy = Proxy :: Proxy PatchFailed in format proxy
|
||||||
|
, let proxy = Proxy :: Proxy NoToolRequirements in format proxy
|
||||||
|
, let proxy = Proxy :: Proxy InvalidBuildConfig in format proxy
|
||||||
|
, let proxy = Proxy :: Proxy NoToolVersionSet in format proxy
|
||||||
|
, let proxy = Proxy :: Proxy NoNetwork in format proxy
|
||||||
|
, let proxy = Proxy :: Proxy HadrianNotFound in format proxy
|
||||||
|
, let proxy = Proxy :: Proxy ToolShadowed in format proxy
|
||||||
|
, let proxy = Proxy :: Proxy ContentLengthError in format proxy
|
||||||
|
, ""
|
||||||
|
, "# high level errors (4000+)"
|
||||||
|
, let proxy = Proxy :: Proxy DownloadFailed in format proxy
|
||||||
|
, let proxy = Proxy :: Proxy InstallSetError in format proxy
|
||||||
|
, let proxy = Proxy :: Proxy TestFailed in format proxy
|
||||||
|
, let proxy = Proxy :: Proxy BuildFailed in format proxy
|
||||||
|
, let proxy = Proxy :: Proxy GHCupSetError in format proxy
|
||||||
|
, ""
|
||||||
|
, "# true exceptions (500+)"
|
||||||
|
, let proxy = Proxy :: Proxy ParseError in format proxy
|
||||||
|
, let proxy = Proxy :: Proxy UnexpectedListLength in format proxy
|
||||||
|
, let proxy = Proxy :: Proxy NoUrlBase in format proxy
|
||||||
|
, ""
|
||||||
|
, "# orphans (800+)"
|
||||||
|
, let proxy = Proxy :: Proxy URIParseError in format proxy
|
||||||
|
, let proxy = Proxy :: Proxy URIParseError
|
||||||
|
e = MalformedScheme MissingColon
|
||||||
|
in format' e proxy
|
||||||
|
, let proxy = Proxy :: Proxy URIParseError
|
||||||
|
e = MalformedUserInfo
|
||||||
|
in format' e proxy
|
||||||
|
, let proxy = Proxy :: Proxy URIParseError
|
||||||
|
e = MalformedQuery
|
||||||
|
in format' e proxy
|
||||||
|
, let proxy = Proxy :: Proxy URIParseError
|
||||||
|
e = MalformedFragment
|
||||||
|
in format' e proxy
|
||||||
|
, let proxy = Proxy :: Proxy URIParseError
|
||||||
|
e = MalformedHost
|
||||||
|
in format' e proxy
|
||||||
|
, let proxy = Proxy :: Proxy URIParseError
|
||||||
|
e = MalformedPort
|
||||||
|
in format' e proxy
|
||||||
|
, let proxy = Proxy :: Proxy URIParseError
|
||||||
|
e = MalformedPath
|
||||||
|
in format' e proxy
|
||||||
|
, let proxy = Proxy :: Proxy URIParseError
|
||||||
|
e = OtherError ""
|
||||||
|
in format'' e proxy
|
||||||
|
, let proxy = Proxy :: Proxy ArchiveResult in format proxy
|
||||||
|
, let proxy = Proxy :: Proxy ArchiveResult
|
||||||
|
e = ArchiveFatal
|
||||||
|
in format' e proxy
|
||||||
|
, let proxy = Proxy :: Proxy ArchiveResult
|
||||||
|
e = ArchiveFailed
|
||||||
|
in format' e proxy
|
||||||
|
, let proxy = Proxy :: Proxy ArchiveResult
|
||||||
|
e = ArchiveWarn
|
||||||
|
in format' e proxy
|
||||||
|
, let proxy = Proxy :: Proxy ArchiveResult
|
||||||
|
e = ArchiveRetry
|
||||||
|
in format' e proxy
|
||||||
|
, let proxy = Proxy :: Proxy ArchiveResult
|
||||||
|
e = ArchiveOk
|
||||||
|
in format' e proxy
|
||||||
|
, let proxy = Proxy :: Proxy ArchiveResult
|
||||||
|
e = ArchiveEOF
|
||||||
|
in format' e proxy
|
||||||
|
|
||||||
|
, let proxy = Proxy :: Proxy ProcessError in format proxy
|
||||||
|
, let proxy = Proxy :: Proxy ProcessError
|
||||||
|
e = NonZeroExit 0 "" []
|
||||||
|
in format''' e proxy "A process returned a non-zero exit code."
|
||||||
|
, let proxy = Proxy :: Proxy ProcessError
|
||||||
|
e = PTerminated "" []
|
||||||
|
in format''' e proxy "A process terminated prematurely."
|
||||||
|
, let proxy = Proxy :: Proxy ProcessError
|
||||||
|
e = PStopped "" []
|
||||||
|
in format''' e proxy "A process stopped prematurely."
|
||||||
|
, let proxy = Proxy :: Proxy ProcessError
|
||||||
|
e = NoSuchPid "" []
|
||||||
|
in format''' e proxy "Could not find PID for this process."
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
prettyHFError :: (Pretty e, HFErrorProject e) => e -> String
|
||||||
|
prettyHFError e =
|
||||||
|
let errorCode = "GHCup-" <> padIntAndShow (eNum e)
|
||||||
|
in ("[" <> linkEscapeCode errorCode (hfErrorLink errorCode) <> "] ") <> prettyShow e
|
||||||
|
where
|
||||||
|
hfErrorLink errorCode = "https://errors.haskell.org/messages/" <> errorCode
|
||||||
|
padIntAndShow i
|
||||||
|
| i < 10 = "0000" <> show i
|
||||||
|
| i < 100 = "000" <> show i
|
||||||
|
| i < 1000 = "00" <> show i
|
||||||
|
| i < 10000 = "0" <> show i
|
||||||
|
| otherwise = show i
|
||||||
|
|
||||||
|
class HFErrorProject a where
|
||||||
|
eNum :: a -> Int
|
||||||
|
eNum _ = eBase (Proxy :: Proxy a)
|
||||||
|
|
||||||
|
eBase :: Proxy a -> Int
|
||||||
|
|
||||||
|
eDesc :: Proxy a -> String
|
||||||
|
|
||||||
|
linkEscapeCode :: String -> String -> String
|
||||||
|
linkEscapeCode linkText link = "\ESC]8;;" <> link <> "\ESC\\" <> linkText <> "\ESC]8;;\ESC\\"
|
||||||
|
|
||||||
|
|
||||||
------------------------
|
------------------------
|
||||||
--[ Low-level errors ]--
|
--[ Low-level errors ]--
|
||||||
------------------------
|
------------------------
|
||||||
@@ -51,20 +196,32 @@ instance Pretty NoCompatiblePlatform where
|
|||||||
pPrint (NoCompatiblePlatform str') =
|
pPrint (NoCompatiblePlatform str') =
|
||||||
text ("Could not find a compatible platform. Got: " ++ str')
|
text ("Could not find a compatible platform. Got: " ++ str')
|
||||||
|
|
||||||
|
instance HFErrorProject NoCompatiblePlatform where
|
||||||
|
eBase _ = 1
|
||||||
|
eDesc _ = "No compatible platform could be found"
|
||||||
|
|
||||||
-- | Unable to find a download for the requested version/distro.
|
-- | Unable to find a download for the requested version/distro.
|
||||||
data NoDownload = NoDownload
|
data NoDownload = NoDownload
|
||||||
deriving Show
|
deriving Show
|
||||||
|
|
||||||
instance Pretty NoDownload where
|
instance Pretty NoDownload where
|
||||||
pPrint NoDownload =
|
pPrint NoDownload =
|
||||||
text "Unable to find a download for the requested version/distro."
|
text (eDesc (Proxy :: Proxy NoDownload))
|
||||||
|
|
||||||
|
instance HFErrorProject NoDownload where
|
||||||
|
eBase _ = 10
|
||||||
|
eDesc _ = "Unable to find a download for the requested version/distro."
|
||||||
|
|
||||||
-- | No update available or necessary.
|
-- | No update available or necessary.
|
||||||
data NoUpdate = NoUpdate
|
data NoUpdate = NoUpdate
|
||||||
deriving Show
|
deriving Show
|
||||||
|
|
||||||
instance Pretty NoUpdate where
|
instance Pretty NoUpdate where
|
||||||
pPrint NoUpdate = text "No update available or necessary."
|
pPrint NoUpdate = text (eDesc (Proxy :: Proxy NoUpdate))
|
||||||
|
|
||||||
|
instance HFErrorProject NoUpdate where
|
||||||
|
eBase _ = 20
|
||||||
|
eDesc _ = "No update available or necessary."
|
||||||
|
|
||||||
-- | The Architecture is unknown and unsupported.
|
-- | The Architecture is unknown and unsupported.
|
||||||
data NoCompatibleArch = NoCompatibleArch String
|
data NoCompatibleArch = NoCompatibleArch String
|
||||||
@@ -74,13 +231,21 @@ instance Pretty NoCompatibleArch where
|
|||||||
pPrint (NoCompatibleArch arch) =
|
pPrint (NoCompatibleArch arch) =
|
||||||
text ("The Architecture is unknown or unsupported. Got: " ++ arch)
|
text ("The Architecture is unknown or unsupported. Got: " ++ arch)
|
||||||
|
|
||||||
|
instance HFErrorProject NoCompatibleArch where
|
||||||
|
eBase _ = 30
|
||||||
|
eDesc _ = "The Architecture is unknown and unsupported"
|
||||||
|
|
||||||
-- | Unable to figure out the distribution of the host.
|
-- | Unable to figure out the distribution of the host.
|
||||||
data DistroNotFound = DistroNotFound
|
data DistroNotFound = DistroNotFound
|
||||||
deriving Show
|
deriving Show
|
||||||
|
|
||||||
instance Pretty DistroNotFound where
|
instance Pretty DistroNotFound where
|
||||||
pPrint DistroNotFound =
|
pPrint DistroNotFound =
|
||||||
text "Unable to figure out the distribution of the host."
|
text (eDesc (Proxy :: Proxy DistroNotFound))
|
||||||
|
|
||||||
|
instance HFErrorProject DistroNotFound where
|
||||||
|
eBase _ = 40
|
||||||
|
eDesc _ = "Unable to figure out the distribution of the host"
|
||||||
|
|
||||||
-- | The archive format is unknown. We don't know how to extract it.
|
-- | The archive format is unknown. We don't know how to extract it.
|
||||||
data UnknownArchive = UnknownArchive FilePath
|
data UnknownArchive = UnknownArchive FilePath
|
||||||
@@ -90,12 +255,21 @@ instance Pretty UnknownArchive where
|
|||||||
pPrint (UnknownArchive file) =
|
pPrint (UnknownArchive file) =
|
||||||
text $ "The archive format is unknown. We don't know how to extract the file " <> file
|
text $ "The archive format is unknown. We don't know how to extract the file " <> file
|
||||||
|
|
||||||
|
instance HFErrorProject UnknownArchive where
|
||||||
|
eBase _ = 50
|
||||||
|
eDesc _ = "The archive format is unknown. We don't know how to extract it."
|
||||||
|
|
||||||
-- | The scheme is not supported (such as ftp).
|
-- | The scheme is not supported (such as ftp).
|
||||||
data UnsupportedScheme = UnsupportedScheme
|
data UnsupportedScheme = UnsupportedScheme
|
||||||
deriving Show
|
deriving Show
|
||||||
|
|
||||||
instance Pretty UnsupportedScheme where
|
instance Pretty UnsupportedScheme where
|
||||||
pPrint UnsupportedScheme = text "The scheme is not supported (such as ftp)."
|
pPrint UnsupportedScheme =
|
||||||
|
text (eDesc (Proxy :: Proxy UnsupportedScheme))
|
||||||
|
|
||||||
|
instance HFErrorProject UnsupportedScheme where
|
||||||
|
eBase _ = 60
|
||||||
|
eDesc _ = "The scheme is not supported (such as ftp)."
|
||||||
|
|
||||||
-- | Unable to copy a file.
|
-- | Unable to copy a file.
|
||||||
data CopyError = CopyError String
|
data CopyError = CopyError String
|
||||||
@@ -105,6 +279,10 @@ instance Pretty CopyError where
|
|||||||
pPrint (CopyError reason) =
|
pPrint (CopyError reason) =
|
||||||
text ("Unable to copy a file. Reason was: " ++ reason)
|
text ("Unable to copy a file. Reason was: " ++ reason)
|
||||||
|
|
||||||
|
instance HFErrorProject CopyError where
|
||||||
|
eBase _ = 70
|
||||||
|
eDesc _ = "Unable to copy a file."
|
||||||
|
|
||||||
-- | Unable to merge file trees.
|
-- | Unable to merge file trees.
|
||||||
data MergeFileTreeError = MergeFileTreeError IOException FilePath FilePath
|
data MergeFileTreeError = MergeFileTreeError IOException FilePath FilePath
|
||||||
deriving Show
|
deriving Show
|
||||||
@@ -112,7 +290,11 @@ data MergeFileTreeError = MergeFileTreeError IOException FilePath FilePath
|
|||||||
instance Pretty MergeFileTreeError where
|
instance Pretty MergeFileTreeError where
|
||||||
pPrint (MergeFileTreeError e from to) =
|
pPrint (MergeFileTreeError e from to) =
|
||||||
text "Failed to merge file tree from" <+> text from <+> text "to" <+> text to <+> text "\nexception was:" <+> text (displayException e)
|
text "Failed to merge file tree from" <+> text from <+> text "to" <+> text to <+> text "\nexception was:" <+> text (displayException e)
|
||||||
<+> text "\n...tried to clean up" <+> text to <+> text ". Make sure it's gone."
|
<+> text "\n...you may need to delete" <+> text to <+> text "manually. Make sure it's gone."
|
||||||
|
|
||||||
|
instance HFErrorProject MergeFileTreeError where
|
||||||
|
eBase _ = 80
|
||||||
|
eDesc _ = "Unable to merge file trees during installation"
|
||||||
|
|
||||||
-- | Unable to find a tag of a tool.
|
-- | Unable to find a tag of a tool.
|
||||||
data TagNotFound = TagNotFound Tag Tool
|
data TagNotFound = TagNotFound Tag Tool
|
||||||
@@ -122,6 +304,10 @@ instance Pretty TagNotFound where
|
|||||||
pPrint (TagNotFound tag tool) =
|
pPrint (TagNotFound tag tool) =
|
||||||
text "Unable to find tag" <+> pPrint tag <+> text "of tool" <+> pPrint tool
|
text "Unable to find tag" <+> pPrint tag <+> text "of tool" <+> pPrint tool
|
||||||
|
|
||||||
|
instance HFErrorProject TagNotFound where
|
||||||
|
eBase _ = 90
|
||||||
|
eDesc _ = "Unable to find a tag of a tool"
|
||||||
|
|
||||||
-- | Unable to find the next version of a tool (the one after the currently
|
-- | Unable to find the next version of a tool (the one after the currently
|
||||||
-- set one).
|
-- set one).
|
||||||
data NextVerNotFound = NextVerNotFound Tool
|
data NextVerNotFound = NextVerNotFound Tool
|
||||||
@@ -131,21 +317,35 @@ instance Pretty NextVerNotFound where
|
|||||||
pPrint (NextVerNotFound tool) =
|
pPrint (NextVerNotFound tool) =
|
||||||
text "Unable to find next (the one after the currently set one) version of tool" <+> pPrint tool
|
text "Unable to find next (the one after the currently set one) version of tool" <+> pPrint tool
|
||||||
|
|
||||||
|
instance HFErrorProject NextVerNotFound where
|
||||||
|
eBase _ = 100
|
||||||
|
eDesc _ = "Unable to find the next version of a tool (the one after the currently set one)"
|
||||||
|
|
||||||
-- | The tool (such as GHC) is already installed with that version.
|
-- | The tool (such as GHC) is already installed with that version.
|
||||||
data AlreadyInstalled = AlreadyInstalled Tool Version
|
data AlreadyInstalled = AlreadyInstalled Tool Version
|
||||||
deriving Show
|
deriving Show
|
||||||
|
|
||||||
instance Pretty AlreadyInstalled where
|
instance Pretty AlreadyInstalled where
|
||||||
pPrint (AlreadyInstalled tool ver') =
|
pPrint (AlreadyInstalled tool ver') =
|
||||||
pPrint tool <+> text "-" <+> pPrint ver' <+> text "is already installed"
|
(pPrint tool <> text "-" <> pPrint ver') <+> text "is already installed;"
|
||||||
|
<+> text "if you really want to reinstall it, you may want to run 'ghcup install" <+> pPrint tool <+> text "--force" <+> (pPrint ver' <> text "'")
|
||||||
|
|
||||||
|
instance HFErrorProject AlreadyInstalled where
|
||||||
|
eBase _ = 110
|
||||||
|
eDesc _ = "The tool (such as GHC) is already installed with that version"
|
||||||
|
|
||||||
-- | The Directory is supposed to be empty, but wasn't.
|
-- | The Directory is supposed to be empty, but wasn't.
|
||||||
data DirNotEmpty = DirNotEmpty {path :: FilePath}
|
data DirNotEmpty = DirNotEmpty {path :: FilePath}
|
||||||
|
deriving Show
|
||||||
|
|
||||||
instance Pretty DirNotEmpty where
|
instance Pretty DirNotEmpty where
|
||||||
pPrint (DirNotEmpty path) = do
|
pPrint (DirNotEmpty path) = do
|
||||||
text $ "The directory was expected to be empty, but isn't: " <> path
|
text $ "The directory was expected to be empty, but isn't: " <> path
|
||||||
|
|
||||||
|
instance HFErrorProject DirNotEmpty where
|
||||||
|
eBase _ = 120
|
||||||
|
eDesc _ = "The Directory is supposed to be empty, but wasn't"
|
||||||
|
|
||||||
-- | The tool is not installed. Some operations rely on a tool
|
-- | The tool is not installed. Some operations rely on a tool
|
||||||
-- to be installed (such as setting the current GHC version).
|
-- to be installed (such as setting the current GHC version).
|
||||||
data NotInstalled = NotInstalled Tool GHCTargetVersion
|
data NotInstalled = NotInstalled Tool GHCTargetVersion
|
||||||
@@ -155,6 +355,10 @@ instance Pretty NotInstalled where
|
|||||||
pPrint (NotInstalled tool ver) =
|
pPrint (NotInstalled tool ver) =
|
||||||
text "The version" <+> pPrint ver <+> text "of the tool" <+> pPrint tool <+> text "is not installed."
|
text "The version" <+> pPrint ver <+> text "of the tool" <+> pPrint tool <+> text "is not installed."
|
||||||
|
|
||||||
|
instance HFErrorProject NotInstalled where
|
||||||
|
eBase _ = 130
|
||||||
|
eDesc _ = "The required tool is not installed"
|
||||||
|
|
||||||
data UninstallFailed = UninstallFailed FilePath [FilePath]
|
data UninstallFailed = UninstallFailed FilePath [FilePath]
|
||||||
deriving Show
|
deriving Show
|
||||||
|
|
||||||
@@ -162,6 +366,10 @@ instance Pretty UninstallFailed where
|
|||||||
pPrint (UninstallFailed dir files) =
|
pPrint (UninstallFailed dir files) =
|
||||||
text "The following files survived uninstallation: " <+> pPrint files <+> text "...consider removing" <+> pPrint dir <+> text "manually."
|
text "The following files survived uninstallation: " <+> pPrint files <+> text "...consider removing" <+> pPrint dir <+> text "manually."
|
||||||
|
|
||||||
|
instance HFErrorProject UninstallFailed where
|
||||||
|
eBase _ = 140
|
||||||
|
eDesc _ = "Uninstallation failed with leftover files"
|
||||||
|
|
||||||
-- | An executable was expected to be in PATH, but was not found.
|
-- | An executable was expected to be in PATH, but was not found.
|
||||||
data NotFoundInPATH = NotFoundInPATH FilePath
|
data NotFoundInPATH = NotFoundInPATH FilePath
|
||||||
deriving Show
|
deriving Show
|
||||||
@@ -172,6 +380,10 @@ instance Pretty NotFoundInPATH where
|
|||||||
pPrint (NotFoundInPATH exe) =
|
pPrint (NotFoundInPATH exe) =
|
||||||
text $ "The exe " <> exe <> " was not found in PATH."
|
text $ "The exe " <> exe <> " was not found in PATH."
|
||||||
|
|
||||||
|
instance HFErrorProject NotFoundInPATH where
|
||||||
|
eBase _ = 150
|
||||||
|
eDesc _ = "An executable was expected to be in PATH, but was not found"
|
||||||
|
|
||||||
-- | JSON decoding failed.
|
-- | JSON decoding failed.
|
||||||
data JSONError = JSONDecodeError String
|
data JSONError = JSONDecodeError String
|
||||||
deriving Show
|
deriving Show
|
||||||
@@ -180,6 +392,10 @@ instance Pretty JSONError where
|
|||||||
pPrint (JSONDecodeError err) =
|
pPrint (JSONDecodeError err) =
|
||||||
text $ "JSON decoding failed with: " <> err
|
text $ "JSON decoding failed with: " <> err
|
||||||
|
|
||||||
|
instance HFErrorProject JSONError where
|
||||||
|
eBase _ = 160
|
||||||
|
eDesc _ = "JSON decoding failed"
|
||||||
|
|
||||||
-- | A file that is supposed to exist does not exist
|
-- | A file that is supposed to exist does not exist
|
||||||
-- (e.g. when we use file scheme to "download" something).
|
-- (e.g. when we use file scheme to "download" something).
|
||||||
data FileDoesNotExistError = FileDoesNotExistError FilePath
|
data FileDoesNotExistError = FileDoesNotExistError FilePath
|
||||||
@@ -189,6 +405,10 @@ instance Pretty FileDoesNotExistError where
|
|||||||
pPrint (FileDoesNotExistError file) =
|
pPrint (FileDoesNotExistError file) =
|
||||||
text $ "File " <> file <> " does not exist."
|
text $ "File " <> file <> " does not exist."
|
||||||
|
|
||||||
|
instance HFErrorProject FileDoesNotExistError where
|
||||||
|
eBase _ = 170
|
||||||
|
eDesc _ = "A file that is supposed to exist does not exist (oops)"
|
||||||
|
|
||||||
-- | The file already exists
|
-- | The file already exists
|
||||||
-- (e.g. when we use isolated installs with the same path).
|
-- (e.g. when we use isolated installs with the same path).
|
||||||
-- (e.g. This is done to prevent any overwriting)
|
-- (e.g. This is done to prevent any overwriting)
|
||||||
@@ -199,6 +419,10 @@ instance Pretty FileAlreadyExistsError where
|
|||||||
pPrint (FileAlreadyExistsError file) =
|
pPrint (FileAlreadyExistsError file) =
|
||||||
text $ "File " <> file <> " Already exists."
|
text $ "File " <> file <> " Already exists."
|
||||||
|
|
||||||
|
instance HFErrorProject FileAlreadyExistsError where
|
||||||
|
eBase _ = 180
|
||||||
|
eDesc _ = "A file already exists that wasn't expected to exist"
|
||||||
|
|
||||||
data TarDirDoesNotExist = TarDirDoesNotExist TarDir
|
data TarDirDoesNotExist = TarDirDoesNotExist TarDir
|
||||||
deriving Show
|
deriving Show
|
||||||
|
|
||||||
@@ -206,6 +430,10 @@ instance Pretty TarDirDoesNotExist where
|
|||||||
pPrint (TarDirDoesNotExist dir) =
|
pPrint (TarDirDoesNotExist dir) =
|
||||||
text "Tar directory does not exist:" <+> pPrint dir
|
text "Tar directory does not exist:" <+> pPrint dir
|
||||||
|
|
||||||
|
instance HFErrorProject TarDirDoesNotExist where
|
||||||
|
eBase _ = 190
|
||||||
|
eDesc _ = "The tar directory (e.g. inside an archive) does not exist"
|
||||||
|
|
||||||
-- | File digest verification failed.
|
-- | File digest verification failed.
|
||||||
data DigestError = DigestError FilePath Text Text
|
data DigestError = DigestError FilePath Text Text
|
||||||
deriving Show
|
deriving Show
|
||||||
@@ -216,7 +444,11 @@ instance Pretty DigestError where
|
|||||||
<+> text (T.unpack expectedDigest) <+> text "but got" <+> pPrint currentDigest <+> text
|
<+> text (T.unpack expectedDigest) <+> text "but got" <+> pPrint currentDigest <+> text
|
||||||
"\nConsider removing the file in case it's cached and try again."
|
"\nConsider removing the file in case it's cached and try again."
|
||||||
|
|
||||||
-- | File digest verification failed.
|
instance HFErrorProject DigestError where
|
||||||
|
eBase _ = 200
|
||||||
|
eDesc _ = "File digest verification failed"
|
||||||
|
|
||||||
|
-- | File PGP verification failed.
|
||||||
data GPGError = forall xs . (ToVariantMaybe DownloadFailed xs, PopVariant DownloadFailed xs, Show (V xs), Pretty (V xs)) => GPGError (V xs)
|
data GPGError = forall xs . (ToVariantMaybe DownloadFailed xs, PopVariant DownloadFailed xs, Show (V xs), Pretty (V xs)) => GPGError (V xs)
|
||||||
|
|
||||||
deriving instance Show GPGError
|
deriving instance Show GPGError
|
||||||
@@ -224,6 +456,10 @@ deriving instance Show GPGError
|
|||||||
instance Pretty GPGError where
|
instance Pretty GPGError where
|
||||||
pPrint (GPGError reason) = text "GPG verify failed:" <+> pPrint reason
|
pPrint (GPGError reason) = text "GPG verify failed:" <+> pPrint reason
|
||||||
|
|
||||||
|
instance HFErrorProject GPGError where
|
||||||
|
eBase _ = 210
|
||||||
|
eDesc _ = "File PGP verification failed"
|
||||||
|
|
||||||
-- | Unexpected HTTP status.
|
-- | Unexpected HTTP status.
|
||||||
data HTTPStatusError = HTTPStatusError Int (M.Map (CI ByteString) ByteString)
|
data HTTPStatusError = HTTPStatusError Int (M.Map (CI ByteString) ByteString)
|
||||||
deriving Show
|
deriving Show
|
||||||
@@ -232,6 +468,10 @@ instance Pretty HTTPStatusError where
|
|||||||
pPrint (HTTPStatusError status _) =
|
pPrint (HTTPStatusError status _) =
|
||||||
text "Unexpected HTTP status:" <+> pPrint status
|
text "Unexpected HTTP status:" <+> pPrint status
|
||||||
|
|
||||||
|
instance HFErrorProject HTTPStatusError where
|
||||||
|
eBase _ = 220
|
||||||
|
eDesc _ = "Unexpected HTTP status error (e.g. during downloads)"
|
||||||
|
|
||||||
-- | Malformed headers.
|
-- | Malformed headers.
|
||||||
data MalformedHeaders = MalformedHeaders Text
|
data MalformedHeaders = MalformedHeaders Text
|
||||||
deriving Show
|
deriving Show
|
||||||
@@ -240,6 +480,10 @@ instance Pretty MalformedHeaders where
|
|||||||
pPrint (MalformedHeaders h) =
|
pPrint (MalformedHeaders h) =
|
||||||
text "Headers are malformed: " <+> pPrint h
|
text "Headers are malformed: " <+> pPrint h
|
||||||
|
|
||||||
|
instance HFErrorProject MalformedHeaders where
|
||||||
|
eBase _ = 230
|
||||||
|
eDesc _ = "Malformed headers during download"
|
||||||
|
|
||||||
-- | Unexpected HTTP status.
|
-- | Unexpected HTTP status.
|
||||||
data HTTPNotModified = HTTPNotModified Text
|
data HTTPNotModified = HTTPNotModified Text
|
||||||
deriving Show
|
deriving Show
|
||||||
@@ -248,13 +492,21 @@ instance Pretty HTTPNotModified where
|
|||||||
pPrint (HTTPNotModified etag) =
|
pPrint (HTTPNotModified etag) =
|
||||||
text "Remote resource not modifed, etag was:" <+> pPrint etag
|
text "Remote resource not modifed, etag was:" <+> pPrint etag
|
||||||
|
|
||||||
|
instance HFErrorProject HTTPNotModified where
|
||||||
|
eBase _ = 240
|
||||||
|
eDesc _ = "Not modified HTTP status error (e.g. during downloads)."
|
||||||
|
|
||||||
-- | The 'Location' header was expected during a 3xx redirect, but not found.
|
-- | The 'Location' header was expected during a 3xx redirect, but not found.
|
||||||
data NoLocationHeader = NoLocationHeader
|
data NoLocationHeader = NoLocationHeader
|
||||||
deriving Show
|
deriving Show
|
||||||
|
|
||||||
instance Pretty NoLocationHeader where
|
instance Pretty NoLocationHeader where
|
||||||
pPrint NoLocationHeader =
|
pPrint NoLocationHeader =
|
||||||
text "The 'Location' header was expected during a 3xx redirect, but not found."
|
text (eDesc (Proxy :: Proxy NoLocationHeader))
|
||||||
|
|
||||||
|
instance HFErrorProject NoLocationHeader where
|
||||||
|
eBase _ = 250
|
||||||
|
eDesc _ = "The 'Location' header was expected during a 3xx redirect, but not found."
|
||||||
|
|
||||||
-- | Too many redirects.
|
-- | Too many redirects.
|
||||||
data TooManyRedirs = TooManyRedirs
|
data TooManyRedirs = TooManyRedirs
|
||||||
@@ -262,7 +514,11 @@ data TooManyRedirs = TooManyRedirs
|
|||||||
|
|
||||||
instance Pretty TooManyRedirs where
|
instance Pretty TooManyRedirs where
|
||||||
pPrint TooManyRedirs =
|
pPrint TooManyRedirs =
|
||||||
text "Too many redirections."
|
text (eDesc (Proxy :: Proxy TooManyRedirs))
|
||||||
|
|
||||||
|
instance HFErrorProject TooManyRedirs where
|
||||||
|
eBase _ = 260
|
||||||
|
eDesc _ = "Too many redirections."
|
||||||
|
|
||||||
-- | A patch could not be applied.
|
-- | A patch could not be applied.
|
||||||
data PatchFailed = PatchFailed
|
data PatchFailed = PatchFailed
|
||||||
@@ -270,7 +526,11 @@ data PatchFailed = PatchFailed
|
|||||||
|
|
||||||
instance Pretty PatchFailed where
|
instance Pretty PatchFailed where
|
||||||
pPrint PatchFailed =
|
pPrint PatchFailed =
|
||||||
text "A patch could not be applied."
|
text (eDesc (Proxy :: Proxy PatchFailed))
|
||||||
|
|
||||||
|
instance HFErrorProject PatchFailed where
|
||||||
|
eBase _ = 270
|
||||||
|
eDesc _ = "A patch could not be applied."
|
||||||
|
|
||||||
-- | The tool requirements could not be found.
|
-- | The tool requirements could not be found.
|
||||||
data NoToolRequirements = NoToolRequirements
|
data NoToolRequirements = NoToolRequirements
|
||||||
@@ -278,7 +538,11 @@ data NoToolRequirements = NoToolRequirements
|
|||||||
|
|
||||||
instance Pretty NoToolRequirements where
|
instance Pretty NoToolRequirements where
|
||||||
pPrint NoToolRequirements =
|
pPrint NoToolRequirements =
|
||||||
text "The Tool requirements could not be found."
|
text (eDesc (Proxy :: Proxy NoToolRequirements))
|
||||||
|
|
||||||
|
instance HFErrorProject NoToolRequirements where
|
||||||
|
eBase _ = 280
|
||||||
|
eDesc _ = "The Tool requirements could not be found."
|
||||||
|
|
||||||
data InvalidBuildConfig = InvalidBuildConfig Text
|
data InvalidBuildConfig = InvalidBuildConfig Text
|
||||||
deriving Show
|
deriving Show
|
||||||
@@ -287,6 +551,10 @@ instance Pretty InvalidBuildConfig where
|
|||||||
pPrint (InvalidBuildConfig reason) =
|
pPrint (InvalidBuildConfig reason) =
|
||||||
text "The build config is invalid. Reason was:" <+> pPrint reason
|
text "The build config is invalid. Reason was:" <+> pPrint reason
|
||||||
|
|
||||||
|
instance HFErrorProject InvalidBuildConfig where
|
||||||
|
eBase _ = 290
|
||||||
|
eDesc _ = "The build config is invalid."
|
||||||
|
|
||||||
data NoToolVersionSet = NoToolVersionSet Tool
|
data NoToolVersionSet = NoToolVersionSet Tool
|
||||||
deriving Show
|
deriving Show
|
||||||
|
|
||||||
@@ -294,45 +562,90 @@ instance Pretty NoToolVersionSet where
|
|||||||
pPrint (NoToolVersionSet tool) =
|
pPrint (NoToolVersionSet tool) =
|
||||||
text "No version is set for tool" <+> pPrint tool <+> text "."
|
text "No version is set for tool" <+> pPrint tool <+> text "."
|
||||||
|
|
||||||
|
instance HFErrorProject NoToolVersionSet where
|
||||||
|
eBase _ = 300
|
||||||
|
eDesc _ = "No version is set for tool (but was expected)."
|
||||||
|
|
||||||
data NoNetwork = NoNetwork
|
data NoNetwork = NoNetwork
|
||||||
deriving Show
|
deriving Show
|
||||||
|
|
||||||
instance Pretty NoNetwork where
|
instance Pretty NoNetwork where
|
||||||
pPrint NoNetwork =
|
pPrint NoNetwork =
|
||||||
text "A download was required or requested, but '--offline' was specified."
|
text (eDesc (Proxy :: Proxy NoNetwork))
|
||||||
|
|
||||||
|
instance HFErrorProject NoNetwork where
|
||||||
|
eBase _ = 310
|
||||||
|
eDesc _ = "A download was required or requested, but '--offline' was specified."
|
||||||
|
|
||||||
data HadrianNotFound = HadrianNotFound
|
data HadrianNotFound = HadrianNotFound
|
||||||
deriving Show
|
deriving Show
|
||||||
|
|
||||||
instance Pretty HadrianNotFound where
|
instance Pretty HadrianNotFound where
|
||||||
pPrint HadrianNotFound =
|
pPrint HadrianNotFound =
|
||||||
text "Could not find Hadrian build files. Does this GHC version support Hadrian builds?"
|
text (eDesc (Proxy :: Proxy HadrianNotFound))
|
||||||
|
|
||||||
data GHCupShadowed = GHCupShadowed
|
instance HFErrorProject HadrianNotFound where
|
||||||
|
eBase _ = 320
|
||||||
|
eDesc _ = "Could not find Hadrian build files. Does this GHC version support Hadrian builds?"
|
||||||
|
|
||||||
|
data ToolShadowed = ToolShadowed
|
||||||
|
Tool
|
||||||
FilePath -- shadow binary
|
FilePath -- shadow binary
|
||||||
FilePath -- upgraded binary
|
FilePath -- upgraded binary
|
||||||
Version -- upgraded version
|
Version -- upgraded version
|
||||||
deriving Show
|
deriving Show
|
||||||
|
|
||||||
instance Pretty GHCupShadowed where
|
instance Pretty ToolShadowed where
|
||||||
pPrint (GHCupShadowed sh up _) =
|
pPrint (ToolShadowed tool sh up _) =
|
||||||
text ("ghcup is shadowed by "
|
text (prettyShow tool
|
||||||
|
<> " is shadowed by "
|
||||||
<> sh
|
<> sh
|
||||||
<> ". The upgrade will not be in effect, unless you remove "
|
<> ".\nThe upgrade will not be in effect, unless you remove "
|
||||||
<> sh
|
<> sh
|
||||||
<> " or make sure "
|
<> "\nor make sure "
|
||||||
<> takeDirectory up
|
<> takeDirectory up
|
||||||
<> " comes before "
|
<> " comes before "
|
||||||
<> takeDirectory sh
|
<> takeDirectory sh
|
||||||
<> " in PATH."
|
<> " in PATH."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
instance HFErrorProject ToolShadowed where
|
||||||
|
eBase _ = 330
|
||||||
|
eDesc _ = "A tool is shadowed in PATH."
|
||||||
|
|
||||||
|
-- | File content length verification failed.
|
||||||
|
data ContentLengthError = ContentLengthError (Maybe FilePath) (Maybe Integer) Integer
|
||||||
|
deriving Show
|
||||||
|
|
||||||
|
instance Pretty ContentLengthError where
|
||||||
|
pPrint (ContentLengthError Nothing Nothing expectedSize) =
|
||||||
|
text "Content length exceeded expected size:"
|
||||||
|
<+> text (show expectedSize)
|
||||||
|
<+> text "\nConsider removing the file in case it's cached and try again."
|
||||||
|
pPrint (ContentLengthError Nothing (Just currentSize) expectedSize) =
|
||||||
|
text "Content length error. Expected"
|
||||||
|
<+> text (show expectedSize) <+> text "but got" <+> pPrint currentSize <+> text
|
||||||
|
"\nConsider removing the file in case it's cached and try again."
|
||||||
|
pPrint (ContentLengthError (Just fp) (Just currentSize) expectedSize) =
|
||||||
|
text "Content length error for" <+> text (fp <> ": expected")
|
||||||
|
<+> text (show expectedSize) <+> text "but got" <+> pPrint currentSize <+> text
|
||||||
|
"\nConsider removing the file in case it's cached and try again."
|
||||||
|
pPrint (ContentLengthError (Just fp) Nothing expectedSize) =
|
||||||
|
text "Content length error for" <+> text (fp <> ": expected")
|
||||||
|
<+> text (show expectedSize) <+> text "\nConsider removing the file in case it's cached and try again."
|
||||||
|
|
||||||
|
instance Exception ContentLengthError
|
||||||
|
|
||||||
|
instance HFErrorProject ContentLengthError where
|
||||||
|
eBase _ = 340
|
||||||
|
eDesc _ = "File content length verification failed"
|
||||||
|
|
||||||
-------------------------
|
-------------------------
|
||||||
--[ High-level errors ]--
|
--[ High-level errors ]--
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
-- | A download failed. The underlying error is encapsulated.
|
-- | A download failed. The underlying error is encapsulated.
|
||||||
data DownloadFailed = forall xs . (ToVariantMaybe DownloadFailed xs, PopVariant DownloadFailed xs, Show (V xs), Pretty (V xs)) => DownloadFailed (V xs)
|
data DownloadFailed = forall xs . (HFErrorProject (V xs), ToVariantMaybe DownloadFailed xs, PopVariant DownloadFailed xs, Show (V xs), Pretty (V xs)) => DownloadFailed (V xs)
|
||||||
|
|
||||||
instance Pretty DownloadFailed where
|
instance Pretty DownloadFailed where
|
||||||
pPrint (DownloadFailed reason) =
|
pPrint (DownloadFailed reason) =
|
||||||
@@ -342,9 +655,47 @@ instance Pretty DownloadFailed where
|
|||||||
|
|
||||||
deriving instance Show DownloadFailed
|
deriving instance Show DownloadFailed
|
||||||
|
|
||||||
|
instance HFErrorProject DownloadFailed where
|
||||||
|
eBase _ = 5000
|
||||||
|
eNum (DownloadFailed xs) = 5000 + eNum xs
|
||||||
|
eDesc _ = "A download failed."
|
||||||
|
|
||||||
|
data InstallSetError = forall xs1 xs2 . (Show (V xs1), Pretty (V xs1), HFErrorProject (V xs1), Show (V xs2), Pretty (V xs2), HFErrorProject (V xs2)) => InstallSetError (V xs1) (V xs2)
|
||||||
|
|
||||||
|
instance Pretty InstallSetError where
|
||||||
|
pPrint (InstallSetError reason1 reason2) =
|
||||||
|
text "Both installation and setting the tool failed. Install error was:"
|
||||||
|
<+> pPrint reason1
|
||||||
|
<+> text "\nSet error was:"
|
||||||
|
<+> pPrint reason2
|
||||||
|
|
||||||
|
deriving instance Show InstallSetError
|
||||||
|
|
||||||
|
instance HFErrorProject InstallSetError where
|
||||||
|
eBase _ = 7000
|
||||||
|
-- will there be collisions?
|
||||||
|
eNum (InstallSetError xs1 xs2) = 7000 + eNum xs1 + eNum xs2
|
||||||
|
eDesc _ = "Installation or setting the tool failed."
|
||||||
|
|
||||||
|
|
||||||
|
-- | A test failed.
|
||||||
|
data TestFailed = forall es . (ToVariantMaybe TestFailed es, PopVariant TestFailed es, Pretty (V es), Show (V es), HFErrorProject (V es)) => TestFailed FilePath (V es)
|
||||||
|
|
||||||
|
instance Pretty TestFailed where
|
||||||
|
pPrint (TestFailed path reason) =
|
||||||
|
case reason of
|
||||||
|
VMaybe (_ :: TestFailed) -> pPrint reason
|
||||||
|
_ -> text ("The test failed. GHC test suite is fragile and non-portable. Please also check out the " <> linkEscapeCode "issue tracker" " https://gitlab.haskell.org/ghc/ghc/-/issues/?sort=updated_desc&state=opened&label_name%5B%5D=testsuite&label_name%5B%5D=packaging&first_page_size=20" <> ".\nBuild dir was:") <+> text path <+> text "\nReason was:" <+> pPrint reason
|
||||||
|
|
||||||
|
deriving instance Show TestFailed
|
||||||
|
|
||||||
|
instance HFErrorProject TestFailed where
|
||||||
|
eBase _ = 4000
|
||||||
|
eNum (TestFailed _ xs2) = 4000 + eNum xs2
|
||||||
|
eDesc _ = "The test failed."
|
||||||
|
|
||||||
-- | A build failed.
|
-- | A build failed.
|
||||||
data BuildFailed = forall es . (ToVariantMaybe BuildFailed es, PopVariant BuildFailed es, Pretty (V es), Show (V es)) => BuildFailed FilePath (V es)
|
data BuildFailed = forall es . (ToVariantMaybe BuildFailed es, PopVariant BuildFailed es, Pretty (V es), Show (V es), HFErrorProject (V es)) => BuildFailed FilePath (V es)
|
||||||
|
|
||||||
instance Pretty BuildFailed where
|
instance Pretty BuildFailed where
|
||||||
pPrint (BuildFailed path reason) =
|
pPrint (BuildFailed path reason) =
|
||||||
@@ -354,18 +705,28 @@ instance Pretty BuildFailed where
|
|||||||
|
|
||||||
deriving instance Show BuildFailed
|
deriving instance Show BuildFailed
|
||||||
|
|
||||||
|
instance HFErrorProject BuildFailed where
|
||||||
|
eBase _ = 8000
|
||||||
|
eNum (BuildFailed _ xs2) = 8000 + eNum xs2
|
||||||
|
eDesc _ = "The build failed."
|
||||||
|
|
||||||
|
|
||||||
-- | Setting the current GHC version failed.
|
-- | Setting the current GHC version failed.
|
||||||
data GHCupSetError = forall es . (ToVariantMaybe GHCupSetError es, PopVariant GHCupSetError es, Show (V es), Pretty (V es)) => GHCupSetError (V es)
|
data GHCupSetError = forall es . (ToVariantMaybe GHCupSetError es, PopVariant GHCupSetError es, Show (V es), Pretty (V es), HFErrorProject (V es)) => GHCupSetError (V es)
|
||||||
|
|
||||||
instance Pretty GHCupSetError where
|
instance Pretty GHCupSetError where
|
||||||
pPrint (GHCupSetError reason) =
|
pPrint (GHCupSetError reason) =
|
||||||
case reason of
|
case reason of
|
||||||
VMaybe (_ :: GHCupSetError) -> pPrint reason
|
VMaybe (_ :: GHCupSetError) -> pPrint reason
|
||||||
_ -> text "Setting the current GHC version failed:" <+> pPrint reason
|
_ -> text "Setting the current version failed:" <+> pPrint reason
|
||||||
|
|
||||||
deriving instance Show GHCupSetError
|
deriving instance Show GHCupSetError
|
||||||
|
|
||||||
|
instance HFErrorProject GHCupSetError where
|
||||||
|
eBase _ = 9000
|
||||||
|
eNum (GHCupSetError xs) = 9000 + eNum xs
|
||||||
|
eDesc _ = "Setting the current version failed."
|
||||||
|
|
||||||
|
|
||||||
---------------------------------------------
|
---------------------------------------------
|
||||||
--[ True Exceptions (e.g. for MonadThrow) ]--
|
--[ True Exceptions (e.g. for MonadThrow) ]--
|
||||||
@@ -382,6 +743,10 @@ instance Pretty ParseError where
|
|||||||
|
|
||||||
instance Exception ParseError
|
instance Exception ParseError
|
||||||
|
|
||||||
|
instance HFErrorProject ParseError where
|
||||||
|
eBase _ = 500
|
||||||
|
eDesc _ = "A parse error occured."
|
||||||
|
|
||||||
|
|
||||||
data UnexpectedListLength = UnexpectedListLength String
|
data UnexpectedListLength = UnexpectedListLength String
|
||||||
deriving Show
|
deriving Show
|
||||||
@@ -392,6 +757,10 @@ instance Pretty UnexpectedListLength where
|
|||||||
|
|
||||||
instance Exception UnexpectedListLength
|
instance Exception UnexpectedListLength
|
||||||
|
|
||||||
|
instance HFErrorProject UnexpectedListLength where
|
||||||
|
eBase _ = 510
|
||||||
|
eDesc _ = "A list had an unexpected length."
|
||||||
|
|
||||||
data NoUrlBase = NoUrlBase Text
|
data NoUrlBase = NoUrlBase Text
|
||||||
deriving Show
|
deriving Show
|
||||||
|
|
||||||
@@ -401,6 +770,10 @@ instance Pretty NoUrlBase where
|
|||||||
|
|
||||||
instance Exception NoUrlBase
|
instance Exception NoUrlBase
|
||||||
|
|
||||||
|
instance HFErrorProject NoUrlBase where
|
||||||
|
eBase _ = 520
|
||||||
|
eDesc _ = "URL does not have a base filename."
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
------------------------
|
------------------------
|
||||||
@@ -420,6 +793,23 @@ instance
|
|||||||
Right x -> pPrint x
|
Right x -> pPrint x
|
||||||
Left xs -> pPrint xs
|
Left xs -> pPrint xs
|
||||||
|
|
||||||
|
instance HFErrorProject (V '[]) where
|
||||||
|
{-# INLINABLE eBase #-}
|
||||||
|
eBase _ = undefined
|
||||||
|
{-# INLINABLE eDesc #-}
|
||||||
|
eDesc _ = undefined
|
||||||
|
|
||||||
|
instance
|
||||||
|
( HFErrorProject x
|
||||||
|
, HFErrorProject (V xs)
|
||||||
|
) => HFErrorProject (V (x ': xs))
|
||||||
|
where
|
||||||
|
eNum v = case popVariantHead v of
|
||||||
|
Right x -> eNum x
|
||||||
|
Left xs -> eNum xs
|
||||||
|
eDesc _ = undefined
|
||||||
|
eBase _ = undefined
|
||||||
|
|
||||||
instance Pretty URIParseError where
|
instance Pretty URIParseError where
|
||||||
pPrint (MalformedScheme reason) =
|
pPrint (MalformedScheme reason) =
|
||||||
text "Failed to parse URI. Malformed scheme:" <+> text (show reason)
|
text "Failed to parse URI. Malformed scheme:" <+> text (show reason)
|
||||||
@@ -438,6 +828,22 @@ instance Pretty URIParseError where
|
|||||||
pPrint (OtherError err) =
|
pPrint (OtherError err) =
|
||||||
text "Failed to parse URI:" <+> pPrint err
|
text "Failed to parse URI:" <+> pPrint err
|
||||||
|
|
||||||
|
instance HFErrorProject URIParseError where
|
||||||
|
eBase _ = 800
|
||||||
|
|
||||||
|
eNum (MalformedScheme NonAlphaLeading) = 801
|
||||||
|
eNum (MalformedScheme InvalidChars) = 802
|
||||||
|
eNum (MalformedScheme MissingColon) = 803
|
||||||
|
eNum MalformedUserInfo = 804
|
||||||
|
eNum MalformedQuery = 805
|
||||||
|
eNum MalformedFragment = 806
|
||||||
|
eNum MalformedHost = 807
|
||||||
|
eNum MalformedPort = 808
|
||||||
|
eNum MalformedPath = 809
|
||||||
|
eNum (OtherError _) = 810
|
||||||
|
|
||||||
|
eDesc _ = "Failed to parse URI."
|
||||||
|
|
||||||
instance Pretty ArchiveResult where
|
instance Pretty ArchiveResult where
|
||||||
pPrint ArchiveFatal = text "Archive result: fatal"
|
pPrint ArchiveFatal = text "Archive result: fatal"
|
||||||
pPrint ArchiveFailed = text "Archive result: failed"
|
pPrint ArchiveFailed = text "Archive result: failed"
|
||||||
@@ -446,5 +852,37 @@ instance Pretty ArchiveResult where
|
|||||||
pPrint ArchiveOk = text "Archive result: Ok"
|
pPrint ArchiveOk = text "Archive result: Ok"
|
||||||
pPrint ArchiveEOF = text "Archive result: EOF"
|
pPrint ArchiveEOF = text "Archive result: EOF"
|
||||||
|
|
||||||
|
instance HFErrorProject ArchiveResult where
|
||||||
|
eBase _ = 820
|
||||||
|
|
||||||
|
eNum ArchiveFatal = 821
|
||||||
|
eNum ArchiveFailed = 822
|
||||||
|
eNum ArchiveWarn = 823
|
||||||
|
eNum ArchiveRetry = 824
|
||||||
|
eNum ArchiveOk = 825
|
||||||
|
eNum ArchiveEOF = 826
|
||||||
|
|
||||||
|
eDesc _ = "Archive extraction result."
|
||||||
|
|
||||||
instance Pretty T.Text where
|
instance Pretty T.Text where
|
||||||
pPrint = text . T.unpack
|
pPrint = text . T.unpack
|
||||||
|
|
||||||
|
instance Pretty ProcessError where
|
||||||
|
pPrint (NonZeroExit e exe args) =
|
||||||
|
text "Process" <+> pPrint exe <+> text "with arguments" <+> pPrint args <+> text "failed with exit code" <+> text (show e <> ".")
|
||||||
|
pPrint (PTerminated exe args) =
|
||||||
|
text "Process" <+> pPrint exe <+> text "with arguments" <+> pPrint args <+> text "terminated."
|
||||||
|
pPrint (PStopped exe args) =
|
||||||
|
text "Process" <+> pPrint exe <+> text "with arguments" <+> pPrint args <+> text "stopped."
|
||||||
|
pPrint (NoSuchPid exe args) =
|
||||||
|
text "Could not find PID for process running " <+> pPrint exe <+> text " with arguments " <+> text (show args) <+> text "."
|
||||||
|
|
||||||
|
instance HFErrorProject ProcessError where
|
||||||
|
eBase _ = 840
|
||||||
|
|
||||||
|
eNum NonZeroExit{} = 841
|
||||||
|
eNum (PTerminated _ _) = 842
|
||||||
|
eNum (PStopped _ _) = 843
|
||||||
|
eNum (NoSuchPid _ _) = 844
|
||||||
|
|
||||||
|
eDesc _ = "A process exited prematurely."
|
||||||
|
|||||||
309
lib/GHCup/GHC.hs
309
lib/GHCup/GHC.hs
@@ -80,6 +80,150 @@ import qualified Data.Text.Encoding as E
|
|||||||
import qualified Text.Megaparsec as MP
|
import qualified Text.Megaparsec as MP
|
||||||
|
|
||||||
|
|
||||||
|
data GHCVer v = SourceDist v
|
||||||
|
| GitDist GitBranch
|
||||||
|
| RemoteDist URI
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--------------------
|
||||||
|
--[ Tool testing ]--
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
testGHCVer :: ( MonadFail m
|
||||||
|
, MonadMask m
|
||||||
|
, MonadCatch m
|
||||||
|
, MonadReader env m
|
||||||
|
, HasDirs env
|
||||||
|
, HasSettings env
|
||||||
|
, HasPlatformReq env
|
||||||
|
, HasGHCupInfo env
|
||||||
|
, HasLog env
|
||||||
|
, MonadResource m
|
||||||
|
, MonadIO m
|
||||||
|
, MonadUnliftIO m
|
||||||
|
)
|
||||||
|
=> Version
|
||||||
|
-> [T.Text]
|
||||||
|
-> Excepts
|
||||||
|
'[ DigestError
|
||||||
|
, ContentLengthError
|
||||||
|
, GPGError
|
||||||
|
, DownloadFailed
|
||||||
|
, NoDownload
|
||||||
|
, ArchiveResult
|
||||||
|
, TarDirDoesNotExist
|
||||||
|
, UnknownArchive
|
||||||
|
, TestFailed
|
||||||
|
]
|
||||||
|
m
|
||||||
|
()
|
||||||
|
testGHCVer ver addMakeArgs = do
|
||||||
|
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||||
|
|
||||||
|
dlInfo <-
|
||||||
|
preview (ix GHC % ix ver % viTestDL % _Just) dls
|
||||||
|
?? NoDownload
|
||||||
|
|
||||||
|
liftE $ testGHCBindist dlInfo ver addMakeArgs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
testGHCBindist :: ( MonadFail m
|
||||||
|
, MonadMask m
|
||||||
|
, MonadCatch m
|
||||||
|
, MonadReader env m
|
||||||
|
, HasDirs env
|
||||||
|
, HasSettings env
|
||||||
|
, HasPlatformReq env
|
||||||
|
, HasGHCupInfo env
|
||||||
|
, HasLog env
|
||||||
|
, MonadResource m
|
||||||
|
, MonadIO m
|
||||||
|
, MonadUnliftIO m
|
||||||
|
)
|
||||||
|
=> DownloadInfo
|
||||||
|
-> Version
|
||||||
|
-> [T.Text]
|
||||||
|
-> Excepts
|
||||||
|
'[ DigestError
|
||||||
|
, ContentLengthError
|
||||||
|
, GPGError
|
||||||
|
, DownloadFailed
|
||||||
|
, NoDownload
|
||||||
|
, ArchiveResult
|
||||||
|
, TarDirDoesNotExist
|
||||||
|
, UnknownArchive
|
||||||
|
, TestFailed
|
||||||
|
]
|
||||||
|
m
|
||||||
|
()
|
||||||
|
testGHCBindist dlinfo ver addMakeArgs = do
|
||||||
|
-- download (or use cached version)
|
||||||
|
dl <- liftE $ downloadCached dlinfo Nothing
|
||||||
|
|
||||||
|
liftE $ testPackedGHC dl (view dlSubdir dlinfo) ver addMakeArgs
|
||||||
|
|
||||||
|
|
||||||
|
testPackedGHC :: ( MonadMask m
|
||||||
|
, MonadCatch m
|
||||||
|
, MonadReader env m
|
||||||
|
, HasDirs env
|
||||||
|
, HasPlatformReq env
|
||||||
|
, HasSettings env
|
||||||
|
, MonadThrow m
|
||||||
|
, HasLog env
|
||||||
|
, MonadIO m
|
||||||
|
, MonadUnliftIO m
|
||||||
|
, MonadFail m
|
||||||
|
, MonadResource m
|
||||||
|
)
|
||||||
|
=> FilePath -- ^ Path to the packed GHC bindist
|
||||||
|
-> Maybe TarDir -- ^ Subdir of the archive
|
||||||
|
-> Version -- ^ The GHC version
|
||||||
|
-> [T.Text] -- ^ additional make args
|
||||||
|
-> Excepts
|
||||||
|
'[ ArchiveResult, UnknownArchive, TarDirDoesNotExist, TestFailed ] m ()
|
||||||
|
testPackedGHC dl msubdir ver addMakeArgs = do
|
||||||
|
-- unpack
|
||||||
|
tmpUnpack <- lift mkGhcupTmpDir
|
||||||
|
liftE $ cleanUpOnError tmpUnpack (unpackToDir (fromGHCupPath tmpUnpack) dl)
|
||||||
|
|
||||||
|
-- the subdir of the archive where we do the work
|
||||||
|
workdir <- maybe (pure tmpUnpack)
|
||||||
|
(liftE . intoSubdir tmpUnpack)
|
||||||
|
msubdir
|
||||||
|
|
||||||
|
reThrowAll @_ @'[ArchiveResult, UnknownArchive, TarDirDoesNotExist, ProcessError]
|
||||||
|
(TestFailed (fromGHCupPath workdir)) $ liftE $ runBuildAction tmpUnpack
|
||||||
|
(testUnpackedGHC workdir ver addMakeArgs)
|
||||||
|
|
||||||
|
testUnpackedGHC :: ( MonadReader env m
|
||||||
|
, HasDirs env
|
||||||
|
, HasSettings env
|
||||||
|
, MonadThrow m
|
||||||
|
, HasLog env
|
||||||
|
, MonadIO m
|
||||||
|
)
|
||||||
|
=> GHCupPath -- ^ Path to the unpacked GHC bindist (where the make file resides)
|
||||||
|
-> Version -- ^ The GHC version
|
||||||
|
-> [T.Text] -- ^ additional configure args for bindist
|
||||||
|
-> Excepts '[ProcessError] m ()
|
||||||
|
testUnpackedGHC path ver addMakeArgs = do
|
||||||
|
lift $ logInfo $ "Testing GHC version " <> prettyVer ver <> "!"
|
||||||
|
ghcDir <- lift $ ghcupGHCDir (mkTVer ver)
|
||||||
|
let ghcBinDir = fromGHCupPath ghcDir </> "bin"
|
||||||
|
env <- liftIO $ addToPath ghcBinDir False
|
||||||
|
|
||||||
|
lEM $ make' (fmap T.unpack addMakeArgs)
|
||||||
|
(Just $ fromGHCupPath path)
|
||||||
|
"ghc-test"
|
||||||
|
(Just $ ("STAGE1_GHC", "ghc-" <> T.unpack (prettyVer ver)) : env)
|
||||||
|
pure ()
|
||||||
|
|
||||||
|
|
||||||
---------------------
|
---------------------
|
||||||
--[ Tool fetching ]--
|
--[ Tool fetching ]--
|
||||||
---------------------
|
---------------------
|
||||||
@@ -103,6 +247,7 @@ fetchGHCSrc :: ( MonadFail m
|
|||||||
-> Maybe FilePath
|
-> Maybe FilePath
|
||||||
-> Excepts
|
-> Excepts
|
||||||
'[ DigestError
|
'[ DigestError
|
||||||
|
, ContentLengthError
|
||||||
, GPGError
|
, GPGError
|
||||||
, DownloadFailed
|
, DownloadFailed
|
||||||
, NoDownload
|
, NoDownload
|
||||||
@@ -141,10 +286,12 @@ installGHCBindist :: ( MonadFail m
|
|||||||
-> Version -- ^ the version to install
|
-> Version -- ^ the version to install
|
||||||
-> InstallDir
|
-> InstallDir
|
||||||
-> Bool -- ^ Force install
|
-> Bool -- ^ Force install
|
||||||
|
-> [T.Text] -- ^ additional configure args for bindist
|
||||||
-> Excepts
|
-> Excepts
|
||||||
'[ AlreadyInstalled
|
'[ AlreadyInstalled
|
||||||
, BuildFailed
|
, BuildFailed
|
||||||
, DigestError
|
, DigestError
|
||||||
|
, ContentLengthError
|
||||||
, GPGError
|
, GPGError
|
||||||
, DownloadFailed
|
, DownloadFailed
|
||||||
, NoDownload
|
, NoDownload
|
||||||
@@ -159,7 +306,7 @@ installGHCBindist :: ( MonadFail m
|
|||||||
]
|
]
|
||||||
m
|
m
|
||||||
()
|
()
|
||||||
installGHCBindist dlinfo ver installDir forceInstall = do
|
installGHCBindist dlinfo ver installDir forceInstall addConfArgs = do
|
||||||
let tver = mkTVer ver
|
let tver = mkTVer ver
|
||||||
|
|
||||||
lift $ logDebug $ "Requested to install GHC with " <> prettyVer ver
|
lift $ logDebug $ "Requested to install GHC with " <> prettyVer ver
|
||||||
@@ -189,12 +336,12 @@ installGHCBindist dlinfo ver installDir forceInstall = do
|
|||||||
case installDir of
|
case installDir of
|
||||||
IsolateDir isoDir -> do -- isolated install
|
IsolateDir isoDir -> do -- isolated install
|
||||||
lift $ logInfo $ "isolated installing GHC to " <> T.pack isoDir
|
lift $ logInfo $ "isolated installing GHC to " <> T.pack isoDir
|
||||||
liftE $ installPackedGHC dl (view dlSubdir dlinfo) (IsolateDirResolved isoDir) ver forceInstall
|
liftE $ installPackedGHC dl (view dlSubdir dlinfo) (IsolateDirResolved isoDir) ver forceInstall addConfArgs
|
||||||
GHCupInternal -> do -- regular install
|
GHCupInternal -> do -- regular install
|
||||||
-- prepare paths
|
-- prepare paths
|
||||||
ghcdir <- lift $ ghcupGHCDir tver
|
ghcdir <- lift $ ghcupGHCDir tver
|
||||||
|
|
||||||
liftE $ installPackedGHC dl (view dlSubdir dlinfo) (GHCupDir ghcdir) ver forceInstall
|
liftE $ installPackedGHC dl (view dlSubdir dlinfo) (GHCupDir ghcdir) ver forceInstall addConfArgs
|
||||||
|
|
||||||
-- make symlinks & stuff when regular install,
|
-- make symlinks & stuff when regular install,
|
||||||
liftE $ postGHCInstall tver
|
liftE $ postGHCInstall tver
|
||||||
@@ -230,6 +377,7 @@ installPackedGHC :: ( MonadMask m
|
|||||||
-> InstallDirResolved
|
-> InstallDirResolved
|
||||||
-> Version -- ^ The GHC version
|
-> Version -- ^ The GHC version
|
||||||
-> Bool -- ^ Force install
|
-> Bool -- ^ Force install
|
||||||
|
-> [T.Text] -- ^ additional configure args for bindist
|
||||||
-> Excepts
|
-> Excepts
|
||||||
'[ BuildFailed
|
'[ BuildFailed
|
||||||
, UnknownArchive
|
, UnknownArchive
|
||||||
@@ -239,7 +387,7 @@ installPackedGHC :: ( MonadMask m
|
|||||||
, ProcessError
|
, ProcessError
|
||||||
, MergeFileTreeError
|
, MergeFileTreeError
|
||||||
] m ()
|
] m ()
|
||||||
installPackedGHC dl msubdir inst ver forceInstall = do
|
installPackedGHC dl msubdir inst ver forceInstall addConfArgs = do
|
||||||
PlatformRequest {..} <- lift getPlatformReq
|
PlatformRequest {..} <- lift getPlatformReq
|
||||||
|
|
||||||
unless forceInstall
|
unless forceInstall
|
||||||
@@ -256,7 +404,7 @@ installPackedGHC dl msubdir inst ver forceInstall = do
|
|||||||
msubdir
|
msubdir
|
||||||
|
|
||||||
liftE $ runBuildAction tmpUnpack
|
liftE $ runBuildAction tmpUnpack
|
||||||
(installUnpackedGHC workdir inst ver forceInstall)
|
(installUnpackedGHC workdir inst ver forceInstall addConfArgs)
|
||||||
|
|
||||||
|
|
||||||
-- | Install an unpacked GHC distribution. This only deals with the GHC
|
-- | Install an unpacked GHC distribution. This only deals with the GHC
|
||||||
@@ -277,8 +425,9 @@ installUnpackedGHC :: ( MonadReader env m
|
|||||||
-> InstallDirResolved -- ^ Path to install to
|
-> InstallDirResolved -- ^ Path to install to
|
||||||
-> Version -- ^ The GHC version
|
-> Version -- ^ The GHC version
|
||||||
-> Bool -- ^ Force install
|
-> Bool -- ^ Force install
|
||||||
|
-> [T.Text] -- ^ additional configure args for bindist
|
||||||
-> Excepts '[ProcessError, MergeFileTreeError] m ()
|
-> Excepts '[ProcessError, MergeFileTreeError] m ()
|
||||||
installUnpackedGHC path inst ver forceInstall
|
installUnpackedGHC path inst ver forceInstall addConfArgs
|
||||||
| isWindows = do
|
| isWindows = do
|
||||||
lift $ logInfo "Installing GHC (this may take a while)"
|
lift $ logInfo "Installing GHC (this may take a while)"
|
||||||
-- Windows bindists are relocatable and don't need
|
-- Windows bindists are relocatable and don't need
|
||||||
@@ -292,8 +441,9 @@ installUnpackedGHC path inst ver forceInstall
|
|||||||
| otherwise = do
|
| otherwise = do
|
||||||
PlatformRequest {..} <- lift getPlatformReq
|
PlatformRequest {..} <- lift getPlatformReq
|
||||||
|
|
||||||
let alpineArgs
|
let ldOverride
|
||||||
| ver >= [vver|8.2.2|], Linux Alpine <- _rPlatform
|
| ver >= [vver|8.2.2|]
|
||||||
|
, _rPlatform `elem` [Linux Alpine, Darwin]
|
||||||
= ["--disable-ld-override"]
|
= ["--disable-ld-override"]
|
||||||
| otherwise
|
| otherwise
|
||||||
= []
|
= []
|
||||||
@@ -301,7 +451,7 @@ installUnpackedGHC path inst ver forceInstall
|
|||||||
lift $ logInfo "Installing GHC (this may take a while)"
|
lift $ logInfo "Installing GHC (this may take a while)"
|
||||||
lEM $ execLogged "sh"
|
lEM $ execLogged "sh"
|
||||||
("./configure" : ("--prefix=" <> fromInstallDir inst)
|
("./configure" : ("--prefix=" <> fromInstallDir inst)
|
||||||
: alpineArgs
|
: (ldOverride <> (T.unpack <$> addConfArgs))
|
||||||
)
|
)
|
||||||
(Just $ fromGHCupPath path)
|
(Just $ fromGHCupPath path)
|
||||||
"ghc-configure"
|
"ghc-configure"
|
||||||
@@ -342,10 +492,12 @@ installGHCBin :: ( MonadFail m
|
|||||||
=> Version -- ^ the version to install
|
=> Version -- ^ the version to install
|
||||||
-> InstallDir
|
-> InstallDir
|
||||||
-> Bool -- ^ force install
|
-> Bool -- ^ force install
|
||||||
|
-> [T.Text] -- ^ additional configure args for bindist
|
||||||
-> Excepts
|
-> Excepts
|
||||||
'[ AlreadyInstalled
|
'[ AlreadyInstalled
|
||||||
, BuildFailed
|
, BuildFailed
|
||||||
, DigestError
|
, DigestError
|
||||||
|
, ContentLengthError
|
||||||
, GPGError
|
, GPGError
|
||||||
, DownloadFailed
|
, DownloadFailed
|
||||||
, NoDownload
|
, NoDownload
|
||||||
@@ -360,9 +512,9 @@ installGHCBin :: ( MonadFail m
|
|||||||
]
|
]
|
||||||
m
|
m
|
||||||
()
|
()
|
||||||
installGHCBin ver installDir forceInstall = do
|
installGHCBin ver installDir forceInstall addConfArgs = do
|
||||||
dlinfo <- liftE $ getDownloadInfo GHC ver
|
dlinfo <- liftE $ getDownloadInfo GHC ver
|
||||||
liftE $ installGHCBindist dlinfo ver installDir forceInstall
|
liftE $ installGHCBindist dlinfo ver installDir forceInstall addConfArgs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -442,6 +594,11 @@ setGHC ver sghc mBinDir = do
|
|||||||
destL <- binarySymLinkDestination binDir fileWithExt
|
destL <- binarySymLinkDestination binDir fileWithExt
|
||||||
lift $ createLink destL fullF
|
lift $ createLink destL fullF
|
||||||
|
|
||||||
|
when (targetFile == "ghc") $
|
||||||
|
liftIO (isShadowed fullF) >>= \case
|
||||||
|
Nothing -> pure ()
|
||||||
|
Just pa -> lift $ logWarn $ T.pack $ prettyHFError (ToolShadowed GHC pa fullF (_tvVersion ver))
|
||||||
|
|
||||||
when (isNothing mBinDir) $ do
|
when (isNothing mBinDir) $ do
|
||||||
-- create symlink for share dir
|
-- create symlink for share dir
|
||||||
when (isNothing . _tvTarget $ ver) $ lift $ symlinkShareDir (fromGHCupPath ghcdir) verS
|
when (isNothing . _tvTarget $ ver) $ lift $ symlinkShareDir (fromGHCupPath ghcdir) verS
|
||||||
@@ -557,8 +714,11 @@ rmGHCVer ver = do
|
|||||||
lift $ recycleFile f
|
lift $ recycleFile f
|
||||||
when (not (null survivors)) $ throwE $ UninstallFailed dir survivors
|
when (not (null survivors)) $ throwE $ UninstallFailed dir survivors
|
||||||
Nothing -> do
|
Nothing -> do
|
||||||
lift $ logInfo $ "Removing legacy directory recursively: " <> T.pack dir
|
isDir <- liftIO $ doesDirectoryExist dir
|
||||||
lift $ recyclePathForcibly dir'
|
isSyml <- liftIO $ handleIO (\_ -> pure False) $ pathIsSymbolicLink dir
|
||||||
|
when (isDir && not isSyml) $ do
|
||||||
|
lift $ logInfo $ "Removing legacy directory recursively: " <> T.pack dir
|
||||||
|
recyclePathForcibly dir'
|
||||||
|
|
||||||
v' <-
|
v' <-
|
||||||
handle
|
handle
|
||||||
@@ -595,7 +755,7 @@ compileGHC :: ( MonadMask m
|
|||||||
, MonadUnliftIO m
|
, MonadUnliftIO m
|
||||||
, MonadFail m
|
, MonadFail m
|
||||||
)
|
)
|
||||||
=> Either GHCTargetVersion GitBranch -- ^ version to install
|
=> GHCVer GHCTargetVersion
|
||||||
-> Maybe Version -- ^ overwrite version
|
-> Maybe Version -- ^ overwrite version
|
||||||
-> Either Version FilePath -- ^ version to bootstrap with
|
-> Either Version FilePath -- ^ version to bootstrap with
|
||||||
-> Maybe Int -- ^ jobs
|
-> Maybe Int -- ^ jobs
|
||||||
@@ -609,6 +769,7 @@ compileGHC :: ( MonadMask m
|
|||||||
'[ AlreadyInstalled
|
'[ AlreadyInstalled
|
||||||
, BuildFailed
|
, BuildFailed
|
||||||
, DigestError
|
, DigestError
|
||||||
|
, ContentLengthError
|
||||||
, GPGError
|
, GPGError
|
||||||
, DownloadFailed
|
, DownloadFailed
|
||||||
, GHCupSetError
|
, GHCupSetError
|
||||||
@@ -638,7 +799,7 @@ compileGHC targetGhc ov bstrap jobs mbuildConfig patches aargs buildFlavour hadr
|
|||||||
|
|
||||||
(workdir, tmpUnpack, tver) <- case targetGhc of
|
(workdir, tmpUnpack, tver) <- case targetGhc of
|
||||||
-- unpack from version tarball
|
-- unpack from version tarball
|
||||||
Left tver -> do
|
SourceDist tver -> do
|
||||||
lift $ logDebug $ "Requested to compile: " <> tVerToText tver <> " with " <> either prettyVer T.pack bstrap
|
lift $ logDebug $ "Requested to compile: " <> tVerToText tver <> " with " <> either prettyVer T.pack bstrap
|
||||||
|
|
||||||
-- download source tarball
|
-- download source tarball
|
||||||
@@ -657,13 +818,37 @@ compileGHC targetGhc ov bstrap jobs mbuildConfig patches aargs buildFlavour hadr
|
|||||||
(view dlSubdir dlInfo)
|
(view dlSubdir dlInfo)
|
||||||
liftE $ applyAnyPatch patches (fromGHCupPath workdir)
|
liftE $ applyAnyPatch patches (fromGHCupPath workdir)
|
||||||
|
|
||||||
pure (workdir, tmpUnpack, tver)
|
pure (workdir, tmpUnpack, Just tver)
|
||||||
|
|
||||||
|
RemoteDist uri -> do
|
||||||
|
lift $ logDebug $ "Requested to compile (from uri): " <> T.pack (show uri)
|
||||||
|
|
||||||
|
-- download source tarball
|
||||||
|
tmpDownload <- lift withGHCupTmpDir
|
||||||
|
tmpUnpack <- lift mkGhcupTmpDir
|
||||||
|
tar <- liftE $ download uri Nothing Nothing Nothing (fromGHCupPath tmpDownload) Nothing False
|
||||||
|
(bf, tver) <- liftE $ cleanUpOnError @'[UnknownArchive, ArchiveResult, ProcessError] tmpUnpack $ do
|
||||||
|
liftE $ unpackToDir (fromGHCupPath tmpUnpack) tar
|
||||||
|
let regex = [s|^(.*/)*boot$|] :: B.ByteString
|
||||||
|
[bootFile] <- liftIO $ findFilesDeep
|
||||||
|
tmpUnpack
|
||||||
|
(makeRegexOpts compExtended
|
||||||
|
execBlank
|
||||||
|
regex
|
||||||
|
)
|
||||||
|
tver <- liftE $ catchAllE @_ @'[ProcessError, ParseError] @'[] (\_ -> pure Nothing) $ fmap Just $ getGHCVer
|
||||||
|
(appendGHCupPath tmpUnpack (takeDirectory bootFile))
|
||||||
|
pure (bootFile, tver)
|
||||||
|
|
||||||
|
let workdir = appendGHCupPath tmpUnpack (takeDirectory bf)
|
||||||
|
|
||||||
|
pure (workdir, tmpUnpack, mkTVer <$> tver)
|
||||||
|
|
||||||
-- clone from git
|
-- clone from git
|
||||||
Right GitBranch{..} -> do
|
GitDist GitBranch{..} -> do
|
||||||
tmpUnpack <- lift mkGhcupTmpDir
|
tmpUnpack <- lift mkGhcupTmpDir
|
||||||
let git args = execLogged "git" ("--no-pager":args) (Just $ fromGHCupPath tmpUnpack) "git" Nothing
|
let git args = execLogged "git" ("--no-pager":args) (Just $ fromGHCupPath tmpUnpack) "git" Nothing
|
||||||
tver <- reThrowAll @_ @'[PatchFailed, ProcessError, NotFoundInPATH, DigestError, DownloadFailed, GPGError] DownloadFailed $ do
|
tver <- reThrowAll @_ @'[PatchFailed, ProcessError, NotFoundInPATH, DigestError, ContentLengthError, DownloadFailed, GPGError] DownloadFailed $ do
|
||||||
let rep = fromMaybe "https://gitlab.haskell.org/ghc/ghc.git" repo
|
let rep = fromMaybe "https://gitlab.haskell.org/ghc/ghc.git" repo
|
||||||
lift $ logInfo $ "Fetching git repo " <> T.pack rep <> " at ref " <> T.pack ref <> " (this may take a while)"
|
lift $ logInfo $ "Fetching git repo " <> T.pack rep <> " at ref " <> T.pack ref <> " (this may take a while)"
|
||||||
lEM $ git [ "init" ]
|
lEM $ git [ "init" ]
|
||||||
@@ -672,33 +857,54 @@ compileGHC targetGhc ov bstrap jobs mbuildConfig patches aargs buildFlavour hadr
|
|||||||
, "origin"
|
, "origin"
|
||||||
, fromString rep ]
|
, fromString rep ]
|
||||||
|
|
||||||
let fetch_args =
|
-- figure out if we can do a shallow clone
|
||||||
[ "fetch"
|
remoteBranches <- catchE @ProcessError @'[PatchFailed, ProcessError, NotFoundInPATH, DigestError, ContentLengthError, DownloadFailed, GPGError] @'[PatchFailed, NotFoundInPATH, DigestError, DownloadFailed, GPGError] (\(_ :: ProcessError) -> pure [])
|
||||||
, "--depth"
|
$ fmap processBranches $ gitOut ["ls-remote", "--heads", "origin"] (fromGHCupPath tmpUnpack)
|
||||||
, "1"
|
let shallow_clone
|
||||||
, "--quiet"
|
| isCommitHash ref = True
|
||||||
, "origin"
|
| fromString ref `elem` remoteBranches = True
|
||||||
, fromString ref ]
|
| otherwise = False
|
||||||
|
lift $ logDebug $ "Shallow clone: " <> T.pack (show shallow_clone)
|
||||||
|
|
||||||
|
-- fetch
|
||||||
|
let fetch_args
|
||||||
|
| shallow_clone = ["fetch", "--depth", "1", "--quiet", "origin", fromString ref]
|
||||||
|
| otherwise = ["fetch", "--tags", "--quiet", "origin" ]
|
||||||
lEM $ git fetch_args
|
lEM $ git fetch_args
|
||||||
|
|
||||||
lEM $ git [ "checkout", "FETCH_HEAD" ]
|
-- initial checkout
|
||||||
|
lEM $ git [ "checkout", fromString ref ]
|
||||||
|
|
||||||
|
-- gather some info
|
||||||
|
git_describe <- if shallow_clone
|
||||||
|
then pure Nothing
|
||||||
|
else fmap Just $ liftE $ gitOut ["describe", "--tags"] (fromGHCupPath tmpUnpack)
|
||||||
|
chash <- liftE $ gitOut ["rev-parse", "HEAD" ] (fromGHCupPath tmpUnpack)
|
||||||
|
|
||||||
|
-- clone submodules
|
||||||
lEM $ git [ "submodule", "update", "--init", "--depth", "1" ]
|
lEM $ git [ "submodule", "update", "--init", "--depth", "1" ]
|
||||||
|
|
||||||
|
-- apply patches
|
||||||
liftE $ applyAnyPatch patches (fromGHCupPath tmpUnpack)
|
liftE $ applyAnyPatch patches (fromGHCupPath tmpUnpack)
|
||||||
lEM $ execWithGhcEnv "python3" ["./boot"] (Just $ fromGHCupPath tmpUnpack) "ghc-bootstrap"
|
|
||||||
lEM $ execWithGhcEnv "sh" ["./configure"] (Just $ fromGHCupPath tmpUnpack) "ghc-bootstrap"
|
|
||||||
CapturedProcess {..} <- lift $ makeOut
|
|
||||||
["show!", "--quiet", "VALUE=ProjectVersion" ] (Just $ fromGHCupPath tmpUnpack)
|
|
||||||
case _exitCode of
|
|
||||||
ExitSuccess -> throwEither . MP.parse ghcProjectVersion "" . decUTF8Safe' $ _stdOut
|
|
||||||
ExitFailure c -> fail ("Could not figure out GHC project version. Exit code was: " <> show c <> ". Error was: " <> T.unpack (decUTF8Safe' _stdErr))
|
|
||||||
|
|
||||||
liftE $ catchWarn $ lEM @_ @'[ProcessError] $ darwinNotarization _rPlatform (fromGHCupPath tmpUnpack)
|
-- bootstrap
|
||||||
lift $ logInfo $ "Git version " <> T.pack ref <> " corresponds to GHC version " <> prettyVer tver
|
tver <- liftE $ catchAllE @_ @'[ProcessError, ParseError] @'[] (\_ -> pure Nothing) $ fmap Just $ getGHCVer
|
||||||
|
tmpUnpack
|
||||||
|
liftE $ catchWarn $ lEM @_ @'[ProcessError] $ darwinNotarization _rPlatform (fromGHCupPath tmpUnpack)
|
||||||
|
lift $ logInfo $ "Examining git ref " <> T.pack ref <> "\n " <>
|
||||||
|
"GHC version (from Makefile): " <> T.pack (show (prettyVer <$> tver)) <>
|
||||||
|
(if not shallow_clone then "\n " <> "'git describe' output: " <> fromJust git_describe else mempty) <>
|
||||||
|
(if isCommitHash ref then mempty else "\n " <> "commit hash: " <> chash)
|
||||||
|
liftIO $ threadDelay 5000000 -- give the user a sec to intervene
|
||||||
|
|
||||||
pure (tmpUnpack, tmpUnpack, GHCTargetVersion Nothing tver)
|
pure tver
|
||||||
|
|
||||||
|
pure (tmpUnpack, tmpUnpack, mkTVer <$> tver)
|
||||||
-- the version that's installed may differ from the
|
-- the version that's installed may differ from the
|
||||||
-- compiled version, so the user can overwrite it
|
-- compiled version, so the user can overwrite it
|
||||||
let installVer = maybe tver (\ov' -> tver { _tvVersion = ov' }) ov
|
installVer <- if | Just ov' <- ov -> pure (mkTVer ov')
|
||||||
|
| Just tver' <- tver -> pure tver'
|
||||||
|
| otherwise -> fail "Newer GHCs don't support discovering the version in git. Complain to GHC devs: https://gitlab.haskell.org/ghc/ghc/-/issues/22322"
|
||||||
|
|
||||||
alreadyInstalled <- lift $ ghcInstalled installVer
|
alreadyInstalled <- lift $ ghcInstalled installVer
|
||||||
alreadySet <- fmap (== Just installVer) $ lift $ ghcSet (_tvTarget installVer)
|
alreadySet <- fmap (== Just installVer) $ lift $ ghcSet (_tvTarget installVer)
|
||||||
@@ -721,8 +927,10 @@ compileGHC targetGhc ov bstrap jobs mbuildConfig patches aargs buildFlavour hadr
|
|||||||
tmpUnpack
|
tmpUnpack
|
||||||
(do
|
(do
|
||||||
b <- if hadrian
|
b <- if hadrian
|
||||||
then compileHadrianBindist tver (fromGHCupPath workdir) ghcdir
|
-- prefer 'tver', because the real version carries out compatibility checks
|
||||||
else compileMakeBindist tver (fromGHCupPath workdir) ghcdir
|
-- we don't want the user to do funny things with it
|
||||||
|
then compileHadrianBindist (fromMaybe installVer tver) (fromGHCupPath workdir) ghcdir
|
||||||
|
else compileMakeBindist (fromMaybe installVer tver) (fromGHCupPath workdir) ghcdir
|
||||||
bmk <- liftIO $ handleIO (\_ -> pure "") $ B.readFile (build_mk $ fromGHCupPath workdir)
|
bmk <- liftIO $ handleIO (\_ -> pure "") $ B.readFile (build_mk $ fromGHCupPath workdir)
|
||||||
pure (b, bmk)
|
pure (b, bmk)
|
||||||
)
|
)
|
||||||
@@ -742,6 +950,7 @@ compileGHC targetGhc ov bstrap jobs mbuildConfig patches aargs buildFlavour hadr
|
|||||||
ghcdir
|
ghcdir
|
||||||
(installVer ^. tvVersion)
|
(installVer ^. tvVersion)
|
||||||
False -- not a force install, since we already overwrite when compiling.
|
False -- not a force install, since we already overwrite when compiling.
|
||||||
|
[]
|
||||||
|
|
||||||
liftIO $ B.writeFile (fromInstallDir ghcdir </> ghcUpSrcBuiltFile) bmk
|
liftIO $ B.writeFile (fromInstallDir ghcdir </> ghcUpSrcBuiltFile) bmk
|
||||||
|
|
||||||
@@ -757,11 +966,29 @@ compileGHC targetGhc ov bstrap jobs mbuildConfig patches aargs buildFlavour hadr
|
|||||||
pure installVer
|
pure installVer
|
||||||
|
|
||||||
where
|
where
|
||||||
|
getGHCVer :: ( MonadReader env m
|
||||||
|
, HasSettings env
|
||||||
|
, HasDirs env
|
||||||
|
, HasLog env
|
||||||
|
, MonadIO m
|
||||||
|
, MonadThrow m
|
||||||
|
)
|
||||||
|
=> GHCupPath
|
||||||
|
-> Excepts '[ProcessError, ParseError] m Version
|
||||||
|
getGHCVer tmpUnpack = do
|
||||||
|
lEM $ execWithGhcEnv "python3" ["./boot"] (Just $ fromGHCupPath tmpUnpack) "ghc-bootstrap"
|
||||||
|
lEM $ execWithGhcEnv "sh" ["./configure"] (Just $ fromGHCupPath tmpUnpack) "ghc-bootstrap"
|
||||||
|
CapturedProcess {..} <- lift $ makeOut
|
||||||
|
["show!", "--quiet", "VALUE=ProjectVersion" ] (Just $ fromGHCupPath tmpUnpack)
|
||||||
|
case _exitCode of
|
||||||
|
ExitSuccess -> either (throwE . ParseError . show) pure . MP.parse ghcProjectVersion "" . T.pack . stripNewlineEnd . T.unpack . decUTF8Safe' $ _stdOut
|
||||||
|
ExitFailure c -> throwE $ NonZeroExit c "make" ["show!", "--quiet", "VALUE=ProjectVersion" ]
|
||||||
|
|
||||||
defaultConf =
|
defaultConf =
|
||||||
let cross_mk = $(LitE . StringL <$> (qAddDependentFile "data/build_mk/cross" >> runIO (readFile "data/build_mk/cross")))
|
let cross_mk = $(LitE . StringL <$> (qAddDependentFile "data/build_mk/cross" >> runIO (readFile "data/build_mk/cross")))
|
||||||
default_mk = $(LitE . StringL <$> (qAddDependentFile "data/build_mk/default" >> runIO (readFile "data/build_mk/default")))
|
default_mk = $(LitE . StringL <$> (qAddDependentFile "data/build_mk/default" >> runIO (readFile "data/build_mk/default")))
|
||||||
in case targetGhc of
|
in case targetGhc of
|
||||||
Left (GHCTargetVersion (Just _) _) -> cross_mk
|
SourceDist (GHCTargetVersion (Just _) _) -> cross_mk
|
||||||
_ -> default_mk
|
_ -> default_mk
|
||||||
|
|
||||||
compileHadrianBindist :: ( MonadReader env m
|
compileHadrianBindist :: ( MonadReader env m
|
||||||
@@ -938,7 +1165,7 @@ compileGHC targetGhc ov bstrap jobs mbuildConfig patches aargs buildFlavour hadr
|
|||||||
|
|
||||||
-- for cross, we need Stage1Only
|
-- for cross, we need Stage1Only
|
||||||
case targetGhc of
|
case targetGhc of
|
||||||
Left (GHCTargetVersion (Just _) _) -> when ("Stage1Only = YES" `notElem` lines') $ throwE
|
SourceDist (GHCTargetVersion (Just _) _) -> when ("Stage1Only = YES" `notElem` lines') $ throwE
|
||||||
(InvalidBuildConfig
|
(InvalidBuildConfig
|
||||||
[s|Cross compiling needs to be a Stage1 build, add "Stage1Only = YES" to your config!|]
|
[s|Cross compiling needs to be a Stage1 build, add "Stage1Only = YES" to your config!|]
|
||||||
)
|
)
|
||||||
|
|||||||
181
lib/GHCup/HLS.hs
181
lib/GHCup/HLS.hs
@@ -70,6 +70,12 @@ import qualified Data.Text as T
|
|||||||
import qualified Text.Megaparsec as MP
|
import qualified Text.Megaparsec as MP
|
||||||
|
|
||||||
|
|
||||||
|
data HLSVer = SourceDist Version
|
||||||
|
| GitDist GitBranch
|
||||||
|
| HackageDist Version
|
||||||
|
| RemoteDist URI
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--------------------
|
--------------------
|
||||||
--[ Installation ]--
|
--[ Installation ]--
|
||||||
@@ -98,6 +104,7 @@ installHLSBindist :: ( MonadMask m
|
|||||||
'[ AlreadyInstalled
|
'[ AlreadyInstalled
|
||||||
, CopyError
|
, CopyError
|
||||||
, DigestError
|
, DigestError
|
||||||
|
, ContentLengthError
|
||||||
, GPGError
|
, GPGError
|
||||||
, DownloadFailed
|
, DownloadFailed
|
||||||
, NoDownload
|
, NoDownload
|
||||||
@@ -290,6 +297,7 @@ installHLSBin :: ( MonadMask m
|
|||||||
'[ AlreadyInstalled
|
'[ AlreadyInstalled
|
||||||
, CopyError
|
, CopyError
|
||||||
, DigestError
|
, DigestError
|
||||||
|
, ContentLengthError
|
||||||
, GPGError
|
, GPGError
|
||||||
, DownloadFailed
|
, DownloadFailed
|
||||||
, NoDownload
|
, NoDownload
|
||||||
@@ -323,34 +331,39 @@ compileHLS :: ( MonadMask m
|
|||||||
, MonadUnliftIO m
|
, MonadUnliftIO m
|
||||||
, MonadFail m
|
, MonadFail m
|
||||||
)
|
)
|
||||||
=> Either Version GitBranch
|
=> HLSVer
|
||||||
-> [Version]
|
-> [Version]
|
||||||
-> Maybe Int
|
-> Maybe Int
|
||||||
-> Maybe Version
|
-> Either Bool Version
|
||||||
-> InstallDir
|
-> InstallDir
|
||||||
-> Maybe (Either FilePath URI)
|
-> Maybe (Either FilePath URI)
|
||||||
-> Maybe URI
|
-> Maybe URI
|
||||||
|
-> Bool
|
||||||
-> Maybe (Either FilePath [URI]) -- ^ patches
|
-> Maybe (Either FilePath [URI]) -- ^ patches
|
||||||
-> [Text] -- ^ additional args to cabal install
|
-> [Text] -- ^ additional args to cabal install
|
||||||
-> Excepts '[ NoDownload
|
-> Excepts '[ NoDownload
|
||||||
, GPGError
|
, GPGError
|
||||||
, DownloadFailed
|
, DownloadFailed
|
||||||
, DigestError
|
, DigestError
|
||||||
|
, ContentLengthError
|
||||||
, UnknownArchive
|
, UnknownArchive
|
||||||
, TarDirDoesNotExist
|
, TarDirDoesNotExist
|
||||||
, ArchiveResult
|
, ArchiveResult
|
||||||
, BuildFailed
|
, BuildFailed
|
||||||
, NotInstalled
|
, NotInstalled
|
||||||
] m Version
|
] m Version
|
||||||
compileHLS targetHLS ghcs jobs ov installDir cabalProject cabalProjectLocal patches cabalArgs = do
|
compileHLS targetHLS ghcs jobs ov installDir cabalProject cabalProjectLocal updateCabal patches cabalArgs = do
|
||||||
PlatformRequest { .. } <- lift getPlatformReq
|
PlatformRequest { .. } <- lift getPlatformReq
|
||||||
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||||
Dirs { .. } <- lift getDirs
|
Dirs { .. } <- lift getDirs
|
||||||
|
|
||||||
|
when updateCabal $ reThrowAll @_ @'[ProcessError] DownloadFailed $ do
|
||||||
|
lift $ logInfo "Updating cabal DB"
|
||||||
|
lEM $ exec "cabal" ["update"] (Just $ fromGHCupPath tmpDir) Nothing
|
||||||
|
|
||||||
(workdir, tver) <- case targetHLS of
|
(workdir, tmpUnpack, tver, git_describe) <- case targetHLS of
|
||||||
-- unpack from version tarball
|
-- unpack from version tarball
|
||||||
Left tver -> do
|
SourceDist tver -> do
|
||||||
lift $ logDebug $ "Requested to compile: " <> prettyVer tver
|
lift $ logDebug $ "Requested to compile: " <> prettyVer tver
|
||||||
|
|
||||||
-- download source tarball
|
-- download source tarball
|
||||||
@@ -368,13 +381,50 @@ compileHLS targetHLS ghcs jobs ov installDir cabalProject cabalProjectLocal patc
|
|||||||
(liftE . intoSubdir tmpUnpack)
|
(liftE . intoSubdir tmpUnpack)
|
||||||
(view dlSubdir dlInfo)
|
(view dlSubdir dlInfo)
|
||||||
|
|
||||||
pure (workdir, tver)
|
pure (workdir, tmpUnpack, tver, Nothing)
|
||||||
|
|
||||||
|
HackageDist tver -> do
|
||||||
|
lift $ logDebug $ "Requested to compile (from hackage): " <> prettyVer tver
|
||||||
|
|
||||||
|
-- download source tarball
|
||||||
|
tmpUnpack <- lift mkGhcupTmpDir
|
||||||
|
let hls = "haskell-language-server-" <> T.unpack (prettyVer tver)
|
||||||
|
reThrowAll @_ @'[ProcessError] DownloadFailed $ do
|
||||||
|
-- unpack
|
||||||
|
lEM $ exec "cabal" ["unpack", hls] (Just $ fromGHCupPath tmpUnpack) Nothing
|
||||||
|
|
||||||
|
let workdir = appendGHCupPath tmpUnpack hls
|
||||||
|
|
||||||
|
pure (workdir, tmpUnpack, tver, Nothing)
|
||||||
|
|
||||||
|
RemoteDist uri -> do
|
||||||
|
lift $ logDebug $ "Requested to compile (from uri): " <> T.pack (show uri)
|
||||||
|
|
||||||
|
-- download source tarball
|
||||||
|
tmpDownload <- lift withGHCupTmpDir
|
||||||
|
tmpUnpack <- lift mkGhcupTmpDir
|
||||||
|
tar <- liftE $ download uri Nothing Nothing Nothing (fromGHCupPath tmpDownload) Nothing False
|
||||||
|
(cf, tver) <- liftE $ cleanUpOnError tmpUnpack $ do
|
||||||
|
unpackToDir (fromGHCupPath tmpUnpack) tar
|
||||||
|
let regex = [s|^(.*/)*haskell-language-server\.cabal$|] :: B.ByteString
|
||||||
|
[cabalFile] <- liftIO $ findFilesDeep
|
||||||
|
tmpUnpack
|
||||||
|
(makeRegexOpts compExtended
|
||||||
|
execBlank
|
||||||
|
regex
|
||||||
|
)
|
||||||
|
tver <- getCabalVersion (fromGHCupPath tmpUnpack </> cabalFile)
|
||||||
|
pure (cabalFile, tver)
|
||||||
|
|
||||||
|
let workdir = appendGHCupPath tmpUnpack (takeDirectory cf)
|
||||||
|
|
||||||
|
pure (workdir, tmpUnpack, tver, Nothing)
|
||||||
|
|
||||||
-- clone from git
|
-- clone from git
|
||||||
Right GitBranch{..} -> do
|
GitDist GitBranch{..} -> do
|
||||||
tmpUnpack <- lift mkGhcupTmpDir
|
tmpUnpack <- lift mkGhcupTmpDir
|
||||||
let git args = execLogged "git" ("--no-pager":args) (Just $ fromGHCupPath tmpUnpack) "git" Nothing
|
let git args = execLogged "git" ("--no-pager":args) (Just $ fromGHCupPath tmpUnpack) "git" Nothing
|
||||||
tver <- reThrowAll @_ @'[ProcessError] DownloadFailed $ do
|
reThrowAll @_ @'[ProcessError] DownloadFailed $ do
|
||||||
let rep = fromMaybe "https://github.com/haskell/haskell-language-server.git" repo
|
let rep = fromMaybe "https://github.com/haskell/haskell-language-server.git" repo
|
||||||
lift $ logInfo $ "Fetching git repo " <> T.pack rep <> " at ref " <> T.pack ref <> " (this may take a while)"
|
lift $ logInfo $ "Fetching git repo " <> T.pack rep <> " at ref " <> T.pack ref <> " (this may take a while)"
|
||||||
lEM $ git [ "init" ]
|
lEM $ git [ "init" ]
|
||||||
@@ -383,37 +433,57 @@ compileHLS targetHLS ghcs jobs ov installDir cabalProject cabalProjectLocal patc
|
|||||||
, "origin"
|
, "origin"
|
||||||
, fromString rep ]
|
, fromString rep ]
|
||||||
|
|
||||||
let fetch_args =
|
-- figure out if we can do a shallow clone
|
||||||
[ "fetch"
|
remoteBranches <- catchE @ProcessError @'[ProcessError] @'[] (\_ -> pure [])
|
||||||
, "--depth"
|
$ fmap processBranches $ gitOut ["ls-remote", "--heads", "origin"] (fromGHCupPath tmpUnpack)
|
||||||
, "1"
|
let shallow_clone
|
||||||
, "--quiet"
|
| gitDescribeRequested = False
|
||||||
, "origin"
|
| isCommitHash ref = True
|
||||||
, fromString ref ]
|
| fromString ref `elem` remoteBranches = True
|
||||||
|
| otherwise = False
|
||||||
|
|
||||||
|
lift $ logDebug $ "Shallow clone: " <> T.pack (show shallow_clone)
|
||||||
|
|
||||||
|
-- fetch
|
||||||
|
let fetch_args
|
||||||
|
| shallow_clone = ["fetch", "--depth", "1", "--quiet", "origin", fromString ref]
|
||||||
|
| otherwise = ["fetch", "--tags", "--quiet", "origin" ]
|
||||||
lEM $ git fetch_args
|
lEM $ git fetch_args
|
||||||
|
|
||||||
lEM $ git [ "checkout", "FETCH_HEAD" ]
|
-- checkout
|
||||||
(Just gpd) <- parseGenericPackageDescriptionMaybe <$> liftIO (B.readFile (fromGHCupPath tmpUnpack </> "haskell-language-server.cabal"))
|
lEM $ git [ "checkout", fromString ref ]
|
||||||
pure . (\c -> Version Nothing c [] Nothing)
|
|
||||||
. NE.fromList . fmap (NE.fromList . (:[]) . digits . fromIntegral)
|
|
||||||
. versionNumbers
|
|
||||||
. pkgVersion
|
|
||||||
. package
|
|
||||||
. packageDescription
|
|
||||||
$ gpd
|
|
||||||
|
|
||||||
liftE $ catchWarn $ lEM @_ @'[ProcessError] $ darwinNotarization _rPlatform (fromGHCupPath tmpUnpack)
|
-- gather some info
|
||||||
lift $ logInfo $ "Git version " <> T.pack ref <> " corresponds to HLS version " <> prettyVer tver
|
git_describe <- if shallow_clone
|
||||||
|
then pure Nothing
|
||||||
|
else fmap Just $ gitOut ["describe", "--tags"] (fromGHCupPath tmpUnpack)
|
||||||
|
chash <- gitOut ["rev-parse", "HEAD" ] (fromGHCupPath tmpUnpack)
|
||||||
|
tver <- getCabalVersion (fromGHCupPath tmpUnpack </> "haskell-language-server.cabal")
|
||||||
|
|
||||||
pure (tmpUnpack, tver)
|
liftE $ catchWarn $ lEM @_ @'[ProcessError] $ darwinNotarization _rPlatform (fromGHCupPath tmpUnpack)
|
||||||
|
lift $ logInfo $ "Examining git ref " <> T.pack ref <> "\n " <>
|
||||||
|
"HLS version (from cabal file): " <> prettyVer tver <>
|
||||||
|
(if not shallow_clone then "\n " <> "'git describe' output: " <> fromJust git_describe else mempty) <>
|
||||||
|
(if isCommitHash ref then mempty else "\n " <> "commit hash: " <> chash)
|
||||||
|
|
||||||
|
pure (tmpUnpack, tmpUnpack, tver, git_describe)
|
||||||
|
|
||||||
-- the version that's installed may differ from the
|
-- the version that's installed may differ from the
|
||||||
-- compiled version, so the user can overwrite it
|
-- compiled version, so the user can overwrite it
|
||||||
let installVer = fromMaybe tver ov
|
installVer <- case ov of
|
||||||
|
Left True -> case git_describe of
|
||||||
|
-- git describe
|
||||||
|
Just h -> either (fail . displayException) pure . version $ h
|
||||||
|
-- git describe, but not building from git, lol
|
||||||
|
Nothing -> pure tver
|
||||||
|
-- default: use detected version
|
||||||
|
Left False -> pure tver
|
||||||
|
-- overwrite version with users value
|
||||||
|
Right v -> pure v
|
||||||
|
|
||||||
liftE $ runBuildAction
|
liftE $ runBuildAction
|
||||||
workdir
|
tmpUnpack
|
||||||
(reThrowAll @_ @'[GPGError, DownloadFailed, DigestError, PatchFailed, ProcessError, FileAlreadyExistsError, CopyError] @'[BuildFailed] (BuildFailed $ fromGHCupPath workdir) $ do
|
(reThrowAll @_ @'[GPGError, DownloadFailed, DigestError, ContentLengthError, PatchFailed, ProcessError, FileAlreadyExistsError, CopyError] @'[BuildFailed] (BuildFailed $ fromGHCupPath workdir) $ do
|
||||||
let tmpInstallDir = fromGHCupPath workdir </> "out"
|
let tmpInstallDir = fromGHCupPath workdir </> "out"
|
||||||
liftIO $ createDirRecursive' tmpInstallDir
|
liftIO $ createDirRecursive' tmpInstallDir
|
||||||
|
|
||||||
@@ -428,14 +498,22 @@ compileHLS targetHLS ghcs jobs ov installDir cabalProject cabalProjectLocal patc
|
|||||||
pure "cabal.project"
|
pure "cabal.project"
|
||||||
| otherwise -> pure (takeFileName cp)
|
| otherwise -> pure (takeFileName cp)
|
||||||
Just (Right uri) -> do
|
Just (Right uri) -> do
|
||||||
tmpUnpack <- lift withGHCupTmpDir
|
tmpUnpack' <- lift withGHCupTmpDir
|
||||||
cp <- liftE $ download uri Nothing Nothing (fromGHCupPath tmpUnpack) (Just "cabal.project") False
|
cp <- liftE $ download uri Nothing Nothing Nothing (fromGHCupPath tmpUnpack') (Just "cabal.project") False
|
||||||
copyFileE cp (fromGHCupPath workdir </> "cabal.project") False
|
copyFileE cp (fromGHCupPath workdir </> "cabal.project") False
|
||||||
pure "cabal.project"
|
pure "cabal.project"
|
||||||
Nothing -> pure "cabal.project"
|
Nothing
|
||||||
|
| HackageDist _ <- targetHLS -> do
|
||||||
|
liftIO $ B.writeFile (fromGHCupPath workdir </> "cabal.project") "packages: ./"
|
||||||
|
pure "cabal.project"
|
||||||
|
| RemoteDist _ <- targetHLS -> do
|
||||||
|
let cabalFile = fromGHCupPath workdir </> "cabal.project"
|
||||||
|
liftIO $ whenM (not <$> doesFileExist cabalFile) $ B.writeFile cabalFile "packages: ./"
|
||||||
|
pure "cabal.project"
|
||||||
|
| otherwise -> pure "cabal.project"
|
||||||
forM_ cabalProjectLocal $ \uri -> do
|
forM_ cabalProjectLocal $ \uri -> do
|
||||||
tmpUnpack <- lift withGHCupTmpDir
|
tmpUnpack' <- lift withGHCupTmpDir
|
||||||
cpl <- liftE $ download uri Nothing Nothing (fromGHCupPath tmpUnpack) (Just (cp <.> "local")) False
|
cpl <- liftE $ download uri Nothing Nothing Nothing (fromGHCupPath tmpUnpack') (Just (cp <.> "local")) False
|
||||||
copyFileE cpl (fromGHCupPath workdir </> cp <.> "local") False
|
copyFileE cpl (fromGHCupPath workdir </> cp <.> "local") False
|
||||||
artifacts <- forM (sort ghcs) $ \ghc -> do
|
artifacts <- forM (sort ghcs) $ \ghc -> do
|
||||||
let ghcInstallDir = tmpInstallDir </> T.unpack (prettyVer ghc)
|
let ghcInstallDir = tmpInstallDir </> T.unpack (prettyVer ghc)
|
||||||
@@ -463,7 +541,7 @@ compileHLS targetHLS ghcs jobs ov installDir cabalProject cabalProjectLocal patc
|
|||||||
pure ghcInstallDir
|
pure ghcInstallDir
|
||||||
|
|
||||||
forM_ artifacts $ \artifact -> do
|
forM_ artifacts $ \artifact -> do
|
||||||
logInfo $ T.pack (show artifact)
|
logDebug $ T.pack (show artifact)
|
||||||
liftIO $ renameFile (artifact </> "haskell-language-server" <.> exeExt)
|
liftIO $ renameFile (artifact </> "haskell-language-server" <.> exeExt)
|
||||||
(tmpInstallDir </> "haskell-language-server-" <> takeFileName artifact <.> exeExt)
|
(tmpInstallDir </> "haskell-language-server-" <> takeFileName artifact <.> exeExt)
|
||||||
liftIO $ renameFile (artifact </> "haskell-language-server-wrapper" <.> exeExt)
|
liftIO $ renameFile (artifact </> "haskell-language-server-wrapper" <.> exeExt)
|
||||||
@@ -478,6 +556,10 @@ compileHLS targetHLS ghcs jobs ov installDir cabalProject cabalProjectLocal patc
|
|||||||
)
|
)
|
||||||
|
|
||||||
pure installVer
|
pure installVer
|
||||||
|
where
|
||||||
|
gitDescribeRequested = case ov of
|
||||||
|
Left b -> b
|
||||||
|
_ -> False
|
||||||
|
|
||||||
|
|
||||||
-----------------
|
-----------------
|
||||||
@@ -549,6 +631,10 @@ setHLS ver shls mBinDir = do
|
|||||||
when (isNothing mBinDir) $
|
when (isNothing mBinDir) $
|
||||||
lift warnAboutHlsCompatibility
|
lift warnAboutHlsCompatibility
|
||||||
|
|
||||||
|
liftIO (isShadowed wrapper) >>= \case
|
||||||
|
Nothing -> pure ()
|
||||||
|
Just pa -> lift $ logWarn $ T.pack $ prettyHFError (ToolShadowed HLS pa wrapper ver)
|
||||||
|
|
||||||
|
|
||||||
unsetHLS :: ( MonadMask m
|
unsetHLS :: ( MonadMask m
|
||||||
, MonadReader env m
|
, MonadReader env m
|
||||||
@@ -609,8 +695,11 @@ rmHLSVer ver = do
|
|||||||
lift $ recycleFile f
|
lift $ recycleFile f
|
||||||
when (not (null survivors)) $ throwE $ UninstallFailed hlsDir survivors
|
when (not (null survivors)) $ throwE $ UninstallFailed hlsDir survivors
|
||||||
Nothing -> do
|
Nothing -> do
|
||||||
lift $ logInfo $ "Removing legacy directory recursively: " <> T.pack hlsDir
|
isDir <- liftIO $ doesDirectoryExist hlsDir
|
||||||
recyclePathForcibly hlsDir'
|
isSyml <- liftIO $ handleIO (\_ -> pure False) $ pathIsSymbolicLink hlsDir
|
||||||
|
when (isDir && not isSyml) $ do
|
||||||
|
lift $ logInfo $ "Removing legacy directory recursively: " <> T.pack hlsDir
|
||||||
|
recyclePathForcibly hlsDir'
|
||||||
|
|
||||||
when (Just ver == isHlsSet) $ do
|
when (Just ver == isHlsSet) $ do
|
||||||
-- set latest hls
|
-- set latest hls
|
||||||
@@ -618,3 +707,19 @@ rmHLSVer ver = do
|
|||||||
case headMay . reverse . sort $ hlsVers of
|
case headMay . reverse . sort $ hlsVers of
|
||||||
Just latestver -> liftE $ setHLS latestver SetHLSOnly Nothing
|
Just latestver -> liftE $ setHLS latestver SetHLSOnly Nothing
|
||||||
Nothing -> pure ()
|
Nothing -> pure ()
|
||||||
|
|
||||||
|
|
||||||
|
getCabalVersion :: (MonadIO m, MonadFail m) => FilePath -> m Version
|
||||||
|
getCabalVersion fp = do
|
||||||
|
contents <- liftIO $ B.readFile fp
|
||||||
|
gpd <- case parseGenericPackageDescriptionMaybe contents of
|
||||||
|
Nothing -> fail $ "could not parse cabal file: " <> fp
|
||||||
|
Just r -> pure r
|
||||||
|
let tver = (\c -> Version Nothing c [] Nothing)
|
||||||
|
. NE.fromList . fmap (NE.fromList . (:[]) . digits . fromIntegral)
|
||||||
|
. versionNumbers
|
||||||
|
. pkgVersion
|
||||||
|
. package
|
||||||
|
. packageDescription
|
||||||
|
$ gpd
|
||||||
|
pure tver
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
{-# LANGUAGE FlexibleInstances #-}
|
{-# LANGUAGE FlexibleInstances #-}
|
||||||
{-# LANGUAGE ScopedTypeVariables #-}
|
{-# LANGUAGE ScopedTypeVariables #-}
|
||||||
{-# LANGUAGE TypeFamilies #-}
|
{-# LANGUAGE TypeFamilies #-}
|
||||||
|
{-# LANGUAGE TypeOperators #-}
|
||||||
|
|
||||||
{-|
|
{-|
|
||||||
Module : GHCup.Prelude
|
Module : GHCup.Prelude
|
||||||
@@ -27,6 +28,7 @@ module GHCup.Prelude
|
|||||||
)
|
)
|
||||||
where
|
where
|
||||||
|
|
||||||
|
import GHCup.Errors
|
||||||
import GHCup.Prelude.Internal
|
import GHCup.Prelude.Internal
|
||||||
import GHCup.Types.Optics (HasLog)
|
import GHCup.Types.Optics (HasLog)
|
||||||
import GHCup.Prelude.Logger (logWarn)
|
import GHCup.Prelude.Logger (logWarn)
|
||||||
@@ -39,16 +41,44 @@ import GHCup.Prelude.Posix
|
|||||||
import Control.Monad.IO.Class
|
import Control.Monad.IO.Class
|
||||||
import Control.Monad.Reader
|
import Control.Monad.Reader
|
||||||
import Haskus.Utils.Variant.Excepts
|
import Haskus.Utils.Variant.Excepts
|
||||||
import Text.PrettyPrint.HughesPJClass ( prettyShow, Pretty )
|
import Text.PrettyPrint.HughesPJClass ( Pretty )
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- for some obscure reason... this won't type-check if we move it to a different module
|
-- for some obscure reason... this won't type-check if we move it to a different module
|
||||||
catchWarn :: forall es m env . ( Pretty (V es)
|
catchWarn :: forall es m env . ( Pretty (V es)
|
||||||
|
, HFErrorProject (V es)
|
||||||
, MonadReader env m
|
, MonadReader env m
|
||||||
, HasLog env
|
, HasLog env
|
||||||
, MonadIO m
|
, MonadIO m
|
||||||
, Monad m) => Excepts es m () -> Excepts '[] m ()
|
, Monad m) => Excepts es m () -> Excepts '[] m ()
|
||||||
catchWarn = catchAllE @_ @es (\v -> lift $ logWarn (T.pack . prettyShow $ v))
|
catchWarn = catchAllE @_ @es (\v -> lift $ logWarn (T.pack . prettyHFError $ v))
|
||||||
|
|
||||||
|
|
||||||
|
runBothE' :: forall e m a b .
|
||||||
|
( Monad m
|
||||||
|
, Show (V e)
|
||||||
|
, Pretty (V e)
|
||||||
|
, HFErrorProject (V e)
|
||||||
|
, PopVariant InstallSetError e
|
||||||
|
, LiftVariant' e (InstallSetError ': e)
|
||||||
|
, e :<< (InstallSetError ': e)
|
||||||
|
)
|
||||||
|
=> Excepts e m a
|
||||||
|
-> Excepts e m b
|
||||||
|
-> Excepts (InstallSetError ': e) m ()
|
||||||
|
runBothE' a1 a2 = do
|
||||||
|
r1 <- lift $ runE @e a1
|
||||||
|
r2 <- lift $ runE @e a2
|
||||||
|
case (r1, r2) of
|
||||||
|
(VLeft e1, VLeft e2) -> throwE (InstallSetError e1 e2)
|
||||||
|
(VLeft e , _ ) -> throwSomeE e
|
||||||
|
(_ , VLeft e ) -> throwSomeE e
|
||||||
|
(VRight _, VRight _) -> pure ()
|
||||||
|
|
||||||
|
|
||||||
|
-- | Throw some exception
|
||||||
|
throwSomeE :: forall es' es a m. (Monad m, LiftVariant es' es) => V es' -> Excepts es m a
|
||||||
|
{-# INLINABLE throwSomeE #-}
|
||||||
|
throwSomeE = Excepts . pure . VLeft . liftVariant
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ import Streamly.Internal.Data.Unfold.Type
|
|||||||
import qualified Streamly.Internal.Data.Unfold as U
|
import qualified Streamly.Internal.Data.Unfold as U
|
||||||
import Streamly.Internal.Control.Concurrent ( withRunInIO )
|
import Streamly.Internal.Control.Concurrent ( withRunInIO )
|
||||||
import Streamly.Internal.Data.IOFinalizer ( newIOFinalizer, runIOFinalizer )
|
import Streamly.Internal.Data.IOFinalizer ( newIOFinalizer, runIOFinalizer )
|
||||||
|
import GHC.IO.Exception (IOException(ioe_type), IOErrorType (..))
|
||||||
|
|
||||||
|
|
||||||
-- | On unix, we can use symlinks, so we just get the
|
-- | On unix, we can use symlinks, so we just get the
|
||||||
@@ -116,8 +117,18 @@ copyFile from to fail' = do
|
|||||||
let dflags = [ FD.oNofollow
|
let dflags = [ FD.oNofollow
|
||||||
, if fail' then FD.oExcl else FD.oTrunc
|
, if fail' then FD.oExcl else FD.oTrunc
|
||||||
]
|
]
|
||||||
|
let openFdHandle' = openFdHandle to SPI.WriteOnly dflags $ Just sourceFileMode
|
||||||
bracket
|
bracket
|
||||||
(openFdHandle to SPI.WriteOnly dflags $ Just sourceFileMode)
|
(handleIO (\e -> if
|
||||||
|
-- if we copy from regular file to symlink, we need
|
||||||
|
-- to delete the symlink
|
||||||
|
| ioe_type e == InvalidArgument
|
||||||
|
, not fail' -> do
|
||||||
|
removeLink to
|
||||||
|
openFdHandle'
|
||||||
|
| otherwise -> throwIO e
|
||||||
|
)
|
||||||
|
openFdHandle')
|
||||||
(hClose . snd)
|
(hClose . snd)
|
||||||
$ \(_, tH) -> do
|
$ \(_, tH) -> do
|
||||||
hSetBinaryMode fH True
|
hSetBinaryMode fH True
|
||||||
@@ -268,11 +279,11 @@ removeEmptyDirectory = PD.removeDirectory
|
|||||||
|
|
||||||
-- | Create an 'Unfold' of directory contents.
|
-- | Create an 'Unfold' of directory contents.
|
||||||
unfoldDirContents :: (MonadMask m, MonadIO m, S.MonadAsync m) => Unfold m FilePath (FD.DirType, FilePath)
|
unfoldDirContents :: (MonadMask m, MonadIO m, S.MonadAsync m) => Unfold m FilePath (FD.DirType, FilePath)
|
||||||
unfoldDirContents = U.bracket (liftIO . openDirStream) (liftIO . closeDirStream) (Unfold step return)
|
unfoldDirContents = U.bracket (liftIO . openDirStreamPortable) (liftIO . closeDirStreamPortable) (Unfold step return)
|
||||||
where
|
where
|
||||||
{-# INLINE [0] step #-}
|
{-# INLINE [0] step #-}
|
||||||
step dirstream = do
|
step dirstream = do
|
||||||
(typ, e) <- liftIO $ readDirEnt dirstream
|
(typ, e) <- liftIO $ readDirEntPortable dirstream
|
||||||
return $ if
|
return $ if
|
||||||
| null e -> D.Stop
|
| null e -> D.Stop
|
||||||
| "." == e -> D.Skip dirstream
|
| "." == e -> D.Skip dirstream
|
||||||
@@ -297,8 +308,8 @@ getDirectoryContentsRecursiveUnfold = Unfold step (\s -> return (s, Nothing, [""
|
|||||||
step (_, Nothing, []) = return D.Stop
|
step (_, Nothing, []) = return D.Stop
|
||||||
|
|
||||||
step (topdir, Just (cdir, dirstream, finalizer), dirs) = flip onException (runIOFinalizer finalizer) $ do
|
step (topdir, Just (cdir, dirstream, finalizer), dirs) = flip onException (runIOFinalizer finalizer) $ do
|
||||||
(dt, f) <- liftIO $ readDirEnt dirstream
|
(dt, f) <- liftIO $ readDirEntPortable dirstream
|
||||||
if | FD.dtUnknown == dt -> do
|
if | f == "" -> do
|
||||||
runIOFinalizer finalizer
|
runIOFinalizer finalizer
|
||||||
return $ D.Skip (topdir, Nothing, dirs)
|
return $ D.Skip (topdir, Nothing, dirs)
|
||||||
| f == "." || f == ".."
|
| f == "." || f == ".."
|
||||||
@@ -312,8 +323,8 @@ getDirectoryContentsRecursiveUnfold = Unfold step (\s -> return (s, Nothing, [""
|
|||||||
|
|
||||||
acquire dir =
|
acquire dir =
|
||||||
withRunInIO $ \run -> mask_ $ run $ do
|
withRunInIO $ \run -> mask_ $ run $ do
|
||||||
dirstream <- liftIO $ openDirStream dir
|
dirstream <- liftIO $ openDirStreamPortable dir
|
||||||
ref <- newIOFinalizer (liftIO $ closeDirStream dirstream)
|
ref <- newIOFinalizer (liftIO $ closeDirStreamPortable dirstream)
|
||||||
return (dirstream, ref)
|
return (dirstream, ref)
|
||||||
|
|
||||||
getDirectoryContentsRecursiveBFSUnsafe :: (MonadMask m, MonadIO m, S.MonadAsync m)
|
getDirectoryContentsRecursiveBFSUnsafe :: (MonadMask m, MonadIO m, S.MonadAsync m)
|
||||||
|
|||||||
@@ -10,9 +10,20 @@
|
|||||||
module GHCup.Prelude.File.Posix.Traversals (
|
module GHCup.Prelude.File.Posix.Traversals (
|
||||||
-- lower-level stuff
|
-- lower-level stuff
|
||||||
readDirEnt
|
readDirEnt
|
||||||
|
, readDirEntPortable
|
||||||
|
, openDirStreamPortable
|
||||||
|
, closeDirStreamPortable
|
||||||
, unpackDirStream
|
, unpackDirStream
|
||||||
|
, DirStreamPortable
|
||||||
) where
|
) where
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
|
||||||
#if __GLASGOW_HASKELL__ < 710
|
#if __GLASGOW_HASKELL__ < 710
|
||||||
import Control.Applicative ((<$>))
|
import Control.Applicative ((<$>))
|
||||||
@@ -28,6 +39,7 @@ import Foreign.Storable
|
|||||||
import System.Posix
|
import System.Posix
|
||||||
import Foreign (alloca)
|
import Foreign (alloca)
|
||||||
import System.Posix.Internals (peekFilePath)
|
import System.Posix.Internals (peekFilePath)
|
||||||
|
import System.FilePath
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -36,8 +48,8 @@ import System.Posix.Internals (peekFilePath)
|
|||||||
----------------------------------------------------------
|
----------------------------------------------------------
|
||||||
-- dodgy stuff
|
-- dodgy stuff
|
||||||
|
|
||||||
type CDir = ()
|
data {-# CTYPE "DIR" #-} CDir
|
||||||
type CDirent = ()
|
data {-# CTYPE "struct dirent" #-} CDirent
|
||||||
|
|
||||||
-- Posix doesn't export DirStream, so to re-use that type we need to use
|
-- Posix doesn't export DirStream, so to re-use that type we need to use
|
||||||
-- unsafeCoerce. It's just a newtype, so this is a legitimate usage.
|
-- unsafeCoerce. It's just a newtype, so this is a legitimate usage.
|
||||||
@@ -56,7 +68,7 @@ foreign import ccall unsafe "__hscore_free_dirent"
|
|||||||
foreign import ccall unsafe "__hscore_d_name"
|
foreign import ccall unsafe "__hscore_d_name"
|
||||||
c_name :: Ptr CDirent -> IO CString
|
c_name :: Ptr CDirent -> IO CString
|
||||||
|
|
||||||
foreign import ccall unsafe "__posixdir_d_type"
|
foreign import capi unsafe "dirutils.h __posixdir_d_type"
|
||||||
c_type :: Ptr CDirent -> IO DirType
|
c_type :: Ptr CDirent -> IO DirType
|
||||||
|
|
||||||
----------------------------------------------------------
|
----------------------------------------------------------
|
||||||
@@ -90,3 +102,38 @@ readDirEnt (unpackDirStream -> dirp) =
|
|||||||
then return (dtUnknown, mempty)
|
then return (dtUnknown, mempty)
|
||||||
else throwErrno "readDirEnt"
|
else throwErrno "readDirEnt"
|
||||||
|
|
||||||
|
|
||||||
|
newtype DirStreamPortable = DirStreamPortable (FilePath, DirStream)
|
||||||
|
|
||||||
|
openDirStreamPortable :: FilePath -> IO DirStreamPortable
|
||||||
|
openDirStreamPortable fp = do
|
||||||
|
dirs <- openDirStream fp
|
||||||
|
pure $ DirStreamPortable (fp, dirs)
|
||||||
|
|
||||||
|
closeDirStreamPortable :: DirStreamPortable -> IO ()
|
||||||
|
closeDirStreamPortable (DirStreamPortable (_, dirs)) = closeDirStream dirs
|
||||||
|
|
||||||
|
readDirEntPortable :: DirStreamPortable -> IO (DirType, FilePath)
|
||||||
|
readDirEntPortable (DirStreamPortable (basedir, dirs)) = do
|
||||||
|
(dt, fp) <- readDirEnt dirs
|
||||||
|
case (dt, fp) of
|
||||||
|
(DirType #{const DT_BLK}, _) -> pure (dt, fp)
|
||||||
|
(DirType #{const DT_CHR}, _) -> pure (dt, fp)
|
||||||
|
(DirType #{const DT_DIR}, _) -> pure (dt, fp)
|
||||||
|
(DirType #{const DT_FIFO}, _) -> pure (dt, fp)
|
||||||
|
(DirType #{const DT_LNK}, _) -> pure (dt, fp)
|
||||||
|
(DirType #{const DT_REG}, _) -> pure (dt, fp)
|
||||||
|
(DirType #{const DT_SOCK}, _) -> pure (dt, fp)
|
||||||
|
(DirType #{const DT_UNKNOWN}, _) -> pure (dt, fp)
|
||||||
|
(_, _)
|
||||||
|
| fp /= "" -> do
|
||||||
|
stat <- getSymbolicLinkStatus (basedir </> fp)
|
||||||
|
pure $ (, fp) $ if | isBlockDevice stat -> DirType #{const DT_BLK}
|
||||||
|
| isCharacterDevice stat -> DirType #{const DT_CHR}
|
||||||
|
| isDirectory stat -> DirType #{const DT_DIR}
|
||||||
|
| isNamedPipe stat -> DirType #{const DT_FIFO}
|
||||||
|
| isSymbolicLink stat -> DirType #{const DT_LNK}
|
||||||
|
| isRegularFile stat -> DirType #{const DT_REG}
|
||||||
|
| isSocket stat -> DirType #{const DT_SOCK}
|
||||||
|
| otherwise -> DirType #{const DT_UNKNOWN}
|
||||||
|
|
||||||
@@ -206,10 +206,36 @@ exec :: MonadIO m
|
|||||||
-> Maybe [(String, String)] -- ^ optional environment
|
-> Maybe [(String, String)] -- ^ optional environment
|
||||||
-> m (Either ProcessError ())
|
-> m (Either ProcessError ())
|
||||||
exec exe args chdir env = do
|
exec exe args chdir env = do
|
||||||
|
-- https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/375
|
||||||
|
forM_ (Map.fromList <$> env) $ \cEnv -> do
|
||||||
|
let paths = ["PATH", "Path"]
|
||||||
|
curPaths = (\x -> maybe [] splitSearchPath (Map.lookup x cEnv)) =<< paths
|
||||||
|
newPath = intercalate [searchPathSeparator] curPaths
|
||||||
|
liftIO $ setEnv "PATH" ""
|
||||||
|
liftIO $ setEnv "Path" newPath
|
||||||
cp <- createProcessWithMingwPath ((proc exe args) { cwd = chdir, env = env })
|
cp <- createProcessWithMingwPath ((proc exe args) { cwd = chdir, env = env })
|
||||||
exit_code <- liftIO $ withCreateProcess cp $ \_ _ _ p -> waitForProcess p
|
exit_code <- liftIO $ withCreateProcess cp $ \_ _ _ p -> waitForProcess p
|
||||||
pure $ toProcessError exe args exit_code
|
pure $ toProcessError exe args exit_code
|
||||||
|
|
||||||
|
-- | Like 'exec', except doesn't add msys2 stuff to PATH.
|
||||||
|
execNoMinGW :: MonadIO m
|
||||||
|
=> FilePath -- ^ thing to execute
|
||||||
|
-> [FilePath] -- ^ args for the thing
|
||||||
|
-> Maybe FilePath -- ^ optionally chdir into this
|
||||||
|
-> Maybe [(String, String)] -- ^ optional environment
|
||||||
|
-> m (Either ProcessError ())
|
||||||
|
execNoMinGW exe args chdir env = do
|
||||||
|
-- https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/375
|
||||||
|
forM_ (Map.fromList <$> env) $ \cEnv -> do
|
||||||
|
let paths = ["PATH", "Path"]
|
||||||
|
curPaths = (\x -> maybe [] splitSearchPath (Map.lookup x cEnv)) =<< paths
|
||||||
|
newPath = intercalate [searchPathSeparator] curPaths
|
||||||
|
liftIO $ setEnv "PATH" ""
|
||||||
|
liftIO $ setEnv "Path" newPath
|
||||||
|
let cp = (proc exe args) { cwd = chdir, env = env }
|
||||||
|
exit_code <- liftIO $ withCreateProcess cp $ \_ _ _ p -> waitForProcess p
|
||||||
|
pure $ toProcessError exe args exit_code
|
||||||
|
|
||||||
|
|
||||||
-- | Thin wrapper around `executeFile`.
|
-- | Thin wrapper around `executeFile`.
|
||||||
execShell :: MonadIO m
|
execShell :: MonadIO m
|
||||||
@@ -231,8 +257,9 @@ createProcessWithMingwPath :: MonadIO m
|
|||||||
createProcessWithMingwPath cp = do
|
createProcessWithMingwPath cp = do
|
||||||
msys2Dir <- liftIO ghcupMsys2Dir
|
msys2Dir <- liftIO ghcupMsys2Dir
|
||||||
cEnv <- Map.fromList <$> maybe (liftIO getEnvironment) pure (env cp)
|
cEnv <- Map.fromList <$> maybe (liftIO getEnvironment) pure (env cp)
|
||||||
let mingWPaths = [msys2Dir </> "usr" </> "bin"
|
let mingWPaths = [msys2Dir </> "mingw64" </> "bin"
|
||||||
,msys2Dir </> "mingw64" </> "bin"]
|
,msys2Dir </> "usr" </> "bin"
|
||||||
|
]
|
||||||
paths = ["PATH", "Path"]
|
paths = ["PATH", "Path"]
|
||||||
curPaths = (\x -> maybe [] splitSearchPath (Map.lookup x cEnv)) =<< paths
|
curPaths = (\x -> maybe [] splitSearchPath (Map.lookup x cEnv)) =<< paths
|
||||||
newPath = intercalate [searchPathSeparator] (mingWPaths ++ curPaths)
|
newPath = intercalate [searchPathSeparator] (mingWPaths ++ curPaths)
|
||||||
|
|||||||
28
lib/GHCup/Prompts.hs
Normal file
28
lib/GHCup/Prompts.hs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
|
|
||||||
|
module GHCup.Prompts
|
||||||
|
( PromptQuestion,
|
||||||
|
PromptResponse (..),
|
||||||
|
getUserPromptResponse,
|
||||||
|
)
|
||||||
|
where
|
||||||
|
|
||||||
|
import Control.Monad.Reader
|
||||||
|
import qualified Data.Text.IO as TIO
|
||||||
|
import GHCup.Prelude.Logger
|
||||||
|
import GHCup.Types.Optics
|
||||||
|
import GHCup.Types (PromptQuestion, PromptResponse(..))
|
||||||
|
|
||||||
|
getUserPromptResponse :: ( HasLog env
|
||||||
|
, MonadReader env m
|
||||||
|
, MonadIO m)
|
||||||
|
=> PromptQuestion
|
||||||
|
-> m PromptResponse
|
||||||
|
|
||||||
|
getUserPromptResponse prompt = do
|
||||||
|
logInfo prompt
|
||||||
|
resp <- liftIO TIO.getLine
|
||||||
|
if resp `elem` ["YES", "yes", "y", "Y"]
|
||||||
|
then pure PromptYes
|
||||||
|
else pure PromptNo
|
||||||
@@ -81,6 +81,7 @@ installStackBin :: ( MonadMask m
|
|||||||
'[ AlreadyInstalled
|
'[ AlreadyInstalled
|
||||||
, CopyError
|
, CopyError
|
||||||
, DigestError
|
, DigestError
|
||||||
|
, ContentLengthError
|
||||||
, GPGError
|
, GPGError
|
||||||
, DownloadFailed
|
, DownloadFailed
|
||||||
, NoDownload
|
, NoDownload
|
||||||
@@ -119,6 +120,7 @@ installStackBindist :: ( MonadMask m
|
|||||||
'[ AlreadyInstalled
|
'[ AlreadyInstalled
|
||||||
, CopyError
|
, CopyError
|
||||||
, DigestError
|
, DigestError
|
||||||
|
, ContentLengthError
|
||||||
, GPGError
|
, GPGError
|
||||||
, DownloadFailed
|
, DownloadFailed
|
||||||
, NoDownload
|
, NoDownload
|
||||||
@@ -229,6 +231,10 @@ setStack ver = do
|
|||||||
|
|
||||||
lift $ createLink targetFile stackbin
|
lift $ createLink targetFile stackbin
|
||||||
|
|
||||||
|
liftIO (isShadowed stackbin) >>= \case
|
||||||
|
Nothing -> pure ()
|
||||||
|
Just pa -> lift $ logWarn $ T.pack $ prettyHFError (ToolShadowed Cabal pa stackbin ver)
|
||||||
|
|
||||||
pure ()
|
pure ()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ import Data.Text ( Text )
|
|||||||
import Data.Versions
|
import Data.Versions
|
||||||
import GHC.IO.Exception ( ExitCode )
|
import GHC.IO.Exception ( ExitCode )
|
||||||
import Optics ( makeLenses )
|
import Optics ( makeLenses )
|
||||||
import Text.PrettyPrint.HughesPJClass (Pretty, pPrint, text, (<+>))
|
import Text.PrettyPrint.HughesPJClass (Pretty, pPrint, text)
|
||||||
import URI.ByteString
|
import URI.ByteString
|
||||||
#if defined(BRICK)
|
#if defined(BRICK)
|
||||||
import Graphics.Vty ( Key(..) )
|
import Graphics.Vty ( Key(..) )
|
||||||
@@ -138,6 +138,7 @@ data VersionInfo = VersionInfo
|
|||||||
{ _viTags :: [Tag] -- ^ version specific tag
|
{ _viTags :: [Tag] -- ^ version specific tag
|
||||||
, _viChangeLog :: Maybe URI
|
, _viChangeLog :: Maybe URI
|
||||||
, _viSourceDL :: Maybe DownloadInfo -- ^ source tarball
|
, _viSourceDL :: Maybe DownloadInfo -- ^ source tarball
|
||||||
|
, _viTestDL :: Maybe DownloadInfo -- ^ test tarball
|
||||||
, _viArch :: ArchitectureSpec -- ^ descend for binary downloads per arch
|
, _viArch :: ArchitectureSpec -- ^ descend for binary downloads per arch
|
||||||
-- informative messages
|
-- informative messages
|
||||||
, _viPostInstall :: Maybe Text
|
, _viPostInstall :: Maybe Text
|
||||||
@@ -262,6 +263,7 @@ data DownloadInfo = DownloadInfo
|
|||||||
{ _dlUri :: URI
|
{ _dlUri :: URI
|
||||||
, _dlSubdir :: Maybe TarDir
|
, _dlSubdir :: Maybe TarDir
|
||||||
, _dlHash :: Text
|
, _dlHash :: Text
|
||||||
|
, _dlCSize :: Maybe Integer
|
||||||
}
|
}
|
||||||
deriving (Eq, Ord, GHC.Generic, Show)
|
deriving (Eq, Ord, GHC.Generic, Show)
|
||||||
|
|
||||||
@@ -273,6 +275,23 @@ instance NFData DownloadInfo
|
|||||||
--[ Others ]--
|
--[ Others ]--
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
|
data DownloadMirror = DownloadMirror {
|
||||||
|
authority :: Authority
|
||||||
|
, pathPrefix :: Maybe Text
|
||||||
|
} deriving (Eq, Ord, GHC.Generic, Show)
|
||||||
|
|
||||||
|
instance NFData DownloadMirror
|
||||||
|
|
||||||
|
newtype DownloadMirrors = DM (Map Text DownloadMirror)
|
||||||
|
deriving (Eq, Ord, GHC.Generic, Show)
|
||||||
|
|
||||||
|
instance NFData DownloadMirrors
|
||||||
|
|
||||||
|
instance NFData UserInfo
|
||||||
|
instance NFData Host
|
||||||
|
instance NFData Port
|
||||||
|
instance NFData Authority
|
||||||
|
|
||||||
|
|
||||||
-- | How to descend into a tar archive.
|
-- | How to descend into a tar archive.
|
||||||
data TarDir = RealDir FilePath
|
data TarDir = RealDir FilePath
|
||||||
@@ -297,10 +316,16 @@ instance NFData URLSource
|
|||||||
instance NFData (URIRef Absolute) where
|
instance NFData (URIRef Absolute) where
|
||||||
rnf (URI !_ !_ !_ !_ !_) = ()
|
rnf (URI !_ !_ !_ !_ !_) = ()
|
||||||
|
|
||||||
|
data MetaMode = Strict
|
||||||
|
| Lax
|
||||||
|
deriving (Show, Read, Eq, GHC.Generic)
|
||||||
|
|
||||||
|
instance NFData MetaMode
|
||||||
|
|
||||||
data UserSettings = UserSettings
|
data UserSettings = UserSettings
|
||||||
{ uCache :: Maybe Bool
|
{ uCache :: Maybe Bool
|
||||||
, uMetaCache :: Maybe Integer
|
, uMetaCache :: Maybe Integer
|
||||||
|
, uMetaMode :: Maybe MetaMode
|
||||||
, uNoVerify :: Maybe Bool
|
, uNoVerify :: Maybe Bool
|
||||||
, uVerbose :: Maybe Bool
|
, uVerbose :: Maybe Bool
|
||||||
, uKeepDirs :: Maybe KeepDirs
|
, uKeepDirs :: Maybe KeepDirs
|
||||||
@@ -309,17 +334,20 @@ data UserSettings = UserSettings
|
|||||||
, uUrlSource :: Maybe URLSource
|
, uUrlSource :: Maybe URLSource
|
||||||
, uNoNetwork :: Maybe Bool
|
, uNoNetwork :: Maybe Bool
|
||||||
, uGPGSetting :: Maybe GPGSetting
|
, uGPGSetting :: Maybe GPGSetting
|
||||||
|
, uPlatformOverride :: Maybe PlatformRequest
|
||||||
|
, uMirrors :: Maybe DownloadMirrors
|
||||||
}
|
}
|
||||||
deriving (Show, GHC.Generic)
|
deriving (Show, GHC.Generic)
|
||||||
|
|
||||||
defaultUserSettings :: UserSettings
|
defaultUserSettings :: UserSettings
|
||||||
defaultUserSettings = UserSettings Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing
|
defaultUserSettings = UserSettings Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing
|
||||||
|
|
||||||
fromSettings :: Settings -> Maybe KeyBindings -> UserSettings
|
fromSettings :: Settings -> Maybe KeyBindings -> UserSettings
|
||||||
fromSettings Settings{..} Nothing =
|
fromSettings Settings{..} Nothing =
|
||||||
UserSettings {
|
UserSettings {
|
||||||
uCache = Just cache
|
uCache = Just cache
|
||||||
, uMetaCache = Just metaCache
|
, uMetaCache = Just metaCache
|
||||||
|
, uMetaMode = Just metaMode
|
||||||
, uNoVerify = Just noVerify
|
, uNoVerify = Just noVerify
|
||||||
, uVerbose = Just verbose
|
, uVerbose = Just verbose
|
||||||
, uKeepDirs = Just keepDirs
|
, uKeepDirs = Just keepDirs
|
||||||
@@ -328,22 +356,25 @@ fromSettings Settings{..} Nothing =
|
|||||||
, uKeyBindings = Nothing
|
, uKeyBindings = Nothing
|
||||||
, uUrlSource = Just urlSource
|
, uUrlSource = Just urlSource
|
||||||
, uGPGSetting = Just gpgSetting
|
, uGPGSetting = Just gpgSetting
|
||||||
|
, uPlatformOverride = platformOverride
|
||||||
|
, uMirrors = Just mirrors
|
||||||
}
|
}
|
||||||
fromSettings Settings{..} (Just KeyBindings{..}) =
|
fromSettings Settings{..} (Just KeyBindings{..}) =
|
||||||
let ukb = UserKeyBindings
|
let ukb = UserKeyBindings
|
||||||
{ kUp = Just bUp
|
{ kUp = Just bUp
|
||||||
, kDown = Just bDown
|
, kDown = Just bDown
|
||||||
, kQuit = Just bQuit
|
, kQuit = Just bQuit
|
||||||
, kInstall = Just bInstall
|
, kInstall = Just bInstall
|
||||||
, kUninstall = Just bUninstall
|
, kUninstall = Just bUninstall
|
||||||
, kSet = Just bSet
|
, kSet = Just bSet
|
||||||
, kChangelog = Just bChangelog
|
, kChangelog = Just bChangelog
|
||||||
, kShowAll = Just bShowAllVersions
|
, kShowAll = Just bShowAllVersions
|
||||||
, kShowAllTools = Just bShowAllTools
|
, kShowAllTools = Just bShowAllTools
|
||||||
}
|
}
|
||||||
in UserSettings {
|
in UserSettings {
|
||||||
uCache = Just cache
|
uCache = Just cache
|
||||||
, uMetaCache = Just metaCache
|
, uMetaCache = Just metaCache
|
||||||
|
, uMetaMode = Just metaMode
|
||||||
, uNoVerify = Just noVerify
|
, uNoVerify = Just noVerify
|
||||||
, uVerbose = Just verbose
|
, uVerbose = Just verbose
|
||||||
, uKeepDirs = Just keepDirs
|
, uKeepDirs = Just keepDirs
|
||||||
@@ -352,6 +383,8 @@ fromSettings Settings{..} (Just KeyBindings{..}) =
|
|||||||
, uKeyBindings = Just ukb
|
, uKeyBindings = Just ukb
|
||||||
, uUrlSource = Just urlSource
|
, uUrlSource = Just urlSource
|
||||||
, uGPGSetting = Just gpgSetting
|
, uGPGSetting = Just gpgSetting
|
||||||
|
, uPlatformOverride = platformOverride
|
||||||
|
, uMirrors = Just mirrors
|
||||||
}
|
}
|
||||||
|
|
||||||
data UserKeyBindings = UserKeyBindings
|
data UserKeyBindings = UserKeyBindings
|
||||||
@@ -381,7 +414,9 @@ data KeyBindings = KeyBindings
|
|||||||
deriving (Show, GHC.Generic)
|
deriving (Show, GHC.Generic)
|
||||||
|
|
||||||
instance NFData KeyBindings
|
instance NFData KeyBindings
|
||||||
|
#if defined(IS_WINDOWS) || !defined(BRICK)
|
||||||
instance NFData Key
|
instance NFData Key
|
||||||
|
#endif
|
||||||
|
|
||||||
defaultKeyBindings :: KeyBindings
|
defaultKeyBindings :: KeyBindings
|
||||||
defaultKeyBindings = KeyBindings
|
defaultKeyBindings = KeyBindings
|
||||||
@@ -407,6 +442,9 @@ data AppState = AppState
|
|||||||
|
|
||||||
instance NFData AppState
|
instance NFData AppState
|
||||||
|
|
||||||
|
fromAppState :: AppState -> LeanAppState
|
||||||
|
fromAppState AppState {..} = LeanAppState {..}
|
||||||
|
|
||||||
data LeanAppState = LeanAppState
|
data LeanAppState = LeanAppState
|
||||||
{ settings :: Settings
|
{ settings :: Settings
|
||||||
, dirs :: Dirs
|
, dirs :: Dirs
|
||||||
@@ -418,16 +456,19 @@ instance NFData LeanAppState
|
|||||||
|
|
||||||
|
|
||||||
data Settings = Settings
|
data Settings = Settings
|
||||||
{ cache :: Bool
|
{ cache :: Bool
|
||||||
, metaCache :: Integer
|
, metaCache :: Integer
|
||||||
, noVerify :: Bool
|
, metaMode :: MetaMode
|
||||||
, keepDirs :: KeepDirs
|
, noVerify :: Bool
|
||||||
, downloader :: Downloader
|
, keepDirs :: KeepDirs
|
||||||
, verbose :: Bool
|
, downloader :: Downloader
|
||||||
, urlSource :: URLSource
|
, verbose :: Bool
|
||||||
, noNetwork :: Bool
|
, urlSource :: URLSource
|
||||||
, gpgSetting :: GPGSetting
|
, noNetwork :: Bool
|
||||||
, noColor :: Bool -- this also exists in LoggerConfig
|
, gpgSetting :: GPGSetting
|
||||||
|
, noColor :: Bool -- this also exists in LoggerConfig
|
||||||
|
, platformOverride :: Maybe PlatformRequest
|
||||||
|
, mirrors :: DownloadMirrors
|
||||||
}
|
}
|
||||||
deriving (Show, GHC.Generic)
|
deriving (Show, GHC.Generic)
|
||||||
|
|
||||||
@@ -435,7 +476,7 @@ defaultMetaCache :: Integer
|
|||||||
defaultMetaCache = 300 -- 5 minutes
|
defaultMetaCache = 300 -- 5 minutes
|
||||||
|
|
||||||
defaultSettings :: Settings
|
defaultSettings :: Settings
|
||||||
defaultSettings = Settings False defaultMetaCache False Never Curl False GHCupURL False GPGNone False
|
defaultSettings = Settings False defaultMetaCache Lax False Never Curl False GHCupURL False GPGNone False Nothing (DM mempty)
|
||||||
|
|
||||||
instance NFData Settings
|
instance NFData Settings
|
||||||
|
|
||||||
@@ -615,15 +656,7 @@ data ProcessError = NonZeroExit Int FilePath [String]
|
|||||||
| NoSuchPid FilePath [String]
|
| NoSuchPid FilePath [String]
|
||||||
deriving Show
|
deriving Show
|
||||||
|
|
||||||
instance Pretty ProcessError where
|
|
||||||
pPrint (NonZeroExit e exe args) =
|
|
||||||
text "Process" <+> pPrint exe <+> text "with arguments" <+> pPrint args <+> text "failed with exit code" <+> text (show e <> ".")
|
|
||||||
pPrint (PTerminated exe args) =
|
|
||||||
text "Process" <+> pPrint exe <+> text "with arguments" <+> pPrint args <+> text "terminated."
|
|
||||||
pPrint (PStopped exe args) =
|
|
||||||
text "Process" <+> pPrint exe <+> text "with arguments" <+> pPrint args <+> text "stopped."
|
|
||||||
pPrint (NoSuchPid exe args) =
|
|
||||||
text "Could not find PID for process running " <+> pPrint exe <+> text " with arguments " <+> text (show args) <+> text "."
|
|
||||||
data CapturedProcess = CapturedProcess
|
data CapturedProcess = CapturedProcess
|
||||||
{ _exitCode :: ExitCode
|
{ _exitCode :: ExitCode
|
||||||
, _stdOut :: BL.ByteString
|
, _stdOut :: BL.ByteString
|
||||||
@@ -654,10 +687,7 @@ isSafeDir (IsolateDirResolved _) = False
|
|||||||
isSafeDir (GHCupDir _) = True
|
isSafeDir (GHCupDir _) = True
|
||||||
isSafeDir (GHCupBinDir _) = False
|
isSafeDir (GHCupBinDir _) = False
|
||||||
|
|
||||||
|
type PromptQuestion = Text
|
||||||
|
|
||||||
|
data PromptResponse = PromptYes | PromptNo
|
||||||
|
deriving (Show, Eq)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import Control.Applicative ( (<|>) )
|
|||||||
import Data.Aeson hiding (Key)
|
import Data.Aeson hiding (Key)
|
||||||
import Data.Aeson.TH
|
import Data.Aeson.TH
|
||||||
import Data.Aeson.Types hiding (Key)
|
import Data.Aeson.Types hiding (Key)
|
||||||
|
import Data.ByteString ( ByteString )
|
||||||
import Data.List.NonEmpty ( NonEmpty(..) )
|
import Data.List.NonEmpty ( NonEmpty(..) )
|
||||||
import Data.Text.Encoding as E
|
import Data.Text.Encoding as E
|
||||||
import Data.Versions
|
import Data.Versions
|
||||||
@@ -43,6 +44,7 @@ import qualified Text.Megaparsec as MP
|
|||||||
import qualified Text.Megaparsec.Char as MPC
|
import qualified Text.Megaparsec.Char as MPC
|
||||||
|
|
||||||
|
|
||||||
|
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''MetaMode
|
||||||
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''Architecture
|
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''Architecture
|
||||||
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''LinuxDistro
|
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''LinuxDistro
|
||||||
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''VSep
|
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''VSep
|
||||||
@@ -56,6 +58,7 @@ deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''Global
|
|||||||
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''KeepDirs
|
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''KeepDirs
|
||||||
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''Downloader
|
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''Downloader
|
||||||
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''GPGSetting
|
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''GPGSetting
|
||||||
|
deriveJSON defaultOptions { fieldLabelModifier = \str' -> maybe str' T.unpack . T.stripPrefix (T.pack "r-") . T.pack . kebab . tail $ str' } ''PlatformRequest
|
||||||
|
|
||||||
instance ToJSON Tag where
|
instance ToJSON Tag where
|
||||||
toJSON Latest = String "Latest"
|
toJSON Latest = String "Latest"
|
||||||
@@ -79,37 +82,6 @@ instance FromJSON Tag where
|
|||||||
instance ToJSON URI where
|
instance ToJSON URI where
|
||||||
toJSON = toJSON . E.decodeUtf8With E.lenientDecode . serializeURIRef'
|
toJSON = toJSON . E.decodeUtf8With E.lenientDecode . serializeURIRef'
|
||||||
|
|
||||||
instance FromJSON URLSource where
|
|
||||||
parseJSON v =
|
|
||||||
parseGHCupURL v
|
|
||||||
<|> parseOwnSourceLegacy v
|
|
||||||
<|> parseOwnSourceNew1 v
|
|
||||||
<|> parseOwnSourceNew2 v
|
|
||||||
<|> parseOwnSpec v
|
|
||||||
<|> legacyParseAddSource v
|
|
||||||
<|> newParseAddSource v
|
|
||||||
where
|
|
||||||
parseOwnSourceLegacy = withObject "URLSource" $ \o -> do
|
|
||||||
r :: URI <- o .: "OwnSource"
|
|
||||||
pure (OwnSource [Right r])
|
|
||||||
parseOwnSourceNew1 = withObject "URLSource" $ \o -> do
|
|
||||||
r :: [URI] <- o .: "OwnSource"
|
|
||||||
pure (OwnSource (fmap Right r))
|
|
||||||
parseOwnSourceNew2 = withObject "URLSource" $ \o -> do
|
|
||||||
r :: [Either GHCupInfo URI] <- o .: "OwnSource"
|
|
||||||
pure (OwnSource r)
|
|
||||||
parseOwnSpec = withObject "URLSource" $ \o -> do
|
|
||||||
r :: GHCupInfo <- o .: "OwnSpec"
|
|
||||||
pure (OwnSpec r)
|
|
||||||
parseGHCupURL = withObject "URLSource" $ \o -> do
|
|
||||||
_ :: [Value] <- o .: "GHCupURL"
|
|
||||||
pure GHCupURL
|
|
||||||
legacyParseAddSource = withObject "URLSource" $ \o -> do
|
|
||||||
r :: Either GHCupInfo URI <- o .: "AddSource"
|
|
||||||
pure (AddSource [r])
|
|
||||||
newParseAddSource = withObject "URLSource" $ \o -> do
|
|
||||||
r :: [Either GHCupInfo URI] <- o .: "AddSource"
|
|
||||||
pure (AddSource r)
|
|
||||||
|
|
||||||
instance FromJSON URI where
|
instance FromJSON URI where
|
||||||
parseJSON = withText "URL" $ \t ->
|
parseJSON = withText "URL" $ \t ->
|
||||||
@@ -254,6 +226,12 @@ instance FromJSON VersionCmp where
|
|||||||
Right r -> pure r
|
Right r -> pure r
|
||||||
Left e -> fail (MP.errorBundlePretty e)
|
Left e -> fail (MP.errorBundlePretty e)
|
||||||
|
|
||||||
|
instance ToJSON ByteString where
|
||||||
|
toJSON = toJSON . E.decodeUtf8With E.lenientDecode
|
||||||
|
|
||||||
|
instance FromJSON ByteString where
|
||||||
|
parseJSON = withText "ByteString" $ \t -> pure $ E.encodeUtf8 t
|
||||||
|
|
||||||
versionCmpToText :: VersionCmp -> T.Text
|
versionCmpToText :: VersionCmp -> T.Text
|
||||||
versionCmpToText (VR_gt ver') = "> " <> prettyV ver'
|
versionCmpToText (VR_gt ver') = "> " <> prettyV ver'
|
||||||
versionCmpToText (VR_gteq ver') = ">= " <> prettyV ver'
|
versionCmpToText (VR_gteq ver') = ">= " <> prettyV ver'
|
||||||
@@ -349,7 +327,45 @@ deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''GHCupI
|
|||||||
deriveToJSON defaultOptions { sumEncoding = ObjectWithSingleField } ''URLSource
|
deriveToJSON defaultOptions { sumEncoding = ObjectWithSingleField } ''URLSource
|
||||||
deriveJSON defaultOptions { sumEncoding = ObjectWithSingleField } ''Key
|
deriveJSON defaultOptions { sumEncoding = ObjectWithSingleField } ''Key
|
||||||
deriveJSON defaultOptions { fieldLabelModifier = \str' -> maybe str' T.unpack . T.stripPrefix (T.pack "k-") . T.pack . kebab $ str' } ''UserKeyBindings
|
deriveJSON defaultOptions { fieldLabelModifier = \str' -> maybe str' T.unpack . T.stripPrefix (T.pack "k-") . T.pack . kebab $ str' } ''UserKeyBindings
|
||||||
deriveJSON defaultOptions { fieldLabelModifier = \str' -> maybe str' T.unpack . T.stripPrefix (T.pack "u-") . T.pack . kebab $ str' } ''UserSettings
|
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel, unwrapUnaryRecords = True } ''Port
|
||||||
|
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel, unwrapUnaryRecords = True } ''Host
|
||||||
|
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''UserInfo
|
||||||
|
deriveJSON defaultOptions { fieldLabelModifier = \str' -> maybe str' (T.unpack . T.toLower) . T.stripPrefix (T.pack "authority") . T.pack $ str' } ''Authority
|
||||||
|
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''DownloadMirror
|
||||||
|
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''DownloadMirrors
|
||||||
deriveToJSON defaultOptions { fieldLabelModifier = kebab } ''Settings
|
deriveToJSON defaultOptions { fieldLabelModifier = kebab } ''Settings
|
||||||
deriveToJSON defaultOptions { fieldLabelModifier = drop 2 . kebab } ''KeyBindings -- move under key-bindings key
|
deriveToJSON defaultOptions { fieldLabelModifier = drop 2 . kebab } ''KeyBindings -- move under key-bindings key
|
||||||
|
|
||||||
|
instance FromJSON URLSource where
|
||||||
|
parseJSON v =
|
||||||
|
parseGHCupURL v
|
||||||
|
<|> parseOwnSourceLegacy v
|
||||||
|
<|> parseOwnSourceNew1 v
|
||||||
|
<|> parseOwnSourceNew2 v
|
||||||
|
<|> parseOwnSpec v
|
||||||
|
<|> legacyParseAddSource v
|
||||||
|
<|> newParseAddSource v
|
||||||
|
where
|
||||||
|
parseOwnSourceLegacy = withObject "URLSource" $ \o -> do
|
||||||
|
r :: URI <- o .: "OwnSource"
|
||||||
|
pure (OwnSource [Right r])
|
||||||
|
parseOwnSourceNew1 = withObject "URLSource" $ \o -> do
|
||||||
|
r :: [URI] <- o .: "OwnSource"
|
||||||
|
pure (OwnSource (fmap Right r))
|
||||||
|
parseOwnSourceNew2 = withObject "URLSource" $ \o -> do
|
||||||
|
r :: [Either GHCupInfo URI] <- o .: "OwnSource"
|
||||||
|
pure (OwnSource r)
|
||||||
|
parseOwnSpec = withObject "URLSource" $ \o -> do
|
||||||
|
r :: GHCupInfo <- o .: "OwnSpec"
|
||||||
|
pure (OwnSpec r)
|
||||||
|
parseGHCupURL = withObject "URLSource" $ \o -> do
|
||||||
|
_ :: [Value] <- o .: "GHCupURL"
|
||||||
|
pure GHCupURL
|
||||||
|
legacyParseAddSource = withObject "URLSource" $ \o -> do
|
||||||
|
r :: Either GHCupInfo URI <- o .: "AddSource"
|
||||||
|
pure (AddSource [r])
|
||||||
|
newParseAddSource = withObject "URLSource" $ \o -> do
|
||||||
|
r :: [Either GHCupInfo URI] <- o .: "AddSource"
|
||||||
|
pure (AddSource r)
|
||||||
|
|
||||||
|
deriveJSON defaultOptions { fieldLabelModifier = \str' -> maybe str' T.unpack . T.stripPrefix (T.pack "u-") . T.pack . kebab $ str' } ''UserSettings
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ import Control.Monad.Reader
|
|||||||
import Control.Monad.Trans.Resource
|
import Control.Monad.Trans.Resource
|
||||||
hiding ( throwM )
|
hiding ( throwM )
|
||||||
import Control.Monad.IO.Unlift ( MonadUnliftIO( withRunInIO ) )
|
import Control.Monad.IO.Unlift ( MonadUnliftIO( withRunInIO ) )
|
||||||
|
import Data.Char ( isHexDigit )
|
||||||
import Data.Bifunctor ( first )
|
import Data.Bifunctor ( first )
|
||||||
import Data.ByteString ( ByteString )
|
import Data.ByteString ( ByteString )
|
||||||
import Data.Either
|
import Data.Either
|
||||||
@@ -92,6 +93,7 @@ import qualified Data.List.NonEmpty as NE
|
|||||||
import qualified Streamly.Prelude as S
|
import qualified Streamly.Prelude as S
|
||||||
import Control.DeepSeq (force)
|
import Control.DeepSeq (force)
|
||||||
import GHC.IO (evaluate)
|
import GHC.IO (evaluate)
|
||||||
|
import System.Environment (getEnvironment, setEnv)
|
||||||
|
|
||||||
|
|
||||||
-- $setup
|
-- $setup
|
||||||
@@ -966,11 +968,28 @@ make :: ( MonadThrow m
|
|||||||
=> [String]
|
=> [String]
|
||||||
-> Maybe FilePath
|
-> Maybe FilePath
|
||||||
-> m (Either ProcessError ())
|
-> m (Either ProcessError ())
|
||||||
make args workdir = do
|
make args workdir = make' args workdir "ghc-make" Nothing
|
||||||
|
|
||||||
|
|
||||||
|
-- | Calls gmake if it exists in PATH, otherwise make.
|
||||||
|
make' :: ( MonadThrow m
|
||||||
|
, MonadIO m
|
||||||
|
, MonadReader env m
|
||||||
|
, HasDirs env
|
||||||
|
, HasLog env
|
||||||
|
, HasSettings env
|
||||||
|
)
|
||||||
|
=> [String]
|
||||||
|
-> Maybe FilePath
|
||||||
|
-> FilePath -- ^ log filename (opened in append mode)
|
||||||
|
-> Maybe [(String, String)] -- ^ optional environment
|
||||||
|
-> m (Either ProcessError ())
|
||||||
|
make' args workdir logfile menv = do
|
||||||
spaths <- liftIO getSearchPath
|
spaths <- liftIO getSearchPath
|
||||||
has_gmake <- isJust <$> liftIO (searchPath spaths "gmake")
|
has_gmake <- isJust <$> liftIO (searchPath spaths "gmake")
|
||||||
let mymake = if has_gmake then "gmake" else "make"
|
let mymake = if has_gmake then "gmake" else "make"
|
||||||
execLogged mymake args workdir "ghc-make" Nothing
|
execLogged mymake args workdir logfile menv
|
||||||
|
|
||||||
|
|
||||||
makeOut :: (MonadReader env m, HasDirs env, MonadIO m)
|
makeOut :: (MonadReader env m, HasDirs env, MonadIO m)
|
||||||
=> [String]
|
=> [String]
|
||||||
@@ -1034,13 +1053,13 @@ applyAnyPatch :: ( MonadReader env m
|
|||||||
, MonadIO m)
|
, MonadIO m)
|
||||||
=> Maybe (Either FilePath [URI])
|
=> Maybe (Either FilePath [URI])
|
||||||
-> FilePath
|
-> FilePath
|
||||||
-> Excepts '[PatchFailed, DownloadFailed, DigestError, GPGError] m ()
|
-> Excepts '[PatchFailed, DownloadFailed, DigestError, ContentLengthError, GPGError] m ()
|
||||||
applyAnyPatch Nothing _ = pure ()
|
applyAnyPatch Nothing _ = pure ()
|
||||||
applyAnyPatch (Just (Left pdir)) workdir = liftE $ applyPatches pdir workdir
|
applyAnyPatch (Just (Left pdir)) workdir = liftE $ applyPatches pdir workdir
|
||||||
applyAnyPatch (Just (Right uris)) workdir = do
|
applyAnyPatch (Just (Right uris)) workdir = do
|
||||||
tmpUnpack <- fromGHCupPath <$> lift withGHCupTmpDir
|
tmpUnpack <- fromGHCupPath <$> lift withGHCupTmpDir
|
||||||
forM_ uris $ \uri -> do
|
forM_ uris $ \uri -> do
|
||||||
patch <- liftE $ download uri Nothing Nothing tmpUnpack Nothing False
|
patch <- liftE $ download uri Nothing Nothing Nothing tmpUnpack Nothing False
|
||||||
liftE $ applyPatch patch workdir
|
liftE $ applyPatch patch workdir
|
||||||
|
|
||||||
|
|
||||||
@@ -1096,7 +1115,8 @@ runBuildAction bdir action = do
|
|||||||
|
|
||||||
-- | Clean up the given directory if the action fails,
|
-- | Clean up the given directory if the action fails,
|
||||||
-- depending on the Settings.
|
-- depending on the Settings.
|
||||||
cleanUpOnError :: ( MonadReader env m
|
cleanUpOnError :: forall e m a env .
|
||||||
|
( MonadReader env m
|
||||||
, HasDirs env
|
, HasDirs env
|
||||||
, HasSettings env
|
, HasSettings env
|
||||||
, MonadIO m
|
, MonadIO m
|
||||||
@@ -1170,7 +1190,7 @@ ensureGlobalTools :: ( MonadMask m
|
|||||||
, MonadUnliftIO m
|
, MonadUnliftIO m
|
||||||
, MonadFail m
|
, MonadFail m
|
||||||
)
|
)
|
||||||
=> Excepts '[GPGError, DigestError , DownloadFailed, NoDownload] m ()
|
=> Excepts '[GPGError, DigestError, ContentLengthError, DownloadFailed, NoDownload] m ()
|
||||||
ensureGlobalTools
|
ensureGlobalTools
|
||||||
| isWindows = do
|
| isWindows = do
|
||||||
(GHCupInfo _ _ gTools) <- lift getGHCupInfo
|
(GHCupInfo _ _ gTools) <- lift getGHCupInfo
|
||||||
@@ -1182,8 +1202,8 @@ ensureGlobalTools
|
|||||||
lift $ logWarn "Digest doesn't match, redownloading gs.exe..."
|
lift $ logWarn "Digest doesn't match, redownloading gs.exe..."
|
||||||
lift $ logDebug ("rm -f " <> T.pack (fromGHCupPath (cacheDir dirs) </> "gs.exe"))
|
lift $ logDebug ("rm -f " <> T.pack (fromGHCupPath (cacheDir dirs) </> "gs.exe"))
|
||||||
lift $ hideError doesNotExistErrorType $ recycleFile (fromGHCupPath (cacheDir dirs) </> "gs.exe")
|
lift $ hideError doesNotExistErrorType $ recycleFile (fromGHCupPath (cacheDir dirs) </> "gs.exe")
|
||||||
liftE @'[GPGError, DigestError , DownloadFailed] $ dl
|
liftE @'[GPGError, DigestError, ContentLengthError, DownloadFailed] $ dl
|
||||||
) `catchE` liftE @'[GPGError, DigestError , DownloadFailed] dl
|
) `catchE` liftE @'[GPGError, DigestError, ContentLengthError, DownloadFailed] dl
|
||||||
| otherwise = pure ()
|
| otherwise = pure ()
|
||||||
|
|
||||||
|
|
||||||
@@ -1268,10 +1288,60 @@ warnAboutHlsCompatibility = do
|
|||||||
case (currentGHC, currentHLS) of
|
case (currentGHC, currentHLS) of
|
||||||
(Just gv, Just hv) | gv `notElem` supportedGHC -> do
|
(Just gv, Just hv) | gv `notElem` supportedGHC -> do
|
||||||
logWarn $
|
logWarn $
|
||||||
"GHC " <> T.pack (prettyShow gv) <> " is not compatible with " <>
|
"GHC-" <> T.pack (prettyShow gv) <> " appears to have no corresponding HLS-" <> T.pack (prettyShow hv) <> " binary." <> "\n" <>
|
||||||
"Haskell Language Server " <> T.pack (prettyShow hv) <> "." <> "\n" <>
|
"Haskell IDE support may not work." <> "\n" <>
|
||||||
"Haskell IDE support may not work until this is fixed." <> "\n" <>
|
"You can try to either: " <> "\n" <>
|
||||||
"Install a different HLS version, or install and set one of the following GHCs:" <> "\n" <>
|
" 1. Install a different HLS version (e.g. downgrade for older GHCs)" <> "\n" <>
|
||||||
T.pack (prettyShow supportedGHC)
|
" 2. Install and set one of the following GHCs: " <> T.pack (prettyShow supportedGHC) <> "\n" <>
|
||||||
|
" 3. Let GHCup compile HLS for you, e.g. run: ghcup compile hls -g " <> T.pack (prettyShow hv) <> " --ghc " <> T.pack (prettyShow gv) <> " --cabal-update\n" <>
|
||||||
|
" (see https://www.haskell.org/ghcup/guide/#hls for more information)"
|
||||||
|
|
||||||
_ -> return ()
|
_ -> return ()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
addToPath :: FilePath
|
||||||
|
-> Bool -- ^ if False will prepend
|
||||||
|
-> IO [(String, String)]
|
||||||
|
addToPath path append = do
|
||||||
|
cEnv <- Map.fromList <$> getEnvironment
|
||||||
|
let paths = ["PATH", "Path"]
|
||||||
|
curPaths = (\x -> maybe [] splitSearchPath (Map.lookup x cEnv)) =<< paths
|
||||||
|
{- HLINT ignore "Redundant bracket" -}
|
||||||
|
newPath = intercalate [searchPathSeparator] (if append then (curPaths ++ [path]) else (path : curPaths))
|
||||||
|
envWithoutPath = foldr (\x y -> Map.delete x y) cEnv paths
|
||||||
|
pathVar = if isWindows then "Path" else "PATH"
|
||||||
|
envWithNewPath = Map.toList $ Map.insert pathVar newPath envWithoutPath
|
||||||
|
liftIO $ setEnv pathVar newPath
|
||||||
|
return envWithNewPath
|
||||||
|
|
||||||
|
|
||||||
|
-----------
|
||||||
|
--[ Git ]--
|
||||||
|
-----------
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
isCommitHash :: String -> Bool
|
||||||
|
isCommitHash str' = let hex = all isHexDigit str'
|
||||||
|
len = length str'
|
||||||
|
in hex && len == 40
|
||||||
|
|
||||||
|
|
||||||
|
gitOut :: (MonadReader env m, HasLog env, MonadIO m) => [String] -> FilePath -> Excepts '[ProcessError] m T.Text
|
||||||
|
gitOut args dir = do
|
||||||
|
CapturedProcess {..} <- lift $ executeOut "git" args (Just dir)
|
||||||
|
case _exitCode of
|
||||||
|
ExitSuccess -> pure $ T.pack $ stripNewlineEnd $ T.unpack $ decUTF8Safe' _stdOut
|
||||||
|
ExitFailure c -> do
|
||||||
|
let pe = NonZeroExit c "git" args
|
||||||
|
lift $ logDebug $ T.pack (prettyHFError pe)
|
||||||
|
throwE pe
|
||||||
|
|
||||||
|
processBranches :: T.Text -> [String]
|
||||||
|
processBranches str' = let lines' = lines (T.unpack str')
|
||||||
|
words' = fmap words lines'
|
||||||
|
refs = catMaybes $ fmap (`atMay` 1) words'
|
||||||
|
branches = catMaybes $ fmap (stripPrefix "refs/heads/") $ filter (isPrefixOf "refs/heads/") refs
|
||||||
|
in branches
|
||||||
|
|
||||||
|
|||||||
@@ -465,15 +465,22 @@ withGHCupTmpDir :: ( MonadReader env m
|
|||||||
, MonadMask m
|
, MonadMask m
|
||||||
, MonadIO m)
|
, MonadIO m)
|
||||||
=> m GHCupPath
|
=> m GHCupPath
|
||||||
withGHCupTmpDir = snd <$> withRunInIO (\run ->
|
withGHCupTmpDir = do
|
||||||
run
|
Settings{keepDirs} <- getSettings
|
||||||
$ allocate
|
snd <$> withRunInIO (\run ->
|
||||||
(run mkGhcupTmpDir)
|
run
|
||||||
(\fp ->
|
$ allocate
|
||||||
handleIO (\e -> run
|
(run mkGhcupTmpDir)
|
||||||
$ logDebug ("Resource cleanup failed for " <> T.pack (fromGHCupPath fp) <> ", error was: " <> T.pack (displayException e)))
|
(\fp -> if -- we don't know whether there was a failure, so can only
|
||||||
. removePathForcibly
|
-- decide for 'Always'
|
||||||
$ fp))
|
| keepDirs == Always -> pure ()
|
||||||
|
| otherwise -> handleIO (\e -> run
|
||||||
|
$ logDebug ("Resource cleanup failed for "
|
||||||
|
<> T.pack (fromGHCupPath fp)
|
||||||
|
<> ", error was: "
|
||||||
|
<> T.pack (displayException e)))
|
||||||
|
. removePathForcibly
|
||||||
|
$ fp))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
site_name: GHCup
|
site_name: GHCup
|
||||||
site_url: https://www.haskell.org/ghcup
|
site_url: https://www.haskell.org/ghcup
|
||||||
site_description: GHCup is an installer for the general purpose language Haskell.
|
site_description: GHCup is the main installer for the general purpose language Haskell.
|
||||||
site_author: GHCup Team
|
site_author: GHCup Team
|
||||||
site_favicon: haskell_logo.png
|
site_favicon: haskell_logo.png
|
||||||
|
|
||||||
repo_url: https://gitlab.haskell.org/haskell/ghcup-hs
|
repo_url: https://github.com/haskell/ghcup-hs
|
||||||
|
|
||||||
theme:
|
theme:
|
||||||
name: mkdocs
|
name: mkdocs
|
||||||
@@ -13,7 +13,7 @@ theme:
|
|||||||
|
|
||||||
nav:
|
nav:
|
||||||
- Home: index.md
|
- Home: index.md
|
||||||
- "Getting started": install.md
|
- "Installation": install.md
|
||||||
- "First steps": steps.md
|
- "First steps": steps.md
|
||||||
- "User Guide": guide.md
|
- "User Guide": guide.md
|
||||||
- "Developer Guide": dev.md
|
- "Developer Guide": dev.md
|
||||||
|
|||||||
@@ -12,10 +12,12 @@
|
|||||||
# * BOOTSTRAP_HASKELL_VERBOSE - any nonzero value for more verbose installation
|
# * BOOTSTRAP_HASKELL_VERBOSE - any nonzero value for more verbose installation
|
||||||
# * BOOTSTRAP_HASKELL_GHC_VERSION - the ghc version to install
|
# * BOOTSTRAP_HASKELL_GHC_VERSION - the ghc version to install
|
||||||
# * BOOTSTRAP_HASKELL_CABAL_VERSION - the cabal version to install
|
# * BOOTSTRAP_HASKELL_CABAL_VERSION - the cabal version to install
|
||||||
# * BOOTSTRAP_HASKELL_INSTALL_STACK - whether to install latest stack
|
# * BOOTSTRAP_HASKELL_INSTALL_NO_STACK - disable installation of stack
|
||||||
|
# * BOOTSTRAP_HASKELL_INSTALL_NO_STACK_HOOK - disable installation stack ghcup hook
|
||||||
# * BOOTSTRAP_HASKELL_INSTALL_HLS - whether to install latest hls
|
# * BOOTSTRAP_HASKELL_INSTALL_HLS - whether to install latest hls
|
||||||
# * BOOTSTRAP_HASKELL_ADJUST_BASHRC - whether to adjust PATH in bashrc (prepend)
|
# * BOOTSTRAP_HASKELL_ADJUST_BASHRC - whether to adjust PATH in bashrc (prepend)
|
||||||
# * BOOTSTRAP_HASKELL_ADJUST_CABAL_CONFIG - whether to adjust mingw paths in cabal.config on windows
|
# * BOOTSTRAP_HASKELL_ADJUST_CABAL_CONFIG - whether to adjust mingw paths in cabal.config on windows
|
||||||
|
# * BOOTSTRAP_HASKELL_DOWNLOADER - which downloader to use (default: curl)
|
||||||
# * GHCUP_BASE_URL - the base url for ghcup binary download (use this to overwrite https://downloads.haskell.org/~ghcup with a mirror)
|
# * GHCUP_BASE_URL - the base url for ghcup binary download (use this to overwrite https://downloads.haskell.org/~ghcup with a mirror)
|
||||||
|
|
||||||
# License: LGPL-3.0
|
# License: LGPL-3.0
|
||||||
@@ -26,10 +28,11 @@
|
|||||||
|
|
||||||
plat="$(uname -s)"
|
plat="$(uname -s)"
|
||||||
arch=$(uname -m)
|
arch=$(uname -m)
|
||||||
ghver="0.1.17.8"
|
ghver="0.1.19.0"
|
||||||
: "${GHCUP_BASE_URL:=https://downloads.haskell.org/~ghcup}"
|
: "${GHCUP_BASE_URL:=https://downloads.haskell.org/~ghcup}"
|
||||||
|
|
||||||
export GHCUP_SKIP_UPDATE_CHECK=yes
|
export GHCUP_SKIP_UPDATE_CHECK=yes
|
||||||
|
: "${BOOTSTRAP_HASKELL_DOWNLOADER:=curl}"
|
||||||
|
|
||||||
case "${plat}" in
|
case "${plat}" in
|
||||||
MSYS*|MINGW*)
|
MSYS*|MINGW*)
|
||||||
@@ -116,23 +119,43 @@ edo() {
|
|||||||
"$@" || die "\"$*\" failed!"
|
"$@" || die "\"$*\" failed!"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
eghcup_raw() {
|
||||||
|
"${GHCUP_BIN}/ghcup" "$@" || die "\"ghcup $*\" failed!"
|
||||||
|
}
|
||||||
|
|
||||||
eghcup() {
|
eghcup() {
|
||||||
edo _eghcup "$@"
|
_eghcup "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
_eghcup() {
|
_eghcup() {
|
||||||
if [ -n "${BOOTSTRAP_HASKELL_YAML}" ] ; then
|
if [ -n "${BOOTSTRAP_HASKELL_YAML}" ] ; then
|
||||||
args="-s ${BOOTSTRAP_HASKELL_YAML}"
|
args="-s ${BOOTSTRAP_HASKELL_YAML} --metadata-fetching-mode=Strict"
|
||||||
|
else
|
||||||
|
args="--metadata-fetching-mode=Strict"
|
||||||
fi
|
fi
|
||||||
if [ -z "${BOOTSTRAP_HASKELL_VERBOSE}" ] ; then
|
if [ -z "${BOOTSTRAP_HASKELL_VERBOSE}" ] ; then
|
||||||
# shellcheck disable=SC2086
|
# shellcheck disable=SC2086
|
||||||
"${GHCUP_BIN}/ghcup" ${args} "$@"
|
"${GHCUP_BIN}/ghcup" ${args} "$@" || die "\"ghcup ${args} $*\" failed!"
|
||||||
else
|
else
|
||||||
# shellcheck disable=SC2086
|
# shellcheck disable=SC2086
|
||||||
"${GHCUP_BIN}/ghcup" ${args} --verbose "$@"
|
"${GHCUP_BIN}/ghcup" ${args} --verbose "$@" || die "\"ghcup ${args} --verbose $*\" failed!"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_ecabal() {
|
||||||
|
# shellcheck disable=SC2317
|
||||||
|
if [ -n "${CABAL_BIN}" ] ; then
|
||||||
|
"${CABAL_BIN}" "$@"
|
||||||
|
else
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
"${GHCUP_BIN}/cabal" "$@"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
ecabal() {
|
||||||
|
_ecabal "$@" || die "\"cabal $*\" failed!"
|
||||||
|
}
|
||||||
|
|
||||||
_done() {
|
_done() {
|
||||||
echo
|
echo
|
||||||
echo "==============================================================================="
|
echo "==============================================================================="
|
||||||
@@ -265,14 +288,6 @@ download_ghcup() {
|
|||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
"FreeBSD"|"freebsd")
|
"FreeBSD"|"freebsd")
|
||||||
if freebsd-version | grep -E '^12.*' ; then
|
|
||||||
freebsd_ver=12
|
|
||||||
elif freebsd-version | grep -E '^13.*' ; then
|
|
||||||
freebsd_ver=13
|
|
||||||
else
|
|
||||||
die "Unsupported FreeBSD version! Please report a bug at https://gitlab.haskell.org/haskell/ghcup-hs/-/issues"
|
|
||||||
fi
|
|
||||||
|
|
||||||
case "${arch}" in
|
case "${arch}" in
|
||||||
x86_64|amd64)
|
x86_64|amd64)
|
||||||
;;
|
;;
|
||||||
@@ -282,7 +297,7 @@ download_ghcup() {
|
|||||||
*) die "Unknown architecture: ${arch}"
|
*) die "Unknown architecture: ${arch}"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
_url=${GHCUP_BASE_URL}/${ghver}/x86_64-freebsd${freebsd_ver}-ghcup-${ghver}
|
_url=${GHCUP_BASE_URL}/${ghver}/x86_64-portbld-freebsd-ghcup-${ghver}
|
||||||
;;
|
;;
|
||||||
"Darwin"|"darwin")
|
"Darwin"|"darwin")
|
||||||
case "${arch}" in
|
case "${arch}" in
|
||||||
@@ -313,11 +328,35 @@ download_ghcup() {
|
|||||||
esac
|
esac
|
||||||
case "${plat}" in
|
case "${plat}" in
|
||||||
MSYS*|MINGW*)
|
MSYS*|MINGW*)
|
||||||
edo curl -Lf "${_url}" > "${GHCUP_BIN}"/ghcup.exe
|
case "${BOOTSTRAP_HASKELL_DOWNLOADER}" in
|
||||||
|
"curl")
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
edo curl -Lf ${GHCUP_CURL_OPTS} "${_url}" > "${GHCUP_BIN}"/ghcup.exe
|
||||||
|
;;
|
||||||
|
"wget")
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
edo wget -O /dev/stdout ${GHCUP_WGET_OPTS} "${_url}" > "${GHCUP_BIN}"/ghcup.exe
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
die "Unknown downloader: ${BOOTSTRAP_HASKELL_DOWNLOADER}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
edo chmod +x "${GHCUP_BIN}"/ghcup.exe
|
edo chmod +x "${GHCUP_BIN}"/ghcup.exe
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
edo curl -Lf "${_url}" > "${GHCUP_BIN}"/ghcup
|
case "${BOOTSTRAP_HASKELL_DOWNLOADER}" in
|
||||||
|
"curl")
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
edo curl -Lf ${GHCUP_CURL_OPTS} "${_url}" > "${GHCUP_BIN}"/ghcup
|
||||||
|
;;
|
||||||
|
"wget")
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
edo wget -O /dev/stdout ${GHCUP_WGET_OPTS} "${_url}" > "${GHCUP_BIN}"/ghcup
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
die "Unknown downloader: ${BOOTSTRAP_HASKELL_DOWNLOADER}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
edo chmod +x "${GHCUP_BIN}"/ghcup
|
edo chmod +x "${GHCUP_BIN}"/ghcup
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
@@ -344,6 +383,17 @@ download_ghcup() {
|
|||||||
|
|
||||||
# shellcheck disable=SC1090
|
# shellcheck disable=SC1090
|
||||||
edo . "${GHCUP_DIR}"/env
|
edo . "${GHCUP_DIR}"/env
|
||||||
|
case "${BOOTSTRAP_HASKELL_DOWNLOADER}" in
|
||||||
|
"curl")
|
||||||
|
eghcup_raw config set downloader Curl
|
||||||
|
;;
|
||||||
|
"wget")
|
||||||
|
eghcup_raw config set downloader Wget
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
die "Unknown downloader: ${BOOTSTRAP_HASKELL_DOWNLOADER}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
eghcup upgrade
|
eghcup upgrade
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -352,7 +402,11 @@ download_ghcup() {
|
|||||||
find_shell() {
|
find_shell() {
|
||||||
case $SHELL in
|
case $SHELL in
|
||||||
*/zsh) # login shell is zsh
|
*/zsh) # login shell is zsh
|
||||||
GHCUP_PROFILE_FILE="$HOME/.zshrc"
|
if [ -n "$ZDOTDIR" ]; then
|
||||||
|
GHCUP_PROFILE_FILE="$ZDOTDIR/.zshrc"
|
||||||
|
else
|
||||||
|
GHCUP_PROFILE_FILE="$HOME/.zshrc"
|
||||||
|
fi
|
||||||
MY_SHELL="zsh" ;;
|
MY_SHELL="zsh" ;;
|
||||||
*/bash) # login shell is bash
|
*/bash) # login shell is bash
|
||||||
GHCUP_PROFILE_FILE="$HOME/.bashrc"
|
GHCUP_PROFILE_FILE="$HOME/.bashrc"
|
||||||
@@ -537,7 +591,7 @@ adjust_cabal_config() {
|
|||||||
else
|
else
|
||||||
cabal_bin="$HOME/AppData/Roaming/cabal/bin"
|
cabal_bin="$HOME/AppData/Roaming/cabal/bin"
|
||||||
fi
|
fi
|
||||||
edo cabal user-config -a "extra-prog-path: $(cygpath -w "$GHCUP_BIN"), $(cygpath -w "$cabal_bin"), $(cygpath -w "$GHCUP_MSYS2"/usr/bin), $(cygpath -w "$GHCUP_MSYS2"/mingw64/bin)" -a "extra-include-dirs: $(cygpath -w "$GHCUP_MSYS2"/mingw64/include)" -a "extra-lib-dirs: $(cygpath -w "$GHCUP_MSYS2"/mingw64/lib)" -f init
|
ecabal user-config -a "extra-prog-path: $(cygpath -w "$GHCUP_BIN"), $(cygpath -w "$cabal_bin"), $(cygpath -w "$GHCUP_MSYS2"/mingw64/bin), $(cygpath -w "$GHCUP_MSYS2"/usr/bin)" -a "extra-include-dirs: $(cygpath -w "$GHCUP_MSYS2"/mingw64/include)" -a "extra-lib-dirs: $(cygpath -w "$GHCUP_MSYS2"/mingw64/lib)" -f init
|
||||||
}
|
}
|
||||||
|
|
||||||
ask_cabal_config_init() {
|
ask_cabal_config_init() {
|
||||||
@@ -609,7 +663,7 @@ ask_hls() {
|
|||||||
warn "Do you want to install haskell-language-server (HLS)?"
|
warn "Do you want to install haskell-language-server (HLS)?"
|
||||||
warn "HLS is a language-server that provides IDE-like functionality"
|
warn "HLS is a language-server that provides IDE-like functionality"
|
||||||
warn "and can integrate with different editors, such as Vim, Emacs, VS Code, Atom, ..."
|
warn "and can integrate with different editors, such as Vim, Emacs, VS Code, Atom, ..."
|
||||||
warn "Also see https://github.com/haskell/haskell-language-server/blob/master/README.md"
|
warn "Also see https://haskell-language-server.readthedocs.io/en/stable/"
|
||||||
warn ""
|
warn ""
|
||||||
warn "[Y] Yes [N] No [?] Help (default is \"N\")."
|
warn "[Y] Yes [N] No [?] Help (default is \"N\")."
|
||||||
warn ""
|
warn ""
|
||||||
@@ -642,40 +696,44 @@ ask_hls() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ask_stack() {
|
ask_stack() {
|
||||||
if [ -n "${BOOTSTRAP_HASKELL_INSTALL_STACK}" ] ; then
|
if [ -n "${BOOTSTRAP_HASKELL_INSTALL_NO_STACK}" ] ; then
|
||||||
|
return 0
|
||||||
|
elif [ -n "${BOOTSTRAP_HASKELL_INSTALL_NO_STACK_HOOK}" ] ; then
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "${BOOTSTRAP_HASKELL_NONINTERACTIVE}" ] ; then
|
if [ -z "${BOOTSTRAP_HASKELL_NONINTERACTIVE}" ] ; then
|
||||||
echo "-------------------------------------------------------------------------------"
|
echo "-------------------------------------------------------------------------------"
|
||||||
|
|
||||||
warn "Do you want to install stack?"
|
warn "Do you want to enable better integration of stack with GHCup?"
|
||||||
warn "Stack is a haskell build tool similar to cabal that is used by some projects."
|
warn "This means that stack won't install its own GHC versions, but uses GHCup's."
|
||||||
warn "Also see https://docs.haskellstack.org/"
|
warn "For more information see:"
|
||||||
|
warn " https://docs.haskellstack.org/en/stable/yaml_configuration/#ghc-installation-customisation-experimental"
|
||||||
|
warn "If you want to keep stacks vanilla behavior, answer 'No'."
|
||||||
warn ""
|
warn ""
|
||||||
warn "[Y] Yes [N] No [?] Help (default is \"N\")."
|
warn "[Y] Yes [N] No [?] Help (default is \"Y\")."
|
||||||
warn ""
|
warn ""
|
||||||
|
|
||||||
while true; do
|
while true; do
|
||||||
read -r stack_answer </dev/tty
|
read -r stack_answer </dev/tty
|
||||||
|
|
||||||
case $stack_answer in
|
case $stack_answer in
|
||||||
[Yy]*)
|
[Yy]* | "")
|
||||||
|
return 2 ;;
|
||||||
|
[Nn]*)
|
||||||
return 1 ;;
|
return 1 ;;
|
||||||
[Nn]* | "")
|
|
||||||
return 0 ;;
|
|
||||||
*)
|
*)
|
||||||
echo "Possible choices are:"
|
echo "Possible choices are:"
|
||||||
echo
|
echo
|
||||||
echo "Y - Yes, install stack"
|
echo "Y - Yes, enable better integration (default)"
|
||||||
echo "N - No, don't install anything more (default)"
|
echo "N - No, keep stacks vanilla behavior"
|
||||||
echo
|
echo
|
||||||
echo "Please make your choice and press ENTER."
|
echo "Please make your choice and press ENTER."
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
else
|
else
|
||||||
return 0
|
return 2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
unset stack_answer
|
unset stack_answer
|
||||||
@@ -688,11 +746,11 @@ find_shell
|
|||||||
echo
|
echo
|
||||||
echo "Welcome to Haskell!"
|
echo "Welcome to Haskell!"
|
||||||
echo
|
echo
|
||||||
echo "This script will download and install the following binaries:"
|
echo "This script can download and install the following binaries:"
|
||||||
echo " * ghcup - The Haskell toolchain installer"
|
echo " * ghcup - The Haskell toolchain installer"
|
||||||
echo " * ghc - The Glasgow Haskell Compiler"
|
echo " * ghc - The Glasgow Haskell Compiler"
|
||||||
echo " * cabal - The Cabal build tool for managing Haskell software"
|
echo " * cabal - The Cabal build tool for managing Haskell software"
|
||||||
echo " * stack - (optional) A cross-platform program for developing Haskell projects"
|
echo " * stack - A cross-platform program for developing Haskell projects (similar to cabal)"
|
||||||
echo " * hls - (optional) A language server for developers to integrate with their editor/IDE"
|
echo " * hls - (optional) A language server for developers to integrate with their editor/IDE"
|
||||||
echo
|
echo
|
||||||
if [ -z "${GHCUP_USE_XDG_DIRS}" ] ; then
|
if [ -z "${GHCUP_USE_XDG_DIRS}" ] ; then
|
||||||
@@ -735,7 +793,7 @@ edo mkdir -p "${GHCUP_BIN}"
|
|||||||
|
|
||||||
if command -V "ghcup" >/dev/null 2>&1 ; then
|
if command -V "ghcup" >/dev/null 2>&1 ; then
|
||||||
if [ -z "${BOOTSTRAP_HASKELL_NO_UPGRADE}" ] ; then
|
if [ -z "${BOOTSTRAP_HASKELL_NO_UPGRADE}" ] ; then
|
||||||
_eghcup upgrade || download_ghcup
|
( _eghcup upgrade ) || download_ghcup
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
download_ghcup
|
download_ghcup
|
||||||
@@ -763,7 +821,7 @@ if [ -z "${BOOTSTRAP_HASKELL_MINIMAL}" ] ; then
|
|||||||
|
|
||||||
do_cabal_config_init $ask_cabal_config_init_answer
|
do_cabal_config_init $ask_cabal_config_init_answer
|
||||||
|
|
||||||
edo cabal new-update --ignore-project
|
edo cabal update --ignore-project
|
||||||
else # don't install ghc and cabal
|
else # don't install ghc and cabal
|
||||||
case "${plat}" in
|
case "${plat}" in
|
||||||
MSYS*|MINGW*)
|
MSYS*|MINGW*)
|
||||||
@@ -771,7 +829,7 @@ else # don't install ghc and cabal
|
|||||||
# we'll remove it afterwards
|
# we'll remove it afterwards
|
||||||
tmp_dir="$(mktemp -d)"
|
tmp_dir="$(mktemp -d)"
|
||||||
eghcup --cache install cabal -i "${tmp_dir}" "${BOOTSTRAP_HASKELL_CABAL_VERSION}"
|
eghcup --cache install cabal -i "${tmp_dir}" "${BOOTSTRAP_HASKELL_CABAL_VERSION}"
|
||||||
PATH="${tmp_dir}:$PATH" do_cabal_config_init $ask_cabal_config_init_answer
|
CABAL_BIN="${tmp_dir}/cabal" do_cabal_config_init $ask_cabal_config_init_answer
|
||||||
rm "${tmp_dir}/cabal"
|
rm "${tmp_dir}/cabal"
|
||||||
unset tmp_dir
|
unset tmp_dir
|
||||||
;;
|
;;
|
||||||
@@ -782,14 +840,42 @@ fi
|
|||||||
|
|
||||||
case $ask_hls_answer in
|
case $ask_hls_answer in
|
||||||
1)
|
1)
|
||||||
_eghcup --cache install hls || warn "HLS installation failed, continuing anyway"
|
(_eghcup --cache install hls) || warn "HLS installation failed, continuing anyway"
|
||||||
;;
|
;;
|
||||||
*) ;;
|
*) ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
case $ask_stack_answer in
|
case $ask_stack_answer in
|
||||||
1)
|
1)
|
||||||
_eghcup --cache install stack || warn "Stack installation failed, continuing anyway"
|
(_eghcup --cache install stack) || die "Stack installation failed"
|
||||||
|
;;
|
||||||
|
2)
|
||||||
|
(_eghcup --cache install stack) || die "Stack installation failed"
|
||||||
|
edo mkdir -p "${STACK_ROOOT:-$HOME/.stack}"/hooks
|
||||||
|
hook_exe="${STACK_ROOOT:-$HOME/.stack}"/hooks/ghc-install.sh
|
||||||
|
hook_url="https://www.haskell.org/ghcup/sh/hooks/stack/ghc-install.sh"
|
||||||
|
|
||||||
|
if [ -e "${hook_exe}" ] ; then
|
||||||
|
warn "$hook_exe already exists, skipping hook installation."
|
||||||
|
warn "If you want to reinstall the hook, delete it manually and re-run"
|
||||||
|
warn "this script!"
|
||||||
|
else
|
||||||
|
case "${BOOTSTRAP_HASKELL_DOWNLOADER}" in
|
||||||
|
"curl")
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
edo curl -Lf ${GHCUP_CURL_OPTS} "${hook_url}" > "${hook_exe}"
|
||||||
|
;;
|
||||||
|
"wget")
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
edo wget -O /dev/stdout ${GHCUP_WGET_OPTS} "${hook_url}" > "${hook_exe}"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
die "Unknown downloader: ${BOOTSTRAP_HASKELL_DOWNLOADER}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
edo chmod +x "${hook_exe}"
|
||||||
|
fi
|
||||||
|
|
||||||
;;
|
;;
|
||||||
*) ;;
|
*) ;;
|
||||||
esac
|
esac
|
||||||
|
|||||||
@@ -36,9 +36,15 @@ param (
|
|||||||
# Instead of installing a new MSys2, use an existing installation
|
# Instead of installing a new MSys2, use an existing installation
|
||||||
[string]$ExistingMsys2Dir,
|
[string]$ExistingMsys2Dir,
|
||||||
# Specify the cabal root directory (default: '$InstallDir\cabal')
|
# Specify the cabal root directory (default: '$InstallDir\cabal')
|
||||||
[string]$CabalDir
|
[string]$CabalDir,
|
||||||
|
# Whether to disable use of curl.exe
|
||||||
|
[switch]$DisableCurl,
|
||||||
|
# The Msys2 version to download (e.g. 20221216)
|
||||||
|
[string]$Msys2Version
|
||||||
)
|
)
|
||||||
|
|
||||||
|
$DefaultMsys2Version = "20221216"
|
||||||
|
|
||||||
$Silent = !$Interactive
|
$Silent = !$Interactive
|
||||||
|
|
||||||
function Print-Msg {
|
function Print-Msg {
|
||||||
@@ -242,7 +248,7 @@ if ($Silent -and !($InstallDir)) {
|
|||||||
Print-Msg -color Magenta -msg (@'
|
Print-Msg -color Magenta -msg (@'
|
||||||
Welcome to Haskell!
|
Welcome to Haskell!
|
||||||
|
|
||||||
This script will download and install the following programs:
|
This script can download and install the following programs:
|
||||||
* ghcup - The Haskell toolchain installer
|
* ghcup - The Haskell toolchain installer
|
||||||
* ghc - The Glasgow Haskell Compiler
|
* ghc - The Glasgow Haskell Compiler
|
||||||
* msys2 - A linux-style toolchain environment required for many operations
|
* msys2 - A linux-style toolchain environment required for many operations
|
||||||
@@ -421,14 +427,18 @@ if (!(Test-Path -Path ('{0}' -f $MsysDir))) {
|
|||||||
Start-Sleep -s 5
|
Start-Sleep -s 5
|
||||||
|
|
||||||
# Download the archive
|
# Download the archive
|
||||||
Print-Msg -msg 'Downloading Msys2 archive...'
|
if (!($Msys2Version)) {
|
||||||
$archive = 'msys2-x86_64-latest.sfx.exe'
|
$Msys2Version = $DefaultMsys2Version
|
||||||
|
}
|
||||||
|
Print-Msg -msg ('Downloading Msys2 archive {0}...' -f $Msys2Version)
|
||||||
|
$archive = ('msys2-base-x86_64-{0}.sfx.exe' -f $Msys2Version)
|
||||||
|
$msysUrl = ('https://repo.msys2.org/distrib/x86_64/{0}' -f "$archive")
|
||||||
$archivePath = ('{0}\{1}' -f ([IO.Path]::GetTempPath()), "$archive")
|
$archivePath = ('{0}\{1}' -f ([IO.Path]::GetTempPath()), "$archive")
|
||||||
|
|
||||||
if (Get-Command -Name 'curl.exe' -ErrorAction SilentlyContinue) {
|
if ((Get-Command -Name 'curl.exe' -ErrorAction SilentlyContinue) -and !($DisableCurl)) {
|
||||||
Exec "curl.exe" '-o' "$archivePath" ('https://repo.msys2.org/distrib/{0}' -f "$archive")
|
Exec "curl.exe" '-o' "$archivePath" "$msysUrl"
|
||||||
} else {
|
} else {
|
||||||
Get-FileWCSynchronous -url ('https://repo.msys2.org/distrib/{0}' -f $archive) -destinationFolder ([IO.Path]::GetTempPath()) -includeStats
|
Get-FileWCSynchronous -url "$msysUrl" -destinationFolder ([IO.Path]::GetTempPath()) -includeStats
|
||||||
}
|
}
|
||||||
|
|
||||||
Print-Msg -msg 'Extracting Msys2 archive...'
|
Print-Msg -msg 'Extracting Msys2 archive...'
|
||||||
@@ -575,8 +585,8 @@ $Msys2Shell = ('{0}\msys2_shell.cmd' -f $MsysDir)
|
|||||||
# The bootstrap script is always silent, since we ask relevant questions here
|
# The bootstrap script is always silent, since we ask relevant questions here
|
||||||
$SilentExport = 'export BOOTSTRAP_HASKELL_NONINTERACTIVE=1 ;'
|
$SilentExport = 'export BOOTSTRAP_HASKELL_NONINTERACTIVE=1 ;'
|
||||||
|
|
||||||
if ($InstallStack) {
|
if (!($InstallStack)) {
|
||||||
$StackInstallExport = 'export BOOTSTRAP_HASKELL_INSTALL_STACK=1 ;'
|
$StackInstallExport = 'export BOOTSTRAP_HASKELL_INSTALL_NO_STACK=1 ;'
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($InstallHLS) {
|
if ($InstallHLS) {
|
||||||
@@ -591,10 +601,17 @@ if ($Minimal) {
|
|||||||
$MinimalExport = 'export BOOTSTRAP_HASKELL_MINIMAL=1 ;'
|
$MinimalExport = 'export BOOTSTRAP_HASKELL_MINIMAL=1 ;'
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((Get-Process -ID $PID).ProcessName.StartsWith("bootstrap-haskell") -Or $InBash) {
|
if ($DisableCurl) {
|
||||||
Exec "$Bash" '-lc' ('{4} {6} {7} {8} {9} [ -n ''{1}'' ] && export GHCUP_MSYS2=$(cygpath -m ''{1}'') ; [ -n ''{2}'' ] && export GHCUP_INSTALL_BASE_PREFIX=$(cygpath -m ''{2}/'') ; export PATH=$(cygpath -u ''{3}/bin''):$PATH ; export CABAL_DIR=''{5}'' ; [[ ''{0}'' = https* ]] && curl --proto ''=https'' --tlsv1.2 -sSf {0} | bash || cat $(cygpath -m ''{0}'') | bash' -f $BootstrapUrl, $MsysDir, $GhcupBasePrefix, $GhcupDir, $SilentExport, $CabalDirFull, $StackInstallExport, $HLSInstallExport, $AdjustCabalConfigExport, $MinimalExport)
|
$BootstrapDownloader = 'export BOOTSTRAP_HASKELL_DOWNLOADER=wget ;'
|
||||||
|
$DownloadScript = 'wget -O /dev/stdout'
|
||||||
} else {
|
} else {
|
||||||
Exec "$Msys2Shell" '-mingw64' '-mintty' '-c' ('{4} {6} {7} {8} {9} [ -n ''{1}'' ] && export GHCUP_MSYS2=$(cygpath -m ''{1}'') ; [ -n ''{2}'' ] && export GHCUP_INSTALL_BASE_PREFIX=$(cygpath -m ''{2}/'') ; export PATH=$(cygpath -u ''{3}/bin''):$PATH ; export CABAL_DIR=''{5}'' ; trap ''echo Press any key to exit && read -n 1 && exit'' 2 ; [[ ''{0}'' = https* ]] && curl --proto ''=https'' --tlsv1.2 -sSf {0} | bash || cat $(cygpath -m ''{0}'') | bash ; echo ''Press any key to exit'' && read -n 1' -f $BootstrapUrl, $MsysDir, $GhcupBasePrefix, $GhcupDir, $SilentExport, $CabalDirFull, $StackInstallExport, $HLSInstallExport, $AdjustCabalConfigExport, $MinimalExport)
|
$DownloadScript = 'curl --proto ''=https'' --tlsv1.2 -sSf'
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((Get-Process -ID $PID).ProcessName.StartsWith("bootstrap-haskell") -Or $InBash) {
|
||||||
|
Exec "$Bash" '-lc' ('{4} {6} {7} {8} {9} {10} [ -n ''{1}'' ] && export GHCUP_MSYS2=$(cygpath -m ''{1}'') ; [ -n ''{2}'' ] && export GHCUP_INSTALL_BASE_PREFIX=$(cygpath -m ''{2}/'') ; export PATH=$(cygpath -u ''{3}/bin''):$PATH ; export CABAL_DIR=''{5}'' ; [[ ''{0}'' = https* ]] && {11} {0} | bash || cat $(cygpath -m ''{0}'') | bash' -f $BootstrapUrl, $MsysDir, $GhcupBasePrefix, $GhcupDir, $SilentExport, $CabalDirFull, $StackInstallExport, $HLSInstallExport, $AdjustCabalConfigExport, $MinimalExport, $BootstrapDownloader, $DownloadScript)
|
||||||
|
} else {
|
||||||
|
Exec "$Msys2Shell" '-mingw64' '-mintty' '-shell' 'bash' '-c' ('{4} {6} {7} {8} {9} {10} [ -n ''{1}'' ] && export GHCUP_MSYS2=$(cygpath -m ''{1}'') ; [ -n ''{2}'' ] && export GHCUP_INSTALL_BASE_PREFIX=$(cygpath -m ''{2}/'') ; export PATH=$(cygpath -u ''{3}/bin''):$PATH ; export CABAL_DIR=''{5}'' ; trap ''echo Press any key to exit && read -n 1 && exit'' 2 ; [[ ''{0}'' = https* ]] && {11} {0} | bash || cat $(cygpath -m ''{0}'') | bash ; echo ''Press any key to exit'' && read -n 1' -f $BootstrapUrl, $MsysDir, $GhcupBasePrefix, $GhcupDir, $SilentExport, $CabalDirFull, $StackInstallExport, $HLSInstallExport, $AdjustCabalConfigExport, $MinimalExport, $BootstrapDownloader, $DownloadScript)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
24
scripts/hooks/stack/ghc-install.sh
Normal file
24
scripts/hooks/stack/ghc-install.sh
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# !! KEEP THIS SCRIPT POSIX COMPLIANT !!
|
||||||
|
|
||||||
|
# see https://docs.haskellstack.org/en/stable/yaml_configuration/#ghc-installation-customisation-experimental
|
||||||
|
# for documentation about hooks
|
||||||
|
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
case $HOOK_GHC_TYPE in
|
||||||
|
bindist)
|
||||||
|
ghcdir=$(ghcup whereis --directory ghc "$HOOK_GHC_VERSION" || ghcup run --ghc "$HOOK_GHC_VERSION" --install) || exit 3
|
||||||
|
printf "%s/ghc" "${ghcdir}"
|
||||||
|
;;
|
||||||
|
git)
|
||||||
|
# TODO: should be somewhat possible
|
||||||
|
>&2 echo "Hook doesn't support installing from source"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
>&2 echo "Unsupported GHC installation type: $HOOK_GHC_TYPE"
|
||||||
|
exit 2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
@@ -1,49 +1,34 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
set -eu
|
set -eu
|
||||||
|
set -o pipefail
|
||||||
|
|
||||||
tag=v$1
|
shopt -s extglob
|
||||||
ver=$1
|
|
||||||
|
|
||||||
dest=$2
|
RELEASE=$1
|
||||||
gpg_user=$3
|
SIGNER=$2
|
||||||
|
|
||||||
mkdir -p "${dest}"
|
echo "RELEASE: $RELEASE"
|
||||||
|
echo "SIGNER: $SIGNER"
|
||||||
|
|
||||||
cd "${dest}"
|
for com in gh gpg curl sha256sum ; do
|
||||||
|
command -V ${com} >/dev/null 2>&1
|
||||||
|
done
|
||||||
|
|
||||||
base_url="https://gitlab.haskell.org/api/v4/projects/618/jobs/artifacts/${tag}/raw"
|
[ ! -e "gh-release-artifacts/${RELEASE}" ]
|
||||||
|
|
||||||
curl -f -o "x86_64-apple-darwin-ghcup-${ver}" \
|
mkdir -p "gh-release-artifacts/${RELEASE}"
|
||||||
"${base_url}/out/x86_64-apple-darwin-ghcup-${ver}?job=release:darwin"
|
cd "gh-release-artifacts/${RELEASE}"
|
||||||
|
|
||||||
curl -f -o "aarch64-apple-darwin-ghcup-${ver}" \
|
# github
|
||||||
"${base_url}/out/aarch64-apple-darwin-ghcup-${ver}?job=release:darwin:aarch64"
|
gh release download $RELEASE
|
||||||
|
|
||||||
curl -f -o "x86_64-freebsd12-ghcup-${ver}" \
|
rm test-*
|
||||||
"${base_url}/out/x86_64-portbld-freebsd-ghcup-${ver}?job=release:freebsd12"
|
|
||||||
|
|
||||||
curl -f -o "x86_64-freebsd13-ghcup-${ver}" \
|
|
||||||
"${base_url}/out/x86_64-portbld-freebsd-ghcup-${ver}?job=release:freebsd13"
|
|
||||||
|
|
||||||
curl -f -o "i386-linux-ghcup-${ver}" \
|
|
||||||
"${base_url}/out/i386-linux-ghcup-${ver}?job=release:linux:32bit"
|
|
||||||
|
|
||||||
curl -f -o "x86_64-linux-ghcup-${ver}" \
|
|
||||||
"${base_url}/out/x86_64-linux-ghcup-${ver}?job=release:linux:64bit"
|
|
||||||
|
|
||||||
curl -f -o "aarch64-linux-ghcup-${ver}" \
|
|
||||||
"${base_url}/out/aarch64-linux-ghcup-${ver}?job=release:linux:aarch64"
|
|
||||||
|
|
||||||
curl -f -o "armv7-linux-ghcup-${ver}" \
|
|
||||||
"${base_url}/out/armv7-linux-ghcup-${ver}?job=release:linux:armv7"
|
|
||||||
|
|
||||||
curl -f -o "x86_64-mingw64-ghcup-${ver}.exe" \
|
|
||||||
"${base_url}/out/x86_64-mingw64-ghcup-${ver}.exe?job=release:windows"
|
|
||||||
|
|
||||||
rm -f *.sig
|
|
||||||
sha256sum *-ghcup-* > SHA256SUMS
|
|
||||||
gpg --detach-sign -u ${gpg_user} SHA256SUMS
|
|
||||||
for f in *-ghcup-* ; do gpg --detach-sign -u ${gpg_user} $f ; done
|
|
||||||
|
|
||||||
|
# cirrus
|
||||||
|
curl -L -o x86_64-portbld-freebsd-ghcup-${RELEASE} \
|
||||||
|
"https://api.cirrus-ci.com/v1/artifact/github/haskell/ghcup-hs/build/binaries/out/x86_64-portbld-freebsd-ghcup-${RELEASE}?branch=${RELEASE}"
|
||||||
|
|
||||||
|
sha256sum *ghcup* > SHA256SUMS
|
||||||
|
gpg --detach-sign -u "${SIGNER}" SHA256SUMS
|
||||||
|
|
||||||
|
|||||||
@@ -29,8 +29,7 @@ symlink ${ver}/aarch64-linux-ghcup-${ver} aarch64-linux-ghcup
|
|||||||
symlink ${ver}/armv7-linux-ghcup-${ver} armv7-linux-ghcup
|
symlink ${ver}/armv7-linux-ghcup-${ver} armv7-linux-ghcup
|
||||||
symlink ${ver}/i386-linux-ghcup-${ver} i386-linux-ghcup
|
symlink ${ver}/i386-linux-ghcup-${ver} i386-linux-ghcup
|
||||||
symlink ${ver}/x86_64-apple-darwin-ghcup-${ver} x86_64-apple-darwin-ghcup
|
symlink ${ver}/x86_64-apple-darwin-ghcup-${ver} x86_64-apple-darwin-ghcup
|
||||||
symlink ${ver}/x86_64-freebsd12-ghcup-${ver} x86_64-freebsd12-ghcup
|
symlink ${ver}/x86_64-portbld-freebsd-ghcup-${ver} x86_64-portbld-freebsd-ghcup
|
||||||
symlink ${ver}/x86_64-freebsd13-ghcup-${ver} x86_64-freebsd13-ghcup
|
|
||||||
symlink ${ver}/x86_64-linux-ghcup-${ver} x86_64-linux-ghcup
|
symlink ${ver}/x86_64-linux-ghcup-${ver} x86_64-linux-ghcup
|
||||||
symlink ${ver}/x86_64-mingw64-ghcup-${ver}.exe x86_64-mingw64-ghcup.exe
|
symlink ${ver}/x86_64-mingw64-ghcup-${ver}.exe x86_64-mingw64-ghcup.exe
|
||||||
EOF
|
EOF
|
||||||
|
|||||||
@@ -25,22 +25,28 @@ put SHA256SUMS
|
|||||||
put SHA256SUMS.sig
|
put SHA256SUMS.sig
|
||||||
put aarch64-apple-darwin-ghcup-${ver}
|
put aarch64-apple-darwin-ghcup-${ver}
|
||||||
put aarch64-apple-darwin-ghcup-${ver}.sig
|
put aarch64-apple-darwin-ghcup-${ver}.sig
|
||||||
|
put aarch64-apple-darwin-ghcup.plan.json
|
||||||
put aarch64-linux-ghcup-${ver}
|
put aarch64-linux-ghcup-${ver}
|
||||||
put aarch64-linux-ghcup-${ver}.sig
|
put aarch64-linux-ghcup-${ver}.sig
|
||||||
|
put aarch64-linux-ghcup.plan.json
|
||||||
put armv7-linux-ghcup-${ver}
|
put armv7-linux-ghcup-${ver}
|
||||||
put armv7-linux-ghcup-${ver}.sig
|
put armv7-linux-ghcup-${ver}.sig
|
||||||
|
put armv7-linux-ghcup.plan.json
|
||||||
put i386-linux-ghcup-${ver}
|
put i386-linux-ghcup-${ver}
|
||||||
put i386-linux-ghcup-${ver}.sig
|
put i386-linux-ghcup-${ver}.sig
|
||||||
|
put i386-linux-ghcup.plan.json
|
||||||
put x86_64-apple-darwin-ghcup-${ver}
|
put x86_64-apple-darwin-ghcup-${ver}
|
||||||
put x86_64-apple-darwin-ghcup-${ver}.sig
|
put x86_64-apple-darwin-ghcup-${ver}.sig
|
||||||
put x86_64-freebsd12-ghcup-${ver}
|
put x86_64-apple-darwin-ghcup.plan.json
|
||||||
put x86_64-freebsd12-ghcup-${ver}.sig
|
put x86_64-portbld-freebsd-ghcup-${ver}
|
||||||
put x86_64-freebsd13-ghcup-${ver}
|
put x86_64-portbld-freebsd-ghcup-${ver}.sig
|
||||||
put x86_64-freebsd13-ghcup-${ver}.sig
|
put x86_64-portbld-freebsd-ghcup.plan.json
|
||||||
put x86_64-linux-ghcup-${ver}
|
put x86_64-linux-ghcup-${ver}
|
||||||
put x86_64-linux-ghcup-${ver}.sig
|
put x86_64-linux-ghcup-${ver}.sig
|
||||||
|
put x86_64-linux-ghcup.plan.json
|
||||||
put x86_64-mingw64-ghcup-${ver}.exe
|
put x86_64-mingw64-ghcup-${ver}.exe
|
||||||
put x86_64-mingw64-ghcup-${ver}.exe.sig
|
put x86_64-mingw64-ghcup-${ver}.exe.sig
|
||||||
|
put x86_64-mingw64-ghcup.plan.json
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
curl -X PURGE https://downloads.haskell.org/~ghcup/${ver}/
|
curl -X PURGE https://downloads.haskell.org/~ghcup/${ver}/
|
||||||
|
|||||||
40
test/GHCup/Prelude/File/Posix/TraversalsSpec.hs
Normal file
40
test/GHCup/Prelude/File/Posix/TraversalsSpec.hs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
{-# LANGUAGE CPP #-}
|
||||||
|
|
||||||
|
module GHCup.Prelude.File.Posix.TraversalsSpec where
|
||||||
|
|
||||||
|
|
||||||
|
#if !defined(IS_WINDOWS)
|
||||||
|
import GHCup.Prelude.File.Posix.Traversals
|
||||||
|
|
||||||
|
import Control.Monad.IO.Class (liftIO)
|
||||||
|
import Data.List
|
||||||
|
import System.Posix.Directory
|
||||||
|
import Unsafe.Coerce
|
||||||
|
#endif
|
||||||
|
|
||||||
|
import Test.Hspec
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
spec :: Spec
|
||||||
|
spec = do
|
||||||
|
#if defined(IS_WINDOWS)
|
||||||
|
pure ()
|
||||||
|
#else
|
||||||
|
-- https://github.com/haskell/ghcup-hs/issues/415
|
||||||
|
describe "GHCup.Prelude.File.Posix.Traversals" $ do
|
||||||
|
it "readDirEnt" $ do
|
||||||
|
dirstream <- liftIO $ openDirStreamPortable "test/data"
|
||||||
|
(dt1, fp1) <- readDirEntPortable dirstream
|
||||||
|
(dt2, fp2) <- readDirEntPortable dirstream
|
||||||
|
(dt3, fp3) <- readDirEntPortable dirstream
|
||||||
|
(dt4, fp4) <- readDirEntPortable dirstream
|
||||||
|
let xs = sortOn snd [ (dt1, fp1), (dt2, fp2)
|
||||||
|
, (dt3, fp3), (dt4, fp4)
|
||||||
|
]
|
||||||
|
xs `shouldBe` [(unsafeCoerce (4 :: Int),".")
|
||||||
|
,(unsafeCoerce (4 :: Int),"..")
|
||||||
|
,(unsafeCoerce (4 :: Int),"dir")
|
||||||
|
,(unsafeCoerce (8 :: Int),"file")
|
||||||
|
]
|
||||||
|
#endif
|
||||||
@@ -5,6 +5,7 @@ module GHCup.Types.JSONSpec where
|
|||||||
import GHCup.ArbitraryTypes ()
|
import GHCup.ArbitraryTypes ()
|
||||||
import GHCup.Types hiding ( defaultSettings )
|
import GHCup.Types hiding ( defaultSettings )
|
||||||
import GHCup.Types.JSON ()
|
import GHCup.Types.JSON ()
|
||||||
|
import GHCup.Prelude
|
||||||
|
|
||||||
import Test.Aeson.GenericSpecs
|
import Test.Aeson.GenericSpecs
|
||||||
import Test.Hspec
|
import Test.Hspec
|
||||||
@@ -13,5 +14,9 @@ import Test.Hspec
|
|||||||
|
|
||||||
spec :: Spec
|
spec :: Spec
|
||||||
spec = do
|
spec = do
|
||||||
roundtripAndGoldenSpecsWithSettings (defaultSettings { goldenDirectoryOption = CustomDirectoryName "test/golden" }) (Proxy @GHCupInfo)
|
roundtripAndGoldenSpecsWithSettings (defaultSettings { goldenDirectoryOption = CustomDirectoryName goldenDir }) (Proxy @GHCupInfo)
|
||||||
|
where
|
||||||
|
goldenDir
|
||||||
|
| isWindows = "test/golden/windows"
|
||||||
|
| otherwise = "test/golden/unix"
|
||||||
|
|
||||||
|
|||||||
0
test/data/dir/.keep
Normal file
0
test/data/dir/.keep
Normal file
0
test/data/file
Normal file
0
test/data/file
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user