Home | History | Annotate | Line # | Download | only in maintainer-scripts
gcc_release revision 1.8
      1 #! /bin/sh
      2 
      3 ########################################################################
      4 #
      5 # File:   gcc_release
      6 # Author: Jeffrey Law, Bernd Schmidt, Mark Mitchell
      7 # Date:   2001-05-25
      8 #
      9 # Contents:
     10 #   Script to create a GCC release.
     11 #
     12 # Copyright (c) 2001-2015 Free Software Foundation.
     13 #
     14 # This file is part of GCC.
     15 #
     16 # GCC is free software; you can redistribute it and/or modify
     17 # it under the terms of the GNU General Public License as published by
     18 # the Free Software Foundation; either version 3, or (at your option)
     19 # any later version.
     20 #
     21 # GCC is distributed in the hope that it will be useful,
     22 # but WITHOUT ANY WARRANTY; without even the implied warranty of
     23 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     24 # GNU General Public License for more details.
     25 #
     26 # You should have received a copy of the GNU General Public License
     27 # along with GCC; see the file COPYING3.  If not see
     28 # <http://www.gnu.org/licenses/>.
     29 #
     30 ########################################################################
     31 
     32 ########################################################################
     33 # Notes
     34 ########################################################################
     35 
     36 # Here is an example usage of this script, to create a GCC 3.0.2
     37 # prerelease:
     38 #
     39 #   gcc_release -r 3.0.2
     40 #
     41 # This script will automatically use the head of the release branch
     42 # to generate the release.
     43 
     44 ########################################################################
     45 # Functions
     46 ########################################################################
     47 
     48 # Issue the error message given by $1 and exit with a non-zero
     49 # exit code.
     50 
     51 error() {
     52     echo "gcc_release: error: $1"
     53     exit 1
     54 }
     55 
     56 # Issue the informational message given by $1.
     57 
     58 inform() {
     59     echo "gcc_release: $1"
     60 }
     61 
     62 # Issue a usage message explaining how to use this script.
     63 
     64 usage() {
     65 cat <<EOF
     66 gcc_release -r release [-f] [further options]
     67 gcc_release -s name:svnbranch [further options]
     68 
     69 Options:
     70 
     71   -r release           Version of the form X.Y or X.Y.Z.
     72   -s name:svnbranch    Create a snapshot, not a real release.
     73 
     74   -d destination       Local working directory where we will build the release
     75                        (default=${HOME}).
     76   -f                   Create a final release (and update ChangeLogs,...).
     77   -l                   Indicate that we are running on gcc.gnu.org.
     78   -p previous-tarball  Location of a previous tarball (to generate diff files).
     79   -t tag               Tag to mark the release in SVN.
     80   -u username          Username for upload operations.
     81 EOF
     82     exit 1
     83 }
     84 
     85 # Change to the directory given by $1.
     86 
     87 changedir() {
     88   cd $1 || \
     89     error "Could not change directory to $1"
     90 }
     91 
     92 # Build the source tree that will be the basis for the release
     93 # in ${WORKING_DIRECTORY}/gcc-${RELEASE}.
     94 
     95 build_sources() {
     96   # If the WORKING_DIRECTORY already exists, do not risk destroying it.
     97   if [ -r ${WORKING_DIRECTORY} ]; then
     98     error "\`${WORKING_DIRECTORY}' already exists"
     99   fi
    100   # Create the WORKING_DIRECTORY.
    101   mkdir "${WORKING_DIRECTORY}" \
    102     || error "Could not create \`${WORKING_DIRECTORY}'"
    103   changedir "${WORKING_DIRECTORY}"
    104 
    105   # If this is a final release, make sure that the ChangeLogs
    106   # and version strings are updated.
    107   if [ ${FINAL} -ne 0 ]; then
    108     inform "Updating ChangeLogs and version files"
    109 
    110     ${SVN} -q co "${SVNROOT}/${SVNBRANCH}" "`basename ${SOURCE_DIRECTORY}`" ||\
    111            error "Could not check out release sources"
    112     svnciargs=""
    113     for x in `changedir ${SOURCE_DIRECTORY} && \
    114 	      find . -name ChangeLog`; do
    115       # Update this ChangeLog file only if it does not yet contain the
    116       # entry we are going to add.  (This is a safety net for repeated
    117       # runs of this script for the same release.)
    118       if ! grep "GCC ${RELEASE} released." ${SOURCE_DIRECTORY}/${x} > /dev/null ; then       
    119 	cat - ${SOURCE_DIRECTORY}/${x} > ${SOURCE_DIRECTORY}/${x}.new <<EOF
    120 ${LONG_DATE}  Release Manager
    121 
    122 	* GCC ${RELEASE} released.
    123 
    124 EOF
    125 	mv ${SOURCE_DIRECTORY}/${x}.new ${SOURCE_DIRECTORY}/${x} \
    126 	  || error "Could not update ${x}"
    127 	svnciargs="${svnciargs} ${x}"
    128       fi
    129     done
    130 
    131     # Update gcc/DEV-PHASE.
    132 
    133     if [ `cat ${SOURCE_DIRECTORY}/gcc/BASE-VER` != ${RELEASE} ]; then
    134       [ ${RELEASE_MAJOR} -lt 5 ] && \
    135 	error "Release number ${RELEASE} does not match BASE-VER"
    136       if [ `cat ${SOURCE_DIRECTORY}/gcc/BASE-VER` \
    137 	   = ${RELEASE_MAJOR}.`expr ${RELEASE_MINOR} - 1`.1 \
    138 	   -a x${RELEASE_REVISION} = x0 ]; then
    139 	(changedir ${SOURCE_DIRECTORY}/gcc && \
    140 	 echo ${RELEASE} > BASE-VER) || \
    141 	error "Could not update BASE-VER"
    142 	svnciargs="${svnciargs} gcc/BASE-VER"
    143       else
    144 	error "Release number ${RELEASE} does not immediately follow BASE-VER"
    145       fi
    146     fi
    147     (changedir ${SOURCE_DIRECTORY}/gcc && \
    148      : > DEV-PHASE) || \
    149     error "Could not update DEV-PHASE"
    150     svnciargs="${svnciargs} gcc/DEV-PHASE"
    151 
    152     (changedir ${SOURCE_DIRECTORY} && \
    153      ${SVN} -q ci -m 'Update ChangeLog and version files for release' ${svnciargs}) || \
    154     error "Could not commit ChangeLog and version file updates"
    155 
    156     # Make sure we tag the sources for a final release.
    157     TAG="tags/gcc_`echo ${RELEASE} | tr . _`_release"
    158 
    159     rm -rf ${SOURCE_DIRECTORY}
    160   fi
    161 
    162   # Tag the sources.
    163   if [ -n "${TAG}" ]; then
    164     inform "Tagging sources as ${TAG}"
    165     # We don't want to overwrite an existing tag.  So, if the tag
    166     # already exists, issue an error message; the release manager can
    167     # manually remove the tag if appropriate.
    168     echo "${SVN} ls ${SVNROOT}/${TAG}/ChangeLog" 
    169     if ${SVN} ls "${SVNROOT}/${TAG}/ChangeLog"; then 
    170       error "Tag ${TAG} already exists"
    171     fi
    172     ${SVN} -m "Tagging source as ${TAG}" cp "${SVNROOT}/${SVNBRANCH}" "${SVNROOT}/${TAG}" || \
    173       error "Could not tag sources"
    174     SVNBRANCH=${TAG}
    175   fi
    176   SVNREV=`${SVN} info "${SVNROOT}/${SVNBRANCH}"|awk '/Revision:/ {print $2}'`
    177 
    178   # Export the current sources.
    179   inform "Retrieving sources (svn export -r ${SVNREV} ${SVNROOT}/${SVNBRANCH})"
    180 
    181   ${SVN} -q export -r${SVNREV} "${SVNROOT}/${SVNBRANCH}" "`basename ${SOURCE_DIRECTORY}`" ||\
    182     error "Could not retrieve sources"
    183 
    184   # Run gcc_update on them to set up the timestamps nicely, and (re)write
    185   # the LAST_UPDATED file containing the SVN tag/revision used.
    186   changedir "gcc-${RELEASE}"
    187   contrib/gcc_update --touch
    188   echo "Obtained from SVN: ${SVNBRANCH} revision ${SVNREV}" > LAST_UPDATED
    189 
    190   # For a prerelease or real release, we need to generate additional
    191   # files not present in SVN.
    192   changedir "${SOURCE_DIRECTORY}"
    193   if [ $SNAPSHOT -ne 1 ]; then
    194     # Generate the documentation.
    195     inform "Building install docs"
    196     SOURCEDIR=${SOURCE_DIRECTORY}/gcc/doc
    197     DESTDIR=${SOURCE_DIRECTORY}/INSTALL
    198     export SOURCEDIR
    199     export DESTDIR
    200     ${SOURCE_DIRECTORY}/gcc/doc/install.texi2html
    201 
    202     # Regenerate the NEWS file.
    203     contrib/gennews > NEWS || \
    204       error "Could not regenerate NEWS files"
    205 
    206     # Now, we must build the compiler in order to create any generated
    207     # files that are supposed to go in the source directory.  This is
    208     # also a good sanity check to make sure that the release builds
    209     # on at least one platform.
    210     inform "Building compiler"
    211     OBJECT_DIRECTORY=../objdir
    212     contrib/gcc_build -d ${SOURCE_DIRECTORY} -o ${OBJECT_DIRECTORY} \
    213       -c "--enable-generated-files-in-srcdir --disable-multilib" build || \
    214       error "Could not rebuild GCC"
    215   fi
    216 
    217   # Move message catalogs to source directory.
    218   mv ../objdir/gcc/po/*.gmo gcc/po/
    219   [ -f libcpp/po/cpplib.pot ] && mv ../objdir/libcpp/po/*.gmo libcpp/po/
    220 
    221   # Create a "MD5SUMS" file to use for checking the validity of the release.
    222   echo \
    223 "# This file contains the MD5 checksums of the files in the 
    224 # gcc-"${RELEASE}".tar.xz tarball.
    225 #
    226 # Besides verifying that all files in the tarball were correctly expanded,
    227 # it also can be used to determine if any files have changed since the
    228 # tarball was expanded or to verify that a patchfile was correctly applied.
    229 #
    230 # Suggested usage:
    231 # md5sum -c MD5SUMS | grep -v \"OK$\"
    232 #" > MD5SUMS
    233 
    234   find . -type f |
    235   sed -e 's:^\./::' -e '/MD5SUMS/d' |
    236   sort |
    237   xargs md5sum >>MD5SUMS
    238 }
    239 
    240 # Build a single tarfile.  The first argument is the name of the tarfile
    241 # to build, without any suffixes.  They will be added automatically.  The
    242 # rest of the arguments are files or directories to include, and possibly
    243 # other arguments to tar.
    244 
    245 build_tarfile() {
    246   # Get the name of the destination tar file.
    247   TARFILE="$1.tar.xz"
    248   shift
    249 
    250   # Build the tar file itself.
    251   (${TAR} cf - "$@" | ${XZ} > ${TARFILE}) || \
    252     error "Could not build tarfile"
    253   FILE_LIST="${FILE_LIST} ${TARFILE}"
    254 }
    255 
    256 # Build the various tar files for the release.
    257 
    258 build_tarfiles() {
    259   inform "Building tarfiles"
    260 
    261   changedir "${WORKING_DIRECTORY}"
    262 
    263   # The GNU Coding Standards specify that all files should
    264   # world readable.
    265   chmod -R a+r ${SOURCE_DIRECTORY}
    266   # And that all directories have mode 755.
    267   find ${SOURCE_DIRECTORY} -type d -exec chmod 755 {} \;
    268  
    269   # Build one huge tarfile for the entire distribution.
    270   build_tarfile gcc-${RELEASE} `basename ${SOURCE_DIRECTORY}`
    271 }
    272 
    273 # Build .gz files.
    274 build_gzip() {
    275   for f in ${FILE_LIST}; do
    276     target=${f%.xz}.gz
    277     (${XZ} -d -c $f | ${GZIP} > ${target}) || error "Could not create ${target}"
    278   done
    279 }
    280 
    281 # Build diffs against an old release.
    282 build_diffs() {
    283   old_dir=${1%/*}
    284   old_file=${1##*/}
    285   case "$old_file" in
    286     *.tar.xz) old_vers=${old_file%.tar.xz};;
    287     *) old_vers=${old_file%.tar.bz2};;
    288   esac
    289   old_vers=${old_vers#gcc-}
    290   inform "Building diffs against version $old_vers"
    291   for f in gcc; do
    292     if [ -e ${old_dir}/${f}-${old_vers}.tar.xz ]; then
    293       old_tar=${old_dir}/${f}-${old_vers}.tar.xz
    294     else
    295       old_tar=${old_dir}/${f}-${old_vers}.tar.bz2
    296     fi
    297     new_tar=${WORKING_DIRECTORY}/${f}-${RELEASE}.tar.xz
    298     if [ ! -e $old_tar ]; then
    299       inform "$old_tar not found; not generating diff file"
    300     elif [ ! -e $new_tar ]; then
    301       inform "$new_tar not found; not generating diff file"
    302     else
    303       build_diff $old_tar gcc-${old_vers} $new_tar gcc-${RELEASE} \
    304         ${f}-${old_vers}-${RELEASE}.diff.xz
    305     fi
    306   done
    307 }
    308 
    309 # Build an individual diff.
    310 build_diff() {
    311   changedir "${WORKING_DIRECTORY}"
    312   tmpdir=gccdiff.$$
    313   mkdir $tmpdir || error "Could not create directory $tmpdir"
    314   changedir $tmpdir
    315   case "$1" in
    316     *.tar.bz2)
    317       (${BZIP2} -d -c $1 | ${TAR} xf - ) || error "Could not unpack $1 for diffs"
    318       ;;
    319     *.tar.xz)
    320       (${XZ} -d -c $1 | ${TAR} xf - ) || error "Could not unpack $1 for diffs"
    321       ;;
    322   esac
    323   (${XZ} -d -c $3 | ${TAR} xf - ) || error "Could not unpack $3 for diffs"
    324   ${DIFF} $2 $4 > ../${5%.xz}
    325   if [ $? -eq 2 ]; then
    326     error "Trouble making diffs from $1 to $3"
    327   fi
    328   ${XZ} ../${5%.xz} || error "Could not generate ../$5"
    329   changedir ..
    330   rm -rf $tmpdir
    331   FILE_LIST="${FILE_LIST} $5"
    332 }
    333 
    334 # Upload the files to the FTP server.
    335 upload_files() {
    336   inform "Uploading files"
    337 
    338   changedir "${WORKING_DIRECTORY}"
    339 
    340   # Make sure the directory exists on the server.
    341   if [ $LOCAL -eq 0 ]; then
    342     ${SSH} -l ${GCC_USERNAME} ${GCC_HOSTNAME} \
    343       mkdir -p "${FTP_PATH}/diffs"
    344     UPLOAD_PATH="${GCC_USERNAME}@${GCC_HOSTNAME}:${FTP_PATH}"
    345   else
    346     mkdir -p "${FTP_PATH}/diffs" \
    347       || error "Could not create \`${FTP_PATH}'"
    348     UPLOAD_PATH=${FTP_PATH}
    349   fi
    350 
    351   # Then copy files to their respective (sub)directories.
    352   for x in gcc*.gz gcc*.xz; do
    353     if [ -e ${x} ]; then
    354       # Make sure the file will be readable on the server.
    355       chmod a+r ${x}
    356       # Copy it.
    357       case ${x} in
    358         *.diff.*)
    359           SUBDIR="diffs/";
    360           ;;
    361         *)
    362           SUBDIR="";
    363       esac
    364       ${SCP} ${x} ${UPLOAD_PATH}/${SUBDIR} \
    365         || error "Could not upload ${x}"
    366     fi
    367   done
    368 }
    369 
    370 # Print description if snapshot exists.
    371 snapshot_print() {
    372   if [ -e ${RELEASE}/$1 ]; then
    373     hash=`openssl  sha256  ${RELEASE}/$1 | sed -e 's#(.*)##' -e 's# *= *#=#'`
    374     hash2=`openssl sha1 ${RELEASE}/$1 | sed -e 's#(.*)##' -e 's# *= *#=#'`
    375 
    376     printf " %-37s%s\n\n  %s\n  %s\n\n" "$1" "$2" "$hash" "$hash2" \
    377       >> ${SNAPSHOT_README}
    378 
    379      echo "  <tr><td><a href=\"$1\">$1</a></td>" >> ${SNAPSHOT_INDEX}
    380      echo "      <td>$2</td></tr>" >> ${SNAPSHOT_INDEX}
    381   fi
    382 }
    383 
    384 # Announce a snapshot, both on the web and via mail.
    385 announce_snapshot() {
    386   inform "Updating links and READMEs on the FTP server"
    387   
    388   TEXT_DATE=`date --date=$DATE +%B\ %d,\ %Y`
    389   SNAPSHOT_README=${RELEASE}/README
    390   SNAPSHOT_INDEX=${RELEASE}/index.html
    391 
    392   changedir "${SNAPSHOTS_DIR}"
    393   echo \
    394 "Snapshot gcc-"${RELEASE}" is now available on
    395   ftp://gcc.gnu.org/pub/gcc/snapshots/"${RELEASE}"/
    396 and on various mirrors, see http://gcc.gnu.org/mirrors.html for details.
    397 
    398 This snapshot has been generated from the GCC "${BRANCH}" SVN branch
    399 with the following options: "svn://gcc.gnu.org/svn/gcc/${SVNBRANCH} revision ${SVNREV}"
    400 
    401 You'll find:
    402 " > ${SNAPSHOT_README}
    403 
    404   echo \
    405 "<html>
    406 
    407 <head>
    408 <title>GCC "${RELEASE}" Snapshot</title>
    409 </head>
    410 
    411 <body>
    412 <h1>GCC "${RELEASE}" Snapshot</h1>
    413 
    414 <p>The <a href =\"http://gcc.gnu.org/\">GCC Project</a> makes
    415 periodic snapshots of the GCC source tree available to the public
    416 for testing purposes.</p>
    417 	
    418 <p>If you are planning to download and use one of our snapshots, then
    419 we highly recommend you join the GCC developers list.  Details for
    420 how to sign up can be found on the GCC project home page.</p>
    421 
    422 <p>This snapshot has been generated from the GCC "${BRANCH}" SVN branch
    423 with the following options: <code>"svn://gcc.gnu.org/svn/gcc/${SVNBRANCH} revision ${SVNREV}"</code></p>
    424 
    425 <table>" > ${SNAPSHOT_INDEX}
    426        
    427   snapshot_print gcc-${RELEASE}.tar.xz "Complete GCC"
    428 
    429   echo \
    430 "Diffs from "${BRANCH}"-"${LAST_DATE}" are available in the diffs/ subdirectory.
    431 
    432 When a particular snapshot is ready for public consumption the LATEST-"${BRANCH}"
    433 link is updated and a message is sent to the gcc list.  Please do not use
    434 a snapshot before it has been announced that way." >> ${SNAPSHOT_README}
    435 
    436   echo \
    437 "</table>
    438 <p>Diffs from "${BRANCH}"-"${LAST_DATE}" are available in the
    439 <a href=\"diffs/\">diffs/ subdirectory</a>.</p>
    440 
    441 <p>When a particular snapshot is ready for public consumption the LATEST-"${BRANCH}"
    442 link is updated and a message is sent to the gcc list.  Please do not use
    443 a snapshot before it has been announced that way.</p>
    444 
    445 <hr />
    446 
    447 <address>
    448 <a href=\"mailto:gcc (at] gcc.gnu.org\">gcc (at] gcc.gnu.org</a>
    449 <br />
    450 Last modified "${TEXT_DATE}"
    451 </address>
    452 </body>
    453 
    454 </html>" >> ${SNAPSHOT_INDEX}
    455 
    456   rm -f LATEST-${BRANCH}
    457   ln -s ${RELEASE} LATEST-${BRANCH}
    458 
    459   inform "Sending mail"
    460 
    461   export QMAILHOST=gcc.gnu.org
    462   mail -s "gcc-${RELEASE} is now available" gcc@gcc.gnu.org < ${SNAPSHOT_README}
    463 }
    464 
    465 ########################################################################
    466 # Initialization
    467 ########################################################################
    468 
    469 LC_ALL=C
    470 export LC_ALL
    471 
    472 # Today's date.
    473 DATE=`date "+%Y%m%d"`
    474 LONG_DATE=`date "+%Y-%m-%d"`
    475 
    476 SVN=${SVN:-svn}
    477 # The CVS server containing the GCC repository.
    478 SVN_SERVER="gcc.gnu.org"
    479 # The path to the repository on that server.
    480 SVN_REPOSITORY="/svn/gcc"
    481 # The username to use when connecting to the server.
    482 SVN_USERNAME="${USER}"
    483 
    484 # The machine to which files will be uploaded.
    485 GCC_HOSTNAME="gcc.gnu.org"
    486 # The name of the account on the machine to which files are uploaded.
    487 GCC_USERNAME="gccadmin"
    488 # The directory in which the files will be placed (do not use ~user syntax).
    489 FTP_PATH=/var/ftp/pub/gcc
    490 # The directory in which snapshots will be placed.
    491 SNAPSHOTS_DIR=${FTP_PATH}/snapshots
    492 
    493 # The major number for the release.  For release `3.0.2' this would be 
    494 # `3'
    495 RELEASE_MAJOR=""
    496 # The minor number for the release.  For release `3.0.2' this would be
    497 # `0'.
    498 RELEASE_MINOR=""
    499 # The revision number for the release.  For release `3.0.2' this would
    500 # be `2'.
    501 RELEASE_REVISION=""
    502 # The complete name of the release.
    503 RELEASE=""
    504 
    505 # The name of the branch from which the release should be made, in a 
    506 # user-friendly form.
    507 BRANCH=""
    508 
    509 # The name of the branch from which the release should be made, as used
    510 # for our version control system.
    511 SVNBRANCH=""
    512 
    513 # The tag to apply to the sources used for the release.
    514 TAG=""
    515 
    516 # The old tarballs from which to generate diffs.
    517 OLD_TARS=""
    518 
    519 # The directory that will be used to construct the release.  The
    520 # release itself will be placed in a subdirectory of this directory.
    521 DESTINATION=${HOME}
    522 # The subdirectory.
    523 WORKING_DIRECTORY=""
    524 # The directory that will contain the GCC sources.
    525 SOURCE_DIRECTORY=""
    526 
    527 # Non-zero if this is the final release, rather than a prerelease.
    528 FINAL=0
    529 
    530 # Non-zero if we are building a snapshot, and don't build gcc or
    531 # include generated files.
    532 SNAPSHOT=0
    533 
    534 # Non-zero if we are running locally on gcc.gnu.org, and use local CVS
    535 # and copy directly to the FTP directory.
    536 LOCAL=0
    537 
    538 # Major operation modes.
    539 MODE_GZIP=0
    540 MODE_DIFFS=0
    541 MODE_SOURCES=0
    542 MODE_TARFILES=0
    543 MODE_UPLOAD=0
    544 
    545 # List of archive files generated; used to create .gz files from .xz.
    546 FILE_LIST=""
    547 
    548 # Programs we use.
    549 
    550 BZIP2="${BZIP2:-bzip2}"
    551 XZ="${XZ:-xz --best}"
    552 CVS="${CVS:-cvs -f -Q -z9}"
    553 DIFF="${DIFF:-diff -Nrcpad}"
    554 ENV="${ENV:-env}"
    555 GZIP="${GZIP:-gzip --best}"
    556 SCP="${SCP:-scp -p}"
    557 SSH="${SSH:-ssh}"
    558 TAR="${TAR:-tar}"
    559 
    560 ########################################################################
    561 # Command Line Processing
    562 ########################################################################
    563 
    564 # Parse the options.
    565 while getopts "d:fr:u:t:p:s:l" ARG; do
    566     case $ARG in
    567     d)    DESTINATION="${OPTARG}";;
    568     r)    RELEASE="${OPTARG}";;
    569     t)    TAG="${OPTARG}";;
    570     u)    SVN_USERNAME="${OPTARG}";;
    571     f)    FINAL=1;;
    572     s)    SNAPSHOT=1
    573           BRANCH=${OPTARG%:*}
    574           SVNBRANCH=${OPTARG#*:}
    575           ;;
    576     l)    LOCAL=1
    577 	  SCP=cp
    578 	  PATH=~:/usr/local/bin:$PATH;;
    579     p)    OLD_TARS="${OLD_TARS} ${OPTARG}"
    580           if [ ! -f ${OPTARG} ]; then
    581 	    error "-p argument must name a tarball"
    582 	  fi;;
    583     \?)   usage;;
    584     esac
    585 done
    586 shift `expr ${OPTIND} - 1`
    587 
    588 # Handle the major modes.
    589 while [ $# -ne 0 ]; do
    590     case $1 in
    591     diffs)    MODE_DIFFS=1;;
    592     gzip)     MODE_GZIP=1;;
    593     sources)  MODE_SOURCES=1;;
    594     tarfiles) MODE_TARFILES=1;;
    595     upload)   MODE_UPLOAD=1;;
    596     all)      MODE_SOURCES=1; MODE_TARFILES=1; MODE_DIFFS=1; MODE_UPLOAD=1;
    597               if [ $SNAPSHOT -ne 1 ]; then
    598                 # Only for releases and pre-releases.
    599                 MODE_GZIP=1;
    600               fi
    601               ;;
    602     *)        error "Unknown mode $1";;
    603     esac
    604     shift
    605 done
    606 
    607 # Perform consistency checking.
    608 if [ ${LOCAL} -eq 0 ] && [ -z ${SVN_USERNAME} ]; then
    609   error "No username specified"
    610 fi
    611 
    612 if [ ! -d ${DESTINATION} ]; then
    613   error "\`${DESTINATION}' is not a directory"
    614 fi
    615 
    616 if [ $SNAPSHOT -eq 0 ]; then
    617   if [ -z ${RELEASE} ]; then
    618     error "No release number specified"
    619   fi
    620 
    621   # Compute the major and minor release numbers.
    622   RELEASE_MAJOR=`echo $RELEASE | awk --assign FS=. '{ print $1; }'`
    623   RELEASE_MINOR=`echo $RELEASE | awk --assign FS=. '{ print $2; }'`
    624   RELEASE_REVISION=`echo $RELEASE | awk --assign FS=. '{ print $3; }'`
    625 
    626   if [ -z "${RELEASE_MAJOR}" ] || [ -z "${RELEASE_MINOR}" ]; then
    627     error "Release number \`${RELEASE}' is invalid"
    628   fi
    629 
    630   # Compute the full name of the release.
    631   if [ -z "${RELEASE_REVISION}" ]; then
    632     RELEASE="${RELEASE_MAJOR}.${RELEASE_MINOR}"
    633   else
    634     RELEASE="${RELEASE_MAJOR}.${RELEASE_MINOR}.${RELEASE_REVISION}"
    635   fi
    636 
    637   # Compute the name of the branch, which is based solely on the major
    638   # and minor release numbers.
    639   if [ ${RELEASE_MAJOR} -ge 5 ]; then
    640     SVNBRANCH="branches/gcc-${RELEASE_MAJOR}-branch"
    641   else
    642     SVNBRANCH="branches/gcc-${RELEASE_MAJOR}_${RELEASE_MINOR}-branch"
    643   fi
    644 
    645   # If this is not a final release, set various parameters accordingly.
    646   if [ ${FINAL} -ne 1 ]; then
    647     RELEASE="${RELEASE}-RC-${DATE}"
    648     FTP_PATH="${SNAPSHOTS_DIR}/${RELEASE}"
    649   else
    650     FTP_PATH="${FTP_PATH}/releases/gcc-${RELEASE}/"
    651   fi
    652 else
    653   RELEASE=${BRANCH}-${DATE}
    654   FTP_PATH="${FTP_PATH}/snapshots/${RELEASE}"
    655 
    656   # If diffs are requested when building locally on gcc.gnu.org, we (usually)
    657   # know what the last snapshot date was and take the corresponding tarballs,
    658   # unless the user specified tarballs explicitly.
    659   if [ $MODE_DIFFS -ne 0 ] && [ $LOCAL -ne 0 ] && [ -z "${OLD_TARS}" ]; then
    660     LAST_DATE=`cat ~/.snapshot_date-${BRANCH}`
    661     OLD_TARS=${SNAPSHOTS_DIR}/${BRANCH}-${LAST_DATE}/gcc-${BRANCH}-${LAST_DATE}.tar.bz2
    662     if [ ! -e $OLD_TARS ]; then
    663       OLD_TARS=${SNAPSHOTS_DIR}/${BRANCH}-${LAST_DATE}/gcc-${BRANCH}-${LAST_DATE}.tar.xz
    664     fi
    665   fi
    666 fi
    667 
    668 # Compute the name of the WORKING_DIRECTORY and the SOURCE_DIRECTORY.
    669 WORKING_DIRECTORY="${DESTINATION}/gcc-${RELEASE}"
    670 SOURCE_DIRECTORY="${WORKING_DIRECTORY}/gcc-${RELEASE}"
    671 
    672 # Set up SVNROOT.
    673 if [ $LOCAL -eq 0 ]; then
    674     SVNROOT="svn+ssh://${SVN_USERNAME}@${SVN_SERVER}${SVN_REPOSITORY}"
    675 else
    676     SVNROOT="file:///svn/gcc"
    677 fi
    678 export SVNROOT
    679 
    680 ########################################################################
    681 # Main Program
    682 ########################################################################
    683 
    684 # Set the timezone to UTC
    685 TZ="UTC0"
    686 export TZ
    687 
    688 # Build the source directory.
    689 
    690 if [ $MODE_SOURCES -ne 0 ]; then
    691   build_sources
    692 fi
    693 
    694 # Build the tar files.
    695 
    696 if [ $MODE_TARFILES -ne 0 ]; then
    697   build_tarfiles
    698 fi
    699 
    700 # Build diffs
    701 
    702 if [ $MODE_DIFFS -ne 0 ]; then
    703   # Possibly build diffs.
    704   if [ -n "$OLD_TARS" ]; then
    705     for old_tar in $OLD_TARS; do
    706       build_diffs $old_tar
    707     done
    708   fi
    709 fi
    710 
    711 # Build gzip files
    712 if [ $MODE_GZIP -ne 0 ]; then
    713   build_gzip
    714 fi
    715 
    716 # Upload them to the FTP server.
    717 if [ $MODE_UPLOAD -ne 0 ]; then
    718   upload_files
    719 
    720   # For snapshots, make some further updates.
    721   if [ $SNAPSHOT -ne 0 ] && [ $LOCAL -ne 0 ]; then
    722     announce_snapshot
    723 
    724     # Update snapshot date file.
    725     changedir ~
    726     echo $DATE > .snapshot_date-${BRANCH}
    727 
    728     # Remove working directory
    729     rm -rf ${WORKING_DIRECTORY}
    730   fi
    731 fi
    732