Gentoo Archives: gentoo-commits

From: "Fabian Groffen (grobian)" <grobian@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] portage r11287 - in main/branches/prefix: bin doc/package/ebuild/eapi pym/_emerge pym/portage pym/portage/tests pym/portage/tests/dep
Date: Wed, 30 Jul 2008 13:58:49
Message-Id: E1KOCCS-0006eW-Qb@stork.gentoo.org
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 ),