Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 optparse | 6 import optparse |
| 7 import os | 7 import os |
| 8 import re | 8 import re |
| 9 import string | 9 import string |
| 10 import sys | 10 import sys |
| 11 import urllib2 | 11 import urllib2 |
| 12 import urlparse | |
| 12 | 13 |
| 13 import breakpad # pylint: disable=W0611 | 14 import breakpad # pylint: disable=W0611 |
| 14 | 15 |
| 15 import gclient_utils | 16 import gclient_utils |
| 17 import rietveld | |
| 16 import subprocess2 | 18 import subprocess2 |
| 17 | 19 |
| 18 USAGE = """ | 20 USAGE = """ |
| 19 WARNING: Please use this tool in an empty directory | 21 WARNING: Please use this tool in an empty directory |
| 20 (or at least one that you don't mind clobbering.) | 22 (or at least one that you don't mind clobbering.) |
| 21 | 23 |
| 22 REQUIRES: SVN 1.5+ | 24 REQUIRES: SVN 1.5+ |
| 23 NOTE: NO NEED TO CHECKOUT ANYTHING IN ADVANCE OF USING THIS TOOL. | 25 NOTE: NO NEED TO CHECKOUT ANYTHING IN ADVANCE OF USING THIS TOOL. |
| 24 Valid parameters: | 26 Valid parameters: |
| 25 | 27 |
| (...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 414 # Not all of the platforms have the same branch. Prompt the user and return | 416 # Not all of the platforms have the same branch. Prompt the user and return |
| 415 # the greatest (by value) branch on success. | 417 # the greatest (by value) branch on success. |
| 416 if prompt("Not all platforms have the same branch number, " | 418 if prompt("Not all platforms have the same branch number, " |
| 417 "continue with branch %s?" % branch): | 419 "continue with branch %s?" % branch): |
| 418 return branch | 420 return branch |
| 419 | 421 |
| 420 # User cancelled. | 422 # User cancelled. |
| 421 return None | 423 return None |
| 422 | 424 |
| 423 | 425 |
| 426 def getSVNAuthInfo(folder=None): | |
| 427 """Fetches SVN authorization information in the subversion auth folder and | |
| 428 returns it as a dictionary of dictionaries.""" | |
| 429 if not folder: | |
| 430 if sys.platform == 'win32': | |
| 431 folder = '%%APPDATA%\\Subversion\\auth' | |
| 432 else: | |
| 433 folder = '$HOME/.subversion/auth' | |
| 434 folder = os.path.expandvars(folder) | |
|
Isaac (away)
2012/11/22 01:36:05
if you use ~ instead of $HOME, you can call expand
| |
| 435 svn_simple_folder = os.path.join(folder, 'svn.simple') | |
| 436 svn_simple_files = (os.listdir(svn_simple_folder) if | |
| 437 os.path.exists(svn_simple_folder) else []) | |
|
Isaac (away)
2012/11/22 01:36:05
This is a race condition on the folder or svn file
| |
| 438 results = {} | |
| 439 for auth_file in svn_simple_files: | |
| 440 # Read the SVN auth file, convert it into a dictionary, and store it. | |
| 441 results[auth_file] = dict(re.findall(r'K [0-9]+\n(.*)\nV [0-9]+\n(.*)\n', | |
| 442 open(os.path.join(svn_simple_folder, auth_file)).read())) | |
| 443 return results | |
| 444 | |
| 445 | |
| 446 def getCurrentSVNUsers(url): | |
| 447 """Tries to fetch the current SVN in the current checkout by scanning the | |
| 448 SVN authorization folder for a match with the current SVN URL.""" | |
| 449 netloc = urlparse.urlparse(url)[1] | |
| 450 auth_infos = getSVNAuthInfo() | |
| 451 results = [] | |
| 452 for _, auth_info in auth_infos.iteritems(): | |
| 453 if ('svn:realmstring' in auth_info | |
| 454 and netloc in auth_info['svn:realmstring']): | |
|
Isaac (away)
2012/11/22 01:36:05
better to parse the netloc from the svn url and co
| |
| 455 username = auth_info['username'] | |
| 456 results.append(username) | |
| 457 if 'google.com' in username: | |
| 458 results.append(username.replace('google.com', 'chromium.org')) | |
| 459 return results | |
| 460 | |
| 461 | |
| 424 def prompt(question): | 462 def prompt(question): |
| 425 while True: | 463 while True: |
| 426 print question + " [y|n]:", | 464 print question + " [y|n]:", |
| 427 answer = sys.stdin.readline() | 465 answer = sys.stdin.readline() |
| 428 if answer.lower().startswith('n'): | 466 if answer.lower().startswith('n'): |
| 429 return False | 467 return False |
| 430 elif answer.lower().startswith('y'): | 468 elif answer.lower().startswith('y'): |
| 431 return True | 469 return True |
| 432 | 470 |
| 433 | 471 |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 530 revertExportRevision(url, revision) | 568 revertExportRevision(url, revision) |
| 531 | 569 |
| 532 # Check the base url so we actually find the author who made the change | 570 # Check the base url so we actually find the author who made the change |
| 533 if options.auditor: | 571 if options.auditor: |
| 534 author = options.auditor | 572 author = options.auditor |
| 535 else: | 573 else: |
| 536 author = getAuthor(url, revision) | 574 author = getAuthor(url, revision) |
| 537 if not author: | 575 if not author: |
| 538 author = getAuthor(TRUNK_URL, revision) | 576 author = getAuthor(TRUNK_URL, revision) |
| 539 | 577 |
| 578 # Check that the author of the CL is different than the user making | |
| 579 # the revert. If they're the same, then we'll want to prompt the user | |
| 580 # for a different reviewer to TBR. | |
| 581 current_users = getCurrentSVNUsers(BASE_URL) | |
|
Isaac (away)
2012/11/22 01:36:05
can't we just run svn info in the drover checkout
Ryan Tseng
2012/11/29 23:27:35
AFAIK SVN user cache information isn't given in an
| |
| 582 if options.revert and author in current_users: | |
| 583 # Fetch the reverting CL's authors. | |
| 584 revision_log = getRevisionLog(BASE_URL, revision) | |
| 585 review_url_match = re.search("Review URL:\s*(.*)", revision_log) | |
|
Isaac (away)
2012/11/22 01:36:05
the rietveld integration is nice, but it might be
Isaac (away)
2012/11/22 01:43:24
Oh, this comment is slightly stale. I wrote it an
| |
| 586 if review_url_match: | |
| 587 review_url = review_url_match.groups(1)[-1] | |
| 588 parsed_review_url = urlparse.urlparse(review_url) | |
| 589 rietveld_url = parsed_review_url[1] # Index 1 for network location. | |
| 590 issue = int(re.search("\d+", parsed_review_url[2]).group()) | |
| 591 issue_info = rietveld.Rietveld(rietveld_url, | |
| 592 None, None).get_issue_properties(issue, None) | |
| 593 cl_reviewers = (",".join(issue_info["reviewers"]) if "reviewers" in | |
|
Isaac (away)
2012/11/22 01:36:05
See the code for CheckOwners in the presubmit_cann
| |
| 594 issue_info else "") | |
| 595 else: | |
| 596 cl_reviewers = "" | |
| 597 additional_authors = text_prompt("You appear to be reverting " | |
|
Isaac (away)
2012/11/22 01:36:05
appear might be too weak, how about
"Is this a se
| |
| 598 "your own change, please enter additional reviewer(s) to TBR", | |
| 599 cl_reviewers) | |
|
Isaac (away)
2012/11/22 01:36:05
Reviewer lists can be quite long, are you sure we
| |
| 600 if additional_authors: | |
| 601 author += "," + additional_authors | |
|
Isaac (away)
2012/11/22 01:36:05
author of a self-revert should not be in the TBR l
| |
| 602 | |
| 540 filename = str(revision)+".txt" | 603 filename = str(revision)+".txt" |
| 541 out = open(filename,"w") | 604 out = open(filename,"w") |
| 542 out.write(action +" " + str(revision) + " - ") | 605 out.write(action +" " + str(revision) + " - ") |
| 543 out.write(getRevisionLog(url, revision)) | 606 for line in getRevisionLog(url, revision).split('\n'): |
|
Isaac (away)
2012/11/22 01:36:05
use splitlines()
| |
| 607 out.write('> %s\n' % line) | |
|
nsylvain
2012/11/21 23:10:51
we should probably just use spaces instead of ">".
| |
| 544 if (author): | 608 if (author): |
| 545 out.write("\nTBR=" + author) | 609 out.write("\nTBR=" + author) |
| 546 out.close() | 610 out.close() |
| 547 | 611 |
| 548 change_cmd = 'change ' + str(revision) + " " + filename | 612 change_cmd = 'change ' + str(revision) + " " + filename |
| 549 if options.revertbot: | 613 if options.revertbot: |
| 550 if sys.platform == 'win32': | 614 if sys.platform == 'win32': |
| 551 os.environ['SVN_EDITOR'] = 'cmd.exe /c exit' | 615 os.environ['SVN_EDITOR'] = 'cmd.exe /c exit' |
| 552 else: | 616 else: |
| 553 os.environ['SVN_EDITOR'] = 'true' | 617 os.environ['SVN_EDITOR'] = 'true' |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 628 | 692 |
| 629 if options.branch and options.milestone: | 693 if options.branch and options.milestone: |
| 630 option_parser.error("--branch cannot be used with --milestone") | 694 option_parser.error("--branch cannot be used with --milestone") |
| 631 return 1 | 695 return 1 |
| 632 | 696 |
| 633 return drover(options, args) | 697 return drover(options, args) |
| 634 | 698 |
| 635 | 699 |
| 636 if __name__ == "__main__": | 700 if __name__ == "__main__": |
| 637 sys.exit(main()) | 701 sys.exit(main()) |
| OLD | NEW |