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 |