aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2009-08-08 22:04:30 +0100
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2009-08-08 22:04:30 +0100
commitd64d8975ee8db10820028fd0f245565496a621ea (patch)
tree2d60f157d86455cb50497be006befe148db2a15d
parent6277a9d9eb1c576ff16e3fcba415226f37bed786 (diff)
downloadpaludis-d64d8975ee8db10820028fd0f245565496a621ea.tar.gz
paludis-d64d8975ee8db10820028fd0f245565496a621ea.tar.xz
start blockers
-rw-r--r--paludis/resolver/constraint.cc2
-rw-r--r--paludis/resolver/constraint.hh2
-rw-r--r--paludis/resolver/decision.cc9
-rw-r--r--paludis/resolver/decision.hh6
-rw-r--r--paludis/resolver/resolver.cc206
-rw-r--r--paludis/resolver/resolver.hh2
-rw-r--r--paludis/resolver/sanitised_dependencies-fwd.hh3
-rw-r--r--paludis/resolver/sanitised_dependencies.cc121
-rw-r--r--paludis/resolver/sanitised_dependencies.hh13
-rw-r--r--src/clients/cave/cmd_resolve.cc21
10 files changed, 287 insertions, 98 deletions
diff --git a/paludis/resolver/constraint.cc b/paludis/resolver/constraint.cc
index 2fb9d23..5abdc37 100644
--- a/paludis/resolver/constraint.cc
+++ b/paludis/resolver/constraint.cc
@@ -35,6 +35,8 @@ paludis::resolver::operator<< (std::ostream & s, const Constraint & c)
ss << "Constraint(base spec: " << c.base_spec();
if (c.is_blocker())
ss << "; blocker";
+ if (c.nothing_is_fine_too())
+ ss << "; nothing is fine too";
ss
<< "; use_installed: " << stringify(c.use_installed())
<< "; reason: " << (c.reason() ? stringify(*c.reason()) : "none")
diff --git a/paludis/resolver/constraint.hh b/paludis/resolver/constraint.hh
index be95f4e..6e7ac31 100644
--- a/paludis/resolver/constraint.hh
+++ b/paludis/resolver/constraint.hh
@@ -33,6 +33,7 @@ namespace paludis
{
struct base_spec;
struct is_blocker;
+ struct nothing_is_fine_too;
struct reason;
struct to_destination_slash;
struct use_installed;
@@ -44,6 +45,7 @@ namespace paludis
{
NamedValue<n::base_spec, PackageDepSpec> base_spec;
NamedValue<n::is_blocker, bool> is_blocker;
+ NamedValue<n::nothing_is_fine_too, bool> nothing_is_fine_too;
NamedValue<n::reason, std::tr1::shared_ptr<const Reason> > reason;
NamedValue<n::to_destination_slash, bool> to_destination_slash;
NamedValue<n::use_installed, UseInstalled> use_installed;
diff --git a/paludis/resolver/decision.cc b/paludis/resolver/decision.cc
index 70588af..8a0c562 100644
--- a/paludis/resolver/decision.cc
+++ b/paludis/resolver/decision.cc
@@ -28,12 +28,19 @@ paludis::resolver::operator<< (std::ostream & s, const Decision & d)
{
std::stringstream ss;
- ss << "Decision(" << *d.package_id();
+ ss << "Decision(";
+
+ if (d.if_package_id())
+ ss << *d.if_package_id();
+ else
+ ss << "(nothing)";
if (d.is_installed())
ss << ", is installed";
if (d.is_new())
ss << ", is new";
+ if (d.is_nothing())
+ ss << ", is nothing";
if (d.is_same())
ss << ", is same";
if (d.is_same_version())
diff --git a/paludis/resolver/decision.hh b/paludis/resolver/decision.hh
index 737cc87..042b4cd 100644
--- a/paludis/resolver/decision.hh
+++ b/paludis/resolver/decision.hh
@@ -28,24 +28,26 @@ namespace paludis
{
namespace n
{
+ struct if_package_id;
struct is_installed;
struct is_new;
+ struct is_nothing;
struct is_same;
struct is_same_version;
struct is_transient;
- struct package_id;
}
namespace resolver
{
struct Decision
{
+ NamedValue<n::if_package_id, std::tr1::shared_ptr<const PackageID> > if_package_id;
NamedValue<n::is_installed, bool> is_installed;
NamedValue<n::is_new, bool> is_new;
+ NamedValue<n::is_nothing, bool> is_nothing;
NamedValue<n::is_same, bool> is_same;
NamedValue<n::is_same_version, bool> is_same_version;
NamedValue<n::is_transient, bool> is_transient;
- NamedValue<n::package_id, std::tr1::shared_ptr<const PackageID> > package_id;
};
}
}
diff --git a/paludis/resolver/resolver.cc b/paludis/resolver/resolver.cc
index 89807e6..88423df 100644
--- a/paludis/resolver/resolver.cc
+++ b/paludis/resolver/resolver.cc
@@ -123,6 +123,9 @@ Resolver::_resolve_dependencies()
done = false;
_decide(i->first, i->second);
+ if (i->second->decision()->is_nothing())
+ continue;
+
_add_dependencies(i->first, i->second);
}
}
@@ -149,7 +152,7 @@ Resolver::_make_destinations_for(const QPN_S & qpn_s,
{
Context context("When finding destinations for '" + stringify(qpn_s) + "':");
- if (resolution->decision()->is_installed())
+ if (resolution->decision()->is_installed() || resolution->decision()->is_nothing())
return make_shared_ptr(new Destinations(make_named_values<Destinations>(
value_for<n::slash>(make_null_shared_ptr())
)));
@@ -175,7 +178,7 @@ Resolver::_make_slash_destination_for(const QPN_S & qpn_s,
{
Context context("When finding / destination for '" + stringify(qpn_s) + "':");
- if (! resolution->decision())
+ if ((! resolution->decision()) || (! resolution->decision()->if_package_id()))
throw InternalError(PALUDIS_HERE, "not decided. shouldn't happen.");
std::tr1::shared_ptr<const Repository> repo;
@@ -184,7 +187,7 @@ Resolver::_make_slash_destination_for(const QPN_S & qpn_s,
r != r_end ; ++r)
{
if ((*r)->destination_interface() && (*r)->destination_interface()->is_suitable_destination_for(
- *resolution->decision()->package_id()))
+ *resolution->decision()->if_package_id()))
{
if (repo)
throw InternalError(PALUDIS_HERE, "multiple valid destinations.");
@@ -197,7 +200,7 @@ Resolver::_make_slash_destination_for(const QPN_S & qpn_s,
throw InternalError(PALUDIS_HERE, "no valid destination for " + stringify(*resolution));
return make_shared_ptr(new Destination(make_named_values<Destination>(
- value_for<n::replacing>(_find_replacing(resolution->decision()->package_id(), repo)),
+ value_for<n::replacing>(_find_replacing(resolution->decision()->if_package_id(), repo)),
value_for<n::repository>(repo->name())
)));
}
@@ -356,6 +359,7 @@ Resolver::_make_constraint_from_target(
return make_shared_ptr(new Constraint(make_named_values<Constraint>(
value_for<n::base_spec>(spec),
value_for<n::is_blocker>(false),
+ value_for<n::nothing_is_fine_too>(false),
value_for<n::reason>(reason),
value_for<n::to_destination_slash>(true),
value_for<n::use_installed>(_imp->fns.get_use_installed_fn()(qpn_s, spec, reason))
@@ -366,13 +370,26 @@ const std::tr1::shared_ptr<Constraint>
Resolver::_make_constraint_from_dependency(const QPN_S & qpn_s, const SanitisedDependency & dep,
const std::tr1::shared_ptr<const Reason> & reason) const
{
- return make_shared_ptr(new Constraint(make_named_values<Constraint>(
- value_for<n::base_spec>(dep.spec()),
- value_for<n::is_blocker>(false),
- value_for<n::reason>(reason),
- value_for<n::to_destination_slash>(_dependency_to_destination_slash(qpn_s, dep)),
- value_for<n::use_installed>(_imp->fns.get_use_installed_fn()(qpn_s, dep.spec(), reason))
- )));
+ if (dep.spec().if_package())
+ return make_shared_ptr(new Constraint(make_named_values<Constraint>(
+ value_for<n::base_spec>(*dep.spec().if_package()),
+ value_for<n::is_blocker>(false),
+ value_for<n::nothing_is_fine_too>(false),
+ value_for<n::reason>(reason),
+ value_for<n::to_destination_slash>(_dependency_to_destination_slash(qpn_s, dep)),
+ value_for<n::use_installed>(_imp->fns.get_use_installed_fn()(qpn_s, *dep.spec().if_package(), reason))
+ )));
+ else if (dep.spec().if_block())
+ return make_shared_ptr(new Constraint(make_named_values<Constraint>(
+ value_for<n::base_spec>(*dep.spec().if_block()->blocked_spec()),
+ value_for<n::is_blocker>(true),
+ value_for<n::nothing_is_fine_too>(true),
+ value_for<n::reason>(reason),
+ value_for<n::to_destination_slash>(false),
+ value_for<n::use_installed>(ui_if_possible)
+ )));
+ else
+ throw InternalError(PALUDIS_HERE, "huh?");
}
void
@@ -433,7 +450,10 @@ Resolver::_constraint_matches(
break;
}
- ok = ok && (c->is_blocker() ^ match_package(*_imp->env, c->base_spec(), *decision->package_id(), MatchPackageOptions()));
+ if (decision->if_package_id())
+ ok = ok && (c->is_blocker() ^ match_package(*_imp->env, c->base_spec(), *decision->if_package_id(), MatchPackageOptions()));
+ else
+ ok = ok && c->nothing_is_fine_too();
return ok;
}
@@ -457,6 +477,19 @@ Resolver::_try_to_find_decision_for(const QPN_S & qpn_s,
{
std::tr1::shared_ptr<const PackageID> id;
+ bool nothing_is_fine_too(true);
+ for (Constraints::ConstIterator c(resolution->constraints()->begin()),
+ c_end(resolution->constraints()->end()) ;
+ c != c_end ; ++c)
+ if (! (*c)->nothing_is_fine_too())
+ {
+ nothing_is_fine_too = false;
+ break;
+ }
+
+ if (nothing_is_fine_too)
+ return _decision_from_package_id(qpn_s, make_null_shared_ptr());
+
if (((id = _best_installed_id_for(qpn_s, resolution))))
return _decision_from_package_id(qpn_s, id);
@@ -524,8 +557,11 @@ Resolver::_add_dependencies(const QPN_S & our_qpn_s, const std::tr1::shared_ptr<
Context context("When adding dependencies for '" + stringify(our_qpn_s) + "' with '"
+ stringify(*our_resolution) + "':");
+ if (! our_resolution->decision()->if_package_id())
+ throw InternalError(PALUDIS_HERE, "not decided. shouldn't happen.");
+
const std::tr1::shared_ptr<SanitisedDependencies> deps(new SanitisedDependencies);
- deps->populate(*this, our_resolution->decision()->package_id());
+ deps->populate(*this, our_resolution->decision()->if_package_id());
our_resolution->sanitised_dependencies() = deps;
for (SanitisedDependencies::ConstIterator s(deps->begin()), s_end(deps->end()) ;
@@ -538,8 +574,14 @@ Resolver::_add_dependencies(const QPN_S & our_qpn_s, const std::tr1::shared_ptr<
const std::tr1::shared_ptr<DependencyReason> reason(new DependencyReason(our_qpn_s, *s));
- const std::tr1::shared_ptr<const QPN_S_Sequence> qpn_s_s(_imp->fns.get_qpn_s_s_for_fn()(s->spec(), reason));
- if (qpn_s_s->empty())
+ std::tr1::shared_ptr<const QPN_S_Sequence> qpn_s_s;
+
+ if (s->spec().if_package())
+ qpn_s_s = _imp->fns.get_qpn_s_s_for_fn()(*s->spec().if_package(), reason);
+ else
+ qpn_s_s = _get_qpn_s_s_for_blocker(*s->spec().if_block());
+
+ if (qpn_s_s->empty() && s->spec().if_package())
{
if (our_resolution->decision()->is_installed())
Log::get_instance()->message("resolver.cannot_find_installed_dep", ll_warning, lc_context)
@@ -563,6 +605,15 @@ bool
Resolver::_care_about_dependency_spec(const QPN_S & qpn_s,
const std::tr1::shared_ptr<const Resolution> & resolution, const SanitisedDependency & dep) const
{
+ /* dirty dirty hack */
+ if (dep.spec().if_block())
+ if (dep.spec().if_block()->blocked_spec()->package_ptr()->category() == CategoryNamePart("virtual"))
+ {
+ Log::get_instance()->message("resolver.virtual_haxx", ll_warning, lc_context)
+ << "Ignoring " << dep << " from " << qpn_s << " for now";
+ return false;
+ }
+
return _imp->fns.care_about_dep_fn()(qpn_s, resolution, dep);
}
@@ -651,6 +702,12 @@ Resolver::_resolve_arrows()
c_end(i->second->constraints()->end()) ;
c != c_end ; ++c)
{
+ if ((*c)->is_blocker())
+ {
+ /* todo: strong blocks do impose arrows */
+ continue;
+ }
+
GetDependencyReason gdr;
const DependencyReason * if_dependency_reason((*c)->reason()->accept_returning<const DependencyReason *>(gdr));
if (! if_dependency_reason)
@@ -680,10 +737,20 @@ Resolver::_resolve_arrows()
bool
Resolver::_already_met(const SanitisedDependency & dep) const
{
- std::tr1::shared_ptr<const PackageIDSequence> ids((*_imp->env)[selection::SomeArbitraryVersion(
- generator::Matches(dep.spec(), MatchPackageOptions()) |
- filter::SupportsAction<InstalledAction>())]);
- return ! ids->empty();
+ if (dep.spec().if_package())
+ {
+ std::tr1::shared_ptr<const PackageIDSequence> ids((*_imp->env)[selection::SomeArbitraryVersion(
+ generator::Matches(*dep.spec().if_package(), MatchPackageOptions()) |
+ filter::SupportsAction<InstalledAction>())]);
+ return ! ids->empty();
+ }
+ else if (dep.spec().if_block())
+ {
+ /* it's imposing an arrow, so it's a strong block */
+ return false;
+ }
+ else
+ throw InternalError(PALUDIS_HERE, "huh?");
}
void
@@ -695,7 +762,7 @@ Resolver::_resolve_order()
for (ResolutionsByQPN_SMap::iterator i(_imp->resolutions_by_qpn_s.begin()), i_end(_imp->resolutions_by_qpn_s.end()) ;
i != i_end ; ++i)
- if (i->second->decision()->is_installed())
+ if (i->second->decision()->is_installed() || i->second->decision()->is_nothing())
i->second->already_ordered() = true;
while (! done)
@@ -773,9 +840,10 @@ Resolver::_do_order(const QPN_S &, const std::tr1::shared_ptr<Resolution> & reso
const std::tr1::shared_ptr<Decision>
Resolver::_decision_from_package_id(const QPN_S & qpn_s, const std::tr1::shared_ptr<const PackageID> & id) const
{
- bool is_installed, is_transient, is_new, is_same, is_same_version;
+ bool is_installed, is_transient, is_new, is_same, is_same_version, is_nothing;
- is_installed = id->supports_action(SupportsActionTest<InstalledAction>());
+ is_nothing = ! id;
+ is_installed = (! is_nothing) && id->supports_action(SupportsActionTest<InstalledAction>());
is_transient = is_installed && id->transient_key() && id->transient_key()->value();
std::tr1::shared_ptr<const PackageIDSequence> comparison_ids;
@@ -786,32 +854,39 @@ Resolver::_decision_from_package_id(const QPN_S & qpn_s, const std::tr1::shared_
qpn_s.make_slot_filter() |
filter::SupportsAction<InstallAction>() |
filter::NotMasked())]);
- else
+ else if (! is_nothing)
comparison_ids = ((*_imp->env)[selection::BestVersionOnly(
generator::Package(qpn_s.package()) |
qpn_s.make_slot_filter() |
filter::SupportsAction<InstalledAction>())]);
- if (comparison_ids->empty())
+ if (comparison_ids && comparison_ids->empty())
{
is_new = true;
is_same = false;
is_same_version = false;
}
- else
+ else if (comparison_ids)
{
is_new = false;
is_same = ((*comparison_ids->begin())->version() == id->version());
is_same_version = is_same;
}
+ else
+ {
+ is_new = false;
+ is_same = false;
+ is_same_version = false;
+ }
return make_shared_ptr(new Decision(make_named_values<Decision>(
+ value_for<n::if_package_id>(id),
value_for<n::is_installed>(is_installed),
value_for<n::is_new>(is_new),
+ value_for<n::is_nothing>(is_nothing),
value_for<n::is_same>(is_same),
value_for<n::is_same_version>(is_same_version),
- value_for<n::is_transient>(is_transient),
- value_for<n::package_id>(id)
+ value_for<n::is_transient>(is_transient)
)));
}
@@ -918,12 +993,17 @@ Resolver::_make_constraint_for_preloading(
{
const std::tr1::shared_ptr<PresetReason> reason(new PresetReason);
+ if (! d->if_package_id())
+ throw InternalError(PALUDIS_HERE, "not decided. shouldn't happen.");
+
return make_shared_ptr(new Constraint(make_named_values<Constraint>(
- value_for<n::base_spec>(d->package_id()->uniquely_identifying_spec()),
+ value_for<n::base_spec>(d->if_package_id()->uniquely_identifying_spec()),
value_for<n::is_blocker>(false),
+ value_for<n::nothing_is_fine_too>(false),
value_for<n::reason>(reason),
value_for<n::to_destination_slash>(false),
- value_for<n::use_installed>(_imp->fns.get_use_installed_fn()(qpn_s, d->package_id()->uniquely_identifying_spec(), reason))
+ value_for<n::use_installed>(_imp->fns.get_use_installed_fn()(
+ qpn_s, d->if_package_id()->uniquely_identifying_spec(), reason))
)));
}
@@ -963,12 +1043,17 @@ Resolver::find_any_score(const QPN_S & our_qpn_s, const SanitisedDependency & de
Context context("When working out whether we'd like '" + stringify(dep) + "' because of '"
+ stringify(our_qpn_s) + "':");
+ if (dep.spec().if_block())
+ throw InternalError(PALUDIS_HERE, "not yet");
+
+ const PackageDepSpec & spec(*dep.spec().if_package());
+
int operator_bias(0);
- if (dep.spec().version_requirements_ptr() && ! dep.spec().version_requirements_ptr()->empty())
+ if (spec.version_requirements_ptr() && ! spec.version_requirements_ptr()->empty())
{
int score(-1);
- for (VersionRequirements::ConstIterator v(dep.spec().version_requirements_ptr()->begin()),
- v_end(dep.spec().version_requirements_ptr()->end()) ;
+ for (VersionRequirements::ConstIterator v(spec.version_requirements_ptr()->begin()),
+ v_end(spec.version_requirements_ptr()->end()) ;
v != v_end ; ++v)
{
int local_score(0);
@@ -1001,7 +1086,7 @@ Resolver::find_any_score(const QPN_S & our_qpn_s, const SanitisedDependency & de
if (score == -1)
score = local_score;
else
- switch (dep.spec().version_requirements_mode())
+ switch (spec.version_requirements_mode())
{
case vr_and:
score = std::min(score, local_score);
@@ -1027,14 +1112,14 @@ Resolver::find_any_score(const QPN_S & our_qpn_s, const SanitisedDependency & de
/* best: already installed */
{
const std::tr1::shared_ptr<const PackageIDSequence> installed_ids((*_imp->env)[selection::BestVersionOnly(
- generator::Matches(dep.spec(), MatchPackageOptions() + mpo_ignore_additional_requirements) |
+ generator::Matches(spec, MatchPackageOptions() + mpo_ignore_additional_requirements) |
filter::SupportsAction<InstalledAction>())]);
if (! installed_ids->empty())
return 40 + operator_bias;
}
const std::tr1::shared_ptr<DependencyReason> reason(new DependencyReason(our_qpn_s, dep));
- const std::tr1::shared_ptr<const QPN_S_Sequence> qpn_s_s(_imp->fns.get_qpn_s_s_for_fn()(dep.spec(), reason));
+ const std::tr1::shared_ptr<const QPN_S_Sequence> qpn_s_s(_imp->fns.get_qpn_s_s_for_fn()(spec, reason));
/* next: will already be installing */
{
@@ -1064,7 +1149,7 @@ Resolver::find_any_score(const QPN_S & our_qpn_s, const SanitisedDependency & de
/* next: exists */
{
const std::tr1::shared_ptr<const PackageIDSequence> ids((*_imp->env)[selection::BestVersionOnly(
- generator::Matches(dep.spec(), MatchPackageOptions() + mpo_ignore_additional_requirements)
+ generator::Matches(spec, MatchPackageOptions() + mpo_ignore_additional_requirements)
)]);
if (! ids->empty())
return 10 + operator_bias;
@@ -1124,6 +1209,55 @@ Resolver::_find_cycle(const QPN_S & start_qpn_s, const int ignorable_pass) const
return result.str();
}
+namespace
+{
+ struct SlotNameFinder
+ {
+ std::tr1::shared_ptr<SlotName> visit(const SlotExactRequirement & s)
+ {
+ return make_shared_ptr(new SlotName(s.slot()));
+ }
+
+ std::tr1::shared_ptr<SlotName> visit(const SlotAnyUnlockedRequirement &)
+ {
+ return make_null_shared_ptr();
+ }
+
+ std::tr1::shared_ptr<SlotName> visit(const SlotAnyLockedRequirement &)
+ {
+ return make_null_shared_ptr();
+ }
+ };
+}
+
+const std::tr1::shared_ptr<const QPN_S_Sequence>
+Resolver::_get_qpn_s_s_for_blocker(const BlockDepSpec & spec) const
+{
+ Context context("When finding slots for '" + stringify(spec) + "':");
+
+ std::tr1::shared_ptr<SlotName> exact_slot;
+ if (spec.blocked_spec()->slot_requirement_ptr())
+ {
+ SlotNameFinder f;
+ exact_slot = spec.blocked_spec()->slot_requirement_ptr()->accept_returning<std::tr1::shared_ptr<SlotName> >(f);
+ }
+
+ std::tr1::shared_ptr<QPN_S_Sequence> result(new QPN_S_Sequence);
+ if (exact_slot)
+ result->push_back(QPN_S(*spec.blocked_spec(), exact_slot));
+ else
+ {
+ const std::tr1::shared_ptr<const PackageIDSequence> ids((*_imp->env)[selection::BestVersionInEachSlot(
+ generator::Package(*spec.blocked_spec()->package_ptr())
+ )]);
+ for (PackageIDSequence::ConstIterator i(ids->begin()), i_end(ids->end()) ;
+ i != i_end ; ++i)
+ result->push_back(QPN_S(*i));
+ }
+
+ return result;
+}
+
template class WrappedForwardIterator<Resolver::ConstIteratorTag, const std::tr1::shared_ptr<const Resolution> >;
template class WrappedForwardIterator<Resolver::ResolutionsByQPN_SConstIteratorTag,
const std::pair<const QPN_S, std::tr1::shared_ptr<Resolution> > >;
diff --git a/paludis/resolver/resolver.hh b/paludis/resolver/resolver.hh
index ff722e4..8973c55 100644
--- a/paludis/resolver/resolver.hh
+++ b/paludis/resolver/resolver.hh
@@ -53,6 +53,8 @@ namespace paludis
const std::tr1::shared_ptr<Resolution> _resolution_for_qpn_s(const QPN_S &, const bool create);
const std::tr1::shared_ptr<Resolution> _resolution_for_qpn_s(const QPN_S &) const;
+ const std::tr1::shared_ptr<const QPN_S_Sequence> _get_qpn_s_s_for_blocker(const BlockDepSpec &) const;
+
const std::tr1::shared_ptr<Constraint> _make_constraint_from_target(
const QPN_S &,
const PackageDepSpec &,
diff --git a/paludis/resolver/sanitised_dependencies-fwd.hh b/paludis/resolver/sanitised_dependencies-fwd.hh
index 14bc0cf..9ef1bb5 100644
--- a/paludis/resolver/sanitised_dependencies-fwd.hh
+++ b/paludis/resolver/sanitised_dependencies-fwd.hh
@@ -30,7 +30,10 @@ namespace paludis
struct SanitisedDependencies;
struct SanitisedDependency;
+ struct PackageOrBlockDepSpec;
+
std::ostream & operator<< (std::ostream & s, const SanitisedDependency & d) PALUDIS_VISIBLE;
+ std::ostream & operator<< (std::ostream & s, const PackageOrBlockDepSpec & d) PALUDIS_VISIBLE;
}
}
diff --git a/paludis/resolver/sanitised_dependencies.cc b/paludis/resolver/sanitised_dependencies.cc
index 0d25371..a62d633 100644
--- a/paludis/resolver/sanitised_dependencies.cc
+++ b/paludis/resolver/sanitised_dependencies.cc
@@ -37,24 +37,6 @@ using namespace paludis::resolver;
namespace
{
- struct IsUnrestrictedSlot
- {
- bool visit(const SlotExactRequirement &) const
- {
- return false;
- }
-
- bool visit(const SlotAnyUnlockedRequirement &) const
- {
- return true;
- }
-
- bool visit(const SlotAnyLockedRequirement &) const
- {
- return true;
- }
- };
-
template <typename T_>
void list_push_back(std::list<T_> * const l, const T_ & t)
{
@@ -65,17 +47,17 @@ namespace
{
const Resolver & resolver;
const QPN_S our_qpn_s;
- const std::tr1::function<SanitisedDependency (const PackageDepSpec &)> parent_make_sanitised;
+ const std::tr1::function<SanitisedDependency (const PackageOrBlockDepSpec &)> parent_make_sanitised;
bool super_complicated, nested;
- std::list<std::list<PackageDepSpec> > child_groups;
- std::list<PackageDepSpec> * active_sublist;
+ std::list<std::list<PackageOrBlockDepSpec> > child_groups;
+ std::list<PackageOrBlockDepSpec> * active_sublist;
bool seen_any;
AnyDepSpecChildHandler(const Resolver & r, const QPN_S & q,
- const std::tr1::function<SanitisedDependency (const PackageDepSpec &)> & f) :
+ const std::tr1::function<SanitisedDependency (const PackageOrBlockDepSpec &)> & f) :
resolver(r),
our_qpn_s(q),
parent_make_sanitised(f),
@@ -86,33 +68,44 @@ namespace
{
}
- void visit_spec(const PackageDepSpec & spec)
+ void visit_package_or_block_spec(const PackageOrBlockDepSpec & spec)
{
- if (spec.package_ptr())
- {
- seen_any = true;
+ seen_any = true;
- if (active_sublist)
- active_sublist->push_back(spec);
- else
- {
- std::list<PackageDepSpec> l;
- l.push_back(spec);
- child_groups.push_back(l);
- }
+ if (active_sublist)
+ active_sublist->push_back(spec);
+ else
+ {
+ std::list<PackageOrBlockDepSpec> l;
+ l.push_back(spec);
+ child_groups.push_back(l);
}
+ }
+
+ void visit_package_spec(const PackageDepSpec & spec)
+ {
+ if (spec.package_ptr())
+ visit_package_or_block_spec(PackageOrBlockDepSpec(spec));
+ else
+ super_complicated = true;
+ }
+
+ void visit_block_spec(const BlockDepSpec & spec)
+ {
+ if (spec.blocked_spec()->package_ptr())
+ visit_package_or_block_spec(PackageOrBlockDepSpec(spec));
else
super_complicated = true;
}
void visit(const DependencySpecTree::NodeType<PackageDepSpec>::Type & node)
{
- visit_spec(*node.spec());
+ visit_package_spec(*node.spec());
}
- void visit(const DependencySpecTree::NodeType<BlockDepSpec>::Type &)
+ void visit(const DependencySpecTree::NodeType<BlockDepSpec>::Type & node)
{
- super_complicated = true;
+ visit_block_spec(*node.spec());
}
void visit(const DependencySpecTree::NodeType<ConditionalDepSpec>::Type & node)
@@ -125,8 +118,8 @@ namespace
std::for_each(indirect_iterator(node.begin()), indirect_iterator(node.end()), accept_visitor(*this));
else
{
- Save<std::list<PackageDepSpec> *> save_active_sublist(&active_sublist, 0);
- active_sublist = &*child_groups.insert(child_groups.end(), std::list<PackageDepSpec>());
+ Save<std::list<PackageOrBlockDepSpec> *> save_active_sublist(&active_sublist, 0);
+ active_sublist = &*child_groups.insert(child_groups.end(), std::list<PackageOrBlockDepSpec>());
std::for_each(indirect_iterator(node.begin()), indirect_iterator(node.end()), accept_visitor(*this));
}
}
@@ -140,8 +133,8 @@ namespace
std::for_each(indirect_iterator(node.begin()), indirect_iterator(node.end()), accept_visitor(*this));
else
{
- Save<std::list<PackageDepSpec> *> save_active_sublist(&active_sublist, 0);
- active_sublist = &*child_groups.insert(child_groups.end(), std::list<PackageDepSpec>());
+ Save<std::list<PackageOrBlockDepSpec> *> save_active_sublist(&active_sublist, 0);
+ active_sublist = &*child_groups.insert(child_groups.end(), std::list<PackageOrBlockDepSpec>());
std::for_each(indirect_iterator(node.begin()), indirect_iterator(node.end()), accept_visitor(*this));
}
}
@@ -160,15 +153,15 @@ namespace
{
for (std::list<SanitisedDependency>::const_iterator i(l.begin()), i_end(l.end()) ;
i != i_end ; ++i)
- visit_spec(i->spec());
+ visit_package_or_block_spec(i->spec());
}
else
{
- Save<std::list<PackageDepSpec> *> save_active_sublist(&active_sublist, 0);
- active_sublist = &*child_groups.insert(child_groups.end(), std::list<PackageDepSpec>());
+ Save<std::list<PackageOrBlockDepSpec> *> save_active_sublist(&active_sublist, 0);
+ active_sublist = &*child_groups.insert(child_groups.end(), std::list<PackageOrBlockDepSpec>());
for (std::list<SanitisedDependency>::const_iterator i(l.begin()), i_end(l.end()) ;
i != i_end ; ++i)
- visit_spec(i->spec());
+ visit_package_or_block_spec(i->spec());
}
}
@@ -183,7 +176,7 @@ namespace
}
void commit(
- const std::tr1::function<SanitisedDependency (const PackageDepSpec &)> & make_sanitised,
+ const std::tr1::function<SanitisedDependency (const PackageOrBlockDepSpec &)> & make_sanitised,
const std::tr1::function<void (const SanitisedDependency &)> & apply)
{
if (! seen_any)
@@ -194,10 +187,10 @@ namespace
else
{
/* we've got a choice of groups of packages. pick the best score, left to right. */
- std::list<std::list<PackageDepSpec> >::const_iterator g_best(child_groups.end());
+ std::list<std::list<PackageOrBlockDepSpec> >::const_iterator g_best(child_groups.end());
int best_score(-1);
- for (std::list<std::list<PackageDepSpec> >::const_iterator g(child_groups.begin()),
+ for (std::list<std::list<PackageOrBlockDepSpec> >::const_iterator g(child_groups.begin()),
g_end(child_groups.end()) ;
g != g_end ; ++g)
{
@@ -207,10 +200,10 @@ namespace
throw InternalError(PALUDIS_HERE, "why did that happen?");
/* score of a group is the score of the worst child. */
- for (std::list<PackageDepSpec>::const_iterator h(g->begin()), h_end(g->end()) ;
+ for (std::list<PackageOrBlockDepSpec>::const_iterator h(g->begin()), h_end(g->end()) ;
h != h_end ; ++h)
{
- int score(resolver.find_any_score(our_qpn_s, make_sanitised(*h)));
+ int score(resolver.find_any_score(our_qpn_s, make_sanitised(PackageOrBlockDepSpec(*h))));
if ((-1 == worst_score) || (score < worst_score))
worst_score = score;
}
@@ -224,7 +217,7 @@ namespace
if (g_best == child_groups.end())
throw InternalError(PALUDIS_HERE, "why did that happen?");
- for (std::list<PackageDepSpec>::const_iterator h(g_best->begin()), h_end(g_best->end()) ;
+ for (std::list<PackageOrBlockDepSpec>::const_iterator h(g_best->begin()), h_end(g_best->end()) ;
h != h_end ; ++h)
apply(make_sanitised(*h));
}
@@ -256,7 +249,7 @@ namespace
sanitised_dependencies.add(dep);
}
- SanitisedDependency make_sanitised(const PackageDepSpec & spec)
+ SanitisedDependency make_sanitised(const PackageOrBlockDepSpec & spec)
{
return make_named_values<SanitisedDependency>(
value_for<n::active_dependency_labels>(*labels_stack.begin()),
@@ -269,8 +262,9 @@ namespace
add(make_sanitised(*node.spec()));
}
- void visit(const DependencySpecTree::NodeType<BlockDepSpec>::Type &)
+ void visit(const DependencySpecTree::NodeType<BlockDepSpec>::Type & node)
{
+ add(make_sanitised(*node.spec()));
}
void visit(const DependencySpecTree::NodeType<ConditionalDepSpec>::Type & node)
@@ -401,3 +395,24 @@ paludis::resolver::operator<< (std::ostream & s, const SanitisedDependency & d)
return s;
}
+std::ostream &
+paludis::resolver::operator<< (std::ostream & s, const PackageOrBlockDepSpec & d)
+{
+ if (d.if_package())
+ return s << *d.if_package();
+ else
+ return s << *d.if_block();
+}
+
+PackageOrBlockDepSpec::PackageOrBlockDepSpec(const BlockDepSpec & s) :
+ if_block(value_for<n::if_block>(make_shared_ptr(new BlockDepSpec(s)))),
+ if_package(value_for<n::if_package>(make_null_shared_ptr()))
+{
+}
+
+PackageOrBlockDepSpec::PackageOrBlockDepSpec(const PackageDepSpec & s) :
+ if_block(value_for<n::if_block>(make_null_shared_ptr())),
+ if_package(value_for<n::if_package>(make_shared_ptr(new PackageDepSpec(s))))
+{
+}
+
diff --git a/paludis/resolver/sanitised_dependencies.hh b/paludis/resolver/sanitised_dependencies.hh
index 5cb520a..b2881cd 100644
--- a/paludis/resolver/sanitised_dependencies.hh
+++ b/paludis/resolver/sanitised_dependencies.hh
@@ -33,15 +33,26 @@ namespace paludis
namespace n
{
struct active_dependency_labels;
+ struct if_package;
+ struct if_block;
struct spec;
}
namespace resolver
{
+ struct PackageOrBlockDepSpec
+ {
+ NamedValue<n::if_block, std::tr1::shared_ptr<BlockDepSpec> > if_block;
+ NamedValue<n::if_package, std::tr1::shared_ptr<PackageDepSpec> > if_package;
+
+ PackageOrBlockDepSpec(const BlockDepSpec &);
+ PackageOrBlockDepSpec(const PackageDepSpec &);
+ };
+
struct SanitisedDependency
{
NamedValue<n::active_dependency_labels, std::tr1::shared_ptr<const ActiveDependencyLabels> > active_dependency_labels;
- NamedValue<n::spec, PackageDepSpec> spec;
+ NamedValue<n::spec, PackageOrBlockDepSpec> spec;
};
class SanitisedDependencies :
diff --git a/src/clients/cave/cmd_resolve.cc b/src/clients/cave/cmd_resolve.cc
index 8702c8e..4bbe7b0 100644
--- a/src/clients/cave/cmd_resolve.cc
+++ b/src/clients/cave/cmd_resolve.cc
@@ -472,9 +472,12 @@ namespace
for (Resolver::ConstIterator c(resolver->begin()), c_end(resolver->end()) ;
c != c_end ; ++c)
{
- const std::tr1::shared_ptr<const PackageID> id((*c)->decision()->package_id());
- std::cout << "* " << id->canonical_form(idcf_no_version) << " " << id->canonical_form(idcf_version)
- << " to " << *(*c)->destinations() << std::endl;
+ const std::tr1::shared_ptr<const PackageID> id((*c)->decision()->if_package_id());
+ if (id)
+ std::cout << "* " << id->canonical_form(idcf_no_version) << " " << id->canonical_form(idcf_version)
+ << " to " << *(*c)->destinations() << std::endl;
+ else
+ throw InternalError(PALUDIS_HERE, "why did that happen?");
}
std::cout << std::endl;
@@ -525,7 +528,14 @@ namespace
r_end(resolver->end_resolutions_by_qpn_s()) ;
r != r_end ; ++r)
{
- if (! match_package(*env, spec, *r->second->decision()->package_id(), MatchPackageOptions()))
+ if (! r->second->decision()->if_package_id())
+ {
+ /* really we want this to work for simple cat/pkg and
+ * cat/pkg:slot specs anyway, even if we chose nothing */
+ continue;
+ }
+
+ if (! match_package(*env, spec, *r->second->decision()->if_package_id(), MatchPackageOptions()))
continue;
any = true;
@@ -573,7 +583,7 @@ namespace
std::cout << std::endl;
}
std::cout << " The decision made was:" << std::endl;
- std::cout << " Use " << *r->second->decision()->package_id() << std::endl;
+ std::cout << " Use " << *r->second->decision()->if_package_id() << std::endl;
if (r->second->destinations()->slash())
{
std::cout << " Install to / using repository " << r->second->destinations()->slash()->repository() << std::endl;
@@ -771,6 +781,7 @@ namespace
result->add(make_shared_ptr(new Constraint(make_named_values<Constraint>(
value_for<n::base_spec>(make_package_dep_spec(PartiallyMadePackageDepSpecOptions()).package(qpn_s.package())),
value_for<n::is_blocker>(false),
+ value_for<n::nothing_is_fine_too>(false),
value_for<n::reason>(make_shared_ptr(new PresetReason)),
value_for<n::to_destination_slash>(false),
value_for<n::use_installed>(ui_only_if_transient)