OLD | NEW |
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 # Copyright (c) 2010 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2010 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 import optparse | 6 import optparse |
7 import os | 7 import os |
8 import re | 8 import re |
9 import subprocess | 9 import subprocess |
10 import sys | 10 import sys |
11 import webbrowser | |
12 | 11 |
13 import breakpad | 12 import breakpad |
14 | 13 |
| 14 import gclient_utils |
| 15 |
15 USAGE = """ | 16 USAGE = """ |
16 WARNING: Please use this tool in an empty directory | 17 WARNING: Please use this tool in an empty directory |
17 (or at least one that you don't mind clobbering.) | 18 (or at least one that you don't mind clobbering.) |
18 | 19 |
19 REQUIRES: SVN 1.5+ | 20 REQUIRES: SVN 1.5+ |
20 NOTE: NO NEED TO CHECKOUT ANYTHING IN ADVANCE OF USING THIS TOOL." | 21 NOTE: NO NEED TO CHECKOUT ANYTHING IN ADVANCE OF USING THIS TOOL." |
21 Valid parameters: | 22 Valid parameters: |
22 | 23 |
23 [Merge from trunk to branch] | 24 [Merge from trunk to branch] |
24 --merge <revision> --branch <branch_num> | 25 --merge <revision> --branch <branch_num> |
(...skipping 14 matching lines...) Expand all Loading... |
39 [Revert from branch] | 40 [Revert from branch] |
40 --revert <revision> --branch <branch_num> | 41 --revert <revision> --branch <branch_num> |
41 Example: %(app)s --revert 12345 --branch 187 | 42 Example: %(app)s --revert 12345 --branch 187 |
42 """ | 43 """ |
43 | 44 |
44 export_map_ = None | 45 export_map_ = None |
45 files_info_ = None | 46 files_info_ = None |
46 delete_map_ = None | 47 delete_map_ = None |
47 file_pattern_ = r"[ ]+([MADUC])[ ]+/((?:trunk|branches/.*?)/src(.*)/(.*))" | 48 file_pattern_ = r"[ ]+([MADUC])[ ]+/((?:trunk|branches/.*?)/src(.*)/(.*))" |
48 | 49 |
49 def deltree(root): | |
50 """Removes a given directory""" | |
51 if (not os.path.exists(root)): | |
52 return | |
53 | |
54 if sys.platform == 'win32': | |
55 os.system('rmdir /S /Q ' + root.replace('/','\\')) | |
56 else: | |
57 for name in os.listdir(root): | |
58 path = os.path.join(root, name) | |
59 if os.path.isdir(path): | |
60 deltree(path) | |
61 else: | |
62 os.unlink(path) | |
63 os.rmdir(root) | |
64 | |
65 def clobberDir(dirname): | |
66 """Removes a given directory""" | |
67 | |
68 if (os.path.exists(dirname)): | |
69 print dir + " directory found, deleting" | |
70 # The following line was removed due to access controls in Windows | |
71 # which make os.unlink(path) calls impossible. | |
72 #TODO(laforge) : Is this correct? | |
73 deltree(dirname) | |
74 | 50 |
75 def runGcl(subcommand): | 51 def runGcl(subcommand): |
76 gcl_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "gcl") | 52 gcl_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "gcl") |
77 if not os.path.exists(gcl_path): | 53 if not os.path.exists(gcl_path): |
78 print "WARNING: gcl not found beside drover.py. Using system gcl instead..." | 54 print "WARNING: gcl not found beside drover.py. Using system gcl instead..." |
79 gcl_path = 'gcl' | 55 gcl_path = 'gcl' |
80 | 56 |
81 command = "%s %s" % (gcl_path, subcommand) | 57 command = "%s %s" % (gcl_path, subcommand) |
82 return os.system(command) | 58 return os.system(command) |
83 | 59 |
84 def gclUpload(revision, author): | 60 def gclUpload(revision, author): |
85 command = ("upload " + str(revision) + | 61 command = ("upload " + str(revision) + |
86 " --send_mail --no_presubmit --reviewers=" + author) | 62 " --send_mail --no_presubmit --reviewers=" + author) |
87 return runGcl(command) | 63 return runGcl(command) |
88 | 64 |
89 def getSVNInfo(url, revision): | 65 def getSVNInfo(url, revision): |
90 command = 'svn info ' + url + "@"+str(revision) | 66 svn_info = gclient_utils.Popen(['svn', 'info', '%s@%s' % (url, revision)], |
91 svn_info = subprocess.Popen(command, | 67 stdout=subprocess.PIPE, |
92 shell=True, | 68 stderr=subprocess.PIPE).stdout.readlines() |
93 stdout=subprocess.PIPE, | |
94 stderr=subprocess.PIPE).stdout.readlines() | |
95 info = {} | 69 info = {} |
96 for line in svn_info: | 70 for line in svn_info: |
97 match = re.search(r"(.*?):(.*)", line) | 71 match = re.search(r"(.*?):(.*)", line) |
98 if match: | 72 if match: |
99 info[match.group(1).strip()]=match.group(2).strip() | 73 info[match.group(1).strip()]=match.group(2).strip() |
100 | 74 |
101 return info | 75 return info |
102 | 76 |
103 def isSVNDirty(): | 77 def isSVNDirty(): |
104 command = 'svn status' | 78 svn_status = gclient_utils.Popen(['svn', 'status'], |
105 svn_status = subprocess.Popen(command, | 79 stdout=subprocess.PIPE, |
106 shell=True, | 80 stderr=subprocess.PIPE).stdout.readlines() |
107 stdout=subprocess.PIPE, | |
108 stderr=subprocess.PIPE).stdout.readlines() | |
109 for line in svn_status: | 81 for line in svn_status: |
110 match = re.search(r"^[^X?]", line) | 82 match = re.search(r"^[^X?]", line) |
111 if match: | 83 if match: |
112 return True | 84 return True |
113 | 85 |
114 return False | 86 return False |
115 | 87 |
116 def getAuthor(url, revision): | 88 def getAuthor(url, revision): |
117 info = getSVNInfo(url, revision) | 89 info = getSVNInfo(url, revision) |
118 if (info.has_key("Last Changed Author")): | 90 if (info.has_key("Last Changed Author")): |
(...skipping 19 matching lines...) Expand all Loading... |
138 if (not info.has_key("Repository Root")): | 110 if (not info.has_key("Repository Root")): |
139 return False | 111 return False |
140 repo_root = info["Repository Root"] | 112 repo_root = info["Repository Root"] |
141 info = getSVNInfo(os.path.dirname(os.path.abspath(path)), "HEAD") | 113 info = getSVNInfo(os.path.dirname(os.path.abspath(path)), "HEAD") |
142 if (info.get("Repository Root", None) != repo_root): | 114 if (info.get("Repository Root", None) != repo_root): |
143 return True | 115 return True |
144 return False | 116 return False |
145 | 117 |
146 def getRevisionLog(url, revision): | 118 def getRevisionLog(url, revision): |
147 """Takes an svn url and gets the associated revision.""" | 119 """Takes an svn url and gets the associated revision.""" |
148 command = 'svn log ' + url + " -r"+str(revision) | 120 svn_log = gclient_utils.Popen(['svn', 'log', url, '-r', str(revision)], |
149 svn_log = subprocess.Popen(command, | 121 stdout=subprocess.PIPE, |
150 shell=True, | 122 stderr=subprocess.PIPE).stdout.readlines() |
151 stdout=subprocess.PIPE, | |
152 stderr=subprocess.PIPE).stdout.readlines() | |
153 # Don't include the header lines and the trailing "---..." line and eliminate | 123 # Don't include the header lines and the trailing "---..." line and eliminate |
154 # any '\r's. | 124 # any '\r's. |
155 return ''.join([l.replace('\r','') for l in svn_log[3:-1]]) | 125 return ''.join([l.replace('\r','') for l in svn_log[3:-1]]) |
156 | 126 |
157 def getSVNVersionInfo(): | 127 def getSVNVersionInfo(): |
158 """Extract version information from SVN""" | 128 """Extract version information from SVN""" |
159 command = 'svn --version' | 129 svn_info = gclient_utils.Popen(['svn', '--version'], |
160 svn_info = subprocess.Popen(command, | 130 stdout=subprocess.PIPE, |
161 shell=True, | 131 stderr=subprocess.PIPE).stdout.readlines() |
162 stdout=subprocess.PIPE, | |
163 stderr=subprocess.PIPE).stdout.readlines() | |
164 info = {} | 132 info = {} |
165 for line in svn_info: | 133 for line in svn_info: |
166 match = re.search(r"svn, version ((\d+)\.(\d+)\.(\d+)) \(r(\d+)\)", line) | 134 match = re.search(r"svn, version ((\d+)\.(\d+)\.(\d+)) \(r(\d+)\)", line) |
167 if match: | 135 if match: |
168 info['version'] = match.group(1) | 136 info['version'] = match.group(1) |
169 info['major'] = int(match.group(2)) | 137 info['major'] = int(match.group(2)) |
170 info['minor'] = int(match.group(3)) | 138 info['minor'] = int(match.group(3)) |
171 info['patch'] = int(match.group(4)) | 139 info['patch'] = int(match.group(4)) |
172 info['revision'] = match.group(5) | 140 info['revision'] = match.group(5) |
173 return info | 141 return info |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
297 | 265 |
298 def revertRevision(url, revision): | 266 def revertRevision(url, revision): |
299 paths = getBestMergePaths(url, revision) | 267 paths = getBestMergePaths(url, revision) |
300 for path in paths: | 268 for path in paths: |
301 command = ('svn merge -N -r ' + str(revision) + ":" + str(revision-1) + | 269 command = ('svn merge -N -r ' + str(revision) + ":" + str(revision-1) + |
302 " " + url + path + " ." + path) | 270 " " + url + path + " ." + path) |
303 print command | 271 print command |
304 os.system(command) | 272 os.system(command) |
305 | 273 |
306 def getFileInfo(url, revision): | 274 def getFileInfo(url, revision): |
307 global files_info_, file_pattern_ | 275 global files_info_ |
308 | 276 |
309 if (files_info_ != None): | 277 if (files_info_ != None): |
310 return files_info_ | 278 return files_info_ |
311 | 279 |
312 command = 'svn log ' + url + " -r " + str(revision) + " -v" | 280 svn_log = gclient_utils.Popen(['svn', 'log', url, '-r', str(revision), '-v'], |
313 svn_log = subprocess.Popen(command, | 281 stdout=subprocess.PIPE, |
314 shell=True, | 282 stderr=subprocess.PIPE).stdout.readlines() |
315 stdout=subprocess.PIPE, | |
316 stderr=subprocess.PIPE).stdout.readlines() | |
317 | 283 |
318 info = [] | 284 info = [] |
319 for line in svn_log: | 285 for line in svn_log: |
320 # A workaround to dump the (from .*) stuff, regex not so friendly in the 2nd | 286 # A workaround to dump the (from .*) stuff, regex not so friendly in the 2nd |
321 # pass... | 287 # pass... |
322 match = re.search(r"(.*) \(from.*\)", line) | 288 match = re.search(r"(.*) \(from.*\)", line) |
323 if match: | 289 if match: |
324 line = match.group(1) | 290 line = match.group(1) |
325 match = re.search(file_pattern_, line) | 291 match = re.search(file_pattern_, line) |
326 if match: | 292 if match: |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
463 command = 'svn log ' + url + " -r "+str(revision) + " -v" | 429 command = 'svn log ' + url + " -r "+str(revision) + " -v" |
464 os.system(command) | 430 os.system(command) |
465 | 431 |
466 if not (options.revertbot or prompt("Is this the correct revision?")): | 432 if not (options.revertbot or prompt("Is this the correct revision?")): |
467 return 0 | 433 return 0 |
468 | 434 |
469 if (os.path.exists(working)) and not options.local: | 435 if (os.path.exists(working)) and not options.local: |
470 if not (options.revertbot or SKIP_CHECK_WORKING or | 436 if not (options.revertbot or SKIP_CHECK_WORKING or |
471 prompt("Working directory: '%s' already exists, clobber?" % working)): | 437 prompt("Working directory: '%s' already exists, clobber?" % working)): |
472 return 0 | 438 return 0 |
473 deltree(working) | 439 gclient_utils.RemoveDirectory(working) |
474 | 440 |
475 if not options.local: | 441 if not options.local: |
476 os.makedirs(working) | 442 os.makedirs(working) |
477 os.chdir(working) | 443 os.chdir(working) |
478 | 444 |
479 if options.merge: | 445 if options.merge: |
480 action = "Merge" | 446 action = "Merge" |
481 if not options.local: | 447 if not options.local: |
482 branch_url = BRANCH_URL.replace("$branch", options.branch) | 448 branch_url = BRANCH_URL.replace("$branch", options.branch) |
483 # Checkout everything but stuff that got added into a new dir | 449 # Checkout everything but stuff that got added into a new dir |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
584 | 550 |
585 if options.local and (options.revert or options.branch): | 551 if options.local and (options.revert or options.branch): |
586 option_parser.error("--local cannot be used with --revert or --branch") | 552 option_parser.error("--local cannot be used with --revert or --branch") |
587 return 1 | 553 return 1 |
588 | 554 |
589 return drover(options, args) | 555 return drover(options, args) |
590 | 556 |
591 | 557 |
592 if __name__ == "__main__": | 558 if __name__ == "__main__": |
593 sys.exit(main()) | 559 sys.exit(main()) |
OLD | NEW |