Chromium Code Reviews| 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 | 7 | 
| 8 Files | 8 Files | 
| 9 .gclient : Current client configuration, written by 'config' command. | 9 .gclient : Current client configuration, written by 'config' command. | 
| 10 Format is a Python script defining 'solutions', a list whose | 10 Format is a Python script defining 'solutions', a list whose | 
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 136 return self._custom_vars[var_name] | 136 return self._custom_vars[var_name] | 
| 137 elif var_name in self._local_scope.get("vars", {}): | 137 elif var_name in self._local_scope.get("vars", {}): | 
| 138 return self._local_scope["vars"][var_name] | 138 return self._local_scope["vars"][var_name] | 
| 139 raise gclient_utils.Error("Var is not defined: %s" % var_name) | 139 raise gclient_utils.Error("Var is not defined: %s" % var_name) | 
| 140 | 140 | 
| 141 | 141 | 
| 142 class DependencySettings(GClientKeywords): | 142 class DependencySettings(GClientKeywords): | 
| 143 """Immutable configuration settings.""" | 143 """Immutable configuration settings.""" | 
| 144 def __init__( | 144 def __init__( | 
| 145 self, parent, url, safesync_url, managed, custom_deps, custom_vars, | 145 self, parent, url, safesync_url, managed, custom_deps, custom_vars, | 
| 146 deps_file, should_process): | 146 deps_file, target_os, should_process): | 
| 147 GClientKeywords.__init__(self) | 147 GClientKeywords.__init__(self) | 
| 148 | 148 | 
| 149 # These are not mutable: | 149 # These are not mutable: | 
| 150 self._parent = parent | 150 self._parent = parent | 
| 151 self._safesync_url = safesync_url | 151 self._safesync_url = safesync_url | 
| 152 self._deps_file = deps_file | 152 self._deps_file = deps_file | 
| 153 self._url = url | 153 self._url = url | 
| 154 self._target_os = target_os | |
| 
 
John Grabowski
2012/04/19 05:29:04
move this to a spot "right above" should_process t
 
Peter Beverloo
2012/04/19 06:11:03
I disagree. There is a large comment block above _
 
 | |
