OLD | NEW |
---|---|
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2011 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 string | |
9 import sys | 10 import sys |
11 import urllib2 | |
10 | 12 |
11 import breakpad # pylint: disable=W0611 | 13 import breakpad # pylint: disable=W0611 |
12 | 14 |
13 import gclient_utils | 15 import gclient_utils |
14 import subprocess2 | 16 import subprocess2 |
15 | 17 |
16 USAGE = """ | 18 USAGE = """ |
17 WARNING: Please use this tool in an empty directory | 19 WARNING: Please use this tool in an empty directory |
18 (or at least one that you don't mind clobbering.) | 20 (or at least one that you don't mind clobbering.) |
19 | 21 |
20 REQUIRES: SVN 1.5+ | 22 REQUIRES: SVN 1.5+ |
21 NOTE: NO NEED TO CHECKOUT ANYTHING IN ADVANCE OF USING THIS TOOL. | 23 NOTE: NO NEED TO CHECKOUT ANYTHING IN ADVANCE OF USING THIS TOOL. |
22 Valid parameters: | 24 Valid parameters: |
23 | 25 |
24 [Merge from trunk to branch] | 26 [Merge from trunk to branch] |
25 --merge <revision> --branch <branch_num> | 27 --merge <revision> --branch <branch_num> |
26 Example: %(app)s --merge 12345 --branch 187 | 28 Example: %(app)s --merge 12345 --branch 187 |
27 | 29 |
30 [Merge from trunk to milestone] | |
31 --merge <revision> --milestone <milestone_num> | |
32 Example: %(app)s -- merge 12345 --milestone 16 | |
33 | |
28 [Merge from trunk to local copy] | 34 [Merge from trunk to local copy] |
29 --merge <revision> --local | 35 --merge <revision> --local |
30 Example: %(app)s --merge 12345 --local | 36 Example: %(app)s --merge 12345 --local |
31 | 37 |
32 [Merge from branch to branch] | 38 [Merge from branch to branch] |
33 --merge <revision> --sbranch <branch_num> --branch <branch_num> | 39 --merge <revision> --sbranch <branch_num> --branch <branch_num> |
34 Example: %(app)s --merge 12345 --sbranch 248 --branch 249 | 40 Example: %(app)s --merge 12345 --sbranch 248 --branch 249 |
35 | 41 |
36 [Revert from trunk] | 42 [Revert from trunk] |
37 --revert <revision> | 43 --revert <revision> |
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
350 | 356 |
351 | 357 |
352 def getAllFilesInRevision(files_info): | 358 def getAllFilesInRevision(files_info): |
353 """Checks for existing files in the revision. | 359 """Checks for existing files in the revision. |
354 | 360 |
355 Anything that's A will require special treatment (either a merge or an | 361 Anything that's A will require special treatment (either a merge or an |
356 export + add) | 362 export + add) |
357 """ | 363 """ |
358 return ['%s/%s' % (f[2], f[3]) for f in files_info] | 364 return ['%s/%s' % (f[2], f[3]) for f in files_info] |
359 | 365 |
366 def getBranchForMilestone(milestone): | |
367 """Queries omahaproxy.appspot.com for the branch number given |milestone|. | |
368 """ | |
369 OMAHA_PROXY_URL = "http://omahaproxy.appspot.com" | |
370 request = urllib2.Request(OMAHA_PROXY_URL) | |
371 try: | |
372 response = urllib2.urlopen(request) | |
373 except urllib2.HTTPError, e: | |
374 print "Failed to query %s: %d" % (OMAHA_PROXY_URL, e.code) | |
375 return None | |
376 | |
377 # Slice the first line since it's column information text. | |
378 for line in response.readlines()[1:]: | |
laforge
2011/11/09 05:06:12
This approach is a little dangerous, but will prob
James Hawkins
2011/11/10 03:37:36
There are two separate things we can do here:
* De
| |
379 # Version data is CSV. | |
380 parameters = string.split(line, ',') | |
381 | |
382 # Milestone is the third parameter. | |
383 full_milestone = parameters[2] | |
laforge
2011/11/09 05:06:12
It would probably be clearer to call this var vers
James Hawkins
2011/11/10 03:37:36
Done.
| |
384 | |
385 # Full milestone is a quad of numbers separated by periods. | |
386 milestone_str = string.split(full_milestone, '.')[0] | |
387 if int(milestone_str, 10) != milestone: | |
388 continue | |
389 | |
390 # Correct milestone found. Return the branch parameter, which is last. | |
391 return parameters[len(parameters) - 1] | |
laforge
2011/11/09 05:06:12
It would be better here to return full_mstone.spli
James Hawkins
2011/11/10 03:37:36
Done.
| |
392 | |
393 # Milestone not found. | |
394 print "Milestone provided is invalid" | |
395 return None | |
396 | |
360 def prompt(question): | 397 def prompt(question): |
361 while True: | 398 while True: |
362 print question + " [y|n]:", | 399 print question + " [y|n]:", |
363 answer = sys.stdin.readline() | 400 answer = sys.stdin.readline() |
364 if answer.lower().startswith('n'): | 401 if answer.lower().startswith('n'): |
365 return False | 402 return False |
366 elif answer.lower().startswith('y'): | 403 elif answer.lower().startswith('y'): |
367 return True | 404 return True |
368 | 405 |
369 | 406 |
370 def text_prompt(question, default): | 407 def text_prompt(question, default): |
371 print question + " [" + default + "]:" | 408 print question + " [" + default + "]:" |
372 answer = sys.stdin.readline() | 409 answer = sys.stdin.readline() |
373 if answer.strip() == "": | 410 if answer.strip() == "": |
374 return default | 411 return default |
375 return answer | 412 return answer |
376 | 413 |
377 | 414 |
378 def drover(options, args): | 415 def drover(options, args): |
379 revision = options.revert or options.merge | 416 revision = options.revert or options.merge |
380 | 417 |
381 # Initialize some variables used below. They can be overwritten by | 418 # Initialize some variables used below. They can be overwritten by |
382 # the drover.properties file. | 419 # the drover.properties file. |
383 BASE_URL = "svn://svn.chromium.org/chrome" | 420 BASE_URL = "svn://svn.chromium.org/chrome" |
384 TRUNK_URL = BASE_URL + "/trunk/src" | 421 TRUNK_URL = BASE_URL + "/trunk/src" |
385 BRANCH_URL = BASE_URL + "/branches/$branch/src" | 422 BRANCH_URL = BASE_URL + "/branches/$branch/src" |
386 SKIP_CHECK_WORKING = True | 423 SKIP_CHECK_WORKING = True |
387 PROMPT_FOR_AUTHOR = False | 424 PROMPT_FOR_AUTHOR = False |
388 | 425 |
426 # Translate a given milestone to the appropriate branch number. | |
427 if options.milestone: | |
428 options.branch = getBranchForMilestone(options.milestone) | |
429 if options.branch is None: | |
430 return 1 | |
431 | |
389 DEFAULT_WORKING = "drover_" + str(revision) | 432 DEFAULT_WORKING = "drover_" + str(revision) |
390 if options.branch: | 433 if options.branch: |
391 DEFAULT_WORKING += ("_" + options.branch) | 434 DEFAULT_WORKING += ("_" + options.branch) |
392 | 435 |
393 if not isMinimumSVNVersion(1, 5): | 436 if not isMinimumSVNVersion(1, 5): |
394 print "You need to use at least SVN version 1.5.x" | 437 print "You need to use at least SVN version 1.5.x" |
395 return 1 | 438 return 1 |
396 | 439 |
397 # Override the default properties if there is a drover.properties file. | 440 # Override the default properties if there is a drover.properties file. |
398 global file_pattern_ | 441 global file_pattern_ |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
515 else: | 558 else: |
516 return 0 | 559 return 0 |
517 | 560 |
518 | 561 |
519 def main(): | 562 def main(): |
520 option_parser = optparse.OptionParser(usage=USAGE % {"app": sys.argv[0]}) | 563 option_parser = optparse.OptionParser(usage=USAGE % {"app": sys.argv[0]}) |
521 option_parser.add_option('-m', '--merge', type="int", | 564 option_parser.add_option('-m', '--merge', type="int", |
522 help='Revision to merge from trunk to branch') | 565 help='Revision to merge from trunk to branch') |
523 option_parser.add_option('-b', '--branch', | 566 option_parser.add_option('-b', '--branch', |
524 help='Branch to revert or merge from') | 567 help='Branch to revert or merge from') |
568 option_parser.add_option('-M', '--milestone', type="int", | |
569 help='Milestone to revert or merge from') | |
525 option_parser.add_option('-l', '--local', action='store_true', | 570 option_parser.add_option('-l', '--local', action='store_true', |
526 help='Local working copy to merge to') | 571 help='Local working copy to merge to') |
527 option_parser.add_option('-s', '--sbranch', | 572 option_parser.add_option('-s', '--sbranch', |
528 help='Source branch for merge') | 573 help='Source branch for merge') |
529 option_parser.add_option('-r', '--revert', type="int", | 574 option_parser.add_option('-r', '--revert', type="int", |
530 help='Revision to revert') | 575 help='Revision to revert') |
531 option_parser.add_option('-w', '--workdir', | 576 option_parser.add_option('-w', '--workdir', |
532 help='subdir to use for the revert') | 577 help='subdir to use for the revert') |
533 option_parser.add_option('-a', '--auditor', | 578 option_parser.add_option('-a', '--auditor', |
534 help='overrides the author for reviewer') | 579 help='overrides the author for reviewer') |
535 option_parser.add_option('', '--revertbot', action='store_true', | 580 option_parser.add_option('', '--revertbot', action='store_true', |
536 default=False) | 581 default=False) |
537 option_parser.add_option('', '--revertbot-commit', action='store_true', | 582 option_parser.add_option('', '--revertbot-commit', action='store_true', |
538 default=False) | 583 default=False) |
539 option_parser.add_option('', '--revertbot-reviewers') | 584 option_parser.add_option('', '--revertbot-reviewers') |
540 options, args = option_parser.parse_args() | 585 options, args = option_parser.parse_args() |
541 | 586 |
542 if not options.merge and not options.revert: | 587 if not options.merge and not options.revert: |
543 option_parser.error("You need at least --merge or --revert") | 588 option_parser.error("You need at least --merge or --revert") |
544 return 1 | 589 return 1 |
545 | 590 |
546 if options.merge and not options.branch and not options.local: | 591 if (options.merge and not options.branch and not options.milestone and |
592 not options.local): | |
547 option_parser.error("--merge requires either --branch or --local") | 593 option_parser.error("--merge requires either --branch or --local") |
548 return 1 | 594 return 1 |
549 | 595 |
550 if options.local and (options.revert or options.branch): | 596 if options.local and (options.revert or options.branch or options.milestone): |
551 option_parser.error("--local cannot be used with --revert or --branch") | 597 option_parser.error("--local cannot be used with --revert or --branch") |
552 return 1 | 598 return 1 |
553 | 599 |
600 if options.branch and options.milestone: | |
601 option_parser.error("--branch cannot be used with --milestone") | |
602 return 1 | |
603 | |
554 return drover(options, args) | 604 return drover(options, args) |
555 | 605 |
556 | 606 |
557 if __name__ == "__main__": | 607 if __name__ == "__main__": |
558 sys.exit(main()) | 608 sys.exit(main()) |
OLD | NEW |