OLD | NEW |
---|---|
(Empty) | |
1 #!/bin/bash | |
2 # Copyright 2011 the V8 project authors. All rights reserved. | |
Jakob Kummerow
2012/01/27 16:28:12
nit: 2012
danno
2012/01/31 10:37:57
Done.
| |
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 CHANGELOG_ENTRY_FILE="$PERSISTFILE_BASENAME-changelog-entry" | |
35 PATCH_FILE="$PERSISTFILE_BASENAME-patch" | |
36 COMMITMSG_FILE="$PERSISTFILE_BASENAME-commitmsg" | |
37 COMMITMSG_FILE_COPY="$PERSISTFILE_BASENAME-commitmsg-copy" | |
38 TOUCHED_FILES_FILE="$PERSISTFILE_BASENAME-touched-files" | |
39 TRUNK_REVISION_FILE="$PERSISTFILE_BASENAME-trunkrevision" | |
40 STEP=0 | |
41 | |
42 usage() { | |
43 cat << EOF | |
44 usage: $0 [OPTIONS]... BRANCH [REVISION]... | |
45 | |
46 Performs the necessary steps to merge revisions from bleeding_edge | |
47 to other branches, including trunk. | |
48 | |
49 OPTIONS: | |
50 -h Show this message | |
51 -s Specify the step where to start work. Default: 0. | |
52 EOF | |
53 } | |
54 | |
55 ########## Function definitions | |
56 | |
57 die() { | |
58 [[ -n "$1" ]] && echo "Error: $1" | |
59 echo "Exiting." | |
60 exit 1 | |
61 } | |
62 | |
63 confirm() { | |
64 echo -n "$1 [Y/n] " | |
65 read ANSWER | |
66 if [[ -z "$ANSWER" || "$ANSWER" == "Y" || "$ANSWER" == "y" ]] ; then | |
67 return 0 | |
68 else | |
69 return 1 | |
70 fi | |
71 } | |
72 | |
73 delete_branch() { | |
74 local MATCH=$(git branch | grep $1 | awk '{print $NF}' ) | |
75 if [ "$MATCH" == "$1" ] ; then | |
76 confirm "Branch $1 exists, do you want to delete it?" | |
77 if [ $? -eq 0 ] ; then | |
78 git branch -D $1 || die "Deleting branch '$1' failed." | |
79 echo "Branch $1 deleted." | |
80 else | |
81 die "Can't continue. Please delete branch $1 and try again." | |
82 fi | |
83 fi | |
84 } | |
85 | |
86 # Persist and restore variables to support canceling/resuming execution | |
87 # of this script. | |
88 persist() { | |
89 local VARNAME=$1 | |
90 local FILE="$PERSISTFILE_BASENAME-$VARNAME" | |
91 echo "${!VARNAME}" > $FILE | |
92 } | |
93 | |
94 restore() { | |
95 local VARNAME=$1 | |
96 local FILE="$PERSISTFILE_BASENAME-$VARNAME" | |
97 local VALUE="$(cat $FILE)" | |
98 eval "$VARNAME=\"$VALUE\"" | |
99 } | |
100 | |
101 restore_if_unset() { | |
102 local VARNAME=$1 | |
103 [[ -z "${!VARNAME}" ]] && restore "$VARNAME" | |
104 [[ -z "${!VARNAME}" ]] && die "Variable '$VARNAME' could not be restored." | |
105 } | |
106 | |
107 | |
108 ########## Option parsing | |
109 | |
110 while getopts ":hs:" OPTION ; do | |
111 case $OPTION in | |
112 h) usage | |
113 exit 0 | |
114 ;; | |
115 s) STEP=$OPTARG | |
116 ;; | |
117 ?) echo "Illegal option: -$OPTARG" | |
118 usage | |
119 exit 1 | |
120 ;; | |
121 esac | |
122 done | |
123 | |
124 MERGE_TO_BRANCH=$1 | |
125 [[ -n "$MERGE_TO_BRANCH" ]] \ | |
126 || die "Please specify a branch to merge to" | |
127 shift | |
128 | |
129 MERGE_REVISION=$1 | |
130 [[ -n "$MERGE_REVISION" ]] \ | |
131 || die "Please specify a svn revision to merge" | |
132 | |
133 ########## Regular workflow | |
134 | |
135 # Cancel if this is not a git checkout. | |
136 [[ -d .git ]] \ | |
137 || die "This is not a git checkout, this script won't work for you." | |
138 | |
139 # Cancel if EDITOR is unset or not executable. | |
140 [[ -n "$EDITOR" && -x "$(which $EDITOR)" ]] \ | |
141 || die "Please set your EDITOR environment variable, you'll need it." | |
142 | |
143 if [ $STEP -le 0 ] ; then | |
144 echo ">>> Step 0: Preparation" | |
145 # Check for a clean workdir. | |
146 [[ -z "$(git status -s -uno)" ]] \ | |
147 || die "Workspace is not clean. Please commit or undo your changes." | |
148 | |
149 # Persist current branch. | |
150 CURRENT_BRANCH=$(git status -s -b -uno | grep "^##" | awk '{print $2}') | |
151 persist "CURRENT_BRANCH" | |
152 delete_branch $BRANCHNAME | |
153 fi | |
154 | |
155 if [ $STEP -le 1 ] ; then | |
156 echo ">>> Step 1: Fetch unfetched revisions." | |
157 git svn fetch || die "'git svn fetch' failed." | |
158 fi | |
159 | |
160 if [ $STEP -le 2 ] ; then | |
161 echo ">>> Step 2: Create a fresh branch for the patch." | |
162 git checkout -b $BRANCHNAME svn/$MERGE_TO_BRANCH \ | |
163 || die "Creating branch $BRANCHNAME failed." | |
164 fi | |
165 | |
166 if [ $STEP -le 3 ] ; then | |
167 echo ">>> Step 3: Find the git revsions associated with the patches." | |
Jakob Kummerow
2012/01/27 16:28:12
nit: "revisions"
danno
2012/01/31 10:37:57
Done.
| |
168 current=0 | |
169 for REVISION in "$@" | |
Jakob Kummerow
2012/01/27 16:28:12
nit: You can get closer to our C++ style by puttin
danno
2012/01/31 10:37:57
Done.
| |
170 do | |
171 NEXT_HASH=$(git svn find-rev "r$REVISION" bleeding_edge) | |
Jakob Kummerow
2012/01/27 16:28:12
"bleeding_edge" is one of your local git branches.
danno
2012/01/31 10:37:57
Done.
| |
172 [[ -n "$NEXT_HASH" ]] \ | |
173 || die "Cannot determine git hash for r$REVISION" | |
174 PATCH_COMMIT_HASHES[$current]="$NEXT_HASH" | |
175 if [ "$NEW_COMMIT_MSG" ] ; then | |
Jakob Kummerow
2012/01/27 16:28:12
for consistency:
[[ -n "$NEW_COMMIT_MSG" ]] && NE
danno
2012/01/31 10:37:57
Done.
| |
176 NEW_COMMIT_MSG="$NEW_COMMIT_MSG," | |
177 fi | |
178 NEW_COMMIT_MSG="$NEW_COMMIT_MSG r$REVISION" | |
179 let current+=1 | |
180 done | |
181 NEW_COMMIT_MSG="Merged$NEW_COMMIT_MSG into \ | |
182 $MERGE_TO_BRANCH branch." | |
183 persist PATCH_COMMIT_HASHES | |
Jakob Kummerow
2012/01/27 16:28:12
Have you tested whether persist() can handle array
danno
2012/01/31 10:37:57
Done.
| |
184 persist NEW_COMMIT_MSG | |
185 fi | |
186 | |
187 if [ $STEP -le 4 ] ; then | |
188 restore_if_unset "PATCH_COMMIT_HASHES" | |
189 restore_if_unset "NEW_COMMIT_MSG" | |
190 echo ">>> Step 4: Aggregate patch description and bugs numbers." | |
191 | |
192 echo "$NEW_COMMIT_MSG" > $COMMITMSG_FILE | |
Jakob Kummerow
2012/01/27 16:28:12
If you move this to the end of step 3, you don't n
danno
2012/01/31 10:37:57
Done.
| |
193 echo >> $COMMITMSG_FILE | |
194 for HASH in ${PATCH_COMMIT_HASHES[@]} | |
195 do | |
196 PATCH_MERGE_DESCRIPTION=$(git show --notes $HASH \ | |
Jakob Kummerow
2012/01/27 16:28:12
I think what you mean here is just:
PATCH_MERGE_D
danno
2012/01/31 10:37:57
Done.
| |
197 | awk '{ | |
198 if (line_number == 4) { | |
199 printf($0); | |
200 }; | |
201 line_number++ | |
202 }' \ | |
203 | sed 's/ //') | |
204 echo "DESC: $PATCH_MERGE_DESCRIPTION" | |
205 echo "$PATCH_MERGE_DESCRIPTION" >> $COMMITMSG_FILE | |
206 echo >> $COMMITMSG_FILE | |
207 done | |
208 for HASH in ${PATCH_COMMIT_HASHES[@]} | |
209 do | |
210 BUG=$(git show --notes $HASH | grep "BUG=" | awk -F '=' '{print $NF}') | |
Jakob Kummerow
2012/01/27 16:28:12
I guess it doesn't really matter, but "git log -1"
danno
2012/01/31 10:37:57
Done.
| |
211 if [ $BUG ] ; then | |
212 if [ "$BUG_AGGREGATE" ] ; then | |
213 BUG_AGGREGATE="$BUG_AGGREGATE," | |
214 fi | |
215 BUG_AGGREGATE="$BUG_AGGREGATE$BUG" | |
216 fi | |
217 done | |
218 if [ "$BUG_AGGREGATE" ] ; then | |
219 echo "BUG=$BUG_AGGREGATE" >> $COMMITMSG_FILE | |
220 else | |
221 echo "BUG=none" >> $COMMITMSG_FILE | |
222 fi | |
223 fi | |
224 | |
225 if [ $STEP -le 5 ] ; then | |
226 echo ">>> Step 5: Apply the revision patch and create commit message." | |
227 for HASH in ${PATCH_COMMIT_HASHES[@]} | |
Jakob Kummerow
2012/01/27 16:28:12
missing restore_if_unset for PATCH_COMMIT_HASHES
danno
2012/01/31 10:37:57
Done.
| |
228 do | |
229 git log -1 -p $HASH | patch -p1 \ | |
230 || die "Cannot apply the patch for r$MERGE_REVISION on $MERGE_TO_BRANCH" | |
Jakob Kummerow
2012/01/27 16:28:12
Talking about a single MERGE_REVISION here is inco
danno
2012/01/31 10:37:57
Done.
| |
231 done | |
232 fi | |
233 | |
234 if [ $STEP -le 6 ] ; then | |
235 echo ">>> Step 6: Prepare version.cc" | |
236 # These version numbers are used again later for the trunk commit. | |
Jakob Kummerow
2012/01/27 16:28:12
outdated comment?
danno
2012/01/31 10:37:57
Done.
| |
237 MAJOR=$(grep "#define MAJOR_VERSION" "$VERSION_FILE" | awk '{print $NF}') | |
Jakob Kummerow
2012/01/27 16:28:12
do we need MAJOR, MINOR and BUILD at all?
danno
2012/01/31 10:37:57
Yes. For building the tag.
On 2012/01/27 16:28:12,
| |
238 persist "MAJOR" | |
239 MINOR=$(grep "#define MINOR_VERSION" "$VERSION_FILE" | awk '{print $NF}') | |
240 persist "MINOR" | |
241 BUILD=$(grep "#define BUILD_NUMBER" "$VERSION_FILE" | awk '{print $NF}') | |
242 persist "BUILD" | |
243 PATCH=$(grep "#define PATCH_LEVEL" "$VERSION_FILE" | awk '{print $NF}') | |
244 persist "PATCH" | |
245 fi | |
246 | |
247 if [ $STEP -le 7 ] ; then | |
248 echo ">>> Step 7: Increment version number." | |
249 restore_if_unset "PATCH" | |
250 NEWPATCH=$(($PATCH + 1)) | |
251 confirm "Automatically increment BUILD_NUMBER? (Saying 'n' will fire up \ | |
Jakob Kummerow
2012/01/27 16:28:12
s/BUILD_NUMBER/PATCH_LEVEL/
danno
2012/01/31 10:37:57
Done.
| |
252 your EDITOR on $VERSION_FILE so you can make arbitrary changes. When \ | |
253 you're done, save the file and exit your EDITOR.)" | |
254 if [ $? -eq 0 ] ; then | |
255 sed -e "/#define PATCH_LEVEL/s/[0-9]*$/$NEWPATCH/" \ | |
256 -i "$VERSION_FILE" | |
257 else | |
258 $EDITOR "$VERSION_FILE" | |
259 fi | |
260 NEWMAJOR=$(grep "#define MAJOR_VERSION" "$VERSION_FILE" | awk '{print $NF}') | |
261 persist "NEWMAJOR" | |
262 NEWMINOR=$(grep "#define MINOR_VERSION" "$VERSION_FILE" | awk '{print $NF}') | |
263 persist "NEWMINOR" | |
264 NEWBUILD=$(grep "#define BUILD_NUMBER" "$VERSION_FILE" | awk '{print $NF}') | |
265 persist "NEWBUILD" | |
266 NEWPATCH=$(grep "#define PATCH_LEVEL" "$VERSION_FILE" | awk '{print $NF}') | |
267 persist "NEWPATCH" | |
268 fi | |
269 | |
270 if [ $STEP -le 8 ] ; then | |
271 echo ">>> Step 8: Commit to local branch." | |
272 restore_if_unset "NEW_COMMIT_MSG" | |
273 git commit -a -m "$NEW_COMMIT_MSG" \ | |
274 || die "'git commit -a' failed." | |
275 fi | |
276 | |
277 if [ $STEP -le 9 ] ; then | |
278 echo ">>> Step 9: Confirm merge commit." | |
279 echo "This is the message that will be used for the commit:" | |
280 echo "--------------------" | |
281 cat "$COMMITMSG_FILE" | |
282 echo -e "--------------------" | |
Jakob Kummerow
2012/01/27 16:28:12
nit: "-e" is unnecessary (since you don't have any
danno
2012/01/31 10:37:57
Done.
| |
283 confirm "Does this look good to you? (Saying 'n' will fire up your \ | |
284 EDITOR so you can change the commit message. When you're done, save the \ | |
285 file and exit your EDITOR.)" | |
286 if [ $? -ne 0 ] ; then | |
287 $EDITOR "$COMMITMSG_FILE" | |
288 fi | |
289 fi | |
290 | |
291 if [ $STEP -le 10 ] ; then | |
292 echo ">>> Step 10: Upload for code review." | |
293 echo -n "Please enter the email address of a V8 reviewer for your patch: " | |
294 read REVIEWER | |
295 cat $COMMITMSG_FILE > $COMMITMSG_FILE_COPY | |
296 echo "R=$REVIEWER" >> $COMMITMSG_FILE_COPY | |
Jakob Kummerow
2012/01/27 16:28:12
You don't need this. "git cl upload --review" auto
danno
2012/01/31 10:37:57
On 2012/01/27 16:28:12, Jakob wrote:
> You don't n
| |
297 export EDITOR="cat $COMMITMSG_FILE_COPY >" | |
Jakob Kummerow
2012/01/27 16:28:12
I'm not sure I like messing with my EDITOR variabl
danno
2012/01/31 10:37:57
Done.
| |
298 git cl upload --review "$REVIEWER" --send-mail \ | |
299 || die "'git cl upload' failed, please try again." | |
300 fi | |
301 | |
302 if [ $STEP -le 11 ] ; then | |
303 echo ">>> Step 11: Sanity check." | |
304 confirm "Please check if your local checkout is sane: Inspect $VERSION_FILE, \ | |
305 compile, run tests. Do you want to commit this new trunk revision to the \ | |
Jakob Kummerow
2012/01/27 16:28:12
nit: s/new trunk//
Also, we don't really need ste
danno
2012/01/31 10:37:57
Done.
| |
306 repository?" | |
307 [[ $? -eq 0 ]] || die "Execution canceled." | |
308 fi | |
309 | |
310 if [ $STEP -le 12 ] ; then | |
311 echo ">>> Step 12: Commit to the repository." | |
312 echo "Please wait for an LGTM, then type \"LGTM<Return>\" to commit your \ | |
313 change. (If you need to iterate on the patch, do so in another shell. Do not \ | |
Jakob Kummerow
2012/01/27 16:28:12
You can remove the "Do not modify..." part, as it
danno
2012/01/31 10:37:57
Done.
| |
314 modify the existing local commit's commit message.)" | |
315 unset ANSWER | |
316 while [ "$ANSWER" != "LGTM" ] ; do | |
317 [[ -n "$ANSWER" ]] && echo "That was not 'LGTM'." | |
318 echo -n "> " | |
319 read ANSWER | |
320 done | |
321 echo "git-cl dcommit" | |
Jakob Kummerow
2012/01/27 16:28:12
Forgot to remove the "echo".
danno
2012/01/31 10:37:57
Done.
| |
322 fi | |
323 | |
324 if [ $STEP -le 13 ] ; then | |
325 restore_if_unset "NEWMAJOR" | |
326 restore_if_unset "NEWMINOR" | |
327 restore_if_unset "NEWBUILD" | |
328 restore_if_unset "NEWPATCH" | |
329 echo ">>> Step 13: Create the tag." | |
330 echo "svn copy -r ? https://v8.googlecode.com/svn/branches/$MERGE_TO_BRANCH ht tps://v8.googlecode.com/svn/tags/$NEWMAJOR.$NEWMINOR.$NEWBUILD.$NEWPATCH -m \"Ta gging version $NEWMAJOR.$NEWMINOR.$NEWBUILD.$NEWPATCH\"" | |
Jakob Kummerow
2012/01/27 16:28:12
another "echo" that needs to go.
danno
2012/01/31 10:37:57
Done.
| |
331 fi | |
332 | |
333 if [ $STEP -le 14 ] ; then | |
334 echo ">>> Step 14: Cleanup." | |
335 restore_if_unset "CURRENT_BRANCH" | |
336 git checkout -f $CURRENT_BRANCH | |
337 [[ "$BRANCHNAME" != "$CURRENT_BRANCH" ]] && echo "git branch -D $BRANCHNAME" | |
Jakob Kummerow
2012/01/27 16:28:12
another "echo" that needs to go.
danno
2012/01/31 10:37:57
Done.
| |
338 fi | |
OLD | NEW |