diff options
-rw-r--r-- | paludis/elike_blocker-fwd.hh | 36 | ||||
-rw-r--r-- | paludis/elike_blocker.cc | 48 | ||||
-rw-r--r-- | paludis/elike_blocker.hh | 25 | ||||
-rw-r--r-- | paludis/elike_blocker.se | 15 | ||||
-rw-r--r-- | paludis/files.m4 | 1 | ||||
-rw-r--r-- | paludis/repositories/e/dep_parser.cc | 68 | ||||
-rw-r--r-- | paludis/resolver/spec_rewriter.cc | 8 | ||||
-rw-r--r-- | src/clients/cave/cmd_execute_resolution.cc | 32 | ||||
-rw-r--r-- | src/clients/cave/resolve_common.cc | 10 |
9 files changed, 193 insertions, 50 deletions
diff --git a/paludis/elike_blocker-fwd.hh b/paludis/elike_blocker-fwd.hh new file mode 100644 index 000000000..b630068e4 --- /dev/null +++ b/paludis/elike_blocker-fwd.hh @@ -0,0 +1,36 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 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 + * 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_ELIKE_BLOCKER_FWD_HH +#define PALUDIS_GUARD_PALUDIS_ELIKE_BLOCKER_FWD_HH 1 + +#include <paludis/util/attributes.hh> +#include <tuple> +#include <string> +#include <iosfwd> + +namespace paludis +{ +#include <paludis/elike_blocker-se.hh> + + std::tuple<ELikeBlockerKind, std::string, std::string> split_elike_blocker( + const std::string &) PALUDIS_VISIBLE PALUDIS_ATTRIBUTE((warn_unused_result)); +} + +#endif diff --git a/paludis/elike_blocker.cc b/paludis/elike_blocker.cc new file mode 100644 index 000000000..1204f668f --- /dev/null +++ b/paludis/elike_blocker.cc @@ -0,0 +1,48 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 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 + * 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/elike_blocker.hh> +#include <paludis/util/exception.hh> +#include <paludis/util/stringify.hh> +#include <istream> +#include <ostream> + +using namespace paludis; + +#include <paludis/elike_blocker-se.cc> + +std::tuple<ELikeBlockerKind, std::string, std::string> +paludis::split_elike_blocker(const std::string & s) +{ + if ((! s.empty()) && '!' == s.at(0)) + { + if (s.length() >= 2) + { + if ('!' == s.at(1)) + return std::make_tuple(ebk_double_bang, s.substr(0, 2), s.substr(2)); + if ('?' == s.at(1)) + return std::make_tuple(ebk_bang_question, s.substr(0, 2), s.substr(2)); + } + + return std::make_tuple(ebk_single_bang, s.substr(0, 1), s.substr(1)); + } + else + return std::make_tuple(ebk_no_block, "", s); +} + diff --git a/paludis/elike_blocker.hh b/paludis/elike_blocker.hh new file mode 100644 index 000000000..c2e9506c3 --- /dev/null +++ b/paludis/elike_blocker.hh @@ -0,0 +1,25 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 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 + * 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_ELIKE_BLOCKER_HH +#define PALUDIS_GUARD_PALUDIS_ELIKE_BLOCKER_HH 1 + +#include <paludis/elike_blocker-fwd.hh> + +#endif diff --git a/paludis/elike_blocker.se b/paludis/elike_blocker.se new file mode 100644 index 000000000..ce865659f --- /dev/null +++ b/paludis/elike_blocker.se @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +# vim: set sw=4 sts=4 et ft=sh : + +make_enum_ELikeBlockerKind() +{ + prefix ebk + + key ebk_no_block "No block" + key ebk_single_bang "Single !" + key ebk_double_bang "Double !!" + key ebk_bang_question "Synthetic !?" + + want_destringify +} + diff --git a/paludis/files.m4 b/paludis/files.m4 index d56179f48..69ebb3b0c 100644 --- a/paludis/files.m4 +++ b/paludis/files.m4 @@ -33,6 +33,7 @@ add(`dep_spec_data', `hh', `cc', `fwd') add(`dep_spec_flattener', `hh', `cc') add(`distribution', `hh', `cc', `impl', `fwd') add(`elf_linkage_checker', `hh', `cc') +add(`elike_blocker', `hh', `cc', `fwd', `se') add(`elike_choices', `hh', `cc', `fwd', `se') add(`elike_dep_parser', `hh', `cc', `fwd', `test') add(`elike_conditional_dep_spec', `hh', `cc', `fwd') diff --git a/paludis/repositories/e/dep_parser.cc b/paludis/repositories/e/dep_parser.cc index 9f37d71a6..878b5ccb5 100644 --- a/paludis/repositories/e/dep_parser.cc +++ b/paludis/repositories/e/dep_parser.cc @@ -48,6 +48,7 @@ #include <paludis/metadata_key.hh> #include <paludis/package_database.hh> #include <paludis/always_enabled_dependency_label.hh> +#include <paludis/elike_blocker.hh> #include <map> #include <list> #include <set> @@ -123,37 +124,50 @@ namespace const std::string & s, const EAPI & eapi) { - if ((! s.empty()) && ('!' == s.at(0))) - { - BlockFixOp op(bfo_implicit_weak); + auto p(split_elike_blocker(s)); - std::string::size_type specstart(1); - if (2 <= s.length() && '!' == s.at(1)) - { - if (! eapi.supported()->dependency_spec_tree_parse_options()[dstpo_double_bang_blocks]) - throw EDepParseError(s, "Double-! blocks not allowed in this EAPI"); - specstart = 2; - op = bfo_explicit_strong; - } - else - { - if (eapi.supported()->dependency_spec_tree_parse_options()[dstpo_single_bang_block_is_hard]) - op = bfo_implicit_strong; - } + switch (std::get<0>(p)) + { + case ebk_no_block: + package_dep_spec_string_handler<T_>(h, annotations_go_here, s, eapi); + break; - std::shared_ptr<BlockDepSpec> spec(std::make_shared<BlockDepSpec>( - s, - parse_elike_package_dep_spec(s.substr(specstart), - eapi.supported()->package_dep_spec_parse_options(), - eapi.supported()->version_spec_options()))); - h.begin()->item()->append(spec); - h.begin()->block_children().push_back(std::make_pair(spec, op)); - h.begin()->children().push_back(spec); + case ebk_bang_question: + throw EDepParseError(s, "!? blocks not allowed here"); + + case ebk_single_bang: + case ebk_double_bang: + { + BlockFixOp op(bfo_implicit_weak); + + if (std::get<0>(p) == ebk_double_bang) + { + if (! eapi.supported()->dependency_spec_tree_parse_options()[dstpo_double_bang_blocks]) + throw EDepParseError(s, "Double-! blocks not allowed in this EAPI"); + op = bfo_explicit_strong; + } + else + { + if (eapi.supported()->dependency_spec_tree_parse_options()[dstpo_single_bang_block_is_hard]) + op = bfo_implicit_strong; + } + + std::shared_ptr<BlockDepSpec> spec(std::make_shared<BlockDepSpec>( + s, + parse_elike_package_dep_spec(std::get<2>(p), + eapi.supported()->package_dep_spec_parse_options(), + eapi.supported()->version_spec_options()))); + h.begin()->item()->append(spec); + h.begin()->block_children().push_back(std::make_pair(spec, op)); + h.begin()->children().push_back(spec); + + annotations_go_here(spec); + } + break; - annotations_go_here(spec); + case last_ebk: + throw InternalError(PALUDIS_HERE, "unhandled ebk"); } - else - package_dep_spec_string_handler<T_>(h, annotations_go_here, s, eapi); } template <typename T_> diff --git a/paludis/resolver/spec_rewriter.cc b/paludis/resolver/spec_rewriter.cc index 716a80e97..d41bd385b 100644 --- a/paludis/resolver/spec_rewriter.cc +++ b/paludis/resolver/spec_rewriter.cc @@ -37,6 +37,7 @@ #include <paludis/package_id.hh> #include <paludis/metadata_key.hh> #include <paludis/partially_made_package_dep_spec.hh> +#include <paludis/elike_blocker.hh> #include <map> #include <set> @@ -132,11 +133,8 @@ SpecRewriter::rewrite_if_special(const PackageOrBlockDepSpec & s, const std::sha continue; PackageDepSpec spec(PartiallyMadePackageDepSpec(s.if_block()->blocking()).package(*n)); - std::string prefix(s.if_block()->text()); - std::string::size_type p(prefix.find_first_not_of('!')); - if (std::string::npos != p) - prefix.erase(p); - BlockDepSpec b(prefix + stringify(spec), spec); + auto p(split_elike_blocker(s.if_block()->text())); + BlockDepSpec b(std::get<1>(p) + stringify(spec), spec); b.set_annotations(s.if_block()->maybe_annotations()); result->specs()->push_back(b); } diff --git a/src/clients/cave/cmd_execute_resolution.cc b/src/clients/cave/cmd_execute_resolution.cc index 4e14b80bc..e1bdc14b4 100644 --- a/src/clients/cave/cmd_execute_resolution.cc +++ b/src/clients/cave/cmd_execute_resolution.cc @@ -79,6 +79,7 @@ #include <paludis/filtered_generator.hh> #include <paludis/filter.hh> #include <paludis/package_database.hh> +#include <paludis/elike_blocker.hh> #include <set> #include <iterator> @@ -658,23 +659,26 @@ namespace a_end(cmdline.a_world_specs.end_args()) ; a != a_end ; ++a) { - std::string aa(*a); - if (aa.empty()) - continue; - - if ('!' == aa.at(0)) - { - if (! removes) - continue; - aa.erase(0, 1); - } - else + auto p(split_elike_blocker(*a)); + switch (std::get<0>(p)) { - if (removes) - continue; + case ebk_no_block: + if (removes) + continue; + break; + + case ebk_single_bang: + case ebk_bang_question: + case ebk_double_bang: + if (! removes) + continue; + break; + + case last_ebk: + throw InternalError(PALUDIS_HERE, "unhandled ebk"); } - PackageDepSpec spec(parse_user_package_dep_spec(aa, env.get(), { updso_no_disambiguation })); + PackageDepSpec spec(parse_user_package_dep_spec(std::get<2>(p), env.get(), { updso_no_disambiguation })); if (package_dep_spec_has_properties(spec, make_named_values<PackageDepSpecProperties>( n::has_additional_requirements() = false, n::has_category_name_part() = false, diff --git a/src/clients/cave/resolve_common.cc b/src/clients/cave/resolve_common.cc index df6193dd4..98d193ce5 100644 --- a/src/clients/cave/resolve_common.cc +++ b/src/clients/cave/resolve_common.cc @@ -106,6 +106,7 @@ #include <paludis/filter.hh> #include <paludis/generator.hh> #include <paludis/selection.hh> +#include <paludis/elike_blocker.hh> #include <algorithm> #include <iostream> @@ -147,19 +148,20 @@ namespace std::string p_suggesion(p->first); try { + auto b(split_elike_blocker(p->first)); - if ('!' == p->first.at(0)) + if (ebk_no_block != std::get<0>(b)) { - p_suggesion.erase(0, 1); + p_suggesion = std::get<2>(b); seen_packages = true; - PackageDepSpec s(parse_spec_with_nice_error(p->first.substr(1), env.get(), { }, filter::All())); + PackageDepSpec s(parse_spec_with_nice_error(std::get<2>(b), env.get(), { }, filter::All())); BlockDepSpec bs(make_uninstall_blocker(s)); result->push_back(stringify(bs)); resolver->add_target(bs, p->second); } else { - PackageDepSpec s(parse_spec_with_nice_error(p->first, env.get(), { updso_throw_if_set }, filter::All())); + PackageDepSpec s(parse_spec_with_nice_error(std::get<2>(b), env.get(), { updso_throw_if_set }, filter::All())); result->push_back(stringify(s)); resolver->add_target(s, p->second); seen_packages = true; |