aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2010-12-05 16:14:14 +0000
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2010-12-05 21:19:06 +0000
commit74d54724984bc1b3fa49414995151edfe031e368 (patch)
tree1c72f0f666f9dfe358ff794533ebee152c16dd57
parentd97eebaccb30a9669471516db9e7243420cbae47 (diff)
downloadpaludis-74d54724984bc1b3fa49414995151edfe031e368.tar.gz
paludis-74d54724984bc1b3fa49414995151edfe031e368.tar.xz
Split things up
-rw-r--r--paludis/repositories/e/Makefile.am16
-rw-r--r--paludis/repositories/e/a_finder.cc77
-rw-r--r--paludis/repositories/e/a_finder.hh65
-rw-r--r--paludis/repositories/e/check_userpriv.cc65
-rw-r--r--paludis/repositories/e/check_userpriv.hh36
-rw-r--r--paludis/repositories/e/do_fetch_action.cc312
-rw-r--r--paludis/repositories/e/do_fetch_action.hh41
-rw-r--r--paludis/repositories/e/do_info_action.cc127
-rw-r--r--paludis/repositories/e/do_info_action.hh41
-rw-r--r--paludis/repositories/e/do_install_action.cc438
-rw-r--r--paludis/repositories/e/do_install_action.hh42
-rw-r--r--paludis/repositories/e/do_pretend_action.cc201
-rw-r--r--paludis/repositories/e/do_pretend_action.hh41
-rw-r--r--paludis/repositories/e/do_pretend_fetch_action.cc47
-rw-r--r--paludis/repositories/e/do_pretend_fetch_action.hh41
-rw-r--r--paludis/repositories/e/e_repository.cc1135
-rw-r--r--paludis/repositories/e/e_repository.hh17
-rw-r--r--paludis/repositories/e/ebuild_id.cc37
-rw-r--r--paludis/repositories/e/make_use.cc115
-rw-r--r--paludis/repositories/e/make_use.hh42
20 files changed, 1788 insertions, 1148 deletions
diff --git a/paludis/repositories/e/Makefile.am b/paludis/repositories/e/Makefile.am
index b71a2aa..52fe10f 100644
--- a/paludis/repositories/e/Makefile.am
+++ b/paludis/repositories/e/Makefile.am
@@ -20,14 +20,21 @@ lib_LTLIBRARIES = libpaludiserepositoryxmlthings_@PALUDIS_PC_SLOT@.la
endif
noinst_HEADERS = \
+ a_finder.hh \
aa_visitor.hh \
can_skip_phase.hh \
check_fetched_files_visitor.hh \
+ check_userpriv.hh \
dep_parser.hh \
dep_parser-se.hh \
dep_parser-fwd.hh \
dep_spec_pretty_printer.hh \
dependencies_rewriter.hh \
+ do_fetch_action.hh \
+ do_info_action.hh \
+ do_install_action.hh \
+ do_pretend_action.hh \
+ do_pretend_fetch_action.hh \
e_choice_value.hh \
e_installed_repository.hh \
e_installed_repository_id.hh \
@@ -63,6 +70,7 @@ noinst_HEADERS = \
fix_locked_dependencies.hh \
glsa.hh \
layout.hh \
+ make_use.hh \
manifest2_reader.hh \
memoised_hashes.hh \
metadata_xml.hh \
@@ -84,12 +92,19 @@ noinst_HEADERS = \
vdb_unmerger.hh
libpaludiserepository_la_SOURCES = \
+ a_finder.cc \
aa_visitor.cc \
can_skip_phase.cc \
check_fetched_files_visitor.cc \
+ check_userpriv.cc \
dep_parser.cc \
dep_spec_pretty_printer.cc \
dependencies_rewriter.cc \
+ do_fetch_action.cc \
+ do_info_action.cc \
+ do_install_action.cc \
+ do_pretend_action.cc \
+ do_pretend_fetch_action.cc \
e_choice_value.cc \
e_installed_repository.cc \
e_installed_repository_id.cc \
@@ -122,6 +137,7 @@ libpaludiserepository_la_SOURCES = \
fix_locked_dependencies.cc \
glsa.cc \
layout.cc \
+ make_use.cc \
manifest2_reader.cc \
memoised_hashes.cc \
metadata_xml.cc \
diff --git a/paludis/repositories/e/a_finder.cc b/paludis/repositories/e/a_finder.cc
new file mode 100644
index 0000000..956d3e1
--- /dev/null
+++ b/paludis/repositories/e/a_finder.cc
@@ -0,0 +1,77 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2010 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/a_finder.hh>
+#include <paludis/util/indirect_iterator-impl.hh>
+#include <paludis/util/accept_visitor.hh>
+#include <algorithm>
+
+using namespace paludis;
+using namespace paludis::erepository;
+
+AFinder::AFinder(const Environment * const e, const std::shared_ptr<const PackageID> & i) :
+ env(e),
+ id(i)
+{
+ _labels.push_back(0);
+}
+
+void
+AFinder::visit(const FetchableURISpecTree::NodeType<FetchableURIDepSpec>::Type & node)
+{
+ _specs.push_back(std::make_pair(node.spec().get(), *_labels.begin()));
+}
+
+void
+AFinder::visit(const FetchableURISpecTree::NodeType<URILabelsDepSpec>::Type & node)
+{
+ *_labels.begin() = node.spec().get();
+}
+
+void
+AFinder::visit(const FetchableURISpecTree::NodeType<AllDepSpec>::Type & node)
+{
+ _labels.push_front(*_labels.begin());
+ std::for_each(indirect_iterator(node.begin()), indirect_iterator(node.end()), accept_visitor(*this));
+ _labels.pop_front();
+}
+
+void
+AFinder::visit(const FetchableURISpecTree::NodeType<ConditionalDepSpec>::Type & node)
+{
+ if (node.spec()->condition_met())
+ {
+ _labels.push_front(*_labels.begin());
+ std::for_each(indirect_iterator(node.begin()), indirect_iterator(node.end()), accept_visitor(*this));
+ _labels.pop_front();
+ }
+}
+
+AFinder::ConstIterator
+AFinder::begin()
+{
+ return _specs.begin();
+}
+
+AFinder::ConstIterator
+AFinder::end() const
+{
+ return _specs.end();
+}
+
diff --git a/paludis/repositories/e/a_finder.hh b/paludis/repositories/e/a_finder.hh
new file mode 100644
index 0000000..f057a20
--- /dev/null
+++ b/paludis/repositories/e/a_finder.hh
@@ -0,0 +1,65 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2010 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_A_FINDER_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_E_A_FINDER_HH 1
+
+#include <paludis/dep_label.hh>
+#include <paludis/environment.hh>
+#include <paludis/package_id.hh>
+#include <paludis/dep_spec.hh>
+#include <paludis/spec_tree.hh>
+#include <memory>
+#include <list>
+
+namespace paludis
+{
+ namespace erepository
+ {
+ class AFinder
+ {
+ private:
+ std::list<std::pair<const FetchableURIDepSpec *, const URILabelsDepSpec *> > _specs;
+ std::list<const URILabelsDepSpec *> _labels;
+
+ const Environment * const env;
+ const std::shared_ptr<const PackageID> id;
+
+ public:
+ AFinder(const Environment * const e, const std::shared_ptr<const PackageID> & i);
+
+ void visit(const FetchableURISpecTree::NodeType<FetchableURIDepSpec>::Type & node);
+
+ void visit(const FetchableURISpecTree::NodeType<URILabelsDepSpec>::Type & node);
+
+ void visit(const FetchableURISpecTree::NodeType<AllDepSpec>::Type & node);
+
+ void visit(const FetchableURISpecTree::NodeType<ConditionalDepSpec>::Type & node);
+
+ typedef std::list<std::pair<const FetchableURIDepSpec *,
+ const URILabelsDepSpec *> >::const_iterator ConstIterator;
+
+ ConstIterator begin();
+
+ ConstIterator end() const;
+ };
+ }
+}
+
+#endif
diff --git a/paludis/repositories/e/check_userpriv.cc b/paludis/repositories/e/check_userpriv.cc
new file mode 100644
index 0000000..d7a0bac
--- /dev/null
+++ b/paludis/repositories/e/check_userpriv.cc
@@ -0,0 +1,65 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2010 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/check_userpriv.hh>
+#include <paludis/util/exception.hh>
+#include <paludis/util/system.hh>
+#include <paludis/util/fs_stat.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/log.hh>
+#include <paludis/environment.hh>
+
+using namespace paludis;
+using namespace paludis::erepository;
+
+bool
+paludis::erepository::check_userpriv(const FSPath & f, const Environment * env, bool mandatory)
+{
+ Context c("When checking permissions on '" + stringify(f) + "' for userpriv:");
+
+ if (! getenv_with_default("PALUDIS_BYPASS_USERPRIV_CHECKS", "").empty())
+ return false;
+
+ FSStat f_stat(f);
+ if (f_stat.exists())
+ {
+ if (f_stat.group() != env->reduced_gid())
+ {
+ if (mandatory)
+ throw ConfigurationError("Directory '" + stringify(f) + "' owned by group '" + get_group_name(f_stat.group())
+ + "', not '" + get_group_name(env->reduced_gid()) + "'");
+ else
+ Log::get_instance()->message("e.ebuild.userpriv_disabled", ll_warning, lc_context) << "Directory '" <<
+ f << "' owned by group '" << get_group_name(f_stat.group()) << "', not '"
+ << get_group_name(env->reduced_gid()) << "', so cannot enable userpriv";
+ return false;
+ }
+ else if (0 == (f_stat.permissions() & S_IWGRP))
+ {
+ if (mandatory)
+ throw ConfigurationError("Directory '" + stringify(f) + "' does not have group write permission");
+ else
+ Log::get_instance()->message("e.ebuild.userpriv_disabled", ll_warning, lc_context) << "Directory '" <<
+ f << "' does not have group write permission, cannot enable userpriv";
+ return false;
+ }
+ }
+
+ return true;
+}
diff --git a/paludis/repositories/e/check_userpriv.hh b/paludis/repositories/e/check_userpriv.hh
new file mode 100644
index 0000000..1caa3d7
--- /dev/null
+++ b/paludis/repositories/e/check_userpriv.hh
@@ -0,0 +1,36 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2010 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_CHECK_USERPRIV_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_E_CHECK_USERPRIV_HH 1
+
+#include <paludis/util/fs_path.hh>
+#include <paludis/environment-fwd.hh>
+
+namespace paludis
+{
+ namespace erepository
+ {
+ bool
+ check_userpriv(const FSPath & f, const Environment * env, bool mandatory);
+ }
+}
+
+
+#endif
diff --git a/paludis/repositories/e/do_fetch_action.cc b/paludis/repositories/e/do_fetch_action.cc
new file mode 100644
index 0000000..aa61857
--- /dev/null
+++ b/paludis/repositories/e/do_fetch_action.cc
@@ -0,0 +1,312 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2010 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/do_fetch_action.hh>
+#include <paludis/repositories/e/eapi.hh>
+#include <paludis/repositories/e/eapi_phase.hh>
+#include <paludis/repositories/e/check_userpriv.hh>
+#include <paludis/repositories/e/a_finder.hh>
+#include <paludis/repositories/e/aa_visitor.hh>
+#include <paludis/repositories/e/check_fetched_files_visitor.hh>
+#include <paludis/repositories/e/fetch_visitor.hh>
+#include <paludis/repositories/e/make_use.hh>
+#include <paludis/repositories/e/can_skip_phase.hh>
+#include <paludis/repositories/e/ebuild.hh>
+#include <paludis/util/strip.hh>
+#include <paludis/util/make_named_values.hh>
+#include <paludis/util/sequence.hh>
+#include <paludis/util/wrapped_output_iterator.hh>
+#include <paludis/dep_spec_flattener.hh>
+#include <paludis/metadata_key.hh>
+#include <paludis/environment.hh>
+#include <paludis/action.hh>
+#include <paludis/output_manager.hh>
+
+#include <algorithm>
+#include <set>
+
+using namespace paludis;
+using namespace paludis::erepository;
+
+void
+paludis::erepository::do_fetch_action(
+ const Environment * const env,
+ const ERepository * const repo,
+ const std::shared_ptr<const ERepositoryID> & id,
+ const FetchAction & fetch_action)
+{
+ using namespace std::placeholders;
+
+ Context context("When fetching '" + stringify(*id) + "':");
+
+ bool fetch_restrict(false), userpriv_restrict(false);
+ {
+ DepSpecFlattener<PlainTextSpecTree, PlainTextDepSpec> restricts(env);
+ if (id->restrict_key())
+ id->restrict_key()->value()->top()->accept(restricts);
+
+ for (DepSpecFlattener<PlainTextSpecTree, PlainTextDepSpec>::ConstIterator i(restricts.begin()), i_end(restricts.end()) ;
+ i != i_end ; ++i)
+ {
+ if (id->eapi()->supported()->ebuild_options()->restrict_fetch()->end() !=
+ std::find(id->eapi()->supported()->ebuild_options()->restrict_fetch()->begin(),
+ id->eapi()->supported()->ebuild_options()->restrict_fetch()->end(), (*i)->text()))
+ fetch_restrict = true;
+ if ("userpriv" == (*i)->text() || "nouserpriv" == (*i)->text())
+ userpriv_restrict = true;
+ }
+ }
+
+ bool fetch_userpriv_ok(env->reduced_gid() != getgid() &&
+ check_userpriv(FSPath(repo->params().distdir()), env,
+ id->eapi()->supported()->userpriv_cannot_use_root()));
+
+ std::string archives, all_archives;
+ {
+ std::set<std::string> already_in_archives;
+
+ /* make A */
+ AFinder f(env, id);
+ if (id->fetches_key())
+ id->fetches_key()->value()->top()->accept(f);
+
+ for (AFinder::ConstIterator i(f.begin()), i_end(f.end()) ; i != i_end ; ++i)
+ {
+ const FetchableURIDepSpec * const spec(static_cast<const FetchableURIDepSpec *>(i->first));
+
+ if (already_in_archives.end() == already_in_archives.find(spec->filename()))
+ {
+ archives.append(spec->filename());
+ already_in_archives.insert(spec->filename());
+ }
+ archives.append(" ");
+ }
+
+ /* make AA */
+ if (! id->eapi()->supported()->ebuild_environment_variables()->env_aa().empty())
+ {
+ AAVisitor g;
+ if (id->fetches_key())
+ id->fetches_key()->value()->top()->accept(g);
+ std::set<std::string> already_in_all_archives;
+
+ for (AAVisitor::ConstIterator gg(g.begin()), gg_end(g.end()) ; gg != gg_end ; ++gg)
+ {
+ if (already_in_all_archives.end() == already_in_all_archives.find(*gg))
+ {
+ all_archives.append(*gg);
+ already_in_all_archives.insert(*gg);
+ }
+ all_archives.append(" ");
+ }
+ }
+ else
+ all_archives = "AA-not-set-for-this-EAPI";
+ }
+
+ /* Strip trailing space. Some ebuilds rely upon this. From kde-meta.eclass:
+ * [[ -n ${A/${TARBALL}/} ]] && unpack ${A/${TARBALL}/}
+ * Rather annoying.
+ */
+ archives = strip_trailing(archives, " ");
+ all_archives = strip_trailing(all_archives, " ");
+
+ std::shared_ptr<OutputManager> output_manager(fetch_action.options.make_output_manager()(fetch_action));
+
+ CheckFetchedFilesVisitor c(env, id, repo->params().distdir(),
+ fetch_action.options.fetch_parts()[fp_unneeded], fetch_restrict,
+ ((repo->layout()->package_directory(id->name())) / "Manifest"),
+ repo->params().use_manifest(),
+ output_manager, fetch_action.options.exclude_unmirrorable(),
+ fetch_action.options.ignore_unfetched(),
+ fetch_action.options.ignore_not_in_manifest());
+
+ if (id->fetches_key())
+ {
+ /* always use mirror://gentoo/, where gentoo is the name of our first master repository,
+ * or our name if there's no master. */
+ std::string mirrors_name(
+ (repo->params().master_repositories() && ! repo->params().master_repositories()->empty()) ?
+ stringify((*repo->params().master_repositories()->begin())->name()) :
+ stringify(repo->name()));
+
+ if (fetch_action.options.fetch_parts()[fp_regulars] && ! fetch_action.options.ignore_unfetched())
+ {
+ FetchVisitor f(env, id, *id->eapi(),
+ repo->params().distdir(), fetch_action.options.fetch_parts()[fp_unneeded],
+ fetch_userpriv_ok, mirrors_name,
+ id->fetches_key()->initial_label(), fetch_action.options.safe_resume(),
+ output_manager, std::bind(&ERepository::get_mirrors, repo, std::placeholders::_1));
+ id->fetches_key()->value()->top()->accept(f);
+ }
+
+ id->fetches_key()->value()->top()->accept(c);
+ }
+
+ if ( (fetch_action.options.fetch_parts()[fp_extras]) && ((c.need_nofetch()) ||
+ ((! fetch_action.options.ignore_unfetched()) && (! id->eapi()->supported()->ebuild_phases()->ebuild_fetch_extra().empty()))))
+ {
+ bool userpriv_ok((! userpriv_restrict) && (env->reduced_gid() != getgid()) &&
+ check_userpriv(FSPath(repo->params().builddir()), env,
+ id->eapi()->supported()->userpriv_cannot_use_root()));
+ std::string use(make_use(env, *id, repo->profile()));
+ std::shared_ptr<Map<std::string, std::string> > expand_vars(make_expand(
+ env, *id, repo->profile()));
+
+ std::shared_ptr<const FSPathSequence> exlibsdirs(repo->layout()->exlibsdirs(id->name()));
+
+ EAPIPhases fetch_extra_phases(id->eapi()->supported()->ebuild_phases()->ebuild_fetch_extra());
+ if ((! fetch_action.options.ignore_unfetched()) && (fetch_extra_phases.begin_phases() != fetch_extra_phases.end_phases()))
+ {
+ FSPath package_builddir(repo->params().builddir() / (stringify(id->name().category()) + "-" +
+ stringify(id->name().package()) + "-" + stringify(id->version()) + "-fetch_extra"));
+
+ for (EAPIPhases::ConstIterator phase(fetch_extra_phases.begin_phases()), phase_end(fetch_extra_phases.end_phases()) ;
+ phase != phase_end ; ++phase)
+ {
+ bool skip(false);
+ do
+ {
+ switch (fetch_action.options.want_phase()(phase->equal_option("skipname")))
+ {
+ case wp_yes:
+ continue;
+
+ case wp_skip:
+ skip = true;
+ continue;
+
+ case wp_abort:
+ throw ActionAbortedError("Told to abort fetch");
+
+ case last_wp:
+ break;
+ }
+
+ throw InternalError(PALUDIS_HERE, "bad want_phase");
+ } while (false);
+
+ if (skip)
+ continue;
+
+ if (can_skip_phase(id, *phase))
+ continue;
+
+ EbuildCommandParams command_params(make_named_values<EbuildCommandParams>(
+ n::builddir() = repo->params().builddir(),
+ n::clearenv() = phase->option("clearenv"),
+ n::commands() = join(phase->begin_commands(), phase->end_commands(), " "),
+ n::distdir() = repo->params().distdir(),
+ n::ebuild_dir() = repo->layout()->package_directory(id->name()),
+ n::ebuild_file() = id->fs_location_key()->value(),
+ n::eclassdirs() = repo->params().eclassdirs(),
+ n::environment() = env,
+ n::exlibsdirs() = exlibsdirs,
+ n::files_dir() = repo->layout()->package_directory(id->name()) / "files",
+ n::maybe_output_manager() = output_manager,
+ n::package_builddir() = package_builddir,
+ n::package_id() = id,
+ n::portdir() =
+ (repo->params().master_repositories() && ! repo->params().master_repositories()->empty()) ?
+ (*repo->params().master_repositories()->begin())->params().location() : repo->params().location(),
+ n::root() = "/",
+ n::sandbox() = phase->option("sandbox"),
+ n::sydbox() = phase->option("sydbox"),
+ n::userpriv() = phase->option("userpriv") && userpriv_ok
+ ));
+
+ EbuildFetchExtraCommand fetch_extra_cmd(command_params, make_named_values<EbuildFetchExtraCommandParams>(
+ n::a() = archives,
+ n::aa() = all_archives,
+ n::expand_vars() = expand_vars,
+ n::loadsaveenv_dir() = package_builddir / "temp",
+ n::profiles() = repo->params().profiles(),
+ n::profiles_with_parents() = repo->profile()->profiles_with_parents(),
+ n::slot() = id->slot_key() ? stringify(id->slot_key()->value()) : "",
+ n::use() = use,
+ n::use_expand() = join(repo->profile()->use_expand()->begin(), repo->profile()->use_expand()->end(), " "),
+ n::use_expand_hidden() = join(repo->profile()->use_expand_hidden()->begin(), repo->profile()->use_expand_hidden()->end(), " ")
+ ));
+
+ if (! fetch_extra_cmd())
+ throw ActionFailedError("Fetch of '" + stringify(*id) + "' failed");
+ }
+ }
+
+ if (c.need_nofetch())
+ {
+ EAPIPhases phases(id->eapi()->supported()->ebuild_phases()->ebuild_nofetch());
+ for (EAPIPhases::ConstIterator phase(phases.begin_phases()), phase_end(phases.end_phases()) ;
+ phase != phase_end ; ++phase)
+ {
+ EbuildCommandParams command_params(make_named_values<EbuildCommandParams>(
+ n::builddir() = repo->params().builddir(),
+ n::clearenv() = phase->option("clearenv"),
+ n::commands() = join(phase->begin_commands(), phase->end_commands(), " "),
+ n::distdir() = repo->params().distdir(),
+ n::ebuild_dir() = repo->layout()->package_directory(id->name()),
+ n::ebuild_file() = id->fs_location_key()->value(),
+ n::eclassdirs() = repo->params().eclassdirs(),
+ n::environment() = env,
+ n::exlibsdirs() = exlibsdirs,
+ n::files_dir() = repo->layout()->package_directory(id->name()) / "files",
+ n::maybe_output_manager() = output_manager,
+ n::package_builddir() = repo->params().builddir() / (stringify(id->name().category()) + "-" + stringify(id->name().package()) + "-" + stringify(id->version()) + "-nofetch"),
+ n::package_id() = id,
+ n::portdir() = (repo->params().master_repositories() && ! repo->params().master_repositories()->empty()) ?
+ (*repo->params().master_repositories()->begin())->params().location() : repo->params().location(),
+ n::root() = "/",
+ n::sandbox() = phase->option("sandbox"),
+ n::sydbox() = phase->option("sydbox"),
+ n::userpriv() = phase->option("userpriv") && userpriv_ok
+ ));
+
+ EbuildNoFetchCommand nofetch_cmd(command_params,
+ make_named_values<EbuildNoFetchCommandParams>(
+ n::a() = archives,
+ n::aa() = all_archives,
+ n::expand_vars() = expand_vars,
+ n::profiles() = repo->params().profiles(),
+ n::profiles_with_parents() = repo->profile()->profiles_with_parents(),
+ n::use() = use,
+ n::use_expand() = join(repo->profile()->use_expand()->begin(), repo->profile()->use_expand()->end(), " "),
+ n::use_expand_hidden() = join(repo->profile()->use_expand_hidden()->begin(), repo->profile()->use_expand_hidden()->end(), " ")
+ ));
+
+ if (! nofetch_cmd())
+ {
+ std::copy(c.failures()->begin(), c.failures()->end(),
+ fetch_action.options.errors()->back_inserter());
+ throw ActionFailedError("Fetch of '" + stringify(*id) + "' failed");
+ }
+ }
+ }
+ }
+
+ if (! c.failures()->empty())
+ {
+ std::copy(c.failures()->begin(), c.failures()->end(),
+ fetch_action.options.errors()->back_inserter());
+ throw ActionFailedError("Fetch of '" + stringify(*id) + "' failed");
+ }
+
+ output_manager->succeeded();
+}
+
+
diff --git a/paludis/repositories/e/do_fetch_action.hh b/paludis/repositories/e/do_fetch_action.hh
new file mode 100644
index 0000000..5234eee
--- /dev/null
+++ b/paludis/repositories/e/do_fetch_action.hh
@@ -0,0 +1,41 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2010 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_DO_FETCH_ACTION_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_E_DO_FETCH_ACTION_HH 1
+
+#include <paludis/repositories/e/e_repository.hh>
+#include <paludis/repositories/e/e_repository_id.hh>
+#include <paludis/environment-fwd.hh>
+#include <paludis/action-fwd.hh>
+
+namespace paludis
+{
+ namespace erepository
+ {
+ void
+ do_fetch_action(
+ const Environment * const env,
+ const ERepository * const repo,
+ const std::shared_ptr<const ERepositoryID> & id,
+ const FetchAction & fetch_action);
+ }
+}
+
+#endif
diff --git a/paludis/repositories/e/do_info_action.cc b/paludis/repositories/e/do_info_action.cc
new file mode 100644
index 0000000..a2bacb0
--- /dev/null
+++ b/paludis/repositories/e/do_info_action.cc
@@ -0,0 +1,127 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2010 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/do_info_action.hh>
+#include <paludis/repositories/e/eapi.hh>
+#include <paludis/repositories/e/eapi_phase.hh>
+#include <paludis/repositories/e/check_userpriv.hh>
+#include <paludis/repositories/e/make_use.hh>
+#include <paludis/repositories/e/ebuild.hh>
+#include <paludis/util/indirect_iterator-impl.hh>
+#include <paludis/util/make_named_values.hh>
+#include <paludis/dep_spec_flattener.hh>
+#include <paludis/action.hh>
+#include <paludis/metadata_key.hh>
+#include <paludis/environment.hh>
+#include <paludis/output_manager.hh>
+
+#include <algorithm>
+
+using namespace paludis;
+using namespace paludis::erepository;
+
+void
+paludis::erepository::do_info_action(
+ const Environment * const env,
+ const ERepository * const repo,
+ const std::shared_ptr<const ERepositoryID> & id,
+ const InfoAction & a)
+{
+ using namespace std::placeholders;
+
+ Context context("When infoing '" + stringify(*id) + "':");
+
+ std::shared_ptr<OutputManager> output_manager(a.options.make_output_manager()(a));
+
+ bool userpriv_restrict;
+ {
+ DepSpecFlattener<PlainTextSpecTree, PlainTextDepSpec> restricts(env);
+ if (id->restrict_key())
+ id->restrict_key()->value()->top()->accept(restricts);
+
+ userpriv_restrict =
+ indirect_iterator(restricts.end()) != std::find_if(indirect_iterator(restricts.begin()), indirect_iterator(restricts.end()),
+ std::bind(std::equal_to<std::string>(), std::bind(std::mem_fn(&StringDepSpec::text), _1), "userpriv")) ||
+ indirect_iterator(restricts.end()) != std::find_if(indirect_iterator(restricts.begin()), indirect_iterator(restricts.end()),
+ std::bind(std::equal_to<std::string>(), std::bind(std::mem_fn(&StringDepSpec::text), _1), "nouserpriv"));
+ }
+ bool userpriv_ok((! userpriv_restrict) && (env->reduced_gid() != getgid()) &&
+ check_userpriv(FSPath(repo->params().builddir()), env, id->eapi()->supported()->userpriv_cannot_use_root()));
+
+ /* make use */
+ std::string use(make_use(env, *id, repo->profile()));
+
+ /* add expand to use (iuse isn't reliable for use_expand things), and make the expand
+ * environment variables */
+ std::shared_ptr<Map<std::string, std::string> > expand_vars(make_expand(
+ env, *id, repo->profile()));
+
+ std::shared_ptr<const FSPathSequence> exlibsdirs(repo->layout()->exlibsdirs(id->name()));
+
+ EAPIPhases phases(id->eapi()->supported()->ebuild_phases()->ebuild_info());
+ for (EAPIPhases::ConstIterator phase(phases.begin_phases()), phase_end(phases.end_phases()) ;
+ phase != phase_end ; ++phase)
+ {
+ if (phase->option("installed=true"))
+ continue;
+
+ EbuildCommandParams command_params(make_named_values<EbuildCommandParams>(
+ n::builddir() = repo->params().builddir(),
+ n::clearenv() = phase->option("clearenv"),
+ n::commands() = join(phase->begin_commands(), phase->end_commands(), " "),
+ n::distdir() = repo->params().distdir(),
+ n::ebuild_dir() = repo->layout()->package_directory(id->name()),
+ n::ebuild_file() = id->fs_location_key()->value(),
+ n::eclassdirs() = repo->params().eclassdirs(),
+ n::environment() = env,
+ n::exlibsdirs() = exlibsdirs,
+ n::files_dir() = repo->layout()->package_directory(id->name()) / "files",
+ n::maybe_output_manager() = output_manager,
+ n::package_builddir() = repo->params().builddir() / (stringify(id->name().category()) + "-" + stringify(id->name().package()) + "-" + stringify(id->version()) + "-info"),
+ n::package_id() = id,
+ n::portdir() =
+ (repo->params().master_repositories() && ! repo->params().master_repositories()->empty()) ?
+ (*repo->params().master_repositories()->begin())->params().location() : repo->params().location(),
+ n::root() = stringify(env->preferred_root_key()->value()),
+ n::sandbox() = phase->option("sandbox"),
+ n::sydbox() = phase->option("sydbox"),
+ n::userpriv() = phase->option("userpriv") && userpriv_ok
+ ));
+
+ EbuildInfoCommandParams info_params(
+ make_named_values<EbuildInfoCommandParams>(
+ n::expand_vars() = expand_vars,
+ n::info_vars() = repo->info_vars_key() ?
+ repo->info_vars_key()->value() : std::make_shared<const Set<std::string>>(),
+ n::load_environment() = static_cast<const FSPath *>(0),
+ n::profiles() = repo->params().profiles(),
+ n::profiles_with_parents() = repo->profile()->profiles_with_parents(),
+ n::use() = use,
+ n::use_ebuild_file() = true,
+ n::use_expand() = join(repo->profile()->use_expand()->begin(), repo->profile()->use_expand()->end(), " "),
+ n::use_expand_hidden() = join(repo->profile()->use_expand_hidden()->begin(), repo->profile()->use_expand_hidden()->end(), " ")
+ ));
+
+ EbuildInfoCommand cmd(command_params, info_params);
+ cmd();
+ }
+
+ output_manager->succeeded();
+}
+
diff --git a/paludis/repositories/e/do_info_action.hh b/paludis/repositories/e/do_info_action.hh
new file mode 100644
index 0000000..d5ea31e
--- /dev/null
+++ b/paludis/repositories/e/do_info_action.hh
@@ -0,0 +1,41 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2010 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_DO_INFO_ACTION_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_E_DO_INFO_ACTION_HH 1
+
+#include <paludis/repositories/e/e_repository.hh>
+#include <paludis/repositories/e/e_repository_id.hh>
+#include <paludis/environment-fwd.hh>
+#include <paludis/action-fwd.hh>
+
+namespace paludis
+{
+ namespace erepository
+ {
+ void
+ do_info_action(
+ const Environment * const env,
+ const ERepository * const repo,
+ const std::shared_ptr<const ERepositoryID> & id,
+ const InfoAction & a);
+ }
+}
+
+#endif
diff --git a/paludis/repositories/e/do_install_action.cc b/paludis/repositories/e/do_install_action.cc
new file mode 100644
index 0000000..ea848f3
--- /dev/null
+++ b/paludis/repositories/e/do_install_action.cc
@@ -0,0 +1,438 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2010 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/do_install_action.hh>
+#include <paludis/repositories/e/a_finder.hh>
+#include <paludis/repositories/e/eapi.hh>
+#include <paludis/repositories/e/a_finder.hh>
+#include <paludis/repositories/e/aa_visitor.hh>
+#include <paludis/repositories/e/make_use.hh>
+#include <paludis/repositories/e/check_userpriv.hh>
+#include <paludis/repositories/e/eapi_phase.hh>
+#include <paludis/repositories/e/can_skip_phase.hh>
+#include <paludis/repositories/e/e_stripper.hh>
+#include <paludis/repositories/e/ebuild.hh>
+#include <paludis/util/indirect_iterator-impl.hh>
+#include <paludis/util/accept_visitor.hh>
+#include <paludis/util/strip.hh>
+#include <paludis/util/fs_stat.hh>
+#include <paludis/util/make_named_values.hh>
+#include <paludis/util/log.hh>
+#include <paludis/action.hh>
+#include <paludis/dep_spec_flattener.hh>
+#include <paludis/metadata_key.hh>
+#include <paludis/choice.hh>
+#include <paludis/elike_choices.hh>
+#include <paludis/output_manager.hh>
+
+#include <algorithm>
+#include <set>
+
+using namespace paludis;
+using namespace paludis::erepository;
+
+namespace
+{
+ struct AcceptLicenseFinder
+ {
+ std::stringstream s;
+
+ AcceptLicenseFinder()
+ {
+ s << "*";
+ }
+
+ void visit(const LicenseSpecTree::NodeType<AllDepSpec>::Type & node)
+ {
+ std::for_each(indirect_iterator(node.begin()), indirect_iterator(node.end()), accept_visitor(*this));
+ }
+
+ void visit(const LicenseSpecTree::NodeType<AnyDepSpec>::Type & node)
+ {
+ std::for_each(indirect_iterator(node.begin()), indirect_iterator(node.end()), accept_visitor(*this));
+ }
+
+ void visit(const LicenseSpecTree::NodeType<ConditionalDepSpec>::Type & node)
+ {
+ if (node.spec()->condition_met())
+ std::for_each(indirect_iterator(node.begin()), indirect_iterator(node.end()), accept_visitor(*this));
+ }
+
+ void visit(const LicenseSpecTree::NodeType<LicenseDepSpec>::Type & node)
+ {
+ s << " " << node.spec()->text();
+ }
+ };
+
+ void used_this_for_config_protect(std::string & s, const std::string & v)
+ {
+ s = v;
+ }
+
+ bool slot_is_same(const std::shared_ptr<const PackageID> & a,
+ const std::shared_ptr<const PackageID> & b)
+ {
+ if (a->slot_key())
+ return b->slot_key() && a->slot_key()->value() == b->slot_key()->value();
+ else
+ return ! b->slot_key();
+ }
+
+ bool ignore_merged(const std::shared_ptr<const FSPathSet> & s, const FSPath & f)
+ {
+ return s->end() != s->find(f);
+ }
+
+ std::shared_ptr<OutputManager> this_output_manager(const std::shared_ptr<OutputManager> & o, const Action &)
+ {
+ return o;
+ }
+}
+
+void
+paludis::erepository::do_install_action(
+ const Environment * const env,
+ const ERepository * const repo,
+ const std::shared_ptr<const ERepositoryID> & id,
+ const InstallAction & install_action)
+{
+ using namespace std::placeholders;
+
+ Context context("When installing '" + stringify(*id) + "'" +
+ (install_action.options.replacing()->empty() ? "" : " replacing { '"
+ + join(indirect_iterator(install_action.options.replacing()->begin()),
+ indirect_iterator(install_action.options.replacing()->end()), "', '") + "' }") + ":");
+
+ std::shared_ptr<OutputManager> output_manager(install_action.options.make_output_manager()(install_action));
+
+ bool userpriv_restrict, test_restrict, strip_restrict;
+ {
+ DepSpecFlattener<PlainTextSpecTree, PlainTextDepSpec> restricts(env);
+ if (id->restrict_key())
+ id->restrict_key()->value()->top()->accept(restricts);
+
+ userpriv_restrict =
+ indirect_iterator(restricts.end()) != std::find_if(indirect_iterator(restricts.begin()), indirect_iterator(restricts.end()),
+ std::bind(std::equal_to<std::string>(), std::bind(std::mem_fn(&StringDepSpec::text), _1), "userpriv")) ||
+ indirect_iterator(restricts.end()) != std::find_if(indirect_iterator(restricts.begin()), indirect_iterator(restricts.end()),
+ std::bind(std::equal_to<std::string>(), std::bind(std::mem_fn(&StringDepSpec::text), _1), "nouserpriv"));
+
+ test_restrict =
+ indirect_iterator(restricts.end()) != std::find_if(indirect_iterator(restricts.begin()), indirect_iterator(restricts.end()),
+ std::bind(std::equal_to<std::string>(), std::bind(std::mem_fn(&StringDepSpec::text), _1), "test"));
+
+ strip_restrict =
+ indirect_iterator(restricts.end()) != std::find_if(indirect_iterator(restricts.begin()), indirect_iterator(restricts.end()),
+ std::bind(std::equal_to<std::string>(), std::bind(std::mem_fn(&StringDepSpec::text), _1), "strip")) ||
+ indirect_iterator(restricts.end()) != std::find_if(indirect_iterator(restricts.begin()), indirect_iterator(restricts.end()),
+ std::bind(std::equal_to<std::string>(), std::bind(std::mem_fn(&StringDepSpec::text), _1), "nostrip"));
+ }
+
+ std::string archives, all_archives, accept_license;
+ {
+ std::set<std::string> already_in_archives;
+
+ /* make A */
+ AFinder f(env, id);
+ if (id->fetches_key())
+ id->fetches_key()->value()->top()->accept(f);
+
+ for (AFinder::ConstIterator i(f.begin()), i_end(f.end()) ; i != i_end ; ++i)
+ {
+ const FetchableURIDepSpec * const spec(static_cast<const FetchableURIDepSpec *>(i->first));
+
+ if (already_in_archives.end() == already_in_archives.find(spec->filename()))
+ {
+ archives.append(spec->filename());
+ already_in_archives.insert(spec->filename());
+ }
+ archives.append(" ");
+ }
+
+ /* make AA */
+ if (! id->eapi()->supported()->ebuild_environment_variables()->env_aa().empty())
+ {
+ AAVisitor g;
+ if (id->fetches_key())
+ id->fetches_key()->value()->top()->accept(g);
+ std::set<std::string> already_in_all_archives;
+
+ for (AAVisitor::ConstIterator gg(g.begin()), gg_end(g.end()) ; gg != gg_end ; ++gg)
+ {
+ if (already_in_all_archives.end() == already_in_all_archives.find(*gg))
+ {
+ all_archives.append(*gg);
+ already_in_all_archives.insert(*gg);
+ }
+ all_archives.append(" ");
+ }
+ }
+ else
+ all_archives = "AA-not-set-for-this-EAPI";
+
+ /* make ACCEPT_LICENSE */
+ if (! id->eapi()->supported()->ebuild_environment_variables()->env_accept_license().empty())
+ {
+ AcceptLicenseFinder g;
+ if (id->license_key())
+ id->license_key()->value()->top()->accept(g);
+
+ accept_license = g.s.str();
+ }
+ else
+ accept_license = "ACCEPT_LICENSE-not-set-for-this-EAPI";
+ }
+
+ /* Strip trailing space. Some ebuilds rely upon this. From kde-meta.eclass:
+ * [[ -n ${A/${TARBALL}/} ]] && unpack ${A/${TARBALL}/}
+ * Rather annoying.
+ */
+ archives = strip_trailing(archives, " ");
+ all_archives = strip_trailing(all_archives, " ");
+
+ /* make use */
+ std::string use(make_use(env, *id, repo->profile()));
+
+ /* add expand to use (iuse isn't reliable for use_expand things), and make the expand
+ * environment variables */
+ std::shared_ptr<Map<std::string, std::string> > expand_vars(make_expand(env, *id, repo->profile()));
+
+ std::shared_ptr<const FSPathSequence> exlibsdirs(repo->layout()->exlibsdirs(id->name()));
+
+ bool userpriv_ok((! userpriv_restrict) && (env->reduced_gid() != getgid()) &&
+ check_userpriv(FSPath(repo->params().distdir()), env, id->eapi()->supported()->userpriv_cannot_use_root()) &&
+ check_userpriv(FSPath(repo->params().builddir()), env, id->eapi()->supported()->userpriv_cannot_use_root()));
+
+ FSPath package_builddir(repo->params().builddir() / (stringify(id->name().category()) + "-" +
+ stringify(id->name().package()) + "-" + stringify(id->version())));
+
+ std::string used_config_protect;
+ auto merged_entries(std::make_shared<FSPathSet>());
+
+ std::shared_ptr<const ChoiceValue> preserve_work_choice(
+ id->choices_key()->value()->find_by_name_with_prefix(
+ ELikePreserveWorkChoiceValue::canonical_name_with_prefix()));
+
+ EAPIPhases phases(id->eapi()->supported()->ebuild_phases()->ebuild_install());
+ for (EAPIPhases::ConstIterator phase(phases.begin_phases()), phase_end(phases.end_phases()) ;
+ phase != phase_end ; ++phase)
+ {
+ bool skip(false);
+ do
+ {
+ switch (install_action.options.want_phase()(phase->equal_option("skipname")))
+ {
+ case wp_yes:
+ continue;
+
+ case wp_skip:
+ skip = true;
+ continue;
+
+ case wp_abort:
+ throw ActionAbortedError("Told to abort install");
+
+ case last_wp:
+ break;
+ }
+
+ throw InternalError(PALUDIS_HERE, "bad want_phase");
+ } while (false);
+
+ if (skip)
+ continue;
+
+ if (can_skip_phase(id, *phase))
+ {
+ output_manager->stdout_stream() << "--- No need to do anything for " << phase->equal_option("skipname") << " phase" << std::endl;
+ continue;
+ }
+
+ if (phase->option("tidyup") && preserve_work_choice && preserve_work_choice->enabled())
+ {
+ output_manager->stdout_stream() << "--- Skipping " << phase->equal_option("skipname")
+ << " phase to preserve work" << std::endl;
+ continue;
+ }
+
+ if (phase->option("merge"))
+ {
+ if (! (*install_action.options.destination()).destination_interface())
+ throw ActionFailedError("Can't install '" + stringify(*id)
+ + "' to destination '" + stringify(install_action.options.destination()->name())
+ + "' because destination does not provide destination_interface");
+
+ MergerOptions extra_merger_options;
+ if (preserve_work_choice && preserve_work_choice->enabled())
+ extra_merger_options += mo_nondestructive;
+
+ Timestamp build_start_time(FSPath(package_builddir / "temp" / "build_start_time").stat().mtim());
+ (*install_action.options.destination()).destination_interface()->merge(
+ make_named_values<MergeParams>(
+ n::build_start_time() = build_start_time,
+ n::environment_file() = package_builddir / "temp" / "loadsaveenv",
+ n::image_dir() = package_builddir / "image",
+ n::merged_entries() = merged_entries,
+ n::options() = id->eapi()->supported()->merger_options() | extra_merger_options,
+ n::output_manager() = output_manager,
+ n::package_id() = id,
+ n::perform_uninstall() = install_action.options.perform_uninstall(),
+ n::used_this_for_config_protect() = std::bind(
+ &used_this_for_config_protect, std::ref(used_config_protect), std::placeholders::_1)
+ ));
+ }
+ else if (phase->option("strip"))
+ {
+ if ((! id->eapi()->supported()->is_pbin()) && (! strip_restrict))
+ {
+ std::string libdir("lib");
+ FSPath root(install_action.options.destination()->installed_root_key() ?
+ stringify(install_action.options.destination()->installed_root_key()->value()) : "/");
+ if ((root / "usr" / "lib").stat().is_symlink())
+ {
+ libdir = (root / "usr" / "lib").readlink();
+ if (std::string::npos != libdir.find_first_of("./"))
+ libdir = "lib";
+ }
+
+ Log::get_instance()->message("e.ebuild.libdir", ll_debug, lc_context) << "Using '" << libdir << "' for libdir";
+
+ std::shared_ptr<const ChoiceValue> strip_choice(id->choices_key()->value()->find_by_name_with_prefix(
+ ELikeStripChoiceValue::canonical_name_with_prefix()));
+ std::shared_ptr<const ChoiceValue> split_choice(id->choices_key()->value()->find_by_name_with_prefix(
+ ELikeSplitChoiceValue::canonical_name_with_prefix()));
+
+ EStripper stripper(make_named_values<EStripperOptions>(
+ n::debug_dir() = package_builddir / "image" / "usr" / libdir / "debug",
+ n::image_dir() = package_builddir / "image",
+ n::output_manager() = output_manager,
+ n::package_id() = id,
+ n::split() = split_choice && split_choice->enabled(),
+ n::strip() = strip_choice && strip_choice->enabled()
+ ));
+ stripper.strip();
+ }
+ }
+ else if ((! phase->option("prepost")) ||
+ ((*install_action.options.destination()).destination_interface() &&
+ (*install_action.options.destination()).destination_interface()->want_pre_post_phases()))
+ {
+ if (phase->option("optional_tests"))
+ {
+ if (test_restrict)
+ continue;
+
+ std::shared_ptr<const ChoiceValue> choice(id->choices_key()->value()->find_by_name_with_prefix(
+ ELikeOptionalTestsChoiceValue::canonical_name_with_prefix()));
+ if (choice && ! choice->enabled())
+ continue;
+ }
+ else if (phase->option("recommended_tests"))
+ {
+ if (test_restrict)
+ continue;
+
+ std::shared_ptr<const ChoiceValue> choice(id->choices_key()->value()->find_by_name_with_prefix(
+ ELikeRecommendedTestsChoiceValue::canonical_name_with_prefix()));
+ if (choice && ! choice->enabled())
+ continue;
+ }
+ else if (phase->option("expensive_tests"))
+ {
+ std::shared_ptr<const ChoiceValue> choice(id->choices_key()->value()->find_by_name_with_prefix(
+ ELikeExpensiveTestsChoiceValue::canonical_name_with_prefix()));
+ if (choice && ! choice->enabled())
+ continue;
+ }
+
+ EbuildCommandParams command_params(make_named_values<EbuildCommandParams>(
+ n::builddir() = repo->params().builddir(),
+ n::clearenv() = phase->option("clearenv"),
+ n::commands() = join(phase->begin_commands(), phase->end_commands(), " "),
+ n::distdir() = repo->params().distdir(),
+ n::ebuild_dir() = repo->layout()->package_directory(id->name()),
+ n::ebuild_file() = id->fs_location_key()->value(),
+ n::eclassdirs() = repo->params().eclassdirs(),
+ n::environment() = env,
+ n::exlibsdirs() = exlibsdirs,
+ n::files_dir() = repo->layout()->package_directory(id->name()) / "files",
+ n::maybe_output_manager() = output_manager,
+ n::package_builddir() = package_builddir,
+ n::package_id() = id,
+ n::portdir() =
+ (repo->params().master_repositories() && ! repo->params().master_repositories()->empty()) ?
+ (*repo->params().master_repositories()->begin())->params().location() : repo->params().location(),
+ n::root() = install_action.options.destination()->installed_root_key() ?
+ stringify(install_action.options.destination()->installed_root_key()->value()) :
+ "/",
+ n::sandbox() = phase->option("sandbox"),
+ n::sydbox() = phase->option("sydbox"),
+ n::userpriv() = phase->option("userpriv") && userpriv_ok
+ ));
+
+ EbuildInstallCommandParams install_params(
+ make_named_values<EbuildInstallCommandParams>(
+ n::a() = archives,
+ n::aa() = all_archives,
+ n::accept_license() = accept_license,
+ n::config_protect() = repo->environment_updated_profile_variable("CONFIG_PROTECT"),
+ n::config_protect_mask() = repo->environment_updated_profile_variable("CONFIG_PROTECT_MASK"),
+ n::destination() = install_action.options.destination(),
+ n::expand_vars() = expand_vars,
+ n::is_from_pbin() = id->eapi()->supported()->is_pbin(),
+ n::loadsaveenv_dir() = package_builddir / "temp",
+ n::profiles() = repo->params().profiles(),
+ n::profiles_with_parents() = repo->profile()->profiles_with_parents(),
+ n::replacing_ids() = install_action.options.replacing(),
+ n::slot() = id->slot_key() ? stringify(id->slot_key()->value()) : "",
+ n::use() = use,
+ n::use_expand() = join(repo->profile()->use_expand()->begin(), repo->profile()->use_expand()->end(), " "),
+ n::use_expand_hidden() = join(repo->profile()->use_expand_hidden()->begin(), repo->profile()->use_expand_hidden()->end(), " ")
+ ));
+
+ EbuildInstallCommand cmd(command_params, install_params);
+ cmd();
+ }
+ }
+
+ for (PackageIDSequence::ConstIterator i(install_action.options.replacing()->begin()), i_end(install_action.options.replacing()->end()) ;
+ i != i_end ; ++i)
+ {
+ Context local_context("When cleaning '" + stringify(**i) + "':");
+ if ((*i)->name() == id->name() && (*i)->version() == id->version())
+ continue;
+
+ if (id->eapi()->supported()->ebuild_phases()->ebuild_new_upgrade_phase_order())
+ if ((*i)->name() == id->name() && slot_is_same(*i, id))
+ continue;
+
+ UninstallActionOptions uo(make_named_values<UninstallActionOptions>(
+ n::config_protect() = used_config_protect,
+ n::if_for_install_id() = id,
+ n::ignore_for_unmerge() = std::bind(&ignore_merged, merged_entries,
+ std::placeholders::_1),
+ n::is_overwrite() = false,
+ n::make_output_manager() = std::bind(&this_output_manager, output_manager, std::placeholders::_1)
+ ));
+ install_action.options.perform_uninstall()(*i, uo);
+ }
+
+ output_manager->succeeded();
+}
+
diff --git a/paludis/repositories/e/do_install_action.hh b/paludis/repositories/e/do_install_action.hh
new file mode 100644
index 0000000..b4cdad5
--- /dev/null
+++ b/paludis/repositories/e/do_install_action.hh
@@ -0,0 +1,42 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2010 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_DO_INSTALL_ACTION_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_E_DO_INSTALL_ACTION_HH 1
+
+#include <paludis/repositories/e/e_repository.hh>
+#include <paludis/repositories/e/e_repository_id.hh>
+#include <paludis/environment-fwd.hh>
+#include <paludis/action-fwd.hh>
+
+namespace paludis
+{
+ namespace erepository
+ {
+ void
+ do_install_action(
+ const Environment * const env,
+ const ERepository * const repo,
+ const std::shared_ptr<const ERepositoryID> & id,
+ const InstallAction & install_action);
+
+ }
+}
+
+#endif
diff --git a/paludis/repositories/e/do_pretend_action.cc b/paludis/repositories/e/do_pretend_action.cc
new file mode 100644
index 0000000..01631fe
--- /dev/null
+++ b/paludis/repositories/e/do_pretend_action.cc
@@ -0,0 +1,201 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2010 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/do_pretend_action.hh>
+#include <paludis/repositories/e/check_userpriv.hh>
+#include <paludis/repositories/e/eapi.hh>
+#include <paludis/repositories/e/eapi_phase.hh>
+#include <paludis/repositories/e/make_use.hh>
+#include <paludis/repositories/e/myoptions_requirements_verifier.hh>
+#include <paludis/repositories/e/ebuild.hh>
+#include <paludis/repositories/e/can_skip_phase.hh>
+#include <paludis/util/indirect_iterator-impl.hh>
+#include <paludis/util/make_named_values.hh>
+#include <paludis/dep_spec_flattener.hh>
+#include <paludis/metadata_key.hh>
+#include <paludis/environment.hh>
+#include <paludis/action.hh>
+
+#include <algorithm>
+
+using namespace paludis;
+using namespace paludis::erepository;
+
+bool
+paludis::erepository::do_pretend_action(
+ const Environment * const env,
+ const ERepository * const repo,
+ const std::shared_ptr<const ERepositoryID> & id,
+ const PretendAction & a)
+{
+ using namespace std::placeholders;
+
+ Context context("When running pretend for '" + stringify(*id) + "':");
+
+ if (! id->eapi()->supported())
+ return false;
+
+ bool result(true);
+
+ if (! id->raw_myoptions_key())
+ if (id->eapi()->supported()->ebuild_phases()->ebuild_pretend().empty())
+ return result;
+
+ bool userpriv_restrict;
+ {
+ DepSpecFlattener<PlainTextSpecTree, PlainTextDepSpec> restricts(env);
+ if (id->restrict_key())
+ id->restrict_key()->value()->top()->accept(restricts);
+
+ userpriv_restrict =
+ indirect_iterator(restricts.end()) != std::find_if(indirect_iterator(restricts.begin()), indirect_iterator(restricts.end()),
+ std::bind(std::equal_to<std::string>(), std::bind(std::mem_fn(&StringDepSpec::text), _1), "userpriv")) ||
+ indirect_iterator(restricts.end()) != std::find_if(indirect_iterator(restricts.begin()), indirect_iterator(restricts.end()),
+ std::bind(std::equal_to<std::string>(), std::bind(std::mem_fn(&StringDepSpec::text), _1), "nouserpriv"));
+ }
+ bool userpriv_ok((! userpriv_restrict) && (env->reduced_gid() != getgid()) &&
+ check_userpriv(FSPath(repo->params().builddir()), env, id->eapi()->supported()->userpriv_cannot_use_root()));
+
+ std::string use(make_use(env, *id, repo->profile()));
+ std::shared_ptr<Map<std::string, std::string> > expand_vars(make_expand(
+ env, *id, repo->profile()));
+
+ std::shared_ptr<const FSPathSequence> exlibsdirs(repo->layout()->exlibsdirs(id->name()));
+
+ std::shared_ptr<OutputManager> output_manager;
+
+ if (id->raw_myoptions_key())
+ {
+ MyOptionsRequirementsVerifier verifier(id);
+ id->raw_myoptions_key()->value()->top()->accept(verifier);
+
+ if (verifier.unmet_requirements() && ! verifier.unmet_requirements()->empty())
+ {
+ EAPIPhases phases(id->eapi()->supported()->ebuild_phases()->ebuild_bad_options());
+ if (phases.begin_phases() == phases.end_phases())
+ throw InternalError(PALUDIS_HERE, "using myoptions but no ebuild_bad_options phase");
+
+ for (EAPIPhases::ConstIterator phase(phases.begin_phases()), phase_end(phases.end_phases()) ;
+ phase != phase_end ; ++phase)
+ {
+ if (! output_manager)
+ output_manager = a.options.make_output_manager()(a);
+
+ EbuildCommandParams command_params(make_named_values<EbuildCommandParams>(
+ n::builddir() = repo->params().builddir(),
+ n::clearenv() = phase->option("clearenv"),
+ n::commands() = join(phase->begin_commands(), phase->end_commands(), " "),
+ n::distdir() = repo->params().distdir(),
+ n::ebuild_dir() = repo->layout()->package_directory(id->name()),
+ n::ebuild_file() = id->fs_location_key()->value(),
+ n::eclassdirs() = repo->params().eclassdirs(),
+ n::environment() = env,
+ n::exlibsdirs() = exlibsdirs,
+ n::files_dir() = repo->layout()->package_directory(id->name()) / "files",
+ n::maybe_output_manager() = output_manager,
+ n::package_builddir() = repo->params().builddir() / (stringify(id->name().category()) + "-" + stringify(id->name().package()) + "-" + stringify(id->version()) + "-bad_options"),
+ n::package_id() = id,
+ n::portdir() =
+ (repo->params().master_repositories() && ! repo->params().master_repositories()->empty()) ?
+ (*repo->params().master_repositories()->begin())->params().location() : repo->params().location(),
+ n::root() = a.options.destination()->installed_root_key() ?
+ stringify(a.options.destination()->installed_root_key()->value()) :
+ "/",
+ n::sandbox() = phase->option("sandbox"),
+ n::sydbox() = phase->option("sydbox"),
+ n::userpriv() = phase->option("userpriv") && userpriv_ok
+ ));
+
+ EbuildBadOptionsCommand bad_options_cmd(command_params,
+ make_named_values<EbuildBadOptionsCommandParams>(
+ n::expand_vars() = expand_vars,
+ n::profiles() = repo->params().profiles(),
+ n::profiles_with_parents() = repo->profile()->profiles_with_parents(),
+ n::unmet_requirements() = verifier.unmet_requirements(),
+ n::use() = use,
+ n::use_expand() = join(repo->profile()->use_expand()->begin(), repo->profile()->use_expand()->end(), " "),
+ n::use_expand_hidden() = join(repo->profile()->use_expand_hidden()->begin(), repo->profile()->use_expand_hidden()->end(), " ")
+ ));
+
+ if (! bad_options_cmd())
+ throw ActionFailedError("Bad options phase died");
+ }
+
+ result = false;
+ }
+ }
+
+ if (id->eapi()->supported()->ebuild_phases()->ebuild_pretend().empty())
+ return result;
+
+ EAPIPhases phases(id->eapi()->supported()->ebuild_phases()->ebuild_pretend());
+ for (EAPIPhases::ConstIterator phase(phases.begin_phases()), phase_end(phases.end_phases()) ;
+ phase != phase_end ; ++phase)
+ {
+ if (can_skip_phase(id, *phase))
+ continue;
+
+ if (! output_manager)
+ output_manager = a.options.make_output_manager()(a);
+
+ EbuildCommandParams command_params(make_named_values<EbuildCommandParams>(
+ n::builddir() = repo->params().builddir(),
+ n::clearenv() = phase->option("clearenv"),
+ n::commands() = join(phase->begin_commands(), phase->end_commands(), " "),
+ n::distdir() = repo->params().distdir(),
+ n::ebuild_dir() = repo->layout()->package_directory(id->name()),
+ n::ebuild_file() = id->fs_location_key()->value(),
+ n::eclassdirs() = repo->params().eclassdirs(),
+ n::environment() = env,
+ n::exlibsdirs() = exlibsdirs,
+ n::files_dir() = repo->layout()->package_directory(id->name()) / "files",
+ n::maybe_output_manager() = output_manager,
+ n::package_builddir() = repo->params().builddir() / (stringify(id->name().category()) + "-" + stringify(id->name().package()) + "-" + stringify(id->version()) + "-pretend"),
+ n::package_id() = id,
+ n::portdir() =
+ (repo->params().master_repositories() && ! repo->params().master_repositories()->empty()) ?
+ (*repo->params().master_repositories()->begin())->params().location() : repo->params().location(),
+ n::root() = a.options.destination()->installed_root_key() ?
+ stringify(a.options.destination()->installed_root_key()->value()) :
+ "/",
+ n::sandbox() = phase->option("sandbox"),
+ n::sydbox() = phase->option("sydbox"),
+ n::userpriv() = phase->option("userpriv") && userpriv_ok
+ ));
+
+ EbuildPretendCommand pretend_cmd(command_params,
+ make_named_values<EbuildPretendCommandParams>(
+ n::destination() = a.options.destination(),
+ n::expand_vars() = expand_vars,
+ n::is_from_pbin() = id->eapi()->supported()->is_pbin(),
+ n::profiles() = repo->params().profiles(),
+ n::profiles_with_parents() = repo->profile()->profiles_with_parents(),
+ n::replacing_ids() = a.options.replacing(),
+ n::use() = use,
+ n::use_expand() = join(repo->profile()->use_expand()->begin(), repo->profile()->use_expand()->end(), " "),
+ n::use_expand_hidden() = join(repo->profile()->use_expand_hidden()->begin(), repo->profile()->use_expand_hidden()->end(), " ")
+ ));
+
+ if (! pretend_cmd())
+ return false;
+ }
+
+ return result;
+}
+
diff --git a/paludis/repositories/e/do_pretend_action.hh b/paludis/repositories/e/do_pretend_action.hh
new file mode 100644
index 0000000..eed243d
--- /dev/null
+++ b/paludis/repositories/e/do_pretend_action.hh
@@ -0,0 +1,41 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2010 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_DO_PRETEND_ACTION_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_E_DO_PRETEND_ACTION_HH 1
+
+#include <paludis/repositories/e/e_repository.hh>
+#include <paludis/repositories/e/e_repository_id.hh>
+#include <paludis/environment-fwd.hh>
+#include <paludis/action-fwd.hh>
+
+namespace paludis
+{
+ namespace erepository
+ {
+ bool
+ do_pretend_action(
+ const Environment * const env,
+ const ERepository * const repo,
+ const std::shared_ptr<const ERepositoryID> & id,
+ const PretendAction & a);
+ }
+}
+
+#endif
diff --git a/paludis/repositories/e/do_pretend_fetch_action.cc b/paludis/repositories/e/do_pretend_fetch_action.cc
new file mode 100644
index 0000000..af9a0f0
--- /dev/null
+++ b/paludis/repositories/e/do_pretend_fetch_action.cc
@@ -0,0 +1,47 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2010 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/do_pretend_fetch_action.hh>
+#include <paludis/repositories/e/pretend_fetch_visitor.hh>
+#include <paludis/action.hh>
+#include <paludis/metadata_key.hh>
+
+using namespace paludis;
+using namespace paludis::erepository;
+
+void
+paludis::erepository::do_pretend_fetch_action(
+ const Environment * const env,
+ const ERepository * const repo,
+ const std::shared_ptr<const ERepositoryID> & id,
+ PretendFetchAction & a)
+{
+ using namespace std::placeholders;
+
+ Context context("When pretending to fetch ID '" + stringify(*id) + "':");
+
+ if (id->fetches_key())
+ {
+ PretendFetchVisitor f(env, id, *id->eapi(),
+ repo->params().distdir(), a.options.fetch_parts()[fp_unneeded],
+ id->fetches_key()->initial_label(), a);
+ id->fetches_key()->value()->top()->accept(f);
+ }
+}
+
diff --git a/paludis/repositories/e/do_pretend_fetch_action.hh b/paludis/repositories/e/do_pretend_fetch_action.hh
new file mode 100644
index 0000000..c7a95e7
--- /dev/null
+++ b/paludis/repositories/e/do_pretend_fetch_action.hh
@@ -0,0 +1,41 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2010 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_DO_PRETEND_FETCH_ACTION_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_E_DO_PRETEND_FETCH_ACTION_HH 1
+
+#include <paludis/repositories/e/e_repository.hh>
+#include <paludis/repositories/e/e_repository_id.hh>
+#include <paludis/action-fwd.hh>
+#include <paludis/environment-fwd.hh>
+
+namespace paludis
+{
+ namespace erepository
+ {
+ void
+ do_pretend_fetch_action(
+ const Environment * const env,
+ const ERepository * const repo,
+ const std::shared_ptr<const ERepositoryID> & id,
+ PretendFetchAction & a);
+ }
+}
+
+#endif
diff --git a/paludis/repositories/e/e_repository.cc b/paludis/repositories/e/e_repository.cc
index ac37961..ad6b565 100644
--- a/paludis/repositories/e/e_repository.cc
+++ b/paludis/repositories/e/e_repository.cc
@@ -36,15 +36,13 @@
#include <paludis/repositories/e/extra_distribution_data.hh>
#include <paludis/repositories/e/memoised_hashes.hh>
#include <paludis/repositories/e/ebuild_id.hh>
-#include <paludis/repositories/e/check_fetched_files_visitor.hh>
-#include <paludis/repositories/e/fetch_visitor.hh>
#include <paludis/repositories/e/eapi_phase.hh>
#include <paludis/repositories/e/can_skip_phase.hh>
#include <paludis/repositories/e/ebuild.hh>
-#include <paludis/repositories/e/pretend_fetch_visitor.hh>
-#include <paludis/repositories/e/e_stripper.hh>
-#include <paludis/repositories/e/myoptions_requirements_verifier.hh>
#include <paludis/repositories/e/pbin_merger.hh>
+#include <paludis/repositories/e/check_userpriv.hh>
+#include <paludis/repositories/e/make_use.hh>
+#include <paludis/repositories/e/a_finder.hh>
#include <paludis/about.hh>
#include <paludis/action.hh>
@@ -1782,961 +1780,6 @@ ERepository::make_id(const QualifiedPackageName & q, const FSPath & f) const
return result;
}
-namespace
-{
- class AFinder
- {
- private:
- std::list<std::pair<const FetchableURIDepSpec *, const URILabelsDepSpec *> > _specs;
- std::list<const URILabelsDepSpec *> _labels;
-
- const Environment * const env;
- const std::shared_ptr<const PackageID> id;
-
- public:
- AFinder(const Environment * const e, const std::shared_ptr<const PackageID> & i) :
- env(e),
- id(i)
- {
- _labels.push_back(0);
- }
-
- void visit(const FetchableURISpecTree::NodeType<FetchableURIDepSpec>::Type & node)
- {
- _specs.push_back(std::make_pair(node.spec().get(), *_labels.begin()));
- }
-
- void visit(const FetchableURISpecTree::NodeType<URILabelsDepSpec>::Type & node)
- {
- *_labels.begin() = node.spec().get();
- }
-
- void visit(const FetchableURISpecTree::NodeType<AllDepSpec>::Type & node)
- {
- _labels.push_front(*_labels.begin());
- std::for_each(indirect_iterator(node.begin()), indirect_iterator(node.end()), accept_visitor(*this));
- _labels.pop_front();
- }
-
- void visit(const FetchableURISpecTree::NodeType<ConditionalDepSpec>::Type & node)
- {
- if (node.spec()->condition_met())
- {
- _labels.push_front(*_labels.begin());
- std::for_each(indirect_iterator(node.begin()), indirect_iterator(node.end()), accept_visitor(*this));
- _labels.pop_front();
- }
- }
-
- typedef std::list<std::pair<const FetchableURIDepSpec *,
- const URILabelsDepSpec *> >::const_iterator ConstIterator;
-
- ConstIterator begin()
- {
- return _specs.begin();
- }
-
- ConstIterator end() const
- {
- return _specs.end();
- }
- };
-}
-
-namespace
-{
- std::string make_use(const Environment * const,
- const ERepositoryID & id,
- std::shared_ptr<const Profile> profile)
- {
- if (! id.eapi()->supported())
- {
- Log::get_instance()->message("e.ebuild.unknown_eapi", ll_warning, lc_context)
- << "Can't make the USE string for '" << id << "' because its EAPI is unsupported";
- return "";
- }
-
- std::string use;
-
- if (id.choices_key())
- {
- for (Choices::ConstIterator k(id.choices_key()->value()->begin()),
- k_end(id.choices_key()->value()->end()) ;
- k != k_end ; ++k)
- {
- if ((*k)->prefix() == canonical_build_options_prefix())
- continue;
-
- for (Choice::ConstIterator i((*k)->begin()), i_end((*k)->end()) ;
- i != i_end ; ++i)
- if ((*i)->enabled())
- use += stringify((*i)->name_with_prefix()) + " ";
- }
- }
-
- if (! id.eapi()->supported()->ebuild_environment_variables()->env_arch().empty())
- use += profile->environment_variable(id.eapi()->supported()->ebuild_environment_variables()->env_arch()) + " ";
-
- return use;
- }
-
- std::shared_ptr<Map<std::string, std::string> >
- make_expand(const Environment * const,
- const ERepositoryID & e,
- std::shared_ptr<const Profile> profile)
- {
- std::shared_ptr<Map<std::string, std::string> > expand_vars(std::make_shared<Map<std::string, std::string> >());
-
- if (! e.eapi()->supported())
- {
- Log::get_instance()->message("e.ebuild.unknown_eapi", ll_warning, lc_context)
- << "Can't make the USE_EXPAND strings for '" << e << "' because its EAPI is unsupported";
- return expand_vars;
- }
-
- if (! e.choices_key())
- return expand_vars;
-
- for (Set<std::string>::ConstIterator x(profile->use_expand()->begin()), x_end(profile->use_expand()->end()) ;
- x != x_end ; ++x)
- {
- expand_vars->insert(stringify(*x), "");
-
- Choices::ConstIterator k(std::find_if(e.choices_key()->value()->begin(), e.choices_key()->value()->end(),
- std::bind(std::equal_to<std::string>(), *x,
- std::bind(std::mem_fn(&Choice::raw_name), std::placeholders::_1))));
- if (k == e.choices_key()->value()->end())
- continue;
-
- for (Choice::ConstIterator i((*k)->begin()), i_end((*k)->end()) ;
- i != i_end ; ++i)
- if ((*i)->enabled())
- {
- std::string value;
- Map<std::string, std::string>::ConstIterator v(expand_vars->find(stringify(*x)));
- if (expand_vars->end() != v)
- {
- value = v->second;
- if (! value.empty())
- value.append(" ");
- expand_vars->erase(v);
- }
- value.append(stringify((*i)->unprefixed_name()));
- expand_vars->insert(stringify(*x), value);
- }
- }
-
- return expand_vars;
- }
-}
-
-namespace
-{
- bool
- check_userpriv(const FSPath & f, const Environment * env, bool mandatory)
- {
- Context c("When checking permissions on '" + stringify(f) + "' for userpriv:");
-
- if (! getenv_with_default("PALUDIS_BYPASS_USERPRIV_CHECKS", "").empty())
- return false;
-
- FSStat f_stat(f);
- if (f_stat.exists())
- {
- if (f_stat.group() != env->reduced_gid())
- {
- if (mandatory)
- throw ConfigurationError("Directory '" + stringify(f) + "' owned by group '" + get_group_name(f_stat.group())
- + "', not '" + get_group_name(env->reduced_gid()) + "'");
- else
- Log::get_instance()->message("e.ebuild.userpriv_disabled", ll_warning, lc_context) << "Directory '" <<
- f << "' owned by group '" << get_group_name(f_stat.group()) << "', not '"
- << get_group_name(env->reduced_gid()) << "', so cannot enable userpriv";
- return false;
- }
- else if (0 == (f_stat.permissions() & S_IWGRP))
- {
- if (mandatory)
- throw ConfigurationError("Directory '" + stringify(f) + "' does not have group write permission");
- else
- Log::get_instance()->message("e.ebuild.userpriv_disabled", ll_warning, lc_context) << "Directory '" <<
- f << "' does not have group write permission, cannot enable userpriv";
- return false;
- }
- }
-
- return true;
- }
-
- const std::shared_ptr<const MirrorsSequence>
- get_mirrors_fn(const std::string & m, const MirrorMap & map)
- {
- MirrorMap::const_iterator i(map.find(m));
- if (i == map.end())
- return std::make_shared<MirrorsSequence>();
- else
- return i->second;
- }
-}
-
-void
-ERepository::fetch(const std::shared_ptr<const ERepositoryID> & id,
- const FetchAction & fetch_action) const
-{
- using namespace std::placeholders;
-
- Context context("When fetching '" + stringify(*id) + "':");
-
- bool fetch_restrict(false), userpriv_restrict(false);
- {
- DepSpecFlattener<PlainTextSpecTree, PlainTextDepSpec> restricts(_imp->params.environment());
- if (id->restrict_key())
- id->restrict_key()->value()->top()->accept(restricts);
-
- for (DepSpecFlattener<PlainTextSpecTree, PlainTextDepSpec>::ConstIterator i(restricts.begin()), i_end(restricts.end()) ;
- i != i_end ; ++i)
- {
- if (id->eapi()->supported()->ebuild_options()->restrict_fetch()->end() !=
- std::find(id->eapi()->supported()->ebuild_options()->restrict_fetch()->begin(),
- id->eapi()->supported()->ebuild_options()->restrict_fetch()->end(), (*i)->text()))
- fetch_restrict = true;
- if ("userpriv" == (*i)->text() || "nouserpriv" == (*i)->text())
- userpriv_restrict = true;
- }
- }
-
- bool fetch_userpriv_ok(_imp->params.environment()->reduced_gid() != getgid() &&
- check_userpriv(FSPath(_imp->params.distdir()), _imp->params.environment(),
- id->eapi()->supported()->userpriv_cannot_use_root()));
-
- std::string archives, all_archives;
- {
- std::set<std::string> already_in_archives;
-
- /* make A */
- AFinder f(_imp->params.environment(), id);
- if (id->fetches_key())
- id->fetches_key()->value()->top()->accept(f);
-
- for (AFinder::ConstIterator i(f.begin()), i_end(f.end()) ; i != i_end ; ++i)
- {
- const FetchableURIDepSpec * const spec(static_cast<const FetchableURIDepSpec *>(i->first));
-
- if (already_in_archives.end() == already_in_archives.find(spec->filename()))
- {
- archives.append(spec->filename());
- already_in_archives.insert(spec->filename());
- }
- archives.append(" ");
- }
-
- /* make AA */
- if (! id->eapi()->supported()->ebuild_environment_variables()->env_aa().empty())
- {
- AAVisitor g;
- if (id->fetches_key())
- id->fetches_key()->value()->top()->accept(g);
- std::set<std::string> already_in_all_archives;
-
- for (AAVisitor::ConstIterator gg(g.begin()), gg_end(g.end()) ; gg != gg_end ; ++gg)
- {
- if (already_in_all_archives.end() == already_in_all_archives.find(*gg))
- {
- all_archives.append(*gg);
- already_in_all_archives.insert(*gg);
- }
- all_archives.append(" ");
- }
- }
- else
- all_archives = "AA-not-set-for-this-EAPI";
- }
-
- /* Strip trailing space. Some ebuilds rely upon this. From kde-meta.eclass:
- * [[ -n ${A/${TARBALL}/} ]] && unpack ${A/${TARBALL}/}
- * Rather annoying.
- */
- archives = strip_trailing(archives, " ");
- all_archives = strip_trailing(all_archives, " ");
-
- std::shared_ptr<OutputManager> output_manager(fetch_action.options.make_output_manager()(fetch_action));
-
- CheckFetchedFilesVisitor c(_imp->params.environment(), id, _imp->params.distdir(),
- fetch_action.options.fetch_parts()[fp_unneeded], fetch_restrict,
- ((_imp->layout->package_directory(id->name())) / "Manifest"),
- _imp->params.use_manifest(),
- output_manager, fetch_action.options.exclude_unmirrorable(),
- fetch_action.options.ignore_unfetched(),
- fetch_action.options.ignore_not_in_manifest());
-
- if (id->fetches_key())
- {
- /* always use mirror://gentoo/, where gentoo is the name of our first master repository,
- * or our name if there's no master. */
- std::string mirrors_name(
- (_imp->params.master_repositories() && ! _imp->params.master_repositories()->empty()) ?
- stringify((*_imp->params.master_repositories()->begin())->name()) :
- stringify(name()));
-
- if (fetch_action.options.fetch_parts()[fp_regulars] && ! fetch_action.options.ignore_unfetched())
- {
- need_mirrors();
-
- FetchVisitor f(_imp->params.environment(), id, *id->eapi(),
- _imp->params.distdir(), fetch_action.options.fetch_parts()[fp_unneeded],
- fetch_userpriv_ok, mirrors_name,
- id->fetches_key()->initial_label(), fetch_action.options.safe_resume(),
- output_manager, std::bind(&get_mirrors_fn, std::placeholders::_1, std::cref(_imp->mirrors)));
- id->fetches_key()->value()->top()->accept(f);
- }
-
- id->fetches_key()->value()->top()->accept(c);
- }
-
- if ( (fetch_action.options.fetch_parts()[fp_extras]) && ((c.need_nofetch()) ||
- ((! fetch_action.options.ignore_unfetched()) && (! id->eapi()->supported()->ebuild_phases()->ebuild_fetch_extra().empty()))))
- {
- bool userpriv_ok((! userpriv_restrict) && (_imp->params.environment()->reduced_gid() != getgid()) &&
- check_userpriv(FSPath(_imp->params.builddir()), _imp->params.environment(),
- id->eapi()->supported()->userpriv_cannot_use_root()));
- std::string use(make_use(_imp->params.environment(), *id, profile()));
- std::shared_ptr<Map<std::string, std::string> > expand_vars(make_expand(
- _imp->params.environment(), *id, profile()));
-
- std::shared_ptr<const FSPathSequence> exlibsdirs(layout()->exlibsdirs(id->name()));
-
- EAPIPhases fetch_extra_phases(id->eapi()->supported()->ebuild_phases()->ebuild_fetch_extra());
- if ((! fetch_action.options.ignore_unfetched()) && (fetch_extra_phases.begin_phases() != fetch_extra_phases.end_phases()))
- {
- FSPath package_builddir(_imp->params.builddir() / (stringify(id->name().category()) + "-" +
- stringify(id->name().package()) + "-" + stringify(id->version()) + "-fetch_extra"));
-
- for (EAPIPhases::ConstIterator phase(fetch_extra_phases.begin_phases()), phase_end(fetch_extra_phases.end_phases()) ;
- phase != phase_end ; ++phase)
- {
- bool skip(false);
- do
- {
- switch (fetch_action.options.want_phase()(phase->equal_option("skipname")))
- {
- case wp_yes:
- continue;
-
- case wp_skip:
- skip = true;
- continue;
-
- case wp_abort:
- throw ActionAbortedError("Told to abort fetch");
-
- case last_wp:
- break;
- }
-
- throw InternalError(PALUDIS_HERE, "bad want_phase");
- } while (false);
-
- if (skip)
- continue;
-
- if (can_skip_phase(id, *phase))
- continue;
-
- EbuildCommandParams command_params(make_named_values<EbuildCommandParams>(
- n::builddir() = _imp->params.builddir(),
- n::clearenv() = phase->option("clearenv"),
- n::commands() = join(phase->begin_commands(), phase->end_commands(), " "),
- n::distdir() = _imp->params.distdir(),
- n::ebuild_dir() = layout()->package_directory(id->name()),
- n::ebuild_file() = id->fs_location_key()->value(),
- n::eclassdirs() = _imp->params.eclassdirs(),
- n::environment() = _imp->params.environment(),
- n::exlibsdirs() = exlibsdirs,
- n::files_dir() = layout()->package_directory(id->name()) / "files",
- n::maybe_output_manager() = output_manager,
- n::package_builddir() = package_builddir,
- n::package_id() = id,
- n::portdir() =
- (_imp->params.master_repositories() && ! _imp->params.master_repositories()->empty()) ?
- (*_imp->params.master_repositories()->begin())->params().location() : _imp->params.location(),
- n::root() = "/",
- n::sandbox() = phase->option("sandbox"),
- n::sydbox() = phase->option("sydbox"),
- n::userpriv() = phase->option("userpriv") && userpriv_ok
- ));
-
- EbuildFetchExtraCommand fetch_extra_cmd(command_params, make_named_values<EbuildFetchExtraCommandParams>(
- n::a() = archives,
- n::aa() = all_archives,
- n::expand_vars() = expand_vars,
- n::loadsaveenv_dir() = package_builddir / "temp",
- n::profiles() = _imp->params.profiles(),
- n::profiles_with_parents() = profile()->profiles_with_parents(),
- n::slot() = id->slot_key() ? stringify(id->slot_key()->value()) : "",
- n::use() = use,
- n::use_expand() = join(profile()->use_expand()->begin(), profile()->use_expand()->end(), " "),
- n::use_expand_hidden() = join(profile()->use_expand_hidden()->begin(), profile()->use_expand_hidden()->end(), " ")
- ));
-
- if (! fetch_extra_cmd())
- throw ActionFailedError("Fetch of '" + stringify(*id) + "' failed");
- }
- }
-
- if (c.need_nofetch())
- {
- EAPIPhases phases(id->eapi()->supported()->ebuild_phases()->ebuild_nofetch());
- for (EAPIPhases::ConstIterator phase(phases.begin_phases()), phase_end(phases.end_phases()) ;
- phase != phase_end ; ++phase)
- {
- EbuildCommandParams command_params(make_named_values<EbuildCommandParams>(
- n::builddir() = _imp->params.builddir(),
- n::clearenv() = phase->option("clearenv"),
- n::commands() = join(phase->begin_commands(), phase->end_commands(), " "),
- n::distdir() = _imp->params.distdir(),
- n::ebuild_dir() = layout()->package_directory(id->name()),
- n::ebuild_file() = id->fs_location_key()->value(),
- n::eclassdirs() = _imp->params.eclassdirs(),
- n::environment() = _imp->params.environment(),
- n::exlibsdirs() = exlibsdirs,
- n::files_dir() = layout()->package_directory(id->name()) / "files",
- n::maybe_output_manager() = output_manager,
- n::package_builddir() = _imp->params.builddir() / (stringify(id->name().category()) + "-" + stringify(id->name().package()) + "-" + stringify(id->version()) + "-nofetch"),
- n::package_id() = id,
- n::portdir() = (_imp->params.master_repositories() && ! _imp->params.master_repositories()->empty()) ?
- (*_imp->params.master_repositories()->begin())->params().location() : _imp->params.location(),
- n::root() = "/",
- n::sandbox() = phase->option("sandbox"),
- n::sydbox() = phase->option("sydbox"),
- n::userpriv() = phase->option("userpriv") && userpriv_ok
- ));
-
- EbuildNoFetchCommand nofetch_cmd(command_params,
- make_named_values<EbuildNoFetchCommandParams>(
- n::a() = archives,
- n::aa() = all_archives,
- n::expand_vars() = expand_vars,
- n::profiles() = _imp->params.profiles(),
- n::profiles_with_parents() = profile()->profiles_with_parents(),
- n::use() = use,
- n::use_expand() = join(profile()->use_expand()->begin(), profile()->use_expand()->end(), " "),
- n::use_expand_hidden() = join(profile()->use_expand_hidden()->begin(), profile()->use_expand_hidden()->end(), " ")
- ));
-
- if (! nofetch_cmd())
- {
- std::copy(c.failures()->begin(), c.failures()->end(),
- fetch_action.options.errors()->back_inserter());
- throw ActionFailedError("Fetch of '" + stringify(*id) + "' failed");
- }
- }
- }
- }
-
- if (! c.failures()->empty())
- {
- std::copy(c.failures()->begin(), c.failures()->end(),
- fetch_action.options.errors()->back_inserter());
- throw ActionFailedError("Fetch of '" + stringify(*id) + "' failed");
- }
-
- output_manager->succeeded();
-}
-
-void
-ERepository::pretend_fetch(const std::shared_ptr<const ERepositoryID> & id,
- PretendFetchAction & a) const
-{
- using namespace std::placeholders;
-
- Context context("When pretending to fetch ID '" + stringify(*id) + "':");
-
- if (id->fetches_key())
- {
- PretendFetchVisitor f(_imp->params.environment(), id, *id->eapi(),
- params().distdir(), a.options.fetch_parts()[fp_unneeded],
- id->fetches_key()->initial_label(), a);
- id->fetches_key()->value()->top()->accept(f);
- }
-}
-
-namespace
-{
- bool slot_is_same(const std::shared_ptr<const PackageID> & a,
- const std::shared_ptr<const PackageID> & b)
- {
- if (a->slot_key())
- return b->slot_key() && a->slot_key()->value() == b->slot_key()->value();
- else
- return ! b->slot_key();
- }
-
- void used_this_for_config_protect(std::string & s, const std::string & v)
- {
- s = v;
- }
-
- std::shared_ptr<OutputManager> this_output_manager(const std::shared_ptr<OutputManager> & o, const Action &)
- {
- return o;
- }
-
- void installed_this(const FSPath &)
- {
- }
-
- bool ignore_merged(const std::shared_ptr<const FSPathSet> & s, const FSPath & f)
- {
- return s->end() != s->find(f);
- }
-
- struct AcceptLicenseFinder
- {
- std::stringstream s;
-
- AcceptLicenseFinder()
- {
- s << "*";
- }
-
- void visit(const LicenseSpecTree::NodeType<AllDepSpec>::Type & node)
- {
- std::for_each(indirect_iterator(node.begin()), indirect_iterator(node.end()), accept_visitor(*this));
- }
-
- void visit(const LicenseSpecTree::NodeType<AnyDepSpec>::Type & node)
- {
- std::for_each(indirect_iterator(node.begin()), indirect_iterator(node.end()), accept_visitor(*this));
- }
-
- void visit(const LicenseSpecTree::NodeType<ConditionalDepSpec>::Type & node)
- {
- if (node.spec()->condition_met())
- std::for_each(indirect_iterator(node.begin()), indirect_iterator(node.end()), accept_visitor(*this));
- }
-
- void visit(const LicenseSpecTree::NodeType<LicenseDepSpec>::Type & node)
- {
- s << " " << node.spec()->text();
- }
- };
-}
-
-void
-ERepository::install(const std::shared_ptr<const ERepositoryID> & id,
- const InstallAction & install_action) const
-{
- using namespace std::placeholders;
-
- Context context("When installing '" + stringify(*id) + "'" +
- (install_action.options.replacing()->empty() ? "" : " replacing { '"
- + join(indirect_iterator(install_action.options.replacing()->begin()),
- indirect_iterator(install_action.options.replacing()->end()), "', '") + "' }") + ":");
-
- std::shared_ptr<OutputManager> output_manager(install_action.options.make_output_manager()(install_action));
-
- bool userpriv_restrict, test_restrict, strip_restrict;
- {
- DepSpecFlattener<PlainTextSpecTree, PlainTextDepSpec> restricts(_imp->params.environment());
- if (id->restrict_key())
- id->restrict_key()->value()->top()->accept(restricts);
-
- userpriv_restrict =
- indirect_iterator(restricts.end()) != std::find_if(indirect_iterator(restricts.begin()), indirect_iterator(restricts.end()),
- std::bind(std::equal_to<std::string>(), std::bind(std::mem_fn(&StringDepSpec::text), _1), "userpriv")) ||
- indirect_iterator(restricts.end()) != std::find_if(indirect_iterator(restricts.begin()), indirect_iterator(restricts.end()),
- std::bind(std::equal_to<std::string>(), std::bind(std::mem_fn(&StringDepSpec::text), _1), "nouserpriv"));
-
- test_restrict =
- indirect_iterator(restricts.end()) != std::find_if(indirect_iterator(restricts.begin()), indirect_iterator(restricts.end()),
- std::bind(std::equal_to<std::string>(), std::bind(std::mem_fn(&StringDepSpec::text), _1), "test"));
-
- strip_restrict =
- indirect_iterator(restricts.end()) != std::find_if(indirect_iterator(restricts.begin()), indirect_iterator(restricts.end()),
- std::bind(std::equal_to<std::string>(), std::bind(std::mem_fn(&StringDepSpec::text), _1), "strip")) ||
- indirect_iterator(restricts.end()) != std::find_if(indirect_iterator(restricts.begin()), indirect_iterator(restricts.end()),
- std::bind(std::equal_to<std::string>(), std::bind(std::mem_fn(&StringDepSpec::text), _1), "nostrip"));
- }
-
- std::string archives, all_archives, accept_license;
- {
- std::set<std::string> already_in_archives;
-
- /* make A */
- AFinder f(_imp->params.environment(), id);
- if (id->fetches_key())
- id->fetches_key()->value()->top()->accept(f);
-
- for (AFinder::ConstIterator i(f.begin()), i_end(f.end()) ; i != i_end ; ++i)
- {
- const FetchableURIDepSpec * const spec(static_cast<const FetchableURIDepSpec *>(i->first));
-
- if (already_in_archives.end() == already_in_archives.find(spec->filename()))
- {
- archives.append(spec->filename());
- already_in_archives.insert(spec->filename());
- }
- archives.append(" ");
- }
-
- /* make AA */
- if (! id->eapi()->supported()->ebuild_environment_variables()->env_aa().empty())
- {
- AAVisitor g;
- if (id->fetches_key())
- id->fetches_key()->value()->top()->accept(g);
- std::set<std::string> already_in_all_archives;
-
- for (AAVisitor::ConstIterator gg(g.begin()), gg_end(g.end()) ; gg != gg_end ; ++gg)
- {
- if (already_in_all_archives.end() == already_in_all_archives.find(*gg))
- {
- all_archives.append(*gg);
- already_in_all_archives.insert(*gg);
- }
- all_archives.append(" ");
- }
- }
- else
- all_archives = "AA-not-set-for-this-EAPI";
-
- /* make ACCEPT_LICENSE */
- if (! id->eapi()->supported()->ebuild_environment_variables()->env_accept_license().empty())
- {
- AcceptLicenseFinder g;
- if (id->license_key())
- id->license_key()->value()->top()->accept(g);
-
- accept_license = g.s.str();
- }
- else
- accept_license = "ACCEPT_LICENSE-not-set-for-this-EAPI";
- }
-
- /* Strip trailing space. Some ebuilds rely upon this. From kde-meta.eclass:
- * [[ -n ${A/${TARBALL}/} ]] && unpack ${A/${TARBALL}/}
- * Rather annoying.
- */
- archives = strip_trailing(archives, " ");
- all_archives = strip_trailing(all_archives, " ");
-
- /* make use */
- std::string use(make_use(_imp->params.environment(), *id, profile()));
-
- /* add expand to use (iuse isn't reliable for use_expand things), and make the expand
- * environment variables */
- std::shared_ptr<Map<std::string, std::string> > expand_vars(make_expand(
- _imp->params.environment(), *id, profile()));
-
- std::shared_ptr<const FSPathSequence> exlibsdirs(layout()->exlibsdirs(id->name()));
-
- bool userpriv_ok((! userpriv_restrict) && (_imp->params.environment()->reduced_gid() != getgid()) &&
- check_userpriv(FSPath(_imp->params.distdir()), _imp->params.environment(), id->eapi()->supported()->userpriv_cannot_use_root()) &&
- check_userpriv(FSPath(_imp->params.builddir()), _imp->params.environment(), id->eapi()->supported()->userpriv_cannot_use_root()));
-
- FSPath package_builddir(_imp->params.builddir() / (stringify(id->name().category()) + "-" +
- stringify(id->name().package()) + "-" + stringify(id->version())));
-
- std::string used_config_protect;
- auto merged_entries(std::make_shared<FSPathSet>());
-
- std::shared_ptr<const ChoiceValue> preserve_work_choice(
- id->choices_key()->value()->find_by_name_with_prefix(
- ELikePreserveWorkChoiceValue::canonical_name_with_prefix()));
-
- EAPIPhases phases(id->eapi()->supported()->ebuild_phases()->ebuild_install());
- for (EAPIPhases::ConstIterator phase(phases.begin_phases()), phase_end(phases.end_phases()) ;
- phase != phase_end ; ++phase)
- {
- bool skip(false);
- do
- {
- switch (install_action.options.want_phase()(phase->equal_option("skipname")))
- {
- case wp_yes:
- continue;
-
- case wp_skip:
- skip = true;
- continue;
-
- case wp_abort:
- throw ActionAbortedError("Told to abort install");
-
- case last_wp:
- break;
- }
-
- throw InternalError(PALUDIS_HERE, "bad want_phase");
- } while (false);
-
- if (skip)
- continue;
-
- if (can_skip_phase(id, *phase))
- {
- output_manager->stdout_stream() << "--- No need to do anything for " << phase->equal_option("skipname") << " phase" << std::endl;
- continue;
- }
-
- if (phase->option("tidyup") && preserve_work_choice && preserve_work_choice->enabled())
- {
- output_manager->stdout_stream() << "--- Skipping " << phase->equal_option("skipname")
- << " phase to preserve work" << std::endl;
- continue;
- }
-
- if (phase->option("merge"))
- {
- if (! (*install_action.options.destination()).destination_interface())
- throw ActionFailedError("Can't install '" + stringify(*id)
- + "' to destination '" + stringify(install_action.options.destination()->name())
- + "' because destination does not provide destination_interface");
-
- MergerOptions extra_merger_options;
- if (preserve_work_choice && preserve_work_choice->enabled())
- extra_merger_options += mo_nondestructive;
-
- Timestamp build_start_time(FSPath(package_builddir / "temp" / "build_start_time").stat().mtim());
- (*install_action.options.destination()).destination_interface()->merge(
- make_named_values<MergeParams>(
- n::build_start_time() = build_start_time,
- n::environment_file() = package_builddir / "temp" / "loadsaveenv",
- n::image_dir() = package_builddir / "image",
- n::merged_entries() = merged_entries,
- n::options() = id->eapi()->supported()->merger_options() | extra_merger_options,
- n::output_manager() = output_manager,
- n::package_id() = id,
- n::perform_uninstall() = install_action.options.perform_uninstall(),
- n::used_this_for_config_protect() = std::bind(
- &used_this_for_config_protect, std::ref(used_config_protect), std::placeholders::_1)
- ));
- }
- else if (phase->option("strip"))
- {
- if ((! id->eapi()->supported()->is_pbin()) && (! strip_restrict))
- {
- std::string libdir("lib");
- FSPath root(install_action.options.destination()->installed_root_key() ?
- stringify(install_action.options.destination()->installed_root_key()->value()) : "/");
- if ((root / "usr" / "lib").stat().is_symlink())
- {
- libdir = (root / "usr" / "lib").readlink();
- if (std::string::npos != libdir.find_first_of("./"))
- libdir = "lib";
- }
-
- Log::get_instance()->message("e.ebuild.libdir", ll_debug, lc_context) << "Using '" << libdir << "' for libdir";
-
- std::shared_ptr<const ChoiceValue> strip_choice(id->choices_key()->value()->find_by_name_with_prefix(
- ELikeStripChoiceValue::canonical_name_with_prefix()));
- std::shared_ptr<const ChoiceValue> split_choice(id->choices_key()->value()->find_by_name_with_prefix(
- ELikeSplitChoiceValue::canonical_name_with_prefix()));
-
- EStripper stripper(make_named_values<EStripperOptions>(
- n::debug_dir() = package_builddir / "image" / "usr" / libdir / "debug",
- n::image_dir() = package_builddir / "image",
- n::output_manager() = output_manager,
- n::package_id() = id,
- n::split() = split_choice && split_choice->enabled(),
- n::strip() = strip_choice && strip_choice->enabled()
- ));
- stripper.strip();
- }
- }
- else if ((! phase->option("prepost")) ||
- ((*install_action.options.destination()).destination_interface() &&
- (*install_action.options.destination()).destination_interface()->want_pre_post_phases()))
- {
- if (phase->option("optional_tests"))
- {
- if (test_restrict)
- continue;
-
- std::shared_ptr<const ChoiceValue> choice(id->choices_key()->value()->find_by_name_with_prefix(
- ELikeOptionalTestsChoiceValue::canonical_name_with_prefix()));
- if (choice && ! choice->enabled())
- continue;
- }
- else if (phase->option("recommended_tests"))
- {
- if (test_restrict)
- continue;
-
- std::shared_ptr<const ChoiceValue> choice(id->choices_key()->value()->find_by_name_with_prefix(
- ELikeRecommendedTestsChoiceValue::canonical_name_with_prefix()));
- if (choice && ! choice->enabled())
- continue;
- }
- else if (phase->option("expensive_tests"))
- {
- std::shared_ptr<const ChoiceValue> choice(id->choices_key()->value()->find_by_name_with_prefix(
- ELikeExpensiveTestsChoiceValue::canonical_name_with_prefix()));
- if (choice && ! choice->enabled())
- continue;
- }
-
- EbuildCommandParams command_params(make_named_values<EbuildCommandParams>(
- n::builddir() = _imp->params.builddir(),
- n::clearenv() = phase->option("clearenv"),
- n::commands() = join(phase->begin_commands(), phase->end_commands(), " "),
- n::distdir() = _imp->params.distdir(),
- n::ebuild_dir() = layout()->package_directory(id->name()),
- n::ebuild_file() = id->fs_location_key()->value(),
- n::eclassdirs() = _imp->params.eclassdirs(),
- n::environment() = _imp->params.environment(),
- n::exlibsdirs() = exlibsdirs,
- n::files_dir() = layout()->package_directory(id->name()) / "files",
- n::maybe_output_manager() = output_manager,
- n::package_builddir() = package_builddir,
- n::package_id() = id,
- n::portdir() =
- (_imp->params.master_repositories() && ! _imp->params.master_repositories()->empty()) ?
- (*_imp->params.master_repositories()->begin())->params().location() : _imp->params.location(),
- n::root() = install_action.options.destination()->installed_root_key() ?
- stringify(install_action.options.destination()->installed_root_key()->value()) :
- "/",
- n::sandbox() = phase->option("sandbox"),
- n::sydbox() = phase->option("sydbox"),
- n::userpriv() = phase->option("userpriv") && userpriv_ok
- ));
-
- EbuildInstallCommandParams install_params(
- make_named_values<EbuildInstallCommandParams>(
- n::a() = archives,
- n::aa() = all_archives,
- n::accept_license() = accept_license,
- n::config_protect() = environment_updated_profile_variable("CONFIG_PROTECT"),
- n::config_protect_mask() = environment_updated_profile_variable("CONFIG_PROTECT_MASK"),
- n::destination() = install_action.options.destination(),
- n::expand_vars() = expand_vars,
- n::is_from_pbin() = id->eapi()->supported()->is_pbin(),
- n::loadsaveenv_dir() = package_builddir / "temp",
- n::profiles() = _imp->params.profiles(),
- n::profiles_with_parents() = profile()->profiles_with_parents(),
- n::replacing_ids() = install_action.options.replacing(),
- n::slot() = id->slot_key() ? stringify(id->slot_key()->value()) : "",
- n::use() = use,
- n::use_expand() = join(profile()->use_expand()->begin(), profile()->use_expand()->end(), " "),
- n::use_expand_hidden() = join(profile()->use_expand_hidden()->begin(), profile()->use_expand_hidden()->end(), " ")
- ));
-
- EbuildInstallCommand cmd(command_params, install_params);
- cmd();
- }
- }
-
- for (PackageIDSequence::ConstIterator i(install_action.options.replacing()->begin()), i_end(install_action.options.replacing()->end()) ;
- i != i_end ; ++i)
- {
- Context local_context("When cleaning '" + stringify(**i) + "':");
- if ((*i)->name() == id->name() && (*i)->version() == id->version())
- continue;
-
- if (id->eapi()->supported()->ebuild_phases()->ebuild_new_upgrade_phase_order())
- if ((*i)->name() == id->name() && slot_is_same(*i, id))
- continue;
-
- UninstallActionOptions uo(make_named_values<UninstallActionOptions>(
- n::config_protect() = used_config_protect,
- n::if_for_install_id() = id,
- n::ignore_for_unmerge() = std::bind(&ignore_merged, merged_entries,
- std::placeholders::_1),
- n::is_overwrite() = false,
- n::make_output_manager() = std::bind(&this_output_manager, output_manager, std::placeholders::_1)
- ));
- install_action.options.perform_uninstall()(*i, uo);
- }
-
- output_manager->succeeded();
-}
-
-void
-ERepository::info(const std::shared_ptr<const ERepositoryID> & id,
- const InfoAction & a) const
-{
- using namespace std::placeholders;
-
- Context context("When infoing '" + stringify(*id) + "':");
-
- std::shared_ptr<OutputManager> output_manager(a.options.make_output_manager()(a));
-
- bool userpriv_restrict;
- {
- DepSpecFlattener<PlainTextSpecTree, PlainTextDepSpec> restricts(_imp->params.environment());
- if (id->restrict_key())
- id->restrict_key()->value()->top()->accept(restricts);
-
- userpriv_restrict =
- indirect_iterator(restricts.end()) != std::find_if(indirect_iterator(restricts.begin()), indirect_iterator(restricts.end()),
- std::bind(std::equal_to<std::string>(), std::bind(std::mem_fn(&StringDepSpec::text), _1), "userpriv")) ||
- indirect_iterator(restricts.end()) != std::find_if(indirect_iterator(restricts.begin()), indirect_iterator(restricts.end()),
- std::bind(std::equal_to<std::string>(), std::bind(std::mem_fn(&StringDepSpec::text), _1), "nouserpriv"));
- }
- bool userpriv_ok((! userpriv_restrict) && (_imp->params.environment()->reduced_gid() != getgid()) &&
- check_userpriv(FSPath(_imp->params.builddir()), _imp->params.environment(), id->eapi()->supported()->userpriv_cannot_use_root()));
-
- /* make use */
- std::string use(make_use(_imp->params.environment(), *id, profile()));
-
- /* add expand to use (iuse isn't reliable for use_expand things), and make the expand
- * environment variables */
- std::shared_ptr<Map<std::string, std::string> > expand_vars(make_expand(
- _imp->params.environment(), *id, profile()));
-
- std::shared_ptr<const FSPathSequence> exlibsdirs(layout()->exlibsdirs(id->name()));
-
- EAPIPhases phases(id->eapi()->supported()->ebuild_phases()->ebuild_info());
- for (EAPIPhases::ConstIterator phase(phases.begin_phases()), phase_end(phases.end_phases()) ;
- phase != phase_end ; ++phase)
- {
- if (phase->option("installed=true"))
- continue;
-
- EbuildCommandParams command_params(make_named_values<EbuildCommandParams>(
- n::builddir() = _imp->params.builddir(),
- n::clearenv() = phase->option("clearenv"),
- n::commands() = join(phase->begin_commands(), phase->end_commands(), " "),
- n::distdir() = _imp->params.distdir(),
- n::ebuild_dir() = layout()->package_directory(id->name()),
- n::ebuild_file() = id->fs_location_key()->value(),
- n::eclassdirs() = _imp->params.eclassdirs(),
- n::environment() = _imp->params.environment(),
- n::exlibsdirs() = exlibsdirs,
- n::files_dir() = layout()->package_directory(id->name()) / "files",
- n::maybe_output_manager() = output_manager,
- n::package_builddir() = _imp->params.builddir() / (stringify(id->name().category()) + "-" + stringify(id->name().package()) + "-" + stringify(id->version()) + "-info"),
- n::package_id() = id,
- n::portdir() =
- (_imp->params.master_repositories() && ! _imp->params.master_repositories()->empty()) ?
- (*_imp->params.master_repositories()->begin())->params().location() : _imp->params.location(),
- n::root() = stringify(_imp->params.environment()->preferred_root_key()->value()),
- n::sandbox() = phase->option("sandbox"),
- n::sydbox() = phase->option("sydbox"),
- n::userpriv() = phase->option("userpriv") && userpriv_ok
- ));
-
- EbuildInfoCommandParams info_params(
- make_named_values<EbuildInfoCommandParams>(
- n::expand_vars() = expand_vars,
- n::info_vars() = info_vars_key() ?
- info_vars_key()->value() : std::make_shared<const Set<std::string>>(),
- n::load_environment() = static_cast<const FSPath *>(0),
- n::profiles() = _imp->params.profiles(),
- n::profiles_with_parents() = profile()->profiles_with_parents(),
- n::use() = use,
- n::use_ebuild_file() = true,
- n::use_expand() = join(profile()->use_expand()->begin(), profile()->use_expand()->end(), " "),
- n::use_expand_hidden() = join(profile()->use_expand_hidden()->begin(), profile()->use_expand_hidden()->end(), " ")
- ));
-
- EbuildInfoCommand cmd(command_params, info_params);
- cmd();
- }
-
- output_manager->succeeded();
-}
-
std::string
ERepository::get_environment_variable(
const std::shared_ptr<const PackageID> & id_uncasted,
@@ -2954,166 +1997,6 @@ ERepository::extract_package_file_version(const QualifiedPackageName & n, const
_imp->params.eapi_when_unknown())->supported()->version_spec_options());
}
-bool
-ERepository::pretend(
- const std::shared_ptr<const ERepositoryID> & id,
- const PretendAction & a) const
-{
- using namespace std::placeholders;
-
- Context context("When running pretend for '" + stringify(*id) + "':");
-
- if (! id->eapi()->supported())
- return false;
-
- bool result(true);
-
- if (! id->raw_myoptions_key())
- if (id->eapi()->supported()->ebuild_phases()->ebuild_pretend().empty())
- return result;
-
- bool userpriv_restrict;
- {
- DepSpecFlattener<PlainTextSpecTree, PlainTextDepSpec> restricts(_imp->params.environment());
- if (id->restrict_key())
- id->restrict_key()->value()->top()->accept(restricts);
-
- userpriv_restrict =
- indirect_iterator(restricts.end()) != std::find_if(indirect_iterator(restricts.begin()), indirect_iterator(restricts.end()),
- std::bind(std::equal_to<std::string>(), std::bind(std::mem_fn(&StringDepSpec::text), _1), "userpriv")) ||
- indirect_iterator(restricts.end()) != std::find_if(indirect_iterator(restricts.begin()), indirect_iterator(restricts.end()),
- std::bind(std::equal_to<std::string>(), std::bind(std::mem_fn(&StringDepSpec::text), _1), "nouserpriv"));
- }
- bool userpriv_ok((! userpriv_restrict) && (_imp->params.environment()->reduced_gid() != getgid()) &&
- check_userpriv(FSPath(_imp->params.builddir()), _imp->params.environment(), id->eapi()->supported()->userpriv_cannot_use_root()));
-
- std::string use(make_use(_imp->params.environment(), *id, profile()));
- std::shared_ptr<Map<std::string, std::string> > expand_vars(make_expand(
- _imp->params.environment(), *id, profile()));
-
- std::shared_ptr<const FSPathSequence> exlibsdirs(layout()->exlibsdirs(id->name()));
-
- std::shared_ptr<OutputManager> output_manager;
-
- if (id->raw_myoptions_key())
- {
- MyOptionsRequirementsVerifier verifier(id);
- id->raw_myoptions_key()->value()->top()->accept(verifier);
-
- if (verifier.unmet_requirements() && ! verifier.unmet_requirements()->empty())
- {
- EAPIPhases phases(id->eapi()->supported()->ebuild_phases()->ebuild_bad_options());
- if (phases.begin_phases() == phases.end_phases())
- throw InternalError(PALUDIS_HERE, "using myoptions but no ebuild_bad_options phase");
-
- for (EAPIPhases::ConstIterator phase(phases.begin_phases()), phase_end(phases.end_phases()) ;
- phase != phase_end ; ++phase)
- {
- if (! output_manager)
- output_manager = a.options.make_output_manager()(a);
-
- EbuildCommandParams command_params(make_named_values<EbuildCommandParams>(
- n::builddir() = _imp->params.builddir(),
- n::clearenv() = phase->option("clearenv"),
- n::commands() = join(phase->begin_commands(), phase->end_commands(), " "),
- n::distdir() = _imp->params.distdir(),
- n::ebuild_dir() = layout()->package_directory(id->name()),
- n::ebuild_file() = id->fs_location_key()->value(),
- n::eclassdirs() = _imp->params.eclassdirs(),
- n::environment() = _imp->params.environment(),
- n::exlibsdirs() = exlibsdirs,
- n::files_dir() = layout()->package_directory(id->name()) / "files",
- n::maybe_output_manager() = output_manager,
- n::package_builddir() = _imp->params.builddir() / (stringify(id->name().category()) + "-" + stringify(id->name().package()) + "-" + stringify(id->version()) + "-bad_options"),
- n::package_id() = id,
- n::portdir() =
- (_imp->params.master_repositories() && ! _imp->params.master_repositories()->empty()) ?
- (*_imp->params.master_repositories()->begin())->params().location() : _imp->params.location(),
- n::root() = a.options.destination()->installed_root_key() ?
- stringify(a.options.destination()->installed_root_key()->value()) :
- "/",
- n::sandbox() = phase->option("sandbox"),
- n::sydbox() = phase->option("sydbox"),
- n::userpriv() = phase->option("userpriv") && userpriv_ok
- ));
-
- EbuildBadOptionsCommand bad_options_cmd(command_params,
- make_named_values<EbuildBadOptionsCommandParams>(
- n::expand_vars() = expand_vars,
- n::profiles() = _imp->params.profiles(),
- n::profiles_with_parents() = profile()->profiles_with_parents(),
- n::unmet_requirements() = verifier.unmet_requirements(),
- n::use() = use,
- n::use_expand() = join(profile()->use_expand()->begin(), profile()->use_expand()->end(), " "),
- n::use_expand_hidden() = join(profile()->use_expand_hidden()->begin(), profile()->use_expand_hidden()->end(), " ")
- ));
-
- if (! bad_options_cmd())
- throw ActionFailedError("Bad options phase died");
- }
-
- result = false;
- }
- }
-
- if (id->eapi()->supported()->ebuild_phases()->ebuild_pretend().empty())
- return result;
-
- EAPIPhases phases(id->eapi()->supported()->ebuild_phases()->ebuild_pretend());
- for (EAPIPhases::ConstIterator phase(phases.begin_phases()), phase_end(phases.end_phases()) ;
- phase != phase_end ; ++phase)
- {
- if (can_skip_phase(id, *phase))
- continue;
-
- if (! output_manager)
- output_manager = a.options.make_output_manager()(a);
-
- EbuildCommandParams command_params(make_named_values<EbuildCommandParams>(
- n::builddir() = _imp->params.builddir(),
- n::clearenv() = phase->option("clearenv"),
- n::commands() = join(phase->begin_commands(), phase->end_commands(), " "),
- n::distdir() = _imp->params.distdir(),
- n::ebuild_dir() = layout()->package_directory(id->name()),
- n::ebuild_file() = id->fs_location_key()->value(),
- n::eclassdirs() = _imp->params.eclassdirs(),
- n::environment() = _imp->params.environment(),
- n::exlibsdirs() = exlibsdirs,
- n::files_dir() = layout()->package_directory(id->name()) / "files",
- n::maybe_output_manager() = output_manager,
- n::package_builddir() = _imp->params.builddir() / (stringify(id->name().category()) + "-" + stringify(id->name().package()) + "-" + stringify(id->version()) + "-pretend"),
- n::package_id() = id,
- n::portdir() =
- (_imp->params.master_repositories() && ! _imp->params.master_repositories()->empty()) ?
- (*_imp->params.master_repositories()->begin())->params().location() : _imp->params.location(),
- n::root() = a.options.destination()->installed_root_key() ?
- stringify(a.options.destination()->installed_root_key()->value()) :
- "/",
- n::sandbox() = phase->option("sandbox"),
- n::sydbox() = phase->option("sydbox"),
- n::userpriv() = phase->option("userpriv") && userpriv_ok
- ));
-
- EbuildPretendCommand pretend_cmd(command_params,
- make_named_values<EbuildPretendCommandParams>(
- n::destination() = a.options.destination(),
- n::expand_vars() = expand_vars,
- n::is_from_pbin() = id->eapi()->supported()->is_pbin(),
- n::profiles() = _imp->params.profiles(),
- n::profiles_with_parents() = profile()->profiles_with_parents(),
- n::replacing_ids() = a.options.replacing(),
- n::use() = use,
- n::use_expand() = join(profile()->use_expand()->begin(), profile()->use_expand()->end(), " "),
- n::use_expand_hidden() = join(profile()->use_expand_hidden()->begin(), profile()->use_expand_hidden()->end(), " ")
- ));
-
- if (! pretend_cmd())
- return false;
- }
-
- return result;
-}
-
const std::string
ERepository::get_package_file_manifest_key(const FSPath & e, const QualifiedPackageName & q) const
{
@@ -3145,3 +2028,15 @@ ERepository::_guess_eapi(const QualifiedPackageName &, const FSPath & e) const
return Suffixes::get_instance()->guess_eapi(suffix);
}
+const std::shared_ptr<const MirrorsSequence>
+ERepository::get_mirrors(const std::string & m) const
+{
+ need_mirrors();
+
+ MirrorMap::const_iterator i(_imp->mirrors.find(m));
+ if (i == _imp->mirrors.end())
+ return std::make_shared<MirrorsSequence>();
+ else
+ return i->second;
+}
+
diff --git a/paludis/repositories/e/e_repository.hh b/paludis/repositories/e/e_repository.hh
index 666f079..1907135 100644
--- a/paludis/repositories/e/e_repository.hh
+++ b/paludis/repositories/e/e_repository.hh
@@ -197,6 +197,8 @@ namespace paludis
const std::string eapi_for_file(const FSPath &) const PALUDIS_ATTRIBUTE((warn_unused_result));
+ const std::shared_ptr<const MirrorsSequence> get_mirrors(const std::string & m) const;
+
///\name Set methods
///\{
@@ -217,21 +219,6 @@ namespace paludis
const QualifiedPackageName &, const FSPath &) const
PALUDIS_ATTRIBUTE((warn_unused_result));
- void fetch(const std::shared_ptr<const erepository::ERepositoryID> &,
- const FetchAction &) const;
-
- void pretend_fetch(const std::shared_ptr<const erepository::ERepositoryID> &,
- PretendFetchAction &) const;
-
- void install(const std::shared_ptr<const erepository::ERepositoryID> &,
- const InstallAction &) const;
-
- bool pretend(const std::shared_ptr<const erepository::ERepositoryID> &,
- const PretendAction &) const;
-
- void info(const std::shared_ptr<const erepository::ERepositoryID> &,
- const InfoAction &) const;
-
const std::string get_package_file_manifest_key(const FSPath &, const QualifiedPackageName &) const;
const std::string binary_ebuild_name(const QualifiedPackageName &, const VersionSpec &, const std::string &) const
diff --git a/paludis/repositories/e/ebuild_id.cc b/paludis/repositories/e/ebuild_id.cc
index 050ee4f..c7dee18 100644
--- a/paludis/repositories/e/ebuild_id.cc
+++ b/paludis/repositories/e/ebuild_id.cc
@@ -29,6 +29,11 @@
#include <paludis/repositories/e/manifest2_reader.hh>
#include <paludis/repositories/e/e_choice_value.hh>
#include <paludis/repositories/e/metadata_xml.hh>
+#include <paludis/repositories/e/do_pretend_action.hh>
+#include <paludis/repositories/e/do_pretend_fetch_action.hh>
+#include <paludis/repositories/e/do_install_action.hh>
+#include <paludis/repositories/e/do_info_action.hh>
+#include <paludis/repositories/e/do_fetch_action.hh>
#include <paludis/name.hh>
#include <paludis/version_spec.hh>
@@ -1222,37 +1227,41 @@ namespace
{
struct PerformAction
{
+ const Environment * const env;
const std::shared_ptr<const PackageID> id;
- PerformAction(const std::shared_ptr<const PackageID> i) :
- id(i)
- {
- }
-
void visit(InstallAction & a)
{
- std::static_pointer_cast<const ERepository>(id->repository())->install(
+ do_install_action(
+ env,
+ std::static_pointer_cast<const ERepository>(id->repository()).get(),
std::static_pointer_cast<const ERepositoryID>(id),
- a.options);
+ a);
}
void visit(FetchAction & a)
{
- std::static_pointer_cast<const ERepository>(id->repository())->fetch(
+ do_fetch_action(
+ env,
+ std::static_pointer_cast<const ERepository>(id->repository()).get(),
std::static_pointer_cast<const ERepositoryID>(id),
- a.options);
+ a);
}
void visit(PretendFetchAction & a)
{
- std::static_pointer_cast<const ERepository>(id->repository())->pretend_fetch(
+ do_pretend_fetch_action(
+ env,
+ std::static_pointer_cast<const ERepository>(id->repository()).get(),
std::static_pointer_cast<const ERepositoryID>(id),
a);
}
void visit(PretendAction & action)
{
- if (! std::static_pointer_cast<const ERepository>(id->repository())->pretend(
+ if (! do_pretend_action(
+ env,
+ std::static_pointer_cast<const ERepository>(id->repository()).get(),
std::static_pointer_cast<const ERepositoryID>(id),
action))
action.set_failed();
@@ -1260,7 +1269,9 @@ namespace
void visit(InfoAction & action)
{
- std::static_pointer_cast<const ERepository>(id->repository())->info(
+ do_info_action(
+ env,
+ std::static_pointer_cast<const ERepository>(id->repository()).get(),
std::static_pointer_cast<const ERepositoryID>(id),
action);
}
@@ -1286,7 +1297,7 @@ EbuildID::perform_action(Action & a) const
if (! eapi()->supported())
throw ActionFailedError("Unsupported EAPI");
- PerformAction b(shared_from_this());
+ PerformAction b{_imp->environment, shared_from_this()};
a.accept(b);
}
diff --git a/paludis/repositories/e/make_use.cc b/paludis/repositories/e/make_use.cc
new file mode 100644
index 0000000..220a435
--- /dev/null
+++ b/paludis/repositories/e/make_use.cc
@@ -0,0 +1,115 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2010 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/make_use.hh>
+#include <paludis/repositories/e/eapi.hh>
+#include <paludis/util/log.hh>
+#include <paludis/choice.hh>
+#include <paludis/metadata_key.hh>
+#include <paludis/elike_choices.hh>
+
+#include <algorithm>
+
+using namespace paludis;
+using namespace paludis::erepository;
+
+std::string
+paludis::erepository::make_use(const Environment * const,
+ const ERepositoryID & id,
+ std::shared_ptr<const Profile> profile)
+{
+ if (! id.eapi()->supported())
+ {
+ Log::get_instance()->message("e.ebuild.unknown_eapi", ll_warning, lc_context)
+ << "Can't make the USE string for '" << id << "' because its EAPI is unsupported";
+ return "";
+ }
+
+ std::string use;
+
+ if (id.choices_key())
+ {
+ for (Choices::ConstIterator k(id.choices_key()->value()->begin()),
+ k_end(id.choices_key()->value()->end()) ;
+ k != k_end ; ++k)
+ {
+ if ((*k)->prefix() == canonical_build_options_prefix())
+ continue;
+
+ for (Choice::ConstIterator i((*k)->begin()), i_end((*k)->end()) ;
+ i != i_end ; ++i)
+ if ((*i)->enabled())
+ use += stringify((*i)->name_with_prefix()) + " ";
+ }
+ }
+
+ if (! id.eapi()->supported()->ebuild_environment_variables()->env_arch().empty())
+ use += profile->environment_variable(id.eapi()->supported()->ebuild_environment_variables()->env_arch()) + " ";
+
+ return use;
+}
+
+std::shared_ptr<Map<std::string, std::string> >
+paludis::erepository::make_expand(const Environment * const,
+ const ERepositoryID & e,
+ std::shared_ptr<const Profile> profile)
+{
+ std::shared_ptr<Map<std::string, std::string> > expand_vars(std::make_shared<Map<std::string, std::string> >());
+
+ if (! e.eapi()->supported())
+ {
+ Log::get_instance()->message("e.ebuild.unknown_eapi", ll_warning, lc_context)
+ << "Can't make the USE_EXPAND strings for '" << e << "' because its EAPI is unsupported";
+ return expand_vars;
+ }
+
+ if (! e.choices_key())
+ return expand_vars;
+
+ for (Set<std::string>::ConstIterator x(profile->use_expand()->begin()), x_end(profile->use_expand()->end()) ;
+ x != x_end ; ++x)
+ {
+ expand_vars->insert(stringify(*x), "");
+
+ Choices::ConstIterator k(std::find_if(e.choices_key()->value()->begin(), e.choices_key()->value()->end(),
+ std::bind(std::equal_to<std::string>(), *x,
+ std::bind(std::mem_fn(&Choice::raw_name), std::placeholders::_1))));
+ if (k == e.choices_key()->value()->end())
+ continue;
+
+ for (Choice::ConstIterator i((*k)->begin()), i_end((*k)->end()) ;
+ i != i_end ; ++i)
+ if ((*i)->enabled())
+ {
+ std::string value;
+ Map<std::string, std::string>::ConstIterator v(expand_vars->find(stringify(*x)));
+ if (expand_vars->end() != v)
+ {
+ value = v->second;
+ if (! value.empty())
+ value.append(" ");
+ expand_vars->erase(v);
+ }
+ value.append(stringify((*i)->unprefixed_name()));
+ expand_vars->insert(stringify(*x), value);
+ }
+ }
+
+ return expand_vars;
+}
diff --git a/paludis/repositories/e/make_use.hh b/paludis/repositories/e/make_use.hh
new file mode 100644
index 0000000..acf40f0
--- /dev/null
+++ b/paludis/repositories/e/make_use.hh
@@ -0,0 +1,42 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2010 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_MAKE_USE_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_E_MAKE_USE_HH 1
+
+#include <paludis/repositories/e/e_repository_id.hh>
+#include <paludis/repositories/e/profile.hh>
+#include <paludis/environment-fwd.hh>
+
+namespace paludis
+{
+ namespace erepository
+ {
+ std::string make_use(const Environment * const,
+ const ERepositoryID & id,
+ std::shared_ptr<const Profile> profile);
+
+ std::shared_ptr<Map<std::string, std::string> >
+ make_expand(const Environment * const,
+ const ERepositoryID & e,
+ std::shared_ptr<const Profile> profile);
+ }
+}
+
+#endif