* delta creation and delta package installation.

The good part of this relocation implementation is that the 
  relocation info is calculated on-the-fly with no performance
  impact during the installation, so we do not need to find some
  somewhere to keep these.
This commit is contained in:
Faik Uygur
2007-02-05 14:51:05 +00:00
parent d1e650e6f1
commit c13f9aacf4
2 changed files with 62 additions and 7 deletions
+20
View File
@@ -286,6 +286,23 @@ class Install(AtomicOperation):
os.rename(path, newconfig)
os.rename(oldconfig, path)
# Delta package does not contain the files that have the same hash as in
# the old package's. Because it means the file has not changed. But some
# of these files may be relocated to some other directory in the new package.
# We handle these cases here.
def relocate_files():
from shutil import move
from pisi.delta import find_relocations
relocations = find_relocations(self.old_files, self.files)
for old_file, new_file in relocations:
path = "/%s" % os.path.dirname(new_file.path)
if not os.path.exists(path):
os.makedirs(path)
move("/%s" % old_file.path, "/%s" % new_file.path)
# remove left over files from the old package.
def clean_leftovers():
new = set(map(lambda x: str(x.path), self.files.list))
@@ -322,6 +339,9 @@ class Install(AtomicOperation):
if config_changed:
rename_configs()
if self.package_fname.endswith(ctx.const.package_suffix):
relocate_files()
if self.reinstall:
clean_leftovers()
+42 -7
View File
@@ -32,17 +32,16 @@ def create_delta_package(old_package, new_package):
oldfiles = oldpkg.get_files()
newfiles = newpkg.get_files()
files_new = set(map(lambda x:(x.path, x.hash), newfiles.list))
files_old = set(map(lambda x:(x.path, x.hash), oldfiles.list))
files_delta = files_new - files_old
files_delta = find_delta(oldfiles, newfiles)
# FIXME: handle only metadata changed cases
if not files_delta:
ctx.ui.info(_("Nothing has changed between builds, not creating a delta"))
return
ctx.ui.info(_("Creating delta PiSi package between %s %s") % (old_package, new_package))
# Unpack new package to temp
# Unpack new package to temp
newpkg_name = util.package_name(newmd.package.name, newmd.package.version, newmd.package.release, newmd.package.build, False)
newpkg_path = util.join_path(ctx.config.tmp_dir(), newpkg_name)
newpkg.extract_to(newpkg_path, True)
@@ -57,7 +56,6 @@ def create_delta_package(old_package, new_package):
if outdir:
deltaname = util.join_path(outdir, deltaname)
print deltaname
deltapkg = Package(deltaname, "w")
c = os.getcwd()
@@ -75,8 +73,8 @@ def create_delta_package(old_package, new_package):
ctx.build_leftover = util.join_path(ctx.config.tmp_dir(), ctx.const.install_tar_lzma)
tar = archive.ArchiveTar(util.join_path(ctx.config.tmp_dir(), ctx.const.install_tar_lzma), "tarlzma")
for path, hash in files_delta:
tar.add_to_archive(path)
for file in files_delta:
tar.add_to_archive(file.path)
tar.close()
os.chdir(ctx.config.tmp_dir())
@@ -88,3 +86,40 @@ def create_delta_package(old_package, new_package):
os.chdir(c)
ctx.ui.info(_("Done."))
# Hash not equals (these are the deltas)
# Hash equal but path different ones (these are the relocations)
# Hash and also path equal ones (do nothing)
def find_delta(oldfiles, newfiles):
hashto_files = {}
for file in newfiles.list:
hashto_files[file.hash] = file
files_new = set(map(lambda x:x.hash, newfiles.list))
files_old = set(map(lambda x:x.hash, oldfiles.list))
files_delta = files_new - files_old
return map(lambda x:hashto_files[x], files_delta)
def find_relocations(oldfiles, newfiles):
# FIXME: A minor issue: Hash files may collide in any package (same file in different
# places in the same package.. ex. COPYING). Handle this case if check fails while installing.
# Because of that we do not use sets here but lists to append those files.
files_new = {}
for file in newfiles.list:
files_new.setdefault(file.hash, []).append(file)
files_old = {}
for file in oldfiles.list:
files_old.setdefault(file.hash, []).append(file)
relocations = []
for hash in files_new.keys():
if hash in files_old and files_new[hash][0].path != files_old[hash][0].path:
relocations.append((files_old[hash][0], files_new[hash][0]))
return relocations