Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 VERSION_FILE="src/version.cc" | |
| 33 PERSISTFILE_BASENAME=/tmp/v8-merge-to-branch-tempfile | |
| 34 ALREADY_MERGING_SENTINEL_FILE="$PERSISTFILE_BASENAME-already-merging" | |
| 35 CHANGELOG_ENTRY_FILE="$PERSISTFILE_BASENAME-changelog-entry" | |
| 36 PATCH_FILE="$PERSISTFILE_BASENAME-patch" | |
| 37 COMMITMSG_FILE="$PERSISTFILE_BASENAME-commitmsg" | |
| 38 COMMITMSG_FILE_COPY="$PERSISTFILE_BASENAME-commitmsg-copy" | |
| 39 TOUCHED_FILES_FILE="$PERSISTFILE_BASENAME-touched-files" | |
| 40 TRUNK_REVISION_FILE="$PERSISTFILE_BASENAME-trunkrevision" | |
| 41 START_STEP=0 | |
| 42 CURRENT_STEP=0 | |
| 43 | |
| 44 usage() { | |
| 45 cat << EOF | |
| 46 usage: $0 [OPTIONS]... [BRANCH] [REVISION]... | |
| 47 | |
| 48 Performs the necessary steps to merge revisions from bleeding_edge | |
| 49 to other branches, including trunk. | |
| 50 | |
| 51 OPTIONS: | |
| 52 -h Show this message | |
| 53 -s Specify the step where to start work. Default: 0. | |
| 54 EOF | |
| 55 } | |
| 56 | |
| 57 ########## Function definitions | |
| 58 | |
| 59 die() { | |
| 60 [[ -n "$1" ]] && echo "Error: $1" | |
| 61 echo "Exiting." | |
| 62 exit 1 | |
| 63 } | |
| 64 | |
| 65 confirm() { | |
| 66 echo -n "$1 [Y/n] " | |
| 67 read ANSWER | |
| 68 if [[ -z "$ANSWER" || "$ANSWER" == "Y" || "$ANSWER" == "y" ]] ; then | |
| 69 return 0 | |
| 70 else | |
| 71 return 1 | |
| 72 fi | |
| 73 } | |
| 74 | |
| 75 delete_branch() { | |
| 76 local MATCH=$(git branch | grep $1 | awk '{print $NF}' ) | |
| 77 if [ "$MATCH" == "$1" ] ; then | |
| 78 confirm "Branch $1 exists, do you want to delete it?" | |
| 79 if [ $? -eq 0 ] ; then | |
| 80 git branch -D $1 || die "Deleting branch '$1' failed." | |
| 81 echo "Branch $1 deleted." | |
| 82 else | |
| 83 die "Can't continue. Please delete branch $1 and try again." | |
| 84 fi | |
| 85 fi | |
| 86 } | |
| 87 | |
| 88 # Persist and restore variables to support canceling/resuming execution | |
| 89 # of this script. | |
| 90 persist() { | |
| 91 local VARNAME=$1 | |
| 92 local FILE="$PERSISTFILE_BASENAME-$VARNAME" | |
| 93 echo "${!VARNAME}" > $FILE | |
| 94 } | |
| 95 | |
| 96 restore() { | |
| 97 local VARNAME=$1 | |
| 98 local FILE="$PERSISTFILE_BASENAME-$VARNAME" | |
| 99 local VALUE="$(cat $FILE)" | |
| 100 eval "$VARNAME=\"$VALUE\"" | |
| 101 } | |
| 102 | |
| 103 restore_if_unset() { | |
| 104 local VARNAME=$1 | |
| 105 [[ -z "${!VARNAME}" ]] && restore "$VARNAME" | |
| 106 [[ -z "${!VARNAME}" ]] && die "Variable '$VARNAME' could not be restored." | |
| 107 } | |
| 108 | |
| 109 persist_patch_commit_hashes() { | |
| 110 local FILE="$PERSISTFILE_BASENAME-PATCH_COMMIT_HASHES" | |
| 111 echo "PATCH_COMMIT_HASHES=( ${PATCH_COMMIT_HASHES[@]} )" > $FILE | |
| 112 } | |
| 113 | |
| 114 restore_patch_commit_hashes() { | |
| 115 local FILE="$PERSISTFILE_BASENAME-PATCH_COMMIT_HASHES" | |
| 116 source $FILE | |
| 117 } | |
| 118 | |
| 119 restore_patch_commit_hashes_if_unset() { | |
| 120 [[ "${#PATCH_COMMIT_HASHES[@]}" == 0 ]] && restore_patch_commit_hashes | |
| 121 [[ "${#PATCH_COMMIT_HASHES[@]}" == 0 ]] && \ | |
| 122 die "Variable PATCH_COMMIT_HASHES could not be restored." | |
| 123 } | |
| 124 | |
| 125 ########## Option parsing | |
| 126 | |
| 127 while getopts ":hs:f" OPTION ; do | |
| 128 case $OPTION in | |
| 129 h) usage | |
| 130 exit 0 | |
| 131 ;; | |
| 132 f) rm "$ALREADY_MERGING_SENTINEL_FILE" | |
| 133 ;; | |
| 134 s) START_STEP=$OPTARG | |
| 135 ;; | |
| 136 ?) echo "Illegal option: -$OPTARG" | |
| 137 usage | |
| 138 exit 1 | |
| 139 ;; | |
| 140 esac | |
| 141 done | |
| 142 let OPTION_COUNT=$OPTIND-1 | |
| 143 shift $OPTION_COUNT | |
| 144 | |
| 145 ########## Regular workflow | |
| 146 | |
| 147 # If there is a merge in progress, abort. | |
| 148 [[ -e "$ALREADY_MERGING_SENTINEL_FILE" ]] && [[ -z "$START_STEP" ]] \ | |
| 149 && die "A merge is already in progress" | |
| 150 touch "$ALREADY_MERGING_SENTINEL_FILE" | |
| 151 | |
| 152 # Cancel if this is not a git checkout. | |
| 153 [[ -d .git ]] \ | |
| 154 || die "This is not a git checkout, this script won't work for you." | |
| 155 | |
| 156 # Cancel if EDITOR is unset or not executable. | |
| 157 [[ -n "$EDITOR" && -x "$(which $EDITOR)" ]] \ | |
| 158 || die "Please set your EDITOR environment variable, you'll need it." | |
| 159 | |
| 160 if [ $START_STEP -le $CURRENT_STEP ] ; then | |
| 161 MERGE_TO_BRANCH=$1 | |
| 162 [[ -n "$MERGE_TO_BRANCH" ]] \ | |
| 163 || die "Please specify a branch to merge to" | |
| 164 shift | |
| 165 persist "MERGE_TO_BRANCH" | |
| 166 | |
| 167 echo ">>> Step $CURRENT_STEP: Preparation" | |
| 168 # Check for a clean workdir. | |
| 169 [[ -z "$(git status -s -uno)" ]] \ | |
| 170 || die "Workspace is not clean. Please commit or undo your changes." | |
| 171 | |
| 172 # Persist current branch. | |
| 173 CURRENT_BRANCH=$(git status -s -b -uno | grep "^##" | awk '{print $2}') | |
| 174 persist "CURRENT_BRANCH" | |
| 175 delete_branch $BRANCHNAME | |
| 176 fi | |
| 177 | |
| 178 let CURRENT_STEP+=1 | |
| 179 if [ $START_STEP -le $CURRENT_STEP ] ; then | |
| 180 echo ">>> Step $CURRENT_STEP: Fetch unfetched revisions." | |
| 181 git svn fetch || die "'git svn fetch' failed." | |
| 182 fi | |
| 183 | |
| 184 let CURRENT_STEP+=1 | |
| 185 if [ $START_STEP -le $CURRENT_STEP ] ; then | |
| 186 restore_if_unset "MERGE_TO_BRANCH" | |
| 187 echo ">>> Step $CURRENT_STEP: Create a fresh branch for the patch." | |
| 188 git checkout -b $BRANCHNAME svn/$MERGE_TO_BRANCH \ | |
| 189 || die "Creating branch $BRANCHNAME failed." | |
| 190 fi | |
| 191 | |
| 192 let CURRENT_STEP+=1 | |
| 193 if [ $START_STEP -le $CURRENT_STEP ] ; then | |
| 194 echo ">>> Step $CURRENT_STEP: Find the git \ | |
| 195 revisions associated with the patches." | |
| 196 current=0 | |
| 197 for REVISION in "$@" ; do | |
| 198 NEXT_HASH=$(git svn find-rev "r$REVISION" svn/bleeding_edge) | |
| 199 [[ -n "$NEXT_HASH" ]] \ | |
| 200 || die "Cannot determine git hash for r$REVISION" | |
| 201 PATCH_COMMIT_HASHES[$current]="$NEXT_HASH" | |
| 202 [[ -n "$NEW_COMMIT_MSG" ]] && NEW_COMMIT_MSG="$NEW_COMMIT_MSG," | |
| 203 NEW_COMMIT_MSG="$NEW_COMMIT_MSG r$REVISION" | |
| 204 let current+=1 | |
| 205 done | |
| 206 NEW_COMMIT_MSG="Merged$NEW_COMMIT_MSG into \ | |
|
Jakob Kummerow
2012/01/31 11:11:10
nit: fits on one line
danno
2012/01/31 11:13:11
Done.
| |
| 207 $MERGE_TO_BRANCH branch." | |
| 208 | |
| 209 echo "$NEW_COMMIT_MSG" > $COMMITMSG_FILE | |
| 210 echo >> $COMMITMSG_FILE | |
| 211 for HASH in ${PATCH_COMMIT_HASHES[@]} ; do | |
|
Jakob Kummerow
2012/01/31 11:11:10
nit: double space before "do"
danno
2012/01/31 11:13:11
Done.
| |
| 212 PATCH_MERGE_DESCRIPTION=$(git log -1 --format=%s $HASH) | |
| 213 echo "$PATCH_MERGE_DESCRIPTION" >> $COMMITMSG_FILE | |
| 214 echo >> $COMMITMSG_FILE | |
| 215 done | |
| 216 for HASH in ${PATCH_COMMIT_HASHES[@]} ; do | |
| 217 BUG=$(git log -1 $HASH | grep "BUG=" | awk -F '=' '{print $NF}') | |
| 218 if [ $BUG ] ; then | |
| 219 if [ "$BUG_AGGREGATE" ] ; then | |
| 220 BUG_AGGREGATE="$BUG_AGGREGATE," | |
| 221 fi | |
| 222 BUG_AGGREGATE="$BUG_AGGREGATE$BUG" | |
| 223 fi | |
| 224 done | |
| 225 if [ "$BUG_AGGREGATE" ] ; then | |
| 226 echo "BUG=$BUG_AGGREGATE" >> $COMMITMSG_FILE | |
| 227 else | |
| 228 echo "BUG=none" >> $COMMITMSG_FILE | |
|
Jakob Kummerow
2012/01/31 11:11:10
I'd just remove this. "BUG=none" adds no useful in
danno
2012/01/31 11:13:11
Done.
| |
| 229 fi | |
| 230 echo -n "TEST=none" >> $COMMITMSG_FILE | |
|
Jakob Kummerow
2012/01/31 11:11:10
Same here.
danno
2012/01/31 11:13:11
Done.
| |
| 231 persist "NEW_COMMIT_MSG" | |
| 232 persist_patch_commit_hashes | |
| 233 fi | |
| 234 | |
| 235 let CURRENT_STEP+=1 | |
| 236 if [ $START_STEP -le $CURRENT_STEP ] ; then | |
| 237 restore_if_unset "MERGE_TO_BRANCH" | |
| 238 restore_patch_commit_hashes_if_unset "PATCH_COMMIT_HASHES" | |
| 239 echo "${PATCH_COMMIT_HASHES[@]}" | |
| 240 echo ">>> Step $CURRENT_STEP: Apply the revision patch and create commit messa ge." | |
| 241 for HASH in ${PATCH_COMMIT_HASHES[@]} ; do | |
| 242 git log -1 -p $HASH | patch -p1 \ | |
| 243 || die "Cannot apply the patch for $HASH to $MERGE_TO_BRANCH" | |
| 244 done | |
| 245 fi | |
| 246 | |
| 247 let CURRENT_STEP+=1 | |
| 248 if [ $START_STEP -le $CURRENT_STEP ] ; then | |
| 249 echo ">>> Step $CURRENT_STEP: Prepare version.cc" | |
| 250 # These version numbers are used again for creating the tag | |
| 251 MAJOR=$(grep "#define MAJOR_VERSION" "$VERSION_FILE" | awk '{print $NF}') | |
|
Jakob Kummerow
2012/01/31 11:11:10
AFAICS the tag is created using NEWMAJOR, NEWMINOR
danno
2012/01/31 11:13:11
Done.
| |
| 252 persist "MAJOR" | |
| 253 MINOR=$(grep "#define MINOR_VERSION" "$VERSION_FILE" | awk '{print $NF}') | |
| 254 persist "MINOR" | |
| 255 BUILD=$(grep "#define BUILD_NUMBER" "$VERSION_FILE" | awk '{print $NF}') | |
| 256 persist "BUILD" | |
| 257 PATCH=$(grep "#define PATCH_LEVEL" "$VERSION_FILE" | awk '{print $NF}') | |
| 258 persist "PATCH" | |
| 259 fi | |
| 260 | |
| 261 let CURRENT_STEP+=1 | |
| 262 if [ $START_STEP -le $CURRENT_STEP ] ; then | |
| 263 echo ">>> Step $CURRENT_STEP: Increment version number." | |
| 264 restore_if_unset "PATCH" | |
| 265 NEWPATCH=$(($PATCH + 1)) | |
| 266 confirm "Automatically increment PATCH_LEVEL? (Saying 'n' will fire up \ | |
| 267 your EDITOR on $VERSION_FILE so you can make arbitrary changes. When \ | |
| 268 you're done, save the file and exit your EDITOR.)" | |
| 269 if [ $? -eq 0 ] ; then | |
| 270 sed -e "/#define PATCH_LEVEL/s/[0-9]*$/$NEWPATCH/" \ | |
| 271 -i "$VERSION_FILE" | |
| 272 else | |
| 273 $EDITOR "$VERSION_FILE" | |
| 274 fi | |
| 275 NEWMAJOR=$(grep "#define MAJOR_VERSION" "$VERSION_FILE" | awk '{print $NF}') | |
| 276 persist "NEWMAJOR" | |
| 277 NEWMINOR=$(grep "#define MINOR_VERSION" "$VERSION_FILE" | awk '{print $NF}') | |
| 278 persist "NEWMINOR" | |
| 279 NEWBUILD=$(grep "#define BUILD_NUMBER" "$VERSION_FILE" | awk '{print $NF}') | |
| 280 persist "NEWBUILD" | |
| 281 NEWPATCH=$(grep "#define PATCH_LEVEL" "$VERSION_FILE" | awk '{print $NF}') | |
| 282 persist "NEWPATCH" | |
| 283 fi | |
| 284 | |
| 285 let CURRENT_STEP+=1 | |
| 286 if [ $START_STEP -le $CURRENT_STEP ] ; then | |
| 287 echo ">>> Step $CURRENT_STEP: Commit to local branch." | |
| 288 git commit -a -F "$COMMITMSG_FILE" \ | |
| 289 || die "'git commit -a' failed." | |
| 290 fi | |
| 291 | |
| 292 let CURRENT_STEP+=1 | |
| 293 if [ $START_STEP -le $CURRENT_STEP ] ; then | |
| 294 echo ">>> Step $CURRENT_STEP: Upload for code review." | |
| 295 echo -n "Please enter the email address of a V8 reviewer for your patch: " | |
| 296 read REVIEWER | |
| 297 git cl upload -r "$REVIEWER" --send-mail \ | |
| 298 || die "'git cl upload' failed, please try again." | |
| 299 fi | |
| 300 | |
| 301 let CURRENT_STEP+=1 | |
| 302 if [ $START_STEP -le $CURRENT_STEP ] ; then | |
| 303 restore_if_unset "MERGE_TO_BRANCH" | |
| 304 git checkout $BRANCHNAME \ | |
| 305 || die "cannot ensure that the current branch is $BRANCHNAME" | |
| 306 echo ">>> Step $CURRENT_STEP: Commit to the repository." | |
| 307 echo "Please wait for an LGTM, then type \"LGTM<Return>\" to commit your \ | |
| 308 change. (If you need to iterate on the patch or double check that it's \ | |
| 309 sane, do so in another shell, but remember to not change the headline of \ | |
| 310 the uploaded CL." | |
| 311 unset ANSWER | |
| 312 while [ "$ANSWER" != "LGTM" ] ; do | |
| 313 [[ -n "$ANSWER" ]] && echo "That was not 'LGTM'." | |
| 314 echo -n "> " | |
| 315 read ANSWER | |
| 316 done | |
| 317 git cl dcommit || die "failed to commit to $MERGE_TO_BRANCH" | |
| 318 fi | |
| 319 | |
| 320 let CURRENT_STEP+=1 | |
| 321 if [ $START_STEP -le $CURRENT_STEP ] ; then | |
| 322 restore_if_unset "NEW_COMMIT_MSG" | |
| 323 restore_if_unset "MERGE_TO_BRANCH" | |
| 324 echo ">>> Step $CURRENT_STEP: Determine svn commit revision" | |
| 325 git svn fetch || die "'git svn fetch' failed." | |
| 326 COMMIT_HASH=$(git log -1 --format=%H --grep="$NEW_COMMIT_MSG" \ | |
| 327 svn/$MERGE_TO_BRANCH) | |
| 328 [[ -z "$COMMIT_HASH" ]] && die "Unable to map git commit to svn revision" | |
| 329 SVN_REVISION=$(git svn find-rev $COMMIT_HASH) | |
| 330 echo "subversion revision number is r$SVN_REVISION" | |
| 331 persist "SVN_REVISION" | |
| 332 fi | |
| 333 | |
| 334 let CURRENT_STEP+=1 | |
| 335 if [ $START_STEP -le $CURRENT_STEP ] ; then | |
| 336 restore_if_unset "SVN_REVISION" | |
| 337 restore_if_unset "NEWMAJOR" | |
| 338 restore_if_unset "NEWMINOR" | |
| 339 restore_if_unset "NEWBUILD" | |
| 340 restore_if_unset "NEWPATCH" | |
| 341 echo ">>> Step $CURRENT_STEP: Create the tag." | |
| 342 echo "Creating tag svn/tags/$NEWMAJOR.$NEWMINOR.$NEWBUILD.$NEWPATCH" | |
| 343 svn copy -r $SVN_REVISION \ | |
| 344 https://v8.googlecode.com/svn/branches/$MERGE_TO_BRANCH \ | |
| 345 https://v8.googlecode.com/svn/tags/$NEWMAJOR.$NEWMINOR.$NEWBUILD.$NEWPATCH \ | |
| 346 -m "Tagging version $NEWMAJOR.$NEWMINOR.$NEWBUILD.$NEWPATCH" | |
| 347 fi | |
| 348 | |
| 349 let CURRENT_STEP+=1 | |
| 350 if [ $START_STEP -le $CURRENT_STEP ] ; then | |
| 351 echo ">>> Step $CURRENT_STEP: Cleanup." | |
| 352 restore_if_unset "CURRENT_BRANCH" | |
| 353 git checkout -f $CURRENT_BRANCH | |
| 354 [[ "$BRANCHNAME" != "$CURRENT_BRANCH" ]] && git branch -D $BRANCHNAME | |
| 355 rm -f "$ALREADY_MERGING_SENTINEL_FILE" | |
| 356 fi | |
| OLD | NEW |