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 |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
116 return scm_class(url, root_dir, relpath) | 116 return scm_class(url, root_dir, relpath) |
117 | 117 |
118 | 118 |
119 # SCMWrapper base class | 119 # SCMWrapper base class |
120 | 120 |
121 class SCMWrapper(object): | 121 class SCMWrapper(object): |
122 """Add necessary glue between all the supported SCM. | 122 """Add necessary glue between all the supported SCM. |
123 | 123 |
124 This is the abstraction layer to bind to different SCM. | 124 This is the abstraction layer to bind to different SCM. |
125 """ | 125 """ |
126 nag_timer = 30 | |
127 nag_max = 30 | |
128 | |
129 def __init__(self, url=None, root_dir=None, relpath=None): | 126 def __init__(self, url=None, root_dir=None, relpath=None): |
130 self.url = url | 127 self.url = url |
131 self._root_dir = root_dir | 128 self._root_dir = root_dir |
132 if self._root_dir: | 129 if self._root_dir: |
133 self._root_dir = self._root_dir.replace('/', os.sep) | 130 self._root_dir = self._root_dir.replace('/', os.sep) |
134 self.relpath = relpath | 131 self.relpath = relpath |
135 if self.relpath: | 132 if self.relpath: |
136 self.relpath = self.relpath.replace('/', os.sep) | 133 self.relpath = self.relpath.replace('/', os.sep) |
137 if self.relpath and self._root_dir: | 134 if self.relpath and self._root_dir: |
138 self.checkout_path = os.path.join(self._root_dir, self.relpath) | 135 self.checkout_path = os.path.join(self._root_dir, self.relpath) |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
240 """Generates a patch file which can be applied to the root of the | 237 """Generates a patch file which can be applied to the root of the |
241 repository. | 238 repository. |
242 | 239 |
243 The patch file is generated from a diff of the merge base of HEAD and | 240 The patch file is generated from a diff of the merge base of HEAD and |
244 its upstream branch. | 241 its upstream branch. |
245 """ | 242 """ |
246 merge_base = self._Capture(['merge-base', 'HEAD', 'origin']) | 243 merge_base = self._Capture(['merge-base', 'HEAD', 'origin']) |
247 gclient_utils.CheckCallAndFilter( | 244 gclient_utils.CheckCallAndFilter( |
248 ['git', 'diff', merge_base], | 245 ['git', 'diff', merge_base], |
249 cwd=self.checkout_path, | 246 cwd=self.checkout_path, |
250 nag_timer=self.nag_timer, | |
251 nag_max=self.nag_max, | |
252 filter_fn=GitDiffFilterer(self.relpath).Filter) | 247 filter_fn=GitDiffFilterer(self.relpath).Filter) |
253 | 248 |
254 def UpdateSubmoduleConfig(self): | 249 def UpdateSubmoduleConfig(self): |
255 submod_cmd = ['git', 'config', '-f', '$toplevel/.git/config', | 250 submod_cmd = ['git', 'config', '-f', '$toplevel/.git/config', |
256 'submodule.$name.ignore', '||', | 251 'submodule.$name.ignore', '||', |
257 'git', 'config', '-f', '$toplevel/.git/config', | 252 'git', 'config', '-f', '$toplevel/.git/config', |
258 'submodule.$name.ignore', 'all'] | 253 'submodule.$name.ignore', 'all'] |
259 cmd = ['git', 'submodule', '--quiet', 'foreach', ' '.join(submod_cmd)] | 254 cmd = ['git', 'submodule', '--quiet', 'foreach', ' '.join(submod_cmd)] |
260 cmd2 = ['git', 'config', 'diff.ignoreSubmodules', 'all'] | 255 cmd2 = ['git', 'config', 'diff.ignoreSubmodules', 'all'] |
261 cmd3 = ['git', 'config', 'branch.autosetupmerge'] | 256 cmd3 = ['git', 'config', 'branch.autosetupmerge'] |
262 cmd4 = ['git', 'config', 'fetch.recurseSubmodules', 'false'] | 257 cmd4 = ['git', 'config', 'fetch.recurseSubmodules', 'false'] |
263 kwargs = {'cwd': self.checkout_path, | 258 kwargs = {'cwd': self.checkout_path, |
264 'print_stdout': False, | 259 'print_stdout': False, |
265 'nag_timer': self.nag_timer, | |
266 'nag_max': self.nag_max, | |
267 'filter_fn': lambda x: None} | 260 'filter_fn': lambda x: None} |
268 try: | 261 try: |
269 gclient_utils.CheckCallAndFilter(cmd, **kwargs) | 262 gclient_utils.CheckCallAndFilter(cmd, **kwargs) |
270 gclient_utils.CheckCallAndFilter(cmd2, **kwargs) | 263 gclient_utils.CheckCallAndFilter(cmd2, **kwargs) |
271 except subprocess2.CalledProcessError: | 264 except subprocess2.CalledProcessError: |
272 # Not a fatal error, or even very interesting in a non-git-submodule | 265 # Not a fatal error, or even very interesting in a non-git-submodule |
273 # world. So just keep it quiet. | 266 # world. So just keep it quiet. |
274 pass | 267 pass |
275 try: | 268 try: |
276 gclient_utils.CheckCallAndFilter(cmd3, **kwargs) | 269 gclient_utils.CheckCallAndFilter(cmd3, **kwargs) |
(...skipping 752 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1029 # Returns name of current branch or None for detached HEAD | 1022 # Returns name of current branch or None for detached HEAD |
1030 branch = self._Capture(['rev-parse', '--abbrev-ref=strict', 'HEAD']) | 1023 branch = self._Capture(['rev-parse', '--abbrev-ref=strict', 'HEAD']) |
1031 if branch == 'HEAD': | 1024 if branch == 'HEAD': |
1032 return None | 1025 return None |
1033 return branch | 1026 return branch |
1034 | 1027 |
1035 def _Capture(self, args, cwd=None): | 1028 def _Capture(self, args, cwd=None): |
1036 return subprocess2.check_output( | 1029 return subprocess2.check_output( |
1037 ['git'] + args, | 1030 ['git'] + args, |
1038 stderr=subprocess2.VOID, | 1031 stderr=subprocess2.VOID, |
1039 nag_timer=self.nag_timer, | |
1040 nag_max=self.nag_max, | |
1041 cwd=cwd or self.checkout_path).strip() | 1032 cwd=cwd or self.checkout_path).strip() |
1042 | 1033 |
1043 def _UpdateBranchHeads(self, options, fetch=False): | 1034 def _UpdateBranchHeads(self, options, fetch=False): |
1044 """Adds, and optionally fetches, "branch-heads" refspecs if requested.""" | 1035 """Adds, and optionally fetches, "branch-heads" refspecs if requested.""" |
1045 if hasattr(options, 'with_branch_heads') and options.with_branch_heads: | 1036 if hasattr(options, 'with_branch_heads') and options.with_branch_heads: |
1046 backoff_time = 5 | 1037 backoff_time = 5 |
1047 for _ in range(3): | 1038 for _ in range(3): |
1048 try: | 1039 try: |
1049 config_cmd = ['config', 'remote.origin.fetch', | 1040 config_cmd = ['config', 'remote.origin.fetch', |
1050 '+refs/branch-heads/*:refs/remotes/branch-heads/*', | 1041 '+refs/branch-heads/*:refs/remotes/branch-heads/*', |
1051 '^\\+refs/branch-heads/\\*:.*$'] | 1042 '^\\+refs/branch-heads/\\*:.*$'] |
1052 self._Run(config_cmd, options) | 1043 self._Run(config_cmd, options) |
1053 if fetch: | 1044 if fetch: |
1054 fetch_cmd = ['-c', 'core.deltaBaseCacheLimit=2g', 'fetch', 'origin'] | 1045 fetch_cmd = ['-c', 'core.deltaBaseCacheLimit=2g', 'fetch', 'origin'] |
1055 if options.verbose: | 1046 if options.verbose: |
1056 fetch_cmd.append('--verbose') | 1047 fetch_cmd.append('--verbose') |
1057 self._Run(fetch_cmd, options) | 1048 self._Run(fetch_cmd, options) |
1058 break | 1049 break |
1059 except subprocess2.CalledProcessError, e: | 1050 except subprocess2.CalledProcessError, e: |
1060 print(str(e)) | 1051 print(str(e)) |
1061 print('Retrying in %.1f seconds...' % backoff_time) | 1052 print('Retrying in %.1f seconds...' % backoff_time) |
1062 time.sleep(backoff_time) | 1053 time.sleep(backoff_time) |
1063 backoff_time *= 1.3 | 1054 backoff_time *= 1.3 |
1064 | 1055 |
1065 def _Run(self, args, _options, git_filter=False, **kwargs): | 1056 def _Run(self, args, _options, git_filter=False, **kwargs): |
1066 kwargs.setdefault('cwd', self.checkout_path) | 1057 kwargs.setdefault('cwd', self.checkout_path) |
1067 kwargs.setdefault('nag_timer', self.nag_timer) | |
1068 kwargs.setdefault('nag_max', self.nag_max) | |
1069 if git_filter: | 1058 if git_filter: |
1070 kwargs['filter_fn'] = GitFilter(kwargs['nag_timer'] / 2, | 1059 kwargs['filter_fn'] = GitFilter(kwargs.get('filter_fn')) |
1071 kwargs.get('filter_fn')) | |
1072 kwargs.setdefault('print_stdout', False) | 1060 kwargs.setdefault('print_stdout', False) |
1073 # Don't prompt for passwords; just fail quickly and noisily. | 1061 # Don't prompt for passwords; just fail quickly and noisily. |
1074 # By default, git will use an interactive terminal prompt when a username/ | 1062 # By default, git will use an interactive terminal prompt when a username/ |
1075 # password is needed. That shouldn't happen in the chromium workflow, | 1063 # password is needed. That shouldn't happen in the chromium workflow, |
1076 # and if it does, then gclient may hide the prompt in the midst of a flood | 1064 # and if it does, then gclient may hide the prompt in the midst of a flood |
1077 # of terminal spew. The only indication that something has gone wrong | 1065 # of terminal spew. The only indication that something has gone wrong |
1078 # will be when gclient hangs unresponsively. Instead, we disable the | 1066 # will be when gclient hangs unresponsively. Instead, we disable the |
1079 # password prompt and simply allow git to fail noisily. The error | 1067 # password prompt and simply allow git to fail noisily. The error |
1080 # message produced by git will be copied to gclient's output. | 1068 # message produced by git will be copied to gclient's output. |
1081 env = kwargs.get('env') or kwargs.setdefault('env', os.environ.copy()) | 1069 env = kwargs.get('env') or kwargs.setdefault('env', os.environ.copy()) |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1129 def pack(self, _options, args, _file_list): | 1117 def pack(self, _options, args, _file_list): |
1130 """Generates a patch file which can be applied to the root of the | 1118 """Generates a patch file which can be applied to the root of the |
1131 repository.""" | 1119 repository.""" |
1132 if not os.path.isdir(self.checkout_path): | 1120 if not os.path.isdir(self.checkout_path): |
1133 raise gclient_utils.Error('Directory %s is not present.' % | 1121 raise gclient_utils.Error('Directory %s is not present.' % |
1134 self.checkout_path) | 1122 self.checkout_path) |
1135 gclient_utils.CheckCallAndFilter( | 1123 gclient_utils.CheckCallAndFilter( |
1136 ['svn', 'diff', '-x', '--ignore-eol-style'] + args, | 1124 ['svn', 'diff', '-x', '--ignore-eol-style'] + args, |
1137 cwd=self.checkout_path, | 1125 cwd=self.checkout_path, |
1138 print_stdout=False, | 1126 print_stdout=False, |
1139 nag_timer=self.nag_timer, | |
1140 nag_max=self.nag_max, | |
1141 filter_fn=SvnDiffFilterer(self.relpath).Filter) | 1127 filter_fn=SvnDiffFilterer(self.relpath).Filter) |
1142 | 1128 |
1143 def update(self, options, args, file_list): | 1129 def update(self, options, args, file_list): |
1144 """Runs svn to update or transparently checkout the working copy. | 1130 """Runs svn to update or transparently checkout the working copy. |
1145 | 1131 |
1146 All updated files will be appended to file_list. | 1132 All updated files will be appended to file_list. |
1147 | 1133 |
1148 Raises: | 1134 Raises: |
1149 Error: if can't get URL for relative path. | 1135 Error: if can't get URL for relative path. |
1150 """ | 1136 """ |
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1435 'correct.') % rev) | 1421 'correct.') % rev) |
1436 return rev | 1422 return rev |
1437 | 1423 |
1438 def FullUrlForRelativeUrl(self, url): | 1424 def FullUrlForRelativeUrl(self, url): |
1439 # Find the forth '/' and strip from there. A bit hackish. | 1425 # Find the forth '/' and strip from there. A bit hackish. |
1440 return '/'.join(self.url.split('/')[:4]) + url | 1426 return '/'.join(self.url.split('/')[:4]) + url |
1441 | 1427 |
1442 def _Run(self, args, options, **kwargs): | 1428 def _Run(self, args, options, **kwargs): |
1443 """Runs a commands that goes to stdout.""" | 1429 """Runs a commands that goes to stdout.""" |
1444 kwargs.setdefault('cwd', self.checkout_path) | 1430 kwargs.setdefault('cwd', self.checkout_path) |
1445 kwargs.setdefault('nag_timer', self.nag_timer) | |
1446 kwargs.setdefault('nag_max', self.nag_max) | |
1447 gclient_utils.CheckCallAndFilterAndHeader(['svn'] + args, | 1431 gclient_utils.CheckCallAndFilterAndHeader(['svn'] + args, |
1448 always=options.verbose, **kwargs) | 1432 always=options.verbose, **kwargs) |
1449 | 1433 |
1450 def Svnversion(self): | 1434 def Svnversion(self): |
1451 """Runs the lowest checked out revision in the current project.""" | 1435 """Runs the lowest checked out revision in the current project.""" |
1452 info = scm.SVN.CaptureLocalInfo([], os.path.join(self.checkout_path, '.')) | 1436 info = scm.SVN.CaptureLocalInfo([], os.path.join(self.checkout_path, '.')) |
1453 return info['Revision'] | 1437 return info['Revision'] |
1454 | 1438 |
1455 def _RunAndGetFileList(self, args, options, file_list, cwd=None): | 1439 def _RunAndGetFileList(self, args, options, file_list, cwd=None): |
1456 """Runs a commands that goes to stdout and grabs the file listed.""" | 1440 """Runs a commands that goes to stdout and grabs the file listed.""" |
(...skipping 27 matching lines...) Expand all Loading... |
1484 new_command.append('--force') | 1468 new_command.append('--force') |
1485 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: | 1469 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: |
1486 new_command.extend(('--accept', 'theirs-conflict')) | 1470 new_command.extend(('--accept', 'theirs-conflict')) |
1487 elif options.manually_grab_svn_rev: | 1471 elif options.manually_grab_svn_rev: |
1488 new_command.append('--force') | 1472 new_command.append('--force') |
1489 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: | 1473 if command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: |
1490 new_command.extend(('--accept', 'postpone')) | 1474 new_command.extend(('--accept', 'postpone')) |
1491 elif command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: | 1475 elif command[0] != 'checkout' and scm.SVN.AssertVersion('1.6')[0]: |
1492 new_command.extend(('--accept', 'postpone')) | 1476 new_command.extend(('--accept', 'postpone')) |
1493 return new_command | 1477 return new_command |
OLD | NEW |