diff options
-rw-r--r-- | paludis/resolver/decider.cc | 2 | ||||
-rw-r--r-- | paludis/resolver/prefer_or_avoid_helper.cc | 55 | ||||
-rw-r--r-- | paludis/resolver/prefer_or_avoid_helper.hh | 7 | ||||
-rw-r--r-- | paludis/resolver/resolver_functions.hh | 2 | ||||
-rw-r--r-- | src/clients/cave/resolve_cmdline.cc | 4 | ||||
-rw-r--r-- | src/clients/cave/resolve_cmdline.hh | 2 | ||||
-rw-r--r-- | src/clients/cave/resolve_common.cc | 12 |
7 files changed, 73 insertions, 11 deletions
diff --git a/paludis/resolver/decider.cc b/paludis/resolver/decider.cc index edaed7012..63e58e5f8 100644 --- a/paludis/resolver/decider.cc +++ b/paludis/resolver/decider.cc @@ -1235,7 +1235,7 @@ Decider::find_any_score( /* explicit preferences come first */ if (spec.package_ptr()) { - Tribool prefer_or_avoid(_imp->fns.prefer_or_avoid_fn()(*spec.package_ptr())); + Tribool prefer_or_avoid(_imp->fns.prefer_or_avoid_fn()(spec)); if (prefer_or_avoid.is_true()) return std::make_pair(is_block ? acs_avoid : acs_prefer, operator_bias); else if (prefer_or_avoid.is_false()) diff --git a/paludis/resolver/prefer_or_avoid_helper.cc b/paludis/resolver/prefer_or_avoid_helper.cc index 95fc31bc0..1cfa1d94b 100644 --- a/paludis/resolver/prefer_or_avoid_helper.cc +++ b/paludis/resolver/prefer_or_avoid_helper.cc @@ -21,8 +21,13 @@ #include <paludis/util/pimp-impl.hh> #include <paludis/util/hashes.hh> #include <paludis/util/tribool.hh> +#include <paludis/util/make_null_shared_ptr.hh> +#include <paludis/util/options.hh> #include <paludis/name.hh> +#include <paludis/dep_spec.hh> +#include <paludis/match_package.hh> #include <unordered_set> +#include <list> using namespace paludis; using namespace paludis::resolver; @@ -35,6 +40,8 @@ namespace paludis const Environment * const env; std::unordered_set<QualifiedPackageName, Hash<QualifiedPackageName> > prefer_names; std::unordered_set<QualifiedPackageName, Hash<QualifiedPackageName> > avoid_names; + std::list<std::shared_ptr<const PackageIDSequence> > prefer_matching; + std::list<std::shared_ptr<const PackageIDSequence> > avoid_matching; Imp(const Environment * const e) : env(e) @@ -62,14 +69,52 @@ PreferOrAvoidHelper::add_avoid_name(const QualifiedPackageName & name) _imp->avoid_names.insert(name); } +void +PreferOrAvoidHelper::add_prefer_matching(const std::shared_ptr<const PackageIDSequence> & s) +{ + _imp->prefer_matching.push_back(s); +} + +void +PreferOrAvoidHelper::add_avoid_matching(const std::shared_ptr<const PackageIDSequence> & s) +{ + _imp->avoid_matching.push_back(s); +} + Tribool -PreferOrAvoidHelper::operator() (const QualifiedPackageName & n) const +PreferOrAvoidHelper::operator() (const PackageDepSpec & s) const { - if (_imp->prefer_names.end() != _imp->prefer_names.find(n)) - return true; + if (s.package_ptr()) + { + if (_imp->prefer_names.end() != _imp->prefer_names.find(*s.package_ptr())) + return true; - if (_imp->avoid_names.end() != _imp->avoid_names.find(n)) - return false; + if (_imp->avoid_names.end() != _imp->avoid_names.find(*s.package_ptr())) + return false; + } + + for (auto p(_imp->prefer_matching.begin()), p_end(_imp->prefer_matching.end()) ; + p != p_end ; ++p) + { + bool all(true); + for (auto q((*p)->begin()), q_end((*p)->end()) ; q != q_end ; ++q) + if (! match_package(*_imp->env, s, *q, make_null_shared_ptr(), { })) + { + all = false; + break; + } + + if (all) + return true; + } + + for (auto p(_imp->avoid_matching.begin()), p_end(_imp->avoid_matching.end()) ; + p != p_end ; ++p) + { + for (auto q((*p)->begin()), q_end((*p)->end()) ; q != q_end ; ++q) + if (match_package(*_imp->env, s, *q, make_null_shared_ptr(), { })) + return false; + } return indeterminate; } diff --git a/paludis/resolver/prefer_or_avoid_helper.hh b/paludis/resolver/prefer_or_avoid_helper.hh index d2e2bb6f1..7d1c6ea13 100644 --- a/paludis/resolver/prefer_or_avoid_helper.hh +++ b/paludis/resolver/prefer_or_avoid_helper.hh @@ -27,6 +27,8 @@ #include <paludis/util/tribool-fwd.hh> #include <paludis/name-fwd.hh> #include <paludis/environment-fwd.hh> +#include <paludis/package_id-fwd.hh> +#include <paludis/dep_spec-fwd.hh> #include <memory> namespace paludis @@ -45,7 +47,10 @@ namespace paludis void add_prefer_name(const QualifiedPackageName &); void add_avoid_name(const QualifiedPackageName &); - Tribool operator() (const QualifiedPackageName &) const; + void add_prefer_matching(const std::shared_ptr<const PackageIDSequence> &); + void add_avoid_matching(const std::shared_ptr<const PackageIDSequence> &); + + Tribool operator() (const PackageDepSpec &) const; }; } diff --git a/paludis/resolver/resolver_functions.hh b/paludis/resolver/resolver_functions.hh index cbe8b0a04..ebdeda47e 100644 --- a/paludis/resolver/resolver_functions.hh +++ b/paludis/resolver/resolver_functions.hh @@ -182,7 +182,7 @@ namespace paludis )> OrderEarlyFunction; typedef std::function<Tribool ( - const QualifiedPackageName & + const PackageDepSpec & )> PreferOrAvoidFunction; typedef std::function<std::shared_ptr<const PackageIDSequence> ( diff --git a/src/clients/cave/resolve_cmdline.cc b/src/clients/cave/resolve_cmdline.cc index 3e5c939f8..5ad7fb37f 100644 --- a/src/clients/cave/resolve_cmdline.cc +++ b/src/clients/cave/resolve_cmdline.cc @@ -231,8 +231,12 @@ ResolveCommandLineResolutionOptions::ResolveCommandLineResolutionOptions(args::A g_package_options(this, "Package Selection Options", "Control which packages are selected."), a_favour(&g_package_options, "favour", 'F', "If there is a choice (e.g. || ( ) dependencies), favour the " "specified package names"), + a_favour_matching(&g_package_options, "favour-matching", '\0', "If there is a choice (e.g. || ( ) dependencies), favour specs " + "which match all of the packages matching the supplied spec"), a_avoid(&g_package_options, "avoid", 'A', "If there is a choice (e.g. || ( ) dependencies), avoid the " "specified package names"), + a_avoid_matching(&g_package_options, "avoid-matching", '\0', "If there is a choice (e.g. || ( ) dependencies), avoid specs " + "which match any of the packages matching the supplied spec"), a_preset(&g_package_options, "preset", 'p', "Preset a given constraint. For example, --preset =cat/pkg-2.1 will tell " "the resolver to use that particular version. Note that this may lead to errors, if the specified version " "does not satisfy other constraints. Also note that specifying a preset will not force a package to be " diff --git a/src/clients/cave/resolve_cmdline.hh b/src/clients/cave/resolve_cmdline.hh index 8bdd0b4f2..ed787650c 100644 --- a/src/clients/cave/resolve_cmdline.hh +++ b/src/clients/cave/resolve_cmdline.hh @@ -85,7 +85,9 @@ namespace paludis args::ArgsGroup g_package_options; args::StringSetArg a_favour; + args::StringSetArg a_favour_matching; args::StringSetArg a_avoid; + args::StringSetArg a_avoid_matching; args::StringSetArg a_preset; args::StringSetArg a_hide; diff --git a/src/clients/cave/resolve_common.cc b/src/clients/cave/resolve_common.cc index 3ddbddb33..00e4c1ce1 100644 --- a/src/clients/cave/resolve_common.cc +++ b/src/clients/cave/resolve_common.cc @@ -964,10 +964,16 @@ paludis::cave::resolve_common( i_end(resolution_options.a_favour.end_args()) ; i != i_end ; ++i) prefer_or_avoid_helper.add_prefer_name(disambiguate_if_necessary(env.get(), *i)); - for (args::StringSetArg::ConstIterator i(resolution_options.a_avoid.begin_args()), - i_end(resolution_options.a_avoid.end_args()) ; + for (args::StringSetArg::ConstIterator i(resolution_options.a_favour_matching.begin_args()), + i_end(resolution_options.a_favour_matching.end_args()) ; i != i_end ; ++i) - prefer_or_avoid_helper.add_avoid_name(disambiguate_if_necessary(env.get(), *i)); + prefer_or_avoid_helper.add_prefer_matching((*env)[selection::AllVersionsUnsorted(generator::Matches( + parse_spec_with_nice_error(*i, env.get(), { }, filter::All()), make_null_shared_ptr(), { }))]); + for (args::StringSetArg::ConstIterator i(resolution_options.a_avoid_matching.begin_args()), + i_end(resolution_options.a_avoid_matching.end_args()) ; + i != i_end ; ++i) + prefer_or_avoid_helper.add_avoid_matching((*env)[selection::AllVersionsUnsorted(generator::Matches( + parse_spec_with_nice_error(*i, env.get(), { }, filter::All()), make_null_shared_ptr(), { }))]); RemoveIfDependentHelper remove_if_dependent_helper(env.get()); for (args::StringSetArg::ConstIterator i(resolution_options.a_remove_if_dependent.begin_args()), |