Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(604)

Side by Side Diff: gclient.py

Issue 2324513003: Propagate use_relative_paths into recursedeps (Closed)
Patch Set: Add/fix test for recursion Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | tests/gclient_test.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
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, safesync_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, relative):
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._safesync_url = safesync_url
223 self._deps_file = deps_file 223 self._deps_file = deps_file
224 self._url = url 224 self._url = url
225 # 'managed' determines whether or not this dependency is synced/updated by 225 # 'managed' determines whether or not this dependency is synced/updated by
226 # gclient after gclient checks it out initially. The difference between 226 # gclient after gclient checks it out initially. The difference between
227 # 'managed' and 'should_process' is that the user specifies 'managed' via 227 # 'managed' and 'should_process' is that the user specifies 'managed' via
228 # the --unmanaged command-line flag or a .gclient config, where 228 # the --unmanaged command-line flag or a .gclient config, where
229 # '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
230 # 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.
231 self._managed = managed 231 self._managed = managed
232 self._should_process = should_process 232 self._should_process = should_process
233 # If this is a recursed-upon sub-dependency, and the parent has
234 # use_relative_paths set, then this dependency should check out its own
235 # dependencies relative to that parent's path for this, rather than
236 # relative to the .gclient file.
237 self._relative = relative
233 # This is a mutable value which has the list of 'target_os' OSes listed in 238 # This is a mutable value which has the list of 'target_os' OSes listed in
234 # the current deps file. 239 # the current deps file.
235 self.local_target_os = None 240 self.local_target_os = None
236 241
237 # These are only set in .gclient and not in DEPS files. 242 # These are only set in .gclient and not in DEPS files.
238 self._custom_vars = custom_vars or {} 243 self._custom_vars = custom_vars or {}
239 self._custom_deps = custom_deps or {} 244 self._custom_deps = custom_deps or {}
240 self._custom_hooks = custom_hooks or [] 245 self._custom_hooks = custom_hooks or []
241 246
242 # TODO(iannucci): Remove this when all masters are correctly substituting 247 # TODO(iannucci): Remove this when all masters are correctly substituting
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
318 if self.parent: 323 if self.parent:
319 url = self.parent.get_custom_deps(name, url) 324 url = self.parent.get_custom_deps(name, url)
320 # None is a valid return value to disable a dependency. 325 # None is a valid return value to disable a dependency.
321 return self.custom_deps.get(name, url) 326 return self.custom_deps.get(name, url)
322 327
323 328
324 class Dependency(gclient_utils.WorkItem, DependencySettings): 329 class Dependency(gclient_utils.WorkItem, DependencySettings):
325 """Object that represents a dependency checkout.""" 330 """Object that represents a dependency checkout."""
326 331
327 def __init__(self, parent, name, url, safesync_url, managed, custom_deps, 332 def __init__(self, parent, name, url, safesync_url, managed, custom_deps,
328 custom_vars, custom_hooks, deps_file, should_process): 333 custom_vars, custom_hooks, deps_file, should_process,
334 relative):
329 gclient_utils.WorkItem.__init__(self, name) 335 gclient_utils.WorkItem.__init__(self, name)
330 DependencySettings.__init__( 336 DependencySettings.__init__(
331 self, parent, url, safesync_url, managed, custom_deps, custom_vars, 337 self, parent, url, safesync_url, managed, custom_deps, custom_vars,
332 custom_hooks, deps_file, should_process) 338 custom_hooks, deps_file, should_process, relative)
333 339
334 # This is in both .gclient and DEPS files: 340 # This is in both .gclient and DEPS files:
335 self._deps_hooks = [] 341 self._deps_hooks = []
336 342
337 self._pre_deps_hooks = [] 343 self._pre_deps_hooks = []
338 344
339 # Calculates properties: 345 # Calculates properties:
340 self._parsed_url = None 346 self._parsed_url = None
341 self._dependencies = [] 347 self._dependencies = []
342 # A cache of the files affected by the current operation, necessary for 348 # A cache of the files affected by the current operation, necessary for
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after
679 # If a line is in custom_deps, but not in the solution, we want to append 685 # If a line is in custom_deps, but not in the solution, we want to append
680 # this line to the solution. 686 # this line to the solution.
681 for d in self.custom_deps: 687 for d in self.custom_deps:
682 if d not in deps: 688 if d not in deps:
683 deps[d] = self.custom_deps[d] 689 deps[d] = self.custom_deps[d]
684 690
685 # If use_relative_paths is set in the DEPS file, regenerate 691 # If use_relative_paths is set in the DEPS file, regenerate
686 # the dictionary using paths relative to the directory containing 692 # the dictionary using paths relative to the directory containing
687 # the DEPS file. Also update recursedeps if use_relative_paths is 693 # the DEPS file. Also update recursedeps if use_relative_paths is
688 # enabled. 694 # enabled.
695 # If the deps file doesn't set use_relative_paths, but the parent did
696 # (and therefore set self.relative on this Dependency object), then we
697 # want to modify the deps and recursedeps by prepending the parent
698 # directory of this dependency.
689 use_relative_paths = local_scope.get('use_relative_paths', False) 699 use_relative_paths = local_scope.get('use_relative_paths', False)
700 rel_prefix = None
690 if use_relative_paths: 701 if use_relative_paths:
702 rel_prefix = self.name
703 elif self._relative:
704 rel_prefix = os.path.dirname(self.name)
705 if rel_prefix:
691 logging.warning('use_relative_paths enabled.') 706 logging.warning('use_relative_paths enabled.')
692 rel_deps = {} 707 rel_deps = {}
693 for d, url in deps.items(): 708 for d, url in deps.items():
694 # normpath is required to allow DEPS to use .. in their 709 # normpath is required to allow DEPS to use .. in their
695 # dependency local path. 710 # dependency local path.
696 rel_deps[os.path.normpath(os.path.join(self.name, d))] = url 711 rel_deps[os.path.normpath(os.path.join(rel_prefix, d))] = url
697 logging.warning('Updating deps by prepending %s.', self.name) 712 logging.warning('Updating deps by prepending %s.', rel_prefix)
698 deps = rel_deps 713 deps = rel_deps
699 714
700 # Update recursedeps if it's set. 715 # Update recursedeps if it's set.
701 if self.recursedeps is not None: 716 if self.recursedeps is not None:
702 logging.warning('Updating recursedeps by prepending %s.', self.name) 717 logging.warning('Updating recursedeps by prepending %s.', rel_prefix)
703 rel_deps = {} 718 rel_deps = {}
704 for depname, options in self.recursedeps.iteritems(): 719 for depname, options in self.recursedeps.iteritems():
705 rel_deps[os.path.normpath(os.path.join(self.name, depname))] = options 720 rel_deps[
721 os.path.normpath(os.path.join(rel_prefix, depname))] = options
706 self.recursedeps = rel_deps 722 self.recursedeps = rel_deps
707 723
724
708 if 'allowed_hosts' in local_scope: 725 if 'allowed_hosts' in local_scope:
709 try: 726 try:
710 self._allowed_hosts = frozenset(local_scope.get('allowed_hosts')) 727 self._allowed_hosts = frozenset(local_scope.get('allowed_hosts'))
711 except TypeError: # raised if non-iterable 728 except TypeError: # raised if non-iterable
712 pass 729 pass
713 if not self._allowed_hosts: 730 if not self._allowed_hosts:
714 logging.warning("allowed_hosts is specified but empty %s", 731 logging.warning("allowed_hosts is specified but empty %s",
715 self._allowed_hosts) 732 self._allowed_hosts)
716 raise gclient_utils.Error( 733 raise gclient_utils.Error(
717 'ParseDepsFile(%s): allowed_hosts must be absent ' 734 'ParseDepsFile(%s): allowed_hosts must be absent '
718 'or a non-empty iterable' % self.name) 735 'or a non-empty iterable' % self.name)
719 736
720 # Convert the deps into real Dependency. 737 # Convert the deps into real Dependency.
721 deps_to_add = [] 738 deps_to_add = []
722 for name, url in deps.iteritems(): 739 for name, url in deps.iteritems():
723 should_process = self.recursion_limit and self.should_process 740 should_process = self.recursion_limit and self.should_process
724 deps_file = self.deps_file 741 deps_file = self.deps_file
725 if self.recursedeps is not None: 742 if self.recursedeps is not None:
726 ent = self.recursedeps.get(name) 743 ent = self.recursedeps.get(name)
727 if ent is not None: 744 if ent is not None:
728 deps_file = ent['deps_file'] 745 deps_file = ent['deps_file']
729 deps_to_add.append(Dependency( 746 deps_to_add.append(Dependency(
730 self, name, url, None, None, None, self.custom_vars, None, 747 self, name, url, None, None, None, self.custom_vars, None,
731 deps_file, should_process)) 748 deps_file, should_process, use_relative_paths))
732 deps_to_add.sort(key=lambda x: x.name) 749 deps_to_add.sort(key=lambda x: x.name)
733 750
734 # override named sets of hooks by the custom hooks 751 # override named sets of hooks by the custom hooks
735 hooks_to_run = [] 752 hooks_to_run = []
736 hook_names_to_suppress = [c.get('name', '') for c in self.custom_hooks] 753 hook_names_to_suppress = [c.get('name', '') for c in self.custom_hooks]
737 for hook in local_scope.get('hooks', []): 754 for hook in local_scope.get('hooks', []):
738 if hook.get('name', '') not in hook_names_to_suppress: 755 if hook.get('name', '') not in hook_names_to_suppress:
739 hooks_to_run.append(hook) 756 hooks_to_run.append(hook)
740 757
741 # add the replacements and any additions 758 # add the replacements and any additions
(...skipping 468 matching lines...) Expand 10 before | Expand all | Expand 10 after
1210 # Snapshot generated with gclient revinfo --snapshot 1227 # Snapshot generated with gclient revinfo --snapshot
1211 solutions = [ 1228 solutions = [
1212 %(solution_list)s] 1229 %(solution_list)s]
1213 """) 1230 """)
1214 1231
1215 def __init__(self, root_dir, options): 1232 def __init__(self, root_dir, options):
1216 # Do not change previous behavior. Only solution level and immediate DEPS 1233 # Do not change previous behavior. Only solution level and immediate DEPS
1217 # are processed. 1234 # are processed.
1218 self._recursion_limit = 2 1235 self._recursion_limit = 2
1219 Dependency.__init__(self, None, None, None, None, True, None, None, None, 1236 Dependency.__init__(self, None, None, None, None, True, None, None, None,
1220 'unused', True) 1237 'unused', True, None)
1221 self._options = options 1238 self._options = options
1222 if options.deps_os: 1239 if options.deps_os:
1223 enforced_os = options.deps_os.split(',') 1240 enforced_os = options.deps_os.split(',')
1224 else: 1241 else:
1225 enforced_os = [self.DEPS_OS_CHOICES.get(sys.platform, 'unix')] 1242 enforced_os = [self.DEPS_OS_CHOICES.get(sys.platform, 'unix')]
1226 if 'all' in enforced_os: 1243 if 'all' in enforced_os:
1227 enforced_os = self.DEPS_OS_CHOICES.itervalues() 1244 enforced_os = self.DEPS_OS_CHOICES.itervalues()
1228 self._enforced_os = tuple(set(enforced_os)) 1245 self._enforced_os = tuple(set(enforced_os))
1229 self._root_dir = root_dir 1246 self._root_dir = root_dir
1230 self.config_content = None 1247 self.config_content = None
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
1301 for s in config_dict.get('solutions', []): 1318 for s in config_dict.get('solutions', []):
1302 try: 1319 try:
1303 deps_to_add.append(Dependency( 1320 deps_to_add.append(Dependency(
1304 self, s['name'], s['url'], 1321 self, s['name'], s['url'],
1305 s.get('safesync_url', None), 1322 s.get('safesync_url', None),
1306 s.get('managed', True), 1323 s.get('managed', True),
1307 s.get('custom_deps', {}), 1324 s.get('custom_deps', {}),
1308 s.get('custom_vars', {}), 1325 s.get('custom_vars', {}),
1309 s.get('custom_hooks', []), 1326 s.get('custom_hooks', []),
1310 s.get('deps_file', 'DEPS'), 1327 s.get('deps_file', 'DEPS'),
1311 True)) 1328 True,
1329 None))
1312 except KeyError: 1330 except KeyError:
1313 raise gclient_utils.Error('Invalid .gclient file. Solution is ' 1331 raise gclient_utils.Error('Invalid .gclient file. Solution is '
1314 'incomplete: %s' % s) 1332 'incomplete: %s' % s)
1315 self.add_dependencies_and_close(deps_to_add, config_dict.get('hooks', [])) 1333 self.add_dependencies_and_close(deps_to_add, config_dict.get('hooks', []))
1316 logging.info('SetConfig() done') 1334 logging.info('SetConfig() done')
1317 1335
1318 def SaveConfig(self): 1336 def SaveConfig(self):
1319 gclient_utils.FileWrite(os.path.join(self.root_dir, 1337 gclient_utils.FileWrite(os.path.join(self.root_dir,
1320 self._options.config_filename), 1338 self._options.config_filename),
1321 self.config_content) 1339 self.config_content)
(...skipping 1034 matching lines...) Expand 10 before | Expand all | Expand 10 after
2356 2374
2357 2375
2358 if '__main__' == __name__: 2376 if '__main__' == __name__:
2359 try: 2377 try:
2360 sys.exit(main(sys.argv[1:])) 2378 sys.exit(main(sys.argv[1:]))
2361 except KeyboardInterrupt: 2379 except KeyboardInterrupt:
2362 sys.stderr.write('interrupted\n') 2380 sys.stderr.write('interrupted\n')
2363 sys.exit(1) 2381 sys.exit(1)
2364 2382
2365 # vim: ts=2:sw=2:tw=80:et: 2383 # vim: ts=2:sw=2:tw=80:et:
OLDNEW
« no previous file with comments | « no previous file | tests/gclient_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698