1 |
Author: grobian |
2 |
Date: 2008-07-30 13:58:43 +0000 (Wed, 30 Jul 2008) |
3 |
New Revision: 11287 |
4 |
|
5 |
Modified: |
6 |
main/branches/prefix/bin/ebuild |
7 |
main/branches/prefix/doc/package/ebuild/eapi/2.docbook |
8 |
main/branches/prefix/pym/_emerge/__init__.py |
9 |
main/branches/prefix/pym/portage/__init__.py |
10 |
main/branches/prefix/pym/portage/dep.py |
11 |
main/branches/prefix/pym/portage/tests/__init__.py |
12 |
main/branches/prefix/pym/portage/tests/dep/test_isvalidatom.py |
13 |
Log: |
14 |
Merged from trunk 11267:11284 |
15 |
|
16 |
| 11268 | Add a quiet signal handler for SIGINT and SIGTERM since | |
17 |
| zmedico | emerge calls ebuild for fetchs and we don't want the user to | |
18 |
| | see a traceback due to the ebuild process getting killed. | |
19 |
|
20 |
| 11269 | Disable auto_schedule on all of Scheduler._task_queues and | |
21 |
| zmedico | schedule them inside _schedule_tasks(). This should help | |
22 |
| | solve a tight loop. | |
23 |
|
24 |
| 11270 | Fix the last part of Scheduler._main_loop() to work | |
25 |
| zmedico | correctly now that all the queues have auto_schedule | |
26 |
| | disabled. | |
27 |
|
28 |
| 11271 | Avoid triggering a tight loop AssertionError in | |
29 |
| zmedico | Scheduler._main_loop(). | |
30 |
|
31 |
| 11272 | Fix _choose_pkg() to always return something if nothing is | |
32 |
| zmedico | running or merging. | |
33 |
|
34 |
| 11273 | Count state changes in Scheduler._schedule_tasks() and avoid | |
35 |
| zmedico | some extra calls when nothing changes. | |
36 |
|
37 |
| 11274 | Change conditional USE deps syntax and expermental EAPI from | |
38 |
| zmedico | 2_pre0 to 2_pre1. Conditional syntax examples: Compact Form | |
39 |
| | Equivalent Expanded Form foo[bar?] bar? ( foo[bar] ) !bar? ( | |
40 |
| | foo ) foo[!bar?] bar? ( foo ) !bar? ( foo[-bar] ) foo[bar=] | |
41 |
| | bar? ( foo[bar] ) !bar? ( foo[-bar] ) foo[!bar=] bar? ( | |
42 |
| | foo[-bar] ) !bar? ( foo[bar] ) | |
43 |
|
44 |
| 11275 | * Optimize SequentialTaskQueue.schedule() by using a _dirty | |
45 |
| zmedico | attribute to track whether anything relevant has changed | |
46 |
| | since the last schedule call. Since we can always rely on | |
47 |
| | exist listeners being called, set of running tasks is always | |
48 |
| | pruned automatically and there is never any need to actively | |
49 |
| | prune it. * Remove the unused | |
50 |
| | SequentialTaskQueue.auto_schedule feature. | |
51 |
|
52 |
| 11276 | Just return a boolean "state changed" value from | |
53 |
| zmedico | Scheduler._schedule_tasks_imp(), since the other "remaining" | |
54 |
| | part is now unused. | |
55 |
|
56 |
| 11277 | Put a 5 second cap on the delay produced by | |
57 |
| zmedico | Scheduler._job_delay(). | |
58 |
|
59 |
| 11278 | When checking for news items in --pretend mode, pass | |
60 |
| zmedico | update=False into the NewsManager.getUnreadItems() call. | |
61 |
| | Emerge shouldn't have to update anything anyway when in | |
62 |
| | --pretend mode, and this helps to avoid potential permission | |
63 |
| | problems. In order to pass the relevant information about | |
64 |
| | options (--pretend state) to the new code, supporting | |
65 |
| | function parameters have been added to | |
66 |
| | display_news_notification(), post_emerge(), and | |
67 |
| | checkUpdatedNewsItems(). | |
68 |
|
69 |
| 11279 | * Add more use dep validation. * Fix broken handling of | |
70 |
| zmedico | !foo? reported by ABCD. | |
71 |
|
72 |
| 11280 | Remove unused variable. | |
73 |
| zmedico | | |
74 |
|
75 |
| 11281 | Remove redundant use dep validation code that's handled by | |
76 |
| zmedico | regular expression now. | |
77 |
|
78 |
| 11282 | * Fix Scheduler._restart_if_necessary() breakage so that the | |
79 |
| zmedico | given package is correctly compared to the last one in the | |
80 |
| | merge list. * Update code in depgraph.display() to be more | |
81 |
| | consistent with the code in | |
82 |
| | Scheduler._is_restart_necessary(). | |
83 |
|
84 |
| 11283 | Update foo[!bar=] syntax. | |
85 |
| zmedico | | |
86 |
|
87 |
| 11284 | Fix typo. | |
88 |
| zmedico | | |
89 |
|
90 |
|
91 |
Modified: main/branches/prefix/bin/ebuild |
92 |
=================================================================== |
93 |
--- main/branches/prefix/bin/ebuild 2008-07-30 13:55:41 UTC (rev 11286) |
94 |
+++ main/branches/prefix/bin/ebuild 2008-07-30 13:58:43 UTC (rev 11287) |
95 |
@@ -3,9 +3,24 @@ |
96 |
# Distributed under the terms of the GNU General Public License v2 |
97 |
# $Header: /var/cvsroot/gentoo-src/portage/bin/ebuild,v 1.18.2.3 2005/05/07 04:32:59 ferringb Exp $ |
98 |
|
99 |
+import sys |
100 |
+# This block ensures that ^C interrupts are handled quietly. |
101 |
+try: |
102 |
+ import signal |
103 |
+ |
104 |
+ def exithandler(signum,frame): |
105 |
+ signal.signal(signal.SIGINT, signal.SIG_IGN) |
106 |
+ signal.signal(signal.SIGTERM, signal.SIG_IGN) |
107 |
+ sys.exit(1) |
108 |
+ |
109 |
+ signal.signal(signal.SIGINT, exithandler) |
110 |
+ signal.signal(signal.SIGTERM, exithandler) |
111 |
+ |
112 |
+except KeyboardInterrupt: |
113 |
+ sys.exit(1) |
114 |
+ |
115 |
import optparse |
116 |
import os |
117 |
-import sys |
118 |
|
119 |
description = "See the ebuild(1) man page for more info" |
120 |
usage = "Usage: ebuild <ebuild file> <command> [command] ..." |
121 |
|
122 |
Modified: main/branches/prefix/doc/package/ebuild/eapi/2.docbook |
123 |
=================================================================== |
124 |
--- main/branches/prefix/doc/package/ebuild/eapi/2.docbook 2008-07-30 13:55:41 UTC (rev 11286) |
125 |
+++ main/branches/prefix/doc/package/ebuild/eapi/2.docbook 2008-07-30 13:58:43 UTC (rev 11287) |
126 |
@@ -1,5 +1,5 @@ |
127 |
<sect1 id='package-ebuild-eapi-2'> |
128 |
- <title>EAPI 2_pre0</title> |
129 |
+ <title>EAPI 2_pre1</title> |
130 |
<sect2 id='package-ebuild-eapi-2-helpers'> |
131 |
<title>Helpers</title> |
132 |
<sect3 id='package-ebuild-eapi-2-helpers-doman'> |
133 |
@@ -80,7 +80,7 @@ |
134 |
<entry>bar? ( foo[bar] ) !bar? ( foo )</entry> |
135 |
</row> |
136 |
<row> |
137 |
- <entry>foo[-bar?]</entry> |
138 |
+ <entry>foo[!bar?]</entry> |
139 |
<entry>bar? ( foo ) !bar? ( foo[-bar] )</entry> |
140 |
</row> |
141 |
<row> |
142 |
@@ -88,8 +88,8 @@ |
143 |
<entry>bar? ( foo[bar] ) !bar? ( foo[-bar] )</entry> |
144 |
</row> |
145 |
<row> |
146 |
- <entry>foo[bar!=]</entry> |
147 |
- <entry>bar? ( foo[-bar] ) !bar? ( foo[bar] )</entry> |
148 |
+ <entry>foo[!bar=]</entry> |
149 |
+ <entry>bar? ( foo[-bar] ) !bar? ( foo[bar] )</entry> |
150 |
</row> |
151 |
</tbody> |
152 |
</tgroup> |
153 |
|
154 |
Modified: main/branches/prefix/pym/_emerge/__init__.py |
155 |
=================================================================== |
156 |
--- main/branches/prefix/pym/_emerge/__init__.py 2008-07-30 13:55:41 UTC (rev 11286) |
157 |
+++ main/branches/prefix/pym/_emerge/__init__.py 2008-07-30 13:58:43 UTC (rev 11287) |
158 |
@@ -4083,6 +4083,8 @@ |
159 |
if settings.get("PORTAGE_DEBUG", "") == "1": |
160 |
self.edebug = 1 |
161 |
self.spinner = spinner |
162 |
+ self._running_root = trees["/"]["root_config"] |
163 |
+ self._opts_no_restart = Scheduler._opts_no_restart |
164 |
self.pkgsettings = {} |
165 |
# Maps slot atom to package for each Package added to the graph. |
166 |
self._slot_pkg_map = {} |
167 |
@@ -6142,7 +6144,7 @@ |
168 |
node in scheduled_uninstalls)] |
169 |
|
170 |
# sys-apps/portage needs special treatment if ROOT="/" |
171 |
- running_root = "/" |
172 |
+ running_root = self._running_root.root |
173 |
from portage.const import PORTAGE_PACKAGE_ATOM |
174 |
runtime_deps = InternalPackageSet( |
175 |
initial_atoms=[PORTAGE_PACKAGE_ATOM]) |
176 |
@@ -7351,23 +7353,23 @@ |
177 |
myprint="["+pkgprint(pkg_type)+" "+addl+"] "+indent+pkgprint(pkg_key)+" "+myoldbest+" "+verboseadd |
178 |
p.append(myprint) |
179 |
|
180 |
- mysplit = [portage.cpv_getkey(pkg_key)] + \ |
181 |
- list(portage.catpkgsplit(pkg_key)[2:]) |
182 |
- if "--tree" not in self.myopts and mysplit and \ |
183 |
- len(mysplit) == 3 and mysplit[0] == "sys-apps/portage" and \ |
184 |
- x[1] == "/": |
185 |
- |
186 |
- if mysplit[2] == "r0": |
187 |
- myversion = mysplit[1] |
188 |
+ if "--tree" not in self.myopts and \ |
189 |
+ "--quiet" not in self.myopts and \ |
190 |
+ not self._opts_no_restart.intersection(self.myopts) and \ |
191 |
+ pkg.root == self._running_root.root and \ |
192 |
+ portage.match_from_list( |
193 |
+ portage.const.PORTAGE_PACKAGE_ATOM, [pkg]): |
194 |
+ |
195 |
+ pn, ver, rev = pkg.pv_split |
196 |
+ if rev == "r0": |
197 |
+ myversion = ver |
198 |
else: |
199 |
- myversion = "%s-%s" % (mysplit[1], mysplit[2]) |
200 |
- |
201 |
+ myversion = "%s-%s" % (ver, rev) |
202 |
+ |
203 |
if myversion != portage.VERSION and "--quiet" not in self.myopts: |
204 |
if mylist_index < len(mylist) - 1: |
205 |
p.append(colorize("WARN", "*** Portage will stop merging at this point and reload itself,")) |
206 |
p.append(colorize("WARN", " then resume the merge.")) |
207 |
- print |
208 |
- del mysplit |
209 |
|
210 |
for x in p: |
211 |
print x |
212 |
@@ -8153,8 +8155,8 @@ |
213 |
|
214 |
class SequentialTaskQueue(SlotObject): |
215 |
|
216 |
- __slots__ = ("auto_schedule", "max_jobs", "running_tasks") + \ |
217 |
- ("_task_queue", "_scheduling") |
218 |
+ __slots__ = ("max_jobs", "running_tasks") + \ |
219 |
+ ("_dirty", "_scheduling", "_task_queue") |
220 |
|
221 |
def __init__(self, **kwargs): |
222 |
SlotObject.__init__(self, **kwargs) |
223 |
@@ -8162,19 +8164,21 @@ |
224 |
self.running_tasks = set() |
225 |
if self.max_jobs is None: |
226 |
self.max_jobs = 1 |
227 |
+ self._dirty = True |
228 |
|
229 |
def add(self, task): |
230 |
self._task_queue.append(task) |
231 |
- if self.auto_schedule: |
232 |
- self.schedule() |
233 |
+ self._dirty = True |
234 |
|
235 |
def addFront(self, task): |
236 |
self._task_queue.appendleft(task) |
237 |
- if self.auto_schedule: |
238 |
- self.schedule() |
239 |
+ self._dirty = True |
240 |
|
241 |
def schedule(self): |
242 |
|
243 |
+ if not self._dirty: |
244 |
+ return False |
245 |
+ |
246 |
if not self: |
247 |
return False |
248 |
|
249 |
@@ -8190,10 +8194,6 @@ |
250 |
max_jobs = self.max_jobs |
251 |
state_changed = False |
252 |
|
253 |
- for task in list(running_tasks): |
254 |
- if task.poll() is not None: |
255 |
- state_changed = True |
256 |
- |
257 |
while task_queue and \ |
258 |
(max_jobs is True or len(running_tasks) < max_jobs): |
259 |
task = task_queue.popleft() |
260 |
@@ -8204,14 +8204,20 @@ |
261 |
task.start() |
262 |
state_changed = True |
263 |
|
264 |
+ self._dirty = False |
265 |
self._scheduling = False |
266 |
|
267 |
return state_changed |
268 |
|
269 |
def _task_exit(self, task): |
270 |
- self.running_tasks.discard(task) |
271 |
- if self.auto_schedule: |
272 |
- self.schedule() |
273 |
+ """ |
274 |
+ Since we can always rely on exit listeners being called, the set of |
275 |
+ running tasks is always pruned automatically and there is never any need |
276 |
+ to actively prune it. |
277 |
+ """ |
278 |
+ self.running_tasks.remove(task) |
279 |
+ if self._task_queue: |
280 |
+ self._dirty = True |
281 |
|
282 |
def clear(self): |
283 |
self._task_queue.clear() |
284 |
@@ -8220,6 +8226,7 @@ |
285 |
task = running_tasks.pop() |
286 |
task.removeExitListener(self._task_exit) |
287 |
task.cancel() |
288 |
+ self._dirty = False |
289 |
|
290 |
def __nonzero__(self): |
291 |
return bool(self._task_queue or self.running_tasks) |
292 |
@@ -8867,14 +8874,8 @@ |
293 |
self._task_queues = self._task_queues_class() |
294 |
for k in self._task_queues.allowed_keys: |
295 |
setattr(self._task_queues, k, |
296 |
- SequentialTaskQueue(auto_schedule=True)) |
297 |
+ SequentialTaskQueue()) |
298 |
|
299 |
- # Merge tasks currently run synchronously which makes |
300 |
- # it necessary to disable auto_schedule in order to |
301 |
- # avoid excess recursion which prevents tasks from |
302 |
- # being marked complete as soon as they should be. |
303 |
- self._task_queues.merge.auto_schedule = False |
304 |
- |
305 |
self._prefetchers = weakref.WeakValueDictionary() |
306 |
self._pkg_queue = [] |
307 |
self._completed_tasks = set() |
308 |
@@ -8904,6 +8905,7 @@ |
309 |
# The load average takes some time to respond when new |
310 |
# jobs are added, so we need to limit the rate of adding |
311 |
# new jobs. |
312 |
+ self._job_delay_max = 5 |
313 |
self._job_delay_factor = 0.5 |
314 |
self._previous_job_start_time = None |
315 |
|
316 |
@@ -9322,7 +9324,7 @@ |
317 |
if not self._is_restart_necessary(pkg): |
318 |
return |
319 |
|
320 |
- if self._pkg_count.curval >= self._pkg_count.maxval: |
321 |
+ if pkg == self._mergelist[-1]: |
322 |
return |
323 |
|
324 |
self._main_loop_cleanup() |
325 |
@@ -9616,6 +9618,9 @@ |
326 |
return None |
327 |
return self._pkg_queue.pop(0) |
328 |
|
329 |
+ if not (self._jobs or self._task_queues.merge): |
330 |
+ return self._pkg_queue.pop(0) |
331 |
+ |
332 |
self._prune_digraph() |
333 |
|
334 |
chosen_pkg = None |
335 |
@@ -9687,27 +9692,39 @@ |
336 |
merge_queue = self._task_queues.merge |
337 |
|
338 |
while self._schedule(): |
339 |
- self._poll_loop() |
340 |
+ if self._poll_event_handlers: |
341 |
+ self._poll_loop() |
342 |
|
343 |
- while self._jobs or merge_queue: |
344 |
- if merge_queue.schedule() and \ |
345 |
- not self._poll_event_handlers: |
346 |
- continue |
347 |
- self._poll_loop() |
348 |
+ while True: |
349 |
+ self._schedule() |
350 |
+ if not self._jobs or merge_queue: |
351 |
+ break |
352 |
+ if self._poll_event_handlers: |
353 |
+ self._poll_loop() |
354 |
|
355 |
def _schedule_tasks(self): |
356 |
- self._task_queues.merge.schedule() |
357 |
+ self._schedule_tasks_imp() |
358 |
+ self._status_display.display() |
359 |
|
360 |
+ state_change = 0 |
361 |
+ for q in self._task_queues.values(): |
362 |
+ if q.schedule(): |
363 |
+ state_change += 1 |
364 |
+ |
365 |
# Cancel prefetchers if they're the only reason |
366 |
# the main poll loop is still running. |
367 |
if self._failed_pkgs and \ |
368 |
- not (self._jobs or self._task_queues.merge): |
369 |
+ not (self._jobs or self._task_queues.merge) and \ |
370 |
+ self._task_queues.fetch: |
371 |
self._task_queues.fetch.clear() |
372 |
+ state_change += 1 |
373 |
|
374 |
- remaining, state_change = self._schedule_tasks_imp() |
375 |
- self._status_display.display() |
376 |
- return remaining |
377 |
+ if state_change: |
378 |
+ self._schedule_tasks_imp() |
379 |
+ self._status_display.display() |
380 |
|
381 |
+ return bool(self._pkg_queue and not self._failed_pkgs) |
382 |
+ |
383 |
def _job_delay(self): |
384 |
""" |
385 |
@rtype: bool |
386 |
@@ -9718,8 +9735,10 @@ |
387 |
|
388 |
current_time = time.time() |
389 |
|
390 |
- if current_time - self._previous_job_start_time < \ |
391 |
- self._job_delay_factor * self._jobs: |
392 |
+ delay = self._job_delay_factor * self._jobs |
393 |
+ if delay > self._job_delay_max: |
394 |
+ delay = self._job_delay_max |
395 |
+ if (current_time - self._previous_job_start_time) < delay: |
396 |
return True |
397 |
|
398 |
return False |
399 |
@@ -9727,7 +9746,7 @@ |
400 |
def _schedule_tasks_imp(self): |
401 |
""" |
402 |
@rtype: bool |
403 |
- @returns: True if tasks remain to schedule, False otherwise. |
404 |
+ @returns: True if state changed, False otherwise. |
405 |
""" |
406 |
|
407 |
state_change = 0 |
408 |
@@ -9735,16 +9754,16 @@ |
409 |
while True: |
410 |
|
411 |
if not self._pkg_queue or self._failed_pkgs: |
412 |
- return (False, state_change) |
413 |
+ return bool(state_change) |
414 |
|
415 |
if self._choose_pkg_return_early or \ |
416 |
not self._can_add_job() or \ |
417 |
self._job_delay(): |
418 |
- return (True, state_change) |
419 |
+ return bool(state_change) |
420 |
|
421 |
pkg = self._choose_pkg() |
422 |
if pkg is None: |
423 |
- return (True, state_change) |
424 |
+ return bool(state_change) |
425 |
|
426 |
state_change += 1 |
427 |
|
428 |
@@ -9772,7 +9791,7 @@ |
429 |
task.addExitListener(self._build_exit) |
430 |
self._task_queues.jobs.add(task) |
431 |
|
432 |
- return (True, state_change) |
433 |
+ return bool(state_change) |
434 |
|
435 |
def _task(self, pkg): |
436 |
|
437 |
@@ -10653,20 +10672,20 @@ |
438 |
print " "+green("*")+" Processed",icount,"info files." |
439 |
|
440 |
|
441 |
-def display_news_notification(trees): |
442 |
- for target_root in trees: |
443 |
- if len(trees) > 1 and target_root != "/": |
444 |
- break |
445 |
- settings = trees[target_root]["vartree"].settings |
446 |
- portdb = trees[target_root]["porttree"].dbapi |
447 |
- vardb = trees[target_root]["vartree"].dbapi |
448 |
+def display_news_notification(root_config, myopts): |
449 |
+ target_root = root_config.root |
450 |
+ trees = root_config.trees |
451 |
+ settings = trees["vartree"].settings |
452 |
+ portdb = trees["porttree"].dbapi |
453 |
+ vardb = trees["vartree"].dbapi |
454 |
NEWS_PATH = os.path.join("metadata", "news") |
455 |
UNREAD_PATH = os.path.join(target_root, NEWS_LIB_PATH, "news") |
456 |
newsReaderDisplay = False |
457 |
+ update = "--pretend" not in myopts |
458 |
|
459 |
for repo in portdb.getRepositories(): |
460 |
unreadItems = checkUpdatedNewsItems( |
461 |
- portdb, vardb, NEWS_PATH, UNREAD_PATH, repo) |
462 |
+ portdb, vardb, NEWS_PATH, UNREAD_PATH, repo, update=update) |
463 |
if unreadItems: |
464 |
if not newsReaderDisplay: |
465 |
newsReaderDisplay = True |
466 |
@@ -10697,7 +10716,7 @@ |
467 |
mod_echo.finalize() |
468 |
return messages_shown |
469 |
|
470 |
-def post_emerge(trees, mtimedb, retval): |
471 |
+def post_emerge(root_config, myopts, mtimedb, retval): |
472 |
""" |
473 |
Misc. things to run at the end of a merge session. |
474 |
|
475 |
@@ -10718,9 +10737,9 @@ |
476 |
@returns: |
477 |
1. Calls sys.exit(retval) |
478 |
""" |
479 |
- for target_root in trees: |
480 |
- if len(trees) > 1 and target_root != "/": |
481 |
- break |
482 |
+ |
483 |
+ target_root = root_config.root |
484 |
+ trees = { target_root : root_config.trees } |
485 |
vardbapi = trees[target_root]["vartree"].dbapi |
486 |
settings = vardbapi.settings |
487 |
info_mtimes = mtimedb["info"] |
488 |
@@ -10763,7 +10782,7 @@ |
489 |
|
490 |
chk_updated_cfg_files(target_root + EPREFIX, config_protect) |
491 |
|
492 |
- display_news_notification(trees) |
493 |
+ display_news_notification(root_config, myopts) |
494 |
|
495 |
if vardbapi.plib_registry.hasEntries(): |
496 |
print |
497 |
@@ -10832,7 +10851,8 @@ |
498 |
" section of the " + bold("emerge") |
499 |
print " "+yellow("*")+" man page to learn how to update config files." |
500 |
|
501 |
-def checkUpdatedNewsItems(portdb, vardb, NEWS_PATH, UNREAD_PATH, repo_id): |
502 |
+def checkUpdatedNewsItems(portdb, vardb, NEWS_PATH, UNREAD_PATH, repo_id, |
503 |
+ update=False): |
504 |
""" |
505 |
Examines news items in repodir + '/' + NEWS_PATH and attempts to find unread items |
506 |
Returns the number of unread (yet relevent) items. |
507 |
@@ -10854,7 +10874,7 @@ |
508 |
""" |
509 |
from portage.news import NewsManager |
510 |
manager = NewsManager(portdb, vardb, NEWS_PATH, UNREAD_PATH) |
511 |
- return manager.getUnreadItems( repo_id, update=True ) |
512 |
+ return manager.getUnreadItems( repo_id, update=update ) |
513 |
|
514 |
def insert_category_into_atom(atom, category): |
515 |
alphanum = re.search(r'\w', atom) |
516 |
@@ -11357,6 +11377,7 @@ |
517 |
|
518 |
# Reload the whole config from scratch. |
519 |
settings, trees, mtimedb = load_emerge_config(trees=trees) |
520 |
+ root_config = trees[settings["ROOT"]]["root_config"] |
521 |
portdb = trees[settings["ROOT"]]["porttree"].dbapi |
522 |
|
523 |
if os.path.exists(myportdir+"/metadata/cache") and updatecache_flg: |
524 |
@@ -11390,7 +11411,7 @@ |
525 |
print red(" * ")+"To update portage, run 'emerge portage' now." |
526 |
print |
527 |
|
528 |
- display_news_notification(trees) |
529 |
+ display_news_notification(root_config, myopts) |
530 |
|
531 |
def action_metadata(settings, portdb, myopts): |
532 |
portage.writemsg_stdout("\n>>> Updating Portage cache: ") |
533 |
@@ -12838,7 +12859,8 @@ |
534 |
trees[settings["ROOT"]]["vartree"].dbapi.plib_registry.pruneNonExisting() |
535 |
|
536 |
if merge_count and not (buildpkgonly or fetchonly or pretend): |
537 |
- post_emerge(trees, mtimedb, retval) |
538 |
+ root_config = trees[settings["ROOT"]]["root_config"] |
539 |
+ post_emerge(root_config, myopts, mtimedb, retval) |
540 |
return retval |
541 |
|
542 |
def multiple_actions(action1, action2): |
543 |
@@ -13601,6 +13623,9 @@ |
544 |
sys.stderr.write(("emerge: The '%s' action does " + \ |
545 |
"not support '--pretend'.\n") % myaction) |
546 |
return 1 |
547 |
+ |
548 |
+ root_config = trees[settings["ROOT"]]["root_config"] |
549 |
+ |
550 |
if "sync" == myaction: |
551 |
action_sync(settings, trees, mtimedb, myopts, myaction) |
552 |
elif "metadata" == myaction: |
553 |
@@ -13626,30 +13651,29 @@ |
554 |
elif myaction in ("clean", "unmerge") or \ |
555 |
(myaction == "prune" and "--nodeps" in myopts): |
556 |
validate_ebuild_environment(trees) |
557 |
- root_config = trees[settings["ROOT"]]["root_config"] |
558 |
# When given a list of atoms, unmerge |
559 |
# them in the order given. |
560 |
ordered = myaction == "unmerge" |
561 |
if 1 == unmerge(root_config, myopts, myaction, myfiles, |
562 |
mtimedb["ldpath"], ordered=ordered): |
563 |
if not (buildpkgonly or fetchonly or pretend): |
564 |
- post_emerge(trees, mtimedb, os.EX_OK) |
565 |
+ post_emerge(root_config, myopts, mtimedb, os.EX_OK) |
566 |
|
567 |
elif myaction in ("depclean", "prune"): |
568 |
validate_ebuild_environment(trees) |
569 |
action_depclean(settings, trees, mtimedb["ldpath"], |
570 |
myopts, myaction, myfiles, spinner) |
571 |
if not (buildpkgonly or fetchonly or pretend): |
572 |
- post_emerge(trees, mtimedb, os.EX_OK) |
573 |
+ post_emerge(root_config, myopts, mtimedb, os.EX_OK) |
574 |
# "update", "system", or just process files: |
575 |
else: |
576 |
validate_ebuild_environment(trees) |
577 |
if "--pretend" not in myopts: |
578 |
- display_news_notification(trees) |
579 |
+ display_news_notification(root_config, myopts) |
580 |
retval = action_build(settings, trees, mtimedb, |
581 |
myopts, myaction, myfiles, spinner) |
582 |
# if --pretend was not enabled then display_news_notification |
583 |
# was already called by post_emerge |
584 |
if "--pretend" in myopts: |
585 |
- display_news_notification(trees) |
586 |
+ display_news_notification(root_config, myopts) |
587 |
return retval |
588 |
|
589 |
Modified: main/branches/prefix/pym/portage/__init__.py |
590 |
=================================================================== |
591 |
--- main/branches/prefix/pym/portage/__init__.py 2008-07-30 13:55:41 UTC (rev 11286) |
592 |
+++ main/branches/prefix/pym/portage/__init__.py 2008-07-30 13:58:43 UTC (rev 11287) |
593 |
@@ -4525,7 +4525,7 @@ |
594 |
eapi.remove(prop) |
595 |
|
596 |
# now check if what's left is supported (can) |
597 |
- properties = [ "2_pre0" ] # another clumpsy solution |
598 |
+ properties = [ "2_pre1" ] # another clumpsy solution |
599 |
for i in range(portage.const.EAPI + 1): |
600 |
properties.append(str(i)) |
601 |
|
602 |
|
603 |
Modified: main/branches/prefix/pym/portage/dep.py |
604 |
=================================================================== |
605 |
--- main/branches/prefix/pym/portage/dep.py 2008-07-30 13:55:41 UTC (rev 11286) |
606 |
+++ main/branches/prefix/pym/portage/dep.py 2008-07-30 13:58:43 UTC (rev 11287) |
607 |
@@ -347,6 +347,8 @@ |
608 |
_conditionals_class = portage.cache.mappings.slot_dict_class( |
609 |
("disabled", "enabled", "equal", "not_equal"), prefix="") |
610 |
|
611 |
+ _valid_use_re = re.compile(r'^[^-?!=][^?!=]*$') |
612 |
+ |
613 |
def __init__(self, use): |
614 |
enabled_flags = [] |
615 |
disabled_flags = [] |
616 |
@@ -356,23 +358,29 @@ |
617 |
|
618 |
for x in use: |
619 |
last_char = x[-1:] |
620 |
+ first_char = x[:1] |
621 |
+ |
622 |
if "?" == last_char: |
623 |
- if "-" == x[:1]: |
624 |
- conditional.disabled.append(x[1:-1]) |
625 |
+ if "!" == first_char: |
626 |
+ conditional.disabled.append( |
627 |
+ self._validate_flag(x, x[1:-1])) |
628 |
else: |
629 |
- conditional.enabled.append(x[:-1]) |
630 |
+ conditional.enabled.append( |
631 |
+ self._validate_flag(x, x[:-1])) |
632 |
+ |
633 |
elif "=" == last_char: |
634 |
- if "-" == x[:1]: |
635 |
- raise InvalidAtom("Invalid use dep: '%s'" % (x,)) |
636 |
- if "!" == x[-2:-1]: |
637 |
- conditional.not_equal.append(x[:-2]) |
638 |
+ if "!" == first_char: |
639 |
+ conditional.not_equal.append( |
640 |
+ self._validate_flag(x, x[1:-1])) |
641 |
else: |
642 |
- conditional.equal.append(x[:-1]) |
643 |
+ conditional.equal.append( |
644 |
+ self._validate_flag(x, x[:-1])) |
645 |
+ |
646 |
else: |
647 |
- if "-" == x[:1]: |
648 |
- disabled_flags.append(x[1:]) |
649 |
+ if "-" == first_char: |
650 |
+ disabled_flags.append(self._validate_flag(x, x[1:])) |
651 |
else: |
652 |
- enabled_flags.append(x) |
653 |
+ enabled_flags.append(self._validate_flag(x, x)) |
654 |
|
655 |
self.tokens = use |
656 |
if not isinstance(self.tokens, tuple): |
657 |
@@ -395,6 +403,11 @@ |
658 |
self.conditional = conditional |
659 |
break |
660 |
|
661 |
+ def _validate_flag(self, token, flag): |
662 |
+ if self._valid_use_re.match(flag) is None: |
663 |
+ raise InvalidAtom("Invalid use dep: '%s'" % (token,)) |
664 |
+ return flag |
665 |
+ |
666 |
def __nonzero__(self): |
667 |
return bool(self.tokens) |
668 |
|
669 |
@@ -413,22 +426,22 @@ |
670 |
|
671 |
x x? x |
672 |
-x x? |
673 |
- x -x? |
674 |
- -x -x? -x |
675 |
+ x !x? |
676 |
+ -x !x? -x |
677 |
|
678 |
x x= x |
679 |
-x x= -x |
680 |
- x x!= -x |
681 |
- -x x!= x |
682 |
+ x !x= -x |
683 |
+ -x !x= x |
684 |
|
685 |
Conditional syntax examples: |
686 |
|
687 |
- compact form equivalent expanded form |
688 |
+ Compact Form Equivalent Expanded Form |
689 |
|
690 |
foo[bar?] bar? ( foo[bar] ) !bar? ( foo ) |
691 |
- foo[-bar?] bar? ( foo ) !bar? ( foo[-bar] ) |
692 |
+ foo[!bar?] bar? ( foo ) !bar? ( foo[-bar] ) |
693 |
foo[bar=] bar? ( foo[bar] ) !bar? ( foo[-bar] ) |
694 |
- foo[bar!=] bar? ( foo[-bar] ) !bar? ( foo[bar] ) |
695 |
+ foo[!bar=] bar? ( foo[-bar] ) !bar? ( foo[bar] ) |
696 |
|
697 |
""" |
698 |
tokens = [] |
699 |
|
700 |
Modified: main/branches/prefix/pym/portage/tests/__init__.py |
701 |
=================================================================== |
702 |
--- main/branches/prefix/pym/portage/tests/__init__.py 2008-07-30 13:55:41 UTC (rev 11286) |
703 |
+++ main/branches/prefix/pym/portage/tests/__init__.py 2008-07-30 13:58:43 UTC (rev 11287) |
704 |
@@ -178,4 +178,4 @@ |
705 |
test_versions = ['1.0', '1.0-r1','2.3_p4','1.0_alpha57'] |
706 |
test_slots = [ None, '1','gentoo-sources-2.6.17','spankywashere'] |
707 |
test_usedeps = ['foo','-bar', ('foo','bar'), |
708 |
- ('foo','-bar'), ('foo?', '-bar?') ] |
709 |
+ ('foo','-bar'), ('foo?', '!bar?') ] |
710 |
|
711 |
Modified: main/branches/prefix/pym/portage/tests/dep/test_isvalidatom.py |
712 |
=================================================================== |
713 |
--- main/branches/prefix/pym/portage/tests/dep/test_isvalidatom.py 2008-07-30 13:55:41 UTC (rev 11286) |
714 |
+++ main/branches/prefix/pym/portage/tests/dep/test_isvalidatom.py 2008-07-30 13:58:43 UTC (rev 11287) |
715 |
@@ -25,16 +25,24 @@ |
716 |
( "sys-apps/portage:foo", True ), |
717 |
( "sys-apps/portage-2.1:foo", False ), |
718 |
( "sys-apps/portage-2.1:", False ), |
719 |
- ( "=sys-apps/portage-2.2*:foo[bar?,-baz?,doc!=,build=]", True ), |
720 |
- ( "=sys-apps/portage-2.2*:foo[build=]", True ), |
721 |
- ( "=sys-apps/portage-2.2*:foo[doc!=]", True ), |
722 |
+ ( "=sys-apps/portage-2.2*:foo[bar?,!baz?,!doc=,build=]", True ), |
723 |
+ ( "=sys-apps/portage-2.2*:foo[doc?]", True ), |
724 |
+ ( "=sys-apps/portage-2.2*:foo[!doc?]", True ), |
725 |
+ ( "=sys-apps/portage-2.2*:foo[doc=]", True ), |
726 |
+ ( "=sys-apps/portage-2.2*:foo[!doc=]", True ), |
727 |
+ ( "=sys-apps/portage-2.2*:foo[!doc]", False ), |
728 |
+ ( "=sys-apps/portage-2.2*:foo[!-doc]", False ), |
729 |
+ ( "=sys-apps/portage-2.2*:foo[!-doc=]", False ), |
730 |
+ ( "=sys-apps/portage-2.2*:foo[!-doc?]", False ), |
731 |
+ ( "=sys-apps/portage-2.2*:foo[-doc?]", False ), |
732 |
+ ( "=sys-apps/portage-2.2*:foo[-doc=]", False ), |
733 |
( "=sys-apps/portage-2.2*:foo[-doc!=]", False ), |
734 |
( "=sys-apps/portage-2.2*:foo[-doc=]", False ), |
735 |
- ( "=sys-apps/portage-2.2*:foo[bar][-baz][doc?][-build?]", False ), |
736 |
- ( "=sys-apps/portage-2.2*:foo[bar,-baz,doc?,-build?]", True ), |
737 |
- ( "=sys-apps/portage-2.2*:foo[bar,-baz,doc?,-build?,]", False ), |
738 |
- ( "=sys-apps/portage-2.2*:foo[,bar,-baz,doc?,-build?]", False ), |
739 |
- ( "=sys-apps/portage-2.2*:foo[bar,-baz][doc?,-build?]", False ), |
740 |
+ ( "=sys-apps/portage-2.2*:foo[bar][-baz][doc?][!build?]", False ), |
741 |
+ ( "=sys-apps/portage-2.2*:foo[bar,-baz,doc?,!build?]", True ), |
742 |
+ ( "=sys-apps/portage-2.2*:foo[bar,-baz,doc?,!build?,]", False ), |
743 |
+ ( "=sys-apps/portage-2.2*:foo[,bar,-baz,doc?,!build?]", False ), |
744 |
+ ( "=sys-apps/portage-2.2*:foo[bar,-baz][doc?,!build?]", False ), |
745 |
( "=sys-apps/portage-2.2*:foo[bar][doc,build]", False ), |
746 |
( ">~cate-gory/foo-1.0", False ), |
747 |
( ">~category/foo-1.0", False ), |