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

Side by Side Diff: gclient.py

Issue 7892034: Initial step into making Dependency thread safe (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
Patch Set: Created 9 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | gclient_utils.py » ('j') | gclient_utils.py » ('J')
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) 2011 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2011 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 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
138 138
139 class Dependency(GClientKeywords, gclient_utils.WorkItem): 139 class Dependency(GClientKeywords, gclient_utils.WorkItem):
140 """Object that represents a dependency checkout.""" 140 """Object that represents a dependency checkout."""
141 141
142 def __init__(self, parent, name, url, safesync_url, custom_deps, 142 def __init__(self, parent, name, url, safesync_url, custom_deps,
143 custom_vars, deps_file, should_process): 143 custom_vars, deps_file, should_process):
144 # Warning: this function can be called from any thread. Both 144 # Warning: this function can be called from any thread. Both
145 # self.dependencies and self.requirements are read and modified from 145 # self.dependencies and self.requirements are read and modified from
146 # multiple threads at the same time. Sad. 146 # multiple threads at the same time. Sad.
147 GClientKeywords.__init__(self) 147 GClientKeywords.__init__(self)
148 gclient_utils.WorkItem.__init__(self) 148 gclient_utils.WorkItem.__init__(self, name)
149 self.parent = parent 149 self.parent = parent
150 self.name = name
151 self.url = url 150 self.url = url
152 self.parsed_url = None 151 self.parsed_url = None
153 # These 2 are only set in .gclient and not in DEPS files. 152 # These 2 are only set in .gclient and not in DEPS files.
154 self.safesync_url = safesync_url 153 self.safesync_url = safesync_url
155 self.custom_vars = custom_vars or {} 154 self.custom_vars = custom_vars or {}
156 self.custom_deps = custom_deps or {} 155 self.custom_deps = custom_deps or {}
157 self.deps_hooks = [] 156 self.deps_hooks = []
158 self.dependencies = [] 157 self.dependencies = []
159 self.deps_file = deps_file 158 self.deps_file = deps_file
160 # A cache of the files affected by the current operation, necessary for 159 # A cache of the files affected by the current operation, necessary for
161 # hooks. 160 # hooks.
162 self._file_list = [] 161 self._file_list = []
163 # If it is not set to True, the dependency wasn't processed for its child 162 # If it is not set to True, the dependency wasn't processed for its child
164 # dependency, i.e. its DEPS wasn't read. 163 # dependency, i.e. its DEPS wasn't read.
165 self.deps_parsed = False 164 self.deps_parsed = False
166 # This dependency should be processed, i.e. checked out 165 # This dependency should be processed, i.e. checked out
167 self.should_process = should_process 166 self.should_process = should_process
168 # This dependency has been processed, i.e. checked out 167 # This dependency has been processed, i.e. checked out
169 self.processed = False 168 self.processed = False
170 # This dependency had its hook run 169 # This dependency had its hook run
171 self.hooks_ran = False 170 self.hooks_ran = False
172 # Required dependencies to run before running this one:
173 self.requirements = set()
174 171
175 # Post process the url to remove trailing slashes. 172 # Post process the url to remove trailing slashes.
176 if isinstance(self.url, basestring): 173 if isinstance(self.url, basestring):
177 # urls are sometime incorrectly written as proto://host/path/@rev. Replace 174 # urls are sometime incorrectly written as proto://host/path/@rev. Replace
178 # it to proto://host/path@rev. 175 # it to proto://host/path@rev.
179 if self.url.count('@') > 1: 176 if self.url.count('@') > 1:
180 raise gclient_utils.Error('Invalid url "%s"' % self.url) 177 raise gclient_utils.Error('Invalid url "%s"' % self.url)
181 self.url = self.url.replace('/@', '@') 178 self.url = self.url.replace('/@', '@')
182 179
183 self._FindDependencies() 180 self._FindDependencies()
(...skipping 10 matching lines...) Expand all
194 raise gclient_utils.Error('deps_file name must not be a path, just a ' 191 raise gclient_utils.Error('deps_file name must not be a path, just a '
195 'filename. %s' % self.deps_file) 192 'filename. %s' % self.deps_file)
196 193
197 def _FindDependencies(self): 194 def _FindDependencies(self):
198 """Setup self.requirements and find any other dependency who would have self 195 """Setup self.requirements and find any other dependency who would have self
199 as a requirement. 196 as a requirement.
200 """ 197 """
201 # self.parent is implicitly a requirement. This will be recursive by 198 # self.parent is implicitly a requirement. This will be recursive by
202 # definition. 199 # definition.
203 if self.parent and self.parent.name: 200 if self.parent and self.parent.name:
204 self.requirements.add(self.parent.name) 201 self._requirements.add(self.parent.name)
205 202
206 # For a tree with at least 2 levels*, the leaf node needs to depend 203 # For a tree with at least 2 levels*, the leaf node needs to depend
207 # on the level higher up in an orderly way. 204 # on the level higher up in an orderly way.
208 # This becomes messy for >2 depth as the DEPS file format is a dictionary, 205 # This becomes messy for >2 depth as the DEPS file format is a dictionary,
209 # thus unsorted, while the .gclient format is a list thus sorted. 206 # thus unsorted, while the .gclient format is a list thus sorted.
210 # 207 #
211 # * _recursion_limit is hard coded 2 and there is no hope to change this 208 # * _recursion_limit is hard coded 2 and there is no hope to change this
212 # value. 209 # value.
213 # 210 #
214 # Interestingly enough, the following condition only works in the case we 211 # Interestingly enough, the following condition only works in the case we
215 # want: self is a 2nd level node. 3nd level node wouldn't need this since 212 # want: self is a 2nd level node. 3nd level node wouldn't need this since
216 # they already have their parent as a requirement. 213 # they already have their parent as a requirement.
217 if self.parent in self.root_parent().dependencies: 214 if self.parent in self.root_parent().dependencies:
218 root_deps = self.root_parent().dependencies 215 root_deps = self.root_parent().dependencies
219 for i in range(0, root_deps.index(self.parent)): 216 for i in range(0, root_deps.index(self.parent)):
220 value = root_deps[i] 217 value = root_deps[i]
221 if value.name: 218 if value.name:
222 self.requirements.add(value.name) 219 self._requirements.add(value.name)
223 220
224 if isinstance(self.url, self.FromImpl): 221 if isinstance(self.url, self.FromImpl):
225 self.requirements.add(self.url.module_name) 222 self._requirements.add(self.url.module_name)
226 223
227 if self.name and self.should_process: 224 if self.name and self.should_process:
228 def yield_full_tree(root): 225 def yield_full_tree(root):
229 """Depth-first recursion.""" 226 """Depth-first recursion."""
230 yield root 227 yield root
231 for i in root.dependencies: 228 for i in root.dependencies:
232 for j in yield_full_tree(i): 229 for j in yield_full_tree(i):
233 if j.should_process: 230 if j.should_process:
234 yield j 231 yield j
235 232
236 for obj in yield_full_tree(self.root_parent()): 233 for obj in yield_full_tree(self.root_parent()):
237 if obj is self or not obj.name: 234 if obj is self or not obj.name:
238 continue 235 continue
239 # Step 1: Find any requirements self may need. 236 # Step 1: Find any requirements self may need.
240 if self.name.startswith(posixpath.join(obj.name, '')): 237 if self.name.startswith(posixpath.join(obj.name, '')):
241 self.requirements.add(obj.name) 238 self._requirements.add(obj.name)
242 # Step 2: Find any requirements self may impose. 239 # Step 2: Find any requirements self may impose.
243 if obj.name.startswith(posixpath.join(self.name, '')): 240 if obj.name.startswith(posixpath.join(self.name, '')):
244 obj.requirements.add(self.name) 241 obj.requirements.add(self.name)
245 242
246 def LateOverride(self, url): 243 def LateOverride(self, url):
247 """Resolves the parsed url from url. 244 """Resolves the parsed url from url.
248 245
249 Manages From() keyword accordingly. Do not touch self.parsed_url nor 246 Manages From() keyword accordingly. Do not touch self.parsed_url nor
250 self.url because it may called with other urls due to From().""" 247 self.url because it may called with other urls due to From()."""
251 assert self.parsed_url == None or not self.should_process, self.parsed_url 248 assert self.parsed_url == None or not self.should_process, self.parsed_url
(...skipping 1106 matching lines...) Expand 10 before | Expand all | Expand 10 after
1358 except (gclient_utils.Error, subprocess2.CalledProcessError), e: 1355 except (gclient_utils.Error, subprocess2.CalledProcessError), e:
1359 print >> sys.stderr, 'Error: %s' % str(e) 1356 print >> sys.stderr, 'Error: %s' % str(e)
1360 return 1 1357 return 1
1361 1358
1362 1359
1363 if '__main__' == __name__: 1360 if '__main__' == __name__:
1364 fix_encoding.fix_encoding() 1361 fix_encoding.fix_encoding()
1365 sys.exit(Main(sys.argv[1:])) 1362 sys.exit(Main(sys.argv[1:]))
1366 1363
1367 # vim: ts=2:sw=2:tw=80:et: 1364 # vim: ts=2:sw=2:tw=80:et:
OLDNEW
« no previous file with comments | « no previous file | gclient_utils.py » ('j') | gclient_utils.py » ('J')

Powered by Google App Engine
This is Rietveld 408576698