Merge remote-tracking branch 'remotes/origin/PR/meta-file-format'

This commit is contained in:
Julian Ospald 2018-10-30 21:22:32 +08:00
commit a08d5970d3
No known key found for this signature in database
GPG Key ID: 511B62C09D50CD28
6 changed files with 495 additions and 116 deletions

11
.available-versions Normal file
View 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
View 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

View File

@ -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
View 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))

View File

@ -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
View File

@ -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;;