* 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:
@@ -286,6 +286,23 @@ class Install(AtomicOperation):
|
|||||||
os.rename(path, newconfig)
|
os.rename(path, newconfig)
|
||||||
os.rename(oldconfig, path)
|
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.
|
# remove left over files from the old package.
|
||||||
def clean_leftovers():
|
def clean_leftovers():
|
||||||
new = set(map(lambda x: str(x.path), self.files.list))
|
new = set(map(lambda x: str(x.path), self.files.list))
|
||||||
@@ -322,6 +339,9 @@ class Install(AtomicOperation):
|
|||||||
if config_changed:
|
if config_changed:
|
||||||
rename_configs()
|
rename_configs()
|
||||||
|
|
||||||
|
if self.package_fname.endswith(ctx.const.package_suffix):
|
||||||
|
relocate_files()
|
||||||
|
|
||||||
if self.reinstall:
|
if self.reinstall:
|
||||||
clean_leftovers()
|
clean_leftovers()
|
||||||
|
|
||||||
|
|||||||
+41
-6
@@ -32,10 +32,9 @@ def create_delta_package(old_package, new_package):
|
|||||||
oldfiles = oldpkg.get_files()
|
oldfiles = oldpkg.get_files()
|
||||||
newfiles = newpkg.get_files()
|
newfiles = newpkg.get_files()
|
||||||
|
|
||||||
files_new = set(map(lambda x:(x.path, x.hash), newfiles.list))
|
files_delta = find_delta(oldfiles, newfiles)
|
||||||
files_old = set(map(lambda x:(x.path, x.hash), oldfiles.list))
|
|
||||||
files_delta = files_new - files_old
|
|
||||||
|
|
||||||
|
# FIXME: handle only metadata changed cases
|
||||||
if not files_delta:
|
if not files_delta:
|
||||||
ctx.ui.info(_("Nothing has changed between builds, not creating a delta"))
|
ctx.ui.info(_("Nothing has changed between builds, not creating a delta"))
|
||||||
return
|
return
|
||||||
@@ -57,7 +56,6 @@ def create_delta_package(old_package, new_package):
|
|||||||
if outdir:
|
if outdir:
|
||||||
deltaname = util.join_path(outdir, deltaname)
|
deltaname = util.join_path(outdir, deltaname)
|
||||||
|
|
||||||
print deltaname
|
|
||||||
deltapkg = Package(deltaname, "w")
|
deltapkg = Package(deltaname, "w")
|
||||||
|
|
||||||
c = os.getcwd()
|
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)
|
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")
|
tar = archive.ArchiveTar(util.join_path(ctx.config.tmp_dir(), ctx.const.install_tar_lzma), "tarlzma")
|
||||||
for path, hash in files_delta:
|
for file in files_delta:
|
||||||
tar.add_to_archive(path)
|
tar.add_to_archive(file.path)
|
||||||
tar.close()
|
tar.close()
|
||||||
|
|
||||||
os.chdir(ctx.config.tmp_dir())
|
os.chdir(ctx.config.tmp_dir())
|
||||||
@@ -88,3 +86,40 @@ def create_delta_package(old_package, new_package):
|
|||||||
os.chdir(c)
|
os.chdir(c)
|
||||||
|
|
||||||
ctx.ui.info(_("Done."))
|
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
|
||||||
|
|||||||
Reference in New Issue
Block a user