aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2009-09-26 19:58:37 +0100
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2009-09-26 19:58:37 +0100
commita866a87949f80a3659ce8ee89298461ebe1461f1 (patch)
tree765a941d63b8b701ceabc48b349a0a15cab9449b
parentcda153377a26220354b6fc935ff172a99621ac17 (diff)
parent3af824da5ee63dc4a7f1f81d235c791e9fcee25b (diff)
downloadpaludis-a866a87949f80a3659ce8ee89298461ebe1461f1.tar.gz
paludis-a866a87949f80a3659ce8ee89298461ebe1461f1.tar.xz
Merge branch 'nice-mask-messages'
-rw-r--r--paludis/resolver/Makefile.am13
-rw-r--r--paludis/resolver/decision-fwd.hh8
-rw-r--r--paludis/resolver/decision.cc330
-rw-r--r--paludis/resolver/decision.hh140
-rw-r--r--paludis/resolver/decision.se16
-rw-r--r--paludis/resolver/resolver.cc692
-rw-r--r--paludis/resolver/resolver.hh30
-rw-r--r--paludis/resolver/resolver_TEST_serialisation.cc2
-rw-r--r--paludis/resolver/resolver_functions.hh3
-rw-r--r--paludis/resolver/resolver_test.cc81
-rw-r--r--paludis/resolver/resolver_test.hh10
-rw-r--r--paludis/resolver/unsuitable_candidates-fwd.hh35
-rw-r--r--paludis/resolver/unsuitable_candidates.cc51
-rw-r--r--paludis/resolver/unsuitable_candidates.hh50
-rw-r--r--src/clients/cave/cmd_display_resolution.cc193
-rw-r--r--src/clients/cave/cmd_execute_resolution.cc59
-rw-r--r--src/clients/cave/cmd_resolve.cc106
-rw-r--r--src/clients/cave/cmd_resolve_dump.cc59
18 files changed, 1428 insertions, 450 deletions
diff --git a/paludis/resolver/Makefile.am b/paludis/resolver/Makefile.am
index 7a734d5..a6e9319 100644
--- a/paludis/resolver/Makefile.am
+++ b/paludis/resolver/Makefile.am
@@ -1,24 +1,21 @@
CLEANFILES = *~ gmon.out *.gcov *.gcno *.gcda *.loT *.epicfail
MAINTAINERCLEANFILES = Makefile.in
DISTCLEANFILES = \
- decision-se.hh decision-se.cc \
destination_types-se.hh destination_types-se.cc \
use_existing-se.hh use_existing-se.cc
AM_CXXFLAGS = -I$(top_srcdir) @PALUDIS_CXXFLAGS@ @PALUDIS_CXXFLAGS_VISIBILITY@
EXTRA_DIST = \
- decision-se.hh decision-se.cc decision.se \
destination_types-se.hh destination_types-se.cc destination_types.se \
use_existing-se.hh use_existing-se.cc use_existing.se \
$(check_SCRIPTS)
BUILT_SOURCES = \
- decision-se.hh decision-se.cc \
destination_types-se.hh destination_types-se.cc \
use_existing-se.hh use_existing-se.cc
noinst_HEADERS = \
arrow.hh arrow-fwd.hh \
constraint.hh constraint-fwd.hh \
- decision.hh decision-fwd.hh decision-se.hh \
+ decision.hh decision-fwd.hh \
destination.hh destination-fwd.hh \
destination_types.hh destination_types-fwd.hh destination_types-se.hh \
reason.hh reason-fwd.hh \
@@ -30,6 +27,7 @@ noinst_HEADERS = \
sanitised_dependencies.hh sanitised_dependencies-fwd.hh \
serialise.hh serialise-fwd.hh serialise-impl.hh \
suggest_restart.hh suggest_restart-fwd.hh \
+ unsuitable_candidates.hh unsuitable_candidates-fwd.hh \
use_existing.hh use_existing-fwd.hh use_existing-se.hh
libpaludisresolver_a_SOURCES = \
@@ -46,6 +44,7 @@ libpaludisresolver_a_SOURCES = \
sanitised_dependencies.cc \
serialise.cc \
suggest_restart.cc \
+ unsuitable_candidates.cc \
use_existing.cc
TESTS_ENVIRONMENT = env \
@@ -179,12 +178,6 @@ use_existing-se.hh : use_existing.se $(top_srcdir)/misc/make_se.bash
use_existing-se.cc : use_existing.se $(top_srcdir)/misc/make_se.bash
if ! $(top_srcdir)/misc/make_se.bash --source $(srcdir)/use_existing.se > $@ ; then rm -f $@ ; exit 1 ; fi
-decision-se.hh : decision.se $(top_srcdir)/misc/make_se.bash
- if ! $(top_srcdir)/misc/make_se.bash --header $(srcdir)/decision.se > $@ ; then rm -f $@ ; exit 1 ; fi
-
-decision-se.cc : decision.se $(top_srcdir)/misc/make_se.bash
- if ! $(top_srcdir)/misc/make_se.bash --source $(srcdir)/decision.se > $@ ; then rm -f $@ ; exit 1 ; fi
-
destination_types-se.hh : destination_types.se $(top_srcdir)/misc/make_se.bash
if ! $(top_srcdir)/misc/make_se.bash --header $(srcdir)/destination_types.se > $@ ; then rm -f $@ ; exit 1 ; fi
diff --git a/paludis/resolver/decision-fwd.hh b/paludis/resolver/decision-fwd.hh
index 9acc9c1..c1e49b6 100644
--- a/paludis/resolver/decision-fwd.hh
+++ b/paludis/resolver/decision-fwd.hh
@@ -27,10 +27,12 @@ namespace paludis
{
namespace resolver
{
+ class Decision;
-#include <paludis/resolver/decision-se.hh>
-
- struct Decision;
+ class NothingNoChangeDecision;
+ class ExistingNoChangeDecision;
+ class ChangesToMakeDecision;
+ class UnableToMakeDecision;
}
}
diff --git a/paludis/resolver/decision.cc b/paludis/resolver/decision.cc
index 57181ac..f4bfdd5 100644
--- a/paludis/resolver/decision.cc
+++ b/paludis/resolver/decision.cc
@@ -20,43 +20,331 @@
#include <paludis/resolver/decision.hh>
#include <paludis/resolver/serialise-impl.hh>
#include <paludis/resolver/destination.hh>
+#include <paludis/resolver/unsuitable_candidates.hh>
#include <paludis/util/make_named_values.hh>
#include <paludis/util/stringify.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/util/sequence.hh>
+#include <paludis/util/wrapped_forward_iterator.hh>
#include <sstream>
using namespace paludis;
using namespace paludis::resolver;
-#include <paludis/resolver/decision-se.cc>
+#ifdef PALUDIS_HAVE_DEFAULT_DELETED
+Decision::~Decision() = default;
+#else
+Decision::~Decision()
+{
+}
+#endif
+
+const std::tr1::shared_ptr<Decision>
+Decision::deserialise(Deserialisation & d)
+{
+ if (d.class_name() == "NothingNoChangeDecision")
+ {
+ Deserialisator v(d, "NothingNoChangeDecision");
+ return make_shared_ptr(new NothingNoChangeDecision(
+ v.member<bool>("taken")
+ ));
+ }
+ else if (d.class_name() == "ExistingNoChangeDecision")
+ {
+ Deserialisator v(d, "ExistingNoChangeDecision");
+ return make_shared_ptr(new ExistingNoChangeDecision(
+ v.member<std::tr1::shared_ptr<const PackageID> >("existing_id"),
+ v.member<bool>("is_same"),
+ v.member<bool>("is_same_version"),
+ v.member<bool>("is_transient"),
+ v.member<bool>("taken")
+ ));
+ }
+ else if (d.class_name() == "ChangesToMakeDecision")
+ {
+ Deserialisator v(d, "ChangesToMakeDecision");
+ return make_shared_ptr(new ChangesToMakeDecision(
+ v.member<std::tr1::shared_ptr<const PackageID> >("origin_id"),
+ v.member<bool>("best"),
+ v.member<bool>("taken"),
+ v.member<std::tr1::shared_ptr<const Destination> >("destination")
+ ));
+ }
+ else if (d.class_name() == "UnableToMakeDecision")
+ {
+ Deserialisator v(d, "UnableToMakeDecision");
+
+ std::tr1::shared_ptr<UnsuitableCandidates> unsuitable_candidates(new UnsuitableCandidates);
+ Deserialisator vv(*v.find_remove_member("unsuitable_candidates"), "c");
+ for (int n(1), n_end(vv.member<int>("count") + 1) ; n != n_end ; ++n)
+ unsuitable_candidates->push_back(vv.member<UnsuitableCandidate>(stringify(n)));
+
+ return make_shared_ptr(new UnableToMakeDecision(
+ unsuitable_candidates,
+ v.member<bool>("taken")
+ ));
+ }
+ else
+ throw InternalError(PALUDIS_HERE, "unknown class '" + stringify(d.class_name()) + "'");
+}
+
+namespace paludis
+{
+ template <>
+ struct Implementation<NothingNoChangeDecision>
+ {
+ const bool taken;
+
+ Implementation(const bool t) :
+ taken(t)
+ {
+ }
+ };
+}
+
+NothingNoChangeDecision::NothingNoChangeDecision(const bool t) :
+ PrivateImplementationPattern<NothingNoChangeDecision>(new Implementation<NothingNoChangeDecision>(t))
+{
+}
+
+#ifdef PALUDIS_HAVE_DEFAULT_DELETED
+NothingNoChangeDecision::~NothingNoChangeDecision() = default;
+#else
+NothingNoChangeDecision::~NothingNoChangeDecision()
+{
+}
+#endif
+
+bool
+NothingNoChangeDecision::taken() const
+{
+ return _imp->taken;
+}
void
-Decision::serialise(Serialiser & s) const
+NothingNoChangeDecision::serialise(Serialiser & s) const
{
- s.object("Decision")
- .member(SerialiserFlags<serialise::might_be_null>(), "destination", destination())
- .member(SerialiserFlags<serialise::might_be_null>(), "if_package_id", if_package_id())
- .member(SerialiserFlags<>(), "is_best", is_best())
+ s.object("NothingNoChangeDecision")
+ .member(SerialiserFlags<>(), "taken", taken())
+ ;
+}
+
+namespace paludis
+{
+ template <>
+ struct Implementation<ExistingNoChangeDecision>
+ {
+ const std::tr1::shared_ptr<const PackageID> existing_id;
+ const bool is_same;
+ const bool is_same_version;
+ const bool is_transient;
+ const bool taken;
+
+ Implementation(const std::tr1::shared_ptr<const PackageID> & e,
+ const bool s, const bool v, const bool r, const bool t) :
+ existing_id(e),
+ is_same(s),
+ is_same_version(v),
+ is_transient(r),
+ taken(t)
+ {
+ }
+ };
+}
+
+ExistingNoChangeDecision::ExistingNoChangeDecision(const std::tr1::shared_ptr<const PackageID> & e,
+ const bool s, const bool v, const bool r, const bool t) :
+ PrivateImplementationPattern<ExistingNoChangeDecision>(new Implementation<ExistingNoChangeDecision>(
+ e, s, v, r, t))
+{
+}
+
+#ifdef PALUDIS_HAVE_DEFAULT_DELETED
+ExistingNoChangeDecision::~ExistingNoChangeDecision() = default;
+#else
+ExistingNoChangeDecision::~ExistingNoChangeDecision()
+{
+}
+#endif
+
+const std::tr1::shared_ptr<const PackageID>
+ExistingNoChangeDecision::existing_id() const
+{
+ return _imp->existing_id;
+}
+
+bool
+ExistingNoChangeDecision::is_same() const
+{
+ return _imp->is_same;
+}
+
+bool
+ExistingNoChangeDecision::is_same_version() const
+{
+ return _imp->is_same_version;
+}
+
+bool
+ExistingNoChangeDecision::is_transient() const
+{
+ return _imp->is_transient;
+}
+
+bool
+ExistingNoChangeDecision::taken() const
+{
+ return _imp->taken;
+}
+
+void
+ExistingNoChangeDecision::serialise(Serialiser & s) const
+{
+ s.object("ExistingNoChangeDecision")
+ .member(SerialiserFlags<serialise::might_be_null>(), "existing_id", existing_id())
.member(SerialiserFlags<>(), "is_same", is_same())
.member(SerialiserFlags<>(), "is_same_version", is_same_version())
.member(SerialiserFlags<>(), "is_transient", is_transient())
- .member(SerialiserFlags<>(), "kind", stringify(kind()))
- .member(SerialiserFlags<>(), "taken", stringify(taken()))
+ .member(SerialiserFlags<>(), "taken", taken())
;
}
-const std::tr1::shared_ptr<Decision>
-Decision::deserialise(Deserialisation & d)
+namespace paludis
+{
+ template <>
+ struct Implementation<ChangesToMakeDecision>
+ {
+ const std::tr1::shared_ptr<const PackageID> origin_id;
+ const bool best;
+ const bool taken;
+ std::tr1::shared_ptr<const Destination> destination;
+
+ Implementation(
+ const std::tr1::shared_ptr<const PackageID> & o,
+ const bool b,
+ const bool t,
+ const std::tr1::shared_ptr<const Destination> & d) :
+ origin_id(o),
+ best(b),
+ taken(t),
+ destination(d)
+ {
+ }
+ };
+}
+
+ChangesToMakeDecision::ChangesToMakeDecision(
+ const std::tr1::shared_ptr<const PackageID> & o,
+ const bool b,
+ const bool t,
+ const std::tr1::shared_ptr<const Destination> & d) :
+ PrivateImplementationPattern<ChangesToMakeDecision>(new Implementation<ChangesToMakeDecision>(o, b, t, d))
+{
+}
+
+#ifdef PALUDIS_HAVE_DEFAULT_DELETED
+ChangesToMakeDecision::~ChangesToMakeDecision() = default;
+#else
+ChangesToMakeDecision::~ChangesToMakeDecision()
{
- Deserialisator v(d, "Decision");
- return make_shared_ptr(new Decision(make_named_values<Decision>(
- value_for<n::destination>(v.member<std::tr1::shared_ptr<Destination> >("destination")),
- value_for<n::if_package_id>(v.member<std::tr1::shared_ptr<const PackageID> >("if_package_id")),
- value_for<n::is_best>(v.member<bool>("is_best")),
- value_for<n::is_same>(v.member<bool>("is_same")),
- value_for<n::is_same_version>(v.member<bool>("is_same_version")),
- value_for<n::is_transient>(v.member<bool>("is_transient")),
- value_for<n::kind>(destringify<DecisionKind>(v.member<std::string>("kind"))),
- value_for<n::taken>(v.member<bool>("taken"))
- )));
}
+#endif
+
+const std::tr1::shared_ptr<const Destination>
+ChangesToMakeDecision::destination() const
+{
+ return _imp->destination;
+}
+
+void
+ChangesToMakeDecision::set_destination(const std::tr1::shared_ptr<const Destination> & d)
+{
+ _imp->destination = d;
+}
+
+const std::tr1::shared_ptr<const PackageID>
+ChangesToMakeDecision::origin_id() const
+{
+ return _imp->origin_id;
+}
+
+bool
+ChangesToMakeDecision::best() const
+{
+ return _imp->best;
+}
+
+bool
+ChangesToMakeDecision::taken() const
+{
+ return _imp->taken;
+}
+
+void
+ChangesToMakeDecision::serialise(Serialiser & s) const
+{
+ s.object("ChangesToMakeDecision")
+ .member(SerialiserFlags<serialise::might_be_null>(), "origin_id", origin_id())
+ .member(SerialiserFlags<>(), "best", best())
+ .member(SerialiserFlags<serialise::might_be_null>(), "destination", destination())
+ .member(SerialiserFlags<>(), "taken", taken())
+ ;
+}
+
+namespace paludis
+{
+ template <>
+ struct Implementation<UnableToMakeDecision>
+ {
+ const std::tr1::shared_ptr<const UnsuitableCandidates> unsuitable_candidates;
+ const bool taken;
+
+ Implementation(const std::tr1::shared_ptr<const UnsuitableCandidates> & u, const bool t) :
+ unsuitable_candidates(u),
+ taken(t)
+ {
+ }
+ };
+}
+
+UnableToMakeDecision::UnableToMakeDecision(
+ const std::tr1::shared_ptr<const UnsuitableCandidates> & u,
+ const bool t) :
+ PrivateImplementationPattern<UnableToMakeDecision>(new Implementation<UnableToMakeDecision>(u, t))
+{
+}
+
+#ifdef PALUDIS_HAVE_DEFAULT_DELETED
+UnableToMakeDecision::~UnableToMakeDecision() = default;
+#else
+UnableToMakeDecision::~UnableToMakeDecision()
+{
+}
+#endif
+
+const std::tr1::shared_ptr<const UnsuitableCandidates>
+UnableToMakeDecision::unsuitable_candidates() const
+{
+ return _imp->unsuitable_candidates;
+}
+
+bool
+UnableToMakeDecision::taken() const
+{
+ return _imp->taken;
+}
+
+void
+UnableToMakeDecision::serialise(Serialiser & s) const
+{
+ s.object("UnableToMakeDecision")
+ .member(SerialiserFlags<>(), "taken", taken())
+ .member(SerialiserFlags<serialise::might_be_null, serialise::container>(), "unsuitable_candidates", unsuitable_candidates())
+ ;
+}
+
+template class PrivateImplementationPattern<NothingNoChangeDecision>;
+template class PrivateImplementationPattern<ExistingNoChangeDecision>;
+template class PrivateImplementationPattern<ChangesToMakeDecision>;
+template class PrivateImplementationPattern<UnableToMakeDecision>;
diff --git a/paludis/resolver/decision.hh b/paludis/resolver/decision.hh
index c8c395d..c15f299 100644
--- a/paludis/resolver/decision.hh
+++ b/paludis/resolver/decision.hh
@@ -23,42 +23,128 @@
#include <paludis/resolver/decision-fwd.hh>
#include <paludis/resolver/serialise-fwd.hh>
#include <paludis/resolver/destination-fwd.hh>
-#include <paludis/util/named_value.hh>
+#include <paludis/resolver/unsuitable_candidates-fwd.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/util/simple_visitor.hh>
+#include <paludis/util/type_list.hh>
#include <paludis/package_id.hh>
namespace paludis
{
- namespace n
- {
- struct destination;
- struct if_package_id;
- struct is_best;
- struct is_same;
- struct is_same_version;
- struct is_transient;
- struct kind;
- struct taken;
- }
-
namespace resolver
{
- struct Decision
+ class PALUDIS_VISIBLE Decision :
+ public virtual DeclareAbstractAcceptMethods<Decision, MakeTypeList<
+ NothingNoChangeDecision, ExistingNoChangeDecision, ChangesToMakeDecision, UnableToMakeDecision>::Type>
{
- NamedValue<n::destination, std::tr1::shared_ptr<Destination> > destination;
- NamedValue<n::if_package_id, std::tr1::shared_ptr<const PackageID> > if_package_id;
- NamedValue<n::is_best, bool> is_best;
- NamedValue<n::is_same, bool> is_same;
- NamedValue<n::is_same_version, bool> is_same_version;
- NamedValue<n::is_transient, bool> is_transient;
- NamedValue<n::kind, DecisionKind> kind;
- NamedValue<n::taken, bool> taken;
-
- void serialise(Serialiser &) const;
-
- static const std::tr1::shared_ptr<Decision> deserialise(
- Deserialisation & d) PALUDIS_ATTRIBUTE((warn_unused_result));
+ public:
+ virtual ~Decision() = 0;
+
+ virtual bool taken() const PALUDIS_ATTRIBUTE((warn_unused_result)) = 0;
+
+ virtual void serialise(Serialiser &) const = 0;
+
+ static const std::tr1::shared_ptr<Decision> deserialise(
+ Deserialisation & d) PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+
+ class PALUDIS_VISIBLE NothingNoChangeDecision :
+ public Decision,
+ public ImplementAcceptMethods<Decision, NothingNoChangeDecision>,
+ private PrivateImplementationPattern<NothingNoChangeDecision>
+ {
+ public:
+ NothingNoChangeDecision(const bool);
+ ~NothingNoChangeDecision();
+
+ virtual bool taken() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual void serialise(Serialiser &) const;
+ };
+
+ class PALUDIS_VISIBLE ExistingNoChangeDecision :
+ public Decision,
+ public ImplementAcceptMethods<Decision, ExistingNoChangeDecision>,
+ private PrivateImplementationPattern<ExistingNoChangeDecision>
+ {
+ public:
+ ExistingNoChangeDecision(
+ const std::tr1::shared_ptr<const PackageID> &,
+ const bool is_same,
+ const bool is_same_version,
+ const bool is_transient,
+ const bool taken
+ );
+ ~ExistingNoChangeDecision();
+
+ const std::tr1::shared_ptr<const PackageID> existing_id() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ bool is_same() const PALUDIS_ATTRIBUTE((warn_unused_result));
+ bool is_same_version() const PALUDIS_ATTRIBUTE((warn_unused_result));
+ bool is_transient() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual bool taken() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual void serialise(Serialiser &) const;
+ };
+
+ class PALUDIS_VISIBLE ChangesToMakeDecision :
+ public Decision,
+ public ImplementAcceptMethods<Decision, ChangesToMakeDecision>,
+ private PrivateImplementationPattern<ChangesToMakeDecision>
+ {
+ public:
+ ChangesToMakeDecision(
+ const std::tr1::shared_ptr<const PackageID> &,
+ const bool best,
+ const bool taken,
+ const std::tr1::shared_ptr<const Destination> &
+ );
+
+ ~ChangesToMakeDecision();
+
+ const std::tr1::shared_ptr<const Destination> destination() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ void set_destination(const std::tr1::shared_ptr<const Destination> &);
+
+ const std::tr1::shared_ptr<const PackageID> origin_id() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual bool best() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual bool taken() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual void serialise(Serialiser &) const;
+ };
+
+ class PALUDIS_VISIBLE UnableToMakeDecision :
+ public Decision,
+ public ImplementAcceptMethods<Decision, UnableToMakeDecision>,
+ private PrivateImplementationPattern<UnableToMakeDecision>
+ {
+ public:
+ UnableToMakeDecision(
+ const std::tr1::shared_ptr<const UnsuitableCandidates> &,
+ const bool taken);
+ ~UnableToMakeDecision();
+
+ virtual bool taken() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual void serialise(Serialiser &) const;
+
+ const std::tr1::shared_ptr<const UnsuitableCandidates> unsuitable_candidates() const PALUDIS_ATTRIBUTE((warn_unused_result));
};
}
+
+#ifdef PALUDIS_HAVE_EXTERN_TEMPLATE
+ extern template class PrivateImplementationPattern<resolver::NothingNoChangeDecision>;
+ extern template class PrivateImplementationPattern<resolver::ExistingNoChangeDecision>;
+ extern template class PrivateImplementationPattern<resolver::ChangesToMakeDecision>;
+ extern template class PrivateImplementationPattern<resolver::UnableToMakeDecision>;
+#endif
+
}
#endif
diff --git a/paludis/resolver/decision.se b/paludis/resolver/decision.se
deleted file mode 100644
index 58a615e..0000000
--- a/paludis/resolver/decision.se
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/usr/bin/env bash
-# vim: set sw=4 sts=4 et ft=sh :
-
-make_enum_DecisionKind()
-{
- prefix dk
- namespace paludis::resolver
-
- key dk_changes_to_make "We have changes to make"
- key dk_existing_no_change "We have no changes to make, and there's an existing ID."
- key dk_nothing_no_change "We have no changes to make, and there's no existing ID"
- key dk_unable_to_decide "We couldn't decide. No if_package_id."
-
- want_destringify
-}
-
diff --git a/paludis/resolver/resolver.cc b/paludis/resolver/resolver.cc
index 782c538..3bfb2e8 100644
--- a/paludis/resolver/resolver.cc
+++ b/paludis/resolver/resolver.cc
@@ -30,6 +30,7 @@
#include <paludis/resolver/resolutions.hh>
#include <paludis/resolver/serialise.hh>
#include <paludis/resolver/destination.hh>
+#include <paludis/resolver/unsuitable_candidates.hh>
#include <paludis/util/stringify.hh>
#include <paludis/util/make_named_values.hh>
#include <paludis/util/log.hh>
@@ -153,22 +154,7 @@ Resolver::_resolve_decide_with_dependencies()
changed = true;
_decide(i->first, i->second);
- /* we don't have anything left to do unless we're a 'real' decision */
- switch (i->second->decision()->kind())
- {
- case dk_existing_no_change:
- case dk_changes_to_make:
- break;
-
- case dk_nothing_no_change:
- case dk_unable_to_decide:
- case last_dk:
- continue;
- }
-
- /* we don't do dependencies for suggestions */
- if (i->second->decision()->taken())
- _add_dependencies(i->first, i->second);
+ _add_dependencies_if_necessary(i->first, i->second);
}
}
}
@@ -178,53 +164,80 @@ Resolver::_resolve_destinations()
{
Context context("When resolving destinations:");
- for (ResolutionsByResolventMap::iterator i(_imp->resolutions_by_resolvent.begin()), i_end(_imp->resolutions_by_resolvent.end()) ;
+ for (ResolutionsByResolventMap::iterator i(_imp->resolutions_by_resolvent.begin()),
+ i_end(_imp->resolutions_by_resolvent.end()) ;
i != i_end ; ++i)
+ _do_destination_if_necessary(i->first, i->second);
+}
+
+namespace
+{
+ struct DoDestinationIfNecessaryVisitor
{
- if (i->second->decision()->destination())
- continue;
+ typedef std::tr1::function<const std::tr1::shared_ptr<const Destination> (
+ const ChangesToMakeDecision &)> MakeDestinationFunc;
- i->second->decision()->destination() = _make_destination_for(i->first, i->second);
- }
+ MakeDestinationFunc make_destination_for;
+
+ DoDestinationIfNecessaryVisitor(const MakeDestinationFunc & f) :
+ make_destination_for(f)
+ {
+ }
+
+ void visit(ExistingNoChangeDecision &)
+ {
+ }
+
+ void visit(NothingNoChangeDecision &)
+ {
+ }
+
+ void visit(UnableToMakeDecision &)
+ {
+ }
+
+ void visit(ChangesToMakeDecision & decision)
+ {
+ if (! decision.destination())
+ decision.set_destination(make_destination_for(decision));
+ }
+ };
+}
+
+void
+Resolver::_do_destination_if_necessary(
+ const Resolvent & resolvent,
+ const std::tr1::shared_ptr<Resolution> & resolution)
+{
+ DoDestinationIfNecessaryVisitor v(std::tr1::bind(&Resolver::_make_destination_for,
+ this, resolvent, resolution, std::tr1::placeholders::_1));
+ resolution->decision()->accept(v);
}
const std::tr1::shared_ptr<Destination>
Resolver::_make_destination_for(
const Resolvent & resolvent,
- const std::tr1::shared_ptr<const Resolution> & resolution) const
+ const std::tr1::shared_ptr<const Resolution> & resolution,
+ const ChangesToMakeDecision & decision) const
{
- switch (resolution->decision()->kind())
- {
- case dk_existing_no_change:
- case dk_nothing_no_change:
- case dk_unable_to_decide:
- return make_null_shared_ptr();
-
- case dk_changes_to_make:
- {
- const std::tr1::shared_ptr<const Repository> repo(_find_repository_for(resolvent, resolution));
- if ((! repo->destination_interface()) ||
- (! repo->destination_interface()->is_suitable_destination_for(*resolution->decision()->if_package_id())))
- throw InternalError(PALUDIS_HERE, stringify(repo->name()) + " is not a suitable destination for "
- + stringify(*resolution->decision()->if_package_id()));
-
- return make_shared_ptr(new Destination(make_named_values<Destination>(
- value_for<n::replacing>(_find_replacing(resolution->decision()->if_package_id(), repo)),
- value_for<n::repository>(repo->name())
- )));
- }
-
- case last_dk:
- break;
- }
-
- throw InternalError(PALUDIS_HERE, "resolver bug: unhandled dt");
+ const std::tr1::shared_ptr<const Repository> repo(_find_repository_for(resolvent, resolution, decision));
+ if ((! repo->destination_interface()) ||
+ (! repo->destination_interface()->is_suitable_destination_for(*decision.origin_id())))
+ throw InternalError(PALUDIS_HERE, stringify(repo->name()) + " is not a suitable destination for "
+ + stringify(*decision.origin_id()));
+
+ return make_shared_ptr(new Destination(make_named_values<Destination>(
+ value_for<n::replacing>(_find_replacing(decision.origin_id(), repo)),
+ value_for<n::repository>(repo->name())
+ )));
}
const std::tr1::shared_ptr<const Repository>
-Resolver::_find_repository_for(const Resolvent & resolvent, const std::tr1::shared_ptr<const Resolution> & resolution) const
+Resolver::_find_repository_for(const Resolvent & resolvent,
+ const std::tr1::shared_ptr<const Resolution> & resolution,
+ const ChangesToMakeDecision & decision) const
{
- return _imp->fns.find_repository_for_fn()(resolvent, resolution);
+ return _imp->fns.find_repository_for_fn()(resolvent, resolution, decision);
}
FilteredGenerator
@@ -452,55 +465,166 @@ Resolver::_apply_resolution_constraint(
resolution->constraints()->add(constraint);
}
+namespace
+{
+ struct ChosenIDVisitor
+ {
+ const std::tr1::shared_ptr<const PackageID> visit(const ChangesToMakeDecision & decision) const
+ {
+ return decision.origin_id();
+ }
+
+ const std::tr1::shared_ptr<const PackageID> visit(const ExistingNoChangeDecision & decision) const
+ {
+ return decision.existing_id();
+ }
+
+ const std::tr1::shared_ptr<const PackageID> visit(const NothingNoChangeDecision &) const
+ {
+ return make_null_shared_ptr();
+ }
+
+ const std::tr1::shared_ptr<const PackageID> visit(const UnableToMakeDecision &) const
+ {
+ return make_null_shared_ptr();
+ }
+ };
+
+ struct CheckUseExistingVisitor
+ {
+ const std::tr1::shared_ptr<const Constraint> constraint;
+
+ CheckUseExistingVisitor(const std::tr1::shared_ptr<const Constraint> & c) :
+ constraint(c)
+ {
+ }
+
+ bool visit(const ExistingNoChangeDecision & decision) const
+ {
+ switch (constraint->use_existing())
+ {
+ case ue_if_possible:
+ break;
+
+ case ue_only_if_transient:
+ if (! decision.is_transient())
+ return false;
+ break;
+
+ case ue_if_same:
+ if (! decision.is_same())
+ return false;
+ break;
+
+ case ue_if_same_version:
+ if (! decision.is_same_version())
+ return false;
+ break;
+
+ case ue_never:
+ case last_ue:
+ return false;
+ }
+
+ return true;
+ }
+
+ bool visit(const NothingNoChangeDecision &) const
+ {
+ return true;
+ }
+
+ bool visit(const UnableToMakeDecision &) const
+ {
+ return true;
+ }
+
+ bool visit(const ChangesToMakeDecision &) const
+ {
+ return true;
+ }
+ };
+}
+
bool
-Resolver::_verify_new_constraint(const Resolvent &,
- const std::tr1::shared_ptr<const Resolution> & resolution,
- const std::tr1::shared_ptr<const Constraint> & constraint)
+Resolver::_check_constraint(const Resolvent &,
+ const std::tr1::shared_ptr<const Constraint> & constraint,
+ const std::tr1::shared_ptr<const Decision> & decision) const
{
- bool ok;
+ const std::tr1::shared_ptr<const PackageID> chosen_id(decision->accept_returning<
+ std::tr1::shared_ptr<const PackageID> >(ChosenIDVisitor()));
- if (resolution->decision()->if_package_id())
+ if (chosen_id)
{
if (constraint->spec().if_package())
- ok = match_package(*_imp->env, *constraint->spec().if_package(),
- *resolution->decision()->if_package_id(), MatchPackageOptions());
+ {
+ if (! match_package(*_imp->env, *constraint->spec().if_package(), *chosen_id, MatchPackageOptions()))
+ return false;
+ }
else
- ok = ! match_package(*_imp->env, constraint->spec().if_block()->blocking(),
- *resolution->decision()->if_package_id(), MatchPackageOptions());
+ {
+ if (match_package(*_imp->env, constraint->spec().if_block()->blocking(),
+ *chosen_id, MatchPackageOptions()))
+ return false;
+ }
}
else
- ok = constraint->nothing_is_fine_too();
+ {
+ if (! constraint->nothing_is_fine_too())
+ return false;
+ }
+
+ if (! decision->accept_returning<bool>(CheckUseExistingVisitor(constraint)))
+ return false;
- if (ok && dk_existing_no_change == resolution->decision()->kind())
+ if (! constraint->untaken())
{
- switch (constraint->use_existing())
- {
- case ue_if_possible:
- break;
+ if (! decision->taken())
+ return false;
+ }
- case ue_only_if_transient:
- ok = resolution->decision()->is_transient();
- break;
+ return true;
+}
- case ue_if_same:
- ok = resolution->decision()->is_same();
- break;
+bool
+Resolver::_verify_new_constraint(const Resolvent & resolvent,
+ const std::tr1::shared_ptr<const Resolution> & resolution,
+ const std::tr1::shared_ptr<const Constraint> & constraint)
+{
+ return _check_constraint(resolvent, constraint, resolution->decision());
+}
- case ue_if_same_version:
- ok = resolution->decision()->is_same_version();
- break;
+namespace
+{
+ struct WrongDecisionVisitor
+ {
+ std::tr1::function<void ()> restart;
- case ue_never:
- case last_ue:
- ok = false;
- break;
+ WrongDecisionVisitor(const std::tr1::function<void ()> & r) :
+ restart(r)
+ {
}
- }
- if (ok && ! constraint->untaken())
- ok = resolution->decision()->taken();
+ void visit(const NothingNoChangeDecision &) const
+ {
+ /* going from nothing to something is fine */
+ }
+
+ void visit(const UnableToMakeDecision &) const
+ {
+ restart();
+ }
+
+ void visit(const ChangesToMakeDecision &) const
+ {
+ restart();
+ }
- return ok;
+ void visit(const ExistingNoChangeDecision &) const
+ {
+ restart();
+ }
+ };
}
void
@@ -515,22 +639,9 @@ Resolver::_made_wrong_decision(const Resolvent & resolvent,
const std::tr1::shared_ptr<Decision> decision(_try_to_find_decision_for(resolvent, adapted_resolution));
if (decision)
{
- switch (resolution->decision()->kind())
- {
- case dk_nothing_no_change:
- /* going from nothing to something is safe */
- resolution->decision() = decision;
- break;
-
- case dk_unable_to_decide:
- case dk_changes_to_make:
- case dk_existing_no_change:
- _suggest_restart_with(resolvent, resolution, constraint, decision);
- break;
-
- case last_dk:
- break;
- }
+ resolution->decision()->accept(WrongDecisionVisitor(std::tr1::bind(
+ &Resolver::_suggest_restart_with, this, resolvent, resolution, constraint, decision)));
+ resolution->decision() = decision;
}
else
resolution->decision() = _cannot_decide_for(resolvent, adapted_resolution);
@@ -543,28 +654,19 @@ Resolver::_suggest_restart_with(const Resolvent & resolvent,
const std::tr1::shared_ptr<const Decision> & decision) const
{
throw SuggestRestart(resolvent, resolution->decision(), constraint, decision,
- _make_constraint_for_preloading(resolvent, decision));
+ _make_constraint_for_preloading(resolvent, decision, constraint));
}
const std::tr1::shared_ptr<const Constraint>
Resolver::_make_constraint_for_preloading(
- const Resolvent & resolvent,
- const std::tr1::shared_ptr<const Decision> & d) const
+ const Resolvent &,
+ const std::tr1::shared_ptr<const Decision> &,
+ const std::tr1::shared_ptr<const Constraint> & c) const
{
const std::tr1::shared_ptr<PresetReason> reason(new PresetReason);
-
- if (! d->if_package_id())
- throw InternalError(PALUDIS_HERE, "resolver bug: not decided. shouldn't happen.");
-
- return make_shared_ptr(new Constraint(make_named_values<Constraint>(
- value_for<n::destination_type>(resolvent.destination_type()),
- value_for<n::nothing_is_fine_too>(false),
- value_for<n::reason>(reason),
- value_for<n::spec>(d->if_package_id()->uniquely_identifying_spec()),
- value_for<n::untaken>(! d->taken()),
- value_for<n::use_existing>(_imp->fns.get_use_existing_fn()(
- resolvent, d->if_package_id()->uniquely_identifying_spec(), reason))
- )));
+ const std::tr1::shared_ptr<Constraint> result(new Constraint(*c));
+ result->reason() = reason;
+ return result;
}
void
@@ -579,17 +681,54 @@ Resolver::_decide(const Resolvent & resolvent, const std::tr1::shared_ptr<Resolu
resolution->decision() = _cannot_decide_for(resolvent, resolution);
}
+namespace
+{
+ struct DependenciesNecessityVisitor
+ {
+ const std::tr1::shared_ptr<const PackageID> visit(const NothingNoChangeDecision &) const
+ {
+ return make_null_shared_ptr();
+ }
+
+ const std::tr1::shared_ptr<const PackageID> visit(const UnableToMakeDecision &) const
+ {
+ return make_null_shared_ptr();
+ }
+
+ const std::tr1::shared_ptr<const PackageID> visit(const ExistingNoChangeDecision & decision) const
+ {
+ if (decision.taken())
+ return decision.existing_id();
+ else
+ return make_null_shared_ptr();
+ }
+
+ const std::tr1::shared_ptr<const PackageID> visit(const ChangesToMakeDecision & decision) const
+ {
+ if (decision.taken())
+ return decision.origin_id();
+ else
+ return make_null_shared_ptr();
+ }
+ };
+}
+
void
-Resolver::_add_dependencies(const Resolvent & our_resolvent, const std::tr1::shared_ptr<Resolution> & our_resolution)
+Resolver::_add_dependencies_if_necessary(
+ const Resolvent & our_resolvent,
+ const std::tr1::shared_ptr<Resolution> & our_resolution)
{
- if (! our_resolution->decision()->if_package_id())
- throw InternalError(PALUDIS_HERE, "resolver bug: not decided. shouldn't happen.");
+ const std::tr1::shared_ptr<const PackageID> package_id(
+ our_resolution->decision()->accept_returning<std::tr1::shared_ptr<const PackageID> >(
+ DependenciesNecessityVisitor()));
+ if (! package_id)
+ return;
Context context("When adding dependencies for '" + stringify(our_resolvent) + "' with '"
- + stringify(*our_resolution->decision()->if_package_id()) + "':");
+ + stringify(*package_id) + "':");
const std::tr1::shared_ptr<SanitisedDependencies> deps(new SanitisedDependencies);
- deps->populate(*this, our_resolvent, our_resolution->decision()->if_package_id());
+ deps->populate(*this, our_resolvent, package_id);
our_resolution->sanitised_dependencies() = deps;
for (SanitisedDependencies::ConstIterator s(deps->begin()), s_end(deps->end()) ;
@@ -601,7 +740,7 @@ Resolver::_add_dependencies(const Resolvent & our_resolvent, const std::tr1::sha
continue;
const std::tr1::shared_ptr<DependencyReason> reason(new DependencyReason(
- our_resolution->decision()->if_package_id(), our_resolvent, *s));
+ package_id, our_resolvent, *s));
std::tr1::shared_ptr<const Resolvents> resolvents;
@@ -788,44 +927,71 @@ Resolver::_already_met(const SanitisedDependency & dep) const
throw InternalError(PALUDIS_HERE, "resolver bug: huh? it's not a block and it's not a package");
}
-void
-Resolver::_resolve_order()
+namespace
{
- Context context("When finding an order for selected packages:");
-
- bool done(false);
-
- for (ResolutionsByResolventMap::iterator i(_imp->resolutions_by_resolvent.begin()), i_end(_imp->resolutions_by_resolvent.end()) ;
- i != i_end ; ++i)
+ struct ResolveOrderVisitor
{
- switch (i->second->decision()->kind())
+ const std::tr1::function<void ()> already_ordered;
+ const std::tr1::function<void ()> error;
+ const std::tr1::function<void ()> untaken;
+
+ ResolveOrderVisitor(const std::tr1::function<void ()> & a,
+ const std::tr1::function<void ()> & e,
+ const std::tr1::function<void ()> & u) :
+ already_ordered(a),
+ error(e),
+ untaken(u)
{
- case dk_existing_no_change:
- case dk_nothing_no_change:
- i->second->already_ordered() = true;
- break;
+ }
- case dk_unable_to_decide:
- i->second->already_ordered() = true;
- if (i->second->decision()->taken())
- _imp->resolution_lists->errors()->append(i->second);
- else
- _imp->resolution_lists->untaken()->append(i->second);
- break;
+ void visit(const ExistingNoChangeDecision &) const
+ {
+ already_ordered();
+ }
- case dk_changes_to_make:
- if (! i->second->decision()->taken())
- {
- i->second->already_ordered() = true;
- _imp->resolution_lists->untaken()->append(i->second);
- }
- break;
+ void visit(const NothingNoChangeDecision &) const
+ {
+ already_ordered();
+ }
- case last_dk:
- break;
+ void visit(const UnableToMakeDecision & d) const
+ {
+ already_ordered();
+ if (d.taken())
+ error();
+ else
+ untaken();
}
+
+ void visit(const ChangesToMakeDecision & d) const
+ {
+ if (! d.taken())
+ {
+ already_ordered();
+ untaken();
+ }
+ }
+ };
+}
+
+void
+Resolver::_resolve_order()
+{
+ Context context("When finding an order for selected packages:");
+
+ for (ResolutionsByResolventMap::iterator i(_imp->resolutions_by_resolvent.begin()),
+ i_end(_imp->resolutions_by_resolvent.end()) ;
+ i != i_end ; ++i)
+ {
+ i->second->decision()->accept(ResolveOrderVisitor(
+ std::tr1::bind(&NamedValue<n::already_ordered, bool>::operator=,
+ &i->second->already_ordered, value_for<n::already_ordered>(true)),
+ std::tr1::bind(&Resolutions::append, _imp->resolution_lists->errors(), i->second),
+ std::tr1::bind(&Resolutions::append, _imp->resolution_lists->untaken(), i->second)
+ ));
}
+ bool done(false);
while (! done)
{
bool any(false);
@@ -909,7 +1075,7 @@ Resolver::_unable_to_order_more() const
if (i->second->already_ordered())
continue;
- std::cout << " * " << *i->second->decision()->if_package_id() << " because of cycle "
+ std::cout << " * " << i->first << " because of cycle "
<< _find_cycle(i->first, true)
<< std::endl;
}
@@ -1026,8 +1192,13 @@ Resolver::find_any_score(const Resolvent & our_resolvent, const SanitisedDepende
return 40 + operator_bias;
}
- const std::tr1::shared_ptr<DependencyReason> reason(new DependencyReason(
- _resolution_for_resolvent(our_resolvent)->decision()->if_package_id(), our_resolvent, dep));
+ const std::tr1::shared_ptr<const PackageID> id(_resolution_for_resolvent(
+ our_resolvent)->decision()->accept_returning<std::tr1::shared_ptr<const PackageID> >(
+ ChosenIDVisitor()));
+ if (! id)
+ throw InternalError(PALUDIS_HERE, "resolver bug: why don't we have an id?");
+
+ const std::tr1::shared_ptr<DependencyReason> reason(new DependencyReason(id, our_resolvent, dep));
const std::tr1::shared_ptr<const Resolvents> resolvents(_get_resolvents_for(spec, reason));
/* next: will already be installing */
@@ -1239,30 +1410,19 @@ Resolver::_try_to_find_decision_for(
if (resolution->constraints()->nothing_is_fine_too() && ! existing_id)
{
/* nothing existing, but nothing's ok */
- return make_shared_ptr(new Decision(make_named_values<Decision>(
- value_for<n::destination>(make_null_shared_ptr()),
- value_for<n::if_package_id>(make_null_shared_ptr()),
- value_for<n::is_best>(false),
- value_for<n::is_same>(false),
- value_for<n::is_same_version>(false),
- value_for<n::is_transient>(false),
- value_for<n::kind>(dk_nothing_no_change),
- value_for<n::taken>(! resolution->constraints()->all_untaken())
- )));
+ return make_shared_ptr(new NothingNoChangeDecision(
+ ! resolution->constraints()->all_untaken()
+ ));
}
else if (installable_id && ! existing_id)
{
/* there's nothing suitable existing. */
- return make_shared_ptr(new Decision(make_named_values<Decision>(
- value_for<n::destination>(make_null_shared_ptr()),
- value_for<n::if_package_id>(installable_id),
- value_for<n::is_best>(best),
- value_for<n::is_same>(false),
- value_for<n::is_same_version>(false),
- value_for<n::is_transient>(false),
- value_for<n::kind>(dk_changes_to_make),
- value_for<n::taken>(! resolution->constraints()->all_untaken())
- )));
+ return make_shared_ptr(new ChangesToMakeDecision(
+ installable_id,
+ best,
+ ! resolution->constraints()->all_untaken(),
+ make_null_shared_ptr()
+ ));
}
else if (existing_id && ! installable_id)
{
@@ -1288,17 +1448,13 @@ Resolver::_try_to_find_decision_for(
break;
}
- return make_shared_ptr(new Decision(make_named_values<Decision>(
- value_for<n::destination>(make_null_shared_ptr()),
- value_for<n::if_package_id>(existing_id),
- value_for<n::is_best>(false),
- value_for<n::is_same>(true),
- value_for<n::is_same_version>(true),
- value_for<n::is_transient>(is_transient),
- value_for<n::kind>(dk_existing_no_change),
- value_for<n::taken>(! resolution->constraints()->all_untaken())
-
- )));
+ return make_shared_ptr(new ExistingNoChangeDecision(
+ existing_id,
+ true,
+ true,
+ is_transient,
+ ! resolution->constraints()->all_untaken()
+ ));
}
else if ((! existing_id) && (! installable_id))
{
@@ -1362,80 +1518,45 @@ Resolver::_try_to_find_decision_for(
bool is_transient(existing_id->transient_key() && existing_id->transient_key()->value());
/* we've got existing and installable. do we have any reason not to pick the existing id? */
+ const std::tr1::shared_ptr<Decision> existing(new ExistingNoChangeDecision(
+ existing_id,
+ is_same,
+ is_same_version,
+ is_transient,
+ ! resolution->constraints()->all_untaken()
+ ));
+ const std::tr1::shared_ptr<Decision> changes_to_make(new ChangesToMakeDecision(
+ installable_id,
+ best,
+ ! resolution->constraints()->all_untaken(),
+ make_null_shared_ptr()
+ ));
+
switch (resolution->constraints()->strictest_use_existing())
{
case ue_only_if_transient:
case ue_never:
- return make_shared_ptr(new Decision(make_named_values<Decision>(
- value_for<n::destination>(make_null_shared_ptr()),
- value_for<n::if_package_id>(installable_id),
- value_for<n::is_best>(best),
- value_for<n::is_same>(is_same),
- value_for<n::is_same_version>(is_same_version),
- value_for<n::is_transient>(false),
- value_for<n::kind>(dk_changes_to_make),
- value_for<n::taken>(! resolution->constraints()->all_untaken())
- )));
+ return make_shared_ptr(new ChangesToMakeDecision(
+ installable_id,
+ best,
+ ! resolution->constraints()->all_untaken(),
+ make_null_shared_ptr()
+ ));
case ue_if_same:
if (is_same)
- return make_shared_ptr(new Decision(make_named_values<Decision>(
- value_for<n::destination>(make_null_shared_ptr()),
- value_for<n::if_package_id>(existing_id),
- value_for<n::is_best>(false),
- value_for<n::is_same>(is_same),
- value_for<n::is_same_version>(is_same_version),
- value_for<n::is_transient>(false),
- value_for<n::kind>(dk_existing_no_change),
- value_for<n::taken>(! resolution->constraints()->all_untaken())
- )));
+ return existing;
else
- return make_shared_ptr(new Decision(make_named_values<Decision>(
- value_for<n::destination>(make_null_shared_ptr()),
- value_for<n::if_package_id>(installable_id),
- value_for<n::is_best>(best),
- value_for<n::is_same>(is_same),
- value_for<n::is_same_version>(is_same_version),
- value_for<n::is_transient>(is_transient),
- value_for<n::kind>(dk_changes_to_make),
- value_for<n::taken>(! resolution->constraints()->all_untaken())
- )));
+ return changes_to_make;
case ue_if_same_version:
if (is_same_version)
- return make_shared_ptr(new Decision(make_named_values<Decision>(
- value_for<n::destination>(make_null_shared_ptr()),
- value_for<n::if_package_id>(existing_id),
- value_for<n::is_best>(false),
- value_for<n::is_same>(is_same),
- value_for<n::is_same_version>(is_same_version),
- value_for<n::is_transient>(false),
- value_for<n::kind>(dk_existing_no_change),
- value_for<n::taken>(! resolution->constraints()->all_untaken())
- )));
+ return existing;
else
- return make_shared_ptr(new Decision(make_named_values<Decision>(
- value_for<n::destination>(make_null_shared_ptr()),
- value_for<n::if_package_id>(installable_id),
- value_for<n::is_best>(best),
- value_for<n::is_same>(is_same),
- value_for<n::is_same_version>(is_same_version),
- value_for<n::is_transient>(is_transient),
- value_for<n::kind>(dk_changes_to_make),
- value_for<n::taken>(! resolution->constraints()->all_untaken())
- )));
+ return changes_to_make;
case ue_if_possible:
- return make_shared_ptr(new Decision(make_named_values<Decision>(
- value_for<n::destination>(make_null_shared_ptr()),
- value_for<n::if_package_id>(existing_id),
- value_for<n::is_best>(false),
- value_for<n::is_same>(is_same),
- value_for<n::is_same_version>(is_same_version),
- value_for<n::is_transient>(false),
- value_for<n::kind>(dk_existing_no_change),
- value_for<n::taken>(! resolution->constraints()->all_untaken())
- )));
+ return existing;
case last_ue:
break;
@@ -1447,19 +1568,36 @@ Resolver::_try_to_find_decision_for(
const std::tr1::shared_ptr<Decision>
Resolver::_cannot_decide_for(
- const Resolvent &,
+ const Resolvent & resolvent,
const std::tr1::shared_ptr<const Resolution> & resolution) const
{
- return make_shared_ptr(new Decision(make_named_values<Decision>(
- value_for<n::destination>(make_null_shared_ptr()),
- value_for<n::if_package_id>(make_null_shared_ptr()),
- value_for<n::is_best>(false),
- value_for<n::is_same>(false),
- value_for<n::is_same_version>(false),
- value_for<n::is_transient>(false),
- value_for<n::kind>(dk_unable_to_decide),
- value_for<n::taken>(! resolution->constraints()->all_untaken())
- )));
+ const std::tr1::shared_ptr<UnsuitableCandidates> unsuitable_candidates(new UnsuitableCandidates);
+
+ const std::tr1::shared_ptr<const PackageID> existing_id(_find_existing_id_for(resolvent, resolution));
+ if (existing_id)
+ unsuitable_candidates->push_back(_make_unsuitable_candidate(resolvent, resolution, existing_id));
+
+ const std::tr1::shared_ptr<const PackageIDSequence> installable_ids(_find_installable_id_candidates_for(resolvent, resolution, true));
+ for (PackageIDSequence::ConstIterator i(installable_ids->begin()), i_end(installable_ids->end()) ;
+ i != i_end ; ++i)
+ unsuitable_candidates->push_back(_make_unsuitable_candidate(resolvent, resolution, *i));
+
+ return make_shared_ptr(new UnableToMakeDecision(
+ unsuitable_candidates,
+ ! resolution->constraints()->all_untaken()
+ ));
+}
+
+UnsuitableCandidate
+Resolver::_make_unsuitable_candidate(
+ const Resolvent & resolvent,
+ const std::tr1::shared_ptr<const Resolution> &,
+ const std::tr1::shared_ptr<const PackageID> & id) const
+{
+ return make_named_values<UnsuitableCandidate>(
+ value_for<n::package_id>(id),
+ value_for<n::unmet_constraints>(_get_unmatching_constraints(resolvent, id))
+ );
}
const std::tr1::shared_ptr<const PackageID>
@@ -1473,17 +1611,23 @@ Resolver::_find_existing_id_for(const Resolvent & resolvent, const std::tr1::sha
return _find_id_for_from(resolvent, resolution, ids).first;
}
+const std::tr1::shared_ptr<const PackageIDSequence>
+Resolver::_find_installable_id_candidates_for(const Resolvent & resolvent,
+ const std::tr1::shared_ptr<const Resolution> &,
+ const bool include_errors) const
+{
+ return (*_imp->env)[selection::AllVersionsSorted(
+ generator::Package(resolvent.package()) |
+ make_slot_filter(resolvent) |
+ filter::SupportsAction<InstallAction>() |
+ ((! include_errors) ? Filter(filter::NotMasked()) : Filter(filter::All()))
+ )];
+}
+
const std::pair<const std::tr1::shared_ptr<const PackageID>, bool>
Resolver::_find_installable_id_for(const Resolvent & resolvent, const std::tr1::shared_ptr<const Resolution> & resolution) const
{
- const std::tr1::shared_ptr<const PackageIDSequence> ids((*_imp->env)[selection::AllVersionsSorted(
- generator::Package(resolvent.package()) |
- make_slot_filter(resolvent) |
- filter::SupportsAction<InstallAction>() |
- filter::NotMasked()
- )]);
-
- return _find_id_for_from(resolvent, resolution, ids);
+ return _find_id_for_from(resolvent, resolution, _find_installable_id_candidates_for(resolvent, resolution, false));
}
const std::pair<const std::tr1::shared_ptr<const PackageID>, bool>
@@ -1576,6 +1720,30 @@ Resolver::rewrite_if_special(const PackageOrBlockDepSpec & s, const Resolvent &
return make_null_shared_ptr();
}
+const std::tr1::shared_ptr<const Constraints>
+Resolver::_get_unmatching_constraints(
+ const Resolvent & resolvent,
+ const std::tr1::shared_ptr<const PackageID> & id) const
+{
+ const std::tr1::shared_ptr<const Resolution> resolution(_resolution_for_resolvent(resolvent));
+ const std::tr1::shared_ptr<Constraints> result(new Constraints);
+
+ for (Constraints::ConstIterator c(resolution->constraints()->begin()),
+ c_end(resolution->constraints()->end()) ;
+ c != c_end ; ++c)
+ {
+ if (! _check_constraint(resolvent, *c, make_shared_ptr(new ChangesToMakeDecision(
+ id,
+ false,
+ ! (*c)->untaken(),
+ make_null_shared_ptr()
+ ))))
+ result->add(*c);
+ }
+
+ return result;
+}
+
void
Resolver::_need_rewrites() const
{
diff --git a/paludis/resolver/resolver.hh b/paludis/resolver/resolver.hh
index 2e5ed2c..845d676 100644
--- a/paludis/resolver/resolver.hh
+++ b/paludis/resolver/resolver.hh
@@ -32,6 +32,7 @@
#include <paludis/resolver/resolver_functions-fwd.hh>
#include <paludis/resolver/destination_types-fwd.hh>
#include <paludis/resolver/destination-fwd.hh>
+#include <paludis/resolver/unsuitable_candidates-fwd.hh>
#include <paludis/util/private_implementation_pattern.hh>
#include <paludis/util/wrapped_forward_iterator-fwd.hh>
#include <paludis/package_id-fwd.hh>
@@ -85,6 +86,10 @@ namespace paludis
const std::tr1::shared_ptr<Resolution> &,
const std::tr1::shared_ptr<const Constraint> &);
+ bool _check_constraint(const Resolvent &,
+ const std::tr1::shared_ptr<const Constraint> & constraint,
+ const std::tr1::shared_ptr<const Decision> & decision) const;
+
bool _verify_new_constraint(const Resolvent &,
const std::tr1::shared_ptr<const Resolution> &,
const std::tr1::shared_ptr<const Constraint> &);
@@ -100,7 +105,8 @@ namespace paludis
const std::tr1::shared_ptr<const Constraint> _make_constraint_for_preloading(
const Resolvent &,
- const std::tr1::shared_ptr<const Decision> & d) const;
+ const std::tr1::shared_ptr<const Decision> & d,
+ const std::tr1::shared_ptr<const Constraint> & c) const;
const std::tr1::shared_ptr<const PackageIDSequence> _find_replacing(
const std::tr1::shared_ptr<const PackageID> &,
@@ -108,7 +114,8 @@ namespace paludis
const std::tr1::shared_ptr<const Repository> _find_repository_for(
const Resolvent &,
- const std::tr1::shared_ptr<const Resolution> &) const;
+ const std::tr1::shared_ptr<const Resolution> &,
+ const ChangesToMakeDecision &) const;
void _resolve_arrow(const Resolvent &, const std::tr1::shared_ptr<Resolution> &,
const std::tr1::shared_ptr<const Constraint> &);
@@ -120,7 +127,8 @@ namespace paludis
const std::tr1::shared_ptr<Destination> _make_destination_for(
const Resolvent & resolvent,
- const std::tr1::shared_ptr<const Resolution> & resolution) const;
+ const std::tr1::shared_ptr<const Resolution> & resolution,
+ const ChangesToMakeDecision &) const;
FilteredGenerator _make_destination_filtered_generator(const Generator &, const Resolvent & resolvent) const;
@@ -132,7 +140,10 @@ namespace paludis
const std::tr1::shared_ptr<Decision> _cannot_decide_for(
const Resolvent &, const std::tr1::shared_ptr<const Resolution> & resolution) const;
- void _add_dependencies(const Resolvent & our_resolvent,
+ void _do_destination_if_necessary(const Resolvent & our_resolvent,
+ const std::tr1::shared_ptr<Resolution> & our_resolution);
+
+ void _add_dependencies_if_necessary(const Resolvent & our_resolvent,
const std::tr1::shared_ptr<Resolution> & our_resolution);
bool _care_about_dependency_spec(const Resolvent &, const std::tr1::shared_ptr<const Resolution> &,
@@ -158,12 +169,23 @@ namespace paludis
const std::tr1::shared_ptr<const PackageID> _find_existing_id_for(
const Resolvent &, const std::tr1::shared_ptr<const Resolution> &) const;
+ const std::tr1::shared_ptr<const PackageIDSequence> _find_installable_id_candidates_for(
+ const Resolvent &, const std::tr1::shared_ptr<const Resolution> &,
+ const bool include_errors) const;
const std::pair<const std::tr1::shared_ptr<const PackageID>, bool> _find_installable_id_for(
const Resolvent &, const std::tr1::shared_ptr<const Resolution> &) const;
const std::pair<const std::tr1::shared_ptr<const PackageID>, bool> _find_id_for_from(
const Resolvent &, const std::tr1::shared_ptr<const Resolution> &,
const std::tr1::shared_ptr<const PackageIDSequence> &) const;
+ const std::tr1::shared_ptr<const Constraints> _get_unmatching_constraints(
+ const Resolvent &, const std::tr1::shared_ptr<const PackageID> &) const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ UnsuitableCandidate _make_unsuitable_candidate(
+ const Resolvent &,
+ const std::tr1::shared_ptr<const Resolution> &,
+ const std::tr1::shared_ptr<const PackageID> &) const;
+
void _need_rewrites() const;
public:
diff --git a/paludis/resolver/resolver_TEST_serialisation.cc b/paludis/resolver/resolver_TEST_serialisation.cc
index 1ec6c48..eb83133 100644
--- a/paludis/resolver/resolver_TEST_serialisation.cc
+++ b/paludis/resolver/resolver_TEST_serialisation.cc
@@ -87,7 +87,7 @@ namespace test_cases
{
TestMessageSuffix s("errors");
check_resolution_list(resolutions->errors(), ResolutionListChecks()
- .kind(dk_unable_to_decide, QualifiedPackageName("serialisation/error"))
+ .kind("unable_to_make_decision", QualifiedPackageName("serialisation/error"))
.finished()
);
}
diff --git a/paludis/resolver/resolver_functions.hh b/paludis/resolver/resolver_functions.hh
index 86bbace..b18bc43 100644
--- a/paludis/resolver/resolver_functions.hh
+++ b/paludis/resolver/resolver_functions.hh
@@ -53,7 +53,8 @@ namespace paludis
typedef std::tr1::function<const std::tr1::shared_ptr<const Repository> (
const Resolvent &,
- const std::tr1::shared_ptr<const Resolution> &
+ const std::tr1::shared_ptr<const Resolution> &,
+ const ChangesToMakeDecision &
)> FindRepositoryForFunction;
typedef std::tr1::function<DestinationTypes (
diff --git a/paludis/resolver/resolver_test.cc b/paludis/resolver/resolver_test.cc
index 518f228..5739719 100644
--- a/paludis/resolver/resolver_test.cc
+++ b/paludis/resolver/resolver_test.cc
@@ -196,7 +196,8 @@ const std::tr1::shared_ptr<const Repository>
paludis::resolver::resolver_test::find_repository_for_fn(
const Environment * const env,
const Resolvent &,
- const std::tr1::shared_ptr<const Resolution> &)
+ const std::tr1::shared_ptr<const Resolution> &,
+ const ChangesToMakeDecision &)
{
return env->package_database()->fetch_repository(RepositoryName("installed"));
}
@@ -251,7 +252,8 @@ ResolverTestCase::get_resolutions(const PackageDepSpec & target)
Resolver resolver(&env, make_named_values<ResolverFunctions>(
value_for<n::care_about_dep_fn>(&care_about_dep_fn),
value_for<n::find_repository_for_fn>(std::tr1::bind(&find_repository_for_fn,
- &env, std::tr1::placeholders::_1, std::tr1::placeholders::_2)),
+ &env, std::tr1::placeholders::_1, std::tr1::placeholders::_2,
+ std::tr1::placeholders::_3)),
value_for<n::get_destination_types_for_fn>(&get_destination_types_for_fn),
value_for<n::get_initial_constraints_for_fn>(
std::tr1::bind(&initial_constraints_for_fn, std::tr1::ref(initial_constraints),
@@ -279,27 +281,78 @@ ResolverTestCase::get_resolutions(const std::string & target)
return get_resolutions(target_spec);
}
+namespace
+{
+ struct ChosenIDVisitor
+ {
+ const std::tr1::shared_ptr<const PackageID> visit(const ChangesToMakeDecision & decision) const
+ {
+ return decision.origin_id();
+ }
+
+ const std::tr1::shared_ptr<const PackageID> visit(const ExistingNoChangeDecision & decision) const
+ {
+ return decision.existing_id();
+ }
+
+ const std::tr1::shared_ptr<const PackageID> visit(const NothingNoChangeDecision &) const
+ {
+ return make_null_shared_ptr();
+ }
+
+ const std::tr1::shared_ptr<const PackageID> visit(const UnableToMakeDecision &) const
+ {
+ return make_null_shared_ptr();
+ }
+ };
+
+ struct KindNameVisitor
+ {
+ const std::string visit(const UnableToMakeDecision &) const
+ {
+ return "unable_to_make_decision";
+ }
+
+ const std::string visit(const NothingNoChangeDecision &) const
+ {
+ return "nothing_no_change";
+ }
+
+ const std::string visit(const ExistingNoChangeDecision &) const
+ {
+ return "existing_no_change";
+ }
+
+ const std::string visit(const ChangesToMakeDecision &) const
+ {
+ return "changes_to_make";
+ }
+ };
+}
+
bool
ResolverTestCase::ResolutionListChecks::check_qpn(const QualifiedPackageName & q, const std::tr1::shared_ptr<const Resolution> & r)
{
- if ((! r) || (! r->decision()) || (! r->decision()->if_package_id()))
+ const std::tr1::shared_ptr<const PackageID> id(r->decision()->accept_returning<
+ std::tr1::shared_ptr<const PackageID> >(ChosenIDVisitor()));
+ if ((! r) || (! r->decision()) || ! id)
return false;
- return r->decision()->if_package_id()->name() == q;
+ return id->name() == q;
}
bool
-ResolverTestCase::ResolutionListChecks::check_kind(const DecisionKind k,
+ResolverTestCase::ResolutionListChecks::check_kind(const std::string & k,
const QualifiedPackageName & q, const std::tr1::shared_ptr<const Resolution> & r)
{
if ((! r) || (! r->decision()))
return false;
- return r->decision()->kind() == k && r->resolvent().package() == q;
+ return r->decision()->accept_returning<std::string>(KindNameVisitor()) == k && r->resolvent().package() == q;
}
std::string
-ResolverTestCase::ResolutionListChecks::check_kind_msg(const DecisionKind k,
+ResolverTestCase::ResolutionListChecks::check_kind_msg(const std::string & k,
const QualifiedPackageName & q, const std::tr1::shared_ptr<const Resolution> & r)
{
if (! r)
@@ -307,7 +360,8 @@ ResolverTestCase::ResolutionListChecks::check_kind_msg(const DecisionKind k,
else if (! r->decision())
return "Expected " + stringify(k) + " " + stringify(q) + " but got undecided for " + stringify(r->resolvent());
else
- return "Expected " + stringify(k) + " " + stringify(q) + " but got " + stringify(r->decision()->kind()) + " "
+ return "Expected " + stringify(k) + " " + stringify(q) + " but got "
+ + r->decision()->accept_returning<std::string>(KindNameVisitor()) + " "
+ stringify(r->resolvent().package());
}
@@ -318,11 +372,14 @@ ResolverTestCase::ResolutionListChecks::check_generic_msg(const std::string & q,
return "Expected " + stringify(q) + " but got finished";
else if (! r->decision())
return "Expected " + stringify(q) + " but got undecided for " + stringify(r->resolvent());
- else if (! r->decision()->if_package_id())
- return "Expected " + stringify(q) + " but got decided nothing (kind " + stringify(r->decision()->kind()) + ") for "
+ else if (! r->decision()->accept_returning<std::tr1::shared_ptr<const PackageID> >(ChosenIDVisitor()))
+ return "Expected " + stringify(q) + " but got decided nothing (kind "
+ + stringify(r->decision()->accept_returning<std::string>(KindNameVisitor())) + ") for "
+ stringify(r->resolvent());
else
- return "Expected " + stringify(q) + " but got " + stringify(r->decision()->if_package_id()->name()) + " for "
+ return "Expected " + stringify(q) + " but got " + stringify(
+ r->decision()->accept_returning<std::tr1::shared_ptr<const PackageID> >(
+ ChosenIDVisitor())->name()) + " for "
+ stringify(r->resolvent());
}
@@ -355,7 +412,7 @@ ResolverTestCase::ResolutionListChecks::qpn(const QualifiedPackageName & q)
}
ResolverTestCase::ResolutionListChecks &
-ResolverTestCase::ResolutionListChecks::kind(const DecisionKind k, const QualifiedPackageName & q)
+ResolverTestCase::ResolutionListChecks::kind(const std::string & k, const QualifiedPackageName & q)
{
checks.push_back(std::make_pair(
std::tr1::bind(&check_kind, k, q, std::tr1::placeholders::_1),
diff --git a/paludis/resolver/resolver_test.hh b/paludis/resolver/resolver_test.hh
index 170b822..58f8823 100644
--- a/paludis/resolver/resolver_test.hh
+++ b/paludis/resolver/resolver_test.hh
@@ -76,7 +76,8 @@ namespace paludis
const std::tr1::shared_ptr<const Repository> find_repository_for_fn(
const Environment * const,
const Resolvent &,
- const std::tr1::shared_ptr<const Resolution> &);
+ const std::tr1::shared_ptr<const Resolution> &,
+ const ChangesToMakeDecision &);
FilteredGenerator make_destination_filtered_generator_fn(const Generator &, const Resolvent &);
@@ -113,14 +114,15 @@ namespace paludis
static std::string check_finished_msg(const std::tr1::shared_ptr<const Resolution> & r);
- static bool check_kind(const DecisionKind, const QualifiedPackageName &, const std::tr1::shared_ptr<const Resolution> & r);
+ static bool check_kind(const std::string & kind, const QualifiedPackageName &,
+ const std::tr1::shared_ptr<const Resolution> & r);
- static std::string check_kind_msg(const DecisionKind, const QualifiedPackageName &,
+ static std::string check_kind_msg(const std::string &, const QualifiedPackageName &,
const std::tr1::shared_ptr<const Resolution> & r);
ResolutionListChecks & qpn(const QualifiedPackageName & q);
- ResolutionListChecks & kind(const DecisionKind, const QualifiedPackageName & q);
+ ResolutionListChecks & kind(const std::string & kind, const QualifiedPackageName & q);
ResolutionListChecks & finished();
};
diff --git a/paludis/resolver/unsuitable_candidates-fwd.hh b/paludis/resolver/unsuitable_candidates-fwd.hh
new file mode 100644
index 0000000..8bd5892
--- /dev/null
+++ b/paludis/resolver/unsuitable_candidates-fwd.hh
@@ -0,0 +1,35 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2009 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PALUDIS_GUARD_PALUDIS_RESOLVER_UNSUITABLE_CANDIDATES_FWD_HH
+#define PALUDIS_GUARD_PALUDIS_RESOLVER_UNSUITABLE_CANDIDATES_FWD_HH 1
+
+#include <paludis/util/sequence-fwd.hh>
+
+namespace paludis
+{
+ namespace resolver
+ {
+ struct UnsuitableCandidate;
+
+ typedef Sequence<UnsuitableCandidate> UnsuitableCandidates;
+ }
+}
+
+#endif
diff --git a/paludis/resolver/unsuitable_candidates.cc b/paludis/resolver/unsuitable_candidates.cc
new file mode 100644
index 0000000..5dafd3f
--- /dev/null
+++ b/paludis/resolver/unsuitable_candidates.cc
@@ -0,0 +1,51 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2009 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <paludis/resolver/unsuitable_candidates.hh>
+#include <paludis/resolver/serialise-impl.hh>
+#include <paludis/resolver/constraint.hh>
+#include <paludis/util/sequence-impl.hh>
+#include <paludis/util/wrapped_forward_iterator-impl.hh>
+#include <paludis/util/make_named_values.hh>
+
+using namespace paludis;
+using namespace paludis::resolver;
+
+template class Sequence<UnsuitableCandidate>;
+template class WrappedForwardIterator<UnsuitableCandidates::ConstIteratorTag, const UnsuitableCandidate>;
+
+UnsuitableCandidate
+UnsuitableCandidate::deserialise(Deserialisation & d)
+{
+ Deserialisator v(d, "UnsuitableCandidate");
+ return make_named_values<UnsuitableCandidate>(
+ value_for<n::package_id>(v.member<std::tr1::shared_ptr<const PackageID> >("package_id")),
+ value_for<n::unmet_constraints>(v.member<std::tr1::shared_ptr<Constraints> >("unmet_constraints"))
+ );
+}
+
+void
+UnsuitableCandidate::serialise(Serialiser & s) const
+{
+ s.object("UnsuitableCandidate")
+ .member(SerialiserFlags<serialise::might_be_null>(), "package_id", package_id())
+ .member(SerialiserFlags<>(), "unmet_constraints", *unmet_constraints())
+ ;
+}
+
diff --git a/paludis/resolver/unsuitable_candidates.hh b/paludis/resolver/unsuitable_candidates.hh
new file mode 100644
index 0000000..f3d57d4
--- /dev/null
+++ b/paludis/resolver/unsuitable_candidates.hh
@@ -0,0 +1,50 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2009 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PALUDIS_GUARD_PALUDIS_RESOLVER_UNSUITABLE_CANDIDATES_HH
+#define PALUDIS_GUARD_PALUDIS_RESOLVER_UNSUITABLE_CANDIDATES_HH 1
+
+#include <paludis/resolver/unsuitable_candidates-fwd.hh>
+#include <paludis/resolver/serialise-fwd.hh>
+#include <paludis/resolver/constraint-fwd.hh>
+#include <paludis/util/named_value.hh>
+#include <paludis/package_id-fwd.hh>
+
+namespace paludis
+{
+ namespace n
+ {
+ struct package_id;
+ struct unmet_constraints;
+ }
+
+ namespace resolver
+ {
+ struct UnsuitableCandidate
+ {
+ NamedValue<n::package_id, std::tr1::shared_ptr<const PackageID> > package_id;
+ NamedValue<n::unmet_constraints, std::tr1::shared_ptr<const Constraints> > unmet_constraints;
+
+ static UnsuitableCandidate deserialise(Deserialisation &) PALUDIS_ATTRIBUTE((warn_unused_result));
+ void serialise(Serialiser &) const;
+ };
+ }
+}
+
+#endif
diff --git a/src/clients/cave/cmd_display_resolution.cc b/src/clients/cave/cmd_display_resolution.cc
index 1c6aa8f..ada3ac7 100644
--- a/src/clients/cave/cmd_display_resolution.cc
+++ b/src/clients/cave/cmd_display_resolution.cc
@@ -44,6 +44,7 @@
#include <paludis/resolver/resolver.hh>
#include <paludis/resolver/resolvent.hh>
#include <paludis/resolver/destination.hh>
+#include <paludis/resolver/unsuitable_candidates.hh>
#include <paludis/package_id.hh>
#include <paludis/version_spec.hh>
#include <paludis/metadata_key.hh>
@@ -57,6 +58,7 @@
#include <paludis/filtered_generator.hh>
#include <paludis/selection.hh>
#include <paludis/environment.hh>
+#include <paludis/mask.hh>
#include <set>
#include <iterator>
@@ -154,6 +156,29 @@ namespace
}
};
+ struct NotBestVisitor
+ {
+ bool visit(const ExistingNoChangeDecision &) const
+ {
+ return false;
+ }
+
+ bool visit(const NothingNoChangeDecision &) const
+ {
+ return false;
+ }
+
+ bool visit(const UnableToMakeDecision &) const
+ {
+ return false;
+ }
+
+ bool visit(const ChangesToMakeDecision & d) const
+ {
+ return ! d.best();
+ }
+ };
+
void display_reasons(
const std::tr1::shared_ptr<const Resolution> & resolution,
const bool verbose)
@@ -211,11 +236,63 @@ namespace
cout << endl;
}
- if ((! resolution->decision()->is_best()) && resolution->decision()->kind() == dk_changes_to_make)
+ if (resolution->decision()->accept_returning<bool>(NotBestVisitor()))
cout << c::bold_red() << " Which prevented selection of the best candidate" << c::normal() << endl;
}
}
+ std::string mask_stringifier(const Mask & mask)
+ {
+ return stringify(mask.key());
+ }
+
+ struct DisplayOneErrorVisitor
+ {
+ void visit(const UnableToMakeDecision & d) const
+ {
+ if (d.unsuitable_candidates()->empty())
+ cout << " No potential candidates were found" << endl;
+ else
+ {
+ cout << " Potential candidates were:" << endl;
+ for (UnsuitableCandidates::ConstIterator u(d.unsuitable_candidates()->begin()), u_end(d.unsuitable_candidates()->end()) ;
+ u != u_end ; ++u)
+ {
+ cout << " " << *u->package_id() << ": ";
+
+ if (u->package_id()->masked())
+ cout << c::bold_red() << "masked" << c::normal() << " (" << join(indirect_iterator(u->package_id()->begin_masks()),
+ indirect_iterator(u->package_id()->end_masks()), "", mask_stringifier) << ")";
+
+ if (! u->unmet_constraints()->empty())
+ {
+ if (u->package_id()->masked())
+ cout << ", ";
+ cout << c::bold_red() << "unmatching" << c::normal() << " (" << (*u->unmet_constraints()->begin())->spec();
+ int dx(std::distance(u->unmet_constraints()->begin(), u->unmet_constraints()->end()));
+ if (dx > 1)
+ cout << ", " << dx << " more";
+ cout << ")";
+ }
+
+ cout << endl;
+ }
+ }
+ }
+
+ void visit(const ExistingNoChangeDecision &) const
+ {
+ }
+
+ void visit(const ChangesToMakeDecision &) const
+ {
+ }
+
+ void visit(const NothingNoChangeDecision &) const
+ {
+ }
+ };
+
void display_one_error(
const std::tr1::shared_ptr<Environment> &,
const DisplayResolutionCommandLine &,
@@ -230,8 +307,56 @@ namespace
cout << " (no decision could be reached)" << endl;
display_reasons(resolution, verbose);
+
+ resolution->decision()->accept(DisplayOneErrorVisitor());
}
+ struct ChosenIDVisitor
+ {
+ const std::tr1::shared_ptr<const PackageID> visit(const ChangesToMakeDecision & decision) const
+ {
+ return decision.origin_id();
+ }
+
+ const std::tr1::shared_ptr<const PackageID> visit(const ExistingNoChangeDecision & decision) const
+ {
+ return decision.existing_id();
+ }
+
+ const std::tr1::shared_ptr<const PackageID> visit(const NothingNoChangeDecision &) const
+ {
+ return make_null_shared_ptr();
+ }
+
+ const std::tr1::shared_ptr<const PackageID> visit(const UnableToMakeDecision &) const
+ {
+ return make_null_shared_ptr();
+ }
+ };
+
+ struct DestinationVisitor
+ {
+ const std::tr1::shared_ptr<const Destination> visit(const ChangesToMakeDecision & decision) const
+ {
+ return decision.destination();
+ }
+
+ const std::tr1::shared_ptr<const Destination> visit(const ExistingNoChangeDecision &) const
+ {
+ return make_null_shared_ptr();
+ }
+
+ const std::tr1::shared_ptr<const Destination> visit(const NothingNoChangeDecision &) const
+ {
+ return make_null_shared_ptr();
+ }
+
+ const std::tr1::shared_ptr<const Destination> visit(const UnableToMakeDecision &) const
+ {
+ return make_null_shared_ptr();
+ }
+ };
+
void display_resolution_list(
const std::tr1::shared_ptr<Environment> & env,
const std::tr1::shared_ptr<const Resolutions> & list,
@@ -240,34 +365,35 @@ namespace
for (Resolutions::ConstIterator c(list->begin()), c_end(list->end()) ;
c != c_end ; ++c)
{
- const std::tr1::shared_ptr<const PackageID> id((*c)->decision()->if_package_id());
+ const std::tr1::shared_ptr<const PackageID> id((*c)->decision()->accept_returning<
+ std::tr1::shared_ptr<const PackageID> >(ChosenIDVisitor()));
if (! id)
{
- if ((*c)->decision()->kind() == dk_unable_to_decide)
- {
- display_one_error(env, cmdline, *c, false);
- continue;
- }
- else
- throw InternalError(PALUDIS_HERE, "why did that happen?");
+ display_one_error(env, cmdline, *c, false);
+ continue;
}
bool is_new(false), is_upgrade(false), is_downgrade(false), is_reinstall(false),
other_slots(false);
std::tr1::shared_ptr<const PackageID> old_id;
- if ((*c)->decision()->destination()->replacing()->empty())
+ const std::tr1::shared_ptr<const Destination> destination((*c)->decision()->accept_returning<
+ std::tr1::shared_ptr<const Destination> >(DestinationVisitor()));
+ if (! destination)
+ throw InternalError(PALUDIS_HERE, "huh? ! destination");
+
+ if (destination->replacing()->empty())
{
is_new = true;
const std::tr1::shared_ptr<const PackageIDSequence> others((*env)[selection::SomeArbitraryVersion(
generator::Package(id->name()) &
- generator::InRepository((*c)->decision()->destination()->repository())
+ generator::InRepository(destination->repository())
)]);
other_slots = ! others->empty();
}
else
- for (PackageIDSequence::ConstIterator x((*c)->decision()->destination()->replacing()->begin()),
- x_end((*c)->decision()->destination()->replacing()->end()) ;
+ for (PackageIDSequence::ConstIterator x(destination->replacing()->begin()),
+ x_end(destination->replacing()->end()) ;
x != x_end ; ++x)
{
old_id = *x;
@@ -320,13 +446,13 @@ namespace
cout << c::normal() << " " << id->canonical_form(idcf_version);
- cout << " to ::" << (*c)->decision()->destination()->repository();
- if (! (*c)->decision()->destination()->replacing()->empty())
+ cout << " to ::" << destination->repository();
+ if (! destination->replacing()->empty())
{
cout << " replacing";
bool first(true);
- for (PackageIDSequence::ConstIterator x((*c)->decision()->destination()->replacing()->begin()),
- x_end((*c)->decision()->destination()->replacing()->end()) ;
+ for (PackageIDSequence::ConstIterator x(destination->replacing()->begin()),
+ x_end(destination->replacing()->end()) ;
x != x_end ; ++x)
{
bool different(false);
@@ -530,12 +656,7 @@ namespace
for (Resolutions::ConstIterator c(lists.errors()->begin()), c_end(lists.errors()->end()) ;
c != c_end ; ++c)
- {
- if ((*c)->decision()->kind() != dk_unable_to_decide)
- continue;
-
display_one_error(env, cmdline, *c, true);
- }
cout << endl;
}
@@ -561,7 +682,12 @@ namespace
for (Resolutions::ConstIterator r(lists.all()->begin()), r_end(lists.all()->end()) ;
r != r_end ; ++r)
{
- if (! (*r)->decision()->if_package_id())
+ const std::tr1::shared_ptr<const PackageID> id((*r)->decision()->accept_returning<
+ std::tr1::shared_ptr<const PackageID> >(ChosenIDVisitor()));
+ const std::tr1::shared_ptr<const Destination> destination((*r)->decision()->accept_returning<
+ std::tr1::shared_ptr<const Destination> >(DestinationVisitor()));
+
+ if (! id)
{
/* decided nothing, so we can only work for cat/pkg, where
* either can be wildcards (we could work for :slot too,
@@ -591,7 +717,7 @@ namespace
}
else
{
- if (! match_package(*env, spec, *(*r)->decision()->if_package_id(), MatchPackageOptions()))
+ if (! match_package(*env, spec, *id, MatchPackageOptions()))
continue;
}
@@ -648,16 +774,19 @@ namespace
std::cout << std::endl;
}
- if ((*r)->decision()->if_package_id())
+ if (id)
{
std::cout << " The decision made was:" << std::endl;
- std::cout << " Use " << *(*r)->decision()->if_package_id() << std::endl;
- std::cout << " Install to repository " << (*r)->decision()->destination()->repository() << std::endl;
- if (! (*r)->decision()->destination()->replacing()->empty())
- for (PackageIDSequence::ConstIterator x((*r)->decision()->destination()->replacing()->begin()),
- x_end((*r)->decision()->destination()->replacing()->end()) ;
- x != x_end ; ++x)
- std::cout << " Replacing " << **x << std::endl;
+ std::cout << " Use " << *id << std::endl;
+ if (destination)
+ {
+ std::cout << " Install to repository " << destination->repository() << std::endl;
+ if (! destination->replacing()->empty())
+ for (PackageIDSequence::ConstIterator x(destination->replacing()->begin()),
+ x_end(destination->replacing()->end()) ;
+ x != x_end ; ++x)
+ std::cout << " Replacing " << **x << std::endl;
+ }
std::cout << std::endl;
}
else
diff --git a/src/clients/cave/cmd_execute_resolution.cc b/src/clients/cave/cmd_execute_resolution.cc
index c4d3949..e6ea23e 100644
--- a/src/clients/cave/cmd_execute_resolution.cc
+++ b/src/clients/cave/cmd_execute_resolution.cc
@@ -32,6 +32,7 @@
#include <paludis/util/join.hh>
#include <paludis/util/iterator_funcs.hh>
#include <paludis/util/options.hh>
+#include <paludis/util/simple_visitor_cast.hh>
#include <paludis/resolver/resolutions.hh>
#include <paludis/resolver/serialise.hh>
#include <paludis/resolver/reason.hh>
@@ -106,11 +107,10 @@ namespace
int do_pretend(
const std::tr1::shared_ptr<Environment> &,
const ExecuteResolutionCommandLine & cmdline,
- const std::tr1::shared_ptr<const Decision> & c,
+ const ChangesToMakeDecision & decision,
const int x, const int y)
{
- const std::tr1::shared_ptr<const PackageID> id(c->if_package_id());
- Context context("When pretending for '" + stringify(*id) + "':");
+ Context context("When pretending for '" + stringify(*decision.origin_id()) + "':");
if (x > 1)
std::cout << std::string(stringify(x - 1).length() + stringify(y).length() + 4, '\010');
@@ -121,7 +121,7 @@ namespace
command = "$CAVE perform";
command.append(" pretend --hooks --if-supported ");
- command.append(stringify(id->uniquely_identifying_spec()));
+ command.append(stringify(decision.origin_id()->uniquely_identifying_spec()));
command.append(" --x-of-y '" + stringify(x) + " of " + stringify(y) + "'");
paludis::Command cmd(command);
@@ -130,40 +130,40 @@ namespace
void starting_action(
const std::string & action,
- const std::tr1::shared_ptr<const Decision> & c,
+ const ChangesToMakeDecision & decision,
const int x, const int y)
{
cout << endl;
cout << c::bold_blue() << x << " of " << y << ": Starting " << action << " for "
- << *c->if_package_id() << "..." << c::normal() << endl;
+ << *decision.origin_id() << "..." << c::normal() << endl;
cout << endl;
}
void done_action(
const std::string & action,
- const std::tr1::shared_ptr<const Decision> & c,
+ const ChangesToMakeDecision & decision,
const bool success)
{
cout << endl;
if (success)
cout << c::bold_green() << "Done " << action << " for "
- << *c->if_package_id() << c::normal() << endl;
+ << *decision.origin_id() << c::normal() << endl;
else
cout << c::bold_red() << "Failed " << action << " for "
- << *c->if_package_id() << c::normal() << endl;
+ << *decision.origin_id() << c::normal() << endl;
cout << endl;
}
int do_fetch(
const std::tr1::shared_ptr<Environment> &,
const ExecuteResolutionCommandLine & cmdline,
- const std::tr1::shared_ptr<const Decision> & c,
+ const ChangesToMakeDecision & decision,
const int x, const int y)
{
- const std::tr1::shared_ptr<const PackageID> id(c->if_package_id());
+ const std::tr1::shared_ptr<const PackageID> id(decision.origin_id());
Context context("When fetching for '" + stringify(*id) + "':");
- starting_action("fetch", c, x, y);
+ starting_action("fetch", decision, x, y);
std::string command(cmdline.program_options.a_perform_program.argument());
if (command.empty())
@@ -176,20 +176,22 @@ namespace
paludis::Command cmd(command);
int retcode(run_command(cmd));
- done_action("fetch", c, 0 == retcode);
+ done_action("fetch", decision, 0 == retcode);
return retcode;
}
int do_install_slash(
const std::tr1::shared_ptr<Environment> &,
const ExecuteResolutionCommandLine & cmdline,
- const std::tr1::shared_ptr<const Resolution> & r,
+ const std::tr1::shared_ptr<const Resolution> &,
+ const ChangesToMakeDecision & decision,
+ const std::tr1::shared_ptr<const Destination> & destination,
const int x, const int y)
{
- const std::tr1::shared_ptr<const PackageID> id(r->decision()->if_package_id());
+ const std::tr1::shared_ptr<const PackageID> id(decision.origin_id());
Context context("When installing to / for '" + stringify(*id) + "':");
- starting_action("install to /", r->decision(), x, y);
+ starting_action("install to /", decision, x, y);
std::string command(cmdline.program_options.a_perform_program.argument());
if (command.empty())
@@ -197,9 +199,9 @@ namespace
command.append(" install --hooks ");
command.append(stringify(id->uniquely_identifying_spec()));
- command.append(" --destination " + stringify(r->decision()->destination()->repository()));
- for (PackageIDSequence::ConstIterator i(r->decision()->destination()->replacing()->begin()),
- i_end(r->decision()->destination()->replacing()->end()) ;
+ command.append(" --destination " + stringify(destination->repository()));
+ for (PackageIDSequence::ConstIterator i(destination->replacing()->begin()),
+ i_end(destination->replacing()->end()) ;
i != i_end ; ++i)
command.append(" --replacing " + stringify((*i)->uniquely_identifying_spec()));
@@ -235,7 +237,7 @@ namespace
paludis::Command cmd(command);
int retcode(run_command(cmd));
- done_action("install to /", r->decision(), 0 == retcode);
+ done_action("install to /", decision, 0 == retcode);
return retcode;
}
@@ -264,7 +266,13 @@ namespace
for (Resolutions::ConstIterator c(lists.ordered()->begin()), c_end(lists.ordered()->end()) ;
c != c_end ; ++c)
- retcode |= do_pretend(env, cmdline, (*c)->decision(), ++x, y);
+ {
+ const ChangesToMakeDecision * const decision(simple_visitor_cast<const ChangesToMakeDecision>(
+ *(*c)->decision()));
+ if (! decision)
+ throw InternalError(PALUDIS_HERE, "huh? not ChangesToMakeDecision");
+ retcode |= do_pretend(env, cmdline, *decision, ++x, y);
+ }
std::cout << std::endl;
@@ -288,13 +296,18 @@ namespace
{
++x;
- retcode = do_fetch(env, cmdline, (*c)->decision(), x, y);
+ const ChangesToMakeDecision * const decision(simple_visitor_cast<const ChangesToMakeDecision>(
+ *(*c)->decision()));
+ if (! decision)
+ throw InternalError(PALUDIS_HERE, "huh? not ChangesToMakeDecision");
+
+ retcode = do_fetch(env, cmdline, *decision, x, y);
if (0 != retcode)
return retcode;
if ((*c)->resolvent().destination_type() == dt_install_to_slash)
{
- retcode = do_install_slash(env, cmdline, *c, x, y);
+ retcode = do_install_slash(env, cmdline, *c, *decision, decision->destination(), x, y);
if (0 != retcode)
return retcode;
}
diff --git a/src/clients/cave/cmd_resolve.cc b/src/clients/cave/cmd_resolve.cc
index 63af523..b70afb2 100644
--- a/src/clients/cave/cmd_resolve.cc
+++ b/src/clients/cave/cmd_resolve.cc
@@ -574,11 +574,18 @@ namespace
return v.is_compiled_against_dep;
}
- bool care_about_dep_fn(const Environment * const, const ResolveCommandLine & cmdline,
- const Resolvent &, const std::tr1::shared_ptr<const Resolution> & resolution,
- const SanitisedDependency & dep)
+ struct CareAboutDepFnVisitor
{
- if (dk_existing_no_change == resolution->decision()->kind())
+ const ResolveCommandLine & cmdline;
+ const SanitisedDependency dep;
+
+ CareAboutDepFnVisitor(const ResolveCommandLine & c, const SanitisedDependency & d) :
+ cmdline(c),
+ dep(d)
+ {
+ }
+
+ bool visit(const ExistingNoChangeDecision &) const
{
if (! cmdline.resolution_options.a_follow_installed_build_dependencies.specified())
if (is_just_build_dep(dep))
@@ -592,9 +599,32 @@ namespace
/* should only return false if the dep's not already installedish */
return false;
}
+
+ return true;
}
- return true;
+ bool visit(const NothingNoChangeDecision &) const
+ {
+ return true;
+ }
+
+ bool visit(const UnableToMakeDecision &) const
+ {
+ return true;
+ }
+
+ bool visit(const ChangesToMakeDecision &) const
+ {
+ return true;
+ }
+ };
+
+ bool care_about_dep_fn(const Environment * const, const ResolveCommandLine & cmdline,
+ const Resolvent &, const std::tr1::shared_ptr<const Resolution> & resolution,
+ const SanitisedDependency & dep)
+ {
+ CareAboutDepFnVisitor v(cmdline, dep);
+ return resolution->decision()->accept_returning<bool>(v);
}
bool
@@ -614,7 +644,8 @@ namespace
find_repository_for_fn(const Environment * const env,
const ResolveCommandLine & cmdline,
const Resolvent & resolvent,
- const std::tr1::shared_ptr<const Resolution> & resolution)
+ const std::tr1::shared_ptr<const Resolution> &,
+ const ChangesToMakeDecision & decision)
{
std::tr1::shared_ptr<const Repository> result;
for (PackageDatabase::RepositoryConstIterator r(env->package_database()->begin_repositories()),
@@ -641,10 +672,10 @@ namespace
}
if ((*r)->destination_interface() &&
- (*r)->destination_interface()->is_suitable_destination_for(*resolution->decision()->if_package_id()))
+ (*r)->destination_interface()->is_suitable_destination_for(*decision.origin_id()))
{
if (result)
- throw ConfigurationError("For '" + stringify(*resolution->decision()->if_package_id())
+ throw ConfigurationError("For '" + stringify(*decision.origin_id())
+ "' with destination type " + stringify(resolvent.destination_type())
+ ", don't know whether to install to ::" + stringify(result->name())
+ " or ::" + stringify((*r)->name()));
@@ -654,7 +685,7 @@ namespace
}
if (! result)
- throw ConfigurationError("No repository suitable for '" + stringify(*resolution->decision()->if_package_id())
+ throw ConfigurationError("No repository suitable for '" + stringify(*decision.origin_id())
+ "' with destination type " + stringify(resolvent.destination_type()) + " has been configured");
return result;
}
@@ -765,6 +796,52 @@ namespace
become_command(cmd);
}
+ struct ChosenIDVisitor
+ {
+ const std::tr1::shared_ptr<const PackageID> visit(const ChangesToMakeDecision & decision) const
+ {
+ return decision.origin_id();
+ }
+
+ const std::tr1::shared_ptr<const PackageID> visit(const ExistingNoChangeDecision & decision) const
+ {
+ return decision.existing_id();
+ }
+
+ const std::tr1::shared_ptr<const PackageID> visit(const NothingNoChangeDecision &) const
+ {
+ return make_null_shared_ptr();
+ }
+
+ const std::tr1::shared_ptr<const PackageID> visit(const UnableToMakeDecision &) const
+ {
+ return make_null_shared_ptr();
+ }
+ };
+
+ struct KindNameVisitor
+ {
+ const std::string visit(const UnableToMakeDecision &) const
+ {
+ return "unable_to_make_decision";
+ }
+
+ const std::string visit(const NothingNoChangeDecision &) const
+ {
+ return "nothing_no_change";
+ }
+
+ const std::string visit(const ExistingNoChangeDecision &) const
+ {
+ return "existing_no_change";
+ }
+
+ const std::string visit(const ChangesToMakeDecision &) const
+ {
+ return "changes_to_make";
+ }
+ };
+
void display_restarts_if_requested(const std::list<SuggestRestart> & restarts,
const ResolveCommandLine & cmdline)
{
@@ -779,10 +856,12 @@ namespace
std::cout << "* " << r->resolvent() << std::endl;
std::cout << " Had decided upon ";
- if (r->previous_decision()->if_package_id())
- std::cout << *r->previous_decision()->if_package_id();
+ const std::tr1::shared_ptr<const PackageID> id(r->previous_decision()->accept_returning<
+ std::tr1::shared_ptr<const PackageID> >(ChosenIDVisitor()));
+ if (id)
+ std::cout << *id;
else
- std::cout << r->previous_decision()->kind();
+ std::cout << r->previous_decision()->accept_returning<std::string>(KindNameVisitor());
std::cout << std::endl;
std::cout << " Which did not satisfy " << r->problematic_constraint()->spec()
@@ -882,7 +961,8 @@ ResolveCommand::run(
env.get(), std::tr1::cref(cmdline), std::tr1::placeholders::_1,
std::tr1::placeholders::_2, std::tr1::placeholders::_3)),
value_for<n::find_repository_for_fn>(std::tr1::bind(&find_repository_for_fn,
- env.get(), std::tr1::cref(cmdline), std::tr1::placeholders::_1, std::tr1::placeholders::_2)),
+ env.get(), std::tr1::cref(cmdline), std::tr1::placeholders::_1, std::tr1::placeholders::_2,
+ std::tr1::placeholders::_3)),
value_for<n::get_destination_types_for_fn>(std::tr1::bind(&get_destination_types_for_fn,
env.get(), std::tr1::cref(cmdline), std::tr1::placeholders::_1, std::tr1::placeholders::_2)),
value_for<n::get_initial_constraints_for_fn>(std::tr1::bind(&initial_constraints_for_fn,
diff --git a/src/clients/cave/cmd_resolve_dump.cc b/src/clients/cave/cmd_resolve_dump.cc
index 473fd82..252300f 100644
--- a/src/clients/cave/cmd_resolve_dump.cc
+++ b/src/clients/cave/cmd_resolve_dump.cc
@@ -55,33 +55,50 @@ namespace
return s;
}
- std::ostream &
- operator<< (std::ostream & s, const Decision & d)
+ std::string stringify_if_not_null(const std::tr1::shared_ptr<const Destination> & d)
{
- std::stringstream ss;
-
- ss << "Decision(";
-
- ss << d.kind() << " ";
-
- if (d.if_package_id())
- ss << *d.if_package_id();
+ if (d)
+ {
+ std::stringstream ss;
+ ss << *d;
+ return ss.str();
+ }
else
- ss << "(nothing)";
+ return "null";
+ }
- if (d.is_best())
- ss << ", is best";
- if (d.is_same())
- ss << ", is same";
- if (d.is_same_version())
- ss << ", is same version";
+ struct DecisionStringifier
+ {
+ const std::string visit(const UnableToMakeDecision & d) const
+ {
+ return "UnableToMakeDecision(taken: " + stringify(d.taken()) + ")";
+ }
- if (d.destination())
- ss << " -> " << *d.destination();
+ const std::string visit(const NothingNoChangeDecision & d) const
+ {
+ return "NothingNoChangeDecision(taken: " + stringify(d.taken()) + ")";
+ }
- ss << ")";
+ const std::string visit(const ExistingNoChangeDecision & d) const
+ {
+ return "ExistingNoChangeDecision(" + stringify(*d.existing_id()) + " is_same: "
+ + stringify(d.is_same()) + " is_same_version: " + stringify(d.is_same_version())
+ + " is_transient: " + stringify(d.is_transient()) + " taken: " + stringify(d.taken()) + ")";
+ }
- s << ss.str();
+ const std::string visit(const ChangesToMakeDecision & d) const
+ {
+ return "ChangesToMakeDecision(" + stringify(*d.origin_id()) + " best: "
+ + stringify(d.best()) + " taken: " + stringify(d.taken())
+ + " destination: " + stringify_if_not_null(d.destination())
+ + ")";
+ }
+ };
+
+ std::ostream &
+ operator<< (std::ostream & s, const Decision & d)
+ {
+ s << d.accept_returning<std::string>(DecisionStringifier());
return s;
}