| 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 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 163 def __ne__(self, other): | 163 def __ne__(self, other): |
| 164 return not (self == other) | 164 return not (self == other) |
| 165 | 165 |
| 166 def proto_file(self, context): | 166 def proto_file(self, context): |
| 167 """Returns the ProtoFile of the recipes config file in this repository. | 167 """Returns the ProtoFile of the recipes config file in this repository. |
| 168 Requires a good checkout.""" | 168 Requires a good checkout.""" |
| 169 return ProtoFile(InfraRepoConfig().to_recipes_cfg(self.repo_root(context))) | 169 return ProtoFile(InfraRepoConfig().to_recipes_cfg(self.repo_root(context))) |
| 170 | 170 |
| 171 | 171 |
| 172 class GitRepoSpec(RepoSpec): | 172 class GitRepoSpec(RepoSpec): |
| 173 def __init__(self, project_id, repo, branch, revision, path): | 173 def __init__(self, project_id, repo, branch, revision, path, backend): |
| 174 self.project_id = project_id | 174 self.project_id = project_id |
| 175 self.repo = repo | 175 self.repo = repo |
| 176 self.branch = branch | 176 self.branch = branch |
| 177 self.revision = revision | 177 self.revision = revision |
| 178 self.path = path | 178 self.path = path |
| 179 self.backend = backend |
| 179 | 180 |
| 180 def __str__(self): | 181 def __str__(self): |
| 181 return ('GitRepoSpec{project_id="%(project_id)s", repo="%(repo)s", ' | 182 return ('GitRepoSpec{project_id="%(project_id)s", repo="%(repo)s", ' |
| 182 'branch="%(branch)s", revision="%(revision)s", ' | 183 'branch="%(branch)s", revision="%(revision)s", ' |
| 183 'path="%(path)s"}' % self.__dict__) | 184 'path="%(path)s"}' % self.__dict__) |
| 184 | 185 |
| 185 def run_git(self, context, *args): | 186 def run_git(self, context, *args): |
| 186 cmd = [self._git] | 187 cmd = [self._git] |
| 187 if context is not None: | 188 if context is not None: |
| 188 cmd += ['-C', self._dep_dir(context)] | 189 cmd += ['-C', self._dep_dir(context)] |
| 189 cmd += list(args) | 190 cmd += list(args) |
| 190 | 191 |
| 191 logging.info('Running: %s', cmd) | 192 logging.info('Running: %s', cmd) |
| 192 return subprocess.check_output(cmd) | 193 return subprocess.check_output(cmd) |
| 193 | 194 |
| 194 def checkout(self, context): | 195 def checkout(self, context): |
| 195 checkout_dir = self._dep_dir(context) | 196 checkout_dir = self._dep_dir(context) |
| 196 fetch.ensure_git_checkout( | 197 self.backend.checkout( |
| 197 self.repo, self.revision, checkout_dir, context.allow_fetch) | 198 self.repo, self.revision, checkout_dir, context.allow_fetch) |
| 198 cleanup_pyc(checkout_dir) | 199 cleanup_pyc(checkout_dir) |
| 199 | 200 |
| 200 def repo_root(self, context): | 201 def repo_root(self, context): |
| 201 return os.path.join(self._dep_dir(context), self.path) | 202 return os.path.join(self._dep_dir(context), self.path) |
| 202 | 203 |
| 203 def dump(self): | 204 def dump(self): |
| 204 buf = package_pb2.DepSpec( | 205 buf = package_pb2.DepSpec( |
| 205 project_id=self.project_id, | 206 project_id=self.project_id, |
| 206 url=self.repo, | 207 url=self.repo, |
| 207 branch=self.branch, | 208 branch=self.branch, |
| 208 revision=self.revision) | 209 revision=self.revision) |
| 209 if self.path: | 210 if self.path: |
| 210 buf.path_override = self.path | 211 buf.path_override = self.path |
| 211 return buf | 212 return buf |
| 212 | 213 |
| 213 def updates(self, context, other_revision=None): | 214 def updates(self, context, other_revision=None): |
| 214 """Returns a list of all updates to the branch since the revision this | 215 """Returns a list of all updates to the branch since the revision this |
| 215 repo spec refers to. | 216 repo spec refers to. |
| 216 """ | 217 """ |
| 217 raw_updates = self.raw_updates( | 218 raw_updates = self.raw_updates( |
| 218 context, (other_revision or 'origin/%s' % self.branch)) | 219 context, (other_revision or 'origin/%s' % self.branch)) |
| 219 updates = [] | 220 updates = [] |
| 220 for rev in raw_updates: | 221 for rev in raw_updates: |
| 221 info = self._get_commit_info(rev, context) | 222 info = self._get_commit_info(rev, context) |
| 222 updates.append(GitRepoSpec( | 223 updates.append(GitRepoSpec( |
| 223 self.project_id, self.repo, self.branch, rev, self.path)) | 224 self.project_id, |
| 225 self.repo, |
| 226 self.branch, |
| 227 rev, |
| 228 self.path, |
| 229 self.backend)) |
| 224 return updates | 230 return updates |
| 225 | 231 |
| 226 def commit_infos(self, context, other_revision): | 232 def commit_infos(self, context, other_revision): |
| 227 """Returns a list of commit infos on the branch between the pinned revision | 233 """Returns a list of commit infos on the branch between the pinned revision |
| 228 and |other_revision|. | 234 and |other_revision|. |
| 229 """ | 235 """ |
| 230 raw_updates = self.raw_updates(context, other_revision) | 236 raw_updates = self.raw_updates(context, other_revision) |
| 231 return [self._get_commit_info(rev, context) for rev in raw_updates] | 237 return [self._get_commit_info(rev, context) for rev in raw_updates] |
| 232 | 238 |
| 233 def raw_updates(self, context, other_revision): | 239 def raw_updates(self, context, other_revision): |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 480 def load_proto(cls, proto_file): | 486 def load_proto(cls, proto_file): |
| 481 buf = proto_file.read() | 487 buf = proto_file.read() |
| 482 assert buf.api_version == cls.API_VERSION | 488 assert buf.api_version == cls.API_VERSION |
| 483 | 489 |
| 484 deps = { str(dep.project_id): cls.spec_for_dep(dep) | 490 deps = { str(dep.project_id): cls.spec_for_dep(dep) |
| 485 for dep in buf.deps } | 491 for dep in buf.deps } |
| 486 return cls(str(buf.project_id), str(buf.recipes_path), deps) | 492 return cls(str(buf.project_id), str(buf.recipes_path), deps) |
| 487 | 493 |
| 488 @classmethod | 494 @classmethod |
| 489 def spec_for_dep(cls, dep): | 495 def spec_for_dep(cls, dep): |
| 490 """Returns a RepoSpec for the given dependency protobuf. | 496 """Returns a RepoSpec for the given dependency protobuf.""" |
| 491 | 497 |
| 492 This assumes all dependencies are Git dependencies. | 498 if dep.repo_type in (package_pb2.DepSpec.GIT, package_pb2.DepSpec.GITILES): |
| 493 """ | 499 if dep.repo_type == package_pb2.DepSpec.GIT: |
| 494 return GitRepoSpec(str(dep.project_id), | 500 backend = fetch.LocalGitBackend() |
| 495 str(dep.url), | 501 elif dep.repo_type == package_pb2.DepSpec.GITILES: |
| 496 str(dep.branch), | 502 backend = fetch.GitilesGitBackend() |
| 497 str(dep.revision), | 503 return GitRepoSpec(str(dep.project_id), |
| 498 str(dep.path_override)) | 504 str(dep.url), |
| 505 str(dep.branch), |
| 506 str(dep.revision), |
| 507 str(dep.path_override), |
| 508 backend) |
| 509 |
| 510 assert False, 'Unexpected repo type: %s' % dep |
| 499 | 511 |
| 500 @property | 512 @property |
| 501 def project_id(self): | 513 def project_id(self): |
| 502 return self._project_id | 514 return self._project_id |
| 503 | 515 |
| 504 @property | 516 @property |
| 505 def recipes_path(self): | 517 def recipes_path(self): |
| 506 return self._recipes_path | 518 return self._recipes_path |
| 507 | 519 |
| 508 @property | 520 @property |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 649 >>> d = { 'x': 1, 'y': 2 } | 661 >>> d = { 'x': 1, 'y': 2 } |
| 650 >>> sorted(_updated(d, { 'y': 3, 'z': 4 }).items()) | 662 >>> sorted(_updated(d, { 'y': 3, 'z': 4 }).items()) |
| 651 [('x', 1), ('y', 3), ('z', 4)] | 663 [('x', 1), ('y', 3), ('z', 4)] |
| 652 >>> sorted(d.items()) | 664 >>> sorted(d.items()) |
| 653 [('x', 1), ('y', 2)] | 665 [('x', 1), ('y', 2)] |
| 654 """ | 666 """ |
| 655 | 667 |
| 656 d = copy.copy(d) | 668 d = copy.copy(d) |
| 657 d.update(updates) | 669 d.update(updates) |
| 658 return d | 670 return d |
| OLD | NEW |