| 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 |