Compare commits
3 Commits
improve-pw
...
rename
| Author | SHA1 | Date | |
|---|---|---|---|
|
e9db8f9895
|
|||
|
7f542646dd
|
|||
|
34910f853b
|
@@ -15,9 +15,6 @@ variables:
|
|||||||
# Bump to invalidate GitLab CI cache.
|
# Bump to invalidate GitLab CI cache.
|
||||||
CACHE_REV: 0
|
CACHE_REV: 0
|
||||||
|
|
||||||
GIT_SUBMODULE_STRATEGY: recursive
|
|
||||||
|
|
||||||
|
|
||||||
############################################################
|
############################################################
|
||||||
# CI Step
|
# CI Step
|
||||||
############################################################
|
############################################################
|
||||||
@@ -118,7 +115,7 @@ variables:
|
|||||||
script:
|
script:
|
||||||
- bash ./.gitlab/script/ghcup_version.sh
|
- bash ./.gitlab/script/ghcup_version.sh
|
||||||
variables:
|
variables:
|
||||||
JSON_VERSION: "0.0.7"
|
JSON_VERSION: "0.0.6"
|
||||||
artifacts:
|
artifacts:
|
||||||
expire_in: 2 week
|
expire_in: 2 week
|
||||||
paths:
|
paths:
|
||||||
@@ -185,12 +182,12 @@ variables:
|
|||||||
- export HOMEBREW_CHANGE_ARCH_TO_ARM=1
|
- export HOMEBREW_CHANGE_ARCH_TO_ARM=1
|
||||||
|
|
||||||
# make sure to not pollute the machine with temp files etc
|
# make sure to not pollute the machine with temp files etc
|
||||||
- mkdir -p $CI_PROJECT_DIR/.brew_cache
|
- mkdir -p $CI_PROJECT_DIR/.bc
|
||||||
- export HOMEBREW_CACHE=$CI_PROJECT_DIR/.brew_cache
|
- export HOMEBREW_CACHE=$CI_PROJECT_DIR/.bc
|
||||||
- mkdir -p $CI_PROJECT_DIR/.brew_logs
|
- mkdir -p $CI_PROJECT_DIR/.bl
|
||||||
- export HOMEBREW_LOGS=$CI_PROJECT_DIR/.brew_logs
|
- export HOMEBREW_LOGS=$CI_PROJECT_DIR/.bl
|
||||||
- mkdir -p /private/tmp/.brew_tmp
|
- mkdir -p $CI_PROJECT_DIR/.bt
|
||||||
- export HOMEBREW_TEMP=/private/tmp/.brew_tmp
|
- export HOMEBREW_TEMP=$CI_PROJECT_DIR/.bt
|
||||||
|
|
||||||
# update and install packages
|
# update and install packages
|
||||||
- brew update
|
- brew update
|
||||||
@@ -220,9 +217,6 @@ variables:
|
|||||||
- .freebsd13
|
- .freebsd13
|
||||||
- .root_cleanup
|
- .root_cleanup
|
||||||
before_script:
|
before_script:
|
||||||
- sudo pkg update
|
|
||||||
- sudo pkg install --yes compat12x-amd64
|
|
||||||
- sudo ln -s libncurses.so.6 /usr/local/lib/libncurses.so.6.2
|
|
||||||
- ./.gitlab/before_script/freebsd/install_deps.sh
|
- ./.gitlab/before_script/freebsd/install_deps.sh
|
||||||
|
|
||||||
.test_ghcup_version:windows:
|
.test_ghcup_version:windows:
|
||||||
@@ -251,7 +245,7 @@ variables:
|
|||||||
only:
|
only:
|
||||||
- tags
|
- tags
|
||||||
variables:
|
variables:
|
||||||
JSON_VERSION: "0.0.7"
|
JSON_VERSION: "0.0.6"
|
||||||
|
|
||||||
######## stack test ########
|
######## stack test ########
|
||||||
|
|
||||||
@@ -547,12 +541,12 @@ release:darwin:aarch64:
|
|||||||
- export HOMEBREW_CHANGE_ARCH_TO_ARM=1
|
- export HOMEBREW_CHANGE_ARCH_TO_ARM=1
|
||||||
|
|
||||||
# make sure to not pollute the machine with temp files etc
|
# make sure to not pollute the machine with temp files etc
|
||||||
- mkdir -p $CI_PROJECT_DIR/.brew_cache
|
- mkdir -p $CI_PROJECT_DIR/.bc
|
||||||
- export HOMEBREW_CACHE=$CI_PROJECT_DIR/.brew_cache
|
- export HOMEBREW_CACHE=$CI_PROJECT_DIR/.bc
|
||||||
- mkdir -p $CI_PROJECT_DIR/.brew_logs
|
- mkdir -p $CI_PROJECT_DIR/.bl
|
||||||
- export HOMEBREW_LOGS=$CI_PROJECT_DIR/.brew_logs
|
- export HOMEBREW_LOGS=$CI_PROJECT_DIR/.bl
|
||||||
- mkdir -p /private/tmp/.brew_tmp
|
- mkdir -p $CI_PROJECT_DIR/.bt
|
||||||
- export HOMEBREW_TEMP=/private/tmp/.brew_tmp
|
- export HOMEBREW_TEMP=$CI_PROJECT_DIR/.bt
|
||||||
|
|
||||||
# update and install packages
|
# update and install packages
|
||||||
- brew update
|
- brew update
|
||||||
@@ -601,9 +595,6 @@ release:freebsd13:
|
|||||||
- .release_ghcup
|
- .release_ghcup
|
||||||
- .root_cleanup
|
- .root_cleanup
|
||||||
before_script:
|
before_script:
|
||||||
- sudo pkg update
|
|
||||||
- sudo pkg install --yes compat12x-amd64
|
|
||||||
- sudo ln -s libncurses.so.6 /usr/local/lib/libncurses.so.6.2
|
|
||||||
- ./.gitlab/before_script/freebsd/install_deps.sh
|
- ./.gitlab/before_script/freebsd/install_deps.sh
|
||||||
variables:
|
variables:
|
||||||
ARTIFACT: "x86_64-portbld-freebsd-ghcup"
|
ARTIFACT: "x86_64-portbld-freebsd-ghcup"
|
||||||
|
|||||||
@@ -12,8 +12,4 @@ if [ "${OS}" = "WINDOWS" ] ; then
|
|||||||
rm -Rf /c/ghcup
|
rm -Rf /c/ghcup
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "${OS}" = "DARWIN" ] ; then
|
|
||||||
rm -Rf /private/tmp/.brew_tmp
|
|
||||||
fi
|
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
@@ -8,15 +8,7 @@ set -eux
|
|||||||
|
|
||||||
mkdir -p "${TMPDIR}"
|
mkdir -p "${TMPDIR}"
|
||||||
|
|
||||||
if freebsd-version | grep -E '^12.*' ; then
|
curl -sSfL https://downloads.haskell.org/~ghcup/x86_64-portbld-freebsd-ghcup > ./ghcup-bin
|
||||||
freebsd_ver=12
|
|
||||||
elif freebsd-version | grep -E '^13.*' ; then
|
|
||||||
freebsd_ver=13
|
|
||||||
else
|
|
||||||
(>&2 echo "Unsupported FreeBSD version! Please report a bug at https://gitlab.haskell.org/haskell/ghcup-hs/-/issues")
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
curl -sSfL https://downloads.haskell.org/~ghcup/x86_64-freebsd${freebsd_ver}-ghcup > ./ghcup-bin
|
|
||||||
chmod +x ghcup-bin
|
chmod +x ghcup-bin
|
||||||
|
|
||||||
./ghcup-bin -v upgrade -i -f
|
./ghcup-bin -v upgrade -i -f
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
.
|
|
||||||
./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
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
.
|
|
||||||
./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
|
|
||||||
@@ -5,6 +5,8 @@ set -eux
|
|||||||
. "$( cd "$(dirname "$0")" ; pwd -P )/../ghcup_env"
|
. "$( cd "$(dirname "$0")" ; pwd -P )/../ghcup_env"
|
||||||
|
|
||||||
mkdir -p "$CI_PROJECT_DIR"/.local/bin
|
mkdir -p "$CI_PROJECT_DIR"/.local/bin
|
||||||
|
mkdir -p data/
|
||||||
|
git clone https://github.com/haskell/ghcup-metadata.git data/metadata
|
||||||
|
|
||||||
CI_PROJECT_DIR=$(pwd)
|
CI_PROJECT_DIR=$(pwd)
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ set -eux
|
|||||||
. "$( cd "$(dirname "$0")" ; pwd -P )/../ghcup_env"
|
. "$( cd "$(dirname "$0")" ; pwd -P )/../ghcup_env"
|
||||||
|
|
||||||
mkdir -p "$CI_PROJECT_DIR"/.local/bin
|
mkdir -p "$CI_PROJECT_DIR"/.local/bin
|
||||||
|
mkdir -p data/
|
||||||
|
git clone https://github.com/haskell/ghcup-metadata.git data/metadata
|
||||||
|
|
||||||
CI_PROJECT_DIR=$(pwd)
|
CI_PROJECT_DIR=$(pwd)
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ set -eux
|
|||||||
. "$( cd "$(dirname "$0")" ; pwd -P )/../ghcup_env"
|
. "$( cd "$(dirname "$0")" ; pwd -P )/../ghcup_env"
|
||||||
|
|
||||||
mkdir -p "$CI_PROJECT_DIR"/.local/bin
|
mkdir -p "$CI_PROJECT_DIR"/.local/bin
|
||||||
|
mkdir -p data/
|
||||||
|
git clone https://github.com/haskell/ghcup-metadata.git data/metadata
|
||||||
|
|
||||||
CI_PROJECT_DIR=$(pwd)
|
CI_PROJECT_DIR=$(pwd)
|
||||||
|
|
||||||
@@ -41,7 +43,7 @@ cabal --version
|
|||||||
|
|
||||||
eghcup debug-info
|
eghcup debug-info
|
||||||
|
|
||||||
eghcup compile hls -j $(nproc) -v ${HLS_TARGET_VERSION} --ghc ${GHC_VERSION}
|
eghcup compile hls -j $(nproc) -v ${HLS_TARGET_VERSION} ${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}" ]
|
[ `$(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}" ]
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ set -eux
|
|||||||
. "$( cd "$(dirname "$0")" ; pwd -P )/../ghcup_env"
|
. "$( cd "$(dirname "$0")" ; pwd -P )/../ghcup_env"
|
||||||
|
|
||||||
mkdir -p "$CI_PROJECT_DIR"/.local/bin
|
mkdir -p "$CI_PROJECT_DIR"/.local/bin
|
||||||
|
mkdir -p data/
|
||||||
|
git clone https://github.com/haskell/ghcup-metadata.git data/metadata
|
||||||
|
|
||||||
CI_PROJECT_DIR=$(pwd)
|
CI_PROJECT_DIR=$(pwd)
|
||||||
|
|
||||||
@@ -95,7 +97,6 @@ eghcup --numeric-version
|
|||||||
|
|
||||||
eghcup install ghc ${GHC_VERSION}
|
eghcup install 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 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}" ]
|
||||||
@@ -103,22 +104,6 @@ eghcup unset cabal
|
|||||||
"$GHCUP_BIN"/cabal --version && exit || echo yes
|
"$GHCUP_BIN"/cabal --version && exit || echo yes
|
||||||
eghcup set cabal ${CABAL_VERSION}
|
eghcup set cabal ${CABAL_VERSION}
|
||||||
[ `$(eghcup whereis cabal ${CABAL_VERSION}) --numeric-version` = "${CABAL_VERSION}" ]
|
[ `$(eghcup whereis cabal ${CABAL_VERSION}) --numeric-version` = "${CABAL_VERSION}" ]
|
||||||
[ `eghcup run --cabal ${CABAL_VERSION} -- cabal --numeric-version` = "${CABAL_VERSION}" ]
|
|
||||||
|
|
||||||
if [ "${OS}" != "FREEBSD" ] ; then
|
|
||||||
if [ "${ARCH}" = "64" ] ; 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
|
|
||||||
expected=$(cat "$( cd "$(dirname "$0")" ; pwd -P )/../ghcup-run.files.windows" | sort)
|
|
||||||
else
|
|
||||||
expected=$(cat "$( cd "$(dirname "$0")" ; pwd -P )/../ghcup-run.files" | sort)
|
|
||||||
fi
|
|
||||||
actual=$(cd ".bin" && find . | sort)
|
|
||||||
[ "${actual}" = "${expected}" ]
|
|
||||||
unset actual expected
|
|
||||||
rm -rf .bin
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
cabal --version
|
cabal --version
|
||||||
|
|
||||||
@@ -148,7 +133,7 @@ else
|
|||||||
eghcup --offline install ghc 8.10.3
|
eghcup --offline install ghc 8.10.3
|
||||||
if [ "${ARCH}" = "64" ] ; then
|
if [ "${ARCH}" = "64" ] ; then
|
||||||
expected=$(cat "$( cd "$(dirname "$0")" ; pwd -P )/../ghc-8.10.3-linux.files" | sort)
|
expected=$(cat "$( cd "$(dirname "$0")" ; pwd -P )/../ghc-8.10.3-linux.files" | sort)
|
||||||
actual=$(cd "${GHCUP_DIR}/ghc/8.10.3/" && find . | sort)
|
actual=$(cd "${GHCUP_DIR}/ghc/8.10.3/" && find | sort)
|
||||||
[ "${actual}" = "${expected}" ]
|
[ "${actual}" = "${expected}" ]
|
||||||
unset actual expected
|
unset actual expected
|
||||||
fi
|
fi
|
||||||
@@ -156,7 +141,7 @@ else
|
|||||||
eghcup prefetch ghc 8.10.3
|
eghcup prefetch ghc 8.10.3
|
||||||
eghcup --offline install ghc 8.10.3
|
eghcup --offline install ghc 8.10.3
|
||||||
expected=$(cat "$( cd "$(dirname "$0")" ; pwd -P )/../ghc-8.10.3-windows.files" | sort)
|
expected=$(cat "$( cd "$(dirname "$0")" ; pwd -P )/../ghc-8.10.3-windows.files" | sort)
|
||||||
actual=$(cd "${GHCUP_DIR}/ghc/8.10.3/" && find . | sort)
|
actual=$(cd "${GHCUP_DIR}/ghc/8.10.3/" && find | sort)
|
||||||
[ "${actual}" = "${expected}" ]
|
[ "${actual}" = "${expected}" ]
|
||||||
unset actual expected
|
unset actual expected
|
||||||
else
|
else
|
||||||
@@ -197,8 +182,6 @@ else
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# check that lazy loading works for 'whereis'
|
# 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"
|
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"
|
echo '**' > "$CI_PROJECT_DIR/data/metadata/ghcup-${JSON_VERSION}.yaml"
|
||||||
|
|||||||
4
.gitmodules
vendored
4
.gitmodules
vendored
@@ -1,4 +0,0 @@
|
|||||||
[submodule "data/metadata"]
|
|
||||||
path = data/metadata
|
|
||||||
url = https://github.com/haskell/ghcup-metadata.git
|
|
||||||
branch = master
|
|
||||||
38
CHANGELOG.md
38
CHANGELOG.md
@@ -1,43 +1,5 @@
|
|||||||
# Revision history for ghcup
|
# Revision history for ghcup
|
||||||
|
|
||||||
## 0.1.17.7 -- 2022-04-21
|
|
||||||
|
|
||||||
* Fix `ghcup run` on windows wrt [#345](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/345)
|
|
||||||
|
|
||||||
## 0.1.17.6 -- 2022-03-18
|
|
||||||
|
|
||||||
* Vastly improve shell completions wrt [#242](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/242)
|
|
||||||
* Fix 'ghcup install cabal/hls/stack --set' wrt [#324](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/324)
|
|
||||||
* Fix bad error message wrt [#323](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/323)
|
|
||||||
* Use predictable /tmp names for `ghcup run`, fixes [#329](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/329)
|
|
||||||
* Fix bug with isolated installation of not previously installed versions
|
|
||||||
* Add `--no-set` to install commands, fixes [#330](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/330)
|
|
||||||
* Fix serious bug in `ghcup list --raw-format -t <tool> -c installed`
|
|
||||||
* Overhaul metadata merging and add `ghcup config add-release-channel URI` wrt [#328](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/328)
|
|
||||||
* Fix max path issues on windows with `ghcup run`
|
|
||||||
|
|
||||||
## 0.1.17.5 -- 2022-02-26
|
|
||||||
|
|
||||||
* Implement `ghcup run` subcommand wrt [#137](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/137)
|
|
||||||
* Support installation of dynamic HLS bindists wrt [HLS #2675](https://github.com/haskell/haskell-language-server/pull/2675) and [#237](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/237)
|
|
||||||
* Fix XDG support when `~/.local/bin` is a symlink wrt [#311](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/311)
|
|
||||||
* Add support for quilt-style patches wrt [#230](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/230), by James Hobson
|
|
||||||
* Fix redundant upgrade warnings in `ghcup upgrade`
|
|
||||||
* Fix `ghcup whereis ghc` for non-standard versions wrt [#289](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/289)
|
|
||||||
* Don't print logs to stdout, but stderr
|
|
||||||
* Allow unpacking legacy lzma archives wrt [#307](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/307)
|
|
||||||
* Allow to disable self-upgrade functionality wrt [#305](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/305)
|
|
||||||
* Fix `ghcup install ghc --set` when ghc is already installed wrt [#291](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/291)
|
|
||||||
|
|
||||||
## 0.1.17.4 -- 2021-11-13
|
|
||||||
|
|
||||||
* add `--metadata-caching` option, allowing to also disable yaml metadata caching wrt [#278](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/278)
|
|
||||||
* make upgrading ghcup in TUI more pleasant wrt [#276](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/276)
|
|
||||||
* fix parsing of atypical GHC versions (e.g. `8.10.5-patch1`)
|
|
||||||
* fix compiling HLS dynamically linked, also see [#245](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/245)
|
|
||||||
* redo (and break) some of the `ghcup compile <tool>` interface, improving patch options and setting custom cabal.project files
|
|
||||||
* avoid redundant update warnings wrt [#283](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/283)
|
|
||||||
|
|
||||||
## 0.1.17.3 -- 2021-10-27
|
## 0.1.17.3 -- 2021-10-27
|
||||||
|
|
||||||
* clean up during unpack failures as well
|
* clean up during unpack failures as well
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ 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.Utils.Logger
|
import GHCup.Logger
|
||||||
import GHCup.Utils.Prelude ( decUTF8Safe )
|
import GHCup.Prelude ( decUTF8Safe )
|
||||||
import GHCup.Utils.File
|
import GHCup.System.Process
|
||||||
|
|
||||||
import Brick
|
import Brick
|
||||||
import Brick.Widgets.Border
|
import Brick.Widgets.Border
|
||||||
@@ -493,9 +493,9 @@ set' _ (_, ListResult {..}) = do
|
|||||||
|
|
||||||
run (do
|
run (do
|
||||||
case lTool of
|
case lTool of
|
||||||
GHC -> liftE $ setGHC (GHCTargetVersion lCross lVer) SetGHCOnly Nothing $> ()
|
GHC -> liftE $ setGHC (GHCTargetVersion lCross lVer) SetGHCOnly $> ()
|
||||||
Cabal -> liftE $ setCabal lVer $> ()
|
Cabal -> liftE $ setCabal lVer $> ()
|
||||||
HLS -> liftE $ setHLS lVer SetHLSOnly Nothing $> ()
|
HLS -> liftE $ setHLS lVer $> ()
|
||||||
Stack -> liftE $ setStack lVer $> ()
|
Stack -> liftE $ setStack lVer $> ()
|
||||||
GHCup -> pure ()
|
GHCup -> pure ()
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -15,16 +15,13 @@ module GHCup.OptParse (
|
|||||||
, module GHCup.OptParse.Config
|
, module GHCup.OptParse.Config
|
||||||
, module GHCup.OptParse.Whereis
|
, module GHCup.OptParse.Whereis
|
||||||
, module GHCup.OptParse.List
|
, module GHCup.OptParse.List
|
||||||
#ifndef DISABLE_UPGRADE
|
|
||||||
, module GHCup.OptParse.Upgrade
|
, module GHCup.OptParse.Upgrade
|
||||||
#endif
|
|
||||||
, module GHCup.OptParse.ChangeLog
|
, module GHCup.OptParse.ChangeLog
|
||||||
, module GHCup.OptParse.Prefetch
|
, module GHCup.OptParse.Prefetch
|
||||||
, module GHCup.OptParse.GC
|
, module GHCup.OptParse.GC
|
||||||
, module GHCup.OptParse.DInfo
|
, module GHCup.OptParse.DInfo
|
||||||
, module GHCup.OptParse.Nuke
|
, module GHCup.OptParse.Nuke
|
||||||
, module GHCup.OptParse.ToolRequirements
|
, module GHCup.OptParse.ToolRequirements
|
||||||
, module GHCup.OptParse.Run
|
|
||||||
, module GHCup.OptParse
|
, module GHCup.OptParse
|
||||||
) where
|
) where
|
||||||
|
|
||||||
@@ -34,14 +31,11 @@ import GHCup.OptParse.Install
|
|||||||
import GHCup.OptParse.Set
|
import GHCup.OptParse.Set
|
||||||
import GHCup.OptParse.UnSet
|
import GHCup.OptParse.UnSet
|
||||||
import GHCup.OptParse.Rm
|
import GHCup.OptParse.Rm
|
||||||
import GHCup.OptParse.Run
|
|
||||||
import GHCup.OptParse.Compile
|
import GHCup.OptParse.Compile
|
||||||
import GHCup.OptParse.Config
|
import GHCup.OptParse.Config
|
||||||
import GHCup.OptParse.Whereis
|
import GHCup.OptParse.Whereis
|
||||||
import GHCup.OptParse.List
|
import GHCup.OptParse.List
|
||||||
#ifndef DISABLE_UPGRADE
|
|
||||||
import GHCup.OptParse.Upgrade
|
import GHCup.OptParse.Upgrade
|
||||||
#endif
|
|
||||||
import GHCup.OptParse.ChangeLog
|
import GHCup.OptParse.ChangeLog
|
||||||
import GHCup.OptParse.Prefetch
|
import GHCup.OptParse.Prefetch
|
||||||
import GHCup.OptParse.GC
|
import GHCup.OptParse.GC
|
||||||
@@ -95,10 +89,8 @@ data Command
|
|||||||
| Compile CompileCommand
|
| Compile CompileCommand
|
||||||
| Config ConfigCommand
|
| Config ConfigCommand
|
||||||
| Whereis WhereisOptions WhereisCommand
|
| Whereis WhereisOptions WhereisCommand
|
||||||
#ifndef DISABLE_UPGRADE
|
|
||||||
| Upgrade UpgradeOpts Bool
|
| Upgrade UpgradeOpts Bool
|
||||||
#endif
|
| ToolRequirements
|
||||||
| ToolRequirements ToolReqOpts
|
|
||||||
| ChangeLog ChangeLogOptions
|
| ChangeLog ChangeLogOptions
|
||||||
| Nuke
|
| Nuke
|
||||||
#if defined(BRICK)
|
#if defined(BRICK)
|
||||||
@@ -106,15 +98,14 @@ data Command
|
|||||||
#endif
|
#endif
|
||||||
| Prefetch PrefetchCommand
|
| Prefetch PrefetchCommand
|
||||||
| GC GCOptions
|
| GC GCOptions
|
||||||
| Run RunOptions
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
opts :: Parser Options
|
opts :: Parser Options
|
||||||
opts =
|
opts =
|
||||||
Options
|
Options
|
||||||
<$> invertableSwitch "verbose" (Just 'v') False (help "Enable verbosity (default: disabled)")
|
<$> invertableSwitch "verbose" 'v' False (help "Enable verbosity (default: disabled)")
|
||||||
<*> invertableSwitch "cache" (Just 'c') False (help "Cache downloads in ~/.ghcup/cache (default: disabled)")
|
<*> invertableSwitch "cache" '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" <> help "How long the yaml metadata caching interval is (in seconds), 0 to disable" <> internal))
|
||||||
<*> optional
|
<*> optional
|
||||||
(option
|
(option
|
||||||
@@ -124,10 +115,9 @@ opts =
|
|||||||
<> metavar "URL"
|
<> metavar "URL"
|
||||||
<> help "Alternative ghcup download info url"
|
<> help "Alternative ghcup download info url"
|
||||||
<> internal
|
<> internal
|
||||||
<> completer fileUri
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
<*> (fmap . fmap) not (invertableSwitch "verify" (Just 'n') True (help "Disable tarball checksum verification (default: enabled)"))
|
<*> (fmap . fmap) not (invertableSwitch "verify" 'n' True (help "Disable tarball checksum verification (default: enabled)"))
|
||||||
<*> optional (option
|
<*> optional (option
|
||||||
(eitherReader keepOnParser)
|
(eitherReader keepOnParser)
|
||||||
( long "keep"
|
( long "keep"
|
||||||
@@ -135,7 +125,6 @@ opts =
|
|||||||
<> help
|
<> help
|
||||||
"Keep build directories? (default: errors)"
|
"Keep build directories? (default: errors)"
|
||||||
<> hidden
|
<> hidden
|
||||||
<> completer (listCompleter ["always", "errors", "never"])
|
|
||||||
))
|
))
|
||||||
<*> optional (option
|
<*> optional (option
|
||||||
(eitherReader downloaderParser)
|
(eitherReader downloaderParser)
|
||||||
@@ -144,23 +133,20 @@ opts =
|
|||||||
<> metavar "<internal|curl|wget>"
|
<> metavar "<internal|curl|wget>"
|
||||||
<> help
|
<> help
|
||||||
"Downloader to use (default: internal)"
|
"Downloader to use (default: internal)"
|
||||||
<> completer (listCompleter ["internal", "curl", "wget"])
|
|
||||||
#else
|
#else
|
||||||
<> metavar "<curl|wget>"
|
<> metavar "<curl|wget>"
|
||||||
<> help
|
<> help
|
||||||
"Downloader to use (default: curl)"
|
"Downloader to use (default: curl)"
|
||||||
<> completer (listCompleter ["curl", "wget"])
|
|
||||||
#endif
|
#endif
|
||||||
<> hidden
|
<> hidden
|
||||||
))
|
))
|
||||||
<*> invertableSwitch "offline" (Just 'o') False (help "Don't do any network calls, trying cached assets and failing if missing.")
|
<*> invertableSwitch "offline" 'o' False (help "Don't do any network calls, trying cached assets and failing if missing.")
|
||||||
<*> optional (option
|
<*> optional (option
|
||||||
(eitherReader gpgParser)
|
(eitherReader gpgParser)
|
||||||
( long "gpg"
|
( long "gpg"
|
||||||
<> metavar "<strict|lax|none>"
|
<> metavar "<strict|lax|none>"
|
||||||
<> help
|
<> help
|
||||||
"GPG verification (default: none)"
|
"GPG verification (default: none)"
|
||||||
<> completer (listCompleter ["strict", "lax", "none"])
|
|
||||||
))
|
))
|
||||||
<*> com
|
<*> com
|
||||||
where
|
where
|
||||||
@@ -222,7 +208,6 @@ com =
|
|||||||
(info (List <$> listOpts <**> helper)
|
(info (List <$> listOpts <**> helper)
|
||||||
(progDesc "Show available GHCs and other tools")
|
(progDesc "Show available GHCs and other tools")
|
||||||
)
|
)
|
||||||
#ifndef DISABLE_UPGRADE
|
|
||||||
<> command
|
<> command
|
||||||
"upgrade"
|
"upgrade"
|
||||||
(info
|
(info
|
||||||
@@ -233,7 +218,6 @@ com =
|
|||||||
)
|
)
|
||||||
(progDesc "Upgrade ghcup")
|
(progDesc "Upgrade ghcup")
|
||||||
)
|
)
|
||||||
#endif
|
|
||||||
<> command
|
<> command
|
||||||
"compile"
|
"compile"
|
||||||
( Compile
|
( Compile
|
||||||
@@ -271,16 +255,6 @@ com =
|
|||||||
(progDesc "Garbage collection"
|
(progDesc "Garbage collection"
|
||||||
<> footerDoc ( Just $ text gcFooter ))
|
<> footerDoc ( Just $ text gcFooter ))
|
||||||
)
|
)
|
||||||
<> command
|
|
||||||
"run"
|
|
||||||
(Run
|
|
||||||
<$>
|
|
||||||
info
|
|
||||||
(runOpts <**> helper)
|
|
||||||
(progDesc "Run a command with the given tool in PATH"
|
|
||||||
<> footerDoc ( Just $ text runFooter )
|
|
||||||
)
|
|
||||||
)
|
|
||||||
<> commandGroup "Main commands:"
|
<> commandGroup "Main commands:"
|
||||||
)
|
)
|
||||||
<|> subparser
|
<|> subparser
|
||||||
@@ -289,8 +263,8 @@ com =
|
|||||||
((\_ -> DInfo) <$> info helper (progDesc "Show debug info"))
|
((\_ -> DInfo) <$> info helper (progDesc "Show debug info"))
|
||||||
<> command
|
<> command
|
||||||
"tool-requirements"
|
"tool-requirements"
|
||||||
( ToolRequirements
|
( (\_ -> ToolRequirements)
|
||||||
<$> info (toolReqP <**> helper)
|
<$> info helper
|
||||||
(progDesc "Show the requirements for ghc/cabal")
|
(progDesc "Show the requirements for ghc/cabal")
|
||||||
)
|
)
|
||||||
<> command
|
<> command
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ module GHCup.OptParse.ChangeLog where
|
|||||||
|
|
||||||
|
|
||||||
import GHCup.Types
|
import GHCup.Types
|
||||||
import GHCup.Utils.Logger
|
import GHCup.Logger
|
||||||
import GHCup.OptParse.Common
|
import GHCup.OptParse.Common
|
||||||
import GHCup.Utils.String.QQ
|
import GHCup.QQ.String
|
||||||
|
|
||||||
#if !MIN_VERSION_base(4,13,0)
|
#if !MIN_VERSION_base(4,13,0)
|
||||||
import Control.Monad.Fail ( MonadFail )
|
import Control.Monad.Fail ( MonadFail )
|
||||||
@@ -34,8 +34,8 @@ import GHCup.Types.Optics
|
|||||||
import GHCup.Utils
|
import GHCup.Utils
|
||||||
import Data.Versions
|
import Data.Versions
|
||||||
import URI.ByteString (serializeURIRef')
|
import URI.ByteString (serializeURIRef')
|
||||||
import GHCup.Utils.Prelude
|
import GHCup.Prelude
|
||||||
import GHCup.Utils.File (exec)
|
import GHCup.System.Process (exec)
|
||||||
import Data.Char (toLower)
|
import Data.Char (toLower)
|
||||||
|
|
||||||
|
|
||||||
@@ -76,7 +76,6 @@ changelogP =
|
|||||||
)
|
)
|
||||||
(short 't' <> long "tool" <> metavar "<ghc|cabal|ghcup>" <> help
|
(short 't' <> long "tool" <> metavar "<ghc|cabal|ghcup>" <> help
|
||||||
"Open changelog for given tool (default: ghc)"
|
"Open changelog for given tool (default: ghc)"
|
||||||
<> completer toolCompleter
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
<*> optional (toolVersionArgument Nothing Nothing)
|
<*> optional (toolVersionArgument Nothing Nothing)
|
||||||
|
|||||||
@@ -3,8 +3,6 @@
|
|||||||
{-# LANGUAGE FlexibleContexts #-}
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
{-# LANGUAGE DuplicateRecordFields #-}
|
{-# LANGUAGE DuplicateRecordFields #-}
|
||||||
{-# LANGUAGE TypeApplications #-}
|
|
||||||
{-# LANGUAGE NumericUnderscores #-}
|
|
||||||
|
|
||||||
module GHCup.OptParse.Common where
|
module GHCup.OptParse.Common where
|
||||||
|
|
||||||
@@ -16,55 +14,36 @@ import GHCup.Platform
|
|||||||
import GHCup.Types
|
import GHCup.Types
|
||||||
import GHCup.Types.Optics
|
import GHCup.Types.Optics
|
||||||
import GHCup.Utils
|
import GHCup.Utils
|
||||||
import GHCup.Utils.File
|
import GHCup.Logger
|
||||||
import GHCup.Utils.Logger
|
import GHCup.MegaParsec
|
||||||
import GHCup.Utils.MegaParsec
|
import GHCup.Prelude
|
||||||
import GHCup.Utils.Prelude
|
|
||||||
|
|
||||||
import Control.DeepSeq
|
|
||||||
import Control.Concurrent
|
|
||||||
import Control.Concurrent.Async
|
|
||||||
import Control.Exception.Safe
|
import Control.Exception.Safe
|
||||||
#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
|
||||||
import Control.Monad.Reader
|
import Control.Monad.Reader
|
||||||
import Data.Aeson
|
|
||||||
#if MIN_VERSION_aeson(2,0,0)
|
|
||||||
import qualified Data.Aeson.Key as KM
|
|
||||||
import qualified Data.Aeson.KeyMap as KM
|
|
||||||
#else
|
|
||||||
import qualified Data.HashMap.Strict as KM
|
|
||||||
#endif
|
|
||||||
import Data.ByteString.Lazy ( ByteString )
|
|
||||||
import Data.Bifunctor
|
import Data.Bifunctor
|
||||||
import Data.Char
|
import Data.Char
|
||||||
import Data.Either
|
import Data.Either
|
||||||
import Data.Functor
|
import Data.Functor
|
||||||
import Data.List ( nub, sort, sortBy, isPrefixOf, stripPrefix )
|
import Data.List ( nub, sort, sortBy )
|
||||||
import Data.Maybe
|
import Data.Maybe
|
||||||
import Data.Text ( Text )
|
import Data.Text ( Text )
|
||||||
import Data.Versions hiding ( str )
|
import Data.Versions hiding ( str )
|
||||||
import Data.Void
|
import Data.Void
|
||||||
import qualified Data.Vector as V
|
|
||||||
import GHC.IO.Exception
|
|
||||||
import Haskus.Utils.Variant.Excepts
|
import Haskus.Utils.Variant.Excepts
|
||||||
import Options.Applicative hiding ( style )
|
import Options.Applicative hiding ( style )
|
||||||
import Prelude hiding ( appendFile )
|
import Prelude hiding ( appendFile )
|
||||||
import Safe
|
import Safe
|
||||||
import System.Directory
|
|
||||||
import System.Process ( readProcess )
|
|
||||||
import System.FilePath
|
import System.FilePath
|
||||||
import Text.HTML.TagSoup hiding ( Tag )
|
|
||||||
import URI.ByteString
|
import URI.ByteString
|
||||||
|
|
||||||
import qualified Data.ByteString.UTF8 as UTF8
|
import qualified Data.ByteString.UTF8 as UTF8
|
||||||
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 qualified Text.Megaparsec as MP
|
import qualified Text.Megaparsec as MP
|
||||||
import qualified System.FilePath.Posix as FP
|
|
||||||
import GHCup.Version
|
import GHCup.Version
|
||||||
import Control.Exception (evaluate)
|
|
||||||
|
|
||||||
|
|
||||||
-------------
|
-------------
|
||||||
@@ -138,7 +117,7 @@ versionArgument criteria tool = argument (eitherReader tVersionEither) (metavar
|
|||||||
-- the help is shown only for --no-recursive.
|
-- the help is shown only for --no-recursive.
|
||||||
invertableSwitch
|
invertableSwitch
|
||||||
:: String -- ^ long option
|
:: String -- ^ long option
|
||||||
-> Maybe Char -- ^ short option for the non-default option
|
-> Char -- ^ short option for the non-default option
|
||||||
-> Bool -- ^ is switch enabled by default?
|
-> Bool -- ^ is switch enabled by default?
|
||||||
-> Mod FlagFields Bool -- ^ option modifier
|
-> Mod FlagFields Bool -- ^ option modifier
|
||||||
-> Parser (Maybe Bool)
|
-> Parser (Maybe Bool)
|
||||||
@@ -149,14 +128,14 @@ invertableSwitch longopt shortopt defv optmod = invertableSwitch' longopt shorto
|
|||||||
-- | Allows providing option modifiers for both --foo and --no-foo.
|
-- | Allows providing option modifiers for both --foo and --no-foo.
|
||||||
invertableSwitch'
|
invertableSwitch'
|
||||||
:: String -- ^ long option (eg "foo")
|
:: String -- ^ long option (eg "foo")
|
||||||
-> Maybe Char -- ^ short option for the non-default option
|
-> Char -- ^ short option for the non-default option
|
||||||
-> Bool -- ^ is switch enabled by default?
|
-> Bool -- ^ is switch enabled by default?
|
||||||
-> Mod FlagFields Bool -- ^ option modifier for --foo
|
-> Mod FlagFields Bool -- ^ option modifier for --foo
|
||||||
-> Mod FlagFields Bool -- ^ option modifier for --no-foo
|
-> Mod FlagFields Bool -- ^ option modifier for --no-foo
|
||||||
-> Parser (Maybe Bool)
|
-> Parser (Maybe Bool)
|
||||||
invertableSwitch' longopt shortopt defv enmod dismod = optional
|
invertableSwitch' longopt shortopt defv enmod dismod = optional
|
||||||
( flag' True ( enmod <> long longopt <> if defv then mempty else maybe mempty short shortopt)
|
( flag' True ( enmod <> long longopt <> if defv then mempty else short shortopt)
|
||||||
<|> flag' False (dismod <> long nolongopt <> if defv then maybe mempty short shortopt else mempty)
|
<|> flag' False (dismod <> long nolongopt <> if defv then short shortopt else mempty)
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
nolongopt = "no-" ++ longopt
|
nolongopt = "no-" ++ longopt
|
||||||
@@ -217,8 +196,8 @@ platformParser s' = case MP.parse (platformP <* MP.eof) "" (T.pack s') of
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
uriParser :: String -> Either String URI
|
bindistParser :: String -> Either String URI
|
||||||
uriParser = first show . parseURI strictURIParserOptions . UTF8.fromString
|
bindistParser = first show . parseURI strictURIParserOptions . UTF8.fromString
|
||||||
|
|
||||||
|
|
||||||
absolutePathParser :: FilePath -> Either String FilePath
|
absolutePathParser :: FilePath -> Either String FilePath
|
||||||
@@ -267,6 +246,18 @@ criteriaParser s' | t == T.pack "installed" = Right ListInstalled
|
|||||||
where t = T.toLower (T.pack s')
|
where t = T.toLower (T.pack s')
|
||||||
|
|
||||||
|
|
||||||
|
toolVersionParser :: Parser ToolVersion
|
||||||
|
toolVersionParser = verP' <|> toolP
|
||||||
|
where
|
||||||
|
verP' = ToolVersion <$> versionParser
|
||||||
|
toolP =
|
||||||
|
ToolTag
|
||||||
|
<$> option
|
||||||
|
(eitherReader tagEither)
|
||||||
|
(short 't' <> long "tag" <> metavar "TAG" <> help "The target tag")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
keepOnParser :: String -> Either String KeepDirs
|
keepOnParser :: String -> Either String KeepDirs
|
||||||
keepOnParser s' | t == T.pack "always" = Right Always
|
keepOnParser s' | t == T.pack "always" = Right Always
|
||||||
@@ -298,126 +289,6 @@ gpgParser s' | t == T.pack "strict" = Right GPGStrict
|
|||||||
--[ Completers ]--
|
--[ Completers ]--
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
|
||||||
toolCompleter :: Completer
|
|
||||||
toolCompleter = listCompleter ["ghc", "cabal", "hls", "stack"]
|
|
||||||
|
|
||||||
gitFileUri :: [String] -> Completer
|
|
||||||
gitFileUri add = mkCompleter $ fileUri' (["git://"] <> add)
|
|
||||||
|
|
||||||
fileUri :: Completer
|
|
||||||
fileUri = mkCompleter $ fileUri' []
|
|
||||||
|
|
||||||
fileUri' :: [String] -> String -> IO [String]
|
|
||||||
fileUri' add = \case
|
|
||||||
"" -> do
|
|
||||||
pwd <- getCurrentDirectory
|
|
||||||
pure $ ["https://", "http://", "file:///", "file://" <> pwd <> "/"] <> add
|
|
||||||
xs
|
|
||||||
| "file:///" `isPrefixOf` xs -> fmap ("file://" <>) <$>
|
|
||||||
case stripPrefix "file://" xs of
|
|
||||||
Nothing -> pure []
|
|
||||||
Just r -> do
|
|
||||||
pwd <- getCurrentDirectory
|
|
||||||
dirs <- compgen "directory" r ["-S", "/"]
|
|
||||||
files <- filter (\f -> (f <> "/") `notElem` dirs) <$> compgen "file" r []
|
|
||||||
pure (dirs <> files <> if r `isPrefixOf` pwd then [pwd <> "/"] else [])
|
|
||||||
| xs `isPrefixOf` "file:///" -> pure ["file:///"]
|
|
||||||
| xs `isPrefixOf` "https://" -> pure ["https://"]
|
|
||||||
| xs `isPrefixOf` "http://" -> pure ["http://"]
|
|
||||||
| otherwise -> pure []
|
|
||||||
where
|
|
||||||
compgen :: String -> String -> [String] -> IO [String]
|
|
||||||
compgen action' r opts = do
|
|
||||||
let cmd = unwords $ ["compgen", "-A", action'] <> opts <> ["--", requote r]
|
|
||||||
result <- tryIO $ readProcess "bash" ["-c", cmd] ""
|
|
||||||
return . lines . either (const []) id $ result
|
|
||||||
|
|
||||||
-- | Strongly quote the string we pass to compgen.
|
|
||||||
--
|
|
||||||
-- We need to do this so bash doesn't expand out any ~ or other
|
|
||||||
-- chars we want to complete on, or emit an end of line error
|
|
||||||
-- when seeking the close to the quote.
|
|
||||||
--
|
|
||||||
-- NOTE: copied from https://hackage.haskell.org/package/optparse-applicative-0.17.0.0/docs/src/Options.Applicative.Builder.Completer.html#requote
|
|
||||||
requote :: String -> String
|
|
||||||
requote s =
|
|
||||||
let
|
|
||||||
-- Bash doesn't appear to allow "mixed" escaping
|
|
||||||
-- in bash completions. So we don't have to really
|
|
||||||
-- worry about people swapping between strong and
|
|
||||||
-- weak quotes.
|
|
||||||
unescaped =
|
|
||||||
case s of
|
|
||||||
-- It's already strongly quoted, so we
|
|
||||||
-- can use it mostly as is, but we must
|
|
||||||
-- ensure it's closed off at the end and
|
|
||||||
-- there's no single quotes in the
|
|
||||||
-- middle which might confuse bash.
|
|
||||||
('\'': rs) -> unescapeN rs
|
|
||||||
|
|
||||||
-- We're weakly quoted.
|
|
||||||
('"': rs) -> unescapeD rs
|
|
||||||
|
|
||||||
-- We're not quoted at all.
|
|
||||||
-- We need to unescape some characters like
|
|
||||||
-- spaces and quotation marks.
|
|
||||||
elsewise -> unescapeU elsewise
|
|
||||||
in
|
|
||||||
strong unescaped
|
|
||||||
|
|
||||||
where
|
|
||||||
strong ss = '\'' : foldr go "'" ss
|
|
||||||
where
|
|
||||||
-- If there's a single quote inside the
|
|
||||||
-- command: exit from the strong quote and
|
|
||||||
-- emit it the quote escaped, then resume.
|
|
||||||
go '\'' t = "'\\''" ++ t
|
|
||||||
go h t = h : t
|
|
||||||
|
|
||||||
-- Unescape a strongly quoted string
|
|
||||||
-- We have two recursive functions, as we
|
|
||||||
-- can enter and exit the strong escaping.
|
|
||||||
unescapeN = goX
|
|
||||||
where
|
|
||||||
goX ('\'' : xs) = goN xs
|
|
||||||
goX (x : xs) = x : goX xs
|
|
||||||
goX [] = []
|
|
||||||
|
|
||||||
goN ('\\' : '\'' : xs) = '\'' : goN xs
|
|
||||||
goN ('\'' : xs) = goX xs
|
|
||||||
goN (x : xs) = x : goN xs
|
|
||||||
goN [] = []
|
|
||||||
|
|
||||||
-- Unescape an unquoted string
|
|
||||||
unescapeU = goX
|
|
||||||
where
|
|
||||||
goX [] = []
|
|
||||||
goX ('\\' : x : xs) = x : goX xs
|
|
||||||
goX (x : xs) = x : goX xs
|
|
||||||
|
|
||||||
-- Unescape a weakly quoted string
|
|
||||||
unescapeD = goX
|
|
||||||
where
|
|
||||||
-- Reached an escape character
|
|
||||||
goX ('\\' : x : xs)
|
|
||||||
-- If it's true escapable, strip the
|
|
||||||
-- slashes, as we're going to strong
|
|
||||||
-- escape instead.
|
|
||||||
| x `elem` ("$`\"\\\n" :: String) = x : goX xs
|
|
||||||
| otherwise = '\\' : x : goX xs
|
|
||||||
-- We've ended quoted section, so we
|
|
||||||
-- don't recurse on goX, it's done.
|
|
||||||
goX ('"' : xs)
|
|
||||||
= xs
|
|
||||||
-- Not done, but not a special character
|
|
||||||
-- just continue the fold.
|
|
||||||
goX (x : xs)
|
|
||||||
= x : goX xs
|
|
||||||
goX []
|
|
||||||
= []
|
|
||||||
|
|
||||||
|
|
||||||
tagCompleter :: Tool -> [String] -> Completer
|
tagCompleter :: Tool -> [String] -> Completer
|
||||||
tagCompleter tool add = listIOCompleter $ do
|
tagCompleter tool add = listIOCompleter $ do
|
||||||
dirs' <- liftIO getAllDirs
|
dirs' <- liftIO getAllDirs
|
||||||
@@ -475,150 +346,6 @@ versionCompleter criteria tool = listIOCompleter $ do
|
|||||||
return $ T.unpack . prettyVer . lVer <$> installedVersions
|
return $ T.unpack . prettyVer . lVer <$> installedVersions
|
||||||
|
|
||||||
|
|
||||||
toolDlCompleter :: Tool -> Completer
|
|
||||||
toolDlCompleter tool = mkCompleter $ \case
|
|
||||||
"" -> pure (initUrl tool <> ["https://", "http://", "file:///"])
|
|
||||||
word
|
|
||||||
| "file://" `isPrefixOf` word -> fileUri' [] word
|
|
||||||
-- downloads.haskell.org
|
|
||||||
| "https://downloads.haskell.org/" `isPrefixOf` word ->
|
|
||||||
fmap (completePrefix word) . prefixMatch (FP.takeFileName word) <$> fromHRef word
|
|
||||||
|
|
||||||
-- github releases
|
|
||||||
| "https://github.com/haskell/haskell-language-server/releases/download/" `isPrefixOf` word
|
|
||||||
, let xs = splitPath word
|
|
||||||
, (length xs == 6 && last word == '/') || (length xs == 7 && last word /= '/') ->
|
|
||||||
fmap (\x -> completePrefix word x <> "/") . prefixMatch (FP.takeFileName word) <$> getGithubReleases "haskell" "haskell-language-server"
|
|
||||||
| "https://github.com/commercialhaskell/stack/releases/download/" == word
|
|
||||||
, let xs = splitPath word
|
|
||||||
, (length xs == 6 && last word == '/') || (length xs == 7 && last word /= '/') ->
|
|
||||||
fmap (\x -> completePrefix word x <> "/") . prefixMatch (FP.takeFileName word) <$> getGithubReleases "commercialhaskell" "stack"
|
|
||||||
|
|
||||||
-- github release assets
|
|
||||||
| "https://github.com/haskell/haskell-language-server/releases/download/" `isPrefixOf` word
|
|
||||||
, let xs = splitPath word
|
|
||||||
, (length xs == 7 && last word == '/') || length xs == 8
|
|
||||||
, let rel = xs !! 6
|
|
||||||
, length rel > 1 -> do
|
|
||||||
fmap (completePrefix word) . prefixMatch (FP.takeFileName word) <$> getGithubAssets "haskell" "haskell-language-server" (init rel)
|
|
||||||
| "https://github.com/commercialhaskell/stack/releases/download/" `isPrefixOf` word
|
|
||||||
, let xs = splitPath word
|
|
||||||
, (length xs == 7 && last word == '/') || length xs == 8
|
|
||||||
, let rel = xs !! 6
|
|
||||||
, length rel > 1 -> do
|
|
||||||
fmap (completePrefix word) . prefixMatch (FP.takeFileName word) <$> getGithubAssets "commercialhaskell" "stack" (init rel)
|
|
||||||
|
|
||||||
-- github
|
|
||||||
| "https://github.com/c" `isPrefixOf` word -> pure ["https://github.com/commercialhaskell/stack/releases/download/"]
|
|
||||||
| "https://github.com/h" `isPrefixOf` word -> pure ["https://github.com/haskell/haskell-language-server/releases/download/"]
|
|
||||||
| "https://g" `isPrefixOf` word
|
|
||||||
, tool == Stack -> pure ["https://github.com/commercialhaskell/stack/releases/download/"]
|
|
||||||
| "https://g" `isPrefixOf` word
|
|
||||||
, tool == HLS -> pure ["https://github.com/haskell/haskell-language-server/releases/download/"]
|
|
||||||
|
|
||||||
| "https://d" `isPrefixOf` word -> pure $ filter ("https://downloads.haskell.org/" `isPrefixOf`) $ initUrl tool
|
|
||||||
|
|
||||||
| "h" `isPrefixOf` word -> pure $ initUrl tool
|
|
||||||
|
|
||||||
| word `isPrefixOf` "file:///" -> pure ["file:///"]
|
|
||||||
| word `isPrefixOf` "https://" -> pure ["https://"]
|
|
||||||
| word `isPrefixOf` "http://" -> pure ["http://"]
|
|
||||||
|
|
||||||
| otherwise -> pure []
|
|
||||||
where
|
|
||||||
initUrl :: Tool -> [String]
|
|
||||||
initUrl GHC = [ "https://downloads.haskell.org/~ghc/"
|
|
||||||
, "https://downloads.haskell.org/~ghcup/unofficial-bindists/ghc/"
|
|
||||||
]
|
|
||||||
initUrl Cabal = [ "https://downloads.haskell.org/~cabal/"
|
|
||||||
, "https://downloads.haskell.org/~ghcup/unofficial-bindists/cabal/"
|
|
||||||
]
|
|
||||||
initUrl GHCup = [ "https://downloads.haskell.org/~ghcup/" ]
|
|
||||||
initUrl HLS = [ "https://github.com/haskell/haskell-language-server/releases/download/"
|
|
||||||
, "https://downloads.haskell.org/~ghcup/unofficial-bindists/haskell-language-server/"
|
|
||||||
]
|
|
||||||
initUrl Stack = [ "https://github.com/commercialhaskell/stack/releases/download/"
|
|
||||||
, "https://downloads.haskell.org/~ghcup/unofficial-bindists/stack/"
|
|
||||||
]
|
|
||||||
|
|
||||||
completePrefix :: String -- ^ url, e.g. 'https://github.com/haskell/haskell-languag'
|
|
||||||
-> String -- ^ match, e.g. 'haskell-language-server'
|
|
||||||
-> String -- ^ result, e.g. 'https://github.com/haskell/haskell-language-server'
|
|
||||||
completePrefix url match =
|
|
||||||
let base = FP.takeDirectory url
|
|
||||||
fn = FP.takeFileName url
|
|
||||||
in if fn `isPrefixOf` match then base <> "/" <> match else url
|
|
||||||
|
|
||||||
prefixMatch :: String -> [String] -> [String]
|
|
||||||
prefixMatch pref = filter (pref `isPrefixOf`)
|
|
||||||
|
|
||||||
fromHRef :: String -> IO [String]
|
|
||||||
fromHRef url = withCurl (FP.takeDirectory url) 2_000_000 $ \stdout ->
|
|
||||||
pure
|
|
||||||
. fmap (T.unpack . decUTF8Safe' . fromAttrib "href")
|
|
||||||
. filter isTagOpen
|
|
||||||
. filter (~== ("<a href>" :: String))
|
|
||||||
. parseTags
|
|
||||||
$ stdout
|
|
||||||
|
|
||||||
withCurl :: String -- ^ url
|
|
||||||
-> Int -- ^ delay
|
|
||||||
-> (ByteString -> IO [String]) -- ^ callback
|
|
||||||
-> IO [String]
|
|
||||||
withCurl url delay cb = do
|
|
||||||
let limit = threadDelay delay
|
|
||||||
race limit (executeOut "curl" ["-fL", url] Nothing) >>= \case
|
|
||||||
Right (CapturedProcess {_exitCode, _stdOut}) -> do
|
|
||||||
case _exitCode of
|
|
||||||
ExitSuccess ->
|
|
||||||
(try @_ @SomeException . cb $ _stdOut) >>= \case
|
|
||||||
Left _ -> pure []
|
|
||||||
Right r' -> do
|
|
||||||
r <- try @_ @SomeException
|
|
||||||
. evaluate
|
|
||||||
. force
|
|
||||||
$ r'
|
|
||||||
either (\_ -> pure []) pure r
|
|
||||||
ExitFailure _ -> pure []
|
|
||||||
Left _ -> pure []
|
|
||||||
|
|
||||||
getGithubReleases :: String
|
|
||||||
-> String
|
|
||||||
-> IO [String]
|
|
||||||
getGithubReleases owner repo = withCurl url 3_000_000 $ \stdout -> do
|
|
||||||
Just xs <- pure $ decode' @Array stdout
|
|
||||||
fmap V.toList $ forM xs $ \x -> do
|
|
||||||
(Object r) <- pure x
|
|
||||||
Just (String name) <- pure $ KM.lookup (mkval "tag_name") r
|
|
||||||
pure $ T.unpack name
|
|
||||||
where
|
|
||||||
url = "https://api.github.com/repos/" <> owner <> "/" <> repo <> "/releases"
|
|
||||||
|
|
||||||
getGithubAssets :: String
|
|
||||||
-> String
|
|
||||||
-> String
|
|
||||||
-> IO [String]
|
|
||||||
getGithubAssets owner repo tag = withCurl url 3_000_000 $ \stdout -> do
|
|
||||||
Just xs <- pure $ decode' @Object stdout
|
|
||||||
Just (Array assets) <- pure $ KM.lookup (mkval "assets") xs
|
|
||||||
as <- fmap V.toList $ forM assets $ \val -> do
|
|
||||||
(Object asset) <- pure val
|
|
||||||
Just (String name) <- pure $ KM.lookup (mkval "name") asset
|
|
||||||
pure $ T.unpack name
|
|
||||||
pure as
|
|
||||||
where
|
|
||||||
url = "https://api.github.com/repos/" <> owner <> "/" <> repo <> "/releases/tags/" <> tag
|
|
||||||
|
|
||||||
|
|
||||||
#if MIN_VERSION_aeson(2,0,0)
|
|
||||||
mkval = KM.fromString
|
|
||||||
#else
|
|
||||||
mkval = id
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-----------------
|
-----------------
|
||||||
@@ -745,22 +472,42 @@ checkForUpdates :: ( MonadReader env m
|
|||||||
, MonadIO m
|
, MonadIO m
|
||||||
, MonadFail m
|
, MonadFail m
|
||||||
)
|
)
|
||||||
=> m [(Tool, Version)]
|
=> m ()
|
||||||
checkForUpdates = do
|
checkForUpdates = do
|
||||||
GHCupInfo { _ghcupDownloads = dls } <- getGHCupInfo
|
GHCupInfo { _ghcupDownloads = dls } <- getGHCupInfo
|
||||||
lInstalled <- listVersions Nothing (Just ListInstalled)
|
lInstalled <- listVersions Nothing (Just ListInstalled)
|
||||||
let latestInstalled tool = (fmap lVer . lastMay . filter (\lr -> lTool lr == tool)) lInstalled
|
let latestInstalled tool = (fmap lVer . lastMay . filter (\lr -> lTool lr == tool)) lInstalled
|
||||||
|
|
||||||
ghcup <- forMM (getLatest dls GHCup) $ \(l, _) -> do
|
forM_ (getLatest dls GHCup) $ \(l, _) -> do
|
||||||
(Right ghcup_ver) <- pure $ version $ prettyPVP ghcUpVer
|
(Right ghc_ver) <- pure $ version $ prettyPVP ghcUpVer
|
||||||
if (l > ghcup_ver) then pure $ Just (GHCup, l) else pure Nothing
|
when (l > ghc_ver)
|
||||||
|
$ logWarn $
|
||||||
|
"New GHCup version available: " <> prettyVer l <> ". To upgrade, run 'ghcup upgrade'"
|
||||||
|
|
||||||
otherTools <- forM [GHC, Cabal, HLS, Stack] $ \t ->
|
forM_ (getLatest dls GHC) $ \(l, _) -> do
|
||||||
forMM (getLatest dls t) $ \(l, _) -> do
|
let mghc_ver = latestInstalled GHC
|
||||||
let mver = latestInstalled t
|
forM mghc_ver $ \ghc_ver ->
|
||||||
forMM mver $ \ver ->
|
when (l > ghc_ver)
|
||||||
if (l > ver) then pure $ Just (t, l) else pure Nothing
|
$ logWarn $
|
||||||
|
"New GHC version available: " <> prettyVer l <> ". To upgrade, run 'ghcup install ghc " <> prettyVer l <> "'"
|
||||||
|
|
||||||
pure $ catMaybes (ghcup:otherTools)
|
forM_ (getLatest dls Cabal) $ \(l, _) -> do
|
||||||
where
|
let mcabal_ver = latestInstalled Cabal
|
||||||
forMM a f = fmap join $ forM a f
|
forM mcabal_ver $ \cabal_ver ->
|
||||||
|
when (l > cabal_ver)
|
||||||
|
$ logWarn $
|
||||||
|
"New Cabal version available: " <> prettyVer l <> ". To upgrade, run 'ghcup install cabal " <> prettyVer l <> "'"
|
||||||
|
|
||||||
|
forM_ (getLatest dls HLS) $ \(l, _) -> do
|
||||||
|
let mhls_ver = latestInstalled HLS
|
||||||
|
forM mhls_ver $ \hls_ver ->
|
||||||
|
when (l > hls_ver)
|
||||||
|
$ logWarn $
|
||||||
|
"New HLS version available: " <> prettyVer l <> ". To upgrade, run 'ghcup install hls " <> prettyVer l <> "'"
|
||||||
|
|
||||||
|
forM_ (getLatest dls Stack) $ \(l, _) -> do
|
||||||
|
let mstack_ver = latestInstalled Stack
|
||||||
|
forM mstack_ver $ \stack_ver ->
|
||||||
|
when (l > stack_ver)
|
||||||
|
$ logWarn $
|
||||||
|
"New Stack version available: " <> prettyVer l <> ". To upgrade, run 'ghcup install stack " <> prettyVer l <> "'"
|
||||||
|
|||||||
@@ -13,13 +13,13 @@ module GHCup.OptParse.Compile where
|
|||||||
|
|
||||||
import GHCup
|
import GHCup
|
||||||
import GHCup.Errors
|
import GHCup.Errors
|
||||||
import GHCup.Utils.File
|
|
||||||
import GHCup.Types
|
import GHCup.Types
|
||||||
import GHCup.Types.Optics
|
import GHCup.Types.Optics
|
||||||
import GHCup.Utils
|
import GHCup.Utils
|
||||||
import GHCup.Utils.Logger
|
import GHCup.Logger
|
||||||
import GHCup.OptParse.Common
|
import GHCup.OptParse.Common
|
||||||
import GHCup.Utils.String.QQ
|
import GHCup.QQ.String
|
||||||
|
import GHCup.System.Process
|
||||||
|
|
||||||
#if !MIN_VERSION_base(4,13,0)
|
#if !MIN_VERSION_base(4,13,0)
|
||||||
import Control.Monad.Fail ( MonadFail )
|
import Control.Monad.Fail ( MonadFail )
|
||||||
@@ -40,7 +40,6 @@ import Prelude hiding ( appendFile )
|
|||||||
import System.Exit
|
import System.Exit
|
||||||
import Text.PrettyPrint.HughesPJClass ( prettyShow )
|
import Text.PrettyPrint.HughesPJClass ( prettyShow )
|
||||||
|
|
||||||
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)
|
||||||
import System.FilePath (isPathSeparator)
|
import System.FilePath (isPathSeparator)
|
||||||
@@ -69,7 +68,7 @@ data GHCCompileOptions = GHCCompileOptions
|
|||||||
, bootstrapGhc :: Either Version FilePath
|
, bootstrapGhc :: Either Version FilePath
|
||||||
, jobs :: Maybe Int
|
, jobs :: Maybe Int
|
||||||
, buildConfig :: Maybe FilePath
|
, buildConfig :: Maybe FilePath
|
||||||
, patches :: Maybe (Either FilePath [URI])
|
, patchDir :: Maybe FilePath
|
||||||
, crossTarget :: Maybe Text
|
, crossTarget :: Maybe Text
|
||||||
, addConfArgs :: [Text]
|
, addConfArgs :: [Text]
|
||||||
, setCompile :: Bool
|
, setCompile :: Bool
|
||||||
@@ -85,11 +84,10 @@ data HLSCompileOptions = HLSCompileOptions
|
|||||||
, setCompile :: Bool
|
, setCompile :: Bool
|
||||||
, ovewrwiteVer :: Maybe Version
|
, ovewrwiteVer :: Maybe Version
|
||||||
, isolateDir :: Maybe FilePath
|
, isolateDir :: Maybe FilePath
|
||||||
, cabalProject :: Maybe (Either FilePath URI)
|
, cabalProject :: Maybe FilePath
|
||||||
, cabalProjectLocal :: Maybe URI
|
, cabalProjectLocal :: Maybe FilePath
|
||||||
, patches :: Maybe (Either FilePath [URI])
|
, patchDir :: Maybe FilePath
|
||||||
, targetGHCs :: [ToolVersion]
|
, targetGHCs :: [ToolVersion]
|
||||||
, cabalArgs :: [Text]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -150,10 +148,7 @@ Examples:
|
|||||||
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
|
ghcup compile hls -v 1.4.0 -j 12 8.10.5 8.10.7 9.0.1|]
|
||||||
ghcup compile hls -v 1.4.0 -j 12 --ghc 8.10.5 --ghc 8.10.7
|
|
||||||
# compile from master for ghc 8.10.7, linking everything dynamically
|
|
||||||
ghcup compile hls -g master -j 12 --ghc 8.10.7 -- --ghc-options='-dynamic'|]
|
|
||||||
|
|
||||||
|
|
||||||
ghcCompileOpts :: Parser GHCCompileOptions
|
ghcCompileOpts :: Parser GHCCompileOptions
|
||||||
@@ -165,7 +160,6 @@ ghcCompileOpts =
|
|||||||
)
|
)
|
||||||
(short 'v' <> long "version" <> metavar "VERSION" <> help
|
(short 'v' <> long "version" <> metavar "VERSION" <> help
|
||||||
"The tool version to compile"
|
"The tool version to compile"
|
||||||
<> (completer $ versionCompleter Nothing GHC)
|
|
||||||
)
|
)
|
||||||
) <|>
|
) <|>
|
||||||
(Right <$> (GitBranch <$> option
|
(Right <$> (GitBranch <$> option
|
||||||
@@ -173,10 +167,7 @@ ghcCompileOpts =
|
|||||||
(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"
|
||||||
) <*>
|
) <*>
|
||||||
optional (option str (
|
optional (option str (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"])
|
|
||||||
))
|
|
||||||
)))
|
)))
|
||||||
<*> option
|
<*> option
|
||||||
(eitherReader
|
(eitherReader
|
||||||
@@ -189,14 +180,12 @@ ghcCompileOpts =
|
|||||||
<> metavar "BOOTSTRAP_GHC"
|
<> metavar "BOOTSTRAP_GHC"
|
||||||
<> help
|
<> help
|
||||||
"The GHC version (or full path) to bootstrap with (must be installed)"
|
"The GHC version (or full path) to bootstrap with (must be installed)"
|
||||||
<> (completer $ versionCompleter Nothing GHC)
|
|
||||||
)
|
)
|
||||||
<*> optional
|
<*> optional
|
||||||
(option
|
(option
|
||||||
(eitherReader (readEither @Int))
|
(eitherReader (readEither @Int))
|
||||||
(short 'j' <> long "jobs" <> metavar "JOBS" <> help
|
(short 'j' <> long "jobs" <> metavar "JOBS" <> help
|
||||||
"How many jobs to use for make"
|
"How many jobs to use for make"
|
||||||
<> (completer $ listCompleter $ fmap show ([1..12] :: [Int]))
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
<*> optional
|
<*> optional
|
||||||
@@ -204,28 +193,15 @@ ghcCompileOpts =
|
|||||||
str
|
str
|
||||||
(short 'c' <> long "config" <> metavar "CONFIG" <> help
|
(short 'c' <> long "config" <> metavar "CONFIG" <> help
|
||||||
"Absolute path to build config file"
|
"Absolute path to build config file"
|
||||||
<> completer (bashCompleter "file")
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
<*> (optional
|
<*> optional
|
||||||
(
|
(option
|
||||||
(fmap Right $ many $ option
|
str
|
||||||
(eitherReader uriParser)
|
(short 'p' <> long "patchdir" <> metavar "PATCH_DIR" <> help
|
||||||
(long "patch" <> metavar "PATCH_URI" <> help
|
"Absolute path to patch directory (applies all .patch and .diff files in order using -p1)"
|
||||||
"URI to a patch (https/http/file)"
|
|
||||||
<> completer fileUri
|
|
||||||
)
|
|
||||||
)
|
|
||||||
<|>
|
|
||||||
(fmap Left $ option
|
|
||||||
str
|
|
||||||
(short 'p' <> long "patchdir" <> metavar "PATCH_DIR" <> help
|
|
||||||
"Absolute path to patch directory (applies all .patch and .diff files in order using -p1. This order is determined by a quilt series file if it exists, or the patches are lexicographically ordered)"
|
|
||||||
<> completer (bashCompleter "directory")
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
<*> optional
|
<*> optional
|
||||||
(option
|
(option
|
||||||
str
|
str
|
||||||
@@ -234,7 +210,12 @@ ghcCompileOpts =
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
<*> many (argument str (metavar "CONFIGURE_ARGS" <> help "Additional arguments to configure, prefix with '-- ' (longopts)"))
|
<*> many (argument str (metavar "CONFIGURE_ARGS" <> help "Additional arguments to configure, prefix with '-- ' (longopts)"))
|
||||||
<*> fmap (fromMaybe False) (invertableSwitch "set" Nothing False (help "Set as active version after install"))
|
<*> flag
|
||||||
|
False
|
||||||
|
True
|
||||||
|
(long "set" <> help
|
||||||
|
"Set as active version after install"
|
||||||
|
)
|
||||||
<*> optional
|
<*> optional
|
||||||
(option
|
(option
|
||||||
(eitherReader
|
(eitherReader
|
||||||
@@ -242,7 +223,6 @@ ghcCompileOpts =
|
|||||||
)
|
)
|
||||||
(short 'o' <> long "overwrite-version" <> metavar "OVERWRITE_VERSION" <> help
|
(short 'o' <> long "overwrite-version" <> metavar "OVERWRITE_VERSION" <> help
|
||||||
"Allows to overwrite the finally installed VERSION with a different one, e.g. when you build 8.10.4 with your own patches, you might want to set this to '8.10.4-p1'"
|
"Allows to overwrite the finally installed VERSION with a different one, e.g. when you build 8.10.4 with your own patches, you might want to set this to '8.10.4-p1'"
|
||||||
<> (completer $ versionCompleter Nothing GHC)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
<*> optional
|
<*> optional
|
||||||
@@ -262,7 +242,6 @@ ghcCompileOpts =
|
|||||||
<> long "isolate"
|
<> long "isolate"
|
||||||
<> metavar "DIR"
|
<> 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 directory instead of the default one, no symlinks to this installation will be made"
|
||||||
<> completer (bashCompleter "directory")
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -275,7 +254,6 @@ hlsCompileOpts =
|
|||||||
)
|
)
|
||||||
(short 'v' <> long "version" <> metavar "VERSION" <> help
|
(short 'v' <> long "version" <> metavar "VERSION" <> help
|
||||||
"The tool version to compile"
|
"The tool version to compile"
|
||||||
<> (completer $ versionCompleter Nothing HLS)
|
|
||||||
)
|
)
|
||||||
) <|>
|
) <|>
|
||||||
(Right <$> (GitBranch <$> option
|
(Right <$> (GitBranch <$> option
|
||||||
@@ -283,19 +261,21 @@ hlsCompileOpts =
|
|||||||
(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"
|
||||||
) <*>
|
) <*>
|
||||||
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 GHC upstream)"))
|
||||||
<> completer (gitFileUri ["https://github.com/haskell/haskell-language-server.git"])
|
|
||||||
))
|
|
||||||
)))
|
)))
|
||||||
<*> optional
|
<*> optional
|
||||||
(option
|
(option
|
||||||
(eitherReader (readEither @Int))
|
(eitherReader (readEither @Int))
|
||||||
(short 'j' <> long "jobs" <> metavar "JOBS" <> help
|
(short 'j' <> long "jobs" <> metavar "JOBS" <> help
|
||||||
"How many jobs to use for make"
|
"How many jobs to use for make"
|
||||||
<> (completer $ listCompleter $ fmap show ([1..12] :: [Int]))
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
<*> fmap (fromMaybe True) (invertableSwitch "set" Nothing True (help "Don't set as active version after install"))
|
<*> flag
|
||||||
|
False
|
||||||
|
True
|
||||||
|
(long "set" <> help
|
||||||
|
"Set as active version after install"
|
||||||
|
)
|
||||||
<*> optional
|
<*> optional
|
||||||
(option
|
(option
|
||||||
(eitherReader
|
(eitherReader
|
||||||
@@ -303,7 +283,6 @@ hlsCompileOpts =
|
|||||||
)
|
)
|
||||||
(short 'o' <> long "overwrite-version" <> metavar "OVERWRITE_VERSION" <> help
|
(short 'o' <> long "overwrite-version" <> metavar "OVERWRITE_VERSION" <> help
|
||||||
"Allows to overwrite the finally installed VERSION with a different one, e.g. when you build 8.10.4 with your own patches, you might want to set this to '8.10.4-p1'"
|
"Allows to overwrite the finally installed VERSION with a different one, e.g. when you build 8.10.4 with your own patches, you might want to set this to '8.10.4-p1'"
|
||||||
<> (completer $ versionCompleter Nothing HLS)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
<*> optional
|
<*> optional
|
||||||
@@ -313,51 +292,30 @@ hlsCompileOpts =
|
|||||||
<> long "isolate"
|
<> long "isolate"
|
||||||
<> metavar "DIR"
|
<> 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 directory instead of the default one, no symlinks to this installation will be made"
|
||||||
<> completer (bashCompleter "directory")
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
<*> optional
|
<*> optional
|
||||||
(option
|
(option
|
||||||
((fmap Right $ eitherReader uriParser) <|> (fmap Left str))
|
str
|
||||||
(long "cabal-project" <> metavar "CABAL_PROJECT" <> help
|
(long "cabal-project" <> metavar "CABAL_PROJECT" <> help
|
||||||
"If relative filepath, specifies the path to cabal.project inside the unpacked HLS tarball/checkout. Otherwise expects a full URI with https/http/file scheme."
|
"If relative, specifies the path to cabal.project inside the unpacked HLS tarball/checkout. If absolute, will copy the file over."
|
||||||
<> completer fileUri
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
<*> optional
|
<*> optional
|
||||||
(option
|
(option
|
||||||
(eitherReader uriParser)
|
(eitherReader absolutePathParser)
|
||||||
(long "cabal-project-local" <> metavar "CABAL_PROJECT_LOCAL" <> help
|
(long "cabal-project-local" <> metavar "CABAL_PROJECT_LOCAL" <> help
|
||||||
"URI (https/http/file) to a cabal.project.local to be used for the build. Will be copied over."
|
"Absolute path to a cabal.project.local to be used for the build. Will be copied over."
|
||||||
<> completer fileUri
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
<*> (optional
|
<*> optional
|
||||||
(
|
(option
|
||||||
(fmap Right $ many $ option
|
(eitherReader absolutePathParser)
|
||||||
(eitherReader uriParser)
|
(short 'p' <> long "patchdir" <> metavar "PATCH_DIR" <> help
|
||||||
(long "patch" <> metavar "PATCH_URI" <> help
|
"Absolute path to patch directory (applies all .patch and .diff files in order using -p1)"
|
||||||
"URI to a patch (https/http/file)"
|
|
||||||
<> completer fileUri
|
|
||||||
)
|
|
||||||
)
|
|
||||||
<|>
|
|
||||||
(fmap Left $ option
|
|
||||||
str
|
|
||||||
(short 'p' <> long "patchdir" <> metavar "PATCH_DIR" <> help
|
|
||||||
"Absolute path to patch directory (applies all .patch and .diff files in order using -p1)"
|
|
||||||
<> completer (bashCompleter "directory")
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
<*> some (toolVersionArgument Nothing (Just GHC))
|
||||||
<*> some (
|
|
||||||
option (eitherReader toolVersionEither)
|
|
||||||
( long "ghc" <> metavar "GHC_VERSION|TAG" <> help "For which GHC version to compile for (can be specified multiple times)"
|
|
||||||
<> completer (tagCompleter GHC [])
|
|
||||||
<> completer (versionCompleter Nothing GHC))
|
|
||||||
)
|
|
||||||
<*> many (argument str (metavar "CABAL_ARGS" <> help "Additional arguments to cabal install, prefix with '-- ' (longopts)"))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -445,11 +403,11 @@ compile :: ( Monad m
|
|||||||
)
|
)
|
||||||
=> CompileCommand
|
=> CompileCommand
|
||||||
-> Settings
|
-> Settings
|
||||||
-> Dirs
|
|
||||||
-> (forall eff a . ReaderT AppState m (VEither eff a) -> m (VEither eff a))
|
-> (forall eff a . ReaderT AppState m (VEither eff a) -> m (VEither eff a))
|
||||||
-> (ReaderT LeanAppState m () -> m ())
|
-> (ReaderT LeanAppState m () -> m ())
|
||||||
-> m ExitCode
|
-> m ExitCode
|
||||||
compile compileCommand settings Dirs{..} runAppState runLogger = do
|
compile compileCommand settings runAppState runLogger = do
|
||||||
|
VRight Dirs{ .. } <- runAppState (VRight <$> getDirs)
|
||||||
case compileCommand of
|
case compileCommand of
|
||||||
(CompileHLS HLSCompileOptions { .. }) -> do
|
(CompileHLS HLSCompileOptions { .. }) -> do
|
||||||
runCompileHLS runAppState (do
|
runCompileHLS runAppState (do
|
||||||
@@ -472,12 +430,11 @@ compile compileCommand settings Dirs{..} runAppState runLogger = do
|
|||||||
isolateDir
|
isolateDir
|
||||||
cabalProject
|
cabalProject
|
||||||
cabalProjectLocal
|
cabalProjectLocal
|
||||||
patches
|
patchDir
|
||||||
cabalArgs
|
|
||||||
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||||
let vi = getVersionInfo targetVer HLS dls
|
let vi = getVersionInfo targetVer HLS dls
|
||||||
when setCompile $ void $ liftE $
|
when setCompile $ void $ liftE $
|
||||||
setHLS targetVer SetHLSOnly Nothing
|
setHLS targetVer
|
||||||
pure (vi, targetVer)
|
pure (vi, targetVer)
|
||||||
)
|
)
|
||||||
>>= \case
|
>>= \case
|
||||||
@@ -520,7 +477,7 @@ compile compileCommand settings Dirs{..} runAppState runLogger = do
|
|||||||
bootstrapGhc
|
bootstrapGhc
|
||||||
jobs
|
jobs
|
||||||
buildConfig
|
buildConfig
|
||||||
patches
|
patchDir
|
||||||
addConfArgs
|
addConfArgs
|
||||||
buildFlavour
|
buildFlavour
|
||||||
hadrian
|
hadrian
|
||||||
@@ -528,7 +485,7 @@ compile compileCommand settings Dirs{..} runAppState runLogger = do
|
|||||||
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||||
let vi = getVersionInfo (_tvVersion targetVer) GHC dls
|
let vi = getVersionInfo (_tvVersion targetVer) GHC dls
|
||||||
when setCompile $ void $ liftE $
|
when setCompile $ void $ liftE $
|
||||||
setGHC targetVer SetGHCOnly Nothing
|
setGHC targetVer SetGHCOnly
|
||||||
pure (vi, targetVer)
|
pure (vi, targetVer)
|
||||||
)
|
)
|
||||||
>>= \case
|
>>= \case
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
{-# LANGUAGE DuplicateRecordFields #-}
|
{-# LANGUAGE DuplicateRecordFields #-}
|
||||||
{-# LANGUAGE RankNTypes #-}
|
{-# LANGUAGE RankNTypes #-}
|
||||||
{-# LANGUAGE ExplicitForAll #-}
|
|
||||||
|
|
||||||
module GHCup.OptParse.Config where
|
module GHCup.OptParse.Config where
|
||||||
|
|
||||||
@@ -15,10 +14,9 @@ module GHCup.OptParse.Config where
|
|||||||
import GHCup.Errors
|
import GHCup.Errors
|
||||||
import GHCup.Types
|
import GHCup.Types
|
||||||
import GHCup.Utils
|
import GHCup.Utils
|
||||||
import GHCup.Utils.Prelude
|
import GHCup.Prelude
|
||||||
import GHCup.Utils.Logger
|
import GHCup.Logger
|
||||||
import GHCup.Utils.String.QQ
|
import GHCup.QQ.String
|
||||||
import GHCup.OptParse.Common
|
|
||||||
|
|
||||||
#if !MIN_VERSION_base(4,13,0)
|
#if !MIN_VERSION_base(4,13,0)
|
||||||
import Control.Monad.Fail ( MonadFail )
|
import Control.Monad.Fail ( MonadFail )
|
||||||
@@ -29,11 +27,10 @@ import Control.Monad.Trans.Resource
|
|||||||
import Data.Functor
|
import Data.Functor
|
||||||
import Data.Maybe
|
import Data.Maybe
|
||||||
import Haskus.Utils.Variant.Excepts
|
import Haskus.Utils.Variant.Excepts
|
||||||
import Options.Applicative hiding ( style, ParseError )
|
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 URI.ByteString hiding ( uriParser )
|
|
||||||
|
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import qualified Data.ByteString.UTF8 as UTF8
|
import qualified Data.ByteString.UTF8 as UTF8
|
||||||
@@ -52,7 +49,6 @@ data ConfigCommand
|
|||||||
= ShowConfig
|
= ShowConfig
|
||||||
| SetConfig String (Maybe String)
|
| SetConfig String (Maybe String)
|
||||||
| InitConfig
|
| InitConfig
|
||||||
| AddReleaseChannel URI
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -66,7 +62,6 @@ configP = subparser
|
|||||||
( command "init" initP
|
( command "init" initP
|
||||||
<> command "set" setP -- [set] KEY VALUE at help lhs
|
<> command "set" setP -- [set] KEY VALUE at help lhs
|
||||||
<> command "show" showP
|
<> command "show" showP
|
||||||
<> command "add-release-channel" addP
|
|
||||||
)
|
)
|
||||||
<|> argsP -- add show for a single option
|
<|> argsP -- add show for a single option
|
||||||
<|> pure ShowConfig
|
<|> pure ShowConfig
|
||||||
@@ -75,8 +70,6 @@ configP = subparser
|
|||||||
showP = info (pure ShowConfig) (progDesc "Show current config (default)")
|
showP = info (pure ShowConfig) (progDesc "Show current config (default)")
|
||||||
setP = info argsP (progDesc "Set config KEY to VALUE (or specify as single json value)" <> footerDoc (Just $ text configSetFooter))
|
setP = info argsP (progDesc "Set config KEY to VALUE (or specify as single json value)" <> footerDoc (Just $ text configSetFooter))
|
||||||
argsP = SetConfig <$> argument str (metavar "<JSON_VALUE | YAML_KEY>") <*> optional (argument str (metavar "YAML_VALUE"))
|
argsP = SetConfig <$> argument str (metavar "<JSON_VALUE | YAML_KEY>") <*> optional (argument str (metavar "YAML_VALUE"))
|
||||||
addP = info (AddReleaseChannel <$> argument (eitherReader uriParser) (metavar "URI" <> completer fileUri))
|
|
||||||
(progDesc "Add a release channel from a URI")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -121,18 +114,23 @@ formatConfig :: UserSettings -> String
|
|||||||
formatConfig = UTF8.toString . Y.encode
|
formatConfig = UTF8.toString . Y.encode
|
||||||
|
|
||||||
|
|
||||||
updateSettings :: UserSettings -> Settings -> Settings
|
updateSettings :: Monad m => UTF8.ByteString -> Settings -> Excepts '[JSONError] m Settings
|
||||||
updateSettings UserSettings{..} Settings{..} =
|
updateSettings config' settings = do
|
||||||
let cache' = fromMaybe cache uCache
|
settings' <- lE' (JSONDecodeError . displayException) . Y.decodeEither' $ config'
|
||||||
metaCache' = fromMaybe metaCache uMetaCache
|
pure $ mergeConf settings' settings
|
||||||
noVerify' = fromMaybe noVerify uNoVerify
|
where
|
||||||
keepDirs' = fromMaybe keepDirs uKeepDirs
|
mergeConf :: UserSettings -> Settings -> Settings
|
||||||
downloader' = fromMaybe downloader uDownloader
|
mergeConf UserSettings{..} Settings{..} =
|
||||||
verbose' = fromMaybe verbose uVerbose
|
let cache' = fromMaybe cache uCache
|
||||||
urlSource' = fromMaybe urlSource uUrlSource
|
metaCache' = fromMaybe metaCache uMetaCache
|
||||||
noNetwork' = fromMaybe noNetwork uNoNetwork
|
noVerify' = fromMaybe noVerify uNoVerify
|
||||||
gpgSetting' = fromMaybe gpgSetting uGPGSetting
|
keepDirs' = fromMaybe keepDirs uKeepDirs
|
||||||
in Settings cache' metaCache' noVerify' keepDirs' downloader' verbose' urlSource' noNetwork' gpgSetting' noColor
|
downloader' = fromMaybe downloader uDownloader
|
||||||
|
verbose' = fromMaybe verbose uVerbose
|
||||||
|
urlSource' = fromMaybe urlSource uUrlSource
|
||||||
|
noNetwork' = fromMaybe noNetwork uNoNetwork
|
||||||
|
gpgSetting' = fromMaybe gpgSetting uGPGSetting
|
||||||
|
in Settings cache' metaCache' noVerify' keepDirs' downloader' verbose' urlSource' noNetwork' gpgSetting' noColor
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -142,7 +140,7 @@ updateSettings UserSettings{..} Settings{..} =
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
config :: forall m. ( Monad m
|
config :: ( Monad m
|
||||||
, MonadMask m
|
, MonadMask m
|
||||||
, MonadUnliftIO m
|
, MonadUnliftIO m
|
||||||
, MonadFail m
|
, MonadFail m
|
||||||
@@ -163,42 +161,27 @@ config configCommand settings keybindings runLogger = case configCommand of
|
|||||||
liftIO $ putStrLn $ formatConfig $ fromSettings settings (Just keybindings)
|
liftIO $ putStrLn $ formatConfig $ fromSettings settings (Just keybindings)
|
||||||
pure ExitSuccess
|
pure ExitSuccess
|
||||||
|
|
||||||
(SetConfig k mv) -> do
|
(SetConfig k (Just v)) ->
|
||||||
r <- runE @'[JSONError, ParseError] $ do
|
case v of
|
||||||
case mv of
|
"" -> do
|
||||||
Just "" ->
|
runLogger $ logError "Empty values are not allowed"
|
||||||
throwE $ ParseError "Empty values are not allowed"
|
pure $ ExitFailure 55
|
||||||
Nothing -> do
|
_ -> doConfig (k <> ": " <> v <> "\n")
|
||||||
usersettings <- decodeSettings k
|
|
||||||
lift $ doConfig usersettings
|
|
||||||
pure ()
|
|
||||||
Just v -> do
|
|
||||||
usersettings <- decodeSettings (k <> ": " <> v <> "\n")
|
|
||||||
lift $ doConfig usersettings
|
|
||||||
pure ()
|
|
||||||
case r of
|
|
||||||
VRight _ -> pure ExitSuccess
|
|
||||||
VLeft (V (JSONDecodeError e)) -> do
|
|
||||||
runLogger $ logError $ "Error decoding config: " <> T.pack e
|
|
||||||
pure $ ExitFailure 65
|
|
||||||
VLeft _ -> pure $ ExitFailure 65
|
|
||||||
|
|
||||||
AddReleaseChannel uri -> do
|
(SetConfig json Nothing) -> doConfig json
|
||||||
case urlSource settings of
|
|
||||||
AddSource xs -> do
|
|
||||||
doConfig (defaultUserSettings { uUrlSource = Just $ AddSource (xs <> [Right uri]) })
|
|
||||||
pure ExitSuccess
|
|
||||||
_ -> do
|
|
||||||
doConfig (defaultUserSettings { uUrlSource = Just $ AddSource [Right uri] })
|
|
||||||
pure ExitSuccess
|
|
||||||
|
|
||||||
where
|
where
|
||||||
doConfig :: MonadIO m => UserSettings -> m ()
|
doConfig val = do
|
||||||
doConfig usersettings = do
|
r <- runE @'[JSONError] $ do
|
||||||
let settings' = updateSettings usersettings settings
|
settings' <- updateSettings (UTF8.fromString val) settings
|
||||||
path <- liftIO getConfigFilePath
|
path <- liftIO getConfigFilePath
|
||||||
liftIO $ writeFile path $ formatConfig $ fromSettings settings' (Just keybindings)
|
liftIO $ writeFile path $ formatConfig $ fromSettings settings' (Just keybindings)
|
||||||
runLogger $ logDebug $ T.pack $ show settings'
|
lift $ runLogger $ logDebug $ T.pack $ show settings'
|
||||||
pure ()
|
pure ()
|
||||||
|
|
||||||
decodeSettings = lE' (JSONDecodeError . displayException) . Y.decodeEither' . UTF8.fromString
|
case r of
|
||||||
|
VRight _ -> pure ExitSuccess
|
||||||
|
VLeft (V (JSONDecodeError e)) -> do
|
||||||
|
runLogger $ logError $ "Error decoding config: " <> T.pack e
|
||||||
|
pure $ ExitFailure 65
|
||||||
|
VLeft _ -> pure $ ExitFailure 65
|
||||||
|
|||||||
@@ -17,9 +17,10 @@ import GHCup
|
|||||||
import GHCup.Errors
|
import GHCup.Errors
|
||||||
import GHCup.Version
|
import GHCup.Version
|
||||||
import GHCup.Types
|
import GHCup.Types
|
||||||
import GHCup.Utils.Prelude
|
import GHCup.Prelude
|
||||||
import GHCup.Utils.Dirs
|
import GHCup.Directories
|
||||||
import GHCup.Utils.Logger
|
import GHCup.Logger
|
||||||
|
import GHCup.System.Process
|
||||||
|
|
||||||
#if !MIN_VERSION_base(4,13,0)
|
#if !MIN_VERSION_base(4,13,0)
|
||||||
import Control.Monad.Fail ( MonadFail )
|
import Control.Monad.Fail ( MonadFail )
|
||||||
@@ -36,7 +37,6 @@ 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)
|
||||||
import GHCup.Utils.File
|
|
||||||
import Language.Haskell.TH
|
import Language.Haskell.TH
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ module GHCup.OptParse.GC where
|
|||||||
import GHCup
|
import GHCup
|
||||||
import GHCup.Errors
|
import GHCup.Errors
|
||||||
import GHCup.Types
|
import GHCup.Types
|
||||||
import GHCup.Utils.Logger
|
import GHCup.Logger
|
||||||
import GHCup.Utils.String.QQ
|
import GHCup.QQ.String
|
||||||
|
|
||||||
#if !MIN_VERSION_base(4,13,0)
|
#if !MIN_VERSION_base(4,13,0)
|
||||||
import Control.Monad.Fail ( MonadFail )
|
import Control.Monad.Fail ( MonadFail )
|
||||||
@@ -132,7 +132,7 @@ gc GCOptions{..} runAppState runLogger = runGC runAppState (do
|
|||||||
when gcOldGHC rmOldGHC
|
when gcOldGHC rmOldGHC
|
||||||
lift $ when gcProfilingLibs rmProfilingLibs
|
lift $ when gcProfilingLibs rmProfilingLibs
|
||||||
lift $ when gcShareDir rmShareDir
|
lift $ when gcShareDir rmShareDir
|
||||||
liftE $ when gcHLSNoGHC rmHLSNoGHC
|
lift $ when gcHLSNoGHC rmHLSNoGHC
|
||||||
lift $ when gcCache rmCache
|
lift $ when gcCache rmCache
|
||||||
lift $ when gcTmp rmTmp
|
lift $ when gcTmp rmTmp
|
||||||
) >>= \case
|
) >>= \case
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
{-# LANGUAGE QuasiQuotes #-}
|
{-# LANGUAGE QuasiQuotes #-}
|
||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
{-# LANGUAGE DuplicateRecordFields #-}
|
{-# LANGUAGE DuplicateRecordFields #-}
|
||||||
{-# LANGUAGE ViewPatterns #-}
|
|
||||||
|
|
||||||
module GHCup.OptParse.Install where
|
module GHCup.OptParse.Install where
|
||||||
|
|
||||||
@@ -18,8 +17,9 @@ import GHCup.OptParse.Common
|
|||||||
import GHCup
|
import GHCup
|
||||||
import GHCup.Errors
|
import GHCup.Errors
|
||||||
import GHCup.Types
|
import GHCup.Types
|
||||||
import GHCup.Utils.Logger
|
import GHCup.Logger
|
||||||
import GHCup.Utils.String.QQ
|
import GHCup.QQ.String
|
||||||
|
import GHCup.System.Process
|
||||||
|
|
||||||
import Codec.Archive
|
import Codec.Archive
|
||||||
#if !MIN_VERSION_base(4,13,0)
|
#if !MIN_VERSION_base(4,13,0)
|
||||||
@@ -37,7 +37,7 @@ 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 Text.PrettyPrint.HughesPJClass ( prettyShow )
|
||||||
import URI.ByteString hiding ( uriParser )
|
import URI.ByteString
|
||||||
|
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
|
|
||||||
@@ -187,18 +187,21 @@ installOpts tool =
|
|||||||
<*> ( ( (,)
|
<*> ( ( (,)
|
||||||
<$> optional
|
<$> optional
|
||||||
(option
|
(option
|
||||||
(eitherReader uriParser)
|
(eitherReader bindistParser)
|
||||||
(short 'u' <> long "url" <> metavar "BINDIST_URL" <> help
|
(short 'u' <> long "url" <> metavar "BINDIST_URL" <> help
|
||||||
"Install the specified version from this bindist"
|
"Install the specified version from this bindist"
|
||||||
<> completer (toolDlCompleter (fromMaybe GHC tool))
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
<*> (Just <$> toolVersionArgument Nothing tool)
|
<*> (Just <$> toolVersionArgument Nothing tool)
|
||||||
)
|
)
|
||||||
<|> pure (Nothing, Nothing)
|
<|> pure (Nothing, Nothing)
|
||||||
)
|
)
|
||||||
<*> fmap (fromMaybe setDefault) (invertableSwitch "set" Nothing setDefault
|
<*> flag
|
||||||
(help $ if not setDefault then "Set as active version after install" else "Don't set as active version after install"))
|
False
|
||||||
|
True
|
||||||
|
(long "set" <> help
|
||||||
|
"Set as active version after install"
|
||||||
|
)
|
||||||
<*> optional
|
<*> optional
|
||||||
(option
|
(option
|
||||||
(eitherReader isolateParser)
|
(eitherReader isolateParser)
|
||||||
@@ -206,16 +209,10 @@ installOpts tool =
|
|||||||
<> long "isolate"
|
<> long "isolate"
|
||||||
<> metavar "DIR"
|
<> metavar "DIR"
|
||||||
<> help "install in an isolated dir instead of the default one"
|
<> help "install in an isolated dir instead of the default one"
|
||||||
<> completer (bashCompleter "directory")
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
<*> switch
|
<*> switch
|
||||||
(short 'f' <> long "force" <> help "Force install")
|
(short 'f' <> long "force" <> help "Force install")
|
||||||
where
|
|
||||||
setDefault = case tool of
|
|
||||||
Nothing -> False
|
|
||||||
Just GHC -> False
|
|
||||||
Just _ -> True
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -257,48 +254,6 @@ type InstallEffects = '[ AlreadyInstalled
|
|||||||
, NoToolVersionSet
|
, NoToolVersionSet
|
||||||
, FileAlreadyExistsError
|
, FileAlreadyExistsError
|
||||||
, ProcessError
|
, ProcessError
|
||||||
|
|
||||||
, (AlreadyInstalled, ())
|
|
||||||
, (UnknownArchive, ())
|
|
||||||
, (ArchiveResult, ())
|
|
||||||
, (FileDoesNotExistError, ())
|
|
||||||
, (CopyError, ())
|
|
||||||
, (NotInstalled, ())
|
|
||||||
, (DirNotEmpty, ())
|
|
||||||
, (NoDownload, ())
|
|
||||||
, (NotInstalled, ())
|
|
||||||
, (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)
|
|
||||||
, (BuildFailed, NotInstalled)
|
|
||||||
, (TagNotFound, NotInstalled)
|
|
||||||
, (DigestError, NotInstalled)
|
|
||||||
, (GPGError, NotInstalled)
|
|
||||||
, (DownloadFailed, NotInstalled)
|
|
||||||
, (TarDirDoesNotExist, NotInstalled)
|
|
||||||
, (NextVerNotFound, NotInstalled)
|
|
||||||
, (NoToolVersionSet, NotInstalled)
|
|
||||||
, (FileAlreadyExistsError, NotInstalled)
|
|
||||||
, (ProcessError, NotInstalled)
|
|
||||||
|
|
||||||
, ((), NotInstalled)
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@@ -313,64 +268,6 @@ runInstTool appstate' mInstPlatform =
|
|||||||
@InstallEffects
|
@InstallEffects
|
||||||
|
|
||||||
|
|
||||||
type InstallGHCEffects = '[ TagNotFound
|
|
||||||
, NextVerNotFound
|
|
||||||
, NoToolVersionSet
|
|
||||||
, BuildFailed
|
|
||||||
, DirNotEmpty
|
|
||||||
, AlreadyInstalled
|
|
||||||
|
|
||||||
, (AlreadyInstalled, NotInstalled)
|
|
||||||
, (UnknownArchive, NotInstalled)
|
|
||||||
, (ArchiveResult, NotInstalled)
|
|
||||||
, (FileDoesNotExistError, NotInstalled)
|
|
||||||
, (CopyError, NotInstalled)
|
|
||||||
, (NotInstalled, NotInstalled)
|
|
||||||
, (DirNotEmpty, NotInstalled)
|
|
||||||
, (NoDownload, 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, ())
|
|
||||||
, (BuildFailed, ())
|
|
||||||
, (TagNotFound, ())
|
|
||||||
, (DigestError, ())
|
|
||||||
, (GPGError, ())
|
|
||||||
, (DownloadFailed, ())
|
|
||||||
, (TarDirDoesNotExist, ())
|
|
||||||
, (NextVerNotFound, ())
|
|
||||||
, (NoToolVersionSet, ())
|
|
||||||
, (FileAlreadyExistsError, ())
|
|
||||||
, (ProcessError, ())
|
|
||||||
|
|
||||||
, ((), NotInstalled)
|
|
||||||
]
|
|
||||||
|
|
||||||
runInstGHC :: AppState
|
|
||||||
-> Maybe PlatformRequest
|
|
||||||
-> Excepts InstallGHCEffects (ResourceT (ReaderT AppState IO)) a
|
|
||||||
-> IO (VEither InstallGHCEffects a)
|
|
||||||
runInstGHC appstate' mInstPlatform =
|
|
||||||
flip runReaderT (maybe appstate' (\x -> appstate'{ pfreq = x } :: AppState) mInstPlatform)
|
|
||||||
. runResourceT
|
|
||||||
. runE
|
|
||||||
@InstallGHCEffects
|
|
||||||
|
|
||||||
|
|
||||||
-------------------
|
-------------------
|
||||||
--[ Entrypoints ]--
|
--[ Entrypoints ]--
|
||||||
@@ -391,25 +288,23 @@ 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 -> runInstTool s' instPlatform $ do
|
||||||
(v, vi) <- liftE $ fromVersion instVer GHC
|
(v, vi) <- liftE $ fromVersion instVer GHC
|
||||||
void $ liftE $ sequenceE (installGHCBin
|
liftE $ installGHCBin
|
||||||
|
(_tvVersion v)
|
||||||
|
isolateDir
|
||||||
|
forceInstall
|
||||||
|
when instSet $ void $ liftE $ setGHC v SetGHCOnly
|
||||||
|
pure vi
|
||||||
|
Just uri -> do
|
||||||
|
runInstTool s'{ settings = settings {noVerify = True}} instPlatform $ do
|
||||||
|
(v, vi) <- liftE $ fromVersion instVer GHC
|
||||||
|
liftE $ installGHCBindist
|
||||||
|
(DownloadInfo uri (Just $ RegexDir "ghc-.*") "")
|
||||||
(_tvVersion v)
|
(_tvVersion v)
|
||||||
isolateDir
|
isolateDir
|
||||||
forceInstall
|
forceInstall
|
||||||
)
|
when instSet $ void $ liftE $ setGHC v SetGHCOnly
|
||||||
$ when instSet $ when (isNothing isolateDir) $ void $ setGHC v SetGHCOnly Nothing
|
|
||||||
pure vi
|
|
||||||
Just uri -> do
|
|
||||||
runInstGHC s'{ settings = settings {noVerify = True}} instPlatform $ do
|
|
||||||
(v, vi) <- liftE $ fromVersion instVer GHC
|
|
||||||
void $ liftE $ sequenceE (installGHCBindist
|
|
||||||
(DownloadInfo uri (Just $ RegexDir "ghc-.*") "")
|
|
||||||
(_tvVersion v)
|
|
||||||
isolateDir
|
|
||||||
forceInstall
|
|
||||||
)
|
|
||||||
$ when instSet $ when (isNothing isolateDir) $ void $ setGHC v SetGHCOnly Nothing
|
|
||||||
pure vi
|
pure vi
|
||||||
)
|
)
|
||||||
>>= \case
|
>>= \case
|
||||||
@@ -418,25 +313,14 @@ 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
|
|
||||||
runLogger $ logWarn $
|
|
||||||
"GHC ver " <> prettyVer v <> " already installed; if you really want to reinstall it, you may want to run 'ghcup install ghc --force " <> prettyVer v <> "'"
|
|
||||||
pure ExitSuccess
|
|
||||||
VLeft (V (AlreadyInstalled _ v)) -> do
|
VLeft (V (AlreadyInstalled _ v)) -> do
|
||||||
runLogger $ logWarn $
|
runLogger $ logWarn $
|
||||||
"GHC ver " <> prettyVer v <> " already installed; if you really want to reinstall it, you may want to run 'ghcup install ghc --force " <> prettyVer v <> "'"
|
"GHC ver " <> prettyVer v <> " already installed; if you really want to reinstall it, you may want to run 'ghcup install ghc --force " <> prettyVer v <> "'"
|
||||||
pure ExitSuccess
|
pure ExitSuccess
|
||||||
|
|
||||||
VLeft (V (DirNotEmpty fp)) -> do
|
VLeft (V (DirNotEmpty fp)) -> do
|
||||||
runLogger $ logWarn $
|
runLogger $ logWarn $
|
||||||
"Install directory " <> T.pack fp <> " is not empty. Use 'ghcup install ghc --isolate " <> T.pack fp <> " --force ..." <> "' to install regardless."
|
"Install directory " <> T.pack fp <> " is not empty. Use 'ghcup install ghc --isolate " <> T.pack fp <> " --force ..." <> "' to install regardless."
|
||||||
pure $ ExitFailure 3
|
pure $ ExitFailure 3
|
||||||
VLeft (V (DirNotEmpty fp, ())) -> do
|
|
||||||
runLogger $ logWarn $
|
|
||||||
"Install directory " <> T.pack fp <> " is not empty. Use 'ghcup install ghc --isolate " <> T.pack fp <> " --force ..." <> "' to install regardless."
|
|
||||||
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 $ prettyShow err)
|
||||||
@@ -444,14 +328,6 @@ install installCommand settings getAppState' runLogger = case installCommand of
|
|||||||
"Check the logs at " <> T.pack logsDir <> " and the build directory " <> T.pack tmpdir <> " for more clues." <> "\n" <>
|
"Check the logs at " <> T.pack 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
|
|
||||||
case keepDirs settings of
|
|
||||||
Never -> runLogger (logError $ T.pack $ prettyShow err)
|
|
||||||
_ -> runLogger (logError $ T.pack (prettyShow err) <> "\n" <>
|
|
||||||
"Check the logs at " <> T.pack logsDir <> " and the build directory " <> T.pack tmpdir <> " for more clues." <> "\n" <>
|
|
||||||
"Make sure to clean up " <> T.pack tmpdir <> " afterwards.")
|
|
||||||
pure $ ExitFailure 3
|
|
||||||
|
|
||||||
VLeft e -> do
|
VLeft e -> do
|
||||||
runLogger $ do
|
runLogger $ do
|
||||||
logError $ T.pack $ prettyShow e
|
logError $ T.pack $ prettyShow e
|
||||||
@@ -464,22 +340,20 @@ install installCommand settings getAppState' runLogger = case installCommand of
|
|||||||
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' instPlatform $ do
|
||||||
(_tvVersion -> v, vi) <- liftE $ fromVersion instVer Cabal
|
(v, vi) <- liftE $ fromVersion instVer Cabal
|
||||||
void $ liftE $ sequenceE (installCabalBin
|
liftE $ installCabalBin
|
||||||
v
|
(_tvVersion v)
|
||||||
isolateDir
|
isolateDir
|
||||||
forceInstall
|
forceInstall
|
||||||
) $ when instSet $ when (isNothing isolateDir) $ void $ 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}} instPlatform $ do
|
||||||
(_tvVersion -> v, vi) <- liftE $ fromVersion instVer Cabal
|
(v, vi) <- liftE $ fromVersion instVer Cabal
|
||||||
void $ liftE $ sequenceE (installCabalBindist
|
liftE $ installCabalBindist
|
||||||
(DownloadInfo uri Nothing "")
|
(DownloadInfo uri Nothing "")
|
||||||
v
|
(_tvVersion v)
|
||||||
isolateDir
|
isolateDir
|
||||||
forceInstall
|
forceInstall
|
||||||
) $ when instSet $ when (isNothing isolateDir) $ void $ setCabal v
|
|
||||||
pure vi
|
pure vi
|
||||||
)
|
)
|
||||||
>>= \case
|
>>= \case
|
||||||
@@ -496,14 +370,6 @@ install installCommand settings getAppState' runLogger = case installCommand of
|
|||||||
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
|
|
||||||
runLogger $ logWarn $
|
|
||||||
"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
|
|
||||||
VLeft (V (FileAlreadyExistsError fp, ())) -> do
|
|
||||||
runLogger $ logWarn $
|
|
||||||
"File " <> T.pack fp <> " already exists. Use 'ghcup install cabal --isolate " <> T.pack fp <> " --force ..." <> "' if you want to overwrite."
|
|
||||||
pure $ ExitFailure 3
|
|
||||||
VLeft e -> do
|
VLeft e -> do
|
||||||
runLogger $ do
|
runLogger $ do
|
||||||
logError $ T.pack $ prettyShow e
|
logError $ T.pack $ prettyShow e
|
||||||
@@ -515,23 +381,20 @@ install installCommand settings getAppState' runLogger = case installCommand of
|
|||||||
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' instPlatform $ do
|
||||||
(_tvVersion -> v, vi) <- liftE $ fromVersion instVer HLS
|
(v, vi) <- liftE $ fromVersion instVer HLS
|
||||||
void $ liftE $ sequenceE (installHLSBin
|
liftE $ installHLSBin
|
||||||
v
|
(_tvVersion v)
|
||||||
isolateDir
|
isolateDir
|
||||||
forceInstall
|
forceInstall
|
||||||
) $ when instSet $ when (isNothing isolateDir) $ void $ 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}} instPlatform $ do
|
||||||
(_tvVersion -> v, vi) <- liftE $ fromVersion instVer HLS
|
(v, vi) <- liftE $ fromVersion instVer HLS
|
||||||
-- TODO: support legacy
|
liftE $ installHLSBindist
|
||||||
void $ liftE $ sequenceE (installHLSBindist
|
(DownloadInfo uri Nothing "")
|
||||||
(DownloadInfo uri (Just $ RegexDir "haskell-language-server-*") "")
|
(_tvVersion v)
|
||||||
v
|
isolateDir
|
||||||
isolateDir
|
forceInstall
|
||||||
forceInstall
|
|
||||||
) $ when instSet $ when (isNothing isolateDir) $ void $ setHLS v SetHLSOnly Nothing
|
|
||||||
pure vi
|
pure vi
|
||||||
)
|
)
|
||||||
>>= \case
|
>>= \case
|
||||||
@@ -552,18 +415,6 @@ install installCommand settings getAppState' runLogger = case installCommand of
|
|||||||
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
|
|
||||||
runLogger $ logWarn $
|
|
||||||
"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
|
|
||||||
VLeft (V (FileAlreadyExistsError fp, ())) -> do
|
|
||||||
runLogger $ logWarn $
|
|
||||||
"File " <> T.pack fp <> " already exists. Use 'ghcup install hls --isolate " <> T.pack fp <> " --force ..." <> "' if you want to overwrite."
|
|
||||||
pure $ ExitFailure 3
|
|
||||||
VLeft e -> do
|
VLeft e -> do
|
||||||
runLogger $ do
|
runLogger $ do
|
||||||
logError $ T.pack $ prettyShow e
|
logError $ T.pack $ prettyShow e
|
||||||
@@ -575,22 +426,20 @@ install installCommand settings getAppState' runLogger = case installCommand of
|
|||||||
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' instPlatform $ do
|
||||||
(_tvVersion -> v, vi) <- liftE $ fromVersion instVer Stack
|
(v, vi) <- liftE $ fromVersion instVer Stack
|
||||||
void $ liftE $ sequenceE (installStackBin
|
liftE $ installStackBin
|
||||||
v
|
(_tvVersion v)
|
||||||
isolateDir
|
isolateDir
|
||||||
forceInstall
|
forceInstall
|
||||||
) $ when instSet $ when (isNothing isolateDir) $ void $ 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}} instPlatform $ do
|
||||||
(_tvVersion -> v, vi) <- liftE $ fromVersion instVer Stack
|
(v, vi) <- liftE $ fromVersion instVer Stack
|
||||||
void $ liftE $ sequenceE (installStackBindist
|
liftE $ installStackBindist
|
||||||
(DownloadInfo uri Nothing "")
|
(DownloadInfo uri Nothing "")
|
||||||
v
|
(_tvVersion v)
|
||||||
isolateDir
|
isolateDir
|
||||||
forceInstall
|
forceInstall
|
||||||
) $ when instSet $ when (isNothing isolateDir) $ void $ setStack v
|
|
||||||
pure vi
|
pure vi
|
||||||
)
|
)
|
||||||
>>= \case
|
>>= \case
|
||||||
@@ -607,14 +456,6 @@ install installCommand settings getAppState' runLogger = case installCommand of
|
|||||||
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
|
|
||||||
runLogger $ logWarn $
|
|
||||||
"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
|
|
||||||
VLeft (V (FileAlreadyExistsError fp, ())) -> do
|
|
||||||
runLogger $ logWarn $
|
|
||||||
"File " <> T.pack fp <> " already exists. Use 'ghcup install stack --isolate " <> T.pack fp <> " --force ..." <> "' if you want to overwrite."
|
|
||||||
pure $ ExitFailure 3
|
|
||||||
VLeft e -> do
|
VLeft e -> do
|
||||||
runLogger $ do
|
runLogger $ do
|
||||||
logError $ T.pack $ prettyShow e
|
logError $ T.pack $ prettyShow e
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ module GHCup.OptParse.List where
|
|||||||
|
|
||||||
|
|
||||||
import GHCup
|
import GHCup
|
||||||
import GHCup.Utils.Prelude
|
import GHCup.Prelude
|
||||||
import GHCup.Types
|
import GHCup.Types
|
||||||
import GHCup.OptParse.Common
|
import GHCup.OptParse.Common
|
||||||
|
|
||||||
@@ -69,7 +69,6 @@ listOpts =
|
|||||||
(eitherReader toolParser)
|
(eitherReader toolParser)
|
||||||
(short 't' <> long "tool" <> metavar "<ghc|cabal|hls|stack>" <> help
|
(short 't' <> long "tool" <> metavar "<ghc|cabal|hls|stack>" <> help
|
||||||
"Tool to list versions for. Default is all"
|
"Tool to list versions for. Default is all"
|
||||||
<> completer (toolCompleter)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
<*> optional
|
<*> optional
|
||||||
@@ -79,7 +78,6 @@ listOpts =
|
|||||||
<> long "show-criteria"
|
<> long "show-criteria"
|
||||||
<> metavar "<installed|set|available>"
|
<> metavar "<installed|set|available>"
|
||||||
<> help "Show only installed/set/available tool versions"
|
<> help "Show only installed/set/available tool versions"
|
||||||
<> completer (listCompleter ["installed", "set", "available"])
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
<*> switch
|
<*> switch
|
||||||
@@ -143,11 +141,11 @@ printListResult no_color raw lr = do
|
|||||||
)
|
)
|
||||||
$ lr
|
$ lr
|
||||||
let cols =
|
let cols =
|
||||||
foldr (\xs ys -> zipWith (:) xs ys) (repeat []) rows
|
foldr (\xs ys -> zipWith (:) xs ys) (replicate (length rows) []) rows
|
||||||
lengths = fmap (maximum . fmap strWidth) cols
|
lengths = fmap (maximum . fmap strWidth) cols
|
||||||
padded = fmap (\xs -> zipWith padTo xs lengths) rows
|
padded = fmap (\xs -> zipWith padTo xs lengths) rows
|
||||||
|
|
||||||
forM_ (if raw then rows else padded) $ \row -> putStrLn $ unwords row
|
forM_ padded $ \row -> putStrLn $ unwords row
|
||||||
where
|
where
|
||||||
|
|
||||||
padTo str' x =
|
padTo str' x =
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ module GHCup.OptParse.Nuke where
|
|||||||
import GHCup
|
import GHCup
|
||||||
import GHCup.Errors
|
import GHCup.Errors
|
||||||
import GHCup.Types
|
import GHCup.Types
|
||||||
import GHCup.Utils.Logger
|
import GHCup.Logger
|
||||||
|
|
||||||
#if !MIN_VERSION_base(4,13,0)
|
#if !MIN_VERSION_base(4,13,0)
|
||||||
import Control.Monad.Fail ( MonadFail )
|
import Control.Monad.Fail ( MonadFail )
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ module GHCup.OptParse.Prefetch where
|
|||||||
import GHCup
|
import GHCup
|
||||||
import GHCup.Errors
|
import GHCup.Errors
|
||||||
import GHCup.Types
|
import GHCup.Types
|
||||||
import GHCup.Utils.Logger
|
import GHCup.Logger
|
||||||
import GHCup.OptParse.Common
|
import GHCup.OptParse.Common
|
||||||
import GHCup.Utils.String.QQ
|
import GHCup.QQ.String
|
||||||
|
|
||||||
#if !MIN_VERSION_base(4,13,0)
|
#if !MIN_VERSION_base(4,13,0)
|
||||||
import Control.Monad.Fail ( MonadFail )
|
import Control.Monad.Fail ( MonadFail )
|
||||||
@@ -33,7 +33,7 @@ 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)
|
||||||
import GHCup.Utils.Prelude
|
import GHCup.Prelude
|
||||||
import GHCup.Download (getDownloadsF)
|
import GHCup.Download (getDownloadsF)
|
||||||
|
|
||||||
|
|
||||||
@@ -83,7 +83,7 @@ prefetchP = subparser
|
|||||||
(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/)")))
|
||||||
<*> optional (toolVersionArgument Nothing (Just GHC)) )
|
<*> optional (toolVersionArgument Nothing (Just GHC)) )
|
||||||
( progDesc "Download GHC assets for installation")
|
( progDesc "Download GHC assets for installation")
|
||||||
)
|
)
|
||||||
@@ -92,7 +92,7 @@ prefetchP = subparser
|
|||||||
"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/)")))
|
||||||
<*> ( optional (toolVersionArgument Nothing (Just Cabal)) <**> helper ))
|
<*> ( optional (toolVersionArgument Nothing (Just Cabal)) <**> helper ))
|
||||||
( progDesc "Download cabal assets for installation")
|
( progDesc "Download cabal assets for installation")
|
||||||
)
|
)
|
||||||
@@ -101,7 +101,7 @@ prefetchP = subparser
|
|||||||
"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/)")))
|
||||||
<*> ( optional (toolVersionArgument Nothing (Just HLS)) <**> helper ))
|
<*> ( optional (toolVersionArgument Nothing (Just HLS)) <**> helper ))
|
||||||
( progDesc "Download HLS assets for installation")
|
( progDesc "Download HLS assets for installation")
|
||||||
)
|
)
|
||||||
@@ -110,7 +110,7 @@ prefetchP = subparser
|
|||||||
"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/)")))
|
||||||
<*> ( optional (toolVersionArgument Nothing (Just Stack)) <**> helper ))
|
<*> ( optional (toolVersionArgument Nothing (Just Stack)) <**> helper ))
|
||||||
( progDesc "Download stack assets for installation")
|
( progDesc "Download stack assets for installation")
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -18,9 +18,9 @@ import GHCup.Errors
|
|||||||
import GHCup.Types
|
import GHCup.Types
|
||||||
import GHCup.Types.Optics
|
import GHCup.Types.Optics
|
||||||
import GHCup.Utils
|
import GHCup.Utils
|
||||||
import GHCup.Utils.Logger
|
import GHCup.Logger
|
||||||
import GHCup.OptParse.Common
|
import GHCup.OptParse.Common
|
||||||
import GHCup.Utils.String.QQ
|
import GHCup.QQ.String
|
||||||
|
|
||||||
#if !MIN_VERSION_base(4,13,0)
|
#if !MIN_VERSION_base(4,13,0)
|
||||||
import Control.Monad.Fail ( MonadFail )
|
import Control.Monad.Fail ( MonadFail )
|
||||||
|
|||||||
@@ -1,463 +0,0 @@
|
|||||||
{-# LANGUAGE CPP #-}
|
|
||||||
{-# LANGUAGE QuasiQuotes #-}
|
|
||||||
{-# LANGUAGE TypeApplications #-}
|
|
||||||
{-# LANGUAGE DataKinds #-}
|
|
||||||
{-# LANGUAGE RankNTypes #-}
|
|
||||||
{-# LANGUAGE FlexibleContexts #-}
|
|
||||||
{-# LANGUAGE TypeFamilies #-}
|
|
||||||
module GHCup.OptParse.Run where
|
|
||||||
|
|
||||||
|
|
||||||
import GHCup
|
|
||||||
import GHCup.Utils
|
|
||||||
import GHCup.Utils.Prelude
|
|
||||||
import GHCup.Utils.File
|
|
||||||
import GHCup.OptParse.Common
|
|
||||||
import GHCup.Errors
|
|
||||||
import GHCup.Types
|
|
||||||
import GHCup.Types.Optics
|
|
||||||
import GHCup.Utils.Logger
|
|
||||||
import GHCup.Utils.String.QQ
|
|
||||||
|
|
||||||
import Control.Exception.Safe ( MonadMask, MonadCatch )
|
|
||||||
#if !MIN_VERSION_base(4,13,0)
|
|
||||||
import Control.Monad.Fail ( MonadFail )
|
|
||||||
#endif
|
|
||||||
import Codec.Archive
|
|
||||||
import Control.Monad.Reader
|
|
||||||
import Control.Monad.Trans.Resource
|
|
||||||
import Data.Functor
|
|
||||||
import Data.Maybe (isNothing)
|
|
||||||
import Data.List ( intercalate )
|
|
||||||
import Haskus.Utils.Variant.Excepts
|
|
||||||
import Options.Applicative hiding ( style )
|
|
||||||
import Prelude hiding ( appendFile )
|
|
||||||
import System.Directory
|
|
||||||
import System.FilePath
|
|
||||||
import System.Environment
|
|
||||||
import System.Exit
|
|
||||||
import Text.PrettyPrint.HughesPJClass ( prettyShow )
|
|
||||||
|
|
||||||
import qualified Data.Map.Strict as Map
|
|
||||||
import qualified Data.Text as T
|
|
||||||
#ifndef IS_WINDOWS
|
|
||||||
import qualified System.Posix.Process as SPP
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
---------------
|
|
||||||
--[ Options ]--
|
|
||||||
---------------
|
|
||||||
|
|
||||||
|
|
||||||
data RunOptions = RunOptions
|
|
||||||
{ runAppendPATH :: Bool
|
|
||||||
, runInstTool' :: Bool
|
|
||||||
, runGHCVer :: Maybe ToolVersion
|
|
||||||
, runCabalVer :: Maybe ToolVersion
|
|
||||||
, runHLSVer :: Maybe ToolVersion
|
|
||||||
, runStackVer :: Maybe ToolVersion
|
|
||||||
, runBinDir :: Maybe FilePath
|
|
||||||
, runCOMMAND :: [String]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
---------------
|
|
||||||
--[ Parsers ]--
|
|
||||||
---------------
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
runOpts :: Parser RunOptions
|
|
||||||
runOpts =
|
|
||||||
RunOptions
|
|
||||||
<$> switch
|
|
||||||
(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
|
|
||||||
(short 'i' <> long "install" <> help "Install the tool, if missing")
|
|
||||||
<*> optional
|
|
||||||
(option
|
|
||||||
(eitherReader toolVersionEither)
|
|
||||||
(metavar "GHC_VERSION" <> long "ghc" <> help "The ghc version"
|
|
||||||
<> completer (tagCompleter GHC [])
|
|
||||||
<> (completer $ versionCompleter Nothing GHC)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
<*> optional
|
|
||||||
(option
|
|
||||||
(eitherReader toolVersionEither)
|
|
||||||
(metavar "CABAL_VERSION" <> long "cabal" <> help "The cabal version"
|
|
||||||
<> completer (tagCompleter Cabal [])
|
|
||||||
<> (completer $ versionCompleter Nothing Cabal)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
<*> optional
|
|
||||||
(option
|
|
||||||
(eitherReader toolVersionEither)
|
|
||||||
(metavar "HLS_VERSION" <> long "hls" <> help "The HLS version"
|
|
||||||
<> completer (tagCompleter HLS [])
|
|
||||||
<> (completer $ versionCompleter Nothing HLS)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
<*> optional
|
|
||||||
(option
|
|
||||||
(eitherReader toolVersionEither)
|
|
||||||
(metavar "STACK_VERSION" <> long "stack" <> help "The stack version"
|
|
||||||
<> completer (tagCompleter Stack [])
|
|
||||||
<> (completer $ versionCompleter Nothing Stack)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
<*> optional
|
|
||||||
(option
|
|
||||||
(eitherReader isolateParser)
|
|
||||||
( short 'b'
|
|
||||||
<> long "bindir"
|
|
||||||
<> metavar "DIR"
|
|
||||||
<> help "directory where to create the tool symlinks (default: newly created system temp dir)"
|
|
||||||
<> completer (bashCompleter "directory")
|
|
||||||
)
|
|
||||||
)
|
|
||||||
<*> many (argument str (metavar "COMMAND" <> help "The command to run, with arguments (use longopts --). If omitted, just prints the created bin/ dir to stdout and exits."))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--------------
|
|
||||||
--[ Footer ]--
|
|
||||||
--------------
|
|
||||||
|
|
||||||
|
|
||||||
runFooter :: String
|
|
||||||
runFooter = [s|Discussion:
|
|
||||||
Adds the given tools to a dedicated bin/ directory and adds them to PATH, exposing
|
|
||||||
the relevant binaries, then executes a command.
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
# run VSCode with all latest toolchain exposed, installing missing versions if necessary
|
|
||||||
ghcup run --ghc latest --cabal latest --hls latest --stack latest --install -- code Setup.hs
|
|
||||||
|
|
||||||
# create a custom toolchain bin/ dir with GHC and cabal that can be manually added to PATH
|
|
||||||
ghcup run --ghc 8.10.7 --cabal 3.2.0.0 --bindir $HOME/toolchain/bin
|
|
||||||
|
|
||||||
# run a specific ghc version
|
|
||||||
ghcup run --ghc 8.10.7 -- ghc --version|]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
---------------------------
|
|
||||||
--[ Effect interpreters ]--
|
|
||||||
---------------------------
|
|
||||||
|
|
||||||
|
|
||||||
type RunEffects = '[ AlreadyInstalled
|
|
||||||
, UnknownArchive
|
|
||||||
, ArchiveResult
|
|
||||||
, FileDoesNotExistError
|
|
||||||
, CopyError
|
|
||||||
, NotInstalled
|
|
||||||
, DirNotEmpty
|
|
||||||
, NoDownload
|
|
||||||
, NotInstalled
|
|
||||||
, BuildFailed
|
|
||||||
, TagNotFound
|
|
||||||
, DigestError
|
|
||||||
, GPGError
|
|
||||||
, DownloadFailed
|
|
||||||
, TarDirDoesNotExist
|
|
||||||
, NextVerNotFound
|
|
||||||
, NoToolVersionSet
|
|
||||||
, FileAlreadyExistsError
|
|
||||||
, ProcessError
|
|
||||||
]
|
|
||||||
|
|
||||||
runLeanRUN :: (MonadUnliftIO m, MonadIO m)
|
|
||||||
=> LeanAppState
|
|
||||||
-> Excepts RunEffects (ReaderT LeanAppState m) a
|
|
||||||
-> m (VEither RunEffects a)
|
|
||||||
runLeanRUN leanAppstate =
|
|
||||||
-- Don't use runLeanAppState here, which is disabled on windows.
|
|
||||||
-- This is the only command on all platforms that doesn't need full appstate.
|
|
||||||
flip runReaderT leanAppstate
|
|
||||||
. runE
|
|
||||||
@RunEffects
|
|
||||||
|
|
||||||
runRUN :: MonadUnliftIO m
|
|
||||||
=> IO AppState
|
|
||||||
-> Excepts RunEffects (ResourceT (ReaderT AppState m)) a
|
|
||||||
-> m (VEither RunEffects a)
|
|
||||||
runRUN appState action' = do
|
|
||||||
s' <- liftIO appState
|
|
||||||
flip runReaderT s'
|
|
||||||
. runResourceT
|
|
||||||
. runE
|
|
||||||
@RunEffects
|
|
||||||
$ action'
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
------------------
|
|
||||||
--[ Entrypoint ]--
|
|
||||||
------------------
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
run :: forall m.
|
|
||||||
( MonadFail m
|
|
||||||
, MonadMask m
|
|
||||||
, MonadCatch m
|
|
||||||
, MonadIO m
|
|
||||||
, MonadUnliftIO m
|
|
||||||
)
|
|
||||||
=> RunOptions
|
|
||||||
-> IO AppState
|
|
||||||
-> LeanAppState
|
|
||||||
-> (ReaderT LeanAppState m () -> m ())
|
|
||||||
-> m ExitCode
|
|
||||||
run RunOptions{..} runAppState leanAppstate runLogger = do
|
|
||||||
r <- if or (fmap (maybe False isToolTag) [runGHCVer, runCabalVer, runHLSVer, runStackVer]) || runInstTool'
|
|
||||||
then runRUN runAppState $ do
|
|
||||||
toolchain <- liftE resolveToolchainFull
|
|
||||||
tmp <- case runBinDir of
|
|
||||||
Just bindir -> do
|
|
||||||
liftIO $ createDirRecursive' bindir
|
|
||||||
liftIO $ canonicalizePath bindir
|
|
||||||
Nothing -> do
|
|
||||||
d <- liftIO $ predictableTmpDir toolchain
|
|
||||||
liftIO $ createDirRecursive' d
|
|
||||||
liftIO $ canonicalizePath d
|
|
||||||
liftE $ installToolChainFull toolchain tmp
|
|
||||||
pure tmp
|
|
||||||
else runLeanRUN leanAppstate $ do
|
|
||||||
toolchain <- resolveToolchain
|
|
||||||
tmp <- case runBinDir of
|
|
||||||
Just bindir -> do
|
|
||||||
liftIO $ createDirRecursive' bindir
|
|
||||||
liftIO $ canonicalizePath bindir
|
|
||||||
Nothing -> do
|
|
||||||
d <- liftIO $ predictableTmpDir toolchain
|
|
||||||
liftIO $ createDirRecursive' d
|
|
||||||
liftIO $ canonicalizePath d
|
|
||||||
liftE $ installToolChain toolchain tmp
|
|
||||||
pure tmp
|
|
||||||
case r of
|
|
||||||
VRight tmp -> do
|
|
||||||
case runCOMMAND of
|
|
||||||
[] -> do
|
|
||||||
liftIO $ putStr tmp
|
|
||||||
pure ExitSuccess
|
|
||||||
(cmd:args) -> do
|
|
||||||
newEnv <- liftIO $ addToPath tmp
|
|
||||||
#ifndef IS_WINDOWS
|
|
||||||
void $ liftIO $ SPP.executeFile cmd True args (Just newEnv)
|
|
||||||
pure ExitSuccess
|
|
||||||
#else
|
|
||||||
r' <- runLeanRUN leanAppstate $ liftE $ lEM @_ @'[ProcessError] $ exec cmd args Nothing (Just newEnv)
|
|
||||||
case r' of
|
|
||||||
VRight _ -> pure ExitSuccess
|
|
||||||
VLeft e -> do
|
|
||||||
runLogger $ logError $ T.pack $ prettyShow e
|
|
||||||
pure $ ExitFailure 28
|
|
||||||
#endif
|
|
||||||
VLeft e -> do
|
|
||||||
runLogger $ logError $ T.pack $ prettyShow e
|
|
||||||
pure $ ExitFailure 27
|
|
||||||
|
|
||||||
where
|
|
||||||
|
|
||||||
isToolTag :: ToolVersion -> Bool
|
|
||||||
isToolTag (ToolTag _) = True
|
|
||||||
isToolTag _ = False
|
|
||||||
|
|
||||||
-- TODO: doesn't work for cross
|
|
||||||
resolveToolchainFull :: ( MonadFail m
|
|
||||||
, MonadThrow m
|
|
||||||
, MonadIO m
|
|
||||||
, MonadCatch m
|
|
||||||
)
|
|
||||||
=> Excepts
|
|
||||||
'[ TagNotFound
|
|
||||||
, NextVerNotFound
|
|
||||||
, NoToolVersionSet
|
|
||||||
] (ResourceT (ReaderT AppState m)) Toolchain
|
|
||||||
resolveToolchainFull = do
|
|
||||||
ghcVer <- forM runGHCVer $ \ver -> do
|
|
||||||
(v, _) <- liftE $ fromVersion (Just ver) GHC
|
|
||||||
pure v
|
|
||||||
cabalVer <- forM runCabalVer $ \ver -> do
|
|
||||||
(v, _) <- liftE $ fromVersion (Just ver) Cabal
|
|
||||||
pure v
|
|
||||||
hlsVer <- forM runHLSVer $ \ver -> do
|
|
||||||
(v, _) <- liftE $ fromVersion (Just ver) HLS
|
|
||||||
pure v
|
|
||||||
stackVer <- forM runStackVer $ \ver -> do
|
|
||||||
(v, _) <- liftE $ fromVersion (Just ver) Stack
|
|
||||||
pure v
|
|
||||||
pure Toolchain{..}
|
|
||||||
|
|
||||||
resolveToolchain = do
|
|
||||||
ghcVer <- case runGHCVer of
|
|
||||||
Just (ToolVersion v) -> pure $ Just v
|
|
||||||
Nothing -> pure Nothing
|
|
||||||
_ -> fail "Internal error"
|
|
||||||
cabalVer <- case runCabalVer of
|
|
||||||
Just (ToolVersion v) -> pure $ Just v
|
|
||||||
Nothing -> pure Nothing
|
|
||||||
_ -> fail "Internal error"
|
|
||||||
hlsVer <- case runHLSVer of
|
|
||||||
Just (ToolVersion v) -> pure $ Just v
|
|
||||||
Nothing -> pure Nothing
|
|
||||||
_ -> fail "Internal error"
|
|
||||||
stackVer <- case runStackVer of
|
|
||||||
Just (ToolVersion v) -> pure $ Just v
|
|
||||||
Nothing -> pure Nothing
|
|
||||||
_ -> fail "Internal error"
|
|
||||||
pure Toolchain{..}
|
|
||||||
|
|
||||||
installToolChainFull :: ( MonadFail m
|
|
||||||
, MonadThrow m
|
|
||||||
, MonadIO m
|
|
||||||
, MonadCatch m
|
|
||||||
)
|
|
||||||
=> Toolchain
|
|
||||||
-> FilePath
|
|
||||||
-> Excepts
|
|
||||||
'[ TagNotFound
|
|
||||||
, NextVerNotFound
|
|
||||||
, NoToolVersionSet
|
|
||||||
, UnknownArchive
|
|
||||||
, TarDirDoesNotExist
|
|
||||||
, ProcessError
|
|
||||||
, NotInstalled
|
|
||||||
, NoDownload
|
|
||||||
, GPGError
|
|
||||||
, DownloadFailed
|
|
||||||
, DirNotEmpty
|
|
||||||
, DigestError
|
|
||||||
, BuildFailed
|
|
||||||
, ArchiveResult
|
|
||||||
, AlreadyInstalled
|
|
||||||
, FileAlreadyExistsError
|
|
||||||
, CopyError
|
|
||||||
] (ResourceT (ReaderT AppState m)) ()
|
|
||||||
installToolChainFull Toolchain{..} tmp = do
|
|
||||||
forM_ [(GHC,) <$> ghcVer, (Cabal,) <$> cabalVer, (HLS,) <$> hlsVer, (Stack,) <$> stackVer] $ \mt -> do
|
|
||||||
isInstalled <- maybe (pure False) (\(tool, v) -> lift $ checkIfToolInstalled' tool v) mt
|
|
||||||
case mt of
|
|
||||||
Just (GHC, v) -> do
|
|
||||||
unless isInstalled $ when (runInstTool' && isNothing (_tvTarget v)) $ void $ liftE $ installGHCBin
|
|
||||||
(_tvVersion v)
|
|
||||||
Nothing
|
|
||||||
False
|
|
||||||
setTool GHC v tmp
|
|
||||||
Just (Cabal, v) -> do
|
|
||||||
unless isInstalled $ when runInstTool' $ void $ liftE $ installCabalBin
|
|
||||||
(_tvVersion v)
|
|
||||||
Nothing
|
|
||||||
False
|
|
||||||
setTool Cabal v tmp
|
|
||||||
Just (Stack, v) -> do
|
|
||||||
unless isInstalled $ when runInstTool' $ void $ liftE $ installStackBin
|
|
||||||
(_tvVersion v)
|
|
||||||
Nothing
|
|
||||||
False
|
|
||||||
setTool Stack v tmp
|
|
||||||
Just (HLS, v) -> do
|
|
||||||
unless isInstalled $ when runInstTool' $ void $ liftE $ installHLSBin
|
|
||||||
(_tvVersion v)
|
|
||||||
Nothing
|
|
||||||
False
|
|
||||||
setTool HLS v tmp
|
|
||||||
_ -> pure ()
|
|
||||||
|
|
||||||
installToolChain :: ( MonadFail m
|
|
||||||
, MonadThrow m
|
|
||||||
, MonadIO m
|
|
||||||
, MonadCatch m
|
|
||||||
)
|
|
||||||
=> Toolchain
|
|
||||||
-> FilePath
|
|
||||||
-> Excepts '[NotInstalled] (ReaderT LeanAppState m) ()
|
|
||||||
installToolChain Toolchain{..} tmp = do
|
|
||||||
forM_ [(GHC,) <$> ghcVer, (Cabal,) <$> cabalVer, (HLS,) <$> hlsVer, (Stack,) <$> stackVer] $ \mt -> do
|
|
||||||
case mt of
|
|
||||||
Just (GHC, v) -> setTool GHC v tmp
|
|
||||||
Just (Cabal, v) -> setTool Cabal v tmp
|
|
||||||
Just (Stack, v) -> setTool Stack v tmp
|
|
||||||
Just (HLS, v) -> setTool HLS v tmp
|
|
||||||
_ -> pure ()
|
|
||||||
|
|
||||||
setTool tool v tmp =
|
|
||||||
case tool of
|
|
||||||
GHC -> do
|
|
||||||
void $ liftE $ setGHC v SetGHC_XYZ (Just tmp)
|
|
||||||
void $ liftE $ setGHC v SetGHCOnly (Just tmp)
|
|
||||||
Cabal -> do
|
|
||||||
bin <- liftE $ whereIsTool Cabal v
|
|
||||||
cbin <- liftIO $ canonicalizePath bin
|
|
||||||
lift $ createLink (relativeSymlink tmp cbin) (tmp </> ("cabal" <.> exeExt))
|
|
||||||
Stack -> do
|
|
||||||
bin <- liftE $ whereIsTool Stack v
|
|
||||||
cbin <- liftIO $ canonicalizePath bin
|
|
||||||
lift $ createLink (relativeSymlink tmp cbin) (tmp </> ("stack" <.> exeExt))
|
|
||||||
HLS -> do
|
|
||||||
Dirs {..} <- getDirs
|
|
||||||
let v' = _tvVersion v
|
|
||||||
legacy <- isLegacyHLS v'
|
|
||||||
if legacy
|
|
||||||
then do
|
|
||||||
-- TODO: factor this out
|
|
||||||
hlsWrapper <- liftE @_ @'[NotInstalled] $ hlsWrapperBinary v' !? (NotInstalled HLS (mkTVer v'))
|
|
||||||
cw <- liftIO $ canonicalizePath (binDir </> hlsWrapper)
|
|
||||||
lift $ createLink (relativeSymlink tmp cw) (tmp </> takeFileName cw)
|
|
||||||
hlsBins <- hlsServerBinaries v' Nothing >>= liftIO . traverse (canonicalizePath . (binDir </>))
|
|
||||||
forM_ hlsBins $ \bin ->
|
|
||||||
lift $ createLink (relativeSymlink tmp bin) (tmp </> takeFileName bin)
|
|
||||||
liftE $ setHLS (_tvVersion v) SetHLSOnly (Just tmp)
|
|
||||||
else do
|
|
||||||
liftE $ setHLS (_tvVersion v) SetHLS_XYZ (Just tmp)
|
|
||||||
liftE $ setHLS (_tvVersion 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) =
|
|
||||||
liftIO (getTemporaryDirectory >>= \tmp -> pure (tmp </> "ghcup-none"))
|
|
||||||
predictableTmpDir Toolchain{..} = do
|
|
||||||
tmp <- getTemporaryDirectory
|
|
||||||
pure $ tmp
|
|
||||||
</> ("ghcup-" <> intercalate "_"
|
|
||||||
( maybe [] ( (:[]) . ("ghc-" <>) . T.unpack . tVerToText) ghcVer
|
|
||||||
<> maybe [] ( (:[]) . ("cabal-" <>) . T.unpack . tVerToText) cabalVer
|
|
||||||
<> maybe [] ( (:[]) . ("hls-" <>) . T.unpack . tVerToText) hlsVer
|
|
||||||
<> maybe [] ( (:[]) . ("stack-" <>) . T.unpack . tVerToText) stackVer
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-------------------------
|
|
||||||
--[ Other local types ]--
|
|
||||||
-------------------------
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
data Toolchain = Toolchain
|
|
||||||
{ ghcVer :: Maybe GHCTargetVersion
|
|
||||||
, cabalVer :: Maybe GHCTargetVersion
|
|
||||||
, hlsVer :: Maybe GHCTargetVersion
|
|
||||||
, stackVer :: Maybe GHCTargetVersion
|
|
||||||
}
|
|
||||||
@@ -17,8 +17,8 @@ import GHCup.OptParse.Common
|
|||||||
import GHCup
|
import GHCup
|
||||||
import GHCup.Errors
|
import GHCup.Errors
|
||||||
import GHCup.Types
|
import GHCup.Types
|
||||||
import GHCup.Utils.Logger
|
import GHCup.Logger
|
||||||
import GHCup.Utils.String.QQ
|
import GHCup.QQ.String
|
||||||
|
|
||||||
#if !MIN_VERSION_base(4,13,0)
|
#if !MIN_VERSION_base(4,13,0)
|
||||||
import Control.Monad.Fail ( MonadFail )
|
import Control.Monad.Fail ( MonadFail )
|
||||||
@@ -271,10 +271,10 @@ set setCommand runAppState runLeanAppState runLogger = case setCommand of
|
|||||||
-> m ExitCode
|
-> m ExitCode
|
||||||
setGHC' SetOptions{ sToolVer } =
|
setGHC' SetOptions{ sToolVer } =
|
||||||
case sToolVer of
|
case sToolVer of
|
||||||
(SetToolVersion v) -> runSetGHC runLeanAppState (liftE $ setGHC v SetGHCOnly Nothing >> pure v)
|
(SetToolVersion v) -> runSetGHC runLeanAppState (liftE $ setGHC v SetGHCOnly >> pure v)
|
||||||
_ -> runSetGHC runAppState (do
|
_ -> runSetGHC runAppState (do
|
||||||
v <- liftE $ fst <$> fromVersion' sToolVer GHC
|
v <- liftE $ fst <$> fromVersion' sToolVer GHC
|
||||||
liftE $ setGHC v SetGHCOnly Nothing
|
liftE $ setGHC v SetGHCOnly
|
||||||
)
|
)
|
||||||
>>= \case
|
>>= \case
|
||||||
VRight GHCTargetVersion{..} -> do
|
VRight GHCTargetVersion{..} -> do
|
||||||
@@ -311,10 +311,10 @@ set setCommand runAppState runLeanAppState runLogger = case setCommand of
|
|||||||
-> m ExitCode
|
-> m ExitCode
|
||||||
setHLS' SetOptions{ sToolVer } =
|
setHLS' SetOptions{ sToolVer } =
|
||||||
case sToolVer of
|
case sToolVer of
|
||||||
(SetToolVersion v) -> runSetHLS runLeanAppState (liftE $ setHLS (_tvVersion v) SetHLSOnly Nothing >> pure v)
|
(SetToolVersion v) -> runSetHLS runLeanAppState (liftE $ setHLS (_tvVersion v) >> pure v)
|
||||||
_ -> runSetHLS runAppState (do
|
_ -> 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)
|
||||||
pure v
|
pure v
|
||||||
)
|
)
|
||||||
>>= \case
|
>>= \case
|
||||||
|
|||||||
@@ -4,15 +4,13 @@
|
|||||||
{-# LANGUAGE FlexibleContexts #-}
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
{-# LANGUAGE DuplicateRecordFields #-}
|
{-# LANGUAGE DuplicateRecordFields #-}
|
||||||
{-# LANGUAGE RankNTypes #-}
|
{-# LANGUAGE RankNTypes #-}
|
||||||
{-# LANGUAGE QuasiQuotes #-}
|
|
||||||
|
|
||||||
module GHCup.OptParse.ToolRequirements where
|
module GHCup.OptParse.ToolRequirements where
|
||||||
|
|
||||||
|
|
||||||
import GHCup.Errors
|
import GHCup.Errors
|
||||||
import GHCup.Types
|
import GHCup.Types
|
||||||
import GHCup.Utils.Logger
|
import GHCup.Logger
|
||||||
import GHCup.Utils.String.QQ
|
|
||||||
|
|
||||||
#if !MIN_VERSION_base(4,13,0)
|
#if !MIN_VERSION_base(4,13,0)
|
||||||
import Control.Monad.Fail ( MonadFail )
|
import Control.Monad.Fail ( MonadFail )
|
||||||
@@ -30,47 +28,12 @@ import qualified Data.Text.IO as T
|
|||||||
import Control.Exception.Safe (MonadMask)
|
import Control.Exception.Safe (MonadMask)
|
||||||
import GHCup.Types.Optics
|
import GHCup.Types.Optics
|
||||||
import GHCup.Platform
|
import GHCup.Platform
|
||||||
import GHCup.Utils.Prelude
|
import GHCup.Prelude
|
||||||
import GHCup.Requirements
|
import GHCup.Requirements
|
||||||
import System.IO
|
import System.IO
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
---------------
|
|
||||||
--[ Options ]--
|
|
||||||
---------------
|
|
||||||
|
|
||||||
|
|
||||||
data ToolReqOpts = ToolReqOpts
|
|
||||||
{ tlrRaw :: Bool
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
---------------
|
|
||||||
--[ Parsers ]--
|
|
||||||
---------------
|
|
||||||
|
|
||||||
|
|
||||||
toolReqP :: Parser ToolReqOpts
|
|
||||||
toolReqP =
|
|
||||||
ToolReqOpts
|
|
||||||
<$> switch (short 'r' <> long "raw-format" <> help "machine-parsable format")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--------------
|
|
||||||
--[ Footer ]--
|
|
||||||
--------------
|
|
||||||
|
|
||||||
|
|
||||||
toolReqFooter :: String
|
|
||||||
toolReqFooter = [s|Discussion:
|
|
||||||
Print tool requirements on the current platform.
|
|
||||||
If you want to pass this to your package manage, use '--raw-format'.|]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
---------------------------
|
---------------------------
|
||||||
@@ -103,17 +66,14 @@ toolRequirements :: ( Monad m
|
|||||||
, MonadFail m
|
, MonadFail m
|
||||||
, Alternative m
|
, Alternative m
|
||||||
)
|
)
|
||||||
=> ToolReqOpts
|
=> (ReaderT AppState m (VEither ToolRequirementsEffects ()) -> m (VEither ToolRequirementsEffects ()))
|
||||||
-> (ReaderT AppState m (VEither ToolRequirementsEffects ()) -> m (VEither ToolRequirementsEffects ()))
|
|
||||||
-> (ReaderT LeanAppState m () -> m ())
|
-> (ReaderT LeanAppState m () -> m ())
|
||||||
-> m ExitCode
|
-> m ExitCode
|
||||||
toolRequirements ToolReqOpts{..} runAppState runLogger = runToolRequirements runAppState (do
|
toolRequirements runAppState runLogger = runToolRequirements runAppState (do
|
||||||
GHCupInfo { .. } <- lift getGHCupInfo
|
GHCupInfo { .. } <- lift getGHCupInfo
|
||||||
platform' <- liftE getPlatform
|
platform' <- liftE getPlatform
|
||||||
req <- getCommonRequirements platform' _toolRequirements ?? NoToolRequirements
|
req <- getCommonRequirements platform' _toolRequirements ?? NoToolRequirements
|
||||||
if tlrRaw
|
liftIO $ T.hPutStr stdout (prettyRequirements req)
|
||||||
then liftIO $ T.hPutStr stdout (rawRequirements req)
|
|
||||||
else liftIO $ T.hPutStr stdout (prettyRequirements req)
|
|
||||||
)
|
)
|
||||||
>>= \case
|
>>= \case
|
||||||
VRight _ -> pure ExitSuccess
|
VRight _ -> pure ExitSuccess
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ module GHCup.OptParse.UnSet where
|
|||||||
import GHCup
|
import GHCup
|
||||||
import GHCup.Errors
|
import GHCup.Errors
|
||||||
import GHCup.Types
|
import GHCup.Types
|
||||||
import GHCup.Utils.Logger
|
import GHCup.Logger
|
||||||
import GHCup.Utils.String.QQ
|
import GHCup.QQ.String
|
||||||
|
|
||||||
#if !MIN_VERSION_base(4,13,0)
|
#if !MIN_VERSION_base(4,13,0)
|
||||||
import Control.Monad.Fail ( MonadFail )
|
import Control.Monad.Fail ( MonadFail )
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ module GHCup.OptParse.Upgrade where
|
|||||||
import GHCup
|
import GHCup
|
||||||
import GHCup.Errors
|
import GHCup.Errors
|
||||||
import GHCup.Types
|
import GHCup.Types
|
||||||
import GHCup.Utils.Logger
|
import GHCup.Logger
|
||||||
|
|
||||||
#if !MIN_VERSION_base(4,13,0)
|
#if !MIN_VERSION_base(4,13,0)
|
||||||
import Control.Monad.Fail ( MonadFail )
|
import Control.Monad.Fail ( MonadFail )
|
||||||
@@ -72,7 +72,6 @@ upgradeOptsP =
|
|||||||
str
|
str
|
||||||
(short 't' <> long "target" <> metavar "TARGET_DIR" <> help
|
(short 't' <> long "target" <> metavar "TARGET_DIR" <> help
|
||||||
"Absolute filepath to write ghcup into"
|
"Absolute filepath to write ghcup into"
|
||||||
<> completer (bashCompleter "file")
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
<|> pure UpgradeGHCupDir
|
<|> pure UpgradeGHCupDir
|
||||||
@@ -114,17 +113,17 @@ runUpgrade runAppState =
|
|||||||
|
|
||||||
|
|
||||||
upgrade :: ( Monad m
|
upgrade :: ( Monad m
|
||||||
, MonadMask m
|
, MonadMask m
|
||||||
, MonadUnliftIO m
|
, MonadUnliftIO m
|
||||||
, MonadFail m
|
, MonadFail m
|
||||||
)
|
)
|
||||||
=> UpgradeOpts
|
=> UpgradeOpts
|
||||||
-> Bool
|
-> Bool
|
||||||
-> Dirs
|
|
||||||
-> (forall a. ReaderT AppState m (VEither UpgradeEffects a) -> m (VEither UpgradeEffects a))
|
-> (forall a. ReaderT AppState m (VEither UpgradeEffects a) -> m (VEither UpgradeEffects a))
|
||||||
-> (ReaderT LeanAppState m () -> m ())
|
-> (ReaderT LeanAppState m () -> m ())
|
||||||
-> m ExitCode
|
-> m ExitCode
|
||||||
upgrade uOpts force' Dirs{..} runAppState runLogger = do
|
upgrade uOpts force' runAppState runLogger = do
|
||||||
|
VRight Dirs{ .. } <- runAppState (VRight <$> getDirs)
|
||||||
target <- case uOpts of
|
target <- case uOpts of
|
||||||
UpgradeInplace -> Just <$> liftIO getExecutablePath
|
UpgradeInplace -> Just <$> liftIO getExecutablePath
|
||||||
(UpgradeAt p) -> pure $ Just p
|
(UpgradeAt p) -> pure $ Just p
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ import GHCup
|
|||||||
import GHCup.Errors
|
import GHCup.Errors
|
||||||
import GHCup.OptParse.Common
|
import GHCup.OptParse.Common
|
||||||
import GHCup.Types
|
import GHCup.Types
|
||||||
import GHCup.Utils.Logger
|
import GHCup.Logger
|
||||||
import GHCup.Utils.String.QQ
|
import GHCup.QQ.String
|
||||||
|
|
||||||
#if !MIN_VERSION_base(4,13,0)
|
#if !MIN_VERSION_base(4,13,0)
|
||||||
import Control.Monad.Fail ( MonadFail )
|
import Control.Monad.Fail ( MonadFail )
|
||||||
|
|||||||
@@ -20,11 +20,10 @@ import GHCup.Download
|
|||||||
import GHCup.Errors
|
import GHCup.Errors
|
||||||
import GHCup.Platform
|
import GHCup.Platform
|
||||||
import GHCup.Types
|
import GHCup.Types
|
||||||
import GHCup.Types.Optics hiding ( toolRequirements )
|
|
||||||
import GHCup.Utils
|
import GHCup.Utils
|
||||||
import GHCup.Utils.Logger
|
import GHCup.Logger
|
||||||
import GHCup.Utils.Prelude
|
import GHCup.Prelude
|
||||||
import GHCup.Utils.String.QQ
|
import GHCup.QQ.String
|
||||||
import GHCup.Version
|
import GHCup.Version
|
||||||
|
|
||||||
import Cabal.Plan ( findPlanJson, SearchPlanJson(..) )
|
import Cabal.Plan ( findPlanJson, SearchPlanJson(..) )
|
||||||
@@ -40,7 +39,6 @@ import Data.Aeson.Encode.Pretty ( encodePretty )
|
|||||||
import Data.Either
|
import Data.Either
|
||||||
import Data.Functor
|
import Data.Functor
|
||||||
import Data.Maybe
|
import Data.Maybe
|
||||||
import Data.Versions
|
|
||||||
import GHC.IO.Encoding
|
import GHC.IO.Encoding
|
||||||
import Haskus.Utils.Variant.Excepts
|
import Haskus.Utils.Variant.Excepts
|
||||||
import Language.Haskell.TH
|
import Language.Haskell.TH
|
||||||
@@ -82,7 +80,7 @@ toSettings options = do
|
|||||||
keepDirs = fromMaybe (fromMaybe (Types.keepDirs defaultSettings) uKeepDirs) optKeepDirs
|
keepDirs = fromMaybe (fromMaybe (Types.keepDirs defaultSettings) uKeepDirs) optKeepDirs
|
||||||
downloader = fromMaybe (fromMaybe defaultDownloader uDownloader) optsDownloader
|
downloader = fromMaybe (fromMaybe defaultDownloader uDownloader) optsDownloader
|
||||||
keyBindings = maybe defaultKeyBindings mergeKeys uKeyBindings
|
keyBindings = maybe defaultKeyBindings mergeKeys uKeyBindings
|
||||||
urlSource = maybe (fromMaybe (Types.urlSource defaultSettings) uUrlSource) (OwnSource . (:[]) . Right) optUrlSource
|
urlSource = maybe (fromMaybe (Types.urlSource defaultSettings) uUrlSource) OwnSource 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
|
||||||
in (Settings {..}, keyBindings)
|
in (Settings {..}, keyBindings)
|
||||||
@@ -140,12 +138,7 @@ main = do
|
|||||||
<> hidden
|
<> hidden
|
||||||
)
|
)
|
||||||
let listCommands = infoOption
|
let listCommands = infoOption
|
||||||
("install set rm install-cabal list"
|
"install set rm install-cabal list upgrade compile debug-info tool-requirements changelog"
|
||||||
#ifndef DISABLE_UPGRADE
|
|
||||||
<> " upgrade"
|
|
||||||
#endif
|
|
||||||
<> " compile debug-info tool-requirements changelog"
|
|
||||||
)
|
|
||||||
( long "list-commands"
|
( long "list-commands"
|
||||||
<> help "List available commands for shell completion"
|
<> help "List available commands for shell completion"
|
||||||
<> internal
|
<> internal
|
||||||
@@ -198,7 +191,7 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
|
|||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
|
|
||||||
let appState = do
|
appState = do
|
||||||
pfreq <- (
|
pfreq <- (
|
||||||
runLogger . runE @'[NoCompatiblePlatform, NoCompatibleArch, DistroNotFound] . liftE $ platformRequest
|
runLogger . runE @'[NoCompatiblePlatform, NoCompatibleArch, DistroNotFound] . liftE $ platformRequest
|
||||||
) >>= \case
|
) >>= \case
|
||||||
@@ -228,40 +221,14 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
|
|||||||
Nuke -> pure ()
|
Nuke -> pure ()
|
||||||
Whereis _ _ -> pure ()
|
Whereis _ _ -> pure ()
|
||||||
DInfo -> pure ()
|
DInfo -> pure ()
|
||||||
ToolRequirements _ -> pure ()
|
ToolRequirements -> pure ()
|
||||||
ChangeLog _ -> pure ()
|
ChangeLog _ -> pure ()
|
||||||
UnSet _ -> pure ()
|
UnSet _ -> pure ()
|
||||||
#if defined(BRICK)
|
#if defined(BRICK)
|
||||||
Interactive -> pure ()
|
Interactive -> pure ()
|
||||||
#endif
|
#endif
|
||||||
-- check for new tools
|
_ -> lookupEnv "GHCUP_SKIP_UPDATE_CHECK" >>= \case
|
||||||
_
|
Nothing -> runReaderT checkForUpdates s'
|
||||||
| Just False <- optVerbose -> pure ()
|
|
||||||
| otherwise -> lookupEnv "GHCUP_SKIP_UPDATE_CHECK" >>= \case
|
|
||||||
Nothing -> void . flip runReaderT s' . runE @'[TagNotFound, NextVerNotFound, NoToolVersionSet] $ do
|
|
||||||
newTools <- lift checkForUpdates
|
|
||||||
forM_ newTools $ \newTool@(t, l) -> do
|
|
||||||
-- https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/283
|
|
||||||
alreadyInstalling' <- alreadyInstalling optCommand newTool
|
|
||||||
when (not alreadyInstalling') $
|
|
||||||
case t of
|
|
||||||
#ifdef DISABLE_UPGRADE
|
|
||||||
GHCup -> pure ()
|
|
||||||
#else
|
|
||||||
GHCup -> runLogger $
|
|
||||||
logWarn ("New GHCup version available: "
|
|
||||||
<> prettyVer l
|
|
||||||
<> ". To upgrade, run 'ghcup upgrade'")
|
|
||||||
#endif
|
|
||||||
_ -> runLogger $
|
|
||||||
logWarn ("New "
|
|
||||||
<> T.pack (prettyShow t)
|
|
||||||
<> " version available. "
|
|
||||||
<> "To upgrade, run 'ghcup install "
|
|
||||||
<> T.pack (prettyShow t)
|
|
||||||
<> " "
|
|
||||||
<> prettyVer l
|
|
||||||
<> "'")
|
|
||||||
Just _ -> pure ()
|
Just _ -> pure ()
|
||||||
|
|
||||||
-- TODO: always run for windows
|
-- TODO: always run for windows
|
||||||
@@ -303,19 +270,16 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
|
|||||||
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 runAppState runLogger
|
||||||
Config configCommand -> config configCommand settings keybindings runLogger
|
Config configCommand -> config configCommand settings keybindings runLogger
|
||||||
Whereis whereisOptions
|
Whereis whereisOptions
|
||||||
whereisCommand -> whereis whereisCommand whereisOptions runAppState leanAppstate runLogger
|
whereisCommand -> whereis whereisCommand whereisOptions runAppState leanAppstate runLogger
|
||||||
#ifndef DISABLE_UPGRADE
|
Upgrade uOpts force' -> upgrade uOpts force' runAppState runLogger
|
||||||
Upgrade uOpts force' -> upgrade uOpts force' dirs runAppState runLogger
|
ToolRequirements -> toolRequirements runAppState runLogger
|
||||||
#endif
|
|
||||||
ToolRequirements topts -> toolRequirements topts runAppState runLogger
|
|
||||||
ChangeLog changelogOpts -> changelog changelogOpts runAppState runLogger
|
ChangeLog changelogOpts -> changelog changelogOpts runAppState runLogger
|
||||||
Nuke -> nuke appState runLogger
|
Nuke -> nuke appState runLogger
|
||||||
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
|
|
||||||
|
|
||||||
case res of
|
case res of
|
||||||
ExitSuccess -> pure ()
|
ExitSuccess -> pure ()
|
||||||
@@ -323,58 +287,4 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
|
|||||||
|
|
||||||
pure ()
|
pure ()
|
||||||
|
|
||||||
where
|
|
||||||
alreadyInstalling :: ( HasLog env
|
|
||||||
, MonadFail m
|
|
||||||
, MonadReader env m
|
|
||||||
, HasGHCupInfo env
|
|
||||||
, HasDirs env
|
|
||||||
, MonadThrow m
|
|
||||||
, MonadIO m
|
|
||||||
, MonadCatch m
|
|
||||||
)
|
|
||||||
=> Command
|
|
||||||
-> (Tool, Version)
|
|
||||||
-> Excepts
|
|
||||||
'[ TagNotFound
|
|
||||||
, NextVerNotFound
|
|
||||||
, NoToolVersionSet
|
|
||||||
] m Bool
|
|
||||||
alreadyInstalling (Install (Right InstallOptions{..})) (GHC, ver) = cmp' GHC instVer ver
|
|
||||||
alreadyInstalling (Install (Left (InstallGHC InstallOptions{..}))) (GHC, ver) = cmp' GHC instVer ver
|
|
||||||
alreadyInstalling (Install (Left (InstallCabal InstallOptions{..}))) (Cabal, ver) = cmp' Cabal 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 (Compile (CompileGHC GHCCompileOptions{ ovewrwiteVer = Just over }))
|
|
||||||
(GHC, ver) = cmp' GHC (Just $ ToolVersion (mkTVer over)) ver
|
|
||||||
alreadyInstalling (Compile (CompileGHC GHCCompileOptions{ targetGhc = Left tver }))
|
|
||||||
(GHC, ver) = cmp' GHC (Just $ ToolVersion (mkTVer tver)) ver
|
|
||||||
alreadyInstalling (Compile (CompileHLS HLSCompileOptions{ ovewrwiteVer = Just over }))
|
|
||||||
(HLS, ver) = cmp' HLS (Just $ ToolVersion (mkTVer over)) ver
|
|
||||||
alreadyInstalling (Compile (CompileHLS HLSCompileOptions{ targetHLS = Left tver }))
|
|
||||||
(HLS, ver) = cmp' HLS (Just $ ToolVersion (mkTVer tver)) ver
|
|
||||||
#ifndef DISABLE_UPGRADE
|
|
||||||
alreadyInstalling (Upgrade _ _) (GHCup, _) = pure True
|
|
||||||
#endif
|
|
||||||
alreadyInstalling _ _ = pure False
|
|
||||||
|
|
||||||
cmp' :: ( HasLog env
|
|
||||||
, MonadFail m
|
|
||||||
, MonadReader env m
|
|
||||||
, HasGHCupInfo env
|
|
||||||
, HasDirs env
|
|
||||||
, MonadThrow m
|
|
||||||
, MonadIO m
|
|
||||||
, MonadCatch m
|
|
||||||
)
|
|
||||||
=> Tool
|
|
||||||
-> Maybe ToolVersion
|
|
||||||
-> Version
|
|
||||||
-> Excepts
|
|
||||||
'[ TagNotFound
|
|
||||||
, NextVerNotFound
|
|
||||||
, NoToolVersionSet
|
|
||||||
] m Bool
|
|
||||||
cmp' tool instVer ver = do
|
|
||||||
(v, _) <- liftE $ fromVersion instVer tool
|
|
||||||
pure (v == mkTVer ver)
|
|
||||||
|
|||||||
@@ -8,11 +8,6 @@ package ghcup
|
|||||||
tests: True
|
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.Cabal ==3.6.2.0,
|
||||||
any.aeson >= 2.0.1.0
|
any.aeson >= 2.0.1.0
|
||||||
|
|||||||
@@ -4,18 +4,18 @@ constraints: any.Cabal ==3.6.2.0,
|
|||||||
any.HUnit ==1.6.2.0,
|
any.HUnit ==1.6.2.0,
|
||||||
any.HsOpenSSL ==0.11.7.2,
|
any.HsOpenSSL ==0.11.7.2,
|
||||||
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.QuickCheck ==2.14.2,
|
any.QuickCheck ==2.14.2,
|
||||||
QuickCheck -old-random +templatehaskell,
|
QuickCheck -old-random +templatehaskell,
|
||||||
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.0.1.0,
|
||||||
aeson -cffi +ordered-keymap,
|
aeson -bytestring-builder -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.6,
|
||||||
any.ansi-terminal ==0.11.1,
|
alex +small_base,
|
||||||
|
any.ansi-terminal ==0.11,
|
||||||
ansi-terminal -example,
|
ansi-terminal -example,
|
||||||
any.ansi-wl-pprint ==0.6.9,
|
any.ansi-wl-pprint ==0.6.9,
|
||||||
ansi-wl-pprint -example,
|
ansi-wl-pprint -example,
|
||||||
@@ -25,14 +25,14 @@ constraints: any.Cabal ==3.6.2.0,
|
|||||||
async -bench,
|
async -bench,
|
||||||
any.atomic-primops ==0.8.4,
|
any.atomic-primops ==0.8.4,
|
||||||
atomic-primops -debug,
|
atomic-primops -debug,
|
||||||
any.attoparsec ==0.14.4,
|
any.attoparsec ==0.13.2.5,
|
||||||
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.0,
|
||||||
any.base-compat-batteries ==0.12.1,
|
any.base-compat-batteries ==0.12.0,
|
||||||
any.base-orphans ==0.8.6,
|
any.base-orphans ==0.8.5,
|
||||||
any.base16-bytestring ==1.0.2.0,
|
any.base16-bytestring ==1.0.1.0,
|
||||||
any.base64-bytestring ==1.2.1.0,
|
any.base64-bytestring ==1.1.0.0,
|
||||||
any.bifunctors ==5.5.11,
|
any.bifunctors ==5.5.11,
|
||||||
bifunctors +semigroups +tagged,
|
bifunctors +semigroups +tagged,
|
||||||
any.binary ==0.8.8.0,
|
any.binary ==0.8.8.0,
|
||||||
@@ -52,7 +52,7 @@ 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,
|
any.clock ==0.8.2,
|
||||||
clock -llvm,
|
clock -llvm,
|
||||||
any.colour ==2.3.6,
|
any.colour ==2.3.6,
|
||||||
any.comonad ==5.0.8,
|
any.comonad ==5.0.8,
|
||||||
@@ -66,10 +66,10 @@ constraints: any.Cabal ==3.6.2.0,
|
|||||||
contravariant +semigroups +statevar +tagged,
|
contravariant +semigroups +statevar +tagged,
|
||||||
any.cpphs ==1.20.9.1,
|
any.cpphs ==1.20.9.1,
|
||||||
cpphs -old-locale,
|
cpphs -old-locale,
|
||||||
any.cryptohash-sha1 ==0.11.101.0,
|
any.cryptohash-sha1 ==0.11.100.1,
|
||||||
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-clist ==0.2,
|
any.data-clist ==0.1.2.3,
|
||||||
any.data-fix ==0.3.2,
|
any.data-fix ==0.3.2,
|
||||||
any.deepseq ==1.4.4.0,
|
any.deepseq ==1.4.4.0,
|
||||||
any.directory ==1.3.6.0,
|
any.directory ==1.3.6.0,
|
||||||
@@ -82,34 +82,29 @@ constraints: any.Cabal ==3.6.2.0,
|
|||||||
any.filepath ==1.4.2.1,
|
any.filepath ==1.4.2.1,
|
||||||
any.free ==5.1.7,
|
any.free ==5.1.7,
|
||||||
any.fusion-plugin-types ==0.1.0,
|
any.fusion-plugin-types ==0.1.0,
|
||||||
any.generic-arbitrary ==0.2.0,
|
any.generic-arbitrary ==0.1.0,
|
||||||
any.ghc ==8.10.7,
|
|
||||||
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.3.4.1,
|
||||||
hashable +containers +integer-gmp -random-initial-seed,
|
hashable +integer-gmp -random-initial-seed,
|
||||||
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.1,
|
||||||
any.heaps ==0.4,
|
any.heaps ==0.4,
|
||||||
any.hpc ==0.6.1.0,
|
any.hsc2hs ==0.68.7,
|
||||||
any.hsc2hs ==0.68.8,
|
|
||||||
hsc2hs -in-ghc-tree,
|
hsc2hs -in-ghc-tree,
|
||||||
any.hspec ==2.9.4,
|
any.hspec ==2.7.10,
|
||||||
any.hspec-core ==2.9.4,
|
any.hspec-core ==2.7.10,
|
||||||
any.hspec-discover ==2.9.4,
|
any.hspec-discover ==2.7.10,
|
||||||
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.0,
|
||||||
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.1,
|
||||||
any.indexed-traversable-instances ==0.1.1,
|
any.indexed-traversable-instances ==0.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,
|
||||||
@@ -117,20 +112,20 @@ constraints: any.Cabal ==3.6.2.0,
|
|||||||
io-streams +network -nointeractivetests +zlib,
|
io-streams +network -nointeractivetests +zlib,
|
||||||
any.language-c ==0.9.0.1,
|
any.language-c ==0.9.0.1,
|
||||||
language-c -allwarnings +iecfpextension +usebytestrings,
|
language-c -allwarnings +iecfpextension +usebytestrings,
|
||||||
any.libarchive ==3.0.3.2,
|
any.libarchive ==3.0.3.1,
|
||||||
libarchive -cross -low-memory +no-exe -system-libarchive,
|
libarchive -cross -low-memory -system-libarchive,
|
||||||
any.libyaml-streamly ==0.2.1,
|
any.libyaml-streamly ==0.2.0,
|
||||||
libyaml-streamly -no-unicode -system-libyaml,
|
libyaml-streamly -no-unicode -system-libyaml,
|
||||||
any.lockfree-queue ==0.2.3.1,
|
any.lockfree-queue ==0.2.3.1,
|
||||||
any.lzma-static ==5.2.5.4,
|
any.lzma-static ==5.2.5.4,
|
||||||
any.megaparsec ==9.2.0,
|
any.megaparsec ==9.0.1,
|
||||||
megaparsec -dev,
|
megaparsec -dev,
|
||||||
any.microlens ==0.4.12.0,
|
any.microlens ==0.4.12.0,
|
||||||
any.microlens-mtl ==0.2.0.1,
|
any.microlens-mtl ==0.2.0.1,
|
||||||
any.microlens-th ==0.4.3.10,
|
any.microlens-th ==0.4.3.10,
|
||||||
any.monad-control ==1.0.3.1,
|
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.5,
|
||||||
network -devel,
|
network -devel,
|
||||||
any.network-uri ==2.6.4.1,
|
any.network-uri ==2.6.4.1,
|
||||||
any.openssl-streams ==1.2.3.0,
|
any.openssl-streams ==1.2.3.0,
|
||||||
@@ -139,7 +134,7 @@ constraints: any.Cabal ==3.6.2.0,
|
|||||||
optics-core -explicit-generic-labels,
|
optics-core -explicit-generic-labels,
|
||||||
any.optics-extra ==0.4,
|
any.optics-extra ==0.4,
|
||||||
any.optics-th ==0.4,
|
any.optics-th ==0.4,
|
||||||
any.optparse-applicative ==0.17.0.0,
|
any.optparse-applicative ==0.16.1.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,
|
||||||
@@ -150,15 +145,15 @@ constraints: any.Cabal ==3.6.2.0,
|
|||||||
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.2.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,
|
||||||
any.recursion-schemes ==5.2.2.2,
|
any.recursion-schemes ==5.2.2.1,
|
||||||
recursion-schemes +template-haskell,
|
recursion-schemes +template-haskell,
|
||||||
any.regex-base ==0.94.0.2,
|
any.regex-base ==0.94.0.1,
|
||||||
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.4.3,
|
||||||
@@ -169,37 +164,34 @@ constraints: any.Cabal ==3.6.2.0,
|
|||||||
any.safe-exceptions ==0.1.7.2,
|
any.safe-exceptions ==0.1.7.2,
|
||||||
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,
|
||||||
semialign +semigroupoids,
|
semialign +semigroupoids,
|
||||||
any.semigroupoids ==5.3.7,
|
any.semigroupoids ==5.3.6,
|
||||||
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.4,
|
||||||
any.splitmix ==0.1.0.4,
|
any.splitmix ==0.1.0.3,
|
||||||
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.0,
|
||||||
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 -no-fusion +opt -streamk -use-c-malloc,
|
||||||
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.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.2.1,
|
||||||
any.terminfo ==0.4.1.4,
|
any.terminfo ==0.4.1.4,
|
||||||
any.text ==1.2.4.1,
|
any.text ==1.2.4.1,
|
||||||
any.text-short ==0.1.5,
|
|
||||||
text-short -asserts,
|
|
||||||
any.text-zipper ==0.11,
|
any.text-zipper ==0.11,
|
||||||
any.tf-random ==0.5,
|
any.tf-random ==0.5,
|
||||||
any.th-abstraction ==0.4.3.0,
|
any.th-abstraction ==0.4.3.0,
|
||||||
any.th-compat ==0.1.3,
|
any.th-compat ==0.1.3,
|
||||||
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.18,
|
||||||
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 +200,14 @@ 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,
|
||||||
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,
|
|
||||||
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.5,
|
||||||
any.unix-compat ==0.5.4,
|
any.unix-compat ==0.5.3,
|
||||||
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.14.0,
|
||||||
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 +215,15 @@ 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.versions ==5.0.0,
|
||||||
any.vty ==5.33,
|
any.vty ==5.33,
|
||||||
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.0,
|
||||||
any.yaml-streamly ==0.12.1,
|
any.yaml-streamly ==0.12.0,
|
||||||
yaml-streamly +no-examples +no-exe,
|
yaml-streamly +no-examples +no-exe,
|
||||||
any.zlib ==0.6.2.3,
|
any.zlib ==0.6.2.3,
|
||||||
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 2021-10-24T10:21:56Z
|
||||||
|
|||||||
@@ -8,11 +8,6 @@ package ghcup
|
|||||||
tests: True
|
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.Cabal ==3.6.2.0,
|
||||||
any.aeson >= 2.0.1.0
|
any.aeson >= 2.0.1.0
|
||||||
@@ -31,4 +26,4 @@ package aeson
|
|||||||
|
|
||||||
allow-newer: base, ghc-prim, template-haskell, language-c
|
allow-newer: base, ghc-prim, template-haskell, language-c
|
||||||
|
|
||||||
with-compiler: ghc-9.0.2
|
with-compiler: ghc-9.0.1
|
||||||
@@ -4,18 +4,18 @@ constraints: any.Cabal ==3.6.2.0,
|
|||||||
any.HUnit ==1.6.2.0,
|
any.HUnit ==1.6.2.0,
|
||||||
any.HsOpenSSL ==0.11.7.2,
|
any.HsOpenSSL ==0.11.7.2,
|
||||||
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.QuickCheck ==2.14.2,
|
any.QuickCheck ==2.14.2,
|
||||||
QuickCheck -old-random +templatehaskell,
|
QuickCheck -old-random +templatehaskell,
|
||||||
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.0.1.0,
|
||||||
aeson -cffi +ordered-keymap,
|
aeson -bytestring-builder -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.6,
|
||||||
any.ansi-terminal ==0.11.1,
|
alex +small_base,
|
||||||
|
any.ansi-terminal ==0.11,
|
||||||
ansi-terminal -example,
|
ansi-terminal -example,
|
||||||
any.ansi-wl-pprint ==0.6.9,
|
any.ansi-wl-pprint ==0.6.9,
|
||||||
ansi-wl-pprint -example,
|
ansi-wl-pprint -example,
|
||||||
@@ -25,14 +25,14 @@ constraints: any.Cabal ==3.6.2.0,
|
|||||||
async -bench,
|
async -bench,
|
||||||
any.atomic-primops ==0.8.4,
|
any.atomic-primops ==0.8.4,
|
||||||
atomic-primops -debug,
|
atomic-primops -debug,
|
||||||
any.attoparsec ==0.14.4,
|
any.attoparsec ==0.13.2.5,
|
||||||
attoparsec -developer,
|
attoparsec -developer,
|
||||||
any.base ==4.15.1.0,
|
any.base ==4.15.0.0,
|
||||||
any.base-compat ==0.12.1,
|
any.base-compat ==0.12.0,
|
||||||
any.base-compat-batteries ==0.12.1,
|
any.base-compat-batteries ==0.12.0,
|
||||||
any.base-orphans ==0.8.6,
|
any.base-orphans ==0.8.5,
|
||||||
any.base16-bytestring ==1.0.2.0,
|
any.base16-bytestring ==1.0.1.0,
|
||||||
any.base64-bytestring ==1.2.1.0,
|
any.base64-bytestring ==1.1.0.0,
|
||||||
any.bifunctors ==5.5.11,
|
any.bifunctors ==5.5.11,
|
||||||
bifunctors +semigroups +tagged,
|
bifunctors +semigroups +tagged,
|
||||||
any.binary ==0.8.8.0,
|
any.binary ==0.8.8.0,
|
||||||
@@ -52,7 +52,7 @@ 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,
|
any.clock ==0.8.2,
|
||||||
clock -llvm,
|
clock -llvm,
|
||||||
any.colour ==2.3.6,
|
any.colour ==2.3.6,
|
||||||
any.comonad ==5.0.8,
|
any.comonad ==5.0.8,
|
||||||
@@ -66,13 +66,13 @@ constraints: any.Cabal ==3.6.2.0,
|
|||||||
contravariant +semigroups +statevar +tagged,
|
contravariant +semigroups +statevar +tagged,
|
||||||
any.cpphs ==1.20.9.1,
|
any.cpphs ==1.20.9.1,
|
||||||
cpphs -old-locale,
|
cpphs -old-locale,
|
||||||
any.cryptohash-sha1 ==0.11.101.0,
|
any.cryptohash-sha1 ==0.11.100.1,
|
||||||
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-clist ==0.2,
|
any.data-clist ==0.1.2.3,
|
||||||
any.data-fix ==0.3.2,
|
any.data-fix ==0.3.2,
|
||||||
any.deepseq ==1.4.5.0,
|
any.deepseq ==1.4.5.0,
|
||||||
any.directory ==1.3.6.2,
|
any.directory ==1.3.6.1,
|
||||||
any.disk-free-space ==0.1.0.1,
|
any.disk-free-space ==0.1.0.1,
|
||||||
any.distributive ==0.6.2.1,
|
any.distributive ==0.6.2.1,
|
||||||
distributive +semigroups +tagged,
|
distributive +semigroups +tagged,
|
||||||
@@ -82,55 +82,50 @@ constraints: any.Cabal ==3.6.2.0,
|
|||||||
any.filepath ==1.4.2.1,
|
any.filepath ==1.4.2.1,
|
||||||
any.free ==5.1.7,
|
any.free ==5.1.7,
|
||||||
any.fusion-plugin-types ==0.1.0,
|
any.fusion-plugin-types ==0.1.0,
|
||||||
any.generic-arbitrary ==0.2.0,
|
any.generic-arbitrary ==0.1.0,
|
||||||
any.ghc ==9.0.2,
|
any.ghc-bignum ==1.0,
|
||||||
any.ghc-bignum ==1.1,
|
any.ghc-boot-th ==9.0.1,
|
||||||
any.ghc-boot ==9.0.2,
|
|
||||||
any.ghc-boot-th ==9.0.2,
|
|
||||||
any.ghc-byteorder ==4.11.0.0.10,
|
any.ghc-byteorder ==4.11.0.0.10,
|
||||||
any.ghc-heap ==9.0.2,
|
|
||||||
any.ghc-prim ==0.7.0,
|
any.ghc-prim ==0.7.0,
|
||||||
any.ghci ==9.0.2,
|
|
||||||
any.happy ==1.20.0,
|
any.happy ==1.20.0,
|
||||||
any.hashable ==1.4.0.2,
|
any.hashable ==1.3.4.1,
|
||||||
hashable +containers +integer-gmp -random-initial-seed,
|
hashable +integer-gmp -random-initial-seed,
|
||||||
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.1,
|
||||||
any.heaps ==0.4,
|
any.heaps ==0.4,
|
||||||
any.hpc ==0.6.1.0,
|
any.hsc2hs ==0.68.7,
|
||||||
any.hsc2hs ==0.68.8,
|
|
||||||
hsc2hs -in-ghc-tree,
|
hsc2hs -in-ghc-tree,
|
||||||
any.hspec ==2.9.4,
|
any.hspec ==2.7.10,
|
||||||
any.hspec-core ==2.9.4,
|
any.hspec-core ==2.7.10,
|
||||||
any.hspec-discover ==2.9.4,
|
any.hspec-discover ==2.7.10,
|
||||||
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.0,
|
||||||
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.1,
|
||||||
any.indexed-traversable-instances ==0.1.1,
|
any.indexed-traversable-instances ==0.1,
|
||||||
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.1,
|
||||||
io-streams +network -nointeractivetests +zlib,
|
io-streams +network -nointeractivetests +zlib,
|
||||||
any.language-c ==0.9.0.1,
|
any.language-c ==0.9.0.1,
|
||||||
language-c -allwarnings +iecfpextension +usebytestrings,
|
language-c -allwarnings +iecfpextension +usebytestrings,
|
||||||
any.libarchive ==3.0.3.2,
|
any.libarchive ==3.0.3.1,
|
||||||
libarchive -cross -low-memory +no-exe -system-libarchive,
|
libarchive -cross -low-memory -system-libarchive,
|
||||||
any.libyaml-streamly ==0.2.1,
|
any.libyaml-streamly ==0.2.0,
|
||||||
libyaml-streamly -no-unicode -system-libyaml,
|
libyaml-streamly -no-unicode -system-libyaml,
|
||||||
any.lockfree-queue ==0.2.3.1,
|
any.lockfree-queue ==0.2.3.1,
|
||||||
any.lzma-static ==5.2.5.4,
|
any.lzma-static ==5.2.5.4,
|
||||||
any.megaparsec ==9.2.0,
|
any.megaparsec ==9.0.1,
|
||||||
megaparsec -dev,
|
megaparsec -dev,
|
||||||
any.microlens ==0.4.12.0,
|
any.microlens ==0.4.12.0,
|
||||||
any.microlens-mtl ==0.2.0.1,
|
any.microlens-mtl ==0.2.0.1,
|
||||||
any.microlens-th ==0.4.3.10,
|
any.microlens-th ==0.4.3.10,
|
||||||
any.monad-control ==1.0.3.1,
|
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.5,
|
||||||
network -devel,
|
network -devel,
|
||||||
any.network-uri ==2.6.4.1,
|
any.network-uri ==2.6.4.1,
|
||||||
any.openssl-streams ==1.2.3.0,
|
any.openssl-streams ==1.2.3.0,
|
||||||
@@ -139,7 +134,7 @@ constraints: any.Cabal ==3.6.2.0,
|
|||||||
optics-core -explicit-generic-labels,
|
optics-core -explicit-generic-labels,
|
||||||
any.optics-extra ==0.4,
|
any.optics-extra ==0.4,
|
||||||
any.optics-th ==0.4,
|
any.optics-th ==0.4,
|
||||||
any.optparse-applicative ==0.17.0.0,
|
any.optparse-applicative ==0.16.1.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,
|
||||||
@@ -150,56 +145,53 @@ constraints: any.Cabal ==3.6.2.0,
|
|||||||
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.2.0,
|
||||||
any.process ==1.6.13.2,
|
any.process ==1.6.11.0,
|
||||||
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,
|
||||||
any.recursion-schemes ==5.2.2.2,
|
any.recursion-schemes ==5.2.2.1,
|
||||||
recursion-schemes +template-haskell,
|
recursion-schemes +template-haskell,
|
||||||
any.regex-base ==0.94.0.2,
|
any.regex-base ==0.94.0.1,
|
||||||
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.4.3,
|
||||||
any.retry ==0.8.1.2,
|
any.retry ==0.8.1.2,
|
||||||
retry -lib-werror,
|
retry -lib-werror,
|
||||||
any.rts ==1.0.2,
|
any.rts ==1.0,
|
||||||
any.safe ==0.3.19,
|
any.safe ==0.3.19,
|
||||||
any.safe-exceptions ==0.1.7.2,
|
any.safe-exceptions ==0.1.7.2,
|
||||||
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,
|
||||||
semialign +semigroupoids,
|
semialign +semigroupoids,
|
||||||
any.semigroupoids ==5.3.7,
|
any.semigroupoids ==5.3.6,
|
||||||
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.4,
|
||||||
any.splitmix ==0.1.0.4,
|
any.splitmix ==0.1.0.3,
|
||||||
splitmix -optimised-mixer,
|
splitmix -optimised-mixer,
|
||||||
any.stm ==2.5.0.0,
|
any.stm ==2.5.0.0,
|
||||||
any.streamly ==0.8.2,
|
any.streamly ==0.8.0,
|
||||||
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 -no-fusion +opt -streamk -use-c-malloc,
|
||||||
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.template-haskell ==2.17.0.0,
|
any.template-haskell ==2.17.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.2.1,
|
||||||
any.terminfo ==0.4.1.5,
|
any.terminfo ==0.4.1.4,
|
||||||
any.text ==1.2.5.0,
|
any.text ==1.2.4.1,
|
||||||
any.text-short ==0.1.5,
|
|
||||||
text-short -asserts,
|
|
||||||
any.text-zipper ==0.11,
|
any.text-zipper ==0.11,
|
||||||
any.tf-random ==0.5,
|
any.tf-random ==0.5,
|
||||||
any.th-abstraction ==0.4.3.0,
|
any.th-abstraction ==0.4.3.0,
|
||||||
any.th-compat ==0.1.3,
|
any.th-compat ==0.1.3,
|
||||||
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.18,
|
||||||
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 +200,14 @@ 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,
|
||||||
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,
|
|
||||||
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.5,
|
||||||
any.unix-compat ==0.5.4,
|
any.unix-compat ==0.5.3,
|
||||||
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.14.0,
|
||||||
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 +215,15 @@ 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.versions ==5.0.0,
|
||||||
any.vty ==5.33,
|
any.vty ==5.33,
|
||||||
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.0,
|
||||||
any.yaml-streamly ==0.12.1,
|
any.yaml-streamly ==0.12.0,
|
||||||
yaml-streamly +no-examples +no-exe,
|
yaml-streamly +no-examples +no-exe,
|
||||||
any.zlib ==0.6.2.3,
|
any.zlib ==0.6.2.3,
|
||||||
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 2021-10-24T10:21:56Z
|
||||||
@@ -8,16 +8,14 @@ package ghcup
|
|||||||
tests: True
|
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.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
|
source-repository-package
|
||||||
|
type: git
|
||||||
|
location: https://github.com/input-output-hk/optparse-applicative
|
||||||
|
tag: 7497a29cb998721a9068d5725d49461f2bba0e7a
|
||||||
|
|
||||||
package libarchive
|
package libarchive
|
||||||
flags: -system-libarchive
|
flags: -system-libarchive
|
||||||
|
|||||||
@@ -48,16 +48,12 @@ url-source:
|
|||||||
|
|
||||||
## Example 1: Read download info from this location instead
|
## Example 1: Read download info from this location instead
|
||||||
## Accepts file/http/https scheme
|
## Accepts file/http/https scheme
|
||||||
## Can also be an array of URLs or an array of 'Either GHCupInfo URL', in
|
|
||||||
## which case they are merged right-biased (overwriting duplicate versions).
|
|
||||||
# OwnSource: "file:///home/jule/git/ghcup-hs/ghcup-0.0.3.yaml"
|
# OwnSource: "file:///home/jule/git/ghcup-hs/ghcup-0.0.3.yaml"
|
||||||
|
|
||||||
## Example 2: Add custom tarballs to the default downloads, overwriting duplicate versions.
|
## Example 2: Add custom tarballs to the default downloads, overwriting duplicate versions
|
||||||
## Can also be an array of 'Either GHCupInfo URL', also see Example 3.
|
|
||||||
# AddSource:
|
# AddSource:
|
||||||
# Left:
|
# Left:
|
||||||
# globalTools: {}
|
# toolRequirements: {} # this is ignored
|
||||||
# toolRequirements: {}
|
|
||||||
# ghcupDownloads:
|
# ghcupDownloads:
|
||||||
# GHC:
|
# GHC:
|
||||||
# 9.10.2:
|
# 9.10.2:
|
||||||
@@ -70,8 +66,6 @@ url-source:
|
|||||||
# dlSubdir: ghc-7.10.3
|
# dlSubdir: ghc-7.10.3
|
||||||
# dlHash: 01cfbad8dff1e8b34a5fdca8caeaf843b56e36af919e29cd68870d2588563db5
|
# dlHash: 01cfbad8dff1e8b34a5fdca8caeaf843b56e36af919e29cd68870d2588563db5
|
||||||
|
|
||||||
## Example 3: Add multiple custom download files to the default downloads via right-biased merge (overwriting duplicate
|
## Example 3: Add a custom download file to the default downloads, overwriting duplicate versions
|
||||||
## versions).
|
|
||||||
# AddSource:
|
# AddSource:
|
||||||
# - 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"
|
|
||||||
|
|||||||
Submodule data/metadata deleted from 6fae2f7bc2
@@ -1,8 +1,5 @@
|
|||||||
:root {
|
:root {
|
||||||
--theme-purple: #5E5184;
|
--theme-purple: #5E5184;
|
||||||
--theme-purple-dark: rgba(69, 59, 97, 0.5);
|
|
||||||
--ukraine-top: #0057B8;
|
|
||||||
--ukraine-bottom: #FFD700;
|
|
||||||
--link-pink: #9E358F;
|
--link-pink: #9E358F;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,12 +108,12 @@ body.homepage>div.container div.col-md-9 {
|
|||||||
|
|
||||||
.bg-primary {
|
.bg-primary {
|
||||||
background-image: none;
|
background-image: none;
|
||||||
background-color: var(--ukraine-top) !important;
|
background-color: var(--theme-purple) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
body .bg-primary {
|
body .bg-primary {
|
||||||
background-image: none;
|
background-image: none;
|
||||||
background-color: var(--ukraine-top);
|
background-color: var(--theme-purple);
|
||||||
border: 0px;
|
border: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,8 +125,8 @@ body .btn-primary {
|
|||||||
|
|
||||||
.navbar.fixed-top {
|
.navbar.fixed-top {
|
||||||
background-image: none;
|
background-image: none;
|
||||||
background-color: var(--ukraine-top);
|
background-color: var(--theme-purple);
|
||||||
border-bottom: 40px solid var(--ukraine-bottom);
|
border-bottom: 5px solid rgba(69, 59, 97, 0.5);
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
27
docs/dev.md
27
docs/dev.md
@@ -12,7 +12,8 @@ organised tree-ish in `GHCup.Utils` and `GHCup.Utils.*`.
|
|||||||
Anything dealing with ghcup specific directories is in
|
Anything dealing with ghcup specific directories is in
|
||||||
`GHCup.Utils.Dirs`.
|
`GHCup.Utils.Dirs`.
|
||||||
|
|
||||||
Download information on where to fetch bindists from is in the [ghcup-metadata](https://github.com/haskell/ghcup-metadata) repository.
|
Download information on where to fetch bindists from is in the appropriate
|
||||||
|
yaml files: `data/metadata/ghcup-<yaml-ver>.yaml`.
|
||||||
|
|
||||||
## Design decisions
|
## Design decisions
|
||||||
|
|
||||||
@@ -88,33 +89,25 @@ Every subcommand now lives in its own module under [GHCup.OptParse.MyCommand](ht
|
|||||||
|
|
||||||
# Releasing
|
# Releasing
|
||||||
|
|
||||||
1. Update version in `ghcup.cabal`
|
1. Update version in `ghcup.cabal` and `boostrap-haskell` (`ghver` variable at the top of the script)
|
||||||
|
|
||||||
2. Update `GHCup.Version` module. `ghcupURL` must only be updated if we change the `GHCupInfo` type or the YAML representation of it. The version of the YAML represents the change increments. `ghcUpVer` is the current application version, read from `ghcup.cabal`.
|
2. Update `GHCup.Version` module. `ghcupURL` must only be updated if we change the `GHCupInfo` type or the YAML representation of it. The version of the YAML represents the change increments. `ghcUpVer` is the current application version, read from `ghcup.cabal`.
|
||||||
|
|
||||||
3. Add ChangeLog entry
|
3. Add ChangeLog entry
|
||||||
|
|
||||||
4. If a new ghcup yaml version is needed, create one at [ghcup-metadata repo](https://github.com/haskell/ghcup-metadata) and push to a temporary release branch, then update the `data/metadata` submodule in ghcup-hs repo to that branch, so CI can pass
|
4. Commit and git push with tag. Wait for tests to succeed and release artifacts to build.
|
||||||
|
|
||||||
5. Commit and git push with tag. Wait for tests to succeed and release artifacts to build.
|
5. Download release artifacts and upload them `downloads.haskell.org/~ghcup` along with checksum files (`sha256sum --tag * > SHA256SUMS && gpg --detach-sign -u <your-email> SHA256SUMS`)
|
||||||
|
|
||||||
6. Download release artifacts and upload them `downloads.haskell.org/~ghcup` along with checksum files (also check `scripts/releasing/pull_release_artifacts.sh` and `scripts/releasing/sftp-upload-artifacts.sh`)
|
6. Add ghcup release artifacts to ALL yaml files, see [ghcup-metadata repo](https://github.com/haskell/ghcup-metadata)
|
||||||
|
|
||||||
7. Add ghcup release artifacts to ALL yaml files, see [ghcup-metadata repo](https://github.com/haskell/ghcup-metadata)
|
7. Upload the final `ghcup-<ver>.yaml` (and a detached GPG sig of it) to `webhost.haskell.org/ghcup/data/` (for yaml versions <= 0.0.6) as well as [https://github.com/haskell/ghcup-metadata](https://github.com/haskell/ghcup-metadata) (for all versions).
|
||||||
|
|
||||||
8. Upload the final `ghcup-<ver>.yaml` (and a detached GPG sig of it) to `webhost.haskell.org/ghcup/data/` (for yaml versions <= 0.0.6) as well as [https://github.com/haskell/ghcup-metadata](https://github.com/haskell/ghcup-metadata) (for all versions).
|
8. Upload `bootstrap-haskell` and `bootstrap-haskell.ps1` to `webhost.haskell.org/ghcup/sh/`
|
||||||
|
|
||||||
9. Update version in `scripts/bootstrap/bootstrap-haskell` (`ghver` variable at the top of the script)
|
9. Update the top-level ghcup symlinks at `downloads.haskell.org/~ghcup`
|
||||||
|
|
||||||
10. Upload `scripts/bootstrap/bootstrap-haskell` and `scripts/bootstrap/bootstrap-haskell.ps1` to `webhost.haskell.org/ghcup/sh/`
|
10. Post on reddit/discourse/etc. and collect rewards
|
||||||
|
|
||||||
11. Update the top-level ghcup symlinks at `downloads.haskell.org/~ghcup` (see `scripts/releasing/sftp-symlink-artifacts.sh`)
|
|
||||||
|
|
||||||
12. Update the `data/metadata` submodule in ghcup-hs repo to master
|
|
||||||
|
|
||||||
13. Do hackage release
|
|
||||||
|
|
||||||
14. Post on reddit/discourse/etc. and collect rewards
|
|
||||||
|
|
||||||
# Documentation
|
# Documentation
|
||||||
|
|
||||||
|
|||||||
287
docs/guide.md
287
docs/guide.md
@@ -1,6 +1,6 @@
|
|||||||
# User Guide
|
# User Guide
|
||||||
|
|
||||||
This is a more in-depth guide specific to GHCup. `ghcup --help` is your friend.
|
`ghcup --help` is your friend.
|
||||||
|
|
||||||
## Basic usage
|
## Basic usage
|
||||||
|
|
||||||
@@ -32,16 +32,12 @@ ghcup install cabal
|
|||||||
ghcup upgrade
|
ghcup upgrade
|
||||||
```
|
```
|
||||||
|
|
||||||
### Tags and shortcuts
|
## Configuration
|
||||||
|
|
||||||
GHCup has a number of tags and version shortcuts, that can be used as arguments to **install**/**set** etc.
|
A configuration file can be put in `~/.ghcup/config.yaml`. The default config file
|
||||||
All of the following are valid arguments to `ghcup install ghc`:
|
explaining all possible configurations can be found in this repo: [config.yaml](https://gitlab.haskell.org/haskell/ghcup-hs/-/blob/master/data/config.yaml).
|
||||||
|
|
||||||
* `latest`, `recommended`
|
Partial configuration is fine. Command line options always override the config file settings.
|
||||||
* `base-4.15.1.0`
|
|
||||||
* `9.0.2`, `9.0`, `9`
|
|
||||||
|
|
||||||
If the argument is omitted, the default is `recommended`.
|
|
||||||
|
|
||||||
## Manpages
|
## Manpages
|
||||||
|
|
||||||
@@ -57,40 +53,6 @@ as e.g. `/etc/bash_completion.d/ghcup` (depending on distro)
|
|||||||
and make sure your bashrc sources the startup script
|
and make sure your bashrc sources the startup script
|
||||||
(`/usr/share/bash-completion/bash_completion` on some distros).
|
(`/usr/share/bash-completion/bash_completion` on some distros).
|
||||||
|
|
||||||
# Configuration
|
|
||||||
|
|
||||||
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).
|
|
||||||
|
|
||||||
Partial configuration is fine. Command line options always override the config file settings.
|
|
||||||
|
|
||||||
## Env variables
|
|
||||||
|
|
||||||
This is the complete list of env variables that change GHCup behavior:
|
|
||||||
|
|
||||||
* `GHCUP_USE_XDG_DIRS`: see [XDG support](#xdg-support) above
|
|
||||||
* `TMPDIR`: where ghcup does the work (unpacking, building, ...)
|
|
||||||
* `GHCUP_INSTALL_BASE_PREFIX`: the base of ghcup (default: `$HOME`)
|
|
||||||
* `GHCUP_CURL_OPTS`: additional options that can be passed to curl
|
|
||||||
* `GHCUP_WGET_OPTS`: additional options that can be passed to wget
|
|
||||||
* `GHCUP_GPG_OPTS`: additional options that can be passed to gpg
|
|
||||||
* `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
|
|
||||||
|
|
||||||
### XDG support
|
|
||||||
|
|
||||||
To enable XDG style directories, set the environment variable `GHCUP_USE_XDG_DIRS` to anything.
|
|
||||||
|
|
||||||
Then you can control the locations via XDG environment variables as such:
|
|
||||||
|
|
||||||
* `XDG_DATA_HOME`: GHCs will be unpacked in `ghcup/ghc` subdir (default: `~/.local/share`)
|
|
||||||
* `XDG_CACHE_HOME`: logs and download files will be stored in `ghcup` subdir (default: `~/.cache`)
|
|
||||||
* `XDG_BIN_HOME`: binaries end up here (default: `~/.local/bin`)
|
|
||||||
* `XDG_CONFIG_HOME`: the config file is stored in `ghcup` subdir as `config.yaml` (default: `~/.config`)
|
|
||||||
|
|
||||||
**Note that `ghcup` makes some assumptions about structure of files in `XDG_BIN_HOME`. So if you have other tools
|
|
||||||
installing e.g. stack/cabal/ghc into it, this will likely clash. In that case consider disabling XDG support.**
|
|
||||||
|
|
||||||
## Caching
|
## Caching
|
||||||
|
|
||||||
GHCup has a few caching mechanisms to avoid redownloads. All cached files end up in `~/.ghcup/cache` by default.
|
GHCup has a few caching mechanisms to avoid redownloads. All cached files end up in `~/.ghcup/cache` by default.
|
||||||
@@ -110,92 +72,6 @@ have a 5 minutes cache per default depending on the last access time of the file
|
|||||||
|
|
||||||
If you experience problems, consider clearing the cache via `ghcup gc --cache`.
|
If you experience problems, consider clearing the cache via `ghcup gc --cache`.
|
||||||
|
|
||||||
## Metadata
|
|
||||||
|
|
||||||
The metadata are the files that describe tool versions, where to download them etc. and
|
|
||||||
can be viewed here: [https://github.com/haskell/ghcup-metadata](https://github.com/haskell/ghcup-metadata)
|
|
||||||
|
|
||||||
### Mirrors
|
|
||||||
|
|
||||||
GHCup allows to use custom mirrors/download-info hosted by yourself or 3rd parties.
|
|
||||||
|
|
||||||
To use a mirror, set the following option in `~/.ghcup/config.yaml`:
|
|
||||||
|
|
||||||
```yml
|
|
||||||
url-source:
|
|
||||||
# Accepts file/http/https scheme
|
|
||||||
OwnSource: "https://some-url/ghcup-0.0.6.yaml"
|
|
||||||
```
|
|
||||||
|
|
||||||
See [config.yaml](https://gitlab.haskell.org/haskell/ghcup-hs/-/blob/master/data/config.yaml)
|
|
||||||
for more options.
|
|
||||||
|
|
||||||
Alternatively you can do it via a cli switch:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
ghcup --url-source=https://some-url/ghcup-0.0.6.yaml list
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Known mirrors
|
|
||||||
|
|
||||||
1. [https://mirror.sjtu.edu.cn/docs/ghcup](https://mirror.sjtu.edu.cn/docs/ghcup)
|
|
||||||
|
|
||||||
### (Pre-)Release channels
|
|
||||||
|
|
||||||
A release channel is basically just a metadata file location. You can add additional release
|
|
||||||
channels that complement the default one, such as the **prerelease channel** like so:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
ghcup config add-release-channel https://raw.githubusercontent.com/haskell/ghcup-metadata/master/ghcup-prereleases-0.0.7.yaml
|
|
||||||
```
|
|
||||||
|
|
||||||
This will result in `~/.ghcup/config.yaml` to contain this record:
|
|
||||||
|
|
||||||
```yml
|
|
||||||
url-source:
|
|
||||||
AddSource:
|
|
||||||
- Right: https://raw.githubusercontent.com/haskell/ghcup-metadata/master/ghcup-prereleases-0.0.7.yaml
|
|
||||||
```
|
|
||||||
|
|
||||||
You can add as many channels as you like. They are combined under *Last*, so versions from the prerelease channel
|
|
||||||
here overwrite the default ones, if any.
|
|
||||||
|
|
||||||
To remove the channel, delete the entire `url-source` section or set it back to the default:
|
|
||||||
|
|
||||||
```yml
|
|
||||||
url-source:
|
|
||||||
GHCupURL: []
|
|
||||||
```
|
|
||||||
|
|
||||||
If you want to combine your release channel with a mirror, you'd do it like so:
|
|
||||||
|
|
||||||
```yml
|
|
||||||
url-source:
|
|
||||||
OwnSource:
|
|
||||||
# base metadata
|
|
||||||
- "https://mirror.sjtu.edu.cn/ghcup/yaml/ghcup/data/ghcup-0.0.6.yaml"
|
|
||||||
# prerelease channel
|
|
||||||
- "https://raw.githubusercontent.com/haskell/ghcup-metadata/master/ghcup-prereleases-0.0.7.yaml"
|
|
||||||
```
|
|
||||||
|
|
||||||
# More on installation
|
|
||||||
|
|
||||||
## Installing custom bindists
|
|
||||||
|
|
||||||
There are a couple of good use cases to install custom bindists:
|
|
||||||
|
|
||||||
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`
|
|
||||||
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`
|
|
||||||
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`
|
|
||||||
|
|
||||||
Since the version parser is pretty lax, `8.10.2-eff` and `head` are both valid versions
|
|
||||||
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
|
|
||||||
detected).
|
|
||||||
|
|
||||||
## Compiling GHC from source
|
## Compiling GHC from source
|
||||||
|
|
||||||
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`
|
||||||
@@ -219,6 +95,49 @@ For distributions with non-standard locations of cross toolchain and
|
|||||||
libraries, this may need some tweaking of `build.mk` or configure args.
|
libraries, this may need some tweaking of `build.mk` or configure args.
|
||||||
See `ghcup compile ghc --help` for further information.
|
See `ghcup compile ghc --help` for further information.
|
||||||
|
|
||||||
|
## XDG support
|
||||||
|
|
||||||
|
To enable XDG style directories, set the environment variable `GHCUP_USE_XDG_DIRS` to anything.
|
||||||
|
|
||||||
|
Then you can control the locations via XDG environment variables as such:
|
||||||
|
|
||||||
|
* `XDG_DATA_HOME`: GHCs will be unpacked in `ghcup/ghc` subdir (default: `~/.local/share`)
|
||||||
|
* `XDG_CACHE_HOME`: logs and download files will be stored in `ghcup` subdir (default: `~/.cache`)
|
||||||
|
* `XDG_BIN_HOME`: binaries end up here (default: `~/.local/bin`)
|
||||||
|
* `XDG_CONFIG_HOME`: the config file is stored in `ghcup` subdir as `config.yaml` (default: `~/.config`)
|
||||||
|
|
||||||
|
**Note that `ghcup` makes some assumptions about structure of files in `XDG_BIN_HOME`. So if you have other tools
|
||||||
|
installing e.g. stack/cabal/ghc into it, this will likely clash. In that case consider disabling XDG support.**
|
||||||
|
|
||||||
|
## Env variables
|
||||||
|
|
||||||
|
This is the complete list of env variables that change GHCup behavior:
|
||||||
|
|
||||||
|
* `GHCUP_USE_XDG_DIRS`: see [XDG support](#xdg-support) above
|
||||||
|
* `TMPDIR`: where ghcup does the work (unpacking, building, ...)
|
||||||
|
* `GHCUP_INSTALL_BASE_PREFIX`: the base of ghcup (default: `$HOME`)
|
||||||
|
* `GHCUP_CURL_OPTS`: additional options that can be passed to curl
|
||||||
|
* `GHCUP_WGET_OPTS`: additional options that can be passed to wget
|
||||||
|
* `GHCUP_GPG_OPTS`: additional options that can be passed to gpg
|
||||||
|
* `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
|
||||||
|
|
||||||
|
## Installing custom bindists
|
||||||
|
|
||||||
|
There are a couple of good use cases to install custom bindists:
|
||||||
|
|
||||||
|
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`
|
||||||
|
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`
|
||||||
|
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`
|
||||||
|
|
||||||
|
Since the version parser is pretty lax, `8.10.2-eff` and `head` are both valid versions
|
||||||
|
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
|
||||||
|
detected).
|
||||||
|
|
||||||
## Isolated installs
|
## Isolated installs
|
||||||
|
|
||||||
Ghcup also enables you to install a tool (GHC, Cabal, HLS, Stack) at an isolated location of your choosing.
|
Ghcup also enables you to install a tool (GHC, Cabal, HLS, Stack) at an isolated location of your choosing.
|
||||||
@@ -269,10 +188,66 @@ For the full list of env variables and 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 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)
|
* [bootstrap-haskell.ps1 for windows](https://gitlab.haskell.org/haskell/ghcup-hs/-/blob/master/scripts/bootstrap/bootstrap-haskell.ps1#L17)
|
||||||
|
|
||||||
### github workflows
|
### Example github workflow
|
||||||
|
|
||||||
On github workflows you can use [https://github.com/haskell/actions/](https://github.com/haskell/actions/).
|
On github workflows you can use [https://github.com/haskell/actions/](https://github.com/haskell/actions/)
|
||||||
GHCup itself is also pre-installed on all platforms, but may use non-standard install locations.
|
|
||||||
|
If you want to install ghcup manually though, here's an example config:
|
||||||
|
|
||||||
|
```yml
|
||||||
|
name: Haskell CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ master ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-cabal:
|
||||||
|
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-latest, macOS-latest, windows-latest]
|
||||||
|
ghc: ['8.10.7', '9.0.1']
|
||||||
|
cabal: ['3.4.0.0']
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- if: matrix.os == 'windows-latest'
|
||||||
|
name: Install ghcup on windows
|
||||||
|
run: 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:\"
|
||||||
|
|
||||||
|
- if: matrix.os == 'windows-latest'
|
||||||
|
name: Add ghcup to PATH
|
||||||
|
run: echo "/c/ghcup/bin" >> $GITHUB_PATH
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
- if: matrix.os != 'windows-latest'
|
||||||
|
name: Install ghcup on non-windows
|
||||||
|
run: curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | BOOTSTRAP_HASKELL_NONINTERACTIVE=1 BOOTSTRAP_HASKELL_MINIMAL=1 sh
|
||||||
|
|
||||||
|
- name: Install ghc/cabal
|
||||||
|
run: |
|
||||||
|
ghcup install ghc ${{ matrix.ghc }}
|
||||||
|
ghcup install cabal ${{ matrix.cabal }}
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
- name: Update cabal index
|
||||||
|
run: cabal update
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: cabal build --enable-tests --enable-benchmarks
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: cabal test
|
||||||
|
shell: bash
|
||||||
|
```
|
||||||
|
|
||||||
## GPG verification
|
## GPG verification
|
||||||
|
|
||||||
@@ -302,16 +277,50 @@ 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
|
### with_ghc wrapper (e.g. for HLS)
|
||||||
|
|
||||||
If you don't want to explicitly switch the active GHC all the time and are using
|
Due to some HLS [bugs](https://github.com/mpickering/hie-bios/issues/194) it's necessary that the `ghc` in PATH
|
||||||
tools that rely on the plain `ghc` binary, GHCup provides an easy way to execute
|
is the one defined in `cabal.project`. With some simple shell functions, we can start our editor with the appropriate
|
||||||
commands with a certain toolchain prepended to PATH, e.g.:
|
path prepended.
|
||||||
|
|
||||||
|
For bash, in e.g. `~/.bashrc` define:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
ghcup run --ghc 8.10.7 --cabal latest --hls latest --stack latest --install -- code Setup.hs
|
with_ghc() {
|
||||||
|
local np=$(ghcup --offline whereis -d ghc $1 || { ghcup --cache install ghc $1 && ghcup whereis -d ghc $1 ;})
|
||||||
|
if [ -e "${np}" ] ; then
|
||||||
|
shift
|
||||||
|
PATH="$np:$PATH" "$@"
|
||||||
|
else
|
||||||
|
>&2 echo "Cannot find or install GHC version $1"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
This will execute vscode with GHC set to 8.10.7 and all other tools to their latest version.
|
For fish shell, in e.g. `~/.config/fish/config.fish` define:
|
||||||
|
|
||||||
|
```fish
|
||||||
|
function with_ghc
|
||||||
|
set --local np (ghcup --offline whereis -d ghc $argv[1] ; or begin ghcup --cache install ghc $argv[1] ; and ghcup whereis -d ghc $argv[1] ; end)
|
||||||
|
if test -e "$np"
|
||||||
|
PATH="$np:$PATH" $argv[2..-1]
|
||||||
|
else
|
||||||
|
echo "Cannot find or install GHC version $argv[1]" 1>&2
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
Then start a new shell and issue:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# replace 'code' with your editor
|
||||||
|
with_ghc 8.10.5 code path/to/haskell/source
|
||||||
|
```
|
||||||
|
|
||||||
|
Cabal and HLS will now see `8.10.5` as the primary GHC, without the need to
|
||||||
|
run `ghcup set` all the time when switching between projects.
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ hide:
|
|||||||
|
|
||||||
<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">Getting Started</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>
|
||||||
|
|
||||||
|
|||||||
114
docs/install.md
114
docs/install.md
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
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](./install/#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 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
|
## Installation
|
||||||
|
|
||||||
@@ -22,113 +22,28 @@ For Windows, run this in a PowerShell session:
|
|||||||
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;Invoke-Command -ScriptBlock ([ScriptBlock]::Create((Invoke-WebRequest https://www.haskell.org/ghcup/sh/bootstrap-haskell.ps1 -UseBasicParsing))) -ArgumentList $true
|
||||||
```
|
```
|
||||||
|
|
||||||
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://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.
|
||||||
|
|
||||||
### Which versions get installed?
|
## First steps
|
||||||
|
|
||||||
GHCup has two main channels for every tool: **recommended** and **latest**. By default, it installs *recommended*.
|
1. To get started with creating a Haskell project, follow the [Getting Started with Haskell and Cabal](https://cabal.readthedocs.io/en/latest/getting-started.html) guide
|
||||||
|
2. To properly learn Haskell, run through the [CIS 194 Haskell course](https://www.cis.upenn.edu/~cis194/spring13/) including exercises
|
||||||
*latest* follows the latest release of every tool, while *recommended* is at the discretion of the GHCup maintainers and based on community adoption (hackage libraries, tools like HLS, stackage support, etc.) and known bugs.
|
3. To learn more about Haskell Toolchain management, check out the [ghcup user guide](./guide.md)
|
||||||
|
|
||||||
Also see [tags and shortcuts](../guide/#tags-and-shortcuts) for more information.
|
|
||||||
|
|
||||||
## 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
|
|
||||||
2. To understand the difference and overlap of `stack` and `cabal`, read on [here](https://gist.github.com/merijn/8152d561fb8b011f9313c48d876ceb07)
|
|
||||||
3. To learn Haskell proper check out the links at [How to learn Haskell proper](../steps#how-to-learn-haskell-proper)
|
|
||||||
4. To learn more about Haskell Toolchain management, check out the [ghcup user guide](./guide.md)
|
|
||||||
|
|
||||||
## Uninstallation
|
## Uninstallation
|
||||||
|
|
||||||
On linux, just run `ghcup nuke`, then make sure any ghcup added lines in your `~/.bashrc` (or similar) are removed.
|
On linux, just run `ghcup nuke`, then make sure any ghcup added lines in your `~/.bashrc` (or similar) are removed.
|
||||||
|
|
||||||
On windows, right click on the `Uninstall Haskell.ps1` PowerShell script on your Desktop and select *Run with PowerShell*.
|
On windows, double-click on the `Uninstall Haskell.ps1` PowerShell script on your Desktop.
|
||||||
|
|
||||||
## Supported tools
|
## Supported tools
|
||||||
|
|
||||||
GHCup supports the following tools, which are also known as the **Haskell Toolchain**:
|
GHCup supports the following tools, which are also known as the **Haskell Toolchain**:
|
||||||
|
|
||||||
<details> <summary>Show all supported <a href='https://www.haskell.org/ghc/'>GHC</a> versions</summary>
|
1. [GHC](https://www.haskell.org/ghc/)
|
||||||
<table>
|
2. [cabal-install](https://cabal.readthedocs.io/en/latest/)
|
||||||
<thead><tr><th>GHC Version</th><th>Tags</th></tr></thead>
|
3. [haskell-language-server](https://haskell-language-server.readthedocs.io/en/latest/)
|
||||||
<tbody>
|
4. [stack](https://docs.haskellstack.org/en/latest/README/)
|
||||||
<tr><td>9.2.2</td><td><span style="color:blue">latest</span>, base-4.16.1.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.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.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.4</td><td>base-4.14.1.0</td></tr>
|
|
||||||
<tr><td>8.10.3</td><td>base-4.14.1.0</td></tr>
|
|
||||||
<tr><td>8.10.2</td><td>base-4.14.1.0</td></tr>
|
|
||||||
<tr><td>8.10.1</td><td>base-4.14.0.0</td></tr>
|
|
||||||
<tr><td>8.8.4</td><td>base-4.13.0.0</td></tr>
|
|
||||||
<tr><td>8.8.3</td><td>base-4.13.0.0</td></tr>
|
|
||||||
<tr><td>8.8.2</td><td>base-4.13.0.0</td></tr>
|
|
||||||
<tr><td>8.8.1</td><td>base-4.13.0.0</td></tr>
|
|
||||||
<tr><td>8.6.5</td><td>base-4.12.0.0</td></tr>
|
|
||||||
<tr><td>8.6.4</td><td>base-4.12.0.0</td></tr>
|
|
||||||
<tr><td>8.6.3</td><td>base-4.12.0.0</td></tr>
|
|
||||||
<tr><td>8.6.2</td><td>base-4.12.0.0</td></tr>
|
|
||||||
<tr><td>8.6.1</td><td>base-4.12.0.0</td></tr>
|
|
||||||
<tr><td>8.4.4</td><td>base-4.11.1.0</td></tr>
|
|
||||||
<tr><td>8.4.3</td><td>base-4.11.1.0</td></tr>
|
|
||||||
<tr><td>8.4.2</td><td>base-4.11.1.0</td></tr>
|
|
||||||
<tr><td>8.4.1</td><td>base-4.11.0.0</td></tr>
|
|
||||||
<tr><td>8.2.2</td><td>base-4.10.1.0</td></tr>
|
|
||||||
<tr><td>8.0.2</td><td>base-4.9.1.0</td></tr>
|
|
||||||
<tr><td>7.10.3</td><td>base-4.8.2.0</td></tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details> <summary>Show all supported <a href='https://cabal.readthedocs.io/en/stable/'>cabal-install</a> versions</summary>
|
|
||||||
<table>
|
|
||||||
<thead><tr><th>Cabal Version</th><th>Tags</th></tr></thead>
|
|
||||||
<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.6.0.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.2.0.0</td><td></td></tr>
|
|
||||||
<tr><td>3.0.0.0</td><td></td></tr>
|
|
||||||
<tr><td>2.4.1.0</td><td></td></tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details> <summary>Show all supported <a href='https://haskell-language-server.readthedocs.io/en/stable/'>HLS</a> versions</summary>
|
|
||||||
<table>
|
|
||||||
<thead><tr><th>HLS Version</th><th>Tags</th></tr></thead>
|
|
||||||
<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.6.1.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.0</td><td></td></tr>
|
|
||||||
<tr><td>1.4.0</td><td></td></tr>
|
|
||||||
<tr><td>1.3.0</td><td></td></tr>
|
|
||||||
<tr><td>1.2.0</td><td></td></tr>
|
|
||||||
<tr><td>1.1.0</td><td></td></tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details> <summary>Show all supported <a href='https://docs.haskellstack.org/en/stable/README/'>Stack</a> versions</summary>
|
|
||||||
<table>
|
|
||||||
<thead><tr><th>Stack Version</th><th>Tags</th></tr></thead>
|
|
||||||
<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.7.3</td><td></td></tr>
|
|
||||||
<tr><td>2.7.1</td><td></td></tr>
|
|
||||||
<tr><td>2.5.1</td><td></td></tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Supported platforms
|
## Supported platforms
|
||||||
|
|
||||||
@@ -163,15 +78,14 @@ May or may not work, several issues:
|
|||||||
|
|
||||||
Unsupported. GHC may or may not work. Upgrade to WSL2.
|
Unsupported. GHC may or may not work. Upgrade to WSL2.
|
||||||
|
|
||||||
### MacOS <10.13
|
### MacOS <13
|
||||||
|
|
||||||
Not supported. Would require separate binaries, since >=10.13 binaries are incompatible.
|
Not supported. Would require separate binaries, since >=13 binaries are incompatible.
|
||||||
Please upgrade.
|
Please upgrade.
|
||||||
|
|
||||||
### MacOS aarch64
|
### MacOS aarch64
|
||||||
|
|
||||||
HLS bindists are still experimental. Stack has only unofficial binaries for this platform.
|
HLS bindists are still experimental. Stack is theoretically supported, but has no binaries yet.
|
||||||
There are various issues with GHC itself.
|
|
||||||
|
|
||||||
### FreeBSD
|
### FreeBSD
|
||||||
|
|
||||||
@@ -180,7 +94,7 @@ HLS bindists are experimental.
|
|||||||
|
|
||||||
### Linux ARMv7/AARCH64
|
### Linux ARMv7/AARCH64
|
||||||
|
|
||||||
Lower availability of bindists. Stack and HLS binaries are experimental.
|
Lower availability of bindists. HLS only has experimental ones. Stack not supported currently.
|
||||||
|
|
||||||
## Manual install
|
## Manual install
|
||||||
|
|
||||||
|
|||||||
349
docs/steps.md
349
docs/steps.md
@@ -1,349 +0,0 @@
|
|||||||
# First steps
|
|
||||||
|
|
||||||
In this guide we'll take a look at a few core tools that are installed
|
|
||||||
with the Haskell toolchain, namely, `ghc`, `runghc` and `ghci`.
|
|
||||||
These tools can be used to compile, interpret or explore Haskell programs.
|
|
||||||
|
|
||||||
First, let's start by opening your system's command line interface
|
|
||||||
and running `ghc --version` to make sure we have successfully
|
|
||||||
installed a Haskell toolchain:
|
|
||||||
|
|
||||||
```
|
|
||||||
➜ ghc --version
|
|
||||||
The Glorious Glasgow Haskell Compilation System, version 8.10.7
|
|
||||||
```
|
|
||||||
|
|
||||||
If this fails, consult [the Getting started page](../install) for information on
|
|
||||||
how to install Haskell on your computer.
|
|
||||||
|
|
||||||
This guide is partly based on [Gil Mizrahi's blog](https://gilmi.me/blog/post/2021/08/14/hs-core-tools).
|
|
||||||
|
|
||||||
## Compiling programs with ghc
|
|
||||||
|
|
||||||
Running `ghc` invokes the Glasgow Haskell Compiler (GHC), and can be used to
|
|
||||||
compile Haskell modules and programs into native executables and libraries.
|
|
||||||
|
|
||||||
Create a new Haskell source file named `hello.hs`,
|
|
||||||
and write the following code in it:
|
|
||||||
|
|
||||||
```hs
|
|
||||||
main = putStrLn "Hello, Haskell!"
|
|
||||||
```
|
|
||||||
|
|
||||||
Now, we can compile the program by invoking `ghc` with the file name:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
➜ ghc hello.hs
|
|
||||||
[1 of 1] Compiling Main ( hello.hs, hello.o )
|
|
||||||
Linking hello ...
|
|
||||||
```
|
|
||||||
|
|
||||||
For more in-depth information about the files `ghc` produces,
|
|
||||||
follow the [GHC user guide](https://downloads.haskell.org/ghc/latest/docs/html/users_guide/using.html#getting-started-compiling-programs) guide.
|
|
||||||
|
|
||||||
Now we run our program:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
➜ ./hello
|
|
||||||
Hello, Haskell!
|
|
||||||
```
|
|
||||||
|
|
||||||
Alternatively, we can skip the compilation phase by using the command `runghc`:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
➜ runghc hello.hs
|
|
||||||
Hello, Haskell!
|
|
||||||
```
|
|
||||||
|
|
||||||
`runghc` interprets the source file instead of compiling it and does not
|
|
||||||
create build artifacts. This makes it very useful when developing programs
|
|
||||||
and can help accelerate the feedback loop. More information about `runghc`
|
|
||||||
can be found in the
|
|
||||||
[GHC user guide](https://downloads.haskell.org/ghc/latest/docs/html/users_guide/runghc.html).
|
|
||||||
|
|
||||||
### Turning on warnings
|
|
||||||
|
|
||||||
The `-Wall` flag will enable GHC to emit warnings about our code.
|
|
||||||
|
|
||||||
```sh
|
|
||||||
➜ ghc -Wall hello.hs -fforce-recomp
|
|
||||||
[1 of 1] Compiling Main ( hello.hs, hello.o )
|
|
||||||
|
|
||||||
hello.hs:1:1: warning: [-Wmissing-signatures]
|
|
||||||
Top-level binding with no type signature: main :: IO ()
|
|
||||||
|
|
|
||||||
1 | main = putStrLn "Hello, Haskell!"
|
|
||||||
| ^^^^
|
|
||||||
Linking hello ...
|
|
||||||
```
|
|
||||||
|
|
||||||
While Haskell can infer
|
|
||||||
the types of most expressions, it is recommended that top-level definitions
|
|
||||||
are annotated with their types.
|
|
||||||
|
|
||||||
Now our `hello.hs` source file should looks like this:
|
|
||||||
|
|
||||||
```hs
|
|
||||||
main :: IO ()
|
|
||||||
main = putStrLn "Hello, world!"
|
|
||||||
```
|
|
||||||
|
|
||||||
And now GHC will compile `hello.hs` without warnings.
|
|
||||||
|
|
||||||
## An interactive environment
|
|
||||||
|
|
||||||
GHC provides an interactive environment in a form of a
|
|
||||||
Read-Evaluate-Print Loop (REPL) called GHCi.
|
|
||||||
To enter the environment run the program `ghci`.
|
|
||||||
|
|
||||||
```sh
|
|
||||||
➜ ghci
|
|
||||||
GHCi, version 9.0.2: https://www.haskell.org/ghc/ :? for help
|
|
||||||
ghci>
|
|
||||||
```
|
|
||||||
|
|
||||||
It provides an interactive prompt where Haskell expressions can be written and
|
|
||||||
evaluated.
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
ghci> 1 + 1
|
|
||||||
2
|
|
||||||
ghci> putStrLn "Hello, world!"
|
|
||||||
Hello, world!
|
|
||||||
```
|
|
||||||
|
|
||||||
We can define new names:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
ghci> double x = x + x
|
|
||||||
ghci> double 2
|
|
||||||
4
|
|
||||||
```
|
|
||||||
|
|
||||||
We can write multi-line code by surrounding it with `:{` and `:}`:
|
|
||||||
|
|
||||||
```hs
|
|
||||||
ghci> :{
|
|
||||||
| map f list =
|
|
||||||
| case list of
|
|
||||||
| [] -> []
|
|
||||||
| x : xs -> f x : map f xs
|
|
||||||
| :}
|
|
||||||
ghci> map (+1) [1, 2, 3]
|
|
||||||
[2,3,4]
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
We can import Haskell source files using the `:load` command (`:l` for short):
|
|
||||||
|
|
||||||
```sh
|
|
||||||
ghci> :load hello.hs
|
|
||||||
[1 of 1] Compiling Main ( hello.hs, interpreted )
|
|
||||||
Ok, one module loaded.
|
|
||||||
ghci> main
|
|
||||||
Hello, Haskell!
|
|
||||||
```
|
|
||||||
|
|
||||||
As well as import library modules:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
ghci> import Data.Bits
|
|
||||||
ghci> shiftL 32 1
|
|
||||||
64
|
|
||||||
ghci> clearBit 33 0
|
|
||||||
32
|
|
||||||
```
|
|
||||||
|
|
||||||
We can even ask what the type of an expression is using the `:type` command
|
|
||||||
(`:t` for short):
|
|
||||||
|
|
||||||
```sh
|
|
||||||
λ> :type putStrLn
|
|
||||||
putStrLn :: String -> IO ()
|
|
||||||
```
|
|
||||||
|
|
||||||
To exit `ghci`, use the `:quit` command (or `:q` for short)
|
|
||||||
|
|
||||||
```sh
|
|
||||||
ghci> :quit
|
|
||||||
Leaving GHCi.
|
|
||||||
```
|
|
||||||
|
|
||||||
A more thorough introduction to GHCi can be found in the
|
|
||||||
[GHC user guide](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/ghci.html).
|
|
||||||
|
|
||||||
### Using external packages in ghci
|
|
||||||
|
|
||||||
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).
|
|
||||||
|
|
||||||
However, users of the [cabal-install](https://www.haskell.org/cabal) and
|
|
||||||
[stack](http://haskellstack.org) build tools can download and load external packages
|
|
||||||
very easily using the following commands:
|
|
||||||
|
|
||||||
cabal-install:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
cabal repl --build-depends async,say
|
|
||||||
```
|
|
||||||
|
|
||||||
Stack:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
stack exec --package async --package say -- ghci
|
|
||||||
```
|
|
||||||
|
|
||||||
And the modules of the relevant packages will be available for import:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
GHCi, version 9.0.1: https://www.haskell.org/ghc/ :? for help
|
|
||||||
ghci> import Control.Concurrent.Async
|
|
||||||
ghci> import Say
|
|
||||||
ghci> concurrently_ (sayString "Hello") (sayString "World")
|
|
||||||
Hello
|
|
||||||
World
|
|
||||||
```
|
|
||||||
|
|
||||||
Stack users can also use this feature with `runghc` and `ghc` by replacing
|
|
||||||
`ghci` in the command above, and cabal-install users can generate an
|
|
||||||
environment file that will make `async` and `say` visible for GHC tools
|
|
||||||
in the current directory using this command:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
cabal install --lib async say --package-env .
|
|
||||||
```
|
|
||||||
|
|
||||||
Many more packages are waiting for you on [Hackage](https://hackage.haskell.org).
|
|
||||||
|
|
||||||
## Creating a proper package with modules
|
|
||||||
|
|
||||||
The previous methods to compile Haskell code are for quick experiments and small
|
|
||||||
programs. Usually in Haskell, we create cabal projects, where build tools such as
|
|
||||||
`cabal-install` or `stack` will install necessary dependencies and compile modules
|
|
||||||
in correct order. For simplicity's sake, this section will only use `cabal-install`.
|
|
||||||
|
|
||||||
To get started, run:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mkdir haskell-project
|
|
||||||
cd haskell-project
|
|
||||||
cabal init --interactive
|
|
||||||
```
|
|
||||||
|
|
||||||
If you let it generate a simple project with sensible defaults, then you should have these files:
|
|
||||||
|
|
||||||
* `src/MyLib.hs`: the library module of your project
|
|
||||||
* `app/Main.hs`: the entry point of your project
|
|
||||||
* `haskell-project.cabal`: the "cabal" file, describing your project, its dependencies and how it's built
|
|
||||||
|
|
||||||
To build the project, run:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
cabal build
|
|
||||||
```
|
|
||||||
|
|
||||||
To run the main executable, run:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
➜ cabal run
|
|
||||||
Hello, Haskell!
|
|
||||||
someFunc
|
|
||||||
```
|
|
||||||
|
|
||||||
### Adding dependencies
|
|
||||||
|
|
||||||
Now let's add a dependency and adjust our library module. Open `haskell-project.cabal`
|
|
||||||
and find the library section:
|
|
||||||
|
|
||||||
```
|
|
||||||
library
|
|
||||||
exposed-modules: MyLib
|
|
||||||
|
|
||||||
-- Modules included in this library but not exported.
|
|
||||||
-- other-modules:
|
|
||||||
|
|
||||||
-- LANGUAGE extensions used by modules in this package.
|
|
||||||
-- other-extensions:
|
|
||||||
build-depends: base ^>=4.14.3.0
|
|
||||||
hs-source-dirs: src
|
|
||||||
default-language: Haskell2010
|
|
||||||
```
|
|
||||||
|
|
||||||
The interesting parts here are `exposed-modules` and `build-depends`.
|
|
||||||
To add a dependency, it should look like this:
|
|
||||||
|
|
||||||
```
|
|
||||||
build-depends: base ^>=4.14.3.0
|
|
||||||
, directory
|
|
||||||
```
|
|
||||||
|
|
||||||
Now open `src/MyLib.hs` and change it to:
|
|
||||||
|
|
||||||
```hs
|
|
||||||
module MyLib (someFunc) where
|
|
||||||
|
|
||||||
import System.Directory
|
|
||||||
|
|
||||||
someFunc :: IO ()
|
|
||||||
someFunc = do
|
|
||||||
contents <- listDirectory "src"
|
|
||||||
putStrLn (show contents)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Adding modules
|
|
||||||
|
|
||||||
To add a module to your package, adjust `exposed-modules`, like so
|
|
||||||
|
|
||||||
```
|
|
||||||
exposed-modules: MyLib
|
|
||||||
OtherLib
|
|
||||||
```
|
|
||||||
|
|
||||||
then create `src/OtherLib.hs` with the following contents:
|
|
||||||
|
|
||||||
```hs
|
|
||||||
module OtherLib where
|
|
||||||
|
|
||||||
otherFunc :: String -> Int
|
|
||||||
otherFunc str = length str
|
|
||||||
```
|
|
||||||
|
|
||||||
To use this function interactively, we can run:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
➜ cabal repl
|
|
||||||
ghci> import OtherLib
|
|
||||||
ghci> otherFunc "Hello Haskell"
|
|
||||||
13
|
|
||||||
```
|
|
||||||
|
|
||||||
For further information about how to manage Haskell projects
|
|
||||||
see the [Cabal user guide](https://cabal.readthedocs.io/en/stable/getting-started.html).
|
|
||||||
|
|
||||||
# Where to go from here
|
|
||||||
|
|
||||||
<div class="text-center main-buttons">
|
|
||||||
<a href="https://hackage.haskell.org/" class="btn btn-primary" role="button">Discover Haskell packages</a>
|
|
||||||
<a href="https://hackage.haskell.org/package/base" class="btn btn-primary" role="button">The standard library</a>
|
|
||||||
<a href="https://haskell-language-server.readthedocs.io/en/stable/installation.html" class="btn btn-primary" role="button">Editor setup with HLS</a>
|
|
||||||
<a href="https://play-haskell.tomsmeding.com/play" class="btn btn-primary" role="button">Online playground</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
## How to learn Haskell proper
|
|
||||||
|
|
||||||
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/))
|
|
||||||
- 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
|
|
||||||
|
|
||||||
* [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/commercialhaskell/stack](https://github.com/commercialhaskell/stack)
|
|
||||||
* [https://gitlab.haskell.org/haskell/ghcup-hs](https://gitlab.haskell.org/haskell/ghcup-hs)
|
|
||||||
* [https://github.com/jgm/pandoc](https://github.com/jgm/pandoc)
|
|
||||||
* [https://github.com/simonmichael/hledger](https://github.com/simonmichael/hledger)
|
|
||||||
* [https://github.com/koalaman/shellcheck](https://github.com/koalaman/shellcheck)
|
|
||||||
84
ghcup.cabal
84
ghcup.cabal
@@ -1,6 +1,6 @@
|
|||||||
cabal-version: 3.0
|
cabal-version: 3.0
|
||||||
name: ghcup
|
name: ghcup
|
||||||
version: 0.1.17.7
|
version: 0.1.17.3
|
||||||
license: LGPL-3.0-only
|
license: LGPL-3.0-only
|
||||||
license-file: LICENSE
|
license-file: LICENSE
|
||||||
copyright: Julian Ospald 2020
|
copyright: Julian Ospald 2020
|
||||||
@@ -48,34 +48,36 @@ flag no-exe
|
|||||||
default: False
|
default: False
|
||||||
manual: True
|
manual: True
|
||||||
|
|
||||||
flag disable-upgrade
|
|
||||||
description:
|
|
||||||
Disable upgrade functionality. This is mainly to support brew packagers.
|
|
||||||
|
|
||||||
default: False
|
|
||||||
manual: True
|
|
||||||
|
|
||||||
library
|
library
|
||||||
exposed-modules:
|
exposed-modules:
|
||||||
GHCup
|
GHCup
|
||||||
|
GHCup.Data.Versions
|
||||||
|
GHCup.GHC
|
||||||
|
GHCup.GHC.Rm
|
||||||
|
GHCup.GHC.Unset
|
||||||
|
GHCup.GHC.Set
|
||||||
|
GHCup.GHC.Compile
|
||||||
|
GHCup.GHC.Common
|
||||||
|
GHCup.GHC.Install
|
||||||
GHCup.Download
|
GHCup.Download
|
||||||
GHCup.Download.Utils
|
GHCup.Download.Common
|
||||||
GHCup.Errors
|
GHCup.Errors
|
||||||
GHCup.Platform
|
GHCup.Platform
|
||||||
GHCup.Requirements
|
GHCup.Requirements
|
||||||
GHCup.Types
|
GHCup.Types
|
||||||
GHCup.Types.JSON
|
GHCup.Types.JSON
|
||||||
GHCup.Types.JSON.Utils
|
|
||||||
GHCup.Types.Optics
|
GHCup.Types.Optics
|
||||||
GHCup.Utils
|
GHCup.Utils
|
||||||
GHCup.Utils.Dirs
|
GHCup.Directories
|
||||||
GHCup.Utils.File
|
GHCup.System.Process
|
||||||
GHCup.Utils.File.Common
|
GHCup.System.Directory
|
||||||
GHCup.Utils.Logger
|
GHCup.System.Process.Common
|
||||||
GHCup.Utils.MegaParsec
|
GHCup.System.Console
|
||||||
GHCup.Utils.Prelude
|
GHCup.Logger
|
||||||
GHCup.Utils.String.QQ
|
GHCup.MegaParsec
|
||||||
GHCup.Utils.Version.QQ
|
GHCup.Prelude
|
||||||
|
GHCup.QQ.String
|
||||||
|
GHCup.QQ.Version
|
||||||
GHCup.Version
|
GHCup.Version
|
||||||
|
|
||||||
hs-source-dirs: lib
|
hs-source-dirs: lib
|
||||||
@@ -118,10 +120,10 @@ library
|
|||||||
, disk-free-space ^>=0.1.0.1
|
, disk-free-space ^>=0.1.0.1
|
||||||
, filepath ^>=1.4.2.1
|
, filepath ^>=1.4.2.1
|
||||||
, haskus-utils-types ^>=1.5
|
, haskus-utils-types ^>=1.5
|
||||||
, haskus-utils-variant ^>=3.2.1
|
, haskus-utils-variant >=3.0 && <3.2
|
||||||
, libarchive ^>=3.0.3.0
|
, libarchive ^>=3.0.3.0
|
||||||
, lzma-static ^>=5.2.5.3
|
, lzma-static ^>=5.2.5.3
|
||||||
, megaparsec >=8.0.0 && <9.3
|
, megaparsec >=8.0.0 && <9.1
|
||||||
, mtl ^>=2.2
|
, mtl ^>=2.2
|
||||||
, optics ^>=0.4
|
, optics ^>=0.4
|
||||||
, os-release ^>=1.0.0
|
, os-release ^>=1.0.0
|
||||||
@@ -160,9 +162,9 @@ library
|
|||||||
if os(windows)
|
if os(windows)
|
||||||
cpp-options: -DIS_WINDOWS
|
cpp-options: -DIS_WINDOWS
|
||||||
other-modules:
|
other-modules:
|
||||||
GHCup.Utils.File.Windows
|
GHCup.System.Process.Windows
|
||||||
GHCup.Utils.Prelude.Windows
|
GHCup.Prelude.Windows
|
||||||
GHCup.Utils.Windows
|
GHCup.System.Console.Windows
|
||||||
|
|
||||||
build-depends:
|
build-depends:
|
||||||
, bzlib
|
, bzlib
|
||||||
@@ -171,13 +173,14 @@ library
|
|||||||
|
|
||||||
else
|
else
|
||||||
other-modules:
|
other-modules:
|
||||||
GHCup.Utils.File.Posix
|
GHCup.System.Process.Posix
|
||||||
GHCup.Utils.Posix
|
GHCup.System.Console.Posix
|
||||||
GHCup.Utils.Prelude.Posix
|
GHCup.Prelude.Posix
|
||||||
|
System.Console.Terminal.Common
|
||||||
|
System.Console.Terminal.Posix
|
||||||
|
|
||||||
build-depends:
|
build-depends:
|
||||||
, bz2 >=0.5.0.5 && <1.1
|
, bz2 >=0.5.0.5 && <1.1
|
||||||
, terminal-size ^>=0.3.2.1
|
|
||||||
, unix ^>=2.7
|
, unix ^>=2.7
|
||||||
, unix-bytestring ^>=0.3.7.3
|
, unix-bytestring ^>=0.3.7.3
|
||||||
|
|
||||||
@@ -200,10 +203,10 @@ executable ghcup
|
|||||||
GHCup.OptParse.Nuke
|
GHCup.OptParse.Nuke
|
||||||
GHCup.OptParse.Prefetch
|
GHCup.OptParse.Prefetch
|
||||||
GHCup.OptParse.Rm
|
GHCup.OptParse.Rm
|
||||||
GHCup.OptParse.Run
|
|
||||||
GHCup.OptParse.Set
|
GHCup.OptParse.Set
|
||||||
GHCup.OptParse.ToolRequirements
|
GHCup.OptParse.ToolRequirements
|
||||||
GHCup.OptParse.UnSet
|
GHCup.OptParse.UnSet
|
||||||
|
GHCup.OptParse.Upgrade
|
||||||
GHCup.OptParse.Whereis
|
GHCup.OptParse.Whereis
|
||||||
|
|
||||||
hs-source-dirs: app/ghcup
|
hs-source-dirs: app/ghcup
|
||||||
@@ -234,25 +237,20 @@ executable ghcup
|
|||||||
, directory ^>=1.3.6.0
|
, directory ^>=1.3.6.0
|
||||||
, filepath ^>=1.4.2.1
|
, filepath ^>=1.4.2.1
|
||||||
, ghcup
|
, ghcup
|
||||||
, haskus-utils-variant ^>=3.2.1
|
, haskus-utils-variant >=3.0 && <3.2
|
||||||
, libarchive ^>=3.0.3.0
|
, libarchive ^>=3.0.3.0
|
||||||
, megaparsec >=8.0.0 && <9.3
|
, megaparsec >=8.0.0 && <9.1
|
||||||
, mtl ^>=2.2
|
, mtl ^>=2.2
|
||||||
, optparse-applicative >=0.15.1.0 && <0.18
|
, optparse-applicative-fork >=0.15.1.0 && <0.17
|
||||||
, pretty ^>=1.1.3.1
|
, pretty ^>=1.1.3.1
|
||||||
, pretty-terminal ^>=0.1.0.0
|
, pretty-terminal ^>=0.1.0.0
|
||||||
, process ^>=1.6.11.0
|
|
||||||
, resourcet ^>=1.2.2
|
, resourcet ^>=1.2.2
|
||||||
, safe ^>=0.3.18
|
, safe ^>=0.3.18
|
||||||
, safe-exceptions ^>=0.1
|
, safe-exceptions ^>=0.1
|
||||||
, tagsoup ^>=0.14
|
|
||||||
, template-haskell >=2.7 && <2.18
|
, template-haskell >=2.7 && <2.18
|
||||||
, temporary ^>=1.3
|
|
||||||
, text ^>=1.2.4.0
|
, text ^>=1.2.4.0
|
||||||
, unordered-containers ^>=0.2
|
|
||||||
, uri-bytestring ^>=0.3.2.2
|
, uri-bytestring ^>=0.3.2.2
|
||||||
, utf8-string ^>=1.0
|
, utf8-string ^>=1.0
|
||||||
, vector ^>=0.12
|
|
||||||
, versions >=4.0.1 && <5.1
|
, versions >=4.0.1 && <5.1
|
||||||
, yaml-streamly ^>=0.12.0
|
, yaml-streamly ^>=0.12.0
|
||||||
|
|
||||||
@@ -266,23 +264,15 @@ executable ghcup
|
|||||||
, brick ^>=0.64
|
, brick ^>=0.64
|
||||||
, transformers ^>=0.5
|
, transformers ^>=0.5
|
||||||
, unix ^>=2.7
|
, unix ^>=2.7
|
||||||
|
, vector ^>=0.12
|
||||||
, vty >=5.28.2 && <5.34
|
, vty >=5.28.2 && <5.34
|
||||||
|
|
||||||
if os(windows)
|
if os(windows)
|
||||||
cpp-options: -DIS_WINDOWS
|
cpp-options: -DIS_WINDOWS
|
||||||
|
|
||||||
else
|
|
||||||
build-depends: unix ^>=2.7
|
|
||||||
|
|
||||||
if flag(no-exe)
|
if flag(no-exe)
|
||||||
buildable: False
|
buildable: False
|
||||||
|
|
||||||
if flag(disable-upgrade)
|
|
||||||
cpp-options: -DDISABLE_UPGRADE
|
|
||||||
|
|
||||||
else
|
|
||||||
other-modules: GHCup.OptParse.Upgrade
|
|
||||||
|
|
||||||
test-suite ghcup-test
|
test-suite ghcup-test
|
||||||
type: exitcode-stdio-1.0
|
type: exitcode-stdio-1.0
|
||||||
main-is: Main.hs
|
main-is: Main.hs
|
||||||
@@ -310,9 +300,9 @@ test-suite ghcup-test
|
|||||||
, base >=4.12 && <5
|
, base >=4.12 && <5
|
||||||
, bytestring ^>=0.10
|
, bytestring ^>=0.10
|
||||||
, containers ^>=0.6
|
, containers ^>=0.6
|
||||||
, generic-arbitrary >=0.1.0 && <0.3
|
, generic-arbitrary ^>=0.1.0
|
||||||
, ghcup
|
, ghcup
|
||||||
, hspec >=2.7.10 && <2.10
|
, hspec ^>=2.7.10
|
||||||
, 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
|
||||||
|
|||||||
1232
lib/GHCup.hs
1232
lib/GHCup.hs
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,7 @@
|
|||||||
{-# LANGUAGE ViewPatterns #-}
|
{-# LANGUAGE ViewPatterns #-}
|
||||||
|
|
||||||
{-|
|
{-|
|
||||||
Module : GHCup.Utils.Dirs
|
Module : GHCup.Directories
|
||||||
Description : Definition of GHCup directories
|
Description : Definition of GHCup directories
|
||||||
Copyright : (c) Julian Ospald, 2020
|
Copyright : (c) Julian Ospald, 2020
|
||||||
License : LGPL-3.0
|
License : LGPL-3.0
|
||||||
@@ -13,18 +13,15 @@ Maintainer : hasufell@hasufell.de
|
|||||||
Stability : experimental
|
Stability : experimental
|
||||||
Portability : portable
|
Portability : portable
|
||||||
-}
|
-}
|
||||||
module GHCup.Utils.Dirs
|
module GHCup.Directories
|
||||||
( getAllDirs
|
( getAllDirs
|
||||||
, ghcupBaseDir
|
, ghcupBaseDir
|
||||||
, ghcupConfigFile
|
, ghcupConfigFile
|
||||||
, ghcupCacheDir
|
, ghcupCacheDir
|
||||||
, ghcupGHCBaseDir
|
, ghcupGHCBaseDir
|
||||||
, ghcupGHCDir
|
, ghcupGHCDir
|
||||||
, ghcupHLSBaseDir
|
|
||||||
, ghcupHLSDir
|
|
||||||
, mkGhcupTmpDir
|
, mkGhcupTmpDir
|
||||||
, parseGHCupGHCDir
|
, parseGHCupGHCDir
|
||||||
, parseGHCupHLSDir
|
|
||||||
, relativeSymlink
|
, relativeSymlink
|
||||||
, withGHCupTmpDir
|
, withGHCupTmpDir
|
||||||
, getConfigFilePath
|
, getConfigFilePath
|
||||||
@@ -38,9 +35,9 @@ import GHCup.Errors
|
|||||||
import GHCup.Types
|
import GHCup.Types
|
||||||
import GHCup.Types.JSON ( )
|
import GHCup.Types.JSON ( )
|
||||||
import GHCup.Types.Optics
|
import GHCup.Types.Optics
|
||||||
import GHCup.Utils.MegaParsec
|
import GHCup.MegaParsec
|
||||||
import GHCup.Utils.Logger
|
import GHCup.Logger
|
||||||
import GHCup.Utils.Prelude
|
import GHCup.Prelude
|
||||||
|
|
||||||
import Control.Exception.Safe
|
import Control.Exception.Safe
|
||||||
import Control.Monad
|
import Control.Monad
|
||||||
@@ -49,7 +46,6 @@ import Control.Monad.Reader
|
|||||||
import Control.Monad.Trans.Resource hiding (throwM)
|
import Control.Monad.Trans.Resource hiding (throwM)
|
||||||
import Data.Bifunctor
|
import Data.Bifunctor
|
||||||
import Data.Maybe
|
import Data.Maybe
|
||||||
import Data.Versions
|
|
||||||
import GHC.IO.Exception ( IOErrorType(NoSuchThing) )
|
import GHC.IO.Exception ( IOErrorType(NoSuchThing) )
|
||||||
import Haskus.Utils.Variant.Excepts
|
import Haskus.Utils.Variant.Excepts
|
||||||
import Optics
|
import Optics
|
||||||
@@ -248,24 +244,6 @@ parseGHCupGHCDir :: MonadThrow m => FilePath -> m GHCTargetVersion
|
|||||||
parseGHCupGHCDir (T.pack -> fp) =
|
parseGHCupGHCDir (T.pack -> fp) =
|
||||||
throwEither $ MP.parse ghcTargetVerP "" fp
|
throwEither $ MP.parse ghcTargetVerP "" fp
|
||||||
|
|
||||||
parseGHCupHLSDir :: MonadThrow m => FilePath -> m Version
|
|
||||||
parseGHCupHLSDir (T.pack -> fp) =
|
|
||||||
throwEither $ MP.parse version' "" fp
|
|
||||||
|
|
||||||
-- | ~/.ghcup/hls by default, for new-style installs.
|
|
||||||
ghcupHLSBaseDir :: (MonadReader env m, HasDirs env) => m FilePath
|
|
||||||
ghcupHLSBaseDir = do
|
|
||||||
Dirs {..} <- getDirs
|
|
||||||
pure (baseDir </> "hls")
|
|
||||||
|
|
||||||
-- | Gets '~/.ghcup/hls/<hls-ver>' for new-style installs.
|
|
||||||
ghcupHLSDir :: (MonadReader env m, HasDirs env, MonadThrow m)
|
|
||||||
=> Version
|
|
||||||
-> m FilePath
|
|
||||||
ghcupHLSDir ver = do
|
|
||||||
basedir <- ghcupHLSBaseDir
|
|
||||||
let verdir = T.unpack $ prettyVer ver
|
|
||||||
pure (basedir </> verdir)
|
|
||||||
|
|
||||||
mkGhcupTmpDir :: ( MonadReader env m
|
mkGhcupTmpDir :: ( MonadReader env m
|
||||||
, HasDirs env
|
, HasDirs env
|
||||||
@@ -335,19 +313,16 @@ useXDG :: IO Bool
|
|||||||
useXDG = isJust <$> lookupEnv "GHCUP_USE_XDG_DIRS"
|
useXDG = isJust <$> lookupEnv "GHCUP_USE_XDG_DIRS"
|
||||||
|
|
||||||
|
|
||||||
-- | Like 'relpath'. Assumes the inputs are resolved in case of symlinks.
|
|
||||||
relativeSymlink :: FilePath -- ^ the path in which to create the symlink
|
relativeSymlink :: FilePath -- ^ the path in which to create the symlink
|
||||||
-> FilePath -- ^ the symlink destination
|
-> FilePath -- ^ the symlink destination
|
||||||
-> FilePath
|
-> FilePath
|
||||||
relativeSymlink p1 p2
|
relativeSymlink p1 p2 =
|
||||||
| isWindows = p2 -- windows quickly gets into MAX_PATH issues so we don't care about relative symlinks
|
let d1 = splitDirectories p1
|
||||||
| otherwise =
|
d2 = splitDirectories p2
|
||||||
let d1 = splitDirectories p1
|
common = takeWhile (\(x, y) -> x == y) $ zip d1 d2
|
||||||
d2 = splitDirectories p2
|
cPrefix = drop (length common) d1
|
||||||
common = takeWhile (\(x, y) -> x == y) $ zip d1 d2
|
in joinPath (replicate (length cPrefix) "..")
|
||||||
cPrefix = drop (length common) d1
|
<> joinPath ([pathSeparator] : drop (length common) d2)
|
||||||
in joinPath (replicate (length cPrefix) "..")
|
|
||||||
<> joinPath ([pathSeparator] : drop (length common) d2)
|
|
||||||
|
|
||||||
|
|
||||||
cleanupTrash :: ( MonadIO m
|
cleanupTrash :: ( MonadIO m
|
||||||
@@ -27,16 +27,16 @@ module GHCup.Download where
|
|||||||
|
|
||||||
#if defined(INTERNAL_DOWNLOADER)
|
#if defined(INTERNAL_DOWNLOADER)
|
||||||
import GHCup.Download.IOStreams
|
import GHCup.Download.IOStreams
|
||||||
import GHCup.Download.Utils
|
import GHCup.Download.Common
|
||||||
#endif
|
#endif
|
||||||
import GHCup.Errors
|
import GHCup.Errors
|
||||||
import GHCup.Types
|
import GHCup.Types
|
||||||
import GHCup.Types.Optics
|
import GHCup.Types.Optics
|
||||||
import GHCup.Types.JSON ( )
|
import GHCup.Types.JSON ( )
|
||||||
import GHCup.Utils.Dirs
|
import GHCup.Directories
|
||||||
import GHCup.Utils.File
|
import GHCup.System.Process
|
||||||
import GHCup.Utils.Logger
|
import GHCup.Logger
|
||||||
import GHCup.Utils.Prelude
|
import GHCup.Prelude
|
||||||
import GHCup.Version
|
import GHCup.Version
|
||||||
|
|
||||||
import Control.Applicative
|
import Control.Applicative
|
||||||
@@ -121,25 +121,28 @@ getDownloadsF = do
|
|||||||
Settings { urlSource } <- lift getSettings
|
Settings { urlSource } <- lift getSettings
|
||||||
case urlSource of
|
case urlSource of
|
||||||
GHCupURL -> liftE $ getBase ghcupURL
|
GHCupURL -> liftE $ getBase ghcupURL
|
||||||
(OwnSource exts) -> do
|
(OwnSource url) -> liftE $ getBase url
|
||||||
ext <- liftE $ mapM (either pure getBase) exts
|
|
||||||
mergeGhcupInfo ext
|
|
||||||
(OwnSpec av) -> pure av
|
(OwnSpec av) -> pure av
|
||||||
(AddSource exts) -> do
|
(AddSource (Left ext)) -> do
|
||||||
base <- liftE $ getBase ghcupURL
|
base <- liftE $ getBase ghcupURL
|
||||||
ext <- liftE $ mapM (either pure getBase) exts
|
pure (mergeGhcupInfo base ext)
|
||||||
mergeGhcupInfo (base:ext)
|
(AddSource (Right uri)) -> do
|
||||||
|
base <- liftE $ getBase ghcupURL
|
||||||
|
ext <- liftE $ getBase uri
|
||||||
|
pure (mergeGhcupInfo base ext)
|
||||||
|
|
||||||
where
|
where
|
||||||
mergeGhcupInfo :: MonadFail m
|
|
||||||
=> [GHCupInfo]
|
mergeGhcupInfo :: GHCupInfo -- ^ base to merge with
|
||||||
-> m GHCupInfo
|
-> GHCupInfo -- ^ extension overwriting the base
|
||||||
mergeGhcupInfo [] = fail "mergeGhcupInfo: internal error: need at least one GHCupInfo"
|
-> GHCupInfo
|
||||||
mergeGhcupInfo xs@(GHCupInfo{}: _) =
|
mergeGhcupInfo (GHCupInfo tr base base2) (GHCupInfo _ ext ext2) =
|
||||||
let newDownloads = M.unionsWith (M.unionWith (\_ b2 -> b2)) (_ghcupDownloads <$> xs)
|
let newDownloads = M.mapWithKey (\k a -> case M.lookup k ext of
|
||||||
newGlobalTools = M.unionsWith (\_ a2 -> a2 ) (_globalTools <$> xs)
|
Just a' -> M.union a' a
|
||||||
newToolReqs = M.unionsWith (M.unionWith (\_ b2 -> b2)) (_toolRequirements <$> xs)
|
Nothing -> a
|
||||||
in pure $ GHCupInfo newToolReqs newDownloads newGlobalTools
|
) base
|
||||||
|
newGlobalTools = M.union base2 ext2
|
||||||
|
in GHCupInfo tr newDownloads newGlobalTools
|
||||||
|
|
||||||
|
|
||||||
yamlFromCache :: (MonadReader env m, HasDirs env) => URI -> m FilePath
|
yamlFromCache :: (MonadReader env m, HasDirs env) => URI -> m FilePath
|
||||||
|
|||||||
@@ -4,13 +4,13 @@
|
|||||||
{-# LANGUAGE TypeFamilies #-}
|
{-# LANGUAGE TypeFamilies #-}
|
||||||
|
|
||||||
|
|
||||||
module GHCup.Download.Utils where
|
module GHCup.Download.Common where
|
||||||
|
|
||||||
|
|
||||||
import GHCup.Errors
|
import GHCup.Errors
|
||||||
import GHCup.Types.Optics
|
import GHCup.Types.Optics
|
||||||
import GHCup.Types.JSON ( )
|
import GHCup.Types.JSON ( )
|
||||||
import GHCup.Utils.Prelude
|
import GHCup.Prelude
|
||||||
|
|
||||||
import Control.Applicative
|
import Control.Applicative
|
||||||
import Control.Monad
|
import Control.Monad
|
||||||
@@ -7,10 +7,10 @@
|
|||||||
module GHCup.Download.IOStreams where
|
module GHCup.Download.IOStreams where
|
||||||
|
|
||||||
|
|
||||||
import GHCup.Download.Utils
|
import GHCup.Download.Common
|
||||||
import GHCup.Errors
|
import GHCup.Errors
|
||||||
import GHCup.Types.JSON ( )
|
import GHCup.Types.JSON ( )
|
||||||
import GHCup.Utils.Prelude
|
import GHCup.Prelude
|
||||||
|
|
||||||
import Control.Applicative
|
import Control.Applicative
|
||||||
import Control.Exception.Safe
|
import Control.Exception.Safe
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
{-# LANGUAGE FlexibleContexts #-}
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
|
{-# LANGUAGE QuasiQuotes #-}
|
||||||
{-# LANGUAGE DataKinds #-}
|
{-# LANGUAGE DataKinds #-}
|
||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
|
||||||
{-|
|
{-|
|
||||||
Module : GHCup.Utils.Logger
|
Module : GHCup.Logger
|
||||||
Description : logger definition
|
Description : logger definition
|
||||||
Copyright : (c) Julian Ospald, 2020
|
Copyright : (c) Julian Ospald, 2020
|
||||||
License : LGPL-3.0
|
License : LGPL-3.0
|
||||||
@@ -13,12 +14,12 @@ Portability : portable
|
|||||||
|
|
||||||
Here we define our main logger.
|
Here we define our main logger.
|
||||||
-}
|
-}
|
||||||
module GHCup.Utils.Logger where
|
module GHCup.Logger where
|
||||||
|
|
||||||
import GHCup.Types
|
import GHCup.Types
|
||||||
import GHCup.Types.Optics
|
import GHCup.Types.Optics
|
||||||
import {-# SOURCE #-} GHCup.Utils.File.Common (findFiles)
|
import {-# SOURCE #-} GHCup.System.Directory
|
||||||
import GHCup.Utils.String.QQ
|
import GHCup.QQ.String
|
||||||
|
|
||||||
import Control.Exception.Safe
|
import Control.Exception.Safe
|
||||||
import Control.Monad
|
import Control.Monad
|
||||||
@@ -33,7 +34,7 @@ import System.IO.Error
|
|||||||
import Text.Regex.Posix
|
import Text.Regex.Posix
|
||||||
|
|
||||||
import qualified Data.ByteString as B
|
import qualified Data.ByteString as B
|
||||||
import GHCup.Utils.Prelude
|
import GHCup.Prelude
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
|
|
||||||
logInfo :: ( MonadReader env m
|
logInfo :: ( MonadReader env m
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
{-# LANGUAGE FlexibleContexts #-}
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
|
{-# LANGUAGE QuasiQuotes #-}
|
||||||
{-# LANGUAGE DataKinds #-}
|
{-# LANGUAGE DataKinds #-}
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
|
||||||
module GHCup.Utils.Logger where
|
module GHCup.Logger where
|
||||||
|
|
||||||
import GHCup.Types
|
import GHCup.Types
|
||||||
|
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
|
||||||
{-|
|
{-|
|
||||||
Module : GHCup.Utils.MegaParsec
|
Module : GHCup.MegaParsec
|
||||||
Description : MegaParsec utilities
|
Description : MegaParsec utilities
|
||||||
Copyright : (c) Julian Ospald, 2020
|
Copyright : (c) Julian Ospald, 2020
|
||||||
License : LGPL-3.0
|
License : LGPL-3.0
|
||||||
@@ -10,7 +10,7 @@ Maintainer : hasufell@hasufell.de
|
|||||||
Stability : experimental
|
Stability : experimental
|
||||||
Portability : portable
|
Portability : portable
|
||||||
-}
|
-}
|
||||||
module GHCup.Utils.MegaParsec where
|
module GHCup.MegaParsec where
|
||||||
|
|
||||||
import GHCup.Types
|
import GHCup.Types
|
||||||
|
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
{-# LANGUAGE FlexibleInstances #-}
|
{-# LANGUAGE FlexibleInstances #-}
|
||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
{-# LANGUAGE QuasiQuotes #-}
|
{-# LANGUAGE QuasiQuotes #-}
|
||||||
{-# LANGUAGE TemplateHaskellQuotes #-}
|
{-# LANGUAGE TemplateHaskell #-}
|
||||||
|
|
||||||
|
|
||||||
{-|
|
{-|
|
||||||
@@ -23,10 +23,10 @@ import GHCup.Errors
|
|||||||
import GHCup.Types
|
import GHCup.Types
|
||||||
import GHCup.Types.Optics
|
import GHCup.Types.Optics
|
||||||
import GHCup.Types.JSON ( )
|
import GHCup.Types.JSON ( )
|
||||||
import GHCup.Utils.File
|
import GHCup.System.Process
|
||||||
import GHCup.Utils.Logger
|
import GHCup.Logger
|
||||||
import GHCup.Utils.Prelude
|
import GHCup.Prelude
|
||||||
import GHCup.Utils.String.QQ
|
import GHCup.QQ.String
|
||||||
|
|
||||||
#if !MIN_VERSION_base(4,13,0)
|
#if !MIN_VERSION_base(4,13,0)
|
||||||
import Control.Monad.Fail ( MonadFail )
|
import Control.Monad.Fail ( MonadFail )
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
{-# LANGUAGE TypeOperators #-}
|
{-# LANGUAGE TypeOperators #-}
|
||||||
|
|
||||||
{-|
|
{-|
|
||||||
Module : GHCup.Utils.Prelude
|
Module : GHCup.Prelude
|
||||||
Description : MegaParsec utilities
|
Description : MegaParsec utilities
|
||||||
Copyright : (c) Julian Ospald, 2020
|
Copyright : (c) Julian Ospald, 2020
|
||||||
License : LGPL-3.0
|
License : LGPL-3.0
|
||||||
@@ -17,12 +17,12 @@ Portability : portable
|
|||||||
|
|
||||||
GHCup specific prelude. Lots of Excepts functionality.
|
GHCup specific prelude. Lots of Excepts functionality.
|
||||||
-}
|
-}
|
||||||
module GHCup.Utils.Prelude
|
module GHCup.Prelude
|
||||||
(module GHCup.Utils.Prelude,
|
(module GHCup.Prelude,
|
||||||
#if defined(IS_WINDOWS)
|
#if defined(IS_WINDOWS)
|
||||||
module GHCup.Utils.Prelude.Windows
|
module GHCup.Prelude.Windows
|
||||||
#else
|
#else
|
||||||
module GHCup.Utils.Prelude.Posix
|
module GHCup.Prelude.Posix
|
||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
@@ -30,11 +30,11 @@ where
|
|||||||
import GHCup.Types
|
import GHCup.Types
|
||||||
import GHCup.Errors
|
import GHCup.Errors
|
||||||
import GHCup.Types.Optics
|
import GHCup.Types.Optics
|
||||||
import {-# SOURCE #-} GHCup.Utils.Logger (logWarn)
|
import {-# SOURCE #-} GHCup.Logger
|
||||||
#if defined(IS_WINDOWS)
|
#if defined(IS_WINDOWS)
|
||||||
import GHCup.Utils.Prelude.Windows
|
import GHCup.Prelude.Windows
|
||||||
#else
|
#else
|
||||||
import GHCup.Utils.Prelude.Posix
|
import GHCup.Prelude.Posix
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
import Control.Applicative
|
import Control.Applicative
|
||||||
@@ -308,6 +308,11 @@ intToText :: Integral a => a -> T.Text
|
|||||||
intToText = TL.toStrict . B.toLazyText . B.decimal
|
intToText = TL.toStrict . B.toLazyText . B.decimal
|
||||||
|
|
||||||
|
|
||||||
|
removeLensFieldLabel :: String -> String
|
||||||
|
removeLensFieldLabel str' =
|
||||||
|
maybe str' T.unpack . T.stripPrefix (T.pack "_") . T.pack $ str'
|
||||||
|
|
||||||
|
|
||||||
pvpToVersion :: MonadThrow m => PVP -> Text -> m Version
|
pvpToVersion :: MonadThrow m => PVP -> Text -> m Version
|
||||||
pvpToVersion pvp_ rest =
|
pvpToVersion pvp_ rest =
|
||||||
either (\_ -> throwM $ ParseError "Couldn't convert PVP to Version") pure . version . (<> rest) . prettyPVP $ pvp_
|
either (\_ -> throwM $ ParseError "Couldn't convert PVP to Version") pure . version . (<> rest) . prettyPVP $ pvp_
|
||||||
@@ -472,9 +477,7 @@ recyclePathForcibly fp
|
|||||||
let dest = tmp </> takeFileName fp
|
let dest = tmp </> takeFileName fp
|
||||||
liftIO (moveFile fp dest)
|
liftIO (moveFile fp dest)
|
||||||
`catch`
|
`catch`
|
||||||
(\e -> if | isDoesNotExistError e -> pure ()
|
(\e -> if isPermissionError e {- EXDEV on windows -} then recover (liftIO $ removePathForcibly fp) else throwIO e)
|
||||||
| isPermissionError e || ioeGetErrorType e == UnsupportedOperation {- EXDEV on windows -} -> recover (liftIO $ removePathForcibly fp)
|
|
||||||
| otherwise -> throwIO e)
|
|
||||||
`finally`
|
`finally`
|
||||||
liftIO (handleIO (\_ -> pure ()) $ removePathForcibly tmp)
|
liftIO (handleIO (\_ -> pure ()) $ removePathForcibly tmp)
|
||||||
| otherwise = liftIO $ removePathForcibly fp
|
| otherwise = liftIO $ removePathForcibly fp
|
||||||
@@ -515,7 +518,7 @@ recycleFile fp
|
|||||||
let dest = tmp </> takeFileName fp
|
let dest = tmp </> takeFileName fp
|
||||||
liftIO (moveFile fp dest)
|
liftIO (moveFile fp dest)
|
||||||
`catch`
|
`catch`
|
||||||
(\e -> if isPermissionError e || ioeGetErrorType e == UnsupportedOperation {- EXDEV on windows -} then recover (liftIO $ removePathForcibly fp) else throwIO e)
|
(\e -> if isPermissionError e {- EXDEV on windows -} then recover (liftIO $ removePathForcibly fp) else throwIO e)
|
||||||
`finally`
|
`finally`
|
||||||
liftIO (handleIO (\_ -> pure ()) $ removePathForcibly tmp)
|
liftIO (handleIO (\_ -> pure ()) $ removePathForcibly tmp)
|
||||||
| otherwise = liftIO $ removeFile fp
|
| otherwise = liftIO $ removeFile fp
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
module GHCup.Utils.Prelude.Posix where
|
module GHCup.Prelude.Posix where
|
||||||
|
|
||||||
import System.Directory
|
import System.Directory
|
||||||
import System.Posix.Files
|
import System.Posix.Files
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
module GHCup.Utils.Prelude.Windows where
|
module GHCup.Prelude.Windows where
|
||||||
|
|
||||||
import qualified System.Win32.File as Win32
|
import qualified System.Win32.File as Win32
|
||||||
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{-# LANGUAGE TemplateHaskellQuotes #-}
|
{-# LANGUAGE TemplateHaskell #-}
|
||||||
|
|
||||||
{-|
|
{-|
|
||||||
Module : GHCup.Utils.String.QQ
|
Module : GHCup.QQ.String
|
||||||
Description : String quasi quoters
|
Description : String quasi quoters
|
||||||
Copyright : (c) Audrey Tang <audreyt@audreyt.org> 2019, Julian Ospald <hasufell@posteo.de> 2020
|
Copyright : (c) Audrey Tang <audreyt@audreyt.org> 2019, Julian Ospald <hasufell@posteo.de> 2020
|
||||||
License : LGPL-3.0
|
License : LGPL-3.0
|
||||||
@@ -30,7 +30,7 @@ Any instance of the IsString type is permitted.
|
|||||||
(For GHC versions 6, write "[$s||]" instead of "[s||]".)
|
(For GHC versions 6, write "[$s||]" instead of "[s||]".)
|
||||||
|
|
||||||
-}
|
-}
|
||||||
module GHCup.Utils.String.QQ
|
module GHCup.QQ.String
|
||||||
( s
|
( s
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
@@ -4,11 +4,11 @@
|
|||||||
{-# LANGUAGE DeriveLift #-}
|
{-# LANGUAGE DeriveLift #-}
|
||||||
{-# LANGUAGE FlexibleInstances #-}
|
{-# LANGUAGE FlexibleInstances #-}
|
||||||
{-# LANGUAGE StandaloneDeriving #-}
|
{-# LANGUAGE StandaloneDeriving #-}
|
||||||
{-# LANGUAGE TemplateHaskellQuotes #-}
|
{-# LANGUAGE TemplateHaskell #-}
|
||||||
|
|
||||||
|
|
||||||
{-|
|
{-|
|
||||||
Module : GHCup.Utils.Version.QQ
|
Module : GHCup.QQ.Version
|
||||||
Description : Version quasi-quoters
|
Description : Version quasi-quoters
|
||||||
Copyright : (c) Julian Ospald, 2020
|
Copyright : (c) Julian Ospald, 2020
|
||||||
License : LGPL-3.0
|
License : LGPL-3.0
|
||||||
@@ -16,7 +16,7 @@ Maintainer : hasufell@hasufell.de
|
|||||||
Stability : experimental
|
Stability : experimental
|
||||||
Portability : portable
|
Portability : portable
|
||||||
-}
|
-}
|
||||||
module GHCup.Utils.Version.QQ where
|
module GHCup.QQ.Version where
|
||||||
|
|
||||||
import Data.Data
|
import Data.Data
|
||||||
import Data.Text ( Text )
|
import Data.Text ( Text )
|
||||||
@@ -67,9 +67,3 @@ prettyRequirements Requirements {..} =
|
|||||||
else ""
|
else ""
|
||||||
n = if not . T.null $ _notes then "\n Note: " <> _notes else ""
|
n = if not . T.null $ _notes then "\n Note: " <> _notes else ""
|
||||||
in "System requirements " <> d <> n
|
in "System requirements " <> d <> n
|
||||||
|
|
||||||
rawRequirements :: Requirements -> T.Text
|
|
||||||
rawRequirements Requirements {..} =
|
|
||||||
if not . null $ _distroPKGs
|
|
||||||
then T.intercalate " " _distroPKGs
|
|
||||||
else ""
|
|
||||||
|
|||||||
16
lib/GHCup/System/Console.hs
Normal file
16
lib/GHCup/System/Console.hs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{-# LANGUAGE CPP #-}
|
||||||
|
|
||||||
|
module GHCup.System.Console (
|
||||||
|
#if IS_WINDOWS
|
||||||
|
module GHCup.System.Console.Windows
|
||||||
|
#else
|
||||||
|
module GHCup.System.Console.Posix
|
||||||
|
#endif
|
||||||
|
) where
|
||||||
|
|
||||||
|
|
||||||
|
#if IS_WINDOWS
|
||||||
|
import GHCup.System.Console.Windows
|
||||||
|
#else
|
||||||
|
import GHCup.System.Console.Posix
|
||||||
|
#endif
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
module GHCup.Utils.Posix where
|
module GHCup.System.Console.Posix where
|
||||||
|
|
||||||
|
|
||||||
-- | Enables ANSI support on windows, does nothing on unix.
|
-- | Enables ANSI support on windows, does nothing on unix.
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
{-# LANGUAGE FlexibleContexts #-}
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
|
||||||
module GHCup.Utils.Windows where
|
module GHCup.System.Console.Windows where
|
||||||
|
|
||||||
|
|
||||||
import Control.Exception.Safe
|
import Control.Exception.Safe
|
||||||
@@ -1,32 +1,29 @@
|
|||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
{-# LANGUAGE FlexibleContexts #-}
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
|
{-# LANGUAGE TemplateHaskell #-}
|
||||||
|
{-# LANGUAGE ViewPatterns #-}
|
||||||
|
|
||||||
module GHCup.Utils.File.Common (
|
module GHCup.System.Directory where
|
||||||
module GHCup.Utils.File.Common
|
|
||||||
, ProcessError(..)
|
|
||||||
, CapturedProcess(..)
|
|
||||||
) where
|
|
||||||
|
|
||||||
import GHCup.Utils.Prelude
|
import GHCup.Prelude
|
||||||
import GHCup.Types(ProcessError(..), CapturedProcess(..))
|
|
||||||
|
|
||||||
import Control.Monad.Reader
|
import Control.Monad.Reader
|
||||||
import Data.Maybe
|
import Data.Maybe
|
||||||
import Data.Text ( Text )
|
import Data.Text ( Text )
|
||||||
import Data.Void
|
import Data.Void
|
||||||
import GHC.IO.Exception
|
import GHC.IO.Exception
|
||||||
import Optics hiding ((<|), (|>))
|
import System.Directory
|
||||||
import System.Directory hiding (findFiles)
|
|
||||||
import System.FilePath
|
import System.FilePath
|
||||||
import Text.PrettyPrint.HughesPJClass hiding ( (<>) )
|
|
||||||
import Text.Regex.Posix
|
import Text.Regex.Posix
|
||||||
|
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import qualified Data.ByteString.Lazy as BL
|
|
||||||
import qualified Text.Megaparsec as MP
|
import qualified Text.Megaparsec as MP
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- | Search for a file in the search paths.
|
-- | Search for a file in the search paths.
|
||||||
--
|
--
|
||||||
-- Catches `PermissionDenied` and `NoSuchThing` and returns `Nothing`.
|
-- Catches `PermissionDenied` and `NoSuchThing` and returns `Nothing`.
|
||||||
@@ -76,21 +73,6 @@ isInPath p = do
|
|||||||
else pure False
|
else pure False
|
||||||
|
|
||||||
|
|
||||||
-- | Follows the first match in case of Regex.
|
|
||||||
expandFilePath :: [Either FilePath Regex] -> IO [FilePath]
|
|
||||||
expandFilePath = go ""
|
|
||||||
where
|
|
||||||
go :: FilePath -> [Either FilePath Regex] -> IO [FilePath]
|
|
||||||
go p [] = pure [p]
|
|
||||||
go p (x:xs) = do
|
|
||||||
case x of
|
|
||||||
Left s -> go (p </> s) xs
|
|
||||||
Right regex -> do
|
|
||||||
fps <- findFiles p regex
|
|
||||||
res <- forM fps $ \fp -> go (p </> fp) xs
|
|
||||||
pure $ mconcat res
|
|
||||||
|
|
||||||
|
|
||||||
findFiles :: FilePath -> Regex -> IO [FilePath]
|
findFiles :: FilePath -> Regex -> IO [FilePath]
|
||||||
findFiles path regex = do
|
findFiles path regex = do
|
||||||
contents <- listDirectory path
|
contents <- listDirectory path
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
module GHCup.Utils.File.Common where
|
module GHCup.System.Directory where
|
||||||
|
|
||||||
import Text.Regex.Posix
|
import Text.Regex.Posix
|
||||||
|
|
||||||
19
lib/GHCup/System/Process.hs
Normal file
19
lib/GHCup/System/Process.hs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{-# LANGUAGE CPP #-}
|
||||||
|
|
||||||
|
module GHCup.System.Process (
|
||||||
|
module GHCup.System.Process.Common,
|
||||||
|
#if IS_WINDOWS
|
||||||
|
module GHCup.System.Process.Windows
|
||||||
|
#else
|
||||||
|
module GHCup.System.Process.Posix
|
||||||
|
#endif
|
||||||
|
) where
|
||||||
|
|
||||||
|
|
||||||
|
#if IS_WINDOWS
|
||||||
|
import GHCup.System.Process.Windows
|
||||||
|
#else
|
||||||
|
import GHCup.System.Process.Posix
|
||||||
|
#endif
|
||||||
|
|
||||||
|
import GHCup.System.Process.Common
|
||||||
37
lib/GHCup/System/Process/Common.hs
Normal file
37
lib/GHCup/System/Process/Common.hs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
{-# LANGUAGE TemplateHaskell #-}
|
||||||
|
|
||||||
|
module GHCup.System.Process.Common where
|
||||||
|
|
||||||
|
|
||||||
|
import GHC.IO.Exception
|
||||||
|
import Optics hiding ((<|), (|>))
|
||||||
|
import Text.PrettyPrint.HughesPJClass hiding ( (<>) )
|
||||||
|
|
||||||
|
import qualified Data.ByteString.Lazy as BL
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
data ProcessError = NonZeroExit Int FilePath [String]
|
||||||
|
| PTerminated FilePath [String]
|
||||||
|
| PStopped FilePath [String]
|
||||||
|
| NoSuchPid FilePath [String]
|
||||||
|
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
|
||||||
|
{ _exitCode :: ExitCode
|
||||||
|
, _stdOut :: BL.ByteString
|
||||||
|
, _stdErr :: BL.ByteString
|
||||||
|
}
|
||||||
|
deriving (Eq, Show)
|
||||||
|
|
||||||
|
makeLenses ''CapturedProcess
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
{-# LANGUAGE FlexibleContexts #-}
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
|
|
||||||
{-|
|
{-|
|
||||||
Module : GHCup.Utils.File.Posix
|
Module : GHCup.System.Process.Posix
|
||||||
Description : File and unix APIs
|
Description : File and unix APIs
|
||||||
Copyright : (c) Julian Ospald, 2020
|
Copyright : (c) Julian Ospald, 2020
|
||||||
License : LGPL-3.0
|
License : LGPL-3.0
|
||||||
@@ -13,13 +13,13 @@ Portability : POSIX
|
|||||||
This module handles file and executable handling.
|
This module handles file and executable handling.
|
||||||
Some of these functions use sophisticated logging.
|
Some of these functions use sophisticated logging.
|
||||||
-}
|
-}
|
||||||
module GHCup.Utils.File.Posix where
|
module GHCup.System.Process.Posix where
|
||||||
|
|
||||||
import GHCup.Utils.File.Common
|
import GHCup.Prelude
|
||||||
import GHCup.Utils.Prelude
|
import GHCup.Logger
|
||||||
import GHCup.Utils.Logger
|
|
||||||
import GHCup.Types
|
import GHCup.Types
|
||||||
import GHCup.Types.Optics
|
import GHCup.Types.Optics
|
||||||
|
import GHCup.System.Process.Common
|
||||||
|
|
||||||
import Control.Concurrent
|
import Control.Concurrent
|
||||||
import Control.Concurrent.Async
|
import Control.Concurrent.Async
|
||||||
@@ -35,7 +35,7 @@ import Data.Sequence ( Seq, (|>) )
|
|||||||
import Data.List
|
import Data.List
|
||||||
import Data.Word8
|
import Data.Word8
|
||||||
import GHC.IO.Exception
|
import GHC.IO.Exception
|
||||||
import System.IO ( stderr )
|
import System.Console.Terminal.Common
|
||||||
import System.IO.Error
|
import System.IO.Error
|
||||||
import System.FilePath
|
import System.FilePath
|
||||||
import System.Directory
|
import System.Directory
|
||||||
@@ -51,7 +51,7 @@ import qualified Data.Sequence as Sq
|
|||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import qualified Data.Text.Encoding as E
|
import qualified Data.Text.Encoding as E
|
||||||
import qualified System.Posix.Process as SPP
|
import qualified System.Posix.Process as SPP
|
||||||
import qualified System.Console.Terminal.Size as TP
|
import qualified System.Console.Terminal.Posix as TP
|
||||||
import qualified Data.ByteString as BS
|
import qualified Data.ByteString as BS
|
||||||
import qualified Data.ByteString.Lazy as BL
|
import qualified Data.ByteString.Lazy as BL
|
||||||
import qualified "unix-bytestring" System.Posix.IO.ByteString
|
import qualified "unix-bytestring" System.Posix.IO.ByteString
|
||||||
@@ -73,7 +73,6 @@ executeOut path args chdir = liftIO $ captureOutStreams $ do
|
|||||||
|
|
||||||
execLogged :: ( MonadReader env m
|
execLogged :: ( MonadReader env m
|
||||||
, HasSettings env
|
, HasSettings env
|
||||||
, HasLog env
|
|
||||||
, HasDirs env
|
, HasDirs env
|
||||||
, MonadIO m
|
, MonadIO m
|
||||||
, MonadThrow m)
|
, MonadThrow m)
|
||||||
@@ -86,7 +85,6 @@ execLogged :: ( MonadReader env m
|
|||||||
execLogged exe args chdir lfile env = do
|
execLogged exe args chdir lfile env = do
|
||||||
Settings {..} <- getSettings
|
Settings {..} <- getSettings
|
||||||
Dirs {..} <- getDirs
|
Dirs {..} <- getDirs
|
||||||
logDebug $ T.pack $ "Running " <> exe <> " with arguments " <> show args
|
|
||||||
let logfile = logsDir </> lfile <> ".log"
|
let logfile = logsDir </> lfile <> ".log"
|
||||||
liftIO $ bracket (openFd logfile WriteOnly (Just newFilePerms) defaultFileFlags{ append = True })
|
liftIO $ bracket (openFd logfile WriteOnly (Just newFilePerms) defaultFileFlags{ append = True })
|
||||||
closeFd
|
closeFd
|
||||||
@@ -143,14 +141,14 @@ execLogged exe args chdir lfile env = do
|
|||||||
printToRegion :: Fd -> Fd -> Int -> MVar Bool -> Bool -> IO ()
|
printToRegion :: Fd -> Fd -> Int -> MVar Bool -> Bool -> IO ()
|
||||||
printToRegion fileFd fdIn size pState no_color = do
|
printToRegion fileFd fdIn size pState no_color = do
|
||||||
-- init region
|
-- init region
|
||||||
forM_ [1..size] $ \_ -> BS.hPut stderr "\n"
|
forM_ [1..size] $ \_ -> BS.putStr "\n"
|
||||||
|
|
||||||
void $ flip runStateT mempty
|
void $ flip runStateT mempty
|
||||||
$ do
|
$ do
|
||||||
handle
|
handle
|
||||||
(\(ex :: SomeException) -> do
|
(\(ex :: SomeException) -> do
|
||||||
ps <- liftIO $ takeMVar pState
|
ps <- liftIO $ takeMVar pState
|
||||||
when ps (liftIO $ BS.hPut stderr (pos1 <> moveLineUp size <> clearScreen))
|
when ps (liftIO $ BS.putStr (pos1 <> moveLineUp size <> clearScreen))
|
||||||
throw ex
|
throw ex
|
||||||
) $ readTilEOF lineAction fdIn
|
) $ readTilEOF lineAction fdIn
|
||||||
|
|
||||||
@@ -182,10 +180,10 @@ execLogged exe args chdir lfile env = do
|
|||||||
modify (swapRegs bs')
|
modify (swapRegs bs')
|
||||||
liftIO TP.size >>= \case
|
liftIO TP.size >>= \case
|
||||||
Nothing -> pure ()
|
Nothing -> pure ()
|
||||||
Just (TP.Window _ w) -> do
|
Just (Window _ w) -> do
|
||||||
regs <- get
|
regs <- get
|
||||||
liftIO $ forM_ (Sq.zip regs (Sq.fromList [0..(Sq.length regs - 1)])) $ \(bs, i) -> do
|
liftIO $ forM_ (Sq.zip regs (Sq.fromList [0..(Sq.length regs - 1)])) $ \(bs, i) -> do
|
||||||
BS.hPut stderr
|
BS.putStr
|
||||||
. overwriteNthLine (size - i)
|
. overwriteNthLine (size - i)
|
||||||
. trim w
|
. trim w
|
||||||
. blue
|
. blue
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
{-# LANGUAGE FlexibleContexts #-}
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
|
|
||||||
{-|
|
{-|
|
||||||
Module : GHCup.Utils.File.Windows
|
Module : GHCup.System.Process.Windows
|
||||||
Description : File and windows APIs
|
Description : File and windows APIs
|
||||||
Copyright : (c) Julian Ospald, 2020
|
Copyright : (c) Julian Ospald, 2020
|
||||||
License : LGPL-3.0
|
License : LGPL-3.0
|
||||||
@@ -13,14 +13,14 @@ Portability : Windows
|
|||||||
This module handles file and executable handling.
|
This module handles file and executable handling.
|
||||||
Some of these functions use sophisticated logging.
|
Some of these functions use sophisticated logging.
|
||||||
-}
|
-}
|
||||||
module GHCup.Utils.File.Windows where
|
module GHCup.System.Process.Windows where
|
||||||
|
|
||||||
import {-# SOURCE #-} GHCup.Utils ( getLinkTarget, pathIsLink )
|
import {-# SOURCE #-} GHCup.Utils ( getLinkTarget, pathIsLink )
|
||||||
import GHCup.Utils.Dirs
|
import GHCup.Directories
|
||||||
import GHCup.Utils.File.Common
|
|
||||||
import GHCup.Utils.Logger
|
|
||||||
import GHCup.Types
|
import GHCup.Types
|
||||||
import GHCup.Types.Optics
|
import GHCup.Types.Optics
|
||||||
|
import GHCup.System.Directory
|
||||||
|
import GHCup.System.Process.Common
|
||||||
|
|
||||||
import Control.Concurrent
|
import Control.Concurrent
|
||||||
import Control.DeepSeq
|
import Control.DeepSeq
|
||||||
@@ -41,7 +41,6 @@ import qualified Control.Exception as EX
|
|||||||
import qualified Data.ByteString as BS
|
import qualified Data.ByteString as BS
|
||||||
import qualified Data.ByteString.Lazy as BL
|
import qualified Data.ByteString.Lazy as BL
|
||||||
import qualified Data.Map.Strict as Map
|
import qualified Data.Map.Strict as Map
|
||||||
import qualified Data.Text as T
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -151,7 +150,6 @@ executeOut path args chdir = do
|
|||||||
|
|
||||||
execLogged :: ( MonadReader env m
|
execLogged :: ( MonadReader env m
|
||||||
, HasDirs env
|
, HasDirs env
|
||||||
, HasLog env
|
|
||||||
, HasSettings env
|
, HasSettings env
|
||||||
, MonadIO m
|
, MonadIO m
|
||||||
, MonadThrow m)
|
, MonadThrow m)
|
||||||
@@ -163,7 +161,6 @@ execLogged :: ( MonadReader env m
|
|||||||
-> m (Either ProcessError ())
|
-> m (Either ProcessError ())
|
||||||
execLogged exe args chdir lfile env = do
|
execLogged exe args chdir lfile env = do
|
||||||
Dirs {..} <- getDirs
|
Dirs {..} <- getDirs
|
||||||
logDebug $ T.pack $ "Running " <> exe <> " with arguments " <> show args
|
|
||||||
let stdoutLogfile = logsDir </> lfile <> ".stdout.log"
|
let stdoutLogfile = logsDir </> lfile <> ".stdout.log"
|
||||||
stderrLogfile = logsDir </> lfile <> ".stderr.log"
|
stderrLogfile = logsDir </> lfile <> ".stderr.log"
|
||||||
cp <- createProcessWithMingwPath ((proc exe args)
|
cp <- createProcessWithMingwPath ((proc exe args)
|
||||||
@@ -196,8 +193,7 @@ execLogged exe args chdir lfile env = do
|
|||||||
then pure ()
|
then pure ()
|
||||||
else do
|
else do
|
||||||
void $ BS.appendFile logFile some
|
void $ BS.appendFile logFile some
|
||||||
-- subprocess stdout also goes to stderr for logging
|
void $ BS.hPut stdout some
|
||||||
void $ BS.hPut stderr some
|
|
||||||
go
|
go
|
||||||
|
|
||||||
|
|
||||||
@@ -6,7 +6,6 @@
|
|||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
{-# LANGUAGE FlexibleContexts #-}
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
{-# LANGUAGE FlexibleInstances #-}
|
{-# LANGUAGE FlexibleInstances #-}
|
||||||
{-# LANGUAGE TemplateHaskell #-}
|
|
||||||
{-# LANGUAGE DuplicateRecordFields #-}
|
{-# LANGUAGE DuplicateRecordFields #-}
|
||||||
|
|
||||||
{-|
|
{-|
|
||||||
@@ -31,15 +30,12 @@ import Data.Map.Strict ( Map )
|
|||||||
import Data.List.NonEmpty ( NonEmpty (..) )
|
import Data.List.NonEmpty ( NonEmpty (..) )
|
||||||
import Data.Text ( Text )
|
import Data.Text ( Text )
|
||||||
import Data.Versions
|
import Data.Versions
|
||||||
import GHC.IO.Exception ( ExitCode )
|
import Text.PrettyPrint.HughesPJClass (Pretty, pPrint, text)
|
||||||
import Optics ( makeLenses )
|
|
||||||
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(..) )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
import qualified Data.ByteString.Lazy as BL
|
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import qualified GHC.Generics as GHC
|
import qualified GHC.Generics as GHC
|
||||||
|
|
||||||
@@ -286,9 +282,9 @@ instance Pretty TarDir where
|
|||||||
|
|
||||||
-- | Where to fetch GHCupDownloads from.
|
-- | Where to fetch GHCupDownloads from.
|
||||||
data URLSource = GHCupURL
|
data URLSource = GHCupURL
|
||||||
| OwnSource [Either GHCupInfo URI] -- ^ complete source list
|
| OwnSource URI
|
||||||
| OwnSpec GHCupInfo
|
| OwnSpec GHCupInfo
|
||||||
| AddSource [Either GHCupInfo URI] -- ^ merge with GHCupURL
|
| AddSource (Either GHCupInfo URI) -- ^ merge with GHCupURL
|
||||||
deriving (GHC.Generic, Show)
|
deriving (GHC.Generic, Show)
|
||||||
|
|
||||||
instance NFData URLSource
|
instance NFData URLSource
|
||||||
@@ -488,10 +484,6 @@ data SetGHC = SetGHCOnly -- ^ unversioned 'ghc'
|
|||||||
| SetGHC_XYZ -- ^ ghc-x.y.z
|
| SetGHC_XYZ -- ^ ghc-x.y.z
|
||||||
deriving (Eq, Show)
|
deriving (Eq, Show)
|
||||||
|
|
||||||
data SetHLS = SetHLSOnly -- ^ unversioned 'hls'
|
|
||||||
| SetHLS_XYZ -- ^ haskell-language-server-a.b.c~x.y.z, where a.b.c is GHC version and x.y.z is HLS version
|
|
||||||
deriving (Eq, Show)
|
|
||||||
|
|
||||||
|
|
||||||
data PlatformResult = PlatformResult
|
data PlatformResult = PlatformResult
|
||||||
{ _platform :: Platform
|
{ _platform :: Platform
|
||||||
@@ -604,27 +596,3 @@ data LoggerConfig = LoggerConfig
|
|||||||
|
|
||||||
instance NFData LoggerConfig where
|
instance NFData LoggerConfig where
|
||||||
rnf (LoggerConfig !lcPrintDebug !_ !_ !fancyColors) = rnf (lcPrintDebug, fancyColors)
|
rnf (LoggerConfig !lcPrintDebug !_ !_ !fancyColors) = rnf (lcPrintDebug, fancyColors)
|
||||||
|
|
||||||
data ProcessError = NonZeroExit Int FilePath [String]
|
|
||||||
| PTerminated FilePath [String]
|
|
||||||
| PStopped FilePath [String]
|
|
||||||
| NoSuchPid FilePath [String]
|
|
||||||
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
|
|
||||||
{ _exitCode :: ExitCode
|
|
||||||
, _stdOut :: BL.ByteString
|
|
||||||
, _stdErr :: BL.ByteString
|
|
||||||
}
|
|
||||||
deriving (Eq, Show)
|
|
||||||
|
|
||||||
makeLenses ''CapturedProcess
|
|
||||||
|
|||||||
@@ -22,8 +22,10 @@ Portability : portable
|
|||||||
module GHCup.Types.JSON where
|
module GHCup.Types.JSON where
|
||||||
|
|
||||||
import GHCup.Types
|
import GHCup.Types
|
||||||
import GHCup.Types.JSON.Utils
|
import GHCup.MegaParsec
|
||||||
import GHCup.Utils.MegaParsec
|
import GHCup.Prelude
|
||||||
|
import GHCup.Logger () -- TH is broken shite and needs GHCup.Logger for linking, although we don't depend on the file.
|
||||||
|
-- This is due to the boot file.
|
||||||
|
|
||||||
import Control.Applicative ( (<|>) )
|
import Control.Applicative ( (<|>) )
|
||||||
import Data.Aeson hiding (Key)
|
import Data.Aeson hiding (Key)
|
||||||
@@ -38,7 +40,6 @@ import Text.Casing
|
|||||||
|
|
||||||
import qualified Data.List.NonEmpty as NE
|
import qualified Data.List.NonEmpty as NE
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import qualified Data.Text.Encoding.Error as E
|
|
||||||
import qualified Text.Megaparsec as MP
|
import qualified Text.Megaparsec as MP
|
||||||
import qualified Text.Megaparsec.Char as MPC
|
import qualified Text.Megaparsec.Char as MPC
|
||||||
|
|
||||||
@@ -77,39 +78,7 @@ instance FromJSON Tag where
|
|||||||
x -> pure (UnknownTag x)
|
x -> pure (UnknownTag x)
|
||||||
|
|
||||||
instance ToJSON URI where
|
instance ToJSON URI where
|
||||||
toJSON = toJSON . E.decodeUtf8With E.lenientDecode . serializeURIRef'
|
toJSON = toJSON . decUTF8Safe . 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 ->
|
||||||
@@ -346,7 +315,7 @@ deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''Requir
|
|||||||
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''DownloadInfo
|
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''DownloadInfo
|
||||||
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''VersionInfo
|
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''VersionInfo
|
||||||
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''GHCupInfo
|
deriveJSON defaultOptions { fieldLabelModifier = removeLensFieldLabel } ''GHCupInfo
|
||||||
deriveToJSON defaultOptions { sumEncoding = ObjectWithSingleField } ''URLSource
|
deriveJSON 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 = \str' -> maybe str' T.unpack . T.stripPrefix (T.pack "u-") . T.pack . kebab $ str' } ''UserSettings
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
{-|
|
|
||||||
Module : GHCup.Types.JSON.Utils
|
|
||||||
Description : Utils for TH splices
|
|
||||||
Copyright : (c) Julian Ospald, 2020
|
|
||||||
License : LGPL-3.0
|
|
||||||
Maintainer : hasufell@hasufell.de
|
|
||||||
Stability : experimental
|
|
||||||
Portability : portable
|
|
||||||
-}
|
|
||||||
|
|
||||||
module GHCup.Types.JSON.Utils where
|
|
||||||
|
|
||||||
import qualified Data.Text as T
|
|
||||||
|
|
||||||
removeLensFieldLabel :: String -> String
|
|
||||||
removeLensFieldLabel str' =
|
|
||||||
maybe str' T.unpack . T.stripPrefix (T.pack "_") . T.pack $ str'
|
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
{-# LANGUAGE FlexibleContexts #-}
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
{-# LANGUAGE QuasiQuotes #-}
|
{-# LANGUAGE QuasiQuotes #-}
|
||||||
|
{-# LANGUAGE TemplateHaskell #-}
|
||||||
{-# LANGUAGE TypeApplications #-}
|
{-# LANGUAGE TypeApplications #-}
|
||||||
{-# LANGUAGE ViewPatterns #-}
|
{-# LANGUAGE ViewPatterns #-}
|
||||||
|
|
||||||
@@ -19,33 +20,37 @@ This module contains GHCup helpers specific to
|
|||||||
installation and introspection of files/versions etc.
|
installation and introspection of files/versions etc.
|
||||||
-}
|
-}
|
||||||
module GHCup.Utils
|
module GHCup.Utils
|
||||||
( module GHCup.Utils.Dirs
|
( module GHCup.Directories
|
||||||
, module GHCup.Utils
|
, module GHCup.Utils
|
||||||
#if defined(IS_WINDOWS)
|
#if defined(IS_WINDOWS)
|
||||||
, module GHCup.Utils.Windows
|
, module GHCup.System.Console.Windows
|
||||||
#else
|
#else
|
||||||
, module GHCup.Utils.Posix
|
, module GHCup.System.Console.Posix
|
||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
|
|
||||||
|
|
||||||
#if defined(IS_WINDOWS)
|
#if defined(IS_WINDOWS)
|
||||||
import GHCup.Utils.Windows
|
import GHCup.System.Console.Windows
|
||||||
#else
|
#else
|
||||||
import GHCup.Utils.Posix
|
import GHCup.System.Console.Posix
|
||||||
#endif
|
#endif
|
||||||
|
import {-# SOURCE #-} GHCup.GHC.Common
|
||||||
|
import {-# SOURCE #-} GHCup.GHC.Set
|
||||||
|
import GHCup.Data.Versions
|
||||||
import GHCup.Download
|
import GHCup.Download
|
||||||
import GHCup.Errors
|
import GHCup.Errors
|
||||||
import GHCup.Types
|
import GHCup.Types
|
||||||
import GHCup.Types.Optics
|
import GHCup.Types.Optics
|
||||||
import GHCup.Types.JSON ( )
|
import GHCup.Types.JSON ( )
|
||||||
import GHCup.Utils.Dirs
|
import GHCup.Directories
|
||||||
import GHCup.Utils.File
|
import GHCup.Logger
|
||||||
import GHCup.Utils.Logger
|
import GHCup.MegaParsec
|
||||||
import GHCup.Utils.MegaParsec
|
import GHCup.Prelude
|
||||||
import GHCup.Utils.Prelude
|
import GHCup.QQ.String
|
||||||
import GHCup.Utils.String.QQ
|
import GHCup.System.Directory
|
||||||
|
import GHCup.System.Process
|
||||||
|
|
||||||
import Codec.Archive hiding ( Directory )
|
import Codec.Archive hiding ( Directory )
|
||||||
import Control.Applicative
|
import Control.Applicative
|
||||||
@@ -66,7 +71,7 @@ import Data.List
|
|||||||
import Data.List.NonEmpty ( NonEmpty( (:|) ))
|
import Data.List.NonEmpty ( NonEmpty( (:|) ))
|
||||||
import Data.Maybe
|
import Data.Maybe
|
||||||
import Data.Text ( Text )
|
import Data.Text ( Text )
|
||||||
import Data.Versions hiding ( patch )
|
import Data.Versions
|
||||||
import GHC.IO.Exception
|
import GHC.IO.Exception
|
||||||
import Haskus.Utils.Variant.Excepts
|
import Haskus.Utils.Variant.Excepts
|
||||||
import Optics
|
import Optics
|
||||||
@@ -76,6 +81,7 @@ import System.FilePath
|
|||||||
import System.IO.Error
|
import System.IO.Error
|
||||||
import Text.Regex.Posix
|
import Text.Regex.Posix
|
||||||
import URI.ByteString
|
import URI.ByteString
|
||||||
|
import Text.PrettyPrint.HughesPJClass ( prettyShow )
|
||||||
|
|
||||||
import qualified Codec.Compression.BZip as BZip
|
import qualified Codec.Compression.BZip as BZip
|
||||||
import qualified Codec.Compression.GZip as GZip
|
import qualified Codec.Compression.GZip as GZip
|
||||||
@@ -96,14 +102,14 @@ import qualified Data.List.NonEmpty as NE
|
|||||||
-- >>> import System.Directory
|
-- >>> import System.Directory
|
||||||
-- >>> import URI.ByteString
|
-- >>> import URI.ByteString
|
||||||
-- >>> import qualified Data.Text as T
|
-- >>> import qualified Data.Text as T
|
||||||
-- >>> import GHCup.Utils.Prelude
|
-- >>> import GHCup.Prelude
|
||||||
-- >>> import GHCup.Download
|
-- >>> import GHCup.Download
|
||||||
-- >>> import GHCup.Version
|
-- >>> import GHCup.Version
|
||||||
-- >>> import GHCup.Errors
|
-- >>> import GHCup.Errors
|
||||||
-- >>> import GHCup.Types
|
-- >>> import GHCup.Types
|
||||||
-- >>> import GHCup.Types.Optics
|
-- >>> import GHCup.Types.Optics
|
||||||
-- >>> import Optics
|
-- >>> import Optics
|
||||||
-- >>> import GHCup.Utils.Version.QQ
|
-- >>> import GHCup.QQ.Version
|
||||||
-- >>> import qualified Data.Text.Encoding as E
|
-- >>> import qualified Data.Text.Encoding as E
|
||||||
-- >>> import Control.Monad.Reader
|
-- >>> import Control.Monad.Reader
|
||||||
-- >>> import Haskus.Utils.Variant.Excepts
|
-- >>> import Haskus.Utils.Variant.Excepts
|
||||||
@@ -119,218 +125,6 @@ import qualified Data.List.NonEmpty as NE
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
------------------------
|
|
||||||
--[ Symlink handling ]--
|
|
||||||
------------------------
|
|
||||||
|
|
||||||
|
|
||||||
-- | Create a relative symlink destination for the binary directory,
|
|
||||||
-- given a target toolpath.
|
|
||||||
binarySymLinkDestination :: ( MonadThrow m
|
|
||||||
, MonadIO m
|
|
||||||
)
|
|
||||||
=> FilePath -- ^ binary dir
|
|
||||||
-> FilePath -- ^ the full toolpath
|
|
||||||
-> m FilePath
|
|
||||||
binarySymLinkDestination binDir toolPath = do
|
|
||||||
toolPath' <- liftIO $ canonicalizePath toolPath
|
|
||||||
binDir' <- liftIO $ canonicalizePath binDir
|
|
||||||
pure (relativeSymlink binDir' toolPath')
|
|
||||||
|
|
||||||
|
|
||||||
-- | Removes the minor GHC symlinks, e.g. ghc-8.6.5.
|
|
||||||
rmMinorGHCSymlinks :: ( MonadReader env m
|
|
||||||
, HasDirs env
|
|
||||||
, MonadIO m
|
|
||||||
, HasLog env
|
|
||||||
, MonadThrow m
|
|
||||||
, MonadFail m
|
|
||||||
, MonadMask m
|
|
||||||
)
|
|
||||||
=> GHCTargetVersion
|
|
||||||
-> Excepts '[NotInstalled] m ()
|
|
||||||
rmMinorGHCSymlinks tv@GHCTargetVersion{..} = do
|
|
||||||
Dirs {..} <- lift getDirs
|
|
||||||
|
|
||||||
files <- liftE $ ghcToolFiles tv
|
|
||||||
forM_ files $ \f -> do
|
|
||||||
let f_xyz = f <> "-" <> T.unpack (prettyVer _tvVersion) <> exeExt
|
|
||||||
let fullF = binDir </> f_xyz
|
|
||||||
lift $ logDebug ("rm -f " <> T.pack fullF)
|
|
||||||
lift $ hideError doesNotExistErrorType $ rmLink fullF
|
|
||||||
|
|
||||||
|
|
||||||
-- | Removes the set ghc version for the given target, if any.
|
|
||||||
rmPlainGHC :: ( MonadReader env m
|
|
||||||
, HasDirs env
|
|
||||||
, HasLog env
|
|
||||||
, MonadThrow m
|
|
||||||
, MonadFail m
|
|
||||||
, MonadIO m
|
|
||||||
, MonadMask m
|
|
||||||
)
|
|
||||||
=> Maybe Text -- ^ target
|
|
||||||
-> Excepts '[NotInstalled] m ()
|
|
||||||
rmPlainGHC target = do
|
|
||||||
Dirs {..} <- lift getDirs
|
|
||||||
mtv <- lift $ ghcSet target
|
|
||||||
forM_ mtv $ \tv -> do
|
|
||||||
files <- liftE $ ghcToolFiles tv
|
|
||||||
forM_ files $ \f -> do
|
|
||||||
let fullF = binDir </> f <> exeExt
|
|
||||||
lift $ logDebug ("rm -f " <> T.pack fullF)
|
|
||||||
lift $ hideError doesNotExistErrorType $ rmLink fullF
|
|
||||||
-- old ghcup
|
|
||||||
let hdc_file = binDir </> "haddock-ghc" <> exeExt
|
|
||||||
lift $ logDebug ("rm -f " <> T.pack hdc_file)
|
|
||||||
lift $ hideError doesNotExistErrorType $ rmLink hdc_file
|
|
||||||
|
|
||||||
|
|
||||||
-- | Remove the major GHC symlink, e.g. ghc-8.6.
|
|
||||||
rmMajorGHCSymlinks :: ( MonadReader env m
|
|
||||||
, HasDirs env
|
|
||||||
, MonadIO m
|
|
||||||
, HasLog env
|
|
||||||
, MonadThrow m
|
|
||||||
, MonadFail m
|
|
||||||
, MonadMask m
|
|
||||||
)
|
|
||||||
=> GHCTargetVersion
|
|
||||||
-> Excepts '[NotInstalled] m ()
|
|
||||||
rmMajorGHCSymlinks tv@GHCTargetVersion{..} = do
|
|
||||||
Dirs {..} <- lift getDirs
|
|
||||||
(mj, mi) <- getMajorMinorV _tvVersion
|
|
||||||
let v' = intToText mj <> "." <> intToText mi
|
|
||||||
|
|
||||||
files <- liftE $ ghcToolFiles tv
|
|
||||||
forM_ files $ \f -> do
|
|
||||||
let f_xy = f <> "-" <> T.unpack v' <> exeExt
|
|
||||||
let fullF = binDir </> f_xy
|
|
||||||
lift $ logDebug ("rm -f " <> T.pack fullF)
|
|
||||||
lift $ hideError doesNotExistErrorType $ rmLink fullF
|
|
||||||
|
|
||||||
|
|
||||||
-- | Removes the minor HLS files, e.g. 'haskell-language-server-8.10.7~1.6.1.0'
|
|
||||||
-- and 'haskell-language-server-wrapper-1.6.1.0'.
|
|
||||||
rmMinorHLSSymlinks :: ( MonadReader env m
|
|
||||||
, HasDirs env
|
|
||||||
, MonadIO m
|
|
||||||
, HasLog env
|
|
||||||
, MonadThrow m
|
|
||||||
, MonadFail m
|
|
||||||
, MonadMask m
|
|
||||||
)
|
|
||||||
=> Version
|
|
||||||
-> Excepts '[NotInstalled] m ()
|
|
||||||
rmMinorHLSSymlinks ver = do
|
|
||||||
Dirs {..} <- lift getDirs
|
|
||||||
|
|
||||||
hlsBins <- hlsAllBinaries ver
|
|
||||||
forM_ hlsBins $ \f -> do
|
|
||||||
let fullF = binDir </> f
|
|
||||||
lift $ logDebug ("rm -f " <> T.pack fullF)
|
|
||||||
-- on unix, this may be either a file (legacy) or a symlink
|
|
||||||
-- on windows, this is always a file... hence 'rmFile'
|
|
||||||
-- works consistently across platforms
|
|
||||||
lift $ rmFile fullF
|
|
||||||
|
|
||||||
-- | Removes the set HLS version, if any.
|
|
||||||
rmPlainHLS :: ( MonadReader env m
|
|
||||||
, HasDirs env
|
|
||||||
, HasLog env
|
|
||||||
, MonadThrow m
|
|
||||||
, MonadFail m
|
|
||||||
, MonadIO m
|
|
||||||
, MonadMask m
|
|
||||||
)
|
|
||||||
=> Excepts '[NotInstalled] m ()
|
|
||||||
rmPlainHLS = do
|
|
||||||
Dirs {..} <- lift getDirs
|
|
||||||
|
|
||||||
-- delete 'haskell-language-server-8.10.7'
|
|
||||||
hlsBins <- fmap (filter (\f -> not ("haskell-language-server-wrapper" `isPrefixOf` f) && ('~' `notElem` f)))
|
|
||||||
$ liftIO $ handleIO (\_ -> pure []) $ findFiles
|
|
||||||
binDir
|
|
||||||
(makeRegexOpts compExtended execBlank ([s|^haskell-language-server-.*$|] :: ByteString))
|
|
||||||
forM_ hlsBins $ \f -> do
|
|
||||||
let fullF = binDir </> f
|
|
||||||
lift $ logDebug ("rm -f " <> T.pack fullF)
|
|
||||||
if isWindows
|
|
||||||
then lift $ rmLink fullF
|
|
||||||
else lift $ rmFile fullF
|
|
||||||
|
|
||||||
-- 'haskell-language-server-wrapper'
|
|
||||||
let hlswrapper = binDir </> "haskell-language-server-wrapper" <> exeExt
|
|
||||||
lift $ logDebug ("rm -f " <> T.pack hlswrapper)
|
|
||||||
if isWindows
|
|
||||||
then lift $ hideError doesNotExistErrorType $ rmLink hlswrapper
|
|
||||||
else lift $ hideError doesNotExistErrorType $ rmFile hlswrapper
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-----------------------------------
|
|
||||||
--[ Set/Installed introspection ]--
|
|
||||||
-----------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
-- | Whether the given GHC versin is installed.
|
|
||||||
ghcInstalled :: (MonadIO m, MonadReader env m, HasDirs env, MonadThrow m) => GHCTargetVersion -> m Bool
|
|
||||||
ghcInstalled ver = do
|
|
||||||
ghcdir <- ghcupGHCDir ver
|
|
||||||
liftIO $ doesDirectoryExist ghcdir
|
|
||||||
|
|
||||||
|
|
||||||
-- | Whether the given GHC version is installed from source.
|
|
||||||
ghcSrcInstalled :: (MonadIO m, MonadReader env m, HasDirs env, MonadThrow m) => GHCTargetVersion -> m Bool
|
|
||||||
ghcSrcInstalled ver = do
|
|
||||||
ghcdir <- ghcupGHCDir ver
|
|
||||||
liftIO $ doesFileExist (ghcdir </> ghcUpSrcBuiltFile)
|
|
||||||
|
|
||||||
|
|
||||||
-- | Whether the given GHC version is set as the current.
|
|
||||||
ghcSet :: (MonadReader env m, HasDirs env, MonadThrow m, MonadIO m)
|
|
||||||
=> Maybe Text -- ^ the target of the GHC version, if any
|
|
||||||
-- (e.g. armv7-unknown-linux-gnueabihf)
|
|
||||||
-> m (Maybe GHCTargetVersion)
|
|
||||||
ghcSet mtarget = do
|
|
||||||
Dirs {..} <- getDirs
|
|
||||||
let ghc = maybe "ghc" (\t -> T.unpack t <> "-ghc") mtarget
|
|
||||||
let ghcBin = binDir </> ghc <> exeExt
|
|
||||||
|
|
||||||
-- link destination is of the form ../ghc/<ver>/bin/ghc
|
|
||||||
-- for old ghcup, it is ../ghc/<ver>/bin/ghc-<ver>
|
|
||||||
liftIO $ handleIO' NoSuchThing (\_ -> pure Nothing) $ do
|
|
||||||
link <- liftIO $ getLinkTarget ghcBin
|
|
||||||
Just <$> ghcLinkVersion link
|
|
||||||
where
|
|
||||||
ghcLinkVersion :: MonadThrow m => FilePath -> m GHCTargetVersion
|
|
||||||
ghcLinkVersion (T.pack . dropSuffix exeExt -> t) = throwEither $ MP.parse parser "ghcLinkVersion" t
|
|
||||||
where
|
|
||||||
parser =
|
|
||||||
(do
|
|
||||||
_ <- parseUntil1 ghcSubPath
|
|
||||||
_ <- ghcSubPath
|
|
||||||
r <- parseUntil1 pathSep
|
|
||||||
rest <- MP.getInput
|
|
||||||
MP.setInput r
|
|
||||||
x <- ghcTargetVerP
|
|
||||||
MP.setInput rest
|
|
||||||
pure x
|
|
||||||
)
|
|
||||||
<* MP.some pathSep
|
|
||||||
<* MP.takeRest
|
|
||||||
<* MP.eof
|
|
||||||
ghcSubPath = MP.some pathSep <* MP.chunk "ghc" *> MP.some pathSep
|
|
||||||
|
|
||||||
-- | Get all installed GHCs by reading ~/.ghcup/ghc/<dir>.
|
|
||||||
-- If a dir cannot be parsed, returns left.
|
|
||||||
getInstalledGHCs :: (MonadReader env m, HasDirs env, MonadIO m) => m [Either FilePath GHCTargetVersion]
|
|
||||||
getInstalledGHCs = do
|
|
||||||
ghcdir <- ghcupGHCBaseDir
|
|
||||||
fs <- liftIO $ hideErrorDef [NoSuchThing] [] $ listDirectory ghcdir
|
|
||||||
forM fs $ \f -> case parseGHCupGHCDir f of
|
|
||||||
Right r -> pure $ Right r
|
|
||||||
Left _ -> pure $ Left f
|
|
||||||
|
|
||||||
|
|
||||||
-- | Get all installed cabals, by matching on @~\/.ghcup\/bin/cabal-*@.
|
-- | Get all installed cabals, by matching on @~\/.ghcup\/bin/cabal-*@.
|
||||||
@@ -398,10 +192,10 @@ cabalSet = do
|
|||||||
cabalParse = MP.chunk "cabal-" *> version'
|
cabalParse = MP.chunk "cabal-" *> version'
|
||||||
-- parses any path component ending with path separator,
|
-- parses any path component ending with path separator,
|
||||||
-- e.g. "foo/"
|
-- e.g. "foo/"
|
||||||
stripPathComponet = parseUntil1 pathSep *> MP.some pathSep
|
stripPathComponet = parseUntil1 pathSep *> pathSep
|
||||||
-- parses an absolute path up until the last path separator,
|
-- parses an absolute path up until the last path separator,
|
||||||
-- e.g. "/bar/baz/foo" -> "/bar/baz/", leaving "foo"
|
-- e.g. "/bar/baz/foo" -> "/bar/baz/", leaving "foo"
|
||||||
stripAbsolutePath = MP.some pathSep *> MP.many (MP.try stripPathComponet)
|
stripAbsolutePath = pathSep *> MP.many (MP.try stripPathComponet)
|
||||||
-- parses a relative path up until the last path separator,
|
-- parses a relative path up until the last path separator,
|
||||||
-- e.g. "bar/baz/foo" -> "bar/baz/", leaving "foo"
|
-- e.g. "bar/baz/foo" -> "bar/baz/", leaving "foo"
|
||||||
stripRelativePath = MP.many (MP.try stripPathComponet)
|
stripRelativePath = MP.many (MP.try stripPathComponet)
|
||||||
@@ -409,8 +203,7 @@ cabalSet = do
|
|||||||
|
|
||||||
|
|
||||||
-- | Get all installed hls, by matching on
|
-- | Get all installed hls, by matching on
|
||||||
-- @~\/.ghcup\/bin/haskell-language-server-wrapper-<\hlsver\>@,
|
-- @~\/.ghcup\/bin/haskell-language-server-wrapper-<\hlsver\>@.
|
||||||
-- as well as @~\/.ghcup\/hls\/<\hlsver\>@
|
|
||||||
getInstalledHLSs :: (MonadReader env m, HasDirs env, MonadIO m, MonadCatch m)
|
getInstalledHLSs :: (MonadReader env m, HasDirs env, MonadIO m, MonadCatch m)
|
||||||
=> m [Either FilePath Version]
|
=> m [Either FilePath Version]
|
||||||
getInstalledHLSs = do
|
getInstalledHLSs = do
|
||||||
@@ -421,7 +214,7 @@ getInstalledHLSs = do
|
|||||||
execBlank
|
execBlank
|
||||||
([s|^haskell-language-server-wrapper-.*$|] :: ByteString)
|
([s|^haskell-language-server-wrapper-.*$|] :: ByteString)
|
||||||
)
|
)
|
||||||
legacy <- forM bins $ \f ->
|
forM bins $ \f ->
|
||||||
case
|
case
|
||||||
version . T.pack <$> (stripSuffix exeExt =<< stripPrefix "haskell-language-server-wrapper-" f)
|
version . T.pack <$> (stripSuffix exeExt =<< stripPrefix "haskell-language-server-wrapper-" f)
|
||||||
of
|
of
|
||||||
@@ -429,14 +222,6 @@ getInstalledHLSs = do
|
|||||||
Just (Left _) -> pure $ Left f
|
Just (Left _) -> pure $ Left f
|
||||||
Nothing -> pure $ Left f
|
Nothing -> pure $ Left f
|
||||||
|
|
||||||
hlsdir <- ghcupHLSBaseDir
|
|
||||||
fs <- liftIO $ hideErrorDef [NoSuchThing] [] $ listDirectory hlsdir
|
|
||||||
new <- forM fs $ \f -> case parseGHCupHLSDir f of
|
|
||||||
Right r -> pure $ Right r
|
|
||||||
Left _ -> pure $ Left f
|
|
||||||
pure (nub (new <> legacy))
|
|
||||||
|
|
||||||
|
|
||||||
-- | Get all installed stacks, by matching on
|
-- | Get all installed stacks, by matching on
|
||||||
-- @~\/.ghcup\/bin/stack-<\stackver\>@.
|
-- @~\/.ghcup\/bin/stack-<\stackver\>@.
|
||||||
getInstalledStacks :: (MonadReader env m, HasDirs env, MonadIO m, MonadCatch m)
|
getInstalledStacks :: (MonadReader env m, HasDirs env, MonadIO m, MonadCatch m)
|
||||||
@@ -492,10 +277,10 @@ stackSet = do
|
|||||||
cabalParse = MP.chunk "stack-" *> version'
|
cabalParse = MP.chunk "stack-" *> version'
|
||||||
-- parses any path component ending with path separator,
|
-- parses any path component ending with path separator,
|
||||||
-- e.g. "foo/"
|
-- e.g. "foo/"
|
||||||
stripPathComponet = parseUntil1 pathSep *> MP.some pathSep
|
stripPathComponet = parseUntil1 pathSep *> pathSep
|
||||||
-- parses an absolute path up until the last path separator,
|
-- parses an absolute path up until the last path separator,
|
||||||
-- e.g. "/bar/baz/foo" -> "/bar/baz/", leaving "foo"
|
-- e.g. "/bar/baz/foo" -> "/bar/baz/", leaving "foo"
|
||||||
stripAbsolutePath = MP.some pathSep *> MP.many (MP.try stripPathComponet)
|
stripAbsolutePath = pathSep *> MP.many (MP.try stripPathComponet)
|
||||||
-- parses a relative path up until the last path separator,
|
-- parses a relative path up until the last path separator,
|
||||||
-- e.g. "bar/baz/foo" -> "bar/baz/", leaving "foo"
|
-- e.g. "bar/baz/foo" -> "bar/baz/", leaving "foo"
|
||||||
stripRelativePath = MP.many (MP.try stripPathComponet)
|
stripRelativePath = MP.many (MP.try stripPathComponet)
|
||||||
@@ -512,10 +297,6 @@ hlsInstalled ver = do
|
|||||||
vers <- fmap rights getInstalledHLSs
|
vers <- fmap rights getInstalledHLSs
|
||||||
pure $ elem ver vers
|
pure $ elem ver vers
|
||||||
|
|
||||||
isLegacyHLS :: (MonadIO m, MonadReader env m, HasDirs env, MonadCatch m) => Version -> m Bool
|
|
||||||
isLegacyHLS ver = do
|
|
||||||
bdir <- ghcupHLSDir ver
|
|
||||||
not <$> liftIO (doesDirectoryExist bdir)
|
|
||||||
|
|
||||||
|
|
||||||
-- Return the currently set hls version, if any.
|
-- Return the currently set hls version, if any.
|
||||||
@@ -543,10 +324,10 @@ hlsSet = do
|
|||||||
cabalParse = MP.chunk "haskell-language-server-wrapper-" *> version'
|
cabalParse = MP.chunk "haskell-language-server-wrapper-" *> version'
|
||||||
-- parses any path component ending with path separator,
|
-- parses any path component ending with path separator,
|
||||||
-- e.g. "foo/"
|
-- e.g. "foo/"
|
||||||
stripPathComponet = parseUntil1 pathSep *> MP.some pathSep
|
stripPathComponet = parseUntil1 pathSep *> pathSep
|
||||||
-- parses an absolute path up until the last path separator,
|
-- parses an absolute path up until the last path separator,
|
||||||
-- e.g. "/bar/baz/foo" -> "/bar/baz/", leaving "foo"
|
-- e.g. "/bar/baz/foo" -> "/bar/baz/", leaving "foo"
|
||||||
stripAbsolutePath = MP.some pathSep *> MP.many (MP.try stripPathComponet)
|
stripAbsolutePath = pathSep *> MP.many (MP.try stripPathComponet)
|
||||||
-- parses a relative path up until the last path separator,
|
-- parses a relative path up until the last path separator,
|
||||||
-- e.g. "bar/baz/foo" -> "bar/baz/", leaving "foo"
|
-- e.g. "bar/baz/foo" -> "bar/baz/", leaving "foo"
|
||||||
stripRelativePath = MP.many (MP.try stripPathComponet)
|
stripRelativePath = MP.many (MP.try stripPathComponet)
|
||||||
@@ -587,7 +368,7 @@ hlsGHCVersions' v' = do
|
|||||||
pure . sortBy (flip compare) . rights $ vers
|
pure . sortBy (flip compare) . rights $ vers
|
||||||
|
|
||||||
|
|
||||||
-- | Get all server binaries for an hls version from the ~/.ghcup/bin directory, if any.
|
-- | Get all server binaries for an hls version, if any.
|
||||||
hlsServerBinaries :: (MonadReader env m, HasDirs env, MonadIO m)
|
hlsServerBinaries :: (MonadReader env m, HasDirs env, MonadIO m)
|
||||||
=> Version
|
=> Version
|
||||||
-> Maybe Version -- ^ optional GHC version
|
-> Maybe Version -- ^ optional GHC version
|
||||||
@@ -608,44 +389,6 @@ hlsServerBinaries ver mghcVer = do
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
-- | Get all scripts for a hls version from the ~/.ghcup/hls/<ver>/bin directory, if any.
|
|
||||||
-- Returns the full path.
|
|
||||||
hlsInternalServerScripts :: (MonadReader env m, HasDirs env, MonadIO m, MonadThrow m)
|
|
||||||
=> Version
|
|
||||||
-> Maybe Version -- ^ optional GHC version
|
|
||||||
-> m [FilePath]
|
|
||||||
hlsInternalServerScripts ver mghcVer = do
|
|
||||||
dir <- ghcupHLSDir ver
|
|
||||||
let bdir = dir </> "bin"
|
|
||||||
fmap (bdir </>) . filter (\f -> maybe True (\gv -> ("-" <> T.unpack (prettyVer gv)) `isSuffixOf` f) mghcVer)
|
|
||||||
<$> liftIO (listDirectory bdir)
|
|
||||||
|
|
||||||
-- | Get all binaries for a hls version from the ~/.ghcup/hls/<ver>/lib/haskell-language-server-<ver>/bin directory, if any.
|
|
||||||
-- Returns the full path.
|
|
||||||
hlsInternalServerBinaries :: (MonadReader env m, HasDirs env, MonadIO m, MonadThrow m, MonadFail m)
|
|
||||||
=> Version
|
|
||||||
-> Maybe Version -- ^ optional GHC version
|
|
||||||
-> m [FilePath]
|
|
||||||
hlsInternalServerBinaries ver mghcVer = do
|
|
||||||
dir <- ghcupHLSDir ver
|
|
||||||
let regex = makeRegexOpts compExtended execBlank ([s|^haskell-language-server-.*$|] :: ByteString)
|
|
||||||
(Just bdir) <- fmap headMay $ liftIO $ expandFilePath [Left (dir </> "lib"), Right regex, Left "bin"]
|
|
||||||
fmap (bdir </>) . filter (\f -> maybe True (\gv -> ("-" <> T.unpack (prettyVer gv)) `isSuffixOf` f) mghcVer)
|
|
||||||
<$> liftIO (listDirectory bdir)
|
|
||||||
|
|
||||||
-- | Get all libraries for a hls version from the ~/.ghcup/hls/<ver>/lib/haskell-language-server-<ver>/lib/<ghc-ver>/
|
|
||||||
-- directory, if any.
|
|
||||||
-- Returns the full path.
|
|
||||||
hlsInternalServerLibs :: (MonadReader env m, HasDirs env, MonadIO m, MonadThrow m, MonadFail m)
|
|
||||||
=> Version
|
|
||||||
-> Version -- ^ GHC version
|
|
||||||
-> m [FilePath]
|
|
||||||
hlsInternalServerLibs ver ghcVer = do
|
|
||||||
dir <- ghcupHLSDir ver
|
|
||||||
let regex = makeRegexOpts compExtended execBlank ([s|^haskell-language-server-.*$|] :: ByteString)
|
|
||||||
(Just bdir) <- fmap headMay $ liftIO $ expandFilePath [Left (dir </> "lib"), Right regex, Left ("lib" </> T.unpack (prettyVer ghcVer))]
|
|
||||||
fmap (bdir </>) <$> liftIO (listDirectory bdir)
|
|
||||||
|
|
||||||
|
|
||||||
-- | Get the wrapper binary for an hls version, if any.
|
-- | Get the wrapper binary for an hls version, if any.
|
||||||
hlsWrapperBinary :: (MonadReader env m, HasDirs env, MonadThrow m, MonadIO m)
|
hlsWrapperBinary :: (MonadReader env m, HasDirs env, MonadThrow m, MonadIO m)
|
||||||
@@ -676,82 +419,25 @@ hlsAllBinaries ver = do
|
|||||||
pure (maybeToList wrapper ++ hls)
|
pure (maybeToList wrapper ++ hls)
|
||||||
|
|
||||||
|
|
||||||
|
-- | Get the active symlinks for hls.
|
||||||
|
hlsSymlinks :: (MonadReader env m, HasDirs env, MonadIO m, MonadCatch m) => m [FilePath]
|
||||||
|
hlsSymlinks = do
|
||||||
|
Dirs {..} <- getDirs
|
||||||
|
oldSyms <- liftIO $ handleIO (\_ -> pure []) $ findFiles
|
||||||
|
binDir
|
||||||
|
(makeRegexOpts compExtended
|
||||||
|
execBlank
|
||||||
|
([s|^haskell-language-server-.*$|] :: ByteString)
|
||||||
|
)
|
||||||
|
filterM
|
||||||
|
( liftIO
|
||||||
|
. pathIsLink
|
||||||
|
. (binDir </>)
|
||||||
|
)
|
||||||
|
oldSyms
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-----------------------------------------
|
|
||||||
--[ Major version introspection (X.Y) ]--
|
|
||||||
-----------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
-- | 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"
|
|
||||||
|
|
||||||
|
|
||||||
matchMajor :: Version -> Int -> Int -> Bool
|
|
||||||
matchMajor v' major' minor' = case getMajorMinorV v' of
|
|
||||||
Just (x, y) -> x == major' && y == minor'
|
|
||||||
Nothing -> False
|
|
||||||
|
|
||||||
-- | Match PVP prefix.
|
|
||||||
--
|
|
||||||
-- >>> matchPVPrefix [pver|8.8|] [pver|8.8.4|]
|
|
||||||
-- True
|
|
||||||
-- >>> matchPVPrefix [pver|8|] [pver|8.8.4|]
|
|
||||||
-- True
|
|
||||||
-- >>> matchPVPrefix [pver|8.10|] [pver|8.8.4|]
|
|
||||||
-- False
|
|
||||||
-- >>> matchPVPrefix [pver|8.10|] [pver|8.10.7|]
|
|
||||||
-- True
|
|
||||||
matchPVPrefix :: PVP -> PVP -> Bool
|
|
||||||
matchPVPrefix (toL -> prefix) (toL -> full) = and $ zipWith (==) prefix full
|
|
||||||
|
|
||||||
toL :: PVP -> [Int]
|
|
||||||
toL (PVP inner) = fmap fromIntegral $ NE.toList inner
|
|
||||||
|
|
||||||
|
|
||||||
-- | Get the latest installed full GHC version that satisfies the given (possibly partial)
|
|
||||||
-- PVP version.
|
|
||||||
getGHCForPVP :: (MonadReader env m, HasDirs env, MonadIO m, MonadThrow m)
|
|
||||||
=> PVP
|
|
||||||
-> Maybe Text -- ^ the target triple
|
|
||||||
-> m (Maybe GHCTargetVersion)
|
|
||||||
getGHCForPVP pvpIn mt = do
|
|
||||||
ghcs <- rights <$> getInstalledGHCs
|
|
||||||
-- we're permissive here... failed parse just means we have no match anyway
|
|
||||||
let ghcs' = catMaybes $ flip fmap ghcs $ \GHCTargetVersion{..} -> do
|
|
||||||
(pvp_, rest) <- versionToPVP _tvVersion
|
|
||||||
pure (pvp_, rest, _tvTarget)
|
|
||||||
|
|
||||||
getGHCForPVP' pvpIn ghcs' mt
|
|
||||||
|
|
||||||
-- | 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"}})
|
|
||||||
-- >>> fmap prettyShow $ getGHCForPVP' [pver|8.8|] installedVersions Nothing
|
|
||||||
-- "Just 8.8.4"
|
|
||||||
-- >>> fmap prettyShow $ getGHCForPVP' [pver|8.10.4|] installedVersions Nothing
|
|
||||||
-- "Just 8.10.4"
|
|
||||||
getGHCForPVP' :: MonadThrow m
|
|
||||||
=> PVP
|
|
||||||
-> [(PVP, Text, Maybe Text)] -- ^ installed GHCs
|
|
||||||
-> Maybe Text -- ^ the target triple
|
|
||||||
-> m (Maybe GHCTargetVersion)
|
|
||||||
getGHCForPVP' pvpIn ghcs' mt = do
|
|
||||||
let mResult = lastMay
|
|
||||||
. sortBy (\(x, _, _) (y, _, _) -> compare x y)
|
|
||||||
. filter
|
|
||||||
(\(pvp_, _, target) ->
|
|
||||||
target == mt && matchPVPrefix pvp_ pvpIn
|
|
||||||
)
|
|
||||||
$ ghcs'
|
|
||||||
forM mResult $ \(pvp_, rest, target) -> do
|
|
||||||
ver' <- pvpToVersion pvp_ rest
|
|
||||||
pure (GHCTargetVersion target ver')
|
|
||||||
|
|
||||||
|
|
||||||
-- | Get the latest available ghc for the given PVP version, which
|
-- | Get the latest available ghc for the given PVP version, which
|
||||||
@@ -806,7 +492,7 @@ unpackToDir dfp av = do
|
|||||||
(untar . GZip.decompress =<< rf av)
|
(untar . GZip.decompress =<< rf av)
|
||||||
| ".tar.xz" `isSuffixOf` fn -> do
|
| ".tar.xz" `isSuffixOf` fn -> do
|
||||||
filecontents <- liftE $ rf av
|
filecontents <- liftE $ rf av
|
||||||
let decompressed = Lzma.decompressWith (Lzma.defaultDecompressParams { Lzma.decompressAutoDecoder= True }) filecontents
|
let decompressed = Lzma.decompress filecontents
|
||||||
liftE $ untar decompressed
|
liftE $ untar decompressed
|
||||||
| ".tar.bz2" `isSuffixOf` fn ->
|
| ".tar.bz2" `isSuffixOf` fn ->
|
||||||
liftE (untar . BZip.decompress =<< rf av)
|
liftE (untar . BZip.decompress =<< rf av)
|
||||||
@@ -835,7 +521,7 @@ getArchiveFiles av = do
|
|||||||
(entries . GZip.decompress =<< rf av)
|
(entries . GZip.decompress =<< rf av)
|
||||||
| ".tar.xz" `isSuffixOf` fn -> do
|
| ".tar.xz" `isSuffixOf` fn -> do
|
||||||
filecontents <- liftE $ rf av
|
filecontents <- liftE $ rf av
|
||||||
let decompressed = Lzma.decompressWith (Lzma.defaultDecompressParams { Lzma.decompressAutoDecoder= True }) filecontents
|
let decompressed = Lzma.decompress filecontents
|
||||||
liftE $ entries decompressed
|
liftE $ entries decompressed
|
||||||
| ".tar.bz2" `isSuffixOf` fn ->
|
| ".tar.bz2" `isSuffixOf` fn ->
|
||||||
liftE (entries . BZip.decompress =<< rf av)
|
liftE (entries . BZip.decompress =<< rf av)
|
||||||
@@ -900,48 +586,8 @@ getLatestBaseVersion av pvpVer =
|
|||||||
--[ Other ]--
|
--[ Other ]--
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
-- | Usually @~\/.ghcup\/ghc\/\<ver\>\/bin\/@
|
|
||||||
ghcInternalBinDir :: (MonadReader env m, HasDirs env, MonadThrow m, MonadFail m, MonadIO m)
|
|
||||||
=> GHCTargetVersion
|
|
||||||
-> m FilePath
|
|
||||||
ghcInternalBinDir ver = do
|
|
||||||
ghcdir <- ghcupGHCDir ver
|
|
||||||
pure (ghcdir </> "bin")
|
|
||||||
|
|
||||||
|
|
||||||
-- | Get tool files from @~\/.ghcup\/ghc\/\<ver\>\/bin\/\*@
|
|
||||||
-- while ignoring @*-\<ver\>@ symlinks and accounting for cross triple prefix.
|
|
||||||
--
|
|
||||||
-- Returns unversioned relative files without extension, e.g.:
|
|
||||||
--
|
|
||||||
-- - @["hsc2hs","haddock","hpc","runhaskell","ghc","ghc-pkg","ghci","runghc","hp2ps"]@
|
|
||||||
ghcToolFiles :: (MonadReader env m, HasDirs env, MonadThrow m, MonadFail m, MonadIO m)
|
|
||||||
=> GHCTargetVersion
|
|
||||||
-> Excepts '[NotInstalled] m [FilePath]
|
|
||||||
ghcToolFiles ver = do
|
|
||||||
bindir <- ghcInternalBinDir ver
|
|
||||||
|
|
||||||
-- fail if ghc is not installed
|
|
||||||
whenM (fmap not $ ghcInstalled ver)
|
|
||||||
(throwE (NotInstalled GHC ver))
|
|
||||||
|
|
||||||
files <- liftIO (listDirectory bindir >>= filterM (doesFileExist . (bindir </>)))
|
|
||||||
pure (getUniqueTools . groupToolFiles . fmap (dropSuffix exeExt) $ files)
|
|
||||||
|
|
||||||
where
|
|
||||||
|
|
||||||
groupToolFiles :: [FilePath] -> [[(FilePath, String)]]
|
|
||||||
groupToolFiles = groupBy (\(a, _) (b, _) -> a == b) . fmap (splitOnPVP "-")
|
|
||||||
|
|
||||||
getUniqueTools :: [[(FilePath, String)]] -> [String]
|
|
||||||
getUniqueTools = filter (isNotAnyInfix blackListedTools) . nub . fmap fst . filter ((== "") . snd) . concat
|
|
||||||
|
|
||||||
blackListedTools :: [String]
|
|
||||||
blackListedTools = ["haddock-ghc"]
|
|
||||||
|
|
||||||
isNotAnyInfix :: [String] -> String -> Bool
|
|
||||||
isNotAnyInfix xs t = foldr (\a b -> not (a `isInfixOf` t) && b) True xs
|
|
||||||
|
|
||||||
|
|
||||||
-- | This file, when residing in @~\/.ghcup\/ghc\/\<ver\>\/@ signals that
|
-- | This file, when residing in @~\/.ghcup\/ghc\/\<ver\>\/@ signals that
|
||||||
-- this GHC was built from source. It contains the build config.
|
-- this GHC was built from source. It contains the build config.
|
||||||
@@ -954,7 +600,6 @@ make :: ( MonadThrow m
|
|||||||
, MonadIO m
|
, MonadIO m
|
||||||
, MonadReader env m
|
, MonadReader env m
|
||||||
, HasDirs env
|
, HasDirs env
|
||||||
, HasLog env
|
|
||||||
, HasSettings env
|
, HasSettings env
|
||||||
)
|
)
|
||||||
=> [String]
|
=> [String]
|
||||||
@@ -977,43 +622,28 @@ makeOut args workdir = do
|
|||||||
executeOut mymake args workdir
|
executeOut mymake args workdir
|
||||||
|
|
||||||
|
|
||||||
-- | Try to apply patches in order. The order is determined by
|
-- | Try to apply patches in order. Fails with 'PatchFailed'
|
||||||
-- a quilt series file (in the patch directory) if one exists,
|
-- on first failure.
|
||||||
-- else the patches are applied in lexicographical order.
|
|
||||||
-- Fails with 'PatchFailed' on first failure.
|
|
||||||
applyPatches :: (MonadReader env m, HasDirs env, HasLog env, MonadIO m)
|
applyPatches :: (MonadReader env m, HasDirs env, HasLog env, MonadIO m)
|
||||||
=> FilePath -- ^ dir containing patches
|
=> FilePath -- ^ dir containing patches
|
||||||
-> FilePath -- ^ dir to apply patches in
|
-> FilePath -- ^ dir to apply patches in
|
||||||
-> Excepts '[PatchFailed] m ()
|
-> Excepts '[PatchFailed] m ()
|
||||||
applyPatches pdir ddir = do
|
applyPatches pdir ddir = do
|
||||||
let lexicographical = (fmap . fmap) (pdir </>) $ sort <$> findFiles
|
patches <- (fmap . fmap) (pdir </>) $ liftIO $ findFiles
|
||||||
pdir
|
pdir
|
||||||
(makeRegexOpts compExtended
|
(makeRegexOpts compExtended
|
||||||
execBlank
|
execBlank
|
||||||
([s|.+\.(patch|diff)$|] :: ByteString)
|
([s|.+\.(patch|diff)$|] :: ByteString)
|
||||||
)
|
)
|
||||||
let quilt = map (pdir </>) . lines <$> readFile (pdir </> "series")
|
forM_ (sort patches) $ \patch' -> do
|
||||||
|
lift $ logInfo $ "Applying patch " <> T.pack patch'
|
||||||
patches <- liftIO $ quilt `catchIO` (\e ->
|
fmap (either (const Nothing) Just)
|
||||||
if isDoesNotExistError e || isPermissionError e then
|
(exec
|
||||||
lexicographical
|
"patch"
|
||||||
else throwIO e)
|
["-p1", "-i", patch']
|
||||||
forM_ patches $ \patch' -> applyPatch patch' ddir
|
(Just ddir)
|
||||||
|
Nothing)
|
||||||
|
!? PatchFailed
|
||||||
applyPatch :: (MonadReader env m, HasDirs env, HasLog env, MonadIO m)
|
|
||||||
=> FilePath -- ^ Patch
|
|
||||||
-> FilePath -- ^ dir to apply patches in
|
|
||||||
-> Excepts '[PatchFailed] m ()
|
|
||||||
applyPatch patch ddir = do
|
|
||||||
lift $ logInfo $ "Applying patch " <> T.pack patch
|
|
||||||
fmap (either (const Nothing) Just)
|
|
||||||
(exec
|
|
||||||
"patch"
|
|
||||||
["-p1", "-s", "-f", "-i", patch]
|
|
||||||
(Just ddir)
|
|
||||||
Nothing)
|
|
||||||
!? PatchFailed
|
|
||||||
|
|
||||||
|
|
||||||
-- | https://gitlab.haskell.org/ghc/ghc/-/issues/17353
|
-- | https://gitlab.haskell.org/ghc/ghc/-/issues/17353
|
||||||
@@ -1247,27 +877,41 @@ ensureDirectories (Dirs baseDir binDir cacheDir logsDir confDir trashDir) = do
|
|||||||
|
|
||||||
-- | For ghc without arch triple, this is:
|
-- | For ghc without arch triple, this is:
|
||||||
--
|
--
|
||||||
-- - ghc
|
-- - ghc-<ver> (e.g. ghc-8.10.4)
|
||||||
--
|
--
|
||||||
-- For ghc with arch triple:
|
-- For ghc with arch triple:
|
||||||
--
|
--
|
||||||
-- - <triple>-ghc (e.g. arm-linux-gnueabihf-ghc)
|
-- - <triple>-ghc-<ver> (e.g. arm-linux-gnueabihf-ghc-8.10.4)
|
||||||
ghcBinaryName :: GHCTargetVersion -> String
|
ghcBinaryName :: GHCTargetVersion -> String
|
||||||
ghcBinaryName (GHCTargetVersion (Just t) _) = T.unpack (t <> "-ghc" <> T.pack exeExt)
|
ghcBinaryName (GHCTargetVersion (Just t) v') = T.unpack (t <> "-ghc-" <> prettyVer v' <> T.pack exeExt)
|
||||||
ghcBinaryName (GHCTargetVersion Nothing _) = T.unpack ("ghc" <> T.pack exeExt)
|
ghcBinaryName (GHCTargetVersion Nothing v') = T.unpack ("ghc-" <> prettyVer v' <> T.pack exeExt)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- | Warn if the installed and set HLS is not compatible with the installed and
|
||||||
|
-- set GHC version.
|
||||||
|
warnAboutHlsCompatibility :: ( MonadReader env m
|
||||||
|
, HasDirs env
|
||||||
|
, HasLog env
|
||||||
|
, MonadThrow m
|
||||||
|
, MonadCatch m
|
||||||
|
, MonadIO m
|
||||||
|
)
|
||||||
|
=> m ()
|
||||||
|
warnAboutHlsCompatibility = do
|
||||||
|
supportedGHC <- hlsGHCVersions
|
||||||
|
currentGHC <- fmap _tvVersion <$> ghcSet Nothing
|
||||||
|
currentHLS <- hlsSet
|
||||||
|
|
||||||
|
case (currentGHC, currentHLS) of
|
||||||
|
(Just gv, Just hv) | gv `notElem` supportedGHC -> do
|
||||||
|
logWarn $
|
||||||
|
"GHC " <> T.pack (prettyShow gv) <> " is not compatible with " <>
|
||||||
|
"Haskell Language Server " <> T.pack (prettyShow hv) <> "." <> "\n" <>
|
||||||
|
"Haskell IDE support may not work until this is fixed." <> "\n" <>
|
||||||
|
"Install a different HLS version, or install and set one of the following GHCs:" <> "\n" <>
|
||||||
|
T.pack (prettyShow supportedGHC)
|
||||||
|
|
||||||
|
_ -> return ()
|
||||||
|
|
||||||
|
|
||||||
-- | Does basic checks for isolated installs
|
|
||||||
-- Isolated Directory:
|
|
||||||
-- 1. if it doesn't exist -> proceed
|
|
||||||
-- 2. if it exists and is empty -> proceed
|
|
||||||
-- 3. if it exists and is non-empty -> panic and leave the house
|
|
||||||
installDestSanityCheck :: ( MonadIO m
|
|
||||||
, MonadCatch m
|
|
||||||
) =>
|
|
||||||
FilePath ->
|
|
||||||
Excepts '[DirNotEmpty] m ()
|
|
||||||
installDestSanityCheck isoDir = do
|
|
||||||
hideErrorDef [doesNotExistErrorType] () $ do
|
|
||||||
contents <- liftIO $ getDirectoryContentsRecursive isoDir
|
|
||||||
unless (null contents) (throwE $ DirNotEmpty isoDir)
|
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
{-# LANGUAGE CPP #-}
|
|
||||||
|
|
||||||
module GHCup.Utils.File (
|
|
||||||
module GHCup.Utils.File.Common,
|
|
||||||
#if IS_WINDOWS
|
|
||||||
module GHCup.Utils.File.Windows
|
|
||||||
#else
|
|
||||||
module GHCup.Utils.File.Posix
|
|
||||||
#endif
|
|
||||||
) where
|
|
||||||
|
|
||||||
import GHCup.Utils.File.Common
|
|
||||||
#if IS_WINDOWS
|
|
||||||
import GHCup.Utils.File.Windows
|
|
||||||
#else
|
|
||||||
import GHCup.Utils.File.Posix
|
|
||||||
#endif
|
|
||||||
@@ -28,7 +28,7 @@ import qualified Data.Text as T
|
|||||||
-- Note that when updating this, CI requires that the file exsists AND the same file exists at
|
-- Note that when updating this, CI requires that the file exsists AND the same file exists at
|
||||||
-- 'https://www.haskell.org/ghcup/exp/ghcup-<ver>.yaml' with some newlines added.
|
-- 'https://www.haskell.org/ghcup/exp/ghcup-<ver>.yaml' with some newlines added.
|
||||||
ghcupURL :: URI
|
ghcupURL :: URI
|
||||||
ghcupURL = [uri|https://raw.githubusercontent.com/haskell/ghcup-metadata/master/ghcup-0.0.7.yaml|]
|
ghcupURL = [uri|https://raw.githubusercontent.com/haskell/ghcup-metadata/master/ghcup-0.0.6.yaml|]
|
||||||
|
|
||||||
-- | The current ghcup version.
|
-- | The current ghcup version.
|
||||||
ghcUpVer :: PVP
|
ghcUpVer :: PVP
|
||||||
|
|||||||
43
lib/System/Console/Terminal/Common.hs
Normal file
43
lib/System/Console/Terminal/Common.hs
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
{-# LANGUAGE CPP #-}
|
||||||
|
{-# LANGUAGE DeriveDataTypeable #-}
|
||||||
|
{-# LANGUAGE DeriveTraversable #-}
|
||||||
|
|
||||||
|
#if __GLASGOW_HASKELL__ >= 702
|
||||||
|
#define LANGUAGE_DeriveGeneric
|
||||||
|
{-# LANGUAGE DeriveGeneric #-}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
module System.Console.Terminal.Common
|
||||||
|
( Window(..)
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Data.Data (Typeable, Data)
|
||||||
|
|
||||||
|
#if __GLASGOW_HASKELL__ < 710
|
||||||
|
import Data.Foldable (Foldable)
|
||||||
|
import Data.Traversable (Traversable)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef LANGUAGE_DeriveGeneric
|
||||||
|
import GHC.Generics
|
||||||
|
( Generic
|
||||||
|
#if __GLASGOW_HASKELL__ >= 706
|
||||||
|
, Generic1
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
-- | Terminal window width and height
|
||||||
|
data Window a = Window
|
||||||
|
{ height :: !a
|
||||||
|
, width :: !a
|
||||||
|
} deriving
|
||||||
|
( Show, Eq, Read, Data, Typeable
|
||||||
|
, Foldable, Functor, Traversable
|
||||||
|
#ifdef LANGUAGE_DeriveGeneric
|
||||||
|
, Generic
|
||||||
|
#if __GLASGOW_HASKELL__ >= 706
|
||||||
|
, Generic1
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
)
|
||||||
65
lib/System/Console/Terminal/Posix.hsc
Normal file
65
lib/System/Console/Terminal/Posix.hsc
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
{-# LANGUAGE CApiFFI #-}
|
||||||
|
|
||||||
|
module System.Console.Terminal.Posix
|
||||||
|
( size, fdSize, hSize
|
||||||
|
) where
|
||||||
|
|
||||||
|
import System.Console.Terminal.Common
|
||||||
|
import Control.Exception (catch)
|
||||||
|
import Data.Typeable (cast)
|
||||||
|
import Foreign
|
||||||
|
import Foreign.C.Error
|
||||||
|
import Foreign.C.Types
|
||||||
|
import GHC.IO.FD (FD(FD, fdFD))
|
||||||
|
import GHC.IO.Handle.Internals (withHandle_)
|
||||||
|
import GHC.IO.Handle.Types (Handle, Handle__(Handle__, haDevice))
|
||||||
|
#if defined(__GLASGOW_HASKELL__) && (__GLASGOW_HASKELL__ < 706)
|
||||||
|
import Prelude hiding (catch)
|
||||||
|
#endif
|
||||||
|
import System.Posix.Types (Fd(Fd))
|
||||||
|
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
||||||
|
#let alignment t = "%lu", (unsigned long)offsetof(struct {char x__; t (y__); }, y__)
|
||||||
|
|
||||||
|
|
||||||
|
-- Interesting part of @struct winsize@
|
||||||
|
data CWin = CWin CUShort CUShort
|
||||||
|
|
||||||
|
instance Storable CWin where
|
||||||
|
sizeOf _ = (#size struct winsize)
|
||||||
|
alignment _ = (#alignment struct winsize)
|
||||||
|
peek ptr = do
|
||||||
|
row <- (#peek struct winsize, ws_row) ptr
|
||||||
|
col <- (#peek struct winsize, ws_col) ptr
|
||||||
|
return $ CWin row col
|
||||||
|
poke ptr (CWin row col) = do
|
||||||
|
(#poke struct winsize, ws_row) ptr row
|
||||||
|
(#poke struct winsize, ws_col) ptr col
|
||||||
|
|
||||||
|
|
||||||
|
fdSize :: Integral n => Fd -> IO (Maybe (Window n))
|
||||||
|
fdSize (Fd fd) = with (CWin 0 0) $ \ws -> do
|
||||||
|
_ <- throwErrnoIfMinus1 "ioctl" $
|
||||||
|
ioctl fd (#const TIOCGWINSZ) ws
|
||||||
|
CWin row col <- peek ws
|
||||||
|
return . Just $ Window (fromIntegral row) (fromIntegral col)
|
||||||
|
`catch`
|
||||||
|
handler
|
||||||
|
where
|
||||||
|
handler :: IOError -> IO (Maybe (Window h))
|
||||||
|
handler _ = return Nothing
|
||||||
|
|
||||||
|
foreign import capi "sys/ioctl.h ioctl"
|
||||||
|
ioctl :: CInt -> CULong -> Ptr CWin -> IO CInt
|
||||||
|
|
||||||
|
size :: Integral n => IO (Maybe (Window n))
|
||||||
|
size = fdSize (Fd (#const STDOUT_FILENO))
|
||||||
|
|
||||||
|
hSize :: Integral n => Handle -> IO (Maybe (Window n))
|
||||||
|
hSize h = withHandle_ "hSize" h $ \Handle__ { haDevice = dev } ->
|
||||||
|
case cast dev of
|
||||||
|
Nothing -> return Nothing
|
||||||
|
Just FD { fdFD = fd } -> fdSize (Fd fd)
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
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 documentation
|
||||||
site_author: GHCup Team
|
site_author: GHCup Team
|
||||||
site_favicon: haskell_logo.png
|
site_favicon: haskell_logo.png
|
||||||
|
|
||||||
@@ -13,8 +13,7 @@ theme:
|
|||||||
|
|
||||||
nav:
|
nav:
|
||||||
- Home: index.md
|
- Home: index.md
|
||||||
- "Getting started": install.md
|
- "Getting Started": install.md
|
||||||
- "First steps": steps.md
|
|
||||||
- "User Guide": guide.md
|
- "User Guide": guide.md
|
||||||
- "Developer Guide": dev.md
|
- "Developer Guide": dev.md
|
||||||
- About: about.md
|
- About: about.md
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
# * 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
|
||||||
# * 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,8 +25,8 @@
|
|||||||
|
|
||||||
plat="$(uname -s)"
|
plat="$(uname -s)"
|
||||||
arch=$(uname -m)
|
arch=$(uname -m)
|
||||||
ghver="0.1.17.7"
|
ghver="0.1.17.3"
|
||||||
: "${GHCUP_BASE_URL:=https://downloads.haskell.org/~ghcup}"
|
base_url="https://downloads.haskell.org/~ghcup"
|
||||||
|
|
||||||
export GHCUP_SKIP_UPDATE_CHECK=yes
|
export GHCUP_SKIP_UPDATE_CHECK=yes
|
||||||
|
|
||||||
@@ -40,6 +39,7 @@ case "${plat}" in
|
|||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
: "${GHCUP_INSTALL_BASE_PREFIX:=$HOME}"
|
: "${GHCUP_INSTALL_BASE_PREFIX:=$HOME}"
|
||||||
|
export GHCUP_USE_XDG_DIRS
|
||||||
|
|
||||||
if [ -n "${GHCUP_USE_XDG_DIRS}" ] ; then
|
if [ -n "${GHCUP_USE_XDG_DIRS}" ] ; then
|
||||||
GHCUP_DIR=${XDG_DATA_HOME:=$HOME/.local/share}/ghcup
|
GHCUP_DIR=${XDG_DATA_HOME:=$HOME/.local/share}/ghcup
|
||||||
@@ -158,7 +158,7 @@ _done() {
|
|||||||
green "and the \"Mingw package management docs\""
|
green "and the \"Mingw package management docs\""
|
||||||
green "desktop shortcuts."
|
green "desktop shortcuts."
|
||||||
green
|
green
|
||||||
green "If you are new to Haskell, check out https://www.haskell.org/ghcup/steps/"
|
green "If you are new to Haskell, check out https://www.haskell.org/ghcup/install/#first-steps"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
green
|
green
|
||||||
@@ -173,7 +173,7 @@ _done() {
|
|||||||
green "To install other GHC versions and tools, run:"
|
green "To install other GHC versions and tools, run:"
|
||||||
green " ghcup tui"
|
green " ghcup tui"
|
||||||
green
|
green
|
||||||
green "If you are new to Haskell, check out https://www.haskell.org/ghcup/steps/"
|
green "If you are new to Haskell, check out https://www.haskell.org/ghcup/install/#first-steps"
|
||||||
;;
|
;;
|
||||||
|
|
||||||
esac
|
esac
|
||||||
@@ -182,51 +182,6 @@ _done() {
|
|||||||
exit 0
|
exit 0
|
||||||
}
|
}
|
||||||
|
|
||||||
# @FUNCTION: posix_realpath
|
|
||||||
# @USAGE: <file>
|
|
||||||
# @DESCRIPTION:
|
|
||||||
# Portably gets the realpath and prints it to stdout.
|
|
||||||
# This was initially inspired by
|
|
||||||
# https://gist.github.com/tvlooy/cbfbdb111a4ebad8b93e
|
|
||||||
# and
|
|
||||||
# https://stackoverflow.com/a/246128
|
|
||||||
#
|
|
||||||
# If the file does not exist, just prints it appended to the current directory.
|
|
||||||
# @STDOUT: realpath of the given file
|
|
||||||
posix_realpath() {
|
|
||||||
[ -z "$1" ] && die "Internal error: no argument given to posix_realpath"
|
|
||||||
current_loop=0
|
|
||||||
max_loops=50
|
|
||||||
mysource=$1
|
|
||||||
# readlink and '[ -h $path ]' behave different wrt '/sbin/' and '/sbin', so we strip it
|
|
||||||
mysource=${mysource%/}
|
|
||||||
[ -z "${mysource}" ] && mysource=$1
|
|
||||||
|
|
||||||
while [ -h "${mysource}" ]; do
|
|
||||||
current_loop=$((current_loop+1))
|
|
||||||
mydir="$( cd -P "$( dirname "${mysource}" )" > /dev/null 2>&1 && pwd )"
|
|
||||||
mysource="$(readlink "${mysource}")"
|
|
||||||
[ "${mysource%"${mysource#?}"}"x != '/x' ] && mysource="${mydir%/}/${mysource}"
|
|
||||||
|
|
||||||
if [ ${current_loop} -gt ${max_loops} ] ; then
|
|
||||||
(>&2 echo "${1}: Too many levels of symbolic links")
|
|
||||||
echo "$1"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
mydir="$( cd -P "$( dirname "${mysource}" )" > /dev/null 2>&1 && pwd )"
|
|
||||||
|
|
||||||
# TODO: better distinguish between "does not exist" and "permission denied"
|
|
||||||
if [ -z "${mydir}" ] ; then
|
|
||||||
(>&2 echo "${1}: Permission denied")
|
|
||||||
echo "$(pwd)/$1"
|
|
||||||
else
|
|
||||||
echo "${mydir%/}/$(basename "${mysource}")"
|
|
||||||
fi
|
|
||||||
|
|
||||||
unset current_loop max_loops mysource mydir
|
|
||||||
}
|
|
||||||
|
|
||||||
download_ghcup() {
|
download_ghcup() {
|
||||||
|
|
||||||
case "${plat}" in
|
case "${plat}" in
|
||||||
@@ -236,26 +191,26 @@ download_ghcup() {
|
|||||||
# we could be in a 32bit docker container, in which
|
# we could be in a 32bit docker container, in which
|
||||||
# case uname doesn't give us what we want
|
# case uname doesn't give us what we want
|
||||||
if [ "$(getconf LONG_BIT)" = "32" ] ; then
|
if [ "$(getconf LONG_BIT)" = "32" ] ; then
|
||||||
_url=${GHCUP_BASE_URL}/${ghver}/i386-linux-ghcup-${ghver}
|
_url=${base_url}/${ghver}/i386-linux-ghcup-${ghver}
|
||||||
elif [ "$(getconf LONG_BIT)" = "64" ] ; then
|
elif [ "$(getconf LONG_BIT)" = "64" ] ; then
|
||||||
_url=${GHCUP_BASE_URL}/${ghver}/x86_64-linux-ghcup-${ghver}
|
_url=${base_url}/${ghver}/x86_64-linux-ghcup-${ghver}
|
||||||
else
|
else
|
||||||
die "Unknown long bit size: $(getconf LONG_BIT)"
|
die "Unknown long bit size: $(getconf LONG_BIT)"
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
i*86)
|
i*86)
|
||||||
_url=${GHCUP_BASE_URL}/${ghver}/i386-linux-ghcup-${ghver}
|
_url=${base_url}/${ghver}/i386-linux-ghcup-${ghver}
|
||||||
;;
|
;;
|
||||||
armv7*|*armv8l*)
|
armv7*|*armv8l*)
|
||||||
_url=${GHCUP_BASE_URL}/${ghver}/armv7-linux-ghcup-${ghver}
|
_url=${base_url}/${ghver}/armv7-linux-ghcup-${ghver}
|
||||||
;;
|
;;
|
||||||
aarch64|arm64)
|
aarch64|arm64)
|
||||||
# we could be in a 32bit docker container, in which
|
# we could be in a 32bit docker container, in which
|
||||||
# case uname doesn't give us what we want
|
# case uname doesn't give us what we want
|
||||||
if [ "$(getconf LONG_BIT)" = "32" ] ; then
|
if [ "$(getconf LONG_BIT)" = "32" ] ; then
|
||||||
_url=${GHCUP_BASE_URL}/${ghver}/armv7-linux-ghcup-${ghver}
|
_url=${base_url}/${ghver}/armv7-linux-ghcup-${ghver}
|
||||||
elif [ "$(getconf LONG_BIT)" = "64" ] ; then
|
elif [ "$(getconf LONG_BIT)" = "64" ] ; then
|
||||||
_url=${GHCUP_BASE_URL}/${ghver}/aarch64-linux-ghcup-${ghver}
|
_url=${base_url}/${ghver}/aarch64-linux-ghcup-${ghver}
|
||||||
else
|
else
|
||||||
die "Unknown long bit size: $(getconf LONG_BIT)"
|
die "Unknown long bit size: $(getconf LONG_BIT)"
|
||||||
fi
|
fi
|
||||||
@@ -282,15 +237,15 @@ 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=${base_url}/${ghver}/x86_64-portbld-freebsd${freebsd_ver}-ghcup-${ghver}
|
||||||
;;
|
;;
|
||||||
"Darwin"|"darwin")
|
"Darwin"|"darwin")
|
||||||
case "${arch}" in
|
case "${arch}" in
|
||||||
x86_64|amd64)
|
x86_64|amd64)
|
||||||
_url=${GHCUP_BASE_URL}/${ghver}/x86_64-apple-darwin-ghcup-${ghver}
|
_url=${base_url}/${ghver}/x86_64-apple-darwin-ghcup-${ghver}
|
||||||
;;
|
;;
|
||||||
aarch64|arm64|armv8l)
|
aarch64|arm64|armv8l)
|
||||||
_url=${GHCUP_BASE_URL}/${ghver}/aarch64-apple-darwin-ghcup-${ghver}
|
_url=${base_url}/${ghver}/aarch64-apple-darwin-ghcup-${ghver}
|
||||||
;;
|
;;
|
||||||
i*86)
|
i*86)
|
||||||
die "i386 currently not supported!"
|
die "i386 currently not supported!"
|
||||||
@@ -302,7 +257,7 @@ download_ghcup() {
|
|||||||
MSYS*|MINGW*)
|
MSYS*|MINGW*)
|
||||||
case "${arch}" in
|
case "${arch}" in
|
||||||
x86_64|amd64)
|
x86_64|amd64)
|
||||||
_url=${GHCUP_BASE_URL}/${ghver}/x86_64-mingw64-ghcup-${ghver}.exe
|
_url=${base_url}/${ghver}/x86_64-mingw64-ghcup-${ghver}.exe
|
||||||
;;
|
;;
|
||||||
*) die "Unknown architecture: ${arch}"
|
*) die "Unknown architecture: ${arch}"
|
||||||
;;
|
;;
|
||||||
@@ -326,20 +281,7 @@ download_ghcup() {
|
|||||||
|
|
||||||
# we may overwrite this in adjust_bashrc
|
# we may overwrite this in adjust_bashrc
|
||||||
cat <<-EOF > "${GHCUP_DIR}"/env || die "Failed to create env file"
|
cat <<-EOF > "${GHCUP_DIR}"/env || die "Failed to create env file"
|
||||||
case ":\$PATH:" in
|
export PATH="\$HOME/.cabal/bin:${GHCUP_BIN}:\$PATH"
|
||||||
*:"${GHCUP_BIN}":*)
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
export PATH="${GHCUP_BIN}:\$PATH"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
case ":\$PATH:" in
|
|
||||||
*:"\$HOME/.cabal/bin":*)
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
export PATH="\$HOME/.cabal/bin:\$PATH"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# shellcheck disable=SC1090
|
# shellcheck disable=SC1090
|
||||||
@@ -427,38 +369,12 @@ adjust_bashrc() {
|
|||||||
case $1 in
|
case $1 in
|
||||||
1)
|
1)
|
||||||
cat <<-EOF > "${GHCUP_DIR}"/env || die "Failed to create env file"
|
cat <<-EOF > "${GHCUP_DIR}"/env || die "Failed to create env file"
|
||||||
case ":\$PATH:" in
|
export PATH="\$HOME/.cabal/bin:${GHCUP_BIN}:\$PATH"
|
||||||
*:"${GHCUP_BIN}":*)
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
export PATH="${GHCUP_BIN}:\$PATH"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
case ":\$PATH:" in
|
|
||||||
*:"\$HOME/.cabal/bin":*)
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
export PATH="\$HOME/.cabal/bin:\$PATH"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
EOF
|
EOF
|
||||||
;;
|
;;
|
||||||
2)
|
2)
|
||||||
cat <<-EOF > "${GHCUP_DIR}"/env || die "Failed to create env file"
|
cat <<-EOF > "${GHCUP_DIR}"/env || die "Failed to create env file"
|
||||||
case ":\$PATH:" in
|
export PATH="\$PATH:\$HOME/.cabal/bin:${GHCUP_BIN}"
|
||||||
*:"\$HOME/.cabal/bin":*)
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
export PATH="\$PATH:\$HOME/.cabal/bin"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
case ":\$PATH:" in
|
|
||||||
*:"${GHCUP_BIN}":*)
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
export PATH="\$PATH:${GHCUP_BIN}"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
EOF
|
EOF
|
||||||
;;
|
;;
|
||||||
*) ;;
|
*) ;;
|
||||||
@@ -473,23 +389,23 @@ adjust_bashrc() {
|
|||||||
;;
|
;;
|
||||||
fish)
|
fish)
|
||||||
mkdir -p "${GHCUP_PROFILE_FILE%/*}"
|
mkdir -p "${GHCUP_PROFILE_FILE%/*}"
|
||||||
sed -i -e '/# ghcup-env$/ s/^#*/#/' "$(posix_realpath "${GHCUP_PROFILE_FILE}")"
|
sed -i -e '/# ghcup-env$/ s/^#*/#/' "${GHCUP_PROFILE_FILE}"
|
||||||
case $1 in
|
case $1 in
|
||||||
1)
|
1)
|
||||||
printf "\n%s" "set -q GHCUP_INSTALL_BASE_PREFIX[1]; or set GHCUP_INSTALL_BASE_PREFIX \$HOME ; set -gx PATH \$HOME/.cabal/bin $GHCUP_BIN \$PATH # ghcup-env" >> "${GHCUP_PROFILE_FILE}"
|
echo "set -q GHCUP_INSTALL_BASE_PREFIX[1]; or set GHCUP_INSTALL_BASE_PREFIX \$HOME ; set -gx PATH \$HOME/.cabal/bin $GHCUP_BIN \$PATH # ghcup-env" >> "${GHCUP_PROFILE_FILE}"
|
||||||
;;
|
;;
|
||||||
2)
|
2)
|
||||||
printf "\n%s" "set -q GHCUP_INSTALL_BASE_PREFIX[1]; or set GHCUP_INSTALL_BASE_PREFIX \$HOME ; set -gx PATH \$HOME/.cabal/bin \$PATH $GHCUP_BIN # ghcup-env" >> "${GHCUP_PROFILE_FILE}"
|
echo "set -q GHCUP_INSTALL_BASE_PREFIX[1]; or set GHCUP_INSTALL_BASE_PREFIX \$HOME ; set -gx PATH \$HOME/.cabal/bin \$PATH $GHCUP_BIN # ghcup-env" >> "${GHCUP_PROFILE_FILE}"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
bash)
|
bash)
|
||||||
sed -i -e '/# ghcup-env$/ s/^#*/#/' "$(posix_realpath "${GHCUP_PROFILE_FILE}")"
|
sed -i -e '/# ghcup-env$/ s/^#*/#/' "${GHCUP_PROFILE_FILE}"
|
||||||
printf "\n%s" "[ -f \"${GHCUP_DIR}/env\" ] && source \"${GHCUP_DIR}/env\" # ghcup-env" >> "${GHCUP_PROFILE_FILE}"
|
echo "[ -f \"${GHCUP_DIR}/env\" ] && source \"${GHCUP_DIR}/env\" # ghcup-env" >> "${GHCUP_PROFILE_FILE}"
|
||||||
case "${plat}" in
|
case "${plat}" in
|
||||||
"Darwin"|"darwin")
|
"Darwin"|"darwin")
|
||||||
if ! grep -q "ghcup-env" "${HOME}/.bash_profile" ; then
|
if ! grep -q "ghcup-env" "${HOME}/.bash_profile" ; then
|
||||||
printf "\n%s" "[[ -f ~/.bashrc ]] && source ~/.bashrc # ghcup-env" >> "${HOME}/.bash_profile"
|
echo "[[ -f ~/.bashrc ]] && source ~/.bashrc # ghcup-env" >> "${HOME}/.bash_profile"
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
MSYS*|MINGW*)
|
MSYS*|MINGW*)
|
||||||
@@ -503,8 +419,8 @@ adjust_bashrc() {
|
|||||||
;;
|
;;
|
||||||
|
|
||||||
zsh)
|
zsh)
|
||||||
sed -i -e '/# ghcup-env$/ s/^#*/#/' "$(posix_realpath "${GHCUP_PROFILE_FILE}")"
|
sed -i -e '/# ghcup-env$/ s/^#*/#/' "${GHCUP_PROFILE_FILE}"
|
||||||
printf "\n%s" "[ -f \"${GHCUP_DIR}/env\" ] && source \"${GHCUP_DIR}/env\" # ghcup-env" >> "${GHCUP_PROFILE_FILE}"
|
echo "[ -f \"${GHCUP_DIR}/env\" ] && source \"${GHCUP_DIR}/env\" # ghcup-env" >> "${GHCUP_PROFILE_FILE}"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
echo
|
echo
|
||||||
@@ -571,7 +487,7 @@ ask_cabal_config_init() {
|
|||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
else
|
else
|
||||||
return 0
|
return 1
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
@@ -589,8 +505,8 @@ do_cabal_config_init() {
|
|||||||
adjust_cabal_config
|
adjust_cabal_config
|
||||||
;;
|
;;
|
||||||
0)
|
0)
|
||||||
warn "Make sure that your global cabal.config references the correct mingw64 paths (extra-prog-path, extra-include-dirs and extra-lib-dirs)."
|
echo "Make sure that your global cabal.config references the correct mingw64 paths (extra-prog-path, extra-include-dirs and extra-lib-dirs)."
|
||||||
warn "And set the environment variable GHCUP_MSYS2 to the root path of your msys2 installation."
|
echo "And set the environment variable GHCUP_MSYS2 to the root path of your msys2 installation."
|
||||||
sleep 5
|
sleep 5
|
||||||
return ;;
|
return ;;
|
||||||
*) ;;
|
*) ;;
|
||||||
@@ -763,7 +679,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 new-update
|
||||||
else # don't install ghc and cabal
|
else # don't install ghc and cabal
|
||||||
case "${plat}" in
|
case "${plat}" in
|
||||||
MSYS*|MINGW*)
|
MSYS*|MINGW*)
|
||||||
|
|||||||
@@ -29,11 +29,11 @@ param (
|
|||||||
[switch]$InstallStack,
|
[switch]$InstallStack,
|
||||||
# Whether to install hls as well
|
# Whether to install hls as well
|
||||||
[switch]$InstallHLS,
|
[switch]$InstallHLS,
|
||||||
# Specify the install root (default: 'C:\')
|
|
||||||
[string]$InstallDir,
|
|
||||||
# Specify the bootstrap url (default: 'https://www.haskell.org/ghcup/sh/bootstrap-haskell')
|
# Specify the bootstrap url (default: 'https://www.haskell.org/ghcup/sh/bootstrap-haskell')
|
||||||
[string]$BootstrapUrl,
|
[string]$InstallDir,
|
||||||
# Instead of installing a new MSys2, use an existing installation
|
# Instead of installing a new MSys2, use an existing installation
|
||||||
|
[string]$BootstrapUrl,
|
||||||
|
# Specify the install root (default: 'C:\')
|
||||||
[string]$ExistingMsys2Dir,
|
[string]$ExistingMsys2Dir,
|
||||||
# Specify the cabal root directory (default: '$InstallDir\cabal')
|
# Specify the cabal root directory (default: '$InstallDir\cabal')
|
||||||
[string]$CabalDir
|
[string]$CabalDir
|
||||||
@@ -239,34 +239,13 @@ if ($Silent -and !($InstallDir)) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
while ($true) {
|
while ($true) {
|
||||||
Print-Msg -color Magenta -msg (@'
|
Print-Msg -color Magenta -msg ('Where to install to (this should be a short Path, preferably a Drive like ''C:\''){1}Press enter to accept the default [{0}]:' -f $defaultGhcupBasePrefix, "`n")
|
||||||
Welcome to Haskell!
|
|
||||||
|
|
||||||
This script will download and install the following programs:
|
|
||||||
* ghcup - The Haskell toolchain installer
|
|
||||||
* ghc - The Glasgow Haskell Compiler
|
|
||||||
* msys2 - A linux-style toolchain environment required for many operations
|
|
||||||
* cabal - The Cabal build tool for managing Haskell software
|
|
||||||
* stack - (optional) A cross-platform program for developing Haskell projects
|
|
||||||
* hls - (optional) A language server for developers to integrate with their editor/IDE
|
|
||||||
|
|
||||||
Please not that ANTIVIRUS may interfere with the installation. If you experience problems, consider
|
|
||||||
disabling it temporarily.
|
|
||||||
|
|
||||||
Where to install to (this should be a short Path, preferably a Drive like 'C:\')?
|
|
||||||
If you accept this path, binaries will be installed into '{0}ghcup\bin' and msys2 into '{0}ghcup\msys64'.
|
|
||||||
Press enter to accept the default [{0}]:
|
|
||||||
|
|
||||||
'@ -f $defaultGhcupBasePrefix)
|
|
||||||
|
|
||||||
|
|
||||||
$basePrefixPrompt = Read-Host
|
$basePrefixPrompt = Read-Host
|
||||||
$GhcupBasePrefix = ($defaultGhcupBasePrefix,$basePrefixPrompt)[[bool]$basePrefixPrompt]
|
$GhcupBasePrefix = ($defaultGhcupBasePrefix,$basePrefixPrompt)[[bool]$basePrefixPrompt]
|
||||||
if (!($GhcupBasePrefix.EndsWith('\'))) {
|
if (!($GhcupBasePrefix.EndsWith('\'))) {
|
||||||
$GhcupBasePrefix = ('{0}\' -f $GhcupBasePrefix)
|
$GhcupBasePrefix = ('{0}\' -f $GhcupBasePrefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
$GhcupBasePrefix = $GhcupBasePrefix.TrimEnd().TrimStart()
|
|
||||||
if (!($GhcupBasePrefix)) {
|
if (!($GhcupBasePrefix)) {
|
||||||
Print-Msg -color Red -msg "No directory specified!"
|
Print-Msg -color Red -msg "No directory specified!"
|
||||||
} elseif (!(Test-Path -LiteralPath ('{0}' -f $GhcupBasePrefix))) {
|
} elseif (!(Test-Path -LiteralPath ('{0}' -f $GhcupBasePrefix))) {
|
||||||
@@ -354,7 +333,6 @@ if ($CabalDir) {
|
|||||||
$CabalDirPrompt = Read-Host
|
$CabalDirPrompt = Read-Host
|
||||||
$CabDirEnv = ($defaultCabalDir,$CabalDirPrompt)[[bool]$CabalDirPrompt]
|
$CabDirEnv = ($defaultCabalDir,$CabalDirPrompt)[[bool]$CabalDirPrompt]
|
||||||
|
|
||||||
$CabDirEnv = $CabDirEnv.TrimEnd().TrimStart()
|
|
||||||
if (!($CabDirEnv)) {
|
if (!($CabDirEnv)) {
|
||||||
Print-Msg -color Red -msg "No directory specified!"
|
Print-Msg -color Red -msg "No directory specified!"
|
||||||
} elseif (!(Split-Path -IsAbsolute -Path "$CabDirEnv")) {
|
} elseif (!(Split-Path -IsAbsolute -Path "$CabDirEnv")) {
|
||||||
@@ -423,17 +401,16 @@ if (!(Test-Path -Path ('{0}' -f $MsysDir))) {
|
|||||||
# Download the archive
|
# Download the archive
|
||||||
Print-Msg -msg 'Downloading Msys2 archive...'
|
Print-Msg -msg 'Downloading Msys2 archive...'
|
||||||
$archive = 'msys2-x86_64-latest.sfx.exe'
|
$archive = 'msys2-x86_64-latest.sfx.exe'
|
||||||
$archivePath = ('{0}\{1}' -f ([IO.Path]::GetTempPath()), "$archive")
|
|
||||||
|
|
||||||
if (Get-Command -Name 'curl.exe' -ErrorAction SilentlyContinue) {
|
if (Get-Command -Name 'curl.exe' -ErrorAction SilentlyContinue) {
|
||||||
Exec "curl.exe" '-o' "$archivePath" ('https://repo.msys2.org/distrib/{0}' -f "$archive")
|
Exec "curl.exe" '-o' ('{0}\{1}' -f $env:TEMP, $archive) ('https://repo.msys2.org/distrib/{0}' -f $archive)
|
||||||
} else {
|
} else {
|
||||||
Get-FileWCSynchronous -url ('https://repo.msys2.org/distrib/{0}' -f $archive) -destinationFolder ([IO.Path]::GetTempPath()) -includeStats
|
Get-FileWCSynchronous -url ('https://repo.msys2.org/distrib/{0}' -f $archive) -destinationFolder "$env:TEMP" -includeStats
|
||||||
}
|
}
|
||||||
|
|
||||||
Print-Msg -msg 'Extracting Msys2 archive...'
|
Print-Msg -msg 'Extracting Msys2 archive...'
|
||||||
$null = & "$archivePath" '-y' ('-o{0}' -f $GhcupDir) # Extract
|
$null = & "$env:TEMP\$archive" '-y' ('-o{0}' -f $GhcupDir) # Extract
|
||||||
Remove-Item -Path "$archivePath"
|
Remove-Item -Path ('{0}/{1}' -f $env:TEMP, $archive)
|
||||||
|
|
||||||
Print-Msg -msg 'Processing MSYS2 bash for first time use...'
|
Print-Msg -msg 'Processing MSYS2 bash for first time use...'
|
||||||
Exec "$Bash" '-lc' 'exit'
|
Exec "$Bash" '-lc' 'exit'
|
||||||
@@ -467,7 +444,6 @@ if (!(Test-Path -Path ('{0}' -f $MsysDir))) {
|
|||||||
Print-Msg -color Magenta -msg 'Input existing MSys2 toolchain directory:'
|
Print-Msg -color Magenta -msg 'Input existing MSys2 toolchain directory:'
|
||||||
$MsysDir = Read-Host
|
$MsysDir = Read-Host
|
||||||
}
|
}
|
||||||
$MsysDir = $MsysDir.TrimEnd().TrimStart()
|
|
||||||
if (!($MsysDir)) {
|
if (!($MsysDir)) {
|
||||||
Print-Msg -color Red -msg "No directory specified!"
|
Print-Msg -color Red -msg "No directory specified!"
|
||||||
} elseif (!(Test-Path -LiteralPath ('{0}' -f $MsysDir))) {
|
} elseif (!(Test-Path -LiteralPath ('{0}' -f $MsysDir))) {
|
||||||
|
|||||||
@@ -1,49 +0,0 @@
|
|||||||
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
tag=v$1
|
|
||||||
ver=$1
|
|
||||||
|
|
||||||
dest=$2
|
|
||||||
gpg_user=$3
|
|
||||||
|
|
||||||
mkdir -p "${dest}"
|
|
||||||
|
|
||||||
cd "${dest}"
|
|
||||||
|
|
||||||
base_url="https://gitlab.haskell.org/api/v4/projects/618/jobs/artifacts/${tag}/raw"
|
|
||||||
|
|
||||||
curl -f -o "x86_64-apple-darwin-ghcup-${ver}" \
|
|
||||||
"${base_url}/out/x86_64-apple-darwin-ghcup-${ver}?job=release:darwin"
|
|
||||||
|
|
||||||
curl -f -o "aarch64-apple-darwin-ghcup-${ver}" \
|
|
||||||
"${base_url}/out/aarch64-apple-darwin-ghcup-${ver}?job=release:darwin:aarch64"
|
|
||||||
|
|
||||||
curl -f -o "x86_64-freebsd12-ghcup-${ver}" \
|
|
||||||
"${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
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
url=$1
|
|
||||||
ver=$2
|
|
||||||
|
|
||||||
die() {
|
|
||||||
(>&2 printf "%s\\n" "$1")
|
|
||||||
exit 2
|
|
||||||
}
|
|
||||||
|
|
||||||
[ -z $url ] && die "no url set"
|
|
||||||
[ -z $ver ] && die "no version set"
|
|
||||||
|
|
||||||
sftp $url <<EOF
|
|
||||||
cd ghcup
|
|
||||||
|
|
||||||
rm aarch64-apple-darwin-ghcup
|
|
||||||
rm aarch64-linux-ghcup
|
|
||||||
rm armv7-linux-ghcup
|
|
||||||
rm i386-linux-ghcup
|
|
||||||
rm x86_64-apple-darwin-ghcup
|
|
||||||
rm x86_64-linux-ghcup
|
|
||||||
rm x86_64-mingw64-ghcup.exe
|
|
||||||
rm x86_64-freebsd12-ghcup
|
|
||||||
rm x86_64-freebsd13-ghcup
|
|
||||||
|
|
||||||
symlink ${ver}/aarch64-apple-darwin-ghcup-${ver} aarch64-apple-darwin-ghcup
|
|
||||||
symlink ${ver}/aarch64-linux-ghcup-${ver} aarch64-linux-ghcup
|
|
||||||
symlink ${ver}/armv7-linux-ghcup-${ver} armv7-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-freebsd12-ghcup-${ver} x86_64-freebsd12-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-mingw64-ghcup-${ver}.exe x86_64-mingw64-ghcup.exe
|
|
||||||
EOF
|
|
||||||
|
|
||||||
curl -X PURGE https://downloads.haskell.org/~ghcup/
|
|
||||||
curl -X PURGE https://downloads.haskell.org/ghcup/
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
url=$1
|
|
||||||
ver=$2
|
|
||||||
artifacts_dir=$3
|
|
||||||
|
|
||||||
die() {
|
|
||||||
(>&2 printf "%s\\n" "$1")
|
|
||||||
exit 2
|
|
||||||
}
|
|
||||||
|
|
||||||
[ -z $url ] && die "no url set"
|
|
||||||
[ -z $ver ] && die "no version set"
|
|
||||||
[ -z "${artifacts_dir}" ] && die "artifacts_dir not set"
|
|
||||||
[ -e "${artifacts_dir}" ] || die "artifacts_dir \"${artifacts_dir}\" does not exist"
|
|
||||||
|
|
||||||
cd "${artifacts_dir}"
|
|
||||||
|
|
||||||
sftp $url <<EOF
|
|
||||||
cd ghcup
|
|
||||||
|
|
||||||
mkdir ${ver}
|
|
||||||
cd ${ver}
|
|
||||||
put SHA256SUMS
|
|
||||||
put SHA256SUMS.sig
|
|
||||||
put aarch64-apple-darwin-ghcup-${ver}
|
|
||||||
put aarch64-apple-darwin-ghcup-${ver}.sig
|
|
||||||
put aarch64-linux-ghcup-${ver}
|
|
||||||
put aarch64-linux-ghcup-${ver}.sig
|
|
||||||
put armv7-linux-ghcup-${ver}
|
|
||||||
put armv7-linux-ghcup-${ver}.sig
|
|
||||||
put i386-linux-ghcup-${ver}
|
|
||||||
put i386-linux-ghcup-${ver}.sig
|
|
||||||
put x86_64-apple-darwin-ghcup-${ver}
|
|
||||||
put x86_64-apple-darwin-ghcup-${ver}.sig
|
|
||||||
put x86_64-freebsd12-ghcup-${ver}
|
|
||||||
put x86_64-freebsd12-ghcup-${ver}.sig
|
|
||||||
put x86_64-freebsd13-ghcup-${ver}
|
|
||||||
put x86_64-freebsd13-ghcup-${ver}.sig
|
|
||||||
put x86_64-linux-ghcup-${ver}
|
|
||||||
put x86_64-linux-ghcup-${ver}.sig
|
|
||||||
put x86_64-mingw64-ghcup-${ver}.exe
|
|
||||||
put x86_64-mingw64-ghcup-${ver}.exe.sig
|
|
||||||
EOF
|
|
||||||
|
|
||||||
curl -X PURGE https://downloads.haskell.org/~ghcup/${ver}/
|
|
||||||
curl -X PURGE https://downloads.haskell.org/ghcup/${ver}/
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
resolver: lts-18.27
|
resolver: lts-18.12
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
- .
|
- .
|
||||||
@@ -16,7 +16,7 @@ extra-deps:
|
|||||||
- composition-prelude-3.0.0.2@sha256:1ffed216bd28d810fce0b5be83a661e2a892696d73b3f8de5c0f5edb9b5f0090,1216
|
- composition-prelude-3.0.0.2@sha256:1ffed216bd28d810fce0b5be83a661e2a892696d73b3f8de5c0f5edb9b5f0090,1216
|
||||||
- haskus-utils-data-1.4@sha256:bfa94363b94b14779edd6834fbd59dbb847c3d7b8f48e3844f456ffdc077da4a,1466
|
- haskus-utils-data-1.4@sha256:bfa94363b94b14779edd6834fbd59dbb847c3d7b8f48e3844f456ffdc077da4a,1466
|
||||||
- haskus-utils-types-1.5.1@sha256:991c472f4e751e2f0d7aab6ad4220ef151d6160876dcf0511bbf876bbd432020,1298
|
- haskus-utils-types-1.5.1@sha256:991c472f4e751e2f0d7aab6ad4220ef151d6160876dcf0511bbf876bbd432020,1298
|
||||||
- haskus-utils-variant-3.2.1@sha256:791f4cf1e786eb578f4d37aef60986641f84c36e130164321f7d01542584066a,2200
|
- haskus-utils-variant-3.1@sha256:e602dd23e068c98d03c1027af20503addef8df6368577622453f44ccabea2a5b,2159
|
||||||
- heaps-0.3.6.1@sha256:7928b759ca5180d35722c45948c0bde264229f3c99c1888188a3d9285f13d3d2,1340
|
- heaps-0.3.6.1@sha256:7928b759ca5180d35722c45948c0bde264229f3c99c1888188a3d9285f13d3d2,1340
|
||||||
- hpath-filepath-0.10.4@sha256:e9e44fb5fdbade7f30b5b5451257dbee15b6ef1aae4060034d73008bb3b5d878,1269
|
- hpath-filepath-0.10.4@sha256:e9e44fb5fdbade7f30b5b5451257dbee15b6ef1aae4060034d73008bb3b5d878,1269
|
||||||
- hpath-posix-0.13.3@sha256:abe472cf16bccd3a8b8814865ed3551a728fde0f3a2baea2acc03023bec6c565,1615
|
- hpath-posix-0.13.3@sha256:abe472cf16bccd3a8b8814865ed3551a728fde0f3a2baea2acc03023bec6c565,1615
|
||||||
|
|||||||
Reference in New Issue
Block a user