diff options
author | Richard Maw <richard.maw@codethink.co.uk> | 2012-06-14 10:27:16 +0100 |
---|---|---|
committer | Richard Maw <richard.maw@codethink.co.uk> | 2012-06-14 11:32:52 +0000 |
commit | 501ffc431346e6123458549daa3e96c1f24058db (patch) | |
tree | bd426ed522f8b4414f2215a625efc8f31c1d4b5b | |
parent | 22b6a835d3645aacecc82ad522148bcba681ea78 (diff) | |
download | morph-501ffc431346e6123458549daa3e96c1f24058db.tar.gz |
builder2: write json to cache instead of tarball
Note that this has no way to deal with an old cached stratum
being a tarball yet.
Strata are now json files listing basenames, which get converted into
ArtifactCacheReferences.
SystemBuilders now have to ensure they download the chunks as well, since
having the strata doesn't imply that the chunks are also available.
Overlap checking is slightly more complicated by strata not being tarballs
any more, but this is dealt with by looking at the chunks' tarballs.
-rw-r--r-- | morphlib/builder2.py | 86 |
1 files changed, 53 insertions, 33 deletions
diff --git a/morphlib/builder2.py b/morphlib/builder2.py index caf0d8e1..56834902 100644 --- a/morphlib/builder2.py +++ b/morphlib/builder2.py @@ -23,6 +23,7 @@ from collections import defaultdict import tarfile import morphlib +from morphlib.artifactcachereference import ArtifactCacheReference def ldconfig(runcmd, rootdir): # pragma: no cover @@ -60,17 +61,40 @@ def ldconfig(runcmd, rootdir): # pragma: no cover else: logging.debug('No %s, not running ldconfig' % conf) +def download_depends(constituents, lac, rac): + for constituent in constituents: + if not lac.has(constituent): + source = rac.get(constituent) + target = lac.put(constituent) + shutil.copyfileobj(source, target) + target.close() + source.close() + +def get_chunk_files(f): + tar = tarfile.open(fileobj=f) + for member in tar.getmembers(): + if member.type is not tarfile.DIRTYPE: + yield member.name + tar.close() + +def get_stratum_files(f, lac): + for ca in ((ArtifactCacheReference(a) for a in json.load(f)): + cf = lac.get(ca) + for filename in get_chunk_files(cf): + yield filename + cf.close() def check_overlap(artifact, constituents, lac): #pragma: no cover # check whether strata overlap installed = defaultdict(set) for dep in constituents: handle = lac.get(dep) - tar = tarfile.open(fileobj=handle) - for member in tar.getmembers(): - if member.type is not tarfile.DIRTYPE: - installed[member.name].add(dep) - tar.close() + if artifact.source.morphology['kind'] == 'stratum': + for filename in get_chunk_files(handle): + installed[filename].add(dep) + elif artifact.source.morphology['kind'] == 'system': + for filename in get_stratum_files(handle, lac): + installed[filename].add(dep) handle.close() overlaps = defaultdict(set) for filename, artifacts in installed.iteritems(): @@ -344,35 +368,23 @@ class StratumBuilder(BuilderBase): constituents = [dependency for dependency in self.artifact.dependencies if dependency.source.morphology['kind'] == 'chunk'] - with self.build_watch('unpack-chunks'): + # the only reason the StratumBuilder has to download chunks is to check + # for overlap now that strata are lists of chunks + with self.build_watch('check-chunks'): # download the chunk artifact if necessary - for chunk_artifact in constituents: - if not self.local_artifact_cache.has(chunk_artifact): - source = self.remote_artifact_cache.get(chunk_artifact) - target = self.local_artifact_cache.put(chunk_artifact) - shutil.copyfileobj(source, target) - target.close() - source.close() - + download_depends(constituents, + self.local_artifact_cache, + self.remote_artifact_cache) # check for chunk overlaps check_overlap(self.artifact, constituents, self.local_artifact_cache) - # unpack it from the local artifact cache - for chunk_artifact in constituents: - logging.debug('unpacking chunk %s into stratum %s' % - (chunk_artifact.basename(), - self.artifact.basename())) - f = self.local_artifact_cache.get(chunk_artifact) - morphlib.bins.unpack_binary_from_file(f, destdir) - f.close() - - with self.build_watch('create-binary'): + with self.build_watch('create-chunk-list'): artifact_name = self.artifact.source.morphology['name'] self.write_metadata(destdir, artifact_name) artifact = self.new_artifact(artifact_name) with self.local_artifact_cache.put(artifact) as f: - morphlib.bins.create_stratum(destdir, f) + json.dump([c.basename() for c in constituents], f) self.save_build_times() @@ -481,14 +493,19 @@ class SystemBuilder(BuilderBase): # pragma: no cover def _unpack_strata(self, path): logging.debug('Unpacking strata to %s' % path) with self.build_watch('unpack-strata'): - # download the stratum artifact if necessary + # download the stratum artifacts if necessary + download_depends(self.artifact.dependencies, + self.local_artifact_cache, + self.remote_artifact_cache) + + # download the chunk artifacts if necessary for stratum_artifact in self.artifact.dependencies: - if not self.local_artifact_cache.has(stratum_artifact): - source = self.remote_artifact_cache.get(stratum_artifact) - target = self.local_artifact_cache.put(stratum_artifact) - shutil.copyfileobj(source, target) - target.close() - source.close() + f = self.local_artifact_cache.get(stratum_artifact) + chunks = [ArtifactCacheReference(a) for a in json.load(f)] + download_depends(chunks, + self.local_artifact_cache, + self.remote_artifact_cache) + f.close() # check whether the strata overlap check_overlap(self.artifact, self.artifact.dependencies, @@ -497,7 +514,10 @@ class SystemBuilder(BuilderBase): # pragma: no cover # unpack it from the local artifact cache for stratum_artifact in self.artifact.dependencies: f = self.local_artifact_cache.get(stratum_artifact) - morphlib.bins.unpack_binary_from_file(f, path) + for chunk in (ArtifactCacheReference(a) for a in json.load(f)): + chunk_handle = self.local_artifact_cache.get(chunk) + morphlib.bins.unpack_binary_from_file(chunk_handle, path) + chunk_handle.close() f.close() ldconfig(self.app.runcmd, path) |