It took some time for me to figure this out, but yay!
authorFabian Groffen <grobian@gentoo.org>
Mon, 24 Mar 2008 09:58:07 +0000 (09:58 -0000)
committerFabian Groffen <grobian@gentoo.org>
Mon, 24 Mar 2008 09:58:07 +0000 (09:58 -0000)
Fix preserve-libs immediately unmerging a just preserved (copied over)
lib, because it is no longer needed (!needed).

The problem was/is that the Darwin library naming is
lib<name>.<ver>.dylib instead of lib<name>.so.<ver>.  This results in
doing a simple sort() over the list a wrong order of the files, such
that the actual file (libneon.27.1.11.dylib) is seen before it's "soname"
symlink, which is recorded in the reverse NEEDED map.  Result, the code
thinks libneon.27.1.11.dylib is no longer needed, and unmerges it.

I now implemented a naive comparator which puts symlinks on top, as this
was implied order for the loop, which by coincidence works for .so
objects with sort().

I think this commit (or an improved version of it) is eligable for
merging in the trunk, as it is a safer (and more explicit) way of
ensuring that symlinks are seen before the actual files.

svn path=/main/branches/prefix/; revision=9499

pym/portage/dbapi/vartree.py

index a91a76b86450e690a86534e1ee554bda4f9fd286..c079e404eba0afe8349f6b4dceb11cc4341a1802 100644 (file)
@@ -1200,7 +1200,34 @@ class dblink(object):
                        plib_dict = plib_registry.getPreservedLibs()
                        for cpv in plib_dict:
                                keeplist = []
-                               plib_dict[cpv].sort()
+
+                               # for the loop below to work correctly, we need all
+                               # symlinks to come before the actual files, such that
+                               # the recorded symlinks (sonames) will be resolved into
+                               # their real target before the object is found not to be
+                               # in the reverse NEEDED map
+                               def symlink_compare(x, y):
+                                       if not os.path.exists(x):
+                                               if not os.path.exists(y):
+                                                       return 0
+                                               else:
+                                                       return -1
+                                       else:
+                                               if not os.path.exists(y):
+                                                       return 1
+                                               else:
+                                                       if os.path.islink(x):
+                                                               if os.path.islink(y):
+                                                                       return 0
+                                                               else:
+                                                                       return -1
+                                                       else:
+                                                               if os.path.islink(y):
+                                                                       return 1
+                                                               else:
+                                                                       return 0
+
+                               plib_dict[cpv].sort(symlink_compare)
                                for f in plib_dict[cpv]:
                                        if not os.path.exists(f) or os.path.realpath(f) in keeplist:
                                                continue