| 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 import collections | 7 import collections |
| 8 import logging | 8 import logging |
| 9 import os | 9 import os |
| 10 import posixpath | 10 import posixpath |
| 11 import re | 11 import re |
| 12 import sys | 12 import sys |
| 13 import tempfile | 13 import tempfile |
| 14 import threading | 14 import threading |
| 15 import time | |
| 16 import urlparse | 15 import urlparse |
| 17 | 16 |
| 18 import download_from_google_storage | 17 import download_from_google_storage |
| 19 import gclient_utils | 18 import gclient_utils |
| 20 import scm | 19 import scm |
| 21 import subprocess2 | 20 import subprocess2 |
| 22 | 21 |
| 23 | 22 |
| 24 THIS_FILE_PATH = os.path.abspath(__file__) | 23 THIS_FILE_PATH = os.path.abspath(__file__) |
| 25 | 24 |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 135 if not command in commands: | 134 if not command in commands: |
| 136 raise gclient_utils.Error('Unknown command %s' % command) | 135 raise gclient_utils.Error('Unknown command %s' % command) |
| 137 | 136 |
| 138 if not command in dir(self): | 137 if not command in dir(self): |
| 139 raise gclient_utils.Error('Command %s not implemented in %s wrapper' % ( | 138 raise gclient_utils.Error('Command %s not implemented in %s wrapper' % ( |
| 140 command, self.__class__.__name__)) | 139 command, self.__class__.__name__)) |
| 141 | 140 |
| 142 return getattr(self, command)(options, args, file_list) | 141 return getattr(self, command)(options, args, file_list) |
| 143 | 142 |
| 144 | 143 |
| 145 class GitFilter(object): | |
| 146 """A filter_fn implementation for quieting down git output messages. | |
| 147 | |
| 148 Allows a custom function to skip certain lines (predicate), and will throttle | |
| 149 the output of percentage completed lines to only output every X seconds. | |
| 150 """ | |
| 151 PERCENT_RE = re.compile('.* ([0-9]{1,2})% .*') | |
| 152 | |
| 153 def __init__(self, time_throttle=0, predicate=None): | |
| 154 """ | |
| 155 Args: | |
| 156 time_throttle (int): GitFilter will throttle 'noisy' output (such as the | |
| 157 XX% complete messages) to only be printed at least |time_throttle| | |
| 158 seconds apart. | |
| 159 predicate (f(line)): An optional function which is invoked for every line. | |
| 160 The line will be skipped if predicate(line) returns False. | |
| 161 """ | |
| 162 self.last_time = 0 | |
| 163 self.time_throttle = time_throttle | |
| 164 self.predicate = predicate | |
| 165 | |
| 166 def __call__(self, line): | |
| 167 # git uses an escape sequence to clear the line; elide it. | |
| 168 esc = line.find(unichr(033)) | |
| 169 if esc > -1: | |
| 170 line = line[:esc] | |
| 171 if self.predicate and not self.predicate(line): | |
| 172 return | |
| 173 now = time.time() | |
| 174 match = self.PERCENT_RE.match(line) | |
| 175 if not match: | |
| 176 self.last_time = 0 | |
| 177 if (now - self.last_time) >= self.time_throttle: | |
| 178 self.last_time = now | |
| 179 print line | |
| 180 | |
| 181 | |
| 182 class GitWrapper(SCMWrapper): | 144 class GitWrapper(SCMWrapper): |
| 183 """Wrapper for Git""" | 145 """Wrapper for Git""" |
| 184 name = 'git' | 146 name = 'git' |
| 185 remote = 'origin' | 147 remote = 'origin' |
| 186 | 148 |
| 187 cache_dir = None | 149 cache_dir = None |
| 188 # If a given cache is used in a solution more than once, prevent multiple | 150 # If a given cache is used in a solution more than once, prevent multiple |
| 189 # threads from updating it simultaneously. | 151 # threads from updating it simultaneously. |
| 190 cache_locks = collections.defaultdict(threading.Lock) | 152 cache_locks = collections.defaultdict(threading.Lock) |
| 191 | 153 |
| (...skipping 833 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1025 if fetch: | 987 if fetch: |
| 1026 fetch_cmd = ['-c', 'core.deltaBaseCacheLimit=2g', 'fetch', self.remote] | 988 fetch_cmd = ['-c', 'core.deltaBaseCacheLimit=2g', 'fetch', self.remote] |
| 1027 if options.verbose: | 989 if options.verbose: |
| 1028 fetch_cmd.append('--verbose') | 990 fetch_cmd.append('--verbose') |
| 1029 self._Run(fetch_cmd, options, retry=True) | 991 self._Run(fetch_cmd, options, retry=True) |
| 1030 | 992 |
| 1031 def _Run(self, args, options, **kwargs): | 993 def _Run(self, args, options, **kwargs): |
| 1032 kwargs.setdefault('cwd', self.checkout_path) | 994 kwargs.setdefault('cwd', self.checkout_path) |
| 1033 git_filter = not options.verbose | 995 git_filter = not options.verbose |
| 1034 if git_filter: | 996 if git_filter: |
| 1035 kwargs['filter_fn'] = GitFilter(kwargs.get('filter_fn')) | 997 kwargs['filter_fn'] = gclient_utils.GitFilter(kwargs.get('filter_fn')) |
| 1036 kwargs.setdefault('print_stdout', False) | 998 kwargs.setdefault('print_stdout', False) |
| 1037 # Don't prompt for passwords; just fail quickly and noisily. | 999 # Don't prompt for passwords; just fail quickly and noisily. |
| 1038 # By default, git will use an interactive terminal prompt when a username/ | 1000 # By default, git will use an interactive terminal prompt when a username/ |
| 1039 # password is needed. That shouldn't happen in the chromium workflow, | 1001 # password is needed. That shouldn't happen in the chromium workflow, |
| 1040 # and if it does, then gclient may hide the prompt in the midst of a flood | 1002 # and if it does, then gclient may hide the prompt in the midst of a flood |
| 1041 # of terminal spew. The only indication that something has gone wrong | 1003 # of terminal spew. The only indication that something has gone wrong |
| 1042 # will be when gclient hangs unresponsively. Instead, we disable the | 1004 # will be when gclient hangs unresponsively. Instead, we disable the |
| 1043 # password prompt and simply allow git to fail noisily. The error | 1005 # password prompt and simply allow git to fail noisily. The error |
| 1044 # message produced by git will be copied to gclient's output. | 1006 # message produced by git will be copied to gclient's output. |
| 1045 env = kwargs.get('env') or kwargs.setdefault('env', os.environ.copy()) | 1007 env = kwargs.get('env') or kwargs.setdefault('env', os.environ.copy()) |
| (...skipping 424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1470 new_command.append('--force') | 1432 new_command.append('--force') |
| 1471 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: | 1433 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: |
| 1472 new_command.extend(('--accept', 'theirs-conflict')) | 1434 new_command.extend(('--accept', 'theirs-conflict')) |
| 1473 elif options.manually_grab_svn_rev: | 1435 elif options.manually_grab_svn_rev: |
| 1474 new_command.append('--force') | 1436 new_command.append('--force') |
| 1475 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: | 1437 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: |
| 1476 new_command.extend(('--accept', 'postpone')) | 1438 new_command.extend(('--accept', 'postpone')) |
| 1477 elif command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: | 1439 elif command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: |
| 1478 new_command.extend(('--accept', 'postpone')) | 1440 new_command.extend(('--accept', 'postpone')) |
| 1479 return new_command | 1441 return new_command |
| OLD | NEW |