OLD | NEW |
---|---|
1 # Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2009 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 import optparse | |
6 import os | |
7 import re | |
5 import subprocess | 8 import subprocess |
6 import sys | 9 import sys |
7 import re | |
8 import os | |
9 import webbrowser | 10 import webbrowser |
10 | 11 |
12 USAGE = """ | |
13 WARNING: Please use this tool in an empty directory | |
14 (or at least one that you don't mind clobbering.) | |
15 | |
16 REQUIRES: SVN 1.5+ | |
17 NOTE: NO NEED TO CHECKOUT ANYTHING IN ADVANCE OF USING THIS TOOL." | |
18 Valid parameters: | |
19 | |
20 [Merge from trunk to branch] | |
21 <revision> --merge <branch_num> | |
22 Example: %(app)s 12345 --merge 187 | |
23 | |
24 [Merge from trunk to branch, ignoring revision history] | |
25 <revision> --mplus <branch_num> | |
26 Example: %(app)s 12345 --mplus 187 | |
27 | |
28 [Revert from trunk] | |
29 <revision> --revert | |
30 Example: %(app)s 12345 --revert | |
31 | |
32 | |
33 [Revert from branch] | |
34 <revision> --revert <branch_num> | |
35 Example: %(app)s 12345 --revert 187 | |
36 """ | |
37 | |
11 export_map_ = None | 38 export_map_ = None |
12 files_info_ = None | 39 files_info_ = None |
13 delete_map_ = None | 40 delete_map_ = None |
14 file_pattern_ = r"[ ]+([MADUC])[ ]+/((?:trunk|branches/\d+)/src(.*)/(.*))" | 41 file_pattern_ = r"[ ]+([MADUC])[ ]+/((?:trunk|branches/\d+)/src(.*)/(.*))" |
15 | 42 |
16 def deltree(root): | 43 def deltree(root): |
17 """ | 44 """Removes a given directory""" |
18 Removes a given directory | |
19 """ | |
20 if (not os.path.exists(root)): | 45 if (not os.path.exists(root)): |
21 return | 46 return |
22 | 47 |
23 if sys.platform == 'win32': | 48 if sys.platform == 'win32': |
24 os.system('rmdir /S /Q ' + root.replace('/','\\')) | 49 os.system('rmdir /S /Q ' + root.replace('/','\\')) |
25 else: | 50 else: |
26 for name in os.listdir(root): | 51 for name in os.listdir(root): |
27 path = os.path.join(root, name) | 52 path = os.path.join(root, name) |
28 if os.path.isdir(path): | 53 if os.path.isdir(path): |
29 deltree(path) | 54 deltree(path) |
30 else: | 55 else: |
31 os.unlink(path) | 56 os.unlink(path) |
32 os.rmdir(root) | 57 os.rmdir(root) |
33 | 58 |
34 def clobberDir(dir): | 59 def clobberDir(dir): |
35 """ | 60 """Removes a given directory""" |
36 Removes a given directory | 61 |
37 """ | |
38 | |
39 if (os.path.exists(dir)): | 62 if (os.path.exists(dir)): |
40 print dir + " directory found, deleting" | 63 print dir + " directory found, deleting" |
41 #The following line was removed due to access controls in Windows | 64 # The following line was removed due to access controls in Windows |
42 #which make os.unlink(path) calls impossible. | 65 # which make os.unlink(path) calls impossible. |
43 #deltree(dir) | 66 #TODO(laforge) : Is this correct? |
laforge
2009/10/16 14:57:25
That's correct
| |
44 os.system('rmdir /S /Q ' + dir.replace('/','\\')) | 67 deltree(dir) |
45 | 68 |
46 def gclUpload(revision, author): | 69 def gclUpload(revision, author): |
47 command = ("gcl upload " + str(revision) + | 70 command = ("gcl upload " + str(revision) + |
48 " --send_mail --no_try --no_presubmit --reviewers=" + author) | 71 " --send_mail --no_try --no_presubmit --reviewers=" + author) |
49 os.system(command) | 72 os.system(command) |
50 | 73 |
51 def getSVNInfo(url, revision): | 74 def getSVNInfo(url, revision): |
52 command = 'svn info ' + url + "@"+str(revision) | 75 command = 'svn info ' + url + "@"+str(revision) |
53 svn_info = subprocess.Popen(command, | 76 svn_info = subprocess.Popen(command, |
54 shell=True, | 77 shell=True, |
55 stdout=subprocess.PIPE, | 78 stdout=subprocess.PIPE, |
56 stderr=subprocess.PIPE).stdout.readlines() | 79 stderr=subprocess.PIPE).stdout.readlines() |
57 rtn = {} | 80 info = {} |
58 for line in svn_info: | 81 for line in svn_info: |
59 match = re.search(r"(.*?):(.*)", line) | 82 match = re.search(r"(.*?):(.*)", line) |
60 if match: | 83 if match: |
61 » rtn[match.group(1).strip()]=match.group(2).strip() | 84 » info[match.group(1).strip()]=match.group(2).strip() |
62 | 85 |
63 return rtn | 86 return info |
64 | 87 |
65 def getAuthor(url, revision): | 88 def getAuthor(url, revision): |
66 info = getSVNInfo(url, revision) | 89 info = getSVNInfo(url, revision) |
67 | |
68 if (info.has_key("Last Changed Author")): | 90 if (info.has_key("Last Changed Author")): |
69 return info["Last Changed Author"] | 91 return info["Last Changed Author"] |
70 | |
71 return None | 92 return None |
72 | 93 |
73 def isSVNFile(url, revision): | 94 def isSVNFile(url, revision): |
74 info = getSVNInfo(url, revision) | 95 info = getSVNInfo(url, revision) |
75 | |
76 if (info.has_key("Node Kind")): | 96 if (info.has_key("Node Kind")): |
77 if (info["Node Kind"] == "file"): return True | 97 if (info["Node Kind"] == "file"): |
78 | 98 return True |
79 return False | 99 return False |
80 | 100 |
81 def isSVNDirectory(url, revision): | 101 def isSVNDirectory(url, revision): |
82 info = getSVNInfo(url, revision) | 102 info = getSVNInfo(url, revision) |
83 | |
84 if (info.has_key("Node Kind")): | 103 if (info.has_key("Node Kind")): |
85 if (info["Node Kind"] == "directory"): return True | 104 if (info["Node Kind"] == "directory"): |
86 | 105 return True |
87 return False | 106 return False |
88 | 107 |
89 def getRevisionLog(url, revision): | 108 def getRevisionLog(url, revision): |
90 """ | 109 """Takes an svn url and gets the associated revision.""" |
91 Takes an svn url and gets the associated revision. | |
92 """ | |
93 command = 'svn log ' + url + " -r"+str(revision) | 110 command = 'svn log ' + url + " -r"+str(revision) |
94 svn_info = subprocess.Popen(command, | 111 svn_log = subprocess.Popen(command, |
95 shell=True, | 112 shell=True, |
96 stdout=subprocess.PIPE, | 113 stdout=subprocess.PIPE, |
97 stderr=subprocess.PIPE).stdout.readlines() | 114 stderr=subprocess.PIPE).stdout.readlines() |
98 rtn= "" | 115 log = "" |
99 pos = 0 | 116 pos = 0 |
100 for line in svn_info: | 117 for line in svn_log: |
101 if (pos > 2): | 118 if (pos > 2): |
102 rtn += line.replace('-','').replace('\r','') | 119 log += line.replace('-','').replace('\r','') |
103 else: | 120 else: |
104 pos = pos + 1 | 121 pos = pos + 1 |
105 | 122 return log |
106 return rtn | |
107 | 123 |
108 def checkoutRevision(url, revision, branch_url, revert=False): | 124 def checkoutRevision(url, revision, branch_url, revert=False): |
109 files_info = getFileInfo(url, revision) | 125 files_info = getFileInfo(url, revision) |
110 paths = getBestMergePaths2(files_info, revision) | 126 paths = getBestMergePaths2(files_info, revision) |
111 export_map = getBestExportPathsMap2(files_info, revision) | 127 export_map = getBestExportPathsMap2(files_info, revision) |
112 | 128 |
113 command = 'svn checkout -N ' + branch_url | 129 command = 'svn checkout -N ' + branch_url |
114 print command | 130 print command |
115 os.system(command) | 131 os.system(command) |
116 | 132 |
117 match = re.search(r"svn://.*/(.*)", branch_url) | 133 match = re.search(r"svn://.*/(.*)", branch_url) |
118 | 134 |
119 if match: | 135 if match: |
120 os.chdir(match.group(1)) | 136 os.chdir(match.group(1)) |
121 | 137 |
122 #This line is extremely important due to the way svn behaves in the set-depths | 138 # This line is extremely important due to the way svn behaves in the |
123 #action. If parents aren't handled before children, the child directories get | 139 # set-depths action. If parents aren't handled before children, the child |
124 #clobbered and the merge step fails. | 140 # directories get clobbered and the merge step fails. |
125 paths.sort() | 141 paths.sort() |
126 | 142 |
127 #Checkout the directories that already exist | 143 # Checkout the directories that already exist |
128 for path in paths: | 144 for path in paths: |
129 if (export_map.has_key(path) and not revert): | 145 if (export_map.has_key(path) and not revert): |
130 print "Exclude new directory " + path | 146 print "Exclude new directory " + path |
131 continue | 147 continue |
132 subpaths = path.split('/') | 148 subpaths = path.split('/') |
133 subpaths.pop(0) | 149 subpaths.pop(0) |
134 base = '' | 150 base = '' |
135 for subpath in subpaths: | 151 for subpath in subpaths: |
136 base += '/' + subpath | 152 base += '/' + subpath |
137 #This logic ensures that you don't empty out any directories | 153 # This logic ensures that you don't empty out any directories |
138 if not os.path.exists("." + base): | 154 if not os.path.exists("." + base): |
139 command = ('svn update --depth empty ' + "." + base) | 155 command = ('svn update --depth empty ' + "." + base) |
140 print command | 156 print command |
141 os.system(command) | 157 os.system(command) |
142 | 158 |
143 if (revert): | 159 if (revert): |
144 files = getAllFilesInRevision(files_info) | 160 files = getAllFilesInRevision(files_info) |
145 else: | 161 else: |
146 files = getExistingFilesInRevision(files_info) | 162 files = getExistingFilesInRevision(files_info) |
147 | 163 |
148 for file in files: | 164 for file in files: |
149 #Prevent the tool from clobbering the src directory | 165 # Prevent the tool from clobbering the src directory |
150 if (file == ""): | 166 if (file == ""): |
151 continue | 167 continue |
152 command = ('svn up ".' + file + '"') | 168 command = ('svn up ".' + file + '"') |
153 print command | 169 print command |
154 os.system(command) | 170 os.system(command) |
155 | 171 |
156 def mergeRevision(url, revision): | 172 def mergeRevision(url, revision): |
157 paths = getBestMergePaths(url, revision) | 173 paths = getBestMergePaths(url, revision) |
158 export_map = getBestExportPathsMap(url, revision) | 174 export_map = getBestExportPathsMap(url, revision) |
159 | 175 |
160 for path in paths: | 176 for path in paths: |
161 if export_map.has_key(path): | 177 if export_map.has_key(path): |
162 continue | 178 continue |
163 command = ('svn merge -N -r ' + str(revision-1) + ":" + str(revision) + " ") | 179 command = ('svn merge -N -r ' + str(revision-1) + ":" + str(revision) + " ") |
164 command = command + url + path + "@" + str(revision) + " ." + path | 180 command = command + url + path + "@" + str(revision) + " ." + path |
165 | 181 |
166 print command | 182 print command |
167 os.system(command) | 183 os.system(command) |
168 | 184 |
169 def exportRevision(url, revision): | 185 def exportRevision(url, revision): |
170 paths = getBestExportPathsMap(url, revision).keys() | 186 paths = getBestExportPathsMap(url, revision).keys() |
171 | |
172 paths.sort() | 187 paths.sort() |
173 | 188 |
174 for path in paths: | 189 for path in paths: |
175 command = ('svn export -N ' + url + path + "@" + str(revision) + " ." | 190 command = ('svn export -N ' + url + path + "@" + str(revision) + " ." + |
176 + path) | 191 path) |
177 print command | 192 print command |
178 os.system(command) | 193 os.system(command) |
179 | 194 |
180 command = ('svn add .' + path) | 195 command = 'svn add .' + path |
181 print command | 196 print command |
182 os.system(command) | 197 os.system(command) |
183 | 198 |
184 def deleteRevision(url, revision): | 199 def deleteRevision(url, revision): |
185 paths = getBestDeletePathsMap(url, revision).keys() | 200 paths = getBestDeletePathsMap(url, revision).keys() |
186 paths.sort() | 201 paths.sort() |
187 paths.reverse() | 202 paths.reverse() |
188 | 203 |
189 for path in paths: | 204 for path in paths: |
190 command = ("svn delete ." + path) | 205 command = "svn delete ." + path |
191 print command | 206 print command |
192 os.system(command) | 207 os.system(command) |
193 | 208 |
194 | |
195 def revertExportRevision(url, revision): | 209 def revertExportRevision(url, revision): |
196 paths = getBestExportPathsMap(url, revision).keys() | 210 paths = getBestExportPathsMap(url, revision).keys() |
197 paths.sort() | 211 paths.sort() |
198 paths.reverse() | 212 paths.reverse() |
199 | 213 |
200 for path in paths: | 214 for path in paths: |
201 command = ("svn delete ." + path) | 215 command = "svn delete ." + path |
202 print command | 216 print command |
203 os.system(command) | 217 os.system(command) |
204 | 218 |
205 def revertRevision(url, revision): | 219 def revertRevision(url, revision): |
206 paths = getBestMergePaths(url, revision) | 220 paths = getBestMergePaths(url, revision) |
207 for path in paths: | 221 for path in paths: |
208 command = ('svn merge -N -r ' + str(revision) + ":" + str(revision-1) + | 222 command = ('svn merge -N -r ' + str(revision) + ":" + str(revision-1) + |
209 " " + url + path + " ." + path) | 223 " " + url + path + " ." + path) |
210 print command | 224 print command |
211 os.system(command) | 225 os.system(command) |
212 | 226 |
213 def getFileInfo(url, revision): | 227 def getFileInfo(url, revision): |
214 global files_info_, file_pattern_ | 228 global files_info_, file_pattern_ |
215 | 229 |
216 if (files_info_ != None): | 230 if (files_info_ != None): |
217 return files_info_ | 231 return files_info_ |
218 | 232 |
219 command = 'svn log ' + url + " -r " + str(revision) + " -v" | 233 command = 'svn log ' + url + " -r " + str(revision) + " -v" |
220 svn_log = subprocess.Popen(command, | 234 svn_log = subprocess.Popen(command, |
221 shell=True, | 235 shell=True, |
222 stdout=subprocess.PIPE, | 236 stdout=subprocess.PIPE, |
223 stderr=subprocess.PIPE).stdout.readlines() | 237 stderr=subprocess.PIPE).stdout.readlines() |
224 | 238 |
225 rtn = [] | 239 info = [] |
226 for line in svn_log: | 240 for line in svn_log: |
227 #A workaround to dump the (from .*) stuff, regex not so friendly in the 2nd | 241 # A workaround to dump the (from .*) stuff, regex not so friendly in the 2nd |
228 #pass... | 242 # pass... |
229 match = re.search(r"(.*) \(from.*\)", line) | 243 match = re.search(r"(.*) \(from.*\)", line) |
230 if match: | 244 if match: |
231 line = match.group(1) | 245 line = match.group(1) |
232 match = re.search(file_pattern_, line) | 246 match = re.search(file_pattern_, line) |
233 if match: | 247 if match: |
234 rtn.append([match.group(1).strip(), match.group(2).strip(), | 248 info.append([match.group(1).strip(), match.group(2).strip(), |
235 match.group(3).strip(),match.group(4).strip()]) | 249 match.group(3).strip(),match.group(4).strip()]) |
236 | 250 |
237 files_info_ = rtn | 251 files_info_ = info |
238 return rtn | 252 return rtn |
239 | 253 |
240 def getBestMergePaths(url, revision): | 254 def getBestMergePaths(url, revision): |
241 """ | 255 """Takes an svn url and gets the associated revision.""" |
242 Takes an svn url and gets the associated revision. | |
243 """ | |
244 return getBestMergePaths2(getFileInfo(url, revision), revision) | 256 return getBestMergePaths2(getFileInfo(url, revision), revision) |
245 | 257 |
246 def getBestMergePaths2(files_info, revision): | 258 def getBestMergePaths2(files_info, revision): |
247 """ | 259 """Takes an svn url and gets the associated revision.""" |
248 Takes an svn url and gets the associated revision. | |
249 """ | |
250 | 260 |
251 map = dict() | 261 map = dict() |
252 for file_info in files_info: | 262 for file_info in files_info: |
253 map[file_info[2]] = file_info[2] | 263 map[file_info[2]] = file_info[2] |
254 | 264 |
255 return map.keys() | 265 return map.keys() |
256 | 266 |
257 def getBestExportPathsMap(url, revision): | 267 def getBestExportPathsMap(url, revision): |
258 return getBestExportPathsMap2(getFileInfo(url, revision), revision) | 268 return getBestExportPathsMap2(getFileInfo(url, revision), revision) |
259 | 269 |
260 def getBestExportPathsMap2(files_info, revision): | 270 def getBestExportPathsMap2(files_info, revision): |
261 """ | 271 """Takes an svn url and gets the associated revision.""" |
262 Takes an svn url and gets the associated revision. | |
263 """ | |
264 global export_map_ | 272 global export_map_ |
265 | 273 |
266 if export_map_: | 274 if export_map_: |
267 return export_map_ | 275 return export_map_ |
268 | 276 |
269 map = dict() | 277 map = dict() |
270 for file_info in files_info: | 278 for file_info in files_info: |
271 if (file_info[0] == "A"): | 279 if (file_info[0] == "A"): |
272 if(isSVNDirectory("svn://chrome-svn/chrome/" + file_info[1], revision)): | 280 if(isSVNDirectory("svn://chrome-svn/chrome/" + file_info[1], revision)): |
273 map[file_info[2] + "/" + file_info[3]] = "" | 281 map[file_info[2] + "/" + file_info[3]] = "" |
274 | 282 |
275 export_map_ = map | 283 export_map_ = map |
276 | |
277 return map | 284 return map |
278 | 285 |
279 def getBestDeletePathsMap(url, revision): | 286 def getBestDeletePathsMap(url, revision): |
280 return getBestDeletePathsMap2(getFileInfo(url, revision), revision) | 287 return getBestDeletePathsMap2(getFileInfo(url, revision), revision) |
281 | 288 |
282 def getBestDeletePathsMap2(files_info, revision): | 289 def getBestDeletePathsMap2(files_info, revision): |
283 """ | 290 """Takes an svn url and gets the associated revision.""" |
284 Takes an svn url and gets the associated revision. | |
285 """ | |
286 global delete_map_ | 291 global delete_map_ |
287 | 292 |
288 if delete_map_: | 293 if delete_map_: |
289 return delete_map_ | 294 return delete_map_ |
290 | 295 |
291 map = dict() | 296 map = dict() |
292 for file_info in files_info: | 297 for file_info in files_info: |
293 if (file_info[0] == "D"): | 298 if (file_info[0] == "D"): |
294 if(isSVNDirectory("svn://chrome-svn/chrome/" + file_info[1], revision)): | 299 if(isSVNDirectory("svn://chrome-svn/chrome/" + file_info[1], revision)): |
295 map[file_info[2] + "/" + file_info[3]] = "" | 300 map[file_info[2] + "/" + file_info[3]] = "" |
296 | 301 |
297 delete_map_ = map | 302 delete_map_ = map |
298 | |
299 return map | 303 return map |
300 | 304 |
301 def getExistingFilesInRevision(files_info): | 305 def getExistingFilesInRevision(files_info): |
302 """ | 306 """Checks for existing files in the revision. |
303 Checks for existing files in the revision, anything that's A will require | 307 |
304 special treatment (either a merge or an export + add) | 308 Anything that's A will require special treatment (either a merge or an |
309 export + add) | |
305 """ | 310 """ |
306 map = [] | 311 map = [] |
307 for file_info in files_info: | 312 for file_info in files_info: |
308 if file_info[0] != "A": | 313 if file_info[0] != "A": |
309 map.append(file_info[2] + "/" + file_info[3]) | 314 map.append(file_info[2] + "/" + file_info[3]) |
310 | 315 |
311 return map | 316 return map |
312 | 317 |
313 def getAllFilesInRevision(files_info): | 318 def getAllFilesInRevision(files_info): |
314 """ | 319 """Checks for existing files in the revision. |
315 Checks for existing files in the revision, anything that's A will require | 320 |
316 special treatment (either a merge or an export + add) | 321 Anything that's A will require special treatment (either a merge or an |
322 export + add) | |
317 """ | 323 """ |
318 map = [] | 324 map = [] |
319 for file_info in files_info: | 325 for file_info in files_info: |
320 map.append(file_info[2] + "/" + file_info[3]) | 326 map.append(file_info[2] + "/" + file_info[3]) |
321 | |
322 return map | 327 return map |
323 | 328 |
324 def prompt(question): | 329 def prompt(question): |
325 p = None | 330 answer = None |
326 | 331 |
327 while not p: | 332 while not p: |
328 print question + " [y|n]:" | 333 print question + " [y|n]:" |
329 p = sys.stdin.readline() | 334 answer = sys.stdin.readline() |
330 if p.lower().startswith('n'): | 335 if answer.lower().startswith('n'): |
331 return False | 336 return False |
332 elif p.lower().startswith('y'): | 337 elif answer.lower().startswith('y'): |
333 return True | 338 return True |
334 else: | 339 else: |
335 p = None | 340 answer = None |
336 | 341 |
337 def text_prompt(question, default): | 342 def text_prompt(question, default): |
338 print question + " [" + default + "]:" | 343 print question + " [" + default + "]:" |
339 p = sys.stdin.readline() | 344 answer = sys.stdin.readline() |
340 if p.strip() == "": | 345 if answer.strip() == "": |
341 return default | 346 return default |
342 return p | 347 return answer |
343 | 348 |
344 def main(argv=None): | 349 def main(argv=None): |
345 BASE_URL = "svn://chrome-svn/chrome" | 350 BASE_URL = "svn://chrome-svn/chrome" |
346 TRUNK_URL = BASE_URL + "/trunk/src" | 351 TRUNK_URL = BASE_URL + "/trunk/src" |
347 BRANCH_URL = BASE_URL + "/branches/$branch/src" | 352 BRANCH_URL = BASE_URL + "/branches/$branch/src" |
348 DEFAULT_WORKING = "working" | 353 DEFAULT_WORKING = "working" |
349 SKIP_CHECK_WORKING = True | 354 SKIP_CHECK_WORKING = True |
350 PROMPT_FOR_AUTHOR = False | 355 PROMPT_FOR_AUTHOR = False |
351 | 356 |
357 # Override the default properties if there is a drover.properties file. | |
352 global file_pattern_ | 358 global file_pattern_ |
353 if os.path.exists("drover.properties"): | 359 if os.path.exists("drover.properties"): |
354 file = open("drover.properties") | 360 file = open("drover.properties") |
355 exec(file) | 361 exec(file) |
356 file.close() | 362 file.close() |
357 if FILE_PATTERN: | 363 if FILE_PATTERN: |
358 file_pattern_ = FILE_PATTERN | 364 file_pattern_ = FILE_PATTERN |
359 | 365 |
360 if (len(sys.argv) == 1): | 366 if (len(sys.argv) == 1): |
361 print "WARNING: Please use this tool in an empty directory (or at least one" | 367 print USAGE % {"app": sys.argv[0]} |
362 print "that you don't mind clobbering." | |
363 print "REQUIRES: SVN 1.5+" | |
364 print "NOTE: NO NEED TO CHECKOUT ANYTHING IN ADVANCE OF USING THIS TOOL." | |
365 print "\nValid parameters:" | |
366 print "\n[Merge from trunk to branch]" | |
367 print "<revision> --merge <branch_num>" | |
368 print "Example " + sys.argv[0] + " 12345 --merge 187" | |
369 print "\n[Merge from trunk to branch, ignoring revision history]" | |
370 print "<revision> --mplus <branch_num>" | |
371 print "Example " + sys.argv[0] + " 12345 --mplus 187" | |
372 print "\n[Revert from trunk]" | |
373 print " <revision> --revert" | |
374 print "Example " + sys.argv[0] + " 12345 --revert" | |
375 print "\n[Revert from branch]" | |
376 print " <revision> --revert <branch_num>" | |
377 print "Example " + sys.argv[0] + " 12345 --revert 187" | |
378 sys.exit(0) | 368 sys.exit(0) |
379 | 369 |
380 revision = int(sys.argv[1]) | 370 revision = int(sys.argv[1]) |
381 if ((len(sys.argv) >= 4) and (sys.argv[2] in ['--revert','-r'])): | 371 if ((len(sys.argv) >= 4) and (sys.argv[2] in ['--revert','-r'])): |
382 url = BRANCH_URL.replace("$branch", sys.argv[3]) | 372 url = BRANCH_URL.replace("$branch", sys.argv[3]) |
383 else: | 373 else: |
384 url = TRUNK_URL | 374 url = TRUNK_URL |
385 action = "Merge" | 375 action = "Merge" |
386 | 376 |
387 working = DEFAULT_WORKING | 377 working = DEFAULT_WORKING |
388 | 378 |
389 command = 'svn log ' + url + " -r "+str(revision) + " -v" | 379 command = 'svn log ' + url + " -r "+str(revision) + " -v" |
390 os.system(command) | 380 os.system(command) |
391 | 381 |
392 if not prompt("Is this the correct revision?"): | 382 if not prompt("Is this the correct revision?"): |
393 sys.exit(0) | 383 sys.exit(0) |
394 | 384 |
395 if (os.path.exists(working)): | 385 if (os.path.exists(working)): |
396 if not (SKIP_CHECK_WORKING or prompt("Working directory: '" + working + "' a lready exists, clobber?")): | 386 if not (SKIP_CHECK_WORKING or prompt("Working directory: '" + working + "' a lready exists, clobber?")): |
397 sys.exit(0) | 387 sys.exit(0) |
398 deltree(working) | 388 deltree(working) |
399 | 389 |
400 os.makedirs(working) | 390 os.makedirs(working) |
401 os.chdir(working) | 391 os.chdir(working) |
402 | 392 |
403 if (len(sys.argv) > 1): | 393 if (len(sys.argv) > 1): |
404 if sys.argv[2] in ['--merge','-m']: | 394 if sys.argv[2] in ['--merge','-m']: |
405 if (len(sys.argv) != 4): | 395 if (len(sys.argv) != 4): |
406 print "Please specify the branch # you want (i.e. 182) after --merge" | 396 print "Please specify the branch # you want (i.e. 182) after --merge" |
407 sys.exit(0) | 397 sys.exit(0) |
408 | 398 |
409 branch_url = BRANCH_URL.replace("$branch", sys.argv[3]) | 399 branch_url = BRANCH_URL.replace("$branch", sys.argv[3]) |
410 #Checkout everything but stuff that got added into a new dir | 400 # Checkout everything but stuff that got added into a new dir |
411 checkoutRevision(url, revision, branch_url) | 401 checkoutRevision(url, revision, branch_url) |
412 #Merge everything that changed | 402 # Merge everything that changed |
413 mergeRevision(url, revision) | 403 mergeRevision(url, revision) |
414 #"Export" files that were added from the source and add them to branch | 404 # "Export" files that were added from the source and add them to branch |
415 exportRevision(url, revision) | 405 exportRevision(url, revision) |
416 #Delete directories that were deleted (file deletes are handled in the | 406 # Delete directories that were deleted (file deletes are handled in the |
417 #merge). | 407 # merge). |
418 deleteRevision(url, revision) | 408 deleteRevision(url, revision) |
419 elif sys.argv[2] in ['--revert','-r']: | 409 elif sys.argv[2] in ['--revert','-r']: |
420 if (len(sys.argv) == 4): | 410 if (len(sys.argv) == 4): |
421 url = BRANCH_URL.replace("$branch", sys.argv[3]) | 411 url = BRANCH_URL.replace("$branch", sys.argv[3]) |
422 checkoutRevision(url, revision, url, True) | 412 checkoutRevision(url, revision, url, True) |
423 revertRevision(url, revision) | 413 revertRevision(url, revision) |
424 revertExportRevision(url, revision) | 414 revertExportRevision(url, revision) |
425 action = "Revert" | 415 action = "Revert" |
426 else: | 416 else: |
427 print "Unknown parameter " + sys.argv[2] | 417 print "Unknown parameter " + sys.argv[2] |
428 sys.exit(0) | 418 sys.exit(0) |
429 | 419 |
430 #Check the base url so we actually find the author who made the change | 420 # Check the base url so we actually find the author who made the change |
431 author = getAuthor(TRUNK_URL, revision) | 421 author = getAuthor(TRUNK_URL, revision) |
432 | 422 |
433 filename = str(revision)+".txt" | 423 filename = str(revision)+".txt" |
434 out = open(filename,"w") | 424 out = open(filename,"w") |
435 out.write(action +" " + str(revision) + " - ") | 425 out.write(action +" " + str(revision) + " - ") |
436 out.write(getRevisionLog(url, revision)) | 426 out.write(getRevisionLog(url, revision)) |
437 if (author): | 427 if (author): |
438 out.write("TBR=" + author) | 428 out.write("TBR=" + author) |
439 out.close() | 429 out.close() |
440 | 430 |
441 os.system('gcl change ' + str(revision) + " " + filename) | 431 os.system('gcl change ' + str(revision) + " " + filename) |
442 os.unlink(filename) | 432 os.unlink(filename) |
443 print author | 433 print author |
444 print revision | 434 print revision |
445 print ("gcl upload " + str(revision) + | 435 print ("gcl upload " + str(revision) + |
446 " --send_mail --no_try --no_presubmit --reviewers=" + author) | 436 " --send_mail --no_try --no_presubmit --reviewers=" + author) |
447 print "gcl commit " + str(revision) + " --no_presubmit --force" | 437 print "gcl commit " + str(revision) + " --no_presubmit --force" |
448 print "gcl delete " + str(revision) | 438 print "gcl delete " + str(revision) |
449 | 439 |
450 if prompt("Would you like to upload?"): | 440 if prompt("Would you like to upload?"): |
451 if PROMPT_FOR_AUTHOR: | 441 if PROMPT_FOR_AUTHOR: |
452 author = text_prompt("Enter a new author or press enter to accept default" , author) | 442 author = text_prompt("Enter a new author or press enter to accept default" , author) |
453 gclUpload(revision, author) | 443 gclUpload(revision, author) |
454 else: | 444 else: |
455 print "Deleting the changelist." | 445 print "Deleting the changelist." |
456 os.system("gcl delete " + str(revision)) | 446 os.system("gcl delete " + str(revision)) |
457 sys.exit(0) | 447 sys.exit(0) |
458 | 448 |
459 if prompt("Would you like to commit?"): | 449 if prompt("Would you like to commit?"): |
460 os.system("gcl commit " + str(revision) + " --no_presubmit --force") | 450 os.system("gcl commit " + str(revision) + " --no_presubmit --force") |
461 else: | 451 else: |
462 sys.exit(0) | 452 sys.exit(0) |
463 | 453 |
464 if __name__ == "__main__": | 454 if __name__ == "__main__": |
465 sys.exit(main()) | 455 sys.exit(main()) |
OLD | NEW |