aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2009-11-22 16:34:22 +0000
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2009-11-22 16:34:22 +0000
commit3d8b1317d30c901fbaf659a29abbcc110c9bf3b7 (patch)
tree59de6cc4817576472d64613db158fdd1af784157
parent38c9cbab07ab6ed6ed47eba2e1b20751051c45ad (diff)
downloadpaludis-3d8b1317d30c901fbaf659a29abbcc110c9bf3b7.tar.gz
paludis-3d8b1317d30c901fbaf659a29abbcc110c9bf3b7.tar.xz
New jobs-based orderer
-rw-r--r--.gitignore2
-rw-r--r--paludis/resolver/Makefile.am51
-rw-r--r--paludis/resolver/arrow-fwd.hh2
-rw-r--r--paludis/resolver/arrow.cc18
-rw-r--r--paludis/resolver/arrow.hh12
-rw-r--r--paludis/resolver/decider.cc75
-rw-r--r--paludis/resolver/decider.hh1
-rw-r--r--paludis/resolver/decision.cc12
-rw-r--r--paludis/resolver/decision.hh6
-rw-r--r--paludis/resolver/job-fwd.hh37
-rw-r--r--paludis/resolver/job.cc388
-rw-r--r--paludis/resolver/job.hh170
-rw-r--r--paludis/resolver/job_id-fwd.hh38
-rw-r--r--paludis/resolver/job_id.cc61
-rw-r--r--paludis/resolver/job_id.hh49
-rw-r--r--paludis/resolver/jobs-fwd.hh31
-rw-r--r--paludis/resolver/jobs.cc207
-rw-r--r--paludis/resolver/jobs.hh67
-rw-r--r--paludis/resolver/orderer.cc655
-rw-r--r--paludis/resolver/orderer.hh22
-rw-r--r--paludis/resolver/resolution.cc9
-rw-r--r--paludis/resolver/resolution.hh5
-rw-r--r--paludis/resolver/resolvent.cc21
-rw-r--r--paludis/resolver/resolvent.hh4
-rw-r--r--paludis/resolver/resolver.cc40
-rw-r--r--paludis/resolver/resolver.hh23
-rw-r--r--paludis/resolver/resolver_TEST_blockers.cc5
-rw-r--r--paludis/resolver/resolver_TEST_cycles.cc142
-rwxr-xr-xpaludis/resolver/resolver_TEST_cycles_cleanup.sh9
-rwxr-xr-xpaludis/resolver/resolver_TEST_cycles_setup.sh64
-rw-r--r--paludis/resolver/resolver_TEST_serialisation.cc7
-rw-r--r--paludis/resolver/resolver_TEST_simple.cc122
-rwxr-xr-xpaludis/resolver/resolver_TEST_simple_cleanup.sh9
-rwxr-xr-xpaludis/resolver/resolver_TEST_simple_setup.sh64
-rw-r--r--paludis/resolver/resolver_TEST_suggestions.cc19
-rw-r--r--paludis/resolver/resolver_TEST_virtuals.cc13
-rw-r--r--paludis/resolver/resolver_lists-fwd.hh31
-rw-r--r--paludis/resolver/resolver_lists.cc80
-rw-r--r--paludis/resolver/resolver_lists.hh60
-rw-r--r--paludis/resolver/resolver_test.cc138
-rw-r--r--paludis/resolver/resolver_test.hh12
-rw-r--r--paludis/resolver/sync_point-fwd.hh34
-rw-r--r--paludis/resolver/sync_point.cc29
-rw-r--r--paludis/resolver/sync_point.hh30
-rw-r--r--paludis/resolver/sync_point.se15
-rw-r--r--src/clients/cave/cmd_display_resolution.cc77
-rw-r--r--src/clients/cave/cmd_execute_resolution.cc225
-rw-r--r--src/clients/cave/cmd_resolve.cc3
-rw-r--r--src/clients/cave/cmd_resolve_dump.cc17
49 files changed, 2673 insertions, 538 deletions
diff --git a/.gitignore b/.gitignore
index cd01c01..0196894 100644
--- a/.gitignore
+++ b/.gitignore
@@ -319,7 +319,9 @@ paludis-*.*.*.tar.bz2
/paludis/repositories/virtuals/virtuals_repository_TEST
/paludis/repository_name_cache_TEST
/paludis/resolver/resolver_TEST_blockers
+/paludis/resolver/resolver_TEST_cycles
/paludis/resolver/resolver_TEST_serialisation
+/paludis/resolver/resolver_TEST_simple
/paludis/resolver/resolver_TEST_suggestions
/paludis/resolver/resolver_TEST_virtuals
/paludis/selection_TEST
diff --git a/paludis/resolver/Makefile.am b/paludis/resolver/Makefile.am
index 575d687..c712da9 100644
--- a/paludis/resolver/Makefile.am
+++ b/paludis/resolver/Makefile.am
@@ -2,19 +2,25 @@ include $(top_srcdir)/misc/common-makefile.am
DISTCLEANFILES = \
destination_types-se.hh destination_types-se.cc \
+ sync_point-se.hh sync_point-se.cc \
use_existing-se.hh use_existing-se.cc
AM_CXXFLAGS = -I$(top_srcdir) @PALUDIS_CXXFLAGS@ @PALUDIS_CXXFLAGS_VISIBILITY@
EXTRA_DIST = \
destination_types-se.hh destination_types-se.cc destination_types.se \
+ sync_point-se.hh sync_point-se.cc sync_point.se \
use_existing-se.hh use_existing-se.cc use_existing.se \
$(check_SCRIPTS)
BUILT_SOURCES = \
destination_types-se.hh destination_types-se.cc \
+ sync_point-se.hh sync_point-se.cc \
use_existing-se.hh use_existing-se.cc
noinst_HEADERS = \
arrow.hh arrow-fwd.hh \
constraint.hh constraint-fwd.hh \
+ job.hh job-fwd.hh \
+ job_id.hh job_id-fwd.hh \
+ jobs.hh jobs-fwd.hh \
decider.hh decider-fwd.hh \
decision.hh decision-fwd.hh \
destination.hh destination-fwd.hh \
@@ -26,9 +32,11 @@ noinst_HEADERS = \
resolvent.hh resolvent-fwd.hh \
resolver.hh resolver-fwd.hh \
resolver_functions.hh resolver_functions-fwd.hh \
+ resolver_lists.hh resolver_lists-fwd.hh \
sanitised_dependencies.hh sanitised_dependencies-fwd.hh \
spec_rewriter.hh spec_rewriter-fwd.hh \
suggest_restart.hh suggest_restart-fwd.hh \
+ sync_point.hh sync_point-fwd.hh sync_point-se.hh \
unsuitable_candidates.hh unsuitable_candidates-fwd.hh \
use_existing.hh use_existing-fwd.hh use_existing-se.hh
@@ -39,15 +47,20 @@ libpaludisresolver_a_SOURCES = \
decision.cc \
destination.cc \
destination_types.cc \
+ job.cc \
+ job_id.cc \
+ jobs.cc \
orderer.cc \
reason.cc \
resolution.cc \
resolutions.cc \
resolvent.cc \
resolver.cc \
+ resolver_lists.cc \
sanitised_dependencies.cc \
spec_rewriter.cc \
suggest_restart.cc \
+ sync_point.cc \
unsuitable_candidates.cc \
use_existing.cc
@@ -59,8 +72,10 @@ if ENABLE_NEW_RESOLVER
noinst_LIBRARIES = libpaludisresolver.a
TESTS = \
- resolver_TEST_blockers \
+ resolver_TEST_simple \
resolver_TEST_serialisation \
+ resolver_TEST_blockers \
+ resolver_TEST_cycles \
resolver_TEST_suggestions \
$(virtuals_tests)
endif
@@ -69,8 +84,10 @@ endif
check_PROGRAMS = $(TESTS)
check_SCRIPTS = \
resolver_TEST_blockers_setup.sh resolver_TEST_blockers_cleanup.sh \
+ resolver_TEST_cycles_setup.sh resolver_TEST_cycles_cleanup.sh \
resolver_TEST_serialisation_setup.sh resolver_TEST_serialisation_cleanup.sh \
resolver_TEST_suggestions_setup.sh resolver_TEST_suggestions_cleanup.sh \
+ resolver_TEST_simple_setup.sh resolver_TEST_simple_cleanup.sh \
resolver_TEST_virtuals_setup.sh resolver_TEST_virtuals_cleanup.sh
check_LIBRARIES = libpaludisresolvertest.a
@@ -91,6 +108,19 @@ resolver_TEST_blockers_LDADD = \
resolver_TEST_blockers_CXXFLAGS = $(AM_CXXFLAGS) @PALUDIS_CXXFLAGS_NO_DEBUGGING@
+resolver_TEST_cycles_SOURCES = resolver_TEST_cycles.cc
+
+resolver_TEST_cycles_LDADD = \
+ libpaludisresolvertest.a \
+ $(top_builddir)/paludis/util/test_extras.o \
+ $(top_builddir)/test/libtest.a \
+ $(top_builddir)/paludis/libpaludis_@PALUDIS_PC_SLOT@.la \
+ $(top_builddir)/paludis/util/libpaludisutil_@PALUDIS_PC_SLOT@.la \
+ libpaludisresolver.a \
+ $(DYNAMIC_LD_LIBS)
+
+resolver_TEST_cycles_CXXFLAGS = $(AM_CXXFLAGS) @PALUDIS_CXXFLAGS_NO_DEBUGGING@
+
resolver_TEST_virtuals_SOURCES = resolver_TEST_virtuals.cc
resolver_TEST_virtuals_LDADD = \
@@ -130,12 +160,31 @@ resolver_TEST_serialisation_LDADD = \
resolver_TEST_serialisation_CXXFLAGS = $(AM_CXXFLAGS) @PALUDIS_CXXFLAGS_NO_DEBUGGING@
+resolver_TEST_simple_SOURCES = resolver_TEST_simple.cc
+
+resolver_TEST_simple_LDADD = \
+ libpaludisresolvertest.a \
+ $(top_builddir)/paludis/util/test_extras.o \
+ $(top_builddir)/test/libtest.a \
+ $(top_builddir)/paludis/libpaludis_@PALUDIS_PC_SLOT@.la \
+ $(top_builddir)/paludis/util/libpaludisutil_@PALUDIS_PC_SLOT@.la \
+ libpaludisresolver.a \
+ $(DYNAMIC_LD_LIBS)
+
+resolver_TEST_simple_CXXFLAGS = $(AM_CXXFLAGS) @PALUDIS_CXXFLAGS_NO_DEBUGGING@
+
use_existing-se.hh : use_existing.se $(top_srcdir)/misc/make_se.bash
if ! $(top_srcdir)/misc/make_se.bash --header $(srcdir)/use_existing.se > $@ ; then rm -f $@ ; exit 1 ; fi
use_existing-se.cc : use_existing.se $(top_srcdir)/misc/make_se.bash
if ! $(top_srcdir)/misc/make_se.bash --source $(srcdir)/use_existing.se > $@ ; then rm -f $@ ; exit 1 ; fi
+sync_point-se.hh : sync_point.se $(top_srcdir)/misc/make_se.bash
+ if ! $(top_srcdir)/misc/make_se.bash --header $(srcdir)/sync_point.se > $@ ; then rm -f $@ ; exit 1 ; fi
+
+sync_point-se.cc : sync_point.se $(top_srcdir)/misc/make_se.bash
+ if ! $(top_srcdir)/misc/make_se.bash --source $(srcdir)/sync_point.se > $@ ; then rm -f $@ ; exit 1 ; fi
+
destination_types-se.hh : destination_types.se $(top_srcdir)/misc/make_se.bash
if ! $(top_srcdir)/misc/make_se.bash --header $(srcdir)/destination_types.se > $@ ; then rm -f $@ ; exit 1 ; fi
diff --git a/paludis/resolver/arrow-fwd.hh b/paludis/resolver/arrow-fwd.hh
index f3a79e3..0355e05 100644
--- a/paludis/resolver/arrow-fwd.hh
+++ b/paludis/resolver/arrow-fwd.hh
@@ -30,7 +30,7 @@ namespace paludis
{
struct Arrow;
- typedef Sequence<std::tr1::shared_ptr<Arrow> > ArrowSequence;
+ typedef Sequence<Arrow> ArrowSequence;
}
}
diff --git a/paludis/resolver/arrow.cc b/paludis/resolver/arrow.cc
index da04241..e945b26 100644
--- a/paludis/resolver/arrow.cc
+++ b/paludis/resolver/arrow.cc
@@ -32,22 +32,20 @@ Arrow::serialise(Serialiser & s) const
{
s.object("Arrow")
.member(SerialiserFlags<>(), "comes_after", comes_after())
- .member(SerialiserFlags<>(), "ignorable_pass", ignorable_pass())
- .member(SerialiserFlags<serialise::might_be_null>(), "reason", reason())
+ .member(SerialiserFlags<serialise::might_be_null>(), "maybe_reason", maybe_reason())
;
}
-const std::tr1::shared_ptr<Arrow>
+const Arrow
Arrow::deserialise(Deserialisation & d)
{
Deserialisator v(d, "Arrow");
- return make_shared_ptr(new Arrow(make_named_values<Arrow>(
- value_for<n::comes_after>(v.member<Resolvent>("comes_after")),
- value_for<n::ignorable_pass>(v.member<bool>("ignorable_pass")),
- value_for<n::reason>(v.member<std::tr1::shared_ptr<const Reason> >("reason"))
- )));
+ return make_named_values<Arrow>(
+ value_for<n::comes_after>(v.member<JobID>("comes_after")),
+ value_for<n::maybe_reason>(v.member<std::tr1::shared_ptr<const Reason> >("maybe_reason"))
+ );
}
-template class Sequence<std::tr1::shared_ptr<Arrow> >;
-template class WrappedForwardIterator<ArrowSequence::ConstIteratorTag, const std::tr1::shared_ptr<Arrow> >;
+template class Sequence<Arrow>;
+template class WrappedForwardIterator<ArrowSequence::ConstIteratorTag, const Arrow>;
diff --git a/paludis/resolver/arrow.hh b/paludis/resolver/arrow.hh
index a55aa69..deea7e8 100644
--- a/paludis/resolver/arrow.hh
+++ b/paludis/resolver/arrow.hh
@@ -23,6 +23,7 @@
#include <paludis/resolver/arrow-fwd.hh>
#include <paludis/resolver/resolvent.hh>
#include <paludis/resolver/reason-fwd.hh>
+#include <paludis/resolver/job_id.hh>
#include <paludis/serialise-fwd.hh>
#include <paludis/util/named_value.hh>
@@ -31,22 +32,19 @@ namespace paludis
namespace n
{
struct comes_after;
- struct ignorable_pass;
- struct reason;
+ struct maybe_reason;
}
namespace resolver
{
struct Arrow
{
- NamedValue<n::comes_after, Resolvent> comes_after;
- NamedValue<n::ignorable_pass, int> ignorable_pass;
- NamedValue<n::reason, std::tr1::shared_ptr<const Reason> > reason;
+ NamedValue<n::comes_after, JobID> comes_after;
+ NamedValue<n::maybe_reason, std::tr1::shared_ptr<const Reason> > maybe_reason;
void serialise(Serialiser &) const;
- static const std::tr1::shared_ptr<Arrow> deserialise(
- Deserialisation & d) PALUDIS_ATTRIBUTE((warn_unused_result));
+ static const Arrow deserialise(Deserialisation & d) PALUDIS_ATTRIBUTE((warn_unused_result));
};
}
}
diff --git a/paludis/resolver/decider.cc b/paludis/resolver/decider.cc
index 4597717..744af6b 100644
--- a/paludis/resolver/decider.cc
+++ b/paludis/resolver/decider.cc
@@ -30,6 +30,7 @@
#include <paludis/resolver/reason.hh>
#include <paludis/resolver/unsuitable_candidates.hh>
#include <paludis/resolver/resolver.hh>
+#include <paludis/resolver/resolver_lists.hh>
#include <paludis/util/exception.hh>
#include <paludis/util/stringify.hh>
#include <paludis/util/make_named_values.hh>
@@ -271,8 +272,6 @@ 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)
@@ -289,7 +288,7 @@ Decider::_resolution_for_resolvent(const Resolvent & r, const bool 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->lists->all()->append(resolution);
+ _imp->lists->all_resolutions()->append(resolution);
}
else
throw InternalError(PALUDIS_HERE, "resolver bug: expected resolution for "
@@ -1317,75 +1316,5 @@ 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->lists->all()->begin()),
- i_end(_imp->lists->all()->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->lists->errors(), *i),
- std::tr1::bind(&Resolutions::append, _imp->lists->unordered(), *i),
- std::tr1::bind(&Resolutions::append, _imp->lists->untaken(), *i)
- ));
- }
}
diff --git a/paludis/resolver/decider.hh b/paludis/resolver/decider.hh
index fc6931e..617e810 100644
--- a/paludis/resolver/decider.hh
+++ b/paludis/resolver/decider.hh
@@ -118,7 +118,6 @@ namespace paludis
void _resolve_decide_with_dependencies();
void _resolve_destinations();
- void _resolve_unordered();
const std::tr1::shared_ptr<Destination> _make_destination_for(
const Resolvent & resolvent,
diff --git a/paludis/resolver/decision.cc b/paludis/resolver/decision.cc
index 97e8c3e..d019247 100644
--- a/paludis/resolver/decision.cc
+++ b/paludis/resolver/decision.cc
@@ -88,6 +88,18 @@ Decision::deserialise(Deserialisation & d)
throw InternalError(PALUDIS_HERE, "unknown class '" + stringify(d.class_name()) + "'");
}
+const std::tr1::shared_ptr<ChangesToMakeDecision>
+ChangesToMakeDecision::deserialise(Deserialisation & d)
+{
+ Deserialisator v(d, "ChangesToMakeDecision");
+ return make_shared_ptr(new ChangesToMakeDecision(
+ v.member<std::tr1::shared_ptr<const PackageID> >("origin_id"),
+ v.member<bool>("best"),
+ v.member<bool>("taken"),
+ v.member<std::tr1::shared_ptr<const Destination> >("destination")
+ ));
+}
+
namespace paludis
{
template <>
diff --git a/paludis/resolver/decision.hh b/paludis/resolver/decision.hh
index 30b0443..95c5da5 100644
--- a/paludis/resolver/decision.hh
+++ b/paludis/resolver/decision.hh
@@ -92,7 +92,8 @@ namespace paludis
class PALUDIS_VISIBLE ChangesToMakeDecision :
public Decision,
public ImplementAcceptMethods<Decision, ChangesToMakeDecision>,
- private PrivateImplementationPattern<ChangesToMakeDecision>
+ private PrivateImplementationPattern<ChangesToMakeDecision>,
+ public std::tr1::enable_shared_from_this<ChangesToMakeDecision>
{
public:
ChangesToMakeDecision(
@@ -117,6 +118,9 @@ namespace paludis
virtual bool taken() const PALUDIS_ATTRIBUTE((warn_unused_result));
virtual void serialise(Serialiser &) const;
+
+ static const std::tr1::shared_ptr<ChangesToMakeDecision> deserialise(
+ Deserialisation & d) PALUDIS_ATTRIBUTE((warn_unused_result));
};
class PALUDIS_VISIBLE UnableToMakeDecision :
diff --git a/paludis/resolver/job-fwd.hh b/paludis/resolver/job-fwd.hh
new file mode 100644
index 0000000..5f7f71e
--- /dev/null
+++ b/paludis/resolver/job-fwd.hh
@@ -0,0 +1,37 @@
+/* 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_JOB_FWD_HH
+#define PALUDIS_GUARD_PALUDIS_RESOLVER_JOB_FWD_HH 1
+
+namespace paludis
+{
+ namespace resolver
+ {
+ struct Job;
+
+ struct SimpleInstallJob;
+ struct PretendJob;
+ struct NoChangeJob;
+ struct SyncPointJob;
+ struct UntakenInstallJob;
+ }
+}
+
+#endif
diff --git a/paludis/resolver/job.cc b/paludis/resolver/job.cc
new file mode 100644
index 0000000..2a29bb2
--- /dev/null
+++ b/paludis/resolver/job.cc
@@ -0,0 +1,388 @@
+/* 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/job.hh>
+#include <paludis/resolver/arrow.hh>
+#include <paludis/resolver/resolution.hh>
+#include <paludis/resolver/decision.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/util/sequence.hh>
+#include <paludis/util/make_named_values.hh>
+#include <paludis/util/wrapped_forward_iterator.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/serialise-impl.hh>
+
+using namespace paludis;
+using namespace paludis::resolver;
+
+namespace paludis
+{
+ template <>
+ struct Implementation<NoChangeJob>
+ {
+ const std::tr1::shared_ptr<const Resolution> resolution;
+ const std::tr1::shared_ptr<ArrowSequence> arrows;
+
+ Implementation(const std::tr1::shared_ptr<const Resolution> & r) :
+ resolution(r),
+ arrows(new ArrowSequence)
+ {
+ }
+ };
+
+ template <>
+ struct Implementation<PretendJob>
+ {
+ const std::tr1::shared_ptr<const Resolution> resolution;
+ const std::tr1::shared_ptr<const ChangesToMakeDecision> decision;
+ const std::tr1::shared_ptr<ArrowSequence> arrows;
+
+ Implementation(const std::tr1::shared_ptr<const Resolution> & r,
+ const std::tr1::shared_ptr<const ChangesToMakeDecision> & d) :
+ resolution(r),
+ decision(d),
+ arrows(new ArrowSequence)
+ {
+ }
+ };
+
+ template <>
+ struct Implementation<SimpleInstallJob>
+ {
+ const std::tr1::shared_ptr<const Resolution> resolution;
+ const std::tr1::shared_ptr<const ChangesToMakeDecision> decision;
+ const std::tr1::shared_ptr<ArrowSequence> arrows;
+
+ Implementation(const std::tr1::shared_ptr<const Resolution> & r,
+ const std::tr1::shared_ptr<const ChangesToMakeDecision> & d) :
+ resolution(r),
+ decision(d),
+ arrows(new ArrowSequence)
+ {
+ }
+ };
+
+ template <>
+ struct Implementation<UntakenInstallJob>
+ {
+ const std::tr1::shared_ptr<const Resolution> resolution;
+ const std::tr1::shared_ptr<ArrowSequence> arrows;
+
+ Implementation(const std::tr1::shared_ptr<const Resolution> & r) :
+ resolution(r),
+ arrows(new ArrowSequence)
+ {
+ }
+ };
+
+ template <>
+ struct Implementation<SyncPointJob>
+ {
+ const SyncPoint sync_point;
+ const std::tr1::shared_ptr<ArrowSequence> arrows;
+
+ Implementation(const SyncPoint s) :
+ sync_point(s),
+ arrows(new ArrowSequence)
+ {
+ }
+ };
+}
+
+Job::~Job()
+{
+}
+
+namespace
+{
+ void do_arrows(
+ const std::tr1::shared_ptr<Job> & result,
+ Deserialisator & v)
+ {
+ Deserialisator vv(*v.find_remove_member("arrows"), "c");
+ for (int n(1), n_end(vv.member<int>("count") + 1) ; n != n_end ; ++n)
+ result->arrows()->push_back(vv.member<Arrow>(stringify(n)));
+ }
+}
+
+const std::tr1::shared_ptr<Job>
+Job::deserialise(Deserialisation & d)
+{
+ std::tr1::shared_ptr<Job> result;
+
+ if (d.class_name() == "NoChangeJob")
+ {
+ Deserialisator v(d, "NoChangeJob");
+ result.reset(new NoChangeJob(
+ v.member<std::tr1::shared_ptr<Resolution> >("resolution")
+ ));
+ do_arrows(result, v);
+ }
+ else if (d.class_name() == "SimpleInstallJob")
+ {
+ Deserialisator v(d, "SimpleInstallJob");
+ result.reset(new SimpleInstallJob(
+ v.member<std::tr1::shared_ptr<Resolution> >("resolution"),
+ v.member<std::tr1::shared_ptr<ChangesToMakeDecision> >("decision")
+ ));
+ do_arrows(result, v);
+ }
+ else if (d.class_name() == "PretendJob")
+ {
+ Deserialisator v(d, "PretendJob");
+ result.reset(new PretendJob(
+ v.member<std::tr1::shared_ptr<Resolution> >("resolution"),
+ v.member<std::tr1::shared_ptr<ChangesToMakeDecision> >("decision")
+ ));
+ do_arrows(result, v);
+ }
+ else if (d.class_name() == "UntakenInstallJob")
+ {
+ Deserialisator v(d, "UntakenInstallJob");
+ result.reset(new UntakenInstallJob(
+ v.member<std::tr1::shared_ptr<Resolution> >("resolution")
+ ));
+ do_arrows(result, v);
+ }
+ else if (d.class_name() == "SyncPointJob")
+ {
+ Deserialisator v(d, "SyncPointJob");
+ result.reset(new SyncPointJob(
+ destringify<SyncPoint>(v.member<std::string>("sync_point"))
+ ));
+ do_arrows(result, v);
+ }
+ else
+ throw InternalError(PALUDIS_HERE, "unknown class '" + stringify(d.class_name()) + "'");
+
+ return result;
+}
+
+NoChangeJob::NoChangeJob(const std::tr1::shared_ptr<const Resolution> & r) :
+ PrivateImplementationPattern<NoChangeJob>(new Implementation<NoChangeJob>(r))
+{
+}
+
+NoChangeJob::~NoChangeJob()
+{
+}
+
+const std::tr1::shared_ptr<const Resolution>
+NoChangeJob::resolution() const
+{
+ return _imp->resolution;
+}
+
+const std::tr1::shared_ptr<ArrowSequence>
+NoChangeJob::arrows() const
+{
+ return _imp->arrows;
+}
+
+const JobID
+NoChangeJob::id() const
+{
+ return make_named_values<JobID>(
+ value_for<n::string_id>("n:" + stringify(resolution()->resolvent()))
+ );
+}
+
+void
+NoChangeJob::serialise(Serialiser & s) const
+{
+ s.object("NoChangeJob")
+ .member(SerialiserFlags<serialise::might_be_null, serialise::container>(), "arrows", arrows())
+ .member(SerialiserFlags<serialise::might_be_null>(), "resolution", resolution())
+ ;
+}
+
+PretendJob::PretendJob(const std::tr1::shared_ptr<const Resolution> & r,
+ const std::tr1::shared_ptr<const ChangesToMakeDecision> & d) :
+ PrivateImplementationPattern<PretendJob>(new Implementation<PretendJob>(r, d))
+{
+}
+
+PretendJob::~PretendJob()
+{
+}
+
+const std::tr1::shared_ptr<const Resolution>
+PretendJob::resolution() const
+{
+ return _imp->resolution;
+}
+
+const std::tr1::shared_ptr<const ChangesToMakeDecision>
+PretendJob::decision() const
+{
+ return _imp->decision;
+}
+
+const std::tr1::shared_ptr<ArrowSequence>
+PretendJob::arrows() const
+{
+ return _imp->arrows;
+}
+
+const JobID
+PretendJob::id() const
+{
+ return make_named_values<JobID>(
+ value_for<n::string_id>("p:" + stringify(resolution()->resolvent()))
+ );
+}
+
+void
+PretendJob::serialise(Serialiser & s) const
+{
+ s.object("PretendJob")
+ .member(SerialiserFlags<serialise::might_be_null, serialise::container>(), "arrows", arrows())
+ .member(SerialiserFlags<serialise::might_be_null>(), "decision", decision())
+ .member(SerialiserFlags<serialise::might_be_null>(), "resolution", resolution())
+ ;
+}
+
+SimpleInstallJob::SimpleInstallJob(const std::tr1::shared_ptr<const Resolution> & r,
+ const std::tr1::shared_ptr<const ChangesToMakeDecision> & d) :
+ PrivateImplementationPattern<SimpleInstallJob>(new Implementation<SimpleInstallJob>(r, d))
+{
+}
+
+SimpleInstallJob::~SimpleInstallJob()
+{
+}
+
+const std::tr1::shared_ptr<const Resolution>
+SimpleInstallJob::resolution() const
+{
+ return _imp->resolution;
+}
+
+const std::tr1::shared_ptr<const ChangesToMakeDecision>
+SimpleInstallJob::decision() const
+{
+ return _imp->decision;
+}
+
+const std::tr1::shared_ptr<ArrowSequence>
+SimpleInstallJob::arrows() const
+{
+ return _imp->arrows;
+}
+
+const JobID
+SimpleInstallJob::id() const
+{
+ return make_named_values<JobID>(
+ value_for<n::string_id>("i:" + stringify(resolution()->resolvent()))
+ );
+}
+
+void
+SimpleInstallJob::serialise(Serialiser & s) const
+{
+ s.object("SimpleInstallJob")
+ .member(SerialiserFlags<serialise::might_be_null, serialise::container>(), "arrows", arrows())
+ .member(SerialiserFlags<serialise::might_be_null>(), "decision", decision())
+ .member(SerialiserFlags<serialise::might_be_null>(), "resolution", resolution())
+ ;
+}
+
+UntakenInstallJob::UntakenInstallJob(const std::tr1::shared_ptr<const Resolution> & r) :
+ PrivateImplementationPattern<UntakenInstallJob>(new Implementation<UntakenInstallJob>(r))
+{
+}
+
+UntakenInstallJob::~UntakenInstallJob()
+{
+}
+
+const std::tr1::shared_ptr<const Resolution>
+UntakenInstallJob::resolution() const
+{
+ return _imp->resolution;
+}
+
+const std::tr1::shared_ptr<ArrowSequence>
+UntakenInstallJob::arrows() const
+{
+ return _imp->arrows;
+}
+
+const JobID
+UntakenInstallJob::id() const
+{
+ return make_named_values<JobID>(
+ value_for<n::string_id>("u:" + stringify(resolution()->resolvent()))
+ );
+}
+
+void
+UntakenInstallJob::serialise(Serialiser & s) const
+{
+ s.object("UntakenInstallJob")
+ .member(SerialiserFlags<serialise::might_be_null, serialise::container>(), "arrows", arrows())
+ .member(SerialiserFlags<serialise::might_be_null>(), "resolution", resolution())
+ ;
+}
+
+SyncPointJob::SyncPointJob(const SyncPoint s) :
+ PrivateImplementationPattern<SyncPointJob>(new Implementation<SyncPointJob>(s))
+{
+}
+
+SyncPointJob::~SyncPointJob()
+{
+}
+
+SyncPoint
+SyncPointJob::sync_point() const
+{
+ return _imp->sync_point;
+}
+
+const std::tr1::shared_ptr<ArrowSequence>
+SyncPointJob::arrows() const
+{
+ return _imp->arrows;
+}
+
+const JobID
+SyncPointJob::id() const
+{
+ return make_named_values<JobID>(
+ value_for<n::string_id>("s:" + stringify(sync_point()))
+ );
+}
+
+void
+SyncPointJob::serialise(Serialiser & s) const
+{
+ s.object("SyncPointJob")
+ .member(SerialiserFlags<serialise::might_be_null, serialise::container>(), "arrows", arrows())
+ .member(SerialiserFlags<>(), "sync_point", stringify(sync_point()))
+ ;
+}
+
+template class PrivateImplementationPattern<resolver::NoChangeJob>;
+template class PrivateImplementationPattern<resolver::PretendJob>;
+template class PrivateImplementationPattern<resolver::SimpleInstallJob>;
+template class PrivateImplementationPattern<resolver::SyncPointJob>;
+template class PrivateImplementationPattern<resolver::UntakenInstallJob>;
+
diff --git a/paludis/resolver/job.hh b/paludis/resolver/job.hh
new file mode 100644
index 0000000..c2c68f6
--- /dev/null
+++ b/paludis/resolver/job.hh
@@ -0,0 +1,170 @@
+/* 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_JOB_HH
+#define PALUDIS_GUARD_PALUDIS_RESOLVER_JOB_HH 1
+
+#include <paludis/resolver/job-fwd.hh>
+#include <paludis/resolver/job_id-fwd.hh>
+#include <paludis/resolver/arrow-fwd.hh>
+#include <paludis/resolver/resolution-fwd.hh>
+#include <paludis/resolver/decision-fwd.hh>
+#include <paludis/resolver/sync_point-fwd.hh>
+#include <paludis/util/attributes.hh>
+#include <paludis/util/simple_visitor.hh>
+#include <paludis/util/type_list.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/serialise-fwd.hh>
+#include <tr1/memory>
+
+namespace paludis
+{
+ namespace resolver
+ {
+ class PALUDIS_VISIBLE Job :
+ public virtual DeclareAbstractAcceptMethods<Job, MakeTypeList<
+ NoChangeJob, SimpleInstallJob, PretendJob, UntakenInstallJob, SyncPointJob>::Type>
+ {
+ public:
+ virtual ~Job() = 0;
+
+ virtual const JobID id()
+ const PALUDIS_ATTRIBUTE((warn_unused_result)) = 0;
+
+ virtual const std::tr1::shared_ptr<ArrowSequence> arrows()
+ const PALUDIS_ATTRIBUTE((warn_unused_result)) = 0;
+
+ virtual void serialise(Serialiser &) const = 0;
+
+ static const std::tr1::shared_ptr<Job> deserialise(
+ Deserialisation & d) PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+
+ class PALUDIS_VISIBLE NoChangeJob :
+ public Job,
+ public ImplementAcceptMethods<Job, NoChangeJob>,
+ private PrivateImplementationPattern<NoChangeJob>
+ {
+ public:
+ NoChangeJob(const std::tr1::shared_ptr<const Resolution> &);
+ ~NoChangeJob();
+
+ virtual const JobID id() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual const std::tr1::shared_ptr<ArrowSequence> arrows()
+ const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ const std::tr1::shared_ptr<const Resolution> resolution() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual void serialise(Serialiser &) const;
+ };
+
+ class PALUDIS_VISIBLE PretendJob :
+ public Job,
+ public ImplementAcceptMethods<Job, PretendJob>,
+ private PrivateImplementationPattern<PretendJob>
+ {
+ public:
+ PretendJob(
+ const std::tr1::shared_ptr<const Resolution> &,
+ const std::tr1::shared_ptr<const ChangesToMakeDecision> &);
+ ~PretendJob();
+
+ virtual const JobID id() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual const std::tr1::shared_ptr<ArrowSequence> arrows()
+ const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ const std::tr1::shared_ptr<const Resolution> resolution() const PALUDIS_ATTRIBUTE((warn_unused_result));
+ const std::tr1::shared_ptr<const ChangesToMakeDecision> decision() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual void serialise(Serialiser &) const;
+ };
+
+ class PALUDIS_VISIBLE SimpleInstallJob :
+ public Job,
+ public ImplementAcceptMethods<Job, SimpleInstallJob>,
+ private PrivateImplementationPattern<SimpleInstallJob>
+ {
+ public:
+ SimpleInstallJob(
+ const std::tr1::shared_ptr<const Resolution> &,
+ const std::tr1::shared_ptr<const ChangesToMakeDecision> &);
+ ~SimpleInstallJob();
+
+ virtual const JobID id() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual const std::tr1::shared_ptr<ArrowSequence> arrows()
+ const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ const std::tr1::shared_ptr<const Resolution> resolution() const PALUDIS_ATTRIBUTE((warn_unused_result));
+ const std::tr1::shared_ptr<const ChangesToMakeDecision> decision() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual void serialise(Serialiser &) const;
+ };
+
+ class PALUDIS_VISIBLE SyncPointJob :
+ public Job,
+ public ImplementAcceptMethods<Job, SyncPointJob>,
+ private PrivateImplementationPattern<SyncPointJob>
+ {
+ public:
+ SyncPointJob(const SyncPoint);
+ ~SyncPointJob();
+
+ virtual const JobID id() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual const std::tr1::shared_ptr<ArrowSequence> arrows()
+ const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ SyncPoint sync_point() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual void serialise(Serialiser &) const;
+ };
+
+ class PALUDIS_VISIBLE UntakenInstallJob :
+ public Job,
+ public ImplementAcceptMethods<Job, UntakenInstallJob>,
+ private PrivateImplementationPattern<UntakenInstallJob>
+ {
+ public:
+ UntakenInstallJob(const std::tr1::shared_ptr<const Resolution> &);
+ ~UntakenInstallJob();
+
+ virtual const JobID id() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual const std::tr1::shared_ptr<ArrowSequence> arrows()
+ const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ const std::tr1::shared_ptr<const Resolution> resolution() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual void serialise(Serialiser &) const;
+ };
+ }
+
+#ifdef PALUDIS_HAVE_EXTERN_TEMPLATE
+ extern template class PrivateImplementationPattern<resolver::NoChangeJob>;
+ extern template class PrivateImplementationPattern<resolver::PretendJob>;
+ extern template class PrivateImplementationPattern<resolver::SimpleInstallJob>;
+ extern template class PrivateImplementationPattern<resolver::SyncPointJob>;
+ extern template class PrivateImplementationPattern<resolver::UntakenInstallJob>;
+#endif
+}
+
+#endif
diff --git a/paludis/resolver/job_id-fwd.hh b/paludis/resolver/job_id-fwd.hh
new file mode 100644
index 0000000..a027329
--- /dev/null
+++ b/paludis/resolver/job_id-fwd.hh
@@ -0,0 +1,38 @@
+/* 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_JOB_ID_FWD_HH
+#define PALUDIS_GUARD_PALUDIS_RESOLVER_JOB_ID_FWD_HH 1
+
+#include <paludis/util/sequence-fwd.hh>
+#include <paludis/util/attributes.hh>
+
+namespace paludis
+{
+ namespace resolver
+ {
+ struct JobID;
+
+ bool operator== (const JobID &, const JobID &) PALUDIS_VISIBLE PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ typedef Sequence<JobID> JobIDSequence;
+ }
+}
+
+#endif
diff --git a/paludis/resolver/job_id.cc b/paludis/resolver/job_id.cc
new file mode 100644
index 0000000..adba996
--- /dev/null
+++ b/paludis/resolver/job_id.cc
@@ -0,0 +1,61 @@
+/* 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/job_id.hh>
+#include <paludis/util/hashes.hh>
+#include <paludis/util/make_named_values.hh>
+#include <paludis/util/wrapped_forward_iterator-impl.hh>
+#include <paludis/util/sequence-impl.hh>
+#include <paludis/serialise-impl.hh>
+
+using namespace paludis;
+using namespace paludis::resolver;
+
+bool
+paludis::resolver::operator== (const JobID & a, const JobID & b)
+{
+ return a.string_id() == b.string_id();
+}
+
+std::size_t
+JobID::hash() const
+{
+ return Hash<std::string>()(string_id());
+}
+
+void
+JobID::serialise(Serialiser & s) const
+{
+ s.object("JobID")
+ .member(SerialiserFlags<>(), "string_id", string_id())
+ ;
+}
+
+const JobID
+JobID::deserialise(Deserialisation & d)
+{
+ Deserialisator v(d, "JobID");
+ return make_named_values<JobID>(
+ value_for<n::string_id>(v.member<std::string>("string_id"))
+ );
+}
+
+template class Sequence<JobID>;
+template class WrappedForwardIterator<JobIDSequence::ConstIteratorTag, const JobID>;
+
diff --git a/paludis/resolver/job_id.hh b/paludis/resolver/job_id.hh
new file mode 100644
index 0000000..e93c9de
--- /dev/null
+++ b/paludis/resolver/job_id.hh
@@ -0,0 +1,49 @@
+/* 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_JOB_ID_HH
+#define PALUDIS_GUARD_PALUDIS_RESOLVER_JOB_ID_HH 1
+
+#include <paludis/resolver/job_id-fwd.hh>
+#include <paludis/util/named_value.hh>
+#include <paludis/serialise-fwd.hh>
+#include <string>
+
+namespace paludis
+{
+ namespace n
+ {
+ struct string_id;
+ }
+
+ namespace resolver
+ {
+ struct JobID
+ {
+ NamedValue<n::string_id, std::string> string_id;
+
+ std::size_t hash() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ void serialise(Serialiser &) const;
+ static const JobID deserialise(Deserialisation & d) PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+ }
+}
+
+#endif
diff --git a/paludis/resolver/jobs-fwd.hh b/paludis/resolver/jobs-fwd.hh
new file mode 100644
index 0000000..bde750c
--- /dev/null
+++ b/paludis/resolver/jobs-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_JOBS_FWD_HH
+#define PALUDIS_GUARD_PALUDIS_RESOLVER_JOBS_FWD_HH 1
+
+namespace paludis
+{
+ namespace resolver
+ {
+ struct Jobs;
+ }
+}
+
+#endif
diff --git a/paludis/resolver/jobs.cc b/paludis/resolver/jobs.cc
new file mode 100644
index 0000000..2a78ee2
--- /dev/null
+++ b/paludis/resolver/jobs.cc
@@ -0,0 +1,207 @@
+/* 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/jobs.hh>
+#include <paludis/resolver/job.hh>
+#include <paludis/resolver/job_id.hh>
+#include <paludis/resolver/resolution.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/util/hashes.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/exception.hh>
+#include <paludis/serialise-impl.hh>
+#include <list>
+#include <map>
+
+using namespace paludis;
+using namespace paludis::resolver;
+
+typedef std::list<std::tr1::shared_ptr<Job> > JobsList;
+typedef std::multimap<Resolvent, JobsList::const_iterator> JobsListByResolventIndex;
+
+namespace paludis
+{
+ template <>
+ struct Implementation<Jobs>
+ {
+ JobsList jobs;
+ JobsListByResolventIndex jobs_list_by_resolvent_index;
+ };
+}
+
+Jobs::Jobs() :
+ PrivateImplementationPattern<Jobs>(new Implementation<Jobs>)
+{
+}
+
+Jobs::~Jobs()
+{
+}
+
+namespace
+{
+ struct Indexer
+ {
+ JobsListByResolventIndex & jobs_list_by_resolvent_index;
+ JobsList::const_iterator i;
+
+ Indexer(JobsListByResolventIndex & j, const JobsList::const_iterator & c) :
+ jobs_list_by_resolvent_index(j),
+ i(c)
+ {
+ }
+
+ void visit(const NoChangeJob & j)
+ {
+ jobs_list_by_resolvent_index.insert(std::make_pair(j.resolution()->resolvent(), i));
+ }
+
+ void visit(const SimpleInstallJob & j)
+ {
+ jobs_list_by_resolvent_index.insert(std::make_pair(j.resolution()->resolvent(), i));
+ }
+
+ void visit(const UntakenInstallJob & j)
+ {
+ jobs_list_by_resolvent_index.insert(std::make_pair(j.resolution()->resolvent(), i));
+ }
+
+ void visit(const PretendJob & j)
+ {
+ jobs_list_by_resolvent_index.insert(std::make_pair(j.resolution()->resolvent(), i));
+ }
+
+ void visit(const SyncPointJob &)
+ {
+ }
+ };
+}
+
+void
+Jobs::add(const std::tr1::shared_ptr<Job> & j)
+{
+ JobsList::const_iterator i(_imp->jobs.insert(_imp->jobs.end(), j));
+ Indexer x(_imp->jobs_list_by_resolvent_index, i);
+ j->accept(x);
+}
+
+namespace
+{
+ struct BuildJobChecker
+ {
+ bool visit(const PretendJob &) const
+ {
+ return false;
+ }
+
+ bool visit(const SyncPointJob &) const
+ {
+ return false;
+ }
+
+ bool visit(const UntakenInstallJob &) const
+ {
+ return true;
+ }
+
+ bool visit(const NoChangeJob &) const
+ {
+ return true;
+ }
+
+ bool visit(const SimpleInstallJob &) const
+ {
+ return true;
+ }
+ };
+}
+
+const JobID
+Jobs::find_id_for_building(const Resolvent & r) const
+{
+ std::pair<JobsListByResolventIndex::const_iterator, JobsListByResolventIndex::const_iterator> candidates(
+ _imp->jobs_list_by_resolvent_index.equal_range(r));
+
+ for ( ; candidates.first != candidates.second ; ++candidates.first)
+ {
+ if ((*candidates.first->second)->accept_returning<bool>(BuildJobChecker()))
+ return (*candidates.first->second)->id();
+ }
+
+ throw InternalError(PALUDIS_HERE, "no build job for " + stringify(r));
+}
+
+bool
+Jobs::have_job_for_building(const Resolvent & r) const
+{
+ std::pair<JobsListByResolventIndex::const_iterator, JobsListByResolventIndex::const_iterator> candidates(
+ _imp->jobs_list_by_resolvent_index.equal_range(r));
+
+ for ( ; candidates.first != candidates.second ; ++candidates.first)
+ {
+ if ((*candidates.first->second)->accept_returning<bool>(BuildJobChecker()))
+ return true;
+ }
+
+ return false;
+}
+
+const std::tr1::shared_ptr<Job>
+Jobs::fetch(const JobID & id)
+{
+ for (JobsList::const_iterator j(_imp->jobs.begin()), j_end(_imp->jobs.end()) ;
+ j != j_end ; ++j)
+ if ((*j)->id() == id)
+ return *j;
+
+ throw InternalError(PALUDIS_HERE, "no job for id");
+}
+
+const std::tr1::shared_ptr<const Job>
+Jobs::fetch(const JobID & id) const
+{
+ for (JobsList::const_iterator j(_imp->jobs.begin()), j_end(_imp->jobs.end()) ;
+ j != j_end ; ++j)
+ if ((*j)->id() == id)
+ return *j;
+
+ throw InternalError(PALUDIS_HERE, "no job for id");
+}
+
+void
+Jobs::serialise(Serialiser & s) const
+{
+ s.object("Jobs")
+ .member(SerialiserFlags<serialise::container>(), "items", _imp->jobs)
+ ;
+}
+
+const std::tr1::shared_ptr<Jobs>
+Jobs::deserialise(Deserialisation & d)
+{
+ Deserialisator v(d, "Jobs");
+ Deserialisator vv(*v.find_remove_member("items"), "c");
+ std::tr1::shared_ptr<Jobs> result(new Jobs);
+ for (int n(1), n_end(vv.member<int>("count") + 1) ; n != n_end ; ++n)
+ result->add(vv.member<std::tr1::shared_ptr<Job> >(stringify(n)));
+ return result;
+}
+
+template class PrivateImplementationPattern<resolver::Jobs>;
+
diff --git a/paludis/resolver/jobs.hh b/paludis/resolver/jobs.hh
new file mode 100644
index 0000000..6010d82
--- /dev/null
+++ b/paludis/resolver/jobs.hh
@@ -0,0 +1,67 @@
+/* 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_JOBS_HH
+#define PALUDIS_GUARD_PALUDIS_RESOLVER_JOBS_HH 1
+
+#include <paludis/resolver/jobs-fwd.hh>
+#include <paludis/resolver/job-fwd.hh>
+#include <paludis/resolver/job_id-fwd.hh>
+#include <paludis/resolver/resolvent-fwd.hh>
+#include <paludis/util/attributes.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/serialise-fwd.hh>
+#include <tr1/memory>
+
+namespace paludis
+{
+ namespace resolver
+ {
+ class PALUDIS_VISIBLE Jobs :
+ private PrivateImplementationPattern<Jobs>
+ {
+ public:
+ Jobs();
+ ~Jobs();
+
+ void add(const std::tr1::shared_ptr<Job> &);
+
+ bool have_job_for_building(const Resolvent &) const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ const JobID find_id_for_building(const Resolvent &) const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ const std::tr1::shared_ptr<Job> fetch(
+ const JobID &) PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ const std::tr1::shared_ptr<const Job> fetch(
+ const JobID &) const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ void serialise(Serialiser &) const;
+
+ static const std::tr1::shared_ptr<Jobs> deserialise(
+ Deserialisation & d) PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+ }
+
+#ifdef PALUDIS_HAVE_EXTERN_TEMPLATE
+ extern template class PrivateImplementationPattern<resolver::Jobs>;
+#endif
+
+}
+#endif
diff --git a/paludis/resolver/orderer.cc b/paludis/resolver/orderer.cc
index a362abf..fcfd9c2 100644
--- a/paludis/resolver/orderer.cc
+++ b/paludis/resolver/orderer.cc
@@ -27,8 +27,11 @@
#include <paludis/resolver/decision.hh>
#include <paludis/resolver/resolutions.hh>
#include <paludis/resolver/resolver.hh>
+#include <paludis/resolver/resolver_lists.hh>
+#include <paludis/resolver/job.hh>
+#include <paludis/resolver/jobs.hh>
#include <paludis/util/exception.hh>
-#include <paludis/util/sequence.hh>
+#include <paludis/util/sequence-impl.hh>
#include <paludis/util/wrapped_forward_iterator-impl.hh>
#include <paludis/util/indirect_iterator-impl.hh>
#include <paludis/util/accept_visitor.hh>
@@ -37,15 +40,16 @@
#include <paludis/util/stringify.hh>
#include <paludis/util/private_implementation_pattern-impl.hh>
#include <paludis/util/log.hh>
+#include <paludis/util/simple_visitor_cast.hh>
+#include <paludis/util/hashes.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>
+#include <tr1/unordered_set>
using namespace paludis;
using namespace paludis::resolver;
@@ -60,6 +64,8 @@ namespace paludis
const std::tr1::shared_ptr<ResolverLists> lists;
+ std::tr1::unordered_set<JobID, Hash<JobID> > already_ordered;
+
Implementation(const Environment * const e,
const std::tr1::shared_ptr<const Decider> & d,
const std::tr1::shared_ptr<ResolverLists> & l) :
@@ -82,352 +88,541 @@ Orderer::~Orderer()
}
void
-Orderer::_resolve_arrows()
+Orderer::resolve()
{
- Context context("When creating arrows for order resolution:");
+ _resolve_jobs();
+ _resolve_jobs_dep_arrows();
+ _resolve_order();
+}
- for (Resolutions::ConstIterator i(_imp->lists->all()->begin()),
- i_end(_imp->lists->all()->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 paludis
+{
+ namespace n
+ {
+ struct done_installs;
+ struct done_pretends;
+ }
}
namespace
{
- struct GetDependencyReason
+ struct CommonJobs
+ {
+ NamedValue<n::done_installs, std::tr1::shared_ptr<Job> > done_installs;
+ NamedValue<n::done_pretends, std::tr1::shared_ptr<Job> > done_pretends;
+ };
+
+ struct DecisionHandler
{
- const DependencyReason * visit(const DependencyReason & r) const
+ CommonJobs & common_jobs;
+ const std::tr1::shared_ptr<Resolution> resolution;
+ const std::tr1::shared_ptr<ResolverLists> lists;
+
+ DecisionHandler(
+ CommonJobs & c,
+ const std::tr1::shared_ptr<Resolution> & r,
+ const std::tr1::shared_ptr<ResolverLists> & l) :
+ common_jobs(c),
+ resolution(r),
+ lists(l)
+ {
+ }
+
+ void visit(const NothingNoChangeDecision & d)
{
- return &r;
+ if (d.taken())
+ {
+ Log::get_instance()->message("resolver.orderer.job.nothing_no_change", ll_debug, lc_no_context)
+ << "taken " << resolution->resolvent() << " nothing no change";
+
+ const std::tr1::shared_ptr<NoChangeJob> no_change_job(new NoChangeJob(resolution));
+ lists->jobs()->add(no_change_job);
+ lists->unordered_job_ids()->push_back(no_change_job->id());
+
+ /* we want to do all of these as part of the main build process,
+ * not at pretend time */
+ no_change_job->arrows()->push_back(make_named_values<Arrow>(
+ value_for<n::comes_after>(common_jobs.done_pretends()->id()),
+ value_for<n::maybe_reason>(make_null_shared_ptr())
+ ));
+ }
+ else
+ {
+ Log::get_instance()->message("resolver.orderer.job.nothing_no_change", ll_debug, lc_no_context)
+ << "untaken " << resolution->resolvent() << " nothing no change";
+ }
}
- const DependencyReason * visit(const SetReason & r) const
+ void visit(const ExistingNoChangeDecision & d)
{
- return r.reason_for_set()->accept_returning<const DependencyReason *>(*this);
+ if (d.taken())
+ {
+ Log::get_instance()->message("resolver.orderer.job.existing_no_change", ll_debug, lc_no_context)
+ << "taken " << resolution->resolvent() << " existing no change";
+
+ const std::tr1::shared_ptr<NoChangeJob> no_change_job(new NoChangeJob(resolution));
+ lists->jobs()->add(no_change_job);
+ lists->unordered_job_ids()->push_back(no_change_job->id());
+
+ /* we want to do all of these as part of the main build process,
+ * not at pretend time */
+ no_change_job->arrows()->push_back(make_named_values<Arrow>(
+ value_for<n::comes_after>(common_jobs.done_pretends()->id()),
+ value_for<n::maybe_reason>(make_null_shared_ptr())
+ ));
+ }
+ else
+ {
+ Log::get_instance()->message("resolver.orderer.job.existing_no_change", ll_debug, lc_no_context)
+ << "untaken " << resolution->resolvent() << " existing no change";
+ }
}
- const DependencyReason * visit(const TargetReason &) const
+ void visit(const ChangesToMakeDecision & d)
{
- return 0;
+ if (d.taken())
+ {
+ Log::get_instance()->message("resolver.orderer.job.changes_to_make", ll_debug, lc_no_context)
+ << "taken " << resolution->resolvent() << " changes to make";
+
+ const std::tr1::shared_ptr<PretendJob> pretend_job(new PretendJob(resolution,
+ d.shared_from_this()));
+ lists->jobs()->add(pretend_job);
+ lists->unordered_job_ids()->push_back(pretend_job->id());
+
+ const std::tr1::shared_ptr<SimpleInstallJob> install_job(new SimpleInstallJob(resolution,
+ d.shared_from_this()));
+ lists->jobs()->add(install_job);
+ lists->unordered_job_ids()->push_back(install_job->id());
+
+ /* we can't do any installs until all pretends have passed */
+ install_job->arrows()->push_back(make_named_values<Arrow>(
+ value_for<n::comes_after>(common_jobs.done_pretends()->id()),
+ value_for<n::maybe_reason>(make_null_shared_ptr())
+ ));
+
+ /* we haven't done all our pretends until we've done our pretend */
+ common_jobs.done_pretends()->arrows()->push_back(make_named_values<Arrow>(
+ value_for<n::comes_after>(pretend_job->id()),
+ value_for<n::maybe_reason>(make_null_shared_ptr())
+ ));
+
+ /* we haven't done all our installs until we've done our install */
+ common_jobs.done_installs()->arrows()->push_back(make_named_values<Arrow>(
+ value_for<n::comes_after>(install_job->id()),
+ value_for<n::maybe_reason>(make_null_shared_ptr())
+ ));
+ }
+ else
+ {
+ Log::get_instance()->message("resolver.orderer.job.changes_to_make", ll_debug, lc_no_context)
+ << "untaken " << resolution->resolvent() << " changes to make";
+
+ const std::tr1::shared_ptr<UntakenInstallJob> install_job(new UntakenInstallJob(resolution));
+ lists->jobs()->add(install_job);
+ lists->untaken_job_ids()->push_back(install_job->id());
+ }
}
- const DependencyReason * visit(const PresetReason &) const
+ void visit(const UnableToMakeDecision & d)
{
- return 0;
+ if (d.taken())
+ {
+ Log::get_instance()->message("resolver.orderer.job.unable_to_make", ll_debug, lc_no_context)
+ << "taken " << resolution->resolvent() << " unable to make";
+
+ lists->error_resolutions()->append(resolution);
+ }
+ else
+ {
+ Log::get_instance()->message("resolver.orderer.job.unable_to_make", ll_debug, lc_no_context)
+ << "untaken " << resolution->resolvent() << " unable to make";
+
+ const std::tr1::shared_ptr<UntakenInstallJob> install_job(new UntakenInstallJob(resolution));
+ lists->jobs()->add(install_job);
+ lists->untaken_job_ids()->push_back(install_job->id());
+ }
}
};
+}
+
+void
+Orderer::_resolve_jobs()
+{
+ CommonJobs common_jobs(make_named_values<CommonJobs>(
+ value_for<n::done_installs>(make_shared_ptr(new SyncPointJob(sp_done_installs))),
+ value_for<n::done_pretends>(make_shared_ptr(new SyncPointJob(sp_done_pretends)))
+ ));
+
+ _imp->lists->jobs()->add(common_jobs.done_installs());
+ _imp->lists->unordered_job_ids()->push_back(common_jobs.done_installs()->id());
+
+ _imp->lists->jobs()->add(common_jobs.done_pretends());
+ _imp->lists->unordered_job_ids()->push_back(common_jobs.done_pretends()->id());
+
+ for (Resolutions::ConstIterator i(_imp->lists->all_resolutions()->begin()),
+ i_end(_imp->lists->all_resolutions()->end()) ;
+ i != i_end ; ++i)
+ {
+ DecisionHandler d(common_jobs, *i, _imp->lists);
+ (*i)->decision()->accept(d);
+ }
+}
- struct ArrowInfo
+namespace
+{
+ struct LabelArrowsInfo
{
- bool causes_pre_arrow;
- bool ignorable;
+ bool build;
+ bool run;
- ArrowInfo(const DependencyReason & reason) :
- causes_pre_arrow(false),
- ignorable(true)
+ LabelArrowsInfo() :
+ build(false),
+ run(false)
{
- 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;
+ build = true;
}
- void visit(const DependenciesTestLabel &)
+ void visit(const DependenciesInstallLabel &)
{
- causes_pre_arrow = true;
- ignorable = false;
+ build = true;
+ }
+
+ void visit(const DependenciesFetchLabel &)
+ {
+ build = true;
}
void visit(const DependenciesRunLabel &)
{
- causes_pre_arrow = true;
+ run = true;
+ }
+
+ void visit(const DependenciesTestLabel &)
+ {
+ build = true;
}
void visit(const DependenciesPostLabel &)
{
}
- void visit(const DependenciesInstallLabel &)
+ void visit(const DependenciesSuggestionLabel &)
+ {
+ }
+
+ void visit(const DependenciesRecommendationLabel &)
{
- causes_pre_arrow = true;
- ignorable = false;
}
void visit(const DependenciesCompileAgainstLabel &)
{
- causes_pre_arrow = true;
- ignorable = false;
+ build = true;
}
+ };
- void visit(const DependenciesFetchLabel &)
+ struct DepArrowsAdder
+ {
+ const std::tr1::shared_ptr<Jobs> jobs;
+ const JobID we_are_usable_identifier;
+ const std::tr1::shared_ptr<const Reason> reason;
+
+ DepArrowsAdder(
+ const std::tr1::shared_ptr<Jobs> & j,
+ const JobID & i,
+ const std::tr1::shared_ptr<const Reason> & r) :
+ jobs(j),
+ we_are_usable_identifier(i),
+ reason(r)
{
- causes_pre_arrow = true;
- ignorable = false;
}
- void visit(const DependenciesRecommendationLabel &)
+ void visit(const TargetReason &) const
{
}
- void visit(const DependenciesSuggestionLabel &)
+ void visit(const PresetReason &) const
{
}
- };
-}
-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;
+ void visit(const SetReason & r) const
+ {
+ r.reason_for_set()->accept(*this);
+ }
- const Resolvent from_resolvent(if_dependency_reason->from_resolvent());
- const std::tr1::shared_ptr<Resolution> resolution(_imp->decider->resolution_for_resolvent(from_resolvent));
+ void visit(const DependencyReason & r) const
+ {
+ Context context("When adding arrows for job '" + stringify(we_are_usable_identifier.string_id())
+ + "' with reason '" + stringify(r.sanitised_dependency().spec())
+ + "' from '" + stringify(r.from_resolvent()) + "':");
+
+ /* we might not be changing anything (e.g. for a blocker), or we
+ * might be a dependency that got cancelled out later when
+ * something was changed from a decision to an error. */
+ if (! jobs->have_job_for_building(r.from_resolvent()))
+ {
+ Log::get_instance()->message("resolver.orderer.job.no_job_for_building", ll_warning, lc_context)
+ << "No job for building '" << r.from_resolvent() << "'. Verify manually that this is sane for now.";
+ return;
+ }
- /* 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 (r.sanitised_dependency().spec().if_block())
+ {
+ /* only strong blockers impose arrows. todo: maybe weak
+ * blockers should impose some kind of weak arrow? or would
+ * that make matters worse with silly Gentoo KDE blockers? */
+ if (r.sanitised_dependency().spec().if_block()->strong())
+ {
+ /* todo: this should probably only cause an arrow if the
+ * blocker is currently met */
+ jobs->fetch(jobs->find_id_for_building(r.from_resolvent()))->arrows()->push_back(
+ make_named_values<Arrow>(
+ value_for<n::comes_after>(we_are_usable_identifier),
+ value_for<n::maybe_reason>(reason)
+ ));
+ }
+ }
+ else
+ {
+ LabelArrowsInfo v;
+ for (DependenciesLabelSequence::ConstIterator l(r.sanitised_dependency().active_dependency_labels()->begin()),
+ l_end(r.sanitised_dependency().active_dependency_labels()->end()) ;
+ l != l_end ; ++l)
+ (*l)->accept(v);
+
+ if (v.build || v.run)
+ {
+ jobs->fetch(jobs->find_id_for_building(r.from_resolvent()))->arrows()->push_back(
+ make_named_values<Arrow>(
+ value_for<n::comes_after>(we_are_usable_identifier),
+ value_for<n::maybe_reason>(reason)
+ ));
+ }
+ }
+ }
+ };
- if (constraint->spec().if_block())
+ struct DepArrowHandler
{
- if (constraint->spec().if_block()->strong())
+ const std::tr1::shared_ptr<Jobs> jobs;
+ const JobID we_are_usable_identifier;
+
+ DepArrowHandler(
+ const std::tr1::shared_ptr<Jobs> & j,
+ const JobID & i) :
+ jobs(j),
+ we_are_usable_identifier(i)
{
- 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)
+
+ void add_dep_arrows(const std::tr1::shared_ptr<const Resolution> & r)
{
- int ignorable_pass(0);
- if (_already_met(if_dependency_reason->sanitised_dependency()))
- ignorable_pass = 1;
- else if (a.ignorable)
- ignorable_pass = 2;
+ for (Constraints::ConstIterator c(r->constraints()->begin()), c_end(r->constraints()->end()) ;
+ c != c_end ; ++c)
+ if ((*c)->reason())
+ (*c)->reason()->accept(DepArrowsAdder(jobs, we_are_usable_identifier, (*c)->reason()));
+ }
- 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())
- ))));
+ void visit(const SimpleInstallJob & c)
+ {
+ add_dep_arrows(c.resolution());
}
- }
+
+ void visit(const NoChangeJob & c)
+ {
+ /* a dep b dep c, b not changing. we still want c before a. */
+ add_dep_arrows(c.resolution());
+ }
+
+ void visit(const PretendJob &)
+ {
+ }
+
+ void visit(const UntakenInstallJob &)
+ {
+ }
+
+ void visit(const SyncPointJob &)
+ {
+ }
+ };
}
-bool
-Orderer::_already_met(const SanitisedDependency & dep) const
+void
+Orderer::_resolve_jobs_dep_arrows()
{
- 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())
+ Context context("When resolving dep arrows:");
+
+ for (JobIDSequence::ConstIterator i(_imp->lists->unordered_job_ids()->begin()),
+ i_end(_imp->lists->unordered_job_ids()->end()) ;
+ i != i_end ; ++i)
{
- /* it's imposing an arrow, so it's a strong block */
- return false;
+ DepArrowHandler d(_imp->lists->jobs(), *i);
+ _imp->lists->jobs()->fetch(*i)->accept(d);
}
- 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 remaining(true);
+ int pass(1);
+ while (remaining)
{
+ remaining = false;
bool any(false);
- done = true;
- int ignore_pass(0);
- while (true)
+ _imp->env->trigger_notifier_callback(NotifierCallbackResolverStepEvent());
+
+ for (JobIDSequence::ConstIterator i(_imp->lists->unordered_job_ids()->begin()),
+ i_end(_imp->lists->unordered_job_ids()->end()) ;
+ i != i_end ; ++i)
{
- for (Resolutions::ConstIterator i(_imp->lists->unordered()->begin()),
- i_end(_imp->lists->unordered()->end()) ;
- i != i_end ; ++i)
- {
- if ((*i)->already_ordered())
- continue;
+ if (_already_ordered(*i))
+ 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;
- }
+ remaining = true;
- 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)
+ if (! _can_order(*i, 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;
- }
+ _imp->lists->ordered_job_ids()->push_back(*i);
+ any = true;
+ _mark_already_ordered(*i);
- return true;
-}
+ if (pass >= 3)
+ Log::get_instance()->message("resolver.orderer.job.broke_cycle", ll_warning, lc_context)
+ << "Had to use cycle breaking to order " << i->string_id() << " (pass " << pass << ")";
-void
-Orderer::_do_order(const Resolvent &, const std::tr1::shared_ptr<Resolution> & resolution)
-{
- _imp->lists->ordered()->append(resolution);
- resolution->already_ordered() = true;
-}
+ pass = 1;
+ }
-void
-Orderer::_unable_to_order_more() const
-{
- std::cout << "Unable to order any of the following:" << std::endl;
+ if (remaining && ! any)
+ {
+ if (++pass < 4)
+ continue;
- for (Resolutions::ConstIterator i(_imp->lists->unordered()->begin()),
- i_end(_imp->lists->unordered()->end()) ;
- i != i_end ; ++i)
- {
- if ((*i)->already_ordered())
- continue;
+ std::stringstream s;
+ for (JobIDSequence::ConstIterator i(_imp->lists->unordered_job_ids()->begin()),
+ i_end(_imp->lists->unordered_job_ids()->end()) ;
+ i != i_end ; ++i)
+ {
+ if (_already_ordered(*i))
+ continue;
- std::cout << " * " << (*i)->resolvent() << " because of cycle "
- << _find_cycle((*i)->resolvent(), true)
- << std::endl;
- }
+ s << " {{{" << i->string_id() << " missing";
+ const std::tr1::shared_ptr<const Job> job(_imp->lists->jobs()->fetch(*i));
+ for (ArrowSequence::ConstIterator a(job->arrows()->begin()), a_end(job->arrows()->end()) ;
+ a != a_end ; ++a)
+ if (! _already_ordered(a->comes_after()))
+ s << " [" << a->comes_after().string_id() << "]";
+ s << " }}}";
+ }
- throw InternalError(PALUDIS_HERE, "unimplemented: unfixable dep cycle");
+ throw InternalError(PALUDIS_HERE, "unbreakable cycle, remaining" + s.str());
+ }
+ }
}
namespace
{
- struct ReasonDescriber
+ typedef std::tr1::function<bool (const PackageOrBlockDepSpec &)> AlreadyMetFn;
+
+ struct AlreadyMetDep
{
- const std::string visit(const DependencyReason & r) const
+ const AlreadyMetFn already_met;
+
+ AlreadyMetDep(const AlreadyMetFn & a) :
+ already_met(a)
+ {
+ }
+
+ bool visit(const PresetReason &) const
{
- return " (" + r.sanitised_dependency().active_dependency_labels_as_string() + " " +
- stringify(r.sanitised_dependency().spec()) + ")";
+ return false;
}
- const std::string visit(const TargetReason &) const
+ bool visit(const TargetReason &) const
{
- return "";
+ return false;
}
- const std::string visit(const PresetReason &) const
+ bool visit(const SetReason & r) const
{
- return "";
+ return r.reason_for_set()->accept_returning<bool>(*this);
}
- const std::string visit(const SetReason &) const
+ bool visit(const DependencyReason & r) const
{
- return "";
+ return already_met(r.sanitised_dependency().spec());
}
};
}
-const std::string
-Orderer::_find_cycle(const Resolvent & start_resolvent, const int ignorable_pass) const
+bool
+Orderer::_can_order(const JobID & i, const int pass) const
{
- std::stringstream result;
-
- std::set<Resolvent> seen;
- Resolvent current(start_resolvent);
-
- bool first(true);
- while (true)
+ const std::tr1::shared_ptr<const Job> job(_imp->lists->jobs()->fetch(i));
+ for (ArrowSequence::ConstIterator a(job->arrows()->begin()), a_end(job->arrows()->end()) ;
+ a != a_end ; ++a)
{
- 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 (! _already_ordered(a->comes_after()))
{
- if (_can_order_now(current, resolution, ignorable_pass))
- continue;
+ bool skippable(false);
- const std::tr1::shared_ptr<const Resolution> to_resolution(
- _imp->decider->resolution_for_resolvent((*a)->comes_after()));
- if (to_resolution->already_ordered())
- continue;
+ if ((! skippable) && (pass >= 2))
+ {
+ /* if our job is a NoChangeJob, and we're supposed to come
+ * after a NoChangeJob, ignore the arrow. */
+ const std::tr1::shared_ptr<const Job> other_job(_imp->lists->jobs()->fetch(a->comes_after()));
+ if (simple_visitor_cast<const NoChangeJob>(*job) &&
+ simple_visitor_cast<const NoChangeJob>(*other_job))
+ skippable = true;
+ }
- ok = true;
- result << (*a)->reason()->accept_returning<std::string>(ReasonDescriber());
- current = (*a)->comes_after();
- break;
- }
+ if ((! skippable) && (pass >= 3))
+ {
+ /* we can also ignore any arrows that are already met (e.g a
+ * dep b, b dep a, a is already installed */
+ if (a->maybe_reason() && a->maybe_reason()->accept_returning<bool>(
+ AlreadyMetDep(std::tr1::bind(&Orderer::_already_met, this, std::tr1::placeholders::_1))))
+ skippable = true;
+ }
- if (! ok)
- throw InternalError(PALUDIS_HERE, "resolver bug: there's a cycle, but we don't know what it is");
+ if (! skippable)
+ return false;
+ }
}
- return result.str();
+ return true;
+}
+
+bool
+Orderer::_already_ordered(const JobID & i) const
+{
+ return _imp->already_ordered.end() != _imp->already_ordered.find(i);
}
void
-Orderer::resolve()
+Orderer::_mark_already_ordered(const JobID & i)
{
- _resolve_arrows();
- _resolve_order();
+ if (! _imp->already_ordered.insert(i).second)
+ throw InternalError(PALUDIS_HERE, "already already ordered");
+}
+
+bool
+Orderer::_already_met(const PackageOrBlockDepSpec & spec) const
+{
+ const std::tr1::shared_ptr<const PackageIDSequence> installed_ids((*_imp->env)[selection::BestVersionOnly(
+ generator::Matches(spec.if_package() ? *spec.if_package() : spec.if_block()->blocking(), MatchPackageOptions()) |
+ filter::InstalledAtRoot(FSEntry("/")))]);
+ if (installed_ids->empty())
+ return spec.if_block();
+ else
+ return spec.if_package();
}
diff --git a/paludis/resolver/orderer.hh b/paludis/resolver/orderer.hh
index 4ac496a..045efe4 100644
--- a/paludis/resolver/orderer.hh
+++ b/paludis/resolver/orderer.hh
@@ -30,6 +30,7 @@
#include <paludis/resolver/sanitised_dependencies-fwd.hh>
#include <paludis/resolver/decider-fwd.hh>
#include <paludis/resolver/resolver-fwd.hh>
+#include <paludis/resolver/job_id-fwd.hh>
#include <paludis/util/attributes.hh>
#include <paludis/util/private_implementation_pattern.hh>
#include <paludis/environment.hh>
@@ -43,24 +44,15 @@ namespace paludis
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_jobs();
+ void _resolve_jobs_dep_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_ordered(const JobID &) const PALUDIS_ATTRIBUTE((warn_unused_result));
+ bool _can_order(const JobID &, const int pass) const PALUDIS_ATTRIBUTE((warn_unused_result));
+ void _mark_already_ordered(const JobID &);
- bool _already_met(const SanitisedDependency & dep) const;
+ bool _already_met(const PackageOrBlockDepSpec &) const PALUDIS_ATTRIBUTE((warn_unused_result));
public:
Orderer(
diff --git a/paludis/resolver/resolution.cc b/paludis/resolver/resolution.cc
index 0a160b4..22afd05 100644
--- a/paludis/resolver/resolution.cc
+++ b/paludis/resolver/resolution.cc
@@ -37,8 +37,6 @@ void
Resolution::serialise(Serialiser & s) const
{
s.object("Resolution")
- .member(SerialiserFlags<>(), "already_ordered", already_ordered())
- .member(SerialiserFlags<serialise::container, serialise::might_be_null>(), "arrows", arrows())
.member(SerialiserFlags<>(), "constraints", *constraints())
.member(SerialiserFlags<serialise::might_be_null>(), "decision", decision())
.member(SerialiserFlags<>(), "resolvent", resolvent())
@@ -50,14 +48,7 @@ Resolution::deserialise(Deserialisation & d)
{
Deserialisator v(d, "Resolution");
- std::tr1::shared_ptr<ArrowSequence> arrows(new ArrowSequence);
- Deserialisator vv(*v.find_remove_member("arrows"), "c");
- for (int n(1), n_end(vv.member<int>("count") + 1) ; n != n_end ; ++n)
- arrows->push_back(vv.member<std::tr1::shared_ptr<Arrow> >(stringify(n)));
-
return make_shared_ptr(new Resolution(make_named_values<Resolution>(
- value_for<n::already_ordered>(v.member<bool>("already_ordered")),
- value_for<n::arrows>(arrows),
value_for<n::constraints>(v.member<std::tr1::shared_ptr<Constraints> >("constraints")),
value_for<n::decision>(v.member<std::tr1::shared_ptr<Decision> >("decision")),
value_for<n::resolvent>(v.member<Resolvent>("resolvent"))
diff --git a/paludis/resolver/resolution.hh b/paludis/resolver/resolution.hh
index defa8bb..9ca9b69 100644
--- a/paludis/resolver/resolution.hh
+++ b/paludis/resolver/resolution.hh
@@ -21,7 +21,6 @@
#define PALUDIS_GUARD_PALUDIS_RESOLVER_RESOLUTION_HH 1
#include <paludis/resolver/resolution-fwd.hh>
-#include <paludis/resolver/arrow-fwd.hh>
#include <paludis/resolver/constraint-fwd.hh>
#include <paludis/resolver/decision-fwd.hh>
#include <paludis/resolver/resolvent.hh>
@@ -32,8 +31,6 @@ namespace paludis
{
namespace n
{
- struct already_ordered;
- struct arrows;
struct constraints;
struct decision;
struct resolvent;
@@ -43,8 +40,6 @@ namespace paludis
{
struct Resolution
{
- NamedValue<n::already_ordered, bool> already_ordered;
- NamedValue<n::arrows, std::tr1::shared_ptr<ArrowSequence> > arrows;
NamedValue<n::constraints, std::tr1::shared_ptr<Constraints> > constraints;
NamedValue<n::decision, std::tr1::shared_ptr<Decision> > decision;
NamedValue<n::resolvent, Resolvent> resolvent;
diff --git a/paludis/resolver/resolvent.cc b/paludis/resolver/resolvent.cc
index 79ca129..480a011 100644
--- a/paludis/resolver/resolvent.cc
+++ b/paludis/resolver/resolvent.cc
@@ -22,6 +22,7 @@
#include <paludis/util/wrapped_forward_iterator-impl.hh>
#include <paludis/util/make_named_values.hh>
#include <paludis/util/destringify.hh>
+#include <paludis/util/hashes.hh>
#include <paludis/dep_spec.hh>
#include <paludis/filter.hh>
#include <paludis/package_id.hh>
@@ -77,7 +78,7 @@ paludis::resolver::operator== (const Resolvent & a, const Resolvent & b)
bool
paludis::resolver::operator== (const SlotNameOrNull & a, const SlotNameOrNull & b)
{
- if (a.name_or_null() != b.name_or_null())
+ if ((!! a.name_or_null()) != (!! b.name_or_null()))
return false;
if ((a.name_or_null()) && (*a.name_or_null() != *b.name_or_null()))
@@ -189,6 +190,16 @@ Resolvent::deserialise(Deserialisation & d)
);
}
+std::size_t
+Resolvent::hash() const
+{
+ return
+ static_cast<int>(destination_type()) ^
+ Hash<QualifiedPackageName>()(package()) ^
+ Hash<SlotNameOrNull>()(slot())
+ ;
+}
+
Filter
paludis::resolver::make_slot_filter(const Resolvent & r)
{
@@ -241,6 +252,14 @@ SlotNameOrNull::deserialise(Deserialisation & d)
);
}
+std::size_t
+SlotNameOrNull::hash() const
+{
+ if (name_or_null())
+ return Hash<SlotName>()(*name_or_null());
+ else
+ return 0xdeadbeef;
+}
template class Sequence<Resolvent>;
template class WrappedForwardIterator<Resolvents::ConstIteratorTag, Resolvent>;
diff --git a/paludis/resolver/resolvent.hh b/paludis/resolver/resolvent.hh
index 9d67cff..4648e91 100644
--- a/paludis/resolver/resolvent.hh
+++ b/paludis/resolver/resolvent.hh
@@ -49,6 +49,8 @@ namespace paludis
void serialise(Serialiser &) const;
static const SlotNameOrNull deserialise(Deserialisation &) PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ std::size_t hash() const PALUDIS_ATTRIBUTE((warn_unused_result));
};
struct Resolvent
@@ -69,6 +71,8 @@ namespace paludis
void serialise(Serialiser &) const;
static const Resolvent deserialise(Deserialisation &) PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ std::size_t hash() const PALUDIS_ATTRIBUTE((warn_unused_result));
};
}
}
diff --git a/paludis/resolver/resolver.cc b/paludis/resolver/resolver.cc
index 16059f6..d98d57e 100644
--- a/paludis/resolver/resolver.cc
+++ b/paludis/resolver/resolver.cc
@@ -19,19 +19,21 @@
#include <paludis/resolver/resolver.hh>
#include <paludis/resolver/resolver_functions.hh>
+#include <paludis/resolver/resolver_lists.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/resolver/jobs.hh>
+#include <paludis/resolver/job_id.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/make_shared_copy.hh>
-#include <paludis/serialise-impl.hh>
#include <paludis/environment.hh>
#include <paludis/notifier_callback.hh>
#include <paludis/dep_spec_flattener.hh>
@@ -56,11 +58,12 @@ namespace paludis
env(e),
fns(f),
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::unordered>(make_shared_ptr(new Resolutions)),
- value_for<n::untaken>(make_shared_ptr(new Resolutions))
+ value_for<n::all_resolutions>(make_shared_ptr(new Resolutions)),
+ value_for<n::error_resolutions>(make_shared_ptr(new Resolutions)),
+ value_for<n::jobs>(make_shared_ptr(new Jobs)),
+ value_for<n::ordered_job_ids>(make_shared_ptr(new JobIDSequence)),
+ value_for<n::unordered_job_ids>(make_shared_ptr(new JobIDSequence)),
+ value_for<n::untaken_job_ids>(make_shared_ptr(new JobIDSequence))
))),
decider(new Decider(e, f, lists)),
orderer(new Orderer(e, decider, lists))
@@ -116,28 +119,3 @@ Resolver::lists() const
return _imp->lists;
}
-void
-ResolverLists::serialise(Serialiser & s) const
-{
- 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>(), "unordered", unordered())
- .member(SerialiserFlags<serialise::might_be_null>(), "untaken", untaken())
- ;
-}
-
-const ResolverLists
-ResolverLists::deserialise(Deserialisation & d)
-{
- 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::unordered>(v.member<std::tr1::shared_ptr<Resolutions> >("unordered")),
- value_for<n::untaken>(v.member<std::tr1::shared_ptr<Resolutions> >("untaken"))
- );
-}
-
diff --git a/paludis/resolver/resolver.hh b/paludis/resolver/resolver.hh
index d6a0241..0c98fa8 100644
--- a/paludis/resolver/resolver.hh
+++ b/paludis/resolver/resolver.hh
@@ -26,8 +26,8 @@
#include <paludis/resolver/decider-fwd.hh>
#include <paludis/resolver/orderer-fwd.hh>
#include <paludis/resolver/resolutions-fwd.hh>
+#include <paludis/resolver/resolver_lists-fwd.hh>
#include <paludis/util/private_implementation_pattern.hh>
-#include <paludis/util/named_value.hh>
#include <paludis/package_id-fwd.hh>
#include <paludis/dep_spec-fwd.hh>
#include <paludis/name.hh>
@@ -40,29 +40,8 @@
namespace paludis
{
- namespace n
- {
- struct all;
- struct errors;
- struct ordered;
- struct unordered;
- struct untaken;
- }
-
namespace resolver
{
- struct ResolverLists
- {
- 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::unordered, std::tr1::shared_ptr<Resolutions> > unordered;
- NamedValue<n::untaken, std::tr1::shared_ptr<Resolutions> > untaken;
-
- static const ResolverLists deserialise(Deserialisation &) PALUDIS_ATTRIBUTE((warn_unused_result));
- void serialise(Serialiser &) const;
- };
-
class PALUDIS_VISIBLE Resolver :
private PrivateImplementationPattern<Resolver>
{
diff --git a/paludis/resolver/resolver_TEST_blockers.cc b/paludis/resolver/resolver_TEST_blockers.cc
index 24c067d..28ab165 100644
--- a/paludis/resolver/resolver_TEST_blockers.cc
+++ b/paludis/resolver/resolver_TEST_blockers.cc
@@ -25,6 +25,7 @@
#include <paludis/resolver/constraint.hh>
#include <paludis/resolver/resolvent.hh>
#include <paludis/resolver/suggest_restart.hh>
+#include <paludis/resolver/resolver_lists.hh>
#include <paludis/environments/test/test_environment.hh>
#include <paludis/util/make_named_values.hh>
#include <paludis/util/options.hh>
@@ -78,14 +79,14 @@ namespace test_cases
{
TestMessageSuffix s("errors");
- check_resolution_list(resolutions->errors(), ResolutionListChecks()
+ check_resolution_list(resolutions->jobs(), resolutions->error_resolutions(), ResolutionListChecks()
.finished()
);
}
{
TestMessageSuffix s("ordered");
- check_resolution_list(resolutions->ordered(), ResolutionListChecks()
+ check_resolution_list(resolutions->jobs(), resolutions->ordered_job_ids(), ResolutionListChecks()
.qpn(QualifiedPackageName("hard/a-pkg"))
.qpn(QualifiedPackageName("hard/z-pkg"))
.qpn(QualifiedPackageName("hard/target"))
diff --git a/paludis/resolver/resolver_TEST_cycles.cc b/paludis/resolver/resolver_TEST_cycles.cc
new file mode 100644
index 0000000..5636ccc
--- /dev/null
+++ b/paludis/resolver/resolver_TEST_cycles.cc
@@ -0,0 +1,142 @@
+/* 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/resolver.hh>
+#include <paludis/resolver/resolver_functions.hh>
+#include <paludis/resolver/resolution.hh>
+#include <paludis/resolver/decision.hh>
+#include <paludis/resolver/resolutions.hh>
+#include <paludis/resolver/constraint.hh>
+#include <paludis/resolver/resolvent.hh>
+#include <paludis/resolver/suggest_restart.hh>
+#include <paludis/resolver/resolver_lists.hh>
+#include <paludis/environments/test/test_environment.hh>
+#include <paludis/util/make_named_values.hh>
+#include <paludis/util/options.hh>
+#include <paludis/util/wrapped_forward_iterator-impl.hh>
+#include <paludis/util/make_shared_ptr.hh>
+#include <paludis/util/sequence.hh>
+#include <paludis/util/map.hh>
+#include <paludis/util/indirect_iterator-impl.hh>
+#include <paludis/util/accept_visitor.hh>
+#include <paludis/user_dep_spec.hh>
+#include <paludis/repository_factory.hh>
+#include <paludis/package_database.hh>
+
+#include <paludis/resolver/resolver_test.hh>
+#include <test/test_runner.hh>
+#include <test/test_framework.hh>
+
+#include <list>
+#include <tr1/functional>
+#include <algorithm>
+#include <map>
+
+using namespace paludis;
+using namespace paludis::resolver;
+using namespace paludis::resolver::resolver_test;
+using namespace test;
+
+namespace
+{
+ struct ResolverCyclesTestCase : ResolverTestCase
+ {
+ ResolverCyclesTestCase(const std::string & s) :
+ ResolverTestCase("cycles", s, "exheres-0", "exheres")
+ {
+ }
+ };
+
+ UseExisting
+ use_existing_if_same(
+ const Resolvent &,
+ const PackageDepSpec &,
+ const std::tr1::shared_ptr<const Reason> &)
+ {
+ return ue_if_same;
+ }
+}
+
+namespace test_cases
+{
+ struct TestNoChanges : ResolverCyclesTestCase
+ {
+ TestNoChanges() : ResolverCyclesTestCase("no-changes") { }
+
+ virtual ResolverFunctions get_resolver_functions(InitialConstraints & initial_constraints)
+ {
+ ResolverFunctions result(ResolverCyclesTestCase::get_resolver_functions(initial_constraints));
+ result.get_use_existing_fn() = std::tr1::bind(&use_existing_if_same, std::tr1::placeholders::_1,
+ std::tr1::placeholders::_2, std::tr1::placeholders::_3);
+ return result;
+ }
+
+ void run()
+ {
+ install("no-changes", "dep-a", "1")->build_dependencies_key()->set_from_string("no-changes/dep-b");
+ install("no-changes", "dep-b", "1")->build_dependencies_key()->set_from_string("no-changes/dep-a");
+
+ std::tr1::shared_ptr<const ResolverLists> resolutions(get_resolutions("no-changes/target"));
+
+ {
+ TestMessageSuffix s("errors");
+ check_resolution_list(resolutions->jobs(), resolutions->error_resolutions(), ResolutionListChecks()
+ .finished()
+ );
+ }
+
+ {
+ TestMessageSuffix s("ordered");
+ check_resolution_list(resolutions->jobs(), resolutions->ordered_job_ids(), ResolutionListChecks()
+ .qpn(QualifiedPackageName("no-changes/target"))
+ .finished()
+ );
+ }
+ }
+ } test_no_changes;
+
+ struct TestExistingUsable : ResolverCyclesTestCase
+ {
+ TestExistingUsable() : ResolverCyclesTestCase("existing-usable") { }
+
+ void run()
+ {
+ install("existing-usable", "dep", "1");
+
+ std::tr1::shared_ptr<const ResolverLists> resolutions(get_resolutions("existing-usable/target"));
+
+ {
+ TestMessageSuffix s("errors");
+ check_resolution_list(resolutions->jobs(), resolutions->error_resolutions(), ResolutionListChecks()
+ .finished()
+ );
+ }
+
+ {
+ TestMessageSuffix s("ordered");
+ check_resolution_list(resolutions->jobs(), resolutions->ordered_job_ids(), ResolutionListChecks()
+ .qpn(QualifiedPackageName("existing-usable/target"))
+ .qpn(QualifiedPackageName("existing-usable/dep"))
+ .finished()
+ );
+ }
+ }
+ } test_existing_usable;
+}
+
diff --git a/paludis/resolver/resolver_TEST_cycles_cleanup.sh b/paludis/resolver/resolver_TEST_cycles_cleanup.sh
new file mode 100755
index 0000000..3c1b1ae
--- /dev/null
+++ b/paludis/resolver/resolver_TEST_cycles_cleanup.sh
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+# vim: set ft=sh sw=4 sts=4 et :
+
+if [ -d resolver_TEST_cycles_dir ] ; then
+ rm -fr resolver_TEST_cycles_dir
+else
+ true
+fi
+
diff --git a/paludis/resolver/resolver_TEST_cycles_setup.sh b/paludis/resolver/resolver_TEST_cycles_setup.sh
new file mode 100755
index 0000000..2c04ab1
--- /dev/null
+++ b/paludis/resolver/resolver_TEST_cycles_setup.sh
@@ -0,0 +1,64 @@
+#!/usr/bin/env bash
+# vim: set ft=sh sw=4 sts=4 et :
+
+mkdir resolver_TEST_cycles_dir || exit 1
+cd resolver_TEST_cycles_dir || exit 1
+
+mkdir -p build
+mkdir -p distdir
+mkdir -p installed
+
+mkdir -p repo/{profiles/profile,metadata}
+
+cd repo
+echo "repo" > profiles/repo_name
+: > metadata/categories.conf
+
+# no-changes
+echo 'no-changes' >> metadata/categories.conf
+
+mkdir -p 'packages/no-changes/target'
+cat <<END > packages/no-changes/target/target-1.exheres-0
+SUMMARY="target"
+PLATFORMS="test"
+SLOT="0"
+DEPENDENCIES="no-changes/dep-a no-changes/dep-b"
+END
+
+mkdir -p 'packages/no-changes/dep-a'
+cat <<END > packages/no-changes/dep-a/dep-a-1.exheres-0
+SUMMARY="target"
+PLATFORMS="test"
+SLOT="0"
+DEPENDENCIES="no-changes/dep-b"
+END
+
+mkdir -p 'packages/no-changes/dep-b'
+cat <<END > packages/no-changes/dep-b/dep-b-1.exheres-0
+SUMMARY="target"
+PLATFORMS="test"
+SLOT="0"
+DEPENDENCIES="no-changes/dep-a"
+END
+
+# existing-usable
+echo 'existing-usable' >> metadata/categories.conf
+
+mkdir -p 'packages/existing-usable/target'
+cat <<END > packages/existing-usable/target/target-1.exheres-0
+SUMMARY="target"
+PLATFORMS="test"
+SLOT="0"
+DEPENDENCIES="existing-usable/dep"
+END
+
+mkdir -p 'packages/existing-usable/dep'
+cat <<END > packages/existing-usable/dep/dep-2.exheres-0
+SUMMARY="target"
+PLATFORMS="test"
+SLOT="0"
+DEPENDENCIES="existing-usable/target"
+END
+
+cd ..
+
diff --git a/paludis/resolver/resolver_TEST_serialisation.cc b/paludis/resolver/resolver_TEST_serialisation.cc
index 4fb26b6..b33f380 100644
--- a/paludis/resolver/resolver_TEST_serialisation.cc
+++ b/paludis/resolver/resolver_TEST_serialisation.cc
@@ -25,6 +25,7 @@
#include <paludis/resolver/constraint.hh>
#include <paludis/resolver/resolvent.hh>
#include <paludis/resolver/suggest_restart.hh>
+#include <paludis/resolver/resolver_lists.hh>
#include <paludis/environments/test/test_environment.hh>
#include <paludis/util/make_named_values.hh>
#include <paludis/util/options.hh>
@@ -86,7 +87,7 @@ namespace test_cases
{
TestMessageSuffix s("errors");
- check_resolution_list(resolutions->errors(), ResolutionListChecks()
+ check_resolution_list(resolutions->jobs(), resolutions->error_resolutions(), ResolutionListChecks()
.kind("unable_to_make_decision", QualifiedPackageName("serialisation/error"))
.finished()
);
@@ -94,7 +95,7 @@ namespace test_cases
{
TestMessageSuffix s("ordered");
- check_resolution_list(resolutions->ordered(), ResolutionListChecks()
+ check_resolution_list(resolutions->jobs(), resolutions->ordered_job_ids(), ResolutionListChecks()
.qpn(QualifiedPackageName("serialisation/dep"))
.qpn(QualifiedPackageName("serialisation/target"))
.finished()
@@ -103,7 +104,7 @@ namespace test_cases
{
TestMessageSuffix s("untaken");
- check_resolution_list(resolutions->untaken(), ResolutionListChecks()
+ check_resolution_list(resolutions->jobs(), resolutions->untaken_job_ids(), ResolutionListChecks()
.qpn(QualifiedPackageName("serialisation/suggestion"))
.finished()
);
diff --git a/paludis/resolver/resolver_TEST_simple.cc b/paludis/resolver/resolver_TEST_simple.cc
new file mode 100644
index 0000000..9e50b7e
--- /dev/null
+++ b/paludis/resolver/resolver_TEST_simple.cc
@@ -0,0 +1,122 @@
+/* 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/resolver.hh>
+#include <paludis/resolver/resolver_functions.hh>
+#include <paludis/resolver/resolution.hh>
+#include <paludis/resolver/decision.hh>
+#include <paludis/resolver/resolutions.hh>
+#include <paludis/resolver/constraint.hh>
+#include <paludis/resolver/resolvent.hh>
+#include <paludis/resolver/suggest_restart.hh>
+#include <paludis/resolver/resolver_lists.hh>
+#include <paludis/environments/test/test_environment.hh>
+#include <paludis/util/make_named_values.hh>
+#include <paludis/util/options.hh>
+#include <paludis/util/wrapped_forward_iterator-impl.hh>
+#include <paludis/util/make_shared_ptr.hh>
+#include <paludis/util/sequence.hh>
+#include <paludis/util/map.hh>
+#include <paludis/util/indirect_iterator-impl.hh>
+#include <paludis/util/accept_visitor.hh>
+#include <paludis/user_dep_spec.hh>
+#include <paludis/repository_factory.hh>
+#include <paludis/package_database.hh>
+
+#include <paludis/resolver/resolver_test.hh>
+#include <test/test_runner.hh>
+#include <test/test_framework.hh>
+
+#include <list>
+#include <tr1/functional>
+#include <algorithm>
+#include <map>
+
+using namespace paludis;
+using namespace paludis::resolver;
+using namespace paludis::resolver::resolver_test;
+using namespace test;
+
+namespace
+{
+ struct ResolverSimpleTestCase : ResolverTestCase
+ {
+ ResolverSimpleTestCase(const std::string & s) :
+ ResolverTestCase("simple", s, "exheres-0", "exheres")
+ {
+ }
+ };
+}
+
+namespace test_cases
+{
+ struct TestNoDeps : ResolverSimpleTestCase
+ {
+ TestNoDeps() : ResolverSimpleTestCase("no-deps") { }
+
+ void run()
+ {
+ std::tr1::shared_ptr<const ResolverLists> resolutions(get_resolutions("no-deps/target"));
+
+ {
+ TestMessageSuffix s("errors");
+ check_resolution_list(resolutions->jobs(), resolutions->error_resolutions(), ResolutionListChecks()
+ .finished()
+ );
+ }
+
+ {
+ TestMessageSuffix s("ordered");
+ check_resolution_list(resolutions->jobs(), resolutions->ordered_job_ids(), ResolutionListChecks()
+ .qpn(QualifiedPackageName("no-deps/target"))
+ .finished()
+ );
+ }
+ }
+ } test_no_deps;
+
+ struct TestBuildDeps : ResolverSimpleTestCase
+ {
+ TestBuildDeps() : ResolverSimpleTestCase("build-deps") { }
+
+ void run()
+ {
+ std::tr1::shared_ptr<const ResolverLists> resolutions(get_resolutions("build-deps/target"));
+
+ {
+ TestMessageSuffix s("errors");
+ check_resolution_list(resolutions->jobs(), resolutions->error_resolutions(), ResolutionListChecks()
+ .finished()
+ );
+ }
+
+ {
+ TestMessageSuffix s("ordered");
+ check_resolution_list(resolutions->jobs(), resolutions->ordered_job_ids(), ResolutionListChecks()
+ .qpn(QualifiedPackageName("build-deps/a-dep"))
+ .qpn(QualifiedPackageName("build-deps/b-dep"))
+ .qpn(QualifiedPackageName("build-deps/z-dep"))
+ .qpn(QualifiedPackageName("build-deps/target"))
+ .finished()
+ );
+ }
+ }
+ } test_build_deps;
+}
+
diff --git a/paludis/resolver/resolver_TEST_simple_cleanup.sh b/paludis/resolver/resolver_TEST_simple_cleanup.sh
new file mode 100755
index 0000000..46b868e
--- /dev/null
+++ b/paludis/resolver/resolver_TEST_simple_cleanup.sh
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+# vim: set ft=sh sw=4 sts=4 et :
+
+if [ -d resolver_TEST_simple_dir ] ; then
+ rm -fr resolver_TEST_simple_dir
+else
+ true
+fi
+
diff --git a/paludis/resolver/resolver_TEST_simple_setup.sh b/paludis/resolver/resolver_TEST_simple_setup.sh
new file mode 100755
index 0000000..c025889
--- /dev/null
+++ b/paludis/resolver/resolver_TEST_simple_setup.sh
@@ -0,0 +1,64 @@
+#!/usr/bin/env bash
+# vim: set ft=sh sw=4 sts=4 et :
+
+mkdir resolver_TEST_simple_dir || exit 1
+cd resolver_TEST_simple_dir || exit 1
+
+mkdir -p build
+mkdir -p distdir
+mkdir -p installed
+
+mkdir -p repo/{profiles/profile,metadata}
+
+cd repo
+echo "repo" > profiles/repo_name
+: > metadata/categories.conf
+
+# no-deps
+echo 'no-deps' >> metadata/categories.conf
+
+mkdir -p 'packages/no-deps/target'
+cat <<END > packages/no-deps/target/target-1.exheres-0
+SUMMARY="target"
+PLATFORMS="test"
+SLOT="0"
+DEPENDENCIES=""
+END
+
+# build-deps
+echo 'build-deps' >> metadata/categories.conf
+
+mkdir -p 'packages/build-deps/target'
+cat <<END > packages/build-deps/target/target-1.exheres-0
+SUMMARY="target"
+PLATFORMS="test"
+SLOT="0"
+DEPENDENCIES="build: build-deps/a-dep build-deps/b-dep build-deps/z-dep"
+END
+
+mkdir -p 'packages/build-deps/a-dep'
+cat <<END > packages/build-deps/a-dep/a-dep-1.exheres-0
+SUMMARY="target"
+PLATFORMS="test"
+SLOT="0"
+DEPENDENCIES=""
+END
+
+mkdir -p 'packages/build-deps/b-dep'
+cat <<END > packages/build-deps/b-dep/b-dep-1.exheres-0
+SUMMARY="target"
+PLATFORMS="test"
+SLOT="0"
+DEPENDENCIES=""
+END
+
+mkdir -p 'packages/build-deps/z-dep'
+cat <<END > packages/build-deps/z-dep/z-dep-1.exheres-0
+SUMMARY="target"
+PLATFORMS="test"
+SLOT="0"
+DEPENDENCIES=""
+END
+
+cd ..
+
diff --git a/paludis/resolver/resolver_TEST_suggestions.cc b/paludis/resolver/resolver_TEST_suggestions.cc
index 5ebbe7c..92080e6 100644
--- a/paludis/resolver/resolver_TEST_suggestions.cc
+++ b/paludis/resolver/resolver_TEST_suggestions.cc
@@ -25,6 +25,7 @@
#include <paludis/resolver/constraint.hh>
#include <paludis/resolver/resolvent.hh>
#include <paludis/resolver/suggest_restart.hh>
+#include <paludis/resolver/resolver_lists.hh>
#include <paludis/environments/test/test_environment.hh>
#include <paludis/util/make_named_values.hh>
#include <paludis/util/options.hh>
@@ -75,14 +76,14 @@ namespace test_cases
{
TestMessageSuffix s("errors");
- check_resolution_list(resolutions->errors(), ResolutionListChecks()
+ check_resolution_list(resolutions->jobs(), resolutions->error_resolutions(), ResolutionListChecks()
.finished()
);
}
{
TestMessageSuffix s("ordered");
- check_resolution_list(resolutions->ordered(), ResolutionListChecks()
+ check_resolution_list(resolutions->jobs(), resolutions->ordered_job_ids(), ResolutionListChecks()
.qpn(QualifiedPackageName("suggestion/target"))
.finished()
);
@@ -90,7 +91,7 @@ namespace test_cases
{
TestMessageSuffix s("untaken");
- check_resolution_list(resolutions->untaken(), ResolutionListChecks()
+ check_resolution_list(resolutions->jobs(), resolutions->untaken_job_ids(), ResolutionListChecks()
.qpn(QualifiedPackageName("suggestion/dep"))
.finished()
);
@@ -108,14 +109,14 @@ namespace test_cases
{
TestMessageSuffix s("errors");
- check_resolution_list(resolutions->errors(), ResolutionListChecks()
+ check_resolution_list(resolutions->jobs(), resolutions->error_resolutions(), ResolutionListChecks()
.finished()
);
}
{
TestMessageSuffix s("ordered");
- check_resolution_list(resolutions->ordered(), ResolutionListChecks()
+ check_resolution_list(resolutions->jobs(), resolutions->ordered_job_ids(), ResolutionListChecks()
.qpn(QualifiedPackageName("unmeetable-suggestion/target"))
.finished()
);
@@ -123,7 +124,7 @@ namespace test_cases
{
TestMessageSuffix s("untaken");
- check_resolution_list(resolutions->untaken(), ResolutionListChecks()
+ check_resolution_list(resolutions->jobs(), resolutions->untaken_job_ids(), ResolutionListChecks()
.qpn(QualifiedPackageName("unmeetable-suggestion/unmeetable-dep"))
.finished()
);
@@ -141,14 +142,14 @@ namespace test_cases
{
TestMessageSuffix s("errors");
- check_resolution_list(resolutions->errors(), ResolutionListChecks()
+ check_resolution_list(resolutions->jobs(), resolutions->error_resolutions(), ResolutionListChecks()
.finished()
);
}
{
TestMessageSuffix s("ordered");
- check_resolution_list(resolutions->ordered(), ResolutionListChecks()
+ check_resolution_list(resolutions->jobs(), resolutions->ordered_job_ids(), ResolutionListChecks()
.qpn(QualifiedPackageName("suggestion-then-dependency/a-suggested-dep"))
.qpn(QualifiedPackageName("suggestion-then-dependency/hard-dep"))
.qpn(QualifiedPackageName("suggestion-then-dependency/target"))
@@ -158,7 +159,7 @@ namespace test_cases
{
TestMessageSuffix s("untaken");
- check_resolution_list(resolutions->untaken(), ResolutionListChecks()
+ check_resolution_list(resolutions->jobs(), resolutions->untaken_job_ids(), ResolutionListChecks()
.finished()
);
}
diff --git a/paludis/resolver/resolver_TEST_virtuals.cc b/paludis/resolver/resolver_TEST_virtuals.cc
index ad7c933..c2333fc 100644
--- a/paludis/resolver/resolver_TEST_virtuals.cc
+++ b/paludis/resolver/resolver_TEST_virtuals.cc
@@ -25,6 +25,7 @@
#include <paludis/resolver/constraint.hh>
#include <paludis/resolver/resolvent.hh>
#include <paludis/resolver/suggest_restart.hh>
+#include <paludis/resolver/resolver_lists.hh>
#include <paludis/environments/test/test_environment.hh>
#include <paludis/util/make_named_values.hh>
#include <paludis/util/options.hh>
@@ -75,14 +76,14 @@ namespace test_cases
{
TestMessageSuffix s("errors");
- check_resolution_list(resolutions->errors(), ResolutionListChecks()
+ check_resolution_list(resolutions->jobs(), resolutions->error_resolutions(), ResolutionListChecks()
.finished()
);
}
{
TestMessageSuffix s("ordered");
- check_resolution_list(resolutions->ordered(), ResolutionListChecks()
+ check_resolution_list(resolutions->jobs(), resolutions->ordered_job_ids(), ResolutionListChecks()
.qpn(QualifiedPackageName("cat/foo-a"))
.qpn(QualifiedPackageName("virtuals/target"))
.finished()
@@ -91,7 +92,7 @@ namespace test_cases
{
TestMessageSuffix s("untaken");
- check_resolution_list(resolutions->untaken(), ResolutionListChecks()
+ check_resolution_list(resolutions->jobs(), resolutions->untaken_job_ids(), ResolutionListChecks()
.finished()
);
}
@@ -108,14 +109,14 @@ namespace test_cases
{
TestMessageSuffix s("errors");
- check_resolution_list(resolutions->errors(), ResolutionListChecks()
+ check_resolution_list(resolutions->jobs(), resolutions->error_resolutions(), ResolutionListChecks()
.finished()
);
}
{
TestMessageSuffix s("ordered");
- check_resolution_list(resolutions->ordered(), ResolutionListChecks()
+ check_resolution_list(resolutions->jobs(), resolutions->ordered_job_ids(), ResolutionListChecks()
.qpn(QualifiedPackageName("cat/real-target"))
.finished()
);
@@ -123,7 +124,7 @@ namespace test_cases
{
TestMessageSuffix s("untaken");
- check_resolution_list(resolutions->untaken(), ResolutionListChecks()
+ check_resolution_list(resolutions->jobs(), resolutions->untaken_job_ids(), ResolutionListChecks()
.finished()
);
}
diff --git a/paludis/resolver/resolver_lists-fwd.hh b/paludis/resolver/resolver_lists-fwd.hh
new file mode 100644
index 0000000..6ae3457
--- /dev/null
+++ b/paludis/resolver/resolver_lists-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_RESOLVER_LISTS_FWD_HH
+#define PALUDIS_GUARD_PALUDIS_RESOLVER_RESOLVER_LISTS_FWD_HH 1
+
+namespace paludis
+{
+ namespace resolver
+ {
+ struct ResolverLists;
+ }
+}
+
+#endif
diff --git a/paludis/resolver/resolver_lists.cc b/paludis/resolver/resolver_lists.cc
new file mode 100644
index 0000000..40892ef
--- /dev/null
+++ b/paludis/resolver/resolver_lists.cc
@@ -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
+ */
+
+#include <paludis/resolver/resolver_lists.hh>
+#include <paludis/resolver/resolutions.hh>
+#include <paludis/resolver/jobs.hh>
+#include <paludis/resolver/job_id.hh>
+#include <paludis/util/sequence.hh>
+#include <paludis/util/make_named_values.hh>
+#include <paludis/util/wrapped_forward_iterator.hh>
+#include <paludis/serialise-impl.hh>
+
+using namespace paludis;
+using namespace paludis::resolver;
+
+void
+ResolverLists::serialise(Serialiser & s) const
+{
+ s.object("ResolverLists")
+ .member(SerialiserFlags<serialise::might_be_null>(), "all_resolutions", all_resolutions())
+ .member(SerialiserFlags<serialise::might_be_null>(), "error_resolutions", error_resolutions())
+ .member(SerialiserFlags<serialise::might_be_null>(), "jobs", jobs())
+ .member(SerialiserFlags<serialise::container, serialise::might_be_null>(), "ordered_job_ids", ordered_job_ids())
+ .member(SerialiserFlags<serialise::container, serialise::might_be_null>(), "unordered_job_ids", unordered_job_ids())
+ .member(SerialiserFlags<serialise::container, serialise::might_be_null>(), "untaken_job_ids", untaken_job_ids())
+ ;
+}
+
+const ResolverLists
+ResolverLists::deserialise(Deserialisation & d)
+{
+ Deserialisator v(d, "ResolverLists");
+
+ std::tr1::shared_ptr<JobIDSequence> ordered_job_ids(new JobIDSequence);
+ {
+ Deserialisator vv(*v.find_remove_member("ordered_job_ids"), "c");
+ for (int n(1), n_end(vv.member<int>("count") + 1) ; n != n_end ; ++n)
+ ordered_job_ids->push_back(vv.member<JobID>(stringify(n)));
+ }
+
+ std::tr1::shared_ptr<JobIDSequence> unordered_job_ids(new JobIDSequence);
+ {
+ Deserialisator vv(*v.find_remove_member("unordered_job_ids"), "c");
+ for (int n(1), n_end(vv.member<int>("count") + 1) ; n != n_end ; ++n)
+ unordered_job_ids->push_back(vv.member<JobID>(stringify(n)));
+ }
+
+ std::tr1::shared_ptr<JobIDSequence> untaken_job_ids(new JobIDSequence);
+ {
+ Deserialisator vv(*v.find_remove_member("untaken_job_ids"), "c");
+ for (int n(1), n_end(vv.member<int>("count") + 1) ; n != n_end ; ++n)
+ untaken_job_ids->push_back(vv.member<JobID>(stringify(n)));
+ }
+
+ return make_named_values<ResolverLists>(
+ value_for<n::all_resolutions>(v.member<std::tr1::shared_ptr<Resolutions> >("all_resolutions")),
+ value_for<n::error_resolutions>(v.member<std::tr1::shared_ptr<Resolutions> >("error_resolutions")),
+ value_for<n::jobs>(v.member<std::tr1::shared_ptr<Jobs> >("jobs")),
+ value_for<n::ordered_job_ids>(ordered_job_ids),
+ value_for<n::unordered_job_ids>(unordered_job_ids),
+ value_for<n::untaken_job_ids>(untaken_job_ids)
+ );
+}
+
diff --git a/paludis/resolver/resolver_lists.hh b/paludis/resolver/resolver_lists.hh
new file mode 100644
index 0000000..184d6f5
--- /dev/null
+++ b/paludis/resolver/resolver_lists.hh
@@ -0,0 +1,60 @@
+/* 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_RESOLVER_LISTS_HH
+#define PALUDIS_GUARD_PALUDIS_RESOLVER_RESOLVER_LISTS_HH 1
+
+#include <paludis/resolver/resolver_lists-fwd.hh>
+#include <paludis/resolver/resolutions-fwd.hh>
+#include <paludis/resolver/job_id-fwd.hh>
+#include <paludis/resolver/jobs-fwd.hh>
+#include <paludis/util/named_value.hh>
+#include <paludis/serialise.hh>
+#include <tr1/memory>
+
+namespace paludis
+{
+ namespace n
+ {
+ struct all_resolutions;
+ struct error_resolutions;
+ struct jobs;
+ struct ordered_job_ids;
+ struct unordered_job_ids;
+ struct untaken_job_ids;
+ }
+
+ namespace resolver
+ {
+ struct ResolverLists
+ {
+ NamedValue<n::all_resolutions, std::tr1::shared_ptr<Resolutions> > all_resolutions;
+ NamedValue<n::error_resolutions, std::tr1::shared_ptr<Resolutions> > error_resolutions;
+ NamedValue<n::jobs, std::tr1::shared_ptr<Jobs> > jobs;
+ NamedValue<n::ordered_job_ids, std::tr1::shared_ptr<JobIDSequence> > ordered_job_ids;
+ NamedValue<n::unordered_job_ids, std::tr1::shared_ptr<JobIDSequence> > unordered_job_ids;
+ NamedValue<n::untaken_job_ids, std::tr1::shared_ptr<JobIDSequence> > untaken_job_ids;
+
+ static const ResolverLists deserialise(Deserialisation &) PALUDIS_ATTRIBUTE((warn_unused_result));
+ void serialise(Serialiser &) const;
+ };
+ }
+}
+
+#endif
diff --git a/paludis/resolver/resolver_test.cc b/paludis/resolver/resolver_test.cc
index 443524c..f32176f 100644
--- a/paludis/resolver/resolver_test.cc
+++ b/paludis/resolver/resolver_test.cc
@@ -28,6 +28,9 @@
#include <paludis/resolver/decision.hh>
#include <paludis/resolver/decider.hh>
#include <paludis/resolver/orderer.hh>
+#include <paludis/resolver/job.hh>
+#include <paludis/resolver/jobs.hh>
+#include <paludis/resolver/job_id.hh>
#include <paludis/util/map.hh>
#include <paludis/util/wrapped_forward_iterator-impl.hh>
#include <paludis/util/make_shared_ptr.hh>
@@ -281,6 +284,25 @@ ResolverTestCase::ResolverTestCase(const std::string & t, const std::string & s,
#endif
}
+ResolverFunctions
+ResolverTestCase::get_resolver_functions(InitialConstraints & initial_constraints)
+{
+ return make_named_values<ResolverFunctions>(
+ value_for<n::care_about_dep_fn>(&care_about_dep_fn),
+ value_for<n::find_repository_for_fn>(std::tr1::bind(&find_repository_for_fn,
+ &env, std::tr1::placeholders::_1, std::tr1::placeholders::_2,
+ std::tr1::placeholders::_3)),
+ value_for<n::get_destination_types_for_fn>(&get_destination_types_for_fn),
+ value_for<n::get_initial_constraints_for_fn>(
+ std::tr1::bind(&initial_constraints_for_fn, std::tr1::ref(initial_constraints),
+ std::tr1::placeholders::_1)),
+ value_for<n::get_resolvents_for_fn>(&get_resolvents_for_fn),
+ value_for<n::get_use_existing_fn>(&get_use_existing_fn),
+ value_for<n::make_destination_filtered_generator_fn>(&make_destination_filtered_generator_fn),
+ value_for<n::take_dependency_fn>(&take_dependency_fn)
+ );
+}
+
const std::tr1::shared_ptr<const ResolverLists>
ResolverTestCase::get_resolutions(const PackageDepSpec & target)
{
@@ -290,20 +312,7 @@ ResolverTestCase::get_resolutions(const PackageDepSpec & target)
{
try
{
- Resolver resolver(&env, make_named_values<ResolverFunctions>(
- value_for<n::care_about_dep_fn>(&care_about_dep_fn),
- value_for<n::find_repository_for_fn>(std::tr1::bind(&find_repository_for_fn,
- &env, std::tr1::placeholders::_1, std::tr1::placeholders::_2,
- std::tr1::placeholders::_3)),
- value_for<n::get_destination_types_for_fn>(&get_destination_types_for_fn),
- value_for<n::get_initial_constraints_for_fn>(
- std::tr1::bind(&initial_constraints_for_fn, std::tr1::ref(initial_constraints),
- std::tr1::placeholders::_1)),
- value_for<n::get_resolvents_for_fn>(&get_resolvents_for_fn),
- value_for<n::get_use_existing_fn>(&get_use_existing_fn),
- value_for<n::make_destination_filtered_generator_fn>(&make_destination_filtered_generator_fn),
- value_for<n::take_dependency_fn>(&take_dependency_fn)
- ));
+ Resolver resolver(&env, get_resolver_functions(initial_constraints));
resolver.add_target(target);
resolver.resolve();
return resolver.lists();
@@ -374,9 +383,12 @@ namespace
bool
ResolverTestCase::ResolutionListChecks::check_qpn(const QualifiedPackageName & q, const std::tr1::shared_ptr<const Resolution> & r)
{
+ if ((! r) || (! r->decision()))
+ return false;
+
const std::tr1::shared_ptr<const PackageID> id(r->decision()->accept_returning<
std::tr1::shared_ptr<const PackageID> >(ChosenIDVisitor()));
- if ((! r) || (! r->decision()) || ! id)
+ if (! id)
return false;
return id->name() == q;
@@ -472,25 +484,99 @@ ResolverTestCase::ResolutionListChecks::finished()
return *this;
}
+namespace
+{
+ template <typename T_>
+ struct CheckLists;
+
+ template <>
+ struct CheckLists<std::tr1::shared_ptr<Resolutions> >
+ {
+ typedef Resolutions Type;
+
+ static const std::tr1::shared_ptr<const Resolution> get_resolution(
+ const std::tr1::shared_ptr<const Jobs> &,
+ const std::tr1::shared_ptr<const Resolution> & r)
+ {
+ return r;
+ }
+ };
+
+ struct InstallJobResolution
+ {
+ std::tr1::shared_ptr<const Resolution> visit(const NoChangeJob &) const
+ {
+ return make_null_shared_ptr();
+ }
+
+ std::tr1::shared_ptr<const Resolution> visit(const PretendJob &) const
+ {
+ return make_null_shared_ptr();
+ }
+
+ std::tr1::shared_ptr<const Resolution> visit(const SyncPointJob &) const
+ {
+ return make_null_shared_ptr();
+ }
+
+ std::tr1::shared_ptr<const Resolution> visit(const UntakenInstallJob & j) const
+ {
+ return j.resolution();
+ }
+
+ std::tr1::shared_ptr<const Resolution> visit(const SimpleInstallJob & j) const
+ {
+ return j.resolution();
+ }
+ };
+
+ template <>
+ struct CheckLists<std::tr1::shared_ptr<JobIDSequence> >
+ {
+ typedef JobIDSequence Type;
+
+ static const std::tr1::shared_ptr<const Resolution> get_resolution(
+ const std::tr1::shared_ptr<const Jobs> & jobs,
+ const JobID & j)
+ {
+ return jobs->fetch(j)->accept_returning<std::tr1::shared_ptr<const Resolution> >(InstallJobResolution());
+ }
+ };
+}
+
+template <typename List_>
void
ResolverTestCase::check_resolution_list(
- const std::tr1::shared_ptr<const Resolutions> & list, const ResolutionListChecks & checks)
+ const std::tr1::shared_ptr<const Jobs> & jobs,
+ const List_ & list, const ResolutionListChecks & checks)
{
- Resolutions::ConstIterator r(list->begin()), r_end(list->end());
- for (ResolutionListChecks::List::const_iterator c(checks.checks.begin()), c_end(checks.checks.end()) ;
- c != c_end ; ++c)
+ typename CheckLists<List_>::Type::ConstIterator r(list->begin()), r_end(list->end());
+ ResolutionListChecks::List::const_iterator c(checks.checks.begin()), c_end(checks.checks.end());
+ while (true)
{
- if (r == r_end)
- TEST_CHECK_MESSAGE(c->first(make_null_shared_ptr()), c->second(make_null_shared_ptr()));
- else
- TEST_CHECK_MESSAGE(c->first(*r), c->second(*r));
- ++r;
+ std::tr1::shared_ptr<const Resolution> rn;
+ while ((! rn) && (r != r_end))
+ rn = CheckLists<List_>::get_resolution(jobs, *r++);
+
+ if (c == c_end)
+ break;
+
+ TEST_CHECK_MESSAGE(c->first(rn), c->second(rn));
+ ++c;
}
+
+ TEST_CHECK(r == r_end);
+ TEST_CHECK(c == c_end);
}
-void
+const std::tr1::shared_ptr<FakePackageID>
ResolverTestCase::install(const std::string & c, const std::string & p, const std::string & v)
{
- fake_inst_repo->add_version(c, p, v);
+ return fake_inst_repo->add_version(c, p, v);
}
+template void ResolverTestCase::check_resolution_list(const std::tr1::shared_ptr<const Jobs> &,
+ const std::tr1::shared_ptr<Resolutions> &, const ResolutionListChecks &);
+template void ResolverTestCase::check_resolution_list(const std::tr1::shared_ptr<const Jobs> &,
+ const std::tr1::shared_ptr<JobIDSequence> &, const ResolutionListChecks &);
+
diff --git a/paludis/resolver/resolver_test.hh b/paludis/resolver/resolver_test.hh
index 2ba5f87..9cff289 100644
--- a/paludis/resolver/resolver_test.hh
+++ b/paludis/resolver/resolver_test.hh
@@ -30,7 +30,10 @@
#include <paludis/resolver/decision-fwd.hh>
#include <paludis/resolver/destination_types-fwd.hh>
#include <paludis/resolver/resolver-fwd.hh>
+#include <paludis/resolver/jobs-fwd.hh>
+#include <paludis/resolver/resolver_functions-fwd.hh>
#include <paludis/repositories/fake/fake_installed_repository.hh>
+#include <paludis/repositories/fake/fake_package_id.hh>
#include <paludis/environments/test/test_environment.hh>
#include <paludis/util/map-fwd.hh>
#include <paludis/dep_spec-fwd.hh>
@@ -100,6 +103,8 @@ namespace paludis
const std::tr1::shared_ptr<const ResolverLists> get_resolutions(const std::string & target);
+ virtual ResolverFunctions get_resolver_functions(InitialConstraints &);
+
struct ResolutionListChecks
{
typedef std::tr1::function<bool (const std::tr1::shared_ptr<const Resolution> &) > CheckFunction;
@@ -130,9 +135,12 @@ namespace paludis
ResolutionListChecks & finished();
};
- void check_resolution_list(const std::tr1::shared_ptr<const Resolutions> & list, const ResolutionListChecks & checks);
+ template <typename List_>
+ void check_resolution_list(const std::tr1::shared_ptr<const Jobs> &,
+ const List_ & list, const ResolutionListChecks & checks);
- void install(const std::string & c, const std::string & p, const std::string & v);
+ const std::tr1::shared_ptr<FakePackageID> install(
+ const std::string & c, const std::string & p, const std::string & v);
};
}
}
diff --git a/paludis/resolver/sync_point-fwd.hh b/paludis/resolver/sync_point-fwd.hh
new file mode 100644
index 0000000..54187dd
--- /dev/null
+++ b/paludis/resolver/sync_point-fwd.hh
@@ -0,0 +1,34 @@
+/* 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_SYNC_POINT_FWD_HH
+#define PALUDIS_GUARD_PALUDIS_RESOLVER_SYNC_POINT_FWD_HH 1
+
+#include <paludis/util/attributes.hh>
+#include <iosfwd>
+
+namespace paludis
+{
+ namespace resolver
+ {
+#include <paludis/resolver/sync_point-se.hh>
+ }
+}
+
+#endif
diff --git a/paludis/resolver/sync_point.cc b/paludis/resolver/sync_point.cc
new file mode 100644
index 0000000..2e342d8
--- /dev/null
+++ b/paludis/resolver/sync_point.cc
@@ -0,0 +1,29 @@
+/* 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/sync_point.hh>
+#include <paludis/util/exception.hh>
+#include <paludis/util/stringify.hh>
+#include <ostream>
+
+using namespace paludis;
+using namespace paludis::resolver;
+
+#include <paludis/resolver/sync_point-se.cc>
+
diff --git a/paludis/resolver/sync_point.hh b/paludis/resolver/sync_point.hh
new file mode 100644
index 0000000..ddccb95
--- /dev/null
+++ b/paludis/resolver/sync_point.hh
@@ -0,0 +1,30 @@
+/* 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_SYNC_POINT_HH
+#define PALUDIS_GUARD_PALUDIS_RESOLVER_SYNC_POINT_HH 1
+
+#include <paludis/resolver/sync_point-fwd.hh>
+
+namespace paludis
+{
+
+}
+
+#endif
diff --git a/paludis/resolver/sync_point.se b/paludis/resolver/sync_point.se
new file mode 100644
index 0000000..baef962
--- /dev/null
+++ b/paludis/resolver/sync_point.se
@@ -0,0 +1,15 @@
+#!/usr/bin/env bash
+# vim: set sw=4 sts=4 et ft=sh :
+
+make_enum_SyncPoint()
+{
+ prefix sp
+ namespace paludis::resolver
+
+ key sp_done_pretends "Done pretends"
+ key sp_done_installs "Done installs"
+
+ want_destringify
+}
+
+
diff --git a/src/clients/cave/cmd_display_resolution.cc b/src/clients/cave/cmd_display_resolution.cc
index 0595ed4..34273e8 100644
--- a/src/clients/cave/cmd_display_resolution.cc
+++ b/src/clients/cave/cmd_display_resolution.cc
@@ -35,6 +35,7 @@
#include <paludis/util/options.hh>
#include <paludis/util/set.hh>
#include <paludis/util/make_named_values.hh>
+#include <paludis/util/make_shared_copy.hh>
#include <paludis/resolver/resolutions.hh>
#include <paludis/resolver/reason.hh>
#include <paludis/resolver/sanitised_dependencies.hh>
@@ -45,6 +46,10 @@
#include <paludis/resolver/resolvent.hh>
#include <paludis/resolver/destination.hh>
#include <paludis/resolver/unsuitable_candidates.hh>
+#include <paludis/resolver/resolver_lists.hh>
+#include <paludis/resolver/job.hh>
+#include <paludis/resolver/jobs.hh>
+#include <paludis/resolver/job_id.hh>
#include <paludis/package_id.hh>
#include <paludis/version_spec.hh>
#include <paludis/metadata_key.hh>
@@ -360,19 +365,58 @@ namespace
}
};
+ struct GetResolutionIfInstall
+ {
+ const std::tr1::shared_ptr<const Resolution> visit(
+ const SimpleInstallJob & j) const
+ {
+ return j.resolution();
+ }
+
+ const std::tr1::shared_ptr<const Resolution> visit(
+ const UntakenInstallJob & j) const
+ {
+ return j.resolution();
+ }
+
+ const std::tr1::shared_ptr<const Resolution> visit(
+ const NoChangeJob &) const
+ {
+ return make_null_shared_ptr();
+ }
+
+ const std::tr1::shared_ptr<const Resolution> visit(
+ const PretendJob &) const
+ {
+ return make_null_shared_ptr();
+ }
+
+ const std::tr1::shared_ptr<const Resolution> visit(
+ const SyncPointJob &) const
+ {
+ return make_null_shared_ptr();
+ }
+ };
+
void display_resolution_list(
const std::tr1::shared_ptr<Environment> & env,
- const std::tr1::shared_ptr<const Resolutions> & list,
+ const std::tr1::shared_ptr<const Jobs> & jobs,
+ const std::tr1::shared_ptr<const JobIDSequence> & list,
const DisplayResolutionCommandLine & cmdline)
{
- for (Resolutions::ConstIterator c(list->begin()), c_end(list->end()) ;
+ for (JobIDSequence::ConstIterator c(list->begin()), c_end(list->end()) ;
c != c_end ; ++c)
{
- const std::tr1::shared_ptr<const PackageID> id((*c)->decision()->accept_returning<
+ const std::tr1::shared_ptr<const Resolution> resolution(jobs->fetch(*c)->accept_returning<
+ std::tr1::shared_ptr<const Resolution> >(GetResolutionIfInstall()));
+ if (! resolution)
+ continue;
+
+ const std::tr1::shared_ptr<const PackageID> id(resolution->decision()->accept_returning<
std::tr1::shared_ptr<const PackageID> >(ChosenIDVisitor()));
if (! id)
{
- display_one_error(env, cmdline, *c, false);
+ display_one_error(env, cmdline, resolution, false);
continue;
}
@@ -380,7 +424,7 @@ namespace
other_slots(false);
std::tr1::shared_ptr<const PackageID> old_id;
- const std::tr1::shared_ptr<const Destination> destination((*c)->decision()->accept_returning<
+ const std::tr1::shared_ptr<const Destination> destination(resolution->decision()->accept_returning<
std::tr1::shared_ptr<const Destination> >(DestinationVisitor()));
if (! destination)
throw InternalError(PALUDIS_HERE, "huh? ! destination");
@@ -413,7 +457,7 @@ namespace
is_reinstall = is_reinstall && (! is_downgrade);
std::string destination_string(c::red() + "/" + c::normal());
- switch ((*c)->resolvent().destination_type())
+ switch (resolution->resolvent().destination_type())
{
case dt_install_to_slash:
destination_string = "/";
@@ -427,7 +471,7 @@ namespace
break;
}
- if (! (*c)->decision()->taken())
+ if (! resolution->decision()->taken())
{
cout << "-" << destination_string << " " << c::blue() << id->canonical_form(idcf_no_version);
}
@@ -607,7 +651,7 @@ namespace
cout << " \"" << id->short_description_key()->value() << "\"" << endl;
}
- display_reasons(*c, false);
+ display_reasons(resolution, false);
}
cout << endl;
@@ -620,15 +664,15 @@ namespace
{
Context context("When displaying chosen resolution:");
- if (lists.ordered()->empty())
+ if (lists.ordered_job_ids()->empty())
{
- if (lists.errors()->empty())
+ if (lists.error_resolutions()->empty())
cout << "There are no actions to carry out" << endl << endl;
return;
}
cout << "These are the actions I will take, in order:" << endl << endl;
- display_resolution_list(env, lists.ordered(), cmdline);
+ display_resolution_list(env, lists.jobs(), lists.ordered_job_ids(), cmdline);
}
void display_untaken(
@@ -638,11 +682,11 @@ namespace
{
Context context("When displaying untaken resolutions:");
- if (lists.untaken()->empty())
+ if (lists.untaken_job_ids()->empty())
return;
cout << "I didn't take the following suggestions:" << endl << endl;
- display_resolution_list(env, lists.untaken(), cmdline);
+ display_resolution_list(env, lists.jobs(), lists.untaken_job_ids(), cmdline);
}
void display_errors(
@@ -652,12 +696,13 @@ namespace
{
Context context("When displaying errors for chosen resolution:");
- if (lists.errors()->empty())
+ if (lists.error_resolutions()->empty())
return;
cout << "I encountered the following errors:" << endl << endl;
- for (Resolutions::ConstIterator c(lists.errors()->begin()), c_end(lists.errors()->end()) ;
+ for (Resolutions::ConstIterator c(lists.error_resolutions()->begin()),
+ c_end(lists.error_resolutions()->end()) ;
c != c_end ; ++c)
display_one_error(env, cmdline, *c, true);
@@ -682,7 +727,7 @@ namespace
{
bool any(false);
PackageDepSpec spec(parse_user_package_dep_spec(*i, env.get(), UserPackageDepSpecOptions() + updso_allow_wildcards));
- for (Resolutions::ConstIterator r(lists.all()->begin()), r_end(lists.all()->end()) ;
+ for (Resolutions::ConstIterator r(lists.all_resolutions()->begin()), r_end(lists.all_resolutions()->end()) ;
r != r_end ; ++r)
{
const std::tr1::shared_ptr<const PackageID> id((*r)->decision()->accept_returning<
diff --git a/src/clients/cave/cmd_execute_resolution.cc b/src/clients/cave/cmd_execute_resolution.cc
index 23838e9..b2206ff 100644
--- a/src/clients/cave/cmd_execute_resolution.cc
+++ b/src/clients/cave/cmd_execute_resolution.cc
@@ -43,6 +43,10 @@
#include <paludis/resolver/resolver.hh>
#include <paludis/resolver/resolvent.hh>
#include <paludis/resolver/destination.hh>
+#include <paludis/resolver/resolver_lists.hh>
+#include <paludis/resolver/jobs.hh>
+#include <paludis/resolver/job.hh>
+#include <paludis/resolver/job_id.hh>
#include <paludis/package_id.hh>
#include <paludis/version_spec.hh>
#include <paludis/metadata_key.hh>
@@ -189,7 +193,6 @@ namespace
const ExecuteResolutionCommandLine & cmdline,
const std::tr1::shared_ptr<const Resolution> & resolution,
const ChangesToMakeDecision & decision,
- const std::tr1::shared_ptr<const Destination> & destination,
const int x, const int y)
{
std::string destination_string, action_string;
@@ -223,9 +226,9 @@ namespace
command.append(" install --hooks ");
command.append(stringify(id->uniquely_identifying_spec()));
- command.append(" --destination " + stringify(destination->repository()));
- for (PackageIDSequence::ConstIterator i(destination->replacing()->begin()),
- i_end(destination->replacing()->end()) ;
+ command.append(" --destination " + stringify(decision.destination()->repository()));
+ for (PackageIDSequence::ConstIterator i(decision.destination()->replacing()->begin()),
+ i_end(decision.destination()->replacing()->end()) ;
i != i_end ; ++i)
command.append(" --replacing " + stringify((*i)->uniquely_identifying_spec()));
@@ -265,79 +268,191 @@ namespace
return retcode;
}
- int execute_resolution(
- const std::tr1::shared_ptr<Environment> & env,
- const ResolverLists & lists,
- const ExecuteResolutionCommandLine & cmdline)
+ struct JobCounts
{
- Context context("When executing chosen resolution:");
+ int x_pretends, y_pretends, x_fetches, y_fetches, x_installs, y_installs;
+
+ JobCounts() :
+ x_pretends(0),
+ y_pretends(0),
+ x_fetches(0),
+ y_fetches(0),
+ x_installs(0),
+ y_installs(0)
+ {
+ }
- int retcode(0), x(0), y(std::distance(lists.ordered()->begin(), lists.ordered()->end()));
+ void visit(const PretendJob &)
+ {
+ ++y_pretends;
+ }
- if (0 != env->perform_hook(Hook("install_task_execute_pre")
- ("TARGETS", join(cmdline.begin_parameters(), cmdline.end_parameters(), " "))
- ).max_exit_status())
- throw ActionAbortedError("Aborted by hook");
+ void visit(const SimpleInstallJob &)
+ {
+ ++y_installs;
+ ++y_fetches;
+ }
- try
+ void visit(const NoChangeJob &)
{
- if (0 != env->perform_hook(Hook("pretend_all_pre")
- ("TARGETS", join(cmdline.begin_parameters(), cmdline.end_parameters(), " "))
- ).max_exit_status())
- throw ActionAbortedError("Aborted by hook");
+ }
- std::cout << "Executing pretend actions: " << std::flush;
+ void visit(const SyncPointJob &)
+ {
+ }
- for (Resolutions::ConstIterator c(lists.ordered()->begin()), c_end(lists.ordered()->end()) ;
- c != c_end ; ++c)
+ void visit(const UntakenInstallJob &)
+ {
+ }
+ };
+
+ struct PerformJobs
+ {
+ const std::tr1::shared_ptr<Environment> env;
+ const ExecuteResolutionCommandLine & cmdline;
+ JobCounts & counts;
+
+ bool done_any_pretends;
+ bool done_any_installs;
+ int retcode;
+
+ PerformJobs(
+ const std::tr1::shared_ptr<Environment> & e,
+ const ExecuteResolutionCommandLine & c,
+ JobCounts & k) :
+ env(e),
+ cmdline(c),
+ counts(k),
+ done_any_pretends(false),
+ done_any_installs(false),
+ retcode(0)
+ {
+ }
+
+ bool visit(const PretendJob & job)
+ {
+ if (! done_any_pretends)
{
- const ChangesToMakeDecision * const decision(simple_visitor_cast<const ChangesToMakeDecision>(
- *(*c)->decision()));
- if (! decision)
- throw InternalError(PALUDIS_HERE, "huh? not ChangesToMakeDecision");
- retcode |= do_pretend(env, cmdline, *decision, ++x, y);
+ done_any_pretends = true;
+
+ if (0 != env->perform_hook(Hook("pretend_all_pre")
+ ("TARGETS", join(cmdline.begin_parameters(), cmdline.end_parameters(), " "))
+ ).max_exit_status())
+ throw ActionAbortedError("Aborted by hook");
+
+ std::cout << "Executing pretend actions: " << std::flush;
}
- std::cout << std::endl;
+ retcode |= do_pretend(env, cmdline, *job.decision(), ++counts.x_pretends, counts.y_pretends);
- if (0 != env->perform_hook(Hook("pretend_all_post")
- ("TARGETS", join(cmdline.begin_parameters(), cmdline.end_parameters(), " "))
- ).max_exit_status())
- throw ActionAbortedError("Aborted by hook");
+ /* a pretend failing doesn't abort us yet */
+ return true;
+ }
- if (0 != retcode || cmdline.a_pretend.specified())
- return retcode;
+ bool visit(const SimpleInstallJob & job)
+ {
+ if (0 != retcode)
+ return false;
- x = 0;
+ if (! done_any_installs)
+ {
+ done_any_installs = true;
- if (0 != env->perform_hook(Hook("install_all_pre")
- ("TARGETS", join(cmdline.begin_parameters(), cmdline.end_parameters(), " "))
- ).max_exit_status())
- throw ActionAbortedError("Aborted by hook");
+ if (0 != env->perform_hook(Hook("install_all_pre")
+ ("TARGETS", join(cmdline.begin_parameters(), cmdline.end_parameters(), " "))
+ ).max_exit_status())
+ throw ActionAbortedError("Aborted by hook");
+ }
- for (Resolutions::ConstIterator c(lists.ordered()->begin()), c_end(lists.ordered()->end()) ;
- c != c_end ; ++c)
+ retcode |= do_fetch(env, cmdline, *job.decision(), ++counts.x_fetches, counts.y_fetches);
+ if (0 != retcode)
+ return false;
+
+ retcode |= do_install(env, cmdline, job.resolution(),
+ *job.decision(), ++counts.x_installs, counts.y_installs);
+ if (0 != retcode)
+ return false;
+
+ return true;
+ }
+
+ bool visit(const SyncPointJob & job)
+ {
+ switch (job.sync_point())
{
- ++x;
+ case sp_done_installs:
+ {
+ if (0 != env->perform_hook(Hook("install_all_post")
+ ("TARGETS", join(cmdline.begin_parameters(), cmdline.end_parameters(), " "))
+ ).max_exit_status())
+ throw ActionAbortedError("Aborted by hook");
+ }
+ break;
+
+ case sp_done_pretends:
+ {
+ std::cout << std::endl;
- const ChangesToMakeDecision * const decision(simple_visitor_cast<const ChangesToMakeDecision>(
- *(*c)->decision()));
- if (! decision)
- throw InternalError(PALUDIS_HERE, "huh? not ChangesToMakeDecision");
+ if (0 != env->perform_hook(Hook("pretend_all_post")
+ ("TARGETS", join(cmdline.begin_parameters(), cmdline.end_parameters(), " "))
+ ).max_exit_status())
+ throw ActionAbortedError("Aborted by hook");
- retcode = do_fetch(env, cmdline, *decision, x, y);
- if (0 != retcode)
- return retcode;
+ if ((0 != retcode) || (cmdline.a_pretend.specified()))
+ return false;
+ }
+ break;
- retcode = do_install(env, cmdline, *c, *decision, decision->destination(), x, y);
- if (0 != retcode)
- return retcode;
+ case last_sp:
+ break;
}
- if (0 != env->perform_hook(Hook("install_all_post")
- ("TARGETS", join(cmdline.begin_parameters(), cmdline.end_parameters(), " "))
+ return true;
+ }
+
+ bool visit(const UntakenInstallJob &)
+ {
+ return true;
+ }
+
+ bool visit(const NoChangeJob &)
+ {
+ return true;
+ }
+ };
+
+ int execute_resolution(
+ const std::tr1::shared_ptr<Environment> & env,
+ const ResolverLists & lists,
+ const ExecuteResolutionCommandLine & cmdline)
+ {
+ Context context("When executing chosen resolution:");
+
+ int retcode(0);
+
+ if (0 != env->perform_hook(Hook("install_task_execute_pre")
+ ("TARGETS", join(cmdline.begin_parameters(), cmdline.end_parameters(), " "))
).max_exit_status())
- throw ActionAbortedError("Aborted by hook");
+ throw ActionAbortedError("Aborted by hook");
+
+ try
+ {
+ JobCounts counts;
+ for (JobIDSequence::ConstIterator c(lists.ordered_job_ids()->begin()),
+ c_end(lists.ordered_job_ids()->end()) ;
+ c != c_end ; ++c)
+ lists.jobs()->fetch(*c)->accept(counts);
+
+ PerformJobs perform_jobs(env, cmdline, counts);
+ for (JobIDSequence::ConstIterator c(lists.ordered_job_ids()->begin()),
+ c_end(lists.ordered_job_ids()->end()) ;
+ c != c_end ; ++c)
+ if (! lists.jobs()->fetch(*c)->accept_returning<bool>(perform_jobs))
+ break;
+
+ retcode |= perform_jobs.retcode;
+ if ((0 != retcode) || (cmdline.a_pretend.specified()))
+ return retcode;
if (! cmdline.execution_options.a_preserve_world.specified())
{
diff --git a/src/clients/cave/cmd_resolve.cc b/src/clients/cave/cmd_resolve.cc
index e01928e..550deeb 100644
--- a/src/clients/cave/cmd_resolve.cc
+++ b/src/clients/cave/cmd_resolve.cc
@@ -43,6 +43,7 @@
#include <paludis/resolver/constraint.hh>
#include <paludis/resolver/sanitised_dependencies.hh>
#include <paludis/resolver/resolutions.hh>
+#include <paludis/resolver/resolver_lists.hh>
#include <paludis/user_dep_spec.hh>
#include <paludis/notifier_callback.hh>
#include <paludis/generator.hh>
@@ -1164,7 +1165,7 @@ ResolveCommand::run(
retcode |= display_resolution(env, *resolver->lists(), cmdline);
- if (! resolver->lists()->errors()->empty())
+ if (! resolver->lists()->error_resolutions()->empty())
retcode |= 1;
if (0 == retcode)
diff --git a/src/clients/cave/cmd_resolve_dump.cc b/src/clients/cave/cmd_resolve_dump.cc
index 2032220..6d0e541 100644
--- a/src/clients/cave/cmd_resolve_dump.cc
+++ b/src/clients/cave/cmd_resolve_dump.cc
@@ -28,6 +28,7 @@
#include <paludis/resolver/arrow.hh>
#include <paludis/resolver/destination.hh>
#include <paludis/resolver/resolutions.hh>
+#include <paludis/resolver/resolver_lists.hh>
#include <paludis/util/enum_iterator.hh>
#include <paludis/util/indirect_iterator-impl.hh>
#include <paludis/util/join.hh>
@@ -152,7 +153,7 @@ namespace
{
std::stringstream s;
s << r.sanitised_dependency();
- str = "Dependency(" + s.str() + ")";
+ str = "Dependency(" + s.str() + " from " + stringify(r.from_resolvent()) + ")";
}
};
@@ -181,9 +182,7 @@ namespace
std::ostream &
operator<< (std::ostream & s, const Arrow & a)
{
- s << "Arrow(-> " << a.comes_after();
- if (0 != a.ignorable_pass())
- s << ", ignorable pass " << a.ignorable_pass();
+ s << "Arrow(-> " << a.comes_after().string_id();
s << ")";
return s;
}
@@ -214,11 +213,7 @@ namespace
ss << *r.decision();
else
ss << "none";
- ss
- << "; arrows: " << join(indirect_iterator(r.arrows()->begin()),
- indirect_iterator(r.arrows()->end()), ", ", stringify_arrow)
- << "; already_ordered: " << stringify(r.already_ordered()) << ")"
- << ")";
+ ss << ")";
s << ss.str();
return s;
}
@@ -230,8 +225,8 @@ namespace
{
std::cout << "Dumping resolutions by QPN:S:" << std::endl << std::endl;
- for (Resolutions::ConstIterator c(resolver->lists()->all()->begin()),
- c_end(resolver->lists()->all()->end()) ;
+ for (Resolutions::ConstIterator c(resolver->lists()->all_resolutions()->begin()),
+ c_end(resolver->lists()->all_resolutions()->end()) ;
c != c_end ; ++c)
{
std::cout << (*c)->resolvent() << std::endl;