Chromium Code Reviews| Index: recipe_engine/package.py |
| diff --git a/recipe_engine/package.py b/recipe_engine/package.py |
| index bd0ebf1ea48842beaa5bc6257c35721ac116ab03..7142901d464056ff7ba72c23cb5f7ec33804b021 100644 |
| --- a/recipe_engine/package.py |
| +++ b/recipe_engine/package.py |
| @@ -60,7 +60,12 @@ class ProtoFile(object): |
| """A collection of functions operating on a proto path. |
| This is an object so that it can be mocked in the tests. |
| + |
| + Proto files read will always be upconverted to the current proto in |
| + package.proto, and will be written back in their original format. |
| """ |
| + API_VERSIONS = (1, 2) |
| + |
| def __init__(self, path): |
| self._path = path |
| @@ -73,13 +78,32 @@ class ProtoFile(object): |
| return fh.read() |
| def read(self): |
| - text = self.read_raw() |
| + obj = json.loads(self.read_raw()) |
| + |
| + vers = obj.get('api_version') |
| + assert vers in self.API_VERSIONS, ( |
| + 'expected %r to be in %r' % (vers, self.API_VERSIONS) |
|
nodir
2017/03/28 03:36:13
to be one of
iannucci
2017/03/28 04:06:18
Done.
|
| + ) |
| + |
| + # upconvert old deps-as-a-list to deps-as-a-dict |
| + if 'deps' in obj and obj.get('api_version', 1) == 1: |
|
nodir
2017/03/28 03:36:13
use vers
iannucci
2017/03/28 04:06:18
Done.
|
| + obj['deps'] = {d.pop('project_id'): d for d in obj['deps']} |
| + |
| buf = package_pb2.Package() |
| - json_format.Parse(text, buf, ignore_unknown_fields=True) |
| + json_format.ParseDict(obj, buf, ignore_unknown_fields=True) |
| return buf |
| def to_raw(self, buf): |
| obj = json_format.MessageToDict(buf, preserving_proto_field_name=True) |
| + |
| + # downconvert if api_version is 1 |
| + if 'deps' in obj and obj.get('api_version', 1) < 2: |
|
nodir
2017/03/28 03:36:13
use vers ?
iannucci
2017/03/28 04:06:18
Done.
|
| + deps = [] |
| + for pid, d in sorted(obj['deps'].iteritems()): |
| + d['project_id'] = pid |
| + deps.append(d) |
| + obj['deps'] = deps |
| + |
| return json.dumps(obj, indent=2, sort_keys=True).replace(' \n', '\n') |
| def write(self, buf): |
| @@ -205,7 +229,6 @@ class GitRepoSpec(RepoSpec): |
| def dump(self): |
| buf = package_pb2.DepSpec( |
| - project_id=self.project_id, |
| url=self.repo, |
| branch=self.branch, |
| revision=self.revision) |
| @@ -330,7 +353,6 @@ class PathRepoSpec(RepoSpec): |
| def dump(self): |
| """Returns the package.proto DepSpec form of this RepoSpec.""" |
| return package_pb2.DepSpec( |
| - project_id=self.project_id, |
| url="file://"+self.path) |
| def __eq__(self, other): |
| @@ -462,12 +484,12 @@ class RollCandidate(object): |
| def get_rolled_spec(self): |
| """Returns a PackageSpec with all the deps updates from this roll.""" |
| - # TODO(phajdan.jr): does this preserve comments? should it? |
| new_deps = _updated( |
| self._package_spec.deps, |
| { project_id: spec for project_id, spec in |
| self._updates.iteritems() }) |
| return PackageSpec( |
| + self._package_spec.api_version, |
| self._package_spec.project_id, |
| self._package_spec.recipes_path, |
| new_deps) |
| @@ -499,9 +521,8 @@ class RollCandidate(object): |
| class PackageSpec(object): |
| - API_VERSION = 1 |
| - |
| - def __init__(self, project_id, recipes_path, deps): |
| + def __init__(self, api_version, project_id, recipes_path, deps): |
| + self._api_version = api_version |
| self._project_id = project_id |
| self._recipes_path = recipes_path |
| self._deps = deps |
| @@ -513,25 +534,25 @@ class PackageSpec(object): |
| @classmethod |
| def load_proto(cls, proto_file): |
| buf = proto_file.read() |
| - assert buf.api_version == cls.API_VERSION |
| - deps = { str(dep.project_id): cls.spec_for_dep(dep) |
| - for dep in buf.deps } |
| - return cls(str(buf.project_id), str(buf.recipes_path), deps) |
| + deps = { pid: cls.spec_for_dep(pid, dep) |
| + for pid, dep in buf.deps.iteritems() } |
| + return cls(buf.api_version, str(buf.project_id), str(buf.recipes_path), |
| + deps) |
| @classmethod |
| - def spec_for_dep(cls, dep): |
| + def spec_for_dep(cls, project_id, dep): |
| """Returns a RepoSpec for the given dependency protobuf.""" |
| url = str(dep.url) |
| if url.startswith("file://"): |
| - return PathRepoSpec(str(dep.project_id), url[len("file://"):]) |
| + return PathRepoSpec(str(project_id), url[len("file://"):]) |
| if dep.repo_type in (package_pb2.DepSpec.GIT, package_pb2.DepSpec.GITILES): |
| if dep.repo_type == package_pb2.DepSpec.GIT: |
| backend = fetch.GitBackend() |
| elif dep.repo_type == package_pb2.DepSpec.GITILES: |
| backend = fetch.GitilesBackend() |
| - return GitRepoSpec(str(dep.project_id), |
| + return GitRepoSpec(str(project_id), |
| url, |
| str(dep.branch), |
| str(dep.revision), |
| @@ -552,12 +573,16 @@ class PackageSpec(object): |
| def deps(self): |
| return self._deps |
| + @property |
| + def api_version(self): |
| + return self._api_version |
| + |
| def dump(self): |
| return package_pb2.Package( |
| - api_version=self.API_VERSION, |
| + api_version=self._api_version, |
| project_id=self._project_id, |
| recipes_path=self._recipes_path, |
| - deps=[ self._deps[dep].dump() for dep in sorted(self._deps.keys()) ]) |
| + deps={k: v.dump() for k, v in self._deps.iteritems()}) |
| def roll_candidates(self, root_spec, context): |
| """Returns list of consistent roll candidates, and rejected roll candidates. |