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