aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2008-01-01 02:22:10 +0000
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2008-01-01 02:22:10 +0000
commitc22bb23c8a0c37cc817251489a83744eef91117c (patch)
tree9c114835c1a03c2410b2fe306e4f08abea57855d
parent5af96b9e2a15827bc49e24af497571b45959ca6a (diff)
downloadpaludis-c22bb23c8a0c37cc817251489a83744eef91117c.tar.gz
paludis-c22bb23c8a0c37cc817251489a83744eef91117c.tar.xz
Move pipe command handler into its own files. Make locked_pipe_command work in global scope when PATH is empty. Add initial skeleton for ever, as a proof of concept.
-rw-r--r--paludis/repositories/e/Makefile.am3
-rw-r--r--paludis/repositories/e/e_repository_TEST.cc11
-rwxr-xr-xpaludis/repositories/e/e_repository_TEST_setup.sh27
-rw-r--r--paludis/repositories/e/ebuild.cc199
-rw-r--r--paludis/repositories/e/ebuild.hh5
-rw-r--r--paludis/repositories/e/ebuild/Makefile.am1
-rwxr-xr-xpaludis/repositories/e/ebuild/ebuild.bash4
-rw-r--r--paludis/repositories/e/ebuild/ever_functions.bash27
-rw-r--r--paludis/repositories/e/ebuild/exheres-0/Makefile.am1
-rw-r--r--paludis/repositories/e/ebuild/exheres-0/ever_functions.bash67
-rw-r--r--paludis/repositories/e/pipe_command_handler.cc263
-rw-r--r--paludis/repositories/e/pipe_command_handler.hh38
12 files changed, 444 insertions, 202 deletions
diff --git a/paludis/repositories/e/Makefile.am b/paludis/repositories/e/Makefile.am
index f1a2d44..38cd590 100644
--- a/paludis/repositories/e/Makefile.am
+++ b/paludis/repositories/e/Makefile.am
@@ -80,6 +80,7 @@ paludis_repositories_e_include_HEADERS = \
manifest2_entry-sr.hh \
manifest2_reader.hh \
package_dep_spec.hh \
+ pipe_command_handler.hh \
source_uri_finder.hh \
traditional_layout.hh \
use_desc.hh \
@@ -127,6 +128,7 @@ libpaludiserepository_la_SOURCES = \
make_ebuild_repository.cc \
manifest2_reader.cc \
package_dep_spec.cc \
+ pipe_command_handler.cc \
registration.cc \
source_uri_finder.cc \
traditional_layout.cc \
@@ -388,6 +390,7 @@ TESTS_ENVIRONMENT = env \
TEST_SCRIPT_DIR="$(srcdir)/" \
PALUDIS_REPOSITORY_SO_DIR="$(top_builddir)/paludis/repositories" \
PALUDIS_NO_CHOWN="yes" \
+ PALUDIS_TESTS_KEEP_STDERR="yes" \
LD_LIBRARY_PATH="`echo $$LD_LIBRARY_PATH: | sed -e 's,^:,,'`` \
$(top_srcdir)/paludis/repositories/e/ebuild/utils/canonicalise $(top_builddir)/paludis/repositories/e/`:` \
$(top_srcdir)/paludis/repositories/e/ebuild/utils/canonicalise $(top_builddir)/paludis/repositories/e/.libs/`" \
diff --git a/paludis/repositories/e/e_repository_TEST.cc b/paludis/repositories/e/e_repository_TEST.cc
index db07461..73b3510 100644
--- a/paludis/repositories/e/e_repository_TEST.cc
+++ b/paludis/repositories/e/e_repository_TEST.cc
@@ -1328,6 +1328,17 @@ namespace test_cases
TEST_CHECK(id);
TEST_CHECK_THROWS(id->perform_action(action), InstallActionError);
}
+
+ {
+ TestMessageSuffix suffix("ever", true);
+ const tr1::shared_ptr<const PackageID> id(*env.package_database()->query(query::Matches(
+ PackageDepSpec(parse_user_package_dep_spec("=cat/ever-1.3",
+ UserPackageDepSpecOptions()))), qo_require_exactly_one)->last());
+ TEST_CHECK(id);
+ TEST_CHECK(id->short_description_key());
+ TEST_CHECK_EQUAL(id->short_description_key()->value(), "The Description");
+ id->perform_action(action);
+ }
}
} test_e_repository_install_exheres_0;
}
diff --git a/paludis/repositories/e/e_repository_TEST_setup.sh b/paludis/repositories/e/e_repository_TEST_setup.sh
index 04e86e5..b4e01b0 100755
--- a/paludis/repositories/e/e_repository_TEST_setup.sh
+++ b/paludis/repositories/e/e_repository_TEST_setup.sh
@@ -857,6 +857,33 @@ pkg_setup() {
done
}
END
+mkdir -p "packages/cat/ever"
+cat <<'END' > packages/cat/ever/ever-1.3.ebuild || exit 1
+if ever at_least 2 ; then
+ DESCRIPTION="Really Not The Description"
+elif ever at_least 1.2.3 ; then
+ DESCRIPTION="The Description"
+else
+ DESCRIPTION="Not The Description"
+fi
+
+HOMEPAGE="http://example.com/"
+SRC_URI=""
+SLOT="0"
+MYOPTIONS="spork"
+LICENSE="GPL-2"
+PLATFORM="test"
+
+pkg_setup() {
+ ever at_least 1.2 || die "at_least 1.2"
+ ever at_least 1.3 || die "at_least 1.3"
+ ever at_least 1.4 && die "at_least 1.4"
+
+ ever at_least 1.2 1.2 || die "at_least 1.2 1.2"
+ ever at_least 1.3 1.2 && die "at_least 1.3 1.2"
+ ever at_least 1.4 1.2 && die "at_least 1.4 1.2"
+}
+END
cd ..
mkdir -p repo15/{eclass,distfiles,profiles/profile/subprofile} || exit 1
diff --git a/paludis/repositories/e/ebuild.cc b/paludis/repositories/e/ebuild.cc
index eafea98..5e83649 100644
--- a/paludis/repositories/e/ebuild.cc
+++ b/paludis/repositories/e/ebuild.cc
@@ -23,6 +23,7 @@
#include <paludis/repositories/e/eapi.hh>
#include <paludis/repositories/e/dep_parser.hh>
#include <paludis/repositories/e/package_dep_spec.hh>
+#include <paludis/repositories/e/pipe_command_handler.hh>
#include <paludis/util/system.hh>
#include <paludis/util/strip.hh>
@@ -54,7 +55,6 @@
#include <unistd.h>
#include <list>
-#include <vector>
#include "config.h"
@@ -103,7 +103,7 @@ EbuildCommand::operator() ()
cmd.with_uid_gid(params.environment->reduced_uid(), params.environment->reduced_gid());
using namespace tr1::placeholders;
- cmd.with_pipe_command_handler(tr1::bind(tr1::mem_fn(&EbuildCommand::pipe_command_handler), this, _1));
+ cmd.with_pipe_command_handler(tr1::bind(&pipe_command_handler, params.environment, params.package_id, _1));
tr1::shared_ptr<const FSEntrySequence> syncers_dirs(params.environment->syncers_dirs());
tr1::shared_ptr<const FSEntrySequence> bashrc_files(params.environment->bashrc_files());
@@ -228,201 +228,6 @@ EbuildCommand::do_run_command(const Command & cmd)
return 0 == run_command(cmd);
}
-namespace
-{
- std::string name_and_version(const PackageID & id)
- {
- return stringify(id.name()) + "-" + stringify(id.version());
- }
-}
-
-std::string
-EbuildCommand::pipe_command_handler(const std::string & s) const
-{
- Context context("In ebuild pipe command handler for '" + s + "':");
-
- try
- {
- std::vector<std::string> tokens;
- tokenise_whitespace(s, std::back_inserter(tokens));
- if (tokens.empty())
- {
- Log::get_instance()->message(ll_warning, lc_context) << "Got empty pipe command";
- return "Eempty pipe command";
- }
-
- if (tokens[0] == "PING")
- {
- if (tokens.size() != 3)
- {
- Log::get_instance()->message(ll_warning, lc_context) << "Got bad PING command";
- return "Ebad PING command";
- }
- else
- return "OPONG " + tokens[2];
- }
- else if (tokens[0] == "LOG")
- {
- if (tokens.size() < 4)
- {
- Log::get_instance()->message(ll_warning, lc_context) << "Got too short LOG pipe command";
- return "Ebad LOG command";
- }
- else
- {
- Log::get_instance()->message(destringify<LogLevel>(tokens[2]), lc_context) << join(next(next(next(tokens.begin()))),
- tokens.end(), " ");
- return "O";
- }
- }
- else if (tokens[0] == "BEST_VERSION")
- {
- if (tokens.size() != 3)
- {
- Log::get_instance()->message(ll_warning, lc_context) << "Got bad BEST_VERSION pipe command";
- return "Ebad BEST_VERSION command";
- }
- else
- {
- tr1::shared_ptr<const EAPI> eapi(EAPIData::get_instance()->eapi_from_string(tokens[1]));
- if (! eapi->supported)
- return "EBEST_VERSION EAPI " + tokens[1] + " unsupported";
-
- PackageDepSpec spec(erepository::parse_e_package_dep_spec(tokens[2], *eapi, params.package_id));
- tr1::shared_ptr<const PackageIDSequence> entries(params.environment->package_database()->query(
- query::Matches(spec) & query::InstalledAtRoot(params.environment->root()), qo_order_by_version));
- if (eapi->supported->pipe_commands->rewrite_virtuals && (! entries->empty()) &&
- (*entries->last())->virtual_for_key())
- {
- Log::get_instance()->message(ll_qa, lc_context) << "best-version of '" << spec <<
- "' resolves to '" << **entries->last() << "', which is a virtual for '"
- << *(*entries->last())->virtual_for_key()->value() << "'. This will break with "
- "new style virtuals.";
- tr1::shared_ptr<PackageIDSequence> new_entries(new PackageIDSequence);
- new_entries->push_back((*entries->last())->virtual_for_key()->value());
- entries = new_entries;
- }
-
- if (entries->empty())
- return "O1;";
- else
- {
- if (eapi->supported->pipe_commands->no_slot_or_repo)
- return "O0;" + name_and_version(**entries->last());
- else
- return "O0;" + stringify(**entries->last());
- }
- }
- }
- else if (tokens[0] == "HAS_VERSION")
- {
- if (tokens.size() != 3)
- {
- Log::get_instance()->message(ll_warning, lc_context) << "Got bad HAS_VERSION pipe command";
- return "Ebad HAS_VERSION command";
- }
- else
- {
- tr1::shared_ptr<const EAPI> eapi(EAPIData::get_instance()->eapi_from_string(tokens[1]));
- if (! eapi->supported)
- return "EHAS_VERSION EAPI " + tokens[1] + " unsupported";
-
- PackageDepSpec spec(erepository::parse_e_package_dep_spec(tokens[2], *eapi, params.package_id));
- tr1::shared_ptr<const PackageIDSequence> entries(params.environment->package_database()->query(
- query::Matches(spec) & query::InstalledAtRoot(params.environment->root()), qo_order_by_version));
- if (entries->empty())
- return "O1;";
- else
- return "O0;";
- }
- }
- else if (tokens[0] == "MATCH")
- {
- if (tokens.size() != 3)
- {
- Log::get_instance()->message(ll_warning, lc_context) << "Got bad MATCH pipe command";
- return "Ebad MATCH command";
- }
- else
- {
- tr1::shared_ptr<const EAPI> eapi(EAPIData::get_instance()->eapi_from_string(tokens[1]));
- if (! eapi->supported)
- return "EMATCH EAPI " + tokens[1] + " unsupported";
-
- PackageDepSpec spec(erepository::parse_e_package_dep_spec(tokens[2], *eapi, params.package_id));
- tr1::shared_ptr<const PackageIDSequence> entries(params.environment->package_database()->query(
- query::Matches(spec) & query::InstalledAtRoot(params.environment->root()), qo_order_by_version));
- if (eapi->supported->pipe_commands->rewrite_virtuals && (! entries->empty()))
- {
- tr1::shared_ptr<PackageIDSequence> new_entries(new PackageIDSequence);
- for (PackageIDSequence::ConstIterator i(entries->begin()), i_end(entries->end()) ;
- i != i_end ; ++i)
- {
- if ((*i)->virtual_for_key())
- {
- Log::get_instance()->message(ll_qa, lc_context) << "match of '" << spec <<
- "' resolves to '" << **i << "', which is a virtual for '"
- << *(*i)->virtual_for_key()->value() << "'. This will break with "
- "new style virtuals.";
- new_entries->push_back((*i)->virtual_for_key()->value());
- }
- else
- new_entries->push_back(*i);
- }
- entries = new_entries;
- }
-
- if (entries->empty())
- return "O1;";
- else
- {
- if (eapi->supported->pipe_commands->no_slot_or_repo)
- return "O0;" + join(indirect_iterator(entries->begin()), indirect_iterator(entries->end()), "\n", &name_and_version);
- else
- return "O0;" + join(indirect_iterator(entries->begin()), indirect_iterator(entries->end()), "\n");
- }
- }
- }
- else if (tokens[0] == "VDB_PATH")
- {
- if (tokens.size() != 2)
- {
- Log::get_instance()->message(ll_warning, lc_context) << "Got bad VDB_PATH pipe command";
- return "Ebad VDB_PATH command";
- }
- else
- {
- if (! params.environment->package_database()->has_repository_named(RepositoryName("installed")))
- return "Eno installed repository available";
- tr1::shared_ptr<const Repository> repo(params.environment->package_database()->fetch_repository(RepositoryName("installed")));
- Repository::MetadataConstIterator key(repo->find_metadata("location"));
- if (repo->end_metadata() == key)
- return "Einstalled repository has no location key";
- if (! visitor_cast<const MetadataFSEntryKey>(**key))
- return "Einstalled repository location key is not a MetadataFSEntryKey";
- return "O0;" + stringify(visitor_cast<const MetadataFSEntryKey>(**key)->value());
- }
- }
- else
- {
- Log::get_instance()->message(ll_warning, lc_context) << "Got unknown ebuild pipe command '" + s + "'";
- return "Eunknown pipe command";
- }
- }
- catch (const Exception & e)
- {
- return "Eexception '" + e.message() + "' (" + e.what() + ")";
- }
- catch (const std::exception & e)
- {
- return "Eexception " + stringify(e.what());
- }
- catch (...)
- {
- return "Eexception ???";
- }
-}
-
EbuildMetadataCommand::EbuildMetadataCommand(const EbuildCommandParams & p) :
EbuildCommand(p)
{
diff --git a/paludis/repositories/e/ebuild.hh b/paludis/repositories/e/ebuild.hh
index e1c6cb9..9101c6d 100644
--- a/paludis/repositories/e/ebuild.hh
+++ b/paludis/repositories/e/ebuild.hh
@@ -112,11 +112,6 @@ namespace paludis
*/
virtual Command extend_command(const Command &) = 0;
- /**
- * Pipe command handler.
- */
- virtual std::string pipe_command_handler(const std::string &) const;
-
public:
/**
* Destructor.
diff --git a/paludis/repositories/e/ebuild/Makefile.am b/paludis/repositories/e/ebuild/Makefile.am
index fc45836..a81190a 100644
--- a/paludis/repositories/e/ebuild/Makefile.am
+++ b/paludis/repositories/e/ebuild/Makefile.am
@@ -24,6 +24,7 @@ libexecprog_SCRIPTS = \
echo_functions.bash \
kernel_functions.bash \
eclass_functions.bash \
+ ever_functions.bash \
exlib_functions.bash \
install_functions.bash \
list_functions.bash \
diff --git a/paludis/repositories/e/ebuild/ebuild.bash b/paludis/repositories/e/ebuild/ebuild.bash
index f2b3763..555e56f 100755
--- a/paludis/repositories/e/ebuild/ebuild.bash
+++ b/paludis/repositories/e/ebuild/ebuild.bash
@@ -131,6 +131,7 @@ ebuild_load_module echo_functions
ebuild_load_module kernel_functions
ebuild_load_module sandbox
ebuild_load_module portage_stubs
+ebuild_load_module ever_functions
ebuild_load_module list_functions
ebuild_load_module multilib_functions
ebuild_load_module install_functions
@@ -437,6 +438,9 @@ ebuild_main()
eval "export ebuild_real_${f}=\"$(which $f )\""
eval "${f}() { ebuild_notice qa 'global scope ${f}' ; $(which $f ) \"\$@\" ; }"
done
+ for f in locked_pipe_command ; do
+ eval "${f}() { $(which $f ) \"\$@\" ; }"
+ done
PATH="" ebuild_load_ebuild "${ebuild}"
fi
if ! ebuild_f_${1} ; then
diff --git a/paludis/repositories/e/ebuild/ever_functions.bash b/paludis/repositories/e/ebuild/ever_functions.bash
new file mode 100644
index 0000000..09249dc
--- /dev/null
+++ b/paludis/repositories/e/ebuild/ever_functions.bash
@@ -0,0 +1,27 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2008 Ciaran McCreesh
+#
+# Based in part upon ebuild.sh from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# 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
+
+ever()
+{
+ die "Function 'ever' banned in this EAPI"
+}
+
diff --git a/paludis/repositories/e/ebuild/exheres-0/Makefile.am b/paludis/repositories/e/ebuild/exheres-0/Makefile.am
index c7d058b..18be6c9 100644
--- a/paludis/repositories/e/ebuild/exheres-0/Makefile.am
+++ b/paludis/repositories/e/ebuild/exheres-0/Makefile.am
@@ -9,6 +9,7 @@ libexecprogexheres_SCRIPTS = \
pkg_nofetch.bash \
list_functions.bash \
echo_functions.bash \
+ ever_functions.bash \
portage_stubs.bash
TESTS_ENVIRONMENT = env \
diff --git a/paludis/repositories/e/ebuild/exheres-0/ever_functions.bash b/paludis/repositories/e/ebuild/exheres-0/ever_functions.bash
new file mode 100644
index 0000000..bbdd1c5
--- /dev/null
+++ b/paludis/repositories/e/ebuild/exheres-0/ever_functions.bash
@@ -0,0 +1,67 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2008 Ciaran McCreesh
+#
+# Based in part upon ebuild.sh from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# 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
+
+ever()
+{
+ local r="1;"
+ case "${1}" in
+ split)
+ ;;
+
+ split_all)
+ ;;
+
+ major)
+ ;;
+
+ range)
+ ;;
+
+ remainder)
+ ;;
+
+ replace_separator)
+ ;;
+
+ replace_all_separators)
+ ;;
+
+ delete_separator)
+ ;;
+
+ delete_all_separators)
+ ;;
+
+ at_least)
+ [[ "${#@}" != 2 ]] && [[ "${#@}" != 3 ]] && die "$0 $1 takes one or two extra arguments"
+ r=$(paludis_pipe_command EVER "$EAPI" AT_LEAST "${2}" "${3:-${PVR}}" )
+ ;;
+
+ *)
+ die "ever subcommand ${1} unrecognised"
+ ;;
+ esac
+
+ [[ -z "${r#*;}" ]] || echo "${r#*;}"
+ return ${r%%;*}
+}
+
diff --git a/paludis/repositories/e/pipe_command_handler.cc b/paludis/repositories/e/pipe_command_handler.cc
new file mode 100644
index 0000000..e890007
--- /dev/null
+++ b/paludis/repositories/e/pipe_command_handler.cc
@@ -0,0 +1,263 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007, 2008 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/repositories/e/pipe_command_handler.hh>
+#include <paludis/repositories/e/eapi.hh>
+#include <paludis/repositories/e/package_dep_spec.hh>
+#include <paludis/util/log.hh>
+#include <paludis/util/join.hh>
+#include <paludis/util/exception.hh>
+#include <paludis/util/tokeniser.hh>
+#include <paludis/util/destringify.hh>
+#include <paludis/util/iterator_funcs.hh>
+#include <paludis/util/sequence.hh>
+#include <paludis/util/wrapped_forward_iterator.hh>
+#include <paludis/util/visitor-impl.hh>
+#include <paludis/util/visitor_cast.hh>
+#include <paludis/util/set.hh>
+#include <paludis/package_id.hh>
+#include <paludis/environment.hh>
+#include <paludis/package_database.hh>
+#include <paludis/metadata_key.hh>
+#include <vector>
+
+using namespace paludis;
+
+namespace
+{
+ std::string name_and_version(const PackageID & id)
+ {
+ return stringify(id.name()) + "-" + stringify(id.version());
+ }
+}
+
+std::string
+paludis::erepository::pipe_command_handler(const Environment * const environment,
+ const tr1::shared_ptr<const PackageID> & package_id, const std::string & s)
+{
+ Context context("In ebuild pipe command handler for '" + s + "':");
+
+ try
+ {
+ std::vector<std::string> tokens;
+ tokenise_whitespace(s, std::back_inserter(tokens));
+ if (tokens.empty())
+ {
+ Log::get_instance()->message(ll_warning, lc_context) << "Got empty pipe command";
+ return "Eempty pipe command";
+ }
+
+ if (tokens[0] == "PING")
+ {
+ if (tokens.size() != 3)
+ {
+ Log::get_instance()->message(ll_warning, lc_context) << "Got bad PING command";
+ return "Ebad PING command";
+ }
+ else
+ return "OPONG " + tokens[2];
+ }
+ else if (tokens[0] == "LOG")
+ {
+ if (tokens.size() < 4)
+ {
+ Log::get_instance()->message(ll_warning, lc_context) << "Got too short LOG pipe command";
+ return "Ebad LOG command";
+ }
+ else
+ {
+ Log::get_instance()->message(destringify<LogLevel>(tokens[2]), lc_context) << join(next(next(next(tokens.begin()))),
+ tokens.end(), " ");
+ return "O";
+ }
+ }
+ else if (tokens[0] == "BEST_VERSION")
+ {
+ if (tokens.size() != 3)
+ {
+ Log::get_instance()->message(ll_warning, lc_context) << "Got bad BEST_VERSION pipe command";
+ return "Ebad BEST_VERSION command";
+ }
+ else
+ {
+ tr1::shared_ptr<const EAPI> eapi(EAPIData::get_instance()->eapi_from_string(tokens[1]));
+ if (! eapi->supported)
+ return "EBEST_VERSION EAPI " + tokens[1] + " unsupported";
+
+ PackageDepSpec spec(erepository::parse_e_package_dep_spec(tokens[2], *eapi, package_id));
+ tr1::shared_ptr<const PackageIDSequence> entries(environment->package_database()->query(
+ query::Matches(spec) & query::InstalledAtRoot(environment->root()), qo_order_by_version));
+ if (eapi->supported->pipe_commands->rewrite_virtuals && (! entries->empty()) &&
+ (*entries->last())->virtual_for_key())
+ {
+ Log::get_instance()->message(ll_qa, lc_context) << "best-version of '" << spec <<
+ "' resolves to '" << **entries->last() << "', which is a virtual for '"
+ << *(*entries->last())->virtual_for_key()->value() << "'. This will break with "
+ "new style virtuals.";
+ tr1::shared_ptr<PackageIDSequence> new_entries(new PackageIDSequence);
+ new_entries->push_back((*entries->last())->virtual_for_key()->value());
+ entries = new_entries;
+ }
+
+ if (entries->empty())
+ return "O1;";
+ else
+ {
+ if (eapi->supported->pipe_commands->no_slot_or_repo)
+ return "O0;" + name_and_version(**entries->last());
+ else
+ return "O0;" + stringify(**entries->last());
+ }
+ }
+ }
+ else if (tokens[0] == "HAS_VERSION")
+ {
+ if (tokens.size() != 3)
+ {
+ Log::get_instance()->message(ll_warning, lc_context) << "Got bad HAS_VERSION pipe command";
+ return "Ebad HAS_VERSION command";
+ }
+ else
+ {
+ tr1::shared_ptr<const EAPI> eapi(EAPIData::get_instance()->eapi_from_string(tokens[1]));
+ if (! eapi->supported)
+ return "EHAS_VERSION EAPI " + tokens[1] + " unsupported";
+
+ PackageDepSpec spec(erepository::parse_e_package_dep_spec(tokens[2], *eapi, package_id));
+ tr1::shared_ptr<const PackageIDSequence> entries(environment->package_database()->query(
+ query::Matches(spec) & query::InstalledAtRoot(environment->root()), qo_order_by_version));
+ if (entries->empty())
+ return "O1;";
+ else
+ return "O0;";
+ }
+ }
+ else if (tokens[0] == "MATCH")
+ {
+ if (tokens.size() != 3)
+ {
+ Log::get_instance()->message(ll_warning, lc_context) << "Got bad MATCH pipe command";
+ return "Ebad MATCH command";
+ }
+ else
+ {
+ tr1::shared_ptr<const EAPI> eapi(EAPIData::get_instance()->eapi_from_string(tokens[1]));
+ if (! eapi->supported)
+ return "EMATCH EAPI " + tokens[1] + " unsupported";
+
+ PackageDepSpec spec(erepository::parse_e_package_dep_spec(tokens[2], *eapi, package_id));
+ tr1::shared_ptr<const PackageIDSequence> entries(environment->package_database()->query(
+ query::Matches(spec) & query::InstalledAtRoot(environment->root()), qo_order_by_version));
+ if (eapi->supported->pipe_commands->rewrite_virtuals && (! entries->empty()))
+ {
+ tr1::shared_ptr<PackageIDSequence> new_entries(new PackageIDSequence);
+ for (PackageIDSequence::ConstIterator i(entries->begin()), i_end(entries->end()) ;
+ i != i_end ; ++i)
+ {
+ if ((*i)->virtual_for_key())
+ {
+ Log::get_instance()->message(ll_qa, lc_context) << "match of '" << spec <<
+ "' resolves to '" << **i << "', which is a virtual for '"
+ << *(*i)->virtual_for_key()->value() << "'. This will break with "
+ "new style virtuals.";
+ new_entries->push_back((*i)->virtual_for_key()->value());
+ }
+ else
+ new_entries->push_back(*i);
+ }
+ entries = new_entries;
+ }
+
+ if (entries->empty())
+ return "O1;";
+ else
+ {
+ if (eapi->supported->pipe_commands->no_slot_or_repo)
+ return "O0;" + join(indirect_iterator(entries->begin()), indirect_iterator(entries->end()), "\n", &name_and_version);
+ else
+ return "O0;" + join(indirect_iterator(entries->begin()), indirect_iterator(entries->end()), "\n");
+ }
+ }
+ }
+ else if (tokens[0] == "VDB_PATH")
+ {
+ if (tokens.size() != 2)
+ {
+ Log::get_instance()->message(ll_warning, lc_context) << "Got bad VDB_PATH pipe command";
+ return "Ebad VDB_PATH command";
+ }
+ else
+ {
+ if (! environment->package_database()->has_repository_named(RepositoryName("installed")))
+ return "Eno installed repository available";
+ tr1::shared_ptr<const Repository> repo(environment->package_database()->fetch_repository(RepositoryName("installed")));
+ Repository::MetadataConstIterator key(repo->find_metadata("location"));
+ if (repo->end_metadata() == key)
+ return "Einstalled repository has no location key";
+ if (! visitor_cast<const MetadataFSEntryKey>(**key))
+ return "Einstalled repository location key is not a MetadataFSEntryKey";
+ return "O0;" + stringify(visitor_cast<const MetadataFSEntryKey>(**key)->value());
+ }
+ }
+ else if (tokens[0] == "EVER")
+ {
+ if (tokens.size() < 3)
+ {
+ Log::get_instance()->message(ll_warning, lc_context) << "Got bad EVER pipe command";
+ return "Ebad EVER command";
+ }
+
+ if (tokens[2] == "AT_LEAST")
+ {
+ if (tokens.size() != 5)
+ {
+ Log::get_instance()->message(ll_warning, lc_context) << "Got bad EVER AT_LEAST pipe command";
+ return "Ebad EVER AT_LEAST command {'" + join(tokens.begin(), tokens.end(), "', '") + "'}";
+ }
+
+ VersionSpec v1(tokens[3]), v2(tokens[4]);
+ return v2 >= v1 ? "O0;" : "O1;";
+ }
+ else
+ {
+ Log::get_instance()->message(ll_warning, lc_context) << "Got unknown EVER pipe subcommand";
+ return "Ebad EVER subcommand";
+ }
+ }
+ else
+ {
+ Log::get_instance()->message(ll_warning, lc_context) << "Got unknown ebuild pipe command '" + s + "'";
+ return "Eunknown pipe command";
+ }
+ }
+ catch (const Exception & e)
+ {
+ return "Eexception '" + e.message() + "' (" + e.what() + ")";
+ }
+ catch (const std::exception & e)
+ {
+ return "Eexception " + stringify(e.what());
+ }
+ catch (...)
+ {
+ return "Eexception ???";
+ }
+}
+
+
diff --git a/paludis/repositories/e/pipe_command_handler.hh b/paludis/repositories/e/pipe_command_handler.hh
new file mode 100644
index 0000000..223bba4
--- /dev/null
+++ b/paludis/repositories/e/pipe_command_handler.hh
@@ -0,0 +1,38 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 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_REPOSITORIES_E_PIPE_COMMAND_HANDLER_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_E_PIPE_COMMAND_HANDLER_HH 1
+
+#include <paludis/environment-fwd.hh>
+#include <paludis/package_id-fwd.hh>
+#include <paludis/util/tr1_functional.hh>
+#include <string>
+
+namespace paludis
+{
+ namespace erepository
+ {
+ std::string pipe_command_handler(const Environment * const,
+ const tr1::shared_ptr<const PackageID> &,
+ const std::string & s);
+ }
+}
+
+#endif