Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(748)

Side by Side Diff: tools/push-to-trunk.sh

Issue 7835035: Introduce push-to-trunk.sh (for git users) (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: address comments Created 9 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/bin/bash
2 # Copyright 2011 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 TEMP_BRANCH=v8-push-to-trunk-script-temporary-branch
35 VERSION_FILE="src/version.cc"
36 PERSISTFILE_BASENAME=/tmp/v8-push-to-trunk-tempfile
37 CHANGELOG_ENTRY_FILE="$PERSISTFILE_BASENAME-changelog-entry"
38 PATCH_FILE="$PERSISTFILE_BASENAME-patch"
39 COMMITMSG_FILE="$PERSISTFILE_BASENAME-commitmsg"
40 TOUCHED_FILES_FILE="$PERSISTFILE_BASENAME-touched-files"
41 STEP=0
42
43
44 ########## Function definitions
45
46 usage() {
47 cat << EOF
48 usage: $0 OPTIONS
49
50 Performs the necessary steps for a V8 push to trunk. Only works for \
51 git checkouts.
52
53 OPTIONS:
54 -h Show this message
55 -s Specify the step where to start work. Default: 0.
56 -l Manually specify the git commit ID of the last push to trunk.
57 EOF
58 }
59
60 die() {
61 [[ -n "$1" ]] && echo "Error: $1"
62 echo "Exiting."
63 exit 1
64 }
65
66 confirm() {
67 echo -n "$1 [Y/n] "
68 read ANSWER
69 if [[ -z "$ANSWER" || "$ANSWER" == "Y" || "$ANSWER" == "y" ]] ; then
70 return 0
71 else
72 return 1
73 fi
74 }
75
76 delete_branch() {
77 local MATCH=$(git branch | grep $1)
78 if [ "$MATCH" == "$1" ] ; then
79 confirm "Branch $1 exists, do you want to delete it?"
80 if [ $? -eq 0 ] ; then
81 git branch -D $1
82 echo "Branch $1 deleted."
83 else
84 die "Can't continue. Please delete branch $1 and try again."
85 fi
86 fi
87 }
88
89 # Persist and restore variables to support canceling/resuming execution
90 # of this script.
91 persist() {
92 local VARNAME=$1
93 local FILE="$PERSISTFILE_BASENAME-$VARNAME"
94 echo "${!VARNAME}" > $FILE
95 }
96
97 restore() {
98 local VARNAME=$1
99 local FILE="$PERSISTFILE_BASENAME-$VARNAME"
100 local VALUE="$(cat $FILE)"
101 eval "$VARNAME=\"$VALUE\""
102 }
103
104 restore_if_unset() {
105 local VARNAME=$1
106 [[ -z "${!VARNAME}" ]] && restore "$VARNAME"
107 [[ -z "${!VARNAME}" ]] && die "Variable '$VARNAME' could not be restored."
108 }
109
110
111 ########## Option parsing
112
113 while getopts ":hs:l:" OPTION ; do
114 case $OPTION in
115 h) usage
116 exit 0
117 ;;
118 s) STEP=$OPTARG
119 ;;
120 l) LASTPUSH=$OPTARG
121 ;;
122 ?) echo "Illegal option: -$OPTARG"
123 usage
124 exit 1
125 ;;
126 esac
127 done
128
129
130 ########## Regular workflow
131
132 # Cancel if this is not a git checkout.
133 [[ -d .git ]] \
134 || die "This is not a git checkout, this script won't work for you."
135
136 # Cancel if EDITOR is unset or not executable.
137 [[ -n "$EDITOR" && -x "$(which $EDITOR)" ]] \
138 || die "Please set your EDITOR environment variable, you'll need it."
139
140 if [ $STEP -le 0 ] ; then
141 echo ">>> Step 0: Preparation"
142 # Check for a clean workdir.
143 [[ -z "$(git status -s -uno)" ]] \
144 || die "Workspace is not clean. Please commit or undo your changes."
145
146 # Persist current branch.
147 CURRENT_BRANCH=$(git status -s -b -uno | grep "^##" | awk '{print $2}')
148 persist "CURRENT_BRANCH"
149 # Get ahold of a safe temporary branch and check it out.
150 if [ "$CURRENT_BRANCH" != "$TEMP_BRANCH" ] ; then
151 delete_branch $TEMP_BRANCH
152 git checkout -b $TEMP_BRANCH
153 fi
154 # Delete branches if they exist.
155 delete_branch $BRANCHNAME
156 delete_branch $TRUNKBRANCH
157 fi
158
159 if [ $STEP -le 1 ] ; then
160 echo ">>> Step 1: Fetch unfetched revisions."
161 git svn fetch || die "'git svn fetch' failed."
162 fi
163
164 if [ $STEP -le 2 ] ; then
165 echo ">>> Step 2: Create a fresh branch."
166 git checkout -b $BRANCHNAME svn/bleeding_edge \
167 || die "Creating branch $BRANCHNAME failed."
168 fi
169
170 if [ $STEP -le 3 ] ; then
171 echo ">>> Step 3: Detect commit ID of last push to trunk."
172 [[ -n "$LASTPUSH" ]] || LASTPUSH=$(git log -1 --format=%H ChangeLog)
173 LOOP=1
174 while [ $LOOP -eq 1 ] ; do
175 # Print assumed commit, circumventing git's pager.
176 git log -1 $LASTPUSH | cat
177 confirm "Is the commit printed above the last push to trunk?"
178 if [ $? -eq 0 ] ; then
179 LOOP=0
180 else
181 LASTPUSH=$(git log -1 --format=%H $LASTPUSH^ ChangeLog)
182 fi
183 done
184 persist "LASTPUSH"
185 fi
186
187 if [ $STEP -le 4 ] ; then
188 echo ">>> Step 4: Prepare raw ChangeLog entry."
189 # These version numbers are used again later for the trunk commit.
190 MAJOR=$(grep "#define MAJOR_VERSION" "$VERSION_FILE" | awk '{print $NF}')
191 persist "MAJOR"
192 MINOR=$(grep "#define MINOR_VERSION" "$VERSION_FILE" | awk '{print $NF}')
193 persist "MINOR"
194 BUILD=$(grep "#define BUILD_NUMBER" "$VERSION_FILE" | awk '{print $NF}')
195 persist "BUILD"
196
197 DATE=$(date +%Y-%m-%d)
198 persist "DATE"
199 echo "$DATE: Version $MAJOR.$MINOR.$BUILD" > "$CHANGELOG_ENTRY_FILE"
200 echo "" >> "$CHANGELOG_ENTRY_FILE"
201 COMMITS=$(git log $LASTPUSH..HEAD --format=%H)
202 for commit in $COMMITS ; do
203 # Get the commit's title line.
204 git log -1 $commit --format="%w(80,8,8)%s" >> "$CHANGELOG_ENTRY_FILE"
205 # Grep for "BUG=xxxx" lines in the commit message.
206 git log -1 $commit --format="%b" | grep BUG= | grep -v "BUG=$" \
207 | sed -e 's/^/ /' \
208 >> "$CHANGELOG_ENTRY_FILE"
209 # Append the commit's author for reference.
210 git log -1 $commit --format="%w(80,8,8)(%an)" >> "$CHANGELOG_ENTRY_FILE"
211 echo "" >> "$CHANGELOG_ENTRY_FILE"
212 done
213 fi
214
215 if [ $STEP -le 5 ] ; then
216 echo ">>> Step 5: Edit ChangeLog entry."
217 echo -n "Please press <Return> to have your EDITOR open the ChangeLog entry, \
218 then edit its contents to your liking. When you're done, save the file and \
219 exit your EDITOR. "
220 read ANSWER
221 $EDITOR "$CHANGELOG_ENTRY_FILE"
222 NEWCHANGELOG=$(mktemp)
223 # Eliminate any trailing newlines by going through a shell variable.
224 CHANGELOGENTRY=$(cat "$CHANGELOG_ENTRY_FILE")
225 [[ -n "$CHANGELOGENTRY" ]] || die "Empty ChangeLog entry."
226 echo "$CHANGELOGENTRY" > "$NEWCHANGELOG"
227 echo "" >> "$NEWCHANGELOG" # Explicitly insert two empty lines.
228 echo "" >> "$NEWCHANGELOG"
229 cat ChangeLog >> "$NEWCHANGELOG"
230 mv "$NEWCHANGELOG" ChangeLog
231 fi
232
233 if [ $STEP -le 6 ] ; then
234 echo ">>> Step 6: Increment version number."
235 restore_if_unset "BUILD"
236 NEWBUILD=$(($BUILD + 1))
237 confirm "Automatically increment BUILD_NUMBER? (Saying 'n' will fire up \
238 your EDITOR on $VERSION_FILE so you can make arbitrary changes. When \
239 you're done, save the file and exit your EDITOR.)"
240 if [ $? -eq 0 ] ; then
241 sed -e "/#define BUILD_NUMBER/s/[0-9]*$/$NEWBUILD/" \
242 -i "$VERSION_FILE"
243 else
244 $EDITOR "$VERSION_FILE"
245 fi
246 NEWMAJOR=$(grep "#define MAJOR_VERSION" "$VERSION_FILE" | awk '{print $NF}')
247 persist "NEWMAJOR"
248 NEWMINOR=$(grep "#define MINOR_VERSION" "$VERSION_FILE" | awk '{print $NF}')
249 persist "NEWMINOR"
250 NEWBUILD=$(grep "#define BUILD_NUMBER" "$VERSION_FILE" | awk '{print $NF}')
251 persist "NEWBUILD"
252 fi
253
254 if [ $STEP -le 7 ] ; then
255 echo ">>> Step 7: Commit to local branch."
256 restore_if_unset "NEWMAJOR"
257 restore_if_unset "NEWMINOR"
258 restore_if_unset "NEWBUILD"
259 git commit -a -m "Prepare push to trunk. \
260 Now working on version $NEWMAJOR.$NEWMINOR.$NEWBUILD." \
261 || die "'git commit -a' failed."
262 fi
263
264 if [ $STEP -le 8 ] ; then
265 echo ">>> Step 8: Upload for code review."
266 echo -n "Please enter the email address of a V8 reviewer for your patch: "
267 read REVIEWER
268 git cl upload -r $REVIEWER --send-mail \
269 || die "'git cl upload' failed, please try again."
270 fi
271
272 if [ $STEP -le 9 ] ; then
273 echo ">>> Step 9: Commit to the repository."
274 echo "Please wait for an LGTM, then type \"LGTM<Return>\" to commit your \
275 change. (If you need to iterate on the patch, do so in another shell.)"
276 unset ANSWER
277 while [ "$ANSWER" != "LGTM" ] ; do
278 [[ -n "$ANSWER" ]] && echo "That was not 'LGTM'."
279 echo -n "> "
280 read ANSWER
281 done
282 # Re-read the ChangeLog entry (to pick up possible changes).
283 cat ChangeLog | awk --posix '{
284 if ($0 ~ /^[0-9]{4}-[0-9]{2}-[0-9]{2}:/) {
285 if (in_firstblock == 1) {
286 exit 0;
287 } else {
288 in_firstblock = 1;
289 }
290 };
291 print $0;
292 }' > "$CHANGELOG_ENTRY_FILE"
293 git cl dcommit || die "'git cl dcommit' failed, please try again."
294 fi
295
296 if [ $STEP -le 10 ] ; then
297 echo ">>> Step 10: NOP"
298 # Present in the manual guide, not necessary (even harmful!) for this script.
299 fi
300
301 if [ $STEP -le 11 ] ; then
302 echo ">>> Step 11: Squash commits into one."
303 # Instead of relying on "git rebase -i", we'll just create a diff, because
304 # that's easier to automate.
305 git diff svn/trunk > "$PATCH_FILE"
306 # Convert the ChangeLog entry to commit message format:
307 # - remove date
308 # - remove indentation
309 # - merge paragraphs into single long lines, keeping empty lines between them.
310 restore_if_unset "DATE"
311 CHANGELOGENTRY=$(cat "$CHANGELOG_ENTRY_FILE")
312 echo "$CHANGELOGENTRY" \
313 | sed -e "s/^$DATE: //" \
314 | sed -e 's/^ *//' \
315 | awk '{
316 if (need_space == 1) {
317 printf(" ");
318 };
319 printf("%s", $0);
320 if ($0 ~ /^$/) {
321 printf("\n\n");
322 need_space = 0;
323 } else {
324 need_space = 1;
325 }
326 }' > "$COMMITMSG_FILE" || die "Commit message editing failed."
327 LOOP=1
328 while [ $LOOP -eq 1 ] ; do
329 echo "This is the trunk commit message:"
330 echo "--------------------"
331 cat "$COMMITMSG_FILE"
332 echo -e "\n--------------------"
333 confirm "Does this look good to you? (Saying 'n' will fire up your \
334 EDITOR so you can change the commit message. When you're done, save the \
335 file and exit your EDITOR.)"
336 if [ $? -eq 0 ] ; then
337 LOOP=0
338 else
339 $EDITOR "$COMMITMSG_FILE"
340 fi
341 done
342 rm -f "$CHANGELOG_ENTRY_FILE"
343 fi
344
345 if [ $STEP -le 12 ] ; then
346 echo ">>> Step 12: Create a new branch from trunk."
347 git checkout -b $TRUNKBRANCH svn/trunk \
348 || die "Checking out a new branch '$TRUNKBRANCH' failed."
349 fi
350
351 if [ $STEP -le 13 ] ; then
352 echo ">>> Step 13: Apply squashed changes."
353 patch -p1 < "$PATCH_FILE" | tee >(awk '{print $NF}' >> "$TOUCHED_FILES_FILE")
354 [[ $? -eq 0 ]] || die "Applying the patch to trunk failed."
355 TOUCHED_FILES=$(cat "$TOUCHED_FILES_FILE")
356 for FILE in $TOUCHED_FILES ; do
357 git add "$FILE"
358 done
359 rm -f "$PATCH_FILE"
360 rm -f "$TOUCHED_FILES_FILE"
361 fi
362
363 if [ $STEP -le 14 ] ; then
364 echo ">>> Step 14: Set correct version for trunk."
365 restore_if_unset "MAJOR"
366 restore_if_unset "MINOR"
367 restore_if_unset "BUILD"
368 sed -e "/#define MAJOR_VERSION/s/[0-9]*$/$MAJOR/" \
369 -e "/#define MINOR_VERSION/s/[0-9]*$/$MINOR/" \
370 -e "/#define BUILD_NUMBER/s/[0-9]*$/$BUILD/" \
371 -e "/#define PATCH_LEVEL/s/[0-9]*$/0/" \
372 -e "/#define IS_CANDIDATE_VERSION/s/[0-9]*$/0/" \
373 -i "$VERSION_FILE" || die "Patching $VERSION_FILE failed."
374 fi
375
376 if [ $STEP -le 15 ] ; then
377 echo ">>> Step 15: Commit to local trunk branch."
378 git add "$VERSION_FILE"
379 git commit -F "$COMMITMSG_FILE" || die "'git commit' failed."
380 rm -f "$COMMITMSG_FILE"
381 fi
382
383 if [ $STEP -le 16 ] ; then
384 echo ">>> Step 16: Sanity check."
385 confirm "Please check if your local checkout is sane: Inspect $VERSION_FILE, \
386 compile, run tests. Do you want to commit this new trunk revision to the \
387 repository?"
388 [[ $? -eq 0 ]] || die "Execution canceled."
389 fi
390
391 if [ $STEP -le 17 ] ; then
392 echo ">>> Step 17. Commit to SVN."
393 git svn dcommit || die "'git svn dcommit' failed."
394 fi
395
396 if [ $STEP -le 18 ] ; then
397 echo ">>> Step 18: Tag the new revision."
398 restore_if_unset "MAJOR"
399 restore_if_unset "MINOR"
400 restore_if_unset "BUILD"
401 git svn tag $MAJOR.$MINOR.$BUILD -m "Tagging version $MAJOR.$MINOR.$BUILD" \
402 || die "'git svn tag' failed."
403 fi
404
405 if [ $STEP -le 19 ] ; then
406 echo ">>> Step 19: Cleanup."
407 restore_if_unset "CURRENT_BRANCH"
408 git checkout -f $CURRENT_BRANCH
409 [[ "$TEMP_BRANCH" != "$CURRENT_BRANCH" ]] && git branch -D $TEMP_BRANCH
410 [[ "$BRANCHNAME" != "$CURRENT_BRANCH" ]] && git branch -D $BRANCHNAME
411 [[ "$TRUNKBRANCH" != "$CURRENT_BRANCH" ]] && git branch -D $TRUNKBRANCH
412 fi
413
414 if [ $STEP -le 20 ] ; then
415 echo ">>> Step 20: Done!"
416 restore_if_unset "MAJOR"
417 restore_if_unset "MINOR"
418 restore_if_unset "BUILD"
419 echo "Congratulations, you have successfully created the trunk revision \
420 $MAJOR.$MINOR.$BUILD. Please don't forget to update the v8rel spreadsheet, \
421 and to roll this new version into Chromium."
422 # Clean up all temporary files.
423 rm -f "$PERSISTFILE_BASENAME"*
424 fi
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698