diff options
Diffstat (limited to 'paludis')
-rw-r--r-- | paludis/dep_spec_annotations-fwd.hh | 5 | ||||
-rw-r--r-- | paludis/dep_spec_annotations.cc | 41 | ||||
-rw-r--r-- | paludis/dep_spec_annotations.se | 3 | ||||
-rw-r--r-- | paludis/repositories/e/dep_parser.cc | 88 |
4 files changed, 132 insertions, 5 deletions
diff --git a/paludis/dep_spec_annotations-fwd.hh b/paludis/dep_spec_annotations-fwd.hh index a02167234..2403ff625 100644 --- a/paludis/dep_spec_annotations-fwd.hh +++ b/paludis/dep_spec_annotations-fwd.hh @@ -1,7 +1,7 @@ /* vim: set sw=4 sts=4 et foldmethod=syntax : */ /* - * Copyright (c) 2010 Ciaran McCreesh + * Copyright (c) 2010, 2011 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 @@ -22,6 +22,7 @@ #include <paludis/util/attributes.hh> #include <iosfwd> +#include <memory> namespace paludis { @@ -30,6 +31,8 @@ namespace paludis #include <paludis/dep_spec_annotations-se.hh> + DepSpecAnnotationRole find_blocker_role_in_annotations( + const std::shared_ptr<const DepSpecAnnotations> & maybe_annotations) PALUDIS_VISIBLE PALUDIS_ATTRIBUTE((warn_unused_result)); } #endif diff --git a/paludis/dep_spec_annotations.cc b/paludis/dep_spec_annotations.cc index 3c8762030..d86cd2d96 100644 --- a/paludis/dep_spec_annotations.cc +++ b/paludis/dep_spec_annotations.cc @@ -100,6 +100,47 @@ DepSpecAnnotations::add(const DepSpecAnnotation & a) _imp->annotations.push_back(a); } +DepSpecAnnotationRole +paludis::find_blocker_role_in_annotations( + const std::shared_ptr<const DepSpecAnnotations> & maybe_annotations) +{ + if (! maybe_annotations) + return dsar_none; + + for (auto i(maybe_annotations->begin()), i_end(maybe_annotations->end()) ; + i != i_end ; ++i) + { + switch (i->role()) + { + case dsar_blocker_manual: + case dsar_blocker_uninstall_blocked_after: + case dsar_blocker_uninstall_blocked_before: + case dsar_blocker_upgrade_blocked_before: + case dsar_blocker_weak: + case dsar_blocker_strong: + return i->role(); + + case dsar_none: + case dsar_general_description: + case dsar_general_url: + case dsar_general_note: + case dsar_general_lang: + case dsar_general_defined_in: + case dsar_myoptions_requires: + case dsar_myoptions_n_at_least_one: + case dsar_myoptions_n_at_most_one: + case dsar_myoptions_n_exactly_one: + case dsar_suggestions_group_name: + break; + + case last_dsar: + throw InternalError(PALUDIS_HERE, "bad dsar"); + } + } + + return dsar_none; +} + template class Pimp<DepSpecAnnotations>; template class WrappedForwardIterator<DepSpecAnnotations::ConstIteratorTag, const DepSpecAnnotation>; diff --git a/paludis/dep_spec_annotations.se b/paludis/dep_spec_annotations.se index 02c83aef3..ebe553771 100644 --- a/paludis/dep_spec_annotations.se +++ b/paludis/dep_spec_annotations.se @@ -13,10 +13,13 @@ make_enum_DepSpecAnnotationRole() key dsar_general_lang "A language" key dsar_general_defined_in "Defined in" + # update find_blocker_role_in_annotations when adding here key dsar_blocker_manual "Blocker, resolve manually" key dsar_blocker_uninstall_blocked_after "Blocker, uninstall blocked after" key dsar_blocker_uninstall_blocked_before "Blocker, uninstall blocked before" key dsar_blocker_upgrade_blocked_before "Blocker, upgrade blocked before" + key dsar_blocker_weak "Blocker, weak (generally implicit)" + key dsar_blocker_strong "Blocker, strong (generally implicit)" key dsar_myoptions_requires "MYOPTIONS, requires" key dsar_myoptions_n_at_least_one "MYOPTIONS, at least one" diff --git a/paludis/repositories/e/dep_parser.cc b/paludis/repositories/e/dep_parser.cc index 9906942d1..2d811f090 100644 --- a/paludis/repositories/e/dep_parser.cc +++ b/paludis/repositories/e/dep_parser.cc @@ -52,6 +52,8 @@ #include <list> #include <set> #include <ostream> +#include <algorithm> +#include <functional> using namespace paludis; using namespace paludis::erepository; @@ -125,10 +127,18 @@ namespace call_annotations_go_here(annotations_go_here, spec); } + enum BlockFixOp + { + bfo_explicit_strong, + bfo_implicit_strong, + bfo_implicit_weak + }; + template <typename T_> void package_or_block_dep_spec_string_handler( const typename ParseStackTypes<T_>::Stack & h, const typename ParseStackTypes<T_>::AnnotationsGoHere & annotations_go_here, + BlockFixOp & block_fix_op, const std::string & s, const EAPI & eapi) { @@ -142,11 +152,17 @@ namespace throw EDepParseError(s, "Double-! blocks not allowed in this EAPI"); specstart = 2; strong = true; + block_fix_op = bfo_explicit_strong; } else { if (eapi.supported()->dependency_spec_tree_parse_options()[dstpo_single_bang_block_is_hard]) + { strong = true; + block_fix_op = bfo_implicit_strong; + } + else + block_fix_op = bfo_implicit_weak; } std::shared_ptr<BlockDepSpec> spec(std::make_shared<BlockDepSpec>( @@ -352,6 +368,68 @@ namespace spec = s; block = b; } + + void fix_block_annotations( + const std::shared_ptr<BlockDepSpec> & if_block_spec, + const BlockFixOp & block_fix_op) + { + if (! if_block_spec) + return; + + DepSpecAnnotationRole current_role(dsar_none); + if (if_block_spec->maybe_annotations()) + current_role = find_blocker_role_in_annotations(if_block_spec->maybe_annotations()); + if (dsar_none != current_role) + return; + + std::shared_ptr<DepSpecAnnotations> annotations(std::make_shared<DepSpecAnnotations>()); + if (if_block_spec->maybe_annotations()) + std::for_each(if_block_spec->maybe_annotations()->begin(), if_block_spec->maybe_annotations()->end(), + std::bind(&DepSpecAnnotations::add, annotations, std::placeholders::_1)); + + switch (block_fix_op) + { + case bfo_explicit_strong: + annotations->add(make_named_values<DepSpecAnnotation>( + n::key() = "<resolution>", + n::kind() = dsak_synthetic, + n::role() = dsar_blocker_strong, + n::value() = "<explicit-strong>" + )); + break; + + case bfo_implicit_strong: + annotations->add(make_named_values<DepSpecAnnotation>( + n::key() = "<resolution>", + n::kind() = dsak_synthetic, + n::role() = dsar_blocker_strong, + n::value() = "<implicit-strong>" + )); + break; + + case bfo_implicit_weak: + annotations->add(make_named_values<DepSpecAnnotation>( + n::key() = "<resolution>", + n::kind() = dsak_synthetic, + n::role() = dsar_blocker_weak, + n::value() = "<implicit-weak>" + )); + break; + } + + if_block_spec->set_annotations(annotations); + } + + void apply_annotations_then_fixup( + const EAPI & eapi, + const std::shared_ptr<DepSpec> & spec, + const std::shared_ptr<BlockDepSpec> & if_block_spec, + const BlockFixOp & block_fix_op, + const std::shared_ptr<const Map<std::string, std::string> > & m) + { + apply_annotations(eapi, spec, if_block_spec, m); + fix_block_annotations(if_block_spec, block_fix_op); + } } std::shared_ptr<DependencySpecTree> @@ -363,6 +441,7 @@ paludis::erepository::parse_depend(const std::string & s, const Environment * co std::shared_ptr<AllDepSpec> spec(std::make_shared<AllDepSpec>()); std::shared_ptr<DepSpec> thing_to_annotate(spec); std::shared_ptr<BlockDepSpec> thing_to_annotate_if_block; + BlockFixOp block_fix_op; std::shared_ptr<DependencySpecTree> top(std::make_shared<DependencySpecTree>(spec)); stack.push_front(make_named_values<ParseStackTypes<DependencySpecTree>::Item>( n::item() = top->top(), @@ -372,8 +451,8 @@ paludis::erepository::parse_depend(const std::string & s, const Environment * co ELikeDepParserCallbacks callbacks( make_named_values<ELikeDepParserCallbacks>( n::on_all() = std::bind(&any_all_handler<DependencySpecTree, AllDepSpec>, std::ref(stack)), - n::on_annotations() = std::bind(&apply_annotations, std::cref(eapi), std::ref(thing_to_annotate), - std::ref(thing_to_annotate_if_block), _1), + n::on_annotations() = std::bind(&apply_annotations_then_fixup, std::cref(eapi), std::cref(thing_to_annotate), + std::cref(thing_to_annotate_if_block), std::cref(block_fix_op), _1), n::on_any() = std::bind(&any_all_handler<DependencySpecTree, AnyDepSpec>, std::ref(stack)), n::on_arrow() = std::bind(&arrows_not_allowed_handler, s, _1, _2), n::on_error() = std::bind(&error_handler, s, _1), @@ -383,14 +462,15 @@ paludis::erepository::parse_depend(const std::string & s, const Environment * co ParseStackTypes<DependencySpecTree>::AnnotationsGoHere(std::bind( &set_thing_to_annotate_maybe_block, std::ref(thing_to_annotate), _1, std::ref(thing_to_annotate_if_block), _2)), _1, std::cref(eapi)), - n::on_no_annotations() = &do_nothing, + n::on_no_annotations() = std::bind(&fix_block_annotations, std::cref(thing_to_annotate_if_block), std::cref(block_fix_op)), n::on_pop() = std::bind(&pop_handler<DependencySpecTree>, std::ref(stack), ParseStackTypes<DependencySpecTree>::AnnotationsGoHere(std::bind( &set_thing_to_annotate_maybe_block, std::ref(thing_to_annotate), _1, std::ref(thing_to_annotate_if_block), _2)), s), n::on_should_be_empty() = std::bind(&should_be_empty_handler<DependencySpecTree>, std::ref(stack), s), n::on_string() = std::bind(&package_or_block_dep_spec_string_handler<DependencySpecTree>, std::ref(stack), ParseStackTypes<DependencySpecTree>::AnnotationsGoHere(std::bind( - &set_thing_to_annotate_maybe_block, std::ref(thing_to_annotate), _1, std::ref(thing_to_annotate_if_block), _2)), _1, eapi), + &set_thing_to_annotate_maybe_block, std::ref(thing_to_annotate), _1, std::ref(thing_to_annotate_if_block), _2)), + std::ref(block_fix_op), _1, eapi), n::on_use() = std::bind(&use_handler<DependencySpecTree>, std::ref(stack), _1, env, std::cref(eapi), is_installed), n::on_use_under_any() = std::bind(&use_under_any_handler, s, std::cref(eapi)) )); |