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 31BRANCHNAME=prepare-merge 32PERSISTFILE_BASENAME=/tmp/v8-merge-to-branch-tempfile 33ALREADY_MERGING_SENTINEL_FILE="$PERSISTFILE_BASENAME-already-merging" 34COMMIT_HASHES_FILE="$PERSISTFILE_BASENAME-PATCH_COMMIT_HASHES" 35TEMPORARY_PATCH_FILE="$PERSISTFILE_BASENAME-temporary-patch" 36 37########## Function definitions 38 39source $(dirname $BASH_SOURCE)/common-includes.sh 40 41usage() { 42cat << EOF 43usage: $0 [OPTIONS]... [BRANCH] [REVISION]... 44 45Performs the necessary steps to merge revisions from bleeding_edge 46to other branches, including trunk. 47 48OPTIONS: 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 52EOF 53} 54 55persist_patch_commit_hashes() { 56 echo "PATCH_COMMIT_HASHES=( ${PATCH_COMMIT_HASHES[@]} )" > $COMMIT_HASHES_FILE 57} 58 59restore_patch_commit_hashes() { 60 source $COMMIT_HASHES_FILE 61} 62 63restore_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 71while 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 87done 88let OPTION_COUNT=$OPTIND-1 89shift $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" 96touch "$ALREADY_MERGING_SENTINEL_FILE" 97 98initial_environment_checks 99 100if [ $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 110fi 111 112let CURRENT_STEP+=1 113if [ $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." 118fi 119 120let CURRENT_STEP+=1 121if [ $START_STEP -le $CURRENT_STEP ] ; then 122 echo ">>> Step $CURRENT_STEP: Find the git \ 123revisions 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 160fi 161 162let CURRENT_STEP+=1 163if [ $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 177fi 178 179let CURRENT_STEP+=1 180if [ $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 184fi 185 186let CURRENT_STEP+=1 187if [ $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 \ 192your EDITOR on $VERSION_FILE so you can make arbitrary changes. When \ 193you'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" 201fi 202 203let CURRENT_STEP+=1 204if [ $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." 208fi 209 210upload_step 211 212let CURRENT_STEP+=1 213if [ $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" 220fi 221 222let CURRENT_STEP+=1 223if [ $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" 234fi 235 236let CURRENT_STEP+=1 237if [ $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" 252fi 253 254let CURRENT_STEP+=1 255if [ $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" 267fi 268