Fix make-array transforms.
[sbcl.git] / release.sh
index 6a56997..7003e7e 100755 (executable)
-#! /bin/sh
+#!/bin/bash
+
+# Sourceforge username
+SFUSER=${SFUSER:-$USER}
 
 set -ex
 
-cd "$1"
+## Parse command line arguments
+
+usage () {
+    if ! [ -z "$1" ]
+    then
+        echo $1
+    fi
+    cat <<EOF
+
+usage: $0 [-s] VERSION-NUMBER [REV]
+
+  This script frobs NEWS, makes a "release" commit + tag of the
+  repository in \$PWD/release.sbcl .
+
+  It then clones the repository to a new clean directory and does the
+  following:
+  - Builds source tarball
+  - Builds a SBCL for self-build
+  - Builds x86-64 binaries
+  - Uploads binaries
+  - Pushes the repository
+  - Builds and uploads the documentation
+
+  If -s is given, then use the gpg-sign mechanism of "git tag". You
+  will need to have your gpg secret key handy.
+
+  if REV is given, it is the git revision to build into a release.
+  Default is origin/master.
+
+  ENVIRONMENT:
+
+  SFUSER: Sourceforge username. Defaults to \$USER
+  SBCL_RELEASE_DIR: Absolute path to directory containing all the build
+    artifacts. If not defined, a new build directory is created in \$PWD.
+
+EOF
+    exit 1
+}
+
+if [ "-s" = "$1" ] || [ "--sign" = "$1" ]
+then
+    sign="-s"; shift
+else
+    sign=""
+fi
+
+## Verify version number
+
+if [ -z "$1" ]
+then
+    usage "No version number."
+else
+    VERSION=$1; shift
+    echo $VERSION | perl -pe 'die "Invalid version number: $_\n" if !/^\d+\.\d+\.\d+$/'
+fi
+
+if [ -z "$1" ]
+then
+    rev=origin/master
+else
+    rev=$1; shift
+    type=$(git cat-file -t "$rev" 2> /dev/null || echo "unknown")
+    if ([ "tag" != "$type" ] && [ "commit" != "$type" ])
+    then
+        usage "$rev is $type, not a tag or a commit."
+    fi
+fi
+
+if ! [ -z "$@" ]
+then
+    usage "Extra command-line arguments: $@"
+fi
+
+SBCL_RELEASE_DIR=${SBCL_RELEASE_DIR:-$(mktemp -d $PWD/sbcl-release-dir-$(date +%Y%m%d)-XXXXXXXXX)}
+SBCL_DIR=$SBCL_RELEASE_DIR/sbcl-$VERSION
+GIT_DIR=$PWD/release.sbcl
+LOGFILE=$SBCL_RELEASE_DIR/log.txt
+
+## Frob the git repository, and clone the repo to a clean build directory.
+
+if [ ! -d $SBCL_DIR ]; then
+  cd $GIT_DIR
+
+  sbcl_directory="$(cd "$(dirname $0)"; pwd)"
+
+  branch_name="release-$(date '+%s')"
+  original_branch="$(git describe --all --contains HEAD)"
+
+  echo "Checking that the tree is clean."
+  if ! [ $(git status --porcelain | wc -l) = 0 ]
+  then
+      echo "There are uncommitted / unpushed changes in this checkout!"
+      git status
+      exit 1
+  fi
+
+  ## Perform the necessary changes to the NEWS file:
+
+  echo "Munging NEWS"
+  sed -i.orig "/^changes relative to sbcl-.*:/ s/changes/changes in sbcl-$VERSION/ " NEWS
+  rm -f NEWS.orig
+  if ! grep "^changes in sbcl-$VERSION relative to" NEWS > /dev/null
+  then
+      echo "NEWS munging failed!"
+      exit 1
+  fi
+
+  ## Commit
+
+  cd "$sbcl_directory"
+
+  echo "Committing release version."
+  git add NEWS
+  git commit -m "$VERSION: will be tagged as \"sbcl-$VERSION\""
+
+  ## Make release notes
+
+  if [ ! -f $SBCL_RELEASE_DIR/sbcl-$VERSION-release-notes.txt ]; then
+    awk "BEGIN { state = 0 }
+     /^changes in sbcl-/ { state = 0 } 
+     /^changes in sbcl-$VERSION/ { state = 1 }
+     { if(state == 1) print \$0 }" < $GIT_DIR/NEWS > $SBCL_RELEASE_DIR/sbcl-$VERSION-release-notes.txt
+  fi
+
+  ## Tag
+
+  tag="sbcl-$VERSION"
+  echo "Tagging as $tag"
+  git tag $sign -F $SBCL_RELEASE_DIR/sbcl-$VERSION-release-notes.txt "$tag"
+
+  git clone $GIT_DIR $SBCL_DIR
+fi
+
+## Make the source tarball.
+
+if [ ! \( -f $SBCL_RELEASE_DIR/sbcl-$VERSION-source.tar -o -f $SBCL_RELEASE_DIR/sbcl-$VERSION-source.tar.bz2 \) ]; then
+  cd $SBCL_DIR
+  (. $SBCL_DIR/generate-version.sh; generate_version)
+  mkdir -p CVS
+  sh ./distclean.sh
+  rm -rf .git
+
+  cd $SBCL_RELEASE_DIR
+  sh sbcl-$VERSION/source-distribution.sh sbcl-$VERSION
+
+  mv $SBCL_DIR $SBCL_DIR.git
+
+  tar xvf sbcl-$VERSION-source.tar
+fi
+
+## Build x86-64 binary for bootstrap.
+
+if [ ! -d $SBCL_RELEASE_DIR/bin ]; then
+  cd $SBCL_DIR
+  nice -20 ./make.sh >$LOGFILE 2>&1
+
+  cd tests
+  nice -20 sh ./run-tests.sh >>$LOGFILE 2>&1
+  mkdir -p $SBCL_RELEASE_DIR/bin
+  cp $SBCL_DIR/src/runtime/sbcl $SBCL_RELEASE_DIR/bin/sbcl
+  cp $SBCL_DIR/output/sbcl.core $SBCL_RELEASE_DIR/bin/sbcl.core
+fi
+
+## Build x86-64 release binary.
+
+if [ ! -d $SBCL_RELEASE_DIR/sbcl-$VERSION-x86-64-linux ]; then
+  cd $SBCL_DIR
+  sh clean.sh
+  nice -20 ./make.sh "$SBCL_RELEASE_DIR/bin/sbcl --core $SBCL_RELEASE_DIR/bin/sbcl.core --no-userinit" >> $LOGFILE 2>&1
+  cd doc && sh ./make-doc.sh
+  cd $SBCL_RELEASE_DIR
+
+  ln -s $SBCL_DIR $SBCL_RELEASE_DIR/sbcl-$VERSION-x86-64-linux
+  sh $SBCL_DIR/binary-distribution.sh sbcl-$VERSION-x86-64-linux
+  sh $SBCL_DIR/html-distribution.sh sbcl-$VERSION
+fi
+
+## Build x86 release binary.
+
+#if [ ! -d $SBCL_RELEASE_DIR/sbcl-$VERSION-x86-linux ]; then
+#  cd $SBCL_DIR
+#  sh clean.sh
+#  export SBCL_ARCH=x86
+#  export PATH=/scratch/src/release/x86-gcc-wrapper:$PATH
+#  nice -20 ./make.sh "$SBCL_RELEASE_DIR/bin/sbcl --core $SBCL_RELEASE_DIR/bin/s#bcl.core --no-userinit" >> $LOGFILE 2>&1
+#  cd tests
+#  nice -20 sh ./run-tests.sh >>$LOGFILE 2>&
+
+#  cd $SBCL_RELEASE_DIR
+#  ln -s $SBCL_DIR $SBCL_RELEASE_DIR/sbcl-$VERSION-x86-linux
+#  sh $SBCL_DIR/binary-distribution.sh sbcl-$VERSION-x86-linux
+#fi
+
+## Checksum
+
+if [ ! -f $SBCL_RELEASE_DIR/sbcl-$VERSION-$SFUSER ]; then
+  cd $SBCL_RELEASE_DIR
+  echo "The SHA256 checksums of the following distribution files are:" > sbcl-$VERSION-$SFUSER
+  echo >> sbcl-$VERSION-$SFUSER
+  sha256sum sbcl-$VERSION*.tar >> sbcl-$VERSION-$SFUSER
+  bzip2 sbcl-$VERSION*.tar
+fi
+
+## Bug closing email
+
+if [ ! -f $SBCL_RELEASE_DIR/sbcl-$VERSION-bugmail.txt ]; then
+  cd $SBCL_RELEASE_DIR
+  echo Bugs fixed by sbcl-$VERSION release > sbcl-$VERSION-bugmail.txt
+ for bugnum in $(egrep -o "#[1-9][0-9][0-9][0-9][0-9][0-9]+" sbcl-$VERSION-release-notes.txt | sed s/#// | sort -n); do 
+    printf "\n bug %s\n status fixreleased" $bugnum >> sbcl-$VERSION-bugmail.txt
+  done
+  echo >> sbcl-$VERSION-bugmail.txt
+fi
+
+## Sign
 
-sbcl_directory="$(pwd)"
+if [ ! -f $SBCL_RELEASE_DIR/sbcl-$VERSION-$SFUSER.asc ]; then
+  cd $SBCL_RELEASE_DIR
+  gpg -sta $SBCL_RELEASE_DIR/sbcl-$VERSION-$SFUSER
+fi
 
-cd "$sbcl_directory"
+## Upload to sf.net
 
-tmpfile=$(mktemp --tmpdir sbcl-build-$(date +%Y%m%d)-XXXXXXXXX)
+if [ ! -f $SBCL_RELEASE_DIR/uploaded ]; then
 
-./make.sh >$tmpfile 2>&1
+  read -n 1 -p "Ok to upload? " A; echo  
+  if [ $A \!= "y" ]; then
+    exit 1
+  fi
 
-./src/runtime/sbcl --version | grep '^SBCL [1-9][0-9]*\.[0-9]\+\.[1-9][0-9]*$'
+  cd $SBCL_RELEASE_DIR
+cat > $SBCL_RELEASE_DIR/sftp-batch <<EOF
+cd /home/frs/project/s/sb/sbcl/sbcl
+mkdir $VERSION
+chmod 775 $VERSION
+cd $VERSION
+put sbcl-$VERSION-$SFUSER.asc
+put sbcl-$VERSION-x86-64-linux-binary.tar.bz2
+put sbcl-$VERSION-source.tar.bz2
+put sbcl-$VERSION-documentation-html.tar.bz2
+put sbcl-$VERSION-release-notes.txt
+put sbcl-$VERSION-release-notes.txt README
+EOF
+  sftp -b $SBCL_RELEASE_DIR/sftp-batch $SFUSER,sbcl@frs.sourceforge.net 
+  touch uploaded
+fi
 
-version=$(./src/runtime/sbcl --version | awk '{print $2}')
-grep "^changes in sbcl-$version relative to" NEWS
+## Push
 
-cd tests
-sh ./run-tests.sh >>$tmpfile 2>&1
-cd ..
+if [ ! -f $SBCL_RELEASE_DIR/sbcl-git-pushed ]; then
+  cd $GIT_DIR
+  git diff origin || true
+  
+  read -n 1 -p "Ok? " A; echo  
 
-cp ./src/runtime/sbcl /tmp/sbcl-$version
-cp ./output/sbcl.core /tmp/sbcl-$version.core
+  if [ $A = "y" ]; then
+    git push
+    git push --tags
+    touch $SBCL_RELEASE_DIR/sbcl-git-pushed
+  else
+    exit 1
+  fi
+fi
 
-./make.sh "/tmp/sbcl-$version --core /tmp/sbcl-$version.core" > /tmp/sbcl-$version-build-log 2>&1
-cd doc && sh ./make-doc.sh
+## Build + push documentation
 
-cd ..
+if [ ! -f $SBCL_RELEASE_DIR/sbcl-page-uploaded ]; then
+  cp -af $GIT_DIR/../sbcl-page $SBCL_RELEASE_DIR
+  cd $SBCL_RELEASE_DIR/sbcl-page/sbcl
+  git fetch
+  cd $SBCL_RELEASE_DIR/sbcl-page
+  git pull
+  git submodule update
+  cp $SBCL_DIR/NEWS .
+  perl -i -pe "s/(:x86-64 :linux :available) \".*\"/\$1 \"$VERSION\"/" \
+    platform-support-platforms.lisp
 
-rm /tmp/sbcl-$version /tmp/sbcl-$version.core
+  export LC_CTYPE=en_GB.utf8
 
-cp -a "$sbcl_directory" /tmp/sbcl-$version
+  ## FIXME: this depends on the sbcl-$VERSION tag being visible on sf
+  ## git, not just the local machine (because of the submodule), which
+  ## means that the release.sbcl should have as its origin sf not
+  ## another local copy.
+  nice -20 make manual generate-pages SBCL_TAG=sbcl-$VERSION >>$LOGFILE 2>&1
 
-ln -s /tmp/sbcl-$version /tmp/sbcl-$version-x86-linux
-cd /tmp/
-sh sbcl-$version/binary-distribution.sh sbcl-$version-x86-linux
-sh sbcl-$version/html-distribution.sh sbcl-$version
-cd sbcl-$version
-sh ./distclean.sh
-cd ..
-sh sbcl-$version/source-distribution.sh sbcl-$version
+  COMMIT=false
 
-awk "BEGIN { state = 0 }
- /^changes in sbcl-/ { state = 0 } 
- /^changes in sbcl-$version/ { state = 1 }
- { if(state == 1) print \$0 }" < sbcl-$version/NEWS > sbcl-$version-release-notes.txt
+  git diff || COMMIT=true  
+  links -dump platform-table.html
 
-echo "The SHA256 checksums of the following distribution files are:" > sbcl-$version-crhodes
-echo >> sbcl-$version-crhodes
-sha256sum sbcl-$version*.tar >> sbcl-$version-crhodes
-bzip2 /tmp/sbcl-$version*.tar
+  read -n 1 -p "Ok? " A; echo  
 
-echo Bugs fixed by sbcl-$version release > sbcl-$version-bugmail.txt
-for bugnum in $(egrep -o "#[1-9][0-9][0-9][0-9][0-9][0-9]+" sbcl-$version-release-notes.txt | sed s/#// | sort -n)
-do 
-  printf "\n bug %s\n status fixreleased" $bugnum >> sbcl-$version-bugmail.txt
-done
-echo >> sbcl-$version-bugmail.txt
+  if [ $A = "y" ]; then
+    if [ $COMMIT ]; then
+      git commit -a -m "Update for $VERSION"
+      git push
+    fi
+    make upload-pages upload-manual SBCL_TAG=sbcl-$VERSION
+    touch $SBCL_RELEASE_DIR/sbcl-page-uploaded
+  else
+    exit 1
+  fi
+fi
 
 set +x
 
 echo TODO:
-echo
-echo cvs commit -m "\"$version: will be tagged as sbcl_$(echo $version | sed 's/\./_/g')\""
-echo cvs tag sbcl_$(echo $version | sed 's/\./_/g')
-echo gpg -sta /tmp/sbcl-$version-crhodes
-echo sftp crhodes,sbcl@frs.sourceforge.net
-echo \* cd /home/frs/project/s/sb/sbcl/sbcl
-echo \* mkdir $version
-echo \* chmod 775 $version
-echo \* cd $version
-echo \* put sbcl-$version-crhodes.asc
-echo \* put sbcl-$version-x86-linux-binary.tar.bz2
-echo \* put sbcl-$version-source.tar.bz2
-echo \* put sbcl-$version-documentation-html.tar.bz2
-echo \* put sbcl-$version-release-notes.txt
 echo 
 echo perform administrative tasks:
 echo 
 echo \* https://sourceforge.net/project/admin/?group_id=1373
-echo \* In the File Manager interface, click on the release notes file
-echo \ \ and tick the release notes box.
-echo \* In the File Manager interface, click on the source tarball and
-echo \ \ select as default download for all OSes.
+echo \* In the File Manager interface, click on \"information\" for the
+echo \ \ source tarball and select as default download for all OSes.
 echo \* mail sbcl-announce
-echo \* check and send sbcl-$version-bugmail.txt to edit@bugs.launchpad.net
+echo \* check and send sbcl-$VERSION-bugmail.txt to edit@bugs.launchpad.net
 echo \ \ '(sign: C-c RET s p)'
-echo \* update \#lisp IRC topic
-echo \* update sbcl website
+echo "* update #lisp IRC topic (requires channel ops)"