Index: recipe_engine/package.py |
diff --git a/recipe_engine/package.py b/recipe_engine/package.py |
index bd0ebf1ea48842beaa5bc6257c35721ac116ab03..52a3b6eab66704fc4afc73490e9f6fd8cf75221c 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 one of %r' % (vers, self.API_VERSIONS) |
+ ) |
+ |
+ # upconvert old deps-as-a-list to deps-as-a-dict |
+ if 'deps' in obj and vers == 1: |
+ 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 buf.deps and buf.api_version < 2: |
+ 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. |