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