Discussion:
[gentoo-portage-dev] [PATCH] _unmerge_dirs: revisit parents of removed symlinks (bug 640058)
Zac Medico
2018-07-13 04:09:46 UTC
Permalink
When removal of a symlink is triggered by removal of the directory
that it points to, revisit the parent directories of the symlink.

Bug: https://bugs.gentoo.org/640058
---
pym/portage/dbapi/vartree.py | 23 +++++++++++++++++++++--
1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py
index 1a86940f1..43e3c4f1a 100644
--- a/pym/portage/dbapi/vartree.py
+++ b/pym/portage/dbapi/vartree.py
@@ -2753,9 +2753,13 @@ class dblink(object):
real_root = self.settings['ROOT']

dirs = sorted(dirs)
- dirs.reverse()
+ revisit = {}

- for obj, inode_key in dirs:
+ while True:
+ try:
+ obj, inode_key = dirs.pop()
+ except IndexError:
+ break
# Treat any directory named "info" as a candidate here,
# since it might have been in INFOPATH previously even
# though it may not be there now.
@@ -2818,6 +2822,7 @@ class dblink(object):
raise
if e.errno != errno.ENOENT:
show_unmerge("---", unmerge_desc["!empty"], "dir", obj)
+ revisit[obj] = inode_key

# Since we didn't remove this directory, record the directory
# itself for use in syncfs calls, if we have removed another
@@ -2838,6 +2843,7 @@ class dblink(object):
# no need to protect symlinks that point to it.
unmerge_syms = protected_symlinks.pop(inode_key, None)
if unmerge_syms is not None:
+ parents = []
for relative_path in unmerge_syms:
obj = os.path.join(real_root,
relative_path.lstrip(os.sep))
@@ -2849,6 +2855,19 @@ class dblink(object):
raise
del e
show_unmerge("!!!", "", "sym", obj)
+ else:
+ parents.append(os.path.dirname(obj))
+
+ if parents:
+ # Revisit parents recursively (bug 640058).
+ recursive_parents = []
+ for parent in set(parents):
+ while parent in revisit:
+ recursive_parents.append(parent)
+ parent = os.path.dirname(parent)
+
+ for parent in sorted(set(recursive_parents)):
+ dirs.append((parent, revisit.pop(parent)))

def isowner(self, filename, destroot=None):
"""
--
2.13.6
Brian Dolbec
2018-07-14 15:31:47 UTC
Permalink
On Thu, 12 Jul 2018 21:09:46 -0700
Post by Zac Medico
When removal of a symlink is triggered by removal of the directory
that it points to, revisit the parent directories of the symlink.
Bug: https://bugs.gentoo.org/640058
---
pym/portage/dbapi/vartree.py | 23 +++++++++++++++++++++--
1 file changed, 21 insertions(+), 2 deletions(-)
diff --git a/pym/portage/dbapi/vartree.py
b/pym/portage/dbapi/vartree.py index 1a86940f1..43e3c4f1a 100644
--- a/pym/portage/dbapi/vartree.py
+++ b/pym/portage/dbapi/vartree.py
real_root = self.settings['ROOT']
dirs = sorted(dirs)
- dirs.reverse()
+ revisit = {}
+ obj, inode_key = dirs.pop()
+ break
# Treat any directory named "info" as a
candidate here, # since it might have been in INFOPATH previously even
# though it may not be there now.
raise
show_unmerge("---",
unmerge_desc["!empty"], "dir", obj)
+ revisit[obj] = inode_key
# Since we didn't remove this
directory, record the directory # itself for use in syncfs calls, if
# no need to protect symlinks that
point to it. unmerge_syms = protected_symlinks.pop(inode_key, None)
+ parents = []
for relative_path in
unmerge_syms: obj = os.path.join(real_root,
relative_path.lstrip(os.sep))
raise
del e
show_unmerge("!!!",
"", "sym", obj)
+
parents.append(os.path.dirname(obj)) +
+ # Revisit parents
recursively (bug 640058).
+ recursive_parents =
[]
+ for parent in
+ while parent
+
recursive_parents.append(parent)
+
parent = os.path.dirname(parent) +
+ for parent in
+
dirs.append((parent, revisit.pop(parent)))
"""
LGTM
--
Brian Dolbec <dolsen>
Zac Medico
2018-07-15 00:01:39 UTC
Permalink
Post by Brian Dolbec
On Thu, 12 Jul 2018 21:09:46 -0700
Post by Zac Medico
When removal of a symlink is triggered by removal of the directory
that it points to, revisit the parent directories of the symlink.
Bug: https://bugs.gentoo.org/640058
---
pym/portage/dbapi/vartree.py | 23 +++++++++++++++++++++--
1 file changed, 21 insertions(+), 2 deletions(-)
diff --git a/pym/portage/dbapi/vartree.py
b/pym/portage/dbapi/vartree.py index 1a86940f1..43e3c4f1a 100644
--- a/pym/portage/dbapi/vartree.py
+++ b/pym/portage/dbapi/vartree.py
real_root = self.settings['ROOT']
dirs = sorted(dirs)
- dirs.reverse()
+ revisit = {}
+ obj, inode_key = dirs.pop()
+ break
# Treat any directory named "info" as a
candidate here, # since it might have been in INFOPATH previously even
# though it may not be there now.
raise
show_unmerge("---",
unmerge_desc["!empty"], "dir", obj)
+ revisit[obj] = inode_key
# Since we didn't remove this
directory, record the directory # itself for use in syncfs calls, if
# no need to protect symlinks that
point to it. unmerge_syms = protected_symlinks.pop(inode_key, None)
+ parents = []
for relative_path in
unmerge_syms: obj = os.path.join(real_root,
relative_path.lstrip(os.sep))
raise
del e
show_unmerge("!!!",
"", "sym", obj)
+
parents.append(os.path.dirname(obj)) +
+ # Revisit parents
recursively (bug 640058).
+ recursive_parents =
[]
+ for parent in
+ while parent
+
recursive_parents.append(parent)
+
parent = os.path.dirname(parent) +
+ for parent in
+
dirs.append((parent, revisit.pop(parent)))
"""
LGTM
Thanks, merged:

https://gitweb.gentoo.org/proj/portage.git/commit/?id=3a25c3fa13d7c62ba8c00d6c7a75eb907d34b568
--
Thanks,
Zac
Loading...