| OLD | NEW |
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 # Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2006-2009 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 # Wrapper script around Rietveld's upload.py that groups files into | 6 # Wrapper script around Rietveld's upload.py that groups files into |
| 7 # changelists. | 7 # changelists. |
| 8 | 8 |
| 9 import getpass | 9 import getpass |
| 10 import os | 10 import os |
| (...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 279 # _SEPARATOR\n | 279 # _SEPARATOR\n |
| 280 # description | 280 # description |
| 281 | 281 |
| 282 def __init__(self, name, issue, patchset, description, files): | 282 def __init__(self, name, issue, patchset, description, files): |
| 283 self.name = name | 283 self.name = name |
| 284 self.issue = int(issue) | 284 self.issue = int(issue) |
| 285 self.patchset = int(patchset) | 285 self.patchset = int(patchset) |
| 286 self.description = description | 286 self.description = description |
| 287 if files is None: | 287 if files is None: |
| 288 files = [] | 288 files = [] |
| 289 self.files = files | 289 self._files = files |
| 290 self.patch = None | 290 self.patch = None |
| 291 self._local_root = GetRepositoryRoot() |
| 291 | 292 |
| 292 def FileList(self): | 293 def GetFileNames(self): |
| 293 """Returns a list of files.""" | 294 """Returns the list of file names included in this change.""" |
| 294 return [file[1] for file in self.files] | 295 return [file[1] for file in self._files] |
| 296 |
| 297 def GetFiles(self): |
| 298 """Returns the list of files included in this change with their status.""" |
| 299 return self._files |
| 300 |
| 301 def GetLocalRoot(self): |
| 302 """Returns the local repository checkout root directory.""" |
| 303 return self._local_root |
| 295 | 304 |
| 296 def _NonDeletedFileList(self): | 305 def _NonDeletedFileList(self): |
| 297 """Returns a list of files in this change, not including deleted files.""" | 306 """Returns a list of files in this change, not including deleted files.""" |
| 298 return [file[1] for file in self.files if not file[0].startswith("D")] | 307 return [file[1] for file in self.GetFiles() |
| 308 if not file[0].startswith("D")] |
| 299 | 309 |
| 300 def _AddedFileList(self): | 310 def _AddedFileList(self): |
| 301 """Returns a list of files added in this change.""" | 311 """Returns a list of files added in this change.""" |
| 302 return [file[1] for file in self.files if file[0].startswith("A")] | 312 return [file[1] for file in self.GetFiles() if file[0].startswith("A")] |
| 303 | 313 |
| 304 def Save(self): | 314 def Save(self): |
| 305 """Writes the changelist information to disk.""" | 315 """Writes the changelist information to disk.""" |
| 306 data = ChangeInfo._SEPARATOR.join([ | 316 data = ChangeInfo._SEPARATOR.join([ |
| 307 "%d, %d" % (self.issue, self.patchset), | 317 "%d, %d" % (self.issue, self.patchset), |
| 308 "\n".join([f[0] + f[1] for f in self.files]), | 318 "\n".join([f[0] + f[1] for f in self.GetFiles()]), |
| 309 self.description]) | 319 self.description]) |
| 310 WriteFile(GetChangelistInfoFile(self.name), data) | 320 WriteFile(GetChangelistInfoFile(self.name), data) |
| 311 | 321 |
| 312 def Delete(self): | 322 def Delete(self): |
| 313 """Removes the changelist information from disk.""" | 323 """Removes the changelist information from disk.""" |
| 314 os.remove(GetChangelistInfoFile(self.name)) | 324 os.remove(GetChangelistInfoFile(self.name)) |
| 315 | 325 |
| 316 def CloseIssue(self): | 326 def CloseIssue(self): |
| 317 """Closes the Rietveld issue for this changelist.""" | 327 """Closes the Rietveld issue for this changelist.""" |
| 318 data = [("description", self.description),] | 328 data = [("description", self.description),] |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 370 | 380 |
| 371 Inline methods added to header files won't be detected by this. That's | 381 Inline methods added to header files won't be detected by this. That's |
| 372 acceptable for purposes of determining if a unit test is needed, since | 382 acceptable for purposes of determining if a unit test is needed, since |
| 373 inline methods should be trivial. | 383 inline methods should be trivial. |
| 374 """ | 384 """ |
| 375 # To check for methods added to source or header files, we need the diffs. | 385 # To check for methods added to source or header files, we need the diffs. |
| 376 # We'll generate them all, since there aren't likely to be many files | 386 # We'll generate them all, since there aren't likely to be many files |
| 377 # apart from source and headers; besides, we'll want them all if we're | 387 # apart from source and headers; besides, we'll want them all if we're |
| 378 # uploading anyway. | 388 # uploading anyway. |
| 379 if self.patch is None: | 389 if self.patch is None: |
| 380 self.patch = GenerateDiff(self.FileList()) | 390 self.patch = GenerateDiff(self.GetFileNames()) |
| 381 | 391 |
| 382 definition = "" | 392 definition = "" |
| 383 for line in self.patch.splitlines(): | 393 for line in self.patch.splitlines(): |
| 384 if not line.startswith("+"): | 394 if not line.startswith("+"): |
| 385 continue | 395 continue |
| 386 line = line.strip("+").rstrip(" \t") | 396 line = line.strip("+").rstrip(" \t") |
| 387 # Skip empty lines, comments, and preprocessor directives. | 397 # Skip empty lines, comments, and preprocessor directives. |
| 388 # TODO(pamg): Handle multiline comments if it turns out to be a problem. | 398 # TODO(pamg): Handle multiline comments if it turns out to be a problem. |
| 389 if line == "" or line.startswith("/") or line.startswith("#"): | 399 if line == "" or line.startswith("/") or line.startswith("#"): |
| 390 continue | 400 continue |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 468 | 478 |
| 469 def LoadChangelistInfoForMultiple(changenames, fail_on_not_found=True, | 479 def LoadChangelistInfoForMultiple(changenames, fail_on_not_found=True, |
| 470 update_status=False): | 480 update_status=False): |
| 471 """Loads many changes and merge their files list into one pseudo change. | 481 """Loads many changes and merge their files list into one pseudo change. |
| 472 | 482 |
| 473 This is mainly usefull to concatenate many changes into one for a 'gcl try'. | 483 This is mainly usefull to concatenate many changes into one for a 'gcl try'. |
| 474 """ | 484 """ |
| 475 changes = changenames.split(',') | 485 changes = changenames.split(',') |
| 476 aggregate_change_info = ChangeInfo(changenames, 0, 0, '', None) | 486 aggregate_change_info = ChangeInfo(changenames, 0, 0, '', None) |
| 477 for change in changes: | 487 for change in changes: |
| 478 aggregate_change_info.files += ChangeInfo.Load(change, fail_on_not_found, | 488 aggregate_change_info._files += ChangeInfo.Load(change, fail_on_not_found, |
| 479 update_status).files | 489 update_status).GetFiles() |
| 480 return aggregate_change_info | 490 return aggregate_change_info |
| 481 | 491 |
| 482 | 492 |
| 483 def GetCLs(): | 493 def GetCLs(): |
| 484 """Returns a list of all the changelists in this repository.""" | 494 """Returns a list of all the changelists in this repository.""" |
| 485 cls = os.listdir(GetChangesDir()) | 495 cls = os.listdir(GetChangesDir()) |
| 486 if CODEREVIEW_SETTINGS_FILE in cls: | 496 if CODEREVIEW_SETTINGS_FILE in cls: |
| 487 cls.remove(CODEREVIEW_SETTINGS_FILE) | 497 cls.remove(CODEREVIEW_SETTINGS_FILE) |
| 488 return cls | 498 return cls |
| 489 | 499 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 512 files = {} | 522 files = {} |
| 513 | 523 |
| 514 # Since the files are normalized to the root folder of the repositary, figure | 524 # Since the files are normalized to the root folder of the repositary, figure |
| 515 # out what we need to add to the paths. | 525 # out what we need to add to the paths. |
| 516 dir_prefix = os.getcwd()[len(GetRepositoryRoot()):].strip(os.sep) | 526 dir_prefix = os.getcwd()[len(GetRepositoryRoot()):].strip(os.sep) |
| 517 | 527 |
| 518 # Get a list of all files in changelists. | 528 # Get a list of all files in changelists. |
| 519 files_in_cl = {} | 529 files_in_cl = {} |
| 520 for cl in GetCLs(): | 530 for cl in GetCLs(): |
| 521 change_info = ChangeInfo.Load(cl) | 531 change_info = ChangeInfo.Load(cl) |
| 522 for status, filename in change_info.files: | 532 for status, filename in change_info.GetFiles(): |
| 523 files_in_cl[filename] = change_info.name | 533 files_in_cl[filename] = change_info.name |
| 524 | 534 |
| 525 # Get all the modified files. | 535 # Get all the modified files. |
| 526 status_result = gclient.CaptureSVNStatus(None) | 536 status_result = gclient.CaptureSVNStatus(None) |
| 527 for line in status_result: | 537 for line in status_result: |
| 528 status = line[0] | 538 status = line[0] |
| 529 filename = line[1] | 539 filename = line[1] |
| 530 if status[0] == "?": | 540 if status[0] == "?": |
| 531 continue | 541 continue |
| 532 if dir_prefix: | 542 if dir_prefix: |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 580 | 590 |
| 581 | 591 |
| 582 def Opened(): | 592 def Opened(): |
| 583 """Prints a list of modified files in the current directory down.""" | 593 """Prints a list of modified files in the current directory down.""" |
| 584 files = GetModifiedFiles() | 594 files = GetModifiedFiles() |
| 585 cl_keys = files.keys() | 595 cl_keys = files.keys() |
| 586 cl_keys.sort() | 596 cl_keys.sort() |
| 587 for cl_name in cl_keys: | 597 for cl_name in cl_keys: |
| 588 if cl_name: | 598 if cl_name: |
| 589 note = "" | 599 note = "" |
| 590 if len(ChangeInfo.Load(cl_name).files) != len(files[cl_name]): | 600 if len(ChangeInfo.Load(cl_name).GetFiles()) != len(files[cl_name]): |
| 591 note = " (Note: this changelist contains files outside this directory)" | 601 note = " (Note: this changelist contains files outside this directory)" |
| 592 print "\n--- Changelist " + cl_name + note + ":" | 602 print "\n--- Changelist " + cl_name + note + ":" |
| 593 for file in files[cl_name]: | 603 for file in files[cl_name]: |
| 594 print "".join(file) | 604 print "".join(file) |
| 595 | 605 |
| 596 | 606 |
| 597 def Help(argv=None): | 607 def Help(argv=None): |
| 598 if argv: | 608 if argv: |
| 599 if argv[0] == 'try': | 609 if argv[0] == 'try': |
| 600 TryChange(None, ['--help'], swallow_exception=False) | 610 TryChange(None, ['--help'], swallow_exception=False) |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 726 | 736 |
| 727 | 737 |
| 728 | 738 |
| 729 def OptionallyDoPresubmitChecks(change_info, committing, args): | 739 def OptionallyDoPresubmitChecks(change_info, committing, args): |
| 730 if FilterFlag(args, "--no_presubmit") or FilterFlag(args, "--force"): | 740 if FilterFlag(args, "--no_presubmit") or FilterFlag(args, "--force"): |
| 731 return True | 741 return True |
| 732 return DoPresubmitChecks(change_info, committing, True) | 742 return DoPresubmitChecks(change_info, committing, True) |
| 733 | 743 |
| 734 | 744 |
| 735 def UploadCL(change_info, args): | 745 def UploadCL(change_info, args): |
| 736 if not change_info.FileList(): | 746 if not change_info.GetFiles(): |
| 737 print "Nothing to upload, changelist is empty." | 747 print "Nothing to upload, changelist is empty." |
| 738 return | 748 return |
| 739 if not OptionallyDoPresubmitChecks(change_info, False, args): | 749 if not OptionallyDoPresubmitChecks(change_info, False, args): |
| 740 return | 750 return |
| 741 no_try = FilterFlag(args, "--no_try") or FilterFlag(args, "--no-try") | 751 no_try = FilterFlag(args, "--no_try") or FilterFlag(args, "--no-try") |
| 742 no_watchlists = FilterFlag(args, "--no_watchlists") or \ | 752 no_watchlists = FilterFlag(args, "--no_watchlists") or \ |
| 743 FilterFlag(args, "--no-watchlists") | 753 FilterFlag(args, "--no-watchlists") |
| 744 | 754 |
| 745 # Map --send-mail to --send_mail | 755 # Map --send-mail to --send_mail |
| 746 if FilterFlag(args, "--send-mail"): | 756 if FilterFlag(args, "--send-mail"): |
| (...skipping 28 matching lines...) Expand all Loading... |
| 775 upload_arg.append("--issue=%d" % change_info.issue) | 785 upload_arg.append("--issue=%d" % change_info.issue) |
| 776 else: # First time we upload. | 786 else: # First time we upload. |
| 777 handle, desc_file = tempfile.mkstemp(text=True) | 787 handle, desc_file = tempfile.mkstemp(text=True) |
| 778 os.write(handle, change_info.description) | 788 os.write(handle, change_info.description) |
| 779 os.close(handle) | 789 os.close(handle) |
| 780 | 790 |
| 781 # Watchlist processing -- CC people interested in this changeset | 791 # Watchlist processing -- CC people interested in this changeset |
| 782 # http://dev.chromium.org/developers/contributing-code/watchlists | 792 # http://dev.chromium.org/developers/contributing-code/watchlists |
| 783 if not no_watchlists: | 793 if not no_watchlists: |
| 784 import watchlists | 794 import watchlists |
| 785 watchlist = watchlists.Watchlists(GetRepositoryRoot()) | 795 watchlist = watchlists.Watchlists(change_info.GetLocalRoot()) |
| 786 watchers = watchlist.GetWatchersForPaths(change_info.FileList()) | 796 watchers = watchlist.GetWatchersForPaths(change_info.FileList()) |
| 787 | 797 |
| 788 cc_list = GetCodeReviewSetting("CC_LIST") | 798 cc_list = GetCodeReviewSetting("CC_LIST") |
| 789 if not no_watchlists and watchers: | 799 if not no_watchlists and watchers: |
| 790 # Filter out all empty elements and join by ',' | 800 # Filter out all empty elements and join by ',' |
| 791 cc_list = ','.join(filter(None, [cc_list] + watchers)) | 801 cc_list = ','.join(filter(None, [cc_list] + watchers)) |
| 792 if cc_list: | 802 if cc_list: |
| 793 upload_arg.append("--cc=" + cc_list) | 803 upload_arg.append("--cc=" + cc_list) |
| 794 upload_arg.append("--description_file=" + desc_file + "") | 804 upload_arg.append("--description_file=" + desc_file + "") |
| 795 if change_info.description: | 805 if change_info.description: |
| 796 subject = change_info.description[:77] | 806 subject = change_info.description[:77] |
| 797 if subject.find("\r\n") != -1: | 807 if subject.find("\r\n") != -1: |
| 798 subject = subject[:subject.find("\r\n")] | 808 subject = subject[:subject.find("\r\n")] |
| 799 if subject.find("\n") != -1: | 809 if subject.find("\n") != -1: |
| 800 subject = subject[:subject.find("\n")] | 810 subject = subject[:subject.find("\n")] |
| 801 if len(change_info.description) > 77: | 811 if len(change_info.description) > 77: |
| 802 subject = subject + "..." | 812 subject = subject + "..." |
| 803 upload_arg.append("--message=" + subject) | 813 upload_arg.append("--message=" + subject) |
| 804 | 814 |
| 805 # Change the current working directory before calling upload.py so that it | 815 # Change the current working directory before calling upload.py so that it |
| 806 # shows the correct base. | 816 # shows the correct base. |
| 807 previous_cwd = os.getcwd() | 817 previous_cwd = os.getcwd() |
| 808 os.chdir(GetRepositoryRoot()) | 818 os.chdir(change_info.GetLocalRoot()) |
| 809 | 819 |
| 810 # If we have a lot of files with long paths, then we won't be able to fit | 820 # If we have a lot of files with long paths, then we won't be able to fit |
| 811 # the command to "svn diff". Instead, we generate the diff manually for | 821 # the command to "svn diff". Instead, we generate the diff manually for |
| 812 # each file and concatenate them before passing it to upload.py. | 822 # each file and concatenate them before passing it to upload.py. |
| 813 if change_info.patch is None: | 823 if change_info.patch is None: |
| 814 change_info.patch = GenerateDiff(change_info.FileList()) | 824 change_info.patch = GenerateDiff(change_info.GetFileNames()) |
| 815 issue, patchset = upload.RealMain(upload_arg, change_info.patch) | 825 issue, patchset = upload.RealMain(upload_arg, change_info.patch) |
| 816 if issue and patchset: | 826 if issue and patchset: |
| 817 change_info.issue = int(issue) | 827 change_info.issue = int(issue) |
| 818 change_info.patchset = int(patchset) | 828 change_info.patchset = int(patchset) |
| 819 change_info.Save() | 829 change_info.Save() |
| 820 | 830 |
| 821 if desc_file: | 831 if desc_file: |
| 822 os.remove(desc_file) | 832 os.remove(desc_file) |
| 823 | 833 |
| 824 # Do background work on Rietveld to lint the file so that the results are | 834 # Do background work on Rietveld to lint the file so that the results are |
| 825 # ready when the issue is viewed. | 835 # ready when the issue is viewed. |
| 826 SendToRietveld("/lint/issue%s_%s" % (issue, patchset), timeout=0.5) | 836 SendToRietveld("/lint/issue%s_%s" % (issue, patchset), timeout=0.5) |
| 827 | 837 |
| 828 # Once uploaded to Rietveld, send it to the try server. | 838 # Once uploaded to Rietveld, send it to the try server. |
| 829 if not no_try: | 839 if not no_try: |
| 830 try_on_upload = GetCodeReviewSetting('TRY_ON_UPLOAD') | 840 try_on_upload = GetCodeReviewSetting('TRY_ON_UPLOAD') |
| 831 if try_on_upload and try_on_upload.lower() == 'true': | 841 if try_on_upload and try_on_upload.lower() == 'true': |
| 832 trychange_args = [] | 842 trychange_args = [] |
| 833 if clobber: | 843 if clobber: |
| 834 trychange_args.append('--clobber') | 844 trychange_args.append('--clobber') |
| 835 TryChange(change_info, trychange_args, swallow_exception=True) | 845 TryChange(change_info, trychange_args, swallow_exception=True) |
| 836 | 846 |
| 837 os.chdir(previous_cwd) | 847 os.chdir(previous_cwd) |
| 838 | 848 |
| 839 | 849 |
| 840 def PresubmitCL(change_info): | 850 def PresubmitCL(change_info): |
| 841 """Reports what presubmit checks on the change would report.""" | 851 """Reports what presubmit checks on the change would report.""" |
| 842 if not change_info.FileList(): | 852 if not change_info.GetFiles(): |
| 843 print "Nothing to presubmit check, changelist is empty." | 853 print "Nothing to presubmit check, changelist is empty." |
| 844 return | 854 return |
| 845 | 855 |
| 846 print "*** Presubmit checks for UPLOAD would report: ***" | 856 print "*** Presubmit checks for UPLOAD would report: ***" |
| 847 DoPresubmitChecks(change_info, False, False) | 857 DoPresubmitChecks(change_info, False, False) |
| 848 | 858 |
| 849 print "\n*** Presubmit checks for COMMIT would report: ***" | 859 print "\n*** Presubmit checks for COMMIT would report: ***" |
| 850 DoPresubmitChecks(change_info, True, False) | 860 DoPresubmitChecks(change_info, True, False) |
| 851 | 861 |
| 852 | 862 |
| 853 def TryChange(change_info, args, swallow_exception): | 863 def TryChange(change_info, args, swallow_exception): |
| 854 """Create a diff file of change_info and send it to the try server.""" | 864 """Create a diff file of change_info and send it to the try server.""" |
| 855 try: | 865 try: |
| 856 import trychange | 866 import trychange |
| 857 except ImportError: | 867 except ImportError: |
| 858 if swallow_exception: | 868 if swallow_exception: |
| 859 return | 869 return |
| 860 ErrorExit("You need to install trychange.py to use the try server.") | 870 ErrorExit("You need to install trychange.py to use the try server.") |
| 861 | 871 |
| 862 if change_info: | 872 if change_info: |
| 863 trychange_args = ['--name', change_info.name] | 873 trychange_args = ['--name', change_info.name] |
| 864 if change_info.issue: | 874 if change_info.issue: |
| 865 trychange_args.extend(["--issue", str(change_info.issue)]) | 875 trychange_args.extend(["--issue", str(change_info.issue)]) |
| 866 if change_info.patchset: | 876 if change_info.patchset: |
| 867 trychange_args.extend(["--patchset", str(change_info.patchset)]) | 877 trychange_args.extend(["--patchset", str(change_info.patchset)]) |
| 868 trychange_args.extend(args) | 878 trychange_args.extend(args) |
| 869 trychange.TryChange(trychange_args, | 879 trychange.TryChange(trychange_args, |
| 870 file_list=change_info.FileList(), | 880 file_list=change_info.GetFileNames(), |
| 871 swallow_exception=swallow_exception, | 881 swallow_exception=swallow_exception, |
| 872 prog='gcl try') | 882 prog='gcl try') |
| 873 else: | 883 else: |
| 874 trychange.TryChange(args, | 884 trychange.TryChange(args, |
| 875 file_list=None, | 885 file_list=None, |
| 876 swallow_exception=swallow_exception, | 886 swallow_exception=swallow_exception, |
| 877 prog='gcl try') | 887 prog='gcl try') |
| 878 | 888 |
| 879 | 889 |
| 880 def Commit(change_info, args): | 890 def Commit(change_info, args): |
| 881 if not change_info.FileList(): | 891 if not change_info.GetFiles(): |
| 882 print "Nothing to commit, changelist is empty." | 892 print "Nothing to commit, changelist is empty." |
| 883 return | 893 return |
| 884 if not OptionallyDoPresubmitChecks(change_info, True, args): | 894 if not OptionallyDoPresubmitChecks(change_info, True, args): |
| 885 return | 895 return |
| 886 | 896 |
| 887 # We face a problem with svn here: Let's say change 'bleh' modifies | 897 # We face a problem with svn here: Let's say change 'bleh' modifies |
| 888 # svn:ignore on dir1\. but another unrelated change 'pouet' modifies | 898 # svn:ignore on dir1\. but another unrelated change 'pouet' modifies |
| 889 # dir1\foo.cc. When the user `gcl commit bleh`, foo.cc is *also committed*. | 899 # dir1\foo.cc. When the user `gcl commit bleh`, foo.cc is *also committed*. |
| 890 # The only fix is to use --non-recursive but that has its issues too: | 900 # The only fix is to use --non-recursive but that has its issues too: |
| 891 # Let's say if dir1 is deleted, --non-recursive must *not* be used otherwise | 901 # Let's say if dir1 is deleted, --non-recursive must *not* be used otherwise |
| 892 # you'll get "svn: Cannot non-recursively commit a directory deletion of a | 902 # you'll get "svn: Cannot non-recursively commit a directory deletion of a |
| 893 # directory with child nodes". Yay... | 903 # directory with child nodes". Yay... |
| 894 commit_cmd = ["svn", "commit"] | 904 commit_cmd = ["svn", "commit"] |
| 895 filename = '' | 905 filename = '' |
| 896 if change_info.issue: | 906 if change_info.issue: |
| 897 # Get the latest description from Rietveld. | 907 # Get the latest description from Rietveld. |
| 898 change_info.description = GetIssueDescription(change_info.issue) | 908 change_info.description = GetIssueDescription(change_info.issue) |
| 899 | 909 |
| 900 commit_message = change_info.description.replace('\r\n', '\n') | 910 commit_message = change_info.description.replace('\r\n', '\n') |
| 901 if change_info.issue: | 911 if change_info.issue: |
| 902 commit_message += ('\nReview URL: http://%s/%d' % | 912 commit_message += ('\nReview URL: http://%s/%d' % |
| 903 (GetCodeReviewSetting("CODE_REVIEW_SERVER"), | 913 (GetCodeReviewSetting("CODE_REVIEW_SERVER"), |
| 904 change_info.issue)) | 914 change_info.issue)) |
| 905 | 915 |
| 906 handle, commit_filename = tempfile.mkstemp(text=True) | 916 handle, commit_filename = tempfile.mkstemp(text=True) |
| 907 os.write(handle, commit_message) | 917 os.write(handle, commit_message) |
| 908 os.close(handle) | 918 os.close(handle) |
| 909 | 919 |
| 910 handle, targets_filename = tempfile.mkstemp(text=True) | 920 handle, targets_filename = tempfile.mkstemp(text=True) |
| 911 os.write(handle, "\n".join(change_info.FileList())) | 921 os.write(handle, "\n".join(change_info.GetFileNames())) |
| 912 os.close(handle) | 922 os.close(handle) |
| 913 | 923 |
| 914 commit_cmd += ['--file=' + commit_filename] | 924 commit_cmd += ['--file=' + commit_filename] |
| 915 commit_cmd += ['--targets=' + targets_filename] | 925 commit_cmd += ['--targets=' + targets_filename] |
| 916 # Change the current working directory before calling commit. | 926 # Change the current working directory before calling commit. |
| 917 previous_cwd = os.getcwd() | 927 previous_cwd = os.getcwd() |
| 918 os.chdir(GetRepositoryRoot()) | 928 os.chdir(change_info.GetLocalRoot()) |
| 919 output = RunShell(commit_cmd, True) | 929 output = RunShell(commit_cmd, True) |
| 920 os.remove(commit_filename) | 930 os.remove(commit_filename) |
| 921 os.remove(targets_filename) | 931 os.remove(targets_filename) |
| 922 if output.find("Committed revision") != -1: | 932 if output.find("Committed revision") != -1: |
| 923 change_info.Delete() | 933 change_info.Delete() |
| 924 | 934 |
| 925 if change_info.issue: | 935 if change_info.issue: |
| 926 revision = re.compile(".*?\nCommitted revision (\d+)", | 936 revision = re.compile(".*?\nCommitted revision (\d+)", |
| 927 re.DOTALL).match(output).group(1) | 937 re.DOTALL).match(output).group(1) |
| 928 viewvc_url = GetCodeReviewSetting("VIEW_VC") | 938 viewvc_url = GetCodeReviewSetting("VIEW_VC") |
| (...skipping 25 matching lines...) Expand all Loading... |
| 954 | 964 |
| 955 other_files = GetFilesNotInCL() | 965 other_files = GetFilesNotInCL() |
| 956 | 966 |
| 957 #Edited files will have a letter for the first character in a string. | 967 #Edited files will have a letter for the first character in a string. |
| 958 #This regex looks for the presence of that character. | 968 #This regex looks for the presence of that character. |
| 959 file_re = re.compile(r"^[a-z].+\Z", re.IGNORECASE) | 969 file_re = re.compile(r"^[a-z].+\Z", re.IGNORECASE) |
| 960 affected_files = filter(lambda x: file_re.match(x[0]), other_files) | 970 affected_files = filter(lambda x: file_re.match(x[0]), other_files) |
| 961 unaffected_files = filter(lambda x: not file_re.match(x[0]), other_files) | 971 unaffected_files = filter(lambda x: not file_re.match(x[0]), other_files) |
| 962 | 972 |
| 963 separator1 = ("\n---All lines above this line become the description.\n" | 973 separator1 = ("\n---All lines above this line become the description.\n" |
| 964 "---Repository Root: " + GetRepositoryRoot() + "\n" | 974 "---Repository Root: " + change_info.GetLocalRoot() + "\n" |
| 965 "---Paths in this changelist (" + change_info.name + "):\n") | 975 "---Paths in this changelist (" + change_info.name + "):\n") |
| 966 separator2 = "\n\n---Paths modified but not in any changelist:\n\n" | 976 separator2 = "\n\n---Paths modified but not in any changelist:\n\n" |
| 967 text = (description + separator1 + '\n' + | 977 text = (description + separator1 + '\n' + |
| 968 '\n'.join([f[0] + f[1] for f in change_info.files]) + separator2 + | 978 '\n'.join([f[0] + f[1] for f in change_info.GetFiles()]) + |
| 979 separator2 + |
| 969 '\n'.join([f[0] + f[1] for f in affected_files]) + '\n' + | 980 '\n'.join([f[0] + f[1] for f in affected_files]) + '\n' + |
| 970 '\n'.join([f[0] + f[1] for f in unaffected_files]) + '\n') | 981 '\n'.join([f[0] + f[1] for f in unaffected_files]) + '\n') |
| 971 | 982 |
| 972 handle, filename = tempfile.mkstemp(text=True) | 983 handle, filename = tempfile.mkstemp(text=True) |
| 973 os.write(handle, text) | 984 os.write(handle, text) |
| 974 os.close(handle) | 985 os.close(handle) |
| 975 | 986 |
| 976 os.system(GetEditor() + " " + filename) | 987 os.system(GetEditor() + " " + filename) |
| 977 | 988 |
| 978 result = ReadFile(filename) | 989 result = ReadFile(filename) |
| (...skipping 16 matching lines...) Expand all Loading... |
| 995 | 1006 |
| 996 new_cl_files = [] | 1007 new_cl_files = [] |
| 997 for line in cl_files_text.splitlines(): | 1008 for line in cl_files_text.splitlines(): |
| 998 if not len(line): | 1009 if not len(line): |
| 999 continue | 1010 continue |
| 1000 if line.startswith("---"): | 1011 if line.startswith("---"): |
| 1001 break | 1012 break |
| 1002 status = line[:7] | 1013 status = line[:7] |
| 1003 file = line[7:] | 1014 file = line[7:] |
| 1004 new_cl_files.append((status, file)) | 1015 new_cl_files.append((status, file)) |
| 1005 change_info.files = new_cl_files | 1016 change_info._files = new_cl_files |
| 1006 | 1017 |
| 1007 change_info.Save() | 1018 change_info.Save() |
| 1008 print change_info.name + " changelist saved." | 1019 print change_info.name + " changelist saved." |
| 1009 if change_info.MissingTests(): | 1020 if change_info.MissingTests(): |
| 1010 Warn("WARNING: " + MISSING_TEST_MSG) | 1021 Warn("WARNING: " + MISSING_TEST_MSG) |
| 1011 | 1022 |
| 1012 # We don't lint files in these path prefixes. | 1023 # We don't lint files in these path prefixes. |
| 1013 IGNORE_PATHS = ("webkit",) | 1024 IGNORE_PATHS = ("webkit",) |
| 1014 | 1025 |
| 1015 # Valid extensions for files we want to lint. | 1026 # Valid extensions for files we want to lint. |
| 1016 CPP_EXTENSIONS = ("cpp", "cc", "h") | 1027 CPP_EXTENSIONS = ("cpp", "cc", "h") |
| 1017 | 1028 |
| 1018 def Lint(change_info, args): | 1029 def Lint(change_info, args): |
| 1019 """Runs cpplint.py on all the files in |change_info|""" | 1030 """Runs cpplint.py on all the files in |change_info|""" |
| 1020 try: | 1031 try: |
| 1021 import cpplint | 1032 import cpplint |
| 1022 except ImportError: | 1033 except ImportError: |
| 1023 ErrorExit("You need to install cpplint.py to lint C++ files.") | 1034 ErrorExit("You need to install cpplint.py to lint C++ files.") |
| 1024 | 1035 |
| 1025 # Change the current working directory before calling lint so that it | 1036 # Change the current working directory before calling lint so that it |
| 1026 # shows the correct base. | 1037 # shows the correct base. |
| 1027 previous_cwd = os.getcwd() | 1038 previous_cwd = os.getcwd() |
| 1028 os.chdir(GetRepositoryRoot()) | 1039 os.chdir(change_info.GetLocalRoot()) |
| 1029 | 1040 |
| 1030 # Process cpplints arguments if any. | 1041 # Process cpplints arguments if any. |
| 1031 filenames = cpplint.ParseArguments(args + change_info.FileList()) | 1042 filenames = cpplint.ParseArguments(args + change_info.GetFileNames()) |
| 1032 | 1043 |
| 1033 for file in filenames: | 1044 for file in filenames: |
| 1034 if len([file for suffix in CPP_EXTENSIONS if file.endswith(suffix)]): | 1045 if len([file for suffix in CPP_EXTENSIONS if file.endswith(suffix)]): |
| 1035 if len([file for prefix in IGNORE_PATHS if file.startswith(prefix)]): | 1046 if len([file for prefix in IGNORE_PATHS if file.startswith(prefix)]): |
| 1036 print "Ignoring non-Google styled file %s" % file | 1047 print "Ignoring non-Google styled file %s" % file |
| 1037 else: | 1048 else: |
| 1038 cpplint.ProcessFile(file, cpplint._cpplint_state.verbose_level) | 1049 cpplint.ProcessFile(file, cpplint._cpplint_state.verbose_level) |
| 1039 | 1050 |
| 1040 print "Total errors found: %d\n" % cpplint._cpplint_state.error_count | 1051 print "Total errors found: %d\n" % cpplint._cpplint_state.error_count |
| 1041 os.chdir(previous_cwd) | 1052 os.chdir(previous_cwd) |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1056 if not result and may_prompt: | 1067 if not result and may_prompt: |
| 1057 print "\nPresubmit errors, can't continue (use --no_presubmit to bypass)" | 1068 print "\nPresubmit errors, can't continue (use --no_presubmit to bypass)" |
| 1058 return result | 1069 return result |
| 1059 | 1070 |
| 1060 | 1071 |
| 1061 def Changes(): | 1072 def Changes(): |
| 1062 """Print all the changelists and their files.""" | 1073 """Print all the changelists and their files.""" |
| 1063 for cl in GetCLs(): | 1074 for cl in GetCLs(): |
| 1064 change_info = ChangeInfo.Load(cl, True, True) | 1075 change_info = ChangeInfo.Load(cl, True, True) |
| 1065 print "\n--- Changelist " + change_info.name + ":" | 1076 print "\n--- Changelist " + change_info.name + ":" |
| 1066 for file in change_info.files: | 1077 for file in change_info.GetFiles(): |
| 1067 print "".join(file) | 1078 print "".join(file) |
| 1068 | 1079 |
| 1069 | 1080 |
| 1070 def main(argv=None): | 1081 def main(argv=None): |
| 1071 if argv is None: | 1082 if argv is None: |
| 1072 argv = sys.argv | 1083 argv = sys.argv |
| 1073 | 1084 |
| 1074 if len(argv) == 1: | 1085 if len(argv) == 1: |
| 1075 Help() | 1086 Help() |
| 1076 return 0; | 1087 return 0; |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1152 UploadCL(change_info, argv[3:]) | 1163 UploadCL(change_info, argv[3:]) |
| 1153 elif command == "presubmit": | 1164 elif command == "presubmit": |
| 1154 PresubmitCL(change_info) | 1165 PresubmitCL(change_info) |
| 1155 elif command in ("commit", "submit"): | 1166 elif command in ("commit", "submit"): |
| 1156 Commit(change_info, argv[3:]) | 1167 Commit(change_info, argv[3:]) |
| 1157 elif command == "delete": | 1168 elif command == "delete": |
| 1158 change_info.Delete() | 1169 change_info.Delete() |
| 1159 elif command == "try": | 1170 elif command == "try": |
| 1160 # When the change contains no file, send the "changename" positional | 1171 # When the change contains no file, send the "changename" positional |
| 1161 # argument to trychange.py. | 1172 # argument to trychange.py. |
| 1162 if change_info.files: | 1173 if change_info.GetFiles(): |
| 1163 args = argv[3:] | 1174 args = argv[3:] |
| 1164 else: | 1175 else: |
| 1165 change_info = None | 1176 change_info = None |
| 1166 args = argv[2:] | 1177 args = argv[2:] |
| 1167 TryChange(change_info, args, swallow_exception=False) | 1178 TryChange(change_info, args, swallow_exception=False) |
| 1168 else: | 1179 else: |
| 1169 # Everything else that is passed into gcl we redirect to svn, after adding | 1180 # Everything else that is passed into gcl we redirect to svn, after adding |
| 1170 # the files. This allows commands such as 'gcl diff xxx' to work. | 1181 # the files. This allows commands such as 'gcl diff xxx' to work. |
| 1171 args =["svn", command] | 1182 args =["svn", command] |
| 1172 root = GetRepositoryRoot() | 1183 root = GetRepositoryRoot() |
| 1173 args.extend([os.path.join(root, x) for x in change_info.FileList()]) | 1184 args.extend([os.path.join(root, x) for x in change_info.GetFileNames()]) |
| 1174 RunShell(args, True) | 1185 RunShell(args, True) |
| 1175 return 0 | 1186 return 0 |
| 1176 | 1187 |
| 1177 | 1188 |
| 1178 if __name__ == "__main__": | 1189 if __name__ == "__main__": |
| 1179 sys.exit(main()) | 1190 sys.exit(main()) |
| OLD | NEW |