OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 """Meta checkout manager supporting both Subversion and GIT.""" | 6 """Meta checkout manager supporting both Subversion and GIT.""" |
7 # Files | 7 # Files |
8 # .gclient : Current client configuration, written by 'config' command. | 8 # .gclient : Current client configuration, written by 'config' command. |
9 # Format is a Python script defining 'solutions', a list whose | 9 # Format is a Python script defining 'solutions', a list whose |
10 # entries each are maps binding the strings "name" and "url" | 10 # entries each are maps binding the strings "name" and "url" |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
206 if var_name in self._custom_vars: | 206 if var_name in self._custom_vars: |
207 return self._custom_vars[var_name] | 207 return self._custom_vars[var_name] |
208 elif var_name in self._local_scope.get("vars", {}): | 208 elif var_name in self._local_scope.get("vars", {}): |
209 return self._local_scope["vars"][var_name] | 209 return self._local_scope["vars"][var_name] |
210 raise gclient_utils.Error("Var is not defined: %s" % var_name) | 210 raise gclient_utils.Error("Var is not defined: %s" % var_name) |
211 | 211 |
212 | 212 |
213 class DependencySettings(GClientKeywords): | 213 class DependencySettings(GClientKeywords): |
214 """Immutable configuration settings.""" | 214 """Immutable configuration settings.""" |
215 def __init__( | 215 def __init__( |
216 self, parent, url, managed, custom_deps, custom_vars, | 216 self, parent, url, safesync_url, managed, custom_deps, custom_vars, |
217 custom_hooks, deps_file, should_process): | 217 custom_hooks, deps_file, should_process): |
218 GClientKeywords.__init__(self) | 218 GClientKeywords.__init__(self) |
219 | 219 |
220 # These are not mutable: | 220 # These are not mutable: |
221 self._parent = parent | 221 self._parent = parent |
| 222 self._safesync_url = safesync_url |
222 self._deps_file = deps_file | 223 self._deps_file = deps_file |
223 self._url = url | 224 self._url = url |
224 # 'managed' determines whether or not this dependency is synced/updated by | 225 # 'managed' determines whether or not this dependency is synced/updated by |
225 # gclient after gclient checks it out initially. The difference between | 226 # gclient after gclient checks it out initially. The difference between |
226 # 'managed' and 'should_process' is that the user specifies 'managed' via | 227 # 'managed' and 'should_process' is that the user specifies 'managed' via |
227 # the --managed command-line flag or a .gclient config, where | 228 # the --unmanaged command-line flag or a .gclient config, where |
228 # 'should_process' is dynamically set by gclient if it goes over its | 229 # 'should_process' is dynamically set by gclient if it goes over its |
229 # recursion limit and controls gclient's behavior so it does not misbehave. | 230 # recursion limit and controls gclient's behavior so it does not misbehave. |
230 self._managed = managed | 231 self._managed = managed |
231 self._should_process = should_process | 232 self._should_process = should_process |
232 # This is a mutable value which has the list of 'target_os' OSes listed in | 233 # This is a mutable value which has the list of 'target_os' OSes listed in |
233 # the current deps file. | 234 # the current deps file. |
234 self.local_target_os = None | 235 self.local_target_os = None |
235 | 236 |
236 # These are only set in .gclient and not in DEPS files. | 237 # These are only set in .gclient and not in DEPS files. |
237 self._custom_vars = custom_vars or {} | 238 self._custom_vars = custom_vars or {} |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
274 | 275 |
275 @property | 276 @property |
276 def root(self): | 277 def root(self): |
277 """Returns the root node, a GClient object.""" | 278 """Returns the root node, a GClient object.""" |
278 if not self.parent: | 279 if not self.parent: |
279 # This line is to signal pylint that it could be a GClient instance. | 280 # This line is to signal pylint that it could be a GClient instance. |
280 return self or GClient(None, None) | 281 return self or GClient(None, None) |
281 return self.parent.root | 282 return self.parent.root |
282 | 283 |
283 @property | 284 @property |
| 285 def safesync_url(self): |
| 286 return self._safesync_url |
| 287 |
| 288 @property |
284 def should_process(self): | 289 def should_process(self): |
285 """True if this dependency should be processed, i.e. checked out.""" | 290 """True if this dependency should be processed, i.e. checked out.""" |
286 return self._should_process | 291 return self._should_process |
287 | 292 |
288 @property | 293 @property |
289 def custom_vars(self): | 294 def custom_vars(self): |
290 return self._custom_vars.copy() | 295 return self._custom_vars.copy() |
291 | 296 |
292 @property | 297 @property |
293 def custom_deps(self): | 298 def custom_deps(self): |
(...skipping 18 matching lines...) Expand all Loading... |
312 """Returns a custom deps if applicable.""" | 317 """Returns a custom deps if applicable.""" |
313 if self.parent: | 318 if self.parent: |
314 url = self.parent.get_custom_deps(name, url) | 319 url = self.parent.get_custom_deps(name, url) |
315 # None is a valid return value to disable a dependency. | 320 # None is a valid return value to disable a dependency. |
316 return self.custom_deps.get(name, url) | 321 return self.custom_deps.get(name, url) |
317 | 322 |
318 | 323 |
319 class Dependency(gclient_utils.WorkItem, DependencySettings): | 324 class Dependency(gclient_utils.WorkItem, DependencySettings): |
320 """Object that represents a dependency checkout.""" | 325 """Object that represents a dependency checkout.""" |
321 | 326 |
322 def __init__(self, parent, name, url, managed, custom_deps, | 327 def __init__(self, parent, name, url, safesync_url, managed, custom_deps, |
323 custom_vars, custom_hooks, deps_file, should_process): | 328 custom_vars, custom_hooks, deps_file, should_process): |
324 gclient_utils.WorkItem.__init__(self, name) | 329 gclient_utils.WorkItem.__init__(self, name) |
325 DependencySettings.__init__( | 330 DependencySettings.__init__( |
326 self, parent, url, managed, custom_deps, custom_vars, | 331 self, parent, url, safesync_url, managed, custom_deps, custom_vars, |
327 custom_hooks, deps_file, should_process) | 332 custom_hooks, deps_file, should_process) |
328 | 333 |
329 # This is in both .gclient and DEPS files: | 334 # This is in both .gclient and DEPS files: |
330 self._deps_hooks = [] | 335 self._deps_hooks = [] |
331 | 336 |
332 self._pre_deps_hooks = [] | 337 self._pre_deps_hooks = [] |
333 | 338 |
334 # Calculates properties: | 339 # Calculates properties: |
335 self._parsed_url = None | 340 self._parsed_url = None |
336 self._dependencies = [] | 341 self._dependencies = [] |
(...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
715 # Convert the deps into real Dependency. | 720 # Convert the deps into real Dependency. |
716 deps_to_add = [] | 721 deps_to_add = [] |
717 for name, url in deps.iteritems(): | 722 for name, url in deps.iteritems(): |
718 should_process = self.recursion_limit and self.should_process | 723 should_process = self.recursion_limit and self.should_process |
719 deps_file = self.deps_file | 724 deps_file = self.deps_file |
720 if self.recursedeps is not None: | 725 if self.recursedeps is not None: |
721 ent = self.recursedeps.get(name) | 726 ent = self.recursedeps.get(name) |
722 if ent is not None: | 727 if ent is not None: |
723 deps_file = ent['deps_file'] | 728 deps_file = ent['deps_file'] |
724 deps_to_add.append(Dependency( | 729 deps_to_add.append(Dependency( |
725 self, name, url, None, None, self.custom_vars, None, | 730 self, name, url, None, None, None, self.custom_vars, None, |
726 deps_file, should_process)) | 731 deps_file, should_process)) |
727 deps_to_add.sort(key=lambda x: x.name) | 732 deps_to_add.sort(key=lambda x: x.name) |
728 | 733 |
729 # override named sets of hooks by the custom hooks | 734 # override named sets of hooks by the custom hooks |
730 hooks_to_run = [] | 735 hooks_to_run = [] |
731 hook_names_to_suppress = [c.get('name', '') for c in self.custom_hooks] | 736 hook_names_to_suppress = [c.get('name', '') for c in self.custom_hooks] |
732 for hook in local_scope.get('hooks', []): | 737 for hook in local_scope.get('hooks', []): |
733 if hook.get('name', '') not in hook_names_to_suppress: | 738 if hook.get('name', '') not in hook_names_to_suppress: |
734 hooks_to_run.append(hook) | 739 hooks_to_run.append(hook) |
735 | 740 |
(...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1122 | 1127 |
1123 @property | 1128 @property |
1124 def file_list_and_children(self): | 1129 def file_list_and_children(self): |
1125 result = list(self.file_list) | 1130 result = list(self.file_list) |
1126 for d in self.dependencies: | 1131 for d in self.dependencies: |
1127 result.extend(d.file_list_and_children) | 1132 result.extend(d.file_list_and_children) |
1128 return tuple(result) | 1133 return tuple(result) |
1129 | 1134 |
1130 def __str__(self): | 1135 def __str__(self): |
1131 out = [] | 1136 out = [] |
1132 for i in ('name', 'url', 'parsed_url', 'custom_deps', | 1137 for i in ('name', 'url', 'parsed_url', 'safesync_url', 'custom_deps', |
1133 'custom_vars', 'deps_hooks', 'file_list', 'should_process', | 1138 'custom_vars', 'deps_hooks', 'file_list', 'should_process', |
1134 'processed', 'hooks_ran', 'deps_parsed', 'requirements', | 1139 'processed', 'hooks_ran', 'deps_parsed', 'requirements', |
1135 'allowed_hosts'): | 1140 'allowed_hosts'): |
1136 # First try the native property if it exists. | 1141 # First try the native property if it exists. |
1137 if hasattr(self, '_' + i): | 1142 if hasattr(self, '_' + i): |
1138 value = getattr(self, '_' + i, False) | 1143 value = getattr(self, '_' + i, False) |
1139 else: | 1144 else: |
1140 value = getattr(self, i, False) | 1145 value = getattr(self, i, False) |
1141 if value: | 1146 if value: |
1142 out.append('%s: %s' % (i, value)) | 1147 out.append('%s: %s' % (i, value)) |
(...skipping 28 matching lines...) Expand all Loading... |
1171 "mac": "mac", | 1176 "mac": "mac", |
1172 "unix": "unix", | 1177 "unix": "unix", |
1173 "linux": "unix", | 1178 "linux": "unix", |
1174 "linux2": "unix", | 1179 "linux2": "unix", |
1175 "linux3": "unix", | 1180 "linux3": "unix", |
1176 "android": "android", | 1181 "android": "android", |
1177 } | 1182 } |
1178 | 1183 |
1179 DEFAULT_CLIENT_FILE_TEXT = ("""\ | 1184 DEFAULT_CLIENT_FILE_TEXT = ("""\ |
1180 solutions = [ | 1185 solutions = [ |
1181 { | 1186 { "name" : "%(solution_name)s", |
1182 "name" : "%(solution_name)s", | |
1183 "url" : "%(solution_url)s", | 1187 "url" : "%(solution_url)s", |
1184 "deps_file" : "%(deps_file)s", | 1188 "deps_file" : "%(deps_file)s", |
1185 "managed" : %(managed)s, | 1189 "managed" : %(managed)s, |
1186 "custom_deps" : {}, | 1190 "custom_deps" : { |
| 1191 }, |
| 1192 "safesync_url": "%(safesync_url)s", |
1187 }, | 1193 }, |
1188 ] | 1194 ] |
1189 cache_dir = %(cache_dir)r | 1195 cache_dir = %(cache_dir)r |
1190 """) | 1196 """) |
1191 | 1197 |
1192 DEFAULT_SNAPSHOT_SOLUTION_TEXT = ("""\ | 1198 DEFAULT_SNAPSHOT_SOLUTION_TEXT = ("""\ |
1193 { | 1199 { "name" : "%(solution_name)s", |
1194 "name" : "%(solution_name)s", | |
1195 "url" : "%(solution_url)s", | 1200 "url" : "%(solution_url)s", |
1196 "deps_file" : "%(deps_file)s", | 1201 "deps_file" : "%(deps_file)s", |
1197 "managed" : %(managed)s, | 1202 "managed" : %(managed)s, |
1198 "custom_deps" : { | 1203 "custom_deps" : { |
1199 %(solution_deps)s | 1204 %(solution_deps)s }, |
1200 }, | 1205 "safesync_url": "%(safesync_url)s", |
1201 }, | 1206 }, |
1202 """) | 1207 """) |
1203 | 1208 |
1204 DEFAULT_SNAPSHOT_FILE_TEXT = ("""\ | 1209 DEFAULT_SNAPSHOT_FILE_TEXT = ("""\ |
1205 # Snapshot generated with gclient revinfo --snapshot | 1210 # Snapshot generated with gclient revinfo --snapshot |
1206 solutions = [ | 1211 solutions = [ |
1207 %(solution_list)s] | 1212 %(solution_list)s] |
1208 """) | 1213 """) |
1209 | 1214 |
1210 def __init__(self, root_dir, options): | 1215 def __init__(self, root_dir, options): |
1211 # Do not change previous behavior. Only solution level and immediate DEPS | 1216 # Do not change previous behavior. Only solution level and immediate DEPS |
1212 # are processed. | 1217 # are processed. |
1213 self._recursion_limit = 2 | 1218 self._recursion_limit = 2 |
1214 Dependency.__init__(self, None, None, None, True, None, None, None, | 1219 Dependency.__init__(self, None, None, None, None, True, None, None, None, |
1215 'unused', True) | 1220 'unused', True) |
1216 self._options = options | 1221 self._options = options |
1217 if options.deps_os: | 1222 if options.deps_os: |
1218 enforced_os = options.deps_os.split(',') | 1223 enforced_os = options.deps_os.split(',') |
1219 else: | 1224 else: |
1220 enforced_os = [self.DEPS_OS_CHOICES.get(sys.platform, 'unix')] | 1225 enforced_os = [self.DEPS_OS_CHOICES.get(sys.platform, 'unix')] |
1221 if 'all' in enforced_os: | 1226 if 'all' in enforced_os: |
1222 enforced_os = self.DEPS_OS_CHOICES.itervalues() | 1227 enforced_os = self.DEPS_OS_CHOICES.itervalues() |
1223 self._enforced_os = tuple(set(enforced_os)) | 1228 self._enforced_os = tuple(set(enforced_os)) |
1224 self._root_dir = root_dir | 1229 self._root_dir = root_dir |
(...skipping 20 matching lines...) Expand all Loading... |
1245 | 1250 |
1246 The .gclient file contains: | 1251 The .gclient file contains: |
1247 URL: %(expected_url)s (%(expected_scm)s) | 1252 URL: %(expected_url)s (%(expected_scm)s) |
1248 Cache mirror: %(mirror_string)s | 1253 Cache mirror: %(mirror_string)s |
1249 | 1254 |
1250 The local checkout in %(checkout_path)s reports: | 1255 The local checkout in %(checkout_path)s reports: |
1251 %(actual_url)s (%(actual_scm)s) | 1256 %(actual_url)s (%(actual_scm)s) |
1252 | 1257 |
1253 You should ensure that the URL listed in .gclient is correct and either change | 1258 You should ensure that the URL listed in .gclient is correct and either change |
1254 it or fix the checkout. If you're managing your own git checkout in | 1259 it or fix the checkout. If you're managing your own git checkout in |
1255 %(checkout_path)s but the URL in .gclient is for an svn repository, you should | 1260 %(checkout_path)s but the URL in .gclient is for an svn repository, you probably |
1256 set 'managed': False in .gclient. | 1261 want to set 'managed': False in .gclient. |
1257 ''' % {'checkout_path': os.path.join(self.root_dir, dep.name), | 1262 ''' % {'checkout_path': os.path.join(self.root_dir, dep.name), |
1258 'expected_url': dep.url, | 1263 'expected_url': dep.url, |
1259 'expected_scm': gclient_scm.GetScmName(dep.url), | 1264 'expected_scm': gclient_scm.GetScmName(dep.url), |
1260 'mirror_string' : mirror_string, | 1265 'mirror_string' : mirror_string, |
1261 'actual_url': actual_url, | 1266 'actual_url': actual_url, |
1262 'actual_scm': gclient_scm.GetScmName(actual_url)}) | 1267 'actual_scm': gclient_scm.GetScmName(actual_url)}) |
1263 | 1268 |
1264 def SetConfig(self, content): | 1269 def SetConfig(self, content): |
1265 assert not self.dependencies | 1270 assert not self.dependencies |
1266 config_dict = {} | 1271 config_dict = {} |
(...skipping 20 matching lines...) Expand all Loading... |
1287 cache_dir, '--force', '--all']) | 1292 cache_dir, '--force', '--all']) |
1288 gclient_scm.GitWrapper.cache_dir = cache_dir | 1293 gclient_scm.GitWrapper.cache_dir = cache_dir |
1289 git_cache.Mirror.SetCachePath(cache_dir) | 1294 git_cache.Mirror.SetCachePath(cache_dir) |
1290 | 1295 |
1291 if not target_os and config_dict.get('target_os_only', False): | 1296 if not target_os and config_dict.get('target_os_only', False): |
1292 raise gclient_utils.Error('Can\'t use target_os_only if target_os is ' | 1297 raise gclient_utils.Error('Can\'t use target_os_only if target_os is ' |
1293 'not specified') | 1298 'not specified') |
1294 | 1299 |
1295 deps_to_add = [] | 1300 deps_to_add = [] |
1296 for s in config_dict.get('solutions', []): | 1301 for s in config_dict.get('solutions', []): |
1297 if s.get('safesync_url'): | |
1298 raise gclient_utils.Error('safesync_url is not supported anymore. ' | |
1299 'Please remove it from your .gclient file.') | |
1300 try: | 1302 try: |
1301 deps_to_add.append(Dependency( | 1303 deps_to_add.append(Dependency( |
1302 self, s['name'], s['url'], | 1304 self, s['name'], s['url'], |
1303 s.get('managed', False), | 1305 s.get('safesync_url', None), |
| 1306 s.get('managed', True), |
1304 s.get('custom_deps', {}), | 1307 s.get('custom_deps', {}), |
1305 s.get('custom_vars', {}), | 1308 s.get('custom_vars', {}), |
1306 s.get('custom_hooks', []), | 1309 s.get('custom_hooks', []), |
1307 s.get('deps_file', 'DEPS'), | 1310 s.get('deps_file', 'DEPS'), |
1308 True)) | 1311 True)) |
1309 except KeyError: | 1312 except KeyError: |
1310 raise gclient_utils.Error('Invalid .gclient file. Solution is ' | 1313 raise gclient_utils.Error('Invalid .gclient file. Solution is ' |
1311 'incomplete: %s' % s) | 1314 'incomplete: %s' % s) |
1312 self.add_dependencies_and_close(deps_to_add, config_dict.get('hooks', [])) | 1315 self.add_dependencies_and_close(deps_to_add, config_dict.get('hooks', [])) |
1313 logging.info('SetConfig() done') | 1316 logging.info('SetConfig() done') |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1419 ('You must specify the full solution name like --revision %s@%s\n' | 1422 ('You must specify the full solution name like --revision %s@%s\n' |
1420 'when you have multiple solutions setup in your .gclient file.\n' | 1423 'when you have multiple solutions setup in your .gclient file.\n' |
1421 'Other solutions present are: %s.') % ( | 1424 'Other solutions present are: %s.') % ( |
1422 client.dependencies[0].name, | 1425 client.dependencies[0].name, |
1423 options.revisions[0], | 1426 options.revisions[0], |
1424 ', '.join(s.name for s in client.dependencies[1:])), | 1427 ', '.join(s.name for s in client.dependencies[1:])), |
1425 file=sys.stderr) | 1428 file=sys.stderr) |
1426 return client | 1429 return client |
1427 | 1430 |
1428 def SetDefaultConfig(self, solution_name, deps_file, solution_url, | 1431 def SetDefaultConfig(self, solution_name, deps_file, solution_url, |
1429 managed=False, cache_dir=None): | 1432 safesync_url, managed=True, cache_dir=None): |
1430 self.SetConfig(self.DEFAULT_CLIENT_FILE_TEXT % { | 1433 self.SetConfig(self.DEFAULT_CLIENT_FILE_TEXT % { |
1431 'solution_name': solution_name, | 1434 'solution_name': solution_name, |
1432 'solution_url': solution_url, | 1435 'solution_url': solution_url, |
1433 'deps_file': deps_file, | 1436 'deps_file': deps_file, |
| 1437 'safesync_url' : safesync_url, |
1434 'managed': managed, | 1438 'managed': managed, |
1435 'cache_dir': cache_dir, | 1439 'cache_dir': cache_dir, |
1436 }) | 1440 }) |
1437 | 1441 |
1438 def _SaveEntries(self): | 1442 def _SaveEntries(self): |
1439 """Creates a .gclient_entries file to record the list of unique checkouts. | 1443 """Creates a .gclient_entries file to record the list of unique checkouts. |
1440 | 1444 |
1441 The .gclient_entries file lives in the same directory as .gclient. | 1445 The .gclient_entries file lives in the same directory as .gclient. |
1442 """ | 1446 """ |
1443 # Sometimes pprint.pformat will use {', sometimes it'll use { ' ... It | 1447 # Sometimes pprint.pformat will use {', sometimes it'll use { ' ... It |
(...skipping 22 matching lines...) Expand all Loading... |
1466 return {} | 1470 return {} |
1467 try: | 1471 try: |
1468 exec(gclient_utils.FileRead(filename), scope) | 1472 exec(gclient_utils.FileRead(filename), scope) |
1469 except SyntaxError as e: | 1473 except SyntaxError as e: |
1470 gclient_utils.SyntaxErrorToError(filename, e) | 1474 gclient_utils.SyntaxErrorToError(filename, e) |
1471 return scope['entries'] | 1475 return scope['entries'] |
1472 | 1476 |
1473 def _EnforceRevisions(self): | 1477 def _EnforceRevisions(self): |
1474 """Checks for revision overrides.""" | 1478 """Checks for revision overrides.""" |
1475 revision_overrides = {} | 1479 revision_overrides = {} |
| 1480 if self._options.head: |
| 1481 return revision_overrides |
| 1482 # Do not check safesync_url if one or more --revision flag is specified. |
1476 if not self._options.revisions: | 1483 if not self._options.revisions: |
1477 for s in self.dependencies: | 1484 for s in self.dependencies: |
1478 if not s.managed and not self._options.__dict__.get('head', False): | 1485 if not s.managed: |
1479 self._options.revisions.append('%s@unmanaged' % s.name) | 1486 self._options.revisions.append('%s@unmanaged' % s.name) |
| 1487 elif s.safesync_url: |
| 1488 self._ApplySafeSyncRev(dep=s) |
1480 if not self._options.revisions: | 1489 if not self._options.revisions: |
1481 return revision_overrides | 1490 return revision_overrides |
1482 solutions_names = [s.name for s in self.dependencies] | 1491 solutions_names = [s.name for s in self.dependencies] |
1483 for i, revision in enumerate(self._options.revisions): | 1492 index = 0 |
1484 if '@' in revision: | 1493 for revision in self._options.revisions: |
1485 name, rev = revision.split('@', 1) | 1494 if not '@' in revision: |
1486 else: | |
1487 # Support for --revision 123 | 1495 # Support for --revision 123 |
1488 name, rev = solutions_names[i], revision | 1496 revision = '%s@%s' % (solutions_names[index], revision) |
| 1497 name, rev = revision.split('@', 1) |
1489 revision_overrides[name] = rev | 1498 revision_overrides[name] = rev |
| 1499 index += 1 |
1490 return revision_overrides | 1500 return revision_overrides |
1491 | 1501 |
| 1502 def _ApplySafeSyncRev(self, dep): |
| 1503 """Finds a valid revision from the content of the safesync_url and apply it |
| 1504 by appending revisions to the revision list. Throws if revision appears to |
| 1505 be invalid for the given |dep|.""" |
| 1506 assert len(dep.safesync_url) > 0 |
| 1507 handle = urllib.urlopen(dep.safesync_url) |
| 1508 rev = handle.read().strip() |
| 1509 handle.close() |
| 1510 if not rev: |
| 1511 raise gclient_utils.Error( |
| 1512 'It appears your safesync_url (%s) is not working properly\n' |
| 1513 '(as it returned an empty response). Check your config.' % |
| 1514 dep.safesync_url) |
| 1515 scm = gclient_scm.CreateSCM( |
| 1516 dep.url, dep.root.root_dir, dep.name, self.outbuf) |
| 1517 safe_rev = scm.GetUsableRev(rev, self._options) |
| 1518 if self._options.verbose: |
| 1519 print('Using safesync_url revision: %s.\n' % safe_rev) |
| 1520 self._options.revisions.append('%s@%s' % (dep.name, safe_rev)) |
| 1521 |
1492 def RunOnDeps(self, command, args, ignore_requirements=False, progress=True): | 1522 def RunOnDeps(self, command, args, ignore_requirements=False, progress=True): |
1493 """Runs a command on each dependency in a client and its dependencies. | 1523 """Runs a command on each dependency in a client and its dependencies. |
1494 | 1524 |
1495 Args: | 1525 Args: |
1496 command: The command to use (e.g., 'status' or 'diff') | 1526 command: The command to use (e.g., 'status' or 'diff') |
1497 args: list of str - extra arguments to add to the command line. | 1527 args: list of str - extra arguments to add to the command line. |
1498 """ | 1528 """ |
1499 if not self.dependencies: | 1529 if not self.dependencies: |
1500 raise gclient_utils.Error('No solution specified') | 1530 raise gclient_utils.Error('No solution specified') |
1501 | 1531 |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1666 for k in sorted(entries.keys()): | 1696 for k in sorted(entries.keys()): |
1667 if entries[k]: | 1697 if entries[k]: |
1668 # Quotes aren't escaped... | 1698 # Quotes aren't escaped... |
1669 custom_deps.append(' \"%s\": \'%s\',\n' % (k, entries[k])) | 1699 custom_deps.append(' \"%s\": \'%s\',\n' % (k, entries[k])) |
1670 else: | 1700 else: |
1671 custom_deps.append(' \"%s\": None,\n' % k) | 1701 custom_deps.append(' \"%s\": None,\n' % k) |
1672 new_gclient += self.DEFAULT_SNAPSHOT_SOLUTION_TEXT % { | 1702 new_gclient += self.DEFAULT_SNAPSHOT_SOLUTION_TEXT % { |
1673 'solution_name': d.name, | 1703 'solution_name': d.name, |
1674 'solution_url': d.url, | 1704 'solution_url': d.url, |
1675 'deps_file': d.deps_file, | 1705 'deps_file': d.deps_file, |
| 1706 'safesync_url' : d.safesync_url or '', |
1676 'managed': d.managed, | 1707 'managed': d.managed, |
1677 'solution_deps': ''.join(custom_deps), | 1708 'solution_deps': ''.join(custom_deps), |
1678 } | 1709 } |
1679 # Print the snapshot configuration file | 1710 # Print the snapshot configuration file |
1680 print(self.DEFAULT_SNAPSHOT_FILE_TEXT % {'solution_list': new_gclient}) | 1711 print(self.DEFAULT_SNAPSHOT_FILE_TEXT % {'solution_list': new_gclient}) |
1681 else: | 1712 else: |
1682 entries = {} | 1713 entries = {} |
1683 for d in self.root.subtree(False): | 1714 for d in self.root.subtree(False): |
1684 if self._options.actual: | 1715 if self._options.actual: |
1685 entries[d.name] = GetURLAndRev(d) | 1716 entries[d.name] = GetURLAndRev(d) |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1831 def CMDroot(parser, args): | 1862 def CMDroot(parser, args): |
1832 """Outputs the solution root (or current dir if there isn't one).""" | 1863 """Outputs the solution root (or current dir if there isn't one).""" |
1833 (options, args) = parser.parse_args(args) | 1864 (options, args) = parser.parse_args(args) |
1834 client = GClient.LoadCurrentConfig(options) | 1865 client = GClient.LoadCurrentConfig(options) |
1835 if client: | 1866 if client: |
1836 print(os.path.abspath(client.root_dir)) | 1867 print(os.path.abspath(client.root_dir)) |
1837 else: | 1868 else: |
1838 print(os.path.abspath('.')) | 1869 print(os.path.abspath('.')) |
1839 | 1870 |
1840 | 1871 |
1841 @subcommand.usage('[url]') | 1872 @subcommand.usage('[url] [safesync url]') |
1842 def CMDconfig(parser, args): | 1873 def CMDconfig(parser, args): |
1843 """Creates a .gclient file in the current directory. | 1874 """Creates a .gclient file in the current directory. |
1844 | 1875 |
1845 This specifies the configuration for further commands. After update/sync, | 1876 This specifies the configuration for further commands. After update/sync, |
1846 top-level DEPS files in each module are read to determine dependent | 1877 top-level DEPS files in each module are read to determine dependent |
1847 modules to operate on as well. If optional [url] parameter is | 1878 modules to operate on as well. If optional [url] parameter is |
1848 provided, then configuration is read from a specified Subversion server | 1879 provided, then configuration is read from a specified Subversion server |
1849 URL. | 1880 URL. |
1850 """ | 1881 """ |
1851 # We do a little dance with the --gclientfile option. 'gclient config' is the | 1882 # We do a little dance with the --gclientfile option. 'gclient config' is the |
1852 # only command where it's acceptable to have both '--gclientfile' and '--spec' | 1883 # only command where it's acceptable to have both '--gclientfile' and '--spec' |
1853 # arguments. So, we temporarily stash any --gclientfile parameter into | 1884 # arguments. So, we temporarily stash any --gclientfile parameter into |
1854 # options.output_config_file until after the (gclientfile xor spec) error | 1885 # options.output_config_file until after the (gclientfile xor spec) error |
1855 # check. | 1886 # check. |
1856 parser.remove_option('--gclientfile') | 1887 parser.remove_option('--gclientfile') |
1857 parser.add_option('--gclientfile', dest='output_config_file', | 1888 parser.add_option('--gclientfile', dest='output_config_file', |
1858 help='Specify an alternate .gclient file') | 1889 help='Specify an alternate .gclient file') |
1859 parser.add_option('--name', | 1890 parser.add_option('--name', |
1860 help='overrides the default name for the solution') | 1891 help='overrides the default name for the solution') |
1861 parser.add_option('--deps-file', default='DEPS', | 1892 parser.add_option('--deps-file', default='DEPS', |
1862 help='overrides the default name for the DEPS file for the' | 1893 help='overrides the default name for the DEPS file for the' |
1863 'main solutions and all sub-dependencies') | 1894 'main solutions and all sub-dependencies') |
1864 parser.add_option('--managed', action='store_true', default=False, | 1895 parser.add_option('--unmanaged', action='store_true', default=False, |
1865 help='overrides the default behavior to make it possible ' | 1896 help='overrides the default behavior to make it possible ' |
1866 'to have the main solution managed by gclient ' | 1897 'to have the main solution untouched by gclient ' |
1867 '(gclient will always auto-sync managed solutions ' | 1898 '(gclient will check out unmanaged dependencies but ' |
1868 ' rather than leaving them untouched)') | 1899 'will never sync them)') |
1869 parser.add_option('--unmanaged', action='store_true', default=True, | |
1870 help='This flag is a no-op; unmanaged is now the default.') | |
1871 parser.add_option('--cache-dir', | 1900 parser.add_option('--cache-dir', |
1872 help='(git only) Cache all git repos into this dir and do ' | 1901 help='(git only) Cache all git repos into this dir and do ' |
1873 'shared clones from the cache, instead of cloning ' | 1902 'shared clones from the cache, instead of cloning ' |
1874 'directly from the remote. (experimental)') | 1903 'directly from the remote. (experimental)') |
1875 parser.set_defaults(config_filename=None) | 1904 parser.set_defaults(config_filename=None) |
1876 (options, args) = parser.parse_args(args) | 1905 (options, args) = parser.parse_args(args) |
1877 if options.output_config_file: | 1906 if options.output_config_file: |
1878 setattr(options, 'config_filename', getattr(options, 'output_config_file')) | 1907 setattr(options, 'config_filename', getattr(options, 'output_config_file')) |
1879 if ((options.spec and args) or len(args) > 2 or | 1908 if ((options.spec and args) or len(args) > 2 or |
1880 (not options.spec and not args)): | 1909 (not options.spec and not args)): |
(...skipping 11 matching lines...) Expand all Loading... |
1892 else: | 1921 else: |
1893 # specify an alternate relpath for the given URL. | 1922 # specify an alternate relpath for the given URL. |
1894 name = options.name | 1923 name = options.name |
1895 if not os.path.abspath(os.path.join(os.getcwd(), name)).startswith( | 1924 if not os.path.abspath(os.path.join(os.getcwd(), name)).startswith( |
1896 os.getcwd()): | 1925 os.getcwd()): |
1897 parser.error('Do not pass a relative path for --name.') | 1926 parser.error('Do not pass a relative path for --name.') |
1898 if any(x in ('..', '.', '/', '\\') for x in name.split(os.sep)): | 1927 if any(x in ('..', '.', '/', '\\') for x in name.split(os.sep)): |
1899 parser.error('Do not include relative path components in --name.') | 1928 parser.error('Do not include relative path components in --name.') |
1900 | 1929 |
1901 deps_file = options.deps_file | 1930 deps_file = options.deps_file |
1902 client.SetDefaultConfig(name, deps_file, base_url, | 1931 safesync_url = '' |
1903 managed=options.managed, | 1932 if len(args) > 1: |
| 1933 safesync_url = args[1] |
| 1934 client.SetDefaultConfig(name, deps_file, base_url, safesync_url, |
| 1935 managed=not options.unmanaged, |
1904 cache_dir=options.cache_dir) | 1936 cache_dir=options.cache_dir) |
1905 client.SaveConfig() | 1937 client.SaveConfig() |
1906 return 0 | 1938 return 0 |
1907 | 1939 |
1908 | 1940 |
1909 @subcommand.epilog("""Example: | 1941 @subcommand.epilog("""Example: |
1910 gclient pack > patch.txt | 1942 gclient pack > patch.txt |
1911 generate simple patch for configured client and dependences | 1943 generate simple patch for configured client and dependences |
1912 """) | 1944 """) |
1913 def CMDpack(parser, args): | 1945 def CMDpack(parser, args): |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1981 parser.add_option('-n', '--nohooks', action='store_true', | 2013 parser.add_option('-n', '--nohooks', action='store_true', |
1982 help='don\'t run hooks after the update is complete') | 2014 help='don\'t run hooks after the update is complete') |
1983 parser.add_option('-p', '--noprehooks', action='store_true', | 2015 parser.add_option('-p', '--noprehooks', action='store_true', |
1984 help='don\'t run pre-DEPS hooks', default=False) | 2016 help='don\'t run pre-DEPS hooks', default=False) |
1985 parser.add_option('-r', '--revision', action='append', | 2017 parser.add_option('-r', '--revision', action='append', |
1986 dest='revisions', metavar='REV', default=[], | 2018 dest='revisions', metavar='REV', default=[], |
1987 help='Enforces revision/hash for the solutions with the ' | 2019 help='Enforces revision/hash for the solutions with the ' |
1988 'format src@rev. The src@ part is optional and can be ' | 2020 'format src@rev. The src@ part is optional and can be ' |
1989 'skipped. -r can be used multiple times when .gclient ' | 2021 'skipped. -r can be used multiple times when .gclient ' |
1990 'has multiple solutions configured and will work even ' | 2022 'has multiple solutions configured and will work even ' |
1991 'if the src@ part is skipped.') | 2023 'if the src@ part is skipped. Note that specifying ' |
| 2024 '--revision means your safesync_url gets ignored.') |
1992 parser.add_option('--with_branch_heads', action='store_true', | 2025 parser.add_option('--with_branch_heads', action='store_true', |
1993 help='Clone git "branch_heads" refspecs in addition to ' | 2026 help='Clone git "branch_heads" refspecs in addition to ' |
1994 'the default refspecs. This adds about 1/2GB to a ' | 2027 'the default refspecs. This adds about 1/2GB to a ' |
1995 'full checkout. (git only)') | 2028 'full checkout. (git only)') |
1996 parser.add_option('--with_tags', action='store_true', | 2029 parser.add_option('--with_tags', action='store_true', |
1997 help='Clone git tags in addition to the default refspecs.') | 2030 help='Clone git tags in addition to the default refspecs.') |
1998 parser.add_option('-t', '--transitive', action='store_true', | 2031 parser.add_option('-t', '--transitive', action='store_true', |
1999 help='When a revision is specified (in the DEPS file or ' | 2032 help='When a revision is specified (in the DEPS file or ' |
2000 'with the command-line flag), transitively update ' | 2033 'with the command-line flag), transitively update ' |
2001 'the dependencies to the date of the given revision. ' | 2034 'the dependencies to the date of the given revision. ' |
2002 'Only supported for SVN repositories.') | 2035 'Only supported for SVN repositories.') |
2003 parser.add_option('-H', '--head', action='store_true', | 2036 parser.add_option('-H', '--head', action='store_true', |
2004 help='Begin by automatically syncing the root gclient ' | 2037 help='skips any safesync_urls specified in ' |
2005 'solutions to HEAD of the remote repository. Similar ' | 2038 'configured solutions and sync to head instead') |
2006 'to making the solution temporarily "managed".') | |
2007 parser.add_option('-D', '--delete_unversioned_trees', action='store_true', | 2039 parser.add_option('-D', '--delete_unversioned_trees', action='store_true', |
2008 help='Deletes from the working copy any dependencies that ' | 2040 help='Deletes from the working copy any dependencies that ' |
2009 'have been removed since the last sync, as long as ' | 2041 'have been removed since the last sync, as long as ' |
2010 'there are no local modifications. When used with ' | 2042 'there are no local modifications. When used with ' |
2011 '--force, such dependencies are removed even if they ' | 2043 '--force, such dependencies are removed even if they ' |
2012 'have local modifications. When used with --reset, ' | 2044 'have local modifications. When used with --reset, ' |
2013 'all untracked directories are removed from the ' | 2045 'all untracked directories are removed from the ' |
2014 'working copy, excluding those which are explicitly ' | 2046 'working copy, excluding those which are explicitly ' |
2015 'ignored in the repository.') | 2047 'ignored in the repository.') |
2016 parser.add_option('-R', '--reset', action='store_true', | 2048 parser.add_option('-R', '--reset', action='store_true', |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2051 'thing operating on the git repos (e.g. on a bot).') | 2083 'thing operating on the git repos (e.g. on a bot).') |
2052 parser.add_option('--lock_timeout', type='int', default=5000, | 2084 parser.add_option('--lock_timeout', type='int', default=5000, |
2053 help='GIT ONLY - Deadline (in seconds) to wait for git ' | 2085 help='GIT ONLY - Deadline (in seconds) to wait for git ' |
2054 'cache lock to become available. Default is %default.') | 2086 'cache lock to become available. Default is %default.') |
2055 (options, args) = parser.parse_args(args) | 2087 (options, args) = parser.parse_args(args) |
2056 client = GClient.LoadCurrentConfig(options) | 2088 client = GClient.LoadCurrentConfig(options) |
2057 | 2089 |
2058 if not client: | 2090 if not client: |
2059 raise gclient_utils.Error('client not configured; see \'gclient config\'') | 2091 raise gclient_utils.Error('client not configured; see \'gclient config\'') |
2060 | 2092 |
| 2093 if options.revisions and options.head: |
| 2094 # TODO(maruel): Make it a parser.error if it doesn't break any builder. |
| 2095 print('Warning: you cannot use both --head and --revision') |
| 2096 |
2061 if options.verbose: | 2097 if options.verbose: |
2062 client.PrintLocationAndContents() | 2098 client.PrintLocationAndContents() |
2063 ret = client.RunOnDeps('update', args) | 2099 ret = client.RunOnDeps('update', args) |
2064 if options.output_json: | 2100 if options.output_json: |
2065 slns = {} | 2101 slns = {} |
2066 for d in client.subtree(True): | 2102 for d in client.subtree(True): |
2067 normed = d.name.replace('\\', '/').rstrip('/') + '/' | 2103 normed = d.name.replace('\\', '/').rstrip('/') + '/' |
2068 slns[normed] = { | 2104 slns[normed] = { |
2069 'revision': d.got_revision, | 2105 'revision': d.got_revision, |
2070 'scm': d.used_scm.name if d.used_scm else None, | 2106 'scm': d.used_scm.name if d.used_scm else None, |
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2257 if not options.config_filename: | 2293 if not options.config_filename: |
2258 options.config_filename = self.gclientfile_default | 2294 options.config_filename = self.gclientfile_default |
2259 options.entries_filename = options.config_filename + '_entries' | 2295 options.entries_filename = options.config_filename + '_entries' |
2260 if options.jobs < 1: | 2296 if options.jobs < 1: |
2261 self.error('--jobs must be 1 or higher') | 2297 self.error('--jobs must be 1 or higher') |
2262 | 2298 |
2263 # These hacks need to die. | 2299 # These hacks need to die. |
2264 if not hasattr(options, 'revisions'): | 2300 if not hasattr(options, 'revisions'): |
2265 # GClient.RunOnDeps expects it even if not applicable. | 2301 # GClient.RunOnDeps expects it even if not applicable. |
2266 options.revisions = [] | 2302 options.revisions = [] |
| 2303 if not hasattr(options, 'head'): |
| 2304 options.head = None |
2267 if not hasattr(options, 'nohooks'): | 2305 if not hasattr(options, 'nohooks'): |
2268 options.nohooks = True | 2306 options.nohooks = True |
2269 if not hasattr(options, 'noprehooks'): | 2307 if not hasattr(options, 'noprehooks'): |
2270 options.noprehooks = True | 2308 options.noprehooks = True |
2271 if not hasattr(options, 'deps_os'): | 2309 if not hasattr(options, 'deps_os'): |
2272 options.deps_os = None | 2310 options.deps_os = None |
2273 if not hasattr(options, 'manually_grab_svn_rev'): | 2311 if not hasattr(options, 'manually_grab_svn_rev'): |
2274 options.manually_grab_svn_rev = None | 2312 options.manually_grab_svn_rev = None |
2275 if not hasattr(options, 'force'): | 2313 if not hasattr(options, 'force'): |
2276 options.force = None | 2314 options.force = None |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2317 | 2355 |
2318 | 2356 |
2319 if '__main__' == __name__: | 2357 if '__main__' == __name__: |
2320 try: | 2358 try: |
2321 sys.exit(main(sys.argv[1:])) | 2359 sys.exit(main(sys.argv[1:])) |
2322 except KeyboardInterrupt: | 2360 except KeyboardInterrupt: |
2323 sys.stderr.write('interrupted\n') | 2361 sys.stderr.write('interrupted\n') |
2324 sys.exit(1) | 2362 sys.exit(1) |
2325 | 2363 |
2326 # vim: ts=2:sw=2:tw=80:et: | 2364 # vim: ts=2:sw=2:tw=80:et: |
OLD | NEW |