]> git.lizzy.rs Git - rust.git/blob - src/etc/rustup.sh
cleanup: s/impl Copy/#[derive(Copy)]/g
[rust.git] / src / etc / rustup.sh
1 #!/bin/sh
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
13 msg() {
14     echo "rustup: $1"
15 }
16
17 step_msg() {
18     msg
19     msg "$1"
20     msg
21 }
22
23 warn() {
24     echo "rustup: WARNING: $1"
25 }
26
27 err() {
28     echo "rustup: error: $1"
29     exit 1
30 }
31
32 need_ok() {
33     if [ $? -ne 0 ]
34     then
35         err "$1"
36     fi
37 }
38
39
40 putvar() {
41     local T
42     eval T=\$$1
43     eval TLEN=\${#$1}
44     if [ $TLEN -gt 35 ]
45     then
46         printf "rustup: %-20s := %.35s ...\n" $1 "$T"
47     else
48         printf "rustup: %-20s := %s %s\n" $1 "$T" "$2"
49     fi
50 }
51
52 probe() {
53     local V=$1
54     shift
55     local P
56     local T
57     for P
58     do
59         T=$(which $P 2>&1)
60         if [ $? -eq 0 ]
61         then
62             VER0=$($P --version 2>/dev/null | head -1 \
63                 |  sed -e 's/[^0-9]*\([vV]\?[0-9.]\+[^ ]*\).*/\1/' )
64             if [ $? -eq 0 -a "x${VER0}" != "x" ]
65             then
66               VER="($VER0)"
67             else
68               VER=""
69             fi
70             break
71         else
72             VER=""
73             T=""
74         fi
75     done
76     eval $V=\$T
77     putvar $V "$VER"
78 }
79
80 probe_need() {
81     local V=$1
82     probe $*
83     eval VV=\$$V
84     if [ -z "$VV" ]
85     then
86         err "needed, but unable to find any of: $*"
87     fi
88 }
89
90
91 valopt() {
92     VAL_OPTIONS="$VAL_OPTIONS $1"
93
94     local OP=$1
95     local DEFAULT=$2
96     shift
97     shift
98     local DOC="$*"
99     if [ $HELP -eq 0 ]
100     then
101         local UOP=$(echo $OP | tr '[:lower:]' '[:upper:]' | tr '\-' '\_')
102         local V="CFG_${UOP}"
103         eval $V="$DEFAULT"
104         for arg in $CFG_ARGS
105         do
106             if echo "$arg" | grep -q -- "--$OP="
107             then
108                 val=$(echo "$arg" | cut -f2 -d=)
109                 eval $V=$val
110             fi
111         done
112         putvar $V
113     else
114         if [ -z "$DEFAULT" ]
115         then
116             DEFAULT="<none>"
117         fi
118         OP="${OP}=[${DEFAULT}]"
119         printf "    --%-30s %s\n" "$OP" "$DOC"
120     fi
121 }
122
123 opt() {
124     BOOL_OPTIONS="$BOOL_OPTIONS $1"
125
126     local OP=$1
127     local DEFAULT=$2
128     shift
129     shift
130     local DOC="$*"
131     local FLAG=""
132
133     if [ $DEFAULT -eq 0 ]
134     then
135         FLAG="enable"
136     else
137         FLAG="disable"
138         DOC="don't $DOC"
139     fi
140
141     if [ $HELP -eq 0 ]
142     then
143         for arg in $CFG_ARGS
144         do
145             if [ "$arg" = "--${FLAG}-${OP}" ]
146             then
147                 OP=$(echo $OP | tr 'a-z-' 'A-Z_')
148                 FLAG=$(echo $FLAG | tr 'a-z' 'A-Z')
149                 local V="CFG_${FLAG}_${OP}"
150                 eval $V=1
151                 putvar $V
152             fi
153         done
154     else
155         if [ ! -z "$META" ]
156         then
157             OP="$OP=<$META>"
158         fi
159         printf "    --%-30s %s\n" "$FLAG-$OP" "$DOC"
160      fi
161 }
162
163 flag() {
164     BOOL_OPTIONS="$BOOL_OPTIONS $1"
165
166     local OP=$1
167     shift
168     local DOC="$*"
169
170     if [ $HELP -eq 0 ]
171     then
172         for arg in $CFG_ARGS
173         do
174             if [ "$arg" = "--${OP}" ]
175             then
176                 OP=$(echo $OP | tr 'a-z-' 'A-Z_')
177                 local V="CFG_${OP}"
178                 eval $V=1
179                 putvar $V
180             fi
181         done
182     else
183         if [ ! -z "$META" ]
184         then
185             OP="$OP=<$META>"
186         fi
187         printf "    --%-30s %s\n" "$OP" "$DOC"
188      fi
189 }
190
191 validate_opt() {
192     for arg in $CFG_ARGS
193     do
194         isArgValid=0
195         for option in $BOOL_OPTIONS
196         do
197             if test --disable-$option = $arg
198             then
199                 isArgValid=1
200             fi
201             if test --enable-$option = $arg
202             then
203                 isArgValid=1
204             fi
205             if test --$option = $arg
206             then
207                 isArgValid=1
208             fi
209         done
210         for option in $VAL_OPTIONS
211         do
212             if echo "$arg" | grep -q -- "--$option="
213             then
214                 isArgValid=1
215             fi
216         done
217         if [ "$arg" = "--help" ]
218         then
219             echo
220             echo "No more help available for Configure options,"
221             echo "check the Wiki or join our IRC channel"
222             break
223         else
224             if test $isArgValid -eq 0
225             then
226                 err "Option '$arg' is not recognized"
227             fi
228         fi
229     done
230 }
231
232 create_tmp_dir() {
233     local TMP_DIR=`pwd`/rustup-tmp-install
234
235     rm -Rf "${TMP_DIR}"
236     need_ok "failed to remove temporary installation directory"
237
238     mkdir -p "${TMP_DIR}"
239     need_ok "failed to create create temporary installation directory"
240
241     echo $TMP_DIR
242 }
243
244 probe_need CFG_CURL  curl
245 probe_need CFG_TAR   tar
246 probe_need CFG_FILE  file
247
248 probe CFG_SHA256SUM sha256sum
249 probe CFG_SHASUM shasum
250
251 if [ -z "$CFG_SHA256SUM" -a -z "$CFG_SHASUM" ]; then
252     err "unable to find either sha256sum or shasum"
253 fi
254
255 calculate_hash() {
256     if [ -n "$CFG_SHA256SUM" ]; then
257         ${CFG_SHA256SUM} $@
258     else
259         ${CFG_SHASUM} -a 256 $@
260     fi
261 }
262
263 CFG_SRC_DIR="$(cd $(dirname $0) && pwd)/"
264 CFG_SELF="$0"
265 CFG_ARGS="$@"
266
267 HELP=0
268 if [ "$1" = "--help" ]
269 then
270     HELP=1
271     shift
272     echo
273     echo "Usage: $CFG_SELF [options]"
274     echo
275     echo "Options:"
276     echo
277 else
278     step_msg "processing $CFG_SELF args"
279 fi
280
281 OPTIONS=""
282 BOOL_OPTIONS=""
283 VAL_OPTIONS=""
284
285 flag uninstall "only uninstall from the installation prefix"
286 valopt prefix "" "set installation prefix"
287 valopt date "" "use the YYYY-MM-DD nightly instead of the current nightly"
288 flag save "save the downloaded nightlies to ~/.rustup"
289
290 if [ $HELP -eq 1 ]
291 then
292     echo
293     exit 0
294 fi
295
296 step_msg "validating $CFG_SELF args"
297 validate_opt
298
299
300 # Platform detection copied from `configure`
301
302 CFG_OSTYPE=$(uname -s)
303 CFG_CPUTYPE=$(uname -m)
304
305 if [ $CFG_OSTYPE = Darwin -a $CFG_CPUTYPE = i386 ]
306 then
307     # Darwin's `uname -s` lies and always returns i386. We have to use sysctl
308     # instead.
309     if sysctl hw.optional.x86_64 | grep -q ': 1'
310     then
311         CFG_CPUTYPE=x86_64
312     fi
313 fi
314
315 # The goal here is to come up with the same triple as LLVM would,
316 # at least for the subset of platforms we're willing to target.
317
318 case $CFG_OSTYPE in
319
320     Linux)
321         CFG_OSTYPE=unknown-linux-gnu
322         ;;
323
324     FreeBSD)
325         CFG_OSTYPE=unknown-freebsd
326         ;;
327
328     Darwin)
329         CFG_OSTYPE=apple-darwin
330         ;;
331
332     MINGW32*)
333         CFG_OSTYPE=pc-mingw32
334         ;;
335 # Thad's Cygwin identifers below
336
337 #   Vista 32 bit
338     CYGWIN_NT-6.0)
339         CFG_OSTYPE=pc-mingw32
340         CFG_CPUTYPE=i686
341         ;;
342
343 #   Vista 64 bit
344     CYGWIN_NT-6.0-WOW64)
345         CFG_OSTYPE=w64-mingw32
346         CFG_CPUTYPE=x86_64
347         ;;
348
349 #   Win 7 32 bit
350     CYGWIN_NT-6.1)
351         CFG_OSTYPE=pc-mingw32
352         CFG_CPUTYPE=i686
353         ;;
354
355 #   Win 7 64 bit
356     CYGWIN_NT-6.1-WOW64)
357         CFG_OSTYPE=w64-mingw32
358         CFG_CPUTYPE=x86_64
359         ;;
360
361 # We do not detect other OS such as XP/2003 using 64 bit using uname.
362 # If we want to in the future, we will need to use Cygwin
363 # Chuck's csih helper in /usr/lib/csih/winProductName.exe or alternative.
364     *)
365         err "unknown OS type: $CFG_OSTYPE"
366         ;;
367 esac
368
369
370 case $CFG_CPUTYPE in
371
372     i386 | i486 | i686 | i786 | x86)
373         CFG_CPUTYPE=i686
374         ;;
375
376     xscale | arm)
377         CFG_CPUTYPE=arm
378         ;;
379
380     x86_64 | x86-64 | x64 | amd64)
381         CFG_CPUTYPE=x86_64
382         ;;
383
384     *)
385         err "unknown CPU type: $CFG_CPUTYPE"
386 esac
387
388 # Detect 64 bit linux systems with 32 bit userland and force 32 bit compilation
389 if [ $CFG_OSTYPE = unknown-linux-gnu -a $CFG_CPUTYPE = x86_64 ]
390 then
391     "${CFG_FILE}" -L "$SHELL" | grep -q "x86[_-]64"
392     if [ $? != 0 ]; then
393         CFG_CPUTYPE=i686
394     fi
395 fi
396
397 HOST_TRIPLE="${CFG_CPUTYPE}-${CFG_OSTYPE}"
398
399 # Is this a triple we have nightlies for?
400 case $HOST_TRIPLE in
401
402         x86_64-unknown-linux-gnu)
403                 ;;
404
405         i686-unknown-linux-gnu)
406                 ;;
407
408         x86_64-apple-darwin)
409                 ;;
410
411         i686-apple-darwin)
412                 ;;
413
414         *)
415                 err "rustup.sh doesn't work for host $HOST_TRIPLE"
416
417 esac
418
419 msg "host triple: ${HOST_TRIPLE}"
420
421 CFG_INSTALL_FLAGS=""
422 if [ -n "${CFG_UNINSTALL}" ]
423 then
424     CFG_INSTALL_FLAGS="${CFG_INSTALL_FLAGS} --uninstall"
425 fi
426
427 if [ -n "${CFG_PREFIX}" ]
428 then
429     CFG_INSTALL_FLAGS="${CFG_INSTALL_FLAGS} --prefix=${CFG_PREFIX}"
430 fi
431
432 CFG_TMP_DIR=$(mktemp -d 2>/dev/null \
433            || mktemp -d -t 'rustup-tmp-install' 2>/dev/null \
434            || create_tmp_dir)
435
436 # If we're saving nightlies and we didn't specify which one, grab the latest
437 # verison from the perspective of the server. Buildbot has typically finished
438 # building and uploading by ~8UTC, but we want to include a little buffer.
439 #
440 # FIXME It would be better to use the known most recent nightly that has been
441 # built. This is waiting on a change to have buildbot publish metadata that
442 # can be queried.
443 if [ -n "${CFG_SAVE}" -a -z "${CFG_DATE}" ];
444 then
445     CFG_DATE=`TZ=Etc/UTC+9 date "+%Y-%m-%d"`
446 fi
447
448 RUST_URL="https://static.rust-lang.org/dist"
449 RUST_PACKAGE_NAME=rust-nightly
450 RUST_PACKAGE_NAME_AND_TRIPLE="${RUST_PACKAGE_NAME}-${HOST_TRIPLE}"
451 RUST_TARBALL_NAME="${RUST_PACKAGE_NAME_AND_TRIPLE}.tar.gz"
452 RUST_LOCAL_INSTALL_DIR="${CFG_TMP_DIR}/${RUST_PACKAGE_NAME_AND_TRIPLE}"
453 RUST_LOCAL_INSTALL_SCRIPT="${RUST_LOCAL_INSTALL_DIR}/install.sh"
454
455 # add a date suffix if we want a particular nighly.
456 if [ -n "${CFG_DATE}" ];
457 then
458     RUST_URL="${RUST_URL}/${CFG_DATE}"
459 fi
460
461 download_hash() {
462     msg "Downloading ${remote_sha256}"
463     remote_sha256=`"${CFG_CURL}" -f "${remote_sha256}"`
464     if [ -n "${CFG_SAVE}" ]; then
465         echo "${remote_sha256}" > "${local_sha_file}"
466     fi
467     if [ "$?" -ne 0 ]; then
468         rm -Rf "${CFG_TMP_DIR}"
469         err "Failed to download ${remote_url}"
470     fi
471 }
472
473 verify_hash() {
474     remote_sha256="$1"
475     local_file="$2"
476     local_sha_file="${local_file}.sha256"
477
478     if [ -n "${CFG_SAVE}" ]; then
479         if [ -f "${local_sha_file}" ]; then
480             msg "Local ${local_sha_file} exists, treating as remote hash"
481             remote_sha256=`cat "${local_sha_file}"`
482         else
483             download_hash
484         fi
485     else
486         download_hash
487     fi
488
489     msg "Verifying hash"
490     local_sha256=$(calculate_hash "${local_file}")
491     if [ "$?" -ne 0 ]; then
492         rm -Rf "${CFG_TMP_DIR}"
493         err "Failed to compute hash for ${local_tarball}"
494     fi
495
496     # We only need the sha, not the filenames
497     remote_sha256=`echo ${remote_sha256} | cut -f 1 -d ' '`
498     local_sha256=`echo ${local_sha256} | cut -f 1 -d ' '`
499
500     if [ "${remote_sha256}" != "${local_sha256}" ]; then
501         rm -Rf "${CFG_TMP_DIR}"
502         errmsg="invalid sha256.\n"
503         errmsg="$errmsg ${remote_sha256}\t${remote_tarball}\n"
504         errmsg="$errmsg ${local_sha256}\t${local_tarball}"
505         err "$errmsg"
506     fi
507 }
508
509 # Fetch the package. Optionally caches the tarballs.
510 download_package() {
511     remote_tarball="$1"
512     local_tarball="$2"
513     remote_sha256="${remote_tarball}.sha256"
514
515     # Check if we've already downloaded this file.
516     if [ -e "${local_tarball}.tmp" ]; then
517         msg "Resuming ${remote_tarball} to ${local_tarball}"
518
519         "${CFG_CURL}" -f -C - -o "${local_tarball}.tmp" "${remote_tarball}"
520         if [ $? -ne 0 ]
521         then
522             rm -Rf "${CFG_TMP_DIR}"
523             err "failed to download installer"
524         fi
525
526         mv "${local_tarball}.tmp" "${local_tarball}"
527     elif [ ! -e "${local_tarball}" ]; then
528         msg "Downloading ${remote_tarball} to ${local_tarball}"
529
530         "${CFG_CURL}" -f -o "${local_tarball}.tmp" "${remote_tarball}"
531         if [ $? -ne 0 ]
532         then
533             rm -Rf "${CFG_TMP_DIR}"
534             err "failed to download installer"
535         fi
536
537         mv "${local_tarball}.tmp" "${local_tarball}"
538     fi
539
540     verify_hash "${remote_sha256}" "${local_tarball}"
541 }
542
543 # Wrap all the commands needed to install a package.
544 install_package() {
545     local_tarball="$1"
546     install_script="$2"
547
548     msg "Extracting ${local_tarball}"
549     (cd "${CFG_TMP_DIR}" && "${CFG_TAR}" -xzf "${local_tarball}")
550     if [ $? -ne 0 ]; then
551         rm -Rf "${CFG_TMP_DIR}"
552         err "failed to unpack installer"
553     fi
554
555     sh "${install_script}" "${CFG_INSTALL_FLAGS}"
556     if [ $? -ne 0 ]
557     then
558         rm -Rf "${CFG_TMP_DIR}"
559         err "failed to install Rust"
560     fi
561 }
562
563 # It's possible that curl could be interrupted partway though downloading
564 # `rustup.sh`, truncating the file. This could be especially bad if we were in
565 # the middle of a line that would run "rm -rf ". To protect against this, we
566 # wrap up the `rustup.sh` destructive functionality in this helper function,
567 # which we call as the last thing we do. This means we will not do anything
568 # unless we have the entire file downloaded.
569 install_packages() {
570     rm -Rf "${CFG_TMP_DIR}"
571     need_ok "failed to remove temporary installation directory"
572
573     mkdir -p "${CFG_TMP_DIR}"
574     need_ok "failed to create create temporary installation directory"
575
576     # If we're saving our nightlies, put them in $HOME/.rustup.
577     if [ -n "${CFG_SAVE}" ]
578     then
579         RUST_DOWNLOAD_DIR="${HOME}/.rustup/${CFG_DATE}"
580     else
581         RUST_DOWNLOAD_DIR="${CFG_TMP_DIR}"
582     fi
583
584     mkdir -p "${RUST_DOWNLOAD_DIR}"
585     need_ok "failed to create create download directory"
586
587     RUST_LOCAL_TARBALL="${RUST_DOWNLOAD_DIR}/${RUST_TARBALL_NAME}"
588
589     download_package \
590         "${RUST_URL}/${RUST_TARBALL_NAME}" \
591         "${RUST_LOCAL_TARBALL}"
592
593     install_package \
594         "${RUST_LOCAL_TARBALL}" \
595         "${RUST_LOCAL_INSTALL_SCRIPT}"
596
597     rm -Rf "${CFG_TMP_DIR}"
598     need_ok "couldn't rm temporary installation directory"
599 }
600
601 install_packages