Chromium Code Reviews| 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 logging | 9 import logging |
| 10 import os | 10 import os |
| 11 import posixpath | 11 import posixpath |
| 12 import re | 12 import re |
| 13 import shlex | 13 import shlex |
| 14 import sys | 14 import sys |
| 15 import tempfile | 15 import tempfile |
| 16 import traceback | 16 import traceback |
| 17 import urlparse | 17 import urlparse |
| 18 | 18 |
| 19 import download_from_google_storage | 19 import download_from_google_storage |
| 20 import gclient_utils | 20 import gclient_utils |
| 21 import git_cache | |
| 21 import scm | 22 import scm |
| 22 import subprocess2 | 23 import subprocess2 |
| 23 | 24 |
| 24 | 25 |
| 25 THIS_FILE_PATH = os.path.abspath(__file__) | 26 THIS_FILE_PATH = os.path.abspath(__file__) |
| 26 | 27 |
| 27 GSUTIL_DEFAULT_PATH = os.path.join( | 28 GSUTIL_DEFAULT_PATH = os.path.join( |
| 28 os.path.dirname(os.path.abspath(__file__)), | 29 os.path.dirname(os.path.abspath(__file__)), |
| 29 'third_party', 'gsutil', 'gsutil') | 30 'third_party', 'gsutil', 'gsutil') |
| 30 | 31 |
| 31 | 32 CHROMIUM_SRC_URL = 'https://chromium.googlesource.com/chromium/src.git' |
| 32 class DiffFiltererWrapper(object): | 33 class DiffFiltererWrapper(object): |
| 33 """Simple base class which tracks which file is being diffed and | 34 """Simple base class which tracks which file is being diffed and |
| 34 replaces instances of its file name in the original and | 35 replaces instances of its file name in the original and |
| 35 working copy lines of the svn/git diff output.""" | 36 working copy lines of the svn/git diff output.""" |
| 36 index_string = None | 37 index_string = None |
| 37 original_prefix = "--- " | 38 original_prefix = "--- " |
| 38 working_prefix = "+++ " | 39 working_prefix = "+++ " |
| 39 | 40 |
| 40 def __init__(self, relpath, print_func): | 41 def __init__(self, relpath, print_func): |
| 41 # Note that we always use '/' as the path separator to be | 42 # Note that we always use '/' as the path separator to be |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 152 if not command in dir(self): | 153 if not command in dir(self): |
| 153 raise gclient_utils.Error('Command %s not implemented in %s wrapper' % ( | 154 raise gclient_utils.Error('Command %s not implemented in %s wrapper' % ( |
| 154 command, self.__class__.__name__)) | 155 command, self.__class__.__name__)) |
| 155 | 156 |
| 156 return getattr(self, command)(options, args, file_list) | 157 return getattr(self, command)(options, args, file_list) |
| 157 | 158 |
| 158 def GetActualRemoteURL(self, options): | 159 def GetActualRemoteURL(self, options): |
| 159 """Attempt to determine the remote URL for this SCMWrapper.""" | 160 """Attempt to determine the remote URL for this SCMWrapper.""" |
| 160 # Git | 161 # Git |
| 161 if os.path.exists(os.path.join(self.checkout_path, '.git')): | 162 if os.path.exists(os.path.join(self.checkout_path, '.git')): |
| 162 actual_remote_url = shlex.split(scm.GIT.Capture( | 163 actual_remote_url = shlex.split(self._Capture( |
|
kustermann
2014/05/01 23:35:15
This line raises an exception on a "gclient sync"
| |
| 163 ['config', '--local', '--get-regexp', r'remote.*.url'], | 164 ['config', '--local', '--get-regexp', r'remote.*.url'], |
| 164 self.checkout_path))[1] | 165 self.checkout_path))[1] |
| 165 | 166 |
| 166 # If a cache_dir is used, obtain the actual remote URL from the cache. | 167 # If a cache_dir is used, obtain the actual remote URL from the cache. |
| 167 if getattr(self, 'cache_dir', None): | 168 if getattr(self, 'cache_dir', None): |
| 168 try: | 169 mirror = git_cache.Mirror(self.url) |
| 169 full_cache_dir = self._Run(['cache', 'exists', '--cache-dir', | 170 if (mirror.exists() and mirror.mirror_path.replace('\\', '/') == |
| 170 self.cache_dir, self.url], | |
| 171 options, cwd=self._root_dir).strip() | |
| 172 except subprocess2.CalledProcessError: | |
| 173 full_cache_dir = None | |
| 174 if (full_cache_dir.replace('\\', '/') == | |
| 175 actual_remote_url.replace('\\', '/')): | 171 actual_remote_url.replace('\\', '/')): |
| 176 actual_remote_url = shlex.split(scm.GIT.Capture( | 172 actual_remote_url = shlex.split(self._Capture( |
| 177 ['config', '--local', '--get-regexp', r'remote.*.url'], | 173 ['config', '--local', '--get-regexp', r'remote.*.url'], |
| 178 os.path.join(self._root_dir, full_cache_dir)))[1] | 174 cwd=mirror.mirror_path))[1] |
| 179 return actual_remote_url | 175 return actual_remote_url |
| 180 | 176 |
| 181 # Svn | 177 # Svn |
| 182 if os.path.exists(os.path.join(self.checkout_path, '.svn')): | 178 if os.path.exists(os.path.join(self.checkout_path, '.svn')): |
| 183 return scm.SVN.CaptureLocalInfo([], self.checkout_path)['URL'] | 179 return scm.SVN.CaptureLocalInfo([], self.checkout_path)['URL'] |
| 184 return None | 180 return None |
| 185 | 181 |
| 186 def DoesRemoteURLMatch(self, options): | 182 def DoesRemoteURLMatch(self, options): |
| 187 """Determine whether the remote URL of this checkout is the expected URL.""" | 183 """Determine whether the remote URL of this checkout is the expected URL.""" |
| 188 if not os.path.exists(self.checkout_path): | 184 if not os.path.exists(self.checkout_path): |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 199 return False | 195 return False |
| 200 | 196 |
| 201 | 197 |
| 202 class GitWrapper(SCMWrapper): | 198 class GitWrapper(SCMWrapper): |
| 203 """Wrapper for Git""" | 199 """Wrapper for Git""" |
| 204 name = 'git' | 200 name = 'git' |
| 205 remote = 'origin' | 201 remote = 'origin' |
| 206 | 202 |
| 207 cache_dir = None | 203 cache_dir = None |
| 208 | 204 |
| 209 def __init__(self, url=None, root_dir=None, relpath=None, out_fh=None, | 205 def __init__(self, url=None, *args): |
| 210 out_cb=None): | |
| 211 """Removes 'git+' fake prefix from git URL.""" | 206 """Removes 'git+' fake prefix from git URL.""" |
| 212 if url.startswith('git+http://') or url.startswith('git+https://'): | 207 if url.startswith('git+http://') or url.startswith('git+https://'): |
| 213 url = url[4:] | 208 url = url[4:] |
| 214 SCMWrapper.__init__(self, url, root_dir, relpath, out_fh, out_cb) | 209 SCMWrapper.__init__(self, url, *args) |
| 210 filter_kwargs = { 'time_throttle': 1, 'out_fh': self.out_fh } | |
| 211 if self.out_cb: | |
| 212 filter_kwargs['predicate'] = self.out_cb | |
| 213 self.filter = gclient_utils.GitFilter(**filter_kwargs) | |
| 215 | 214 |
| 216 @staticmethod | 215 @staticmethod |
| 217 def BinaryExists(): | 216 def BinaryExists(): |
| 218 """Returns true if the command exists.""" | 217 """Returns true if the command exists.""" |
| 219 try: | 218 try: |
| 220 # We assume git is newer than 1.7. See: crbug.com/114483 | 219 # We assume git is newer than 1.7. See: crbug.com/114483 |
| 221 result, version = scm.GIT.AssertVersion('1.7') | 220 result, version = scm.GIT.AssertVersion('1.7') |
| 222 if not result: | 221 if not result: |
| 223 raise gclient_utils.Error('Git version is older than 1.7: %s' % version) | 222 raise gclient_utils.Error('Git version is older than 1.7: %s' % version) |
| 224 return result | 223 return result |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 460 if options.force or options.reset: | 459 if options.force or options.reset: |
| 461 target = 'HEAD' | 460 target = 'HEAD' |
| 462 if options.upstream and upstream_branch: | 461 if options.upstream and upstream_branch: |
| 463 target = upstream_branch | 462 target = upstream_branch |
| 464 self._Run(['reset', '--hard', target], options) | 463 self._Run(['reset', '--hard', target], options) |
| 465 | 464 |
| 466 if current_type == 'detached': | 465 if current_type == 'detached': |
| 467 # case 0 | 466 # case 0 |
| 468 self._CheckClean(rev_str) | 467 self._CheckClean(rev_str) |
| 469 self._CheckDetachedHead(rev_str, options) | 468 self._CheckDetachedHead(rev_str, options) |
| 470 self._Capture(['checkout', '--quiet', '%s' % revision]) | 469 if self._Capture(['rev-list', '-n', '1', 'HEAD']) == revision: |
| 470 self.Print('Up-to-date; skipping checkout.') | |
| 471 else: | |
| 472 self._Capture(['checkout', '--quiet', '%s' % revision]) | |
| 471 if not printed_path: | 473 if not printed_path: |
| 472 self.Print('_____ %s%s' % (self.relpath, rev_str), timestamp=False) | 474 self.Print('_____ %s%s' % (self.relpath, rev_str), timestamp=False) |
| 473 elif current_type == 'hash': | 475 elif current_type == 'hash': |
| 474 # case 1 | 476 # case 1 |
| 475 if scm.GIT.IsGitSvn(self.checkout_path) and upstream_branch is not None: | 477 if scm.GIT.IsGitSvn(self.checkout_path) and upstream_branch is not None: |
| 476 # Our git-svn branch (upstream_branch) is our upstream | 478 # Our git-svn branch (upstream_branch) is our upstream |
| 477 self._AttemptRebase(upstream_branch, files, options, | 479 self._AttemptRebase(upstream_branch, files, options, |
| 478 newbase=revision, printed_path=printed_path, | 480 newbase=revision, printed_path=printed_path, |
| 479 merge=options.merge) | 481 merge=options.merge) |
| 480 printed_path = True | 482 printed_path = True |
| (...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 735 return base_url[:base_url.rfind('/')] + url | 737 return base_url[:base_url.rfind('/')] + url |
| 736 | 738 |
| 737 def _CreateOrUpdateCache(self, url, options): | 739 def _CreateOrUpdateCache(self, url, options): |
| 738 """Make a new git mirror or update existing mirror for |url|, and return the | 740 """Make a new git mirror or update existing mirror for |url|, and return the |
| 739 mirror URI to clone from. | 741 mirror URI to clone from. |
| 740 | 742 |
| 741 If no cache-dir is specified, just return |url| unchanged. | 743 If no cache-dir is specified, just return |url| unchanged. |
| 742 """ | 744 """ |
| 743 if not self.cache_dir: | 745 if not self.cache_dir: |
| 744 return url | 746 return url |
| 745 v = ['-v'] if options.verbose else [] | 747 mirror_kwargs = { 'print_func': self.filter } |
| 746 self._Run(['cache', 'populate'] + v + ['--cache-dir', self.cache_dir, url], | 748 if url == CHROMIUM_SRC_URL or url + '.git' == CHROMIUM_SRC_URL: |
| 747 options, cwd=self._root_dir, retry=True) | 749 mirror_kwargs['refs'] = ['refs/tags/lkgr', 'refs/tags/lkcr'] |
| 748 return self._Run(['cache', 'exists', '--cache-dir', self.cache_dir, url], | 750 mirror = git_cache.Mirror(url, **mirror_kwargs) |
| 749 options, cwd=self._root_dir, ).strip() | 751 mirror.populate(verbose=options.verbose, bootstrap=True) |
| 752 mirror.unlock() | |
| 753 return mirror.mirror_path if mirror.exists() else None | |
| 750 | 754 |
| 751 def _Clone(self, revision, url, options): | 755 def _Clone(self, revision, url, options): |
| 752 """Clone a git repository from the given URL. | 756 """Clone a git repository from the given URL. |
| 753 | 757 |
| 754 Once we've cloned the repo, we checkout a working branch if the specified | 758 Once we've cloned the repo, we checkout a working branch if the specified |
| 755 revision is a branch head. If it is a tag or a specific commit, then we | 759 revision is a branch head. If it is a tag or a specific commit, then we |
| 756 leave HEAD detached as it makes future updates simpler -- in this case the | 760 leave HEAD detached as it makes future updates simpler -- in this case the |
| 757 user should first create a new branch or switch to an existing branch before | 761 user should first create a new branch or switch to an existing branch before |
| 758 making changes in the repo.""" | 762 making changes in the repo.""" |
| 759 if not options.verbose: | 763 if not options.verbose: |
| (...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 975 if fetch: | 979 if fetch: |
| 976 cfg = gclient_utils.DefaultIndexPackConfig(self.url) | 980 cfg = gclient_utils.DefaultIndexPackConfig(self.url) |
| 977 fetch_cmd = cfg + ['fetch', self.remote] | 981 fetch_cmd = cfg + ['fetch', self.remote] |
| 978 if options.verbose: | 982 if options.verbose: |
| 979 fetch_cmd.append('--verbose') | 983 fetch_cmd.append('--verbose') |
| 980 self._Run(fetch_cmd, options, retry=True) | 984 self._Run(fetch_cmd, options, retry=True) |
| 981 | 985 |
| 982 def _Run(self, args, options, **kwargs): | 986 def _Run(self, args, options, **kwargs): |
| 983 cwd = kwargs.setdefault('cwd', self.checkout_path) | 987 cwd = kwargs.setdefault('cwd', self.checkout_path) |
| 984 kwargs.setdefault('stdout', self.out_fh) | 988 kwargs.setdefault('stdout', self.out_fh) |
| 985 filter_kwargs = { 'time_throttle': 10, 'out_fh': self.out_fh } | 989 kwargs['filter_fn'] = self.filter |
| 986 if self.out_cb: | |
| 987 filter_kwargs['predicate'] = self.out_cb | |
| 988 kwargs['filter_fn'] = git_filter = gclient_utils.GitFilter(**filter_kwargs) | |
| 989 kwargs.setdefault('print_stdout', False) | 990 kwargs.setdefault('print_stdout', False) |
| 990 # Don't prompt for passwords; just fail quickly and noisily. | 991 # Don't prompt for passwords; just fail quickly and noisily. |
| 991 # By default, git will use an interactive terminal prompt when a username/ | 992 # By default, git will use an interactive terminal prompt when a username/ |
| 992 # password is needed. That shouldn't happen in the chromium workflow, | 993 # password is needed. That shouldn't happen in the chromium workflow, |
| 993 # and if it does, then gclient may hide the prompt in the midst of a flood | 994 # and if it does, then gclient may hide the prompt in the midst of a flood |
| 994 # of terminal spew. The only indication that something has gone wrong | 995 # of terminal spew. The only indication that something has gone wrong |
| 995 # will be when gclient hangs unresponsively. Instead, we disable the | 996 # will be when gclient hangs unresponsively. Instead, we disable the |
| 996 # password prompt and simply allow git to fail noisily. The error | 997 # password prompt and simply allow git to fail noisily. The error |
| 997 # message produced by git will be copied to gclient's output. | 998 # message produced by git will be copied to gclient's output. |
| 998 env = kwargs.get('env') or kwargs.setdefault('env', os.environ.copy()) | 999 env = kwargs.get('env') or kwargs.setdefault('env', os.environ.copy()) |
| 999 env.setdefault('GIT_ASKPASS', 'true') | 1000 env.setdefault('GIT_ASKPASS', 'true') |
| 1000 env.setdefault('SSH_ASKPASS', 'true') | 1001 env.setdefault('SSH_ASKPASS', 'true') |
| 1001 | 1002 |
| 1002 cmd = ['git'] + args | 1003 cmd = ['git'] + args |
| 1003 header = "running '%s' in '%s'" % (' '.join(cmd), cwd) | 1004 header = "running '%s' in '%s'" % (' '.join(cmd), cwd) |
| 1004 git_filter(header) | 1005 self.filter(header) |
| 1005 return gclient_utils.CheckCallAndFilter(cmd, **kwargs) | 1006 return gclient_utils.CheckCallAndFilter(cmd, **kwargs) |
| 1006 | 1007 |
| 1007 | 1008 |
| 1008 class SVNWrapper(SCMWrapper): | 1009 class SVNWrapper(SCMWrapper): |
| 1009 """ Wrapper for SVN """ | 1010 """ Wrapper for SVN """ |
| 1010 name = 'svn' | 1011 name = 'svn' |
| 1011 | 1012 |
| 1012 @staticmethod | 1013 @staticmethod |
| 1013 def BinaryExists(): | 1014 def BinaryExists(): |
| 1014 """Returns true if the command exists.""" | 1015 """Returns true if the command exists.""" |
| (...skipping 450 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1465 new_command.append('--force') | 1466 new_command.append('--force') |
| 1466 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: | 1467 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: |
| 1467 new_command.extend(('--accept', 'theirs-conflict')) | 1468 new_command.extend(('--accept', 'theirs-conflict')) |
| 1468 elif options.manually_grab_svn_rev: | 1469 elif options.manually_grab_svn_rev: |
| 1469 new_command.append('--force') | 1470 new_command.append('--force') |
| 1470 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: | 1471 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: |
| 1471 new_command.extend(('--accept', 'postpone')) | 1472 new_command.extend(('--accept', 'postpone')) |
| 1472 elif command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: | 1473 elif command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: |
| 1473 new_command.extend(('--accept', 'postpone')) | 1474 new_command.extend(('--accept', 'postpone')) |
| 1474 return new_command | 1475 return new_command |
| OLD | NEW |