diff options
author | Daniel Burrows <dburrows@debian.org> | 2010-04-20 08:39:18 -0700 |
---|---|---|
committer | Daniel Burrows <dburrows@debian.org> | 2010-04-20 08:39:18 -0700 |
commit | 81c463456e9e67cf894286c78d6b9c342fdf67ac (patch) | |
tree | 5a46aca111012218ef7fd0d7c4f0c6a29bd3fde5 | |
parent | 4d0d07d1bb75ba3c1ebc532d85eb05a84ac3f6e7 (diff) | |
download | aptitude-81c463456e9e67cf894286c78d6b9c342fdf67ac.tar.gz |
Allow "conflict" to be specified as a safety level again, with its old behavior, and fix setting safety levels using the old names.
aptitude's behavior should now be fully compatible with pre-0.6.2
releases (by default). The safety level change fixes the fact that
you could raise safety levels using the old names but not lower them.
-rw-r--r-- | doc/en/aptitude.xml | 21 | ||||
-rw-r--r-- | src/generic/apt/aptitude_resolver.cc | 67 | ||||
-rw-r--r-- | src/generic/apt/aptitude_resolver.h | 11 | ||||
-rw-r--r-- | src/generic/apt/aptitude_resolver_universe.cc | 79 | ||||
-rw-r--r-- | src/generic/apt/aptitude_resolver_universe.h | 73 | ||||
-rw-r--r-- | tests/test_resolver_hints.cc | 12 |
6 files changed, 214 insertions, 49 deletions
diff --git a/doc/en/aptitude.xml b/doc/en/aptitude.xml index ad958ed2..b4b80ff3 100644 --- a/doc/en/aptitude.xml +++ b/doc/en/aptitude.xml @@ -4827,6 +4827,16 @@ e: Examine !: Apply .: Next ,: Previous</screen> </para> </listitem> + <listitem id='hintDiscard'> + <para> + <quote><literal>discard</literal></quote>: Discard + every solution containing the version. Differs from + <quote><literal>reject</literal></quote> in that it is + not visible to the user and cannot be modified + interactively. + </para> + </listitem> + <listitem> <para> <quote><literal>increase-safety-cost-to @@ -4848,6 +4858,17 @@ e: Examine !: Apply .: Next ,: Previous</screen> Several special cost levels can be chosen by name: <orderedlist> + <listitem> + <para> + <literal>conflict</literal>, + <literal>discard</literal>: instead of changing + the safety cost, discard solutions containing + the version as if the <quote><link + linkend='hintDiscard'><literal>discard</literal></link></quote> + hint had been applied. + </para> + </listitem> + <listitem> <para> <literal>maximum</literal>: the highest safety diff --git a/src/generic/apt/aptitude_resolver.cc b/src/generic/apt/aptitude_resolver.cc index e2f8ea61..b8ea38db 100644 --- a/src/generic/apt/aptitude_resolver.cc +++ b/src/generic/apt/aptitude_resolver.cc @@ -207,6 +207,10 @@ std::ostream &operator<<(std::ostream &out, const aptitude_resolver::hint &hint) out << "raise-cost-component " << hint.get_component_name() << " " << hint.get_amt(); break; + case aptitude_resolver::hint::discard: + out << "discard " << hint.get_component_name(); + break; + default: out << "bad-hint-type " << hint.get_type(); break; @@ -413,12 +417,12 @@ int aptitude_resolver::hint::compare(const hint &other) const TRACE_HINTS_INEQUAL(1, "[type]"); return 1; } - else if(amt < other.amt) + else if(type != discard && amt < other.amt) { TRACE_HINTS_INEQUAL(-1, "[amt]"); return -1; } - else if(amt > other.amt) + else if(type != discard && amt > other.amt) { TRACE_HINTS_INEQUAL(1, "[amt]"); return 1; @@ -486,6 +490,7 @@ bool aptitude_resolver::hint::parse(const std::string &hint, aptitude_resolver:: ++start; int amt = -1; + cfg_level safety_level; std::string component_name; if(action == "add-to-cost-component" || action == "raise-cost-component") @@ -559,7 +564,7 @@ bool aptitude_resolver::hint::parse(const std::string &hint, aptitude_resolver:: while(start != hint.end() && isspace(*start)) ++start; - amt = aptitude_universe::parse_level(level_number); + safety_level = aptitude_universe::parse_level(level_number); } if(start == hint.end()) @@ -688,11 +693,18 @@ bool aptitude_resolver::hint::parse(const std::string &hint, aptitude_resolver:: else if(action == "approve") out = make_mandate(target, selection); else if(action == "increase-tier-to" || action == "increase-safety-cost-to") - out = make_raise_cost_component(target, selection, "safety", amt); + { + if(safety_level.get_is_discard()) + out = make_discard(target, selection); + else + out = make_raise_cost_component(target, selection, "safety", safety_level.get_level()); + } else if(action == "add-to-cost-component") out = make_add_to_cost_component(target, selection, component_name, amt); else if(action == "raise-cost-component") out = make_raise_cost_component(target, selection, component_name, amt); + else if(action == "discard") + out = make_discard(target, selection); else { unsigned long score_tweak = 0; @@ -718,6 +730,20 @@ aptitude_resolver::hint::~hint() { } +namespace +{ + inline + cost apply_cfg_level(const cfg_level &level, + aptitude_resolver_cost_settings &cost_settings, + const aptitude_resolver_cost_settings::component &safety_component) + { + if(level.get_is_discard()) + return cost_limits::conflict_cost; + else + return cost_settings.raise_cost(safety_component, level.get_level()); + } +} + aptitude_resolver::aptitude_resolver(int step_score, int broken_score, int unfixed_soft_score, @@ -748,8 +774,8 @@ aptitude_resolver::aptitude_resolver(int step_score, aptitude_resolver_cost_settings::component safety_component = cost_settings.get_or_create_component("safety", aptitude_resolver_cost_settings::maximized); - int keep_all_level(aptitude_universe::get_keep_all_level()); - cost keep_all_cost(cost_settings.raise_cost(safety_component, keep_all_level)); + cfg_level keep_all_level(aptitude_universe::get_keep_all_level()); + cost keep_all_cost(apply_cfg_level(keep_all_level, cost_settings, safety_component)); for(pkgCache::PkgIterator i = cache->PkgBegin(); !i.end(); ++i) { @@ -1178,12 +1204,12 @@ void aptitude_resolver::add_action_scores(int preserve_score, int auto_score, const std::map<package, bool> &initial_state_manual_flags, const std::vector<hint> &hints) { - int safe_level(aptitude_universe::get_safe_level()); - int keep_all_level(aptitude_universe::get_keep_all_level()); - int remove_level(aptitude_universe::get_remove_level()); - int break_hold_level(aptitude_universe::get_break_hold_level()); - int non_default_level(aptitude_universe::get_non_default_level()); - int remove_essential_level(aptitude_universe::get_remove_essential_level()); + cfg_level safe_level(aptitude_universe::get_safe_level()); + cfg_level keep_all_level(aptitude_universe::get_keep_all_level()); + cfg_level remove_level(aptitude_universe::get_remove_level()); + cfg_level break_hold_level(aptitude_universe::get_break_hold_level()); + cfg_level non_default_level(aptitude_universe::get_non_default_level()); + cfg_level remove_essential_level(aptitude_universe::get_remove_essential_level()); LOG_TRACE(loggerScores, "Setting up action scores; score parameters: preserver_score = " << preserve_score << ", auto_score = " << auto_score << ", remove_score = " << remove_score @@ -1358,6 +1384,11 @@ void aptitude_resolver::add_action_scores(int preserve_score, int auto_score, modify_version_cost(v, cost_settings.add_to_cost(component, h.get_amt())); break; + case hint::discard: + LOG_DEBUG(loggerScores, "** Discarding " << v); + modify_version_cost(v, cost_limits::conflict_cost); + break; + case hint::raise_cost_component: LOG_DEBUG(loggerScores, "** Raising the cost component \"" << h.get_component_name() << "\" to " << h.get_amt() << " for " << v); modify_version_cost(v, cost_settings.raise_cost(component, h.get_amt())); @@ -1433,7 +1464,7 @@ void aptitude_resolver::add_action_scores(int preserve_score, int auto_score, } modify_version_cost(v, - cost_settings.raise_cost(safety_component, safe_level) + apply_cfg_level(safe_level, cost_settings, safety_component) + cost_settings.add_to_cost(canceled_actions_component, 1)); LOG_DEBUG(loggerCosts, "** Safety level raised to at least " << safe_level << " for " << v @@ -1453,7 +1484,7 @@ void aptitude_resolver::add_action_scores(int preserve_score, int auto_score, } modify_version_cost(v, - cost_settings.raise_cost(safety_component, remove_level) + apply_cfg_level(remove_level, cost_settings, safety_component) + cost_settings.add_to_cost(removals_component, 1)); LOG_DEBUG(loggerCosts, "** Safety level raised to at least " << remove_level << " for " << v @@ -1483,7 +1514,7 @@ void aptitude_resolver::add_action_scores(int preserve_score, int auto_score, } modify_version_cost(v, - cost_settings.raise_cost(safety_component, safe_level)); + apply_cfg_level(safe_level, cost_settings, safety_component)); LOG_DEBUG(loggerCosts, "** Safety level raised to at least " << safe_level << " for " << v << " because it is the default install version of a package (" PACKAGE "::ProblemResolver::Safe-Level)."); @@ -1503,7 +1534,7 @@ void aptitude_resolver::add_action_scores(int preserve_score, int auto_score, add_version_score(v, non_default_score); modify_version_cost(v, - cost_settings.raise_cost(safety_component, non_default_level) + apply_cfg_level(non_default_level, cost_settings, safety_component) + cost_settings.add_to_cost(non_default_versions_component, 1)); LOG_DEBUG(loggerCosts, "** Safety level raised to at least " << non_default_level << " for " << v @@ -1527,7 +1558,7 @@ void aptitude_resolver::add_action_scores(int preserve_score, int auto_score, } modify_version_cost(v, - cost_settings.raise_cost(safety_component, break_hold_level) + apply_cfg_level(break_hold_level, cost_settings, safety_component) + cost_settings.add_to_cost(broken_holds_component, 1)); LOG_DEBUG(loggerCosts, "** Safety level raised to at least " << break_hold_level << " for " << v @@ -1550,7 +1581,7 @@ void aptitude_resolver::add_action_scores(int preserve_score, int auto_score, reject_version(v); modify_version_cost(v, - cost_settings.raise_cost(safety_component, remove_essential_level)); + apply_cfg_level(remove_essential_level, cost_settings, safety_component)); LOG_DEBUG(loggerCosts, "** Safety level raised to at least " << remove_essential_level << " for " << v << " because it represents removing an essential package."); diff --git a/src/generic/apt/aptitude_resolver.h b/src/generic/apt/aptitude_resolver.h index 0f792804..f2fa566a 100644 --- a/src/generic/apt/aptitude_resolver.h +++ b/src/generic/apt/aptitude_resolver.h @@ -90,6 +90,10 @@ public: * cost tuple should have a number added to it. */ add_to_cost_component, + /** \brief A hint indicating that the target should be + * discarded. + */ + discard, /** \brief A hint indicating that a named component of the * cost tuple should be increased to an upper bound. */ @@ -318,6 +322,13 @@ public: target, selection, component_name); } + /** \brief Create a hint that discards solutions containing the target. */ + static hint make_discard(const cwidget::util::ref_ptr<aptitude::matching::pattern> &target, + const version_selection &selection) + { + return hint(discard, 0, target, selection, ""); + } + /** \brief Create a hint that increases a single component of the * cost level to the given value. */ diff --git a/src/generic/apt/aptitude_resolver_universe.cc b/src/generic/apt/aptitude_resolver_universe.cc index c1c54953..db9d892f 100644 --- a/src/generic/apt/aptitude_resolver_universe.cc +++ b/src/generic/apt/aptitude_resolver_universe.cc @@ -800,65 +800,96 @@ std::ostream &operator<<(ostream &out, const aptitude_resolver_dep &d) return out; } +std::ostream &operator<<(std::ostream &out, const cfg_level &level) +{ + if(level.get_is_discard()) + out << "discard"; + else + out << level.get_level(); + + return out; +} -int aptitude_universe::parse_level(const std::string &s) +cfg_level aptitude_universe::parse_level(const std::string &s) { typedef generic_problem_resolver<aptitude_universe> aptitude_resolver; if(s == "maximum") - return cost_limits::maximum_level; + return cfg_level::make_level(cost_limits::maximum_level); else if(s == "minimum" || s == "") - return cost_limits::minimum_level; + return cfg_level::make_level(cost_limits::minimum_level); + else if(s == "conflict" || s == "discard") + return cfg_level::make_conflict(); else { char *endptr; int n = static_cast<int>(strtol(s.c_str(), &endptr, 0)); if(*endptr != '\0') { - std::string msg(ssprintf(N_("Invalid safety level \"%s\" (not \"maximum\", \"minimum\", or an integer)."), s.c_str())); + std::string msg(ssprintf(N_("Invalid safety level \"%s\" (not \"discard\", \"maximum\", \"minimum\", or an integer)."), s.c_str())); LOG_ERROR(Loggers::getAptitudeResolverCosts(), msg); _error->Error("%s", _(msg.c_str())); - return cost_limits::minimum_level; + return cfg_level::make_level(cost_limits::minimum_level); } else - return n; + return cfg_level::make_level(n); } } -int aptitude_universe::get_safe_level() +cfg_level aptitude_universe::parse_levels(const std::string &level1, + const std::string &level2, + cfg_level default_level) +{ + if(level1.empty() && level2.empty()) + return default_level; + else if(level1.empty()) + return parse_level(level2); + else if(level2.empty()) + return parse_level(level1); + else + return std::max<cfg_level>(parse_level(level1), parse_level(level2)); +} + +cfg_level aptitude_universe::get_safe_level() { return - std::max<int>(parse_level(aptcfg->Find(PACKAGE "::ProblemResolver::Safe-Level", "10000")), - parse_level(aptcfg->Find(PACKAGE "::ProblemResolver::Safe-Tier", "minimum"))); + parse_levels(aptcfg->Find(PACKAGE "::ProblemResolver::Safe-Level", ""), + aptcfg->Find(PACKAGE "::ProblemResolver::Safe-Tier", ""), + cfg_level::make_level(10000)); } -int aptitude_universe::get_keep_all_level() +cfg_level aptitude_universe::get_keep_all_level() { - return std::max<int>(parse_level(aptcfg->Find(PACKAGE "::ProblemResolver::Keep-All-Level", "20000")), - parse_level(aptcfg->Find(PACKAGE "::ProblemResolver::Keep-All-Tier", "minimum"))); + return parse_levels(aptcfg->Find(PACKAGE "::ProblemResolver::Keep-All-Level", ""), + aptcfg->Find(PACKAGE "::ProblemResolver::Keep-All-Tier", ""), + cfg_level::make_level(20000)); } -int aptitude_universe::get_remove_level() +cfg_level aptitude_universe::get_remove_level() { - return std::max<int>(parse_level(aptcfg->Find(PACKAGE "::ProblemResolver::Remove-Level", "10000")), - parse_level(aptcfg->Find(PACKAGE "::ProblemResolver::Remove-Tier", "minimum"))); + return parse_levels(aptcfg->Find(PACKAGE "::ProblemResolver::Remove-Level", ""), + aptcfg->Find(PACKAGE "::ProblemResolver::Remove-Tier", ""), + cfg_level::make_level(10000)); } -int aptitude_universe::get_break_hold_level() +cfg_level aptitude_universe::get_break_hold_level() { - return std::max<int>(parse_level(aptcfg->Find(PACKAGE "::ProblemResolver::Break-Hold-Level", "40000")), - parse_level(aptcfg->Find(PACKAGE "::ProblemResolver::Break-Hold-Tier", "minimum"))); + return parse_levels(aptcfg->Find(PACKAGE "::ProblemResolver::Break-Hold-Level", ""), + aptcfg->Find(PACKAGE "::ProblemResolver::Break-Hold-Tier", ""), + cfg_level::make_level(40000)); } -int aptitude_universe::get_non_default_level() +cfg_level aptitude_universe::get_non_default_level() { - return std::max<int>(parse_level(aptcfg->Find(PACKAGE "::ProblemResolver::Non-Default-Level", "50000")), - parse_level(aptcfg->Find(PACKAGE "::ProblemResolver::Non-Default-Tier", "minimum"))); + return parse_levels(aptcfg->Find(PACKAGE "::ProblemResolver::Non-Default-Level", ""), + aptcfg->Find(PACKAGE "::ProblemResolver::Non-Default-Tier", ""), + cfg_level::make_level(50000)); } -int aptitude_universe::get_remove_essential_level() +cfg_level aptitude_universe::get_remove_essential_level() { - return std::max<int>(parse_level(aptcfg->Find(PACKAGE "::ProblemResolver::Remove-Essential-Level", "60000")), - parse_level(aptcfg->Find(PACKAGE "::ProblemResolver::Remove-Essential-Tier", "minimum"))); + return parse_levels(aptcfg->Find(PACKAGE "::ProblemResolver::Remove-Essential-Level", ""), + aptcfg->Find(PACKAGE "::ProblemResolver::Remove-Essential-Tier", ""), + cfg_level::make_level(60000)); } bool aptitude_universe::is_candidate_for_initial_set(const aptitude_resolver_dep &d) const diff --git a/src/generic/apt/aptitude_resolver_universe.h b/src/generic/apt/aptitude_resolver_universe.h index b5aecfc1..d044bad3 100644 --- a/src/generic/apt/aptitude_resolver_universe.h +++ b/src/generic/apt/aptitude_resolver_universe.h @@ -1043,6 +1043,55 @@ bool aptitude_resolver_dep::broken_under(const InstallationType &I) const } } +/** \brief Representation of a level value as stored in the + * configuration. + * + * All levels are integers ... except for the special level "discard" + * (formerly "conflict"), which is a separate entity. + */ +class cfg_level +{ + int level; + bool is_discard; + + cfg_level(int _level, bool _is_discard) + : level(_level), is_discard(_is_discard) + { + } + +public: + /** \brief Create a cfg_level that has no effect. */ + cfg_level() + : level(INT_MIN), is_discard(false) + { + } + + static cfg_level make_level(int level) + { + return cfg_level(level, false); + } + + static cfg_level make_conflict() + { + return cfg_level(INT_MAX, true); + } + + bool get_is_discard() const { return is_discard; } + int get_level() const { return level; } + + bool operator<(const cfg_level &other) const + { + if(is_discard) + return false; + else if(other.is_discard) + return true; + else + return level < other.level; + } +}; + +std::ostream &operator<<(std::ostream &out, const cfg_level &level); + /** \brief This class translates an APT package system into the * abstract package system as described in \ref abstract_universe. * @@ -1299,15 +1348,25 @@ public: } // Configuration helper -- should this be somewhere better? - static int parse_level(const std::string &s); + static cfg_level parse_level(const std::string &s); + /** \brief Parse two level strings and combine them. + * + * - If neither is set, the given default level is used. + * - If only one is set, its value is used. + * - If both are set, the higher value is used (where "conflict" + * is taken to be higher than any numeric level). + */ + static cfg_level parse_levels(const std::string &level1, + const std::string &level2, + cfg_level default_level); // Configuration fetchers. - static int get_safe_level(); - static int get_keep_all_level(); - static int get_remove_level(); - static int get_break_hold_level(); - static int get_non_default_level(); - static int get_remove_essential_level(); + static cfg_level get_safe_level(); + static cfg_level get_keep_all_level(); + static cfg_level get_remove_level(); + static cfg_level get_break_hold_level(); + static cfg_level get_non_default_level(); + static cfg_level get_remove_essential_level(); }; /** \brief Write an aptitude_resolver_package to the given stream. */ diff --git a/tests/test_resolver_hints.cc b/tests/test_resolver_hints.cc index b4ca2cb4..8a0d3010 100644 --- a/tests/test_resolver_hints.cc +++ b/tests/test_resolver_hints.cc @@ -88,6 +88,12 @@ namespace hint::version_selection::make_inst(), "safety", INT_MAX)), + test("increase-tier-to conflict xroach", + hint::make_discard(pattern::make_exact_name("xroach"), + hint::version_selection::make_inst())), + test("increase-tier-to discard bob", + hint::make_discard(pattern::make_exact_name("bob"), + hint::version_selection::make_inst())), test("increase-tier-to 800 xroach", hint::make_raise_cost_component(pattern::make_exact_name("xroach"), hint::version_selection::make_inst(), @@ -105,6 +111,12 @@ namespace hint::version_selection::make_inst(), "albertComponent", 299)), + test("discard albert", + hint::make_discard(pattern::make_exact_name("albert"), + hint::version_selection::make_inst())), + test("discard xyzzy /unstable", + hint::make_discard(pattern::make_exact_name("xyzzy"), + hint::version_selection::make_archive("unstable"))), }; const int num_resolver_tests = sizeof(resolver_tests) / sizeof(resolver_tests[0]); |