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

Side by Side Diff: tools/merge-to-branch.sh

Issue 9298012: Add patch-merging script (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: fix bugs Created 8 years, 10 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 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
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