| 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 | |
| 30 ########## Global variable definitions | |
| 31 | |
| 32 BRANCHNAME=prepare-push | |
| 33 TRUNKBRANCH=trunk-push | |
| 34 PERSISTFILE_BASENAME=/tmp/v8-push-to-trunk-tempfile | |
| 35 CHROME_PATH= | |
| 36 | |
| 37 ########## Function definitions | |
| 38 | |
| 39 source $(dirname $BASH_SOURCE)/common-includes.sh | |
| 40 | |
| 41 usage() { | |
| 42 cat << EOF | |
| 43 usage: $0 OPTIONS | |
| 44 | |
| 45 Performs the necessary steps for a V8 push to trunk. Only works for \ | |
| 46 git checkouts. | |
| 47 | |
| 48 OPTIONS: | |
| 49 -h Show this message | |
| 50 -s Specify the step where to start work. Default: 0. | |
| 51 -l Manually specify the git commit ID of the last push to trunk. | |
| 52 -c Specify the path to your Chromium src/ directory to automate the | |
| 53 V8 roll. | |
| 54 EOF | |
| 55 } | |
| 56 | |
| 57 ########## Option parsing | |
| 58 | |
| 59 while getopts ":hs:l:c:" OPTION ; do | |
| 60 case $OPTION in | |
| 61 h) usage | |
| 62 exit 0 | |
| 63 ;; | |
| 64 s) START_STEP=$OPTARG | |
| 65 ;; | |
| 66 l) LASTPUSH=$OPTARG | |
| 67 ;; | |
| 68 c) CHROME_PATH=$OPTARG | |
| 69 ;; | |
| 70 ?) echo "Illegal option: -$OPTARG" | |
| 71 usage | |
| 72 exit 1 | |
| 73 ;; | |
| 74 esac | |
| 75 done | |
| 76 | |
| 77 | |
| 78 ########## Regular workflow | |
| 79 | |
| 80 initial_environment_checks | |
| 81 | |
| 82 if [ $START_STEP -le $CURRENT_STEP ] ; then | |
| 83 echo ">>> Step $CURRENT_STEP: Preparation" | |
| 84 common_prepare | |
| 85 delete_branch $TRUNKBRANCH | |
| 86 fi | |
| 87 | |
| 88 let CURRENT_STEP+=1 | |
| 89 if [ $START_STEP -le $CURRENT_STEP ] ; then | |
| 90 echo ">>> Step $CURRENT_STEP: Create a fresh branch." | |
| 91 git checkout -b $BRANCHNAME svn/bleeding_edge \ | |
| 92 || die "Creating branch $BRANCHNAME failed." | |
| 93 fi | |
| 94 | |
| 95 let CURRENT_STEP+=1 | |
| 96 if [ $START_STEP -le $CURRENT_STEP ] ; then | |
| 97 echo ">>> Step $CURRENT_STEP: Detect commit ID of last push to trunk." | |
| 98 [[ -n "$LASTPUSH" ]] || LASTPUSH=$(git log -1 --format=%H ChangeLog) | |
| 99 LOOP=1 | |
| 100 while [ $LOOP -eq 1 ] ; do | |
| 101 # Print assumed commit, circumventing git's pager. | |
| 102 git log -1 $LASTPUSH | cat | |
| 103 confirm "Is the commit printed above the last push to trunk?" | |
| 104 if [ $? -eq 0 ] ; then | |
| 105 LOOP=0 | |
| 106 else | |
| 107 LASTPUSH=$(git log -1 --format=%H $LASTPUSH^ ChangeLog) | |
| 108 fi | |
| 109 done | |
| 110 persist "LASTPUSH" | |
| 111 fi | |
| 112 | |
| 113 let CURRENT_STEP+=1 | |
| 114 if [ $START_STEP -le $CURRENT_STEP ] ; then | |
| 115 echo ">>> Step $CURRENT_STEP: Prepare raw ChangeLog entry." | |
| 116 # These version numbers are used again later for the trunk commit. | |
| 117 read_and_persist_version | |
| 118 | |
| 119 DATE=$(date +%Y-%m-%d) | |
| 120 persist "DATE" | |
| 121 echo "$DATE: Version $MAJOR.$MINOR.$BUILD" > "$CHANGELOG_ENTRY_FILE" | |
| 122 echo "" >> "$CHANGELOG_ENTRY_FILE" | |
| 123 COMMITS=$(git log $LASTPUSH..HEAD --format=%H) | |
| 124 for commit in $COMMITS ; do | |
| 125 # Get the commit's title line. | |
| 126 git log -1 $commit --format="%w(80,8,8)%s" >> "$CHANGELOG_ENTRY_FILE" | |
| 127 # Grep for "BUG=xxxx" lines in the commit message and convert them to | |
| 128 # "(issue xxxx)". | |
| 129 git log -1 $commit --format="%B" \ | |
| 130 | grep "^BUG=" | grep -v "BUG=$" | grep -v "BUG=none$" \ | |
| 131 | sed -e 's/^/ /' \ | |
| 132 | sed -e 's/BUG=v8:\(.*\)$/(issue \1)/' \ | |
| 133 | sed -e 's/BUG=chromium:\(.*\)$/(Chromium issue \1)/' \ | |
| 134 | sed -e 's/BUG=\(.*\)$/(Chromium issue \1)/' \ | |
| 135 >> "$CHANGELOG_ENTRY_FILE" | |
| 136 # Append the commit's author for reference. | |
| 137 git log -1 $commit --format="%w(80,8,8)(%an)" >> "$CHANGELOG_ENTRY_FILE" | |
| 138 echo "" >> "$CHANGELOG_ENTRY_FILE" | |
| 139 done | |
| 140 echo " Performance and stability improvements on all platforms." \ | |
| 141 >> "$CHANGELOG_ENTRY_FILE" | |
| 142 fi | |
| 143 | |
| 144 let CURRENT_STEP+=1 | |
| 145 if [ $START_STEP -le $CURRENT_STEP ] ; then | |
| 146 echo ">>> Step $CURRENT_STEP: Edit ChangeLog entry." | |
| 147 echo -n "Please press <Return> to have your EDITOR open the ChangeLog entry, \ | |
| 148 then edit its contents to your liking. When you're done, save the file and \ | |
| 149 exit your EDITOR. " | |
| 150 read ANSWER | |
| 151 $EDITOR "$CHANGELOG_ENTRY_FILE" | |
| 152 NEWCHANGELOG=$(mktemp) | |
| 153 # Eliminate any trailing newlines by going through a shell variable. | |
| 154 # Also (1) eliminate tabs, (2) fix too little and (3) too much indentation, | |
| 155 # and (4) eliminate trailing whitespace. | |
| 156 CHANGELOGENTRY=$(cat "$CHANGELOG_ENTRY_FILE" \ | |
| 157 | sed -e 's/\t/ /g' \ | |
| 158 | sed -e 's/^ \{1,7\}\([^ ]\)/ \1/g' \ | |
| 159 | sed -e 's/^ \{9,80\}\([^ ]\)/ \1/g' \ | |
| 160 | sed -e 's/ \+$//') | |
| 161 [[ -n "$CHANGELOGENTRY" ]] || die "Empty ChangeLog entry." | |
| 162 echo "$CHANGELOGENTRY" > "$NEWCHANGELOG" | |
| 163 echo "" >> "$NEWCHANGELOG" # Explicitly insert two empty lines. | |
| 164 echo "" >> "$NEWCHANGELOG" | |
| 165 cat ChangeLog >> "$NEWCHANGELOG" | |
| 166 mv "$NEWCHANGELOG" ChangeLog | |
| 167 fi | |
| 168 | |
| 169 let CURRENT_STEP+=1 | |
| 170 if [ $START_STEP -le $CURRENT_STEP ] ; then | |
| 171 echo ">>> Step $CURRENT_STEP: Increment version number." | |
| 172 restore_if_unset "BUILD" | |
| 173 NEWBUILD=$(($BUILD + 1)) | |
| 174 confirm "Automatically increment BUILD_NUMBER? (Saying 'n' will fire up \ | |
| 175 your EDITOR on $VERSION_FILE so you can make arbitrary changes. When \ | |
| 176 you're done, save the file and exit your EDITOR.)" | |
| 177 if [ $? -eq 0 ] ; then | |
| 178 sed -e "/#define BUILD_NUMBER/s/[0-9]*$/$NEWBUILD/" \ | |
| 179 -i "$VERSION_FILE" | |
| 180 else | |
| 181 $EDITOR "$VERSION_FILE" | |
| 182 fi | |
| 183 read_and_persist_version "NEW" | |
| 184 fi | |
| 185 | |
| 186 let CURRENT_STEP+=1 | |
| 187 if [ $START_STEP -le $CURRENT_STEP ] ; then | |
| 188 echo ">>> Step $CURRENT_STEP: Commit to local branch." | |
| 189 restore_version_if_unset "NEW" | |
| 190 PREPARE_COMMIT_MSG="Prepare push to trunk. \ | |
| 191 Now working on version $NEWMAJOR.$NEWMINOR.$NEWBUILD." | |
| 192 persist "PREPARE_COMMIT_MSG" | |
| 193 git commit -a -m "$PREPARE_COMMIT_MSG" \ | |
| 194 || die "'git commit -a' failed." | |
| 195 fi | |
| 196 | |
| 197 upload_step | |
| 198 | |
| 199 let CURRENT_STEP+=1 | |
| 200 if [ $START_STEP -le $CURRENT_STEP ] ; then | |
| 201 echo ">>> Step $CURRENT_STEP: Commit to the repository." | |
| 202 wait_for_lgtm | |
| 203 # Re-read the ChangeLog entry (to pick up possible changes). | |
| 204 cat ChangeLog | awk --posix '{ | |
| 205 if ($0 ~ /^[0-9]{4}-[0-9]{2}-[0-9]{2}:/) { | |
| 206 if (in_firstblock == 1) { | |
| 207 exit 0; | |
| 208 } else { | |
| 209 in_firstblock = 1; | |
| 210 } | |
| 211 }; | |
| 212 print $0; | |
| 213 }' > "$CHANGELOG_ENTRY_FILE" | |
| 214 PRESUBMIT_TREE_CHECK="skip" git cl dcommit \ | |
| 215 || die "'git cl dcommit' failed, please try again." | |
| 216 fi | |
| 217 | |
| 218 let CURRENT_STEP+=1 | |
| 219 if [ $START_STEP -le $CURRENT_STEP ] ; then | |
| 220 echo ">>> Step $CURRENT_STEP: Fetch straggler commits that sneaked in \ | |
| 221 since this script was started." | |
| 222 git svn fetch || die "'git svn fetch' failed." | |
| 223 git checkout svn/bleeding_edge | |
| 224 restore_if_unset "PREPARE_COMMIT_MSG" | |
| 225 PREPARE_COMMIT_HASH=$(git log -1 --format=%H --grep="$PREPARE_COMMIT_MSG") | |
| 226 persist "PREPARE_COMMIT_HASH" | |
| 227 fi | |
| 228 | |
| 229 let CURRENT_STEP+=1 | |
| 230 if [ $START_STEP -le $CURRENT_STEP ] ; then | |
| 231 echo ">>> Step $CURRENT_STEP: Squash commits into one." | |
| 232 # Instead of relying on "git rebase -i", we'll just create a diff, because | |
| 233 # that's easier to automate. | |
| 234 restore_if_unset "PREPARE_COMMIT_HASH" | |
| 235 git diff svn/trunk $PREPARE_COMMIT_HASH > "$PATCH_FILE" | |
| 236 # Convert the ChangeLog entry to commit message format: | |
| 237 # - remove date | |
| 238 # - remove indentation | |
| 239 # - merge paragraphs into single long lines, keeping empty lines between them. | |
| 240 restore_if_unset "DATE" | |
| 241 CHANGELOGENTRY=$(cat "$CHANGELOG_ENTRY_FILE") | |
| 242 echo "$CHANGELOGENTRY" \ | |
| 243 | sed -e "s/^$DATE: //" \ | |
| 244 | sed -e 's/^ *//' \ | |
| 245 | awk '{ | |
| 246 if (need_space == 1) { | |
| 247 printf(" "); | |
| 248 }; | |
| 249 printf("%s", $0); | |
| 250 if ($0 ~ /^$/) { | |
| 251 printf("\n\n"); | |
| 252 need_space = 0; | |
| 253 } else { | |
| 254 need_space = 1; | |
| 255 } | |
| 256 }' > "$COMMITMSG_FILE" || die "Commit message editing failed." | |
| 257 rm -f "$CHANGELOG_ENTRY_FILE" | |
| 258 fi | |
| 259 | |
| 260 let CURRENT_STEP+=1 | |
| 261 if [ $START_STEP -le $CURRENT_STEP ] ; then | |
| 262 echo ">>> Step $CURRENT_STEP: Create a new branch from trunk." | |
| 263 git checkout -b $TRUNKBRANCH svn/trunk \ | |
| 264 || die "Checking out a new branch '$TRUNKBRANCH' failed." | |
| 265 fi | |
| 266 | |
| 267 let CURRENT_STEP+=1 | |
| 268 if [ $START_STEP -le $CURRENT_STEP ] ; then | |
| 269 echo ">>> Step $CURRENT_STEP: Apply squashed changes." | |
| 270 rm -f "$TOUCHED_FILES_FILE" | |
| 271 apply_patch "$PATCH_FILE" | |
| 272 rm -f "$PATCH_FILE" | |
| 273 fi | |
| 274 | |
| 275 let CURRENT_STEP+=1 | |
| 276 if [ $START_STEP -le $CURRENT_STEP ] ; then | |
| 277 echo ">>> Step $CURRENT_STEP: Set correct version for trunk." | |
| 278 restore_version_if_unset | |
| 279 sed -e "/#define MAJOR_VERSION/s/[0-9]*$/$MAJOR/" \ | |
| 280 -e "/#define MINOR_VERSION/s/[0-9]*$/$MINOR/" \ | |
| 281 -e "/#define BUILD_NUMBER/s/[0-9]*$/$BUILD/" \ | |
| 282 -e "/#define PATCH_LEVEL/s/[0-9]*$/0/" \ | |
| 283 -e "/#define IS_CANDIDATE_VERSION/s/[0-9]*$/0/" \ | |
| 284 -i "$VERSION_FILE" || die "Patching $VERSION_FILE failed." | |
| 285 fi | |
| 286 | |
| 287 let CURRENT_STEP+=1 | |
| 288 if [ $START_STEP -le $CURRENT_STEP ] ; then | |
| 289 echo ">>> Step $CURRENT_STEP: Commit to local trunk branch." | |
| 290 git add "$VERSION_FILE" | |
| 291 git commit -F "$COMMITMSG_FILE" || die "'git commit' failed." | |
| 292 rm -f "$COMMITMSG_FILE" | |
| 293 fi | |
| 294 | |
| 295 let CURRENT_STEP+=1 | |
| 296 if [ $START_STEP -le $CURRENT_STEP ] ; then | |
| 297 echo ">>> Step $CURRENT_STEP: Sanity check." | |
| 298 confirm "Please check if your local checkout is sane: Inspect $VERSION_FILE, \ | |
| 299 compile, run tests. Do you want to commit this new trunk revision to the \ | |
| 300 repository?" | |
| 301 [[ $? -eq 0 ]] || die "Execution canceled." | |
| 302 fi | |
| 303 | |
| 304 let CURRENT_STEP+=1 | |
| 305 if [ $START_STEP -le $CURRENT_STEP ] ; then | |
| 306 echo ">>> Step $CURRENT_STEP: Commit to SVN." | |
| 307 git svn dcommit 2>&1 | tee >(grep -E "^Committed r[0-9]+" \ | |
| 308 | sed -e 's/^Committed r\([0-9]\+\)/\1/' \ | |
| 309 > "$TRUNK_REVISION_FILE") \ | |
| 310 || die "'git svn dcommit' failed." | |
| 311 TRUNK_REVISION=$(cat "$TRUNK_REVISION_FILE") | |
| 312 # Sometimes grepping for the revision fails. No idea why. If you figure | |
| 313 # out why it is flaky, please do fix it properly. | |
| 314 if [ -z "$TRUNK_REVISION" ] ; then | |
| 315 echo "Sorry, grepping for the SVN revision failed. Please look for it in \ | |
| 316 the last command's output above and provide it manually (just the number, \ | |
| 317 without the leading \"r\")." | |
| 318 while [ -z "$TRUNK_REVISION" ] ; do | |
| 319 echo -n "> " | |
| 320 read TRUNK_REVISION | |
| 321 done | |
| 322 fi | |
| 323 persist "TRUNK_REVISION" | |
| 324 rm -f "$TRUNK_REVISION_FILE" | |
| 325 fi | |
| 326 | |
| 327 let CURRENT_STEP+=1 | |
| 328 if [ $START_STEP -le $CURRENT_STEP ] ; then | |
| 329 echo ">>> Step $CURRENT_STEP: Tag the new revision." | |
| 330 restore_version_if_unset | |
| 331 git svn tag $MAJOR.$MINOR.$BUILD -m "Tagging version $MAJOR.$MINOR.$BUILD" \ | |
| 332 || die "'git svn tag' failed." | |
| 333 fi | |
| 334 | |
| 335 if [ -z "$CHROME_PATH" ] ; then | |
| 336 echo ">>> (asking for Chromium checkout)" | |
| 337 echo -n "Do you have a \"NewGit\" Chromium checkout and want this script \ | |
| 338 to automate creation of the roll CL? If yes, enter the path to (and including) \ | |
| 339 the \"src\" directory here, otherwise just press <Return>: " | |
| 340 read CHROME_PATH | |
| 341 fi | |
| 342 | |
| 343 if [ -n "$CHROME_PATH" ] ; then | |
| 344 | |
| 345 let CURRENT_STEP+=1 | |
| 346 if [ $START_STEP -le $CURRENT_STEP ] ; then | |
| 347 echo ">>> Step $CURRENT_STEP: Switch to Chromium checkout." | |
| 348 V8_PATH=$(pwd) | |
| 349 persist "V8_PATH" | |
| 350 cd "$CHROME_PATH" | |
| 351 initial_environment_checks | |
| 352 # Check for a clean workdir. | |
| 353 [[ -z "$(git status -s -uno)" ]] \ | |
| 354 || die "Workspace is not clean. Please commit or undo your changes." | |
| 355 # Assert that the DEPS file is there. | |
| 356 [[ -w "DEPS" ]] || die "DEPS file not present or not writable; \ | |
| 357 current directory is: $(pwd)." | |
| 358 fi | |
| 359 | |
| 360 let CURRENT_STEP+=1 | |
| 361 if [ $START_STEP -le $CURRENT_STEP ] ; then | |
| 362 echo ">>> Step $CURRENT_STEP: Update the checkout and create a new branch." | |
| 363 git checkout master || die "'git checkout master' failed." | |
| 364 git pull || die "'git pull' failed, please try again." | |
| 365 restore_if_unset "TRUNK_REVISION" | |
| 366 git checkout -b "v8-roll-$TRUNK_REVISION" \ | |
| 367 || die "Failed to checkout a new branch." | |
| 368 fi | |
| 369 | |
| 370 let CURRENT_STEP+=1 | |
| 371 if [ $START_STEP -le $CURRENT_STEP ] ; then | |
| 372 echo ">>> Step $CURRENT_STEP: Create and upload CL." | |
| 373 # Patch DEPS file. | |
| 374 sed -r -e "/\"v8_revision\": /s/\"[0-9]+\"/\"$TRUNK_REVISION\"/" \ | |
| 375 -i DEPS | |
| 376 restore_version_if_unset | |
| 377 echo -n "Please enter the email address of a reviewer for the roll CL: " | |
| 378 read REVIEWER | |
| 379 git commit -am "Update V8 to version $MAJOR.$MINOR.$BUILD. | |
| 380 | |
| 381 TBR=$REVIEWER" || die "'git commit' failed." | |
| 382 git cl upload --send-mail \ | |
| 383 || die "'git cl upload' failed, please try again." | |
| 384 echo "CL uploaded." | |
| 385 fi | |
| 386 | |
| 387 let CURRENT_STEP+=1 | |
| 388 if [ $START_STEP -le $CURRENT_STEP ] ; then | |
| 389 echo ">>> Step $CURRENT_STEP: Returning to V8 checkout." | |
| 390 restore_if_unset "V8_PATH" | |
| 391 cd "$V8_PATH" | |
| 392 fi | |
| 393 fi # if [ -n "$CHROME_PATH" ] | |
| 394 | |
| 395 let CURRENT_STEP+=1 | |
| 396 if [ $START_STEP -le $CURRENT_STEP ] ; then | |
| 397 echo ">>> Step $CURRENT_STEP: Done!" | |
| 398 restore_version_if_unset | |
| 399 restore_if_unset "TRUNK_REVISION" | |
| 400 if [ -n "$CHROME_PATH" ] ; then | |
| 401 echo "Congratulations, you have successfully created the trunk revision \ | |
| 402 $MAJOR.$MINOR.$BUILD and rolled it into Chromium. Please don't forget to \ | |
| 403 update the v8rel spreadsheet:" | |
| 404 else | |
| 405 echo "Congratulations, you have successfully created the trunk revision \ | |
| 406 $MAJOR.$MINOR.$BUILD. Please don't forget to roll this new version into \ | |
| 407 Chromium, and to update the v8rel spreadsheet:" | |
| 408 fi | |
| 409 echo -e "$MAJOR.$MINOR.$BUILD\ttrunk\t$TRUNK_REVISION" | |
| 410 common_cleanup | |
| 411 [[ "$TRUNKBRANCH" != "$CURRENT_BRANCH" ]] && git branch -D $TRUNKBRANCH | |
| 412 fi | |
| OLD | NEW |