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 |