| 154 # 'managed' determines whether or not this dependency is synced/updated by | 155 # 'managed' determines whether or not this dependency is synced/updated by | 
| 155 # gclient after gclient checks it out initially. The difference between | 156 # gclient after gclient checks it out initially. The difference between | 
| 156 # 'managed' and 'should_process' is that the user specifies 'managed' via | 157 # 'managed' and 'should_process' is that the user specifies 'managed' via | 
| 157 # the --unmanaged command-line flag or a .gclient config, where | 158 # the --unmanaged command-line flag or a .gclient config, where | 
| 158 # 'should_process' is dynamically set by gclient if it goes over its | 159 # 'should_process' is dynamically set by gclient if it goes over its | 
| 159 # recursion limit and controls gclient's behavior so it does not misbehave. | 160 # recursion limit and controls gclient's behavior so it does not misbehave. | 
| 160 self._managed = managed | 161 self._managed = managed | 
| 161 self._should_process = should_process | 162 self._should_process = should_process | 
| 162 | 163 | 
| 163 # These are only set in .gclient and not in DEPS files. | 164 # These are only set in .gclient and not in DEPS files. | 
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 213 | 214 | 
| 214 @property | 215 @property | 
| 215 def custom_deps(self): | 216 def custom_deps(self): | 
| 216 return self._custom_deps.copy() | 217 return self._custom_deps.copy() | 
| 217 | 218 | 
| 218 @property | 219 @property | 
| 219 def url(self): | 220 def url(self): | 
| 220 return self._url | 221 return self._url | 
| 221 | 222 | 
| 222 @property | 223 @property | 
| 224 def target_os(self): | |
| 225 return self._target_os | |
| 226 | |
| 227 @property | |
| 223 def recursion_limit(self): | 228 def recursion_limit(self): | 
| 224 """Returns > 0 if this dependency is not too recursed to be processed.""" | 229 """Returns > 0 if this dependency is not too recursed to be processed.""" | 
| 225 return max(self.parent.recursion_limit - 1, 0) | 230 return max(self.parent.recursion_limit - 1, 0) | 
| 226 | 231 | 
| 227 def get_custom_deps(self, name, url): | 232 def get_custom_deps(self, name, url): | 
| 228 """Returns a custom deps if applicable.""" | 233 """Returns a custom deps if applicable.""" | 
| 229 if self.parent: | 234 if self.parent: | 
| 230 url = self.parent.get_custom_deps(name, url) | 235 url = self.parent.get_custom_deps(name, url) | 
| 231 # None is a valid return value to disable a dependency. | 236 # None is a valid return value to disable a dependency. | 
| 232 return self.custom_deps.get(name, url) | 237 return self.custom_deps.get(name, url) | 
| 233 | 238 | 
| 234 | 239 | 
| 235 class Dependency(gclient_utils.WorkItem, DependencySettings): | 240 class Dependency(gclient_utils.WorkItem, DependencySettings): | 
| 236 """Object that represents a dependency checkout.""" | 241 """Object that represents a dependency checkout.""" | 
| 237 | 242 | 
| 238 def __init__(self, parent, name, url, safesync_url, managed, custom_deps, | 243 def __init__(self, parent, name, url, safesync_url, managed, custom_deps, | 
| 239 custom_vars, deps_file, should_process): | 244 custom_vars, deps_file, target_os, should_process): | 
| 240 gclient_utils.WorkItem.__init__(self, name) | 245 gclient_utils.WorkItem.__init__(self, name) | 
| 241 DependencySettings.__init__( | 246 DependencySettings.__init__( | 
| 242 self, parent, url, safesync_url, managed, custom_deps, custom_vars, | 247 self, parent, url, safesync_url, managed, custom_deps, custom_vars, | 
| 243 deps_file, should_process) | 248 deps_file, target_os, should_process) | 
| 244 | 249 | 
| 245 # This is in both .gclient and DEPS files: | 250 # This is in both .gclient and DEPS files: | 
| 246 self._deps_hooks = [] | 251 self._deps_hooks = [] | 
| 247 | 252 | 
| 248 # Calculates properties: | 253 # Calculates properties: | 
| 249 self._parsed_url = None | 254 self._parsed_url = None | 
| 250 self._dependencies = [] | 255 self._dependencies = [] | 
| 251 # A cache of the files affected by the current operation, necessary for | 256 # A cache of the files affected by the current operation, necessary for | 
| 252 # hooks. | 257 # hooks. | 
| 253 self._file_list = [] | 258 self._file_list = [] | 
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 423 # Eval the content. | 428 # Eval the content. | 
| 424 try: | 429 try: | 
| 425 exec(deps_content, global_scope, local_scope) | 430 exec(deps_content, global_scope, local_scope) | 
| 426 except SyntaxError, e: | 431 except SyntaxError, e: | 
| 427 gclient_utils.SyntaxErrorToError(filepath, e) | 432 gclient_utils.SyntaxErrorToError(filepath, e) | 
| 428 deps = local_scope.get('deps', {}) | 433 deps = local_scope.get('deps', {}) | 
| 429 # load os specific dependencies if defined. these dependencies may | 434 # load os specific dependencies if defined. these dependencies may | 
| 430 # override or extend the values defined by the 'deps' member. | 435 # override or extend the values defined by the 'deps' member. | 
| 431 if 'deps_os' in local_scope: | 436 if 'deps_os' in local_scope: | 
| 432 enforced_os = self.root.enforced_os | 437 enforced_os = self.root.enforced_os | 
| 438 if self.target_os and self.target_os not in enforced_os: | |
| 439 enforced_os = enforced_os + tuple([self.target_os]) | |
| 
 
John Grabowski
2012/04/19 05:29:04
tuple() seems redundant.  How about just
  enforce
 
