From: Fabian Groffen Date: Sat, 22 Nov 2008 11:26:59 +0000 (-0000) Subject: Merged from trunk -r11947:11964 X-Git-Url: http://git.tremily.us/gitweb.cgi?a=commitdiff_plain;h=ab10d2417e2aff1bfbdb093b04c26c6ee10077a2;p=portage.git Merged from trunk -r11947:11964 | 11948 | Bug #246853 - Redirect all ouput from | | zmedico | depgraph.display_problems() to stderr. | | 11949 | Make depgraph.display_problems() send unsatisfied dependency | | zmedico | ouput to stdout, for parsing by programs such as autounmask. | | 11951 | Bug #246821 - Avoid TypeError from binarytree.isremote() by | | zmedico | returning early if self._remotepkgs is None due to | | | PORTAGE_BINHOST being unset. | | 11953 | Check the return value from depgraph._add_pkg() when adding | | zmedico | library consumers inside action_depclean(). | | 11954 | Inside depgraph._add_pkg(), handle the case where multiple | | zmedico | different instances of the same version (typically one | | | installed and another not yet installed) have been pulled | | | into the graph due to a USE dependency. The "slot collision" | | | display is not helpful in a case like this, so display it as | | | an unsatisfied dependency. Thanks to Peter Volkov | | | for reporting. | | 11956 | Make NewsManager.updateItems() and getUnreadItems() return | | zmedico | early if PermissionDenied errors are encountered when | | | attempting to read the skip or unread files. | | 11958 | Fix logic inside PollScheduler._can_add_job() so that load | | zmedico | average is properly considered when a single job is running. | | 11960 | When a "slot conflict" occurs due to USE dependencies, | | zmedico | display the usual slot conflict output together with the | | | unsatisfied USE dependency output, since both might be | | | useful. | | 11962 | In order to reduce time consumed for dependency checks, skip | | zmedico | 'dev' profiles by default and add an --include-dev option | | | which causes them to be checked. Given the current | | | profiles.desc content, this approximately halves the number | | | of profiles checked by default and also halves the time | | | consumed by repoman. Thanks to Donnie Berkholz | | | for the suggestion. | | 11964 | Add a short -d option for the new --include-dev option. | | zmedico | Thanks to Joshua Kinard for the suggestion. | svn path=/main/branches/prefix/; revision=12035 --- diff --git a/bin/repoman b/bin/repoman index 89dc322bf..c28504d2f 100755 --- a/bin/repoman +++ b/bin/repoman @@ -191,6 +191,9 @@ def ParseArgs(args, qahelp): parser.add_option('-I', '--ignore-masked', dest='ignore_masked', action='store_true', default=False, help='ignore masked packages (not allowed with commit mode)') + parser.add_option('-d', '--include-dev', dest='include_dev', action='store_true', + default=False, help='include dev profiles in dependency checks') + parser.add_option('--without-mask', dest='without_mask', action='store_true', default=False, help='behave as if no package.mask entries exist (not allowed with commit mode)') @@ -1453,7 +1456,8 @@ for x in scanlist: for prof in profiles[arch]: - if prof[1] not in ("stable", "dev"): + if prof[1] not in ("stable", "dev") or \ + prof[1] == "dev" and not options.include_dev: continue profdir = portdir+"/profiles/"+prof[0] diff --git a/man/repoman.1 b/man/repoman.1 index a4a92a731..14165aae9 100644 --- a/man/repoman.1 +++ b/man/repoman.1 @@ -37,6 +37,9 @@ Ignore arch-specific failures (where arch != host) \fB\-I\fR, \fB\-\-ignore\-masked\fR Ignore masked packages (not allowed with commit mode) .TP +\fB\-d\fR, \fB\-\-include\-dev\fR +Include dev profiles in dependency checks. +.TP \fB\-\-without\-mask\fR Behave as if no package.mask entries exist (not allowed with commit mode) .TP diff --git a/pym/_emerge/__init__.py b/pym/_emerge/__init__.py index 4a1e55b78..c8415db65 100644 --- a/pym/_emerge/__init__.py +++ b/pym/_emerge/__init__.py @@ -4357,7 +4357,7 @@ class depgraph(object): self._show_merge_list() msg = [] - msg.append("\n!!! Multiple versions within a single " + \ + msg.append("\n!!! Multiple package instances within a single " + \ "package slot have been pulled\n") msg.append("!!! into the dependency graph, resulting" + \ " in a slot conflict:\n\n") @@ -4616,6 +4616,23 @@ class depgraph(object): priority=priority) return 1 else: + + if pkg.cpv == existing_node.cpv and \ + dep.atom is not None and \ + dep.atom.use: + # Multiple different instances of the same version + # (typically one installed and another not yet + # installed) have been pulled into the graph due + # to a USE dependency. The "slot collision" display + # is not helpful in a case like this, so display it + # as an unsatisfied dependency. + self._unsatisfied_deps_for_display.append( + ((dep.root, dep.atom), {"myparent":dep.parent})) + self._slot_collision_info.add((pkg.slot_atom, pkg.root)) + self._slot_collision_nodes.add(pkg) + self.digraph.addnode(pkg, myparent, priority=priority) + return 0 + if pkg in self._slot_collision_nodes: return 1 # A slot collision has occurred. Sometimes this coincides @@ -7613,8 +7630,35 @@ class depgraph(object): the merge list where it is most likely to be seen, but if display() is not going to be called then this method should be called explicitly to ensure that the user is notified of problems with the graph. + + All output goes to stderr, except for unsatisfied dependencies which + go to stdout for parsing by programs such as autounmask. """ + # Note that show_masked_packages() sends it's output to + # stdout, and some programs such as autounmask parse the + # output in cases when emerge bails out. However, when + # show_masked_packages() is called for installed packages + # here, the message is a warning that is more appropriate + # to send to stderr, so temporarily redirect stdout to + # stderr. TODO: Fix output code so there's a cleaner way + # to redirect everything to stderr. + sys.stdout.flush() + sys.stderr.flush() + stdout = sys.stdout + try: + sys.stdout = sys.stderr + self._display_problems() + finally: + sys.stdout = stdout + sys.stdout.flush() + sys.stderr.flush() + + # This goes to stdout for parsing by programs like autounmask. + for pargs, kwargs in self._unsatisfied_deps_for_display: + self._show_unsatisfied_dep(*pargs, **kwargs) + + def _display_problems(self): if self._circular_deps_for_display is not None: self._show_circular_deps( self._circular_deps_for_display) @@ -7709,9 +7753,6 @@ class depgraph(object): show_mask_docs() print - for pargs, kwargs in self._unsatisfied_deps_for_display: - self._show_unsatisfied_dep(*pargs, **kwargs) - def calc_changelog(self,ebuildpath,current,next): if ebuildpath == None or not os.path.exists(ebuildpath): return [] @@ -8561,7 +8602,7 @@ class PollScheduler(object): if max_load is not None and \ (max_jobs is True or max_jobs > 1) and \ - self._running_job_count() > 1: + self._running_job_count() >= 1: try: avg1, avg5, avg15 = os.getloadavg() except OSError, e: @@ -12742,9 +12783,12 @@ def action_depclean(settings, trees, ldpath_mtimes, for consumer_dblink in set(chain(*consumers.values())): consumer_pkg = vardb.get(("installed", myroot, consumer_dblink.mycpv, "nomerge")) - resolver._add_pkg(pkg, Dependency(parent=consumer_pkg, + if not resolver._add_pkg(pkg, + Dependency(parent=consumer_pkg, priority=UnmergeDepPriority(runtime=True), - root=pkg.root)) + root=pkg.root)): + resolver.display_problems() + return 1 writemsg_level("\nCalculating dependencies ") success = resolver._complete_graph() diff --git a/pym/portage/dbapi/bintree.py b/pym/portage/dbapi/bintree.py index c46ba7e76..e3822aeff 100644 --- a/pym/portage/dbapi/bintree.py +++ b/pym/portage/dbapi/bintree.py @@ -980,7 +980,7 @@ class binarytree(object): def isremote(self, pkgname): """Returns true if the package is kept remotely and it has not been downloaded (or it is only partially downloaded).""" - if pkgname not in self._remotepkgs: + if self._remotepkgs is None or pkgname not in self._remotepkgs: return False pkg_path = self.getname(pkgname) if os.path.exists(pkg_path) and \ diff --git a/pym/portage/news.py b/pym/portage/news.py index aa979dabd..90dd3a065 100644 --- a/pym/portage/news.py +++ b/pym/portage/news.py @@ -100,10 +100,13 @@ class NewsManager(object): unread_filename = self._unread_filename(repoid) unread_lock = lockfile(unread_filename, wantnewlockfile=1) try: - unread = set(grabfile(unread_filename)) - unread_orig = unread.copy() - skip = set(grabfile(skip_filename)) - skip_orig = skip.copy() + try: + unread = set(grabfile(unread_filename)) + unread_orig = unread.copy() + skip = set(grabfile(skip_filename)) + skip_orig = skip.copy() + except PermissionDenied: + return updates = [] for itemid in news: @@ -156,7 +159,10 @@ class NewsManager(object): except (InvalidLocation, OperationNotPermitted, PermissionDenied): return 0 try: - return len(grabfile(unread_filename)) + try: + return len(grabfile(unread_filename)) + except PermissionDenied: + return 0 finally: if unread_lock: unlockfile(unread_lock)