aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2009-11-10 09:05:00 +0000
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2009-11-10 00:42:19 +0000
commit0a82ab54b4b85948f1a8ad2ef4beeb3a314c7fe2 (patch)
tree206a924e0f2ec803cd106b7c07fe745a0170b777
parentdaf84e391031dda45b09b66ac19ef3bebf5a6194 (diff)
downloadpaludis-0a82ab54b4b85948f1a8ad2ef4beeb3a314c7fe2.tar.gz
paludis-0a82ab54b4b85948f1a8ad2ef4beeb3a314c7fe2.tar.xz
Refactor
-rw-r--r--paludis/resolver/Makefile.am4
-rw-r--r--paludis/resolver/decider-fwd.hh31
-rw-r--r--paludis/resolver/decider.cc1402
-rw-r--r--paludis/resolver/decider.hh195
-rw-r--r--paludis/resolver/orderer-fwd.hh31
-rw-r--r--paludis/resolver/orderer.cc441
-rw-r--r--paludis/resolver/orderer.hh80
-rw-r--r--paludis/resolver/resolutions-fwd.hh1
-rw-r--r--paludis/resolver/resolutions.cc27
-rw-r--r--paludis/resolver/resolutions.hh16
-rw-r--r--paludis/resolver/resolver-fwd.hh1
-rw-r--r--paludis/resolver/resolver.cc1729
-rw-r--r--paludis/resolver/resolver.hh189
-rw-r--r--paludis/resolver/resolver_TEST_blockers.cc2
-rw-r--r--paludis/resolver/resolver_TEST_serialisation.cc8
-rw-r--r--paludis/resolver/resolver_TEST_suggestions.cc6
-rw-r--r--paludis/resolver/resolver_TEST_virtuals.cc4
-rw-r--r--paludis/resolver/resolver_functions.hh5
-rw-r--r--paludis/resolver/resolver_test.cc9
-rw-r--r--paludis/resolver/resolver_test.hh5
-rw-r--r--paludis/resolver/sanitised_dependencies.cc39
-rw-r--r--paludis/resolver/sanitised_dependencies.hh6
-rw-r--r--src/clients/cave/cmd_display_resolution.cc12
-rw-r--r--src/clients/cave/cmd_execute_resolution.cc6
-rw-r--r--src/clients/cave/cmd_resolve.cc12
-rw-r--r--src/clients/cave/cmd_resolve_dump.cc9
26 files changed, 2324 insertions, 1946 deletions
diff --git a/paludis/resolver/Makefile.am b/paludis/resolver/Makefile.am
index e00e40f..575d687 100644
--- a/paludis/resolver/Makefile.am
+++ b/paludis/resolver/Makefile.am
@@ -15,9 +15,11 @@ BUILT_SOURCES = \
noinst_HEADERS = \
arrow.hh arrow-fwd.hh \
constraint.hh constraint-fwd.hh \
+ decider.hh decider-fwd.hh \
decision.hh decision-fwd.hh \
destination.hh destination-fwd.hh \
destination_types.hh destination_types-fwd.hh destination_types-se.hh \
+ orderer.hh orderer-fwd.hh \
reason.hh reason-fwd.hh \
resolution.hh resolution-fwd.hh \
resolutions.hh resolutions-fwd.hh \
@@ -33,9 +35,11 @@ noinst_HEADERS = \
libpaludisresolver_a_SOURCES = \
arrow.cc \
constraint.cc \
+ decider.cc \
decision.cc \
destination.cc \
destination_types.cc \
+ orderer.cc \
reason.cc \
resolution.cc \
resolutions.cc \
diff --git a/paludis/resolver/decider-fwd.hh b/paludis/resolver/decider-fwd.hh
new file mode 100644
index 0000000..3a4fbfd
--- /dev/null
+++ b/paludis/resolver/decider-fwd.hh
@@ -0,0 +1,31 @@
+/* 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_DECIDER_FWD_HH
+#define PALUDIS_GUARD_PALUDIS_RESOLVER_DECIDER_FWD_HH 1
+
+namespace paludis
+{
+ namespace resolver
+ {
+ struct Decider;
+ }
+}
+
+#endif
diff --git a/paludis/resolver/decider.cc b/paludis/resolver/decider.cc
new file mode 100644
index 0000000..2f02dc1
--- /dev/null
+++ b/paludis/resolver/decider.cc
@@ -0,0 +1,1402 @@
+/* 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/decider.hh>
+#include <paludis/resolver/resolver_functions.hh>
+#include <paludis/resolver/spec_rewriter.hh>
+#include <paludis/resolver/resolvent.hh>
+#include <paludis/resolver/resolution.hh>
+#include <paludis/resolver/constraint.hh>
+#include <paludis/resolver/decision.hh>
+#include <paludis/resolver/destination.hh>
+#include <paludis/resolver/resolutions.hh>
+#include <paludis/resolver/suggest_restart.hh>
+#include <paludis/resolver/reason.hh>
+#include <paludis/resolver/unsuitable_candidates.hh>
+#include <paludis/resolver/resolver.hh>
+#include <paludis/util/exception.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/make_named_values.hh>
+#include <paludis/util/make_shared_ptr.hh>
+#include <paludis/util/wrapped_forward_iterator.hh>
+#include <paludis/util/enum_iterator.hh>
+#include <paludis/environment.hh>
+#include <paludis/notifier_callback.hh>
+#include <paludis/repository.hh>
+#include <paludis/filtered_generator.hh>
+#include <paludis/package_database.hh>
+#include <paludis/metadata_key.hh>
+#include <paludis/generator.hh>
+#include <paludis/selection.hh>
+#include <paludis/filter.hh>
+#include <paludis/match_package.hh>
+#include <paludis/version_requirements.hh>
+#include <paludis/slot_requirement.hh>
+#include <paludis/choice.hh>
+#include <map>
+#include <set>
+
+using namespace paludis;
+using namespace paludis::resolver;
+
+typedef std::map<Resolvent, std::tr1::shared_ptr<Resolution> > ResolutionsByResolventMap;
+
+namespace paludis
+{
+ template <>
+ struct Implementation<Decider>
+ {
+ const Environment * const env;
+ const ResolverFunctions fns;
+ SpecRewriter rewriter;
+
+ ResolutionsByResolventMap resolutions_by_resolvent;
+
+ const std::tr1::shared_ptr<Resolutions> all_resolutions;
+ const std::tr1::shared_ptr<Resolutions> untaken_resolutions;
+ const std::tr1::shared_ptr<Resolutions> error_resolutions;
+ const std::tr1::shared_ptr<Resolutions> unordered_resolutions;
+
+ Implementation(const Environment * const e, const ResolverFunctions & f,
+ const ResolverLists & l) :
+ env(e),
+ fns(f),
+ rewriter(env),
+ all_resolutions(l.all()),
+ untaken_resolutions(l.untaken()),
+ error_resolutions(l.errors()),
+ unordered_resolutions(new Resolutions)
+ {
+ }
+ };
+}
+
+Decider::Decider(const Environment * const e, const ResolverFunctions & f, const ResolverLists & l) :
+ PrivateImplementationPattern<Decider>(new Implementation<Decider>(e, f, l))
+{
+}
+
+Decider::~Decider()
+{
+}
+
+void
+Decider::_resolve_decide_with_dependencies()
+{
+ Context context("When resolving and adding dependencies recursively:");
+
+ enum State { deciding_non_suggestions, deciding_suggestions, finished } state = deciding_non_suggestions;
+ bool changed(true);
+ while (true)
+ {
+ if (! changed)
+ state = State(state + 1);
+ if (state == finished)
+ break;
+
+ changed = false;
+ for (ResolutionsByResolventMap::iterator i(_imp->resolutions_by_resolvent.begin()),
+ i_end(_imp->resolutions_by_resolvent.end()) ;
+ i != i_end ; ++i)
+ {
+ /* we've already decided */
+ if (i->second->decision())
+ continue;
+
+ /* we're only being suggested. don't do this on the first pass, so
+ * we don't have to do restarts for suggestions later becoming hard
+ * deps. */
+ if (state == deciding_non_suggestions && i->second->constraints()->all_untaken())
+ continue;
+
+ _imp->env->trigger_notifier_callback(NotifierCallbackResolverStepEvent());
+
+ changed = true;
+ _decide(i->first, i->second);
+
+ _add_dependencies_if_necessary(i->first, i->second);
+ }
+ }
+}
+
+void
+Decider::_resolve_destinations()
+{
+ Context context("When resolving destinations:");
+
+ 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
+ {
+ typedef std::tr1::function<const std::tr1::shared_ptr<const Destination> (
+ const ChangesToMakeDecision &)> MakeDestinationFunc;
+
+ 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
+Decider::_do_destination_if_necessary(
+ const Resolvent & resolvent,
+ const std::tr1::shared_ptr<Resolution> & resolution)
+{
+ DoDestinationIfNecessaryVisitor v(std::tr1::bind(&Decider::_make_destination_for,
+ this, resolvent, resolution, std::tr1::placeholders::_1));
+ resolution->decision()->accept(v);
+}
+
+const std::tr1::shared_ptr<Destination>
+Decider::_make_destination_for(
+ const Resolvent & resolvent,
+ const std::tr1::shared_ptr<const Resolution> & resolution,
+ const ChangesToMakeDecision & decision) const
+{
+ 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>
+Decider::_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, decision);
+}
+
+FilteredGenerator
+Decider::_make_destination_filtered_generator(const Generator & g, const Resolvent & resolvent) const
+{
+ return _imp->fns.make_destination_filtered_generator_fn()(g, resolvent);
+}
+
+const std::tr1::shared_ptr<const PackageIDSequence>
+Decider::_find_replacing(
+ const std::tr1::shared_ptr<const PackageID> & id,
+ const std::tr1::shared_ptr<const Repository> & repo) const
+{
+ Context context("When working out what is replaced by '" + stringify(*id) +
+ "' when it is installed to '" + stringify(repo->name()) + "':");
+
+ std::set<RepositoryName, RepositoryNameComparator> repos;
+
+ if (repo->installed_root_key())
+ {
+ for (PackageDatabase::RepositoryConstIterator r(_imp->env->package_database()->begin_repositories()),
+ r_end(_imp->env->package_database()->end_repositories()) ;
+ r != r_end ; ++r)
+ if ((*r)->installed_root_key() &&
+ (*r)->installed_root_key()->value() == repo->installed_root_key()->value())
+ repos.insert((*r)->name());
+ }
+ else
+ repos.insert(repo->name());
+
+ std::tr1::shared_ptr<PackageIDSequence> result(new PackageIDSequence);
+ for (std::set<RepositoryName, RepositoryNameComparator>::const_iterator r(repos.begin()),
+ r_end(repos.end()) ;
+ r != r_end ; ++r)
+ {
+ std::tr1::shared_ptr<const PackageIDSequence> ids((*_imp->env)[selection::AllVersionsUnsorted(
+ generator::Package(id->name()) & generator::InRepository(*r))]);
+ for (PackageIDSequence::ConstIterator i(ids->begin()), i_end(ids->end()) ;
+ i != i_end ; ++i)
+ {
+ if ((*i)->version() == id->version() || _same_slot(*i, id))
+ result->push_back(*i);
+ }
+ }
+
+ return result;
+}
+
+bool
+Decider::_same_slot(const std::tr1::shared_ptr<const PackageID> & a,
+ const std::tr1::shared_ptr<const PackageID> & b) const
+{
+ if (a->slot_key())
+ return b->slot_key() && a->slot_key()->value() == b->slot_key()->value();
+ else
+ return ! b->slot_key();
+}
+
+const std::tr1::shared_ptr<Resolution>
+Decider::_create_resolution_for_resolvent(const Resolvent & r) const
+{
+ return make_shared_ptr(new Resolution(make_named_values<Resolution>(
+ value_for<n::already_ordered>(false),
+ value_for<n::arrows>(make_shared_ptr(new ArrowSequence)),
+ value_for<n::constraints>(_initial_constraints_for(r)),
+ value_for<n::decision>(make_null_shared_ptr()),
+ value_for<n::resolvent>(r)
+ )));
+}
+
+const std::tr1::shared_ptr<Resolution>
+Decider::_resolution_for_resolvent(const Resolvent & r, const bool create)
+{
+ ResolutionsByResolventMap::iterator i(_imp->resolutions_by_resolvent.find(r));
+ if (_imp->resolutions_by_resolvent.end() == i)
+ {
+ if (create)
+ {
+ std::tr1::shared_ptr<Resolution> resolution(_create_resolution_for_resolvent(r));
+ i = _imp->resolutions_by_resolvent.insert(std::make_pair(r, resolution)).first;
+ _imp->all_resolutions->append(resolution);
+ }
+ else
+ throw InternalError(PALUDIS_HERE, "resolver bug: expected resolution for "
+ + stringify(r) + " to exist, but it doesn't");
+ }
+
+ return i->second;
+}
+
+const std::tr1::shared_ptr<Resolution>
+Decider::resolution_for_resolvent(const Resolvent & r) const
+{
+ ResolutionsByResolventMap::const_iterator i(_imp->resolutions_by_resolvent.find(r));
+ if (_imp->resolutions_by_resolvent.end() == i)
+ throw InternalError(PALUDIS_HERE, "resolver bug: expected resolution for "
+ + stringify(r) + " to exist, but it doesn't");
+
+ return i->second;
+}
+
+const std::tr1::shared_ptr<ConstraintSequence>
+Decider::_make_constraints_from_target(
+ const Resolvent & resolvent,
+ const PackageDepSpec & spec,
+ const std::tr1::shared_ptr<const Reason> & reason) const
+{
+ const std::tr1::shared_ptr<ConstraintSequence> result(new ConstraintSequence);
+ result->push_back(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>(spec),
+ value_for<n::untaken>(false),
+ value_for<n::use_existing>(_imp->fns.get_use_existing_fn()(resolvent, spec, reason))
+ ))));
+ return result;
+}
+
+const std::tr1::shared_ptr<ConstraintSequence>
+Decider::_make_constraints_from_dependency(const Resolvent & resolvent, const SanitisedDependency & dep,
+ const std::tr1::shared_ptr<const Reason> & reason) const
+{
+ const std::tr1::shared_ptr<ConstraintSequence> result(new ConstraintSequence);
+ if (dep.spec().if_package())
+ {
+ result->push_back(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>(*dep.spec().if_package()),
+ value_for<n::untaken>(! _imp->fns.take_dependency_fn()(
+ resolvent, dep, reason)),
+ value_for<n::use_existing>(_imp->fns.get_use_existing_fn()(
+ resolvent, *dep.spec().if_package(), reason))
+ ))));
+ }
+ else if (dep.spec().if_block())
+ {
+ /* nothing is fine too if there's nothing installed matching the block. */
+ const std::tr1::shared_ptr<const PackageIDSequence> ids((*_imp->env)[selection::SomeArbitraryVersion(
+ generator::Matches(dep.spec().if_block()->blocking(), MatchPackageOptions()) |
+ filter::InstalledAtRoot(FSEntry("/")))]);
+
+ DestinationTypes destination_types(_get_destination_types_for_blocker(*dep.spec().if_block()));
+ for (EnumIterator<DestinationType> t, t_end(last_dt) ; t != t_end ; ++t)
+ if (destination_types[*t])
+ result->push_back(make_shared_ptr(new Constraint(make_named_values<Constraint>(
+ value_for<n::destination_type>(*t),
+ value_for<n::nothing_is_fine_too>(ids->empty()),
+ value_for<n::reason>(reason),
+ value_for<n::spec>(dep.spec()),
+ value_for<n::untaken>(false),
+ value_for<n::use_existing>(ue_if_possible)
+ ))));
+ }
+ else
+ throw InternalError(PALUDIS_HERE, "resolver bug: huh? it's not a block and it's not a package");
+
+ return result;
+}
+
+void
+Decider::_apply_resolution_constraint(
+ const Resolvent & resolvent,
+ const std::tr1::shared_ptr<Resolution> & resolution,
+ const std::tr1::shared_ptr<const Constraint> & constraint)
+{
+ if (resolution->decision())
+ if (! _verify_new_constraint(resolvent, resolution, constraint))
+ _made_wrong_decision(resolvent, 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
+Decider::_check_constraint(const Resolvent &,
+ const std::tr1::shared_ptr<const Constraint> & constraint,
+ const std::tr1::shared_ptr<const Decision> & decision) const
+{
+ const std::tr1::shared_ptr<const PackageID> chosen_id(decision->accept_returning<
+ std::tr1::shared_ptr<const PackageID> >(ChosenIDVisitor()));
+
+ if (chosen_id)
+ {
+ if (constraint->spec().if_package())
+ {
+ if (! match_package(*_imp->env, *constraint->spec().if_package(), *chosen_id, MatchPackageOptions()))
+ return false;
+ }
+ else
+ {
+ if (match_package(*_imp->env, constraint->spec().if_block()->blocking(),
+ *chosen_id, MatchPackageOptions()))
+ return false;
+ }
+ }
+ else
+ {
+ if (! constraint->nothing_is_fine_too())
+ return false;
+ }
+
+ if (! decision->accept_returning<bool>(CheckUseExistingVisitor(constraint)))
+ return false;
+
+ if (! constraint->untaken())
+ {
+ if (! decision->taken())
+ return false;
+ }
+
+ return true;
+}
+
+bool
+Decider::_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());
+}
+
+namespace
+{
+ struct WrongDecisionVisitor
+ {
+ std::tr1::function<void ()> restart;
+
+ WrongDecisionVisitor(const std::tr1::function<void ()> & r) :
+ restart(r)
+ {
+ }
+
+ void visit(const NothingNoChangeDecision &) const
+ {
+ /* going from nothing to something is fine */
+ }
+
+ void visit(const UnableToMakeDecision &) const
+ {
+ restart();
+ }
+
+ void visit(const ChangesToMakeDecision &) const
+ {
+ restart();
+ }
+
+ void visit(const ExistingNoChangeDecision &) const
+ {
+ restart();
+ }
+ };
+}
+
+void
+Decider::_made_wrong_decision(const Resolvent & resolvent,
+ const std::tr1::shared_ptr<Resolution> & resolution,
+ const std::tr1::shared_ptr<const Constraint> & constraint)
+{
+ /* can we find a resolution that works for all our constraints? */
+ std::tr1::shared_ptr<Resolution> adapted_resolution(make_shared_ptr(new Resolution(*resolution)));
+ adapted_resolution->constraints()->add(constraint);
+
+ const std::tr1::shared_ptr<Decision> decision(_try_to_find_decision_for(resolvent, adapted_resolution));
+ if (decision)
+ {
+ resolution->decision()->accept(WrongDecisionVisitor(std::tr1::bind(
+ &Decider::_suggest_restart_with, this, resolvent, resolution, constraint, decision)));
+ resolution->decision() = decision;
+ }
+ else
+ resolution->decision() = _cannot_decide_for(resolvent, adapted_resolution);
+}
+
+void
+Decider::_suggest_restart_with(const Resolvent & resolvent,
+ const std::tr1::shared_ptr<const Resolution> & resolution,
+ const std::tr1::shared_ptr<const Constraint> & constraint,
+ const std::tr1::shared_ptr<const Decision> & decision) const
+{
+ throw SuggestRestart(resolvent, resolution->decision(), constraint, decision,
+ _make_constraint_for_preloading(resolvent, decision, constraint));
+}
+
+const std::tr1::shared_ptr<const Constraint>
+Decider::_make_constraint_for_preloading(
+ const Resolvent &,
+ const std::tr1::shared_ptr<const Decision> &,
+ const std::tr1::shared_ptr<const Constraint> & c) const
+{
+ const std::tr1::shared_ptr<Constraint> result(new Constraint(*c));
+
+ const std::tr1::shared_ptr<PresetReason> reason(new PresetReason);
+ result->reason() = reason;
+
+ if (result->spec().if_package())
+ {
+ PackageDepSpec s(_make_spec_for_preloading(*result->spec().if_package()));
+ result->spec().if_package() = make_shared_ptr(new PackageDepSpec(s));
+ }
+ else
+ {
+ PackageDepSpec s(_make_spec_for_preloading(result->spec().if_block()->blocking()));
+ result->spec().if_block() = make_shared_ptr(new BlockDepSpec(
+ "!" + stringify(s),
+ s,
+ result->spec().if_block()->strong()));
+ }
+
+ return result;
+}
+
+const PackageDepSpec
+Decider::_make_spec_for_preloading(const PackageDepSpec & spec) const
+{
+ PartiallyMadePackageDepSpec result(spec);
+
+ /* we don't want to copy use deps from the constraint, since things like
+ * [foo?] start to get weird when there's no longer an associated ID. */
+ result.clear_additional_requirements();
+
+ return result;
+}
+
+void
+Decider::_decide(const Resolvent & resolvent, const std::tr1::shared_ptr<Resolution> & resolution)
+{
+ Context context("When deciding upon an origin ID to use for '" + stringify(resolvent) + "':");
+
+ std::tr1::shared_ptr<Decision> decision(_try_to_find_decision_for(resolvent, resolution));
+ if (decision)
+ resolution->decision() = decision;
+ else
+ 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
+Decider::_add_dependencies_if_necessary(
+ const Resolvent & our_resolvent,
+ const std::tr1::shared_ptr<Resolution> & our_resolution)
+{
+ 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(*package_id) + "':");
+
+ const std::tr1::shared_ptr<SanitisedDependencies> deps(new SanitisedDependencies);
+ deps->populate(*this, our_resolvent, package_id);
+
+ for (SanitisedDependencies::ConstIterator s(deps->begin()), s_end(deps->end()) ;
+ s != s_end ; ++s)
+ {
+ Context context_2("When handling dependency '" + stringify(s->spec()) + "':");
+
+ if (! _care_about_dependency_spec(our_resolvent, our_resolution, *s))
+ continue;
+
+ const std::tr1::shared_ptr<DependencyReason> reason(new DependencyReason(
+ package_id, our_resolvent, *s));
+
+ std::tr1::shared_ptr<const Resolvents> resolvents;
+
+ if (s->spec().if_package())
+ resolvents = _get_resolvents_for(*s->spec().if_package(), reason);
+ else
+ resolvents = _get_resolvents_for_blocker(*s->spec().if_block());
+
+ if (resolvents->empty())
+ {
+ if (s->spec().if_package())
+ resolvents = _get_error_resolvents_for(*s->spec().if_package(), reason);
+ else
+ {
+ /* blocking on something that doesn't exist is fine */
+ }
+ }
+
+ for (Resolvents::ConstIterator r(resolvents->begin()), r_end(resolvents->end()) ;
+ r != r_end ; ++r)
+ {
+ const std::tr1::shared_ptr<Resolution> dep_resolution(_resolution_for_resolvent(*r, true));
+ const std::tr1::shared_ptr<ConstraintSequence> constraints(_make_constraints_from_dependency(our_resolvent, *s, reason));
+
+ for (ConstraintSequence::ConstIterator c(constraints->begin()), c_end(constraints->end()) ;
+ c != c_end ; ++c)
+ _apply_resolution_constraint(*r, dep_resolution, *c);
+ }
+ }
+}
+
+bool
+Decider::_care_about_dependency_spec(const Resolvent & resolvent,
+ const std::tr1::shared_ptr<const Resolution> & resolution, const SanitisedDependency & dep) const
+{
+ return _imp->fns.care_about_dep_fn()(resolvent, resolution, dep);
+}
+
+const std::tr1::shared_ptr<Constraints>
+Decider::_initial_constraints_for(const Resolvent & r) const
+{
+ return _imp->fns.get_initial_constraints_for_fn()(r);
+}
+
+int
+Decider::find_any_score(const Resolvent & our_resolvent, const SanitisedDependency & dep) const
+{
+ Context context("When working out whether we'd like '" + stringify(dep.spec()) + "' because of '"
+ + stringify(our_resolvent) + "':");
+
+ if (dep.spec().if_block())
+ throw InternalError(PALUDIS_HERE, "unimplemented: blockers inside || blocks are horrid");
+
+ const PackageDepSpec & spec(*dep.spec().if_package());
+
+ int operator_bias(0);
+ if (spec.version_requirements_ptr() && ! spec.version_requirements_ptr()->empty())
+ {
+ int score(-1);
+ for (VersionRequirements::ConstIterator v(spec.version_requirements_ptr()->begin()),
+ v_end(spec.version_requirements_ptr()->end()) ;
+ v != v_end ; ++v)
+ {
+ int local_score(0);
+
+ switch (v->version_operator().value())
+ {
+ case vo_greater:
+ case vo_greater_equal:
+ local_score = 9;
+ break;
+
+ case vo_equal:
+ case vo_tilde:
+ case vo_nice_equal_star:
+ case vo_stupid_equal_star:
+ case vo_tilde_greater:
+ local_score = 2;
+ break;
+
+ case vo_less_equal:
+ case vo_less:
+ local_score = 1;
+ break;
+
+ case last_vo:
+ local_score = 1;
+ break;
+ }
+
+ if (score == -1)
+ score = local_score;
+ else
+ switch (spec.version_requirements_mode())
+ {
+ case vr_and:
+ score = std::min(score, local_score);
+ break;
+
+ case vr_or:
+ score = std::max(score, local_score);
+ break;
+
+ case last_vr:
+ break;
+ }
+ }
+ operator_bias = score;
+ }
+ else
+ {
+ /* don't bias no operator over a >= operator, so || ( >=foo-2 bar )
+ * still likes foo. */
+ operator_bias = 9;
+ }
+
+ /* best: already installed */
+ {
+ const std::tr1::shared_ptr<const PackageIDSequence> installed_ids((*_imp->env)[selection::BestVersionOnly(
+ generator::Matches(spec, MatchPackageOptions()) |
+ filter::InstalledAtRoot(FSEntry("/")))]);
+ if (! installed_ids->empty())
+ return 50 + operator_bias;
+ }
+
+ /* next: already installed, except with the wrong options */
+ if (spec.additional_requirements_ptr())
+ {
+ const std::tr1::shared_ptr<const PackageIDSequence> installed_ids((*_imp->env)[selection::BestVersionOnly(
+ generator::Matches(spec, MatchPackageOptions() + mpo_ignore_additional_requirements) |
+ filter::InstalledAtRoot(FSEntry("/")))]);
+ if (! installed_ids->empty())
+ return 40 + operator_bias;
+ }
+
+ 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 */
+ {
+ for (Resolvents::ConstIterator r(resolvents->begin()), r_end(resolvents->end()) ;
+ r != r_end ; ++r)
+ {
+ ResolutionsByResolventMap::const_iterator i(_imp->resolutions_by_resolvent.find(*r));
+ if (i != _imp->resolutions_by_resolvent.end())
+ return 30 + operator_bias;
+ }
+ }
+
+ /* next: could install */
+ {
+ for (Resolvents::ConstIterator r(resolvents->begin()), r_end(resolvents->end()) ;
+ r != r_end ; ++r)
+ {
+ const std::tr1::shared_ptr<Resolution> resolution(_create_resolution_for_resolvent(*r));
+ const std::tr1::shared_ptr<ConstraintSequence> constraints(_make_constraints_from_dependency(our_resolvent, dep, reason));
+ for (ConstraintSequence::ConstIterator c(constraints->begin()), c_end(constraints->end()) ;
+ c != c_end ; ++c)
+ resolution->constraints()->add(*c);
+ const std::tr1::shared_ptr<Decision> decision(_try_to_find_decision_for(*r, resolution));
+ if (decision)
+ return 20 + operator_bias;
+ }
+ }
+
+ /* next: exists */
+ {
+ const std::tr1::shared_ptr<const PackageIDSequence> ids((*_imp->env)[selection::BestVersionOnly(
+ generator::Matches(spec, MatchPackageOptions() + mpo_ignore_additional_requirements)
+ )]);
+ if (! ids->empty())
+ return 10 + operator_bias;
+ }
+
+ /* yay, people are depping upon packages that don't exist again. I SMELL A LESSPIPE. */
+ return 0;
+}
+
+namespace
+{
+ struct SlotNameFinder
+ {
+ std::tr1::shared_ptr<SlotName> visit(const SlotExactRequirement & s)
+ {
+ return make_shared_ptr(new SlotName(s.slot()));
+ }
+
+ std::tr1::shared_ptr<SlotName> visit(const SlotAnyUnlockedRequirement &)
+ {
+ return make_null_shared_ptr();
+ }
+
+ std::tr1::shared_ptr<SlotName> visit(const SlotAnyLockedRequirement &)
+ {
+ return make_null_shared_ptr();
+ }
+ };
+}
+
+const std::tr1::shared_ptr<const Resolvents>
+Decider::_get_resolvents_for_blocker(const BlockDepSpec & spec) const
+{
+ Context context("When finding slots for '" + stringify(spec) + "':");
+
+ std::tr1::shared_ptr<SlotName> exact_slot;
+ if (spec.blocking().slot_requirement_ptr())
+ {
+ SlotNameFinder f;
+ exact_slot = spec.blocking().slot_requirement_ptr()->accept_returning<std::tr1::shared_ptr<SlotName> >(f);
+ }
+
+ DestinationTypes destination_types(_get_destination_types_for_blocker(spec));
+ std::tr1::shared_ptr<Resolvents> result(new Resolvents);
+ if (exact_slot)
+ {
+ for (EnumIterator<DestinationType> t, t_end(last_dt) ; t != t_end ; ++t)
+ if (destination_types[*t])
+ result->push_back(Resolvent(spec.blocking(), *exact_slot, *t));
+ }
+ else
+ {
+ const std::tr1::shared_ptr<const PackageIDSequence> ids((*_imp->env)[selection::BestVersionInEachSlot(
+ generator::Package(*spec.blocking().package_ptr())
+ )]);
+ for (PackageIDSequence::ConstIterator i(ids->begin()), i_end(ids->end()) ;
+ i != i_end ; ++i)
+ for (EnumIterator<DestinationType> t, t_end(last_dt) ; t != t_end ; ++t)
+ if (destination_types[*t])
+ result->push_back(Resolvent(*i, *t));
+ }
+
+ return result;
+}
+
+const DestinationTypes
+Decider::_get_destination_types_for_blocker(const BlockDepSpec &) const
+{
+ return DestinationTypes() + dt_install_to_slash;
+}
+
+const std::tr1::shared_ptr<const Resolvents>
+Decider::_get_resolvents_for(
+ const PackageDepSpec & spec,
+ const std::tr1::shared_ptr<const Reason> & reason) const
+{
+ Context context("When finding slots for '" + stringify(spec) + "':");
+
+ std::tr1::shared_ptr<SlotName> exact_slot;
+
+ if (spec.slot_requirement_ptr())
+ {
+ SlotNameFinder f;
+ exact_slot = spec.slot_requirement_ptr()->accept_returning<std::tr1::shared_ptr<SlotName> >(f);
+ }
+
+ return _imp->fns.get_resolvents_for_fn()(spec, exact_slot, reason);
+}
+
+const DestinationTypes
+Decider::_get_destination_types_for(
+ const PackageDepSpec & spec,
+ const std::tr1::shared_ptr<const PackageID> & id,
+ const std::tr1::shared_ptr<const Reason> & reason) const
+{
+ return _imp->fns.get_destination_types_for_fn()(spec, id, reason);
+}
+
+const std::tr1::shared_ptr<const Resolvents>
+Decider::_get_error_resolvents_for(
+ const PackageDepSpec & spec,
+ const std::tr1::shared_ptr<const Reason> & reason) const
+{
+ Context context("When finding slots for '" + stringify(spec) + "', which can't be found the normal way:");
+
+ std::tr1::shared_ptr<Resolvents> result(new Resolvents);
+ DestinationTypes destination_types(_get_destination_types_for(spec, make_null_shared_ptr(), reason));
+ for (EnumIterator<DestinationType> t, t_end(last_dt) ; t != t_end ; ++t)
+ if (destination_types[*t])
+ result->push_back(Resolvent(spec, true, *t));
+ return result;
+}
+
+const std::tr1::shared_ptr<Decision>
+Decider::_try_to_find_decision_for(
+ const Resolvent & resolvent,
+ const std::tr1::shared_ptr<const Resolution> & resolution) const
+{
+ const std::tr1::shared_ptr<const PackageID> existing_id(_find_existing_id_for(resolvent, resolution));
+ std::pair<const std::tr1::shared_ptr<const PackageID>, bool> installable_id_best(_find_installable_id_for(resolvent, resolution));
+ const std::tr1::shared_ptr<const PackageID> installable_id(installable_id_best.first);
+ bool best(installable_id_best.second);
+
+ if (resolution->constraints()->nothing_is_fine_too() && ! existing_id)
+ {
+ /* nothing existing, but nothing's ok */
+ 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 ChangesToMakeDecision(
+ installable_id,
+ best,
+ ! resolution->constraints()->all_untaken(),
+ make_null_shared_ptr()
+ ));
+ }
+ else if (existing_id && ! installable_id)
+ {
+ /* there's nothing installable. this may or may not be ok. */
+ bool is_transient(existing_id->transient_key() && existing_id->transient_key()->value());
+
+ switch (resolution->constraints()->strictest_use_existing())
+ {
+ case ue_if_possible:
+ break;
+
+ case ue_only_if_transient:
+ case ue_if_same:
+ case ue_if_same_version:
+ if (! is_transient)
+ return make_null_shared_ptr();
+ break;
+
+ case ue_never:
+ return make_null_shared_ptr();
+
+ case last_ue:
+ break;
+ }
+
+ return make_shared_ptr(new ExistingNoChangeDecision(
+ existing_id,
+ true,
+ true,
+ is_transient,
+ ! resolution->constraints()->all_untaken()
+ ));
+ }
+ else if ((! existing_id) && (! installable_id))
+ {
+ return make_null_shared_ptr();
+ }
+ else if (existing_id && installable_id)
+ {
+ bool is_same_version(existing_id->version() == installable_id->version());
+ bool is_same(false);
+
+ if (is_same_version)
+ {
+ is_same = true;
+
+ std::set<ChoiceNameWithPrefix> common;
+ if (existing_id->choices_key() && installable_id->choices_key())
+ {
+ std::set<ChoiceNameWithPrefix> i_common, u_common;
+ for (Choices::ConstIterator k(installable_id->choices_key()->value()->begin()),
+ k_end(installable_id->choices_key()->value()->end()) ;
+ k != k_end ; ++k)
+ {
+ if (! (*k)->consider_added_or_changed())
+ continue;
+
+ for (Choice::ConstIterator i((*k)->begin()), i_end((*k)->end()) ;
+ i != i_end ; ++i)
+ if ((*i)->explicitly_listed())
+ i_common.insert((*i)->name_with_prefix());
+ }
+
+ for (Choices::ConstIterator k(existing_id->choices_key()->value()->begin()),
+ k_end(existing_id->choices_key()->value()->end()) ;
+ k != k_end ; ++k)
+ {
+ if (! (*k)->consider_added_or_changed())
+ continue;
+
+ for (Choice::ConstIterator i((*k)->begin()), i_end((*k)->end()) ;
+ i != i_end ; ++i)
+ if ((*i)->explicitly_listed())
+ u_common.insert((*i)->name_with_prefix());
+ }
+
+ std::set_intersection(
+ i_common.begin(), i_common.end(),
+ u_common.begin(), u_common.end(),
+ std::inserter(common, common.begin()));
+ }
+
+ for (std::set<ChoiceNameWithPrefix>::const_iterator f(common.begin()), f_end(common.end()) ;
+ f != f_end ; ++f)
+ if (installable_id->choices_key()->value()->find_by_name_with_prefix(*f)->enabled() !=
+ existing_id->choices_key()->value()->find_by_name_with_prefix(*f)->enabled())
+ {
+ is_same = false;
+ break;
+ }
+ }
+
+ 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 ChangesToMakeDecision(
+ installable_id,
+ best,
+ ! resolution->constraints()->all_untaken(),
+ make_null_shared_ptr()
+ ));
+
+ case ue_if_same:
+ if (is_same)
+ return existing;
+ else
+ return changes_to_make;
+
+ case ue_if_same_version:
+ if (is_same_version)
+ return existing;
+ else
+ return changes_to_make;
+
+ case ue_if_possible:
+ return existing;
+
+ case last_ue:
+ break;
+ }
+ }
+
+ throw InternalError(PALUDIS_HERE, "resolver bug: shouldn't be reached");
+}
+
+const std::tr1::shared_ptr<Decision>
+Decider::_cannot_decide_for(
+ const Resolvent & resolvent,
+ const std::tr1::shared_ptr<const Resolution> & resolution) const
+{
+ 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
+Decider::_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>
+Decider::_find_existing_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(
+ _make_destination_filtered_generator(generator::Package(resolvent.package()), resolvent) |
+ make_slot_filter(resolvent)
+ )]);
+
+ return _find_id_for_from(resolvent, resolution, ids).first;
+}
+
+const std::tr1::shared_ptr<const PackageIDSequence>
+Decider::_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>
+Decider::_find_installable_id_for(const Resolvent & resolvent, const std::tr1::shared_ptr<const Resolution> & resolution) const
+{
+ 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>
+Decider::_find_id_for_from(
+ const Resolvent &, const std::tr1::shared_ptr<const Resolution> & resolution,
+ const std::tr1::shared_ptr<const PackageIDSequence> & ids) const
+{
+ bool best(true);
+ for (PackageIDSequence::ReverseConstIterator i(ids->rbegin()), i_end(ids->rend()) ;
+ i != i_end ; ++i)
+ {
+ bool ok(true);
+ for (Constraints::ConstIterator c(resolution->constraints()->begin()),
+ c_end(resolution->constraints()->end()) ;
+ c != c_end ; ++c)
+ {
+ if ((*c)->spec().if_package())
+ ok = ok && match_package(*_imp->env, *(*c)->spec().if_package(), **i, MatchPackageOptions());
+ else
+ ok = ok && ! match_package(*_imp->env, (*c)->spec().if_block()->blocking(), **i, MatchPackageOptions());
+
+ if (! ok)
+ break;
+ }
+
+ if (ok)
+ return std::make_pair(*i, best);
+
+ best = false;
+ }
+
+ return std::make_pair(make_null_shared_ptr(), false);
+}
+
+const std::tr1::shared_ptr<const Constraints>
+Decider::_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;
+}
+
+const std::tr1::shared_ptr<const RewrittenSpec>
+Decider::rewrite_if_special(
+ const PackageOrBlockDepSpec & spec,
+ const std::tr1::shared_ptr<const Resolvent> & maybe_from) const
+{
+ return _imp->rewriter.rewrite_if_special(spec, maybe_from);
+}
+
+void
+Decider::add_target_with_reason(const PackageDepSpec & spec, const std::tr1::shared_ptr<const Reason> & reason)
+{
+ Context context("When adding target '" + stringify(spec) + "':");
+
+ _imp->env->trigger_notifier_callback(NotifierCallbackResolverStepEvent());
+
+ const std::tr1::shared_ptr<const RewrittenSpec> if_rewritten(
+ rewrite_if_special(PackageOrBlockDepSpec(spec), make_null_shared_ptr()));
+ if (if_rewritten)
+ {
+ for (Sequence<PackageOrBlockDepSpec>::ConstIterator i(if_rewritten->specs()->begin()), i_end(if_rewritten->specs()->end()) ;
+ i != i_end ; ++i)
+ if (i->if_package())
+ add_target_with_reason(*i->if_package(), reason);
+ else
+ throw InternalError(PALUDIS_HERE, "resolver bug: rewritten " + stringify(spec) + " includes " + stringify(*i));
+ }
+ else
+ {
+ std::tr1::shared_ptr<const Resolvents> resolvents(_get_resolvents_for(spec, reason));
+ if (resolvents->empty())
+ resolvents = _get_error_resolvents_for(spec, reason);
+
+ for (Resolvents::ConstIterator r(resolvents->begin()), r_end(resolvents->end()) ;
+ r != r_end ; ++r)
+ {
+ Context context_2("When adding constraints from target '" + stringify(spec) + "' to resolvent '"
+ + stringify(*r) + "':");
+
+ const std::tr1::shared_ptr<Resolution> dep_resolution(_resolution_for_resolvent(*r, true));
+ const std::tr1::shared_ptr<ConstraintSequence> constraints(_make_constraints_from_target(*r, spec, reason));
+
+ for (ConstraintSequence::ConstIterator c(constraints->begin()), c_end(constraints->end()) ;
+ c != c_end ; ++c)
+ _apply_resolution_constraint(*r, dep_resolution, *c);
+ }
+ }
+}
+
+const std::tr1::shared_ptr<const Resolutions>
+Decider::unordered_resolutions() const
+{
+ return _imp->unordered_resolutions;
+}
+
+void
+Decider::resolve()
+{
+ _resolve_decide_with_dependencies();
+ _resolve_destinations();
+ _resolve_unordered();
+}
+
+namespace
+{
+ struct ResolveOrderVisitor
+ {
+ const std::tr1::function<void ()> already_ordered;
+ const std::tr1::function<void ()> error;
+ const std::tr1::function<void ()> unordered;
+ const std::tr1::function<void ()> untaken;
+
+ ResolveOrderVisitor(const std::tr1::function<void ()> & a,
+ const std::tr1::function<void ()> & e,
+ const std::tr1::function<void ()> & o,
+ const std::tr1::function<void ()> & u) :
+ already_ordered(a),
+ error(e),
+ unordered(o),
+ untaken(u)
+ {
+ }
+
+ void visit(const ExistingNoChangeDecision &) const
+ {
+ already_ordered();
+ }
+
+ void visit(const NothingNoChangeDecision &) const
+ {
+ already_ordered();
+ }
+
+ 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();
+ }
+ else
+ unordered();
+ }
+ };
+}
+
+void
+Decider::_resolve_unordered()
+{
+ for (Resolutions::ConstIterator i(_imp->all_resolutions->begin()),
+ i_end(_imp->all_resolutions->end()) ;
+ i != i_end ; ++i)
+ {
+ (*i)->decision()->accept(ResolveOrderVisitor(
+ std::tr1::bind(&NamedValue<n::already_ordered, bool>::operator=,
+ &(*i)->already_ordered, value_for<n::already_ordered>(true)),
+ std::tr1::bind(&Resolutions::append, _imp->error_resolutions, *i),
+ std::tr1::bind(&Resolutions::append, _imp->unordered_resolutions, *i),
+ std::tr1::bind(&Resolutions::append, _imp->untaken_resolutions, *i)
+ ));
+ }
+}
+
diff --git a/paludis/resolver/decider.hh b/paludis/resolver/decider.hh
new file mode 100644
index 0000000..1350985
--- /dev/null
+++ b/paludis/resolver/decider.hh
@@ -0,0 +1,195 @@
+/* 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_DECIDER_HH
+#define PALUDIS_GUARD_PALUDIS_RESOLVER_DECIDER_HH 1
+
+#include <paludis/resolver/decider-fwd.hh>
+#include <paludis/resolver/resolution-fwd.hh>
+#include <paludis/resolver/resolvent-fwd.hh>
+#include <paludis/resolver/reason-fwd.hh>
+#include <paludis/resolver/destination_types-fwd.hh>
+#include <paludis/resolver/constraint-fwd.hh>
+#include <paludis/resolver/sanitised_dependencies-fwd.hh>
+#include <paludis/resolver/decision-fwd.hh>
+#include <paludis/resolver/destination-fwd.hh>
+#include <paludis/resolver/unsuitable_candidates-fwd.hh>
+#include <paludis/resolver/spec_rewriter-fwd.hh>
+#include <paludis/resolver/resolutions-fwd.hh>
+#include <paludis/resolver/resolver_functions-fwd.hh>
+#include <paludis/resolver/resolver-fwd.hh>
+#include <paludis/util/attributes.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/dep_spec-fwd.hh>
+#include <paludis/package_id-fwd.hh>
+#include <paludis/repository-fwd.hh>
+#include <paludis/filtered_generator-fwd.hh>
+#include <paludis/generator-fwd.hh>
+
+namespace paludis
+{
+ namespace resolver
+ {
+ class PALUDIS_VISIBLE Decider :
+ private PrivateImplementationPattern<Decider>
+ {
+ private:
+ const std::tr1::shared_ptr<Resolution> _create_resolution_for_resolvent(const Resolvent &) const;
+ const std::tr1::shared_ptr<Resolution> _resolution_for_resolvent(const Resolvent &, const bool create);
+
+ const std::tr1::shared_ptr<const Resolvents> _get_resolvents_for_blocker(const BlockDepSpec &) const;
+
+ const DestinationTypes _get_destination_types_for_blocker(const BlockDepSpec &) const;
+
+ const std::tr1::shared_ptr<const Resolvents> _get_resolvents_for(
+ const PackageDepSpec & spec,
+ const std::tr1::shared_ptr<const Reason> & reason) const;
+
+ const DestinationTypes _get_destination_types_for(
+ const PackageDepSpec & spec,
+ const std::tr1::shared_ptr<const PackageID> &,
+ const std::tr1::shared_ptr<const Reason> &) const;
+
+ const std::tr1::shared_ptr<const Resolvents> _get_error_resolvents_for(
+ const PackageDepSpec & spec,
+ const std::tr1::shared_ptr<const Reason> & reason) const;
+
+ const std::tr1::shared_ptr<ConstraintSequence> _make_constraints_from_target(
+ const Resolvent &,
+ const PackageDepSpec &,
+ const std::tr1::shared_ptr<const Reason> &) const;
+
+ const std::tr1::shared_ptr<ConstraintSequence> _make_constraints_from_dependency(
+ const Resolvent &, const SanitisedDependency &,
+ const std::tr1::shared_ptr<const Reason> &) const;
+
+ void _apply_resolution_constraint(const Resolvent &,
+ 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> &);
+
+ void _made_wrong_decision(const Resolvent &,
+ const std::tr1::shared_ptr<Resolution> & resolution,
+ const std::tr1::shared_ptr<const Constraint> & constraint);
+
+ void _suggest_restart_with(const Resolvent &,
+ const std::tr1::shared_ptr<const Resolution> & resolution,
+ const std::tr1::shared_ptr<const Constraint> & constraint,
+ const std::tr1::shared_ptr<const Decision> & decision) const PALUDIS_ATTRIBUTE((noreturn));
+
+ const std::tr1::shared_ptr<const Constraint> _make_constraint_for_preloading(
+ const Resolvent &,
+ const std::tr1::shared_ptr<const Decision> & d,
+ const std::tr1::shared_ptr<const Constraint> & c) const;
+
+ const PackageDepSpec _make_spec_for_preloading(const PackageDepSpec & spec) const;
+
+ const std::tr1::shared_ptr<const PackageIDSequence> _find_replacing(
+ const std::tr1::shared_ptr<const PackageID> &,
+ const std::tr1::shared_ptr<const Repository> &) const;
+
+ const std::tr1::shared_ptr<const Repository> _find_repository_for(
+ const Resolvent &,
+ const std::tr1::shared_ptr<const Resolution> &,
+ const ChangesToMakeDecision &) const;
+
+ void _resolve_decide_with_dependencies();
+ void _resolve_destinations();
+ void _resolve_unordered();
+
+ const std::tr1::shared_ptr<Destination> _make_destination_for(
+ const Resolvent & resolvent,
+ const std::tr1::shared_ptr<const Resolution> & resolution,
+ const ChangesToMakeDecision &) const;
+
+ FilteredGenerator _make_destination_filtered_generator(const Generator &, const Resolvent & resolvent) const;
+
+ void _decide(const Resolvent &, const std::tr1::shared_ptr<Resolution> & resolution);
+
+ const std::tr1::shared_ptr<Decision> _try_to_find_decision_for(
+ const Resolvent &, const std::tr1::shared_ptr<const Resolution> & resolution) const;
+
+ const std::tr1::shared_ptr<Decision> _cannot_decide_for(
+ const Resolvent &, const std::tr1::shared_ptr<const Resolution> & resolution) const;
+
+ 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> &,
+ const SanitisedDependency &) const;
+
+ const std::tr1::shared_ptr<Constraints> _initial_constraints_for(const Resolvent &) const;
+
+ bool _same_slot(const std::tr1::shared_ptr<const PackageID> & a,
+ const std::tr1::shared_ptr<const PackageID> & b) const;
+
+ 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;
+
+
+ public:
+ Decider(const Environment * const,
+ const ResolverFunctions &,
+ const ResolverLists &);
+ ~Decider();
+
+ void resolve();
+
+ void add_target_with_reason(const PackageDepSpec &, const std::tr1::shared_ptr<const Reason> &);
+
+ int find_any_score(const Resolvent &, const SanitisedDependency &) const;
+
+ const std::tr1::shared_ptr<const RewrittenSpec> rewrite_if_special(const PackageOrBlockDepSpec &,
+ const std::tr1::shared_ptr<const Resolvent> & maybe_from) const;
+
+ const std::tr1::shared_ptr<const Resolutions> unordered_resolutions() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ const std::tr1::shared_ptr<Resolution> resolution_for_resolvent(const Resolvent &) const;
+ };
+ }
+}
+
+#endif
diff --git a/paludis/resolver/orderer-fwd.hh b/paludis/resolver/orderer-fwd.hh
new file mode 100644
index 0000000..77cfbc5
--- /dev/null
+++ b/paludis/resolver/orderer-fwd.hh
@@ -0,0 +1,31 @@
+/* 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_ORDERER_FWD_HH
+#define PALUDIS_GUARD_PALUDIS_RESOLVER_ORDERER_FWD_HH 1
+
+namespace paludis
+{
+ namespace resolver
+ {
+ struct Orderer;
+ }
+}
+
+#endif
diff --git a/paludis/resolver/orderer.cc b/paludis/resolver/orderer.cc
new file mode 100644
index 0000000..77a28c2
--- /dev/null
+++ b/paludis/resolver/orderer.cc
@@ -0,0 +1,441 @@
+/* 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/orderer.hh>
+#include <paludis/resolver/reason.hh>
+#include <paludis/resolver/constraint.hh>
+#include <paludis/resolver/resolvent.hh>
+#include <paludis/resolver/decider.hh>
+#include <paludis/resolver/resolution.hh>
+#include <paludis/resolver/arrow.hh>
+#include <paludis/resolver/decision.hh>
+#include <paludis/resolver/resolutions.hh>
+#include <paludis/resolver/resolver.hh>
+#include <paludis/util/exception.hh>
+#include <paludis/util/sequence.hh>
+#include <paludis/util/wrapped_forward_iterator.hh>
+#include <paludis/util/indirect_iterator-impl.hh>
+#include <paludis/util/accept_visitor.hh>
+#include <paludis/util/make_named_values.hh>
+#include <paludis/util/make_shared_ptr.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/util/log.hh>
+#include <paludis/match_package.hh>
+#include <paludis/generator.hh>
+#include <paludis/filter.hh>
+#include <paludis/filtered_generator.hh>
+#include <paludis/selection.hh>
+#include <paludis/notifier_callback.hh>
+#include <iostream>
+#include <algorithm>
+#include <set>
+
+using namespace paludis;
+using namespace paludis::resolver;
+
+namespace paludis
+{
+ template <>
+ struct Implementation<Orderer>
+ {
+ const Environment * const env;
+ const std::tr1::shared_ptr<const Decider> decider;
+
+ const std::tr1::shared_ptr<Resolutions> all_resolutions;
+ const std::tr1::shared_ptr<Resolutions> ordered_resolutions;
+
+ Implementation(const Environment * const e,
+ const std::tr1::shared_ptr<const Decider> & d,
+ const ResolverLists & l) :
+ env(e),
+ decider(d),
+ all_resolutions(l.all()),
+ ordered_resolutions(l.ordered())
+ {
+ }
+ };
+}
+
+Orderer::Orderer(const Environment * const e, const std::tr1::shared_ptr<const Decider> & d,
+ const ResolverLists & l) :
+ PrivateImplementationPattern<Orderer>(new Implementation<Orderer>(e, d, l))
+{
+}
+
+Orderer::~Orderer()
+{
+}
+
+void
+Orderer::_resolve_arrows()
+{
+ Context context("When creating arrows for order resolution:");
+
+ for (Resolutions::ConstIterator i(_imp->all_resolutions->begin()),
+ i_end(_imp->all_resolutions->end()) ;
+ i != i_end ; ++i)
+ for (Constraints::ConstIterator c((*i)->constraints()->begin()),
+ c_end((*i)->constraints()->end()) ;
+ c != c_end ; ++c)
+ _resolve_arrow((*i)->resolvent(), _imp->decider->resolution_for_resolvent((*i)->resolvent()), *c);
+}
+
+namespace
+{
+ struct GetDependencyReason
+ {
+ const DependencyReason * visit(const DependencyReason & r) const
+ {
+ return &r;
+ }
+
+ const DependencyReason * visit(const SetReason & r) const
+ {
+ return r.reason_for_set()->accept_returning<const DependencyReason *>(*this);
+ }
+
+ const DependencyReason * visit(const TargetReason &) const
+ {
+ return 0;
+ }
+
+ const DependencyReason * visit(const PresetReason &) const
+ {
+ return 0;
+ }
+ };
+
+ struct ArrowInfo
+ {
+ bool causes_pre_arrow;
+ bool ignorable;
+
+ ArrowInfo(const DependencyReason & reason) :
+ causes_pre_arrow(false),
+ ignorable(true)
+ {
+ std::for_each(indirect_iterator(reason.sanitised_dependency().active_dependency_labels()->begin()),
+ indirect_iterator(reason.sanitised_dependency().active_dependency_labels()->end()), accept_visitor(*this));
+ }
+
+ void visit(const DependenciesBuildLabel &)
+ {
+ causes_pre_arrow = true;
+ ignorable = false;
+ }
+
+ void visit(const DependenciesTestLabel &)
+ {
+ causes_pre_arrow = true;
+ ignorable = false;
+ }
+
+ void visit(const DependenciesRunLabel &)
+ {
+ causes_pre_arrow = true;
+ }
+
+ void visit(const DependenciesPostLabel &)
+ {
+ }
+
+ void visit(const DependenciesInstallLabel &)
+ {
+ causes_pre_arrow = true;
+ ignorable = false;
+ }
+
+ void visit(const DependenciesCompileAgainstLabel &)
+ {
+ causes_pre_arrow = true;
+ ignorable = false;
+ }
+
+ void visit(const DependenciesFetchLabel &)
+ {
+ causes_pre_arrow = true;
+ ignorable = false;
+ }
+
+ void visit(const DependenciesRecommendationLabel &)
+ {
+ }
+
+ void visit(const DependenciesSuggestionLabel &)
+ {
+ }
+ };
+}
+
+void
+Orderer::_resolve_arrow(
+ const Resolvent & resolvent,
+ const std::tr1::shared_ptr<Resolution> &,
+ const std::tr1::shared_ptr<const Constraint> & constraint)
+{
+ GetDependencyReason gdr;
+ const DependencyReason * if_dependency_reason(constraint->reason()->accept_returning<const DependencyReason *>(gdr));
+ if (! if_dependency_reason)
+ return;
+
+ const Resolvent from_resolvent(if_dependency_reason->from_resolvent());
+ const std::tr1::shared_ptr<Resolution> resolution(_imp->decider->resolution_for_resolvent(from_resolvent));
+
+ /* deps between binaries don't count */
+ if (resolvent.destination_type() == dt_create_binary &&
+ if_dependency_reason->from_resolvent().destination_type() == dt_create_binary)
+ return;
+
+ if (constraint->spec().if_block())
+ {
+ if (constraint->spec().if_block()->strong())
+ {
+ resolution->arrows()->push_back(make_shared_ptr(new Arrow(make_named_values<Arrow>(
+ value_for<n::comes_after>(resolvent),
+ value_for<n::ignorable_pass>(0),
+ value_for<n::reason>(constraint->reason())
+ ))));
+ }
+ }
+ else
+ {
+ ArrowInfo a(*if_dependency_reason);
+ if (a.causes_pre_arrow)
+ {
+ int ignorable_pass(0);
+ if (_already_met(if_dependency_reason->sanitised_dependency()))
+ ignorable_pass = 1;
+ else if (a.ignorable)
+ ignorable_pass = 2;
+
+ resolution->arrows()->push_back(make_shared_ptr(new Arrow(make_named_values<Arrow>(
+ value_for<n::comes_after>(resolvent),
+ value_for<n::ignorable_pass>(ignorable_pass),
+ value_for<n::reason>(constraint->reason())
+ ))));
+ }
+ }
+}
+
+bool
+Orderer::_already_met(const SanitisedDependency & dep) const
+{
+ if (dep.spec().if_package())
+ {
+ std::tr1::shared_ptr<const PackageIDSequence> ids((*_imp->env)[selection::SomeArbitraryVersion(
+ generator::Matches(*dep.spec().if_package(), MatchPackageOptions()) |
+ filter::InstalledAtRoot(FSEntry("/")))]);
+ return ! ids->empty();
+ }
+ else if (dep.spec().if_block())
+ {
+ /* it's imposing an arrow, so it's a strong block */
+ return false;
+ }
+ else
+ throw InternalError(PALUDIS_HERE, "resolver bug: huh? it's not a block and it's not a package");
+}
+
+void
+Orderer::_resolve_order()
+{
+ Context context("When finding an order for selected packages:");
+
+ bool done(false);
+ while (! done)
+ {
+ bool any(false);
+ done = true;
+
+ int ignore_pass(0);
+ while (true)
+ {
+ for (Resolutions::ConstIterator i(_imp->decider->unordered_resolutions()->begin()),
+ i_end(_imp->decider->unordered_resolutions()->end()) ;
+ i != i_end ; ++i)
+ {
+ if ((*i)->already_ordered())
+ continue;
+
+ if (_can_order_now((*i)->resolvent(), *i, ignore_pass))
+ {
+ if (0 != ignore_pass)
+ Log::get_instance()->message("resolver.cycle_breaking", ll_warning, lc_context)
+ << "Had to use cycle breaking with ignore pass " << ignore_pass
+ << " to order " << (*i)->resolvent() << " because of cycle "
+ << _find_cycle((*i)->resolvent(), false);
+
+ _imp->env->trigger_notifier_callback(NotifierCallbackResolverStepEvent());
+ _do_order((*i)->resolvent(), _imp->decider->resolution_for_resolvent((*i)->resolvent()));
+ any = true;
+
+ if (0 != ignore_pass)
+ break;
+ }
+ else
+ done = false;
+ }
+
+ if ((! done) && (! any))
+ {
+ if (ignore_pass >= 2)
+ _unable_to_order_more();
+ else
+ ++ignore_pass;
+ }
+ else
+ break;
+ }
+ }
+}
+
+bool
+Orderer::_can_order_now(const Resolvent &, const std::tr1::shared_ptr<const Resolution> & resolution,
+ const int ignorable_pass) const
+{
+ for (ArrowSequence::ConstIterator a(resolution->arrows()->begin()), a_end(resolution->arrows()->end()) ;
+ a != a_end ; ++a)
+ {
+ if (0 != (*a)->ignorable_pass())
+ if ((*a)->ignorable_pass() <= ignorable_pass)
+ continue;
+
+ const std::tr1::shared_ptr<const Resolution> dep_resolution(
+ _imp->decider->resolution_for_resolvent((*a)->comes_after()));
+ if (! dep_resolution->already_ordered())
+ return false;
+ }
+
+ return true;
+}
+
+void
+Orderer::_do_order(const Resolvent &, const std::tr1::shared_ptr<Resolution> & resolution)
+{
+ _imp->ordered_resolutions->append(resolution);
+ resolution->already_ordered() = true;
+}
+
+void
+Orderer::_unable_to_order_more() const
+{
+ std::cout << "Unable to order any of the following:" << std::endl;
+
+ for (Resolutions::ConstIterator i(_imp->decider->unordered_resolutions()->begin()),
+ i_end(_imp->decider->unordered_resolutions()->end()) ;
+ i != i_end ; ++i)
+ {
+ if ((*i)->already_ordered())
+ continue;
+
+ std::cout << " * " << (*i)->resolvent() << " because of cycle "
+ << _find_cycle((*i)->resolvent(), true)
+ << std::endl;
+ }
+
+ throw InternalError(PALUDIS_HERE, "unimplemented: unfixable dep cycle");
+}
+
+namespace
+{
+ struct ReasonDescriber
+ {
+ const std::string visit(const DependencyReason & r) const
+ {
+ return " (" + r.sanitised_dependency().active_dependency_labels_as_string() + " " +
+ stringify(r.sanitised_dependency().spec()) + ")";
+ }
+
+ const std::string visit(const TargetReason &) const
+ {
+ return "";
+ }
+
+ const std::string visit(const PresetReason &) const
+ {
+ return "";
+ }
+
+ const std::string visit(const SetReason &) const
+ {
+ return "";
+ }
+ };
+}
+
+const std::string
+Orderer::_find_cycle(const Resolvent & start_resolvent, const int ignorable_pass) const
+{
+ std::stringstream result;
+
+ std::set<Resolvent> seen;
+ Resolvent current(start_resolvent);
+
+ bool first(true);
+ while (true)
+ {
+ if (! first)
+ result << " -> ";
+ first = false;
+
+ result << current;
+
+ if (! seen.insert(current).second)
+ break;
+
+ bool ok(false);
+ const std::tr1::shared_ptr<const Resolution> resolution(_imp->decider->resolution_for_resolvent(current));
+ for (ArrowSequence::ConstIterator a(resolution->arrows()->begin()), a_end(resolution->arrows()->end()) ;
+ a != a_end ; ++a)
+ {
+ if (_can_order_now(current, resolution, ignorable_pass))
+ continue;
+
+ const std::tr1::shared_ptr<const Resolution> to_resolution(
+ _imp->decider->resolution_for_resolvent((*a)->comes_after()));
+ if (to_resolution->already_ordered())
+ continue;
+
+ ok = true;
+ result << (*a)->reason()->accept_returning<std::string>(ReasonDescriber());
+ current = (*a)->comes_after();
+ break;
+ }
+
+ if (! ok)
+ throw InternalError(PALUDIS_HERE, "resolver bug: there's a cycle, but we don't know what it is");
+ }
+
+ return result.str();
+}
+
+const std::tr1::shared_ptr<const Resolutions>
+Orderer::ordered_resolutions() const
+{
+ return _imp->ordered_resolutions;
+}
+
+void
+Orderer::resolve()
+{
+ _resolve_arrows();
+ _resolve_order();
+}
+
diff --git a/paludis/resolver/orderer.hh b/paludis/resolver/orderer.hh
new file mode 100644
index 0000000..d953182
--- /dev/null
+++ b/paludis/resolver/orderer.hh
@@ -0,0 +1,80 @@
+/* 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_ORDERER_HH
+#define PALUDIS_GUARD_PALUDIS_RESOLVER_ORDERER_HH 1
+
+#include <paludis/resolver/orderer-fwd.hh>
+#include <paludis/resolver/resolvent-fwd.hh>
+#include <paludis/resolver/resolution-fwd.hh>
+#include <paludis/resolver/resolutions-fwd.hh>
+#include <paludis/resolver/constraint-fwd.hh>
+#include <paludis/resolver/reason-fwd.hh>
+#include <paludis/resolver/resolver_functions-fwd.hh>
+#include <paludis/resolver/sanitised_dependencies-fwd.hh>
+#include <paludis/resolver/decider-fwd.hh>
+#include <paludis/resolver/resolver-fwd.hh>
+#include <paludis/util/attributes.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/environment.hh>
+#include <tr1/memory>
+
+namespace paludis
+{
+ namespace resolver
+ {
+ class PALUDIS_VISIBLE Orderer :
+ private PrivateImplementationPattern<Orderer>
+ {
+ private:
+ bool _can_order_now(const Resolvent &, const std::tr1::shared_ptr<const Resolution> & resolution,
+ const int ignorable_pass) const;
+
+ void _do_order(const Resolvent &, const std::tr1::shared_ptr<Resolution> & resolution);
+
+ void _unable_to_order_more() const PALUDIS_ATTRIBUTE((noreturn));
+
+ void _resolve_arrow(const Resolvent &, const std::tr1::shared_ptr<Resolution> &,
+ const std::tr1::shared_ptr<const Constraint> &);
+
+ void _resolve_arrows();
+ void _resolve_order();
+
+ bool _causes_pre_arrow(const DependencyReason &) const;
+
+ const std::string _find_cycle(const Resolvent &, const int ignorable_pass) const;
+
+ bool _already_met(const SanitisedDependency & dep) const;
+
+ public:
+ Orderer(
+ const Environment * const,
+ const std::tr1::shared_ptr<const Decider> &,
+ const ResolverLists &);
+ ~Orderer();
+
+ void resolve();
+
+ const std::tr1::shared_ptr<const Resolutions> ordered_resolutions() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+ }
+}
+
+#endif
diff --git a/paludis/resolver/resolutions-fwd.hh b/paludis/resolver/resolutions-fwd.hh
index 506dfaa..801e57f 100644
--- a/paludis/resolver/resolutions-fwd.hh
+++ b/paludis/resolver/resolutions-fwd.hh
@@ -27,7 +27,6 @@ namespace paludis
{
namespace resolver
{
- struct ResolutionLists;
struct Resolutions;
}
}
diff --git a/paludis/resolver/resolutions.cc b/paludis/resolver/resolutions.cc
index 4f3b5fb..37cb765 100644
--- a/paludis/resolver/resolutions.cc
+++ b/paludis/resolver/resolutions.cc
@@ -34,7 +34,7 @@ namespace paludis
template <>
struct Implementation<Resolutions>
{
- Sequence<std::tr1::shared_ptr<const Resolution> > resolutions;
+ Sequence<std::tr1::shared_ptr<Resolution> > resolutions;
};
}
@@ -48,7 +48,7 @@ Resolutions::~Resolutions()
}
void
-Resolutions::append(const std::tr1::shared_ptr<const Resolution> & r)
+Resolutions::append(const std::tr1::shared_ptr<Resolution> & r)
{
_imp->resolutions.push_back(r);
}
@@ -90,29 +90,6 @@ Resolutions::deserialise(Deserialisation & d)
return result;
}
-void
-ResolutionLists::serialise(Serialiser & s) const
-{
- s.object("ResolutionLists")
- .member(SerialiserFlags<serialise::might_be_null>(), "all", all())
- .member(SerialiserFlags<serialise::might_be_null>(), "errors", errors())
- .member(SerialiserFlags<serialise::might_be_null>(), "ordered", ordered())
- .member(SerialiserFlags<serialise::might_be_null>(), "untaken", untaken())
- ;
-}
-
-ResolutionLists
-ResolutionLists::deserialise(Deserialisation & d)
-{
- Deserialisator v(d, "ResolutionLists");
- return make_named_values<ResolutionLists>(
- value_for<n::all>(v.member<std::tr1::shared_ptr<Resolutions> >("all")),
- value_for<n::errors>(v.member<std::tr1::shared_ptr<Resolutions> >("errors")),
- value_for<n::ordered>(v.member<std::tr1::shared_ptr<Resolutions> >("ordered")),
- value_for<n::untaken>(v.member<std::tr1::shared_ptr<Resolutions> >("untaken"))
- );
-}
-
template class PrivateImplementationPattern<Resolutions>;
template class WrappedForwardIterator<Resolutions::ConstIteratorTag, const std::tr1::shared_ptr<const Resolution> >;
diff --git a/paludis/resolver/resolutions.hh b/paludis/resolver/resolutions.hh
index 6b2e447..ca8c602 100644
--- a/paludis/resolver/resolutions.hh
+++ b/paludis/resolver/resolutions.hh
@@ -40,18 +40,6 @@ namespace paludis
namespace resolver
{
- struct ResolutionLists
- {
- NamedValue<n::all, std::tr1::shared_ptr<Resolutions> > all;
- NamedValue<n::errors, std::tr1::shared_ptr<Resolutions> > errors;
- NamedValue<n::ordered, std::tr1::shared_ptr<Resolutions> > ordered;
- NamedValue<n::untaken, std::tr1::shared_ptr<Resolutions> > untaken;
-
- void serialise(Serialiser &) const;
- static ResolutionLists deserialise(
- Deserialisation & d) PALUDIS_ATTRIBUTE((warn_unused_result));
- };
-
class PALUDIS_VISIBLE Resolutions :
private PrivateImplementationPattern<Resolutions>
{
@@ -59,11 +47,11 @@ namespace paludis
Resolutions();
~Resolutions();
- void append(const std::tr1::shared_ptr<const Resolution> &);
+ void append(const std::tr1::shared_ptr<Resolution> &);
struct ConstIteratorTag;
typedef WrappedForwardIterator<ConstIteratorTag,
- const std::tr1::shared_ptr<const Resolution> > ConstIterator;
+ const std::tr1::shared_ptr<Resolution> > ConstIterator;
ConstIterator begin() const PALUDIS_ATTRIBUTE((warn_unused_result));
ConstIterator end() const PALUDIS_ATTRIBUTE((warn_unused_result));
diff --git a/paludis/resolver/resolver-fwd.hh b/paludis/resolver/resolver-fwd.hh
index df41385..495bb5d 100644
--- a/paludis/resolver/resolver-fwd.hh
+++ b/paludis/resolver/resolver-fwd.hh
@@ -25,6 +25,7 @@ namespace paludis
namespace resolver
{
struct Resolver;
+ struct ResolverLists;
}
}
diff --git a/paludis/resolver/resolver.cc b/paludis/resolver/resolver.cc
index 0bdd8e4..66dba8d 100644
--- a/paludis/resolver/resolver.cc
+++ b/paludis/resolver/resolver.cc
@@ -18,58 +18,27 @@
*/
#include <paludis/resolver/resolver.hh>
-#include <paludis/resolver/resolution.hh>
-#include <paludis/resolver/constraint.hh>
-#include <paludis/resolver/reason.hh>
-#include <paludis/resolver/resolvent.hh>
-#include <paludis/resolver/sanitised_dependencies.hh>
-#include <paludis/resolver/arrow.hh>
-#include <paludis/resolver/decision.hh>
#include <paludis/resolver/resolver_functions.hh>
-#include <paludis/resolver/suggest_restart.hh>
-#include <paludis/resolver/resolutions.hh>
-#include <paludis/resolver/destination.hh>
-#include <paludis/resolver/unsuitable_candidates.hh>
#include <paludis/resolver/spec_rewriter.hh>
+#include <paludis/resolver/decider.hh>
+#include <paludis/resolver/orderer.hh>
+#include <paludis/resolver/sanitised_dependencies.hh>
+#include <paludis/resolver/reason.hh>
+#include <paludis/resolver/resolutions.hh>
#include <paludis/util/stringify.hh>
+#include <paludis/util/make_shared_ptr.hh>
+#include <paludis/util/sequence.hh>
+#include <paludis/util/wrapped_forward_iterator.hh>
#include <paludis/util/make_named_values.hh>
-#include <paludis/util/log.hh>
-#include <paludis/util/join.hh>
-#include <paludis/util/wrapped_forward_iterator-impl.hh>
-#include <paludis/util/simple_visitor_cast.hh>
-#include <paludis/util/mutex.hh>
-#include <paludis/util/enum_iterator.hh>
+#include <paludis/util/make_shared_copy.hh>
+#include <paludis/serialise-impl.hh>
#include <paludis/environment.hh>
#include <paludis/notifier_callback.hh>
#include <paludis/dep_spec_flattener.hh>
-#include <paludis/spec_tree.hh>
-#include <paludis/slot_requirement.hh>
-#include <paludis/filter.hh>
-#include <paludis/filtered_generator.hh>
-#include <paludis/generator.hh>
-#include <paludis/selection.hh>
-#include <paludis/metadata_key.hh>
-#include <paludis/match_package.hh>
-#include <paludis/action.hh>
-#include <paludis/version_spec.hh>
-#include <paludis/version_requirements.hh>
-#include <paludis/package_database.hh>
-#include <paludis/repository.hh>
-#include <paludis/choice.hh>
-#include <paludis/spec_tree.hh>
-#include <paludis/serialise.hh>
-#include <iostream>
-#include <iomanip>
-#include <list>
-#include <map>
-#include <set>
-#include "config.h"
using namespace paludis;
using namespace paludis::resolver;
-typedef std::map<Resolvent, std::tr1::shared_ptr<Resolution> > ResolutionsByResolventMap;
-
namespace paludis
{
template <>
@@ -77,22 +46,22 @@ namespace paludis
{
const Environment * const env;
const ResolverFunctions fns;
- SpecRewriter rewriter;
- ResolutionsByResolventMap resolutions_by_resolvent;
+ const std::tr1::shared_ptr<ResolverLists> lists;
- std::tr1::shared_ptr<ResolutionLists> resolution_lists;
+ const std::tr1::shared_ptr<Decider> decider;
+ std::tr1::shared_ptr<Orderer> orderer;
Implementation(const Environment * const e, const ResolverFunctions & f) :
env(e),
fns(f),
- rewriter(env),
- resolution_lists(new ResolutionLists(make_named_values<ResolutionLists>(
- value_for<n::all>(new Resolutions),
- value_for<n::errors>(new Resolutions),
- value_for<n::ordered>(new Resolutions),
- value_for<n::untaken>(new Resolutions)
- )))
+ lists(new ResolverLists(make_named_values<ResolverLists>(
+ value_for<n::all>(make_shared_ptr(new Resolutions)),
+ value_for<n::errors>(make_shared_ptr(new Resolutions)),
+ value_for<n::ordered>(make_shared_ptr(new Resolutions)),
+ value_for<n::untaken>(make_shared_ptr(new Resolutions))
+ ))),
+ decider(new Decider(e, f, *lists))
{
}
};
@@ -108,234 +77,9 @@ Resolver::~Resolver()
}
void
-Resolver::resolve()
-{
- Context context("When finding an appropriate resolution:");
-
- _resolve_decide_with_dependencies();
- _resolve_destinations();
- _resolve_arrows();
- _resolve_order();
-}
-
-void
-Resolver::_resolve_decide_with_dependencies()
-{
- Context context("When resolving and adding dependencies recursively:");
-
- enum State { deciding_non_suggestions, deciding_suggestions, finished } state = deciding_non_suggestions;
- bool changed(true);
- while (true)
- {
- if (! changed)
- state = State(state + 1);
- if (state == finished)
- break;
-
- changed = false;
- for (ResolutionsByResolventMap::iterator i(_imp->resolutions_by_resolvent.begin()), i_end(_imp->resolutions_by_resolvent.end()) ;
- i != i_end ; ++i)
- {
- /* we've already decided */
- if (i->second->decision())
- continue;
-
- /* we're only being suggested. don't do this on the first pass, so
- * we don't have to do restarts for suggestions later becoming hard
- * deps. */
- if (state == deciding_non_suggestions && i->second->constraints()->all_untaken())
- continue;
-
- _imp->env->trigger_notifier_callback(NotifierCallbackResolverStepEvent());
-
- changed = true;
- _decide(i->first, i->second);
-
- _add_dependencies_if_necessary(i->first, i->second);
- }
- }
-}
-
-void
-Resolver::_resolve_destinations()
-{
- Context context("When resolving destinations:");
-
- 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
- {
- typedef std::tr1::function<const std::tr1::shared_ptr<const Destination> (
- const ChangesToMakeDecision &)> MakeDestinationFunc;
-
- 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 ChangesToMakeDecision & decision) const
-{
- 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 ChangesToMakeDecision & decision) const
-{
- return _imp->fns.find_repository_for_fn()(resolvent, resolution, decision);
-}
-
-FilteredGenerator
-Resolver::_make_destination_filtered_generator(const Generator & g, const Resolvent & resolvent) const
-{
- return _imp->fns.make_destination_filtered_generator_fn()(g, resolvent);
-}
-
-const std::tr1::shared_ptr<const PackageIDSequence>
-Resolver::_find_replacing(
- const std::tr1::shared_ptr<const PackageID> & id,
- const std::tr1::shared_ptr<const Repository> & repo) const
-{
- Context context("When working out what is replaced by '" + stringify(*id) +
- "' when it is installed to '" + stringify(repo->name()) + "':");
-
- std::set<RepositoryName, RepositoryNameComparator> repos;
-
- if (repo->installed_root_key())
- {
- for (PackageDatabase::RepositoryConstIterator r(_imp->env->package_database()->begin_repositories()),
- r_end(_imp->env->package_database()->end_repositories()) ;
- r != r_end ; ++r)
- if ((*r)->installed_root_key() &&
- (*r)->installed_root_key()->value() == repo->installed_root_key()->value())
- repos.insert((*r)->name());
- }
- else
- repos.insert(repo->name());
-
- std::tr1::shared_ptr<PackageIDSequence> result(new PackageIDSequence);
- for (std::set<RepositoryName, RepositoryNameComparator>::const_iterator r(repos.begin()),
- r_end(repos.end()) ;
- r != r_end ; ++r)
- {
- std::tr1::shared_ptr<const PackageIDSequence> ids((*_imp->env)[selection::AllVersionsUnsorted(
- generator::Package(id->name()) & generator::InRepository(*r))]);
- for (PackageIDSequence::ConstIterator i(ids->begin()), i_end(ids->end()) ;
- i != i_end ; ++i)
- {
- if ((*i)->version() == id->version() || _same_slot(*i, id))
- result->push_back(*i);
- }
- }
-
- return result;
-}
-
-bool
-Resolver::_same_slot(const std::tr1::shared_ptr<const PackageID> & a,
- const std::tr1::shared_ptr<const PackageID> & b) const
-{
- if (a->slot_key())
- return b->slot_key() && a->slot_key()->value() == b->slot_key()->value();
- else
- return ! b->slot_key();
-}
-
-void
-Resolver::add_target_with_reason(const PackageDepSpec & spec, const std::tr1::shared_ptr<const Reason> & reason)
-{
- Context context("When adding target '" + stringify(spec) + "':");
-
- _imp->env->trigger_notifier_callback(NotifierCallbackResolverStepEvent());
-
- const std::tr1::shared_ptr<const RewrittenSpec> if_rewritten(rewrite_if_special(spec, make_null_shared_ptr()));
- if (if_rewritten)
- {
- for (Sequence<PackageOrBlockDepSpec>::ConstIterator i(if_rewritten->specs()->begin()), i_end(if_rewritten->specs()->end()) ;
- i != i_end ; ++i)
- if (i->if_package())
- add_target_with_reason(*i->if_package(), reason);
- else
- throw InternalError(PALUDIS_HERE, "resolver bug: rewritten " + stringify(spec) + " includes " + stringify(*i));
- }
- else
- {
- std::tr1::shared_ptr<const Resolvents> resolvents(_get_resolvents_for(spec, reason));
- if (resolvents->empty())
- resolvents = _get_error_resolvents_for(spec, reason);
-
- for (Resolvents::ConstIterator r(resolvents->begin()), r_end(resolvents->end()) ;
- r != r_end ; ++r)
- {
- Context context_2("When adding constraints from target '" + stringify(spec) + "' to resolvent '"
- + stringify(*r) + "':");
-
- const std::tr1::shared_ptr<Resolution> dep_resolution(_resolution_for_resolvent(*r, true));
- const std::tr1::shared_ptr<ConstraintSequence> constraints(_make_constraints_from_target(*r, spec, reason));
-
- for (ConstraintSequence::ConstIterator c(constraints->begin()), c_end(constraints->end()) ;
- c != c_end ; ++c)
- _apply_resolution_constraint(*r, dep_resolution, *c);
- }
- }
-}
-
-void
Resolver::add_target(const PackageDepSpec & spec)
{
- add_target_with_reason(spec, make_shared_ptr(new TargetReason));
+ _imp->decider->add_target_with_reason(spec, make_shared_ptr(new TargetReason));
}
void
@@ -354,1429 +98,44 @@ Resolver::add_target(const SetName & set_name)
const std::tr1::shared_ptr<Reason> reason(new SetReason(set_name, make_shared_ptr(new TargetReason)));
for (DepSpecFlattener<SetSpecTree, PackageDepSpec>::ConstIterator s(flattener.begin()), s_end(flattener.end()) ;
s != s_end ; ++s)
- add_target_with_reason(**s, reason);
-}
-
-const std::tr1::shared_ptr<Resolution>
-Resolver::_create_resolution_for_resolvent(const Resolvent & r) const
-{
- return make_shared_ptr(new Resolution(make_named_values<Resolution>(
- value_for<n::already_ordered>(false),
- value_for<n::arrows>(make_shared_ptr(new ArrowSequence)),
- value_for<n::constraints>(_initial_constraints_for(r)),
- value_for<n::decision>(make_null_shared_ptr()),
- value_for<n::resolvent>(r)
- )));
-}
-
-const std::tr1::shared_ptr<Resolution>
-Resolver::_resolution_for_resolvent(const Resolvent & r, const bool create)
-{
- ResolutionsByResolventMap::iterator i(_imp->resolutions_by_resolvent.find(r));
- if (_imp->resolutions_by_resolvent.end() == i)
- {
- if (create)
- {
- std::tr1::shared_ptr<Resolution> resolution(_create_resolution_for_resolvent(r));
- i = _imp->resolutions_by_resolvent.insert(std::make_pair(r, resolution)).first;
- _imp->resolution_lists->all()->append(resolution);
- }
- else
- throw InternalError(PALUDIS_HERE, "resolver bug: expected resolution for "
- + stringify(r) + " to exist, but it doesn't");
- }
-
- return i->second;
-}
-
-const std::tr1::shared_ptr<Resolution>
-Resolver::_resolution_for_resolvent(const Resolvent & r) const
-{
- ResolutionsByResolventMap::const_iterator i(_imp->resolutions_by_resolvent.find(r));
- if (_imp->resolutions_by_resolvent.end() == i)
- throw InternalError(PALUDIS_HERE, "resolver bug: expected resolution for "
- + stringify(r) + " to exist, but it doesn't");
-
- return i->second;
-}
-
-const std::tr1::shared_ptr<ConstraintSequence>
-Resolver::_make_constraints_from_target(
- const Resolvent & resolvent,
- const PackageDepSpec & spec,
- const std::tr1::shared_ptr<const Reason> & reason) const
-{
- const std::tr1::shared_ptr<ConstraintSequence> result(new ConstraintSequence);
- result->push_back(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>(spec),
- value_for<n::untaken>(false),
- value_for<n::use_existing>(_imp->fns.get_use_existing_fn()(resolvent, spec, reason))
- ))));
- return result;
-}
-
-const std::tr1::shared_ptr<ConstraintSequence>
-Resolver::_make_constraints_from_dependency(const Resolvent & resolvent, const SanitisedDependency & dep,
- const std::tr1::shared_ptr<const Reason> & reason) const
-{
- const std::tr1::shared_ptr<ConstraintSequence> result(new ConstraintSequence);
- if (dep.spec().if_package())
- {
- result->push_back(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>(*dep.spec().if_package()),
- value_for<n::untaken>(! _imp->fns.take_dependency_fn()(
- resolvent, dep, reason)),
- value_for<n::use_existing>(_imp->fns.get_use_existing_fn()(
- resolvent, *dep.spec().if_package(), reason))
- ))));
- }
- else if (dep.spec().if_block())
- {
- /* nothing is fine too if there's nothing installed matching the block. */
- const std::tr1::shared_ptr<const PackageIDSequence> ids((*_imp->env)[selection::SomeArbitraryVersion(
- generator::Matches(dep.spec().if_block()->blocking(), MatchPackageOptions()) |
- filter::InstalledAtRoot(FSEntry("/")))]);
-
- DestinationTypes destination_types(_get_destination_types_for_blocker(*dep.spec().if_block()));
- for (EnumIterator<DestinationType> t, t_end(last_dt) ; t != t_end ; ++t)
- if (destination_types[*t])
- result->push_back(make_shared_ptr(new Constraint(make_named_values<Constraint>(
- value_for<n::destination_type>(*t),
- value_for<n::nothing_is_fine_too>(ids->empty()),
- value_for<n::reason>(reason),
- value_for<n::spec>(dep.spec()),
- value_for<n::untaken>(false),
- value_for<n::use_existing>(ue_if_possible)
- ))));
- }
- else
- throw InternalError(PALUDIS_HERE, "resolver bug: huh? it's not a block and it's not a package");
-
- return result;
-}
-
-void
-Resolver::_apply_resolution_constraint(
- const Resolvent & resolvent,
- const std::tr1::shared_ptr<Resolution> & resolution,
- const std::tr1::shared_ptr<const Constraint> & constraint)
-{
- if (resolution->decision())
- if (! _verify_new_constraint(resolvent, resolution, constraint))
- _made_wrong_decision(resolvent, 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::_check_constraint(const Resolvent &,
- const std::tr1::shared_ptr<const Constraint> & constraint,
- const std::tr1::shared_ptr<const Decision> & decision) const
-{
- const std::tr1::shared_ptr<const PackageID> chosen_id(decision->accept_returning<
- std::tr1::shared_ptr<const PackageID> >(ChosenIDVisitor()));
-
- if (chosen_id)
- {
- if (constraint->spec().if_package())
- {
- if (! match_package(*_imp->env, *constraint->spec().if_package(), *chosen_id, MatchPackageOptions()))
- return false;
- }
- else
- {
- if (match_package(*_imp->env, constraint->spec().if_block()->blocking(),
- *chosen_id, MatchPackageOptions()))
- return false;
- }
- }
- else
- {
- if (! constraint->nothing_is_fine_too())
- return false;
- }
-
- if (! decision->accept_returning<bool>(CheckUseExistingVisitor(constraint)))
- return false;
-
- if (! constraint->untaken())
- {
- if (! decision->taken())
- return false;
- }
-
- return true;
-}
-
-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());
-}
-
-namespace
-{
- struct WrongDecisionVisitor
- {
- std::tr1::function<void ()> restart;
-
- WrongDecisionVisitor(const std::tr1::function<void ()> & r) :
- restart(r)
- {
- }
-
- void visit(const NothingNoChangeDecision &) const
- {
- /* going from nothing to something is fine */
- }
-
- void visit(const UnableToMakeDecision &) const
- {
- restart();
- }
-
- void visit(const ChangesToMakeDecision &) const
- {
- restart();
- }
-
- void visit(const ExistingNoChangeDecision &) const
- {
- restart();
- }
- };
-}
-
-void
-Resolver::_made_wrong_decision(const Resolvent & resolvent,
- const std::tr1::shared_ptr<Resolution> & resolution,
- const std::tr1::shared_ptr<const Constraint> & constraint)
-{
- /* can we find a resolution that works for all our constraints? */
- std::tr1::shared_ptr<Resolution> adapted_resolution(make_shared_ptr(new Resolution(*resolution)));
- adapted_resolution->constraints()->add(constraint);
-
- const std::tr1::shared_ptr<Decision> decision(_try_to_find_decision_for(resolvent, adapted_resolution));
- if (decision)
- {
- 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);
-}
-
-void
-Resolver::_suggest_restart_with(const Resolvent & resolvent,
- const std::tr1::shared_ptr<const Resolution> & resolution,
- const std::tr1::shared_ptr<const Constraint> & constraint,
- const std::tr1::shared_ptr<const Decision> & decision) const
-{
- throw SuggestRestart(resolvent, resolution->decision(), constraint, decision,
- _make_constraint_for_preloading(resolvent, decision, constraint));
-}
-
-const std::tr1::shared_ptr<const Constraint>
-Resolver::_make_constraint_for_preloading(
- const Resolvent &,
- const std::tr1::shared_ptr<const Decision> &,
- const std::tr1::shared_ptr<const Constraint> & c) const
-{
- const std::tr1::shared_ptr<Constraint> result(new Constraint(*c));
-
- const std::tr1::shared_ptr<PresetReason> reason(new PresetReason);
- result->reason() = reason;
-
- if (result->spec().if_package())
- {
- PackageDepSpec s(_make_spec_for_preloading(*result->spec().if_package()));
- result->spec().if_package() = make_shared_ptr(new PackageDepSpec(s));
- }
- else
- {
- PackageDepSpec s(_make_spec_for_preloading(result->spec().if_block()->blocking()));
- result->spec().if_block() = make_shared_ptr(new BlockDepSpec(
- "!" + stringify(s),
- s,
- result->spec().if_block()->strong()));
- }
-
- return result;
-}
-
-const PackageDepSpec
-Resolver::_make_spec_for_preloading(const PackageDepSpec & spec) const
-{
- PartiallyMadePackageDepSpec result(spec);
-
- /* we don't want to copy use deps from the constraint, since things like
- * [foo?] start to get weird when there's no longer an associated ID. */
- result.clear_additional_requirements();
-
- return result;
-}
-
-void
-Resolver::_decide(const Resolvent & resolvent, const std::tr1::shared_ptr<Resolution> & resolution)
-{
- Context context("When deciding upon an origin ID to use for '" + stringify(resolvent) + "':");
-
- std::tr1::shared_ptr<Decision> decision(_try_to_find_decision_for(resolvent, resolution));
- if (decision)
- resolution->decision() = decision;
- else
- 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_if_necessary(
- const Resolvent & our_resolvent,
- const std::tr1::shared_ptr<Resolution> & our_resolution)
-{
- 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(*package_id) + "':");
-
- const std::tr1::shared_ptr<SanitisedDependencies> deps(new SanitisedDependencies);
- deps->populate(*this, our_resolvent, package_id);
-
- for (SanitisedDependencies::ConstIterator s(deps->begin()), s_end(deps->end()) ;
- s != s_end ; ++s)
- {
- Context context_2("When handling dependency '" + stringify(s->spec()) + "':");
-
- if (! _care_about_dependency_spec(our_resolvent, our_resolution, *s))
- continue;
-
- const std::tr1::shared_ptr<DependencyReason> reason(new DependencyReason(
- package_id, our_resolvent, *s));
-
- std::tr1::shared_ptr<const Resolvents> resolvents;
-
- if (s->spec().if_package())
- resolvents = _get_resolvents_for(*s->spec().if_package(), reason);
- else
- resolvents = _get_resolvents_for_blocker(*s->spec().if_block());
-
- if (resolvents->empty())
- {
- if (s->spec().if_package())
- resolvents = _get_error_resolvents_for(*s->spec().if_package(), reason);
- else
- {
- /* blocking on something that doesn't exist is fine */
- }
- }
-
- for (Resolvents::ConstIterator r(resolvents->begin()), r_end(resolvents->end()) ;
- r != r_end ; ++r)
- {
- const std::tr1::shared_ptr<Resolution> dep_resolution(_resolution_for_resolvent(*r, true));
- const std::tr1::shared_ptr<ConstraintSequence> constraints(_make_constraints_from_dependency(our_resolvent, *s, reason));
-
- for (ConstraintSequence::ConstIterator c(constraints->begin()), c_end(constraints->end()) ;
- c != c_end ; ++c)
- _apply_resolution_constraint(*r, dep_resolution, *c);
- }
- }
-}
-
-bool
-Resolver::_care_about_dependency_spec(const Resolvent & resolvent,
- const std::tr1::shared_ptr<const Resolution> & resolution, const SanitisedDependency & dep) const
-{
- return _imp->fns.care_about_dep_fn()(resolvent, resolution, dep);
-}
-
-namespace
-{
- struct GetDependencyReason
- {
- const DependencyReason * visit(const DependencyReason & r) const
- {
- return &r;
- }
-
- const DependencyReason * visit(const SetReason & r) const
- {
- return r.reason_for_set()->accept_returning<const DependencyReason *>(*this);
- }
-
- const DependencyReason * visit(const TargetReason &) const
- {
- return 0;
- }
-
- const DependencyReason * visit(const PresetReason &) const
- {
- return 0;
- }
- };
-
- struct ArrowInfo
- {
- bool causes_pre_arrow;
- bool ignorable;
-
- ArrowInfo(const DependencyReason & reason) :
- causes_pre_arrow(false),
- ignorable(true)
- {
- std::for_each(indirect_iterator(reason.sanitised_dependency().active_dependency_labels()->begin()),
- indirect_iterator(reason.sanitised_dependency().active_dependency_labels()->end()), accept_visitor(*this));
- }
-
- void visit(const DependenciesBuildLabel &)
- {
- causes_pre_arrow = true;
- ignorable = false;
- }
-
- void visit(const DependenciesTestLabel &)
- {
- causes_pre_arrow = true;
- ignorable = false;
- }
-
- void visit(const DependenciesRunLabel &)
- {
- causes_pre_arrow = true;
- }
-
- void visit(const DependenciesPostLabel &)
- {
- }
-
- void visit(const DependenciesInstallLabel &)
- {
- causes_pre_arrow = true;
- ignorable = false;
- }
-
- void visit(const DependenciesCompileAgainstLabel &)
- {
- causes_pre_arrow = true;
- ignorable = false;
- }
-
- void visit(const DependenciesFetchLabel &)
- {
- causes_pre_arrow = true;
- ignorable = false;
- }
-
- void visit(const DependenciesRecommendationLabel &)
- {
- }
-
- void visit(const DependenciesSuggestionLabel &)
- {
- }
- };
-}
-
-void
-Resolver::_resolve_arrows()
-{
- Context context("When creating arrows for order resolution:");
-
- for (ResolutionsByResolventMap::iterator i(_imp->resolutions_by_resolvent.begin()), i_end(_imp->resolutions_by_resolvent.end()) ;
- i != i_end ; ++i)
- for (Constraints::ConstIterator c(i->second->constraints()->begin()),
- c_end(i->second->constraints()->end()) ;
- c != c_end ; ++c)
- _resolve_arrow(i->first, i->second, *c);
-}
-
-void
-Resolver::_resolve_arrow(
- const Resolvent & resolvent,
- const std::tr1::shared_ptr<Resolution> &,
- const std::tr1::shared_ptr<const Constraint> & constraint)
-{
- GetDependencyReason gdr;
- const DependencyReason * if_dependency_reason(constraint->reason()->accept_returning<const DependencyReason *>(gdr));
- if (! if_dependency_reason)
- return;
-
- const Resolvent from_resolvent(if_dependency_reason->from_resolvent());
- const std::tr1::shared_ptr<Resolution> resolution(_resolution_for_resolvent(from_resolvent, false));
-
- /* deps between binaries don't count */
- if (resolvent.destination_type() == dt_create_binary &&
- if_dependency_reason->from_resolvent().destination_type() == dt_create_binary)
- return;
-
- if (constraint->spec().if_block())
- {
- if (constraint->spec().if_block()->strong())
- {
- resolution->arrows()->push_back(make_shared_ptr(new Arrow(make_named_values<Arrow>(
- value_for<n::comes_after>(resolvent),
- value_for<n::ignorable_pass>(0),
- value_for<n::reason>(constraint->reason())
- ))));
- }
- }
- else
- {
- ArrowInfo a(*if_dependency_reason);
- if (a.causes_pre_arrow)
- {
- int ignorable_pass(0);
- if (_already_met(if_dependency_reason->sanitised_dependency()))
- ignorable_pass = 1;
- else if (a.ignorable)
- ignorable_pass = 2;
-
- resolution->arrows()->push_back(make_shared_ptr(new Arrow(make_named_values<Arrow>(
- value_for<n::comes_after>(resolvent),
- value_for<n::ignorable_pass>(ignorable_pass),
- value_for<n::reason>(constraint->reason())
- ))));
- }
- }
-}
-
-bool
-Resolver::_already_met(const SanitisedDependency & dep) const
-{
- if (dep.spec().if_package())
- {
- std::tr1::shared_ptr<const PackageIDSequence> ids((*_imp->env)[selection::SomeArbitraryVersion(
- generator::Matches(*dep.spec().if_package(), MatchPackageOptions()) |
- filter::InstalledAtRoot(FSEntry("/")))]);
- return ! ids->empty();
- }
- else if (dep.spec().if_block())
- {
- /* it's imposing an arrow, so it's a strong block */
- return false;
- }
- else
- throw InternalError(PALUDIS_HERE, "resolver bug: huh? it's not a block and it's not a package");
-}
-
-namespace
-{
- struct ResolveOrderVisitor
- {
- 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)
- {
- }
-
- void visit(const ExistingNoChangeDecision &) const
- {
- already_ordered();
- }
-
- void visit(const NothingNoChangeDecision &) const
- {
- already_ordered();
- }
-
- 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();
- }
- }
- };
+ _imp->decider->add_target_with_reason(**s, reason);
}
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);
- done = true;
-
- int ignore_pass(0);
- while (true)
- {
- for (ResolutionsByResolventMap::iterator i(_imp->resolutions_by_resolvent.begin()), i_end(_imp->resolutions_by_resolvent.end()) ;
- i != i_end ; ++i)
- {
- if (i->second->already_ordered())
- continue;
-
- if (_can_order_now(i->first, i->second, ignore_pass))
- {
- if (0 != ignore_pass)
- Log::get_instance()->message("resolver.cycle_breaking", ll_warning, lc_context)
- << "Had to use cycle breaking with ignore pass " << ignore_pass
- << " to order " << i->first << " because of cycle "
- << _find_cycle(i->first, false);
-
- _imp->env->trigger_notifier_callback(NotifierCallbackResolverStepEvent());
- _do_order(i->first, i->second);
- any = true;
-
- if (0 != ignore_pass)
- break;
- }
- else
- done = false;
- }
-
- if ((! done) && (! any))
- {
- if (ignore_pass >= 2)
- _unable_to_order_more();
- else
- ++ignore_pass;
- }
- else
- break;
- }
- }
-}
-
-bool
-Resolver::_can_order_now(const Resolvent &, const std::tr1::shared_ptr<const Resolution> & resolution,
- const int ignorable_pass) const
+Resolver::resolve()
{
- for (ArrowSequence::ConstIterator a(resolution->arrows()->begin()), a_end(resolution->arrows()->end()) ;
- a != a_end ; ++a)
- {
- if (0 != (*a)->ignorable_pass())
- if ((*a)->ignorable_pass() <= ignorable_pass)
- continue;
-
- const std::tr1::shared_ptr<const Resolution> dep_resolution(_resolution_for_resolvent((*a)->comes_after()));
- if (! dep_resolution->already_ordered())
- return false;
- }
+ _imp->decider->resolve();
- return true;
+ _imp->orderer.reset(new Orderer(_imp->env, _imp->decider, *_imp->lists));
+ _imp->orderer->resolve();
}
-void
-Resolver::_do_order(const Resolvent &, const std::tr1::shared_ptr<Resolution> & resolution)
+const std::tr1::shared_ptr<const ResolverLists>
+Resolver::lists() const
{
- _imp->resolution_lists->ordered()->append(resolution);
- resolution->already_ordered() = true;
+ return _imp->lists;
}
void
-Resolver::_unable_to_order_more() const
-{
- std::cout << "Unable to order any of the following:" << std::endl;
-
- for (ResolutionsByResolventMap::const_iterator i(_imp->resolutions_by_resolvent.begin()), i_end(_imp->resolutions_by_resolvent.end()) ;
- i != i_end ; ++i)
- {
- if (i->second->already_ordered())
- continue;
-
- std::cout << " * " << i->first << " because of cycle "
- << _find_cycle(i->first, true)
- << std::endl;
- }
-
- throw InternalError(PALUDIS_HERE, "unimplemented: unfixable dep cycle");
-}
-
-const std::tr1::shared_ptr<Constraints>
-Resolver::_initial_constraints_for(const Resolvent & r) const
-{
- return _imp->fns.get_initial_constraints_for_fn()(r);
-}
-
-Resolver::ResolutionsByResolventConstIterator
-Resolver::begin_resolutions_by_resolvent() const
-{
- return ResolutionsByResolventConstIterator(_imp->resolutions_by_resolvent.begin());
-}
-
-Resolver::ResolutionsByResolventConstIterator
-Resolver::end_resolutions_by_resolvent() const
-{
- return ResolutionsByResolventConstIterator(_imp->resolutions_by_resolvent.end());
-}
-
-int
-Resolver::find_any_score(const Resolvent & our_resolvent, const SanitisedDependency & dep) const
-{
- Context context("When working out whether we'd like '" + stringify(dep.spec()) + "' because of '"
- + stringify(our_resolvent) + "':");
-
- if (dep.spec().if_block())
- throw InternalError(PALUDIS_HERE, "unimplemented: blockers inside || blocks are horrid");
-
- const PackageDepSpec & spec(*dep.spec().if_package());
-
- int operator_bias(0);
- if (spec.version_requirements_ptr() && ! spec.version_requirements_ptr()->empty())
- {
- int score(-1);
- for (VersionRequirements::ConstIterator v(spec.version_requirements_ptr()->begin()),
- v_end(spec.version_requirements_ptr()->end()) ;
- v != v_end ; ++v)
- {
- int local_score(0);
-
- switch (v->version_operator().value())
- {
- case vo_greater:
- case vo_greater_equal:
- local_score = 9;
- break;
-
- case vo_equal:
- case vo_tilde:
- case vo_nice_equal_star:
- case vo_stupid_equal_star:
- case vo_tilde_greater:
- local_score = 2;
- break;
-
- case vo_less_equal:
- case vo_less:
- local_score = 1;
- break;
-
- case last_vo:
- local_score = 1;
- break;
- }
-
- if (score == -1)
- score = local_score;
- else
- switch (spec.version_requirements_mode())
- {
- case vr_and:
- score = std::min(score, local_score);
- break;
-
- case vr_or:
- score = std::max(score, local_score);
- break;
-
- case last_vr:
- break;
- }
- }
- operator_bias = score;
- }
- else
- {
- /* don't bias no operator over a >= operator, so || ( >=foo-2 bar )
- * still likes foo. */
- operator_bias = 9;
- }
-
- /* best: already installed */
- {
- const std::tr1::shared_ptr<const PackageIDSequence> installed_ids((*_imp->env)[selection::BestVersionOnly(
- generator::Matches(spec, MatchPackageOptions()) |
- filter::InstalledAtRoot(FSEntry("/")))]);
- if (! installed_ids->empty())
- return 50 + operator_bias;
- }
-
- /* next: already installed, except with the wrong options */
- if (spec.additional_requirements_ptr())
- {
- const std::tr1::shared_ptr<const PackageIDSequence> installed_ids((*_imp->env)[selection::BestVersionOnly(
- generator::Matches(spec, MatchPackageOptions() + mpo_ignore_additional_requirements) |
- filter::InstalledAtRoot(FSEntry("/")))]);
- if (! installed_ids->empty())
- return 40 + operator_bias;
- }
-
- 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 */
- {
- for (Resolvents::ConstIterator r(resolvents->begin()), r_end(resolvents->end()) ;
- r != r_end ; ++r)
- {
- ResolutionsByResolventMap::const_iterator i(_imp->resolutions_by_resolvent.find(*r));
- if (i != _imp->resolutions_by_resolvent.end())
- return 30 + operator_bias;
- }
- }
-
- /* next: could install */
- {
- for (Resolvents::ConstIterator r(resolvents->begin()), r_end(resolvents->end()) ;
- r != r_end ; ++r)
- {
- const std::tr1::shared_ptr<Resolution> resolution(_create_resolution_for_resolvent(*r));
- const std::tr1::shared_ptr<ConstraintSequence> constraints(_make_constraints_from_dependency(our_resolvent, dep, reason));
- for (ConstraintSequence::ConstIterator c(constraints->begin()), c_end(constraints->end()) ;
- c != c_end ; ++c)
- resolution->constraints()->add(*c);
- const std::tr1::shared_ptr<Decision> decision(_try_to_find_decision_for(*r, resolution));
- if (decision)
- return 20 + operator_bias;
- }
- }
-
- /* next: exists */
- {
- const std::tr1::shared_ptr<const PackageIDSequence> ids((*_imp->env)[selection::BestVersionOnly(
- generator::Matches(spec, MatchPackageOptions() + mpo_ignore_additional_requirements)
- )]);
- if (! ids->empty())
- return 10 + operator_bias;
- }
-
- /* yay, people are depping upon packages that don't exist again. I SMELL A LESSPIPE. */
- return 0;
-}
-
-namespace
-{
- struct ReasonDescriber
- {
- const std::string visit(const DependencyReason & r) const
- {
- return " (" + r.sanitised_dependency().active_dependency_labels_as_string() + " " +
- stringify(r.sanitised_dependency().spec()) + ")";
- }
-
- const std::string visit(const TargetReason &) const
- {
- return "";
- }
-
- const std::string visit(const PresetReason &) const
- {
- return "";
- }
-
- const std::string visit(const SetReason &) const
- {
- return "";
- }
- };
-}
-
-const std::string
-Resolver::_find_cycle(const Resolvent & start_resolvent, const int ignorable_pass) const
-{
- std::stringstream result;
-
- std::set<Resolvent> seen;
- Resolvent current(start_resolvent);
-
- bool first(true);
- while (true)
- {
- if (! first)
- result << " -> ";
- first = false;
-
- result << current;
-
- if (! seen.insert(current).second)
- break;
-
- bool ok(false);
- const std::tr1::shared_ptr<const Resolution> resolution(_resolution_for_resolvent(current));
- for (ArrowSequence::ConstIterator a(resolution->arrows()->begin()), a_end(resolution->arrows()->end()) ;
- a != a_end ; ++a)
- {
- if (_can_order_now(current, resolution, ignorable_pass))
- continue;
-
- const std::tr1::shared_ptr<const Resolution> to_resolution(_resolution_for_resolvent((*a)->comes_after()));
- if (to_resolution->already_ordered())
- continue;
-
- ok = true;
- result << (*a)->reason()->accept_returning<std::string>(ReasonDescriber());
- current = (*a)->comes_after();
- break;
- }
-
- if (! ok)
- throw InternalError(PALUDIS_HERE, "resolver bug: there's a cycle, but we don't know what it is");
- }
-
- return result.str();
-}
-
-namespace
-{
- struct SlotNameFinder
- {
- std::tr1::shared_ptr<SlotName> visit(const SlotExactRequirement & s)
- {
- return make_shared_ptr(new SlotName(s.slot()));
- }
-
- std::tr1::shared_ptr<SlotName> visit(const SlotAnyUnlockedRequirement &)
- {
- return make_null_shared_ptr();
- }
-
- std::tr1::shared_ptr<SlotName> visit(const SlotAnyLockedRequirement &)
- {
- return make_null_shared_ptr();
- }
- };
-}
-
-const std::tr1::shared_ptr<const Resolvents>
-Resolver::_get_resolvents_for_blocker(const BlockDepSpec & spec) const
-{
- Context context("When finding slots for '" + stringify(spec) + "':");
-
- std::tr1::shared_ptr<SlotName> exact_slot;
- if (spec.blocking().slot_requirement_ptr())
- {
- SlotNameFinder f;
- exact_slot = spec.blocking().slot_requirement_ptr()->accept_returning<std::tr1::shared_ptr<SlotName> >(f);
- }
-
- DestinationTypes destination_types(_get_destination_types_for_blocker(spec));
- std::tr1::shared_ptr<Resolvents> result(new Resolvents);
- if (exact_slot)
- {
- for (EnumIterator<DestinationType> t, t_end(last_dt) ; t != t_end ; ++t)
- if (destination_types[*t])
- result->push_back(Resolvent(spec.blocking(), *exact_slot, *t));
- }
- else
- {
- const std::tr1::shared_ptr<const PackageIDSequence> ids((*_imp->env)[selection::BestVersionInEachSlot(
- generator::Package(*spec.blocking().package_ptr())
- )]);
- for (PackageIDSequence::ConstIterator i(ids->begin()), i_end(ids->end()) ;
- i != i_end ; ++i)
- for (EnumIterator<DestinationType> t, t_end(last_dt) ; t != t_end ; ++t)
- if (destination_types[*t])
- result->push_back(Resolvent(*i, *t));
- }
-
- return result;
-}
-
-const DestinationTypes
-Resolver::_get_destination_types_for_blocker(const BlockDepSpec &) const
-{
- return DestinationTypes() + dt_install_to_slash;
-}
-
-const std::tr1::shared_ptr<const Resolvents>
-Resolver::_get_resolvents_for(
- const PackageDepSpec & spec,
- const std::tr1::shared_ptr<const Reason> & reason) const
-{
- Context context("When finding slots for '" + stringify(spec) + "':");
-
- std::tr1::shared_ptr<SlotName> exact_slot;
-
- if (spec.slot_requirement_ptr())
- {
- SlotNameFinder f;
- exact_slot = spec.slot_requirement_ptr()->accept_returning<std::tr1::shared_ptr<SlotName> >(f);
- }
-
- return _imp->fns.get_resolvents_for_fn()(spec, exact_slot, reason);
-}
-
-const DestinationTypes
-Resolver::_get_destination_types_for(
- const PackageDepSpec & spec,
- const std::tr1::shared_ptr<const PackageID> & id,
- const std::tr1::shared_ptr<const Reason> & reason) const
-{
- return _imp->fns.get_destination_types_for_fn()(spec, id, reason);
-}
-
-const std::tr1::shared_ptr<const Resolvents>
-Resolver::_get_error_resolvents_for(
- const PackageDepSpec & spec,
- const std::tr1::shared_ptr<const Reason> & reason) const
-{
- Context context("When finding slots for '" + stringify(spec) + "', which can't be found the normal way:");
-
- std::tr1::shared_ptr<Resolvents> result(new Resolvents);
- DestinationTypes destination_types(_get_destination_types_for(spec, make_null_shared_ptr(), reason));
- for (EnumIterator<DestinationType> t, t_end(last_dt) ; t != t_end ; ++t)
- if (destination_types[*t])
- result->push_back(Resolvent(spec, true, *t));
- return result;
-}
-
-const std::tr1::shared_ptr<Decision>
-Resolver::_try_to_find_decision_for(
- const Resolvent & resolvent,
- const std::tr1::shared_ptr<const Resolution> & resolution) const
+ResolverLists::serialise(Serialiser & s) const
{
- const std::tr1::shared_ptr<const PackageID> existing_id(_find_existing_id_for(resolvent, resolution));
- std::pair<const std::tr1::shared_ptr<const PackageID>, bool> installable_id_best(_find_installable_id_for(resolvent, resolution));
- const std::tr1::shared_ptr<const PackageID> installable_id(installable_id_best.first);
- bool best(installable_id_best.second);
-
- if (resolution->constraints()->nothing_is_fine_too() && ! existing_id)
- {
- /* nothing existing, but nothing's ok */
- 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 ChangesToMakeDecision(
- installable_id,
- best,
- ! resolution->constraints()->all_untaken(),
- make_null_shared_ptr()
- ));
- }
- else if (existing_id && ! installable_id)
- {
- /* there's nothing installable. this may or may not be ok. */
- bool is_transient(existing_id->transient_key() && existing_id->transient_key()->value());
-
- switch (resolution->constraints()->strictest_use_existing())
- {
- case ue_if_possible:
- break;
-
- case ue_only_if_transient:
- case ue_if_same:
- case ue_if_same_version:
- if (! is_transient)
- return make_null_shared_ptr();
- break;
-
- case ue_never:
- return make_null_shared_ptr();
-
- case last_ue:
- break;
- }
-
- return make_shared_ptr(new ExistingNoChangeDecision(
- existing_id,
- true,
- true,
- is_transient,
- ! resolution->constraints()->all_untaken()
- ));
- }
- else if ((! existing_id) && (! installable_id))
- {
- return make_null_shared_ptr();
- }
- else if (existing_id && installable_id)
- {
- bool is_same_version(existing_id->version() == installable_id->version());
- bool is_same(false);
-
- if (is_same_version)
- {
- is_same = true;
-
- std::set<ChoiceNameWithPrefix> common;
- if (existing_id->choices_key() && installable_id->choices_key())
- {
- std::set<ChoiceNameWithPrefix> i_common, u_common;
- for (Choices::ConstIterator k(installable_id->choices_key()->value()->begin()),
- k_end(installable_id->choices_key()->value()->end()) ;
- k != k_end ; ++k)
- {
- if (! (*k)->consider_added_or_changed())
- continue;
-
- for (Choice::ConstIterator i((*k)->begin()), i_end((*k)->end()) ;
- i != i_end ; ++i)
- if ((*i)->explicitly_listed())
- i_common.insert((*i)->name_with_prefix());
- }
-
- for (Choices::ConstIterator k(existing_id->choices_key()->value()->begin()),
- k_end(existing_id->choices_key()->value()->end()) ;
- k != k_end ; ++k)
- {
- if (! (*k)->consider_added_or_changed())
- continue;
-
- for (Choice::ConstIterator i((*k)->begin()), i_end((*k)->end()) ;
- i != i_end ; ++i)
- if ((*i)->explicitly_listed())
- u_common.insert((*i)->name_with_prefix());
- }
-
- std::set_intersection(
- i_common.begin(), i_common.end(),
- u_common.begin(), u_common.end(),
- std::inserter(common, common.begin()));
- }
-
- for (std::set<ChoiceNameWithPrefix>::const_iterator f(common.begin()), f_end(common.end()) ;
- f != f_end ; ++f)
- if (installable_id->choices_key()->value()->find_by_name_with_prefix(*f)->enabled() !=
- existing_id->choices_key()->value()->find_by_name_with_prefix(*f)->enabled())
- {
- is_same = false;
- break;
- }
- }
-
- 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 ChangesToMakeDecision(
- installable_id,
- best,
- ! resolution->constraints()->all_untaken(),
- make_null_shared_ptr()
- ));
-
- case ue_if_same:
- if (is_same)
- return existing;
- else
- return changes_to_make;
-
- case ue_if_same_version:
- if (is_same_version)
- return existing;
- else
- return changes_to_make;
-
- case ue_if_possible:
- return existing;
-
- case last_ue:
- break;
- }
- }
-
- throw InternalError(PALUDIS_HERE, "resolver bug: shouldn't be reached");
+ s.object("ResolverLists")
+ .member(SerialiserFlags<serialise::might_be_null>(), "all", all())
+ .member(SerialiserFlags<serialise::might_be_null>(), "errors", errors())
+ .member(SerialiserFlags<serialise::might_be_null>(), "ordered", ordered())
+ .member(SerialiserFlags<serialise::might_be_null>(), "untaken", untaken())
+ ;
}
-const std::tr1::shared_ptr<Decision>
-Resolver::_cannot_decide_for(
- const Resolvent & resolvent,
- const std::tr1::shared_ptr<const Resolution> & resolution) const
+const ResolverLists
+ResolverLists::deserialise(Deserialisation & d)
{
- 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))
+ Deserialisator v(d, "ResolverLists");
+ return make_named_values<ResolverLists>(
+ value_for<n::all>(v.member<std::tr1::shared_ptr<Resolutions> >("all")),
+ value_for<n::errors>(v.member<std::tr1::shared_ptr<Resolutions> >("errors")),
+ value_for<n::ordered>(v.member<std::tr1::shared_ptr<Resolutions> >("ordered")),
+ value_for<n::untaken>(v.member<std::tr1::shared_ptr<Resolutions> >("untaken"))
);
}
-const std::tr1::shared_ptr<const PackageID>
-Resolver::_find_existing_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(
- _make_destination_filtered_generator(generator::Package(resolvent.package()), resolvent) |
- make_slot_filter(resolvent)
- )]);
-
- 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
-{
- 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>
-Resolver::_find_id_for_from(
- const Resolvent &, const std::tr1::shared_ptr<const Resolution> & resolution,
- const std::tr1::shared_ptr<const PackageIDSequence> & ids) const
-{
- bool best(true);
- for (PackageIDSequence::ReverseConstIterator i(ids->rbegin()), i_end(ids->rend()) ;
- i != i_end ; ++i)
- {
- bool ok(true);
- for (Constraints::ConstIterator c(resolution->constraints()->begin()),
- c_end(resolution->constraints()->end()) ;
- c != c_end ; ++c)
- {
- if ((*c)->spec().if_package())
- ok = ok && match_package(*_imp->env, *(*c)->spec().if_package(), **i, MatchPackageOptions());
- else
- ok = ok && ! match_package(*_imp->env, (*c)->spec().if_block()->blocking(), **i, MatchPackageOptions());
-
- if (! ok)
- break;
- }
-
- if (ok)
- return std::make_pair(*i, best);
-
- best = false;
- }
-
- return std::make_pair(make_null_shared_ptr(), false);
-}
-
-const std::tr1::shared_ptr<const ResolutionLists>
-Resolver::resolution_lists() const
-{
- return _imp->resolution_lists;
-}
-
-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;
-}
-
-const std::tr1::shared_ptr<const RewrittenSpec>
-Resolver::rewrite_if_special(
- const PackageOrBlockDepSpec & spec,
- const std::tr1::shared_ptr<const Resolvent> & maybe_from) const
-{
- return _imp->rewriter.rewrite_if_special(spec, maybe_from);
-}
-
-template class WrappedForwardIterator<Resolver::ResolutionsByResolventConstIteratorTag,
- const std::pair<const Resolvent, std::tr1::shared_ptr<Resolution> > >;
-
diff --git a/paludis/resolver/resolver.hh b/paludis/resolver/resolver.hh
index 861b54c..1b95696 100644
--- a/paludis/resolver/resolver.hh
+++ b/paludis/resolver/resolver.hh
@@ -21,21 +21,13 @@
#define PALUDIS_GUARD_PALUDIS_RESOLVER_RESOLVER_HH 1
#include <paludis/resolver/resolver-fwd.hh>
-#include <paludis/resolver/resolution-fwd.hh>
-#include <paludis/resolver/resolvent-fwd.hh>
-#include <paludis/resolver/constraint-fwd.hh>
-#include <paludis/resolver/sanitised_dependencies-fwd.hh>
-#include <paludis/resolver/decision-fwd.hh>
#include <paludis/resolver/reason-fwd.hh>
-#include <paludis/resolver/use_existing-fwd.hh>
-#include <paludis/resolver/resolutions-fwd.hh>
#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/resolver/spec_rewriter-fwd.hh>
+#include <paludis/resolver/decider-fwd.hh>
+#include <paludis/resolver/orderer-fwd.hh>
+#include <paludis/resolver/resolutions-fwd.hh>
#include <paludis/util/private_implementation_pattern.hh>
-#include <paludis/util/wrapped_forward_iterator-fwd.hh>
+#include <paludis/util/named_value.hh>
#include <paludis/package_id-fwd.hh>
#include <paludis/dep_spec-fwd.hh>
#include <paludis/name.hh>
@@ -48,175 +40,42 @@
namespace paludis
{
+ namespace n
+ {
+ struct all;
+ struct errors;
+ struct ordered;
+ struct untaken;
+ }
+
namespace resolver
{
- class PALUDIS_VISIBLE Resolver :
- private PrivateImplementationPattern<Resolver>
+ struct ResolverLists
{
- private:
- const std::tr1::shared_ptr<Resolution> _create_resolution_for_resolvent(const Resolvent &) const;
- const std::tr1::shared_ptr<Resolution> _resolution_for_resolvent(const Resolvent &, const bool create);
- const std::tr1::shared_ptr<Resolution> _resolution_for_resolvent(const Resolvent &) const;
-
- const std::tr1::shared_ptr<const Resolvents> _get_resolvents_for_blocker(const BlockDepSpec &) const;
-
- const DestinationTypes _get_destination_types_for_blocker(const BlockDepSpec &) const;
-
- const std::tr1::shared_ptr<const Resolvents> _get_resolvents_for(
- const PackageDepSpec & spec,
- const std::tr1::shared_ptr<const Reason> & reason) const;
-
- const DestinationTypes _get_destination_types_for(
- const PackageDepSpec & spec,
- const std::tr1::shared_ptr<const PackageID> &,
- const std::tr1::shared_ptr<const Reason> &) const;
-
- const std::tr1::shared_ptr<const Resolvents> _get_error_resolvents_for(
- const PackageDepSpec & spec,
- const std::tr1::shared_ptr<const Reason> & reason) const;
-
- const std::tr1::shared_ptr<ConstraintSequence> _make_constraints_from_target(
- const Resolvent &,
- const PackageDepSpec &,
- const std::tr1::shared_ptr<const Reason> &) const;
-
- const std::tr1::shared_ptr<ConstraintSequence> _make_constraints_from_dependency(
- const Resolvent &, const SanitisedDependency &,
- const std::tr1::shared_ptr<const Reason> &) const;
-
- void _apply_resolution_constraint(const Resolvent &,
- 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> &);
-
- void _made_wrong_decision(const Resolvent &,
- const std::tr1::shared_ptr<Resolution> & resolution,
- const std::tr1::shared_ptr<const Constraint> & constraint);
-
- void _suggest_restart_with(const Resolvent &,
- const std::tr1::shared_ptr<const Resolution> & resolution,
- const std::tr1::shared_ptr<const Constraint> & constraint,
- const std::tr1::shared_ptr<const Decision> & decision) const PALUDIS_ATTRIBUTE((noreturn));
-
- const std::tr1::shared_ptr<const Constraint> _make_constraint_for_preloading(
- const Resolvent &,
- const std::tr1::shared_ptr<const Decision> & d,
- const std::tr1::shared_ptr<const Constraint> & c) const;
-
- const PackageDepSpec _make_spec_for_preloading(const PackageDepSpec & spec) const;
-
- const std::tr1::shared_ptr<const PackageIDSequence> _find_replacing(
- const std::tr1::shared_ptr<const PackageID> &,
- const std::tr1::shared_ptr<const Repository> &) const;
-
- const std::tr1::shared_ptr<const Repository> _find_repository_for(
- const Resolvent &,
- 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> &);
-
- void _resolve_decide_with_dependencies();
- void _resolve_destinations();
- void _resolve_arrows();
- void _resolve_order();
+ NamedValue<n::all, std::tr1::shared_ptr<Resolutions> > all;
+ NamedValue<n::errors, std::tr1::shared_ptr<Resolutions> > errors;
+ NamedValue<n::ordered, std::tr1::shared_ptr<Resolutions> > ordered;
+ NamedValue<n::untaken, std::tr1::shared_ptr<Resolutions> > untaken;
- const std::tr1::shared_ptr<Destination> _make_destination_for(
- const Resolvent & resolvent,
- const std::tr1::shared_ptr<const Resolution> & resolution,
- const ChangesToMakeDecision &) const;
-
- FilteredGenerator _make_destination_filtered_generator(const Generator &, const Resolvent & resolvent) const;
-
- void _decide(const Resolvent &, const std::tr1::shared_ptr<Resolution> & resolution);
-
- const std::tr1::shared_ptr<Decision> _try_to_find_decision_for(
- const Resolvent &, const std::tr1::shared_ptr<const Resolution> & resolution) const;
-
- const std::tr1::shared_ptr<Decision> _cannot_decide_for(
- const Resolvent &, const std::tr1::shared_ptr<const Resolution> & resolution) const;
-
- 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> &,
- const SanitisedDependency &) const;
-
- bool _causes_pre_arrow(const DependencyReason &) const;
-
- bool _can_order_now(const Resolvent &, const std::tr1::shared_ptr<const Resolution> & resolution,
- const int ignorable_pass) const;
-
- void _do_order(const Resolvent &, const std::tr1::shared_ptr<Resolution> & resolution);
-
- void _unable_to_order_more() const PALUDIS_ATTRIBUTE((noreturn));
-
- const std::tr1::shared_ptr<Constraints> _initial_constraints_for(const Resolvent &) const;
-
- bool _same_slot(const std::tr1::shared_ptr<const PackageID> & a,
- const std::tr1::shared_ptr<const PackageID> & b) const;
-
- bool _already_met(const SanitisedDependency & dep) const;
-
- const std::string _find_cycle(const Resolvent &, const int ignorable_pass) const;
-
- 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;
+ static const ResolverLists deserialise(Deserialisation &) PALUDIS_ATTRIBUTE((warn_unused_result));
+ void serialise(Serialiser &) const;
+ };
+ class PALUDIS_VISIBLE Resolver :
+ private PrivateImplementationPattern<Resolver>
+ {
public:
Resolver(
const Environment * const,
const ResolverFunctions &);
~Resolver();
- void add_target_with_reason(const PackageDepSpec &, const std::tr1::shared_ptr<const Reason> &);
void add_target(const PackageDepSpec &);
void add_target(const SetName &);
void resolve();
- const std::tr1::shared_ptr<const ResolutionLists> resolution_lists() const PALUDIS_ATTRIBUTE((warn_unused_result));
-
- struct ResolutionsByResolventConstIteratorTag;
- typedef WrappedForwardIterator<ResolutionsByResolventConstIteratorTag,
- const std::pair<const Resolvent, std::tr1::shared_ptr<Resolution> > >
- ResolutionsByResolventConstIterator;
- ResolutionsByResolventConstIterator begin_resolutions_by_resolvent() const
- PALUDIS_ATTRIBUTE((warn_unused_result));
- ResolutionsByResolventConstIterator end_resolutions_by_resolvent() const
- PALUDIS_ATTRIBUTE((warn_unused_result));
-
- int find_any_score(const Resolvent &, const SanitisedDependency &) const;
-
- const std::tr1::shared_ptr<const RewrittenSpec> rewrite_if_special(const PackageOrBlockDepSpec &,
- const std::tr1::shared_ptr<const Resolvent> & maybe_from) const;
+ const std::tr1::shared_ptr<const ResolverLists> lists() const PALUDIS_ATTRIBUTE((warn_unused_result));
};
}
}
diff --git a/paludis/resolver/resolver_TEST_blockers.cc b/paludis/resolver/resolver_TEST_blockers.cc
index 3f53739..24c067d 100644
--- a/paludis/resolver/resolver_TEST_blockers.cc
+++ b/paludis/resolver/resolver_TEST_blockers.cc
@@ -74,7 +74,7 @@ namespace test_cases
install("hard", "a-pkg", "1");
install("hard", "z-pkg", "1");
- std::tr1::shared_ptr<const ResolutionLists> resolutions(get_resolutions("hard/target"));
+ std::tr1::shared_ptr<const ResolverLists> resolutions(get_resolutions("hard/target"));
{
TestMessageSuffix s("errors");
diff --git a/paludis/resolver/resolver_TEST_serialisation.cc b/paludis/resolver/resolver_TEST_serialisation.cc
index 38bcad6..4fb26b6 100644
--- a/paludis/resolver/resolver_TEST_serialisation.cc
+++ b/paludis/resolver/resolver_TEST_serialisation.cc
@@ -72,16 +72,16 @@ namespace test_cases
void run()
{
- std::tr1::shared_ptr<const ResolutionLists> resolutions;
+ std::tr1::shared_ptr<const ResolverLists> resolutions;
{
- std::tr1::shared_ptr<const ResolutionLists> orig_resolutions(get_resolutions("serialisation/target"));
+ std::tr1::shared_ptr<const ResolverLists> orig_resolutions(get_resolutions("serialisation/target"));
std::stringstream str;
Serialiser ser(str);
orig_resolutions->serialise(ser);
Deserialiser deser(&env, str.str());
- Deserialisation desern("ResolutionLists", deser);
- resolutions = make_shared_ptr(new ResolutionLists(ResolutionLists::deserialise(desern)));
+ Deserialisation desern("ResolverLists", deser);
+ resolutions = make_shared_ptr(new ResolverLists(ResolverLists::deserialise(desern)));
}
{
diff --git a/paludis/resolver/resolver_TEST_suggestions.cc b/paludis/resolver/resolver_TEST_suggestions.cc
index ef5e976..5ebbe7c 100644
--- a/paludis/resolver/resolver_TEST_suggestions.cc
+++ b/paludis/resolver/resolver_TEST_suggestions.cc
@@ -71,7 +71,7 @@ namespace test_cases
void run()
{
- std::tr1::shared_ptr<const ResolutionLists> resolutions(get_resolutions("suggestion/target"));
+ std::tr1::shared_ptr<const ResolverLists> resolutions(get_resolutions("suggestion/target"));
{
TestMessageSuffix s("errors");
@@ -104,7 +104,7 @@ namespace test_cases
void run()
{
- std::tr1::shared_ptr<const ResolutionLists> resolutions(get_resolutions("unmeetable-suggestion/target"));
+ std::tr1::shared_ptr<const ResolverLists> resolutions(get_resolutions("unmeetable-suggestion/target"));
{
TestMessageSuffix s("errors");
@@ -137,7 +137,7 @@ namespace test_cases
void run()
{
- std::tr1::shared_ptr<const ResolutionLists> resolutions(get_resolutions("suggestion-then-dependency/target"));
+ std::tr1::shared_ptr<const ResolverLists> resolutions(get_resolutions("suggestion-then-dependency/target"));
{
TestMessageSuffix s("errors");
diff --git a/paludis/resolver/resolver_TEST_virtuals.cc b/paludis/resolver/resolver_TEST_virtuals.cc
index a50aa5e..ad7c933 100644
--- a/paludis/resolver/resolver_TEST_virtuals.cc
+++ b/paludis/resolver/resolver_TEST_virtuals.cc
@@ -71,7 +71,7 @@ namespace test_cases
void run()
{
- std::tr1::shared_ptr<const ResolutionLists> resolutions(get_resolutions("virtuals/target"));
+ std::tr1::shared_ptr<const ResolverLists> resolutions(get_resolutions("virtuals/target"));
{
TestMessageSuffix s("errors");
@@ -104,7 +104,7 @@ namespace test_cases
void run()
{
- std::tr1::shared_ptr<const ResolutionLists> resolutions(get_resolutions("virtual/virtual-target"));
+ std::tr1::shared_ptr<const ResolverLists> resolutions(get_resolutions("virtual/virtual-target"));
{
TestMessageSuffix s("errors");
diff --git a/paludis/resolver/resolver_functions.hh b/paludis/resolver/resolver_functions.hh
index 04d5e28..e544282 100644
--- a/paludis/resolver/resolver_functions.hh
+++ b/paludis/resolver/resolver_functions.hh
@@ -25,8 +25,13 @@
#include <paludis/resolver/resolution-fwd.hh>
#include <paludis/resolver/resolvent-fwd.hh>
#include <paludis/resolver/reason-fwd.hh>
+#include <paludis/resolver/sanitised_dependencies-fwd.hh>
+#include <paludis/resolver/decision-fwd.hh>
+#include <paludis/resolver/destination_types-fwd.hh>
+#include <paludis/resolver/constraint-fwd.hh>
#include <paludis/util/named_value.hh>
#include <paludis/filter-fwd.hh>
+#include <paludis/name-fwd.hh>
#include <tr1/functional>
namespace paludis
diff --git a/paludis/resolver/resolver_test.cc b/paludis/resolver/resolver_test.cc
index cfd40c8..443524c 100644
--- a/paludis/resolver/resolver_test.cc
+++ b/paludis/resolver/resolver_test.cc
@@ -26,6 +26,8 @@
#include <paludis/resolver/resolver_functions.hh>
#include <paludis/resolver/suggest_restart.hh>
#include <paludis/resolver/decision.hh>
+#include <paludis/resolver/decider.hh>
+#include <paludis/resolver/orderer.hh>
#include <paludis/util/map.hh>
#include <paludis/util/wrapped_forward_iterator-impl.hh>
#include <paludis/util/make_shared_ptr.hh>
@@ -34,6 +36,7 @@
#include <paludis/util/accept_visitor.hh>
#include <paludis/util/fs_entry.hh>
#include <paludis/util/make_named_values.hh>
+#include <paludis/util/make_shared_copy.hh>
#include <paludis/repositories/fake/fake_installed_repository.hh>
#include <paludis/repository_factory.hh>
#include <paludis/package_database.hh>
@@ -278,7 +281,7 @@ ResolverTestCase::ResolverTestCase(const std::string & t, const std::string & s,
#endif
}
-const std::tr1::shared_ptr<const ResolutionLists>
+const std::tr1::shared_ptr<const ResolverLists>
ResolverTestCase::get_resolutions(const PackageDepSpec & target)
{
InitialConstraints initial_constraints;
@@ -303,7 +306,7 @@ ResolverTestCase::get_resolutions(const PackageDepSpec & target)
));
resolver.add_target(target);
resolver.resolve();
- return resolver.resolution_lists();
+ return resolver.lists();
}
catch (const SuggestRestart & e)
{
@@ -312,7 +315,7 @@ ResolverTestCase::get_resolutions(const PackageDepSpec & target)
}
}
-const std::tr1::shared_ptr<const ResolutionLists>
+const std::tr1::shared_ptr<const ResolverLists>
ResolverTestCase::get_resolutions(const std::string & target)
{
PackageDepSpec target_spec(parse_user_package_dep_spec(target, &env, UserPackageDepSpecOptions()));
diff --git a/paludis/resolver/resolver_test.hh b/paludis/resolver/resolver_test.hh
index 81256ce..2ba5f87 100644
--- a/paludis/resolver/resolver_test.hh
+++ b/paludis/resolver/resolver_test.hh
@@ -29,6 +29,7 @@
#include <paludis/resolver/resolutions-fwd.hh>
#include <paludis/resolver/decision-fwd.hh>
#include <paludis/resolver/destination_types-fwd.hh>
+#include <paludis/resolver/resolver-fwd.hh>
#include <paludis/repositories/fake/fake_installed_repository.hh>
#include <paludis/environments/test/test_environment.hh>
#include <paludis/util/map-fwd.hh>
@@ -95,9 +96,9 @@ namespace paludis
ResolverTestCase(const std::string & group, const std::string & test_name, const std::string & eapi,
const std::string & layout);
- const std::tr1::shared_ptr<const ResolutionLists> get_resolutions(const PackageDepSpec & target);
+ const std::tr1::shared_ptr<const ResolverLists> get_resolutions(const PackageDepSpec & target);
- const std::tr1::shared_ptr<const ResolutionLists> get_resolutions(const std::string & target);
+ const std::tr1::shared_ptr<const ResolverLists> get_resolutions(const std::string & target);
struct ResolutionListChecks
{
diff --git a/paludis/resolver/sanitised_dependencies.cc b/paludis/resolver/sanitised_dependencies.cc
index f648581..cb1375f 100644
--- a/paludis/resolver/sanitised_dependencies.cc
+++ b/paludis/resolver/sanitised_dependencies.cc
@@ -21,6 +21,7 @@
#include <paludis/resolver/resolver.hh>
#include <paludis/resolver/resolvent.hh>
#include <paludis/resolver/spec_rewriter.hh>
+#include <paludis/resolver/decider.hh>
#include <paludis/util/make_named_values.hh>
#include <paludis/util/save.hh>
#include <paludis/util/stringify.hh>
@@ -99,7 +100,7 @@ namespace
struct AnyDepSpecChildHandler
{
- const Resolver & resolver;
+ const Decider & decider;
const Resolvent our_resolvent;
const std::tr1::function<SanitisedDependency (const PackageOrBlockDepSpec &)> parent_make_sanitised;
@@ -110,9 +111,9 @@ namespace
bool seen_any;
- AnyDepSpecChildHandler(const Resolver & r, const Resolvent & q,
+ AnyDepSpecChildHandler(const Decider & r, const Resolvent & q,
const std::tr1::function<SanitisedDependency (const PackageOrBlockDepSpec &)> & f) :
- resolver(r),
+ decider(r),
our_resolvent(q),
parent_make_sanitised(f),
super_complicated(false),
@@ -126,7 +127,7 @@ namespace
{
seen_any = true;
- const std::tr1::shared_ptr<const RewrittenSpec> if_rewritten(resolver.rewrite_if_special(spec,
+ const std::tr1::shared_ptr<const RewrittenSpec> if_rewritten(decider.rewrite_if_special(spec,
make_shared_copy(our_resolvent)));
if (if_rewritten)
if_rewritten->as_spec_tree()->root()->accept(*this);
@@ -202,7 +203,7 @@ namespace
void visit(const DependencySpecTree::NodeType<AnyDepSpec>::Type & node)
{
- AnyDepSpecChildHandler h(resolver, our_resolvent, parent_make_sanitised);
+ AnyDepSpecChildHandler h(decider, our_resolvent, parent_make_sanitised);
std::for_each(indirect_iterator(node.begin()), indirect_iterator(node.end()), accept_visitor(h));
std::list<SanitisedDependency> l;
h.commit(
@@ -264,7 +265,7 @@ namespace
for (std::list<PackageOrBlockDepSpec>::const_iterator h(g->begin()), h_end(g->end()) ;
h != h_end ; ++h)
{
- int score(resolver.find_any_score(our_resolvent, make_sanitised(PackageOrBlockDepSpec(*h))));
+ int score(decider.find_any_score(our_resolvent, make_sanitised(PackageOrBlockDepSpec(*h))));
if ((-1 == worst_score) || (score < worst_score))
worst_score = score;
}
@@ -287,7 +288,7 @@ namespace
struct Finder
{
- const Resolver & resolver;
+ const Decider & decider;
const Resolvent our_resolvent;
SanitisedDependencies & sanitised_dependencies;
const std::string raw_name;
@@ -296,14 +297,14 @@ namespace
std::list<std::tr1::shared_ptr<const DependenciesLabelSequence> > labels_stack;
Finder(
- const Resolver & r,
+ const Decider & r,
const Resolvent & q,
SanitisedDependencies & s,
const std::tr1::shared_ptr<const DependenciesLabelSequence> & l,
const std::string & rn,
const std::string & hn,
const std::string & a) :
- resolver(r),
+ decider(r),
our_resolvent(q),
sanitised_dependencies(s),
raw_name(rn),
@@ -316,7 +317,7 @@ namespace
void add(const SanitisedDependency & dep)
{
- const std::tr1::shared_ptr<const RewrittenSpec> if_rewritten(resolver.rewrite_if_special(dep.spec(),
+ const std::tr1::shared_ptr<const RewrittenSpec> if_rewritten(decider.rewrite_if_special(dep.spec(),
make_shared_copy(our_resolvent)));
if (if_rewritten)
if_rewritten->as_spec_tree()->root()->accept(*this);
@@ -379,7 +380,7 @@ namespace
original_specs_as_string = "|| (" + v.result + " )";
}
- AnyDepSpecChildHandler h(resolver, our_resolvent, std::tr1::bind(&Finder::make_sanitised, this, std::tr1::placeholders::_1));
+ AnyDepSpecChildHandler h(decider, our_resolvent, std::tr1::bind(&Finder::make_sanitised, this, std::tr1::placeholders::_1));
std::for_each(indirect_iterator(node.begin()), indirect_iterator(node.end()), accept_visitor(h));
h.commit(
std::tr1::bind(&Finder::make_sanitised, this, std::tr1::placeholders::_1),
@@ -421,7 +422,7 @@ SanitisedDependencies::~SanitisedDependencies()
void
SanitisedDependencies::_populate_one(
- const Resolver & resolver,
+ const Decider & decider,
const Resolvent & resolvent,
const std::tr1::shared_ptr<const PackageID> & id,
const std::tr1::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> > (PackageID::* const pmf) () const
@@ -429,31 +430,31 @@ SanitisedDependencies::_populate_one(
{
Context context("When finding dependencies for '" + stringify(*id) + "' from key '" + ((*id).*pmf)()->raw_name() + "':");
- Finder f(resolver, resolvent, *this, ((*id).*pmf)()->initial_labels(), ((*id).*pmf)()->raw_name(),
+ Finder f(decider, resolvent, *this, ((*id).*pmf)()->initial_labels(), ((*id).*pmf)()->raw_name(),
((*id).*pmf)()->human_name(), "");
((*id).*pmf)()->value()->root()->accept(f);
}
void
SanitisedDependencies::populate(
- const Resolver & resolver,
+ const Decider & decider,
const Resolvent & resolvent,
const std::tr1::shared_ptr<const PackageID> & id)
{
Context context("When finding dependencies for '" + stringify(*id) + "':");
if (id->dependencies_key())
- _populate_one(resolver, resolvent, id, &PackageID::dependencies_key);
+ _populate_one(decider, resolvent, id, &PackageID::dependencies_key);
else
{
if (id->build_dependencies_key())
- _populate_one(resolver, resolvent, id, &PackageID::build_dependencies_key);
+ _populate_one(decider, resolvent, id, &PackageID::build_dependencies_key);
if (id->run_dependencies_key())
- _populate_one(resolver, resolvent, id, &PackageID::run_dependencies_key);
+ _populate_one(decider, resolvent, id, &PackageID::run_dependencies_key);
if (id->post_dependencies_key())
- _populate_one(resolver, resolvent, id, &PackageID::post_dependencies_key);
+ _populate_one(decider, resolvent, id, &PackageID::post_dependencies_key);
if (id->suggested_dependencies_key())
- _populate_one(resolver, resolvent, id, &PackageID::suggested_dependencies_key);
+ _populate_one(decider, resolvent, id, &PackageID::suggested_dependencies_key);
}
}
diff --git a/paludis/resolver/sanitised_dependencies.hh b/paludis/resolver/sanitised_dependencies.hh
index d778766..830b607 100644
--- a/paludis/resolver/sanitised_dependencies.hh
+++ b/paludis/resolver/sanitised_dependencies.hh
@@ -21,7 +21,7 @@
#define PALUDIS_GUARD_PALUDIS_RESOLVER_SANITISED_DEPENDENCIES_HH 1
#include <paludis/resolver/sanitised_dependencies-fwd.hh>
-#include <paludis/resolver/resolver-fwd.hh>
+#include <paludis/resolver/decider-fwd.hh>
#include <paludis/resolver/resolvent-fwd.hh>
#include <paludis/util/named_value.hh>
#include <paludis/dep_label-fwd.hh>
@@ -82,7 +82,7 @@ namespace paludis
{
private:
void _populate_one(
- const Resolver &,
+ const Decider &,
const Resolvent &,
const std::tr1::shared_ptr<const PackageID> &,
const std::tr1::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> > (PackageID::* const) () const
@@ -93,7 +93,7 @@ namespace paludis
~SanitisedDependencies();
void populate(
- const Resolver &,
+ const Decider &,
const Resolvent &,
const std::tr1::shared_ptr<const PackageID> &);
diff --git a/src/clients/cave/cmd_display_resolution.cc b/src/clients/cave/cmd_display_resolution.cc
index ed9b626..0595ed4 100644
--- a/src/clients/cave/cmd_display_resolution.cc
+++ b/src/clients/cave/cmd_display_resolution.cc
@@ -615,7 +615,7 @@ namespace
void display_resolution(
const std::tr1::shared_ptr<Environment> & env,
- const ResolutionLists & lists,
+ const ResolverLists & lists,
const DisplayResolutionCommandLine & cmdline)
{
Context context("When displaying chosen resolution:");
@@ -633,7 +633,7 @@ namespace
void display_untaken(
const std::tr1::shared_ptr<Environment> & env,
- const ResolutionLists & lists,
+ const ResolverLists & lists,
const DisplayResolutionCommandLine & cmdline)
{
Context context("When displaying untaken resolutions:");
@@ -647,7 +647,7 @@ namespace
void display_errors(
const std::tr1::shared_ptr<Environment> & env,
- const ResolutionLists & lists,
+ const ResolverLists & lists,
const DisplayResolutionCommandLine & cmdline)
{
Context context("When displaying errors for chosen resolution:");
@@ -666,7 +666,7 @@ namespace
void display_explanations(
const std::tr1::shared_ptr<Environment> & env,
- const ResolutionLists & lists,
+ const ResolverLists & lists,
const DisplayResolutionCommandLine & cmdline)
{
Context context("When displaying explanations:");
@@ -811,8 +811,8 @@ DisplayResolutionCommand::run(
SafeIFStream deser_stream(fd);
const std::string deser_str((std::istreambuf_iterator<char>(deser_stream)), std::istreambuf_iterator<char>());
Deserialiser deserialiser(env.get(), deser_str);
- Deserialisation deserialisation("ResolutionLists", deserialiser);
- ResolutionLists lists(ResolutionLists::deserialise(deserialisation));
+ Deserialisation deserialisation("ResolverLists", deserialiser);
+ ResolverLists lists(ResolverLists::deserialise(deserialisation));
display_resolution(env, lists, cmdline);
display_untaken(env, lists, cmdline);
diff --git a/src/clients/cave/cmd_execute_resolution.cc b/src/clients/cave/cmd_execute_resolution.cc
index f996cec..23838e9 100644
--- a/src/clients/cave/cmd_execute_resolution.cc
+++ b/src/clients/cave/cmd_execute_resolution.cc
@@ -267,7 +267,7 @@ namespace
int execute_resolution(
const std::tr1::shared_ptr<Environment> & env,
- const ResolutionLists & lists,
+ const ResolverLists & lists,
const ExecuteResolutionCommandLine & cmdline)
{
Context context("When executing chosen resolution:");
@@ -457,8 +457,8 @@ ExecuteResolutionCommand::run(
SafeIFStream deser_stream(fd);
const std::string deser_str((std::istreambuf_iterator<char>(deser_stream)), std::istreambuf_iterator<char>());
Deserialiser deserialiser(env.get(), deser_str);
- Deserialisation deserialisation("ResolutionLists", deserialiser);
- ResolutionLists lists(ResolutionLists::deserialise(deserialisation));
+ Deserialisation deserialisation("ResolverLists", deserialiser);
+ ResolverLists lists(ResolverLists::deserialise(deserialisation));
return execute_resolution(env, lists, cmdline);
}
diff --git a/src/clients/cave/cmd_resolve.cc b/src/clients/cave/cmd_resolve.cc
index f9e6e6c..903150c 100644
--- a/src/clients/cave/cmd_resolve.cc
+++ b/src/clients/cave/cmd_resolve.cc
@@ -851,7 +851,7 @@ namespace
int display_resolution(
const std::tr1::shared_ptr<Environment> &,
- const ResolutionLists & resolution_lists,
+ const ResolverLists & resolution_lists,
const ResolveCommandLine & cmdline)
{
Context context("When displaying chosen resolution:");
@@ -886,13 +886,13 @@ namespace
void perform_resolution(
const std::tr1::shared_ptr<Environment> &,
- const ResolutionLists & resolution_lists,
+ const ResolverLists & resolution_lists,
const ResolveCommandLine & cmdline,
const bool is_set) PALUDIS_ATTRIBUTE((noreturn));
void perform_resolution(
const std::tr1::shared_ptr<Environment> &,
- const ResolutionLists & resolution_lists,
+ const ResolverLists & resolution_lists,
const ResolveCommandLine & cmdline,
const bool is_set)
{
@@ -1162,13 +1162,13 @@ ResolveCommand::run(
dump_if_requested(env, resolver, cmdline);
- retcode |= display_resolution(env, *resolver->resolution_lists(), cmdline);
+ retcode |= display_resolution(env, *resolver->lists(), cmdline);
- if (! resolver->resolution_lists()->errors()->empty())
+ if (! resolver->lists()->errors()->empty())
retcode |= 1;
if (0 == retcode)
- perform_resolution(env, *resolver->resolution_lists(), cmdline, is_set);
+ perform_resolution(env, *resolver->lists(), cmdline, is_set);
}
catch (...)
{
diff --git a/src/clients/cave/cmd_resolve_dump.cc b/src/clients/cave/cmd_resolve_dump.cc
index fcb8ed6..2032220 100644
--- a/src/clients/cave/cmd_resolve_dump.cc
+++ b/src/clients/cave/cmd_resolve_dump.cc
@@ -27,6 +27,7 @@
#include <paludis/resolver/reason.hh>
#include <paludis/resolver/arrow.hh>
#include <paludis/resolver/destination.hh>
+#include <paludis/resolver/resolutions.hh>
#include <paludis/util/enum_iterator.hh>
#include <paludis/util/indirect_iterator-impl.hh>
#include <paludis/util/join.hh>
@@ -229,12 +230,12 @@ namespace
{
std::cout << "Dumping resolutions by QPN:S:" << std::endl << std::endl;
- for (Resolver::ResolutionsByResolventConstIterator c(resolver->begin_resolutions_by_resolvent()),
- c_end(resolver->end_resolutions_by_resolvent()) ;
+ for (Resolutions::ConstIterator c(resolver->lists()->all()->begin()),
+ c_end(resolver->lists()->all()->end()) ;
c != c_end ; ++c)
{
- std::cout << c->first << std::endl;
- std::cout << " = " << *c->second << std::endl;
+ std::cout << (*c)->resolvent() << std::endl;
+ std::cout << " = " << **c << std::endl;
}
std::cout << std::endl;