| OLD | NEW |
| 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2012 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 from __future__ import print_function | 7 from __future__ import print_function |
| 8 | 8 |
| 9 import errno | 9 import errno |
| 10 import logging | 10 import logging |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 import shutil | 23 import shutil |
| 24 import subprocess2 | 24 import subprocess2 |
| 25 | 25 |
| 26 | 26 |
| 27 THIS_FILE_PATH = os.path.abspath(__file__) | 27 THIS_FILE_PATH = os.path.abspath(__file__) |
| 28 | 28 |
| 29 GSUTIL_DEFAULT_PATH = os.path.join( | 29 GSUTIL_DEFAULT_PATH = os.path.join( |
| 30 os.path.dirname(os.path.abspath(__file__)), 'gsutil.py') | 30 os.path.dirname(os.path.abspath(__file__)), 'gsutil.py') |
| 31 | 31 |
| 32 | 32 |
| 33 class NoUsableRevError(gclient_utils.Error): | |
| 34 """Raised if requested revision isn't found in checkout.""" | |
| 35 | |
| 36 | |
| 37 class DiffFiltererWrapper(object): | 33 class DiffFiltererWrapper(object): |
| 38 """Simple base class which tracks which file is being diffed and | 34 """Simple base class which tracks which file is being diffed and |
| 39 replaces instances of its file name in the original and | 35 replaces instances of its file name in the original and |
| 40 working copy lines of the svn/git diff output.""" | 36 working copy lines of the svn/git diff output.""" |
| 41 index_string = None | 37 index_string = None |
| 42 original_prefix = "--- " | 38 original_prefix = "--- " |
| 43 working_prefix = "+++ " | 39 working_prefix = "+++ " |
| 44 | 40 |
| 45 def __init__(self, relpath, print_func): | 41 def __init__(self, relpath, print_func): |
| 46 # Note that we always use '/' as the path separator to be | 42 # Note that we always use '/' as the path separator to be |
| (...skipping 699 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 746 default_rev = "refs/heads/master" | 742 default_rev = "refs/heads/master" |
| 747 if options.upstream: | 743 if options.upstream: |
| 748 if self._GetCurrentBranch(): | 744 if self._GetCurrentBranch(): |
| 749 upstream_branch = scm.GIT.GetUpstreamBranch(self.checkout_path) | 745 upstream_branch = scm.GIT.GetUpstreamBranch(self.checkout_path) |
| 750 default_rev = upstream_branch or default_rev | 746 default_rev = upstream_branch or default_rev |
| 751 _, deps_revision = gclient_utils.SplitUrlRevision(self.url) | 747 _, deps_revision = gclient_utils.SplitUrlRevision(self.url) |
| 752 if not deps_revision: | 748 if not deps_revision: |
| 753 deps_revision = default_rev | 749 deps_revision = default_rev |
| 754 if deps_revision.startswith('refs/heads/'): | 750 if deps_revision.startswith('refs/heads/'): |
| 755 deps_revision = deps_revision.replace('refs/heads/', self.remote + '/') | 751 deps_revision = deps_revision.replace('refs/heads/', self.remote + '/') |
| 756 try: | |
| 757 deps_revision = self.GetUsableRev(deps_revision, options) | |
| 758 except NoUsableRevError as e: | |
| 759 # If the DEPS entry's url and hash changed, try to update the origin. | |
| 760 # See also http://crbug.com/520067. | |
| 761 logging.warn( | |
| 762 'Couldn\'t find usable revision, will retrying to update instead: %s', | |
| 763 e.message) | |
| 764 return self.update(options, [], file_list) | |
| 765 | 752 |
| 766 if file_list is not None: | 753 if file_list is not None: |
| 767 files = self._Capture(['diff', deps_revision, '--name-only']).split() | 754 files = self._Capture(['diff', deps_revision, '--name-only']).split() |
| 768 | 755 |
| 769 self._Run(['reset', '--hard', deps_revision], options) | 756 self._Run(['reset', '--hard', deps_revision], options) |
| 770 self._Run(['clean', '-f', '-d'], options) | 757 self._Run(['clean', '-f', '-d'], options) |
| 771 | 758 |
| 772 if file_list is not None: | 759 if file_list is not None: |
| 773 file_list.extend([os.path.join(self.checkout_path, f) for f in files]) | 760 file_list.extend([os.path.join(self.checkout_path, f) for f in files]) |
| 774 | 761 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 785 self.Print('________ couldn\'t run status in %s:\n' | 772 self.Print('________ couldn\'t run status in %s:\n' |
| 786 'The directory does not exist.' % self.checkout_path) | 773 'The directory does not exist.' % self.checkout_path) |
| 787 else: | 774 else: |
| 788 merge_base = self._Capture(['merge-base', 'HEAD', self.remote]) | 775 merge_base = self._Capture(['merge-base', 'HEAD', self.remote]) |
| 789 self._Run(['diff', '--name-status', merge_base], options, | 776 self._Run(['diff', '--name-status', merge_base], options, |
| 790 stdout=self.out_fh) | 777 stdout=self.out_fh) |
| 791 if file_list is not None: | 778 if file_list is not None: |
| 792 files = self._Capture(['diff', '--name-only', merge_base]).split() | 779 files = self._Capture(['diff', '--name-only', merge_base]).split() |
| 793 file_list.extend([os.path.join(self.checkout_path, f) for f in files]) | 780 file_list.extend([os.path.join(self.checkout_path, f) for f in files]) |
| 794 | 781 |
| 795 def GetUsableRev(self, rev, options): | |
| 796 """Finds a useful revision for this repository. | |
| 797 | |
| 798 If SCM is git-svn and the head revision is less than |rev|, git svn fetch | |
| 799 will be called on the source.""" | |
| 800 sha1 = None | |
| 801 if not os.path.isdir(self.checkout_path): | |
| 802 raise NoUsableRevError( | |
| 803 ( 'We could not find a valid hash for safesync_url response "%s".\n' | |
| 804 'Safesync URLs with a git checkout currently require the repo to\n' | |
| 805 'be cloned without a safesync_url before adding the safesync_url.\n' | |
| 806 'For more info, see: ' | |
| 807 'http://code.google.com/p/chromium/wiki/UsingNewGit' | |
| 808 '#Initial_checkout' ) % rev) | |
| 809 elif rev.isdigit() and len(rev) < 7: | |
| 810 # Handles an SVN rev. As an optimization, only verify an SVN revision as | |
| 811 # [0-9]{1,6} for now to avoid making a network request. | |
| 812 if scm.GIT.IsGitSvn(cwd=self.checkout_path): | |
| 813 local_head = scm.GIT.GetGitSvnHeadRev(cwd=self.checkout_path) | |
| 814 if not local_head or local_head < int(rev): | |
| 815 try: | |
| 816 logging.debug('Looking for git-svn configuration optimizations.') | |
| 817 if scm.GIT.Capture(['config', '--get', 'svn-remote.svn.fetch'], | |
| 818 cwd=self.checkout_path): | |
| 819 self._Fetch(options) | |
| 820 except subprocess2.CalledProcessError: | |
| 821 logging.debug('git config --get svn-remote.svn.fetch failed, ' | |
| 822 'ignoring possible optimization.') | |
| 823 if options.verbose: | |
| 824 self.Print('Running git svn fetch. This might take a while.\n') | |
| 825 scm.GIT.Capture(['svn', 'fetch'], cwd=self.checkout_path) | |
| 826 try: | |
| 827 sha1 = scm.GIT.GetBlessedSha1ForSvnRev( | |
| 828 cwd=self.checkout_path, rev=rev) | |
| 829 except gclient_utils.Error, e: | |
| 830 sha1 = e.message | |
| 831 self.Print('Warning: Could not find a git revision with accurate\n' | |
| 832 '.DEPS.git that maps to SVN revision %s. Sync-ing to\n' | |
| 833 'the closest sane git revision, which is:\n' | |
| 834 ' %s\n' % (rev, e.message)) | |
| 835 if not sha1: | |
| 836 raise NoUsableRevError( | |
| 837 ( 'It appears that either your git-svn remote is incorrectly\n' | |
| 838 'configured or the revision in your safesync_url is\n' | |
| 839 'higher than git-svn remote\'s HEAD as we couldn\'t find a\n' | |
| 840 'corresponding git hash for SVN rev %s.' ) % rev) | |
| 841 else: | |
| 842 if scm.GIT.IsValidRevision(cwd=self.checkout_path, rev=rev): | |
| 843 sha1 = rev | |
| 844 else: | |
| 845 # May exist in origin, but we don't have it yet, so fetch and look | |
| 846 # again. | |
| 847 self._Fetch(options) | |
| 848 if scm.GIT.IsValidRevision(cwd=self.checkout_path, rev=rev): | |
| 849 sha1 = rev | |
| 850 | |
| 851 if not sha1: | |
| 852 raise NoUsableRevError( | |
| 853 ( 'We could not find a valid hash for safesync_url response "%s".\n' | |
| 854 'Safesync URLs with a git checkout currently require a git-svn\n' | |
| 855 'remote or a safesync_url that provides git sha1s. Please add a\n' | |
| 856 'git-svn remote or change your safesync_url. For more info, see:\n' | |
| 857 'http://code.google.com/p/chromium/wiki/UsingNewGit' | |
| 858 '#Initial_checkout' ) % rev) | |
| 859 | |
| 860 return sha1 | |
| 861 | |
| 862 def FullUrlForRelativeUrl(self, url): | 782 def FullUrlForRelativeUrl(self, url): |
| 863 # Strip from last '/' | 783 # Strip from last '/' |
| 864 # Equivalent to unix basename | 784 # Equivalent to unix basename |
| 865 base_url = self.url | 785 base_url = self.url |
| 866 return base_url[:base_url.rfind('/')] + url | 786 return base_url[:base_url.rfind('/')] + url |
| 867 | 787 |
| 868 def GetGitBackupDirPath(self): | 788 def GetGitBackupDirPath(self): |
| 869 """Returns the path where the .git folder for the current project can be | 789 """Returns the path where the .git folder for the current project can be |
| 870 staged/restored. Use case: subproject moved from DEPS <-> outer project.""" | 790 staged/restored. Use case: subproject moved from DEPS <-> outer project.""" |
| 871 return os.path.join(self._root_dir, | 791 return os.path.join(self._root_dir, |
| (...skipping 784 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1656 command = ['status'] + args | 1576 command = ['status'] + args |
| 1657 if not os.path.isdir(self.checkout_path): | 1577 if not os.path.isdir(self.checkout_path): |
| 1658 # svn status won't work if the directory doesn't exist. | 1578 # svn status won't work if the directory doesn't exist. |
| 1659 self.Print(('\n________ couldn\'t run \'%s\' in \'%s\':\n' | 1579 self.Print(('\n________ couldn\'t run \'%s\' in \'%s\':\n' |
| 1660 'The directory does not exist.') % | 1580 'The directory does not exist.') % |
| 1661 (' '.join(command), self.checkout_path)) | 1581 (' '.join(command), self.checkout_path)) |
| 1662 # There's no file list to retrieve. | 1582 # There's no file list to retrieve. |
| 1663 else: | 1583 else: |
| 1664 self._RunAndGetFileList(command, options, file_list) | 1584 self._RunAndGetFileList(command, options, file_list) |
| 1665 | 1585 |
| 1666 def GetUsableRev(self, rev, _options): | |
| 1667 """Verifies the validity of the revision for this repository.""" | |
| 1668 if not scm.SVN.IsValidRevision(url='%s@%s' % (self.url, rev)): | |
| 1669 raise NoUsableRevError( | |
| 1670 ( '%s isn\'t a valid revision. Please check that your safesync_url is\n' | |
| 1671 'correct.') % rev) | |
| 1672 return rev | |
| 1673 | |
| 1674 def FullUrlForRelativeUrl(self, url): | 1586 def FullUrlForRelativeUrl(self, url): |
| 1675 # Find the forth '/' and strip from there. A bit hackish. | 1587 # Find the forth '/' and strip from there. A bit hackish. |
| 1676 return '/'.join(self.url.split('/')[:4]) + url | 1588 return '/'.join(self.url.split('/')[:4]) + url |
| 1677 | 1589 |
| 1678 def _Run(self, args, options, **kwargs): | 1590 def _Run(self, args, options, **kwargs): |
| 1679 """Runs a commands that goes to stdout.""" | 1591 """Runs a commands that goes to stdout.""" |
| 1680 kwargs.setdefault('cwd', self.checkout_path) | 1592 kwargs.setdefault('cwd', self.checkout_path) |
| 1681 gclient_utils.CheckCallAndFilterAndHeader(['svn'] + args, | 1593 gclient_utils.CheckCallAndFilterAndHeader(['svn'] + args, |
| 1682 always=options.verbose, **kwargs) | 1594 always=options.verbose, **kwargs) |
| 1683 | 1595 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1718 new_command.append('--force') | 1630 new_command.append('--force') |
| 1719 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: | 1631 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: |
| 1720 new_command.extend(('--accept', 'theirs-conflict')) | 1632 new_command.extend(('--accept', 'theirs-conflict')) |
| 1721 elif options.manually_grab_svn_rev: | 1633 elif options.manually_grab_svn_rev: |
| 1722 new_command.append('--force') | 1634 new_command.append('--force') |
| 1723 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: | 1635 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: |
| 1724 new_command.extend(('--accept', 'postpone')) | 1636 new_command.extend(('--accept', 'postpone')) |
| 1725 elif command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: | 1637 elif command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: |
| 1726 new_command.extend(('--accept', 'postpone')) | 1638 new_command.extend(('--accept', 'postpone')) |
| 1727 return new_command | 1639 return new_command |
| OLD | NEW |