OLD | NEW |
1 # Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2010 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 """Gclient-specific SCM-specific operations.""" | 5 """Gclient-specific SCM-specific operations.""" |
6 | 6 |
7 import logging | 7 import logging |
8 import os | 8 import os |
9 import posixpath | 9 import posixpath |
10 import re | 10 import re |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
147 """Generates a patch file which can be applied to the root of the | 147 """Generates a patch file which can be applied to the root of the |
148 repository. | 148 repository. |
149 | 149 |
150 The patch file is generated from a diff of the merge base of HEAD and | 150 The patch file is generated from a diff of the merge base of HEAD and |
151 its upstream branch. | 151 its upstream branch. |
152 """ | 152 """ |
153 path = os.path.join(self._root_dir, self.relpath) | 153 path = os.path.join(self._root_dir, self.relpath) |
154 merge_base = self._Run(['merge-base', 'HEAD', 'origin']) | 154 merge_base = self._Run(['merge-base', 'HEAD', 'origin']) |
155 command = ['diff', merge_base] | 155 command = ['diff', merge_base] |
156 filterer = DiffFilterer(self.relpath) | 156 filterer = DiffFilterer(self.relpath) |
157 scm.GIT.RunAndFilterOutput(command, path, False, False, filterer.Filter, | 157 scm.GIT.RunAndFilterOutput(command, cwd=path, filter_fn=filterer.Filter, |
158 stdout=options.stdout) | 158 stdout=options.stdout) |
159 | 159 |
160 def update(self, options, args, file_list): | 160 def update(self, options, args, file_list): |
161 """Runs git to update or transparently checkout the working copy. | 161 """Runs git to update or transparently checkout the working copy. |
162 | 162 |
163 All updated files will be appended to file_list. | 163 All updated files will be appended to file_list. |
164 | 164 |
165 Raises: | 165 Raises: |
166 Error: if can't get URL for relative path. | 166 Error: if can't get URL for relative path. |
167 """ | 167 """ |
(...skipping 469 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
637 def _GetCurrentBranch(self): | 637 def _GetCurrentBranch(self): |
638 # Returns name of current branch or None for detached HEAD | 638 # Returns name of current branch or None for detached HEAD |
639 branch = self._Run(['rev-parse', '--abbrev-ref=strict', 'HEAD']) | 639 branch = self._Run(['rev-parse', '--abbrev-ref=strict', 'HEAD']) |
640 if branch == 'HEAD': | 640 if branch == 'HEAD': |
641 return None | 641 return None |
642 return branch | 642 return branch |
643 | 643 |
644 def _Run(self, args, cwd=None, redirect_stdout=True): | 644 def _Run(self, args, cwd=None, redirect_stdout=True): |
645 # TODO(maruel): Merge with Capture or better gclient_utils.CheckCall(). | 645 # TODO(maruel): Merge with Capture or better gclient_utils.CheckCall(). |
646 if cwd is None: | 646 if cwd is None: |
647 cwd = self.checkout_path | 647 cwd = self.checkout_path |
648 stdout = None | 648 stdout = None |
649 if redirect_stdout: | 649 if redirect_stdout: |
650 stdout = subprocess.PIPE | 650 stdout = subprocess.PIPE |
651 if cwd == None: | 651 if cwd == None: |
652 cwd = self.checkout_path | 652 cwd = self.checkout_path |
653 cmd = [scm.GIT.COMMAND] | 653 cmd = [scm.GIT.COMMAND] |
654 cmd.extend(args) | 654 cmd.extend(args) |
655 logging.debug(cmd) | 655 logging.debug(cmd) |
656 try: | 656 try: |
657 sp = gclient_utils.Popen(cmd, cwd=cwd, stdout=stdout) | 657 sp = gclient_utils.Popen(cmd, cwd=cwd, stdout=stdout) |
658 output = sp.communicate()[0] | 658 output = sp.communicate()[0] |
659 except OSError: | 659 except OSError: |
660 raise gclient_utils.Error("git command '%s' failed to run." % | 660 raise gclient_utils.Error("git command '%s' failed to run." % |
661 ' '.join(cmd) + "\nCheck that you have git installed.") | 661 ' '.join(cmd) + "\nCheck that you have git installed.") |
662 if sp.returncode: | 662 if sp.returncode: |
663 raise gclient_utils.Error('git command %s returned %d' % | 663 raise gclient_utils.Error('git command %s returned %d' % |
664 (args[0], sp.returncode)) | 664 (args[0], sp.returncode)) |
665 if output is not None: | 665 if output is not None: |
666 return output.strip() | 666 return output.strip() |
667 | 667 |
668 | 668 |
669 class SVNWrapper(SCMWrapper): | 669 class SVNWrapper(SCMWrapper): |
670 """ Wrapper for SVN """ | 670 """ Wrapper for SVN """ |
671 | 671 |
672 def cleanup(self, options, args, file_list): | 672 def cleanup(self, options, args, file_list): |
673 """Cleanup working copy.""" | 673 """Cleanup working copy.""" |
674 command = ['cleanup'] | 674 scm.SVN.Run(['cleanup'] + args, |
675 command.extend(args) | 675 cwd=os.path.join(self._root_dir, self.relpath)) |
676 scm.SVN.Run(command, os.path.join(self._root_dir, self.relpath)) | |
677 | 676 |
678 def diff(self, options, args, file_list): | 677 def diff(self, options, args, file_list): |
679 # NOTE: This function does not currently modify file_list. | 678 # NOTE: This function does not currently modify file_list. |
680 path = os.path.join(self._root_dir, self.relpath) | 679 path = os.path.join(self._root_dir, self.relpath) |
681 if not os.path.isdir(path): | 680 if not os.path.isdir(path): |
682 raise gclient_utils.Error('Directory %s is not present.' % path) | 681 raise gclient_utils.Error('Directory %s is not present.' % path) |
683 command = ['diff'] | 682 scm.SVN.Run(['diff'] + args, cwd=path) |
684 command.extend(args) | |
685 scm.SVN.Run(command, path) | |
686 | 683 |
687 def export(self, options, args, file_list): | 684 def export(self, options, args, file_list): |
688 """Export a clean directory tree into the given path.""" | 685 """Export a clean directory tree into the given path.""" |
689 assert len(args) == 1 | 686 assert len(args) == 1 |
690 export_path = os.path.abspath(os.path.join(args[0], self.relpath)) | 687 export_path = os.path.abspath(os.path.join(args[0], self.relpath)) |
691 try: | 688 try: |
692 os.makedirs(export_path) | 689 os.makedirs(export_path) |
693 except OSError: | 690 except OSError: |
694 pass | 691 pass |
695 assert os.path.exists(export_path) | 692 assert os.path.exists(export_path) |
696 command = ['export', '--force', '.'] | 693 scm.SVN.Run(['export', '--force', '.', export_path], |
697 command.append(export_path) | 694 cwd=os.path.join(self._root_dir, self.relpath)) |
698 scm.SVN.Run(command, os.path.join(self._root_dir, self.relpath)) | |
699 | 695 |
700 def pack(self, options, args, file_list): | 696 def pack(self, options, args, file_list): |
701 """Generates a patch file which can be applied to the root of the | 697 """Generates a patch file which can be applied to the root of the |
702 repository.""" | 698 repository.""" |
703 path = os.path.join(self._root_dir, self.relpath) | 699 path = os.path.join(self._root_dir, self.relpath) |
704 if not os.path.isdir(path): | 700 if not os.path.isdir(path): |
705 raise gclient_utils.Error('Directory %s is not present.' % path) | 701 raise gclient_utils.Error('Directory %s is not present.' % path) |
706 command = ['diff', '-x', '--ignore-eol-style'] | 702 command = ['diff', '-x', '--ignore-eol-style'] |
707 command.extend(args) | 703 command.extend(args) |
708 | 704 |
709 filterer = DiffFilterer(self.relpath) | 705 filterer = DiffFilterer(self.relpath) |
710 scm.SVN.RunAndFilterOutput(command, path, False, False, filterer.Filter, | 706 scm.SVN.RunAndFilterOutput(command, cwd=path, print_messages=False, |
| 707 print_stdout=False, filter_fn=filterer.Filter, |
711 stdout=options.stdout) | 708 stdout=options.stdout) |
712 | 709 |
713 def update(self, options, args, file_list): | 710 def update(self, options, args, file_list): |
714 """Runs svn to update or transparently checkout the working copy. | 711 """Runs svn to update or transparently checkout the working copy. |
715 | 712 |
716 All updated files will be appended to file_list. | 713 All updated files will be appended to file_list. |
717 | 714 |
718 Raises: | 715 Raises: |
719 Error: if can't get URL for relative path. | 716 Error: if can't get URL for relative path. |
720 """ | 717 """ |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
758 if not from_info: | 755 if not from_info: |
759 raise gclient_utils.Error(('Can\'t update/checkout %r if an unversioned ' | 756 raise gclient_utils.Error(('Can\'t update/checkout %r if an unversioned ' |
760 'directory is present. Delete the directory ' | 757 'directory is present. Delete the directory ' |
761 'and try again.') % | 758 'and try again.') % |
762 checkout_path) | 759 checkout_path) |
763 | 760 |
764 # Look for locked directories. | 761 # Look for locked directories. |
765 dir_info = scm.SVN.CaptureStatus(os.path.join(checkout_path, '.')) | 762 dir_info = scm.SVN.CaptureStatus(os.path.join(checkout_path, '.')) |
766 if [True for d in dir_info if d[0][2] == 'L' and d[1] == checkout_path]: | 763 if [True for d in dir_info if d[0][2] == 'L' and d[1] == checkout_path]: |
767 # The current directory is locked, clean it up. | 764 # The current directory is locked, clean it up. |
768 scm.SVN.Run(['cleanup'], checkout_path) | 765 scm.SVN.Run(['cleanup'], cwd=checkout_path) |
769 | 766 |
770 # Retrieve the current HEAD version because svn is slow at null updates. | 767 # Retrieve the current HEAD version because svn is slow at null updates. |
771 if options.manually_grab_svn_rev and not revision: | 768 if options.manually_grab_svn_rev and not revision: |
772 from_info_live = scm.SVN.CaptureInfo(from_info['URL'], '.') | 769 from_info_live = scm.SVN.CaptureInfo(from_info['URL'], '.') |
773 revision = str(from_info_live['Revision']) | 770 revision = str(from_info_live['Revision']) |
774 rev_str = ' at %s' % revision | 771 rev_str = ' at %s' % revision |
775 | 772 |
776 if from_info['URL'] != base_url: | 773 if from_info['URL'] != base_url: |
777 # The repository url changed, need to switch. | 774 # The repository url changed, need to switch. |
778 to_info = scm.SVN.CaptureInfo(url, '.') | 775 to_info = scm.SVN.CaptureInfo(url, '.') |
(...skipping 11 matching lines...) Expand all Loading... |
790 # to reflect where we "are now." (This is the same way that | 787 # to reflect where we "are now." (This is the same way that |
791 # Subversion itself handles the metadata when switch --relocate | 788 # Subversion itself handles the metadata when switch --relocate |
792 # is used.) This makes the checks below for whether we | 789 # is used.) This makes the checks below for whether we |
793 # can update to a revision or have to switch to a different | 790 # can update to a revision or have to switch to a different |
794 # branch work as expected. | 791 # branch work as expected. |
795 # TODO(maruel): TEST ME ! | 792 # TODO(maruel): TEST ME ! |
796 command = ['switch', '--relocate', | 793 command = ['switch', '--relocate', |
797 from_info['Repository Root'], | 794 from_info['Repository Root'], |
798 to_info['Repository Root'], | 795 to_info['Repository Root'], |
799 self.relpath] | 796 self.relpath] |
800 scm.SVN.Run(command, self._root_dir) | 797 scm.SVN.Run(command, cwd=self._root_dir) |
801 from_info['URL'] = from_info['URL'].replace( | 798 from_info['URL'] = from_info['URL'].replace( |
802 from_info['Repository Root'], | 799 from_info['Repository Root'], |
803 to_info['Repository Root']) | 800 to_info['Repository Root']) |
804 else: | 801 else: |
805 if not options.force and not options.reset: | 802 if not options.force and not options.reset: |
806 # Look for local modifications but ignore unversioned files. | 803 # Look for local modifications but ignore unversioned files. |
807 for status in scm.SVN.CaptureStatus(checkout_path): | 804 for status in scm.SVN.CaptureStatus(checkout_path): |
808 if status[0] != '?': | 805 if status[0] != '?': |
809 raise gclient_utils.Error( | 806 raise gclient_utils.Error( |
810 ('Can\'t switch the checkout to %s; UUID don\'t match and ' | 807 ('Can\'t switch the checkout to %s; UUID don\'t match and ' |
(...skipping 22 matching lines...) Expand all Loading... |
833 file_list) | 830 file_list) |
834 | 831 |
835 def updatesingle(self, options, args, file_list): | 832 def updatesingle(self, options, args, file_list): |
836 checkout_path = os.path.join(self._root_dir, self.relpath) | 833 checkout_path = os.path.join(self._root_dir, self.relpath) |
837 filename = args.pop() | 834 filename = args.pop() |
838 if scm.SVN.AssertVersion("1.5")[0]: | 835 if scm.SVN.AssertVersion("1.5")[0]: |
839 if not os.path.exists(os.path.join(checkout_path, '.svn')): | 836 if not os.path.exists(os.path.join(checkout_path, '.svn')): |
840 # Create an empty checkout and then update the one file we want. Future | 837 # Create an empty checkout and then update the one file we want. Future |
841 # operations will only apply to the one file we checked out. | 838 # operations will only apply to the one file we checked out. |
842 command = ["checkout", "--depth", "empty", self.url, checkout_path] | 839 command = ["checkout", "--depth", "empty", self.url, checkout_path] |
843 scm.SVN.Run(command, self._root_dir) | 840 scm.SVN.Run(command, cwd=self._root_dir) |
844 if os.path.exists(os.path.join(checkout_path, filename)): | 841 if os.path.exists(os.path.join(checkout_path, filename)): |
845 os.remove(os.path.join(checkout_path, filename)) | 842 os.remove(os.path.join(checkout_path, filename)) |
846 command = ["update", filename] | 843 command = ["update", filename] |
847 scm.SVN.RunAndGetFileList(options.verbose, command, checkout_path, | 844 scm.SVN.RunAndGetFileList(options.verbose, command, checkout_path, |
848 file_list) | 845 file_list) |
849 # After the initial checkout, we can use update as if it were any other | 846 # After the initial checkout, we can use update as if it were any other |
850 # dep. | 847 # dep. |
851 self.update(options, args, file_list) | 848 self.update(options, args, file_list) |
852 else: | 849 else: |
853 # If the installed version of SVN doesn't support --depth, fallback to | 850 # If the installed version of SVN doesn't support --depth, fallback to |
854 # just exporting the file. This has the downside that revision | 851 # just exporting the file. This has the downside that revision |
855 # information is not stored next to the file, so we will have to | 852 # information is not stored next to the file, so we will have to |
856 # re-export the file every time we sync. | 853 # re-export the file every time we sync. |
857 if not os.path.exists(checkout_path): | 854 if not os.path.exists(checkout_path): |
858 os.makedirs(checkout_path) | 855 os.makedirs(checkout_path) |
859 command = ["export", os.path.join(self.url, filename), | 856 command = ["export", os.path.join(self.url, filename), |
860 os.path.join(checkout_path, filename)] | 857 os.path.join(checkout_path, filename)] |
861 command = self._AddAdditionalUpdateFlags(command, options, | 858 command = self._AddAdditionalUpdateFlags(command, options, |
862 options.revision) | 859 options.revision) |
863 scm.SVN.Run(command, self._root_dir) | 860 scm.SVN.Run(command, cwd=self._root_dir) |
864 | 861 |
865 def revert(self, options, args, file_list): | 862 def revert(self, options, args, file_list): |
866 """Reverts local modifications. Subversion specific. | 863 """Reverts local modifications. Subversion specific. |
867 | 864 |
868 All reverted files will be appended to file_list, even if Subversion | 865 All reverted files will be appended to file_list, even if Subversion |
869 doesn't know about them. | 866 doesn't know about them. |
870 """ | 867 """ |
871 path = os.path.join(self._root_dir, self.relpath) | 868 path = os.path.join(self._root_dir, self.relpath) |
872 if not os.path.isdir(path): | 869 if not os.path.isdir(path): |
873 # svn revert won't work if the directory doesn't exist. It needs to | 870 # svn revert won't work if the directory doesn't exist. It needs to |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
963 | 960 |
964 This method returns a new list to be used as a command.""" | 961 This method returns a new list to be used as a command.""" |
965 new_command = command[:] | 962 new_command = command[:] |
966 if revision: | 963 if revision: |
967 new_command.extend(['--revision', str(revision).strip()]) | 964 new_command.extend(['--revision', str(revision).strip()]) |
968 # --force was added to 'svn update' in svn 1.5. | 965 # --force was added to 'svn update' in svn 1.5. |
969 if ((options.force or options.manually_grab_svn_rev) and | 966 if ((options.force or options.manually_grab_svn_rev) and |
970 scm.SVN.AssertVersion("1.5")[0]): | 967 scm.SVN.AssertVersion("1.5")[0]): |
971 new_command.append('--force') | 968 new_command.append('--force') |
972 return new_command | 969 return new_command |
OLD | NEW |