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 traceback | 15 import traceback |
17 import urlparse | 16 import urlparse |
18 | 17 |
19 import download_from_google_storage | 18 import download_from_google_storage |
20 import gclient_utils | 19 import gclient_utils |
21 import scm | 20 import scm |
22 import subprocess2 | 21 import subprocess2 |
23 | 22 |
24 | 23 |
25 THIS_FILE_PATH = os.path.abspath(__file__) | 24 THIS_FILE_PATH = os.path.abspath(__file__) |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
136 if not command in commands: | 135 if not command in commands: |
137 raise gclient_utils.Error('Unknown command %s' % command) | 136 raise gclient_utils.Error('Unknown command %s' % command) |
138 | 137 |
139 if not command in dir(self): | 138 if not command in dir(self): |
140 raise gclient_utils.Error('Command %s not implemented in %s wrapper' % ( | 139 raise gclient_utils.Error('Command %s not implemented in %s wrapper' % ( |
141 command, self.__class__.__name__)) | 140 command, self.__class__.__name__)) |
142 | 141 |
143 return getattr(self, command)(options, args, file_list) | 142 return getattr(self, command)(options, args, file_list) |
144 | 143 |
145 | 144 |
146 class GitFilter(object): | |
147 """A filter_fn implementation for quieting down git output messages. | |
148 | |
149 Allows a custom function to skip certain lines (predicate), and will throttle | |
150 the output of percentage completed lines to only output every X seconds. | |
151 """ | |
152 PERCENT_RE = re.compile('.* ([0-9]{1,2})% .*') | |
153 | |
154 def __init__(self, time_throttle=0, predicate=None): | |
155 """ | |
156 Args: | |
157 time_throttle (int): GitFilter will throttle 'noisy' output (such as the | |
158 XX% complete messages) to only be printed at least |time_throttle| | |
159 seconds apart. | |
160 predicate (f(line)): An optional function which is invoked for every line. | |
161 The line will be skipped if predicate(line) returns False. | |
162 """ | |
163 self.last_time = 0 | |
164 self.time_throttle = time_throttle | |
165 self.predicate = predicate | |
166 | |
167 def __call__(self, line): | |
168 # git uses an escape sequence to clear the line; elide it. | |
169 esc = line.find(unichr(033)) | |
170 if esc > -1: | |
171 line = line[:esc] | |
172 if self.predicate and not self.predicate(line): | |
173 return | |
174 now = time.time() | |
175 match = self.PERCENT_RE.match(line) | |
176 if not match: | |
177 self.last_time = 0 | |
178 if (now - self.last_time) >= self.time_throttle: | |
179 self.last_time = now | |
180 print line | |
181 | |
182 | |
183 class GitWrapper(SCMWrapper): | 145 class GitWrapper(SCMWrapper): |
184 """Wrapper for Git""" | 146 """Wrapper for Git""" |
185 name = 'git' | 147 name = 'git' |
186 remote = 'origin' | 148 remote = 'origin' |
187 | 149 |
188 cache_dir = None | 150 cache_dir = None |
189 # If a given cache is used in a solution more than once, prevent multiple | 151 # If a given cache is used in a solution more than once, prevent multiple |
190 # threads from updating it simultaneously. | 152 # threads from updating it simultaneously. |
191 cache_locks = collections.defaultdict(threading.Lock) | 153 cache_locks = collections.defaultdict(threading.Lock) |
192 | 154 |
(...skipping 864 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1057 if fetch: | 1019 if fetch: |
1058 fetch_cmd = ['-c', 'core.deltaBaseCacheLimit=2g', 'fetch', self.remote] | 1020 fetch_cmd = ['-c', 'core.deltaBaseCacheLimit=2g', 'fetch', self.remote] |
1059 if options.verbose: | 1021 if options.verbose: |
1060 fetch_cmd.append('--verbose') | 1022 fetch_cmd.append('--verbose') |
1061 self._Run(fetch_cmd, options, retry=True) | 1023 self._Run(fetch_cmd, options, retry=True) |
1062 | 1024 |
1063 def _Run(self, args, options, **kwargs): | 1025 def _Run(self, args, options, **kwargs): |
1064 kwargs.setdefault('cwd', self.checkout_path) | 1026 kwargs.setdefault('cwd', self.checkout_path) |
1065 git_filter = not options.verbose | 1027 git_filter = not options.verbose |
1066 if git_filter: | 1028 if git_filter: |
1067 kwargs['filter_fn'] = GitFilter(kwargs.get('filter_fn')) | 1029 kwargs['filter_fn'] = gclient_utils.GitFilter(kwargs.get('filter_fn')) |
1068 kwargs.setdefault('print_stdout', False) | 1030 kwargs.setdefault('print_stdout', False) |
1069 # Don't prompt for passwords; just fail quickly and noisily. | 1031 # Don't prompt for passwords; just fail quickly and noisily. |
1070 # By default, git will use an interactive terminal prompt when a username/ | 1032 # By default, git will use an interactive terminal prompt when a username/ |
1071 # password is needed. That shouldn't happen in the chromium workflow, | 1033 # password is needed. That shouldn't happen in the chromium workflow, |
1072 # and if it does, then gclient may hide the prompt in the midst of a flood | 1034 # and if it does, then gclient may hide the prompt in the midst of a flood |
1073 # of terminal spew. The only indication that something has gone wrong | 1035 # of terminal spew. The only indication that something has gone wrong |
1074 # will be when gclient hangs unresponsively. Instead, we disable the | 1036 # will be when gclient hangs unresponsively. Instead, we disable the |
1075 # password prompt and simply allow git to fail noisily. The error | 1037 # password prompt and simply allow git to fail noisily. The error |
1076 # message produced by git will be copied to gclient's output. | 1038 # message produced by git will be copied to gclient's output. |
1077 env = kwargs.get('env') or kwargs.setdefault('env', os.environ.copy()) | 1039 env = kwargs.get('env') or kwargs.setdefault('env', os.environ.copy()) |
(...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1544 new_command.append('--force') | 1506 new_command.append('--force') |
1545 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: | 1507 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: |
1546 new_command.extend(('--accept', 'theirs-conflict')) | 1508 new_command.extend(('--accept', 'theirs-conflict')) |
1547 elif options.manually_grab_svn_rev: | 1509 elif options.manually_grab_svn_rev: |
1548 new_command.append('--force') | 1510 new_command.append('--force') |
1549 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: | 1511 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: |
1550 new_command.extend(('--accept', 'postpone')) | 1512 new_command.extend(('--accept', 'postpone')) |
1551 elif command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: | 1513 elif command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: |
1552 new_command.extend(('--accept', 'postpone')) | 1514 new_command.extend(('--accept', 'postpone')) |
1553 return new_command | 1515 return new_command |
OLD | NEW |