aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2010-06-17 13:21:34 +0100
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2010-06-17 13:21:34 +0100
commit228726b06ac580bb3330bfb961586713b99d71d8 (patch)
treee74cf7fe93d47f7aac1e20709e7451e665bcdb69
parent79c8a8bc2ba392b8dd06c6f81cb045d60c31fffe (diff)
downloadpaludis-228726b06ac580bb3330bfb961586713b99d71d8.tar.gz
paludis-228726b06ac580bb3330bfb961586713b99d71d8.tar.xz
continue-on-failure
-rw-r--r--.gitignore1
-rw-r--r--paludis/resolver/Makefile.am28
-rw-r--r--paludis/resolver/job-fwd.hh2
-rw-r--r--paludis/resolver/job.cc71
-rw-r--r--paludis/resolver/job.hh12
-rw-r--r--paludis/resolver/job_list-fwd.hh2
-rw-r--r--paludis/resolver/job_list.cc9
-rw-r--r--paludis/resolver/job_list.hh3
-rw-r--r--paludis/resolver/job_requirements-fwd.hh41
-rw-r--r--paludis/resolver/job_requirements.cc56
-rw-r--r--paludis/resolver/job_requirements.hh57
-rw-r--r--paludis/resolver/job_requirements.se16
-rw-r--r--paludis/resolver/orderer.cc106
-rw-r--r--paludis/resolver/orderer.hh2
-rw-r--r--paludis/resolver/resolver_TEST_continue_on_failure.cc159
-rwxr-xr-xpaludis/resolver/resolver_TEST_continue_on_failure_cleanup.sh9
-rwxr-xr-xpaludis/resolver/resolver_TEST_continue_on_failure_setup.sh56
-rw-r--r--src/clients/cave/cmd_execute_resolution.cc66
18 files changed, 669 insertions, 27 deletions
diff --git a/.gitignore b/.gitignore
index 8d63900..db321be 100644
--- a/.gitignore
+++ b/.gitignore
@@ -326,6 +326,7 @@ paludis-*.*.*.tar.bz2
/paludis/repository_name_cache_TEST
/paludis/resolver/resolver_TEST_any
/paludis/resolver/resolver_TEST_blockers
+/paludis/resolver/resolver_TEST_continue_on_failure
/paludis/resolver/resolver_TEST_cycles
/paludis/resolver/resolver_TEST_errors
/paludis/resolver/resolver_TEST_serialisation
diff --git a/paludis/resolver/Makefile.am b/paludis/resolver/Makefile.am
index 59e4fe2..7ef1706 100644
--- a/paludis/resolver/Makefile.am
+++ b/paludis/resolver/Makefile.am
@@ -3,6 +3,7 @@ include $(top_srcdir)/misc/common-makefile.am
DISTCLEANFILES = \
any_child_score-se.hh any_child_score-se.cc \
change_type-se.hh change_type-se.cc \
+ job_requirements-se.hh job_requirements-se.cc \
destination_types-se.hh destination_types-se.cc \
resolver_functions-se.hh resolver_functions-se.cc \
use_existing-se.hh use_existing-se.cc
@@ -11,6 +12,7 @@ EXTRA_DIST = \
any_child_score-se.hh any_child_score-se.cc any_child_score.se \
change_type-se.hh change_type-se.cc change_type.se \
destination_types-se.hh destination_types-se.cc destination_types.se \
+ job_requirements-se.hh job_requirements-se.cc job_requirements.se \
resolver_functions-se.hh resolver_functions-se.cc resolver_functions.se \
use_existing-se.hh use_existing-se.cc use_existing.se \
$(check_SCRIPTS)
@@ -18,6 +20,7 @@ BUILT_SOURCES = \
any_child_score-se.hh any_child_score-se.cc \
change_type-se.hh change_type-se.cc \
destination_types-se.hh destination_types-se.cc \
+ job_requirements-se.hh job_requirements-se.cc \
resolver_functions-se.hh resolver_functions-se.cc \
use_existing-se.hh use_existing-se.cc
@@ -33,6 +36,7 @@ noinst_HEADERS = \
job.hh job-fwd.hh \
job_list.hh job_list-fwd.hh \
job_lists.hh job_lists-fwd.hh \
+ job_requirements.hh job_requirements-fwd.hh \
job_state.hh job_state-fwd.hh \
nag.hh nag-fwd.hh \
orderer.hh orderer-fwd.hh \
@@ -66,6 +70,7 @@ libpaludisresolver_a_SOURCES = \
job.cc \
job_list.cc \
job_lists.cc \
+ job_requirements.cc \
job_state.cc \
nag.cc \
orderer.cc \
@@ -102,6 +107,7 @@ TESTS = \
resolver_TEST_suggestions \
resolver_TEST_any \
resolver_TEST_errors \
+ resolver_TEST_continue_on_failure \
$(virtuals_tests)
endif
@@ -115,7 +121,8 @@ check_SCRIPTS = \
resolver_TEST_simple_setup.sh resolver_TEST_simple_cleanup.sh \
resolver_TEST_virtuals_setup.sh resolver_TEST_virtuals_cleanup.sh \
resolver_TEST_any_setup.sh resolver_TEST_any_cleanup.sh \
- resolver_TEST_errors_setup.sh resolver_TEST_errors_cleanup.sh
+ resolver_TEST_errors_setup.sh resolver_TEST_errors_cleanup.sh \
+ resolver_TEST_continue_on_failure_setup.sh resolver_TEST_continue_on_failure_cleanup.sh
check_LIBRARIES = libpaludisresolvertest.a
libpaludisresolvertest_a_SOURCES = \
@@ -226,6 +233,19 @@ resolver_TEST_errors_LDADD = \
resolver_TEST_errors_CXXFLAGS = $(AM_CXXFLAGS) @PALUDIS_CXXFLAGS_NO_DEBUGGING@
+resolver_TEST_continue_on_failure_SOURCES = resolver_TEST_continue_on_failure.cc
+
+resolver_TEST_continue_on_failure_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_continue_on_failure_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
@@ -256,3 +276,9 @@ resolver_functions-se.hh : resolver_functions.se $(top_srcdir)/misc/make_se.bash
resolver_functions-se.cc : resolver_functions.se $(top_srcdir)/misc/make_se.bash
if ! $(top_srcdir)/misc/make_se.bash --source $(srcdir)/resolver_functions.se > $@ ; then rm -f $@ ; exit 1 ; fi
+job_requirements-se.hh : job_requirements.se $(top_srcdir)/misc/make_se.bash
+ if ! $(top_srcdir)/misc/make_se.bash --header $(srcdir)/job_requirements.se > $@ ; then rm -f $@ ; exit 1 ; fi
+
+job_requirements-se.cc : job_requirements.se $(top_srcdir)/misc/make_se.bash
+ if ! $(top_srcdir)/misc/make_se.bash --source $(srcdir)/job_requirements.se > $@ ; then rm -f $@ ; exit 1 ; fi
+
diff --git a/paludis/resolver/job-fwd.hh b/paludis/resolver/job-fwd.hh
index 0d74f6a..c342b11 100644
--- a/paludis/resolver/job-fwd.hh
+++ b/paludis/resolver/job-fwd.hh
@@ -30,6 +30,8 @@ namespace paludis
class FetchJob;
class InstallJob;
class UninstallJob;
+
+ class JobID;
}
}
diff --git a/paludis/resolver/job.cc b/paludis/resolver/job.cc
index 480542c..75bf8c7 100644
--- a/paludis/resolver/job.cc
+++ b/paludis/resolver/job.cc
@@ -18,6 +18,7 @@
*/
#include <paludis/resolver/job.hh>
+#include <paludis/resolver/job_requirements.hh>
#include <paludis/util/private_implementation_pattern-impl.hh>
#include <paludis/util/make_shared_ptr.hh>
#include <paludis/util/sequence.hh>
@@ -96,18 +97,24 @@ namespace paludis
template <>
struct Implementation<FetchJob>
{
+ const std::tr1::shared_ptr<const JobRequirements> requirements;
const std::tr1::shared_ptr<const PackageID> origin_id;
std::tr1::shared_ptr<JobState> state;
- Implementation(const std::tr1::shared_ptr<const PackageID> & o) :
+ Implementation(
+ const std::tr1::shared_ptr<const JobRequirements> & r,
+ const std::tr1::shared_ptr<const PackageID> & o) :
+ requirements(r),
origin_id(o)
{
}
};
}
-FetchJob::FetchJob(const std::tr1::shared_ptr<const PackageID> & o) :
- PrivateImplementationPattern<FetchJob>(new Implementation<FetchJob>(o))
+FetchJob::FetchJob(
+ const std::tr1::shared_ptr<const JobRequirements> & r,
+ const std::tr1::shared_ptr<const PackageID> & o) :
+ PrivateImplementationPattern<FetchJob>(new Implementation<FetchJob>(r, o))
{
}
@@ -133,11 +140,26 @@ FetchJob::set_state(const std::tr1::shared_ptr<JobState> & s)
_imp->state = s;
}
+const std::tr1::shared_ptr<const JobRequirements>
+FetchJob::requirements() const
+{
+ return _imp->requirements;
+}
+
const std::tr1::shared_ptr<FetchJob>
FetchJob::deserialise(Deserialisation & d)
{
Deserialisator v(d, "FetchJob");
+
+ std::tr1::shared_ptr<JobRequirements> requirements(new JobRequirements);
+ {
+ Deserialisator vv(*v.find_remove_member("requirements"), "c");
+ for (int n(1), n_end(vv.member<int>("count") + 1) ; n != n_end ; ++n)
+ requirements->push_back(vv.member<JobRequirement>(stringify(n)));
+ }
+
return make_shared_ptr(new FetchJob(
+ requirements,
v.member<std::tr1::shared_ptr<const PackageID> >("origin_id")
));
}
@@ -146,6 +168,7 @@ void
FetchJob::serialise(Serialiser & s) const
{
s.object("FetchJob")
+ .member(SerialiserFlags<serialise::container, serialise::might_be_null>(), "requirements", requirements())
.member(SerialiserFlags<serialise::might_be_null>(), "origin_id", origin_id())
;
}
@@ -155,6 +178,7 @@ namespace paludis
template <>
struct Implementation<InstallJob>
{
+ const std::tr1::shared_ptr<const JobRequirements> requirements;
const std::tr1::shared_ptr<const PackageID> origin_id;
const RepositoryName destination_repository_name;
const DestinationType destination_type;
@@ -163,11 +187,13 @@ namespace paludis
std::tr1::shared_ptr<JobState> state;
Implementation(
+ const std::tr1::shared_ptr<const JobRequirements> & q,
const std::tr1::shared_ptr<const PackageID> & o,
const RepositoryName & d,
const DestinationType t,
const std::tr1::shared_ptr<const PackageIDSequence> & r
) :
+ requirements(q),
origin_id(o),
destination_repository_name(d),
destination_type(t),
@@ -178,12 +204,13 @@ namespace paludis
}
InstallJob::InstallJob(
+ const std::tr1::shared_ptr<const JobRequirements> & q,
const std::tr1::shared_ptr<const PackageID> & o,
const RepositoryName & d,
const DestinationType t,
const std::tr1::shared_ptr<const PackageIDSequence> & r
) :
- PrivateImplementationPattern<InstallJob>(new Implementation<InstallJob>(o, d, t, r))
+ PrivateImplementationPattern<InstallJob>(new Implementation<InstallJob>(q, o, d, t, r))
{
}
@@ -227,6 +254,12 @@ InstallJob::set_state(const std::tr1::shared_ptr<JobState> & s)
_imp->state = s;
}
+const std::tr1::shared_ptr<const JobRequirements>
+InstallJob::requirements() const
+{
+ return _imp->requirements;
+}
+
const std::tr1::shared_ptr<InstallJob>
InstallJob::deserialise(Deserialisation & d)
{
@@ -239,7 +272,15 @@ InstallJob::deserialise(Deserialisation & d)
replacing->push_back(vv.member<std::tr1::shared_ptr<const PackageID> >(stringify(n)));
}
+ std::tr1::shared_ptr<JobRequirements> requirements(new JobRequirements);
+ {
+ Deserialisator vv(*v.find_remove_member("requirements"), "c");
+ for (int n(1), n_end(vv.member<int>("count") + 1) ; n != n_end ; ++n)
+ requirements->push_back(vv.member<JobRequirement>(stringify(n)));
+ }
+
return make_shared_ptr(new InstallJob(
+ requirements,
v.member<std::tr1::shared_ptr<const PackageID> >("origin_id"),
RepositoryName(v.member<std::string>("destination_repository_name")),
destringify<DestinationType>(v.member<std::string>("destination_type")),
@@ -251,6 +292,7 @@ void
InstallJob::serialise(Serialiser & s) const
{
s.object("InstallJob")
+ .member(SerialiserFlags<serialise::container, serialise::might_be_null>(), "requirements", requirements())
.member(SerialiserFlags<serialise::might_be_null>(), "origin_id", origin_id())
.member(SerialiserFlags<>(), "destination_repository_name", stringify(destination_repository_name()))
.member(SerialiserFlags<>(), "destination_type", stringify(destination_type()))
@@ -263,13 +305,16 @@ namespace paludis
template <>
struct Implementation<UninstallJob>
{
+ const std::tr1::shared_ptr<const JobRequirements> requirements;
const std::tr1::shared_ptr<const PackageIDSequence> ids_to_remove;
std::tr1::shared_ptr<JobState> state;
Implementation(
+ const std::tr1::shared_ptr<const JobRequirements> & q,
const std::tr1::shared_ptr<const PackageIDSequence> & r
) :
+ requirements(q),
ids_to_remove(r)
{
}
@@ -277,9 +322,10 @@ namespace paludis
}
UninstallJob::UninstallJob(
+ const std::tr1::shared_ptr<const JobRequirements> & q,
const std::tr1::shared_ptr<const PackageIDSequence> & r
) :
- PrivateImplementationPattern<UninstallJob>(new Implementation<UninstallJob>(r))
+ PrivateImplementationPattern<UninstallJob>(new Implementation<UninstallJob>(q, r))
{
}
@@ -305,6 +351,12 @@ UninstallJob::set_state(const std::tr1::shared_ptr<JobState> & s)
_imp->state = s;
}
+const std::tr1::shared_ptr<const JobRequirements>
+UninstallJob::requirements() const
+{
+ return _imp->requirements;
+}
+
const std::tr1::shared_ptr<UninstallJob>
UninstallJob::deserialise(Deserialisation & d)
{
@@ -317,7 +369,15 @@ UninstallJob::deserialise(Deserialisation & d)
ids_to_remove->push_back(vv.member<std::tr1::shared_ptr<const PackageID> >(stringify(n)));
}
+ std::tr1::shared_ptr<JobRequirements> requirements(new JobRequirements);
+ {
+ Deserialisator vv(*v.find_remove_member("requirements"), "c");
+ for (int n(1), n_end(vv.member<int>("count") + 1) ; n != n_end ; ++n)
+ requirements->push_back(vv.member<JobRequirement>(stringify(n)));
+ }
+
return make_shared_ptr(new UninstallJob(
+ requirements,
ids_to_remove
));
}
@@ -326,6 +386,7 @@ void
UninstallJob::serialise(Serialiser & s) const
{
s.object("UninstallJob")
+ .member(SerialiserFlags<serialise::container, serialise::might_be_null>(), "requirements", requirements())
.member(SerialiserFlags<serialise::container, serialise::might_be_null>(), "ids_to_remove", ids_to_remove())
;
}
diff --git a/paludis/resolver/job.hh b/paludis/resolver/job.hh
index 3483bea..a27bc17 100644
--- a/paludis/resolver/job.hh
+++ b/paludis/resolver/job.hh
@@ -22,6 +22,7 @@
#include <paludis/resolver/job-fwd.hh>
#include <paludis/resolver/job_state-fwd.hh>
+#include <paludis/resolver/job_requirements-fwd.hh>
#include <paludis/resolver/destination_types-fwd.hh>
#include <paludis/util/private_implementation_pattern.hh>
#include <paludis/util/simple_visitor.hh>
@@ -60,6 +61,8 @@ namespace paludis
virtual const std::tr1::shared_ptr<JobState> state() const PALUDIS_ATTRIBUTE((warn_unused_result)) = 0;
virtual void set_state(const std::tr1::shared_ptr<JobState> &) = 0;
+ virtual const std::tr1::shared_ptr<const JobRequirements> requirements() const PALUDIS_ATTRIBUTE((warn_unused_result)) = 0;
+
static const std::tr1::shared_ptr<ExecuteJob> deserialise(Deserialisation &) PALUDIS_ATTRIBUTE((warn_unused_result));
virtual void serialise(Serialiser &) const = 0;
};
@@ -71,6 +74,7 @@ namespace paludis
{
public:
FetchJob(
+ const std::tr1::shared_ptr<const JobRequirements> &,
const std::tr1::shared_ptr<const PackageID> &
);
~FetchJob();
@@ -80,6 +84,8 @@ namespace paludis
virtual const std::tr1::shared_ptr<JobState> state() const PALUDIS_ATTRIBUTE((warn_unused_result));
virtual void set_state(const std::tr1::shared_ptr<JobState> &);
+ virtual const std::tr1::shared_ptr<const JobRequirements> requirements() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
static const std::tr1::shared_ptr<FetchJob> deserialise(Deserialisation &) PALUDIS_ATTRIBUTE((warn_unused_result));
virtual void serialise(Serialiser &) const;
};
@@ -91,6 +97,7 @@ namespace paludis
{
public:
InstallJob(
+ const std::tr1::shared_ptr<const JobRequirements> &,
const std::tr1::shared_ptr<const PackageID> &,
const RepositoryName &,
const DestinationType,
@@ -105,6 +112,8 @@ namespace paludis
virtual const std::tr1::shared_ptr<JobState> state() const PALUDIS_ATTRIBUTE((warn_unused_result));
virtual void set_state(const std::tr1::shared_ptr<JobState> &);
+ virtual const std::tr1::shared_ptr<const JobRequirements> requirements() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
static const std::tr1::shared_ptr<InstallJob> deserialise(Deserialisation &) PALUDIS_ATTRIBUTE((warn_unused_result));
virtual void serialise(Serialiser &) const;
};
@@ -116,6 +125,7 @@ namespace paludis
{
public:
UninstallJob(
+ const std::tr1::shared_ptr<const JobRequirements> &,
const std::tr1::shared_ptr<const PackageIDSequence> &
);
~UninstallJob();
@@ -125,6 +135,8 @@ namespace paludis
virtual const std::tr1::shared_ptr<JobState> state() const PALUDIS_ATTRIBUTE((warn_unused_result));
virtual void set_state(const std::tr1::shared_ptr<JobState> &);
+ virtual const std::tr1::shared_ptr<const JobRequirements> requirements() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
static const std::tr1::shared_ptr<UninstallJob> deserialise(Deserialisation &) PALUDIS_ATTRIBUTE((warn_unused_result));
virtual void serialise(Serialiser &) const;
};
diff --git a/paludis/resolver/job_list-fwd.hh b/paludis/resolver/job_list-fwd.hh
index f7943f1..da4256e 100644
--- a/paludis/resolver/job_list-fwd.hh
+++ b/paludis/resolver/job_list-fwd.hh
@@ -27,7 +27,7 @@ namespace paludis
template <typename Job_>
struct JobList;
- typedef int JobListIndex;
+ typedef int JobNumber;
}
}
diff --git a/paludis/resolver/job_list.cc b/paludis/resolver/job_list.cc
index ec3203f..031c028 100644
--- a/paludis/resolver/job_list.cc
+++ b/paludis/resolver/job_list.cc
@@ -60,7 +60,7 @@ JobList<Job_>::~JobList()
}
template <typename Job_>
-JobListIndex
+JobNumber
JobList<Job_>::append(const std::tr1::shared_ptr<Job_> & i)
{
typename std::vector<std::tr1::shared_ptr<Job_> >::const_iterator p(_imp->list.insert(_imp->list.end(), i));
@@ -89,6 +89,13 @@ JobList<Job_>::end() const
}
template <typename Job_>
+typename JobList<Job_>::ConstIterator
+JobList<Job_>::fetch(const JobNumber n) const
+{
+ return ConstIterator(_imp->list.begin() + n);
+}
+
+template <typename Job_>
const std::tr1::shared_ptr<JobList<Job_> >
JobList<Job_>::deserialise(Deserialisation & d)
{
diff --git a/paludis/resolver/job_list.hh b/paludis/resolver/job_list.hh
index c116d17..a2bc464 100644
--- a/paludis/resolver/job_list.hh
+++ b/paludis/resolver/job_list.hh
@@ -45,7 +45,7 @@ namespace paludis
JobList();
~JobList();
- JobListIndex append(const std::tr1::shared_ptr<Job_> &);
+ JobNumber append(const std::tr1::shared_ptr<Job_> &);
int length() const PALUDIS_ATTRIBUTE((warn_unused_result));
@@ -53,6 +53,7 @@ namespace paludis
typedef WrappedForwardIterator<ConstIteratorTag, const std::tr1::shared_ptr<Job_> > ConstIterator;
ConstIterator begin() const PALUDIS_ATTRIBUTE((warn_unused_result));
ConstIterator end() const PALUDIS_ATTRIBUTE((warn_unused_result));
+ ConstIterator fetch(const JobNumber) const PALUDIS_ATTRIBUTE((warn_unused_result));
static const std::tr1::shared_ptr<JobList<Job_> > deserialise(Deserialisation &) PALUDIS_ATTRIBUTE((warn_unused_result));
void serialise(Serialiser &) const;
diff --git a/paludis/resolver/job_requirements-fwd.hh b/paludis/resolver/job_requirements-fwd.hh
new file mode 100644
index 0000000..4c974d8
--- /dev/null
+++ b/paludis/resolver/job_requirements-fwd.hh
@@ -0,0 +1,41 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2010 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_REQUIREMENTS_FWD_HH
+#define PALUDIS_GUARD_PALUDIS_RESOLVER_JOB_REQUIREMENTS_FWD_HH 1
+
+#include <paludis/util/sequence-fwd.hh>
+#include <paludis/util/options-fwd.hh>
+#include <paludis/util/attributes.hh>
+#include <iosfwd>
+
+namespace paludis
+{
+ namespace resolver
+ {
+#include <paludis/resolver/job_requirements-se.hh>
+
+ typedef Options<JobRequirementIf> JobRequirementIfs;
+
+ struct JobRequirement;
+ typedef Sequence<JobRequirement> JobRequirements;
+ }
+}
+
+#endif
diff --git a/paludis/resolver/job_requirements.cc b/paludis/resolver/job_requirements.cc
new file mode 100644
index 0000000..7fda1d0
--- /dev/null
+++ b/paludis/resolver/job_requirements.cc
@@ -0,0 +1,56 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2010 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_requirements.hh>
+#include <paludis/util/exception.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/wrapped_forward_iterator-impl.hh>
+#include <paludis/util/sequence-impl.hh>
+#include <paludis/util/make_named_values.hh>
+#include <paludis/serialise-impl.hh>
+#include <istream>
+#include <ostream>
+
+using namespace paludis;
+using namespace paludis::resolver;
+
+#include <paludis/resolver/job_requirements-se.cc>
+
+const JobRequirement
+JobRequirement::deserialise(Deserialisation & d)
+{
+ Deserialisator v(d, "JobRequirement");
+ return make_named_values<JobRequirement>(
+ n::job_number() = v.member<JobNumber>("job_number"),
+ n::required_if() = v.member<JobRequirementIfs>("required_if")
+ );
+}
+
+void
+JobRequirement::serialise(Serialiser & s) const
+{
+ s.object("JobRequirement")
+ .member(SerialiserFlags<>(), "job_number", job_number())
+ .member(SerialiserFlags<>(), "required_if", required_if())
+ ;
+}
+
+template class Sequence<JobRequirement>;
+template class WrappedForwardIterator<Sequence<JobRequirement>::ConstIteratorTag, const JobRequirement>;
+
diff --git a/paludis/resolver/job_requirements.hh b/paludis/resolver/job_requirements.hh
new file mode 100644
index 0000000..cd31777
--- /dev/null
+++ b/paludis/resolver/job_requirements.hh
@@ -0,0 +1,57 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2010 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_REQUIREMENTS_HH
+#define PALUDIS_GUARD_PALUDIS_RESOLVER_JOB_REQUIREMENTS_HH 1
+
+#include <paludis/resolver/job_requirements-fwd.hh>
+#include <paludis/resolver/job_list-fwd.hh>
+#include <paludis/util/options.hh>
+#include <paludis/util/named_value.hh>
+#include <paludis/util/sequence.hh>
+#include <paludis/util/wrapped_forward_iterator.hh>
+#include <paludis/serialise-fwd.hh>
+
+namespace paludis
+{
+ namespace n
+ {
+ typedef Name<struct job_number_name> job_number;
+ typedef Name<struct required_if_name> required_if;
+ }
+
+ namespace resolver
+ {
+ struct JobRequirement
+ {
+ NamedValue<n::job_number, JobNumber> job_number;
+ NamedValue<n::required_if, JobRequirementIfs> required_if;
+
+ static const JobRequirement deserialise(Deserialisation & d) PALUDIS_ATTRIBUTE((warn_unused_result));
+ void serialise(Serialiser &) const;
+ };
+ }
+
+#ifdef PALUDIS_HAVE_EXTERN_TEMPLATE
+ extern template class Sequence<resolver::JobRequirement>;
+ extern template class WrappedForwardIterator<Sequence<resolver::JobRequirement>::ConstIteratorTag, const resolver::JobRequirement>;
+#endif
+}
+
+#endif
diff --git a/paludis/resolver/job_requirements.se b/paludis/resolver/job_requirements.se
new file mode 100644
index 0000000..ab9b52d
--- /dev/null
+++ b/paludis/resolver/job_requirements.se
@@ -0,0 +1,16 @@
+#!/usr/bin/env bash
+# vim: set sw=4 sts=4 et ft=sh :
+
+make_enum_JobRequirementIf()
+{
+ prefix jri
+ namespace paludis::resolver
+
+ key jri_require_for_satisfied "Require it if we're in if-satisfied mode"
+ key jri_require_for_independent "Require it if we're in if-independent mode"
+ key jri_require_always "Always require it"
+
+ want_destringify
+}
+
+
diff --git a/paludis/resolver/orderer.cc b/paludis/resolver/orderer.cc
index 60b96bb..b533b7d 100644
--- a/paludis/resolver/orderer.cc
+++ b/paludis/resolver/orderer.cc
@@ -29,6 +29,7 @@
#include <paludis/resolver/job_lists.hh>
#include <paludis/resolver/job_list.hh>
#include <paludis/resolver/job.hh>
+#include <paludis/resolver/job_requirements.hh>
#include <paludis/resolver/destination.hh>
#include <paludis/resolver/orderer_notes.hh>
#include <paludis/util/private_implementation_pattern-impl.hh>
@@ -50,6 +51,7 @@ using namespace paludis;
using namespace paludis::resolver;
typedef std::tr1::unordered_map<Resolvent, std::tr1::shared_ptr<const ChangeOrRemoveDecision>, Hash<Resolvent> > ChangeOrRemoveResolvents;
+typedef std::tr1::unordered_map<Resolvent, JobNumber, Hash<Resolvent> > InstallJobNumbers;
namespace paludis
{
@@ -59,6 +61,7 @@ namespace paludis
const Environment * const env;
const std::tr1::shared_ptr<Resolved> resolved;
ChangeOrRemoveResolvents change_or_remove_resolvents;
+ InstallJobNumbers install_job_numbers;
Implementation(
const Environment * const e,
@@ -375,7 +378,8 @@ Orderer::resolve()
{
/* there's only one real package in the component, so there's no
* need to try anything clever */
- _schedule(_imp->change_or_remove_resolvents.find(*changes_in_scc.begin())->second,
+ _schedule(*changes_in_scc.begin(),
+ _imp->change_or_remove_resolvents.find(*changes_in_scc.begin())->second,
make_shared_copy(make_named_values<OrdererNotes>(
n::cycle_breaking() = ""
)));
@@ -427,7 +431,8 @@ Orderer::_order_sub_ssccs(
if (sub_scc->nodes()->size() == 1)
{
/* yay. it's all on its own. */
- _schedule(_imp->change_or_remove_resolvents.find(*sub_scc->nodes()->begin())->second,
+ _schedule(*sub_scc->nodes()->begin(),
+ _imp->change_or_remove_resolvents.find(*sub_scc->nodes()->begin())->second,
make_shared_copy(make_named_values<OrdererNotes>(
n::cycle_breaking() = (can_recurse ?
"In dependency cycle with existing packages: " + join(scc_nag.begin_nodes(), scc_nag.end_nodes(), ", ", nice_resolvent) :
@@ -441,12 +446,13 @@ Orderer::_order_sub_ssccs(
* dependency cycles which we can order however we like! */
for (Set<Resolvent>::ConstIterator r(sub_scc->nodes()->begin()), r_end(sub_scc->nodes()->end()) ;
r != r_end ; ++r)
- _schedule(_imp->change_or_remove_resolvents.find(*r)->second,
- make_shared_copy(make_named_values<OrdererNotes>(
- n::cycle_breaking() = "In run dependency cycle with: " + join(
- sub_scc->nodes()->begin(), sub_scc->nodes()->end(), ", ", nice_resolvent) + (can_recurse ?
- " in dependency cycle with " + join(top_scc.nodes()->begin(), top_scc.nodes()->end(), ", ", nice_resolvent) : "")
- )));
+ _schedule(*r,
+ _imp->change_or_remove_resolvents.find(*r)->second,
+ make_shared_copy(make_named_values<OrdererNotes>(
+ n::cycle_breaking() = "In run dependency cycle with: " + join(
+ sub_scc->nodes()->begin(), sub_scc->nodes()->end(), ", ", nice_resolvent) + (can_recurse ?
+ " in dependency cycle with " + join(top_scc.nodes()->begin(), top_scc.nodes()->end(), ", ", nice_resolvent) : "")
+ )));
}
else if (can_recurse)
{
@@ -485,8 +491,53 @@ Orderer::_order_sub_ssccs(
}
}
+namespace
+{
+ typedef std::tr1::unordered_set<Resolvent, Hash<Resolvent> > RecursedRequirements;
+
+ void populate_requirements(
+ const std::tr1::shared_ptr<const NAG> & nag,
+ const InstallJobNumbers & install_job_numbers,
+ const Resolvent & resolvent,
+ const std::tr1::shared_ptr<JobRequirements> & requirements,
+ const bool recursing,
+ RecursedRequirements & recursed)
+ {
+ if (! recursing)
+ for (NAG::EdgesFromConstIterator e(nag->begin_edges_from(resolvent)),
+ e_end(nag->end_edges_from(resolvent)) ;
+ e != e_end ; ++e)
+ {
+ if ((! e->second.build_all_met()) || (! e->second.run_all_met()))
+ {
+ InstallJobNumbers::const_iterator n(install_job_numbers.find(e->first));
+ if (n != install_job_numbers.end())
+ requirements->push_back(make_named_values<JobRequirement>(
+ n::job_number() = n->second,
+ n::required_if() = JobRequirementIfs() + jri_require_for_satisfied
+ ));
+ }
+ }
+
+ if (recursed.insert(resolvent).second)
+ for (NAG::EdgesFromConstIterator e(nag->begin_edges_from(resolvent)),
+ e_end(nag->end_edges_from(resolvent)) ;
+ e != e_end ; ++e)
+ {
+ InstallJobNumbers::const_iterator n(install_job_numbers.find(e->first));
+ if (n != install_job_numbers.end())
+ requirements->push_back(make_named_values<JobRequirement>(
+ n::job_number() = n->second,
+ n::required_if() = JobRequirementIfs() + jri_require_for_independent
+ ));
+ populate_requirements(nag, install_job_numbers, e->first, requirements, true, recursed);
+ }
+ }
+}
+
void
Orderer::_schedule(
+ const Resolvent & resolvent,
const std::tr1::shared_ptr<const ChangeOrRemoveDecision> & d,
const std::tr1::shared_ptr<const OrdererNotes> & n)
{
@@ -502,19 +553,40 @@ Orderer::_schedule(
_imp->resolved->job_lists()->pretend_job_list()->append(make_shared_ptr(new PretendJob(
changes_to_make_decision->origin_id())));
- _imp->resolved->job_lists()->execute_job_list()->append(make_shared_ptr(new FetchJob(
- changes_to_make_decision->origin_id())));
-
- _imp->resolved->job_lists()->execute_job_list()->append(make_shared_ptr(new InstallJob(
- changes_to_make_decision->origin_id(),
- changes_to_make_decision->destination()->repository(),
- changes_to_make_decision->resolvent().destination_type(),
- changes_to_make_decision->destination()->replacing()
- )));
+ JobNumber fetch_job_n(_imp->resolved->job_lists()->execute_job_list()->append(make_shared_ptr(new FetchJob(
+ make_shared_ptr(new JobRequirements),
+ changes_to_make_decision->origin_id()))));
+
+ const std::tr1::shared_ptr<JobRequirements> requirements(new JobRequirements);
+ requirements->push_back(make_named_values<JobRequirement>(
+ n::job_number() = fetch_job_n,
+ n::required_if() = JobRequirementIfs() + jri_require_for_satisfied + jri_require_for_independent + jri_require_always
+ ));
+
+ RecursedRequirements recursed;
+ populate_requirements(
+ _imp->resolved->nag(),
+ _imp->install_job_numbers,
+ resolvent,
+ requirements,
+ false,
+ recursed
+ );
+
+ JobNumber install_job_n(_imp->resolved->job_lists()->execute_job_list()->append(make_shared_ptr(new InstallJob(
+ requirements,
+ changes_to_make_decision->origin_id(),
+ changes_to_make_decision->destination()->repository(),
+ changes_to_make_decision->resolvent().destination_type(),
+ changes_to_make_decision->destination()->replacing()
+ ))));
+
+ _imp->install_job_numbers.insert(std::make_pair(resolvent, install_job_n));
}
else if (remove_decision)
{
_imp->resolved->job_lists()->execute_job_list()->append(make_shared_ptr(new UninstallJob(
+ make_shared_ptr(new JobRequirements),
remove_decision->ids()
)));
}
diff --git a/paludis/resolver/orderer.hh b/paludis/resolver/orderer.hh
index a80119b..8edc785 100644
--- a/paludis/resolver/orderer.hh
+++ b/paludis/resolver/orderer.hh
@@ -26,6 +26,7 @@
#include <paludis/resolver/decision-fwd.hh>
#include <paludis/resolver/strongly_connected_component-fwd.hh>
#include <paludis/resolver/nag-fwd.hh>
+#include <paludis/resolver/resolvent-fwd.hh>
#include <paludis/util/private_implementation_pattern.hh>
#include <paludis/environment-fwd.hh>
@@ -38,6 +39,7 @@ namespace paludis
{
private:
void _schedule(
+ const Resolvent &,
const std::tr1::shared_ptr<const ChangeOrRemoveDecision> &,
const std::tr1::shared_ptr<const OrdererNotes> &);
diff --git a/paludis/resolver/resolver_TEST_continue_on_failure.cc b/paludis/resolver/resolver_TEST_continue_on_failure.cc
new file mode 100644
index 0000000..597d693
--- /dev/null
+++ b/paludis/resolver/resolver_TEST_continue_on_failure.cc
@@ -0,0 +1,159 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2010 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/constraint.hh>
+#include <paludis/resolver/resolvent.hh>
+#include <paludis/resolver/suggest_restart.hh>
+#include <paludis/resolver/job_lists.hh>
+#include <paludis/resolver/job_list.hh>
+#include <paludis/resolver/job.hh>
+#include <paludis/resolver/job_requirements.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-impl.hh>
+#include <paludis/util/indirect_iterator-impl.hh>
+#include <paludis/util/accept_visitor.hh>
+#include <paludis/util/tribool.hh>
+#include <paludis/util/make_shared_copy.hh>
+#include <paludis/util/simple_visitor_cast.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 ResolverContinueOnFailureTestCase : ResolverTestCase
+ {
+ ResolverContinueOnFailureTestCase(const std::string & s) :
+ ResolverTestCase("continue_on_failure", s, "exheres-0", "exheres")
+ {
+ }
+ };
+
+ UseExisting
+ use_existing_if_same(
+ const std::tr1::shared_ptr<const Resolution> &,
+ const PackageDepSpec &,
+ const std::tr1::shared_ptr<const Reason> &)
+ {
+ return ue_if_same;
+ }
+
+ std::string
+ stringify_req(const JobRequirement & r)
+ {
+ std::stringstream result;
+ result << r.job_number();
+ if (r.required_if()[jri_require_for_satisfied])
+ result << " satisfied";
+ if (r.required_if()[jri_require_for_independent])
+ result << " independent";
+ if (r.required_if()[jri_require_always])
+ result << " always";
+ return result.str();
+ }
+}
+
+namespace test_cases
+{
+ struct TestContinueOnFailure : ResolverContinueOnFailureTestCase
+ {
+ const bool direct_dep_installed;
+
+ TestContinueOnFailure(const bool d) :
+ ResolverContinueOnFailureTestCase("continue on failure " + stringify(d)),
+ direct_dep_installed(d)
+ {
+ if (d)
+ install("continue-on-failure", "direct-dep", "0");
+ install("continue-on-failure", "unchanged-dep", "1")->build_dependencies_key()->set_from_string("continue-on-failure/indirect-dep");
+ }
+
+ virtual ResolverFunctions get_resolver_functions(InitialConstraints & initial_constraints)
+ {
+ ResolverFunctions result(ResolverContinueOnFailureTestCase::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()
+ {
+ std::tr1::shared_ptr<const Resolved> resolved(get_resolved("continue-on-failure/target"));
+
+ check_resolved(resolved,
+ n::taken_change_or_remove_decisions() = make_shared_copy(DecisionChecks()
+ .change(QualifiedPackageName("continue-on-failure/direct-dep"))
+ .change(QualifiedPackageName("continue-on-failure/indirect-dep"))
+ .change(QualifiedPackageName("continue-on-failure/target"))
+ .finished()),
+ n::taken_unable_to_make_decisions() = make_shared_copy(DecisionChecks()
+ .finished()),
+ n::untaken_change_or_remove_decisions() = make_shared_copy(DecisionChecks()
+ .finished()),
+ n::untaken_unable_to_make_decisions() = make_shared_copy(DecisionChecks()
+ .finished())
+ );
+
+ TEST_CHECK_EQUAL(resolved->job_lists()->execute_job_list()->length(), 6);
+
+ const InstallJob * const direct_dep_job(simple_visitor_cast<const InstallJob>(**resolved->job_lists()->execute_job_list()->fetch(1)));
+ TEST_CHECK(direct_dep_job);
+ TEST_CHECK_EQUAL(join(direct_dep_job->requirements()->begin(), direct_dep_job->requirements()->end(), ", ", stringify_req),
+ "0 satisfied independent always");
+
+ const InstallJob * const indirect_dep_job(simple_visitor_cast<const InstallJob>(**resolved->job_lists()->execute_job_list()->fetch(3)));
+ TEST_CHECK(indirect_dep_job);
+ TEST_CHECK_EQUAL(join(indirect_dep_job->requirements()->begin(), indirect_dep_job->requirements()->end(), ", ", stringify_req),
+ "2 satisfied independent always");
+
+ const InstallJob * const target_job(simple_visitor_cast<const InstallJob>(**resolved->job_lists()->execute_job_list()->fetch(5)));
+ TEST_CHECK(target_job);
+ if (direct_dep_installed)
+ TEST_CHECK_EQUAL(join(target_job->requirements()->begin(), target_job->requirements()->end(), ", ", stringify_req),
+ "4 satisfied independent always, 3 independent, 1 independent");
+ else
+ TEST_CHECK_EQUAL(join(target_job->requirements()->begin(), target_job->requirements()->end(), ", ", stringify_req),
+ "4 satisfied independent always, 1 satisfied, 3 independent, 1 independent");
+ }
+ } test_continue_on_failure_false(false), test_continue_on_failure_true(true);
+}
+
diff --git a/paludis/resolver/resolver_TEST_continue_on_failure_cleanup.sh b/paludis/resolver/resolver_TEST_continue_on_failure_cleanup.sh
new file mode 100755
index 0000000..849bc51
--- /dev/null
+++ b/paludis/resolver/resolver_TEST_continue_on_failure_cleanup.sh
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+# vim: set ft=sh sw=4 sts=4 et :
+
+if [ -d resolver_TEST_continue_on_failure_dir ] ; then
+ rm -fr resolver_TEST_continue_on_failure_dir
+else
+ true
+fi
+
diff --git a/paludis/resolver/resolver_TEST_continue_on_failure_setup.sh b/paludis/resolver/resolver_TEST_continue_on_failure_setup.sh
new file mode 100755
index 0000000..ffa8f7c
--- /dev/null
+++ b/paludis/resolver/resolver_TEST_continue_on_failure_setup.sh
@@ -0,0 +1,56 @@
+#!/usr/bin/env bash
+# vim: set ft=sh sw=4 sts=4 et :
+
+mkdir resolver_TEST_continue_on_failure_dir || exit 1
+cd resolver_TEST_continue_on_failure_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
+
+# continue-on-failure
+echo 'continue-on-failure' >> metadata/categories.conf
+
+mkdir -p 'packages/continue-on-failure/target'
+cat <<END > packages/continue-on-failure/target/target-1.exheres-0
+SUMMARY="target"
+PLATFORMS="test"
+SLOT="0"
+DEPENDENCIES="
+ continue-on-failure/unchanged-dep
+ continue-on-failure/direct-dep
+ "
+END
+
+mkdir -p 'packages/continue-on-failure/direct-dep'
+cat <<END > packages/continue-on-failure/direct-dep/direct-dep-1.exheres-0
+SUMMARY="dep"
+PLATFORMS="test"
+SLOT="0"
+END
+
+mkdir -p 'packages/continue-on-failure/unchanged-dep'
+cat <<END > packages/continue-on-failure/unchanged-dep/unchanged-dep-1.exheres-0
+SUMMARY="dep"
+PLATFORMS="test"
+SLOT="0"
+DEPENDENCIES="
+ continue-on-failure/indirect-dep
+ "
+END
+
+mkdir -p 'packages/continue-on-failure/indirect-dep'
+cat <<END > packages/continue-on-failure/indirect-dep/indirect-dep-1.exheres-0
+SUMMARY="dep"
+PLATFORMS="test"
+SLOT="0"
+END
+
+cd ..
+
diff --git a/src/clients/cave/cmd_execute_resolution.cc b/src/clients/cave/cmd_execute_resolution.cc
index 78f9d7f..59d4d74 100644
--- a/src/clients/cave/cmd_execute_resolution.cc
+++ b/src/clients/cave/cmd_execute_resolution.cc
@@ -54,6 +54,7 @@
#include <paludis/resolver/job_list.hh>
#include <paludis/resolver/job.hh>
#include <paludis/resolver/job_state.hh>
+#include <paludis/resolver/job_requirements.hh>
#include <paludis/package_id.hh>
#include <paludis/version_spec.hh>
#include <paludis/metadata_key.hh>
@@ -703,6 +704,35 @@ namespace
}
};
+ struct ContinueAfterState
+ {
+ bool visit(const JobPendingState &) const
+ {
+ /* it's still pending because it's a circular dep that we ended up ignoring */
+ return true;
+ }
+
+ bool visit(const JobActiveState &) const PALUDIS_ATTRIBUTE((noreturn))
+ {
+ throw InternalError(PALUDIS_HERE, "still active? how did that happen?");
+ }
+
+ bool visit(const JobSucceededState &) const
+ {
+ return true;
+ }
+
+ bool visit(const JobFailedState &) const
+ {
+ return false;
+ }
+
+ bool visit(const JobSkippedState &) const
+ {
+ return false;
+ }
+ };
+
int execute_executions(
const std::tr1::shared_ptr<Environment> & env,
const std::tr1::shared_ptr<JobLists> & lists,
@@ -716,11 +746,45 @@ namespace
).max_exit_status())
throw ActionAbortedError("Aborted by hook");
+ JobRequirementIf require_if(last_jri);
+ if (cmdline.execution_options.a_continue_on_failure.argument() == "always")
+ require_if = jri_require_always;
+ else if (cmdline.execution_options.a_continue_on_failure.argument() == "if-satisfied")
+ require_if = jri_require_for_satisfied;
+ else if (cmdline.execution_options.a_continue_on_failure.argument() == "if-independent")
+ require_if = jri_require_for_independent;
+ else if (cmdline.execution_options.a_continue_on_failure.argument() == "never")
+ require_if = last_jri;
+ else
+ throw args::DoHelp("Don't understand argument '"
+ + cmdline.execution_options.a_continue_on_failure.argument() + "' to '--"
+ + cmdline.execution_options.a_continue_on_failure.long_name() + "'");
+
for (JobList<ExecuteJob>::ConstIterator c(lists->execute_job_list()->begin()),
c_end(lists->execute_job_list()->end()) ;
c != c_end ; ++c)
{
- if (0 == retcode)
+ bool want(true);
+
+ if (0 != retcode)
+ {
+ if (last_jri == require_if)
+ want = false;
+ else
+ {
+ for (JobRequirements::ConstIterator r((*c)->requirements()->begin()), r_end((*c)->requirements()->end()) ;
+ r != r_end && want ; ++r)
+ {
+ if (! r->required_if()[require_if])
+ continue;
+
+ const std::tr1::shared_ptr<const ExecuteJob> req(*lists->execute_job_list()->fetch(r->job_number()));
+ want = want && req->state()->accept_returning<bool>(ContinueAfterState());
+ }
+ }
+ }
+
+ if (want)
{
ExecuteOneVisitor execute(env, cmdline, x_fetch, x_install, y);
retcode |= (*c)->accept_returning<int>(execute);