install: Optimize clean_leftover to gain speed

This improves the installation time of packages that have
lots of files with the same name.

e.g. kernel-module-headers having lots of files named
     "Makefile" and "Kconfig".
This commit is contained in:
Fatih Aşıcı
2010-05-07 22:11:00 +00:00
parent 837839abc8
commit 8ce34f239e
+28 -18
View File
@@ -418,37 +418,47 @@ class Install(AtomicOperation):
# remove left over files from the old package. # remove left over files from the old package.
def clean_leftovers(): def clean_leftovers():
new_files = dict((f.path, f) for f in self.files.list) stat_cache = {}
files_by_name = {}
new_paths = []
for f in self.files.list:
files_by_name.setdefault(os.path.basename(f.path), []).append(f)
new_paths.append(f.path)
for old_file in self.old_files.list: for old_file in self.old_files.list:
if old_file.path in new_files: if old_file.path in new_paths:
continue continue
old_file_path = os.path.join(ctx.config.dest_dir(), old_file.path) old_file_path = os.path.join(ctx.config.dest_dir(), old_file.path)
if not os.path.lexists(old_file_path): try:
old_file_stat = os.lstat(old_file_path)
except OSError:
continue continue
old_file_stat = None
old_filename = os.path.basename(old_file.path) old_filename = os.path.basename(old_file.path)
for new_file in self.files.list: # If one of the parent directories is a symlink, it is possible
# If one of the parent directories is a symlink, it is possible # that the new and old file paths refer to the same file.
# that the new and old file paths refer to the same file. # In this case, we must not remove the old file.
# In this case, we must not remove the old file. #
# # e.g. /lib/libdl.so and /lib64/libdl.so when /lib64 is
# e.g. /lib/libdl.so and /lib64/libdl.so when /lib64 is # a symlink to /lib.
# a symlink to /lib. for new_file in files_by_name.get(old_filename, []):
if os.path.basename(new_file.path) != old_filename: new_file_stat = stat_cache.get(new_file.path)
continue
new_file_path = os.path.join(ctx.config.dest_dir(), new_file.path) if new_file_stat is None:
if not os.path.lexists(new_file_path): path = os.path.join(ctx.config.dest_dir(), new_file.path)
continue try:
new_file_stat = os.lstat(path)
except OSError:
continue
old_file_stat = old_file_stat or os.lstat(old_file_path) stat_cache[new_file.path] = new_file_stat
if os.path.samestat(os.lstat(new_file_path), old_file_stat):
if os.path.samestat(new_file_stat, old_file_stat):
break break
else: else:
Remove.remove_file(old_file, self.pkginfo.name) Remove.remove_file(old_file, self.pkginfo.name)