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

Side by Side Diff: gclient.py

Issue 7982005: Move dependencies to a locked property. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
Patch Set: Not using locks yet since it's having issues Created 9 years, 2 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 | 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) 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 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
196 def custom_deps(self): 196 def custom_deps(self):
197 """Immutable so no need to lock.""" 197 """Immutable so no need to lock."""
198 return self._custom_deps.copy() 198 return self._custom_deps.copy()
199 199
200 200
201 class Dependency(GClientKeywords, gclient_utils.WorkItem, DependencySettings): 201 class Dependency(GClientKeywords, gclient_utils.WorkItem, DependencySettings):
202 """Object that represents a dependency checkout.""" 202 """Object that represents a dependency checkout."""
203 203
204 def __init__(self, parent, name, url, safesync_url, managed, custom_deps, 204 def __init__(self, parent, name, url, safesync_url, managed, custom_deps,
205 custom_vars, deps_file, should_process): 205 custom_vars, deps_file, should_process):
206 # Warning: this function can be called from any thread. Both
207 # self.dependencies and self.requirements are read and modified from
208 # multiple threads at the same time. Sad.
209 GClientKeywords.__init__(self) 206 GClientKeywords.__init__(self)
210 gclient_utils.WorkItem.__init__(self, name) 207 gclient_utils.WorkItem.__init__(self, name)
211 DependencySettings.__init__( 208 DependencySettings.__init__(
212 self, parent, safesync_url, managed, custom_deps, custom_vars, 209 self, parent, safesync_url, managed, custom_deps, custom_vars,
213 deps_file, should_process) 210 deps_file, should_process)
214 211
215 # This is in both .gclient and DEPS files: 212 # This is in both .gclient and DEPS files:
216 self.url = url 213 self.url = url
217 214
218 self.deps_hooks = [] 215 self.deps_hooks = []
219 216
220 # Calculates properties: 217 # Calculates properties:
221 self.parsed_url = None 218 self.parsed_url = None
222 self.dependencies = [] 219 self._dependencies = []
223 # A cache of the files affected by the current operation, necessary for 220 # A cache of the files affected by the current operation, necessary for
224 # hooks. 221 # hooks.
225 self._file_list = [] 222 self._file_list = []
226 # If it is not set to True, the dependency wasn't processed for its child 223 # If it is not set to True, the dependency wasn't processed for its child
227 # dependency, i.e. its DEPS wasn't read. 224 # dependency, i.e. its DEPS wasn't read.
228 self.deps_parsed = False 225 self.deps_parsed = False
229 # This dependency has been processed, i.e. checked out 226 # This dependency has been processed, i.e. checked out
230 self.processed = False 227 self.processed = False
231 # This dependency had its hook run 228 # This dependency had its hook run
232 self.hooks_ran = False 229 self.hooks_ran = False
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
431 if use_relative_paths: 428 if use_relative_paths:
432 rel_deps = {} 429 rel_deps = {}
433 for d, url in deps.items(): 430 for d, url in deps.items():
434 # normpath is required to allow DEPS to use .. in their 431 # normpath is required to allow DEPS to use .. in their
435 # dependency local path. 432 # dependency local path.
436 rel_deps[os.path.normpath(os.path.join(self.name, d))] = url 433 rel_deps[os.path.normpath(os.path.join(self.name, d))] = url
437 deps = rel_deps 434 deps = rel_deps
438 435
439 # Convert the deps into real Dependency. 436 # Convert the deps into real Dependency.
440 for name, url in deps.iteritems(): 437 for name, url in deps.iteritems():
441 if name in [s.name for s in self.dependencies]: 438 if name in [s.name for s in self._dependencies]:
442 raise gclient_utils.Error( 439 raise gclient_utils.Error(
443 'The same name "%s" appears multiple times in the deps section' % 440 'The same name "%s" appears multiple times in the deps section' %
444 name) 441 name)
445 should_process = self.recursion_limit and self.should_process 442 should_process = self.recursion_limit and self.should_process
446 if should_process: 443 if should_process:
447 tree = dict((d.name, d) for d in self.root.subtree(False)) 444 tree = dict((d.name, d) for d in self.root.subtree(False))
448 if name in tree: 445 if name in tree:
449 if url == tree[name].url: 446 if url == tree[name].url:
450 logging.info('Won\'t process duplicate dependency %s' % tree[name]) 447 logging.info('Won\'t process duplicate dependency %s' % tree[name])
451 # In theory we could keep it as a shadow of the other one. In 448 # In theory we could keep it as a shadow of the other one. In
452 # practice, simply ignore it. 449 # practice, simply ignore it.
453 #should_process = False 450 #should_process = False
454 continue 451 continue
455 else: 452 else:
456 raise gclient_utils.Error( 453 raise gclient_utils.Error(
457 'Dependency %s specified more than once:\n %s\nvs\n %s' % 454 'Dependency %s specified more than once:\n %s\nvs\n %s' %
458 (name, tree[name].hierarchy(), self.hierarchy())) 455 (name, tree[name].hierarchy(), self.hierarchy()))
459 self.dependencies.append(Dependency(self, name, url, None, None, None, 456 self._dependencies.append(
460 None, self.deps_file, should_process)) 457 Dependency(
458 self, name, url, None, None, None, None,
459 self.deps_file, should_process))
461 logging.debug('Loaded: %s' % str(self)) 460 logging.debug('Loaded: %s' % str(self))
462 461
463 # Arguments number differs from overridden method 462 # Arguments number differs from overridden method
464 # pylint: disable=W0221 463 # pylint: disable=W0221
465 def run(self, revision_overrides, command, args, work_queue, options): 464 def run(self, revision_overrides, command, args, work_queue, options):
466 """Runs 'command' before parsing the DEPS in case it's a initial checkout 465 """Runs 'command' before parsing the DEPS in case it's a initial checkout
467 or a revert.""" 466 or a revert."""
468 467
469 def maybeGetParentRevision(options): 468 def maybeGetParentRevision(options):
470 """If we are performing an update and --transitive is set, set the 469 """If we are performing an update and --transitive is set, set the
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
631 630
632 @property 631 @property
633 def recursion_limit(self): 632 def recursion_limit(self):
634 """Returns > 0 if this dependency is not too recursed to be processed. 633 """Returns > 0 if this dependency is not too recursed to be processed.
635 634
636 Immutable so no need to lock. 635 Immutable so no need to lock.
637 """ 636 """
638 return max(self.parent.recursion_limit - 1, 0) 637 return max(self.parent.recursion_limit - 1, 0)
639 638
640 @property 639 @property
641 @gclient_utils.lockedmethod 640 def dependencies(self):
641 return tuple(self._dependencies)
642
643 @property
642 def file_list(self): 644 def file_list(self):
643 result = self._file_list[:] 645 result = self._file_list[:]
644 for d in self.dependencies: 646 for d in self.dependencies:
645 result.extend(d.file_list) 647 result.extend(d.file_list)
646 return tuple(result) 648 return tuple(result)
647 649
648 def __str__(self): 650 def __str__(self):
649 out = [] 651 out = []
650 for i in ('name', 'url', 'parsed_url', 'safesync_url', 'custom_deps', 652 for i in ('name', 'url', 'parsed_url', 'safesync_url', 'custom_deps',
651 'custom_vars', 'deps_hooks', 'file_list', 'should_process', 653 'custom_vars', 'deps_hooks', 'file_list', 'should_process',
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
754 try: 756 try:
755 exec(content, config_dict) 757 exec(content, config_dict)
756 except SyntaxError, e: 758 except SyntaxError, e:
757 gclient_utils.SyntaxErrorToError('.gclient', e) 759 gclient_utils.SyntaxErrorToError('.gclient', e)
758 for s in config_dict.get('solutions', []): 760 for s in config_dict.get('solutions', []):
759 try: 761 try:
760 tree = dict((d.name, d) for d in self.root.subtree(False)) 762 tree = dict((d.name, d) for d in self.root.subtree(False))
761 if s['name'] in tree: 763 if s['name'] in tree:
762 raise gclient_utils.Error( 764 raise gclient_utils.Error(
763 'Dependency %s specified more than once in .gclient' % s['name']) 765 'Dependency %s specified more than once in .gclient' % s['name'])
764 self.dependencies.append(Dependency( 766 self._dependencies.append(Dependency(
765 self, s['name'], s['url'], 767 self, s['name'], s['url'],
766 s.get('safesync_url', None), 768 s.get('safesync_url', None),
767 s.get('managed', True), 769 s.get('managed', True),
768 s.get('custom_deps', {}), 770 s.get('custom_deps', {}),
769 s.get('custom_vars', {}), 771 s.get('custom_vars', {}),
770 s.get('deps_file', 'DEPS'), 772 s.get('deps_file', 'DEPS'),
771 True)) 773 True))
772 except KeyError: 774 except KeyError:
773 raise gclient_utils.Error('Invalid .gclient file. Solution is ' 775 raise gclient_utils.Error('Invalid .gclient file. Solution is '
774 'incomplete: %s' % s) 776 'incomplete: %s' % s)
(...skipping 662 matching lines...) Expand 10 before | Expand all | Expand 10 after
1437 except (gclient_utils.Error, subprocess2.CalledProcessError), e: 1439 except (gclient_utils.Error, subprocess2.CalledProcessError), e:
1438 print >> sys.stderr, 'Error: %s' % str(e) 1440 print >> sys.stderr, 'Error: %s' % str(e)
1439 return 1 1441 return 1
1440 1442
1441 1443
1442 if '__main__' == __name__: 1444 if '__main__' == __name__:
1443 fix_encoding.fix_encoding() 1445 fix_encoding.fix_encoding()
1444 sys.exit(Main(sys.argv[1:])) 1446 sys.exit(Main(sys.argv[1:]))
1445 1447
1446 # vim: ts=2:sw=2:tw=80:et: 1448 # 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