def __init__(self, fname, ufname=None, chksums=None, uchksums=None): # just calculate checksums if they weren't provided manually if chksums is None and uchksums is None: self.chksums = Chksum(fname) # calculate decompressed checksums remove_uncompressed = False if ufname is None: tmp_dir = tempdir() ufname = uncompress(fname, tmp_dir) remove_uncompressed = True self.uchksums = Chksum(ufname) if remove_uncompressed: rmtree(tmp_dir) # manual elif chksums is not None and uchksums is not None: if isinstance(chksums, Chksum): self.chksums = chksums else: self.chksums = Chksum(**chksums) if isinstance(uchksums, Chksum): self.uchksums = uchksums else: self.uchksums = Chksum(**uchksums) else: raise DeltaDBException('You need to provide both dictionaries ' \ 'or none of them: chksums and uchksums.') # we just want the basename stored self.fname = os.path.basename(fname) if ufname is None: ufname = uncompressed_filename_and_compressor(fname)[0] self.ufname = os.path.basename(ufname)
def generate(self, output_dir, clean_sources=True, compress=True, force=False): # running diffball from a git repository, while a version with xz support # isn't released :) diffball_bindir = os.environ.get('DIFFBALL_BINDIR', '/usr/bin') differ = os.path.join(diffball_bindir, 'differ') if not os.path.exists(output_dir): os.makedirs(output_dir) # building delta filename self.diff_file = os.path.join(output_dir, '%s-%s.%s' % (self.src.fname, self.dest.fname, self.patch_format)) # check if delta already exists diff_indisk = self.diff_file[:] if compress: diff_indisk += '.xz' if os.path.exists(diff_indisk) and not force: self.diff_file = diff_indisk raise DiffExists distdir = portage.settings['DISTDIR'] # copy files to output dir and uncompress src = os.path.join(output_dir, self.src.fname) dest = os.path.join(output_dir, self.dest.fname) copy2(os.path.join(distdir, self.src.fname), src) clean_sources and self.cleanup_register(src) copy2(os.path.join(distdir, self.dest.fname), dest) clean_sources and self.cleanup_register(dest) usrc = uncompress(src, output_dir) clean_sources and self.cleanup_register(usrc) udest = uncompress(dest, output_dir) clean_sources and self.cleanup_register(udest) cmd = [differ, usrc, udest, '--patch-format', self.patch_format, self.diff_file] if call(cmd) != os.EX_OK: raise DiffException('Failed to generate diff: %s' % self.diff_file) # validation of delta tmp_dir = tempdir() clean_sources and self.cleanup_register(tmp_dir) copy2(usrc, tmp_dir) copy2(self.diff_file, tmp_dir) uchksums = Chksum(self.diff_file) # xz it if compress: if call(['xz', '-f', self.diff_file]) != os.EX_OK: raise DiffException('Failed to xz diff: %s' % self.diff_file) self.diff_file += '.xz' self.dbrecord = DeltaDBRecord(DeltaDBFile(src, usrc), DeltaDBFile(dest, udest), DeltaDBFile(self.diff_file, chksums=Chksum( self.diff_file), uchksums=uchksums)) # reconstruct dest file from src and delta try: patch = Patch(self.dbrecord) patch.reconstruct(output_dir, tmp_dir, False) except PatchException, err: if clean_sources: os.unlink(self.diff_file) raise DiffException('Delta reconstruction failed: %s' % str(err))