summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Burrows <dburrows@debian.org>2008-04-21 18:20:01 -0700
committerDaniel Burrows <dburrows@debian.org>2008-04-21 18:20:01 -0700
commita261ca7f4647c5dde1c61456fbe828546d7a3d27 (patch)
tree07911a2a6c335e639675bac929704964e3bcba87
parent107d8df7aa949f1410879817534586d4f906b8cb (diff)
downloadaptitude-a261ca7f4647c5dde1c61456fbe828546d7a3d27.tar.gz
Instead of bailing if the user asks for the justification chain of a manually installed package, search for a nontrivial solution. (Closes: #477038)
More precisely, this restricts the "why" algorithm to return only chains that are more than one step long. This means that instead of the lame excuse "<x> is manually installed" or "<x> is a starting point of the search", you now get an honest-to-goodness chain for manually installed packages, if one exists. The reason for doing this is simple: IMO, it's far more useful than simply refusing to show anything; the information might be interesting to the user, and it's not confusing since the "why" output always includes the automatic indicator for the package.
-rw-r--r--src/cmdline/cmdline_why.cc49
1 files changed, 26 insertions, 23 deletions
diff --git a/src/cmdline/cmdline_why.cc b/src/cmdline/cmdline_why.cc
index 686505ff..e1a112b4 100644
--- a/src/cmdline/cmdline_why.cc
+++ b/src/cmdline/cmdline_why.cc
@@ -702,12 +702,21 @@ namespace aptitude
bool &package_is_seen = seen_packages[frontid];
if(package_is_seen)
continue;
- package_is_seen = true;
-
- // Test whether the front node is a leaf; if it is, return
- // it and quit.
+ // Don't flag the starting package as "seen", since we want
+ // to be able to find self-loops.
+ if(!front.get_actions().empty())
+ package_is_seen = true;
+
+ // If we've stepped at least once, test whether the front
+ // node is a leaf; if it is, return it and quit.
+ //
+ // Checking that we stepped at least once (verified by
+ // checking whether we have any actions in our result list)
+ // ensures that we always return nontrivial answers (i.e.,
+ // even if the target of the search matches a leaf pattern,
+ // we'll keep looking past it).
pkgCache::VerIterator frontver = params.selected_version(frontpkg);
- if(!frontver.end())
+ if(!frontver.end() && !front.get_actions().empty())
for(std::vector<pkg_matcher *>::const_iterator it = leaves.begin();
!reached_leaf && it != leaves.end(); ++it)
{
@@ -889,16 +898,20 @@ cw::fragment *do_why(const std::vector<pkg_matcher *> &leaves,
else
seen_results.insert(results);
- if(first)
- first = false;
- else
- rval.push_back(cw::newline_fragment());
-
if(results.empty())
- return cw::fragf(_("The package \"%s\" is a starting point of the search.\n"),
- root.Name());
+ // This is a starting point of the search, but just keep
+ // going and try to find other people who depend on it.
+ // NB: this shouldn't be necessary (the search itself
+ // should filter out empty results) but it's left in for
+ // the sake of defensive programming.
+ continue;
else
{
+ if(first)
+ first = false;
+ else
+ rval.push_back(cw::newline_fragment());
+
std::vector<cw::fragment *> col1_entries, col2_entries, col3_entries;
for(std::vector<action>::const_iterator it = results.begin();
it != results.end(); ++it)
@@ -1106,17 +1119,7 @@ int cmdline_why(int argc, char *argv[],
if(m == NULL)
parsing_arguments_failed = true;
else
- {
- matchers.push_back(m);
- if(!pkg.end() && apply_matcher(m, pkg, pkg.CurrentVer(),
- *apt_cache_file, *apt_package_records))
- {
- printf(_("The package \"%s\" is manually installed.\n"),
- pkg.Name());
- delete m;
- return 0;
- }
- }
+ matchers.push_back(m);
}