Merged from trunk -r11947:11964
authorFabian Groffen <grobian@gentoo.org>
Sat, 22 Nov 2008 11:26:59 +0000 (11:26 -0000)
committerFabian Groffen <grobian@gentoo.org>
Sat, 22 Nov 2008 11:26:59 +0000 (11:26 -0000)
   | 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 <pva@g.o>  |
   |         | 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               |
   |         | <dberkholz@g.o> for the suggestion.                          |

   | 11964   | Add a short -d option for the new --include-dev option.      |
   | zmedico | Thanks to Joshua Kinard <kumba@g.o> for the suggestion.      |

svn path=/main/branches/prefix/; revision=12035

bin/repoman
man/repoman.1
pym/_emerge/__init__.py
pym/portage/dbapi/bintree.py
pym/portage/news.py

index 89dc322bf91a7c71575a48f40d19b1146176e094..c28504d2f42bb545695ab5e7b1102e3880bb00c7 100755 (executable)
@@ -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]
index a4a92a731ceb42dc4cd4de2d88065936756409bf..14165aae9d3a87a395c2c0724a35adbf595e18c3 100644 (file)
@@ -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
index 4a1e55b78246ed172c3368c0c56e1454914babaf..c8415db65e6421791825af3fa7609e8ed06b24a5 100644 (file)
@@ -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()
index c46ba7e76a59b6ebacbd088742b9e9bdf0879a34..e3822aeff306debf679fa8ba4f8f7514a0a7c349 100644 (file)
@@ -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 \
index aa979dabd921657e175e8cbc1abd1ebcc61b3dbf..90dd3a065796eb1af512d6b17a873e3fab86b9c0 100644 (file)
@@ -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)