summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Burrows <dburrows@debian.org>2010-04-20 08:39:18 -0700
committerDaniel Burrows <dburrows@debian.org>2010-04-20 08:39:18 -0700
commit81c463456e9e67cf894286c78d6b9c342fdf67ac (patch)
tree5a46aca111012218ef7fd0d7c4f0c6a29bd3fde5
parent4d0d07d1bb75ba3c1ebc532d85eb05a84ac3f6e7 (diff)
downloadaptitude-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.xml21
-rw-r--r--src/generic/apt/aptitude_resolver.cc67
-rw-r--r--src/generic/apt/aptitude_resolver.h11
-rw-r--r--src/generic/apt/aptitude_resolver_universe.cc79
-rw-r--r--src/generic/apt/aptitude_resolver_universe.h73
-rw-r--r--tests/test_resolver_hints.cc12
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]);