Permalink
Cannot retrieve contributors at this time
Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign up
Fetching contributors…
| #!/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 "$@" |