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