From 411a8461d08b88c5636e900d6297c2b4873af549 Mon Sep 17 00:00:00 2001 From: Zac Medico Date: Wed, 22 Feb 2012 21:30:19 -0800 Subject: [PATCH] Unmerge orphan directory symlinks for bug 384397. --- pym/portage/dbapi/vartree.py | 88 ++++++++++++++++++++++++++++++++++-- 1 file changed, 85 insertions(+), 3 deletions(-) diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py index 4b1ede121..6d354af20 100644 --- a/pym/portage/dbapi/vartree.py +++ b/pym/portage/dbapi/vartree.py @@ -2027,9 +2027,6 @@ class dblink(object): settings=self.settings, vartree=self.vartree, treetype="vartree", pipe=self._pipe)) - dest_root = self._eroot - dest_root_len = len(dest_root) - 1 - cfgfiledict = grabdict(self.vartree.dbapi._conf_mem_file) stale_confmem = [] protected_symlinks = {} @@ -2333,6 +2330,11 @@ class dblink(object): self._unmerge_dirs(mydirs, infodirs_inodes, protected_symlinks, unmerge_desc, unlink, os) + mydirs.clear() + + if protected_symlinks: + self._unmerge_protected_symlinks(others_in_slot, infodirs_inodes, + protected_symlinks, unmerge_desc, unlink, os) if protected_symlinks: msg = "One or more symlinks to directories have been " + \ @@ -2358,6 +2360,86 @@ class dblink(object): #remove self from vartree database so that our own virtual gets zapped if we're the last node self.vartree.zap(self.mycpv) + def _unmerge_protected_symlinks(self, others_in_slot, infodirs_inodes, + protected_symlinks, unmerge_desc, unlink, os): + + real_root = self.settings['ROOT'] + show_unmerge = self._show_unmerge + ignored_unlink_errnos = self._ignored_unlink_errnos + + flat_list = set() + flat_list.update(*protected_symlinks.values()) + flat_list = sorted(flat_list) + + for f in flat_list: + for dblnk in others_in_slot: + if dblnk.isowner(f): + # If another package in the same slot installed + # a file via a protected symlink, return early + # and don't bother searching for any other owners. + return + + msg = [] + msg.append("") + msg.append(_("Directory symlink(s) may need protection:")) + msg.append("") + + for f in flat_list: + msg.append("\t%s" % \ + os.path.join(real_root, f.lstrip(os.path.sep))) + + msg.append("") + msg.append(_("Searching all installed" + " packages for files installed via above symlink(s)...")) + msg.append("") + self._elog("elog", "postrm", msg) + + self.lockdb() + try: + owners = self.vartree.dbapi._owners.get_owners(flat_list) + self.vartree.dbapi.flush_cache() + finally: + self.unlockdb() + + for owner in list(owners): + if owner.mycpv == self.mycpv: + owners.pop(owner, None) + + if not owners: + msg = [] + msg.append(_("The above directory symlink(s) are all " + "safe to remove. Removing them now...")) + msg.append("") + self._elog("elog", "postrm", msg) + dirs = set() + for unmerge_syms in protected_symlinks.values(): + for relative_path in unmerge_syms: + obj = os.path.join(real_root, + relative_path.lstrip(os.sep)) + parent = os.path.dirname(obj) + while len(parent) > len(self._eroot): + try: + lstatobj = os.lstat(parent) + except OSError: + break + else: + dirs.add((parent, + (lstatobj.st_dev, lstatobj.st_ino))) + parent = os.path.dirname(parent) + try: + unlink(obj, os.lstat(obj)) + show_unmerge("<<<", "", "sym", obj) + except (OSError, IOError) as e: + if e.errno not in ignored_unlink_errnos: + raise + del e + show_unmerge("!!!", "", "sym", obj) + + protected_symlinks.clear() + self._unmerge_dirs(dirs, infodirs_inodes, + protected_symlinks, unmerge_desc, unlink, os) + dirs.clear() + def _unmerge_dirs(self, dirs, infodirs_inodes, protected_symlinks, unmerge_desc, unlink, os): -- 2.26.2