diff options
author | Daniel Burrows <dburrows@debian.org> | 2008-04-21 18:20:01 -0700 |
---|---|---|
committer | Daniel Burrows <dburrows@debian.org> | 2008-04-21 18:20:01 -0700 |
commit | a261ca7f4647c5dde1c61456fbe828546d7a3d27 (patch) | |
tree | 07911a2a6c335e639675bac929704964e3bcba87 | |
parent | 107d8df7aa949f1410879817534586d4f906b8cb (diff) | |
download | aptitude-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.cc | 49 |
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); } |