Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(60)

Side by Side Diff: drover.py

Issue 12670008: Extend drover so it can revert any chrome revision. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
Patch Set: Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2012 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 datetime
6 import optparse 7 import optparse
7 import os 8 import os
8 import re 9 import re
9 import string 10 import string
10 import sys 11 import sys
11 import urllib2 12 import urllib2
12 import urlparse 13 import urlparse
13 14
14 import breakpad # pylint: disable=W0611 15 import breakpad # pylint: disable=W0611
15 16
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
65 command = "%s %s" % (gcl_path, subcommand) 66 command = "%s %s" % (gcl_path, subcommand)
66 return os.system(command) 67 return os.system(command)
67 68
68 def gclUpload(revision, author): 69 def gclUpload(revision, author):
69 command = ("upload " + str(revision) + 70 command = ("upload " + str(revision) +
70 " --send_mail --no_presubmit --reviewers=" + author) 71 " --send_mail --no_presubmit --reviewers=" + author)
71 return runGcl(command) 72 return runGcl(command)
72 73
73 def getSVNInfo(url, revision): 74 def getSVNInfo(url, revision):
74 info = {} 75 info = {}
75 try: 76 svn_info = subprocess2.capture(
76 svn_info = subprocess2.check_output( 77 ['svn', 'info', '--non-interactive', '%s@%s' % (url, revision)],
77 ['svn', 'info', '%s@%s' % (url, revision)]).splitlines() 78 stderr=subprocess2.VOID).splitlines()
78 for line in svn_info: 79 for line in svn_info:
79 match = re.search(r"(.*?):(.*)", line) 80 match = re.search(r"(.*?):(.*)", line)
80 if match: 81 if match:
81 info[match.group(1).strip()] = match.group(2).strip() 82 info[match.group(1).strip()] = match.group(2).strip()
82 except subprocess2.CalledProcessError:
83 pass
84 return info 83 return info
85 84
86 def isSVNDirty(): 85 def isSVNDirty():
87 svn_status = subprocess2.check_output(['svn', 'status']).splitlines() 86 svn_status = subprocess2.check_output(['svn', 'status']).splitlines()
88 for line in svn_status: 87 for line in svn_status:
89 match = re.search(r"^[^X?]", line) 88 match = re.search(r"^[^X?]", line)
90 if match: 89 if match:
91 return True 90 return True
92 91
93 return False 92 return False
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after
484 return default 483 return default
485 return answer 484 return answer
486 485
487 486
488 def drover(options, args): 487 def drover(options, args):
489 revision = options.revert or options.merge 488 revision = options.revert or options.merge
490 489
491 # Initialize some variables used below. They can be overwritten by 490 # Initialize some variables used below. They can be overwritten by
492 # the drover.properties file. 491 # the drover.properties file.
493 BASE_URL = "svn://svn.chromium.org/chrome" 492 BASE_URL = "svn://svn.chromium.org/chrome"
493 REVERT_ALT_URLS = ['svn://svn.chromium.org/chrome-internal',
494 'svn://svn.chromium.org/native_client']
494 TRUNK_URL = BASE_URL + "/trunk/src" 495 TRUNK_URL = BASE_URL + "/trunk/src"
495 BRANCH_URL = BASE_URL + "/branches/$branch/src" 496 BRANCH_URL = BASE_URL + "/branches/$branch/src"
496 SKIP_CHECK_WORKING = True 497 SKIP_CHECK_WORKING = True
497 PROMPT_FOR_AUTHOR = False 498 PROMPT_FOR_AUTHOR = False
498 499
499 # Translate a given milestone to the appropriate branch number. 500 # Translate a given milestone to the appropriate branch number.
500 if options.milestone: 501 if options.milestone:
501 options.branch = getBranchForMilestone(options.milestone) 502 options.branch = getBranchForMilestone(options.milestone)
502 if not options.branch: 503 if not options.branch:
503 return 1 504 return 1
(...skipping 10 matching lines...) Expand all
514 global file_pattern_ 515 global file_pattern_
515 if os.path.exists("drover.properties"): 516 if os.path.exists("drover.properties"):
516 FILE_PATTERN = file_pattern_ 517 FILE_PATTERN = file_pattern_
517 f = open("drover.properties") 518 f = open("drover.properties")
518 exec(f) 519 exec(f)
519 f.close() 520 f.close()
520 if FILE_PATTERN: 521 if FILE_PATTERN:
521 file_pattern_ = FILE_PATTERN 522 file_pattern_ = FILE_PATTERN
522 523
523 if options.revert and options.branch: 524 if options.revert and options.branch:
525 print 'Note: --branch is usually not needed for reverts.'
524 url = BRANCH_URL.replace("$branch", options.branch) 526 url = BRANCH_URL.replace("$branch", options.branch)
525 elif options.merge and options.sbranch: 527 elif options.merge and options.sbranch:
526 url = BRANCH_URL.replace("$branch", options.sbranch) 528 url = BRANCH_URL.replace("$branch", options.sbranch)
527 elif options.revert and options.url: 529 elif options.revert:
528 url = options.url 530 url = options.url or BASE_URL
529 file_pattern_ = r"[ ]+([MADUC])[ ]+((/.*)/(.*))" 531 file_pattern_ = r"[ ]+([MADUC])[ ]+((/.*)/(.*))"
530 else: 532 else:
531 url = TRUNK_URL 533 url = TRUNK_URL
532 534
533 working = options.workdir or DEFAULT_WORKING 535 working = options.workdir or DEFAULT_WORKING
534 536
535 if options.local: 537 if options.local:
536 working = os.getcwd() 538 working = os.getcwd()
537 if not inCheckoutRoot(working): 539 if not inCheckoutRoot(working):
538 print "'%s' appears not to be the root of a working copy" % working 540 print "'%s' appears not to be the root of a working copy" % working
539 return 1 541 return 1
540 if (isSVNDirty() and not 542 if (isSVNDirty() and not
541 prompt("Working copy contains uncommitted files. Continue?")): 543 prompt("Working copy contains uncommitted files. Continue?")):
542 return 1 544 return 1
543 545
546 if options.revert and not options.no_alt_urls:
547 for cur_url in [url] + REVERT_ALT_URLS:
548 try:
549 commit_date_str = getSVNInfo(
550 cur_url, options.revert).get('Last Changed Date', 'x').split()[0]
551 commit_date = datetime.datetime.strptime(commit_date_str, '%Y-%m-%d')
552 if (datetime.datetime.now() - commit_date).days < 120:
553 if cur_url != url:
554 print 'Guessing svn repo: %s.' % cur_url,
555 print 'Use --no-alt-urls to disable heuristic.'
556 url = cur_url
557 break
558 except ValueError:
559 pass
544 command = 'svn log ' + url + " -r "+str(revision) + " -v" 560 command = 'svn log ' + url + " -r "+str(revision) + " -v"
545 os.system(command) 561 os.system(command)
546 562
547 if not (options.revertbot or prompt("Is this the correct revision?")): 563 if not (options.revertbot or prompt("Is this the correct revision?")):
548 return 0 564 return 0
549 565
550 if (os.path.exists(working)) and not options.local: 566 if (os.path.exists(working)) and not options.local:
551 if not (options.revertbot or SKIP_CHECK_WORKING or 567 if not (options.revertbot or SKIP_CHECK_WORKING or
552 prompt("Working directory: '%s' already exists, clobber?" % working)): 568 prompt("Working directory: '%s' already exists, clobber?" % working)):
553 return 0 569 return 0
(...skipping 11 matching lines...) Expand all
565 checkoutRevision(url, revision, branch_url) 581 checkoutRevision(url, revision, branch_url)
566 # Merge everything that changed 582 # Merge everything that changed
567 mergeRevision(url, revision) 583 mergeRevision(url, revision)
568 # "Export" files that were added from the source and add them to branch 584 # "Export" files that were added from the source and add them to branch
569 exportRevision(url, revision) 585 exportRevision(url, revision)
570 # Delete directories that were deleted (file deletes are handled in the 586 # Delete directories that were deleted (file deletes are handled in the
571 # merge). 587 # merge).
572 deleteRevision(url, revision) 588 deleteRevision(url, revision)
573 elif options.revert: 589 elif options.revert:
574 action = "Revert" 590 action = "Revert"
575 if options.branch:
576 url = BRANCH_URL.replace("$branch", options.branch)
577 pop_em = not options.url 591 pop_em = not options.url
578 checkoutRevision(url, revision, url, True, pop_em) 592 checkoutRevision(url, revision, url, True, pop_em)
579 revertRevision(url, revision) 593 revertRevision(url, revision)
580 revertExportRevision(url, revision) 594 revertExportRevision(url, revision)
581 595
582 # Check the base url so we actually find the author who made the change 596 # Check the base url so we actually find the author who made the change
583 if options.auditor: 597 if options.auditor:
584 author = options.auditor 598 author = options.auditor
585 else: 599 else:
586 author = getAuthor(url, revision) 600 author = getAuthor(url, revision)
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
665 option_parser.add_option('-s', '--sbranch', 679 option_parser.add_option('-s', '--sbranch',
666 help='Source branch for merge') 680 help='Source branch for merge')
667 option_parser.add_option('-r', '--revert', type="int", 681 option_parser.add_option('-r', '--revert', type="int",
668 help='Revision to revert') 682 help='Revision to revert')
669 option_parser.add_option('-w', '--workdir', 683 option_parser.add_option('-w', '--workdir',
670 help='subdir to use for the revert') 684 help='subdir to use for the revert')
671 option_parser.add_option('-u', '--url', 685 option_parser.add_option('-u', '--url',
672 help='svn url to use for the revert') 686 help='svn url to use for the revert')
673 option_parser.add_option('-a', '--auditor', 687 option_parser.add_option('-a', '--auditor',
674 help='overrides the author for reviewer') 688 help='overrides the author for reviewer')
675 option_parser.add_option('', '--revertbot', action='store_true', 689 option_parser.add_option('--revertbot', action='store_true',
676 default=False) 690 default=False)
677 option_parser.add_option('', '--revertbot-commit', action='store_true', 691 option_parser.add_option('--no-alt-urls', action='store_true',
692 help='Disable heuristics used to determine svn url')
693 option_parser.add_option('--revertbot-commit', action='store_true',
678 default=False) 694 default=False)
679 option_parser.add_option('', '--revertbot-reviewers') 695 option_parser.add_option('--revertbot-reviewers')
680 options, args = option_parser.parse_args() 696 options, args = option_parser.parse_args()
681 697
682 if not options.merge and not options.revert: 698 if not options.merge and not options.revert:
683 option_parser.error("You need at least --merge or --revert") 699 option_parser.error("You need at least --merge or --revert")
684 return 1 700 return 1
685 701
686 if options.merge and not (options.branch or options.milestone or 702 if options.merge and not (options.branch or options.milestone or
687 options.local): 703 options.local):
688 option_parser.error("--merge requires either --branch " 704 option_parser.error("--merge requires either --branch "
689 "or --milestone or --local") 705 "or --milestone or --local")
690 return 1 706 return 1
691 707
692 if options.local and (options.revert or options.branch or options.milestone): 708 if options.local and (options.revert or options.branch or options.milestone):
693 option_parser.error("--local cannot be used with --revert " 709 option_parser.error("--local cannot be used with --revert "
694 "or --branch or --milestone") 710 "or --branch or --milestone")
695 return 1 711 return 1
696 712
697 if options.branch and options.milestone: 713 if options.branch and options.milestone:
698 option_parser.error("--branch cannot be used with --milestone") 714 option_parser.error("--branch cannot be used with --milestone")
699 return 1 715 return 1
700 716
701 return drover(options, args) 717 return drover(options, args)
702 718
703 719
704 if __name__ == "__main__": 720 if __name__ == "__main__":
705 sys.exit(main()) 721 sys.exit(main())
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698