Example #1
0
    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)
Example #2
0
    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))