1 |
Author: zmedico |
2 |
Date: 2008-10-31 20:21:53 +0000 (Fri, 31 Oct 2008) |
3 |
New Revision: 11766 |
4 |
|
5 |
Modified: |
6 |
main/trunk/pym/portage/dbapi/vartree.py |
7 |
Log: |
8 |
Bug #243178 - Handle file collisions with preserved libs by allowing the |
9 |
current package to assume ownership and unregistering the preserved libraries. |
10 |
|
11 |
|
12 |
Modified: main/trunk/pym/portage/dbapi/vartree.py |
13 |
=================================================================== |
14 |
--- main/trunk/pym/portage/dbapi/vartree.py 2008-10-31 18:49:10 UTC (rev 11765) |
15 |
+++ main/trunk/pym/portage/dbapi/vartree.py 2008-10-31 20:21:53 UTC (rev 11766) |
16 |
@@ -2681,6 +2681,18 @@ |
17 |
collision_ignore = set([normalize_path(myignore) for myignore in \ |
18 |
shlex.split(self.settings.get("COLLISION_IGNORE", ""))]) |
19 |
|
20 |
+ # For collisions with preserved libraries, the current package |
21 |
+ # will assume ownership and the libraries will be unregistered. |
22 |
+ plib_dict = self.vartree.dbapi.plib_registry.getPreservedLibs() |
23 |
+ plib_cpv_map = {} |
24 |
+ plib_paths = set() |
25 |
+ for cpv, paths in plib_dict.iteritems(): |
26 |
+ plib_paths.update(paths) |
27 |
+ for f in paths: |
28 |
+ plib_cpv_map[f] = cpv |
29 |
+ plib_inodes = self._lstat_inode_map(plib_paths) |
30 |
+ plib_collisions = {} |
31 |
+ |
32 |
showMessage = self._display_merge |
33 |
scheduler = self._scheduler |
34 |
stopmerge = False |
35 |
@@ -2732,6 +2744,21 @@ |
36 |
raise |
37 |
if f[0] != "/": |
38 |
f="/"+f |
39 |
+ |
40 |
+ plibs = plib_inodes.get((dest_lstat.st_dev, dest_lstat.st_ino)) |
41 |
+ if plibs: |
42 |
+ for path in plibs: |
43 |
+ cpv = plib_cpv_map[path] |
44 |
+ paths = plib_collisions.get(cpv) |
45 |
+ if paths is None: |
46 |
+ paths = set() |
47 |
+ plib_collisions[cpv] = paths |
48 |
+ paths.add(path) |
49 |
+ # The current package will assume ownership and the |
50 |
+ # libraries will be unregistered, so exclude this |
51 |
+ # path from the normal collisions. |
52 |
+ continue |
53 |
+ |
54 |
isowned = False |
55 |
full_path = os.path.join(destroot, f.lstrip(os.path.sep)) |
56 |
for ver in mypkglist: |
57 |
@@ -2752,8 +2779,34 @@ |
58 |
break |
59 |
if stopmerge: |
60 |
collisions.append(f) |
61 |
- return collisions |
62 |
+ return collisions, plib_collisions |
63 |
|
64 |
+ def _lstat_inode_map(self, path_iter): |
65 |
+ """ |
66 |
+ Use lstat to create a map of the form: |
67 |
+ {(st_dev, st_ino) : set([path1, path2, ...])} |
68 |
+ Multiple paths may reference the same inode due to hardlinks. |
69 |
+ All lstat() calls are relative to self.myroot. |
70 |
+ """ |
71 |
+ root = self.myroot |
72 |
+ inode_map = {} |
73 |
+ for f in path_iter: |
74 |
+ path = os.path.join(root, f.lstrip(os.sep)) |
75 |
+ try: |
76 |
+ st = os.lstat(path) |
77 |
+ except OSError, e: |
78 |
+ if e.errno not in (errno.ENOENT, errno.ENOTDIR): |
79 |
+ raise |
80 |
+ del e |
81 |
+ continue |
82 |
+ key = (st.st_dev, st.st_ino) |
83 |
+ paths = inode_map.get(key) |
84 |
+ if paths is None: |
85 |
+ paths = set() |
86 |
+ inode_map[key] = paths |
87 |
+ paths.add(f) |
88 |
+ return inode_map |
89 |
+ |
90 |
def _security_check(self, installed_instances): |
91 |
if not installed_instances: |
92 |
return 0 |
93 |
@@ -3011,7 +3064,8 @@ |
94 |
blockers = self._blockers() |
95 |
if blockers is None: |
96 |
blockers = [] |
97 |
- collisions = self._collision_protect(srcroot, destroot, |
98 |
+ collisions, plib_collisions = \ |
99 |
+ self._collision_protect(srcroot, destroot, |
100 |
others_in_slot + blockers, myfilelist + mylinklist) |
101 |
|
102 |
# Make sure the ebuild environment is initialized and that ${T}/elog |
103 |
@@ -3289,6 +3343,24 @@ |
104 |
self.vartree.dbapi.removeFromContents(blocker, iter(contents), |
105 |
relative_paths=False) |
106 |
|
107 |
+ # Unregister any preserved libs that this package has overwritten |
108 |
+ # and update the contents of the packages that owned them. |
109 |
+ plib_registry = self.vartree.dbapi.plib_registry |
110 |
+ plib_dict = plib_registry.getPreservedLibs() |
111 |
+ for cpv, paths in plib_collisions.iteritems(): |
112 |
+ if cpv not in plib_dict: |
113 |
+ continue |
114 |
+ if cpv == self.mycpv: |
115 |
+ continue |
116 |
+ try: |
117 |
+ slot, counter = self.vartree.dbapi.aux_get( |
118 |
+ cpv, ["SLOT", "COUNTER"]) |
119 |
+ except KeyError: |
120 |
+ continue |
121 |
+ remaining = [f for f in plib_dict[cpv] if f not in paths] |
122 |
+ plib_registry.register(cpv, slot, counter, remaining) |
123 |
+ self.vartree.dbapi.removeFromContents(cpv, paths) |
124 |
+ |
125 |
self.vartree.dbapi._add(self) |
126 |
contents = self.getcontents() |