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 # 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 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 335 self._deps_hooks = [] | 335 self._deps_hooks = [] |
| 336 | 336 |
| 337 self._pre_deps_hooks = [] | 337 self._pre_deps_hooks = [] |
| 338 | 338 |
| 339 # Calculates properties: | 339 # Calculates properties: |
| 340 self._parsed_url = None | 340 self._parsed_url = None |
| 341 self._dependencies = [] | 341 self._dependencies = [] |
| 342 # A cache of the files affected by the current operation, necessary for | 342 # A cache of the files affected by the current operation, necessary for |
| 343 # hooks. | 343 # hooks. |
| 344 self._file_list = [] | 344 self._file_list = [] |
| 345 # List of host names from which from which dependencies are allowed. | |
| 346 # Default is an empty set, meaning unspecified in DEPS file, and hence | |
| 347 # all are hosts will be allowed. Non-empty set means whitelist of hosts. | |
| 348 # allowed_hosts var is scoped to its DEPS file, and so it isn't recurisve. | |
| 349 self._allowed_hosts = set() | |
|
iannucci
2014/09/18 20:54:40
make it an empty frozenset
tandrii(chromium)
2014/09/18 21:45:58
Done.
| |
| 345 # If it is not set to True, the dependency wasn't processed for its child | 350 # If it is not set to True, the dependency wasn't processed for its child |
| 346 # dependency, i.e. its DEPS wasn't read. | 351 # dependency, i.e. its DEPS wasn't read. |
| 347 self._deps_parsed = False | 352 self._deps_parsed = False |
| 348 # This dependency has been processed, i.e. checked out | 353 # This dependency has been processed, i.e. checked out |
| 349 self._processed = False | 354 self._processed = False |
| 350 # This dependency had its pre-DEPS hooks run | 355 # This dependency had its pre-DEPS hooks run |
| 351 self._pre_deps_hooks_ran = False | 356 self._pre_deps_hooks_ran = False |
| 352 # This dependency had its hook run | 357 # This dependency had its hook run |
| 353 self._hooks_ran = False | 358 self._hooks_ran = False |
| 354 # This is the scm used to checkout self.url. It may be used by dependencies | 359 # This is the scm used to checkout self.url. It may be used by dependencies |
| (...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 680 deps = rel_deps | 685 deps = rel_deps |
| 681 | 686 |
| 682 # Update recursedeps if it's set. | 687 # Update recursedeps if it's set. |
| 683 if self.recursedeps is not None: | 688 if self.recursedeps is not None: |
| 684 logging.warning('Updating recursedeps by prepending %s.', self.name) | 689 logging.warning('Updating recursedeps by prepending %s.', self.name) |
| 685 rel_deps = set() | 690 rel_deps = set() |
| 686 for d in self.recursedeps: | 691 for d in self.recursedeps: |
| 687 rel_deps.add(os.path.normpath(os.path.join(self.name, d))) | 692 rel_deps.add(os.path.normpath(os.path.join(self.name, d))) |
| 688 self.recursedeps = rel_deps | 693 self.recursedeps = rel_deps |
| 689 | 694 |
| 695 if 'allowed_hosts' in local_scope: | |
| 696 self._allowed_hosts = set(local_scope.get('allowed_hosts')) | |
|
iannucci
2014/09/18 20:54:41
this could throw a TypeError if it's a non-iterabl
tandrii(chromium)
2014/09/18 21:45:58
Done.
| |
| 697 if not self._allowed_hosts: | |
| 698 logging.warning("allowed_hosts is specified but empty %s", | |
| 699 self._allowed_hosts) | |
| 700 raise gclient_utils.Error( | |
| 701 'ParseDepsFile(%s): allowed_hosts must be a non-empty iterable' % | |
|
iannucci
2014/09/18 20:54:40
may want to tell them to delete it if they're maki
tandrii(chromium)
2014/09/18 21:45:58
Done.
| |
| 702 self.name) | |
| 703 | |
| 690 # Convert the deps into real Dependency. | 704 # Convert the deps into real Dependency. |
| 691 deps_to_add = [] | 705 deps_to_add = [] |
| 692 for name, url in deps.iteritems(): | 706 for name, url in deps.iteritems(): |
| 693 should_process = self.recursion_limit and self.should_process | 707 should_process = self.recursion_limit and self.should_process |
| 694 deps_to_add.append(Dependency( | 708 deps_to_add.append(Dependency( |
| 695 self, name, url, None, None, None, None, None, | 709 self, name, url, None, None, None, None, None, |
| 696 self.deps_file, should_process)) | 710 self.deps_file, should_process)) |
| 697 deps_to_add.sort(key=lambda x: x.name) | 711 deps_to_add.sort(key=lambda x: x.name) |
| 698 | 712 |
| 699 # override named sets of hooks by the custom hooks | 713 # override named sets of hooks by the custom hooks |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 749 'repository.' % options.revision) | 763 'repository.' % options.revision) |
| 750 else: | 764 else: |
| 751 parent_revision_date = self.parent.used_scm.GetRevisionDate( | 765 parent_revision_date = self.parent.used_scm.GetRevisionDate( |
| 752 options.revision) | 766 options.revision) |
| 753 options.revision = gclient_utils.MakeDateRevision( | 767 options.revision = gclient_utils.MakeDateRevision( |
| 754 parent_revision_date) | 768 parent_revision_date) |
| 755 if options.verbose: | 769 if options.verbose: |
| 756 print('Using parent\'s revision date %s since we are in a ' | 770 print('Using parent\'s revision date %s since we are in a ' |
| 757 'different repository.' % options.revision) | 771 'different repository.' % options.revision) |
| 758 | 772 |
| 773 def findDepsFromNotAllowedHosts(self): | |
| 774 """Returns a list of depenecies from not allowed hosts. | |
| 775 | |
| 776 If allowed_hosts is not set, allows all hosts and returns empty list. | |
| 777 """ | |
| 778 if self._allowed_hosts is None: | |
| 779 return [] | |
| 780 bad_deps = [] | |
| 781 for dep in self._dependencies: | |
| 782 if isinstance(dep.url, basestring): | |
| 783 parsed_url = urlparse.urlparse(dep.url) | |
| 784 if parsed_url.netloc and parsed_url.netloc not in self._allowed_hosts: | |
| 785 bad_deps.append(dep) | |
| 786 return bad_deps | |
| 787 | |
| 759 # Arguments number differs from overridden method | 788 # Arguments number differs from overridden method |
| 760 # pylint: disable=W0221 | 789 # pylint: disable=W0221 |
| 761 def run(self, revision_overrides, command, args, work_queue, options): | 790 def run(self, revision_overrides, command, args, work_queue, options): |
| 762 """Runs |command| then parse the DEPS file.""" | 791 """Runs |command| then parse the DEPS file.""" |
| 763 logging.info('Dependency(%s).run()' % self.name) | 792 logging.info('Dependency(%s).run()' % self.name) |
| 764 assert self._file_list == [] | 793 assert self._file_list == [] |
| 765 if not self.should_process: | 794 if not self.should_process: |
| 766 return | 795 return |
| 767 # When running runhooks, there's no need to consult the SCM. | 796 # When running runhooks, there's no need to consult the SCM. |
| 768 # All known hooks are expected to run unconditionally regardless of working | 797 # All known hooks are expected to run unconditionally regardless of working |
| (...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1046 def pre_deps_hooks_ran(self): | 1075 def pre_deps_hooks_ran(self): |
| 1047 return self._pre_deps_hooks_ran | 1076 return self._pre_deps_hooks_ran |
| 1048 | 1077 |
| 1049 @property | 1078 @property |
| 1050 @gclient_utils.lockedmethod | 1079 @gclient_utils.lockedmethod |
| 1051 def hooks_ran(self): | 1080 def hooks_ran(self): |
| 1052 return self._hooks_ran | 1081 return self._hooks_ran |
| 1053 | 1082 |
| 1054 @property | 1083 @property |
| 1055 @gclient_utils.lockedmethod | 1084 @gclient_utils.lockedmethod |
| 1085 def allowed_hosts(self): | |
| 1086 return frozenset(self._allowed_hosts) | |
|
iannucci
2014/09/18 20:54:40
can return a reference since it's an immutable typ
tandrii(chromium)
2014/09/18 21:45:58
Done.
| |
| 1087 | |
| 1088 @property | |
| 1089 @gclient_utils.lockedmethod | |
| 1056 def file_list(self): | 1090 def file_list(self): |
| 1057 return tuple(self._file_list) | 1091 return tuple(self._file_list) |
| 1058 | 1092 |
| 1059 @property | 1093 @property |
| 1060 def used_scm(self): | 1094 def used_scm(self): |
| 1061 """SCMWrapper instance for this dependency or None if not processed yet.""" | 1095 """SCMWrapper instance for this dependency or None if not processed yet.""" |
| 1062 return self._used_scm | 1096 return self._used_scm |
| 1063 | 1097 |
| 1064 @property | 1098 @property |
| 1065 @gclient_utils.lockedmethod | 1099 @gclient_utils.lockedmethod |
| 1066 def got_revision(self): | 1100 def got_revision(self): |
| 1067 return self._got_revision | 1101 return self._got_revision |
| 1068 | 1102 |
| 1069 @property | 1103 @property |
| 1070 def file_list_and_children(self): | 1104 def file_list_and_children(self): |
| 1071 result = list(self.file_list) | 1105 result = list(self.file_list) |
| 1072 for d in self.dependencies: | 1106 for d in self.dependencies: |
| 1073 result.extend(d.file_list_and_children) | 1107 result.extend(d.file_list_and_children) |
| 1074 return tuple(result) | 1108 return tuple(result) |
| 1075 | 1109 |
| 1076 def __str__(self): | 1110 def __str__(self): |
| 1077 out = [] | 1111 out = [] |
| 1078 for i in ('name', 'url', 'parsed_url', 'safesync_url', 'custom_deps', | 1112 for i in ('name', 'url', 'parsed_url', 'safesync_url', 'custom_deps', |
| 1079 'custom_vars', 'deps_hooks', 'file_list', 'should_process', | 1113 'custom_vars', 'deps_hooks', 'file_list', 'should_process', |
| 1080 'processed', 'hooks_ran', 'deps_parsed', 'requirements'): | 1114 'processed', 'hooks_ran', 'deps_parsed', 'requirements', |
| 1115 'allowed_hosts'): | |
| 1081 # First try the native property if it exists. | 1116 # First try the native property if it exists. |
| 1082 if hasattr(self, '_' + i): | 1117 if hasattr(self, '_' + i): |
| 1083 value = getattr(self, '_' + i, False) | 1118 value = getattr(self, '_' + i, False) |
| 1084 else: | 1119 else: |
| 1085 value = getattr(self, i, False) | 1120 value = getattr(self, i, False) |
| 1086 if value: | 1121 if value: |
| 1087 out.append('%s: %s' % (i, value)) | 1122 out.append('%s: %s' % (i, value)) |
| 1088 | 1123 |
| 1089 for d in self.dependencies: | 1124 for d in self.dependencies: |
| 1090 out.extend([' ' + x for x in str(d).splitlines()]) | 1125 out.extend([' ' + x for x in str(d).splitlines()]) |
| (...skipping 988 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2079 (options, args) = parser.parse_args(args) | 2114 (options, args) = parser.parse_args(args) |
| 2080 options.force = True | 2115 options.force = True |
| 2081 client = GClient.LoadCurrentConfig(options) | 2116 client = GClient.LoadCurrentConfig(options) |
| 2082 if not client: | 2117 if not client: |
| 2083 raise gclient_utils.Error('client not configured; see \'gclient config\'') | 2118 raise gclient_utils.Error('client not configured; see \'gclient config\'') |
| 2084 client.RunOnDeps(None, []) | 2119 client.RunOnDeps(None, []) |
| 2085 print '; '.join(' '.join(hook) for hook in client.GetHooks(options)) | 2120 print '; '.join(' '.join(hook) for hook in client.GetHooks(options)) |
| 2086 return 0 | 2121 return 0 |
| 2087 | 2122 |
| 2088 | 2123 |
| 2124 def CMDverify(parser, args): | |
| 2125 """Verifies the DEPS file deps are only from allowed_hosts.""" | |
| 2126 (options, args) = parser.parse_args(args) | |
| 2127 client = GClient.LoadCurrentConfig(options) | |
| 2128 if not client: | |
| 2129 raise gclient_utils.Error('client not configured; see \'gclient config\'') | |
| 2130 client.RunOnDeps(None, []) | |
| 2131 # Look at each first-level dependency of this gclient only. | |
| 2132 for dep in client.dependencies: | |
| 2133 bad_deps = dep.findDepsFromNotAllowedHosts() | |
| 2134 if not bad_deps: | |
| 2135 continue | |
| 2136 print "There are deps from not allowed hosts in file %s" % dep.deps_file | |
| 2137 for bad_dep in bad_deps: | |
| 2138 print "\t%s at %s" % (bad_dep.name, bad_dep.url) | |
| 2139 print "allowed_hosts:", ', '.join(dep.allowed_hosts) | |
| 2140 sys.stdout.flush() | |
| 2141 raise gclient_utils.Error( | |
| 2142 'dependencies from disallowed hosts; check your DEPS file.') | |
| 2143 return 0 | |
| 2144 | |
| 2089 class OptionParser(optparse.OptionParser): | 2145 class OptionParser(optparse.OptionParser): |
| 2090 gclientfile_default = os.environ.get('GCLIENT_FILE', '.gclient') | 2146 gclientfile_default = os.environ.get('GCLIENT_FILE', '.gclient') |
| 2091 | 2147 |
| 2092 def __init__(self, **kwargs): | 2148 def __init__(self, **kwargs): |
| 2093 optparse.OptionParser.__init__( | 2149 optparse.OptionParser.__init__( |
| 2094 self, version='%prog ' + __version__, **kwargs) | 2150 self, version='%prog ' + __version__, **kwargs) |
| 2095 | 2151 |
| 2096 # Some arm boards have issues with parallel sync. | 2152 # Some arm boards have issues with parallel sync. |
| 2097 if platform.machine().startswith('arm'): | 2153 if platform.machine().startswith('arm'): |
| 2098 jobs = 1 | 2154 jobs = 1 |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2194 print >> sys.stderr, 'Error: %s' % str(e) | 2250 print >> sys.stderr, 'Error: %s' % str(e) |
| 2195 return 1 | 2251 return 1 |
| 2196 finally: | 2252 finally: |
| 2197 gclient_utils.PrintWarnings() | 2253 gclient_utils.PrintWarnings() |
| 2198 | 2254 |
| 2199 | 2255 |
| 2200 if '__main__' == __name__: | 2256 if '__main__' == __name__: |
| 2201 sys.exit(Main(sys.argv[1:])) | 2257 sys.exit(Main(sys.argv[1:])) |
| 2202 | 2258 |
| 2203 # vim: ts=2:sw=2:tw=80:et: | 2259 # vim: ts=2:sw=2:tw=80:et: |
| OLD | NEW |