diff options
31 files changed, 1562 insertions, 806 deletions
diff --git a/.gitignore b/.gitignore index f8c4d4df1..ae0445676 100644 --- a/.gitignore +++ b/.gitignore @@ -336,6 +336,7 @@ paludis-*.*.*.tar.bz2 /paludis/syncers/dobzr+ftp /paludis/syncers/dobzr+http /paludis/syncers/dobzr+https +/paludis/syncers/dobzr+lp /paludis/syncers/dobzr+sftp /paludis/syncers/dobzr+ssh /paludis/syncers/docvs+ext diff --git a/paludis/resolver/Makefile.am b/paludis/resolver/Makefile.am index e3c5a7ba1..f479e568b 100644 --- a/paludis/resolver/Makefile.am +++ b/paludis/resolver/Makefile.am @@ -27,6 +27,7 @@ noinst_HEADERS = \ constraint.hh constraint-fwd.hh \ job.hh job-fwd.hh \ job_id.hh job_id-fwd.hh \ + job_state.hh job_state-fwd.hh \ jobs.hh jobs-fwd.hh \ decider.hh decider-fwd.hh \ decision.hh decision-fwd.hh \ @@ -59,6 +60,7 @@ libpaludisresolver_a_SOURCES = \ failure_kinds.cc \ job.cc \ job_id.cc \ + job_state.cc \ jobs.cc \ orderer.cc \ reason.cc \ diff --git a/paludis/resolver/decision.cc b/paludis/resolver/decision.cc index d0192479e..c27a7cf9b 100644 --- a/paludis/resolver/decision.cc +++ b/paludis/resolver/decision.cc @@ -1,7 +1,7 @@ /* vim: set sw=4 sts=4 et foldmethod=syntax : */ /* - * Copyright (c) 2009 Ciaran McCreesh + * Copyright (c) 2009, 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 @@ -62,27 +62,11 @@ Decision::deserialise(Deserialisation & d) } else if (d.class_name() == "ChangesToMakeDecision") { - Deserialisator v(d, "ChangesToMakeDecision"); - return make_shared_ptr(new ChangesToMakeDecision( - v.member<std::tr1::shared_ptr<const PackageID> >("origin_id"), - v.member<bool>("best"), - v.member<bool>("taken"), - v.member<std::tr1::shared_ptr<const Destination> >("destination") - )); + return ChangesToMakeDecision::deserialise(d); } else if (d.class_name() == "UnableToMakeDecision") { - Deserialisator v(d, "UnableToMakeDecision"); - - std::tr1::shared_ptr<UnsuitableCandidates> unsuitable_candidates(new UnsuitableCandidates); - Deserialisator vv(*v.find_remove_member("unsuitable_candidates"), "c"); - for (int n(1), n_end(vv.member<int>("count") + 1) ; n != n_end ; ++n) - unsuitable_candidates->push_back(vv.member<UnsuitableCandidate>(stringify(n))); - - return make_shared_ptr(new UnableToMakeDecision( - unsuitable_candidates, - v.member<bool>("taken") - )); + return UnableToMakeDecision::deserialise(d); } else throw InternalError(PALUDIS_HERE, "unknown class '" + stringify(d.class_name()) + "'"); @@ -100,6 +84,22 @@ ChangesToMakeDecision::deserialise(Deserialisation & d) )); } +const std::tr1::shared_ptr<UnableToMakeDecision> +UnableToMakeDecision::deserialise(Deserialisation & d) +{ + Deserialisator v(d, "UnableToMakeDecision"); + + std::tr1::shared_ptr<UnsuitableCandidates> unsuitable_candidates(new UnsuitableCandidates); + Deserialisator vv(*v.find_remove_member("unsuitable_candidates"), "c"); + for (int n(1), n_end(vv.member<int>("count") + 1) ; n != n_end ; ++n) + unsuitable_candidates->push_back(vv.member<UnsuitableCandidate>(stringify(n))); + + return make_shared_ptr(new UnableToMakeDecision( + unsuitable_candidates, + v.member<bool>("taken") + )); +} + namespace paludis { template <> diff --git a/paludis/resolver/decision.hh b/paludis/resolver/decision.hh index 95c5da517..026aacea2 100644 --- a/paludis/resolver/decision.hh +++ b/paludis/resolver/decision.hh @@ -1,7 +1,7 @@ /* vim: set sw=4 sts=4 et foldmethod=syntax : */ /* - * Copyright (c) 2009 Ciaran McCreesh + * Copyright (c) 2009, 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 @@ -126,7 +126,8 @@ namespace paludis class PALUDIS_VISIBLE UnableToMakeDecision : public Decision, public ImplementAcceptMethods<Decision, UnableToMakeDecision>, - private PrivateImplementationPattern<UnableToMakeDecision> + private PrivateImplementationPattern<UnableToMakeDecision>, + public std::tr1::enable_shared_from_this<UnableToMakeDecision> { public: UnableToMakeDecision( @@ -139,6 +140,9 @@ namespace paludis virtual void serialise(Serialiser &) const; const std::tr1::shared_ptr<const UnsuitableCandidates> unsuitable_candidates() const PALUDIS_ATTRIBUTE((warn_unused_result)); + + static const std::tr1::shared_ptr<UnableToMakeDecision> deserialise( + Deserialisation & d) PALUDIS_ATTRIBUTE((warn_unused_result)); }; } diff --git a/paludis/resolver/job-fwd.hh b/paludis/resolver/job-fwd.hh index 0f88e1b0d..e9ea4da93 100644 --- a/paludis/resolver/job-fwd.hh +++ b/paludis/resolver/job-fwd.hh @@ -1,7 +1,7 @@ /* vim: set sw=4 sts=4 et foldmethod=syntax : */ /* - * Copyright (c) 2009 Ciaran McCreesh + * Copyright (c) 2009, 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 @@ -27,11 +27,10 @@ namespace paludis struct Job; struct SimpleInstallJob; - struct PretendJob; struct FetchJob; struct UsableJob; - struct SyncPointJob; - struct UntakenInstallJob; + struct UsableGroupJob; + struct ErrorJob; } } diff --git a/paludis/resolver/job.cc b/paludis/resolver/job.cc index d09e1f4e6..03d3ea19a 100644 --- a/paludis/resolver/job.cc +++ b/paludis/resolver/job.cc @@ -1,7 +1,7 @@ /* vim: set sw=4 sts=4 et foldmethod=syntax : */ /* - * Copyright (c) 2009 Ciaran McCreesh + * Copyright (c) 2009, 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 @@ -26,6 +26,7 @@ #include <paludis/util/make_named_values.hh> #include <paludis/util/wrapped_forward_iterator.hh> #include <paludis/util/stringify.hh> +#include <paludis/util/join.hh> #include <paludis/serialise-impl.hh> using namespace paludis; @@ -38,26 +39,27 @@ namespace paludis { const std::tr1::shared_ptr<const Resolution> resolution; const std::tr1::shared_ptr<ArrowSequence> arrows; + const std::tr1::shared_ptr<JobIDSequence> used_existing_packages_when_ordering; Implementation(const std::tr1::shared_ptr<const Resolution> & r) : resolution(r), - arrows(new ArrowSequence) + arrows(new ArrowSequence), + used_existing_packages_when_ordering(new JobIDSequence) { } }; template <> - struct Implementation<PretendJob> + struct Implementation<UsableGroupJob> { - const std::tr1::shared_ptr<const Resolution> resolution; - const std::tr1::shared_ptr<const ChangesToMakeDecision> decision; + const std::tr1::shared_ptr<const JobIDSequence> ids; const std::tr1::shared_ptr<ArrowSequence> arrows; + const std::tr1::shared_ptr<JobIDSequence> used_existing_packages_when_ordering; - Implementation(const std::tr1::shared_ptr<const Resolution> & r, - const std::tr1::shared_ptr<const ChangesToMakeDecision> & d) : - resolution(r), - decision(d), - arrows(new ArrowSequence) + Implementation(const std::tr1::shared_ptr<const JobIDSequence> & i) : + ids(i), + arrows(new ArrowSequence), + used_existing_packages_when_ordering(new JobIDSequence) { } }; @@ -68,12 +70,14 @@ namespace paludis const std::tr1::shared_ptr<const Resolution> resolution; const std::tr1::shared_ptr<const ChangesToMakeDecision> decision; const std::tr1::shared_ptr<ArrowSequence> arrows; + const std::tr1::shared_ptr<JobIDSequence> used_existing_packages_when_ordering; Implementation(const std::tr1::shared_ptr<const Resolution> & r, const std::tr1::shared_ptr<const ChangesToMakeDecision> & d) : resolution(r), decision(d), - arrows(new ArrowSequence) + arrows(new ArrowSequence), + used_existing_packages_when_ordering(new JobIDSequence) { } }; @@ -84,38 +88,32 @@ namespace paludis const std::tr1::shared_ptr<const Resolution> resolution; const std::tr1::shared_ptr<const ChangesToMakeDecision> decision; const std::tr1::shared_ptr<ArrowSequence> arrows; + const std::tr1::shared_ptr<JobIDSequence> used_existing_packages_when_ordering; Implementation(const std::tr1::shared_ptr<const Resolution> & r, const std::tr1::shared_ptr<const ChangesToMakeDecision> & d) : resolution(r), decision(d), - arrows(new ArrowSequence) + arrows(new ArrowSequence), + used_existing_packages_when_ordering(new JobIDSequence) { } }; template <> - struct Implementation<UntakenInstallJob> + struct Implementation<ErrorJob> { const std::tr1::shared_ptr<const Resolution> resolution; + const std::tr1::shared_ptr<const UnableToMakeDecision> decision; const std::tr1::shared_ptr<ArrowSequence> arrows; + const std::tr1::shared_ptr<JobIDSequence> used_existing_packages_when_ordering; - Implementation(const std::tr1::shared_ptr<const Resolution> & r) : + Implementation(const std::tr1::shared_ptr<const Resolution> & r, + const std::tr1::shared_ptr<const UnableToMakeDecision> & d) : 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) + decision(d), + arrows(new ArrowSequence), + used_existing_packages_when_ordering(new JobIDSequence) { } }; @@ -135,6 +133,15 @@ namespace for (int n(1), n_end(vv.member<int>("count") + 1) ; n != n_end ; ++n) result->arrows()->push_back(vv.member<Arrow>(stringify(n))); } + + void do_existing( + const std::tr1::shared_ptr<Job> & result, + Deserialisator & v) + { + Deserialisator vv(*v.find_remove_member("used_existing_packages_when_ordering"), "c"); + for (int n(1), n_end(vv.member<int>("count") + 1) ; n != n_end ; ++n) + result->used_existing_packages_when_ordering()->push_back(vv.member<JobID>(stringify(n))); + } } const std::tr1::shared_ptr<Job> @@ -149,24 +156,30 @@ Job::deserialise(Deserialisation & d) v.member<std::tr1::shared_ptr<Resolution> >("resolution") )); do_arrows(result, v); + do_existing(result, v); } - else if (d.class_name() == "SimpleInstallJob") + else if (d.class_name() == "UsableGroupJob") { - Deserialisator v(d, "SimpleInstallJob"); - result.reset(new SimpleInstallJob( - v.member<std::tr1::shared_ptr<Resolution> >("resolution"), - v.member<std::tr1::shared_ptr<ChangesToMakeDecision> >("decision") - )); + Deserialisator v(d, "UsableGroupJob"); + + Deserialisator vv(*v.find_remove_member("job_ids"), "c"); + const std::tr1::shared_ptr<JobIDSequence> ids(new JobIDSequence); + for (int n(1), n_end(vv.member<int>("count") + 1) ; n != n_end ; ++n) + ids->push_back(vv.member<JobID>(stringify(n))); + + result.reset(new UsableGroupJob(ids)); do_arrows(result, v); + do_existing(result, v); } - else if (d.class_name() == "PretendJob") + else if (d.class_name() == "SimpleInstallJob") { - Deserialisator v(d, "PretendJob"); - result.reset(new PretendJob( + 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); + do_existing(result, v); } else if (d.class_name() == "FetchJob") { @@ -176,22 +189,17 @@ Job::deserialise(Deserialisation & d) v.member<std::tr1::shared_ptr<ChangesToMakeDecision> >("decision") )); do_arrows(result, v); + do_existing(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") + else if (d.class_name() == "ErrorJob") { - Deserialisator v(d, "SyncPointJob"); - result.reset(new SyncPointJob( - destringify<SyncPoint>(v.member<std::string>("sync_point")) + Deserialisator v(d, "ErrorJob"); + result.reset(new ErrorJob( + v.member<std::tr1::shared_ptr<Resolution> >("resolution"), + v.member<std::tr1::shared_ptr<UnableToMakeDecision> >("decision") )); do_arrows(result, v); + do_existing(result, v); } else throw InternalError(PALUDIS_HERE, "unknown class '" + stringify(d.class_name()) + "'"); @@ -214,12 +222,30 @@ UsableJob::resolution() const return _imp->resolution; } -const std::tr1::shared_ptr<ArrowSequence> +const std::tr1::shared_ptr<const ArrowSequence> UsableJob::arrows() const { return _imp->arrows; } +const std::tr1::shared_ptr<ArrowSequence> +UsableJob::arrows() +{ + return _imp->arrows; +} + +const std::tr1::shared_ptr<const JobIDSequence> +UsableJob::used_existing_packages_when_ordering() const +{ + return _imp->used_existing_packages_when_ordering; +} + +const std::tr1::shared_ptr<JobIDSequence> +UsableJob::used_existing_packages_when_ordering() +{ + return _imp->used_existing_packages_when_ordering; +} + const JobID UsableJob::id() const { @@ -234,52 +260,74 @@ UsableJob::serialise(Serialiser & s) const s.object("UsableJob") .member(SerialiserFlags<serialise::might_be_null, serialise::container>(), "arrows", arrows()) .member(SerialiserFlags<serialise::might_be_null>(), "resolution", resolution()) + .member(SerialiserFlags<serialise::container, serialise::might_be_null>(), + "used_existing_packages_when_ordering", used_existing_packages_when_ordering()) ; } -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)) +UsableGroupJob::UsableGroupJob(const std::tr1::shared_ptr<const JobIDSequence> & r) : + PrivateImplementationPattern<UsableGroupJob>(new Implementation<UsableGroupJob>(r)) { } -PretendJob::~PretendJob() +UsableGroupJob::~UsableGroupJob() { } -const std::tr1::shared_ptr<const Resolution> -PretendJob::resolution() const +const std::tr1::shared_ptr<const JobIDSequence> +UsableGroupJob::job_ids() const { - return _imp->resolution; + return _imp->ids; } -const std::tr1::shared_ptr<const ChangesToMakeDecision> -PretendJob::decision() const +const std::tr1::shared_ptr<const ArrowSequence> +UsableGroupJob::arrows() const { - return _imp->decision; + return _imp->arrows; } const std::tr1::shared_ptr<ArrowSequence> -PretendJob::arrows() const +UsableGroupJob::arrows() { return _imp->arrows; } +const std::tr1::shared_ptr<const JobIDSequence> +UsableGroupJob::used_existing_packages_when_ordering() const +{ + return _imp->used_existing_packages_when_ordering; +} + +const std::tr1::shared_ptr<JobIDSequence> +UsableGroupJob::used_existing_packages_when_ordering() +{ + return _imp->used_existing_packages_when_ordering; +} + +namespace +{ + std::string stringify_job_id(const JobID & i) + { + return i.string_id(); + } +} + const JobID -PretendJob::id() const +UsableGroupJob::id() const { return make_named_values<JobID>( - value_for<n::string_id>("pretend:" + stringify(resolution()->resolvent())) + value_for<n::string_id>("usable_group:" + join(_imp->ids->begin(), _imp->ids->end(), "+", &stringify_job_id)) ); } void -PretendJob::serialise(Serialiser & s) const +UsableGroupJob::serialise(Serialiser & s) const { - s.object("PretendJob") + s.object("UsableGroupJob") .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()) + .member(SerialiserFlags<serialise::might_be_null, serialise::container>(), "job_ids", job_ids()) + .member(SerialiserFlags<serialise::container, serialise::might_be_null>(), + "used_existing_packages_when_ordering", used_existing_packages_when_ordering()) ; } @@ -305,12 +353,30 @@ FetchJob::decision() const return _imp->decision; } -const std::tr1::shared_ptr<ArrowSequence> +const std::tr1::shared_ptr<const ArrowSequence> FetchJob::arrows() const { return _imp->arrows; } +const std::tr1::shared_ptr<ArrowSequence> +FetchJob::arrows() +{ + return _imp->arrows; +} + +const std::tr1::shared_ptr<const JobIDSequence> +FetchJob::used_existing_packages_when_ordering() const +{ + return _imp->used_existing_packages_when_ordering; +} + +const std::tr1::shared_ptr<JobIDSequence> +FetchJob::used_existing_packages_when_ordering() +{ + return _imp->used_existing_packages_when_ordering; +} + const JobID FetchJob::id() const { @@ -326,6 +392,8 @@ FetchJob::serialise(Serialiser & s) const .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()) + .member(SerialiserFlags<serialise::container, serialise::might_be_null>(), + "used_existing_packages_when_ordering", used_existing_packages_when_ordering()) ; } @@ -351,12 +419,30 @@ SimpleInstallJob::decision() const return _imp->decision; } -const std::tr1::shared_ptr<ArrowSequence> +const std::tr1::shared_ptr<const ArrowSequence> SimpleInstallJob::arrows() const { return _imp->arrows; } +const std::tr1::shared_ptr<ArrowSequence> +SimpleInstallJob::arrows() +{ + return _imp->arrows; +} + +const std::tr1::shared_ptr<const JobIDSequence> +SimpleInstallJob::used_existing_packages_when_ordering() const +{ + return _imp->used_existing_packages_when_ordering; +} + +const std::tr1::shared_ptr<JobIDSequence> +SimpleInstallJob::used_existing_packages_when_ordering() +{ + return _imp->used_existing_packages_when_ordering; +} + const JobID SimpleInstallJob::id() const { @@ -372,89 +458,78 @@ SimpleInstallJob::serialise(Serialiser & s) const .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()) + .member(SerialiserFlags<serialise::container, serialise::might_be_null>(), + "used_existing_packages_when_ordering", used_existing_packages_when_ordering()) ; } -UntakenInstallJob::UntakenInstallJob(const std::tr1::shared_ptr<const Resolution> & r) : - PrivateImplementationPattern<UntakenInstallJob>(new Implementation<UntakenInstallJob>(r)) +ErrorJob::ErrorJob(const std::tr1::shared_ptr<const Resolution> & r, const std::tr1::shared_ptr<const UnableToMakeDecision> & d) : + PrivateImplementationPattern<ErrorJob>(new Implementation<ErrorJob>(r, d)) { } -UntakenInstallJob::~UntakenInstallJob() +ErrorJob::~ErrorJob() { } const std::tr1::shared_ptr<const Resolution> -UntakenInstallJob::resolution() const +ErrorJob::resolution() const { return _imp->resolution; } -const std::tr1::shared_ptr<ArrowSequence> -UntakenInstallJob::arrows() const +const std::tr1::shared_ptr<const ArrowSequence> +ErrorJob::arrows() const { return _imp->arrows; } -const JobID -UntakenInstallJob::id() const -{ - return make_named_values<JobID>( - value_for<n::string_id>("untaken:" + 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)) +const std::tr1::shared_ptr<ArrowSequence> +ErrorJob::arrows() { + return _imp->arrows; } -SyncPointJob::~SyncPointJob() +const std::tr1::shared_ptr<const JobIDSequence> +ErrorJob::used_existing_packages_when_ordering() const { + return _imp->used_existing_packages_when_ordering; } -SyncPoint -SyncPointJob::sync_point() const +const std::tr1::shared_ptr<JobIDSequence> +ErrorJob::used_existing_packages_when_ordering() { - return _imp->sync_point; -} - -const std::tr1::shared_ptr<ArrowSequence> -SyncPointJob::arrows() const -{ - return _imp->arrows; + return _imp->used_existing_packages_when_ordering; } const JobID -SyncPointJob::id() const +ErrorJob::id() const { return make_named_values<JobID>( - value_for<n::string_id>("sync:" + stringify(sync_point())) + value_for<n::string_id>("error:" + stringify(resolution()->resolvent())) ); } void -SyncPointJob::serialise(Serialiser & s) const +ErrorJob::serialise(Serialiser & s) const { - s.object("SyncPointJob") + s.object("ErrorJob") .member(SerialiserFlags<serialise::might_be_null, serialise::container>(), "arrows", arrows()) - .member(SerialiserFlags<>(), "sync_point", stringify(sync_point())) + .member(SerialiserFlags<serialise::might_be_null>(), "decision", decision()) + .member(SerialiserFlags<serialise::might_be_null>(), "resolution", resolution()) + .member(SerialiserFlags<serialise::container, serialise::might_be_null>(), + "used_existing_packages_when_ordering", used_existing_packages_when_ordering()) ; } +const std::tr1::shared_ptr<const UnableToMakeDecision> +ErrorJob::decision() const +{ + return _imp->decision; +} template class PrivateImplementationPattern<resolver::UsableJob>; -template class PrivateImplementationPattern<resolver::PretendJob>; +template class PrivateImplementationPattern<resolver::UsableGroupJob>; template class PrivateImplementationPattern<resolver::FetchJob>; template class PrivateImplementationPattern<resolver::SimpleInstallJob>; -template class PrivateImplementationPattern<resolver::SyncPointJob>; -template class PrivateImplementationPattern<resolver::UntakenInstallJob>; +template class PrivateImplementationPattern<resolver::ErrorJob>; diff --git a/paludis/resolver/job.hh b/paludis/resolver/job.hh index a007ef7bf..a227ddc19 100644 --- a/paludis/resolver/job.hh +++ b/paludis/resolver/job.hh @@ -1,7 +1,7 @@ /* vim: set sw=4 sts=4 et foldmethod=syntax : */ /* - * Copyright (c) 2009 Ciaran McCreesh + * Copyright (c) 2009, 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 @@ -39,7 +39,7 @@ namespace paludis { class PALUDIS_VISIBLE Job : public virtual DeclareAbstractAcceptMethods<Job, MakeTypeList< - UsableJob, SimpleInstallJob, PretendJob, FetchJob, UntakenInstallJob, SyncPointJob>::Type> + UsableJob, UsableGroupJob, SimpleInstallJob, FetchJob, ErrorJob>::Type> { public: virtual ~Job() = 0; @@ -47,9 +47,18 @@ namespace paludis virtual const JobID id() const PALUDIS_ATTRIBUTE((warn_unused_result)) = 0; + virtual const std::tr1::shared_ptr<const ArrowSequence> arrows() + const PALUDIS_ATTRIBUTE((warn_unused_result)) = 0; + virtual const std::tr1::shared_ptr<ArrowSequence> arrows() + PALUDIS_ATTRIBUTE((warn_unused_result)) = 0; + + virtual const std::tr1::shared_ptr<const JobIDSequence> used_existing_packages_when_ordering() const PALUDIS_ATTRIBUTE((warn_unused_result)) = 0; + virtual const std::tr1::shared_ptr<JobIDSequence> used_existing_packages_when_ordering() + PALUDIS_ATTRIBUTE((warn_unused_result)) = 0; + virtual void serialise(Serialiser &) const = 0; static const std::tr1::shared_ptr<Job> deserialise( @@ -67,32 +76,47 @@ namespace paludis virtual const JobID id() const PALUDIS_ATTRIBUTE((warn_unused_result)); + virtual const std::tr1::shared_ptr<const ArrowSequence> arrows() + const PALUDIS_ATTRIBUTE((warn_unused_result)); + virtual const std::tr1::shared_ptr<ArrowSequence> arrows() + PALUDIS_ATTRIBUTE((warn_unused_result)); + + virtual const std::tr1::shared_ptr<const JobIDSequence> used_existing_packages_when_ordering() const PALUDIS_ATTRIBUTE((warn_unused_result)); + virtual const std::tr1::shared_ptr<JobIDSequence> used_existing_packages_when_ordering() + 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 : + class PALUDIS_VISIBLE UsableGroupJob : public Job, - public ImplementAcceptMethods<Job, PretendJob>, - private PrivateImplementationPattern<PretendJob> + public ImplementAcceptMethods<Job, UsableGroupJob>, + private PrivateImplementationPattern<UsableGroupJob> { public: - PretendJob( - const std::tr1::shared_ptr<const Resolution> &, - const std::tr1::shared_ptr<const ChangesToMakeDecision> &); - ~PretendJob(); + UsableGroupJob(const std::tr1::shared_ptr<const JobIDSequence> &); + ~UsableGroupJob(); virtual const JobID id() const PALUDIS_ATTRIBUTE((warn_unused_result)); + virtual const std::tr1::shared_ptr<const ArrowSequence> arrows() + const PALUDIS_ATTRIBUTE((warn_unused_result)); + virtual const std::tr1::shared_ptr<ArrowSequence> arrows() + PALUDIS_ATTRIBUTE((warn_unused_result)); + + virtual const std::tr1::shared_ptr<const JobIDSequence> used_existing_packages_when_ordering() 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 const std::tr1::shared_ptr<JobIDSequence> used_existing_packages_when_ordering() + PALUDIS_ATTRIBUTE((warn_unused_result)); + + const std::tr1::shared_ptr<const JobIDSequence> job_ids() const PALUDIS_ATTRIBUTE((warn_unused_result)); virtual void serialise(Serialiser &) const; }; @@ -110,9 +134,18 @@ namespace paludis virtual const JobID id() const PALUDIS_ATTRIBUTE((warn_unused_result)); + virtual const std::tr1::shared_ptr<const ArrowSequence> arrows() + const PALUDIS_ATTRIBUTE((warn_unused_result)); + virtual const std::tr1::shared_ptr<ArrowSequence> arrows() + PALUDIS_ATTRIBUTE((warn_unused_result)); + + virtual const std::tr1::shared_ptr<const JobIDSequence> used_existing_packages_when_ordering() const PALUDIS_ATTRIBUTE((warn_unused_result)); + virtual const std::tr1::shared_ptr<JobIDSequence> used_existing_packages_when_ordering() + 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)); @@ -132,49 +165,51 @@ namespace paludis virtual const JobID id() const PALUDIS_ATTRIBUTE((warn_unused_result)); + virtual const std::tr1::shared_ptr<const ArrowSequence> arrows() + const PALUDIS_ATTRIBUTE((warn_unused_result)); + virtual const std::tr1::shared_ptr<ArrowSequence> arrows() + PALUDIS_ATTRIBUTE((warn_unused_result)); + + virtual const std::tr1::shared_ptr<const JobIDSequence> used_existing_packages_when_ordering() const PALUDIS_ATTRIBUTE((warn_unused_result)); + virtual const std::tr1::shared_ptr<JobIDSequence> used_existing_packages_when_ordering() + 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 : + class PALUDIS_VISIBLE ErrorJob : public Job, - public ImplementAcceptMethods<Job, SyncPointJob>, - private PrivateImplementationPattern<SyncPointJob> + public ImplementAcceptMethods<Job, ErrorJob>, + private PrivateImplementationPattern<ErrorJob> { public: - SyncPointJob(const SyncPoint); - ~SyncPointJob(); + ErrorJob( + const std::tr1::shared_ptr<const Resolution> &, + const std::tr1::shared_ptr<const UnableToMakeDecision> &); + ~ErrorJob(); virtual const JobID id() const PALUDIS_ATTRIBUTE((warn_unused_result)); - virtual const std::tr1::shared_ptr<ArrowSequence> arrows() + virtual const std::tr1::shared_ptr<const 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() + PALUDIS_ATTRIBUTE((warn_unused_result)); + + virtual const std::tr1::shared_ptr<const JobIDSequence> used_existing_packages_when_ordering() const PALUDIS_ATTRIBUTE((warn_unused_result)); + virtual const std::tr1::shared_ptr<JobIDSequence> used_existing_packages_when_ordering() + 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 UnableToMakeDecision> decision() const PALUDIS_ATTRIBUTE((warn_unused_result)); virtual void serialise(Serialiser &) const; }; @@ -182,11 +217,10 @@ namespace paludis #ifdef PALUDIS_HAVE_EXTERN_TEMPLATE extern template class PrivateImplementationPattern<resolver::UsableJob>; - extern template class PrivateImplementationPattern<resolver::PretendJob>; + extern template class PrivateImplementationPattern<resolver::UsableGroupJob>; extern template class PrivateImplementationPattern<resolver::FetchJob>; extern template class PrivateImplementationPattern<resolver::SimpleInstallJob>; - extern template class PrivateImplementationPattern<resolver::SyncPointJob>; - extern template class PrivateImplementationPattern<resolver::UntakenInstallJob>; + extern template class PrivateImplementationPattern<resolver::ErrorJob>; #endif } diff --git a/paludis/resolver/job_id.cc b/paludis/resolver/job_id.cc index adba99697..a8d577453 100644 --- a/paludis/resolver/job_id.cc +++ b/paludis/resolver/job_id.cc @@ -1,7 +1,7 @@ /* vim: set sw=4 sts=4 et foldmethod=syntax : */ /* - * Copyright (c) 2009 Ciaran McCreesh + * Copyright (c) 2009, 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 @@ -39,6 +39,12 @@ JobID::hash() const return Hash<std::string>()(string_id()); } +bool +JobID::operator< (const JobID & other) const +{ + return string_id() < other.string_id(); +} + void JobID::serialise(Serialiser & s) const { diff --git a/paludis/resolver/job_id.hh b/paludis/resolver/job_id.hh index e93c9ded9..fc63947f6 100644 --- a/paludis/resolver/job_id.hh +++ b/paludis/resolver/job_id.hh @@ -1,7 +1,7 @@ /* vim: set sw=4 sts=4 et foldmethod=syntax : */ /* - * Copyright (c) 2009 Ciaran McCreesh + * Copyright (c) 2009, 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 @@ -39,6 +39,7 @@ namespace paludis NamedValue<n::string_id, std::string> string_id; std::size_t hash() const PALUDIS_ATTRIBUTE((warn_unused_result)); + bool operator< (const JobID &) const PALUDIS_ATTRIBUTE((warn_unused_result)); void serialise(Serialiser &) const; static const JobID deserialise(Deserialisation & d) PALUDIS_ATTRIBUTE((warn_unused_result)); diff --git a/paludis/resolver/job_state-fwd.hh b/paludis/resolver/job_state-fwd.hh new file mode 100644 index 000000000..fab624ec8 --- /dev/null +++ b/paludis/resolver/job_state-fwd.hh @@ -0,0 +1,35 @@ +/* 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_STATE_FWD_HH +#define PALUDIS_GUARD_PALUDIS_RESOLVER_JOB_STATE_FWD_HH 1 + +namespace paludis +{ + namespace resolver + { + struct JobState; + struct JobPendingState; + struct JobSucceededState; + struct JobFailedState; + struct JobSkippedState; + } +} + +#endif diff --git a/paludis/resolver/job_state.cc b/paludis/resolver/job_state.cc new file mode 100644 index 000000000..60afc2c3c --- /dev/null +++ b/paludis/resolver/job_state.cc @@ -0,0 +1,180 @@ +/* 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_state.hh> +#include <paludis/util/private_implementation_pattern-impl.hh> +#include <list> + +using namespace paludis; +using namespace paludis::resolver; + +JobState::~JobState() +{ +} + +namespace paludis +{ + template <> + struct Implementation<JobPendingState> + { + const std::tr1::shared_ptr<const Job> job; + + Implementation(const std::tr1::shared_ptr<const Job> & j) : + job(j) + { + } + }; + + template <> + struct Implementation<JobSucceededState> + { + const std::tr1::shared_ptr<const Job> job; + std::list<std::tr1::shared_ptr<OutputManager> > output_managers; + + Implementation(const std::tr1::shared_ptr<const Job> & j) : + job(j) + { + } + }; + + template <> + struct Implementation<JobFailedState> + { + const std::tr1::shared_ptr<const Job> job; + std::list<std::tr1::shared_ptr<OutputManager> > output_managers; + + Implementation(const std::tr1::shared_ptr<const Job> & j) : + job(j) + { + } + }; + + template <> + struct Implementation<JobSkippedState> + { + const std::tr1::shared_ptr<const Job> job; + + Implementation(const std::tr1::shared_ptr<const Job> & j) : + job(j) + { + } + }; +} + +JobPendingState::JobPendingState(const std::tr1::shared_ptr<const Job> & j) : + PrivateImplementationPattern<JobPendingState>(new Implementation<JobPendingState>(j)) +{ +} + +JobPendingState::~JobPendingState() +{ +} + +const std::tr1::shared_ptr<const Job> +JobPendingState::job() const +{ + return _imp->job; +} + +const std::string +JobPendingState::state_name() const +{ + return "pending"; +} + +JobSucceededState::JobSucceededState(const std::tr1::shared_ptr<const Job> & j) : + PrivateImplementationPattern<JobSucceededState>(new Implementation<JobSucceededState>(j)) +{ +} + +JobSucceededState::~JobSucceededState() +{ +} + +const std::tr1::shared_ptr<const Job> +JobSucceededState::job() const +{ + return _imp->job; +} + +const std::string +JobSucceededState::state_name() const +{ + return "succeeded"; +} + +void +JobSucceededState::add_output_manager(const std::tr1::shared_ptr<OutputManager> & o) +{ + _imp->output_managers.push_back(o); +} + +JobFailedState::JobFailedState(const std::tr1::shared_ptr<const Job> & j) : + PrivateImplementationPattern<JobFailedState>(new Implementation<JobFailedState>(j)) +{ +} + +JobFailedState::~JobFailedState() +{ +} + +const std::tr1::shared_ptr<const Job> +JobFailedState::job() const +{ + return _imp->job; +} + +void +JobFailedState::add_output_manager(const std::tr1::shared_ptr<OutputManager> & o) +{ + _imp->output_managers.push_back(o); +} + +const std::string +JobFailedState::state_name() const +{ + return "failed"; +} + +JobSkippedState::JobSkippedState(const std::tr1::shared_ptr<const Job> & j) : + PrivateImplementationPattern<JobSkippedState>(new Implementation<JobSkippedState>(j)) +{ +} + +JobSkippedState::~JobSkippedState() +{ +} + +const std::tr1::shared_ptr<const Job> +JobSkippedState::job() const +{ + return _imp->job; +} + +const std::string +JobSkippedState::state_name() const +{ + return "skipped"; +} + +template class PrivateImplementationPattern<JobPendingState>; +template class PrivateImplementationPattern<JobSucceededState>; +template class PrivateImplementationPattern<JobFailedState>; +template class PrivateImplementationPattern<JobSkippedState>; + diff --git a/paludis/resolver/job_state.hh b/paludis/resolver/job_state.hh new file mode 100644 index 000000000..1479e764c --- /dev/null +++ b/paludis/resolver/job_state.hh @@ -0,0 +1,114 @@ +/* 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_STATE_HH +#define PALUDIS_GUARD_PALUDIS_RESOLVER_JOB_STATE_HH 1 + +#include <paludis/resolver/job_state-fwd.hh> +#include <paludis/resolver/job-fwd.hh> +#include <paludis/util/private_implementation_pattern.hh> +#include <paludis/util/simple_visitor.hh> +#include <paludis/util/type_list.hh> +#include <paludis/output_manager-fwd.hh> +#include <tr1/memory> +#include <string> + +namespace paludis +{ + namespace resolver + { + class PALUDIS_VISIBLE JobState : + public virtual DeclareAbstractAcceptMethods<JobState, MakeTypeList< + JobPendingState, JobSucceededState, JobFailedState, JobSkippedState>::Type> + { + public: + virtual ~JobState() = 0; + + virtual const std::tr1::shared_ptr<const Job> job() const + PALUDIS_ATTRIBUTE((warn_unused_result)) = 0; + + virtual const std::string state_name() const PALUDIS_ATTRIBUTE((warn_unused_result)) = 0; + }; + + class PALUDIS_VISIBLE JobPendingState : + public JobState, + public ImplementAcceptMethods<JobState, JobPendingState>, + private PrivateImplementationPattern<JobPendingState> + { + public: + JobPendingState(const std::tr1::shared_ptr<const Job> &); + ~JobPendingState(); + + virtual const std::tr1::shared_ptr<const Job> job() const PALUDIS_ATTRIBUTE((warn_unused_result)); + virtual const std::string state_name() const PALUDIS_ATTRIBUTE((warn_unused_result)); + }; + + class PALUDIS_VISIBLE JobSucceededState : + public JobState, + public ImplementAcceptMethods<JobState, JobSucceededState>, + private PrivateImplementationPattern<JobSucceededState> + { + public: + JobSucceededState(const std::tr1::shared_ptr<const Job> &); + ~JobSucceededState(); + + virtual const std::tr1::shared_ptr<const Job> job() const PALUDIS_ATTRIBUTE((warn_unused_result)); + virtual const std::string state_name() const PALUDIS_ATTRIBUTE((warn_unused_result)); + + void add_output_manager(const std::tr1::shared_ptr<OutputManager> &); + }; + + class PALUDIS_VISIBLE JobFailedState : + public JobState, + public ImplementAcceptMethods<JobState, JobFailedState>, + private PrivateImplementationPattern<JobFailedState> + { + public: + JobFailedState(const std::tr1::shared_ptr<const Job> &); + ~JobFailedState(); + + virtual const std::tr1::shared_ptr<const Job> job() const PALUDIS_ATTRIBUTE((warn_unused_result)); + virtual const std::string state_name() const PALUDIS_ATTRIBUTE((warn_unused_result)); + + void add_output_manager(const std::tr1::shared_ptr<OutputManager> &); + }; + + class PALUDIS_VISIBLE JobSkippedState : + public JobState, + public ImplementAcceptMethods<JobState, JobSkippedState>, + private PrivateImplementationPattern<JobSkippedState> + { + public: + JobSkippedState(const std::tr1::shared_ptr<const Job> &); + ~JobSkippedState(); + + virtual const std::tr1::shared_ptr<const Job> job() const PALUDIS_ATTRIBUTE((warn_unused_result)); + virtual const std::string state_name() const PALUDIS_ATTRIBUTE((warn_unused_result)); + }; + } + +#ifdef PALUDIS_HAVE_EXTERN_TEMPLATE + extern template class PrivateImplementationPattern<resolver::JobPendingState>; + extern template class PrivateImplementationPattern<resolver::JobSucceededState>; + extern template class PrivateImplementationPattern<resolver::JobFailedState>; + extern template class PrivateImplementationPattern<resolver::JobSkippedState>; +#endif +} + +#endif diff --git a/paludis/resolver/jobs.cc b/paludis/resolver/jobs.cc index fd299565e..965466e13 100644 --- a/paludis/resolver/jobs.cc +++ b/paludis/resolver/jobs.cc @@ -1,7 +1,7 @@ /* vim: set sw=4 sts=4 et foldmethod=syntax : */ /* - * Copyright (c) 2009 Ciaran McCreesh + * Copyright (c) 2009, 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 @@ -25,6 +25,7 @@ #include <paludis/util/hashes.hh> #include <paludis/util/stringify.hh> #include <paludis/util/exception.hh> +#include <paludis/util/simple_visitor_cast.hh> #include <paludis/serialise-impl.hh> #include <tr1/unordered_map> #include <list> @@ -75,17 +76,16 @@ namespace jobs_list_by_resolvent_index.insert(std::make_pair(j.resolution()->resolvent(), i)); } - void visit(const SimpleInstallJob & j) + void visit(const UsableGroupJob &) { - jobs_list_by_resolvent_index.insert(std::make_pair(j.resolution()->resolvent(), i)); } - void visit(const UntakenInstallJob & j) + void visit(const SimpleInstallJob & j) { jobs_list_by_resolvent_index.insert(std::make_pair(j.resolution()->resolvent(), i)); } - void visit(const PretendJob & j) + void visit(const ErrorJob & j) { jobs_list_by_resolvent_index.insert(std::make_pair(j.resolution()->resolvent(), i)); } @@ -94,10 +94,6 @@ namespace { jobs_list_by_resolvent_index.insert(std::make_pair(j.resolution()->resolvent(), i)); } - - void visit(const SyncPointJob &) - { - } }; } @@ -114,27 +110,22 @@ namespace { struct InstalledJobChecker { - bool visit(const PretendJob &) const + bool visit(const FetchJob &) const { return false; } - bool visit(const SyncPointJob &) const + bool visit(const ErrorJob &) const { - return false; + return true; } - bool visit(const FetchJob &) const + bool visit(const UsableJob &) const { return false; } - bool visit(const UntakenInstallJob &) const - { - return true; - } - - bool visit(const UsableJob &) const + bool visit(const UsableGroupJob &) const { return false; } @@ -147,26 +138,21 @@ namespace struct UsableJobChecker { - bool visit(const PretendJob &) const + bool visit(const FetchJob &) const { return false; } - bool visit(const SyncPointJob &) const + bool visit(const ErrorJob &) const { - return false; + return true; } - bool visit(const FetchJob &) const + bool visit(const UsableGroupJob &) const { return false; } - bool visit(const UntakenInstallJob &) const - { - return true; - } - bool visit(const UsableJob &) const { return true; @@ -251,12 +237,23 @@ Jobs::fetch(const JobID & 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; + JobsListByJobIDIndex::const_iterator i(_imp->jobs_list_by_job_id_index.find(id)); + if (i == _imp->jobs_list_by_job_id_index.end()) + throw InternalError(PALUDIS_HERE, "no job for id"); + return *i->second; +} - throw InternalError(PALUDIS_HERE, "no job for id"); +template <typename J_> +const std::tr1::shared_ptr<const J_> +Jobs::fetch_as(const JobID & id) const +{ + JobsListByJobIDIndex::const_iterator i(_imp->jobs_list_by_job_id_index.find(id)); + if (i == _imp->jobs_list_by_job_id_index.end()) + throw InternalError(PALUDIS_HERE, "no job for id"); + if (simple_visitor_cast<const J_>(**i->second)) + return std::tr1::static_pointer_cast<const J_>(*i->second); + else + throw InternalError(PALUDIS_HERE, "wrong job type id"); } void @@ -280,3 +277,8 @@ Jobs::deserialise(Deserialisation & d) template class PrivateImplementationPattern<resolver::Jobs>; +template const std::tr1::shared_ptr<const SimpleInstallJob> Jobs::fetch_as<SimpleInstallJob>(const JobID &) const; +template const std::tr1::shared_ptr<const ErrorJob> Jobs::fetch_as<ErrorJob>(const JobID &) const; +template const std::tr1::shared_ptr<const FetchJob> Jobs::fetch_as<FetchJob>(const JobID &) const; +template const std::tr1::shared_ptr<const UsableJob> Jobs::fetch_as<UsableJob>(const JobID &) const; + diff --git a/paludis/resolver/jobs.hh b/paludis/resolver/jobs.hh index d49a34991..bdd9dfa05 100644 --- a/paludis/resolver/jobs.hh +++ b/paludis/resolver/jobs.hh @@ -1,7 +1,7 @@ /* vim: set sw=4 sts=4 et foldmethod=syntax : */ /* - * Copyright (c) 2009 Ciaran McCreesh + * Copyright (c) 2009, 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 @@ -56,6 +56,10 @@ namespace paludis const std::tr1::shared_ptr<const Job> fetch( const JobID &) const PALUDIS_ATTRIBUTE((warn_unused_result)); + template <typename J_> + const std::tr1::shared_ptr<const J_> fetch_as( + const JobID &) const PALUDIS_ATTRIBUTE((warn_unused_result)); + void serialise(Serialiser &) const; static const std::tr1::shared_ptr<Jobs> deserialise( diff --git a/paludis/resolver/orderer.cc b/paludis/resolver/orderer.cc index 4aea541c4..a51411ad4 100644 --- a/paludis/resolver/orderer.cc +++ b/paludis/resolver/orderer.cc @@ -1,7 +1,7 @@ /* vim: set sw=4 sts=4 et foldmethod=syntax : */ /* - * Copyright (c) 2009 Ciaran McCreesh + * Copyright (c) 2009, 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 @@ -41,7 +41,6 @@ #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> @@ -49,11 +48,13 @@ #include <paludis/selection.hh> #include <paludis/notifier_callback.hh> #include <algorithm> -#include <tr1/unordered_set> +#include <set> using namespace paludis; using namespace paludis::resolver; +typedef std::set<JobID> ToOrder; + namespace paludis { template <> @@ -64,7 +65,7 @@ namespace paludis const std::tr1::shared_ptr<ResolverLists> lists; - std::tr1::unordered_set<JobID, Hash<JobID> > already_ordered; + ToOrder to_order; Implementation(const Environment * const e, const std::tr1::shared_ptr<const Decider> & d, @@ -109,25 +110,19 @@ namespace paludis namespace { - 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 { - CommonJobs & common_jobs; const std::tr1::shared_ptr<Resolution> resolution; const std::tr1::shared_ptr<ResolverLists> lists; + ToOrder & to_order; DecisionHandler( - CommonJobs & c, const std::tr1::shared_ptr<Resolution> & r, - const std::tr1::shared_ptr<ResolverLists> & l) : - common_jobs(c), + const std::tr1::shared_ptr<ResolverLists> & l, + ToOrder & o) : resolution(r), - lists(l) + lists(l), + to_order(o) { } @@ -140,15 +135,7 @@ namespace const std::tr1::shared_ptr<UsableJob> usable_job(new UsableJob(resolution)); lists->jobs()->add(usable_job); - lists->unordered_job_ids()->push_back(usable_job->id()); - - /* we want to do all of these as part of the main build process, - * not at pretend time */ - usable_job->arrows()->push_back(make_named_values<Arrow>( - value_for<n::comes_after>(common_jobs.done_pretends()->id()), - value_for<n::failure_kinds>(FailureKinds()), - value_for<n::maybe_reason>(make_null_shared_ptr()) - )); + to_order.insert(usable_job->id()); } else { @@ -166,15 +153,7 @@ namespace const std::tr1::shared_ptr<UsableJob> usable_job(new UsableJob(resolution)); lists->jobs()->add(usable_job); - lists->unordered_job_ids()->push_back(usable_job->id()); - - /* we want to do all of these as part of the main build process, - * not at pretend time */ - usable_job->arrows()->push_back(make_named_values<Arrow>( - value_for<n::comes_after>(common_jobs.done_pretends()->id()), - value_for<n::failure_kinds>(FailureKinds()), - value_for<n::maybe_reason>(make_null_shared_ptr()) - )); + to_order.insert(usable_job->id()); } else { @@ -190,53 +169,19 @@ namespace 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<FetchJob> fetch_job(new FetchJob(resolution, d.shared_from_this())); lists->jobs()->add(fetch_job); - lists->unordered_job_ids()->push_back(fetch_job->id()); + to_order.insert(fetch_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()); + to_order.insert(install_job->id()); const std::tr1::shared_ptr<UsableJob> usable_job(new UsableJob(resolution)); lists->jobs()->add(usable_job); - lists->unordered_job_ids()->push_back(usable_job->id()); - - /* we can't do any fetches or installs until all pretends have passed */ - fetch_job->arrows()->push_back(make_named_values<Arrow>( - value_for<n::comes_after>(common_jobs.done_pretends()->id()), - value_for<n::failure_kinds>(FailureKinds()), - value_for<n::maybe_reason>(make_null_shared_ptr()) - )); - - install_job->arrows()->push_back(make_named_values<Arrow>( - value_for<n::comes_after>(common_jobs.done_pretends()->id()), - value_for<n::failure_kinds>(FailureKinds()), - 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::failure_kinds>(FailureKinds()), - value_for<n::maybe_reason>(make_null_shared_ptr()) - )); - - /* we haven't done all our installs until we're usable - * (arguably this should just be install rather than usable, - * but the stronger requirement doesn't seem to hurt */ - common_jobs.done_installs()->arrows()->push_back(make_named_values<Arrow>( - value_for<n::comes_after>(usable_job->id()), - value_for<n::failure_kinds>(FailureKinds()), - value_for<n::maybe_reason>(make_null_shared_ptr()) - )); + to_order.insert(usable_job->id()); /* we can't install until we've fetched */ install_job->arrows()->push_back(make_named_values<Arrow>( @@ -257,7 +202,7 @@ namespace 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)); + const std::tr1::shared_ptr<SimpleInstallJob> install_job(new SimpleInstallJob(resolution, d.shared_from_this())); lists->jobs()->add(install_job); lists->untaken_job_ids()->push_back(install_job->id()); } @@ -270,16 +215,18 @@ namespace 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); + const std::tr1::shared_ptr<ErrorJob> error_job(new ErrorJob(resolution, d.shared_from_this())); + lists->jobs()->add(error_job); + lists->taken_error_job_ids()->push_back(error_job->id()); } 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()); + const std::tr1::shared_ptr<ErrorJob> error_job(new ErrorJob(resolution, d.shared_from_this())); + lists->jobs()->add(error_job); + lists->untaken_error_job_ids()->push_back(error_job->id()); } } }; @@ -288,22 +235,11 @@ namespace 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); + DecisionHandler d(*i, _imp->lists, _imp->to_order); (*i)->decision()->accept(d); } } @@ -512,19 +448,15 @@ namespace add_dep_arrows(true, c.resolution()); } - void visit(const FetchJob &) + void visit(const UsableGroupJob &) { } - void visit(const PretendJob &) - { - } - - void visit(const UntakenInstallJob &) + void visit(const FetchJob &) { } - void visit(const SyncPointJob &) + void visit(const ErrorJob &) { } }; @@ -535,8 +467,8 @@ Orderer::_resolve_jobs_dep_arrows() { Context context("When resolving dep arrows:"); - for (JobIDSequence::ConstIterator i(_imp->lists->unordered_job_ids()->begin()), - i_end(_imp->lists->unordered_job_ids()->end()) ; + for (ToOrder::const_iterator i(_imp->to_order.begin()), + i_end(_imp->to_order.end()) ; i != i_end ; ++i) { DepArrowHandler d(_imp->lists->jobs(), *i); @@ -552,7 +484,7 @@ Orderer::_resolve_order() _imp->env->trigger_notifier_callback(NotifierCallbackResolverStageEvent("Ordering")); /* anything left? */ - if (! _anything_left_to_order()) + if (_imp->to_order.empty()) break; /* first attempt: nothing fancy */ @@ -581,32 +513,16 @@ Orderer::_resolve_order() } bool -Orderer::_anything_left_to_order() const -{ - 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; - - return true; - } - - return false; -} - -bool Orderer::_order_some(const bool desperate, const bool installs_only) { bool result(false); - for (JobIDSequence::ConstIterator i(_imp->lists->unordered_job_ids()->begin()), - i_end(_imp->lists->unordered_job_ids()->end()) ; - i != i_end ; ++i) + for (ToOrder::iterator i(_imp->to_order.begin()), i_next(i), i_end(_imp->to_order.end()) ; + i != i_end ; i = i_next) { - if (_already_ordered(*i)) - continue; + /* i might end up invalidated by the time we're done */ + JobID id(*i); + ++i_next; if (installs_only) { @@ -615,46 +531,42 @@ Orderer::_order_some(const bool desperate, const bool installs_only) continue; } - if (! _can_order(*i, desperate)) + if (! _can_order(id, desperate)) continue; if (desperate) { - const std::tr1::shared_ptr<const Job> job(_imp->lists->jobs()->fetch(*i)); - std::stringstream s; + const std::tr1::shared_ptr<Job> job(_imp->lists->jobs()->fetch(id)); for (ArrowSequence::ConstIterator a(job->arrows()->begin()), a_end(job->arrows()->end()) ; a != a_end ; ++a) - if (! _already_ordered(a->comes_after())) - { - if (! s.str().empty()) - s << ", "; - s << a->comes_after().string_id(); - } - - Log::get_instance()->message("resolver.orderer.cycle_breaking.already_met", ll_warning, lc_context) - << "Had to use existing packages to order " << i->string_id() << " (unmet deps are " << s.str() << ")"; + if (_imp->to_order.end() != _imp->to_order.find(a->comes_after())) + job->used_existing_packages_when_ordering()->push_back(a->comes_after()); } - _imp->lists->ordered_job_ids()->push_back(*i); - _mark_already_ordered(*i); + _order_this(id, false); result = true; } return result; } +void +Orderer::_order_this(const JobID & i, const bool inside_something_else) +{ + if (! inside_something_else) + _imp->lists->taken_job_ids()->push_back(i); + _mark_already_ordered(i); +} + bool Orderer::_remove_usable_cycles() { /* we only want to remove usable jobs... */ - std::tr1::unordered_set<JobID, Hash<JobID> > removable; - for (JobIDSequence::ConstIterator i(_imp->lists->unordered_job_ids()->begin()), - i_end(_imp->lists->unordered_job_ids()->end()) ; + std::set<JobID> removable; + for (ToOrder::const_iterator i(_imp->to_order.begin()), + i_end(_imp->to_order.end()) ; i != i_end ; ++i) { - if (_already_ordered(*i)) - continue; - const std::tr1::shared_ptr<const Job> job(_imp->lists->jobs()->fetch(*i)); if (simple_visitor_cast<const UsableJob>(*job)) removable.insert(job->id()); @@ -674,7 +586,7 @@ Orderer::_remove_usable_cycles() 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())) + if (_imp->to_order.end() != _imp->to_order.find(a->comes_after())) if (removable.end() == removable.find(a->comes_after())) { need_another_pass = true; @@ -690,12 +602,22 @@ Orderer::_remove_usable_cycles() break; } - for (std::tr1::unordered_set<JobID, Hash<JobID> >::iterator i(removable.begin()), - i_end(removable.end()) ; - i != i_end ; ++i) + if (! removable.empty()) { - _imp->lists->ordered_job_ids()->push_back(*i); - _mark_already_ordered(*i); + const std::tr1::shared_ptr<JobIDSequence> ids(new JobIDSequence); + std::copy(removable.begin(), removable.end(), ids->back_inserter()); + + const std::tr1::shared_ptr<UsableGroupJob> usable_group_job(new UsableGroupJob(ids)); + _imp->lists->jobs()->add(usable_group_job); + _order_this(usable_group_job->id(), false); + + for (std::set<JobID>::iterator i(removable.begin()), i_next(i), + i_end(removable.end()) ; + i != i_end ; i = i_next) + { + ++i_next; + _order_this(*i, true); + } } return ! removable.empty(); @@ -705,18 +627,15 @@ void Orderer::_cycle_error() { std::stringstream s; - for (JobIDSequence::ConstIterator i(_imp->lists->unordered_job_ids()->begin()), - i_end(_imp->lists->unordered_job_ids()->end()) ; + for (ToOrder::const_iterator i(_imp->to_order.begin()), + i_end(_imp->to_order.end()) ; i != i_end ; ++i) { - if (_already_ordered(*i)) - continue; - 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())) + if (_imp->to_order.end() != _imp->to_order.find(a->comes_after())) s << " [" << a->comes_after().string_id() << "]"; s << " }}}"; } @@ -759,7 +678,7 @@ Orderer::_can_order(const JobID & i, const bool desperate) const for (ArrowSequence::ConstIterator a(job->arrows()->begin()), a_end(job->arrows()->end()) ; a != a_end ; ++a) { - if (! _already_ordered(a->comes_after())) + if (_imp->to_order.end() != _imp->to_order.find(a->comes_after())) { bool skippable(false); @@ -779,18 +698,10 @@ Orderer::_can_order(const JobID & i, const bool desperate) const return true; } -bool -Orderer::_already_ordered(const JobID & i) const -{ - return _imp->already_ordered.end() != _imp->already_ordered.find(i); -} - void Orderer::_mark_already_ordered(const JobID & i) { - if (! _imp->already_ordered.insert(i).second) - throw InternalError(PALUDIS_HERE, "already already ordered"); - + _imp->to_order.erase(i); _imp->env->trigger_notifier_callback(NotifierCallbackResolverStepEvent()); } diff --git a/paludis/resolver/orderer.hh b/paludis/resolver/orderer.hh index 313d19df1..12523c607 100644 --- a/paludis/resolver/orderer.hh +++ b/paludis/resolver/orderer.hh @@ -1,7 +1,7 @@ /* vim: set sw=4 sts=4 et foldmethod=syntax : */ /* - * Copyright (c) 2009 Ciaran McCreesh + * Copyright (c) 2009, 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 @@ -48,11 +48,10 @@ namespace paludis void _resolve_jobs_dep_arrows(); void _resolve_order(); - bool _already_ordered(const JobID &) const PALUDIS_ATTRIBUTE((warn_unused_result)); bool _can_order(const JobID &, const bool desperate) const PALUDIS_ATTRIBUTE((warn_unused_result)); void _mark_already_ordered(const JobID &); + void _order_this(const JobID &, const bool inside_something_else); - bool _anything_left_to_order() const PALUDIS_ATTRIBUTE((warn_unused_result)); bool _order_some(const bool desperate, const bool installs_only) PALUDIS_ATTRIBUTE((warn_unused_result)); bool _remove_usable_cycles() PALUDIS_ATTRIBUTE((warn_unused_result)); void _cycle_error() PALUDIS_ATTRIBUTE((noreturn)); diff --git a/paludis/resolver/resolver.cc b/paludis/resolver/resolver.cc index 23034e9e9..4876cbbd1 100644 --- a/paludis/resolver/resolver.cc +++ b/paludis/resolver/resolver.cc @@ -1,7 +1,7 @@ /* vim: set sw=4 sts=4 et foldmethod=syntax : */ /* - * Copyright (c) 2009 Ciaran McCreesh + * Copyright (c) 2009, 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 @@ -61,10 +61,10 @@ namespace paludis fns(f), lists(new ResolverLists(make_named_values<ResolverLists>( 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::taken_error_job_ids>(make_shared_ptr(new JobIDSequence)), + value_for<n::taken_job_ids>(make_shared_ptr(new JobIDSequence)), + value_for<n::untaken_error_job_ids>(make_shared_ptr(new JobIDSequence)), value_for<n::untaken_job_ids>(make_shared_ptr(new JobIDSequence)) ))), decider(new Decider(e, f, lists)), diff --git a/paludis/resolver/resolver_TEST_any.cc b/paludis/resolver/resolver_TEST_any.cc index 5b55b6f9c..18c8c284d 100644 --- a/paludis/resolver/resolver_TEST_any.cc +++ b/paludis/resolver/resolver_TEST_any.cc @@ -1,7 +1,7 @@ /* vim: set sw=4 sts=4 et foldmethod=syntax : */ /* - * Copyright (c) 2009 Ciaran McCreesh + * Copyright (c) 2009, 2010 Ciaran McCreesh * Copyright (c) 2009 David Leverton * * This file is part of the Paludis package manager. Paludis is free software; @@ -76,15 +76,23 @@ namespace test_cases std::tr1::shared_ptr<const ResolverLists> resolutions(get_resolutions("test/target")); { - TestMessageSuffix s("errors"); - check_resolution_list(resolutions->jobs(), resolutions->error_resolutions(), ResolutionListChecks() + TestMessageSuffix s("taken errors"); + check_resolution_list(resolutions->jobs(), resolutions->taken_error_job_ids(), ResolutionListChecks() .finished() ); } { + TestMessageSuffix s("untaken errors"); + check_resolution_list(resolutions->jobs(), resolutions->untaken_error_job_ids(), ResolutionListChecks() + .finished() + ); + } + + + { TestMessageSuffix s("ordered"); - check_resolution_list(resolutions->jobs(), resolutions->ordered_job_ids(), ResolutionListChecks() + check_resolution_list(resolutions->jobs(), resolutions->taken_job_ids(), ResolutionListChecks() .qpn(QualifiedPackageName("test/target")) .finished() ); @@ -103,15 +111,22 @@ namespace test_cases std::tr1::shared_ptr<const ResolverLists> resolutions(get_resolutions("test/target")); { - TestMessageSuffix s("errors"); - check_resolution_list(resolutions->jobs(), resolutions->error_resolutions(), ResolutionListChecks() + TestMessageSuffix s("taken errors"); + check_resolution_list(resolutions->jobs(), resolutions->taken_error_job_ids(), ResolutionListChecks() + .finished() + ); + } + + { + TestMessageSuffix s("untaken errors"); + check_resolution_list(resolutions->jobs(), resolutions->untaken_error_job_ids(), ResolutionListChecks() .finished() ); } { TestMessageSuffix s("ordered"); - check_resolution_list(resolutions->jobs(), resolutions->ordered_job_ids(), ResolutionListChecks() + check_resolution_list(resolutions->jobs(), resolutions->taken_job_ids(), ResolutionListChecks() .qpn(QualifiedPackageName("test/dep")) .qpn(QualifiedPackageName("test/target")) .finished() @@ -131,15 +146,22 @@ namespace test_cases std::tr1::shared_ptr<const ResolverLists> resolutions(get_resolutions("test/target")); { - TestMessageSuffix s("errors"); - check_resolution_list(resolutions->jobs(), resolutions->error_resolutions(), ResolutionListChecks() + TestMessageSuffix s("taken errors"); + check_resolution_list(resolutions->jobs(), resolutions->taken_error_job_ids(), ResolutionListChecks() + .finished() + ); + } + + { + TestMessageSuffix s("untaken errors"); + check_resolution_list(resolutions->jobs(), resolutions->untaken_error_job_ids(), ResolutionListChecks() .finished() ); } { TestMessageSuffix s("ordered"); - check_resolution_list(resolutions->jobs(), resolutions->ordered_job_ids(), ResolutionListChecks() + check_resolution_list(resolutions->jobs(), resolutions->taken_job_ids(), ResolutionListChecks() .qpn(QualifiedPackageName("test/target")) .finished() ); diff --git a/paludis/resolver/resolver_TEST_blockers.cc b/paludis/resolver/resolver_TEST_blockers.cc index 28ab165f2..758618c22 100644 --- a/paludis/resolver/resolver_TEST_blockers.cc +++ b/paludis/resolver/resolver_TEST_blockers.cc @@ -1,7 +1,7 @@ /* vim: set sw=4 sts=4 et foldmethod=syntax : */ /* - * Copyright (c) 2009 Ciaran McCreesh + * Copyright (c) 2009, 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 @@ -78,15 +78,22 @@ namespace test_cases std::tr1::shared_ptr<const ResolverLists> resolutions(get_resolutions("hard/target")); { - TestMessageSuffix s("errors"); - check_resolution_list(resolutions->jobs(), resolutions->error_resolutions(), ResolutionListChecks() + TestMessageSuffix s("taken errors"); + check_resolution_list(resolutions->jobs(), resolutions->taken_error_job_ids(), ResolutionListChecks() + .finished() + ); + } + + { + TestMessageSuffix s("untaken errors"); + check_resolution_list(resolutions->jobs(), resolutions->untaken_error_job_ids(), ResolutionListChecks() .finished() ); } { TestMessageSuffix s("ordered"); - check_resolution_list(resolutions->jobs(), resolutions->ordered_job_ids(), ResolutionListChecks() + check_resolution_list(resolutions->jobs(), resolutions->taken_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 index ced07c8ca..71ba3eb86 100644 --- a/paludis/resolver/resolver_TEST_cycles.cc +++ b/paludis/resolver/resolver_TEST_cycles.cc @@ -1,7 +1,7 @@ /* vim: set sw=4 sts=4 et foldmethod=syntax : */ /* - * Copyright (c) 2009 Ciaran McCreesh + * Copyright (c) 2009, 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 @@ -95,15 +95,22 @@ namespace test_cases std::tr1::shared_ptr<const ResolverLists> resolutions(get_resolutions("no-changes/target")); { - TestMessageSuffix s("errors"); - check_resolution_list(resolutions->jobs(), resolutions->error_resolutions(), ResolutionListChecks() + TestMessageSuffix s("taken errors"); + check_resolution_list(resolutions->jobs(), resolutions->taken_error_job_ids(), ResolutionListChecks() + .finished() + ); + } + + { + TestMessageSuffix s("untaken errors"); + check_resolution_list(resolutions->jobs(), resolutions->untaken_error_job_ids(), ResolutionListChecks() .finished() ); } { TestMessageSuffix s("ordered"); - check_resolution_list(resolutions->jobs(), resolutions->ordered_job_ids(), ResolutionListChecks() + check_resolution_list(resolutions->jobs(), resolutions->taken_job_ids(), ResolutionListChecks() .qpn(QualifiedPackageName("no-changes/target")) .finished() ); @@ -122,15 +129,22 @@ namespace test_cases std::tr1::shared_ptr<const ResolverLists> resolutions(get_resolutions("existing-usable/target")); { - TestMessageSuffix s("errors"); - check_resolution_list(resolutions->jobs(), resolutions->error_resolutions(), ResolutionListChecks() + TestMessageSuffix s("taken errors"); + check_resolution_list(resolutions->jobs(), resolutions->taken_error_job_ids(), ResolutionListChecks() + .finished() + ); + } + + { + TestMessageSuffix s("untaken errors"); + check_resolution_list(resolutions->jobs(), resolutions->untaken_error_job_ids(), ResolutionListChecks() .finished() ); } { TestMessageSuffix s("ordered"); - check_resolution_list(resolutions->jobs(), resolutions->ordered_job_ids(), ResolutionListChecks() + check_resolution_list(resolutions->jobs(), resolutions->taken_job_ids(), ResolutionListChecks() .qpn(QualifiedPackageName("existing-usable/target")) .qpn(QualifiedPackageName("existing-usable/dep")) .finished() @@ -148,15 +162,22 @@ namespace test_cases std::tr1::shared_ptr<const ResolverLists> resolutions(get_resolutions("mutual-run-deps/target")); { - TestMessageSuffix s("errors"); - check_resolution_list(resolutions->jobs(), resolutions->error_resolutions(), ResolutionListChecks() + TestMessageSuffix s("taken errors"); + check_resolution_list(resolutions->jobs(), resolutions->taken_error_job_ids(), ResolutionListChecks() + .finished() + ); + } + + { + TestMessageSuffix s("untaken errors"); + check_resolution_list(resolutions->jobs(), resolutions->untaken_error_job_ids(), ResolutionListChecks() .finished() ); } { TestMessageSuffix s("ordered"); - check_resolution_list(resolutions->jobs(), resolutions->ordered_job_ids(), ResolutionListChecks() + check_resolution_list(resolutions->jobs(), resolutions->taken_job_ids(), ResolutionListChecks() .qpn(QualifiedPackageName("mutual-run-deps/dep-a")) .qpn(QualifiedPackageName("mutual-run-deps/dep-b")) .qpn(QualifiedPackageName("mutual-run-deps/dep-c")) diff --git a/paludis/resolver/resolver_TEST_serialisation.cc b/paludis/resolver/resolver_TEST_serialisation.cc index 44cc27381..be037b9c7 100644 --- a/paludis/resolver/resolver_TEST_serialisation.cc +++ b/paludis/resolver/resolver_TEST_serialisation.cc @@ -1,7 +1,7 @@ /* vim: set sw=4 sts=4 et foldmethod=syntax : */ /* - * Copyright (c) 2009 Ciaran McCreesh + * Copyright (c) 2009, 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 @@ -89,16 +89,23 @@ namespace test_cases } { - TestMessageSuffix s("errors"); - check_resolution_list(resolutions->jobs(), resolutions->error_resolutions(), ResolutionListChecks() + TestMessageSuffix s("taken errors"); + check_resolution_list(resolutions->jobs(), resolutions->taken_error_job_ids(), ResolutionListChecks() .kind("unable_to_make_decision", QualifiedPackageName("serialisation/error")) .finished() ); } { + TestMessageSuffix s("untaken errors"); + check_resolution_list(resolutions->jobs(), resolutions->untaken_error_job_ids(), ResolutionListChecks() + .finished() + ); + } + + { TestMessageSuffix s("ordered"); - check_resolution_list(resolutions->jobs(), resolutions->ordered_job_ids(), ResolutionListChecks() + check_resolution_list(resolutions->jobs(), resolutions->taken_job_ids(), ResolutionListChecks() .qpn(QualifiedPackageName("serialisation/dep")) .qpn(QualifiedPackageName("serialisation/target")) .finished() diff --git a/paludis/resolver/resolver_TEST_simple.cc b/paludis/resolver/resolver_TEST_simple.cc index 9e50b7eb4..81bfea050 100644 --- a/paludis/resolver/resolver_TEST_simple.cc +++ b/paludis/resolver/resolver_TEST_simple.cc @@ -1,7 +1,7 @@ /* vim: set sw=4 sts=4 et foldmethod=syntax : */ /* - * Copyright (c) 2009 Ciaran McCreesh + * Copyright (c) 2009, 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 @@ -75,15 +75,23 @@ namespace test_cases std::tr1::shared_ptr<const ResolverLists> resolutions(get_resolutions("no-deps/target")); { - TestMessageSuffix s("errors"); - check_resolution_list(resolutions->jobs(), resolutions->error_resolutions(), ResolutionListChecks() + TestMessageSuffix s("taken errors"); + check_resolution_list(resolutions->jobs(), resolutions->taken_error_job_ids(), ResolutionListChecks() .finished() ); } { + TestMessageSuffix s("untaken errors"); + check_resolution_list(resolutions->jobs(), resolutions->untaken_error_job_ids(), ResolutionListChecks() + .finished() + ); + } + + + { TestMessageSuffix s("ordered"); - check_resolution_list(resolutions->jobs(), resolutions->ordered_job_ids(), ResolutionListChecks() + check_resolution_list(resolutions->jobs(), resolutions->taken_job_ids(), ResolutionListChecks() .qpn(QualifiedPackageName("no-deps/target")) .finished() ); @@ -100,15 +108,23 @@ namespace test_cases std::tr1::shared_ptr<const ResolverLists> resolutions(get_resolutions("build-deps/target")); { - TestMessageSuffix s("errors"); - check_resolution_list(resolutions->jobs(), resolutions->error_resolutions(), ResolutionListChecks() + TestMessageSuffix s("taken errors"); + check_resolution_list(resolutions->jobs(), resolutions->taken_error_job_ids(), ResolutionListChecks() .finished() ); } { + TestMessageSuffix s("untaken errors"); + check_resolution_list(resolutions->jobs(), resolutions->untaken_error_job_ids(), ResolutionListChecks() + .finished() + ); + } + + + { TestMessageSuffix s("ordered"); - check_resolution_list(resolutions->jobs(), resolutions->ordered_job_ids(), ResolutionListChecks() + check_resolution_list(resolutions->jobs(), resolutions->taken_job_ids(), ResolutionListChecks() .qpn(QualifiedPackageName("build-deps/a-dep")) .qpn(QualifiedPackageName("build-deps/b-dep")) .qpn(QualifiedPackageName("build-deps/z-dep")) diff --git a/paludis/resolver/resolver_TEST_suggestions.cc b/paludis/resolver/resolver_TEST_suggestions.cc index 92080e68f..7810b1fd8 100644 --- a/paludis/resolver/resolver_TEST_suggestions.cc +++ b/paludis/resolver/resolver_TEST_suggestions.cc @@ -1,7 +1,7 @@ /* vim: set sw=4 sts=4 et foldmethod=syntax : */ /* - * Copyright (c) 2009 Ciaran McCreesh + * Copyright (c) 2009, 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 @@ -75,15 +75,23 @@ namespace test_cases std::tr1::shared_ptr<const ResolverLists> resolutions(get_resolutions("suggestion/target")); { - TestMessageSuffix s("errors"); - check_resolution_list(resolutions->jobs(), resolutions->error_resolutions(), ResolutionListChecks() + TestMessageSuffix s("taken errors"); + check_resolution_list(resolutions->jobs(), resolutions->taken_error_job_ids(), ResolutionListChecks() .finished() ); } { + TestMessageSuffix s("untaken errors"); + check_resolution_list(resolutions->jobs(), resolutions->untaken_error_job_ids(), ResolutionListChecks() + .finished() + ); + } + + + { TestMessageSuffix s("ordered"); - check_resolution_list(resolutions->jobs(), resolutions->ordered_job_ids(), ResolutionListChecks() + check_resolution_list(resolutions->jobs(), resolutions->taken_job_ids(), ResolutionListChecks() .qpn(QualifiedPackageName("suggestion/target")) .finished() ); @@ -108,15 +116,23 @@ namespace test_cases std::tr1::shared_ptr<const ResolverLists> resolutions(get_resolutions("unmeetable-suggestion/target")); { - TestMessageSuffix s("errors"); - check_resolution_list(resolutions->jobs(), resolutions->error_resolutions(), ResolutionListChecks() + TestMessageSuffix s("taken errors"); + check_resolution_list(resolutions->jobs(), resolutions->taken_error_job_ids(), ResolutionListChecks() + .finished() + ); + } + + { + TestMessageSuffix s("untaken errors"); + check_resolution_list(resolutions->jobs(), resolutions->untaken_error_job_ids(), ResolutionListChecks() .finished() ); } + { TestMessageSuffix s("ordered"); - check_resolution_list(resolutions->jobs(), resolutions->ordered_job_ids(), ResolutionListChecks() + check_resolution_list(resolutions->jobs(), resolutions->taken_job_ids(), ResolutionListChecks() .qpn(QualifiedPackageName("unmeetable-suggestion/target")) .finished() ); @@ -141,15 +157,23 @@ namespace test_cases std::tr1::shared_ptr<const ResolverLists> resolutions(get_resolutions("suggestion-then-dependency/target")); { - TestMessageSuffix s("errors"); - check_resolution_list(resolutions->jobs(), resolutions->error_resolutions(), ResolutionListChecks() + TestMessageSuffix s("taken errors"); + check_resolution_list(resolutions->jobs(), resolutions->taken_error_job_ids(), ResolutionListChecks() .finished() ); } { + TestMessageSuffix s("untaken errors"); + check_resolution_list(resolutions->jobs(), resolutions->untaken_error_job_ids(), ResolutionListChecks() + .finished() + ); + } + + + { TestMessageSuffix s("ordered"); - check_resolution_list(resolutions->jobs(), resolutions->ordered_job_ids(), ResolutionListChecks() + check_resolution_list(resolutions->jobs(), resolutions->taken_job_ids(), ResolutionListChecks() .qpn(QualifiedPackageName("suggestion-then-dependency/a-suggested-dep")) .qpn(QualifiedPackageName("suggestion-then-dependency/hard-dep")) .qpn(QualifiedPackageName("suggestion-then-dependency/target")) diff --git a/paludis/resolver/resolver_TEST_virtuals.cc b/paludis/resolver/resolver_TEST_virtuals.cc index c2333fc72..53385b4a7 100644 --- a/paludis/resolver/resolver_TEST_virtuals.cc +++ b/paludis/resolver/resolver_TEST_virtuals.cc @@ -1,7 +1,7 @@ /* vim: set sw=4 sts=4 et foldmethod=syntax : */ /* - * Copyright (c) 2009 Ciaran McCreesh + * Copyright (c) 2009, 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 @@ -75,15 +75,22 @@ namespace test_cases std::tr1::shared_ptr<const ResolverLists> resolutions(get_resolutions("virtuals/target")); { - TestMessageSuffix s("errors"); - check_resolution_list(resolutions->jobs(), resolutions->error_resolutions(), ResolutionListChecks() + TestMessageSuffix s("taken errors"); + check_resolution_list(resolutions->jobs(), resolutions->taken_error_job_ids(), ResolutionListChecks() + .finished() + ); + } + + { + TestMessageSuffix s("untaken errors"); + check_resolution_list(resolutions->jobs(), resolutions->untaken_error_job_ids(), ResolutionListChecks() .finished() ); } { TestMessageSuffix s("ordered"); - check_resolution_list(resolutions->jobs(), resolutions->ordered_job_ids(), ResolutionListChecks() + check_resolution_list(resolutions->jobs(), resolutions->taken_job_ids(), ResolutionListChecks() .qpn(QualifiedPackageName("cat/foo-a")) .qpn(QualifiedPackageName("virtuals/target")) .finished() @@ -108,15 +115,22 @@ namespace test_cases std::tr1::shared_ptr<const ResolverLists> resolutions(get_resolutions("virtual/virtual-target")); { - TestMessageSuffix s("errors"); - check_resolution_list(resolutions->jobs(), resolutions->error_resolutions(), ResolutionListChecks() + TestMessageSuffix s("taken errors"); + check_resolution_list(resolutions->jobs(), resolutions->taken_error_job_ids(), ResolutionListChecks() + .finished() + ); + } + + { + TestMessageSuffix s("untaken errors"); + check_resolution_list(resolutions->jobs(), resolutions->untaken_error_job_ids(), ResolutionListChecks() .finished() ); } { TestMessageSuffix s("ordered"); - check_resolution_list(resolutions->jobs(), resolutions->ordered_job_ids(), ResolutionListChecks() + check_resolution_list(resolutions->jobs(), resolutions->taken_job_ids(), ResolutionListChecks() .qpn(QualifiedPackageName("cat/real-target")) .finished() ); diff --git a/paludis/resolver/resolver_lists.cc b/paludis/resolver/resolver_lists.cc index 40892efc1..80f095dfb 100644 --- a/paludis/resolver/resolver_lists.cc +++ b/paludis/resolver/resolver_lists.cc @@ -1,7 +1,7 @@ /* vim: set sw=4 sts=4 et foldmethod=syntax : */ /* - * Copyright (c) 2009 Ciaran McCreesh + * Copyright (c) 2009, 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 @@ -34,10 +34,10 @@ 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>(), "taken_error_job_ids", taken_error_job_ids()) + .member(SerialiserFlags<serialise::container, serialise::might_be_null>(), "taken_job_ids", taken_job_ids()) + .member(SerialiserFlags<serialise::container, serialise::might_be_null>(), "untaken_error_job_ids", untaken_error_job_ids()) .member(SerialiserFlags<serialise::container, serialise::might_be_null>(), "untaken_job_ids", untaken_job_ids()) ; } @@ -47,18 +47,25 @@ ResolverLists::deserialise(Deserialisation & d) { Deserialisator v(d, "ResolverLists"); - std::tr1::shared_ptr<JobIDSequence> ordered_job_ids(new JobIDSequence); + std::tr1::shared_ptr<JobIDSequence> taken_error_job_ids(new JobIDSequence); { - Deserialisator vv(*v.find_remove_member("ordered_job_ids"), "c"); + Deserialisator vv(*v.find_remove_member("taken_error_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))); + taken_error_job_ids->push_back(vv.member<JobID>(stringify(n))); } - std::tr1::shared_ptr<JobIDSequence> unordered_job_ids(new JobIDSequence); + std::tr1::shared_ptr<JobIDSequence> taken_job_ids(new JobIDSequence); { - Deserialisator vv(*v.find_remove_member("unordered_job_ids"), "c"); + Deserialisator vv(*v.find_remove_member("taken_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))); + taken_job_ids->push_back(vv.member<JobID>(stringify(n))); + } + + std::tr1::shared_ptr<JobIDSequence> untaken_error_job_ids(new JobIDSequence); + { + Deserialisator vv(*v.find_remove_member("untaken_error_job_ids"), "c"); + for (int n(1), n_end(vv.member<int>("count") + 1) ; n != n_end ; ++n) + untaken_error_job_ids->push_back(vv.member<JobID>(stringify(n))); } std::tr1::shared_ptr<JobIDSequence> untaken_job_ids(new JobIDSequence); @@ -70,10 +77,10 @@ ResolverLists::deserialise(Deserialisation & d) 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::taken_error_job_ids>(taken_error_job_ids), + value_for<n::taken_job_ids>(taken_job_ids), + value_for<n::untaken_error_job_ids>(untaken_error_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 index 184d6f5da..4c704fc79 100644 --- a/paludis/resolver/resolver_lists.hh +++ b/paludis/resolver/resolver_lists.hh @@ -1,7 +1,7 @@ /* vim: set sw=4 sts=4 et foldmethod=syntax : */ /* - * Copyright (c) 2009 Ciaran McCreesh + * Copyright (c) 2009, 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 @@ -33,10 +33,10 @@ namespace paludis namespace n { struct all_resolutions; - struct error_resolutions; struct jobs; - struct ordered_job_ids; - struct unordered_job_ids; + struct taken_error_job_ids; + struct taken_job_ids; + struct untaken_error_job_ids; struct untaken_job_ids; } @@ -45,10 +45,10 @@ namespace paludis 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::taken_error_job_ids, std::tr1::shared_ptr<JobIDSequence> > taken_error_job_ids; + NamedValue<n::taken_job_ids, std::tr1::shared_ptr<JobIDSequence> > taken_job_ids; + NamedValue<n::untaken_error_job_ids, std::tr1::shared_ptr<JobIDSequence> > untaken_error_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)); diff --git a/paludis/resolver/resolver_test.cc b/paludis/resolver/resolver_test.cc index de0310771..72b45f562 100644 --- a/paludis/resolver/resolver_test.cc +++ b/paludis/resolver/resolver_test.cc @@ -1,7 +1,7 @@ /* vim: set sw=4 sts=4 et foldmethod=syntax : */ /* - * Copyright (c) 2009 Ciaran McCreesh + * Copyright (c) 2009, 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 @@ -513,22 +513,17 @@ namespace return make_null_shared_ptr(); } - std::tr1::shared_ptr<const Resolution> visit(const FetchJob &) const - { - return make_null_shared_ptr(); - } - - std::tr1::shared_ptr<const Resolution> visit(const PretendJob &) const + std::tr1::shared_ptr<const Resolution> visit(const UsableGroupJob &) const { return make_null_shared_ptr(); } - std::tr1::shared_ptr<const Resolution> visit(const SyncPointJob &) const + std::tr1::shared_ptr<const Resolution> visit(const FetchJob &) const { return make_null_shared_ptr(); } - std::tr1::shared_ptr<const Resolution> visit(const UntakenInstallJob & j) const + std::tr1::shared_ptr<const Resolution> visit(const ErrorJob & j) const { return j.resolution(); } diff --git a/src/clients/cave/cmd_display_resolution.cc b/src/clients/cave/cmd_display_resolution.cc index cc1d8b044..a8c5dc35e 100644 --- a/src/clients/cave/cmd_display_resolution.cc +++ b/src/clients/cave/cmd_display_resolution.cc @@ -210,26 +210,27 @@ namespace } } - void display_one_constraint(const Constraint & c) + const std::string constraint_as_string(const Constraint & c) { - cout << c.spec(); + std::stringstream result; + result << c.spec(); switch (c.use_existing()) { case ue_if_same: - cout << ", use existing if same"; + result << ", use existing if same"; break; case ue_never: - cout << ", never using existing"; + result << ", never using existing"; break; case ue_only_if_transient: - cout << ", using existing only if transient"; + result << ", using existing only if transient"; break; case ue_if_same_version: - cout << ", use existing if same version"; + result << ", use existing if same version"; break; case ue_if_possible: - cout << ", use existing if possible"; + result << ", use existing if possible"; break; case last_ue: @@ -239,16 +240,18 @@ namespace switch (c.destination_type()) { case dt_install_to_slash: - cout << ", installing to /"; + result << ", installing to /"; break; case dt_create_binary: - cout << ", creating a binary"; + result << ", creating a binary"; break; case last_dt: break; } + + return result.str(); } void display_explanation_constraints(const Constraints & constraints) @@ -257,9 +260,7 @@ namespace for (Constraints::ConstIterator c(constraints.begin()), c_end(constraints.end()) ; c != c_end ; ++c) { - cout << " * "; - display_one_constraint(**c); - cout << endl; + cout << " * " << constraint_as_string(**c) << endl; cout << " Because of "; ReasonNameGetter g(true); cout << (*c)->reason()->accept_returning<std::pair<std::string, bool> >(g).first; @@ -640,16 +641,19 @@ namespace m != m_end ; ++m) cout << " Masked by " << (*m)->description() << endl; + std::set<std::string> duplicates; for (Constraints::ConstIterator c(u->unmet_constraints()->begin()), c_end(u->unmet_constraints()->end()) ; c != c_end ; ++c) { - cout << " Did not meet "; - display_one_constraint(**c); - ReasonNameGetter g(false); - cout << " from " << (*c)->reason()->accept_returning<std::pair<std::string, bool> >(g).first; - cout << endl; + std::string s(constraint_as_string(**c) + " from " + + (*c)->reason()->accept_returning<std::pair<std::string, bool> >(g).first); + + if (! duplicates.insert(s).second) + continue; + + cout << " Did not meet " << s << endl; if ((*c)->spec().if_package() && (*c)->spec().if_package()->additional_requirements_ptr() && (! match_package(*env, *(*c)->spec().if_package(), *u->package_id(), MatchPackageOptions())) && @@ -670,126 +674,98 @@ namespace } } - struct DisplayOneUntakenVisitor + struct ShowJobsDisplayer { const std::tr1::shared_ptr<Environment> env; const DisplayResolutionCommandLine & cmdline; - const std::tr1::shared_ptr<const Resolution> resolution; + const ResolverLists & lists; + const bool all; - DisplayOneUntakenVisitor(const std::tr1::shared_ptr<Environment> & e, + ShowJobsDisplayer( + const std::tr1::shared_ptr<Environment> & e, const DisplayResolutionCommandLine & c, - const std::tr1::shared_ptr<const Resolution> & r) : + const ResolverLists & l, + const bool a + ) : env(e), cmdline(c), - resolution(r) + lists(l), + all(a) { } - bool visit(const NothingNoChangeDecision &) const + bool visit(const SimpleInstallJob & job) { - return false; - } - - bool visit(const ExistingNoChangeDecision &) const - { - return false; - } - - bool visit(const ChangesToMakeDecision & d) const - { - display_one_installish(env, cmdline, d, resolution); + display_one_install(env, cmdline, job); return true; } - bool visit(const UnableToMakeDecision & d) const + bool visit(const UsableJob & job, const bool indent = false) { - display_unable_to_make_decision(env, resolution, d); - return true; - } - }; - - bool display_one_untaken( - const std::tr1::shared_ptr<Environment> & env, - const DisplayResolutionCommandLine & cmdline, - const UntakenInstallJob & job) - { - return job.resolution()->decision()->accept_returning<bool>(DisplayOneUntakenVisitor( - env, cmdline, job.resolution())); - } - - struct DisplayOneJobVisitor - { - const std::tr1::shared_ptr<Environment> env; - const DisplayResolutionCommandLine & cmdline; + if (! all) + return false; - DisplayOneJobVisitor( - const std::tr1::shared_ptr<Environment> & e, - const DisplayResolutionCommandLine & c) : - env(e), - cmdline(c) - { + if (indent) + cout << " "; + cout << "- " << c::bold_normal() << job.resolution()->resolvent() << c::normal() << " now usable" << endl; + return true; } - bool visit(const PretendJob & job) const + bool visit(const UsableGroupJob & job) { - if (! cmdline.display_options.a_show_all_jobs.specified()) + if (! all) return false; - display_special_job_decision(env, cmdline, "Pretend", job.decision()->origin_id()); - + cout << "- " << c::bold_normal() << "group of jobs now usable:" << c::normal() << endl; + for (JobIDSequence::ConstIterator i(job.job_ids()->begin()), i_end(job.job_ids()->end()) ; + i != i_end ; ++i) + visit(*lists.jobs()->fetch_as<UsableJob>(*i), true); return true; } - bool visit(const FetchJob & job) const + bool visit(const FetchJob & job) { - if (! cmdline.display_options.a_show_all_jobs.specified()) + if (! all) return false; - display_special_job_decision(env, cmdline, "Fetch", job.decision()->origin_id()); - + cout << "- " << c::bold_normal() << job.resolution()->resolvent() << c::normal() << " fetch" << endl; return true; } - bool visit(const UsableJob & job) const + bool visit(const ErrorJob &) { - if (! cmdline.display_options.a_show_all_jobs.specified()) - return false; - - cout << "- Can now use " << job.resolution()->resolvent() << endl; - - return true; + return false; } + }; - bool visit(const SimpleInstallJob & job) const + struct JobNameVisitor + { + const std::string visit(const SimpleInstallJob & j) const { - display_one_install(env, cmdline, job); - return true; + return "install " + stringify(*j.decision()->origin_id()); } - bool visit(const SyncPointJob & job) const + const std::string visit(const UsableJob & j) const { - if (! cmdline.display_options.a_show_all_jobs.specified()) - return false; + return "usable " + stringify(j.resolution()->resolvent()); + } - cout << "- Sync point " << job.sync_point() << endl; + const std::string visit(const ErrorJob &) const + { + return "error"; + } - return true; + const std::string visit(const FetchJob & j) const + { + return "fetch " + stringify(*j.decision()->origin_id()); } - bool visit(const UntakenInstallJob & job) const + const std::string visit(const UsableGroupJob & j) const { - return display_one_untaken(env, cmdline, job); + return "usable (" + stringify(std::distance(j.job_ids()->begin(), j.job_ids()->end())) + ")"; } }; - bool display_one_job( - const std::tr1::shared_ptr<Environment> & env, - const DisplayResolutionCommandLine & cmdline, - const std::tr1::shared_ptr<const Job> & job) - { - return job->accept_returning<bool>(DisplayOneJobVisitor(env, cmdline)); - } - void display_jobs( const std::tr1::shared_ptr<Environment> & env, const ResolverLists & lists, @@ -799,21 +775,43 @@ namespace cout << "These are the actions I will take, in order:" << endl << endl; - bool shown_any(false); - for (JobIDSequence::ConstIterator i(lists.ordered_job_ids()->begin()), - i_end(lists.ordered_job_ids()->end()) ; + bool any(false); + for (JobIDSequence::ConstIterator i(lists.taken_job_ids()->begin()), + i_end(lists.taken_job_ids()->end()) ; i != i_end ; ++i) { const std::tr1::shared_ptr<const Job> job(lists.jobs()->fetch(*i)); - shown_any |= display_one_job(env, cmdline, job); + ShowJobsDisplayer d(env, cmdline, lists, cmdline.display_options.a_show_all_jobs.specified() || + ! job->used_existing_packages_when_ordering()->empty()); + any |= job->accept_returning<bool>(d); + + if (! job->used_existing_packages_when_ordering()->empty()) + { + std::set<std::string> missing; + for (JobIDSequence::ConstIterator j(job->used_existing_packages_when_ordering()->begin()), + j_end(job->used_existing_packages_when_ordering()->end()) ; + j != j_end ; ++j) + missing.insert(lists.jobs()->fetch(*j)->accept_returning<std::string>(JobNameVisitor())); + cout << " " << c::bold_normal() << "Couldn't do before: " << c::normal() + << join(missing.begin(), missing.end(), ", ") << endl; + } } - if (! shown_any) + if (! any) cout << "(nothing to do)" << endl; cout << endl; } + void display_one_error( + const std::tr1::shared_ptr<Environment> & env, + const DisplayResolutionCommandLine &, + const std::tr1::shared_ptr<const Resolution> & resolution, + const ErrorJob & j) + { + display_unable_to_make_decision(env, resolution, *j.decision()); + } + void display_untaken( const std::tr1::shared_ptr<Environment> & env, const ResolverLists & lists, @@ -821,7 +819,7 @@ namespace { Context context("When displaying untaken jobs:"); - if (lists.untaken_job_ids()->empty()) + if (lists.untaken_job_ids()->empty() && lists.untaken_error_job_ids()->empty()) return; cout << "I did not take the following:" << endl << endl; @@ -830,55 +828,19 @@ namespace i_end(lists.untaken_job_ids()->end()) ; i != i_end ; ++i) { - const std::tr1::shared_ptr<const Job> job(lists.jobs()->fetch(*i)); - if (! display_one_job(env, cmdline, job)) - throw InternalError(PALUDIS_HERE, "who put something icky on the untaken list?"); - } - - cout << endl; - } - - struct DisplayOneDecisionVisitor - { - const std::tr1::shared_ptr<Environment> env; - const std::tr1::shared_ptr<const Resolution> resolution; - - DisplayOneDecisionVisitor( - const std::tr1::shared_ptr<Environment> & e, - const std::tr1::shared_ptr<const Resolution> & r) : - env(e), - resolution(r) - { + const std::tr1::shared_ptr<const SimpleInstallJob> job(lists.jobs()->fetch_as<SimpleInstallJob>(*i)); + display_one_install(env, cmdline, *job); } - void visit(const NothingNoChangeDecision &) const PALUDIS_ATTRIBUTE((noreturn)) - { - throw InternalError(PALUDIS_HERE, "nothing no change?"); - } - - void visit(const ExistingNoChangeDecision &) const PALUDIS_ATTRIBUTE((noreturn)) - { - throw InternalError(PALUDIS_HERE, "existing no change?"); - } - - void visit(const ChangesToMakeDecision &) const PALUDIS_ATTRIBUTE((noreturn)) - { - throw InternalError(PALUDIS_HERE, "changes to make?"); - } - - void visit(const UnableToMakeDecision & d) const + for (JobIDSequence::ConstIterator i(lists.untaken_error_job_ids()->begin()), + i_end(lists.untaken_error_job_ids()->end()) ; + i != i_end ; ++i) { - display_unable_to_make_decision(env, resolution, d); + const std::tr1::shared_ptr<const ErrorJob> job(lists.jobs()->fetch_as<ErrorJob>(*i)); + display_one_error(env, cmdline, job->resolution(), *job); } - }; - void display_one_decision( - const std::tr1::shared_ptr<Environment> & env, - const DisplayResolutionCommandLine &, - const std::tr1::shared_ptr<const Resolution> & resolution, - const Decision & decision) - { - decision.accept(DisplayOneDecisionVisitor(env, resolution)); + cout << endl; } void display_errors( @@ -888,15 +850,18 @@ namespace { Context context("When displaying errors:"); - if (lists.error_resolutions()->empty()) + if (lists.taken_error_job_ids()->empty()) return; cout << "I encountered the following errors:" << endl << endl; - for (Resolutions::ConstIterator r(lists.error_resolutions()->begin()), - r_end(lists.error_resolutions()->end()) ; - r != r_end ; ++r) - display_one_decision(env, cmdline, *r, *(*r)->decision()); + for (JobIDSequence::ConstIterator i(lists.taken_error_job_ids()->begin()), + i_end(lists.taken_error_job_ids()->end()) ; + i != i_end ; ++i) + { + const std::tr1::shared_ptr<const ErrorJob> job(lists.jobs()->fetch_as<ErrorJob>(*i)); + display_one_error(env, cmdline, job->resolution(), *job); + } cout << endl; } @@ -928,17 +893,20 @@ DisplayResolutionCommand::run( cmdline.import_options.apply(env); - int fd(destringify<int>(getenv_with_default("PALUDIS_SERIALISED_RESOLUTION_FD", ""))); - SafeIFStream deser_stream(fd); - const std::string deser_str((std::istreambuf_iterator<char>(deser_stream)), std::istreambuf_iterator<char>()); - Deserialiser deserialiser(env.get(), deser_str); - Deserialisation deserialisation("ResolverLists", deserialiser); - ResolverLists lists(ResolverLists::deserialise(deserialisation)); - - display_jobs(env, lists, cmdline); - display_untaken(env, lists, cmdline); - display_errors(env, lists, cmdline); - display_explanations(env, lists, cmdline); + std::tr1::shared_ptr<ResolverLists> lists; + { + int fd(destringify<int>(getenv_with_default("PALUDIS_SERIALISED_RESOLUTION_FD", ""))); + SafeIFStream deser_stream(fd); + const std::string deser_str((std::istreambuf_iterator<char>(deser_stream)), std::istreambuf_iterator<char>()); + Deserialiser deserialiser(env.get(), deser_str); + Deserialisation deserialisation("ResolverLists", deserialiser); + lists = make_shared_copy(ResolverLists::deserialise(deserialisation)); + } + + display_jobs(env, *lists, cmdline); + display_untaken(env, *lists, cmdline); + display_errors(env, *lists, cmdline); + display_explanations(env, *lists, cmdline); return 0; } diff --git a/src/clients/cave/cmd_execute_resolution.cc b/src/clients/cave/cmd_execute_resolution.cc index e25c3f69d..8365a7ffb 100644 --- a/src/clients/cave/cmd_execute_resolution.cc +++ b/src/clients/cave/cmd_execute_resolution.cc @@ -33,7 +33,11 @@ #include <paludis/util/iterator_funcs.hh> #include <paludis/util/options.hh> #include <paludis/util/simple_visitor_cast.hh> +#include <paludis/util/simple_visitor-impl.hh> #include <paludis/util/make_named_values.hh> +#include <paludis/util/make_shared_copy.hh> +#include <paludis/util/hashes.hh> +#include <paludis/util/type_list.hh> #include <paludis/resolver/resolutions.hh> #include <paludis/resolver/reason.hh> #include <paludis/resolver/sanitised_dependencies.hh> @@ -47,6 +51,8 @@ #include <paludis/resolver/jobs.hh> #include <paludis/resolver/job.hh> #include <paludis/resolver/job_id.hh> +#include <paludis/resolver/job_state.hh> +#include <paludis/resolver/arrow.hh> #include <paludis/package_id.hh> #include <paludis/version_spec.hh> #include <paludis/metadata_key.hh> @@ -66,6 +72,7 @@ #include <list> #include <cstdlib> #include <algorithm> +#include <tr1/unordered_map> using namespace paludis; using namespace cave; @@ -116,14 +123,12 @@ namespace } }; - typedef std::list<std::tr1::shared_ptr<OutputManager> > CompletedOutputManagers; - - int do_pretend( + bool do_pretend( const std::tr1::shared_ptr<Environment> & env, const ExecuteResolutionCommandLine & cmdline, const ChangesToMakeDecision & decision, const int x, const int y, - CompletedOutputManagers & completed_output_managers) + std::tr1::shared_ptr<OutputManager> & output_manager_goes_here) { Context context("When pretending for '" + stringify(*decision.origin_id()) + "':"); @@ -158,10 +163,10 @@ namespace if (output_manager) { output_manager->nothing_more_to_come(); - completed_output_managers.push_back(output_manager); + output_manager_goes_here = output_manager; } - return retcode; + return 0 == retcode; } void starting_action( @@ -190,12 +195,12 @@ namespace cout << endl; } - int do_fetch( + bool do_fetch( const std::tr1::shared_ptr<Environment> & env, const ExecuteResolutionCommandLine & cmdline, const ChangesToMakeDecision & decision, const int x, const int y, bool normal_only, - CompletedOutputManagers & completed_output_managers) + std::tr1::shared_ptr<OutputManager> & output_manager_goes_here) { const std::tr1::shared_ptr<const PackageID> id(decision.origin_id()); Context context("When fetching for '" + stringify(*id) + "':"); @@ -232,20 +237,20 @@ namespace if (output_manager) { output_manager->nothing_more_to_come(); - completed_output_managers.push_back(output_manager); + output_manager_goes_here = output_manager; } done_action("fetch (" + std::string(normal_only ? "regular parts" : "extra parts") + ")", decision, 0 == retcode); - return retcode; + return 0 == retcode; } - int do_install( + bool do_install( const std::tr1::shared_ptr<Environment> & env, const ExecuteResolutionCommandLine & cmdline, const std::tr1::shared_ptr<const Resolution> & resolution, const ChangesToMakeDecision & decision, const int x, const int y, - CompletedOutputManagers & completed_output_managers) + std::tr1::shared_ptr<OutputManager> & output_manager_goes_here) { std::string destination_string, action_string; switch (resolution->resolvent().destination_type()) @@ -332,20 +337,18 @@ namespace if (output_manager) { output_manager->nothing_more_to_come(); - completed_output_managers.push_back(output_manager); + output_manager_goes_here = output_manager; } done_action(action_string, decision, 0 == retcode); - return retcode; + return 0 == retcode; } struct JobCounts { - int x_pretends, y_pretends, x_fetches, y_fetches, x_installs, y_installs; + int x_fetches, y_fetches, x_installs, y_installs; JobCounts() : - x_pretends(0), - y_pretends(0), x_fetches(0), y_fetches(0), x_installs(0), @@ -353,11 +356,6 @@ namespace { } - void visit(const PretendJob &) - { - ++y_pretends; - } - void visit(const SimpleInstallJob &) { ++y_installs; @@ -372,153 +370,367 @@ namespace { } - void visit(const SyncPointJob &) + void visit(const UsableGroupJob &) { } - void visit(const UntakenInstallJob &) + void visit(const ErrorJob &) { } }; - struct PerformJobs + typedef std::tr1::unordered_map<JobID, std::tr1::shared_ptr<JobState>, Hash<JobID> > JobStateMap; + typedef std::list<std::tr1::shared_ptr<JobPendingState> > PendingJobsList; + + struct DoOneTakenVisitor { const std::tr1::shared_ptr<Environment> env; const ExecuteResolutionCommandLine & cmdline; JobCounts & counts; - CompletedOutputManagers & completed_output_managers; + std::tr1::shared_ptr<JobState> & state; + JobStateMap & job_state_map; - bool done_any_pretends; - bool done_any_installs; - int retcode; - - PerformJobs( + DoOneTakenVisitor( const std::tr1::shared_ptr<Environment> & e, const ExecuteResolutionCommandLine & c, JobCounts & k, - CompletedOutputManagers & m) : + std::tr1::shared_ptr<JobState> & s, + JobStateMap & m) : env(e), cmdline(c), counts(k), - completed_output_managers(m), - done_any_pretends(false), - done_any_installs(false), - retcode(0) + state(s), + job_state_map(m) { } - bool visit(const PretendJob & job) + bool visit(const SimpleInstallJob & job) { - if (! done_any_pretends) + std::tr1::shared_ptr<OutputManager> fetch_output_manager_goes_here, install_output_manager_goes_here; + + ++counts.x_installs; + + /* not all of the fetch is done in the background */ + if (! do_fetch(env, cmdline, *job.decision(), counts.x_installs, counts.y_installs, + false, fetch_output_manager_goes_here)) { - done_any_pretends = true; + std::tr1::shared_ptr<JobFailedState> failed_state(new JobFailedState(state->job())); + if (fetch_output_manager_goes_here) + failed_state->add_output_manager(fetch_output_manager_goes_here); + state = failed_state; + return false; + } - 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"); + if (! do_install(env, cmdline, job.resolution(), + *job.decision(), counts.x_installs, counts.y_installs, install_output_manager_goes_here)) + { + std::tr1::shared_ptr<JobFailedState> failed_state(new JobFailedState(state->job())); + if (fetch_output_manager_goes_here) + failed_state->add_output_manager(fetch_output_manager_goes_here); + if (install_output_manager_goes_here) + failed_state->add_output_manager(install_output_manager_goes_here); + state = failed_state; + return false; + } + else + { + std::tr1::shared_ptr<JobSucceededState> succeeded_state(new JobSucceededState(state->job())); + if (fetch_output_manager_goes_here) + succeeded_state->add_output_manager(fetch_output_manager_goes_here); + if (install_output_manager_goes_here) + succeeded_state->add_output_manager(install_output_manager_goes_here); + state = succeeded_state; + return true; + } + } - std::cout << "Executing pretend actions: " << std::flush; + bool visit(const FetchJob & job) + { + std::tr1::shared_ptr<OutputManager> output_manager_goes_here; + + ++counts.x_fetches; + if (! do_fetch(env, cmdline, *job.decision(), counts.x_fetches, counts.y_fetches, + true, output_manager_goes_here)) + { + std::tr1::shared_ptr<JobFailedState> failed_state(new JobFailedState(state->job())); + if (output_manager_goes_here) + failed_state->add_output_manager(output_manager_goes_here); + state = failed_state; + return false; + } + else + { + std::tr1::shared_ptr<JobSucceededState> succeeded_state(new JobSucceededState(state->job())); + if (output_manager_goes_here) + succeeded_state->add_output_manager(output_manager_goes_here); + state = succeeded_state; + return true; } + } - retcode |= do_pretend(env, cmdline, *job.decision(), ++counts.x_pretends, counts.y_pretends, - completed_output_managers); + bool visit(const ErrorJob &) + { + state.reset(new JobFailedState(state->job())); + return false; + } - /* a pretend failing doesn't abort us yet */ + bool visit(const UsableJob &) + { + state.reset(new JobSucceededState(state->job())); return true; } - bool visit(const SimpleInstallJob & job) + bool visit(const UsableGroupJob & job) { - if (0 != retcode) - return false; + bool result(true); - if (! done_any_installs) + for (JobIDSequence::ConstIterator i(job.job_ids()->begin()), i_end(job.job_ids()->end()) ; + i != i_end ; ++i) { - done_any_installs = true; + JobStateMap::iterator s(job_state_map.find(*i)); + if (s == job_state_map.end()) + throw InternalError(PALUDIS_HERE, "missing state"); - 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"); + DoOneTakenVisitor v(env, cmdline, counts, s->second, job_state_map); + result = s->second->job()->accept_returning<bool>(v) && result; } + state.reset(new JobSucceededState(state->job())); + return result; + } + }; + + struct DoOneSkippedVisitor + { + const std::tr1::shared_ptr<Environment> env; + const ExecuteResolutionCommandLine & cmdline; + JobCounts & counts; + std::tr1::shared_ptr<JobState> & state; + JobStateMap & job_state_map; + + DoOneSkippedVisitor( + const std::tr1::shared_ptr<Environment> & e, + const ExecuteResolutionCommandLine & c, + JobCounts & k, + std::tr1::shared_ptr<JobState> & s, + JobStateMap & m) : + env(e), + cmdline(c), + counts(k), + state(s), + job_state_map(m) + { + } + + void visit(const SimpleInstallJob & job) + { ++counts.x_installs; - /* not all of the fetch is done in the background */ - retcode |= do_fetch(env, cmdline, *job.decision(), counts.x_installs, counts.y_installs, false, - completed_output_managers); - if (0 != retcode) - return false; + cout << endl; + cout << c::bold_blue() << counts.x_installs << " of " << counts.y_installs << ": Skipping install of " + << *job.decision()->origin_id() << c::normal() << endl; + cout << endl; - retcode |= do_install(env, cmdline, job.resolution(), - *job.decision(), counts.x_installs, counts.y_installs, - completed_output_managers); - if (0 != retcode) - return false; + state.reset(new JobSkippedState(state->job())); + } - return true; + void visit(const FetchJob &) + { + ++counts.x_fetches; + + state.reset(new JobSkippedState(state->job())); } - bool visit(const FetchJob & job) + void visit(const ErrorJob &) { - if (0 != retcode) - return false; + state.reset(new JobSkippedState(state->job())); + } - retcode |= do_fetch(env, cmdline, *job.decision(), ++counts.x_fetches, counts.y_fetches, true, - completed_output_managers); - if (0 != retcode) - return false; + void visit(const UsableJob &) + { + state.reset(new JobSkippedState(state->job())); + } - return true; + void visit(const UsableGroupJob & job) + { + for (JobIDSequence::ConstIterator i(job.job_ids()->begin()), i_end(job.job_ids()->end()) ; + i != i_end ; ++i) + { + JobStateMap::iterator s(job_state_map.find(*i)); + if (s == job_state_map.end()) + throw InternalError(PALUDIS_HERE, "missing state"); + + DoOneSkippedVisitor v(env, cmdline, counts, s->second, job_state_map); + s->second->job()->accept(v); + } + + state.reset(new JobSkippedState(state->job())); } + }; + + int execute_update_world( + const std::tr1::shared_ptr<Environment> & env, + const ResolverLists &, + const ExecuteResolutionCommandLine & cmdline) + { + if (cmdline.execution_options.a_preserve_world.specified()) + return 0; + + cout << endl << c::bold_green() << "Updating world" << c::normal() << endl << endl; + + std::string command(cmdline.program_options.a_update_world_program.argument()); + if (command.empty()) + command = "$CAVE update-world"; - bool visit(const SyncPointJob & job) + bool any(false); + if (cmdline.a_set.specified()) { - switch (job.sync_point()) + command.append(" --set"); + for (args::ArgsHandler::ParametersConstIterator a(cmdline.begin_parameters()), + a_end(cmdline.end_parameters()) ; + a != a_end ; ++a) { - 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; + if (*a == "world" || *a == "system" || *a == "security" + || *a == "everything" || *a == "insecurity" + || *a == "installed-packages" || *a == "installed-slots") + cout << "* Special set '" << *a << "' does not belong in world" << endl; + else + { + any = true; + cout << "* Adding '" << *a << "'" << endl; + command.append(" " + *a); + } + } + } + else + { + for (args::ArgsHandler::ParametersConstIterator a(cmdline.begin_parameters()), + a_end(cmdline.end_parameters()) ; + a != a_end ; ++a) + { + PackageDepSpec spec(parse_user_package_dep_spec(*a, env.get(), UserPackageDepSpecOptions())); + if (package_dep_spec_has_properties(spec, make_named_values<PackageDepSpecProperties>( + value_for<n::has_additional_requirements>(false), + value_for<n::has_category_name_part>(false), + value_for<n::has_from_repository>(false), + value_for<n::has_in_repository>(false), + value_for<n::has_installable_to_path>(false), + value_for<n::has_installable_to_repository>(false), + value_for<n::has_installed_at_path>(false), + value_for<n::has_package>(true), + value_for<n::has_package_name_part>(false), + value_for<n::has_slot_requirement>(false), + value_for<n::has_tag>(indeterminate), + value_for<n::has_version_requirements>(false) + ))) + { + any = true; + cout << "* Adding '" << spec << "'" << endl; + command.append(" " + stringify(spec)); + } + else + { + cout << "* Not adding '" << spec << "'" << endl; + } + } + } - case sp_done_pretends: - { - std::cout << std::endl; + if (any) + { + paludis::Command cmd(command); + if (0 != run_command(cmd)) + throw ActionAbortedError("Updating world failed"); + } - 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"); + return 0; + } - if ((0 != retcode) || (cmdline.a_pretend.specified())) - return false; - } - break; + struct Populator + { + const std::tr1::shared_ptr<const Job> job; + const ResolverLists & lists; + JobStateMap & job_state_map; + PendingJobsList * const pending; + + Populator( + const std::tr1::shared_ptr<const Job> & j, + const ResolverLists & l, + JobStateMap & s, + PendingJobsList * const p) : + job(j), + lists(l), + job_state_map(s), + pending(p) + { + } + + void common() const + { + const std::tr1::shared_ptr<JobPendingState> state(new JobPendingState(job)); + if (! job_state_map.insert(std::make_pair(job->id(), state)).second) + throw InternalError(PALUDIS_HERE, "duplicate id"); + + if (pending) + pending->push_back(state); + } + + void visit(const SimpleInstallJob &) const + { + common(); + } + + void visit(const UsableJob &) const + { + common(); + } + + void visit(const FetchJob &) const + { + common(); + } + + void visit(const ErrorJob &) const + { + common(); + } + + void visit(const UsableGroupJob & j) const + { + common(); - case last_sp: - break; + for (JobIDSequence::ConstIterator i(j.job_ids()->begin()), i_end(j.job_ids()->end()) ; + i != i_end ; ++i) + { + const std::tr1::shared_ptr<const Job> k(lists.jobs()->fetch(*i)); + k->accept(Populator(k, lists, job_state_map, 0)); } + } + }; - return true; + struct JobStateChecker + { + bool visit(const JobPendingState &) const PALUDIS_ATTRIBUTE((noreturn)) + { + throw InternalError(PALUDIS_HERE, "still pending"); } - bool visit(const UntakenInstallJob &) + bool visit(const JobFailedState &) const { - return true; + return false; } - bool visit(const UsableJob &) + bool visit(const JobSkippedState &) const + { + return false; + } + + bool visit(const JobSucceededState &) const { return true; } }; - int execute_resolution_main( + int execute_taken( const std::tr1::shared_ptr<Environment> & env, const ResolverLists & lists, const ExecuteResolutionCommandLine & cmdline) @@ -526,94 +738,191 @@ namespace int retcode(0); JobCounts counts; - CompletedOutputManagers completed_output_managers; + JobStateMap job_state_map; + PendingJobsList pending; - for (JobIDSequence::ConstIterator c(lists.ordered_job_ids()->begin()), - c_end(lists.ordered_job_ids()->end()) ; + for (JobIDSequence::ConstIterator c(lists.taken_job_ids()->begin()), + c_end(lists.taken_job_ids()->end()) ; c != c_end ; ++c) - lists.jobs()->fetch(*c)->accept(counts); - - PerformJobs perform_jobs(env, cmdline, counts, completed_output_managers); - 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; - - completed_output_managers.clear(); + { + const std::tr1::shared_ptr<const Job> job(lists.jobs()->fetch(*c)); + job->accept(counts); + job->accept(Populator(job, lists, job_state_map, &pending)); + } - retcode |= perform_jobs.retcode; - if ((0 != retcode) || (cmdline.a_pretend.specified())) - return retcode; + 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 (! cmdline.execution_options.a_preserve_world.specified()) + for (PendingJobsList::iterator p(pending.begin()), p_next(p), p_end(pending.end()) ; + p != p_end ; p = p_next) { - cout << endl << c::bold_green() << "Updating world" << c::normal() << endl << endl; - - std::string command(cmdline.program_options.a_update_world_program.argument()); - if (command.empty()) - command = "$CAVE update-world"; + ++p_next; - bool any(false); - if (cmdline.a_set.specified()) + std::tr1::shared_ptr<const Job> skipped_because_of; + for (ArrowSequence::ConstIterator a((*p)->job()->arrows()->begin()), a_end((*p)->job()->arrows()->end()) ; + a != a_end ; ++a) { - command.append(" --set"); - for (args::ArgsHandler::ParametersConstIterator a(cmdline.begin_parameters()), - a_end(cmdline.end_parameters()) ; - a != a_end ; ++a) + const std::tr1::shared_ptr<const Job> after_job(lists.jobs()->fetch(a->comes_after())); + JobStateMap::const_iterator s(job_state_map.find(after_job->id())); + if (s == job_state_map.end()) + throw InternalError(PALUDIS_HERE, "missing arrow: " + stringify(after_job->id().string_id())); + + if ((*p)->job()->used_existing_packages_when_ordering()->end() != std::find( + (*p)->job()->used_existing_packages_when_ordering()->begin(), + (*p)->job()->used_existing_packages_when_ordering()->end(), + a->comes_after())) { - if (*a == "world" || *a == "system" || *a == "security" - || *a == "everything" || *a == "insecurity" - || *a == "installed-packages" || *a == "installed-slots") - cout << "* Special set '" << *a << "' does not belong in world" << endl; - else + if (! simple_visitor_cast<const JobPendingState>(*s->second)) + throw InternalError(PALUDIS_HERE, "not pending: " + stringify((*p)->job()->id().string_id()) + " -> " + + stringify(a->comes_after().string_id()) + " " + s->second->state_name()); + } + else + { + bool ignorable(false); + + if (cmdline.execution_options.a_continue_on_failure.argument() == "if-satisfied") + ignorable = a->failure_kinds()[fk_ignorable_if_satisfied]; + else if (cmdline.execution_options.a_continue_on_failure.argument() == "always") + ignorable = true; + + if ((! ignorable) && (! s->second->accept_returning<bool>(JobStateChecker()))) { - any = true; - cout << "* Adding '" << *a << "'" << endl; - command.append(" " + *a); + skipped_because_of = after_job; + break; } } } + + JobStateMap::iterator s(job_state_map.find((*p)->job()->id())); + if (s == job_state_map.end()) + throw InternalError(PALUDIS_HERE, "missing state"); + pending.erase(p); + + if (skipped_because_of) + { + DoOneSkippedVisitor v(env, cmdline, counts, s->second, job_state_map); + s->second->job()->accept(v); + retcode |= 1; + } else { - for (args::ArgsHandler::ParametersConstIterator a(cmdline.begin_parameters()), - a_end(cmdline.end_parameters()) ; - a != a_end ; ++a) + DoOneTakenVisitor v(env, cmdline, counts, s->second, job_state_map); + if (! s->second->job()->accept_returning<bool>(v)) { - PackageDepSpec spec(parse_user_package_dep_spec(*a, env.get(), UserPackageDepSpecOptions())); - if (package_dep_spec_has_properties(spec, make_named_values<PackageDepSpecProperties>( - value_for<n::has_additional_requirements>(false), - value_for<n::has_category_name_part>(false), - value_for<n::has_from_repository>(false), - value_for<n::has_in_repository>(false), - value_for<n::has_installable_to_path>(false), - value_for<n::has_installable_to_repository>(false), - value_for<n::has_installed_at_path>(false), - value_for<n::has_package>(true), - value_for<n::has_package_name_part>(false), - value_for<n::has_slot_requirement>(false), - value_for<n::has_tag>(indeterminate), - value_for<n::has_version_requirements>(false) - ))) - { - any = true; - cout << "* Adding '" << spec << "'" << endl; - command.append(" " + stringify(spec)); - } - else - { - cout << "* Not adding '" << spec << "'" << endl; - } + retcode |= 1; + + if (cmdline.execution_options.a_continue_on_failure.argument() == "never") + break; } } + } - if (any) - { - paludis::Command cmd(command); - if (0 != run_command(cmd)) - throw ActionAbortedError("Updating world failed"); - } + 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"); + + return retcode; + } + + struct DoOnePretendVisitor + { + const std::tr1::shared_ptr<Environment> env; + const ExecuteResolutionCommandLine & cmdline; + JobCounts & counts; + + DoOnePretendVisitor( + const std::tr1::shared_ptr<Environment> & e, + const ExecuteResolutionCommandLine & c, + JobCounts & k) : + env(e), + cmdline(c), + counts(k) + { } + + bool visit(const SimpleInstallJob & c) const + { + std::tr1::shared_ptr<OutputManager> output_manager_goes_here; + return do_pretend(env, cmdline, *c.decision(), ++counts.x_installs, counts.y_installs, + output_manager_goes_here); + } + + bool visit(const ErrorJob &) const + { + return true; + } + + bool visit(const FetchJob &) const + { + return true; + } + + bool visit(const UsableJob &) const + { + return true; + } + + bool visit(const UsableGroupJob &) const + { + return true; + } + }; + + int execute_pretends( + const std::tr1::shared_ptr<Environment> & env, + const ResolverLists & lists, + const ExecuteResolutionCommandLine & cmdline) + { + bool failed(false); + JobCounts counts; + + for (JobIDSequence::ConstIterator c(lists.taken_job_ids()->begin()), + c_end(lists.taken_job_ids()->end()) ; + c != c_end ; ++c) + lists.jobs()->fetch(*c)->accept(counts); + + 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; + + for (JobIDSequence::ConstIterator c(lists.taken_job_ids()->begin()), + c_end(lists.taken_job_ids()->end()) ; + c != c_end ; ++c) + failed = failed || ! lists.jobs()->fetch(*c)->accept_returning<bool>(DoOnePretendVisitor(env, cmdline, counts)); + + cout << endl; + + 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"); + + return failed ? 1 : 0; + } + + int execute_resolution_main( + const std::tr1::shared_ptr<Environment> & env, + const ResolverLists & lists, + const ExecuteResolutionCommandLine & cmdline) + { + int retcode(0); + + retcode |= execute_pretends(env, lists, cmdline); + if (0 != retcode || cmdline.a_pretend.specified()) + return retcode; + + retcode |= execute_taken(env, lists, cmdline); + + if (0 != retcode) + return retcode; + + retcode |= execute_update_world(env, lists, cmdline); return retcode; } @@ -625,7 +934,6 @@ namespace 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()) @@ -683,14 +991,17 @@ ExecuteResolutionCommand::run( cmdline.import_options.apply(env); - int fd(destringify<int>(getenv_with_default("PALUDIS_SERIALISED_RESOLUTION_FD", ""))); - SafeIFStream deser_stream(fd); - const std::string deser_str((std::istreambuf_iterator<char>(deser_stream)), std::istreambuf_iterator<char>()); - Deserialiser deserialiser(env.get(), deser_str); - Deserialisation deserialisation("ResolverLists", deserialiser); - ResolverLists lists(ResolverLists::deserialise(deserialisation)); + std::tr1::shared_ptr<ResolverLists> lists; + { + int fd(destringify<int>(getenv_with_default("PALUDIS_SERIALISED_RESOLUTION_FD", ""))); + SafeIFStream deser_stream(fd); + const std::string deser_str((std::istreambuf_iterator<char>(deser_stream)), std::istreambuf_iterator<char>()); + Deserialiser deserialiser(env.get(), deser_str); + Deserialisation deserialisation("ResolverLists", deserialiser); + lists = make_shared_copy(ResolverLists::deserialise(deserialisation)); + } - return execute_resolution(env, lists, cmdline); + return execute_resolution(env, *lists, cmdline); } std::tr1::shared_ptr<args::ArgsHandler> @@ -699,4 +1010,3 @@ ExecuteResolutionCommand::make_doc_cmdline() return make_shared_ptr(new ExecuteResolutionCommandLine); } - diff --git a/src/clients/cave/cmd_resolve_cmdline.cc b/src/clients/cave/cmd_resolve_cmdline.cc index 3b186e639..e7954195e 100644 --- a/src/clients/cave/cmd_resolve_cmdline.cc +++ b/src/clients/cave/cmd_resolve_cmdline.cc @@ -1,7 +1,7 @@ /* vim: set sw=4 sts=4 et foldmethod=syntax : */ /* - * Copyright (c) 2009 Ciaran McCreesh + * Copyright (c) 2009, 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 @@ -88,12 +88,11 @@ ResolveCommandLineResolutionOptions::ResolveCommandLineResolutionOptions(args::A ("never", 'n', "Never") ("if-transient", 't', "Only if the installed package is transient " "(e.g. from 'importare') (default if --everything)") - ("if-same", 's', "If it is the same as the proposed replacement " - "(default if --complete)") + ("if-same", 's', "If it is the same as the proposed replacement") ("if-same-version", 'v', "If it is the same version as the proposed replacement") - ("if-possible", 'p', "If possible"), + ("if-possible", 'p', "If possible (default if --lazy)"), - "if-possible" + "if-same" ), a_reinstall_scm(&g_keep_options, "reinstall-scm", 'R', "Select whether to reinstall SCM packages that would otherwise be kept", @@ -240,12 +239,11 @@ ResolveCommandLineExecutionOptions::ResolveCommandLineExecutionOptions(args::Arg a_continue_on_failure(&g_failure_options, "continue-on-failure", '\0', "Whether to continue after an error occurs", args::EnumArg::EnumArgOptions - ("if-fetching", "Only if we are just fetching packages") ("never", "Never") ("if-satisfied", "If remaining packages' dependencies are satisfied") ("if-independent", "If remaining packages do not depend upon any failing package") ("always", "Always (dangerous)"), - "if-fetching"), + "never"), g_phase_options(this, "Phase Options", "Options controlling which phases to execute. No sanity checking " "is done, allowing you to shoot as many feet off as you desire. Phase names do not have the " @@ -352,6 +350,8 @@ ResolveCommandLineResolutionOptions::apply_shortcuts() if (a_lazy.specified()) { + if (! a_keep.specified()) + a_keep.set_argument("if-possible"); if (! a_target_slots.specified()) a_target_slots.set_argument("best"); if (! a_slots.specified()) @@ -362,8 +362,6 @@ ResolveCommandLineResolutionOptions::apply_shortcuts() if (a_complete.specified()) { - if (! a_keep.specified()) - a_keep.set_argument("if-same"); if (! a_target_slots.specified()) a_target_slots.set_argument("all"); if (! a_slots.specified()) diff --git a/src/clients/cave/resolve_common.cc b/src/clients/cave/resolve_common.cc index 363a2f366..133dc41cb 100644 --- a/src/clients/cave/resolve_common.cc +++ b/src/clients/cave/resolve_common.cc @@ -1199,7 +1199,7 @@ paludis::cave::resolve_common( retcode |= display_resolution(env, *resolver->lists(), resolution_options, display_options, program_options, keys_if_import, targets); - if (! resolver->lists()->error_resolutions()->empty()) + if (! resolver->lists()->taken_error_job_ids()->empty()) retcode |= 1; if (0 == retcode) |