Peter Beverloo
2012/04/19 06:11:03
enforced_os is a tuple, which are not mutable (so
 
 | |
| 440 | |
| 433 for deps_os_key in enforced_os: | 441 for deps_os_key in enforced_os: | 
| 434 os_deps = local_scope['deps_os'].get(deps_os_key, {}) | 442 os_deps = local_scope['deps_os'].get(deps_os_key, {}) | 
| 435 if len(enforced_os) > 1: | 443 if len(enforced_os) > 1: | 
| 436 # Ignore any conflict when including deps for more than one | 444 # Ignore any conflict when including deps for more than one | 
| 437 # platform, so we collect the broadest set of dependencies | 445 # platform, so we collect the broadest set of dependencies | 
| 438 # available. We may end up with the wrong revision of something for | 446 # available. We may end up with the wrong revision of something for | 
| 439 # our platform, but this is the best we can do. | 447 # our platform, but this is the best we can do. | 
| 440 deps.update([x for x in os_deps.items() if not x[0] in deps]) | 448 deps.update([x for x in os_deps.items() if not x[0] in deps]) | 
| 441 else: | 449 else: | 
| 442 deps.update(os_deps) | 450 deps.update(os_deps) | 
| (...skipping 15 matching lines...) Expand all Loading... | |
| 458 # dependency local path. | 466 # dependency local path. | 
| 459 rel_deps[os.path.normpath(os.path.join(self.name, d))] = url | 467 rel_deps[os.path.normpath(os.path.join(self.name, d))] = url | 
| 460 deps = rel_deps | 468 deps = rel_deps | 
| 461 | 469 | 
| 462 # Convert the deps into real Dependency. | 470 # Convert the deps into real Dependency. | 
| 463 deps_to_add = [] | 471 deps_to_add = [] | 
| 464 for name, url in deps.iteritems(): | 472 for name, url in deps.iteritems(): | 
| 465 should_process = self.recursion_limit and self.should_process | 473 should_process = self.recursion_limit and self.should_process | 
| 466 deps_to_add.append(Dependency( | 474 deps_to_add.append(Dependency( | 
| 467 self, name, url, None, None, None, None, | 475 self, name, url, None, None, None, None, | 
| 468 self.deps_file, should_process)) | 476 self.deps_file, self.target_os, should_process)) | 
| 469 deps_to_add.sort(key=lambda x: x.name) | 477 deps_to_add.sort(key=lambda x: x.name) | 
| 470 self.add_dependencies_and_close(deps_to_add, local_scope.get('hooks', [])) | 478 self.add_dependencies_and_close(deps_to_add, local_scope.get('hooks', [])) | 
| 471 logging.info('ParseDepsFile(%s) done' % self.name) | 479 logging.info('ParseDepsFile(%s) done' % self.name) | 
| 472 | 480 | 
| 473 def add_dependencies_and_close(self, deps_to_add, hooks): | 481 def add_dependencies_and_close(self, deps_to_add, hooks): | 
| 474 """Adds the dependencies, hooks and mark the parsing as done.""" | 482 """Adds the dependencies, hooks and mark the parsing as done.""" | 
| 475 for dep in deps_to_add: | 483 for dep in deps_to_add: | 
| 476 if dep.verify_validity(): | 484 if dep.verify_validity(): | 
| 477 self.add_dependency(dep) | 485 self.add_dependency(dep) | 
| 478 self._mark_as_parsed(hooks) | 486 self._mark_as_parsed(hooks) | 
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 736 def file_list_and_children(self): | 744 def file_list_and_children(self): | 
| 737 result = list(self.file_list) | 745 result = list(self.file_list) | 
| 738 for d in self.dependencies: | 746 for d in self.dependencies: | 
| 739 result.extend(d.file_list_and_children) | 747 result.extend(d.file_list_and_children) | 
| 740 return tuple(result) | 748 return tuple(result) | 
| 741 | 749 | 
| 742 def __str__(self): | 750 def __str__(self): | 
| 743 out = [] | 751 out = [] | 
| 744 for i in ('name', 'url', 'parsed_url', 'safesync_url', 'custom_deps', | 752 for i in ('name', 'url', 'parsed_url', 'safesync_url', 'custom_deps', | 
| 745 'custom_vars', 'deps_hooks', 'file_list', 'should_process', | 753 'custom_vars', 'deps_hooks', 'file_list', 'should_process', | 
| 746 'processed', 'hooks_ran', 'deps_parsed', 'requirements'): | 754 'target_os', 'processed', 'hooks_ran', 'deps_parsed', | 
| 
 
John Grabowski
2012/04/19 05:29:04
Somewhere you should document the idea behind targ
 
Peter Beverloo
2012/04/19 06:11:03
Agreed. I added this to the first comment in the f
 
 | |
| 755 'requirements'): | |
| 747 # First try the native property if it exists. | 756 # First try the native property if it exists. | 
| 748 if hasattr(self, '_' + i): | 757 if hasattr(self, '_' + i): | 
| 749 value = getattr(self, '_' + i, False) | 758 value = getattr(self, '_' + i, False) | 
| 750 else: | 759 else: | 
| 751 value = getattr(self, i, False) | 760 value = getattr(self, i, False) | 
| 752 if value: | 761 if value: | 
| 753 out.append('%s: %s' % (i, value)) | 762 out.append('%s: %s' % (i, value)) | 
| 754 | 763 | 
| 755 for d in self.dependencies: | 764 for d in self.dependencies: | 
| 756 out.extend([' ' + x for x in str(d).splitlines()]) | 765 out.extend([' ' + x for x in str(d).splitlines()]) | 
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 814 # Snapshot generated with gclient revinfo --snapshot | 823 # Snapshot generated with gclient revinfo --snapshot | 
| 815 solutions = [ | 824 solutions = [ | 
| 816 %(solution_list)s] | 825 %(solution_list)s] | 
| 817 """) | 826 """) | 
| 818 | 827 | 
| 819 def __init__(self, root_dir, options): | 828 def __init__(self, root_dir, options): | 
| 820 # Do not change previous behavior. Only solution level and immediate DEPS | 829 # Do not change previous behavior. Only solution level and immediate DEPS | 
| 821 # are processed. | 830 # are processed. | 
| 822 self._recursion_limit = 2 | 831 self._recursion_limit = 2 | 
| 823 Dependency.__init__(self, None, None, None, None, True, None, None, | 832 Dependency.__init__(self, None, None, None, None, True, None, None, | 
| 824 'unused', True) | 833 'unused', None, True) | 
| 825 self._options = options | 834 self._options = options | 
| 826 if options.deps_os: | 835 if options.deps_os: | 
| 827 enforced_os = options.deps_os.split(',') | 836 enforced_os = options.deps_os.split(',') | 
| 828 else: | 837 else: | 
| 829 enforced_os = [self.DEPS_OS_CHOICES.get(sys.platform, 'unix')] | 838 enforced_os = [self.DEPS_OS_CHOICES.get(sys.platform, 'unix')] | 
| 830 if 'all' in enforced_os: | 839 if 'all' in enforced_os: | 
| 831 enforced_os = self.DEPS_OS_CHOICES.itervalues() | 840 enforced_os = self.DEPS_OS_CHOICES.itervalues() | 
| 832 self._enforced_os = tuple(set(enforced_os)) | 841 self._enforced_os = tuple(set(enforced_os)) | 
| 833 self._root_dir = root_dir | 842 self._root_dir = root_dir | 
| 834 self.config_content = None | 843 self.config_content = None | 
| (...skipping 10 matching lines...) Expand all Loading... | |
| 845 deps_to_add = [] | 854 deps_to_add = [] | 
| 846 for s in config_dict.get('solutions', []): | 855 for s in config_dict.get('solutions', []): | 
| 847 try: | 856 try: | 
| 848 deps_to_add.append(Dependency( | 857 deps_to_add.append(Dependency( | 
| 849 self, s['name'], s['url'], | 858 self, s['name'], s['url'], | 
| 850 s.get('safesync_url', None), | 859 s.get('safesync_url', None), | 
| 851 s.get('managed', True), | 860 s.get('managed', True), | 
| 852 s.get('custom_deps', {}), | 861 s.get('custom_deps', {}), | 
| 853 s.get('custom_vars', {}), | 862 s.get('custom_vars', {}), | 
| 854 s.get('deps_file', 'DEPS'), | 863 s.get('deps_file', 'DEPS'), | 
| 864 s.get('target_os', None), | |
| 855 True)) | 865 True)) | 
| 856 except KeyError: | 866 except KeyError: | 
| 857 raise gclient_utils.Error('Invalid .gclient file. Solution is ' | 867 raise gclient_utils.Error('Invalid .gclient file. Solution is ' | 
| 858 'incomplete: %s' % s) | 868 'incomplete: %s' % s) | 
| 859 self.add_dependencies_and_close(deps_to_add, config_dict.get('hooks', [])) | 869 self.add_dependencies_and_close(deps_to_add, config_dict.get('hooks', [])) | 
| 860 logging.info('SetConfig() done') | 870 logging.info('SetConfig() done') | 
| 861 | 871 | 
| 862 def SaveConfig(self): | 872 def SaveConfig(self): | 
| 863 gclient_utils.FileWrite(os.path.join(self.root_dir, | 873 gclient_utils.FileWrite(os.path.join(self.root_dir, | 
| 864 self._options.config_filename), | 874 self._options.config_filename), | 
| (...skipping 716 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1581 except (gclient_utils.Error, subprocess2.CalledProcessError), e: | 1591 except (gclient_utils.Error, subprocess2.CalledProcessError), e: | 
| 1582 print >> sys.stderr, 'Error: %s' % str(e) | 1592 print >> sys.stderr, 'Error: %s' % str(e) | 
| 1583 return 1 | 1593 return 1 | 
| 1584 | 1594 | 
| 1585 | 1595 | 
| 1586 if '__main__' == __name__: | 1596 if '__main__' == __name__: | 
| 1587 fix_encoding.fix_encoding() | 1597 fix_encoding.fix_encoding() | 
| 1588 sys.exit(Main(sys.argv[1:])) | 1598 sys.exit(Main(sys.argv[1:])) | 
| 1589 | 1599 | 
| 1590 # vim: ts=2:sw=2:tw=80:et: | 1600 # vim: ts=2:sw=2:tw=80:et: | 
| OLD | NEW |