Skip to content
Permalink
Branch: master
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
executable file 1782 lines (1500 sloc) 49.7 KB
#!/usr/bin/env bash
# <help>
#
# Usage: multirust <command> [--verbose] [--version]
#
# Commands:
#
# default Set the default toolchain
# override Set the toolchain override for the current directory tree
# update Install or update a given toolchain (for example, "stable", "beta", "nightly")
# show-override Show information about the current override
# show-default Show information about the current default
# show-toolchain Show the name of the current toolcain
# list-overrides List all overrides
# list-toolchains List all installed toolchains
# remove-override Remove an override, for current directory unless specified
# remove-toolchain Uninstall a toolchain
# list-available-targets
# List targets available to install
# add-target Add additional compilation targets to an existing toolchain
# run Run a command in an environment configured for a toolchain
# delete-data Delete all user metadata, including installed toolchains
# upgrade-data Upgrade the ~/.multirust directory from previous versions
# doc Open the documentation for the currently active toolchain
# which Report location of the currently active Rust tool.
# help Show help for this command or subcommands
#
# Use `multirust help <command>` for detailed help.
#
# </help>
# <help-default>
#
# Sets the default toolchain.
#
# Usage:
# multirust default <toolchain> [--copy-local <toolchain-path> |
# --link-local <toolchain-path> |
# --installer <installer-path-or-url> |
# --installer <path-or-url>[,<path-or-url>]]
#
# Sets the default toolchain to the one specified. If the toolchain is
# not already installed then it is first installed.
#
# Use --copy-local <path> to install by copying a local
# toolchain. This will copy the toolchain from a local directory to a
# directory in multirust's home.
#
# Use --link-local <path> to install by linking to a local
# toolchain. This will create a soft link to the local toolchain in
# multirust's home.
#
# The --installer flag allows arbitrary builds of rust to be installed
# from a custom-built installer, either from the local filesystem or
# the network. Custom installers are neither checksum nor
# signature-verified.
#
# With --installer, if multiple installers are specified then they are
# all installed to the same location. This can make installing cargo
# easier since otherwise it would need to be combined with rustc into
# a single installer through the rust-packaging project.
#
# If the toolchain is already installed then it is not reinstalled,
# though if installing a custom toolchain with --copy-local,
# --link-local, or --installer then the toolchain is always
# reinstalled.
#
# </help-default>
# <help-override>
#
# Sets the current override toolchain.
#
# Usage:
# multirust override <toolchain> [--copy-local <toolchain-path> |
# --link-local <toolchain-path> |
# --installer <installer-path-or-url> |
# --installer <path-or-url>[,<path-or-url>]]
#
# Sets the toolchain that will be used when working at or below the
# current directory. If the toolchain is not already installed then it
# is first installed.
#
# Use --copy-local <path> to install by copying a local
# toolchain. This will copy the toolchain from a local directory to a
# directory in multirust's home.
#
# Use --link-local <path> to install by linking to a local
# toolchain. This will create a soft link to the local toolchain in
# multirust's home.
#
# The --installer flag allows arbitrary builds of rust to be installed
# from a custom-built installer, either from the local filesystem or
# the network. Custom installers are neither checksum nor
# signature-verified.
#
# With --installer, if multiple installers are specified then they are
# all installed to the same location. This can make installing cargo
# easier since otherwise it would need to be combined with rustc into
# a single installer through the rust-packaging project.
#
# If the toolchain is already installed then it is not reinstalled,
# though if installing a custom toolchain with --copy-local,
# --link-local, or --installer then the toolchain is always
# reinstalled.
#
# To remove an existing override use `multirust remove-override`.
#
# </help-override>
# <help-update>
#
# Updates an installed toolchain or installs from scratch if it is not
# yet installed.
#
# Usage:
# multirust update
# multirust update <toolchain> [--copy-local <toolchain-path> |
# --link-local <toolchain-path> |
# --installer <installer-path-or-url> |
# --installer <path-or-url>[,<path-or-url>]]
#
# With no toolchain specified, the update command updates each of the
# stable, beta, and nightly toolchains from the official release
# channels.
#
# Use --copy-local <path> to install by copying a local
# toolchain. This will copy the toolchain from a local directory to a
# directory in multirust's home.
#
# Use --link-local <path> to install by linking to a local
# toolchain. This will create a soft link to the local toolchain in
# multirust's home.
#
# The --installer flag allows arbitrary builds of rust to be installed
# from a custom-built installer, either from the local filesystem or
# the network. Custom installers are neither checksum nor
# signature-verified.
#
# With --installer, if multiple installers are specified then they are
# all installed to the same location. This can make installing cargo
# easier since otherwise it would need to be combined with rustc into
# a single installer through the rust-packaging project.
#
# </help-update>
# <help-show-default>
#
# Displays information about the default toolchain.
#
# Usage: multirust show-default
#
# </help-show-default>
# <help-show-override>
#
# Displays information about the current toolchain override.
#
# Usage: multirust show-override
#
# </help-show-override>
# <help-show-toolchain>
#
# Displays the name of the toolchain that would be used.
#
# Usage: multirust show-toolchain
#
# </help-show-toolchain>
# <help-list-overrides>
#
# Displays a list of all overrides.
#
# Usage: multirust list-overrides
#
# </help-list-overrides>
# <help-list-toolchains>
#
# Displays a list of all toolchains.
#
# Usage: multirust list-toolchains
#
# </help-list-toolchains>
# <help-remove-override>
#
# Removes the override for the current directory, or the named override
# if one is provided.
#
# Usage: multirust remove-override [override]
#
# </help-remove-override>
# <help-remove-toolchain>
#
# Uninstalls an installed toolchain.
#
# Usage: multirust remove-toolchain <toolchain>
#
# </help-remove-toolchain>
# <help-list-available-targets>
#
# List the targets available to an installed toolchain
#
# Usage:
# multirust list-available-targets <toolchain>
#
# </help-list-available-targets>
# <help-add-target>
#
# Adds the standard library for a given platform to an existing
# installation.
#
# Usage:
# multirust add-target <toolchain> <triple>
#
# </help-add-target>
# <help-run>
#
# Usage: multirust run <toolchain> <command> [arguments]
#
# Configures an environment to use the given toolchain and then runs
# the specified program. The command may be any program, not just
# rustc or cargo. This can be used for testing arbitrary toolchains
# without setting an override.
#
# </help-run>
# <help-delete-data>
#
# Deletes the ~/.multirust directory, removing all installed
# toolchains, overrides, and aliases for the current user.
#
# Prompts for confirmation. Disable prompt with -y.
#
# Does not delete global aliases.
#
# Usage: multirust delete-data [-y].
#
# </help-delete-data>
# <help-upgrade-data>
#
# Usage: multirust upgrade-data
#
# Upgrades the ~/.multirust directory from previous versions.
#
# </help-upgrade-data>
# <help-doc>
#
# Opens the documentation for the currently active toolchain with the default browser.
#
# Usage:
# multirust doc [--all]
#
# By default, it opens the API documentation for the standard library.
#
# Use --all to open the documentation overview page, which gives access to all
# the installed documentation.
#
# </help-doc>
# <help-which>
#
# Report location of the currently active Rust tool.
#
# Usage:
# multirust which binary
#
# </help-which>
# <help-help>
#
# Usage: multirust help [subcommand]
#
# Displays help for multirust or a multirust subcommand.
#
# </help-help>
set -u
main() {
set_globals "$@"
handle_command_line_args "$@"
}
set_globals() {
# Environment sanity checks
assert_nz "$HOME" "\$HOME is undefined"
assert_nz "$0" "\$0 is undefined"
# Some constants
version=0.8.0
# NB: This will be replaced by the build script
commit_version=
metadata_version=2
# The directory on the server containing the dist artifacts
rust_dist_dir=dist
# Useful values pulled from the name of the invoked process
cmd_dirname="$(dirname "$0")"
cmd_basename="$(basename "$0")"
assert_nz "$cmd_dirname" "cmd_dirname"
assert_nz "$cmd_basename" "cmd_basename"
# Set up the multirust data dir
multirust_dir="${MULTIRUST_HOME-$HOME/.multirust}"
assert_nz "$multirust_dir" "multirust_dir"
# Make sure our home dir is absolute. Once multirust is invoked, this
# variables is carried through recursive toolchain invocations. If
# some tool like Cargo changes directories, we want to be sure we can
# find our home dir again.
mkdir -p "$multirust_dir"
need_ok "failed to create home directory"
multirust_dir="$(abs_path "$multirust_dir")"
assert_nz "$multirust_dir" "multirust_dir"
# Export RUSTUP_HOME to configure rustup.sh to store it's stuff
# in the MULTIRUST_HOME directory.
export RUSTUP_HOME="$multirust_dir/rustup"
# Data locations
version_file="$multirust_dir/version"
override_db="$multirust_dir/overrides"
default_file="$multirust_dir/default"
toolchains_dir="$multirust_dir/toolchains"
update_hash_dir="$multirust_dir/update-hashes"
temp_dir="$multirust_dir/tmp"
# Used for delimiting fields in override_db
delim=";"
# Set up the GPG key
official_rust_gpg_key="
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1
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
Mve696B5tlHyc1KxjHR6w9GRsh4=
=5FXw
-----END PGP PUBLIC KEY BLOCK-----
"
if [ -n "${MULTIRUST_GPG_KEY-}" ]; then
gpg_key=`cat "$MULTIRUST_GPG_KEY"`
else
gpg_key="$official_rust_gpg_key"
fi
# Check for some global command-line options
flag_verbose=false
flag_yes=false
for opt in "$@"; do
case "$opt" in
-v | --verbose)
flag_verbose=true
;;
-y | --yes)
flag_yes=true
;;
esac
done
if [ -n "${MULTIRUST_VERBOSE-}" ]; then
flag_verbose=true
fi
# Sanity check. Where's rustup.sh?
if [ ! -e "$cmd_dirname/rustup.sh" ]; then
err "rustup.sh not found at $cmd_dirname/rustup.sh"
fi
}
handle_command_line_args() {
local _cmd_arg="${1-}"
# begin fuzzy matching
# list of all commands
local _cmds=(
update
default
override
show-default
show-override
show-toolchain
list-overrides
list-toolchains
remove-override
remove-toolchain
list-available-targets
add-target
run
delete-data
upgrade-data
doc
which
ctl
help
)
for _cmd in "${_cmds[@]}"; do
if [[ $_cmd =~ - && $_cmd_arg =~ - ]]; then
# split on - then check each part for a prefix match
local _cmd_parts=(${_cmd//-/ })
local _arg_parts=(${_cmd_arg//-/ })
local i
if [[ ${#_cmd_parts[@]} == ${#_arg_parts[@]} ]]; then
local sofar=0
for i in ${!_cmd_parts[@]}; do
if [[ ${_cmd_parts[$i]} == ${_arg_parts[$i]} ]]; then
sofar=$(( $sofar + 1 ))
continue
fi
if [[ $(expr ${_cmd_parts[$i]} : ${_arg_parts[$i]}) > 0 ]]; then
sofar=$(( $sofar + 1 ))
continue
fi
break
done
if [[ $sofar == ${#_cmd_parts[@]} ]]; then
_cmd_arg=$_cmd
break
fi
fi
else
# just check for a prefix match
if [[ $_cmd_arg != '' && $(expr $_cmd : $_cmd_arg) > 0 ]]; then
_cmd_arg=$_cmd
break
fi
fi
done
# end fuzzy matching (if there was a match, $_cmd_arg has been replaced)
# Make sure we're working with an up-to-date metadata format
case "$_cmd_arg" in
upgrade-data | delete-data | help)
# Don't need consistent metadata for these commands
;;
*)
check_metadata_version
;;
esac
case "$_cmd_arg" in
update)
if [ -z "${2-}" ]; then
# As a special case `multirust update` updates all three release channels
update_all_channels
else
# For distribution builds always install
# For custom builds always install toolchain
handle_common_install_args handle_update_toolchain "$@"
fi
;;
default | override)
# For distribution builds install only if not installed
# For custom builds always install toolchain
handle_common_install_args install_toolchain_if_not_installed "$@"
# Run either set_default or set_override to turn it on
toolchain="${2-}"
"set_$_cmd_arg" "$toolchain"
;;
show-default) show_default;;
show-override) show_override;;
show-toolchain) show_toolchain;;
list-overrides) list_overrides;;
list-toolchains) list_toolchains;;
remove-override)
if [ -z "${2-}" ]; then
remove_override "$(pwd -P)"
else
remove_override $2
fi
;;
remove-toolchain)
if [ -z "${2-}" ]; then
err 'unspecified toolchain. try `multirust help remove-toolchain`'
fi
remove_toolchain "$2"
;;
list-available-targets)
if [ -z "${2-}" ]; then
err 'unspecified toolchain. try `multirust help list-available-targets`'
fi
list_available_targets "$2"
;;
add-target)
if [ -z "${2-}" ]; then
err 'unspecified toolchain. try `multirust help add-target`'
fi
if [ -z "${3-}" ]; then
err 'unspecified target. try `multirust help add-target`'
fi
add_target "$2" "$3"
;;
run)
if [ -z "${2-}" ]; then
err 'unspecified toolchain. try `multirust help run`'
fi
shift
run_in_environment "$@"
;;
upgrade-data) upgrade_data;;
delete-data) delete_data;;
which)
if [ -z "${2-}" ]; then
say_err 'USAGE: multirust which <tool-name>'
find_override_toolchain_or_default
if [ $? != 0 ]; then
err "failed to find possible suggestions for <tool-name> because no default toolchain was configured"
fi
local _toolchain="$RETVAL"
get_toolchain_dir "$_toolchain"
say_err " where <tool-name> can be one of: `ls -C \"$RETVAL/bin\"`"
say_err " defaulting to 'which rustc'"
which_for_environment rustc
else
which_for_environment "$2"
fi
;;
ctl)
case "${2-}" in
home)
echo "$multirust_dir"
;;
override-toolchain)
ctl_print_override_toolchain_or_default
;;
default-toolchain)
ctl_print_default_toolchain
;;
toolchain-sysroot)
if [ -z "${3-}" ]; then
err "unspecified toolchain"
fi
ctl_print_toolchain_sysroot "$3"
;;
"")
err 'empty ctl command. try `multirust help ctl`'
;;
*)
err "unrecognized ctl comand \`$2\`. try \`multirust help ctl\`"
;;
esac
;;
doc)
open_documentation "$@"
;;
help)
case "${2-}" in
"")
display_topic help
;;
*)
display_topic help-"${2-}"
if [ $? != 0 ]; then
display_topic help
exit 1
fi
;;
esac
;;
-V | --version)
echo "multirust $version ($commit_version)"
exit 0
;;
*)
display_topic help
;;
esac
}
# Run commands for --installer, --copy-local, --link-local
handle_common_install_args() {
local _else_cmd="$1"
local _cmd="$2"
local _toolchain_arg="${3-}"
if [ -z "$_toolchain_arg" ]; then
err "unspecified $_cmd toolchain. try \`multirust help $_cmd\`"
fi
local _option_name_arg="${4-}"
local _option_value_arg="${5-}"
verbose_say "cmd: $_cmd"
verbose_say "toolchain: $_toolchain_arg"
verbose_say "option_name: $_option_name_arg"
verbose_say "option_value: $_option_value_arg"
case "$_option_name_arg" in
--installer)
handle_install_option "$_cmd" "installer" \
update_custom_toolchain_from_installers \
"$_toolchain_arg" "$_option_value_arg"
;;
--copy-local)
handle_install_option "$_cmd" "toolchain path" \
update_custom_toolchain_from_dir \
"$_toolchain_arg" "$_option_value_arg"
;;
--link-local)
handle_install_option "$_cmd" "toolchain path" \
update_custom_toolchain_from_link \
"$_toolchain_arg" "$_option_value_arg"
;;
"")
"$_else_cmd" "$_toolchain_arg"
;;
*)
err "unrecognized option $_option_name_arg"
;;
esac
}
handle_install_option() {
local _cmd="$1"
local _what="$2"
local _update_cmd="$3"
local _toolchain="$4"
local _install_source_arg="$5"
if [ -z "$_install_source_arg" ]; then
err "unspecified $_what. try \`multirust help $_cmd\`"
fi
"$_update_cmd" "$_toolchain" "$_install_source_arg"
}
handle_update_toolchain() {
local _toolchain="$1"
update_toolchain "$1"
if [ $? != 0 ]; then
exit 1
fi
}
install_toolchain_if_not_installed() {
local _toolchain="$1"
is_toolchain_installed "$_toolchain"
if [ "$RETVAL" = true ]; then
say "using existing install for '$_toolchain'"
return 0
fi
handle_update_toolchain "$_toolchain"
}
update_all_channels() {
local _stable_ok=true
local _beta_ok=true
local _nightly_ok=true
update_toolchain stable
if [ $? != 0 ]; then
_stable_ok=false
fi
update_toolchain beta
if [ $? != 0 ]; then
_beta_ok=false
fi
update_toolchain nightly
if [ $? != 0 ]; then
_nightly_ok=false
fi
if [ "$_stable_ok" = true ]; then
say "'stable' update succeeded"
else
say_err "'stable' update FAILED"
fi
if [ "$_beta_ok" = true ]; then
say "'beta' update succeeded"
else
say_err "'beta' update FAILED"
fi
if [ "$_nightly_ok" = true ]; then
say "'nightly' update succeeded"
else
say_err "'nightly' update FAILED"
fi
say "stable revision:"
show_tool_versions "stable"
say "beta revision:"
show_tool_versions "beta"
say "nightly revision:"
show_tool_versions "nightly"
return 0
}
run_in_environment() {
local _toolchain="$1"
shift
if [ -z "${1-}" ]; then
err "command needed. see \`multirust help run\`"
fi
get_toolchain_dir "$_toolchain"
local _toolchain_dir="$RETVAL"
assert_nz "$_toolchain_dir" "toolchain dir"
export LD_LIBRARY_PATH="$_toolchain_dir/lib:${LD_LIBRARY_PATH-}"
export DYLD_LIBRARY_PATH="$_toolchain_dir/lib:${DYLD_LIBRARY_PATH-}"
export CARGO_HOME="$_toolchain_dir/cargo"
export MULTIRUST_TOOLCHAIN="$_toolchain"
export MULTIRUST_HOME="$multirust_dir"
exec "$@"
}
# Updating toolchains
update_toolchain() {
local _toolchain="$1"
is_toolchain_installed "$_toolchain"
local _is_installed="$RETVAL"
if [ "$_is_installed" = true ]; then
say "updating existing install for '$_toolchain'"
else
say "installing toolchain '$_toolchain'"
fi
install_toolchain_from_dist "$_toolchain"
}
install_toolchain_from_dist() {
local _toolchain="$1"
get_toolchain_dir "$_toolchain"
local _toolchain_dir="$RETVAL"
assert_nz "$_toolchain_dir" "toolchain dir"
local _update_hash_file="$update_hash_dir/$_toolchain"
mkdir -p "$update_hash_dir"
need_ok "failed to create update-hash directory"
verbose_say "toolchain dir is $_toolchain_dir"
call_rustup --prefix="$_toolchain_dir" --spec="$_toolchain" --update-hash-file="$_update_hash_file" --disable-ldconfig
}
install_toolchain() {
local _toolchain="$1"
local _installer="$2"
local _workdir="$3"
local _installer_dir="$_workdir/$(basename "$_installer" | sed s/.tar.gz$//)"
# Extract the toolchain
tar xzf "$_installer" -C "$_workdir"
if [ $? != 0 ]; then
verbose_say "failed to extract installer"
return 1
fi
# Install the toolchain
get_toolchain_dir "$_toolchain"
local _toolchain_dir="$RETVAL"
assert_nz "$_toolchain_dir" "toolchain dir"
verbose_say "installing toolchain to '$_toolchain_dir'"
say "installing toolchain for '$_toolchain'"
mkdir -p "$_toolchain_dir"
if [ $? != 0 ]; then
verbose_say "failed to create toolchain install dir"
return 1
fi
sh "$_installer_dir/install.sh" --prefix="$_toolchain_dir" --disable-ldconfig
if [ $? != 0 ]; then
rm -R "$_toolchain_dir"
verbose_say "failed to install toolchain"
return 1
fi
}
remove_toolchain() {
local _toolchain="$1"
local _toolchain_dir="$toolchains_dir/$_toolchain"
if [ -e "$_toolchain_dir" ]; then
verbose_say "removing directory '$_toolchain_dir'"
# Need to use -f because it contains Cargo's git directories
rm -Rf "$_toolchain_dir"
need_ok "failed to remove toolchain"
say "toolchain '$_toolchain' uninstalled"
else
say "no toolchain installed for '$_toolchain'"
fi
if [ -e "$update_hash_dir/$_toolchain" ]; then
rm "$update_hash_dir/$_toolchain"
need_ok "failed to remove update hash"
fi
}
is_toolchain_installed() {
local _toolchain="$1"
verbose_say "looking for installed toolchain '$_toolchain'"
get_toolchain_dir "$_toolchain"
local _toolchain_dir="$RETVAL"
assert_nz "$_toolchain_dir" "toolchain dir"
if [ -e "$_toolchain_dir" ]; then
RETVAL=true
return
fi
RETVAL=false
}
get_toolchain_dir() {
local _toolchain="$1"
if [ ! -e "$toolchains_dir" ]; then
verbose_say "creating toolchains dir '$toolchains_dir'"
mkdir -p "$toolchains_dir"
need_ok "failed to make toolchain dir"
fi
RETVAL="$toolchains_dir/$_toolchain"
}
list_available_targets() {
local _toolchain="$1"
get_toolchain_dir "$_toolchain"
local _dir="$RETVAL"
if [ ! -e "$_dir" ]; then
err "toolchain '$_toolchain' is not installed"
exit 1
fi
call_rustup --prefix="$_dir" --list-available-targets
if [ $? != 0 ]; then
exit 1
fi
}
add_target() {
local _toolchain="$1"
local _target="$2"
get_toolchain_dir "$_toolchain"
local _dir="$RETVAL"
if [ ! -e "$_dir" ]; then
err "toolchain '$_toolchain' is not installed"
exit 1
fi
call_rustup --prefix="$_dir" --add-target="$_target"
if [ $? != 0 ]; then
exit 1
fi
}
# Custom toolchain installation
update_custom_toolchain_from_dir() {
local _toolchain="$1"
local _custom_toolchain="$2"
update_custom_toolchain_from_dir_common "$_toolchain" "$_custom_toolchain" false
}
update_custom_toolchain_from_link() {
local _toolchain="$1"
local _custom_toolchain="$2"
update_custom_toolchain_from_dir_common "$_toolchain" "$_custom_toolchain" true
}
update_custom_toolchain_from_dir_common() {
local _toolchain="$1"
local _custom_toolchain="$2"
local _create_link="$3"
check_custom_toolchain_name "$_toolchain"
if [ ! -e "$_custom_toolchain" ]; then
err "specified path does not exist $_custom_toolchain"
fi
local _expected_rustc="$_custom_toolchain/bin/rustc"
if [ ! -e "$_expected_rustc" ]; then
err "no rustc in custom toolchain at '$_expected_rustc'"
fi
maybe_remove_existing_custom_toolchain "$_toolchain"
get_toolchain_dir "$_toolchain"
local _toolchain_dir="$RETVAL"
local _custom_toolchain_dir="$(abs_path $_custom_toolchain)"
if [ "$_create_link" = true ]; then
say "creating link from $_custom_toolchain_dir"
ln -s "$_custom_toolchain_dir" "$_toolchain_dir"
need_ok "failed to create link to toolchain"
else
say "copying from $_custom_toolchain_dir"
cp -R "$_custom_toolchain_dir" "$_toolchain_dir"
need_ok "failed to copy toolchain direcotry"
fi
}
update_custom_toolchain_from_installers() {
local _toolchain="$1"
local _installers="$2"
check_custom_toolchain_name "$_toolchain"
maybe_remove_existing_custom_toolchain "$_toolchain"
make_temp_dir
local _workdir="$RETVAL"
assert_nz "$_workdir" "workdir"
verbose_say "download work dir: $_workdir"
# Used for cleanup
get_toolchain_dir "$_toolchain"
local _toolchain_dir="$RETVAL"
assert_nz "$_toolchain_dir" "toolchain dir"
# Iterate through list of installers installing each
while [ -n "$_installers" ]; do
# Pull out the first installer
local _installer="$(echo "$_installers" | cut -f1 -d,)"
need_ok "failed to parse installer"
assert_nz "$_installer" "installer"
# Remove that installer from the list
local _next_installers="$(echo "$_installers" | sed s/[^,]*,//)"
need_ok "failed to shift installer list"
# If that was the last installer...
if [ "$_next_installers" = "$_installers" ]; then
_next_installers=""
fi
_installers="$_next_installers"
case "$_installer" in
*://*)
(cd "$_workdir" && curl -f -O "$_installer")
if [ $? != 0 ]; then
rm -R "$_workdir"
rm -Rf "$_toolchain_dir"
err "failed to download toolchain"
fi
local _local_installer="$_workdir/$(basename "$_installer")"
;;
*)
local _local_installer="$_installer"
;;
esac
install_toolchain "$_toolchain" "$_local_installer" "$_workdir"
if [ $? != 0 ]; then
rm -R "$_workdir"
rm -Rf "$_toolchain_dir"
err "failed to install toolchain"
fi
done
rm -R "$_workdir"
need_ok "failed to remomve work dir"
}
# When updating custom toolchains always blow away whatever already
# exists. If we don't do this then raw 'directory' toolchains that
# don't use the installer could end up breaking things.
maybe_remove_existing_custom_toolchain() {
local _toolchain="$1"
is_toolchain_installed "$_toolchain"
local _is_installed="$RETVAL"
if [ "$_is_installed" = true ]; then
say "removing existing toolchain before the update"
remove_toolchain "$_toolchain"
fi
}
check_custom_toolchain_name() {
local _toolchain="$1"
case "$_toolchain" in
nightly | beta | stable | \
nightly-20[0-9][0-9]-[0-9][0-9]-[0-9][0-9] | \
beta-20[0-9][0-9]-[0-9][0-9]-[0-9][0-9] | \
stable-20[0-9][0-9]-[0-9][0-9]-[0-9][0-9])
err "invalid custom toolchain name: '$_toolchain'"
;;
esac
}
# Default and override
find_override_toolchain_or_default() {
if find_override; then
RETVAL="$RETVAL_TOOLCHAIN"
return
fi
find_default || return 1
RETVAL="$RETVAL_TOOLCHAIN"
}
find_default() {
if [ ! -e "$default_file" ]; then
return 1
fi
local _default="$(cat "$default_file")"
assert_nz "$_default" "default file is empty"
get_toolchain_dir "$_default"
local _sysroot="$RETVAL"
assert_nz "$_sysroot" "sysroot"
if [ ! -e "$_sysroot" ]; then
err "toolchain '$_default' not installed. run \`multirust update $_default\` to install"
fi
RETVAL_TOOLCHAIN="$_default"
RETVAL_SYSROOT="$_sysroot"
}
find_override() {
if [ -n "${MULTIRUST_TOOLCHAIN-}" ]; then
RETVAL_REASON="environment override by MULTIRUST_TOOLCHAIN"
RETVAL_TOOLCHAIN="${MULTIRUST_TOOLCHAIN-}"
get_toolchain_dir "${MULTIRUST_TOOLCHAIN-}"
RETVAL_SYSROOT="$RETVAL"
if [ ! -e "$RETVAL_SYSROOT" ]; then
err "toolchain '${MULTIRUST_TOOLCHAIN-}' not installed. run \`multirust update ${MULTIRUST_TOOLCHAIN-}\` to install"
fi
return
fi
if [ ! -e "$override_db" ]; then
return 1
fi
local _dir="$(pwd -P)"
local _dir_unresolved="$(pwd)"
assert_nz "$_dir" "empty starting dir"
assert_nz "$_dir_unresolved" "empty starting dir"
# Go up the directory hierarchy looking for overrides
while [ "$_dir" != "/" -a "$_dir" != "." ]; do
while read _line; do
local _ovrdir="$(echo "$_line" | cut -d $delim -f1)"
need_ok "extracting record from db failed"
assert_nz "$_ovrdir" "empty dir in override db"
local _toolchain="$(echo "$_line" | cut -d $delim -f2)"
need_ok "extracting record from db failed"
assert_nz "$_toolchain" "empty toolchain in override db"
# Issue #40: Resolve symlinks with `pwd -P` before comparing directories.
# This conversion is *also* done when adding the override directory to
# the override DB. It is only done here to be compatible with older
# multirust installations from before this bug was fixed.
local _ovrdir="$(cd "$_ovrdir" 2>/dev/null && pwd -P)"
# NB: The above may fail, e.g. if _ovrdir no longer exists.
# This is fine since it will just make the next comparision fail as well.
if [ "$_dir" = "$_ovrdir" ]; then
RETVAL_REASON="directory override for '$_dir_unresolved'"
RETVAL_TOOLCHAIN="$_toolchain"
get_toolchain_dir "$_toolchain"
RETVAL_SYSROOT="$RETVAL"
if [ ! -e "$RETVAL_SYSROOT" ]; then
err "toolchain '$_toolchain' not installed. run \`multirust update $_toolchain\` to install"
fi
return
fi
done < "$override_db"
local _dir="$(dirname "$_dir")"
done
return 1
}
set_default() {
local _toolchain="$1"
make_temp
local _workfile="$RETVAL"
assert_nz "$_workfile" "workfile"
echo "$_toolchain" > "$_workfile"
if [ $? != 0 ]; then
rm -R "$_workfile"
err "couldn't write default toolchain to tempfile"
fi
mv -f "$_workfile" "$default_file"
if [ $? != 0 ]; then
rm -R "$_workfile"
err "couldn't set default toolchain"
fi
say "default toolchain set to '$_toolchain'"
}
set_override() {
local _toolchain="$1"
# Issue #40: Resolve symlinks in overrides with `pwd -P`
local _override_dir="$(pwd -P)"
assert_nz "$_override_dir" "empty pwd?"
# Escape forward-slashes
local _escaped_override_dir=`echo "$_override_dir" | sed s/\\\//\\\\\\\\\\\//g`
make_temp
local _workfile="$RETVAL"
assert_nz "$_workfile" "workfile"
# Copy the current db to a new file, removing any existing override
if [ -e "$override_db" ]; then
# Escape the tab because OS X sed won't
sed "/^$_escaped_override_dir$delim/d" "$override_db" > "$_workfile"
if [ $? != 0 ]; then
rm -R "$_workfile"
err "unable to edit override db"
fi
fi
# Append the new override
echo "$_override_dir$delim$_toolchain" >> "$_workfile"
if [ $? != 0 ]; then
rm -R "$_workfile"
err "unable to edit override db"
fi
# Move it back to the database
mv -f "$_workfile" "$override_db"
need_ok "unable to edit override db"
say "override toolchain for '$_override_dir' set to '$_toolchain'"
}
remove_override() {
local _override_dir="$1"
assert_nz "$_override_dir" "empty pwd?"
# Escape forward-slashes
local _escaped_override_dir=`echo "$_override_dir" | sed s/\\\//\\\\\\\\\\\//g`
make_temp
local _workfile="$RETVAL"
assert_nz "$_workfile" "workfile"
# Check if the override exists
local _have_override=false
if [ -e "$override_db" ]; then
# Get an actual tab character because grep doesn't interpret \t
egrep "^$_escaped_override_dir$delim" "$override_db" > /dev/null
if [ $? = 0 ]; then
local _have_override=true
fi
fi
if [ $_have_override = false ]; then
say "no override for directory '$_override_dir'"
return
fi
# Copy the current db to a new file, removing any existing override
if [ -e "$override_db" ]; then
sed "/^$_escaped_override_dir$delim/d" "$override_db" > "$_workfile"
if [ $? != 0 ]; then
rm -R "$_workfile"
err "unable to edit override db"
fi
fi
# Move it back to the database
mv -f "$_workfile" "$override_db"
need_ok "unable to edit override db"
say "override toolchain for '$_override_dir' removed"
}
# Reporting
show_default() {
if find_default; then
local _toolchain="$RETVAL_TOOLCHAIN"
local _sysroot="$RETVAL_SYSROOT"
say "default toolchain: $_toolchain"
say "default location: $_sysroot"
show_tool_versions "$_toolchain"
else
say 'no default toolchain configured. run `multirust help default`'
fi
}
show_override() {
if find_override; then
local _reason="$RETVAL_REASON"
local _toolchain="$RETVAL_TOOLCHAIN"
local _sysroot="$RETVAL_SYSROOT"
say "override toolchain: $_toolchain"
say "override location: $_sysroot"
say "override reason: $_reason"
show_tool_versions "$_toolchain"
else
say "no override"
show_default
fi
}
show_toolchain() {
local _toolchain=
if find_override; then
_toolchain="$RETVAL_TOOLCHAIN"
elif find_default; then
_toolchain="$RETVAL_TOOLCHAIN"
else
_toolchain="No default"
fi
echo "$_toolchain"
}
show_tool_versions() {
local _toolchain="$1"
echo
ensure is_toolchain_installed "$_toolchain"
local _have_toolchain="$RETVAL"
if [ "$_have_toolchain" = true ]; then
get_toolchain_dir "$_toolchain"
local _toolchain_dir="$RETVAL"
local _rustc_path="$_toolchain_dir/bin/rustc"
local _cargo_path="$_toolchain_dir/bin/cargo"
push_toolchain_ldpath "$_toolchain"
if [ -e "$_rustc_path" ]; then
"$_rustc_path" --version
else
echo "(no rustc command in toolchain?)"
fi
if [ -e "$_cargo_path" ]; then
"$_cargo_path" --version
else
echo "(no cargo command in toolchain)"
fi
pop_toolchain_ldpath
else
echo "(toolchain not installed)"
fi
echo
}
list_overrides() {
if [ -e "$override_db" ]; then
local _overrides="$(cat "$override_db" | sort)"
if [ -n "$_overrides" ]; then
echo "$_overrides"
else
say "no overrides"
fi
else
say "no overrides"
fi
}
list_toolchains() {
if [ -e "$toolchains_dir" ]; then
local _toolchains="$(cd "$toolchains_dir" && ls | sort)"
if [ -n "$_toolchains" ]; then
echo "$_toolchains"
else
say "no installed toolchains"
fi
else
say "no installed toolchains"
fi
}
# Open documentation
open_documentation() {
local _cmd
if has_cmd "xdg-open"; then
_cmd="xdg-open"
elif has_cmd "open"; then
_cmd="open"
elif has_cmd "firefox"; then
_cmd="firefox"
elif has_cmd "chromium"; then
_cmd="chromium"
else
err "Need xdg-open, open, firefox, or chromium"
fi
find_override_toolchain_or_default
local _toolchain="$RETVAL"
get_toolchain_dir "$_toolchain"
local _current_toolchain_path="$RETVAL"
local _doc_path="${_current_toolchain_path}/share/doc/rust/html/std/index.html"
case "${2-}" in
--all)
_doc_path="${_current_toolchain_path}/share/doc/rust/html/index.html"
;;
"") ;;
*)
err "unrecognized doc option \`$2\`. try \`multirust help doc\`"
;;
esac
"$_cmd" "$_doc_path" > /dev/null 2> /dev/null &
}
which_for_environment() {
local _cmd="$1"
find_override_toolchain_or_default
if [ $? != 0 ]; then
err "no default toolchain configured"
fi
local _toolchain="$RETVAL"
get_toolchain_dir "$_toolchain"
local _bin_dir="$RETVAL/bin"
local _cmd_fullpath="$_bin_dir/$_cmd"
if [ -f "$_cmd_fullpath" ]; then
echo "$_cmd_fullpath"
else
err "command \"$_cmd\" does not exist"
fi
}
# Management of data in the MULTIRUST_HOME directory
# Verifies that ~/.multirust exists and uses the correct format
check_metadata_version() {
verbose_say "checking metadata version"
test -e "$multirust_dir"
need_ok "multirust_dir must exist"
if [ ! -e "$version_file" ]; then
verbose_say "writing metadata version $metadata_version"
echo "$metadata_version" > "$version_file"
need_ok "failed to write metadata version"
else
local _current_version="$(cat "$version_file")"
verbose_say "got metadata version $_current_version"
if [ "$_current_version" != "$metadata_version" ]; then
err "metadata version is $_current_version, need $metadata_version. run \`multirust upgrade-data\`"
fi
fi
}
upgrade_data() {
if [ ! -e "$version_file" ]; then
say "no need to upgrade. $multirust_dir does not exist"
return
fi
local _current_version="$(cat "$version_file")"
say "upgrading metadata from version $_current_version to $metadata_version"
case "$_current_version" in
2)
# Current version. Do nothing
say "metadata is updated to version $_current_version"
;;
1)
# Ignore errors. These files may not exist.
rm "$multirust_dir/available-updates" > /dev/null 2>&1
rm "$multirust_dir/update-stamp" > /dev/null 2>&1
rm -R "$multirust_dir/channel-sums" > /dev/null 2>&1
rm -R "$multirust_dir/manifests" > /dev/null 2>&1
echo "$metadata_version" > "$version_file"
need_ok "failed to write metadata version"
;;
*)
err "unknown metadata version: $_current_version"
;;
esac
say "success"
}
delete_data() {
if [ ! "$flag_yes" = true ]; then
read -p "This will delete all toolchains, overrides, aliases, and other multirust data associated with this user. Continue? (y/n) " yn
echo
case "$yn" in
[Yy])
# Do nothing
;;
*)
say "aborting"
exit 0
;;
esac
fi
# Need -f for Cargo's write-protected git directories
rm -Rf "$multirust_dir"
need_ok "failed to delete '$multirust_dir'"
say "deleted $multirust_dir"
}
# The multirustproxy control interface
ctl_print_override_toolchain_or_default() {
find_override_toolchain_or_default
if [ $? != 0 ]; then
err "no default toolchain configured"
fi
echo "$RETVAL"
}
ctl_print_default_toolchain() {
find_default
if [ $? != 0 ]; then
err "no default toolchain configured"
fi
echo "$RETVAL_TOOLCHAIN"
}
ctl_print_toolchain_sysroot() {
local _toolchain="$1"
get_toolchain_dir "$_toolchain"
echo "$RETVAL"
}
# Tools
call_rustup() {
assert_nz "$RUSTUP_HOME" "RUSTUP_HOME"
"$cmd_dirname/rustup.sh" "$@" -y --disable-sudo
}
make_temp_name() {
local _pid="$$"
assert_nz "$_pid" "pid"
local _tmp_number="${NEXT_TMP_NUMBER-0}"
local _tmp_name="tmp-$_pid-$_tmp_number"
NEXT_TMP_NUMBER="$(expr "$_tmp_number" + 1)"
assert_nz "$NEXT_TMP_NUMBER" "NEXT_TMP_NUMBER"
RETVAL="$_tmp_name"
}
make_temp() {
mkdir -p "$temp_dir"
need_ok "failed to make temp dir '$temp_dir'"
make_temp_name
local _tmp_name="$temp_dir/$RETVAL"
touch "$_tmp_name"
need_ok "couldn't make temp file '$_tmp_name'"
RETVAL="$_tmp_name"
}
make_temp_dir() {
mkdir -p "$temp_dir"
need_ok "failed to make temp dir '$temp_dir'"
make_temp_name
local _tmp_name="$temp_dir/$RETVAL"
mkdir -p "$_tmp_name"
need_ok "couldn't make temp dir '$_tmp_name'"
RETVAL="$_tmp_name"
}
push_toolchain_ldpath() {
local _toolchain="$1"
get_toolchain_dir "$_toolchain"
local _toolchain_dir="$RETVAL"
local _new_path="$_toolchain_dir/lib"
OLD_LD_LIBRARY_PATH="${LD_LIBRARY_PATH-}"
LD_LIBRARY_PATH="$_new_path:${LD_LIBRARY_PATH-}"
export LD_LIBRARY_PATH
OLD_DYLD_LIBRARY_PATH="${DYLD_LIBRARY_PATH-}"
DYLD_LIBRARY_PATH="$_new_path:${DYLD_LIBRARY_PATH-}"
export DYLD_LIBRARY_PATH
}
pop_toolchain_ldpath() {
LD_LIBRARY_PATH="$OLD_LD_LIBRARY_PATH"
export LD_LIBRARY_PATH
DYLD_LIBRARY_PATH="$OLD_DYLD_LIBRARY_PATH"
export DYLD_LIBRARY_PATH
}
# The help system
display_topic() {
local _topic="$1"
local _multirust_src="$cmd_dirname/multirust"
extract_topic_from_source "$_multirust_src" "$_topic"
ret=$?
if [ $ret != 0 ]; then
say_err "unrecognized topic '$_topic'"
return $ret
fi
return 0
}
extract_topic_from_source() {
local _source="$1"
local _topic="$2"
local _tagged_docs="$(awk "/<$_topic>/,/<\/$_topic>/" "$_source")"
local _docs="$(echo "$_tagged_docs" | sed '1d' | sed '1d' | sed '$d' | sed 's/^\# \?//')"
echo "$_docs"
if [ $? != 0 ]; then
return $?
fi
if [ -z "$_docs" ]; then
return 1
fi
return 0
}
# Standard utilities
say() {
echo "multirust: $1"
}
say_err() {
say "$1" >&2
}
verbose_say() {
if [ "$flag_verbose" = true ]; then
say "$1"
fi
}
err() {
say "$1" >&2
exit 1
}
has_cmd() {
command -v $1 > /dev/null 2>&1
}
need_cmd() {
if ! has_cmd $1; then
err "need $1"
fi
}
need_ok() {
if [ $? != 0 ]; then
err "$1"
fi
}
assert_nz() {
if [ -z "$1" ]; then
err "assert_nz $2"
fi
}
# Run a command that should never fail. If the command fails execution
# will immediately terminate with an error showing the failing
# command.
ensure() {
"$@"
need_ok "command failed: $*"
}
# This is just for indicating that commands' results are being
# intentionally ignored. Usually, because it's being executed
# as part of error handling.
ignore() {
run "$@"
}
# Runs a command and prints it to stderr if it fails.
run() {
"$@"
local _retval=$?
if [ $_retval != 0 ]; then
say_err "command failed: $*"
fi
return $_retval
}
# Prints the absolute path of a directory to stdout
abs_path() {
local _path="$1"
# Unset CDPATH because it causes havok: it makes the destination unpredictable
# and triggers 'cd' to print the path to stdout. Route `cd`'s output to /dev/null
# for good measure.
(unset CDPATH && cd "$_path" > /dev/null && pwd)
}
# Ensure various commands exist
need_cmd dirname
need_cmd basename
need_cmd mkdir
need_cmd cat
need_cmd curl
need_cmd rm
need_cmd egrep
need_cmd grep
need_cmd file
need_cmd uname
need_cmd tar
need_cmd sed
need_cmd sh
need_cmd mv
need_cmd awk
need_cmd cut
need_cmd sort
need_cmd date
need_cmd head
main "$@"
You can’t perform that action at this time.