Gentoo Archives: gentoo-commits

From: Zac Medico <zmedico@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/portage:master commit in: pym/portage/dbapi/, pym/portage/util/
Date: Tue, 28 Apr 2015 23:42:51
Message-Id: 1430264400.fb421c04f4754b5cdc1101bd5c64d27c00e5ea8d.zmedico@gentoo
1 commit: fb421c04f4754b5cdc1101bd5c64d27c00e5ea8d
2 Author: Zac Medico <zmedico <AT> gentoo <DOT> org>
3 AuthorDate: Mon Apr 27 02:57:44 2015 +0000
4 Commit: Zac Medico <zmedico <AT> gentoo <DOT> org>
5 CommitDate: Tue Apr 28 23:40:00 2015 +0000
6 URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=fb421c04
7
8 ro_checker: only check nearest parent (bug 547390)
9
10 The ro_checker code added in commit
11 47ef9a0969474f963dc8e52bfbbb8bc075e8d73c incorrectly asserts that all
12 parent directories be writable. Fix it to only assert that the nearest
13 parent directory be writable.
14
15 Fixes 47ef9a096947: ("Test for read-only filesystems, fixes bug 378869")
16 X-Gentoo-Bug: 547390
17 X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=547390
18 Acked-by: Brian Dolbec <dolsen <AT> gentoo.org>
19
20 pym/portage/dbapi/vartree.py | 44 +++++++++++++++++++++----------------
21 pym/portage/util/writeable_check.py | 24 ++++++++++++++++++--
22 2 files changed, 47 insertions(+), 21 deletions(-)
23
24 diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py
25 index 1c0deab..c59d778 100644
26 --- a/pym/portage/dbapi/vartree.py
27 +++ b/pym/portage/dbapi/vartree.py
28 @@ -33,7 +33,7 @@ portage.proxy.lazyimport.lazyimport(globals(),
29 'portage.util.env_update:env_update',
30 'portage.util.listdir:dircache,listdir',
31 'portage.util.movefile:movefile',
32 - 'portage.util.path:first_existing',
33 + 'portage.util.path:first_existing,iter_parents',
34 'portage.util.writeable_check:get_ro_checker',
35 'portage.util._dyn_libs.PreservedLibsRegistry:PreservedLibsRegistry',
36 'portage.util._dyn_libs.LinkageMapELF:LinkageMapELF@LinkageMap',
37 @@ -3325,6 +3325,8 @@ class dblink(object):
38 showMessage = self._display_merge
39 stopmerge = False
40 collisions = []
41 + dirs = set()
42 + dirs_ro = set()
43 symlink_collisions = []
44 destroot = self.settings['ROOT']
45 showMessage(_(" %s checking %d files for package collisions\n") % \
46 @@ -3337,6 +3339,18 @@ class dblink(object):
47
48 dest_path = normalize_path(
49 os.path.join(destroot, f.lstrip(os.path.sep)))
50 +
51 + parent = os.path.dirname(dest_path)
52 + if parent not in dirs:
53 + for x in iter_parents(parent):
54 + if x in dirs:
55 + break
56 + dirs.add(x)
57 + if os.path.isdir(x):
58 + if not os.access(x, os.W_OK):
59 + dirs_ro.add(x)
60 + break
61 +
62 try:
63 dest_lstat = os.lstat(dest_path)
64 except EnvironmentError as e:
65 @@ -3410,7 +3424,7 @@ class dblink(object):
66 break
67 if stopmerge:
68 collisions.append(f)
69 - return collisions, symlink_collisions, plib_collisions
70 + return collisions, dirs_ro, symlink_collisions, plib_collisions
71
72 def _lstat_inode_map(self, path_iter):
73 """
74 @@ -3759,7 +3773,6 @@ class dblink(object):
75 eagain_error = False
76
77 filelist = []
78 - dirlist = []
79 linklist = []
80 paths_with_newlines = []
81 def onerror(e):
82 @@ -3792,13 +3805,6 @@ class dblink(object):
83 unicode_errors.append(new_parent[ed_len:])
84 break
85
86 - relative_path = parent[srcroot_len:]
87 - if len(relative_path) >= eprefix_len:
88 - # Files are never installed outside of the prefix,
89 - # therefore we skip the readonly filesystem check for
90 - # parent directories of the prefix (see bug 544624).
91 - dirlist.append(os.path.join(destroot, relative_path))
92 -
93 for fname in files:
94 try:
95 fname = _unicode_decode(fname,
96 @@ -3911,9 +3917,17 @@ class dblink(object):
97 for other in others_in_slot])
98 prepare_build_dirs(settings=self.settings, cleanup=cleanup)
99
100 + # check for package collisions
101 + blockers = self._blockers
102 + if blockers is None:
103 + blockers = []
104 + collisions, dirs_ro, symlink_collisions, plib_collisions = \
105 + self._collision_protect(srcroot, destroot,
106 + others_in_slot + blockers, filelist, linklist)
107 +
108 # Check for read-only filesystems.
109 ro_checker = get_ro_checker()
110 - rofilesystems = ro_checker(dirlist)
111 + rofilesystems = ro_checker(dirs_ro)
112
113 if rofilesystems:
114 msg = _("One or more files installed to this package are "
115 @@ -3935,14 +3949,6 @@ class dblink(object):
116 eerror(msg)
117 return 1
118
119 - # check for package collisions
120 - blockers = self._blockers
121 - if blockers is None:
122 - blockers = []
123 - collisions, symlink_collisions, plib_collisions = \
124 - self._collision_protect(srcroot, destroot,
125 - others_in_slot + blockers, filelist, linklist)
126 -
127 if symlink_collisions:
128 # Symlink collisions need to be distinguished from other types
129 # of collisions, in order to avoid confusion (see bug #409359).
130
131 diff --git a/pym/portage/util/writeable_check.py b/pym/portage/util/writeable_check.py
132 index 445b2c2..ac6c039 100644
133 --- a/pym/portage/util/writeable_check.py
134 +++ b/pym/portage/util/writeable_check.py
135 @@ -1,5 +1,5 @@
136 #-*- coding:utf-8 -*-
137 -# Copyright 2014 Gentoo Foundation
138 +# Copyright 2014-2015 Gentoo Foundation
139 # Distributed under the terms of the GNU General Public License v2
140 """
141 Methods to check whether Portage is going to write to read-only filesystems.
142 @@ -13,6 +13,7 @@ from __future__ import unicode_literals
143
144 import io
145 import logging
146 +import os
147
148 from portage import _encodings
149 from portage.util import writemsg_level
150 @@ -68,7 +69,26 @@ def linux_ro_checker(dir_list):
151 level=logging.WARNING, noiselevel=-1)
152 return []
153
154 - return set.intersection(ro_filesystems, set(dir_list))
155 + ro_devs = {}
156 + for x in ro_filesystems:
157 + try:
158 + ro_devs[os.stat(x).st_dev] = x
159 + except OSError:
160 + pass
161 +
162 + ro_filesystems.clear()
163 + for x in set(dir_list):
164 + try:
165 + dev = os.stat(x).st_dev
166 + except OSError:
167 + pass
168 + else:
169 + try:
170 + ro_filesystems.add(ro_devs[dev])
171 + except KeyError:
172 + pass
173 +
174 + return ro_filesystems
175
176
177 def empty_ro_checker(dir_list):