aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2010-06-18 12:42:42 +0100
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2010-06-18 12:42:42 +0100
commitf3c1ae18f68788ed6a6752114fe6e93b454499b6 (patch)
tree2fbd6dbda6b0a89ef513416fdcc3b138cca96924
parentd78e25b173a5078036054cff43833c49ec766db5 (diff)
downloadpaludis-f3c1ae18f68788ed6a6752114fe6e93b454499b6.tar.gz
paludis-f3c1ae18f68788ed6a6752114fe6e93b454499b6.tar.xz
Protect against removing system packages
Fixes: ticket:848
-rw-r--r--paludis/resolver/decider.cc21
-rw-r--r--paludis/resolver/required_confirmations-fwd.hh1
-rw-r--r--paludis/resolver/required_confirmations.cc16
-rw-r--r--paludis/resolver/required_confirmations.hh13
-rw-r--r--src/clients/cave/cmd_display_resolution.cc17
-rw-r--r--src/clients/cave/cmd_resolve_cmdline.cc3
-rw-r--r--src/clients/cave/resolve_common.cc23
7 files changed, 83 insertions, 11 deletions
diff --git a/paludis/resolver/decider.cc b/paludis/resolver/decider.cc
index 0371c5c..2e9d334 100644
--- a/paludis/resolver/decider.cc
+++ b/paludis/resolver/decider.cc
@@ -1787,12 +1787,15 @@ namespace
{
struct ConfirmVisitor
{
+ const Environment * const env;
const ResolverFunctions & fns;
const std::tr1::shared_ptr<const Resolution> resolution;
ConfirmVisitor(
+ const Environment * const e,
const ResolverFunctions & f,
const std::tr1::shared_ptr<const Resolution> & r) :
+ env(e),
fns(f),
resolution(r)
{
@@ -1834,9 +1837,21 @@ namespace
{
}
- void visit(RemoveDecision &) const
+ void visit(RemoveDecision & remove_decision) const
{
- /* remove confirms are done elsewhere */
+ /* we do BreakConfirmation elsewhere */
+ bool is_system(false);
+ for (PackageIDSequence::ConstIterator i(remove_decision.ids()->begin()), i_end(remove_decision.ids()->end()) ;
+ i != i_end && ! is_system ; ++i)
+ if (match_package_in_set(*env, *env->set(SetName("system")), **i, MatchPackageOptions()))
+ is_system = true;
+
+ if (is_system)
+ {
+ const std::tr1::shared_ptr<RemoveSystemPackageConfirmation> c(new RemoveSystemPackageConfirmation);
+ if (! fns.confirm_fn()(resolution, c))
+ remove_decision.add_required_confirmation(c);
+ }
}
};
}
@@ -1845,7 +1860,7 @@ void
Decider::_confirm(
const std::tr1::shared_ptr<const Resolution> & resolution)
{
- resolution->decision()->accept(ConfirmVisitor(_imp->fns, resolution));
+ resolution->decision()->accept(ConfirmVisitor(_imp->env, _imp->fns, resolution));
}
diff --git a/paludis/resolver/required_confirmations-fwd.hh b/paludis/resolver/required_confirmations-fwd.hh
index 94c5d14..169df49 100644
--- a/paludis/resolver/required_confirmations-fwd.hh
+++ b/paludis/resolver/required_confirmations-fwd.hh
@@ -31,6 +31,7 @@ namespace paludis
struct DowngradeConfirmation;
struct NotBestConfirmation;
struct BreakConfirmation;
+ struct RemoveSystemPackageConfirmation;
typedef Sequence<std::tr1::shared_ptr<const RequiredConfirmation> > RequiredConfirmations;
}
diff --git a/paludis/resolver/required_confirmations.cc b/paludis/resolver/required_confirmations.cc
index 1b2bbef..62a654a 100644
--- a/paludis/resolver/required_confirmations.cc
+++ b/paludis/resolver/required_confirmations.cc
@@ -36,6 +36,8 @@ RequiredConfirmation::deserialise(Deserialisation & d)
return NotBestConfirmation::deserialise(d);
else if (d.class_name() == "BreakConfirmation")
return BreakConfirmation::deserialise(d);
+ else if (d.class_name() == "RemoveSystemPackageConfirmation")
+ return RemoveSystemPackageConfirmation::deserialise(d);
else
throw InternalError(PALUDIS_HERE, "unknown class '" + stringify(d.class_name()) + "'");
@@ -84,6 +86,20 @@ BreakConfirmation::serialise(Serialiser & s) const
;
}
+const std::tr1::shared_ptr<RemoveSystemPackageConfirmation>
+RemoveSystemPackageConfirmation::deserialise(Deserialisation & d)
+{
+ Deserialisator v(d, "RemoveSystemPackageConfirmation");
+ return make_shared_ptr(new RemoveSystemPackageConfirmation);
+}
+
+void
+RemoveSystemPackageConfirmation::serialise(Serialiser & s) const
+{
+ s.object("RemoveSystemPackageConfirmation")
+ ;
+}
+
template class Sequence<std::tr1::shared_ptr<const RequiredConfirmation> >;
template class WrappedForwardIterator<RequiredConfirmations::ConstIteratorTag, const std::tr1::shared_ptr<const RequiredConfirmation> >;
diff --git a/paludis/resolver/required_confirmations.hh b/paludis/resolver/required_confirmations.hh
index 0c508f3..825e7f2 100644
--- a/paludis/resolver/required_confirmations.hh
+++ b/paludis/resolver/required_confirmations.hh
@@ -32,7 +32,7 @@ namespace paludis
{
class PALUDIS_VISIBLE RequiredConfirmation :
public virtual DeclareAbstractAcceptMethods<RequiredConfirmation, MakeTypeList<
- DowngradeConfirmation, NotBestConfirmation, BreakConfirmation>::Type>
+ DowngradeConfirmation, NotBestConfirmation, BreakConfirmation, RemoveSystemPackageConfirmation>::Type>
{
public:
virtual void serialise(Serialiser &) const = 0;
@@ -73,6 +73,17 @@ namespace paludis
virtual void serialise(Serialiser &) const;
};
+
+ class PALUDIS_VISIBLE RemoveSystemPackageConfirmation :
+ public RequiredConfirmation,
+ public ImplementAcceptMethods<RequiredConfirmation, RemoveSystemPackageConfirmation>
+ {
+ public:
+ static const std::tr1::shared_ptr<RemoveSystemPackageConfirmation> deserialise(
+ Deserialisation & d) PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual void serialise(Serialiser &) const;
+ };
}
}
diff --git a/src/clients/cave/cmd_display_resolution.cc b/src/clients/cave/cmd_display_resolution.cc
index b504717..6292842 100644
--- a/src/clients/cave/cmd_display_resolution.cc
+++ b/src/clients/cave/cmd_display_resolution.cc
@@ -663,6 +663,11 @@ namespace
{
return "--uninstalls-may-break or --remove-if-dependent";
}
+
+ std::string visit(const RemoveSystemPackageConfirmation &) const
+ {
+ return "--uninstalls-may-break system";
+ }
};
std::string stringify_confirmation(const RequiredConfirmation & c)
@@ -772,7 +777,9 @@ namespace
const std::tr1::shared_ptr<const Resolution> & resolution,
const RemoveDecision & decision,
const bool more_annotations,
- const bool untaken)
+ const bool confirmations,
+ const bool untaken,
+ const std::string & notes)
{
if (untaken)
cout << "(<) " << c::bold_green() << decision.resolvent().package() << c::normal() << " ";
@@ -793,6 +800,10 @@ namespace
cout << endl;
display_reasons(resolution, more_annotations);
+ if (confirmations)
+ display_confirmations(decision);
+ if (! notes.empty())
+ cout << " " << c::bold_normal() << notes << c::normal() << endl;
}
struct NotFixableMask
@@ -1193,7 +1204,9 @@ namespace
resolution,
remove_decision,
more_annotations,
- untaken);
+ unconfirmed,
+ untaken,
+ cycle_breaking);
}
void visit(const BreakDecision & break_decision)
diff --git a/src/clients/cave/cmd_resolve_cmdline.cc b/src/clients/cave/cmd_resolve_cmdline.cc
index 616969e..91ecb95 100644
--- a/src/clients/cave/cmd_resolve_cmdline.cc
+++ b/src/clients/cave/cmd_resolve_cmdline.cc
@@ -76,7 +76,8 @@ ResolveCommandLineResolutionOptions::ResolveCommandLineResolutionOptions(args::A
"dependent packages are treated as errors. These options specify a different behaviour."),
a_uninstalls_may_break(&g_dependent_options, "uninstalls-may-break", 'u',
"Permit uninstalls that might break packages matching the specified specification. May be "
- "specified multiple times. Use '*/*' to allow all packages to be broken."),
+ "specified multiple times. Use '*/*' to allow all packages to be broken. Use 'system' to "
+ "allow system packages to be uninstalled."),
a_remove_if_dependent(&g_dependent_options, "remove-if-dependent", 'r',
"Remove dependent packages that might be broken by other changes if those packages match "
"the specified specification. May be specified multiple times. Use '*/*' to remove all "
diff --git a/src/clients/cave/resolve_common.cc b/src/clients/cave/resolve_common.cc
index 3881004..ca4d3b9 100644
--- a/src/clients/cave/resolve_common.cc
+++ b/src/clients/cave/resolve_common.cc
@@ -1090,6 +1090,7 @@ namespace
const PackageDepSpecList & permit_downgrade;
const PackageDepSpecList & permit_old_version;
const PackageDepSpecList & allowed_to_break_specs;
+ const bool allowed_to_break_system;
const std::tr1::shared_ptr<const PackageID> id;
ConfirmFnVisitor(const Environment * const e,
@@ -1097,12 +1098,14 @@ namespace
const PackageDepSpecList & d,
const PackageDepSpecList & o,
const PackageDepSpecList & a,
+ const bool s,
const std::tr1::shared_ptr<const PackageID> & i) :
env(e),
resolution_options(r),
permit_downgrade(d),
permit_old_version(o),
allowed_to_break_specs(a),
+ allowed_to_break_system(s),
id(i)
{
}
@@ -1145,6 +1148,11 @@ namespace
return false;
}
+
+ bool visit(const RemoveSystemPackageConfirmation &) const
+ {
+ return allowed_to_break_system;
+ }
};
bool confirm_fn(
@@ -1153,10 +1161,12 @@ namespace
const PackageDepSpecList & permit_downgrade,
const PackageDepSpecList & permit_old_version,
const PackageDepSpecList & allowed_to_break_specs,
+ const bool allowed_to_break_system,
const std::tr1::shared_ptr<const Resolution> & r,
const std::tr1::shared_ptr<const RequiredConfirmation> & c)
{
- return c->accept_returning<bool>(ConfirmFnVisitor(env, resolution_options, permit_downgrade, permit_old_version, allowed_to_break_specs,
+ return c->accept_returning<bool>(ConfirmFnVisitor(env, resolution_options, permit_downgrade, permit_old_version,
+ allowed_to_break_specs, allowed_to_break_system,
r->decision()->accept_returning<std::tr1::shared_ptr<const PackageID> >(ChosenIDVisitor())
));
}
@@ -1479,6 +1489,7 @@ paludis::cave::resolve_common(
less_restrictive_remove_blockers_specs, with, without,
permit_old_version, permit_downgrade, take, take_from, ignore, ignore_from,
favour, avoid, no_dependencies_from, no_blockers_from;
+ bool allowed_to_break_system(false);
for (args::StringSetArg::ConstIterator i(resolution_options.a_permit_uninstall.begin_args()),
i_end(resolution_options.a_permit_uninstall.end_args()) ;
@@ -1489,8 +1500,11 @@ paludis::cave::resolve_common(
for (args::StringSetArg::ConstIterator i(resolution_options.a_uninstalls_may_break.begin_args()),
i_end(resolution_options.a_uninstalls_may_break.end_args()) ;
i != i_end ; ++i)
- allowed_to_break_specs.push_back(parse_user_package_dep_spec(*i, env.get(),
- UserPackageDepSpecOptions() + updso_allow_wildcards));
+ if (*i == "system")
+ allowed_to_break_system = true;
+ else
+ allowed_to_break_specs.push_back(parse_user_package_dep_spec(*i, env.get(),
+ UserPackageDepSpecOptions() + updso_allow_wildcards));
for (args::StringSetArg::ConstIterator i(resolution_options.a_remove_if_dependent.begin_args()),
i_end(resolution_options.a_remove_if_dependent.end_args()) ;
@@ -1631,7 +1645,8 @@ paludis::cave::resolve_common(
env.get(), std::tr1::cref(allowed_to_remove_specs), _1),
n::confirm_fn() = std::tr1::bind(&confirm_fn,
env.get(), std::tr1::cref(resolution_options), std::tr1::cref(permit_downgrade),
- std::tr1::cref(permit_old_version), std::tr1::cref(allowed_to_break_specs), _1, _2),
+ std::tr1::cref(permit_old_version), std::tr1::cref(allowed_to_break_specs),
+ allowed_to_break_system, _1, _2),
n::find_repository_for_fn() = std::tr1::bind(&find_repository_for_fn,
env.get(), std::tr1::cref(resolution_options), _1, _2),
n::get_constraints_for_dependent_fn() = std::tr1::bind(&get_constraints_for_dependent_fn,