Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright 2015 The LUCI Authors. All rights reserved. | 1 # Copyright 2015 The LUCI Authors. All rights reserved. |
| 2 # Use of this source code is governed under the Apache License, Version 2.0 | 2 # Use of this source code is governed under the Apache License, Version 2.0 |
| 3 # that can be found in the LICENSE file. | 3 # that can be found in the LICENSE file. |
| 4 | 4 |
| 5 import ast | 5 import ast |
| 6 import collections | 6 import collections |
| 7 import contextlib | 7 import contextlib |
| 8 import copy | 8 import copy |
| 9 import difflib | 9 import difflib |
| 10 import functools | 10 import functools |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 162 raise NotImplementedError() | 162 raise NotImplementedError() |
| 163 | 163 |
| 164 def __ne__(self, other): | 164 def __ne__(self, other): |
| 165 return not (self == other) | 165 return not (self == other) |
| 166 | 166 |
| 167 def proto_file(self, context): | 167 def proto_file(self, context): |
| 168 """Returns the ProtoFile of the recipes config file in this repository. | 168 """Returns the ProtoFile of the recipes config file in this repository. |
| 169 Requires a good checkout.""" | 169 Requires a good checkout.""" |
| 170 return ProtoFile(InfraRepoConfig().to_recipes_cfg(self.repo_root(context))) | 170 return ProtoFile(InfraRepoConfig().to_recipes_cfg(self.repo_root(context))) |
| 171 | 171 |
| 172 def is_consistent_with(self, other): | |
| 173 """Returns True iff |other| can be used in place of |self| while keeping | |
| 174 the dependency graph consistent. Most often it means being pinned at the | |
| 175 same revision, but some specs (like path-based) are always compatible.""" | |
| 176 return (self == other) | |
|
iannucci
2017/01/30 17:53:20
the equality operator overload in this file is a b
Paweł Hajdan Jr.
2017/01/30 19:20:05
Done.
| |
| 177 | |
| 172 | 178 |
| 173 class GitRepoSpec(RepoSpec): | 179 class GitRepoSpec(RepoSpec): |
| 174 def __init__(self, project_id, repo, branch, revision, path, backend): | 180 def __init__(self, project_id, repo, branch, revision, path, backend): |
| 175 self.project_id = project_id | 181 self.project_id = project_id |
| 176 self.repo = repo | 182 self.repo = repo |
| 177 self.branch = branch | 183 self.branch = branch |
| 178 self.revision = revision | 184 self.revision = revision |
| 179 self.path = path | 185 self.path = path |
| 180 self.backend = backend | 186 self.backend = backend |
| 181 | 187 |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 317 def proto_file(self, context): | 323 def proto_file(self, context): |
| 318 """Returns the ProtoFile of the recipes config file in this repository. | 324 """Returns the ProtoFile of the recipes config file in this repository. |
| 319 Requires a good checkout.""" | 325 Requires a good checkout.""" |
| 320 return ProtoFile(InfraRepoConfig().to_recipes_cfg(self.path)) | 326 return ProtoFile(InfraRepoConfig().to_recipes_cfg(self.path)) |
| 321 | 327 |
| 322 def __eq__(self, other): | 328 def __eq__(self, other): |
| 323 if not isinstance(other, type(self)): | 329 if not isinstance(other, type(self)): |
| 324 return False | 330 return False |
| 325 return self.path == other.path | 331 return self.path == other.path |
| 326 | 332 |
| 333 def is_consistent_with(self, other): | |
| 334 # PathRepoSpec is always compatible, unless it's PathRepoSpec with a | |
| 335 # different path. | |
| 336 if isinstance(other, type(self)): | |
| 337 return self.path == other.path | |
| 338 return True | |
| 339 | |
| 327 | 340 |
| 328 class RootRepoSpec(RepoSpec): | 341 class RootRepoSpec(RepoSpec): |
| 329 def __init__(self, proto_file): | 342 def __init__(self, proto_file): |
| 330 self._proto_file = proto_file | 343 self._proto_file = proto_file |
| 331 | 344 |
| 332 def checkout(self, context): | 345 def checkout(self, context): |
| 333 # We assume this is already checked out. | 346 # We assume this is already checked out. |
| 334 pass | 347 pass |
| 335 | 348 |
| 336 def repo_root(self, context): | 349 def repo_root(self, context): |
| (...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 647 def _create_from_spec(self, repo_spec, package_spec, overriding): | 660 def _create_from_spec(self, repo_spec, package_spec, overriding): |
| 648 project_id = package_spec.project_id | 661 project_id = package_spec.project_id |
| 649 | 662 |
| 650 if project_id in self._packages: | 663 if project_id in self._packages: |
| 651 current = self._packages[project_id] | 664 current = self._packages[project_id] |
| 652 if current is None: | 665 if current is None: |
| 653 raise CyclicDependencyError( | 666 raise CyclicDependencyError( |
| 654 'Package %s depends on itself' % project_id) | 667 'Package %s depends on itself' % project_id) |
| 655 | 668 |
| 656 # Only enforce package consistency within the override boundary. | 669 # Only enforce package consistency within the override boundary. |
| 657 if current.is_override == overriding and repo_spec != current.repo_spec: | 670 # It's fine if either spec claims it's consistent with the other. |
| 671 if (current.is_override == overriding and | |
| 672 not repo_spec.is_consistent_with(current.repo_spec) and | |
| 673 not current.repo_spec.is_consistent_with(repo_spec)): | |
| 658 raise InconsistentDependencyGraphError( | 674 raise InconsistentDependencyGraphError( |
| 659 project_id, (repo_spec, current.repo_spec)) | 675 project_id, (repo_spec, current.repo_spec)) |
| 660 self._packages[project_id] = None | 676 self._packages[project_id] = None |
| 661 | 677 |
| 662 deps = {} | 678 deps = {} |
| 663 for dep, dep_repo in sorted(package_spec.deps.items()): | 679 for dep, dep_repo in sorted(package_spec.deps.items()): |
| 664 dep_package = self._packages.get(dep) | 680 dep_package = self._packages.get(dep) |
| 665 if not (dep_package and dep_package.is_override): | 681 if not (dep_package and dep_package.is_override): |
| 666 dep_package = self._create_package(dep_repo, overriding) | 682 dep_package = self._create_package(dep_repo, overriding) |
| 667 deps[dep] = dep_package | 683 deps[dep] = dep_package |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 696 >>> d = { 'x': 1, 'y': 2 } | 712 >>> d = { 'x': 1, 'y': 2 } |
| 697 >>> sorted(_updated(d, { 'y': 3, 'z': 4 }).items()) | 713 >>> sorted(_updated(d, { 'y': 3, 'z': 4 }).items()) |
| 698 [('x', 1), ('y', 3), ('z', 4)] | 714 [('x', 1), ('y', 3), ('z', 4)] |
| 699 >>> sorted(d.items()) | 715 >>> sorted(d.items()) |
| 700 [('x', 1), ('y', 2)] | 716 [('x', 1), ('y', 2)] |
| 701 """ | 717 """ |
| 702 | 718 |
| 703 d = copy.copy(d) | 719 d = copy.copy(d) |
| 704 d.update(updates) | 720 d.update(updates) |
| 705 return d | 721 return d |
| OLD | NEW |