Merge remote-tracking branch 'remotes/origin/PR/meta-file-format'
This commit is contained in:
commit
a08d5970d3
11
.available-versions
Normal file
11
.available-versions
Normal file
@ -0,0 +1,11 @@
|
||||
# fmt-version=1
|
||||
# tab separated columns
|
||||
# tool | version | tag |
|
||||
ghc 8.0.2
|
||||
ghc 8.2.2
|
||||
ghc 8.4.3
|
||||
ghc 8.4.4 recommended
|
||||
ghc 8.6.1 latest,bad
|
||||
cabal-install 2.2.0.0
|
||||
cabal-install 2.4.0.0 latest,recommended
|
||||
|
35
.download-urls
Normal file
35
.download-urls
Normal file
@ -0,0 +1,35 @@
|
||||
# fmt-version=1
|
||||
# tool | version | arch | supported-distros for given url | url |
|
||||
|
||||
ghc 8.0.2 x86_64 debian=7 https://downloads.haskell.org/~ghc/8.0.2/ghc-8.0.2-x86_64-deb7-linux.tar.xz
|
||||
ghc 8.0.2 i386 debian=7 https://downloads.haskell.org/~ghc/8.0.2/ghc-8.0.2-i386-deb7-linux.tar.xz
|
||||
ghc 8.0.2 x86_64 debian=8,debian,ubuntu,unknown https://downloads.haskell.org/~ghc/8.0.2/ghc-8.0.2-x86_64-deb8-linux.tar.xz
|
||||
ghc 8.0.2 i386 debian=8,debian,ubuntu,unknown https://downloads.haskell.org/~ghc/8.0.2/ghc-8.0.2-i386-deb8-linux.tar.xz
|
||||
|
||||
ghc 8.2.2 x86_64 debian=7 https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-x86_64-deb7-linux.tar.xz
|
||||
ghc 8.2.2 i386 debian=7 https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-i386-deb7-linux.tar.xz
|
||||
ghc 8.2.2 x86_64 debian=8,debian,ubuntu https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-x86_64-deb8-linux.tar.xz
|
||||
ghc 8.2.2 i386 debian=8,debian,ubuntu,unknown https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-i386-deb8-linux.tar.xz
|
||||
ghc 8.2.2 x86_64 unknown https://downloads.haskell.org/~ghc/8.2.2/ghc-8.2.2-x86_64-unknown-linux.tar.xz
|
||||
|
||||
ghc 8.4.3 i386 debian=8,debian,ubuntu,unknown https://downloads.haskell.org/~ghc/8.4.3/ghc-8.4.3-i386-deb8-linux.tar.xz
|
||||
ghc 8.4.3 x86_64 debian=8 https://downloads.haskell.org/~ghc/8.4.3/ghc-8.4.3-x86_64-deb8-linux.tar.xz
|
||||
ghc 8.4.3 x86_64 debian=9,debian,ubuntu https://downloads.haskell.org/~ghc/8.4.3/ghc-8.4.3-x86_64-deb9-linux.tar.xz
|
||||
ghc 8.4.3 x86_64 fedora=27,fedora,unknown https://downloads.haskell.org/~ghc/8.4.3/ghc-8.4.3-x86_64-fedora27-linux.tar.xz
|
||||
|
||||
ghc 8.4.4 i386 debian=8,debian,ubuntu,unknown https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-i386-deb8-linux.tar.xz
|
||||
ghc 8.4.4 x86_64 debian=8 https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-x86_64-deb8-linux.tar.xz
|
||||
ghc 8.4.4 x86_64 debian=9,debian,ubuntu https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-x86_64-deb9-linux.tar.xz
|
||||
ghc 8.4.4 x86_64 centos=7,centos https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-x86_64-centos70-linux.tar.xz
|
||||
ghc 8.4.4 x86_64 fedora=27,fedora,unknown https://downloads.haskell.org/~ghc/8.4.4/ghc-8.4.4-x86_64-fedora27-linux.tar.xz
|
||||
|
||||
ghc 8.6.1 i386 debian=8,debian,ubuntu,unknown https://downloads.haskell.org/~ghc/8.6.1/ghc-8.6.1-i386-deb8-linux.tar.xz
|
||||
ghc 8.6.1 x86_64 debian=8 https://downloads.haskell.org/~ghc/8.6.1/ghc-8.6.1-x86_64-deb8-linux.tar.xz
|
||||
ghc 8.6.1 x86_64 debian=9,debian,ubuntu https://downloads.haskell.org/~ghc/8.6.1/ghc-8.6.1-x86_64-deb9-linux.tar.xz
|
||||
ghc 8.6.1 x86_64 fedora=27,fedora,unknown https://downloads.haskell.org/~ghc/8.6.1/ghc-8.6.1-x86_64-fedora27-linux.tar.xz
|
||||
|
||||
cabal-install 2.2.0.0 i386 unknown https://downloads.haskell.org/~cabal/cabal-install-2.2.0.0/cabal-install-2.2.0.0-i386-unknown-linux.tar.gz
|
||||
cabal-install 2.2.0.0 x86_64 unknown https://downloads.haskell.org/~cabal/cabal-install-2.2.0.0/cabal-install-2.2.0.0-x86_64-unknown-linux.tar.gz
|
||||
|
||||
cabal-install 2.4.0.0 x86_64 unknown https://downloads.haskell.org/~cabal/cabal-install-2.4.0.0/cabal-install-2.4.0.0-x86_64-unknown-linux.tar.gz
|
||||
|
15
.travis.sh
15
.travis.sh
@ -26,6 +26,9 @@ edo ./ghcup -v rm -f 8.6.1
|
||||
# set GHC
|
||||
edo ./ghcup -v set 8.2.2
|
||||
|
||||
# install default GHC
|
||||
edo ./ghcup -v install
|
||||
|
||||
export PATH="$HOME/.cabal/bin:$HOME/.ghcup/bin:$HOME/.local/bin:$PATH"
|
||||
edo mkdir -p "$HOME"/.local/bin
|
||||
|
||||
@ -48,11 +51,15 @@ edo mv shellcheck-latest/shellcheck "$HOME"/.local/bin/shellcheck
|
||||
# check our script for errors
|
||||
edo shellcheck ghcup
|
||||
|
||||
# self update
|
||||
edo ghcup self-update
|
||||
edo ghcup -v show
|
||||
|
||||
edo ghcup show
|
||||
edo ghcup -v debug-info
|
||||
|
||||
edo ghcup debug-info
|
||||
edo ghcup -v list
|
||||
edo ghcup -v list -t ghc
|
||||
edo ghcup -v list -t cabal-install
|
||||
|
||||
edo ghc --version
|
||||
|
||||
# self update destructively
|
||||
edo ghcup -v self-update
|
||||
|
25
CONTRIBUTING.md
Normal file
25
CONTRIBUTING.md
Normal file
@ -0,0 +1,25 @@
|
||||
# Contributing
|
||||
|
||||
* PR or email
|
||||
* this script is POSIX shell
|
||||
* use [shellcheck](https://github.com/koalaman/shellcheck) and `checkbashisms.pl` from [debian devscripts](http://http.debian.net/debian/pool/main/d/devscripts/devscripts_2.18.4.tar.xz)
|
||||
* whitespaces, no tabs
|
||||
|
||||
## Adding a new distro, updating GHC versions, ...
|
||||
|
||||
This script makes use of two files:
|
||||
|
||||
1. [.download-urls](https://raw.githubusercontent.com/haskell/ghcup/master/.download-urls),
|
||||
which is meta information on what binary tarball to download for the given version, architecture and distribution.
|
||||
If you know your distribution XY works with a tarball, add a `<distroname>=<distrover>` key to that line. `<distroname>`
|
||||
will be the fallback and after that `unknown`. Lines are unique per tarball url.
|
||||
2. [.available-versions](https://raw.githubusercontent.com/haskell/ghcup/master/.available-versions),
|
||||
which just lists available upstream versions and tags.
|
||||
|
||||
## TODO
|
||||
|
||||
- [ ] FreeBSD support ([#4](https://github.com/haskell/ghcup/issues/4))
|
||||
- [x] Make fetching tarballs more robust ([#5](https://github.com/haskell/ghcup/issues/5))
|
||||
- [x] More code documentation
|
||||
- [x] Allow to compile from source ([#2](https://github.com/haskell/ghcup/issues/2))
|
||||
- [x] Allow to install cabal-install as well ([#3](https://github.com/haskell/ghcup/issues/3))
|
32
README.md
32
README.md
@ -37,6 +37,21 @@ export PATH="$HOME/.cabal/bin:$HOME/.ghcup/bin:$PATH"
|
||||
|
||||
See `ghcup --help`.
|
||||
|
||||
Common use cases are:
|
||||
|
||||
```sh
|
||||
# install the last known "best" GHC version
|
||||
ghcup install
|
||||
# install a specific GHC version
|
||||
ghcup install 8.2.2
|
||||
# set the currently "active" GHC version
|
||||
ghcup set 8.4.4
|
||||
# install cabal-install
|
||||
ghcup install-cabal
|
||||
# update cabal-install
|
||||
cabal new-install cabal-install
|
||||
```
|
||||
|
||||
Generally this is meant to be used with [`cabal-install`](https://hackage.haskell.org/package/cabal-install), which
|
||||
handles your haskell packages and can demand that [a specific version](https://cabal.readthedocs.io/en/latest/nix-local-build.html#cfg-flag---with-compiler) of `ghc` is available, which `ghcup` can do.
|
||||
|
||||
@ -52,13 +67,6 @@ Alternatively, you can also tell it to compile from source (note that this might
|
||||
|
||||
In addition this script can also install `cabal-install`.
|
||||
|
||||
## Contributing
|
||||
|
||||
* PR or email
|
||||
* this script is POSIX shell
|
||||
* use [shellcheck](https://github.com/koalaman/shellcheck) and `checkbashisms.pl` from [debian devscripts](http://http.debian.net/debian/pool/main/d/devscripts/devscripts_2.18.4.tar.xz)
|
||||
* whitespaces, no tabs
|
||||
|
||||
## Known problems
|
||||
|
||||
### Limited distributions supported
|
||||
@ -75,16 +83,6 @@ ncurses and has no compatibility symlinks in place.
|
||||
Ask your distributor on how to solve this or
|
||||
try to compile from source via `ghcup compile <version>`.
|
||||
|
||||
### Unreliable download location
|
||||
|
||||
There is no single reliable URL where to download future
|
||||
GHC binary releases from, since the tarball names contain
|
||||
the distro name and version they were built on. As such,
|
||||
we cannot foresee what will be the next tarball name.
|
||||
|
||||
In such a case, consider to update this script via
|
||||
`ghcup self-update`.
|
||||
|
||||
### Compilation
|
||||
|
||||
Although this script can compile GHC for you, it's just a very thin
|
||||
|
493
ghcup
493
ghcup
@ -40,7 +40,7 @@
|
||||
# @VARIABLE: VERSION
|
||||
# @DESCRIPTION:
|
||||
# Version of this script.
|
||||
VERSION=0.0.5
|
||||
VERSION=0.0.6
|
||||
|
||||
# @VARIABLE: SCRIPT
|
||||
# @DESCRIPTION:
|
||||
@ -100,12 +100,6 @@ SCRIPT_UPDATE_URL="https://raw.githubusercontent.com/haskell/ghcup/master/ghcup"
|
||||
# Base URL for all GHC tarballs.
|
||||
GHC_DOWNLOAD_BASEURL="https://downloads.haskell.org/~ghc"
|
||||
|
||||
# @VARIABLE: KNOWN_GOOD_CABAL
|
||||
# @DESCRIPTION:
|
||||
# The latests known good cabal-install version for
|
||||
# which a pre-built binary exists.
|
||||
KNOWN_GOOD_CABAL="2.4.0.0"
|
||||
|
||||
# @VARIABLE: JOBS
|
||||
# @DESCRIPTION:
|
||||
# How many jobs to use for compiling GHC.
|
||||
@ -117,6 +111,37 @@ JOBS="1"
|
||||
# the script name.
|
||||
SOURCE="$0"
|
||||
|
||||
# @VARIABLE: META_DOWNLOAD_URL
|
||||
# DESCRIPTION:
|
||||
# The url of the meta file for getting
|
||||
# download information for ghc/cabal-install etc.
|
||||
META_DOWNLOAD_URL="https://raw.githubusercontent.com/haskell/ghcup/master/.download-urls"
|
||||
|
||||
# @VARIABLE: META_DOWNLOAD_URL_FORMAT
|
||||
# DESCRIPTION:
|
||||
# The version of the meta file format.
|
||||
# This determines whether this script can read the
|
||||
# file from "${META_DOWNLOAD_URL}".
|
||||
META_DOWNLOAD_URL_FORMAT="1"
|
||||
|
||||
# @VARIABLE: META_VERSION_URL
|
||||
# DESCRIPTION:
|
||||
# The url of the meta file for getting
|
||||
# available versions for ghc/cabal-install etc.
|
||||
META_VERSION_URL="https://raw.githubusercontent.com/haskell/ghcup/master/.available-versions"
|
||||
|
||||
# @VARIABLE: META_VERSION_FORMAT
|
||||
# DESCRIPTION:
|
||||
# The version of the meta file format.
|
||||
# This determines whether this script can read the
|
||||
# file from "${META_VERSION_URL}".
|
||||
META_VERSION_FORMAT="1"
|
||||
|
||||
# @VARIABLE: BUG_URL
|
||||
# DESCRIPTION:
|
||||
# The url to report bugs to.
|
||||
BUG_URL="https://github.com/haskell/ghcup/issues"
|
||||
|
||||
# @VARIABLE: CACHING
|
||||
# @DESCRIPTION:
|
||||
# Whether to cache tarballs in $CACHE_LOCATION.
|
||||
@ -153,6 +178,7 @@ SUBCOMMANDS:
|
||||
compile Compile and install GHC from source
|
||||
show Show current/installed GHC
|
||||
set Set currently active GHC version
|
||||
list Show available GHCs and other tools (upstream)
|
||||
self-update Update this script in-place
|
||||
rm Remove an already installed GHC
|
||||
install-cabal Install cabal-install
|
||||
@ -172,20 +198,21 @@ DISCUSSION:
|
||||
# and exit the script with status code 1.
|
||||
install_usage() {
|
||||
(>&2 echo "ghcup-install
|
||||
Install the specified GHC version
|
||||
Install GHC from binary tarball
|
||||
|
||||
USAGE:
|
||||
${SCRIPT} install [FLAGS] <VERSION>
|
||||
${SCRIPT} install [FLAGS] [VERSION]
|
||||
|
||||
FLAGS:
|
||||
-h, --help Prints help information
|
||||
-f, --force Overwrite already existing installation
|
||||
|
||||
ARGS:
|
||||
<VERSION> E.g. \"8.4.3\" or \"8.6.1\"
|
||||
[VERSION] E.g. \"8.4.3\" or \"8.6.1\"
|
||||
(default: discovers recommended version)
|
||||
|
||||
DISCUSSION:
|
||||
Installs the specified GHC version into
|
||||
Installs the specified GHC version (or a recommended default one) into
|
||||
a self-contained \"~/.ghcup/ghc/<ghcver>\" directory
|
||||
and symlinks the ghc binaries to \"~/.ghcup/bin/<binary>-<ghcver>\".
|
||||
")
|
||||
@ -291,10 +318,10 @@ FLAGS:
|
||||
-h, --help Prints help information
|
||||
|
||||
ARGS:
|
||||
<VERSION> E.g. \"2.4.0.0\"
|
||||
[VERSION] E.g. \"2.4.0.0\"
|
||||
|
||||
DISCUSSION:
|
||||
Installs the specified cabal-install version (or the default ${KNOWN_GOOD_CABAL})
|
||||
Installs the specified cabal-install version (or the default recommended)
|
||||
into \"${BIN_LOCATION}\", so it can be overwritten
|
||||
by later \"cabal new-install cabal-install\", which installs into
|
||||
\"~/.cabal/bin\". Make sure to set up your PATH appropriately, so
|
||||
@ -357,6 +384,29 @@ DISCUSSION:
|
||||
exit 1
|
||||
}
|
||||
|
||||
# @FUNCTION: list_usage
|
||||
# @DESCRIPTION:
|
||||
# Print the help message for 'ghcup list' to STDERR
|
||||
# and exit the script with status code 1.
|
||||
list_usage() {
|
||||
(>&2 echo "ghcup-list
|
||||
Show available GHCs and other tools (from upstream)
|
||||
|
||||
USAGE:
|
||||
${SCRIPT} list
|
||||
|
||||
FLAGS:
|
||||
-h, --help Prints help information
|
||||
-t, --tool Tool to list versions for (e.g. 'ghc' or 'cabal-install').
|
||||
Default is showing all tools.
|
||||
|
||||
DISCUSSION:
|
||||
Prints tools (e.g. GHC and cabal-install) and their
|
||||
available upstream versions.
|
||||
")
|
||||
exit 1
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -439,6 +489,18 @@ red_message() {
|
||||
printf "\\033[0;31m%s\\033[0m\\n" "$1"
|
||||
}
|
||||
|
||||
# @FUNCTION: command_exists
|
||||
# @USAGE: <command>
|
||||
# @DESCRIPTION:
|
||||
# Check if a command exists (no arguments).
|
||||
# @RETURNS: 0 if the command exists, non-zero otherwise
|
||||
command_exists() {
|
||||
[ -z "$1" ] && die "Internal error: no argument given to command_exists"
|
||||
|
||||
command -V "$1" >/dev/null 2>&1
|
||||
return $?
|
||||
}
|
||||
|
||||
# @FUNCTION: get_distro_name
|
||||
# @DESCRIPTION:
|
||||
# Gets the current distro identifier following
|
||||
@ -450,7 +512,7 @@ get_distro_name() {
|
||||
# shellcheck disable=SC1091
|
||||
. /etc/os-release
|
||||
printf "%s" "$NAME"
|
||||
elif command -V lsb_release >/dev/null 2>&1; then
|
||||
elif command_exists lsb_release ; then
|
||||
# linuxbase.org
|
||||
printf "%s" "$(lsb_release -si)"
|
||||
elif [ -f /etc/lsb-release ]; then
|
||||
@ -478,7 +540,7 @@ get_distro_ver() {
|
||||
# shellcheck disable=SC1091
|
||||
. /etc/os-release
|
||||
printf "%s" "$VERSION_ID"
|
||||
elif command -V lsb_release >/dev/null 2>&1; then
|
||||
elif command_exists lsb_release ; then
|
||||
# linuxbase.org
|
||||
printf "%s" "$(lsb_release -sr)"
|
||||
elif [ -f /etc/lsb-release ]; then
|
||||
@ -519,52 +581,143 @@ get_arch() {
|
||||
unset myarch
|
||||
}
|
||||
|
||||
# @FUNCTION: get_download_url
|
||||
# @USAGE: <ghcversion>
|
||||
# @FUNCTION: try_download_url
|
||||
# @USAGE: <tool> <ver> <arch> <distro-ident> <file>
|
||||
# @DESCRIPTION:
|
||||
# Gets the right (hopefully) download url for the given ghc version
|
||||
# Tries to get the download url of a tool with our
|
||||
# specified format for download urls (see ${META_DOWNLOAD_URL}").
|
||||
# STDOUT: the download url, if an appropriate was found
|
||||
try_download_url() {
|
||||
[ "$#" -lt 5 ] && die "Internal error: not enough arguments to try_download_url"
|
||||
|
||||
tool=$1
|
||||
ver=$2
|
||||
arch=$3
|
||||
distro_ident=$4
|
||||
filename=$5
|
||||
|
||||
awk "
|
||||
NF {
|
||||
split(\$4,a,\",\")
|
||||
if (\$1 == \"${tool}\" && \$2 == \"${ver}\" && \$3 == \"${arch}\") {
|
||||
for (i in a) if (a[i] == \"${distro_ident}\") {
|
||||
print \$5
|
||||
exit
|
||||
}
|
||||
}
|
||||
}" "${filename}" || die "awk failed!"
|
||||
|
||||
unset tool ver arch distro_ident filename
|
||||
}
|
||||
|
||||
# @FUNCTION: check_meta_file_version
|
||||
# @USAGE: <file> <metaver>
|
||||
# @DESCRIPTION:
|
||||
# Check that the given meta file has the same format version
|
||||
# as specified, otherwise die.
|
||||
check_meta_file_version() {
|
||||
{ [ -z "$1" ] || [ -z "$2" ] ;} && die "Internal error: not enough arguments given to check_meta_file_version"
|
||||
|
||||
mymetavar=$(awk "
|
||||
NR==1 {
|
||||
if (\$2 ~ \"fmt-version\") {
|
||||
{
|
||||
split(\$2,a,\"=\")
|
||||
print a[2]
|
||||
exit
|
||||
}
|
||||
}
|
||||
}" "$1")
|
||||
|
||||
if [ "${mymetavar}" != "$2" ] ; then
|
||||
die "Unsupported meta file format, run: ghcup self-update"
|
||||
fi
|
||||
|
||||
unset mymetavar
|
||||
}
|
||||
|
||||
# @FUNCTION: get_download_url
|
||||
# @USAGE: <tool> <version>
|
||||
# @DESCRIPTION:
|
||||
# Gets the download url for the given tool and version
|
||||
# and the current distro and architecture (which it tries to discover).
|
||||
# @STDOUT: ghc download url
|
||||
# This uses "${META_DOWNLOAD_URL}" for url discovery.
|
||||
# @STDOUT: download url or nothing if no appropriate was found
|
||||
get_download_url() {
|
||||
[ -z "$1" ] && die "Internal error: no argument given to get_download_url"
|
||||
{ [ -z "$1" ] || [ -z "$2" ] ;} && die "Internal error: not enough arguments given to get_download_url"
|
||||
|
||||
myghcver=$1
|
||||
mytool=$1
|
||||
myver=$2
|
||||
myarch=$(get_arch)
|
||||
mydistro=$(get_distro_name)
|
||||
mydistro=$(get_distro_alias "$(get_distro_name)")
|
||||
mydistrover=$(get_distro_ver)
|
||||
meta_file_name="$(basename "${META_DOWNLOAD_URL}")"
|
||||
|
||||
# TODO: awkward, restructure
|
||||
case "${mydistro},${mydistrover},${myarch},${myghcver}" in
|
||||
Debian*,7,i386,8.2.2)
|
||||
printf "%s" "${GHC_DOWNLOAD_BASEURL}/${myghcver}/ghc-${myghcver}-${myarch}-deb${mydistrover}-linux.tar.xz"
|
||||
;;
|
||||
*,*,i386,*)
|
||||
printf "%s" "${GHC_DOWNLOAD_BASEURL}/${myghcver}/ghc-${myghcver}-${myarch}-deb8-linux.tar.xz"
|
||||
;;
|
||||
Debian*,*,*,8.2.2)
|
||||
printf "%s" "${GHC_DOWNLOAD_BASEURL}/${myghcver}/ghc-${myghcver}-${myarch}-deb8-linux.tar.xz"
|
||||
;;
|
||||
Debian*,8,*,*)
|
||||
printf "%s" "${GHC_DOWNLOAD_BASEURL}/${myghcver}/ghc-${myghcver}-${myarch}-deb8-linux.tar.xz"
|
||||
;;
|
||||
Debian*,*,*,*)
|
||||
printf "%s" "${GHC_DOWNLOAD_BASEURL}/${myghcver}/ghc-${myghcver}-${myarch}-deb9-linux.tar.xz"
|
||||
;;
|
||||
Ubuntu*,*,*,8.2.2)
|
||||
printf "%s" "${GHC_DOWNLOAD_BASEURL}/${myghcver}/ghc-${myghcver}-${myarch}-deb8-linux.tar.xz"
|
||||
;;
|
||||
Ubuntu*,*,*,*)
|
||||
printf "%s" "${GHC_DOWNLOAD_BASEURL}/${myghcver}/ghc-${myghcver}-${myarch}-deb9-linux.tar.xz"
|
||||
;;
|
||||
*,*,*,8.2.2)
|
||||
printf "%s" "${GHC_DOWNLOAD_BASEURL}/${myghcver}/ghc-${myghcver}-${myarch}-deb8-linux.tar.xz"
|
||||
;;
|
||||
*,*,*,*) # this is our best guess
|
||||
printf "%s" "${GHC_DOWNLOAD_BASEURL}/${myghcver}/ghc-${myghcver}-${myarch}-fedora27-linux.tar.xz"
|
||||
;;
|
||||
esac
|
||||
(
|
||||
edo cd "${CACHE_LOCATION}"
|
||||
|
||||
unset myghcver myarch mydistro mydistrover
|
||||
download_silent "${META_DOWNLOAD_URL}"
|
||||
|
||||
check_meta_file_version "${meta_file_name}" "${META_DOWNLOAD_URL_FORMAT}"
|
||||
|
||||
# 1st try with full distro=ver
|
||||
url=$(try_download_url "${mytool}" "${myver}" "${myarch}" "${mydistro}=${mydistrover}" "${meta_file_name}")
|
||||
if [ -n "${url}" ] ; then
|
||||
printf "%s" "${url}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# 2nd try with just distro
|
||||
url=$(try_download_url "${mytool}" "${myver}" "${myarch}" "${mydistro}" "${meta_file_name}")
|
||||
if [ -n "${url}" ] ; then
|
||||
printf "%s" "${url}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# 3rd try with unknown
|
||||
url=$(try_download_url "${mytool}" "${myver}" "${myarch}" "unknown" "${meta_file_name}")
|
||||
if [ -n "${url}" ] ; then
|
||||
printf "%s" "${url}"
|
||||
exit 0
|
||||
fi
|
||||
)
|
||||
|
||||
unset mytool myver myarch mydistro mydistrover meta_file_name
|
||||
}
|
||||
|
||||
# @FUNCTION: get_tool_ver_from_tag
|
||||
# @USAGE: <tool> <tag>
|
||||
# @DESCRIPTION:
|
||||
# Gets the tool version with the given tag (first match) from
|
||||
# "${META_VERSION_URL}".
|
||||
# STDOUT: the version, if any, or nothing
|
||||
get_tool_ver_from_tag() {
|
||||
{ [ -z "$1" ] || [ -z "$2" ] ;} && die "Internal error: not enough arguments given to get_tool_ver_from_tag"
|
||||
|
||||
mytool=$1
|
||||
mytag=$2
|
||||
meta_file_name="$(basename "${META_VERSION_URL}")"
|
||||
|
||||
(
|
||||
edo cd "${CACHE_LOCATION}"
|
||||
|
||||
download_silent "${META_VERSION_URL}"
|
||||
|
||||
check_meta_file_version "${meta_file_name}" "${META_VERSION_FORMAT}"
|
||||
|
||||
awk "
|
||||
NF {
|
||||
if (\$1 == \"${mytool}\") {
|
||||
split(\$3,a,\",\");
|
||||
for (i in a) if (a[i] == \"${mytag}\") {
|
||||
print \$2
|
||||
exit
|
||||
}
|
||||
}
|
||||
}" "${meta_file_name}" || die "awk failed!"
|
||||
)
|
||||
|
||||
unset mytool mytag meta_file_name
|
||||
}
|
||||
|
||||
# @FUNCTION: ghc_already_installed
|
||||
@ -611,6 +764,23 @@ download() {
|
||||
edo ${DOWNLOADER} ${DOWNLOADER_OPTS} "$1"
|
||||
}
|
||||
|
||||
# @FUNCTION: download_silent
|
||||
# @USAGE: <url>
|
||||
# @DESCRIPTION:
|
||||
# Downloads the given url as a file into the current directory, silent, unless
|
||||
# verbosity is on.
|
||||
download_silent() {
|
||||
[ -z "$1" ] && die "Internal error: no argument given to download"
|
||||
|
||||
if ${VERBOSE} ; then
|
||||
# shellcheck disable=SC2086
|
||||
edo ${DOWNLOADER} ${DOWNLOADER_OPTS} "$1"
|
||||
else
|
||||
# shellcheck disable=SC2086
|
||||
edo ${DOWNLOADER} ${DOWNLOADER_OPTS} "$1" 1> /dev/null 2> /dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
# @FUNCTION: unpack
|
||||
# @USAGE: <tarball>
|
||||
# @DESCRIPTION:
|
||||
@ -668,6 +838,72 @@ ask_for_confirmation() {
|
||||
unset confirmation_msg answer
|
||||
}
|
||||
|
||||
# @FUNCTION: get_distro_alias
|
||||
# @USAGE: <distro name>
|
||||
# @DESCRIPTION:
|
||||
# For a given known distro name, return our internal
|
||||
# unique distro alias. E.g.:
|
||||
# Debian GNU/Linux -> debian
|
||||
# STDOUT: our internal distro alias
|
||||
get_distro_alias() {
|
||||
distro_name=$1
|
||||
distro_alias=unknown
|
||||
|
||||
case "${distro_name}" in
|
||||
"Debian"|"Debian GNU/Linux"|"debian")
|
||||
distro_alias=debian
|
||||
;;
|
||||
"Ubuntu"|"ubuntu")
|
||||
distro_alias=ubuntu
|
||||
;;
|
||||
"Exherbo"|"exherbo")
|
||||
distro_alias=exherbo
|
||||
;;
|
||||
"Fedora"|"fedora")
|
||||
distro_alias=fedora
|
||||
;;
|
||||
"CentOS Linux"|"CentOS"|"centos")
|
||||
distro_alias=centos
|
||||
;;
|
||||
esac
|
||||
|
||||
printf "%s" "${distro_alias}"
|
||||
|
||||
unset distro_name distro_alias
|
||||
}
|
||||
|
||||
# @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 the argument unchanged.
|
||||
# @STDOUT: realpath of the given file
|
||||
posix_realpath() {
|
||||
[ -z "$1" ] && die "Internal error: no argument given to posix_realpath"
|
||||
mysource=$1
|
||||
|
||||
while [ -h "${mysource}" ]; do
|
||||
mydir="$( cd -P "$( dirname "${mysource}" )" > /dev/null 2>&1 && pwd )"
|
||||
mysource="$(readlink "${mysource}")"
|
||||
[ "${mysource%${mysource#?}}"x != '/x' ] && mysource="${mydir}/${mysource}"
|
||||
done
|
||||
mydir="$( cd -P "$( dirname "${mysource}" )" > /dev/null 2>&1 && pwd )"
|
||||
|
||||
if [ -z "${mydir}" ] ; then
|
||||
(>&2 echo "${1}: Permission denied")
|
||||
elif [ ! -e "$1" ] ; then
|
||||
echo "${mysource}"
|
||||
else
|
||||
echo "${mydir%/}/$(basename "${mysource}")"
|
||||
fi
|
||||
|
||||
unset mysource mydir posix_realpath_error
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -686,10 +922,16 @@ install_ghc() {
|
||||
|
||||
myghcver=$1
|
||||
inst_location=$(get_ghc_location "$1")
|
||||
download_url=$(get_download_url "${myghcver}")
|
||||
download_url=$(get_download_url "ghc" "${myghcver}")
|
||||
download_tarball_name=$(basename "${download_url}")
|
||||
first_install=true
|
||||
|
||||
if [ -z "${download_url}" ] ; then
|
||||
die "Could not find an appropriate download for the requested GHC-${myghcver} on your system! Please report a bug at ${BUG_URL}"
|
||||
fi
|
||||
|
||||
status_message "Installing GHC-${myghcver} for $(get_distro_name) on architecture $(get_arch)"
|
||||
|
||||
if ghc_already_installed "${myghcver}" ; then
|
||||
if ${FORCE} ; then
|
||||
echo "GHC already installed in ${inst_location}, overwriting!"
|
||||
@ -699,15 +941,10 @@ install_ghc() {
|
||||
first_install=false
|
||||
fi
|
||||
|
||||
status_message "Installing GHC for $(get_distro_name) on architecture $(get_arch)"
|
||||
tmp_dir=$(mktemp -d)
|
||||
[ -z "${tmp_dir}" ] && die "Failed to create temporary directory"
|
||||
(
|
||||
if ${CACHING} ; then
|
||||
[ -e "${CACHE_LOCATION}" ] || {
|
||||
[ -e "${INSTALL_BASE}" ] || edo mkdir "${INSTALL_BASE}"
|
||||
edo mkdir "${CACHE_LOCATION}"
|
||||
}
|
||||
if [ ! -e "${CACHE_LOCATION}/${download_tarball_name}" ] ; then
|
||||
edo cd "${CACHE_LOCATION}"
|
||||
download "${download_url}"
|
||||
@ -806,24 +1043,6 @@ set_ghc() {
|
||||
#--[ Subcommand self-update ]--#
|
||||
################################
|
||||
|
||||
# @FUNCTION: script_dir
|
||||
# @DESCRIPTION:
|
||||
# Portably gets the full directory of where
|
||||
# this script resides in and prints it to stdout.
|
||||
# @STDOUT: script directory
|
||||
script_dir() {
|
||||
mysource=${SOURCE}
|
||||
|
||||
while [ -h "${mysource}" ]; do
|
||||
mydir="$( cd -P "$( dirname "${mysource}" )" > /dev/null && pwd )"
|
||||
mysource="$(readlink "${mysource}")"
|
||||
[ "${mysource%${mysource#?}}"x != '/x' ] && mysource="${mydir}/${mysource}"
|
||||
done
|
||||
mydir="$( cd -P "$( dirname "${mysource}" )" > /dev/null && pwd )"
|
||||
echo "${mydir}"
|
||||
|
||||
unset mysource mydir
|
||||
}
|
||||
|
||||
# @FUNCTION: self_update
|
||||
# @USAGE: <install-location>
|
||||
@ -889,10 +1108,10 @@ show_ghc() {
|
||||
# @STDOUT: current GHC version
|
||||
show_ghc_installed() {
|
||||
current_ghc="${BIN_LOCATION}/ghc"
|
||||
real_ghc=$(realpath "${current_ghc}" 2>/dev/null)
|
||||
real_ghc=$(posix_realpath "${current_ghc}")
|
||||
|
||||
if [ -L "${current_ghc}" ] ; then # is symlink
|
||||
if [ -e "${real_ghc}" ] ; then # exists (realpath was called)
|
||||
if [ -e "${real_ghc}" ] ; then # exists (posix_realpath was called)
|
||||
real_ghc="$(basename "${real_ghc}" | sed 's#ghc-##')"
|
||||
printf "%s" "${real_ghc}"
|
||||
else # is a broken symlink
|
||||
@ -985,9 +1204,15 @@ install_cabal() {
|
||||
mycabalver=$1
|
||||
myarch=$(get_arch)
|
||||
inst_location=$BIN_LOCATION
|
||||
download_url="https://downloads.haskell.org/~cabal/cabal-install-${mycabalver}/cabal-install-${mycabalver}-${myarch}-unknown-linux.tar.gz"
|
||||
download_url=$(get_download_url "cabal-install" "${mycabalver}")
|
||||
download_tarball_name=$(basename "${download_url}")
|
||||
|
||||
if [ -z "${download_url}" ] ; then
|
||||
die "Could not find an appropriate download for the requested cabal-install-${mycabalver} on your system! Please report a bug at ${BUG_URL}"
|
||||
fi
|
||||
|
||||
status_message "Installing cabal-install-${mycabalver} into \"${inst_location}\""
|
||||
|
||||
[ -e "${inst_location}" ] || {
|
||||
# TODO: this is a bit shaky because we don't use -p
|
||||
edo mkdir "${INSTALL_BASE}"
|
||||
@ -998,10 +1223,6 @@ install_cabal() {
|
||||
[ -z "${tmp_dir}" ] && die "Failed to create temporary directory"
|
||||
(
|
||||
if ${CACHING} ; then
|
||||
[ -e "${CACHE_LOCATION}" ] || {
|
||||
[ -e "${INSTALL_BASE}" ] || edo mkdir "${INSTALL_BASE}"
|
||||
edo mkdir "${CACHE_LOCATION}"
|
||||
}
|
||||
if [ ! -e "${CACHE_LOCATION}/${download_tarball_name}" ] ; then
|
||||
edo cd "${CACHE_LOCATION}"
|
||||
download "${download_url}"
|
||||
@ -1069,10 +1290,6 @@ compile_ghc() {
|
||||
[ -z "${tmp_dir}" ] && die "Failed to create temporary directory"
|
||||
(
|
||||
if ${CACHING} ; then
|
||||
[ -e "${CACHE_LOCATION}" ] || {
|
||||
[ -e "${INSTALL_BASE}" ] || edo mkdir "${INSTALL_BASE}"
|
||||
edo mkdir "${CACHE_LOCATION}"
|
||||
}
|
||||
if [ ! -e "${CACHE_LOCATION}/${download_tarball_name}" ] ; then
|
||||
edo cd "${CACHE_LOCATION}"
|
||||
download "${download_url}"
|
||||
@ -1154,7 +1371,10 @@ print_debug_info() {
|
||||
echo " Downloader: ${DOWNLOADER} ${DOWNLOADER_OPTS} <url>"
|
||||
echo " Script update url: ${SCRIPT_UPDATE_URL}"
|
||||
echo " GHC download baseurl: ${GHC_DOWNLOAD_BASEURL}"
|
||||
echo " Known good cabal version: ${KNOWN_GOOD_CABAL}"
|
||||
echo " Meta download url ${META_DOWNLOAD_URL}"
|
||||
echo " Meta download format ${META_DOWNLOAD_URL_FORMAT}"
|
||||
echo " Meta version url ${META_VERSION_URL}"
|
||||
echo " Meta version format ${META_VERSION_FORMAT}"
|
||||
echo
|
||||
echo "Detected system information:"
|
||||
echo " Architecture: $(get_arch)"
|
||||
@ -1163,6 +1383,51 @@ print_debug_info() {
|
||||
}
|
||||
|
||||
|
||||
#########################
|
||||
#--[ Subcommand list ]--#
|
||||
#########################
|
||||
|
||||
|
||||
# @FUNCTION: list
|
||||
# @USAGE: [tool]
|
||||
# @DESCRIPTION:
|
||||
# List available tools and their versions from upstream.
|
||||
list() {
|
||||
mytool=$1
|
||||
|
||||
meta_file_name="$(basename "${META_VERSION_URL}")"
|
||||
|
||||
(
|
||||
edo cd "${CACHE_LOCATION}"
|
||||
|
||||
download_silent "${META_VERSION_URL}"
|
||||
|
||||
check_meta_file_version "${meta_file_name}" "${META_VERSION_FORMAT}"
|
||||
|
||||
echo "Available upstream versions:"
|
||||
echo
|
||||
if [ -z "${mytool}" ] ; then
|
||||
awk "
|
||||
NF {
|
||||
if (\$1 != \"#\") {
|
||||
print \$1 \" \" \$2
|
||||
}
|
||||
}" "${meta_file_name}" || die "awk failed!"
|
||||
else
|
||||
awk "
|
||||
NF {
|
||||
if (\$1 == \"${mytool}\") {
|
||||
print \$1 \" \" \$2
|
||||
}
|
||||
}" "${meta_file_name}" || die "awk failed!"
|
||||
fi
|
||||
)
|
||||
|
||||
unset mytool meta_file_name
|
||||
}
|
||||
|
||||
|
||||
|
||||
#######################
|
||||
#--[ Sanity checks ]--#
|
||||
#######################
|
||||
@ -1172,6 +1437,15 @@ if [ -z "$HOME" ] ; then
|
||||
die "HOME env not set, cannot operate"
|
||||
fi
|
||||
|
||||
if [ ! -e "${INSTALL_BASE}" ] ; then
|
||||
edo mkdir "${INSTALL_BASE}"
|
||||
fi
|
||||
|
||||
if [ ! -e "${CACHE_LOCATION}" ] ; then
|
||||
edo mkdir "${CACHE_LOCATION}"
|
||||
fi
|
||||
|
||||
|
||||
|
||||
|
||||
##############################################
|
||||
@ -1210,7 +1484,13 @@ while [ $# -gt 0 ] ; do
|
||||
usage
|
||||
fi
|
||||
;;
|
||||
*) # TODO: here comes command availability checking
|
||||
*)
|
||||
# check for available commands
|
||||
for com in ${DOWNLOADER} awk uname basename tar xz gzip mktemp dirname ; do
|
||||
command_exists "${com}" || die "Command \"${com}\" is required, but does not exist! Please install."
|
||||
done
|
||||
unset com
|
||||
|
||||
case $1 in
|
||||
install)
|
||||
shift 1
|
||||
@ -1223,8 +1503,15 @@ while [ $# -gt 0 ] ; do
|
||||
break;;
|
||||
esac
|
||||
done
|
||||
[ "${GHC_VER}" ] || install_usage
|
||||
install_ghc "${GHC_VER}"
|
||||
if [ -z "${GHC_VER}" ] ; then
|
||||
_tool_ver="$(get_tool_ver_from_tag "ghc" "recommended")"
|
||||
if [ -z "${_tool_ver}" ] ; then
|
||||
die "Could not find a recommended GHC version, please report a bug at ${BUG_URL}!"
|
||||
fi
|
||||
install_ghc "${_tool_ver}"
|
||||
else
|
||||
install_ghc "${GHC_VER}"
|
||||
fi
|
||||
break;;
|
||||
set)
|
||||
shift 1
|
||||
@ -1250,7 +1537,7 @@ while [ $# -gt 0 ] ; do
|
||||
if [ "${TARGET_LOCATION}" ] ; then
|
||||
self_update "${TARGET_LOCATION}"
|
||||
else
|
||||
self_update "$(script_dir)"
|
||||
self_update "$(dirname "$(posix_realpath "${SOURCE}")")"
|
||||
fi
|
||||
break;;
|
||||
show)
|
||||
@ -1295,10 +1582,14 @@ while [ $# -gt 0 ] ; do
|
||||
break;;
|
||||
esac
|
||||
done
|
||||
if [ "${CABAL_VER}" ] ; then
|
||||
if [ -n "${CABAL_VER}" ] ; then
|
||||
install_cabal "${CABAL_VER}"
|
||||
else
|
||||
install_cabal "${KNOWN_GOOD_CABAL}"
|
||||
_cabal_ver="$(get_tool_ver_from_tag "cabal-install" "recommended")"
|
||||
if [ -z "${_cabal_ver}" ] ; then
|
||||
die "Could not find a recommended cabal-install version, please report a bug at ${BUG_URL}!"
|
||||
fi
|
||||
install_cabal "${_cabal_ver}"
|
||||
fi
|
||||
break;;
|
||||
compile)
|
||||
@ -1331,6 +1622,18 @@ while [ $# -gt 0 ] ; do
|
||||
done
|
||||
print_debug_info
|
||||
break;;
|
||||
list)
|
||||
shift 1
|
||||
while [ $# -gt 0 ] ; do
|
||||
case $1 in
|
||||
-h|--help) list_usage;;
|
||||
-t|--tool) TOOL=$2
|
||||
shift 2;;
|
||||
*) list_usage;;
|
||||
esac
|
||||
done
|
||||
list "${TOOL}"
|
||||
break;;
|
||||
*) usage;;
|
||||
esac
|
||||
break;;
|
||||
|
Loading…
Reference in New Issue
Block a user