Home | History | Annotate | Download | only in tools
      1 #!/bin/bash
      2 # Copyright 2012 the V8 project authors. All rights reserved.
      3 # Redistribution and use in source and binary forms, with or without
      4 # modification, are permitted provided that the following conditions are
      5 # met:
      6 #
      7 #     * Redistributions of source code must retain the above copyright
      8 #       notice, this list of conditions and the following disclaimer.
      9 #     * Redistributions in binary form must reproduce the above
     10 #       copyright notice, this list of conditions and the following
     11 #       disclaimer in the documentation and/or other materials provided
     12 #       with the distribution.
     13 #     * Neither the name of Google Inc. nor the names of its
     14 #       contributors may be used to endorse or promote products derived
     15 #       from this software without specific prior written permission.
     16 #
     17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     18 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     19 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     20 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28 
     29 ########## Global variable definitions
     30 
     31 BRANCHNAME=prepare-merge
     32 PERSISTFILE_BASENAME=/tmp/v8-merge-to-branch-tempfile
     33 ALREADY_MERGING_SENTINEL_FILE="$PERSISTFILE_BASENAME-already-merging"
     34 COMMIT_HASHES_FILE="$PERSISTFILE_BASENAME-PATCH_COMMIT_HASHES"
     35 TEMPORARY_PATCH_FILE="$PERSISTFILE_BASENAME-temporary-patch"
     36 
     37 ########## Function definitions
     38 
     39 source $(dirname $BASH_SOURCE)/common-includes.sh
     40 
     41 usage() {
     42 cat << EOF
     43 usage: $0 [OPTIONS]... [BRANCH] [REVISION]...
     44 
     45 Performs the necessary steps to merge revisions from bleeding_edge
     46 to other branches, including trunk.
     47 
     48 OPTIONS:
     49   -h    Show this message
     50   -s    Specify the step where to start work. Default: 0.
     51   -p    Specify a patch file to apply as part of the merge
     52 EOF
     53 }
     54 
     55 persist_patch_commit_hashes() {
     56   echo "PATCH_COMMIT_HASHES=( ${PATCH_COMMIT_HASHES[@]} )" > $COMMIT_HASHES_FILE
     57 }
     58 
     59 restore_patch_commit_hashes() {
     60   source $COMMIT_HASHES_FILE
     61 }
     62 
     63 restore_patch_commit_hashes_if_unset() {
     64   [[ "${#PATCH_COMMIT_HASHES[@]}" == 0 ]] && restore_patch_commit_hashes
     65   [[ "${#PATCH_COMMIT_HASHES[@]}" == 0 ]] && [[ -z "$EXTRA_PATCH" ]] && \
     66       die "Variable PATCH_COMMIT_HASHES could not be restored."
     67 }
     68 
     69 ########## Option parsing
     70 
     71 while getopts ":hs:fp:" OPTION ; do
     72   case $OPTION in
     73     h)  usage
     74         exit 0
     75         ;;
     76     p)  EXTRA_PATCH=$OPTARG
     77         ;;
     78     f)  rm -f "$ALREADY_MERGING_SENTINEL_FILE"
     79         ;;
     80     s)  START_STEP=$OPTARG
     81         ;;
     82     ?)  echo "Illegal option: -$OPTARG"
     83         usage
     84         exit 1
     85         ;;
     86   esac
     87 done
     88 let OPTION_COUNT=$OPTIND-1
     89 shift $OPTION_COUNT
     90 
     91 ########## Regular workflow
     92 
     93 # If there is a merge in progress, abort.
     94 [[ -e "$ALREADY_MERGING_SENTINEL_FILE" ]] && [[ $START_STEP -eq 0 ]] \
     95    && die "A merge is already in progress"
     96 touch "$ALREADY_MERGING_SENTINEL_FILE"
     97 
     98 initial_environment_checks
     99 
    100 if [ $START_STEP -le $CURRENT_STEP ] ; then
    101   if [ ${#@} -lt 2 ] && [ -z "$EXTRA_PATCH" ] ; then
    102     die "Either a patch file or revision numbers must be specified"
    103   fi
    104   echo ">>> Step $CURRENT_STEP: Preparation"
    105   MERGE_TO_BRANCH=$1
    106   [[ -n "$MERGE_TO_BRANCH" ]] || die "Please specify a branch to merge to"
    107   shift
    108   persist "MERGE_TO_BRANCH"
    109   common_prepare
    110 fi
    111 
    112 let CURRENT_STEP+=1
    113 if [ $START_STEP -le $CURRENT_STEP ] ; then
    114   echo ">>> Step $CURRENT_STEP: Create a fresh branch for the patch."
    115   restore_if_unset "MERGE_TO_BRANCH"
    116   git checkout -b $BRANCHNAME svn/$MERGE_TO_BRANCH \
    117     || die "Creating branch $BRANCHNAME failed."
    118 fi
    119 
    120 let CURRENT_STEP+=1
    121 if [ $START_STEP -le $CURRENT_STEP ] ; then
    122   echo ">>> Step $CURRENT_STEP: Find the git \
    123 revisions associated with the patches."
    124   current=0
    125   for REVISION in "$@" ; do
    126     NEXT_HASH=$(git svn find-rev "r$REVISION" svn/bleeding_edge)
    127     [[ -n "$NEXT_HASH" ]] \
    128       || die "Cannot determine git hash for r$REVISION"
    129     PATCH_COMMIT_HASHES[$current]="$NEXT_HASH"
    130     [[ -n "$REVISION_LIST" ]] && REVISION_LIST="$REVISION_LIST,"
    131     REVISION_LIST="$REVISION_LIST r$REVISION"
    132     let current+=1
    133   done
    134   if [ -z "$REVISION_LIST" ] ; then
    135     NEW_COMMIT_MSG="Applied patch to $MERGE_TO_BRANCH branch."
    136   else
    137     NEW_COMMIT_MSG="Merged$REVISION_LIST into $MERGE_TO_BRANCH branch."
    138   fi;
    139 
    140   echo "$NEW_COMMIT_MSG" > $COMMITMSG_FILE
    141   echo "" >> $COMMITMSG_FILE
    142   for HASH in ${PATCH_COMMIT_HASHES[@]} ; do
    143     PATCH_MERGE_DESCRIPTION=$(git log -1 --format=%s $HASH)
    144     echo "$PATCH_MERGE_DESCRIPTION" >> $COMMITMSG_FILE
    145     echo "" >> $COMMITMSG_FILE
    146   done
    147   for HASH in ${PATCH_COMMIT_HASHES[@]} ; do
    148     BUG=$(git log -1 $HASH | grep "BUG=" | awk -F '=' '{print $NF}')
    149     if [ -n "$BUG" ] ; then
    150       [[ -n "$BUG_AGGREGATE" ]] && BUG_AGGREGATE="$BUG_AGGREGATE,"
    151       BUG_AGGREGATE="$BUG_AGGREGATE$BUG"
    152     fi
    153   done
    154   if [ -n "$BUG_AGGREGATE" ] ; then
    155     echo "BUG=$BUG_AGGREGATE" >> $COMMITMSG_FILE
    156   fi
    157   persist "NEW_COMMIT_MSG"
    158   persist "REVISION_LIST"
    159   persist_patch_commit_hashes
    160 fi
    161 
    162 let CURRENT_STEP+=1
    163 if [ $START_STEP -le $CURRENT_STEP ] ; then
    164   echo ">>> Step $CURRENT_STEP: Apply patches for selected revisions."
    165   restore_if_unset "MERGE_TO_BRANCH"
    166   restore_patch_commit_hashes_if_unset "PATCH_COMMIT_HASHES"
    167   rm -f "$TOUCHED_FILES_FILE"
    168   for HASH in ${PATCH_COMMIT_HASHES[@]} ; do
    169     echo "Applying patch for $HASH to $MERGE_TO_BRANCH..."
    170     git log -1 -p $HASH > "$TEMPORARY_PATCH_FILE"
    171     apply_patch "$TEMPORARY_PATCH_FILE"
    172   done
    173   if [ -n "$EXTRA_PATCH" ] ; then
    174     apply_patch "$EXTRA_PATCH"
    175   fi
    176   stage_files
    177 fi
    178 
    179 let CURRENT_STEP+=1
    180 if [ $START_STEP -le $CURRENT_STEP ] ; then
    181   echo ">>> Step $CURRENT_STEP: Prepare $VERSION_FILE."
    182   # These version numbers are used again for creating the tag
    183   read_and_persist_version
    184 fi
    185 
    186 let CURRENT_STEP+=1
    187 if [ $START_STEP -le $CURRENT_STEP ] ; then
    188   echo ">>> Step $CURRENT_STEP: Increment version number."
    189   restore_if_unset "PATCH"
    190   NEWPATCH=$(($PATCH + 1))
    191   confirm "Automatically increment PATCH_LEVEL? (Saying 'n' will fire up \
    192 your EDITOR on $VERSION_FILE so you can make arbitrary changes. When \
    193 you're done, save the file and exit your EDITOR.)"
    194   if [ $? -eq 0 ] ; then
    195     sed -e "/#define PATCH_LEVEL/s/[0-9]*$/$NEWPATCH/" \
    196         -i "$VERSION_FILE"
    197   else
    198     $EDITOR "$VERSION_FILE"
    199   fi
    200   read_and_persist_version "NEW"
    201 fi
    202 
    203 let CURRENT_STEP+=1
    204 if [ $START_STEP -le $CURRENT_STEP ] ; then
    205   echo ">>> Step $CURRENT_STEP: Commit to local branch."
    206   git commit -a -F "$COMMITMSG_FILE" \
    207     || die "'git commit -a' failed."
    208 fi
    209 
    210 upload_step
    211 
    212 let CURRENT_STEP+=1
    213 if [ $START_STEP -le $CURRENT_STEP ] ; then
    214   echo ">>> Step $CURRENT_STEP: Commit to the repository."
    215   restore_if_unset "MERGE_TO_BRANCH"
    216   git checkout $BRANCHNAME \
    217     || die "cannot ensure that the current branch is $BRANCHNAME"
    218   wait_for_lgtm
    219   git cl dcommit || die "failed to commit to $MERGE_TO_BRANCH"
    220 fi
    221 
    222 let CURRENT_STEP+=1
    223 if [ $START_STEP -le $CURRENT_STEP ] ; then
    224   echo ">>> Step $CURRENT_STEP: Determine svn commit revision"
    225   restore_if_unset "NEW_COMMIT_MSG"
    226   restore_if_unset "MERGE_TO_BRANCH"
    227   git svn fetch || die "'git svn fetch' failed."
    228   COMMIT_HASH=$(git log -1 --format=%H --grep="$NEW_COMMIT_MSG" \
    229     svn/$MERGE_TO_BRANCH)
    230   [[ -z "$COMMIT_HASH" ]] && die "Unable to map git commit to svn revision"
    231   SVN_REVISION=$(git svn find-rev $COMMIT_HASH)
    232   echo "subversion revision number is r$SVN_REVISION"
    233   persist "SVN_REVISION"
    234 fi
    235 
    236 let CURRENT_STEP+=1
    237 if [ $START_STEP -le $CURRENT_STEP ] ; then
    238   echo ">>> Step $CURRENT_STEP: Create the tag."
    239   restore_if_unset "SVN_REVISION"
    240   restore_version_if_unset "NEW"
    241   echo "Creating tag svn/tags/$NEWMAJOR.$NEWMINOR.$NEWBUILD.$NEWPATCH"
    242   if [ "$MERGE_TO_BRANCH" == "trunk" ] ; then
    243     TO_URL="$MERGE_TO_BRANCH"
    244   else
    245     TO_URL="branches/$MERGE_TO_BRANCH"
    246   fi
    247   svn copy -r $SVN_REVISION \
    248     https://v8.googlecode.com/svn/$TO_URL \
    249     https://v8.googlecode.com/svn/tags/$NEWMAJOR.$NEWMINOR.$NEWBUILD.$NEWPATCH \
    250     -m "Tagging version $NEWMAJOR.$NEWMINOR.$NEWBUILD.$NEWPATCH"
    251   persist "TO_URL"
    252 fi
    253 
    254 let CURRENT_STEP+=1
    255 if [ $START_STEP -le $CURRENT_STEP ] ; then
    256   echo ">>> Step $CURRENT_STEP: Cleanup."
    257   restore_if_unset "SVN_REVISION"
    258   restore_if_unset "TO_URL"
    259   restore_if_unset "REVISION_LIST"
    260   restore_version_if_unset "NEW"
    261   common_cleanup
    262   echo "*** SUMMARY ***"
    263   echo "version: $NEWMAJOR.$NEWMINOR.$NEWBUILD.$NEWPATCH"
    264   echo "branch: $TO_URL"
    265   echo "svn revision: $SVN_REVISION"
    266   [[ -n "$REVISION_LIST" ]] && echo "patches:$REVISION_LIST"
    267 fi
    268