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
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.
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.
30 ########## Global variable definitions
32 BRANCHNAME=prepare-push
33 TRUNKBRANCH=trunk-push
34 PERSISTFILE_BASENAME=/tmp/v8-push-to-trunk-tempfile
37 ########## Function definitions
39 source $(dirname $BASH_SOURCE)/common-includes.sh
45 Performs the necessary steps for a V8 push to trunk. Only works for \
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
57 ########## Option parsing
59 while getopts ":hs:l:c:" OPTION ; do
68 c) CHROME_PATH=$OPTARG
70 ?) echo "Illegal option: -$OPTARG"
78 ########## Regular workflow
80 initial_environment_checks
82 if [ $START_STEP -le $CURRENT_STEP ] ; then
83 echo ">>> Step $CURRENT_STEP: Preparation"
85 delete_branch $TRUNKBRANCH
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."
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)
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
107 LASTPUSH=$(git log -1 --format=%H $LASTPUSH^ ChangeLog)
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
119 DATE=$(date +%Y-%m-%d)
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
129 git log -1 $commit --format="%B" \
130 | grep "^BUG=" | grep -v "BUG=$" | grep -v "BUG=none$" \
132 | sed -e 's/BUG=v8:\(.*\)$/(issue \1)/' \
133 | sed -e 's/BUG=\(.*\)$/(Chromium issue \1)/' \
134 >> "$CHANGELOG_ENTRY_FILE"
135 # Append the commit's author for reference.
136 git log -1 $commit --format="%w(80,8,8)(%an)" >> "$CHANGELOG_ENTRY_FILE"
137 echo "" >> "$CHANGELOG_ENTRY_FILE"
139 echo " Performance and stability improvements on all platforms." \
140 >> "$CHANGELOG_ENTRY_FILE"
144 if [ $START_STEP -le $CURRENT_STEP ] ; then
145 echo ">>> Step $CURRENT_STEP: Edit ChangeLog entry."
146 echo -n "Please press <Return> to have your EDITOR open the ChangeLog entry, \
147 then edit its contents to your liking. When you're done, save the file and \
150 $EDITOR "$CHANGELOG_ENTRY_FILE"
151 NEWCHANGELOG=$(mktemp)
152 # Eliminate any trailing newlines by going through a shell variable.
153 # Also (1) eliminate tabs, (2) fix too little and (3) too much indentation,
154 # and (4) eliminate trailing whitespace.
155 CHANGELOGENTRY=$(cat "$CHANGELOG_ENTRY_FILE" \
156 | sed -e 's/\t/ /g' \
157 | sed -e 's/^ \{1,7\}\([^ ]\)/ \1/g' \
158 | sed -e 's/^ \{9,80\}\([^ ]\)/ \1/g' \
160 [[ -n "$CHANGELOGENTRY" ]] || die "Empty ChangeLog entry."
161 echo "$CHANGELOGENTRY" > "$NEWCHANGELOG"
162 echo "" >> "$NEWCHANGELOG" # Explicitly insert two empty lines.
163 echo "" >> "$NEWCHANGELOG"
164 cat ChangeLog >> "$NEWCHANGELOG"
165 mv "$NEWCHANGELOG" ChangeLog
169 if [ $START_STEP -le $CURRENT_STEP ] ; then
170 echo ">>> Step $CURRENT_STEP: Increment version number."
171 restore_if_unset "BUILD"
172 NEWBUILD=$(($BUILD + 1))
173 confirm "Automatically increment BUILD_NUMBER? (Saying 'n' will fire up \
174 your EDITOR on $VERSION_FILE so you can make arbitrary changes. When \
175 you're done, save the file and exit your EDITOR.)"
176 if [ $? -eq 0 ] ; then
177 sed -e "/#define BUILD_NUMBER/s/[0-9]*$/$NEWBUILD/" \
180 $EDITOR "$VERSION_FILE"
182 read_and_persist_version "NEW"
186 if [ $START_STEP -le $CURRENT_STEP ] ; then
187 echo ">>> Step $CURRENT_STEP: Commit to local branch."
188 restore_version_if_unset "NEW"
189 PREPARE_COMMIT_MSG="Prepare push to trunk. \
190 Now working on version $NEWMAJOR.$NEWMINOR.$NEWBUILD."
191 persist "PREPARE_COMMIT_MSG"
192 git commit -a -m "$PREPARE_COMMIT_MSG" \
193 || die "'git commit -a' failed."
199 if [ $START_STEP -le $CURRENT_STEP ] ; then
200 echo ">>> Step $CURRENT_STEP: Commit to the repository."
202 # Re-read the ChangeLog entry (to pick up possible changes).
203 cat ChangeLog | awk --posix '{
204 if ($0 ~ /^[0-9]{4}-[0-9]{2}-[0-9]{2}:/) {
205 if (in_firstblock == 1) {
212 }' > "$CHANGELOG_ENTRY_FILE"
213 git cl dcommit || die "'git cl dcommit' failed, please try again."
217 if [ $START_STEP -le $CURRENT_STEP ] ; then
218 echo ">>> Step $CURRENT_STEP: Fetch straggler commits that sneaked in \
219 since this script was started."
220 git svn fetch || die "'git svn fetch' failed."
221 git checkout svn/bleeding_edge
222 restore_if_unset "PREPARE_COMMIT_MSG"
223 PREPARE_COMMIT_HASH=$(git log -1 --format=%H --grep="$PREPARE_COMMIT_MSG")
224 persist "PREPARE_COMMIT_HASH"
228 if [ $START_STEP -le $CURRENT_STEP ] ; then
229 echo ">>> Step $CURRENT_STEP: Squash commits into one."
230 # Instead of relying on "git rebase -i", we'll just create a diff, because
231 # that's easier to automate.
232 restore_if_unset "PREPARE_COMMIT_HASH"
233 git diff svn/trunk $PREPARE_COMMIT_HASH > "$PATCH_FILE"
234 # Convert the ChangeLog entry to commit message format:
236 # - remove indentation
237 # - merge paragraphs into single long lines, keeping empty lines between them.
238 restore_if_unset "DATE"
239 CHANGELOGENTRY=$(cat "$CHANGELOG_ENTRY_FILE")
240 echo "$CHANGELOGENTRY" \
241 | sed -e "s/^$DATE: //" \
244 if (need_space == 1) {
254 }' > "$COMMITMSG_FILE" || die "Commit message editing failed."
255 rm -f "$CHANGELOG_ENTRY_FILE"
259 if [ $START_STEP -le $CURRENT_STEP ] ; then
260 echo ">>> Step $CURRENT_STEP: Create a new branch from trunk."
261 git checkout -b $TRUNKBRANCH svn/trunk \
262 || die "Checking out a new branch '$TRUNKBRANCH' failed."
266 if [ $START_STEP -le $CURRENT_STEP ] ; then
267 echo ">>> Step $CURRENT_STEP: Apply squashed changes."
268 rm -f "$TOUCHED_FILES_FILE"
269 apply_patch "$PATCH_FILE"
275 if [ $START_STEP -le $CURRENT_STEP ] ; then
276 echo ">>> Step $CURRENT_STEP: Set correct version for trunk."
277 restore_version_if_unset
278 sed -e "/#define MAJOR_VERSION/s/[0-9]*$/$MAJOR/" \
279 -e "/#define MINOR_VERSION/s/[0-9]*$/$MINOR/" \
280 -e "/#define BUILD_NUMBER/s/[0-9]*$/$BUILD/" \
281 -e "/#define PATCH_LEVEL/s/[0-9]*$/0/" \
282 -e "/#define IS_CANDIDATE_VERSION/s/[0-9]*$/0/" \
283 -i "$VERSION_FILE" || die "Patching $VERSION_FILE failed."
287 if [ $START_STEP -le $CURRENT_STEP ] ; then
288 echo ">>> Step $CURRENT_STEP: Commit to local trunk branch."
289 git add "$VERSION_FILE"
290 git commit -F "$COMMITMSG_FILE" || die "'git commit' failed."
291 rm -f "$COMMITMSG_FILE"
295 if [ $START_STEP -le $CURRENT_STEP ] ; then
296 echo ">>> Step $CURRENT_STEP: Sanity check."
297 confirm "Please check if your local checkout is sane: Inspect $VERSION_FILE, \
298 compile, run tests. Do you want to commit this new trunk revision to the \
300 [[ $? -eq 0 ]] || die "Execution canceled."
304 if [ $START_STEP -le $CURRENT_STEP ] ; then
305 echo ">>> Step $CURRENT_STEP: Commit to SVN."
306 git svn dcommit | tee >(grep -E "^Committed r[0-9]+" \
307 | sed -e 's/^Committed r\([0-9]\+\)/\1/' \
308 > "$TRUNK_REVISION_FILE") \
309 || die "'git svn dcommit' failed."
310 TRUNK_REVISION=$(cat "$TRUNK_REVISION_FILE")
311 persist "TRUNK_REVISION"
312 rm -f "$TRUNK_REVISION_FILE"
316 if [ $START_STEP -le $CURRENT_STEP ] ; then
317 echo ">>> Step $CURRENT_STEP: Tag the new revision."
318 restore_version_if_unset
319 git svn tag $MAJOR.$MINOR.$BUILD -m "Tagging version $MAJOR.$MINOR.$BUILD" \
320 || die "'git svn tag' failed."
323 if [ -n "$CHROME_PATH" ] ; then
326 if [ $START_STEP -le $CURRENT_STEP ] ; then
327 echo ">>> Step $CURRENT_STEP: Switch to Chromium checkout."
331 initial_environment_checks
332 # Check for a clean workdir.
333 [[ -z "$(git status -s -uno)" ]] \
334 || die "Workspace is not clean. Please commit or undo your changes."
335 # Assert that the DEPS file is there.
336 [[ -w "DEPS" ]] || die "DEPS file not present or not writable; \
337 current directory is: $(pwd)."
341 if [ $START_STEP -le $CURRENT_STEP ] ; then
342 echo ">>> Step $CURRENT_STEP: Update the checkout and create a new branch."
343 git checkout master || die "'git checkout master' failed."
344 git pull || die "'git pull' failed, please try again."
345 restore_if_unset "TRUNK_REVISION"
346 git checkout -b "v8-roll-$TRUNK_REVISION" \
347 || die "Failed to checkout a new branch."
351 if [ $START_STEP -le $CURRENT_STEP ] ; then
352 echo ">>> Step $CURRENT_STEP: Create and upload CL."
354 sed -r -e "/\"v8_revision\": /s/\"[0-9]+\"/\"$TRUNK_REVISION\"/" \
356 restore_version_if_unset
357 echo -n "Please enter the email address of a reviewer for the roll CL: "
359 git commit -am "Update V8 to version $MAJOR.$MINOR.$BUILD.
361 TBR=$REVIEWER" || die "'git commit' failed."
362 git cl upload --send-mail \
363 || die "'git cl upload' failed, please try again."
368 if [ $START_STEP -le $CURRENT_STEP ] ; then
369 echo ">>> Step $CURRENT_STEP: Returning to V8 checkout."
370 restore_if_unset "V8_PATH"
373 fi # if [ -n "$CHROME_PATH" ]
376 if [ $START_STEP -le $CURRENT_STEP ] ; then
377 echo ">>> Step $CURRENT_STEP: Done!"
378 restore_version_if_unset
379 restore_if_unset "TRUNK_REVISION"
380 if [ -n "$CHROME_PATH" ] ; then
381 echo "Congratulations, you have successfully created the trunk revision \
382 $MAJOR.$MINOR.$BUILD and rolled it into Chromium. Please don't forget to \
383 update the v8rel spreadsheet:"
385 echo "Congratulations, you have successfully created the trunk revision \
386 $MAJOR.$MINOR.$BUILD. Please don't forget to roll this new version into \
387 Chromium, and to update the v8rel spreadsheet:"
389 echo -e "$MAJOR.$MINOR.$BUILD\ttrunk\t$TRUNK_REVISION"
391 [[ "$TRUNKBRANCH" != "$CURRENT_BRANCH" ]] && git branch -D $TRUNKBRANCH