diff --git a/pisi/configfile.py b/pisi/configfile.py index 554f0e1a..078f9575 100644 --- a/pisi/configfile.py +++ b/pisi/configfile.py @@ -91,6 +91,7 @@ class BuildDefaults: buildhelper = None compressionlevel = 1 fallback = "ftp://ftp.pardus.org.tr/pub/source/2009" + max_delta_count = 0 class DirectoriesDefaults: "Default values for [directories] section" diff --git a/pisi/operations/build.py b/pisi/operations/build.py index 38517d57..3fd01ba9 100644 --- a/pisi/operations/build.py +++ b/pisi/operations/build.py @@ -230,6 +230,9 @@ class Builder: self.actionLocals = None self.actionGlobals = None + self.new_packages = [] + self.new_delta_packages = [] + def set_spec_file(self, specuri): if not specuri.is_remote_file(): # FIXME: doesn't work for file:// @@ -326,7 +329,7 @@ class Builder: self.run_install_action() # after all, we are ready to build/prepare the packages - return self.build_packages() + self.build_packages() def set_environment_vars(self): """Sets the environment variables for actions API to use""" @@ -944,9 +947,6 @@ class Builder: if debug_packages: self.spec.packages.extend(debug_packages) - self.new_packages = [] - self.old_packages = [] - install_dir = self.pkg_dir() + ctx.const.install_dir_suffix # Store additional files @@ -1053,24 +1053,15 @@ class Builder: if package.debug_package: orgname = util.join_path("debug", finfo.path) pkg.add_to_install(orgname, finfo.path) - pkg.close() - - # TODO Generate delta packages here os.chdir(c) - old_package_dirs = (ctx.config.compiled_packages_dir(), - ctx.config.debug_packages_dir(), - outdir or ".") + # FIXME Remove this hack + pkg.metadata.package.debug_package = package.debug_package - for update in self.spec.history[1:]: - filename = self.package_filename(self.metadata.package, update) - - for package_dir in old_package_dirs: - path = util.join_path(package_dir, filename) - if os.path.exists(path): - self.old_packages.append(filename) + self.new_delta_packages += self.build_delta_packages(pkg, outdir) + pkg.close() self.set_state("buildpackages") ctx.ui.info(_("Done.")) @@ -1091,7 +1082,33 @@ class Builder: os.environ.clear() os.environ.update(ctx.config.environ) - return self.new_packages, self.old_packages + def build_delta_packages(self, package, outdir): + max_delta_count = int(ctx.config.values.build.max_delta_count) + + if not max_delta_count: + return + + old_package_dirs = (ctx.config.compiled_packages_dir(), + ctx.config.debug_packages_dir(), + outdir or ".") + + old_packages = [] + for update in self.spec.history[1:]: + filename = self.package_filename(package.metadata.package, update) + + for package_dir in old_package_dirs: + path = util.join_path(package_dir, filename) + if os.path.exists(path): + old_packages.append(path) + break + + if len(old_packages) == max_delta_count: + break + + from pisi.operations.delta import create_delta_packages_from_obj + return create_delta_packages_from_obj(old_packages, + package, + self.specdir) # build functions... @@ -1102,7 +1119,7 @@ def build(pspec): else: pb = Builder.from_name(pspec) try: - result = pb.build() + pb.build() except ActionScriptException, e: ctx.ui.error("Action script error caught.") raise e @@ -1110,7 +1127,6 @@ def build(pspec): if ctx.ui.errors or ctx.ui.warnings: ctx.ui.warning(_("*** %d error(s), %d warning(s)") \ % (ctx.ui.errors, ctx.ui.warnings)) - return result order = {"none": 0, "fetch": 1, diff --git a/pisi/operations/delta.py b/pisi/operations/delta.py index 48e0e008..bf71e6c6 100644 --- a/pisi/operations/delta.py +++ b/pisi/operations/delta.py @@ -21,6 +21,78 @@ import pisi.util as util import pisi.archive as archive +# FIXME Reduce code duplication +def create_delta_packages_from_obj(old_packages, new_package_obj, specdir): + new_pkg_info = new_package_obj.metadata.package + new_pkg_files = new_package_obj.files + + new_pkg_path = new_package_obj.tmp_dir + + new_pkg_name = os.path.basename(new_package_obj.filepath) + name, new_version, new_release, new_distro_id, new_arch = \ + util.split_package_filename(new_pkg_name) + + cwd = os.getcwd() + out_dir = ctx.get_option("output_dir") + target_format = ctx.get_option("package_format") + delta_packages = [] + + for old_package in old_packages: + old_pkg = pisi.package.Package(old_package) + old_pkg_info = old_pkg.metadata.package + + delta_name = "-".join((old_pkg_info.name, + old_pkg_info.release, + new_pkg_info.release, + new_distro_id, + new_arch)) + ctx.const.delta_package_suffix + + ctx.ui.info(_("Creating %s...") % delta_name) + + if out_dir: + delta_name = util.join_path(out_dir, delta_name) + + old_pkg_files = old_pkg.get_files() + + delta_pkg = pisi.package.Package(delta_name, "w", format=target_format) + + # add comar files to package + os.chdir(specdir) + for pcomar in new_pkg_info.providesComar: + fname = util.join_path(ctx.const.comar_dir, pcomar.script) + delta_pkg.add_to_package(fname) + + # add xmls and files + os.chdir(new_pkg_path) + + delta_pkg.add_metadata_xml(ctx.const.metadata_xml) + delta_pkg.add_files_xml(ctx.const.files_xml) + + files_delta = find_delta(old_pkg_files, new_pkg_files) + + # only metadata information may change in a package, + # so no install archive added to delta package + if files_delta: + # Sort the files in-place according to their path for an ordered + # tarfile layout which dramatically improves the compression + # performance of lzma. This improvement is stolen from build.py + # (commit r23485). + files_delta.sort(key=lambda x: x.path) + + for finfo in files_delta: + orgname = util.join_path("install", finfo.path) + if new_pkg_info.debug_package: + orgname = util.join_path("debug", finfo.path) + delta_pkg.add_to_install(orgname, finfo.path) + + os.chdir(cwd) + + delta_pkg.close() + delta_packages.append(delta_name) + + # Return delta package names + return delta_packages + def create_delta_packages(old_packages, new_package): if new_package in old_packages: ctx.ui.warning(_("New package '%s' exists in the list of old "