From b1db741e8a10bb38d10dde7538616bdeec42f03b Mon Sep 17 00:00:00 2001 From: Fabio Erculiani Date: Fri, 28 May 2010 19:54:36 +0200 Subject: [PATCH] [entropy.client.interfaces.package] fix critical bug on pkg update Files just installed were removed due to being added to a different symlinked path. Use os.path.realpath to determine if two paths point to the same file object. --- .../entropy/client/interfaces/package.py | 55 ++++++++++++++----- 1 file changed, 40 insertions(+), 15 deletions(-) diff --git a/libraries/entropy/client/interfaces/package.py b/libraries/entropy/client/interfaces/package.py index 31f275da8..21c557a45 100644 --- a/libraries/entropy/client/interfaces/package.py +++ b/libraries/entropy/client/interfaces/package.py @@ -1529,6 +1529,12 @@ class Package: pkg_dbconn.closeDB() + # fix removecontent, need to check if we just installed files + # that resolves at the same directory path (different symlink) + my_remove_content = self.__filter_out_files_installed_on_diff_path( + self.pkgmeta['removecontent'], self.pkgmeta['__items_installed']) + self.pkgmeta['removecontent'] -= my_remove_content + # filter out files not installed from content metadata self.__filter_out_items_not_installed_from_content(data) @@ -1682,6 +1688,10 @@ class Package: return sorted(config_protect) + def __get_sys_root(self): + return self.pkgmeta.get('unittest_root', '') + \ + etpConst['systemroot'] + def _move_image_to_system(self, already_protected_config_files): # load CONFIG_PROTECT and its mask @@ -1689,8 +1699,7 @@ class Package: mask = self.__get_package_match_config_protect(mask = True) # support for unit testing settings - sys_root = self.pkgmeta.get('unittest_root', '') + \ - etpConst['systemroot'] + sys_root = self.__get_sys_root() sys_set_plg_id = \ etpConst['system_settings_plugins_ids']['client_plugin'] misc_data = self._settings[sys_set_plg_id]['misc'] @@ -2081,24 +2090,40 @@ class Package: # EntropyRepository.contentDiff for obvious reasons # (think about stuff in /usr/lib and /usr/lib64, # where the latter is just a symlink to the former) + self.pkgmeta['__items_installed'] = items_installed if self.pkgmeta.get('removecontent'): - my_remove_content = set() - for mypath in self.pkgmeta['removecontent']: - - if not mypath: - continue # empty? - - item_dir = os.path.dirname("%s%s" % (sys_root, mypath,)) - item = os.path.join(os.path.realpath(item_dir), - os.path.basename(mypath)) - - if item in items_installed: - my_remove_content.add(item) - + my_remove_content = self.__filter_out_files_installed_on_diff_path( + self.pkgmeta['removecontent'], + self.pkgmeta['__items_installed']) self.pkgmeta['removecontent'] -= my_remove_content return 0 + def __filter_out_files_installed_on_diff_path(self, remove_content, + installed_content): + """ + Use case: if a package provided files in /lib then, a new version + of that package moved the same files under /lib64, we need to check + if both directory paths solve to the same inode and if so, add to our + set that we're going to return. + """ + sys_root = self.__get_sys_root() + my_remove_content = set() + for mypath in remove_content: + + if not mypath: + continue # empty? + + item_dir = os.path.dirname("%s%s" % (sys_root, mypath,)) + item = os.path.join(os.path.realpath(item_dir), + os.path.basename(mypath)) + + if item in installed_content: + my_remove_content.add(item) + my_remove_content.add(mypath) + + return my_remove_content + def __allocate_masked_file(self, maskfile, fromfile): # check if file and tofile are equal