1 |
Author: grobian |
2 |
Date: 2009-10-03 17:28:16 +0000 (Sat, 03 Oct 2009) |
3 |
New Revision: 14480 |
4 |
|
5 |
Modified: |
6 |
main/branches/prefix/pym/_emerge/depgraph.py |
7 |
main/branches/prefix/pym/portage/__init__.py |
8 |
Log: |
9 |
Merged from trunk -r14472:14478 |
10 |
|
11 |
| 14474 | Bug #287333 - If posible, use ebuild from tree when checking | |
12 |
| zmedico | for keyword mask on installed packages. | |
13 |
|
14 |
| 14476 | Bug #285832 - When updates are missed due to dependencies | |
15 |
| zmedico | that have been masked by backtracking, abbreviate output in | |
16 |
| | order to avoid terminal flooding. | |
17 |
|
18 |
| 14477 | Don't use a fork inside _test_pty_eof() because it gives | |
19 |
| zmedico | inconsistent results. | |
20 |
|
21 |
| 14478 | Fix race condition when using a fork inside _test_pty_eof(). | |
22 |
| zmedico | | |
23 |
|
24 |
|
25 |
Modified: main/branches/prefix/pym/_emerge/depgraph.py |
26 |
=================================================================== |
27 |
--- main/branches/prefix/pym/_emerge/depgraph.py 2009-10-03 10:08:26 UTC (rev 14479) |
28 |
+++ main/branches/prefix/pym/_emerge/depgraph.py 2009-10-03 17:28:16 UTC (rev 14480) |
29 |
@@ -318,9 +318,19 @@ |
30 |
return |
31 |
|
32 |
write = sys.stderr.write |
33 |
+ backtrack_masked = [] |
34 |
|
35 |
for pkg, parent_atoms in missed_updates: |
36 |
|
37 |
+ try: |
38 |
+ for parent, root, atom in parent_atoms: |
39 |
+ self._show_unsatisfied_dep(root, atom, myparent=parent, |
40 |
+ check_backtrack=True) |
41 |
+ except self._backtrack_mask: |
42 |
+ # This is displayed below in abbreviated form. |
43 |
+ backtrack_masked.append((pkg, parent_atoms)) |
44 |
+ continue |
45 |
+ |
46 |
write("\n!!! The following update has been skipped " + \ |
47 |
"due to unsatisfied dependencies:\n\n") |
48 |
|
49 |
@@ -333,6 +343,18 @@ |
50 |
self._show_unsatisfied_dep(root, atom, myparent=parent) |
51 |
write("\n") |
52 |
|
53 |
+ if backtrack_masked: |
54 |
+ # These are shown in abbreviated form, in order to avoid terminal |
55 |
+ # flooding from mask messages as reported in bug #285832. |
56 |
+ write("\n!!! The following update(s) have been skipped " + \ |
57 |
+ "due to unsatisfied dependencies\n" + \ |
58 |
+ "!!! triggered by backtracking:\n\n") |
59 |
+ for pkg, parent_atoms in backtrack_masked: |
60 |
+ write(str(pkg.slot_atom)) |
61 |
+ if pkg.root != '/': |
62 |
+ write(" for %s" % (pkg.root,)) |
63 |
+ write("\n") |
64 |
+ |
65 |
sys.stderr.flush() |
66 |
|
67 |
def _show_missed_update_slot_conflicts(self, missed_updates): |
68 |
@@ -1993,7 +2015,14 @@ |
69 |
|
70 |
return selected_atoms |
71 |
|
72 |
- def _show_unsatisfied_dep(self, root, atom, myparent=None, arg=None): |
73 |
+ def _show_unsatisfied_dep(self, root, atom, myparent=None, arg=None, |
74 |
+ check_backtrack=False): |
75 |
+ """ |
76 |
+ When check_backtrack=True, no output is produced and |
77 |
+ the method either returns or raises _backtrack_mask if |
78 |
+ a matching package has been masked by backtracking. |
79 |
+ """ |
80 |
+ backtrack_mask = False |
81 |
atom_set = InternalPackageSet(initial_atoms=(atom,)) |
82 |
xinfo = '"%s"' % atom |
83 |
if arg: |
84 |
@@ -2038,6 +2067,7 @@ |
85 |
self._dynamic_config._runtime_pkg_mask[pkg] |
86 |
mreasons.append('backtracking: %s' % \ |
87 |
', '.join(sorted(backtrack_reasons))) |
88 |
+ backtrack_mask = True |
89 |
if mreasons: |
90 |
masked_pkg_instances.add(pkg) |
91 |
if atom.use: |
92 |
@@ -2047,6 +2077,12 @@ |
93 |
masked_packages.append( |
94 |
(root_config, pkgsettings, cpv, metadata, mreasons)) |
95 |
|
96 |
+ if check_backtrack: |
97 |
+ if backtrack_mask: |
98 |
+ raise self._backtrack_mask() |
99 |
+ else: |
100 |
+ return |
101 |
+ |
102 |
missing_use_reasons = [] |
103 |
missing_iuse_reasons = [] |
104 |
for pkg in missing_use: |
105 |
@@ -2332,18 +2368,17 @@ |
106 |
different_version = avail_pkg |
107 |
break |
108 |
if different_version is not None: |
109 |
- |
110 |
- if installed and \ |
111 |
- pkgsettings._getMissingKeywords( |
112 |
- pkg.cpv, pkg.metadata): |
113 |
- continue |
114 |
- |
115 |
# If the ebuild no longer exists or it's |
116 |
# keywords have been dropped, reject built |
117 |
# instances (installed or binary). |
118 |
# If --usepkgonly is enabled, assume that |
119 |
# the ebuild status should be ignored. |
120 |
- if not usepkgonly: |
121 |
+ if usepkgonly: |
122 |
+ if installed and \ |
123 |
+ pkgsettings._getMissingKeywords( |
124 |
+ pkg.cpv, pkg.metadata): |
125 |
+ continue |
126 |
+ else: |
127 |
try: |
128 |
pkg_eb = self._pkg( |
129 |
pkg.cpv, "ebuild", root_config) |
130 |
@@ -4934,6 +4969,13 @@ |
131 |
graph in order to avoid making a potentially unsafe decision. |
132 |
""" |
133 |
|
134 |
+ class _backtrack_mask(_internal_exception): |
135 |
+ """ |
136 |
+ This is raised by _show_unsatisfied_dep() when it's called with |
137 |
+ check_backtrack=True and a matching package has been masked by |
138 |
+ backtracking. |
139 |
+ """ |
140 |
+ |
141 |
def need_restart(self): |
142 |
return self._dynamic_config._need_restart |
143 |
|
144 |
|
145 |
Modified: main/branches/prefix/pym/portage/__init__.py |
146 |
=================================================================== |
147 |
--- main/branches/prefix/pym/portage/__init__.py 2009-10-03 10:08:26 UTC (rev 14479) |
148 |
+++ main/branches/prefix/pym/portage/__init__.py 2009-10-03 17:28:16 UTC (rev 14480) |
149 |
@@ -3762,6 +3762,8 @@ |
150 |
Raises an EnvironmentError from openpty() if it fails. |
151 |
""" |
152 |
|
153 |
+ use_fork = False |
154 |
+ |
155 |
import array, fcntl, pty, select, termios |
156 |
test_string = 2 * "blah blah blah\n" |
157 |
test_string = _unicode_decode(test_string, |
158 |
@@ -3781,19 +3783,29 @@ |
159 |
termios.tcsetattr(slave_fd, termios.TCSANOW, mode) |
160 |
|
161 |
# Simulate a subprocess writing some data to the |
162 |
- # slave end of the pipe, and then exiting. Do a |
163 |
- # real fork here since otherwise os.close(slave_fd) |
164 |
- # would block on some platforms such as Darwin. |
165 |
- pids = process.spawn_bash(_unicode_encode("echo -n '%s'" % test_string, |
166 |
- encoding='utf_8', errors='strict'), env=os.environ, |
167 |
- fd_pipes={0:sys.stdin.fileno(), 1:slave_fd, 2:slave_fd}, |
168 |
- returnpid=True) |
169 |
- if isinstance(pids, int): |
170 |
- os.close(master_fd) |
171 |
- os.close(slave_fd) |
172 |
- raise EnvironmentError('spawn failed') |
173 |
+ # slave end of the pipe, and then exiting. |
174 |
+ pid = None |
175 |
+ if use_fork: |
176 |
+ pids = process.spawn_bash(_unicode_encode("echo -n '%s'" % test_string, |
177 |
+ encoding='utf_8', errors='strict'), env=os.environ, |
178 |
+ fd_pipes={0:sys.stdin.fileno(), 1:slave_fd, 2:slave_fd}, |
179 |
+ returnpid=True) |
180 |
+ if isinstance(pids, int): |
181 |
+ os.close(master_fd) |
182 |
+ os.close(slave_fd) |
183 |
+ raise EnvironmentError('spawn failed') |
184 |
+ pid = pids[0] |
185 |
+ else: |
186 |
+ os.write(slave_fd, _unicode_encode(test_string, |
187 |
+ encoding='utf_8', errors='strict')) |
188 |
os.close(slave_fd) |
189 |
|
190 |
+ # If using a fork, we must wait for the child here, |
191 |
+ # in order to avoid a race condition that would |
192 |
+ # lead to inconsistent results. |
193 |
+ if pid is not None: |
194 |
+ os.waitpid(pid, 0) |
195 |
+ |
196 |
master_file = os.fdopen(master_fd, 'rb') |
197 |
eof = False |
198 |
data = [] |
199 |
@@ -3823,7 +3835,6 @@ |
200 |
data.append(_unicode_decode(buf.tostring(), |
201 |
encoding='utf_8', errors='strict')) |
202 |
|
203 |
- os.waitpid(pids[0], 0) |
204 |
master_file.close() |
205 |
|
206 |
return test_string == ''.join(data) |