Compare commits

...

60 Commits

Author SHA1 Message Date
16ae69e994 Fix property tests 2023-10-13 18:08:16 +08:00
94888e9d8e Add temp git ref to versions to fix CI 2023-10-13 17:52:39 +08:00
Colin Woodbury
cc7cc8c0e4 refactor: use upstream TH constructors 2023-10-13 17:35:39 +09:00
Colin Woodbury
28cb01539d chore: bump versions upper bound and squash warnings 2023-10-13 17:31:17 +09:00
Colin Woodbury
8aa05f311e refactor: upgrade versions library usage 2023-10-13 17:09:35 +09:00
2f107197d4 Merge branch 'issue-887' 2023-10-10 16:57:58 +08:00
486a1bac25 Fix segfault in TUI when hitting enter early
Fixes #887
2023-10-10 10:26:35 +08:00
a73ce186b5 Remove documentation of nightlies
GHC nightlies have been broken for a while and unless
they are not only fixed, but GHC upstream demonstrates that
they can make them work reliably, GHCup will not promote them.
2023-10-07 16:54:54 +08:00
76204aa366 Re-enable threaded runtime
Needed for vty.
2023-10-01 17:17:13 +08:00
502f0ea62f Avoid module recompilation 2023-10-01 17:10:50 +08:00
e7e6663017 Update stackage to 20.26 2023-10-01 14:53:37 +08:00
e27fed09f3 Fix sdist 2023-10-01 14:45:41 +08:00
9eeac00714 Further improvement to tag documentation 2023-10-01 14:38:40 +08:00
c0ffb22d6a Improve documentation around tags 2023-10-01 14:35:31 +08:00
f0b145d8dd Merge remote-tracking branch 'origin/pr/890' 2023-09-30 15:20:42 +08:00
bb700281a3 Update gpg docs 2023-09-30 00:02:36 +08:00
openingnow
fcdec4ba2c Add another cabal store path 2023-09-29 16:58:51 +09:00
371eda962f Update system requirements for specific distro version
fixes #777
2023-09-04 15:08:24 +08:00
50252d8613 Merge branch 'fix-optparse-test' 2023-09-03 14:34:40 +08:00
78c393a16e Fix optparse tests on windows 2023-09-02 18:47:42 +08:00
9c3478075f Merge remote-tracking branch 'origin/pr/864' 2023-09-02 16:35:21 +08:00
7e7c11fda4 Merge remote-tracking branch 'origin/pr/868' 2023-09-02 16:34:30 +08:00
bff14761ac Use optparse-test in release/build 2023-09-02 16:32:46 +08:00
99ddcc938f cabal-fmt 2023-09-02 16:20:54 +08:00
e2301e2fa7 Merge remote-tracking branch 'origin/pr/862' 2023-09-02 16:19:56 +08:00
c52096671e Merge remote-tracking branch 'origin/pr/873' 2023-09-01 13:13:10 +08:00
64f03a2f18 Merge remote-tracking branch 'origin/pr/877' 2023-08-29 18:19:04 +08:00
Fendor
a72b78ef96 Update supported tools table for HLS 2.2.0.0 2023-08-27 14:33:42 +02:00
Zubin Duggal
b17849c258 Add my GPG keys to the docs 2023-08-23 17:59:56 +05:30
d759535faa Merge remote-tracking branch 'origin/pr/870' 2023-08-14 17:45:58 +08:00
Fendor
c25c07aa61 Update supported tool list 2023-08-12 11:56:12 +02:00
Lei Zhu
5f361e1e0b Fix compile test 2023-08-05 13:47:51 +08:00
Lei Zhu
bcb498de20 Merge branch 'master' into optparse-test-suite 2023-08-05 13:08:41 +08:00
Arjun Kathuria
fd6ff9f8ec pretty-print instances for VersionRange and VersionCmp types 2023-07-30 12:45:01 +05:30
Lei Zhu
69d311f0b4 ci 2023-07-29 00:43:33 +08:00
Lei Zhu
fde0e712ac add ci 2023-07-28 23:57:59 +08:00
Lei Zhu
c60aa767ca format 2023-07-28 23:48:03 +08:00
Lei Zhu
78df858ba1 run test 2023-07-28 23:39:21 +08:00
Lei Zhu
f1f4d5e836 gc test 2023-07-28 23:26:19 +08:00
Lei Zhu
2726e83235 whereis test 2023-07-28 23:00:15 +08:00
Lei Zhu
f23631054a compile test 2023-07-28 22:06:16 +08:00
Lei Zhu
9189f9a65a Add absolute description 2023-07-25 23:01:44 +08:00
Lei Zhu
7076472bde compile test 2023-07-25 22:58:01 +08:00
Lei Zhu
6f07b6a343 compile test 2023-07-24 23:04:18 +08:00
Lei Zhu
dfebfc9504 upgrade test 2023-07-24 22:26:33 +08:00
Lei Zhu
36463ebf97 list test 2023-07-24 22:09:03 +08:00
Lei Zhu
f400f43b8c list test 2023-07-23 23:51:03 +08:00
Lei Zhu
c92875882a rm test 2023-07-23 16:30:25 +08:00
Lei Zhu
2df2e3da40 extend unset ghc optparse example 2023-07-23 15:47:47 +08:00
Lei Zhu
cf1e8659b0 unset test 2023-07-23 15:41:27 +08:00
Lei Zhu
fb2e3f2740 test test 2023-07-23 15:19:13 +08:00
Lei Zhu
aafb77df7c install test 2023-07-22 23:10:27 +08:00
Lei Zhu
dc1a813305 config test 2023-07-22 17:46:23 +08:00
Lei Zhu
16c7ecabe2 nuke test 2023-07-22 17:20:42 +08:00
Lei Zhu
e1d8ba869a Add missing stack for changelog parser 2023-07-22 17:16:58 +08:00
Lei Zhu
38db038953 changlog test 2023-07-22 17:14:49 +08:00
Lei Zhu
bcdf2b23f1 debug-info test 2023-07-22 16:07:49 +08:00
Lei Zhu
83b82c328b Set test 2023-07-22 15:31:37 +08:00
Lei Zhu
c10924274d Set test 2023-07-22 11:45:29 +08:00
Lei Zhu
e13c5a99af Remove origin test to ghcup-test subdir 2023-07-20 23:09:14 +08:00
64 changed files with 1420 additions and 216 deletions

11
.editorconfig Normal file
View File

@@ -0,0 +1,11 @@
root = true
[*]
end_of_line = LF
trim_trailing_whitespace = true
insert_final_newline = true
[*.hs]
indent_style = space
indent_size = 2
max_line_length = 80

View File

@@ -27,9 +27,11 @@ build_with_cache --project-file=cabal.project.release -w "${GHC}" --enable-tests
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)
binary_opttest=$(cabal --project-file=cabal.project.release list-bin ghcup-optparse-test)
ver=$("${binary}" --numeric-version)
strip_binary "${binary}"
cp "${binary}" "out/${ARTIFACT}-${ver}${ext}"
cp "${binary_test}" "out/test-${ARTIFACT}-${ver}${ext}"
cp "${binary_opttest}" "out/test-optparse-${ARTIFACT}-${ver}${ext}"
cp ./dist-newstyle/cache/plan.json "out/${ARTIFACT}.plan.json"

View File

@@ -18,8 +18,10 @@ mkdir -p "${GHCUP_BIN}"
cp "out/${ARTIFACT}"-* "$GHCUP_BIN/ghcup${ext}"
cp "out/test-${ARTIFACT}"-* "ghcup-test${ext}"
cp "out/test-optparse-${ARTIFACT}"-* "ghcup-test-optparse${ext}"
chmod +x "$GHCUP_BIN/ghcup${ext}"
chmod +x "ghcup-test${ext}"
chmod +x "ghcup-test-optparse${ext}"
"$GHCUP_BIN/ghcup${ext}" --version
eghcup --version
@@ -29,7 +31,8 @@ sha_sum "$(raw_eghcup --offline whereis ghcup)"
### Haskell test suite
./ghcup-test${ext}
rm ghcup-test${ext}
./ghcup-test-optparse${ext}
rm ghcup-test${ext} ghcup-test-optparse${ext}
### manual cli based testing

View File

@@ -45,7 +45,7 @@ import Data.IORef
import Data.Vector ( Vector
, (!?)
)
import Data.Versions hiding ( str )
import Data.Versions
import Haskus.Utils.Variant.Excepts
import Prelude hiding ( appendFile )
import System.FilePath

View File

@@ -8,6 +8,11 @@ package ghcup
constraints: http-io-streams -brotli,
any.aeson >= 2.0.1.0
source-repository-package
type: git
location: https://github.com/fosskers/versions.git
tag: 7bc3355348aac3510771d4622aff09ac38c9924d
package libarchive
flags: -system-libarchive
@@ -23,3 +28,5 @@ package aeson
package streamly
flags: +use-unliftio
package *
test-show-details: direct

View File

