xref: /aosp_15_r20/prebuilts/rust/linux-x86/1.81.0.u1/lib/rustlib/uninstall.sh (revision b40554a23088fb75aa6945dfe8e65169c8484da3)
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