1#!/usr/bin/env bash 2 3# No undefined variables 4set -u 5 6init_logging() { 7 local _abs_libdir="$1" 8 local _logfile="$_abs_libdir/$TEMPLATE_REL_MANIFEST_DIR/install.log" 9 rm -f "$_logfile" 10 need_ok "failed to remove old installation log" 11 touch "$_logfile" 12 need_ok "failed to create installation log" 13 LOGFILE="$_logfile" 14} 15 16log_line() { 17 local _line="$1" 18 19 if [ -n "${LOGFILE-}" -a -e "${LOGFILE-}" ]; then 20 echo "$_line" >> "$LOGFILE" 21 # Ignore errors, which may happen e.g. after the manifest dir is deleted 22 fi 23} 24 25msg() { 26 local _line="install: ${1-}" 27 echo "$_line" 28 log_line "$_line" 29} 30 31verbose_msg() { 32 if [ -n "${CFG_VERBOSE-}" ]; then 33 msg "${1-}" 34 else 35 log_line "install: ${1-}" 36 fi 37} 38 39step_msg() { 40 msg 41 msg "$1" 42 msg 43} 44 45verbose_step_msg() { 46 if [ -n "${CFG_VERBOSE-}" ]; then 47 msg 48 msg "$1" 49 msg 50 else 51 log_line "" 52 log_line "install: $1" 53 log_line "" 54 fi 55} 56 57warn() { 58 local _line="install: WARNING: $1" 59 echo "$_line" >&2 60 log_line "$_line" 61} 62 63err() { 64 local _line="install: error: $1" 65 echo "$_line" >&2 66 log_line "$_line" 67 exit 1 68} 69 70# A non-user error that is likely to result in a corrupted install 71critical_err() { 72 local _line="install: error: $1. see logs at '${LOGFILE-}'" 73 echo "$_line" >&2 74 log_line "$_line" 75 exit 1 76} 77 78need_ok() { 79 if [ $? -ne 0 ] 80 then 81 err "$1" 82 fi 83} 84 85critical_need_ok() { 86 if [ $? -ne 0 ] 87 then 88 critical_err "$1" 89 fi 90} 91 92want_ok() { 93 if [ $? -ne 0 ]; then 94 warn "$1" 95 fi 96} 97 98assert_nz() { 99 if [ -z "$1" ]; then err "assert_nz $2"; fi 100} 101 102need_cmd() { 103 if command -v $1 >/dev/null 2>&1 104 then verbose_msg "found $1" 105 else err "need $1" 106 fi 107} 108 109run() { 110 local _line="\$ $*" 111 "$@" 112 local _retval=$? 113 log_line "$_line" 114 return $_retval 115} 116 117write_to_file() { 118 local _msg="$1" 119 local _file="$2" 120 local _line="$ echo \"$_msg\" > \"$_file\"" 121 echo "$_msg" > "$_file" 122 local _retval=$? 123 log_line "$_line" 124 return $_retval 125} 126 127append_to_file() { 128 local _msg="$1" 129 local _file="$2" 130 local _line="$ echo \"$_msg\" >> \"$_file\"" 131 echo "$_msg" >> "$_file" 132 local _retval=$? 133 log_line "$_line" 134 return $_retval 135} 136 137make_dir_recursive() { 138 local _dir="$1" 139 local _line="$ umask 022 && mkdir -p \"$_dir\"" 140 umask 022 && mkdir -p "$_dir" 141 local _retval=$? 142 log_line "$_line" 143 return $_retval 144} 145 146putvar() { 147 local t 148 local tlen 149 eval t=\$$1 150 eval tlen=\${#$1} 151} 152 153valopt() { 154 VAL_OPTIONS="$VAL_OPTIONS $1" 155 156 local op=$1 157 local default=$2 158 shift 159 shift 160 local doc="$*" 161 if [ $HELP -eq 0 ] 162 then 163 local uop=$(echo $op | tr 'a-z-' 'A-Z_') 164 local v="CFG_${uop}" 165 eval $v="$default" 166 for arg in $CFG_ARGS 167 do 168 if echo "$arg" | grep -q -- "--$op=" 169 then 170 local val=$(echo "$arg" | cut -f2 -d=) 171 eval $v=$val 172 fi 173 done 174 putvar $v 175 else 176 if [ -z "$default" ] 177 then 178 default="<none>" 179 fi 180 op="${op}=[${default}]" 181 printf " --%-30s %s\n" "$op" "$doc" 182 fi 183} 184 185opt() { 186 BOOL_OPTIONS="$BOOL_OPTIONS $1" 187 188 local op=$1 189 local default=$2 190 shift 191 shift 192 local doc="$*" 193 local flag="" 194 195 if [ $default -eq 0 ] 196 then 197 flag="enable" 198 else 199 flag="disable" 200 doc="don't $doc" 201 fi 202 203 if [ $HELP -eq 0 ] 204 then 205 for arg in $CFG_ARGS 206 do 207 if [ "$arg" = "--${flag}-${op}" ] 208 then 209 op=$(echo $op | tr 'a-z-' 'A-Z_') 210 flag=$(echo $flag | tr 'a-z' 'A-Z') 211 local v="CFG_${flag}_${op}" 212 eval $v=1 213 putvar $v 214 fi 215 done 216 else 217 if [ ! -z "${META-}" ] 218 then 219 op="$op=<$META>" 220 fi 221 printf " --%-30s %s\n" "$flag-$op" "$doc" 222 fi 223} 224 225flag() { 226 BOOL_OPTIONS="$BOOL_OPTIONS $1" 227 228 local op=$1 229 shift 230 local doc="$*" 231 232 if [ $HELP -eq 0 ] 233 then 234 for arg in $CFG_ARGS 235 do 236 if [ "$arg" = "--${op}" ] 237 then 238 op=$(echo $op | tr 'a-z-' 'A-Z_') 239 local v="CFG_${op}" 240 eval $v=1 241 putvar $v 242 fi 243 done 244 else 245 if [ ! -z "${META-}" ] 246 then 247 op="$op=<$META>" 248 fi 249 printf " --%-30s %s\n" "$op" "$doc" 250 fi 251} 252 253validate_opt () { 254 for arg in $CFG_ARGS 255 do 256 local is_arg_valid=0 257 for option in $BOOL_OPTIONS 258 do 259 if test --disable-$option = $arg 260 then 261 is_arg_valid=1 262 fi 263 if test --enable-$option = $arg 264 then 265 is_arg_valid=1 266 fi 267 if test --$option = $arg 268 then 269 is_arg_valid=1 270 fi 271 done 272 for option in $VAL_OPTIONS 273 do 274 if echo "$arg" | grep -q -- "--$option=" 275 then 276 is_arg_valid=1 277 fi 278 done 279 if [ "$arg" = "--help" ] 280 then 281 echo 282 echo "No more help available for Configure options," 283 echo "check the Wiki or join our IRC channel" 284 break 285 else 286 if test $is_arg_valid -eq 0 287 then 288 err "Option '$arg' is not recognized" 289 fi 290 fi 291 done 292} 293 294absolutify() { 295 local file_path="$1" 296 local file_path_dirname="$(dirname "$file_path")" 297 local file_path_basename="$(basename "$file_path")" 298 local file_abs_path="$(abs_path "$file_path_dirname")" 299 local file_path="$file_abs_path/$file_path_basename" 300 # This is the return value 301 RETVAL="$file_path" 302} 303 304# Prints the absolute path of a directory to stdout 305abs_path() { 306 local path="$1" 307 # Unset CDPATH because it causes havok: it makes the destination unpredictable 308 # and triggers 'cd' to print the path to stdout. Route `cd`'s output to /dev/null 309 # for good measure. 310 (unset CDPATH && cd "$path" > /dev/null && pwd) 311} 312 313uninstall_legacy() { 314 local _abs_libdir="$1" 315 316 local _uninstalled_something=false 317 318 # Replace commas in legacy manifest list with spaces 319 _legacy_manifest_dirs=`echo "$TEMPLATE_LEGACY_MANIFEST_DIRS" | sed "s/,/ /g"` 320 321 # Uninstall from legacy manifests 322 local _md 323 for _md in $_legacy_manifest_dirs; do 324 # First, uninstall from the installation prefix. 325 # Errors are warnings - try to rm everything in the manifest even if some fail. 326 if [ -f "$_abs_libdir/$_md/manifest" ] 327 then 328 329 # iterate through installed manifest and remove files 330 local _p; 331 while read _p; do 332 # the installed manifest contains absolute paths 333 msg "removing legacy file $_p" 334 if [ -f "$_p" ] 335 then 336 run rm -f "$_p" 337 want_ok "failed to remove $_p" 338 else 339 warn "supposedly installed file $_p does not exist!" 340 fi 341 done < "$_abs_libdir/$_md/manifest" 342 343 # If we fail to remove $md below, then the 344 # installed manifest will still be full; the installed manifest 345 # needs to be empty before install. 346 msg "removing legacy manifest $_abs_libdir/$_md/manifest" 347 run rm -f "$_abs_libdir/$_md/manifest" 348 # For the above reason, this is a hard error 349 need_ok "failed to remove installed manifest" 350 351 # Remove $template_rel_manifest_dir directory 352 msg "removing legacy manifest dir $_abs_libdir/$_md" 353 run rm -R "$_abs_libdir/$_md" 354 want_ok "failed to remove $_md" 355 356 _uninstalled_something=true 357 fi 358 done 359 360 RETVAL="$_uninstalled_something" 361} 362 363uninstall_components() { 364 local _abs_libdir="$1" 365 local _dest_prefix="$2" 366 local _components="$3" 367 368 # We're going to start by uninstalling existing components. This 369 local _uninstalled_something=false 370 371 # First, try removing any 'legacy' manifests from before 372 # rust-installer 373 uninstall_legacy "$_abs_libdir" 374 assert_nz "$RETVAL", "RETVAL" 375 if [ "$RETVAL" = true ]; then 376 _uninstalled_something=true; 377 fi 378 379 # Load the version of the installed installer 380 local _installed_version= 381 if [ -f "$abs_libdir/$TEMPLATE_REL_MANIFEST_DIR/rust-installer-version" ]; then 382 _installed_version=`cat "$_abs_libdir/$TEMPLATE_REL_MANIFEST_DIR/rust-installer-version"` 383 384 # Sanity check 385 if [ ! -n "$_installed_version" ]; then critical_err "rust installer version is empty"; fi 386 fi 387 388 # If there's something installed, then uninstall 389 if [ -n "$_installed_version" ]; then 390 # Check the version of the installed installer 391 case "$_installed_version" in 392 393 # If this is a previous version, then upgrade in place to the 394 # current version before uninstalling. 395 2 ) 396 # The only change between version 2 -> 3 is that components are placed 397 # in subdirectories of the installer tarball. There are no changes 398 # to the installed data format, so nothing to do. 399 ;; 400 401 # This is the current version. Nothing need to be done except uninstall. 402 "$TEMPLATE_RUST_INSTALLER_VERSION") 403 ;; 404 405 # If this is an unknown (future) version then bail. 406 * ) 407 echo "The copy of $TEMPLATE_PRODUCT_NAME at $_dest_prefix was installed using an" 408 echo "unknown version ($_installed_version) of rust-installer." 409 echo "Uninstall it first with the installer used for the original installation" 410 echo "before continuing." 411 exit 1 412 ;; 413 esac 414 415 local _md="$_abs_libdir/$TEMPLATE_REL_MANIFEST_DIR" 416 local _installed_components="$(cat "$_md/components")" 417 418 # Uninstall (our components only) before reinstalling 419 local _available_component 420 for _available_component in $_components; do 421 local _installed_component 422 for _installed_component in $_installed_components; do 423 if [ "$_available_component" = "$_installed_component" ]; then 424 msg "uninstalling component '$_available_component'" 425 local _component_manifest="$_md/manifest-$_installed_component" 426 427 # Sanity check: there should be a component manifest 428 if [ ! -f "$_component_manifest" ]; then 429 critical_err "installed component '$_installed_component' has no manifest" 430 fi 431 432 # Iterate through installed component manifest and remove files 433 local _directive 434 while read _directive; do 435 436 local _command=`echo $_directive | cut -f1 -d:` 437 local _file=`echo $_directive | cut -f2 -d:` 438 439 # Sanity checks 440 if [ ! -n "$_command" ]; then critical_err "malformed installation directive"; fi 441 if [ ! -n "$_file" ]; then critical_err "malformed installation directive"; fi 442 443 case "$_command" in 444 file) 445 verbose_msg "removing file $_file" 446 if [ -f "$_file" ]; then 447 run rm -f "$_file" 448 want_ok "failed to remove $_file" 449 else 450 warn "supposedly installed file $_file does not exist!" 451 fi 452 ;; 453 454 dir) 455 verbose_msg "removing directory $_file" 456 run rm -r "$_file" 457 want_ok "unable to remove directory $_file" 458 ;; 459 460 *) 461 critical_err "unknown installation directive" 462 ;; 463 esac 464 465 done < "$_component_manifest" 466 467 # Remove the installed component manifest 468 verbose_msg "removing component manifest $_component_manifest" 469 run rm "$_component_manifest" 470 # This is a hard error because the installation is unrecoverable 471 local _err_cant_r_manifest="failed to remove installed manifest for component" 472 critical_need_ok "$_err_cant_r_manifest '$_installed_component'" 473 474 # Update the installed component list 475 local _modified_components="$(sed "/^$_installed_component\$/d" "$_md/components")" 476 write_to_file "$_modified_components" "$_md/components" 477 critical_need_ok "failed to update installed component list" 478 fi 479 done 480 done 481 482 # If there are no remaining components delete the manifest directory, 483 # but only if we're doing an uninstall - if we're doing an install, 484 # then leave the manifest directory around to hang onto the logs, 485 # and any files not managed by the installer. 486 if [ -n "${CFG_UNINSTALL-}" ]; then 487 local _remaining_components="$(cat "$_md/components")" 488 if [ ! -n "$_remaining_components" ]; then 489 verbose_msg "removing manifest directory $_md" 490 run rm -r "$_md" 491 want_ok "failed to remove $_md" 492 493 maybe_unconfigure_ld 494 fi 495 fi 496 497 _uninstalled_something=true 498 fi 499 500 # There's no installed version. If we were asked to uninstall, then that's a problem. 501 if [ -n "${CFG_UNINSTALL-}" -a "$_uninstalled_something" = false ] 502 then 503 err "unable to find installation manifest at $CFG_LIBDIR/$TEMPLATE_REL_MANIFEST_DIR" 504 fi 505} 506 507install_components() { 508 local _src_dir="$1" 509 local _abs_libdir="$2" 510 local _dest_prefix="$3" 511 local _components="$4" 512 513 local _component 514 for _component in $_components; do 515 516 msg "installing component '$_component'" 517 518 # The file name of the manifest we're installing from 519 local _input_manifest="$_src_dir/$_component/manifest.in" 520 521 # Sanity check: do we have our input manifests? 522 if [ ! -f "$_input_manifest" ]; then 523 critical_err "manifest for $_component does not exist at $_input_manifest" 524 fi 525 526 # The installed manifest directory 527 local _md="$_abs_libdir/$TEMPLATE_REL_MANIFEST_DIR" 528 529 # The file name of the manifest we're going to create during install 530 local _installed_manifest="$_md/manifest-$_component" 531 532 # Create the installed manifest, which we will fill in with absolute file paths 533 touch "$_installed_manifest" 534 critical_need_ok "failed to create installed manifest" 535 536 # Add this component to the installed component list 537 append_to_file "$_component" "$_md/components" 538 critical_need_ok "failed to update components list for $_component" 539 540 # Now install, iterate through the new manifest and copy files 541 local _directive 542 while read _directive; do 543 544 local _command=`echo $_directive | cut -f1 -d:` 545 local _file=`echo $_directive | cut -f2 -d:` 546 547 # Sanity checks 548 if [ ! -n "$_command" ]; then critical_err "malformed installation directive"; fi 549 if [ ! -n "$_file" ]; then critical_err "malformed installation directive"; fi 550 551 # Decide the destination of the file 552 local _file_install_path="$_dest_prefix/$_file" 553 554 if echo "$_file" | grep "^etc/" > /dev/null 555 then 556 local _f="$(echo "$_file" | sed 's/^etc\///')" 557 _file_install_path="$CFG_SYSCONFDIR/$_f" 558 fi 559 560 if echo "$_file" | grep "^bin/" > /dev/null 561 then 562 local _f="$(echo "$_file" | sed 's/^bin\///')" 563 _file_install_path="$CFG_BINDIR/$_f" 564 fi 565 566 if echo "$_file" | grep "^lib/" > /dev/null 567 then 568 local _f="$(echo "$_file" | sed 's/^lib\///')" 569 _file_install_path="$CFG_LIBDIR/$_f" 570 fi 571 572 if echo "$_file" | grep "^share" > /dev/null 573 then 574 local _f="$(echo "$_file" | sed 's/^share\///')" 575 _file_install_path="$CFG_DATADIR/$_f" 576 fi 577 578 if echo "$_file" | grep "^share/man/" > /dev/null 579 then 580 local _f="$(echo "$_file" | sed 's/^share\/man\///')" 581 _file_install_path="$CFG_MANDIR/$_f" 582 fi 583 584 # HACK: Try to support overriding --docdir. Paths with the form 585 # "share/doc/$product/" can be redirected to a single --docdir 586 # path. If the following detects that --docdir has been specified 587 # then it will replace everything preceeding the "$product" path 588 # component. The problem here is that the combined rust installer 589 # contains two "products": rust and cargo; so the contents of those 590 # directories will both be dumped into the same directory; and the 591 # contents of those directories are _not_ disjoint. Since this feature 592 # is almost entirely to support 'make install' anyway I don't expect 593 # this problem to be a big deal in practice. 594 if [ "$CFG_DOCDIR" != "<default>" ] 595 then 596 if echo "$_file" | grep "^share/doc/" > /dev/null 597 then 598 local _f="$(echo "$_file" | sed 's/^share\/doc\/[^/]*\///')" 599 _file_install_path="$CFG_DOCDIR/$_f" 600 fi 601 fi 602 603 # Make sure there's a directory for it 604 make_dir_recursive "$(dirname "$_file_install_path")" 605 critical_need_ok "directory creation failed" 606 607 # Make the path absolute so we can uninstall it later without 608 # starting from the installation cwd 609 absolutify "$_file_install_path" 610 _file_install_path="$RETVAL" 611 assert_nz "$_file_install_path" "file_install_path" 612 613 case "$_command" in 614 file ) 615 616 verbose_msg "copying file $_file_install_path" 617 618 maybe_backup_path "$_file_install_path" 619 620 if echo "$_file" | grep "^bin/" > /dev/null || test -x "$_src_dir/$_component/$_file" 621 then 622 run cp "$_src_dir/$_component/$_file" "$_file_install_path" 623 run chmod 755 "$_file_install_path" 624 else 625 run cp "$_src_dir/$_component/$_file" "$_file_install_path" 626 run chmod 644 "$_file_install_path" 627 fi 628 critical_need_ok "file creation failed" 629 630 # Update the manifest 631 append_to_file "file:$_file_install_path" "$_installed_manifest" 632 critical_need_ok "failed to update manifest" 633 634 ;; 635 636 dir ) 637 638 verbose_msg "copying directory $_file_install_path" 639 640 maybe_backup_path "$_file_install_path" 641 642 run cp -R "$_src_dir/$_component/$_file" "$_file_install_path" 643 critical_need_ok "failed to copy directory" 644 645 # Set permissions. 0755 for dirs, 644 for files 646 run chmod -R u+rwX,go+rX,go-w "$_file_install_path" 647 critical_need_ok "failed to set permissions on directory" 648 649 # Update the manifest 650 append_to_file "dir:$_file_install_path" "$_installed_manifest" 651 critical_need_ok "failed to update manifest" 652 ;; 653 654 *) 655 critical_err "unknown installation directive" 656 ;; 657 esac 658 done < "$_input_manifest" 659 660 done 661} 662 663maybe_configure_ld() { 664 local _abs_libdir="$1" 665 666 local _ostype="$(uname -s)" 667 assert_nz "$_ostype" "ostype" 668 669 if [ "$_ostype" = "Linux" -a ! -n "${CFG_DISABLE_LDCONFIG-}" ]; then 670 671 # Fedora-based systems do not configure the dynamic linker to look 672 # /usr/local/lib, which is our default installation directory. To 673 # make things just work, try to put that directory in 674 # /etc/ld.so.conf.d/rust-installer-v1 so ldconfig picks it up. 675 # Issue #30. 676 # 677 # This will get rm'd when the last component is uninstalled in 678 # maybe_unconfigure_ld. 679 if [ "$_abs_libdir" = "/usr/local/lib" -a -d "/etc/ld.so.conf.d" ]; then 680 echo "$_abs_libdir" > "/etc/ld.so.conf.d/rust-installer-v1-$TEMPLATE_REL_MANIFEST_DIR.conf" 681 if [ $? -ne 0 ]; then 682 # This shouldn't happen if we've gotten this far 683 # installing to /usr/local 684 warn "failed to update /etc/ld.so.conf.d. this is unexpected" 685 fi 686 fi 687 688 verbose_msg "running ldconfig" 689 if [ -n "${CFG_VERBOSE-}" ]; then 690 ldconfig 691 else 692 ldconfig 2> /dev/null 693 fi 694 if [ $? -ne 0 ] 695 then 696 local _warn_s="failed to run ldconfig. this may happen when \ 697not installing as root. run with --verbose to see the error" 698 warn "$_warn_s" 699 fi 700 fi 701} 702 703maybe_unconfigure_ld() { 704 local _ostype="$(uname -s)" 705 assert_nz "$_ostype" "ostype" 706 707 if [ "$_ostype" != "Linux" ]; then 708 return 0 709 fi 710 711 rm "/etc/ld.so.conf.d/rust-installer-v1-$TEMPLATE_REL_MANIFEST_DIR.conf" 2> /dev/null 712 # Above may fail since that file may not have been created on install 713} 714 715# Doing our own 'install'-like backup that is consistent across platforms 716maybe_backup_path() { 717 local _file_install_path="$1" 718 719 if [ -e "$_file_install_path" ]; then 720 msg "backing up existing file at $_file_install_path" 721 run mv -f "$_file_install_path" "$_file_install_path.old" 722 critical_need_ok "failed to back up $_file_install_path" 723 fi 724} 725 726install_uninstaller() { 727 local _src_dir="$1" 728 local _src_basename="$2" 729 local _abs_libdir="$3" 730 731 local _uninstaller="$_abs_libdir/$TEMPLATE_REL_MANIFEST_DIR/uninstall.sh" 732 msg "creating uninstall script at $_uninstaller" 733 run cp "$_src_dir/$_src_basename" "$_uninstaller" 734 critical_need_ok "unable to install uninstaller" 735} 736 737do_preflight_sanity_checks() { 738 local _src_dir="$1" 739 local _dest_prefix="$2" 740 741 # Sanity check: can we can write to the destination? 742 verbose_msg "verifying destination is writable" 743 make_dir_recursive "$CFG_LIBDIR" 744 need_ok "can't write to destination. consider \`sudo\`." 745 touch "$CFG_LIBDIR/rust-install-probe" > /dev/null 746 if [ $? -ne 0 ] 747 then 748 err "can't write to destination. consider \`sudo\`." 749 fi 750 rm "$CFG_LIBDIR/rust-install-probe" 751 need_ok "failed to remove install probe" 752 753 # Sanity check: don't install to the directory containing the installer. 754 # That would surely cause chaos. 755 verbose_msg "verifying destination is not the same as source" 756 local _prefix_dir="$(abs_path "$dest_prefix")" 757 if [ "$_src_dir" = "$_dest_prefix" -a "${CFG_UNINSTALL-}" != 1 ]; then 758 err "cannot install to same directory as installer" 759 fi 760} 761 762verbose_msg "looking for install programs" 763verbose_msg 764 765need_cmd mkdir 766need_cmd printf 767need_cmd cut 768need_cmd grep 769need_cmd uname 770need_cmd tr 771need_cmd sed 772need_cmd chmod 773need_cmd env 774need_cmd pwd 775 776CFG_ARGS="${@:-}" 777 778HELP=0 779if [ "${1-}" = "--help" ] 780then 781 HELP=1 782 shift 783 echo 784 echo "Usage: $0 [options]" 785 echo 786 echo "Options:" 787 echo 788else 789 verbose_step_msg "processing arguments" 790fi 791 792OPTIONS="" 793BOOL_OPTIONS="" 794VAL_OPTIONS="" 795 796flag uninstall "only uninstall from the installation prefix" 797valopt destdir "" "set installation root" 798valopt prefix "/usr/local" "set installation prefix" 799 800# Avoid prepending an extra / to the prefix path if there's no destdir 801# NB: CFG vars here are undefined when passing --help 802if [ -z "${CFG_DESTDIR-}" ]; then 803 CFG_DESTDIR_PREFIX="${CFG_PREFIX-}" 804else 805 CFG_DESTDIR_PREFIX="$CFG_DESTDIR/$CFG_PREFIX" 806fi 807 808# NB This isn't quite the same definition as in `configure`. 809# just using 'lib' instead of configure's CFG_LIBDIR_RELATIVE 810valopt without "" "comma-separated list of components to not install" 811valopt components "" "comma-separated list of components to install" 812flag list-components "list available components" 813valopt sysconfdir "$CFG_DESTDIR_PREFIX/etc" "install system configuration files" 814valopt bindir "$CFG_DESTDIR_PREFIX/bin" "install binaries" 815valopt libdir "$CFG_DESTDIR_PREFIX/lib" "install libraries" 816valopt datadir "$CFG_DESTDIR_PREFIX/share" "install data" 817# NB We repeat datadir default value because we don't set CFG_DATADIR in --help 818valopt mandir "${CFG_DATADIR-"$CFG_DESTDIR_PREFIX/share"}/man" "install man pages in PATH" 819# NB See the docdir handling in install_components for an explanation of this 820# weird <default> string 821valopt docdir "\<default\>" "install documentation in PATH" 822opt ldconfig 1 "run ldconfig after installation (Linux only)" 823opt verify 1 "obsolete" 824flag verbose "run with verbose output" 825 826if [ $HELP -eq 1 ] 827then 828 echo 829 exit 0 830fi 831 832verbose_step_msg "validating arguments" 833validate_opt 834 835# Template configuration. 836# These names surrounded by '%%` are replaced by sed when generating install.sh 837# FIXME: Might want to consider loading this from a file and not generating install.sh 838 839# Rust or Cargo 840TEMPLATE_PRODUCT_NAME='Rust' 841# rustlib or cargo 842TEMPLATE_REL_MANIFEST_DIR=rustlib 843# 'Rust is ready to roll.' or 'Cargo is cool to cruise.' 844TEMPLATE_SUCCESS_MESSAGE='clippy installed.' 845# Locations to look for directories containing legacy, pre-versioned manifests 846TEMPLATE_LEGACY_MANIFEST_DIRS='rustlib,cargo' 847# The installer version 848TEMPLATE_RUST_INSTALLER_VERSION='3' 849 850# OK, let's get installing ... 851 852# This is where we are installing from 853src_dir="$(abs_path $(dirname "$0"))" 854 855# The name of the script 856src_basename="$(basename "$0")" 857 858# If we've been run as 'uninstall.sh' (from the existing installation) 859# then we're doing a full uninstall, as opposed to the --uninstall flag 860# which just means 'uninstall my components'. 861if [ "$src_basename" = "uninstall.sh" ]; then 862 if [ "${*:-}" != "" ]; then 863 # Currently don't know what to do with arguments in this mode 864 err "uninstall.sh does not take any arguments" 865 fi 866 CFG_UNINSTALL=1 867 CFG_DESTDIR_PREFIX="$(abs_path "$src_dir/../../")" 868 CFG_LIBDIR="$(abs_path "$src_dir/../")" 869fi 870 871# This is where we are installing to 872dest_prefix="$CFG_DESTDIR_PREFIX" 873 874# Open the components file to get the list of components to install. 875# NB: During install this components file is read from the installer's 876# source dir, during a full uninstall it's read from the manifest dir, 877# and thus contains all installed components. 878components=`cat "$src_dir/components"` 879 880# Sanity check: do we have components? 881if [ ! -n "$components" ]; then 882 err "unable to find installation components" 883fi 884 885# If the user asked for a component list, do that and exit 886if [ -n "${CFG_LIST_COMPONENTS-}" ]; then 887 echo 888 echo "# Available components" 889 echo 890 for component in $components; do 891 echo "* $component" 892 done 893 echo 894 exit 0 895fi 896 897# If the user specified which components to install/uninstall, 898# then validate that they exist and select them for installation 899if [ -n "$CFG_COMPONENTS" ]; then 900 # Remove commas 901 user_components="$(echo "$CFG_COMPONENTS" | sed "s/,/ /g")" 902 for user_component in $user_components; do 903 found=false 904 for my_component in $components; do 905 if [ "$user_component" = "$my_component" ]; then 906 found=true 907 fi 908 done 909 if [ "$found" = false ]; then 910 err "unknown component: $user_component" 911 fi 912 done 913 components="$user_components" 914fi 915 916if [ -n "$CFG_WITHOUT" ]; then 917 without_components="$(echo "$CFG_WITHOUT" | sed "s/,/ /g")" 918 919 # This does **not** check that all components in without_components are 920 # actually present in the list of available components. 921 # 922 # Currently that's considered good as it makes it easier to be compatible 923 # with multiple Rust versions (which may change the exact list of 924 # components) when writing install scripts. 925 new_comp="" 926 for component in $components; do 927 found=false 928 for my_component in $without_components; do 929 if [ "$component" = "$my_component" ]; then 930 found=true 931 fi 932 done 933 if [ "$found" = false ]; then 934 # If we didn't find the component in without, then add it to new list. 935 new_comp="$new_comp $component" 936 fi 937 done 938 components="$new_comp" 939fi 940 941if [ -z "$components" ]; then 942 if [ -z "${CFG_UNINSTALL-}" ]; then 943 err "no components selected for installation" 944 else 945 err "no components selected for uninstallation" 946 fi 947fi 948 949do_preflight_sanity_checks "$src_dir" "$dest_prefix" 950 951# Using an absolute path to libdir in a few places so that the status 952# messages are consistently using absolute paths. 953absolutify "$CFG_LIBDIR" 954abs_libdir="$RETVAL" 955assert_nz "$abs_libdir" "abs_libdir" 956 957# Create the manifest directory, where we will put our logs 958make_dir_recursive "$abs_libdir/$TEMPLATE_REL_MANIFEST_DIR" 959need_ok "failed to create $TEMPLATE_REL_MANIFEST_DIR" 960 961# Log messages and commands 962init_logging "$abs_libdir" 963 964# First do any uninstallation, including from legacy manifests. This 965# will also upgrade the metadata of existing installs. 966uninstall_components "$abs_libdir" "$dest_prefix" "$components" 967 968# If we're only uninstalling then exit 969if [ -n "${CFG_UNINSTALL-}" ] 970then 971 echo 972 echo " $TEMPLATE_PRODUCT_NAME is uninstalled." 973 echo 974 exit 0 975fi 976 977# Create the manifest directory again! uninstall_legacy 978# may have deleted it. 979make_dir_recursive "$abs_libdir/$TEMPLATE_REL_MANIFEST_DIR" 980need_ok "failed to create $TEMPLATE_REL_MANIFEST_DIR" 981 982# Drop the version number into the manifest dir 983write_to_file "$TEMPLATE_RUST_INSTALLER_VERSION" \ 984"$abs_libdir/$TEMPLATE_REL_MANIFEST_DIR/rust-installer-version" 985 986critical_need_ok "failed to write installer version" 987 988# Install the uninstaller 989install_uninstaller "$src_dir" "$src_basename" "$abs_libdir" 990 991# Install each component 992install_components "$src_dir" "$abs_libdir" "$dest_prefix" "$components" 993 994# Make dynamic libraries available to the linker 995maybe_configure_ld "$abs_libdir" 996 997echo 998echo " $TEMPLATE_SUCCESS_MESSAGE" 999echo 1000