aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2009-09-25 15:43:10 +0100
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2009-09-26 15:43:15 +0100
commitad84b5e525e5728e8f3a3ccbc887e1e7bd29d1d5 (patch)
tree6af7e4bd4fd4810d17ccd515d20612bb3c1c5d89
parentdeeedf94b29f74c852142c004fe70ecadbd7b114 (diff)
downloadpaludis-ad84b5e525e5728e8f3a3ccbc887e1e7bd29d1d5.tar.gz
paludis-ad84b5e525e5728e8f3a3ccbc887e1e7bd29d1d5.tar.xz
refactor
-rw-r--r--paludis/resolver/Makefile.am11
-rw-r--r--paludis/resolver/decision-fwd.hh8
-rw-r--r--paludis/resolver/decision.cc309
-rw-r--r--paludis/resolver/decision.hh135
-rw-r--r--paludis/resolver/decision.se16
-rw-r--r--paludis/resolver/resolver.cc605
-rw-r--r--paludis/resolver/resolver.hh14
-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--src/clients/cave/cmd_display_resolution.cc137
-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
15 files changed, 1117 insertions, 438 deletions
diff --git a/paludis/resolver/Makefile.am b/paludis/resolver/Makefile.am
index 7a734d5..0d4dd59 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 \
@@ -179,12 +176,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..56bca98 100644
--- a/paludis/resolver/decision.cc
+++ b/paludis/resolver/decision.cc
@@ -22,41 +22,308 @@
#include <paludis/resolver/destination.hh>
#include <paludis/util/make_named_values.hh>
#include <paludis/util/stringify.hh>
+#include <paludis/util/private_implementation_pattern-impl.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");
+ return make_shared_ptr(new UnableToMakeDecision(
+ 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()
+{
+}
+#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
{
- 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"))
- )));
+ 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 bool taken;
+
+ Implementation(const bool t) :
+ taken(t)
+ {
+ }
+ };
+}
+
+UnableToMakeDecision::UnableToMakeDecision(const bool t) :
+ PrivateImplementationPattern<UnableToMakeDecision>(new Implementation<UnableToMakeDecision>(t))
+{
+}
+
+#ifdef PALUDIS_HAVE_DEFAULT_DELETED
+UnableToMakeDecision::~UnableToMakeDecision() = default;
+#else
+UnableToMakeDecision::~UnableToMakeDecision()
+{
+}
+#endif
+
+bool
+UnableToMakeDecision::taken() const
+{
+ return _imp->taken;
+}
+
+void
+UnableToMakeDecision::serialise(Serialiser & s) const
+{
+ s.object("UnableToMakeDecision")
+ .member(SerialiserFlags<>(), "taken", taken())
+ ;
+}
+
+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..1d17626 100644
--- a/paludis/resolver/decision.hh
+++ b/paludis/resolver/decision.hh
@@ -23,42 +23,123 @@
#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/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>
+ {
+ 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>
{
- 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:
+ UnableToMakeDecision(const bool taken);
+ ~UnableToMakeDecision();
+
+ virtual bool taken() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual void serialise(Serialiser &) const;
};
}
+
+#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..2075013 100644
--- a/paludis/resolver/resolver.cc
+++ b/paludis/resolver/resolver.cc
@@ -153,22 +153,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 +163,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 +464,158 @@ 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)
{
- bool ok;
+ const std::tr1::shared_ptr<const PackageID> chosen_id(resolution->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 (! resolution->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 (! resolution->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;
+namespace
+{
+ struct WrongDecisionVisitor
+ {
+ std::tr1::function<void ()> restart;
- case ue_if_same_version:
- ok = resolution->decision()->is_same_version();
- break;
+ WrongDecisionVisitor(const std::tr1::function<void ()> & r) :
+ restart(r)
+ {
+ }
- case ue_never:
- case last_ue:
- ok = false;
- break;
+ void visit(const NothingNoChangeDecision &) const
+ {
+ /* going from nothing to something is fine */
}
- }
- if (ok && ! constraint->untaken())
- ok = resolution->decision()->taken();
+ void visit(const UnableToMakeDecision &) const
+ {
+ restart();
+ }
+
+ void visit(const ChangesToMakeDecision &) const
+ {
+ restart();
+ }
- return ok;
+ void visit(const ExistingNoChangeDecision &) const
+ {
+ restart();
+ }
+ };
}
void
@@ -515,22 +630,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 +645,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 +672,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 +731,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 +918,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 +1066,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 +1183,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 +1401,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 +1439,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 +1509,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;
@@ -1450,16 +1562,9 @@ Resolver::_cannot_decide_for(
const 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())
- )));
+ return make_shared_ptr(new UnableToMakeDecision(
+ ! resolution->constraints()->all_untaken()
+ ));
}
const std::tr1::shared_ptr<const PackageID>
diff --git a/paludis/resolver/resolver.hh b/paludis/resolver/resolver.hh
index 2e5ed2c..bb3ff90 100644
--- a/paludis/resolver/resolver.hh
+++ b/paludis/resolver/resolver.hh
@@ -100,7 +100,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 +109,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 +122,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 +135,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> &,
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/src/clients/cave/cmd_display_resolution.cc b/src/clients/cave/cmd_display_resolution.cc
index 1c6aa8f..9ee672b 100644
--- a/src/clients/cave/cmd_display_resolution.cc
+++ b/src/clients/cave/cmd_display_resolution.cc
@@ -154,6 +154,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,7 +234,7 @@ 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;
}
}
@@ -232,6 +255,52 @@ namespace
display_reasons(resolution, verbose);
}
+ 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 +309,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 +390,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 +600,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 +626,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 +661,7 @@ namespace
}
else
{
- if (! match_package(*env, spec, *(*r)->decision()->if_package_id(), MatchPackageOptions()))
+ if (! match_package(*env, spec, *id, MatchPackageOptions()))
continue;
}
@@ -648,16 +718,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;
}