@@ -4,6 +4,11 @@ optional-packages: ./vendored/*/*.cabal
optimization: 2
source-repository-package
type: git
location: https://github.com/fosskers/versions.git
tag: 7bc3355348aac3510771d4622aff09ac38c9924d
if os(linux)
package ghcup
flags: +tui

View File

@@ -43,6 +43,12 @@ All of the following are valid arguments to `ghcup install ghc`:
If the argument is omitted, the default is `recommended`.
Other tags include:
- `prerelease`: a prerelease version
- `latest-prerelease`: the latest prerelease version
## Manpages
For man pages to work you need [man-db](http://man-db.nongnu.org/) as your `man` provider, then issue `man ghc`. Manpages only work for the currently set ghc.
@@ -203,34 +209,6 @@ url-source:
- "https://raw.githubusercontent.com/haskell/ghcup-metadata/master/ghcup-prereleases-0.0.7.yaml"
```
### Nightlies
Nightlies are just another release channel. Currently, only GHC supports nightlies, which are binary releases
that are built every night from `master`.
To add the nightly channel, run:
```sh
ghcup config add-release-channel https://ghc.gitlab.haskell.org/ghcup-metadata/ghcup-nightlies-0.0.7.yaml
```
To list all nightlies from 2023, run:
```sh
ghcup list --show-nightly --tool=ghc --since=2023-01-01
```
Ways to install a nightly:
```sh
# by date
ghcup install ghc 2023-06-20
# by version
ghcup install ghc 9.7.20230619
# by tag
ghcup install ghc latest-nightly
```
## Stack integration
Stack manages GHC versions internally by default. In order to make it use ghcup installed
@@ -489,8 +467,10 @@ this is cryptographically secure.
First, obtain the gpg keys:
```sh
gpg --batch --keyserver keys.openpgp.org --recv-keys 7D1E8AFD1D4A16D71FADA2F2CCC85C0E40C06A8C
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys 7D1E8AFD1D4A16D71FADA2F2CCC85C0E40C06A8C
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys FE5AB6C91FEA597C3B31180B73EDE9E8CFBAEF01
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys 88B57FCF7DB53B4DB3BFA4B1588764FBE22D19C4
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys EAF2A9A722C0C96F2B431CA511AAD8CEDEE0CAEF
```
Then verify the gpg key in one of these ways:

View File

@@ -38,49 +38,78 @@ Also see [tags and shortcuts](../guide/#tags-and-shortcuts) for more information
### Linux Debian
#### Generic
The following distro packages are required: `build-essential curl libffi-dev libffi6 libgmp-dev libgmp10 libncurses-dev libncurses5 libtinfo5`
#### Version >= 11
The following distro packages are required: `build-essential curl libffi-dev libffi7 libgmp-dev libgmp10 libncurses-dev libncurses5 libtinfo5`
### Linux Ubuntu
#### Generic
The following distro packages are required: `build-essential curl libffi-dev libffi6 libgmp-dev libgmp10 libncurses-dev libncurses5 libtinfo5`
#### Version >= 20.04 && < 20.10
The following distro packages are required: `build-essential curl libffi-dev libffi7 libgmp-dev libgmp10 libncurses-dev libncurses5 libtinfo5`
#### Version >= 20.10
The following distro packages are required: `build-essential curl libffi-dev libffi8ubuntu1 libgmp-dev libgmp10 libncurses-dev libncurses5 libtinfo5`
### Linux Fedora
#### Generic
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
#### Generic
The following distro packages are required: `gcc gcc-c++ gmp gmp-devel make ncurses ncurses-compat-libs xz perl`
#### Version >= 7 && < 8
The following distro packages are required: `gcc gcc-c++ gmp gmp-devel make ncurses xz perl`
### Linux Alpine
#### Generic
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)
#### 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
#### Generic
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
#### Generic
The following distro packages are required: `curl gcc gmp gmake ncurses perl5 libffi libiconv`
Notice that only FreeBSD 13.x is supported. If the installation fails, complaining about `libncursesw.8.so`, you will need to install FreeBSD 12 compat package first, for example, `pkg install misc/compat12x`.
### Windows
#### Generic
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
@@ -104,14 +133,19 @@ GHCup supports the following tools, which are also known as the **Haskell Toolch
<table>
<thead><tr><th>GHC Version</th><th>Tags</th></tr></thead>
<tbody>
<tr><td>9.6.1</td><td><span style="color:blue">latest</span>, base-4.18.0.0</td></tr>
<tr><td>9.6.2</td><td><span style="color:blue">latest</span>, base-4.18.0.0</td></tr>
<tr><td>9.6.1</td><td>base-4.18.0.0</td></tr>
<tr><td>9.4.7</td><td>base-4.17.2.0</td></tr>
<tr><td>9.4.6</td><td>base-4.17.2.0</td></tr>
<tr><td>9.4.5</td><td>base-4.17.1.0</td></tr>
<tr><td>9.4.4</td><td>base-4.17.0.0</td></tr>
<tr><td>9.4.3</td><td>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.8</td><td><span style="color:green">recommended</span>, base-4.16.4.0</td></tr>
<tr><td>9.2.7</td><td>base-4.16.4.0</td></tr>
<tr><td>9.2.6</td><td>base-4.16.4.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.5</td><td>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>
@@ -166,8 +200,13 @@ GHCup supports the following tools, which are also known as the **Haskell Toolch
<table>
<thead><tr><th>HLS Version</th><th>Tags</th></tr></thead>
<tbody>
<tr><td>1.9.1.0</td><td><span style="color:blue">latest</span></td></tr>
<tr><td>1.9.0.0</td><td><span style="color:green">recommended</span></td></tr>
<tr><td>2.2.0.0</td><td><span style="color:blue">latest</span>, <span style="color:green">recommended</span></td></tr>
<tr><td>2.1.0.0</td><td></td></tr>
<tr><td>2.0.0.1</td><td></td></tr>
<tr><td>2.0.0.0</td><td></td></tr>
<tr><td>1.10.0.0</td><td></td></tr>
<tr><td>1.9.1.0</td><td></td></tr>
<tr><td>1.9.0.0</td><td></td></tr>
<tr><td>1.8.0.0</td><td></td></tr>
<tr><td>1.7.0.0</td><td></td></tr>
<tr><td>1.6.1.0</td><td></td></tr>
@@ -186,7 +225,8 @@ GHCup supports the following tools, which are also known as the **Haskell Toolch
<table>
<thead><tr><th>Stack Version</th><th>Tags</th></tr></thead>
<tbody>
<tr><td>2.9.3</td><td><span style="color:blue">latest</span>, <span style="color:green">recommended</span></td></tr>
<tr><td>2.11.1</td><td><span style="color:blue">latest</span></td></tr>
<tr><td>2.9.3</td><td><span style="color:green">recommended</span></td></tr>
<tr><td>2.9.1</td><td></td></tr>
<tr><td>2.7.5</td><td></td></tr>
<tr><td>2.7.3</td><td></td></tr>
@@ -200,7 +240,7 @@ GHCup supports the following tools, which are also known as the **Haskell Toolch
This list may not be exhaustive and specifies support for bindists only.
| Platform | Architecture | ghcup | GHC | cabal | HLS | stack |
| Platform | Architecture | ghcup | GHC | cabal | HLS | stack |
| ------ | ------ | ------ | ------ | ------ | ------ | ------ |
| Windows 7 | amd64 | ❔ | ✅ | ✅ | ✅ | ✅ |
| Windows 10 | amd64 | ✅ | ✅ | ✅ | ✅ | ✅ |
@@ -256,7 +296,14 @@ Lower availability of bindists. Stack and HLS binaries are experimental.
Download the binary for your platform at [https://downloads.haskell.org/~ghcup/](https://downloads.haskell.org/~ghcup/)
and place it into your `PATH` anywhere.
If you want to GPG verify the binaries, import the following keys first: `7D1E8AFD1D4A16D71FADA2F2CCC85C0E40C06A8C` and `FE5AB6C91FEA597C3B31180B73EDE9E8CFBAEF01`.
If you want to GPG verify the binaries, import the following keys first:
```sh
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys 7D1E8AFD1D4A16D71FADA2F2CCC85C0E40C06A8C
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys FE5AB6C91FEA597C3B31180B73EDE9E8CFBAEF01
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys 88B57FCF7DB53B4DB3BFA4B1588764FBE22D19C4
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys EAF2A9A722C0C96F2B431CA511AAD8CEDEE0CAEF
```
Then adjust your `PATH` in `~/.bashrc` (or similar, depending on your shell) like so:

View File

@@ -25,10 +25,10 @@ extra-source-files:
cbits/dirutils.h
data/build_mk/cross
data/build_mk/default
test/data/dir/.keep
test/data/file
test/golden/unix/GHCupInfo.json
test/golden/windows/GHCupInfo.json
test/ghcup-test/data/dir/.keep
test/ghcup-test/data/file
test/ghcup-test/golden/unix/GHCupInfo.json
test/ghcup-test/golden/windows/GHCupInfo.json
source-repository head
type: git
@@ -53,6 +53,43 @@ flag no-exe
default: False
manual: True
common app-common-depends
build-depends:
, aeson >=1.4
, aeson-pretty ^>=0.8.8
, async ^>=2.2.3
, base >=4.12 && <5
, bytestring >=0.10 && <0.12
, cabal-install-parsers >=0.4.5
, cabal-plan ^>=0.7.2
, containers ^>=0.6
, deepseq ^>=1.4
, directory ^>=1.3.6.0
, filepath ^>=1.4.2.1
, haskus-utils-types ^>=1.5
, haskus-utils-variant ^>=3.2.1
, libarchive ^>=3.0.3.0
, megaparsec >=8.0.0 && <9.3
, mtl ^>=2.2
, optparse-applicative >=0.15.1.0 && <0.18
, pretty ^>=1.1.3.1
, pretty-terminal ^>=0.1.0.0
, process ^>=1.6.11.0
, resourcet ^>=1.2.2
, safe ^>=0.3.18
, safe-exceptions ^>=0.1
, tagsoup ^>=0.14
, template-haskell >=2.7 && <2.20
, temporary ^>=1.3
, text ^>=2.0
, time >=1.9.3 && <1.12
, unordered-containers ^>=0.2
, uri-bytestring ^>=0.3.2.2
, utf8-string ^>=1.0
, vector ^>=0.12
, versions >=6.0.3 && <6.1
, yaml-streamly ^>=0.12.0
library
exposed-modules:
GHCup
@@ -137,7 +174,7 @@ library
, pretty-terminal ^>=0.1.0.0
, regex-posix ^>=0.96
, resourcet ^>=1.2.2
, retry ^>=0.8.1.2 || ^>=0.9
, retry >=0.8.1.2 && <0.10
, safe ^>=0.3.18
, safe-exceptions ^>=0.1
, split ^>=0.2.3.4
@@ -146,13 +183,13 @@ library
, template-haskell >=2.7 && <2.20
, temporary ^>=1.3
, text ^>=2.0
, time ^>=1.9.3 || ^>=1.10 || ^>=1.11
, time >=1.9.3 && <1.12
, transformers ^>=0.5
, unliftio-core ^>=0.2.0.1
, unordered-containers ^>=0.2.10.0
, uri-bytestring ^>=0.3.2.2
, vector ^>=0.12
, versions >=4.0.1 && <5.1
, versions >=6.0.3 && <6.1
, word8 ^>=0.1.3
, yaml-streamly ^>=0.12.0
, zlib ^>=0.6.2.2
@@ -199,11 +236,11 @@ library
if (flag(tui) && !os(windows))
cpp-options: -DBRICK
build-depends: vty ^>=5.37
build-depends: vty ^>=5.39
executable ghcup
main-is: Main.hs
other-modules:
library ghcup-optparse
import: app-common-depends
exposed-modules:
GHCup.OptParse
GHCup.OptParse.ChangeLog
GHCup.OptParse.Common
@@ -224,6 +261,40 @@ executable ghcup
GHCup.OptParse.Upgrade
GHCup.OptParse.Whereis
hs-source-dirs: lib-opt
default-language: Haskell2010
default-extensions:
LambdaCase
MultiWayIf
NamedFieldPuns
PackageImports
RecordWildCards
ScopedTypeVariables
StrictData
TupleSections
ghc-options:
-Wall -fwarn-tabs -fwarn-incomplete-uni-patterns
-fwarn-incomplete-record-updates
build-depends: ghcup
if flag(internal-downloader)
cpp-options: -DINTERNAL_DOWNLOADER
if (flag(tui) && !os(windows))
cpp-options: -DBRICK
if os(windows)
cpp-options: -DIS_WINDOWS
else
build-depends: unix ^>=2.7
executable ghcup
import: app-common-depends
main-is: Main.hs
hs-source-dirs: app/ghcup
default-language: Haskell2010
default-extensions:
@@ -241,41 +312,8 @@ executable ghcup
-fwarn-incomplete-record-updates -threaded
build-depends:
, aeson >=1.4
, aeson-pretty ^>=0.8.8
, async ^>=2.2.3
, base >=4.12 && <5
, bytestring >=0.10 && <0.12
, cabal-install-parsers >=0.4.5
, cabal-plan ^>=0.7.2
, containers ^>=0.6
, deepseq ^>=1.4
, directory ^>=1.3.6.0
, filepath ^>=1.4.2.1
, ghcup
, haskus-utils-types ^>=1.5
, haskus-utils-variant ^>=3.2.1
, libarchive ^>=3.0.3.0
, megaparsec >=8.0.0 && <9.3
, mtl ^>=2.2
, optparse-applicative >=0.15.1.0 && <0.18
, pretty ^>=1.1.3.1
, pretty-terminal ^>=0.1.0.0
, process ^>=1.6.11.0
, resourcet ^>=1.2.2
, safe ^>=0.3.18
, safe-exceptions ^>=0.1
, tagsoup ^>=0.14
, template-haskell >=2.7 && <2.20
, temporary ^>=1.3
, text ^>=2.0
, time ^>=1.9.3 || ^>=1.10 || ^>=1.11
, unordered-containers ^>=0.2
, uri-bytestring ^>=0.3.2.2
, utf8-string ^>=1.0
, vector ^>=0.12
, versions >=4.0.1 && <5.1
, yaml-streamly ^>=0.12.0
, ghcup-optparse
if flag(internal-downloader)
cpp-options: -DINTERNAL_DOWNLOADER
@@ -287,7 +325,7 @@ executable ghcup
, brick ^>=1.5
, transformers ^>=0.5
, unix ^>=2.7
, vty ^>=5.37
, vty ^>=5.39
if os(windows)
cpp-options: -DIS_WINDOWS
@@ -302,7 +340,7 @@ test-suite ghcup-test
type: exitcode-stdio-1.0
main-is: Main.hs
build-tool-depends: hspec-discover:hspec-discover -any
hs-source-dirs: test
hs-source-dirs: test/ghcup-test
other-modules:
GHCup.ArbitraryTypes
GHCup.Prelude.File.Posix.TraversalsSpec
@@ -336,13 +374,50 @@ test-suite ghcup-test
, QuickCheck ^>=2.14.1
, quickcheck-arbitrary-adt ^>=0.3.1.0
, streamly ^>=0.8.2
, time ^>=1.9.3 || ^>=1.10 || ^>=1.11
, text ^>=2.0
, time >=1.9.3 && <1.12
, uri-bytestring ^>=0.3.2.2
, versions >=4.0.1 && <5.1
, versions >=6.0.3 && <6.1
if os(windows)
cpp-options: -DIS_WINDOWS
else
build-depends: unix ^>=2.7
test-suite ghcup-optparse-test
type: exitcode-stdio-1.0
hs-source-dirs: test/optparse-test
main-is: Main.hs
other-modules:
ChangeLogTest
CompileTest
ConfigTest
GCTest
InstallTest
ListTest
OtherCommandTest
RmTest
RunTest
SetTest
UnsetTest
UpgradeTest
Utils
WhereisTest
if os(windows)
cpp-options: -DIS_WINDOWS
default-language: Haskell2010
ghc-options: -Wall
build-depends:
, base
, ghcup
, ghcup-optparse
, optparse-applicative
, tasty
, tasty-hunit
, template-haskell
, text
, uri-bytestring
, versions

View File

@@ -5,4 +5,6 @@ cradle:
- component: "ghcup:exe:ghcup"
path: ./app/ghcup
- component: "ghcup:test:ghcup-test"
path: ./test
path: ./test/ghcup-test
- component: "ghcup:test:ghcup-optparse-test"
path: ./test/optparse-test

View File

@@ -49,7 +49,7 @@ data ChangeLogOptions = ChangeLogOptions
{ clOpen :: Bool
, clTool :: Maybe Tool
, clToolVer :: Maybe ToolVersion
}
} deriving (Eq, Show)
@@ -75,7 +75,7 @@ changelogP =
e -> Left e
)
)
(short 't' <> long "tool" <> metavar "<ghc|cabal|hls|ghcup>" <> help
(short 't' <> long "tool" <> metavar "<ghc|cabal|hls|ghcup|stack>" <> help
"Open changelog for given tool (default: ghc)"
<> completer toolCompleter
)

View File

@@ -48,7 +48,7 @@ import Data.Maybe
import Data.Text ( Text )
import Data.Time.Calendar ( Day )
import Data.Time.Format ( parseTimeM, defaultTimeLocale )
import Data.Versions hiding ( str )
import Data.Versions
import Data.Void
import qualified Data.Vector as V
import GHC.IO.Exception
@@ -83,6 +83,7 @@ data SetToolVersion = SetGHCVersion GHCTargetVersion
| SetToolDay Day
| SetRecommended
| SetNext
deriving (Eq, Show)
prettyToolVer :: ToolVersion -> String
prettyToolVer (GHCVersion v') = T.unpack $ tVerToText v'
@@ -823,7 +824,7 @@ checkForUpdates = do
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")
cabalStore <- liftIO $ handleIO (\_ -> if isWindows then pure "C:\\cabal\\store" else pure "~/.cabal/store or ~/.local/state/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

View File

@@ -57,6 +57,7 @@ import Text.Read (readEither)
data CompileCommand = CompileGHC GHCCompileOptions
| CompileHLS HLSCompileOptions
deriving (Eq, Show)
@@ -78,7 +79,7 @@ data GHCCompileOptions = GHCCompileOptions
, buildFlavour :: Maybe String
, buildSystem :: Maybe BuildSystem
, isolateDir :: Maybe FilePath
}
} deriving (Eq, Show)
data HLSCompileOptions = HLSCompileOptions
@@ -93,7 +94,7 @@ data HLSCompileOptions = HLSCompileOptions
, patches :: Maybe (Either FilePath [URI])
, targetGHCs :: [ToolVersion]
, cabalArgs :: [Text]
}
} deriving (Eq, Show)
@@ -283,7 +284,7 @@ ghcCompileOpts =
( short 'i'
<> long "isolate"
<> metavar "DIR"
<> help "install in an isolated directory instead of the default one, no symlinks to this installation will be made"
<> help "install in an isolated absolute directory instead of the default one, no symlinks to this installation will be made"
<> completer (bashCompleter "directory")
)
)
@@ -366,7 +367,7 @@ hlsCompileOpts =
( short 'i'
<> long "isolate"
<> metavar "DIR"
<> help "install in an isolated directory instead of the default one, no symlinks to this installation will be made"
<> help "install in an isolated absolute directory instead of the default one, no symlinks to this installation will be made"
<> completer (bashCompleter "directory")
)
)

View File

@@ -52,6 +52,7 @@ data ConfigCommand
| SetConfig String (Maybe String)
| InitConfig
| AddReleaseChannel Bool URI
deriving (Eq, Show)

View File

@@ -47,7 +47,7 @@ data GCOptions = GCOptions
, gcHLSNoGHC :: Bool
, gcCache :: Bool
, gcTmp :: Bool
}
} deriving (Eq, Show)

View File

@@ -54,6 +54,7 @@ data InstallCommand = InstallGHC InstallOptions
| InstallCabal InstallOptions
| InstallHLS InstallOptions
| InstallStack InstallOptions
deriving (Eq, Show)
@@ -70,7 +71,7 @@ data InstallOptions = InstallOptions
, isolateDir :: Maybe FilePath
, forceInstall :: Bool
, addConfArgs :: [T.Text]
}
} deriving (Eq, Show)
@@ -196,7 +197,7 @@ installOpts tool =
( short 'i'
<> long "isolate"
<> metavar "DIR"
<> help "install in an isolated dir instead of the default one"
<> help "install in an isolated absolute directory instead of the default one"
<> completer (bashCompleter "directory")
)
)

View File

@@ -27,7 +27,7 @@ import Data.List ( intercalate, sort )
import Data.Functor
import Data.Maybe
import Data.Time.Calendar ( Day )
import Data.Versions hiding ( str )
import Data.Versions
import Data.Void
import Options.Applicative hiding ( style )
import Prelude hiding ( appendFile )
@@ -58,7 +58,7 @@ data ListOptions = ListOptions
, lHideOld :: Bool
, lShowNightly :: Bool
, lRawFormat :: Bool
}
} deriving (Eq, Show)

View File

@@ -29,7 +29,7 @@ import Control.Monad.Reader
import Control.Monad.Trans.Resource
import Data.Functor
import Data.Maybe
import Data.Versions hiding ( str )
import Data.Versions
import Haskus.Utils.Variant.Excepts
import Options.Applicative hiding ( style )
import Prelude hiding ( appendFile )
@@ -50,6 +50,7 @@ data RmCommand = RmGHC RmOptions
| RmCabal Version
| RmHLS Version
| RmStack Version
deriving (Eq, Show)
@@ -61,7 +62,7 @@ data RmCommand = RmGHC RmOptions
data RmOptions = RmOptions
{ ghcVer :: GHCTargetVersion
}
} deriving (Eq, Show)

View File

@@ -68,7 +68,7 @@ data RunOptions = RunOptions
, runBinDir :: Maybe FilePath
, runQuick :: Bool
, runCOMMAND :: [String]
}
} deriving (Eq, Show)

View File

@@ -28,7 +28,7 @@ import Control.Monad.Trans.Resource
import Data.Either
import Data.Functor
import Data.Maybe
import Data.Versions hiding ( str )
import Data.Versions
import GHC.Unicode
import Haskus.Utils.Variant.Excepts
import Options.Applicative hiding ( style )
@@ -53,6 +53,7 @@ data SetCommand = SetGHC SetOptions
| SetCabal SetOptions
| SetHLS SetOptions
| SetStack SetOptions
deriving (Eq, Show)
@@ -64,7 +65,7 @@ data SetCommand = SetGHC SetOptions
data SetOptions = SetOptions
{ sToolVer :: SetToolVersion
}
} deriving (Eq, Show)

View File

@@ -48,6 +48,7 @@ data UnsetCommand = UnsetGHC UnsetOptions
| UnsetCabal UnsetOptions
| UnsetHLS UnsetOptions
| UnsetStack UnsetOptions
deriving (Eq, Show)
@@ -59,7 +60,7 @@ data UnsetCommand = UnsetGHC UnsetOptions
data UnsetOptions = UnsetOptions
{ sToolVer :: Maybe T.Text -- target platform triple
}
} deriving (Eq, Show)
@@ -68,7 +69,7 @@ data UnsetOptions = UnsetOptions
--[ Parsers ]--
---------------
unsetParser :: Parser UnsetCommand
unsetParser =
subparser
@@ -113,7 +114,14 @@ unsetParser =
unsetGHCFooter :: String
unsetGHCFooter = [s|Discussion:
Unsets the the current GHC version. That means there won't
be a ~/.ghcup/bin/ghc anymore.|]
be a ~/.ghcup/bin/ghc anymore.
Examples:
# unset ghc
ghcup unset ghc
# unset ghc for the target version
ghcup unset ghc armv7-unknown-linux-gnueabihf|]
unsetCabalFooter :: String
unsetCabalFooter = [s|Discussion:

View File

@@ -35,7 +35,7 @@ import System.Environment
import GHCup.Utils
import System.FilePath
import GHCup.Types.Optics
import Data.Versions hiding (str)
import Data.Versions
@@ -50,7 +50,7 @@ import Data.Versions hiding (str)
data UpgradeOpts = UpgradeInplace
| UpgradeAt FilePath
| UpgradeGHCupDir
deriving Show
deriving (Eq, Show)

View File

@@ -54,6 +54,7 @@ data WhereisCommand = WhereisTool Tool (Maybe ToolVersion)
| WhereisCacheDir
| WhereisLogsDir
| WhereisConfDir
deriving (Eq, Show)
@@ -66,7 +67,7 @@ data WhereisCommand = WhereisTool Tool (Maybe ToolVersion)
data WhereisOptions = WhereisOptions {
directory :: Bool
}
} deriving (Eq, Show)

View File

@@ -83,6 +83,7 @@ import qualified Text.Megaparsec as MP
data GHCVer = SourceDist Version
| GitDist GitBranch
| RemoteDist URI
deriving (Eq, Show)

View File

@@ -75,6 +75,7 @@ data HLSVer = SourceDist Version
| GitDist GitBranch
| HackageDist Version
| RemoteDist URI
deriving (Eq, Show)
@@ -716,8 +717,10 @@ getCabalVersion fp = do
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)
let tver = (\c -> Version Nothing c Nothing Nothing)
. Chunks
. NE.fromList
. fmap (Numeric . fromIntegral)
. versionNumbers
. pkgVersion
. package

View File

@@ -65,7 +65,7 @@ import qualified Data.Text as T
data ListCriteria = ListInstalled Bool
| ListSet Bool
| ListAvailable Bool
deriving Show
deriving (Eq, Show)
-- | A list result describes a single tool version
-- and various of its properties.

View File

@@ -91,18 +91,16 @@ ghcTargetVerP =
verP' :: MP.Parsec Void Text Text
verP' = do
v <- version'
let startsWithDigists =
let startsWithDigits =
and
. take 3
. concatMap
(map
(\case
(Digits _) -> True
(Str _) -> False
) . NE.toList)
. map (\case
Numeric _ -> True
Alphanum _ -> False)
. NE.toList
. (\(Chunks nec) -> nec)
$ _vChunks v
if startsWithDigists && isNothing (_vEpoch v)
if startsWithDigits && isNothing (_vEpoch v)
then pure $ prettyVer v
else fail "Oh"

View File

@@ -26,36 +26,14 @@ import GHC.Base
#endif
import Language.Haskell.TH
import Language.Haskell.TH.Quote ( QuasiQuoter(..) )
import Language.Haskell.TH.Syntax ( Lift
, dataToExpQ
)
import Language.Haskell.TH.Syntax ( dataToExpQ )
import qualified Data.Text as T
import qualified Language.Haskell.TH.Syntax as TH
deriving instance Data Versioning
deriving instance Lift Versioning
deriving instance Data Version
deriving instance Lift Version
deriving instance Data SemVer
deriving instance Lift SemVer
deriving instance Data Mess
deriving instance Lift Mess
deriving instance Data MChunk
deriving instance Lift MChunk
deriving instance Data PVP
deriving instance Lift PVP
deriving instance Lift VSep
deriving instance Data VSep
deriving instance Lift VUnit
deriving instance Data VUnit
#if !MIN_VERSION_base(4,13,0)
deriving instance Lift (NonEmpty Word)
deriving instance Lift (NonEmpty VChunk)
deriving instance Lift (NonEmpty MChunk)
deriving instance Lift (NonEmpty VUnit)
#endif
qq :: (Text -> Q Exp) -> QuasiQuoter

View File

@@ -45,7 +45,8 @@ import Graphics.Vty ( Key(..) )
import qualified Data.ByteString.Lazy as BL
import qualified Data.Text as T
import qualified GHC.Generics as GHC
import qualified Data.List.NonEmpty as NE
import Data.Foldable (foldMap)
#if !defined(BRICK)
data Key = KEsc | KChar Char | KBS | KEnter
@@ -156,13 +157,17 @@ instance NFData VersionInfo
-- | A tag. These are currently attached to a version of a tool.
data Tag = Latest
| Recommended
| Prerelease
| LatestPrerelease
| Nightly
| LatestNightly
| Base PVP
data Tag = Latest -- ^ the latest version of a tool (unique per tool)
| Recommended -- ^ the recommended version of a tool (unique per tool)
| Prerelease -- ^ denotes a prerelease version
-- (a version should either be 'Prerelease' or
-- 'LatestPrerelease', but not both)
| LatestPrerelease -- ^ the latest prerelease (unique per tool)
| Nightly -- ^ denotes a nightly version
-- (a version should either be 'Nightly' or
-- 'LatestNightly', but not both)
| LatestNightly -- ^ the latest nightly (unique per tool)
| Base PVP -- ^ the base version shipped with GHC
| Old -- ^ old versions are hidden by default in TUI
| UnknownTag String -- ^ used for upwardscompat
deriving (Ord, Eq, GHC.Generic, Show) -- FIXME: manual JSON instance
@@ -637,6 +642,17 @@ data VersionRange = SimpleRange (NonEmpty VersionCmp) -- And
instance NFData VersionRange
instance Pretty VersionCmp where
pPrint (VR_gt v) = text "> " <> pPrint v
pPrint (VR_gteq v) = text ">= " <> pPrint v
pPrint (VR_lt v) = text "< " <> pPrint v
pPrint (VR_lteq v) = text "<= " <> pPrint v
pPrint (VR_eq v) = text "= " <> pPrint v
instance Pretty VersionRange where
pPrint (SimpleRange xs) = foldl1 (\x y -> x <> text " && " <> y) $ NE.map pPrint xs
pPrint (OrRange xs vr) = foldMap pPrint xs <> " || " <> pPrint vr
instance Pretty Versioning where
pPrint = text . T.unpack . prettyV
@@ -713,6 +729,7 @@ data ToolVersion = GHCVersion GHCTargetVersion
| ToolVersion Version
| ToolTag Tag
| ToolDay Day
deriving (Eq, Show)
instance Pretty ToolVersion where
pPrint (GHCVersion v) = pPrint v

View File

@@ -48,10 +48,11 @@ deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''MetaMo
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''Architecture
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''LinuxDistro
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''VSep
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''VUnit
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''MChunk
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''Platform
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''Mess
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''Chunk
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''Release
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''SemVer
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''Tool
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''GlobalTool

View File

@@ -119,11 +119,11 @@ import Data.Time (Day(..), diffDays, addDays)
-- >>> let lc = LoggerConfig { lcPrintDebug = False, consoleOutter = mempty, fileOutter = mempty, fancyColors = False }
-- >>> dirs' <- getAllDirs
-- >>> let installedVersions = [ ([pver|8.10.7|], "-debug+lol", Nothing), ([pver|8.10.4|], "", Nothing), ([pver|8.8.4|], "", Nothing), ([pver|8.8.3|], "", Nothing) ]
-- >>> let settings = Settings True 0 False Never Curl False GHCupURL True GPGNone False
-- >>> let settings = defaultSettings { cache = True, metaCache = 0, noNetwork = True }
-- >>> let leanAppState = LeanAppState settings dirs' defaultKeyBindings lc
-- >>> cwd <- getCurrentDirectory
-- >>> (Right ref) <- pure $ parseURI strictURIParserOptions $ "file://" <> E.encodeUtf8 (T.pack cwd) <> "/data/metadata/" <> (urlBaseName . view pathL' $ ghcupURL)
-- >>> (VRight r) <- (fmap . fmap) _ghcupDownloads $ flip runReaderT leanAppState . runE @'[DigestError, GPGError, JSONError , DownloadFailed , FileDoesNotExistError] $ liftE $ getBase ref
-- >>> (VRight r) <- (fmap . fmap) _ghcupDownloads $ flip runReaderT leanAppState . runE @'[DigestError, GPGError, JSONError , DownloadFailed , FileDoesNotExistError, ContentLengthError] $ liftE $ getBase ref
@@ -687,10 +687,8 @@ hlsAllBinaries ver = do
-- | Extract (major, minor) from any version.
getMajorMinorV :: MonadThrow m => Version -> m (Int, Int)
getMajorMinorV Version {..} = case _vChunks of
((Digits x :| []) :| ((Digits y :| []):_)) -> pure (fromIntegral x, fromIntegral y)
_ -> throwM $ ParseError "Could not parse X.Y from version"
getMajorMinorV (Version _ (Chunks (Numeric x :| Numeric y : _)) _ _) = pure (fromIntegral x, fromIntegral y)
getMajorMinorV _ = throwM $ ParseError "Could not parse X.Y from version"
matchMajor :: Version -> Int -> Int -> Bool
matchMajor v' major' minor' = case getMajorMinorV v' of
@@ -732,7 +730,7 @@ getGHCForPVP pvpIn mt = do
-- | Like 'getGHCForPVP', except with explicit input parameter.
--
-- >>> getGHCForPVP' [pver|8|] installedVersions Nothing
-- Just (GHCTargetVersion {_tvTarget = Nothing, _tvVersion = Version {_vEpoch = Nothing, _vChunks = (Digits 8 :| []) :| [Digits 10 :| [],Digits 7 :| []], _vRel = [Str "debug" :| []], _vMeta = Just "lol"}})
-- Just (GHCTargetVersion {_tvTarget = Nothing, _tvVersion = Version {_vEpoch = Nothing, _vChunks = Chunks (Numeric 8 :| [Numeric 10,Numeric 7]), _vRel = Just (Release (Alphanum "debug" :| [])), _vMeta = Just "lol"}})
-- >>> fmap prettyShow $ getGHCForPVP' [pver|8.8|] installedVersions Nothing
-- "Just 8.8.4"
-- >>> fmap prettyShow $ getGHCForPVP' [pver|8.10.4|] installedVersions Nothing
@@ -758,11 +756,11 @@ getGHCForPVP' pvpIn ghcs' mt = do
-- | Get the latest available ghc for the given PVP version, which
-- may only contain parts.
--
-- >>> (fmap . fmap) fst $ getLatestToolFor GHC [pver|8|] r
-- >>> (fmap . fmap) (\(p, _, _) -> p) $ getLatestToolFor GHC Nothing [pver|8|] r
-- Just (PVP {_pComponents = 8 :| [10,7]})
-- >>> (fmap . fmap) fst $ getLatestToolFor GHC [pver|8.8|] r
-- >>> (fmap . fmap) (\(p, _, _) -> p) $ getLatestToolFor GHC Nothing [pver|8.8|] r
-- Just (PVP {_pComponents = 8 :| [8,4]})
-- >>> (fmap . fmap) fst $ getLatestToolFor GHC [pver|8.8.4|] r
-- >>> (fmap . fmap) (\(p, _, _) -> p) $ getLatestToolFor GHC Nothing [pver|8.8.4|] r
-- Just (PVP {_pComponents = 8 :| [8,4]})
getLatestToolFor :: MonadThrow m
=> Tool
@@ -1033,7 +1031,7 @@ applyPatches pdir ddir = do
patches <- liftIO $ quilt `catchIO` (\e ->
if isDoesNotExistError e || isPermissionError e then
lexicographical
lexicographical
else throwIO e)
forM_ patches $ \patch' -> applyPatch patch' ddir

View File

@@ -24,10 +24,10 @@ import qualified Data.Text as T
import qualified Data.Versions as V
import Control.Exception.Safe (MonadThrow)
import Data.Text (Text)
import Data.List.NonEmpty (NonEmpty((:|)))
import Data.List (intersperse)
import Control.Monad.Catch (throwM)
import GHCup.Errors (ParseError(..))
import Text.Megaparsec
import Data.Void (Void)
-- | This reflects the API version of the YAML.
--
@@ -65,44 +65,15 @@ pvpToVersion pvp_ rest =
-- -- prop> \v -> let (Just (pvp', r)) = versionToPVP v in pvpToVersion pvp' r === Just v
versionToPVP :: MonadThrow m => V.Version -> m (V.PVP, Text)
versionToPVP (V.Version (Just _) _ _ _) = throwM $ ParseError "Unexpected epoch"
versionToPVP v = either (\_ -> (, rest v) <$> alternative v) (pure . (, mempty)) . V.pvp . V.prettyVer $ v
versionToPVP v = case parse pvp'' "Version->PVP" $ V.prettyVer v of
Left _ -> throwM $ ParseError "Couldn't convert Version to PVP"
Right r -> pure r
where
alternative :: MonadThrow m => V.Version -> m V.PVP
alternative v' = case NE.takeWhile isDigit (V._vChunks v') of
[] -> throwM $ ParseError "Couldn't convert Version to PVP"
xs -> pure $ pvpFromList (unsafeDigit <$> xs)
rest :: V.Version -> Text
rest (V.Version _ cs pr me) =
let chunks = NE.dropWhile isDigit cs
ver = intersperse (T.pack ".") . chunksAsT $ chunks
me' = maybe [] (\m -> [T.pack "+",m]) me
pr' = foldable [] (T.pack "-" :) $ intersperse (T.pack ".") (chunksAsT pr)
prefix = case (ver, pr', me') of
(_:_, _, _) -> T.pack "."
_ -> T.pack ""
in prefix <> mconcat (ver <> pr' <> me')
where
chunksAsT :: Functor t => t V.VChunk -> t Text
chunksAsT = fmap (foldMap f)
where
f :: V.VUnit -> Text
f (V.Digits i) = T.pack $ show i
f (V.Str s) = s
foldable :: Foldable f => f b -> (f a -> f b) -> f a -> f b
foldable d g f | null f = d
| otherwise = g f
isDigit :: V.VChunk -> Bool
isDigit (V.Digits _ :| []) = True
isDigit _ = False
unsafeDigit :: V.VChunk -> Int
unsafeDigit (V.Digits x :| []) = fromIntegral x
unsafeDigit _ = error "unsafeDigit: wrong input"
pvp'' :: Parsec Void T.Text (V.PVP, T.Text)
pvp'' = do
p <- V.pvp'
s <- getParserState
pure (p, stateInput s)
pvpFromList :: [Int] -> V.PVP
pvpFromList = V.PVP . NE.fromList . fmap fromIntegral

View File

@@ -1,4 +1,4 @@
resolver: lts-20.20
resolver: lts-20.26
packages:
- .
@@ -24,6 +24,8 @@ extra-deps:
- strict-base-0.4.0.0
- text-2.0.2
- yaml-streamly-0.12.2
- github: fosskers/versions
commit: 7bc3355348aac3510771d4622aff09ac38c9924d
flags:
http-io-streams:

View File

@@ -24,7 +24,7 @@ spec = do
-- https://github.com/haskell/ghcup-hs/issues/415
describe "GHCup.Prelude.File.Posix.Traversals" $ do
it "readDirEnt" $ do
dirstream <- liftIO $ openDirStreamPortable "test/data"
dirstream <- liftIO $ openDirStreamPortable "test/ghcup-test/data"
(dt1, fp1) <- readDirEntPortable dirstream
(dt2, fp2) <- readDirEntPortable dirstream
(dt3, fp3) <- readDirEntPortable dirstream

View File

@@ -17,6 +17,6 @@ spec = do
roundtripAndGoldenSpecsWithSettings (defaultSettings { goldenDirectoryOption = CustomDirectoryName goldenDir }) (Proxy @GHCupInfo)
where
goldenDir
| isWindows = "test/golden/windows"
| otherwise = "test/golden/unix"
| isWindows = "test/ghcup-test/golden/windows"
| otherwise = "test/ghcup-test/golden/unix"

View File

@@ -0,0 +1,51 @@
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE OverloadedStrings #-}
module ChangeLogTest where
import Test.Tasty
import GHCup.OptParse
import Utils
import Test.Tasty.HUnit
import Control.Monad.IO.Class
import GHCup.Types
import Data.Versions (versionQ)
changeLogTests :: TestTree
changeLogTests = testGroup "changelog" $ map (uncurry check) checkList
where
check :: String -> ChangeLogOptions -> TestTree
check args expected = testCase args $ do
res <- changeLogParseWith (words args)
liftIO $ res @?= expected
checkList :: [(String, ChangeLogOptions)]
checkList =
[ ("changelog", ChangeLogOptions False Nothing Nothing)
, ("changelog -o", ChangeLogOptions True Nothing Nothing)
, ("changelog -t ghc", ChangeLogOptions False (Just GHC) Nothing)
, ("changelog -t cabal", ChangeLogOptions False (Just Cabal) Nothing)
, ("changelog -t hls", ChangeLogOptions False (Just HLS) Nothing)
, ("changelog -t stack", ChangeLogOptions False (Just Stack) Nothing)
, ("changelog -t ghcup", ChangeLogOptions False (Just GHCup) Nothing)
, ("changelog 9.2", ChangeLogOptions False Nothing
(Just $ GHCVersion
$ GHCTargetVersion
Nothing
$(versionQ "9.2"))
)
, ("changelog recommended", ChangeLogOptions False Nothing (Just $ ToolTag Recommended))
, ("changelog -t cabal recommended", ChangeLogOptions False (Just Cabal) (Just $ ToolTag Recommended))
, ("changelog -t cabal 3.10.1.0", ChangeLogOptions False (Just Cabal)
(Just $ GHCVersion
$ GHCTargetVersion
Nothing
$(versionQ "3.10.1.0"))
)
, ("changelog 2023-07-22", ChangeLogOptions False Nothing (Just (ToolDay (read "2023-07-22"))))
]
changeLogParseWith :: [String] -> IO ChangeLogOptions
changeLogParseWith args = do
ChangeLog a <- parseWith args
pure a

View File

@@ -0,0 +1,191 @@
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE TemplateHaskell #-}
module CompileTest where
import Test.Tasty
import GHCup.OptParse
import Utils
import Data.Versions
import GHCup.Types
import URI.ByteString.QQ
import qualified GHCup.OptParse.Compile as GHC (GHCCompileOptions(..))
import qualified GHCup.OptParse.Compile as HLS (HLSCompileOptions(..))
import GHCup.GHC as GHC
import GHCup.HLS as HLS
compileTests :: TestTree
compileTests = testGroup "compile"
$ map (buildTestTree compileParseWith)
[ ("ghc", compileGhcCheckList)
, ("hls", compileHlsCheckList)
]
mkDefaultGHCCompileOptions :: GHCVer -> Either Version FilePath -> GHCCompileOptions
mkDefaultGHCCompileOptions target boot =
GHCCompileOptions
target
boot
Nothing
Nothing
(Just $ Right [])
Nothing
[]
False
Nothing
Nothing
Nothing
Nothing
mkDefaultHLSCompileOptions :: HLSVer -> [ToolVersion] -> HLSCompileOptions
mkDefaultHLSCompileOptions target ghcs =
HLSCompileOptions
target
Nothing
True
False
(Left False)
Nothing
Nothing
Nothing
(Just $ Right [])
ghcs
[]
compileGhcCheckList :: [(String, CompileCommand)]
compileGhcCheckList = mapSecond CompileGHC
[ ("compile ghc -v 9.4.5 -b 9.2.8", baseOptions)
, ("compile ghc -g a32db0b -b 9.2.8", mkDefaultGHCCompileOptions
(GHC.GitDist $ GitBranch "a32db0b" Nothing)
(Left $(versionQ "9.2.8"))
)
, ("compile ghc -g a32db0b -b 9.2.8 -r https://gitlab.haskell.org/ghc/ghc.git",
mkDefaultGHCCompileOptions
(GHC.GitDist $ GitBranch "a32db0b" (Just "https://gitlab.haskell.org/ghc/ghc.git"))
(Left $(versionQ "9.2.8"))
)
, ("compile ghc -g a32db0b -r https://gitlab.haskell.org/ghc/ghc.git -b /usr/bin/ghc-9.2.2",
mkDefaultGHCCompileOptions
(GHC.GitDist $ GitBranch "a32db0b" (Just "https://gitlab.haskell.org/ghc/ghc.git"))
(Right "/usr/bin/ghc-9.2.2")
)
, ("compile ghc --remote-source-dist https://gitlab.haskell.org/ghc/ghc.git -b 9.2.8", mkDefaultGHCCompileOptions
(GHC.RemoteDist [uri|https://gitlab.haskell.org/ghc/ghc.git|])
(Left $(versionQ "9.2.8"))
)
, (baseCmd <> "-j20", baseOptions{GHC.jobs = Just 20})
, (baseCmd <> "--jobs 10", baseOptions{GHC.jobs = Just 10})
, (baseCmd <> "-c build.mk", baseOptions{GHC.buildConfig = Just "build.mk"})
, (baseCmd <> "--config build.mk", baseOptions{GHC.buildConfig = Just "build.mk"})
, (baseCmd <> "--patch file:///example.patch", baseOptions{GHC.patches = Just $ Right [[uri|file:///example.patch|]]})
, (baseCmd <> "-p patch_dir", baseOptions{GHC.patches = Just (Left "patch_dir")})
, (baseCmd <> "--patchdir patch_dir", baseOptions{GHC.patches = Just (Left "patch_dir")})
, (baseCmd <> "-x armv7-unknown-linux-gnueabihf", baseOptions{GHC.crossTarget = Just "armv7-unknown-linux-gnueabihf"})
, (baseCmd <> "--cross-target armv7-unknown-linux-gnueabihf", baseOptions{GHC.crossTarget = Just "armv7-unknown-linux-gnueabihf"})
, (baseCmd <> "-- --enable-unregisterised", baseOptions{GHC.addConfArgs = ["--enable-unregisterised"]})
, (baseCmd <> "--set", baseOptions{GHC.setCompile = True})
, (baseCmd <> "-o 9.4.5-p1", baseOptions{GHC.ovewrwiteVer = Just $(versionQ "9.4.5-p1")})
, (baseCmd <> "--overwrite-version 9.4.5-p1", baseOptions{GHC.ovewrwiteVer = Just $(versionQ "9.4.5-p1")})
, (baseCmd <> "-f make", baseOptions{GHC.buildFlavour = Just "make"})
, (baseCmd <> "--flavour make", baseOptions{GHC.buildFlavour = Just "make"})
, (baseCmd <> "--hadrian", baseOptions{GHC.buildSystem = Just Hadrian})
, (baseCmd <> "--make", baseOptions{GHC.buildSystem = Just Make})
#ifdef IS_WINDOWS
, (baseCmd <> "-i C:\\\\tmp\\out_dir", baseOptions{GHC.isolateDir = Just "C:\\\\tmp\\out_dir"})
, (baseCmd <> "--isolate C:\\\\tmp\\out_dir", baseOptions{GHC.isolateDir = Just "C:\\\\tmp\\out_dir"})
#else
, (baseCmd <> "-i /tmp/out_dir", baseOptions{GHC.isolateDir = Just "/tmp/out_dir"})
, (baseCmd <> "--isolate /tmp/out_dir", baseOptions{GHC.isolateDir = Just "/tmp/out_dir"})
#endif
]
where
baseCmd :: String
baseCmd = "compile ghc -v 9.4.5 -b 9.2.8 "
baseOptions :: GHCCompileOptions
baseOptions =
mkDefaultGHCCompileOptions
(GHC.SourceDist $(versionQ "9.4.5"))
(Left $(versionQ "9.2.8"))
compileHlsCheckList :: [(String, CompileCommand)]
compileHlsCheckList = mapSecond CompileHLS
[ ("compile hls -v 2.0.0.0 --ghc 9.2.8", baseOptions)
, ("compile hls --version 2.0.0.0 --ghc 9.2.8", baseOptions)
, ("compile hls -g a32db0b --ghc 9.2.8",
mkDefaultHLSCompileOptions
(HLS.GitDist $ GitBranch {ref = "a32db0b", repo = Nothing})
[ghc928]
)
, ("compile hls --git-ref a32db0b --ghc 9.2.8",
mkDefaultHLSCompileOptions
(HLS.GitDist $ GitBranch {ref = "a32db0b", repo = Nothing})
[ghc928]
)
, ("compile hls -g a32db0b -r https://github.com/haskell/haskell-language-server.git --ghc 9.2.8",
mkDefaultHLSCompileOptions
(HLS.GitDist $ GitBranch {ref = "a32db0b", repo = Just "https://github.com/haskell/haskell-language-server.git"})
[ghc928]
)
, ("compile hls -g a32db0b --repository https://github.com/haskell/haskell-language-server.git --ghc 9.2.8",
mkDefaultHLSCompileOptions
(HLS.GitDist $ GitBranch {ref = "a32db0b", repo = Just "https://github.com/haskell/haskell-language-server.git"})
[ghc928]
)
, ("compile hls --source-dist 2.0.0.0 --ghc 9.2.8",
mkDefaultHLSCompileOptions
(HLS.SourceDist $(versionQ "2.0.0.0"))
[ghc928]
)
, ("compile hls --remote-source-dist https://github.com/haskell/haskell-language-server/archive/refs/tags/2.0.0.1.tar.gz --ghc 9.2.8",
mkDefaultHLSCompileOptions
(HLS.RemoteDist [uri|https://github.com/haskell/haskell-language-server/archive/refs/tags/2.0.0.1.tar.gz|])
[ghc928]
)
, ("compile hls -v 2.0.0.0 --ghc latest",
mkDefaultHLSCompileOptions
(HLS.HackageDist $(versionQ "2.0.0.0"))
[ToolTag Latest]
)
, (baseCmd <> "-j20", baseOptions{HLS.jobs = Just 20})
, (baseCmd <> "--jobs 10", baseOptions{HLS.jobs = Just 10})
, (baseCmd <> "--no-set", baseOptions{HLS.setCompile = False})
, (baseCmd <> "--cabal-update", baseOptions{HLS.updateCabal = True})
, (baseCmd <> "-o 2.0.0.0-p1", baseOptions{HLS.ovewrwiteVer = Right $(versionQ "2.0.0.0-p1")})
, (baseCmd <> "--overwrite-version 2.0.0.0-p1", baseOptions{HLS.ovewrwiteVer = Right $(versionQ "2.0.0.0-p1")})
, (baseCmd <> "--git-describe-version", baseOptions{HLS.ovewrwiteVer = Left True})
#ifdef IS_WINDOWS
, (baseCmd <> "-i C:\\\\tmp\\out_dir", baseOptions{HLS.isolateDir = Just "C:\\\\tmp\\out_dir"})
, (baseCmd <> "--isolate C:\\\\tmp\\out_dir", baseOptions{HLS.isolateDir = Just "C:\\\\tmp\\out_dir"})
#else
, (baseCmd <> "-i /tmp/out_dir", baseOptions{HLS.isolateDir = Just "/tmp/out_dir"})
, (baseCmd <> "--isolate /tmp/out_dir", baseOptions{HLS.isolateDir = Just "/tmp/out_dir"})
#endif
, (baseCmd <> "--cabal-project file:///tmp/cabal.project", baseOptions{HLS.cabalProject = Just $ Right [uri|file:///tmp/cabal.project|]})
, (baseCmd <> "--cabal-project cabal.ghc8107.project", baseOptions{HLS.cabalProject = Just $ Left "cabal.ghc8107.project"})
, (baseCmd <> "--cabal-project-local file:///tmp/cabal.project.local", baseOptions{HLS.cabalProjectLocal = Just [uri|file:///tmp/cabal.project.local|]})
, (baseCmd <> "--patch file:///example.patch", baseOptions{HLS.patches = Just $ Right [[uri|file:///example.patch|]]})
, (baseCmd <> "-p patch_dir", baseOptions{HLS.patches = Just (Left "patch_dir")})
, (baseCmd <> "--patchdir patch_dir", baseOptions{HLS.patches = Just (Left "patch_dir")})
, (baseCmd <> "-- --enable-tests", baseOptions{HLS.cabalArgs = ["--enable-tests"]})
]
where
baseCmd :: String
baseCmd = "compile hls -v 2.0.0.0 --ghc 9.2.8 "
baseOptions :: HLSCompileOptions
baseOptions =
mkDefaultHLSCompileOptions
(HLS.HackageDist $(versionQ "2.0.0.0"))
[ghc928]
ghc928 :: ToolVersion
ghc928 = GHCVersion $ GHCTargetVersion Nothing $(versionQ "9.2.8")
compileParseWith :: [String] -> IO CompileCommand
compileParseWith args = do
Compile a <- parseWith args
pure a

View File

@@ -0,0 +1,34 @@
{-# LANGUAGE QuasiQuotes #-}
module ConfigTest where
import Test.Tasty
import Test.Tasty.HUnit
import GHCup.OptParse
import Utils
import Control.Monad.IO.Class
import URI.ByteString.QQ
configTests :: TestTree
configTests = testGroup "config" $ map (uncurry check) checkList
where
check :: String -> ConfigCommand -> TestTree
check args expected = testCase args $ do
res <- configParseWith (words args)
liftIO $ res @?= expected
checkList :: [(String, ConfigCommand)]
checkList =
[ ("config", ShowConfig)
, ("config init", InitConfig)
, ("config show", ShowConfig)
, ("config add-release-channel https://raw.githubusercontent.com/haskell/ghcup-metadata/master/ghcup-prereleases-0.0.7.yaml"
, AddReleaseChannel False [uri|https://raw.githubusercontent.com/haskell/ghcup-metadata/master/ghcup-prereleases-0.0.7.yaml|]
)
, ("config set cache true", SetConfig "cache" (Just "true"))
]
configParseWith :: [String] -> IO ConfigCommand
configParseWith args = do
Config a <- parseWith args
pure a

View File

@@ -0,0 +1,42 @@
module GCTest where
import Test.Tasty
import GHCup.OptParse
import Utils
gcTests :: TestTree
gcTests = buildTestTree gcParseWith ("gc", gcCheckList)
defaultOptions :: GCOptions
defaultOptions =
GCOptions
False
False
False
False
False
False
gcCheckList :: [(String, GCOptions)]
gcCheckList =
[ ("gc", defaultOptions)
, ("gc -o", defaultOptions{gcOldGHC = True})
, ("gc --ghc-old", defaultOptions{gcOldGHC = True})
, ("gc -p", defaultOptions{gcProfilingLibs = True})
, ("gc --profiling-libs", defaultOptions{gcProfilingLibs = True})
, ("gc -s", defaultOptions{gcShareDir = True})
, ("gc --share-dir", defaultOptions{gcShareDir = True})
, ("gc -h", defaultOptions{gcHLSNoGHC = True})
, ("gc --hls-no-ghc", defaultOptions{gcHLSNoGHC = True})
, ("gc -c", defaultOptions{gcCache = True})
, ("gc --cache", defaultOptions{gcCache = True})
, ("gc -t", defaultOptions{gcTmp = True})
, ("gc --tmpdirs", defaultOptions{gcTmp = True})
, ("gc -o -p -s -h -c -t", GCOptions True True True True True True)
]
gcParseWith :: [String] -> IO GCOptions
gcParseWith args = do
GC a <- parseWith args
pure a

View File

@@ -0,0 +1,203 @@
{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
module InstallTest where
import Test.Tasty
import GHCup.OptParse hiding (HLSCompileOptions(isolateDir))
import Utils
import GHCup.Types
import Data.Versions
import Data.List.NonEmpty (NonEmpty ((:|)))
import GHCup.OptParse.Install as Install
import URI.ByteString.QQ
-- Some interests:
-- install ghc *won't* select `set as activate version` as default
-- install cabal *will* select `set as activate version` as default
-- install hls *will* select `set as activate version` as default
-- install stack *will* select `set as activate version` as default
installTests :: TestTree
installTests = testGroup "install"
$ map
(buildTestTree installParseWith)
[ ("old-style", oldStyleCheckList)
, ("ghc", installGhcCheckList)
, ("cabal", installCabalCheckList)
, ("hls", installHlsCheckList)
, ("stack", installStackCheckList)
]
defaultOptions :: InstallOptions
defaultOptions = InstallOptions Nothing Nothing False Nothing False []
-- | Don't set as active version
mkInstallOptions :: ToolVersion -> InstallOptions
mkInstallOptions ver = InstallOptions (Just ver) Nothing False Nothing False []
-- | Set as active version
mkInstallOptions' :: ToolVersion -> InstallOptions
mkInstallOptions' ver = InstallOptions (Just ver) Nothing True Nothing False []
oldStyleCheckList :: [(String, Either InstallCommand InstallOptions)]
oldStyleCheckList =
("install", Right defaultOptions)
: ("install --set", Right defaultOptions{instSet = True})
: ("install --force", Right defaultOptions{forceInstall = True})
#ifdef IS_WINDOWS
: ("install -i C:\\\\", Right defaultOptions{Install.isolateDir = Just "C:\\\\"})
#else
: ("install -i /", Right defaultOptions{Install.isolateDir = Just "/"})
#endif
: ("install -u https://gitlab.haskell.org/ghc/ghc/-/jobs/artifacts/master/raw/ghc-x86_64-linux-fedora33-release.tar.xz head"
, Right defaultOptions
{ instBindist = Just [uri|https://gitlab.haskell.org/ghc/ghc/-/jobs/artifacts/master/raw/ghc-x86_64-linux-fedora33-release.tar.xz|]
, instVer = Just $ GHCVersion $ GHCTargetVersion Nothing $(versionQ "head")
}
)
: mapSecond
(Right . mkInstallOptions)
[ ("install ghc-9.2", GHCVersion
$ GHCTargetVersion
(Just "ghc")
$(versionQ "9.2")
)
-- invalid
, ("install next", GHCVersion
$ GHCTargetVersion
Nothing
$(versionQ "next")
)
, ("install latest", ToolTag Latest)
, ("install nightly", GHCVersion
$ GHCTargetVersion
Nothing
$(versionQ "nightly")
)
, ("install recommended", ToolTag Recommended)
, ("install prerelease", GHCVersion
$ GHCTargetVersion
Nothing
$(versionQ "prerelease")
)
, ("install latest-prerelease", ToolTag LatestPrerelease)
, ("install latest-nightly", ToolTag LatestNightly)
, ("install ghc-javascript-unknown-ghcjs-9.6", GHCVersion
$ GHCTargetVersion
(Just "ghc-javascript-unknown-ghcjs")
$(versionQ "9.6")
)
, ("install base-4.18", ToolTag (Base (PVP {_pComponents = 4 :| [18]})))
, ("install cabal-3.10", GHCVersion
$ GHCTargetVersion
(Just "cabal")
$(versionQ "3.10")
)
, ("install hls-2.0.0.0", GHCVersion
$ GHCTargetVersion
(Just "hls")
$(versionQ "2.0.0.0")
)
, ("install stack-2.9.3", GHCVersion
$ GHCTargetVersion
(Just "stack")
$(versionQ "2.9.3")
)
]
installGhcCheckList :: [(String, Either InstallCommand InstallOptions)]
installGhcCheckList =
("install ghc", Left $ InstallGHC defaultOptions)
: mapSecond (Left . InstallGHC . mkInstallOptions)
[ ("install ghc 9.2", GHCVersion
$ GHCTargetVersion
Nothing
$(versionQ "9.2")
)
, ("install ghc next", GHCVersion
$ GHCTargetVersion
Nothing
$(versionQ "next")
)
, ("install ghc latest", ToolTag Latest)
, ("install ghc nightly", GHCVersion
$ GHCTargetVersion
Nothing
$(versionQ "nightly")
)
, ("install ghc recommended", ToolTag Recommended)
, ("install ghc prerelease", GHCVersion
$ GHCTargetVersion
Nothing
$(versionQ "prerelease")
)
, ("install ghc latest-prerelease", ToolTag LatestPrerelease)
, ("install ghc latest-nightly", ToolTag LatestNightly)
, ("install ghc javascript-unknown-ghcjs-9.6", GHCVersion
$ GHCTargetVersion
(Just "javascript-unknown-ghcjs")
$(versionQ "9.6")
)
, ("install ghc base-4.18", ToolTag (Base (PVP {_pComponents = 4 :| [18]})))
, ("install ghc ghc-9.2", GHCVersion
$ GHCTargetVersion
(Just "ghc")
$(versionQ "9.2")
)
]
installCabalCheckList :: [(String, Either InstallCommand InstallOptions)]
installCabalCheckList =
("install cabal", Left $ InstallCabal defaultOptions{instSet = True})
: mapSecond (Left . InstallCabal . mkInstallOptions')
[ ("install cabal 3.10", ToolVersion $(versionQ "3.10"))
, ("install cabal next", ToolVersion $(versionQ "next"))
, ("install cabal latest", ToolTag Latest)
, ("install cabal nightly", ToolVersion $(versionQ "nightly"))
, ("install cabal recommended", ToolTag Recommended)
, ("install cabal prerelease", ToolVersion $(versionQ "prerelease"))
, ("install cabal latest-prerelease", ToolTag LatestPrerelease)
, ("install cabal latest-nightly", ToolTag LatestNightly)
, ("install cabal base-4.18", ToolTag (Base (PVP {_pComponents = 4 :| [18]})))
, ("install cabal cabal-3.10", ToolVersion $(versionQ "cabal-3.10"))
]
installHlsCheckList :: [(String, Either InstallCommand InstallOptions)]
installHlsCheckList =
("install hls", Left $ InstallHLS defaultOptions{instSet = True})
: mapSecond (Left . InstallHLS . mkInstallOptions')
[ ("install hls 3.10", ToolVersion $(versionQ "3.10"))
, ("install hls next", ToolVersion $(versionQ "next"))
, ("install hls latest", ToolTag Latest)
, ("install hls nightly", ToolVersion $(versionQ "nightly"))
, ("install hls recommended", ToolTag Recommended)
, ("install hls prerelease", ToolVersion $(versionQ "prerelease"))
, ("install hls latest-prerelease", ToolTag LatestPrerelease)
, ("install hls latest-nightly", ToolTag LatestNightly)
, ("install hls base-4.18", ToolTag (Base (PVP {_pComponents = 4 :| [18]})))
, ("install hls hls-2.0", ToolVersion $(versionQ "hls-2.0"))
]
installStackCheckList :: [(String, Either InstallCommand InstallOptions)]
installStackCheckList =
("install stack", Left $ InstallStack defaultOptions{instSet = True})
: mapSecond (Left . InstallStack . mkInstallOptions')
[ ("install stack 3.10", ToolVersion $(versionQ "3.10"))
, ("install stack next", ToolVersion $(versionQ "next"))
, ("install stack latest", ToolTag Latest)
, ("install stack nightly", ToolVersion $(versionQ "nightly"))
, ("install stack recommended", ToolTag Recommended)
, ("install stack prerelease", ToolVersion $(versionQ "prerelease"))
, ("install stack latest-prerelease", ToolTag LatestPrerelease)
, ("install stack latest-nightly", ToolTag LatestNightly)
, ("install stack base-4.18", ToolTag (Base (PVP {_pComponents = 4 :| [18]})))
, ("install stack stack-2.9", ToolVersion $(versionQ "stack-2.9"))
]
installParseWith :: [String] -> IO (Either InstallCommand InstallOptions)
installParseWith args = do
Install a <- parseWith args
pure a

View File

@@ -0,0 +1,46 @@
module ListTest where
import Test.Tasty
import GHCup.OptParse
import Utils
import GHCup.List
import GHCup.Types
listTests :: TestTree
listTests = buildTestTree listParseWith ("list", listCheckList)
defaultOptions :: ListOptions
defaultOptions = ListOptions Nothing Nothing Nothing Nothing False False False
listCheckList :: [(String, ListOptions)]
listCheckList =
[ ("list", defaultOptions)
, ("list -t ghc", defaultOptions{loTool = Just GHC})
, ("list -t cabal", defaultOptions{loTool = Just Cabal})
, ("list -t hls", defaultOptions{loTool = Just HLS})
, ("list -t stack", defaultOptions{loTool = Just Stack})
, ("list -c installed", defaultOptions{lCriteria = Just $ ListInstalled True})
, ("list -c +installed", defaultOptions{lCriteria = Just $ ListInstalled True})
, ("list -c -installed", defaultOptions{lCriteria = Just $ ListInstalled False})
, ("list -c set", defaultOptions{lCriteria = Just $ ListSet True})
, ("list -c +set", defaultOptions{lCriteria = Just $ ListSet True})
, ("list -c -set", defaultOptions{lCriteria = Just $ ListSet False})
, ("list -c available", defaultOptions{lCriteria = Just $ ListAvailable True})
, ("list -c +available", defaultOptions{lCriteria = Just $ ListAvailable True})
, ("list -c -available", defaultOptions{lCriteria = Just $ ListAvailable False})
, ("list -s 2023-07-22", defaultOptions{lFrom = Just $ read "2023-07-22"})
, ("list -u 2023-07-22", defaultOptions{lTo = Just $ read "2023-07-22"})
, ("list --since 2023-07-22 --until 2023-07-22", defaultOptions{lFrom = Just $ read "2023-07-22", lTo = Just $ read "2023-07-22"})
, ("list -o", defaultOptions{lHideOld = True})
, ("list --hide-old", defaultOptions{lHideOld = True})
, ("list -n", defaultOptions{lShowNightly = True})
, ("list --show-nightly", defaultOptions{lShowNightly = True})
, ("list -r", defaultOptions{lRawFormat = True})
, ("list --raw-format", defaultOptions{lRawFormat = True})
]
listParseWith :: [String] -> IO ListOptions
listParseWith args = do
List a <- parseWith args
pure a

View File

@@ -0,0 +1,33 @@
module Main where
import Test.Tasty
import qualified SetTest
import qualified OtherCommandTest
import qualified ChangeLogTest
import qualified ConfigTest
import qualified InstallTest
import qualified UnsetTest
import qualified RmTest
import qualified ListTest
import qualified UpgradeTest
import qualified CompileTest
import qualified WhereisTest
import qualified GCTest
import qualified RunTest
main :: IO ()
main = defaultMain $ testGroup "ghcup"
[ SetTest.setTests
, OtherCommandTest.otherCommandTests
, ChangeLogTest.changeLogTests
, ConfigTest.configTests
, InstallTest.installTests
, UnsetTest.unsetTests
, RmTest.rmTests
, ListTest.listTests
, UpgradeTest.upgradeTests
, CompileTest.compileTests
, WhereisTest.whereisTests
, GCTest.gcTests
, RunTest.runTests
]

View File

@@ -0,0 +1,38 @@
module OtherCommandTest where
import Test.Tasty
import Test.Tasty.HUnit
import GHCup.OptParse
import Utils
import Control.Monad.IO.Class
otherCommandTests :: TestTree
otherCommandTests = testGroup "other command"
[ testCase "debug-info" $ do
res <- parseWith ["debug-info"]
liftIO $ assertBool "debug-info parse failed" (isDInfo res)
, testCase "tool-requirements" $ do
ToolRequirements opt <- parseWith ["tool-requirements"]
liftIO $ tlrRaw opt @?= False
, testCase "tool-requirements -r" $ do
ToolRequirements opt <- parseWith ["tool-requirements", "--raw-format"]
liftIO $ tlrRaw opt @?= True
, testCase "nuke" $ do
res <- parseWith ["nuke"]
liftIO $ assertBool "nuke parse failed" (isNuke res)
, testCase "test ghc" $ do
res <- parseWith ["test", "ghc"]
liftIO $ assertBool "test parse failed" (isTest res)
]
isDInfo :: Command -> Bool
isDInfo DInfo = True
isDInfo _ = False
isNuke :: Command -> Bool
isNuke Nuke = True
isNuke _ = False
isTest :: Command -> Bool
isTest (Test _) = True
isTest _ = False

View File

@@ -0,0 +1,62 @@
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
module RmTest where
import Test.Tasty
import GHCup.OptParse
import Utils
import GHCup.Types
import Data.Versions
rmTests :: TestTree
rmTests =
testGroup "rm"
$ map (buildTestTree rmParseWith)
[ ("old-style", oldStyleCheckList)
, ("ghc", rmGhcCheckList)
, ("cabal", rmCabalCheckList)
, ("hls", rmHlsCheckList)
, ("stack", rmStackCheckList)
]
oldStyleCheckList :: [(String, Either RmCommand RmOptions)]
oldStyleCheckList = mapSecond (Right . RmOptions)
[ -- failed with ("rm", xxx)
("rm 9.2.8", mkTVer $(versionQ "9.2.8"))
, ("rm ghc-9.2.8", GHCTargetVersion (Just "ghc") $(versionQ "9.2.8"))
]
rmGhcCheckList :: [(String, Either RmCommand RmOptions)]
rmGhcCheckList = mapSecond (Left . RmGHC . RmOptions)
[ -- failed with ("rm ghc", xxx)
("rm ghc 9.2.8", mkTVer $(versionQ "9.2.8"))
, ("rm ghc ghc-9.2.8", GHCTargetVersion (Just "ghc") $(versionQ "9.2.8"))
]
rmCabalCheckList :: [(String, Either RmCommand RmOptions)]
rmCabalCheckList = mapSecond (Left . RmCabal)
[ -- failed with ("rm cabal", xxx)
("rm cabal 3.10", $(versionQ "3.10"))
, ("rm cabal cabal-3.10", $(versionQ "cabal-3.10"))
]
rmHlsCheckList :: [(String, Either RmCommand RmOptions)]
rmHlsCheckList = mapSecond (Left . RmHLS)
[ -- failed with ("rm hls", xxx)
("rm hls 2.0", $(versionQ "2.0"))
, ("rm hls hls-2.0", $(versionQ "hls-2.0"))
]
rmStackCheckList :: [(String, Either RmCommand RmOptions)]
rmStackCheckList = mapSecond (Left . RmStack)
[ -- failed with ("rm stack", xxx)
("rm stack 2.9.1", $(versionQ "2.9.1"))
, ("rm stack stack-2.9.1", $(versionQ "stack-2.9.1"))
]
rmParseWith :: [String] -> IO (Either RmCommand RmOptions)
rmParseWith args = do
Rm a <- parseWith args
pure a

View File

@@ -0,0 +1,68 @@
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE TemplateHaskell #-}
module RunTest where
import Test.Tasty
import GHCup.OptParse
import Utils
import GHCup.Types
import Data.Versions (versionQ)
runTests :: TestTree
runTests = buildTestTree runParseWith ("run", runCheckList)
defaultOptions :: RunOptions
defaultOptions =
RunOptions
False
False
False
Nothing
Nothing
Nothing
Nothing
Nothing
False
[]
runCheckList :: [(String, RunOptions)]
runCheckList =
[ ("run", defaultOptions)
, ("run -a", defaultOptions{runAppendPATH = True})
, ("run --append", defaultOptions{runAppendPATH = True})
, ("run -i", defaultOptions{runInstTool' = True})
, ("run --install", defaultOptions{runInstTool' = True})
, ("run -m", defaultOptions{runMinGWPath = True})
, ("run --mingw-path", defaultOptions{runMinGWPath = True})
, ("run --ghc 9.2.8", defaultOptions{runGHCVer = Just $ GHCVersion $ mkTVer $(versionQ "9.2.8")})
, ("run --ghc latest", defaultOptions{runGHCVer = Just $ ToolTag Latest})
, ("run --cabal 3.10", defaultOptions{runCabalVer = Just $ ToolVersion $(versionQ "3.10")})
, ("run --hls 2.0", defaultOptions{runHLSVer = Just $ ToolVersion $(versionQ "2.0")})
, ("run --stack 2.9", defaultOptions{runStackVer = Just $ ToolVersion $(versionQ "2.9") })
#ifdef IS_WINDOWS
, ("run -b C:\\\\tmp\\dir", defaultOptions{runBinDir = Just "C:\\\\tmp\\dir"})
, ("run --bindir C:\\\\tmp\\dir", defaultOptions{runBinDir = Just "C:\\\\tmp\\dir"})
#else
, ("run -b /tmp/dir", defaultOptions{runBinDir = Just "/tmp/dir"})
, ("run --bindir /tmp/dir", defaultOptions{runBinDir = Just "/tmp/dir"})
#endif
, ("run -q", defaultOptions{runQuick = True})
, ("run --quick", defaultOptions{runQuick = True})
, ("run --ghc latest --cabal 3.10 --stack 2.9 --hls 2.0 --install",
defaultOptions
{ runGHCVer = Just $ ToolTag Latest
, runCabalVer = Just $ ToolVersion $(versionQ "3.10")
, runHLSVer = Just $ ToolVersion $(versionQ "2.0")
, runStackVer = Just $ ToolVersion $(versionQ "2.9")
, runInstTool' = True
}
)
]
runParseWith :: [String] -> IO RunOptions
runParseWith args = do
Run a <- parseWith args
pure a

View File

@@ -0,0 +1,156 @@
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
module SetTest where
import GHCup.OptParse
import Test.Tasty
import GHCup.Types
import Data.Versions
import Data.List.NonEmpty (NonEmpty ((:|)))
import Utils
setTests :: TestTree
setTests =
testGroup "set"
$ map
(buildTestTree setParseWith)
[ ("old-style", oldStyleCheckList)
, ("ghc", setGhcCheckList)
, ("cabal", setCabalCheckList)
, ("hls", setHlsCheckList)
, ("stack", setStackCheckList)
]
oldStyleCheckList :: [(String, Either SetCommand SetOptions)]
oldStyleCheckList = mapSecond (Right . SetOptions)
[ ("set", SetRecommended)
, ("set ghc-9.2", SetGHCVersion
$ GHCTargetVersion
(Just "ghc")
$(versionQ "9.2")
)
, ("set next", SetNext)
, ("set latest", SetToolTag Latest)
, ("set nightly", SetGHCVersion
$ GHCTargetVersion
Nothing
$(versionQ "nightly")
)
-- different from `set`
, ("set recommended", SetToolTag Recommended)
, ("set prerelease", SetGHCVersion
$ GHCTargetVersion
Nothing
$(versionQ "prerelease")
)
, ("set latest-prerelease", SetToolTag LatestPrerelease)
, ("set latest-nightly", SetToolTag LatestNightly)
, ("set ghc-javascript-unknown-ghcjs-9.6", SetGHCVersion
$ GHCTargetVersion
(Just "ghc-javascript-unknown-ghcjs")
$(versionQ "9.6")
)
, ("set base-4.18", SetToolTag (Base (PVP {_pComponents = 4 :| [18]})))
, ("set cabal-3.10", SetGHCVersion
$ GHCTargetVersion
(Just "cabal")
$(versionQ "3.10")
)
, ("set hls-2.0.0.0", SetGHCVersion
$ GHCTargetVersion
(Just "hls")
$(versionQ "2.0.0.0")
)
, ("set stack-2.9.3", SetGHCVersion
$ GHCTargetVersion
(Just "stack")
$(versionQ "2.9.3")
)
]
setGhcCheckList :: [(String, Either SetCommand SetOptions)]
setGhcCheckList = mapSecond (Left . SetGHC . SetOptions)
[ ("set ghc", SetRecommended)
, ("set ghc 9.2", SetGHCVersion
$ GHCTargetVersion
Nothing
$(versionQ "9.2")
)
, ("set ghc next", SetNext)
, ("set ghc latest", SetToolTag Latest)
, ("set ghc nightly", SetGHCVersion
$ GHCTargetVersion
Nothing
$(versionQ "nightly")
)
, ("set ghc recommended", SetToolTag Recommended)
, ("set ghc prerelease", SetGHCVersion
$ GHCTargetVersion
Nothing
$(versionQ "prerelease")
)
, ("set ghc latest-prerelease", SetToolTag LatestPrerelease)
, ("set ghc latest-nightly", SetToolTag LatestNightly)
, ("set ghc javascript-unknown-ghcjs-9.6", SetGHCVersion
$ GHCTargetVersion
(Just "javascript-unknown-ghcjs")
$(versionQ "9.6")
)
, ("set ghc base-4.18", SetToolTag (Base (PVP {_pComponents = 4 :| [18]})))
, ("set ghc ghc-9.2", SetGHCVersion
$ GHCTargetVersion
(Just "ghc")
$(versionQ "9.2")
)
]
setCabalCheckList :: [(String, Either SetCommand SetOptions)]
setCabalCheckList = mapSecond (Left . SetCabal . SetOptions)
[ ("set cabal", SetRecommended)
, ("set cabal 3.10", SetToolVersion $(versionQ "3.10"))
, ("set cabal next", SetNext)
, ("set cabal latest", SetToolTag Latest)
, ("set cabal nightly", SetToolVersion $(versionQ "nightly"))
, ("set cabal recommended", SetToolTag Recommended)
, ("set cabal prerelease", SetToolVersion $(versionQ "prerelease"))
, ("set cabal latest-prerelease", SetToolTag LatestPrerelease)
, ("set cabal latest-nightly", SetToolTag LatestNightly)
, ("set cabal base-4.18", SetToolTag (Base (PVP {_pComponents = 4 :| [18]})))
, ("set cabal cabal-3.10", SetToolVersion $(versionQ "cabal-3.10"))
]
setHlsCheckList :: [(String, Either SetCommand SetOptions)]
setHlsCheckList = mapSecond (Left . SetHLS . SetOptions)
[ ("set hls", SetRecommended)
, ("set hls 2.0", SetToolVersion $(versionQ "2.0"))
, ("set hls next", SetNext)
, ("set hls latest", SetToolTag Latest)
, ("set hls nightly", SetToolVersion $(versionQ "nightly"))
, ("set hls recommended", SetToolTag Recommended)
, ("set hls prerelease", SetToolVersion $(versionQ "prerelease"))
, ("set hls latest-prerelease", SetToolTag LatestPrerelease)
, ("set hls latest-nightly", SetToolTag LatestNightly)
, ("set hls base-4.18", SetToolTag (Base (PVP {_pComponents = 4 :| [18]})))
, ("set hls hls-2.0", SetToolVersion $(versionQ "hls-2.0"))
]
setStackCheckList :: [(String, Either SetCommand SetOptions)]
setStackCheckList = mapSecond (Left . SetStack . SetOptions)
[ ("set stack", SetRecommended)
, ("set stack 2.9", SetToolVersion $(versionQ "2.9"))
, ("set stack next", SetNext)
, ("set stack latest", SetToolTag Latest)
, ("set stack nightly", SetToolVersion $(versionQ "nightly"))
, ("set stack recommended", SetToolTag Recommended)
, ("set stack prerelease", SetToolVersion $(versionQ "prerelease"))
, ("set stack latest-prerelease", SetToolTag LatestPrerelease)
, ("set stack latest-nightly", SetToolTag LatestNightly)
, ("set stack base-4.18", SetToolTag (Base (PVP {_pComponents = 4 :| [18]})))
, ("set stack stack-2.9", SetToolVersion $(versionQ "stack-2.9"))
]
setParseWith :: [String] -> IO (Either SetCommand SetOptions)
setParseWith args = do
Set a <- parseWith args
pure a

View File

@@ -0,0 +1,50 @@
{-# LANGUAGE OverloadedStrings #-}
module UnsetTest where
import Test.Tasty
import GHCup.OptParse
import Utils
unsetTests :: TestTree
unsetTests =
testGroup "unset"
$ map (buildTestTree unsetParseWith)
[ ("ghc", unsetGhcCheckList)
, ("cabal", unsetCabalCheckList)
, ("hls", unsetHlsCheckList)
, ("stack", unsetStackCheckList)
]
unsetGhcCheckList :: [(String, UnsetCommand)]
unsetGhcCheckList = mapSecond (UnsetGHC . UnsetOptions)
[ ("unset ghc", Nothing)
, ("unset ghc armv7-unknown-linux-gnueabihf", Just "armv7-unknown-linux-gnueabihf")
]
unsetCabalCheckList :: [(String, UnsetCommand)]
unsetCabalCheckList = mapSecond (UnsetCabal . UnsetOptions)
[ ("unset cabal", Nothing)
-- This never used
, ("unset cabal armv7-unknown-linux-gnueabihf", Just "armv7-unknown-linux-gnueabihf")
]
unsetHlsCheckList :: [(String, UnsetCommand)]
unsetHlsCheckList = mapSecond (UnsetHLS . UnsetOptions)
[ ("unset hls", Nothing)
-- This never used
, ("unset hls armv7-unknown-linux-gnueabihf", Just "armv7-unknown-linux-gnueabihf")
]
unsetStackCheckList :: [(String, UnsetCommand)]
unsetStackCheckList = mapSecond (UnsetStack . UnsetOptions)
[ ("unset stack", Nothing)
-- This never used
, ("unset stack armv7-unknown-linux-gnueabihf", Just "armv7-unknown-linux-gnueabihf")
]
unsetParseWith :: [String] -> IO UnsetCommand
unsetParseWith args = do
UnSet a <- parseWith args
pure a

View File

@@ -0,0 +1,38 @@
{-# LANGUAGE TupleSections #-}
module UpgradeTest where
import Test.Tasty
import GHCup.OptParse
import Utils
upgradeTests :: TestTree
upgradeTests = buildTestTree upgradeParseWith ("upgrade", upgradeCheckList)
type FullUpgradeOpts =
( UpgradeOpts
, Bool -- ^Force update
, Bool -- ^Fails after upgrading if the upgraded ghcup binary is shadowed by something else in PATH (useful for CI)
)
mkDefaultOptions :: UpgradeOpts -> FullUpgradeOpts
mkDefaultOptions = (, False, False)
upgradeCheckList :: [(String, FullUpgradeOpts)]
upgradeCheckList =
[ ("upgrade", mkDefaultOptions UpgradeGHCupDir)
, ("upgrade -f", (UpgradeGHCupDir, True, False))
, ("upgrade --force", (UpgradeGHCupDir, True, False))
, ("upgrade --fail-if-shadowed", (UpgradeGHCupDir, False, True))
, ("upgrade -i", mkDefaultOptions UpgradeInplace)
, ("upgrade --inplace", mkDefaultOptions UpgradeInplace)
, ("upgrade -t ~", mkDefaultOptions $ UpgradeAt "~")
, ("upgrade --target ~", mkDefaultOptions $ UpgradeAt "~")
, ("upgrade -t ~ -f", (UpgradeAt "~", True, False))
]
upgradeParseWith :: [String] -> IO FullUpgradeOpts
upgradeParseWith args = do
Upgrade a b c <- parseWith args
pure (a, b, c)

View File

@@ -0,0 +1,34 @@
{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}
module Utils where
import GHCup.OptParse as GHCup
import Options.Applicative
import Data.Bifunctor
import Test.Tasty
import Test.Tasty.HUnit
import Control.Monad.IO.Class
parseWith :: [String] -> IO Command
parseWith args =
optCommand <$> handleParseResult
(execParserPure defaultPrefs (info GHCup.opts fullDesc) args)
padLeft :: Int -> String -> String
padLeft desiredLength s = padding ++ s
where padding = replicate (desiredLength - length s) ' '
mapSecond :: (b -> c) -> [(a,b)] -> [(a,c)]
mapSecond = map . second
buildTestTree
:: (Eq a, Show a)
=> ([String] -> IO a) -- ^ The parse function
-> (String, [(String, a)]) -- ^ The check list @(test group, [(cli command, expected value)])@
-> TestTree
buildTestTree parse (title, checkList) =
testGroup title
$ zipWith (uncurry . check) [1 :: Int ..] checkList
where
check idx args expected = testCase (padLeft 2 (show idx) ++ "." ++ args) $ do
res <- parse (words args)
liftIO $ res @?= expected

View File

@@ -0,0 +1,42 @@
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
module WhereisTest where
import Test.Tasty
import GHCup.OptParse
import Utils
import GHCup.Types
import Data.Versions (versionQ)
whereisTests :: TestTree
whereisTests = buildTestTree whereisParseWith ("whereis", whereisCheckList)
whereisCheckList :: [(String, (WhereisOptions, WhereisCommand))]
whereisCheckList = concatMap mk
[ ("whereis ghc", WhereisTool GHC Nothing)
, ("whereis ghc 9.2.8", WhereisTool GHC (Just $ GHCVersion $ mkTVer $(versionQ "9.2.8")))
, ("whereis ghc ghc-9.2.8", WhereisTool GHC (Just $ GHCVersion $ GHCTargetVersion (Just "ghc") $(versionQ "9.2.8")))
, ("whereis ghc latest", WhereisTool GHC (Just $ ToolTag Latest))
, ("whereis cabal", WhereisTool Cabal Nothing)
, ("whereis hls", WhereisTool HLS Nothing)
, ("whereis stack", WhereisTool Stack Nothing)
, ("whereis ghcup", WhereisTool GHCup Nothing)
, ("whereis basedir", WhereisBaseDir)
, ("whereis bindir", WhereisBinDir)
, ("whereis cachedir", WhereisCacheDir)
, ("whereis logsdir", WhereisLogsDir)
, ("whereis confdir", WhereisConfDir)
]
where
mk :: (String, WhereisCommand) -> [(String, (WhereisOptions, WhereisCommand))]
mk (cmd, res) =
[ (cmd, (WhereisOptions False, res))
, (cmd <> " -d", (WhereisOptions True, res))
, (cmd <> " --directory", (WhereisOptions True, res))
]
whereisParseWith :: [String] -> IO (WhereisOptions, WhereisCommand)
whereisParseWith args = do
Whereis a b <- parseWith args
pure (a, b)