aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar David Leverton <levertond@googlemail.com> 2008-02-11 01:40:51 +0000
committerAvatar David Leverton <levertond@googlemail.com> 2008-02-11 01:40:51 +0000
commit7f5da5c6222c2311500886d61be1ed729078fdf4 (patch)
tree4a0b4ded406fedd0284680f47d6143cb633fa858
parent5f182fcbdc18a66abf61733d2149c5b34c96d9eb (diff)
downloadpaludis-7f5da5c6222c2311500886d61be1ed729078fdf4.tar.gz
paludis-7f5da5c6222c2311500886d61be1ed729078fdf4.tar.xz
Allow empty directory merge warning to be made an error, and do so for exheres-0.
-rw-r--r--paludis/files.m42
-rw-r--r--paludis/merger-fwd.hh58
-rw-r--r--paludis/merger.cc148
-rw-r--r--paludis/merger.hh20
-rw-r--r--paludis/merger.se18
-rw-r--r--paludis/merger.sr6
-rw-r--r--paludis/merger_TEST.cc66
-rwxr-xr-xpaludis/merger_TEST_setup.sh2
-rw-r--r--paludis/ndbam_merger.cc56
-rw-r--r--paludis/ndbam_merger.hh2
-rw-r--r--paludis/ndbam_merger.sr3
-rw-r--r--paludis/repositories/cran/cran_installed_repository.cc2
-rw-r--r--paludis/repositories/cran/cran_installed_repository.hh2
-rw-r--r--paludis/repositories/e/e_repository.cc4
-rw-r--r--paludis/repositories/e/e_repository.hh2
-rw-r--r--paludis/repositories/e/e_repository_entries.hh2
-rw-r--r--paludis/repositories/e/eapi.cc12
-rw-r--r--paludis/repositories/e/eapi.hh1
-rw-r--r--paludis/repositories/e/eapi.sr3
-rw-r--r--paludis/repositories/e/eapis/0.conf2
-rw-r--r--paludis/repositories/e/eapis/exheres-0.conf2
-rw-r--r--paludis/repositories/e/eapis/paludis-1.conf2
-rw-r--r--paludis/repositories/e/ebuild.hh1
-rw-r--r--paludis/repositories/e/ebuild.sr2
-rw-r--r--paludis/repositories/e/ebuild_entries.cc10
-rw-r--r--paludis/repositories/e/ebuild_entries.hh2
-rw-r--r--paludis/repositories/e/exndbam_repository.cc7
-rw-r--r--paludis/repositories/e/exndbam_repository.hh2
-rw-r--r--paludis/repositories/e/vdb_merger.cc56
-rw-r--r--paludis/repositories/e/vdb_merger.hh2
-rw-r--r--paludis/repositories/e/vdb_merger.sr7
-rw-r--r--paludis/repositories/e/vdb_merger_TEST.cc8
-rw-r--r--paludis/repositories/e/vdb_repository.cc6
-rw-r--r--paludis/repositories/e/vdb_repository.hh2
-rw-r--r--paludis/repositories/fake/fake_installed_repository.cc2
-rw-r--r--paludis/repositories/fake/fake_installed_repository.hh2
-rw-r--r--paludis/repositories/gems/installed_gems_repository.cc2
-rw-r--r--paludis/repositories/gems/installed_gems_repository.hh2
-rw-r--r--paludis/repositories/unpackaged/installed_repository.cc7
-rw-r--r--paludis/repositories/unpackaged/installed_repository.hh2
-rw-r--r--paludis/repositories/unpackaged/unpackaged_id.cc4
-rw-r--r--paludis/repository-fwd.hh2
-rw-r--r--paludis/repository.hh4
-rw-r--r--paludis/repository.sr4
44 files changed, 347 insertions, 204 deletions
diff --git a/paludis/files.m4 b/paludis/files.m4
index a64b81d..3785fcc 100644
--- a/paludis/files.m4
+++ b/paludis/files.m4
@@ -36,7 +36,7 @@ add(`install_task', `hh', `cc', `se')
add(`literal_metadata_key', `hh', `cc')
add(`mask', `hh', `cc', `fwd')
add(`match_package', `hh', `cc')
-add(`merger', `hh', `cc', `se', `sr', `test', `testscript')
+add(`merger', `hh', `cc', `fwd', `se', `sr', `test', `testscript')
add(`merger_entry_type', `hh', `cc', `se')
add(`metadata_key', `hh', `cc', `se', `fwd')
add(`name', `hh', `cc', `fwd', `test', `sr', `se')
diff --git a/paludis/merger-fwd.hh b/paludis/merger-fwd.hh
new file mode 100644
index 0000000..3b8a5ff
--- /dev/null
+++ b/paludis/merger-fwd.hh
@@ -0,0 +1,58 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 David Leverton
+ *
+ * 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_MERGER_FWD_HH
+#define PALUDIS_GUARD_PALUDIS_MERGER_FWD_HH 1
+
+#include <iosfwd>
+#include <paludis/util/attributes.hh>
+#include <paludis/util/options-fwd.hh>
+
+/** \file
+ * Forward declarations for paludis/merger.hh .
+ *
+ * \ingroup g_repository
+ */
+
+namespace paludis
+{
+#include <paludis/merger-se.hh>
+
+ /**
+ * Boolean options for Merger.
+ *
+ * \ingroup g_repository
+ * \since 0.26
+ */
+ typedef Options<MergerOption> MergerOptions;
+
+ /**
+ * Status flags for Merger.
+ *
+ * \ingroup g_repository
+ * \since 0.26
+ */
+ typedef Options<MergeStatusFlag> MergeStatusFlags;
+
+ class MergerParams;
+ class MergerError;
+ class Merger;
+}
+
+#endif
diff --git a/paludis/merger.cc b/paludis/merger.cc
index 9b239a9..ec628ca 100644
--- a/paludis/merger.cc
+++ b/paludis/merger.cc
@@ -37,14 +37,15 @@
using namespace paludis;
#include <paludis/merger-sr.cc>
+#include <paludis/merger-se.cc>
MergerError::MergerError(const std::string & s) throw () :
Exception(s)
{
}
-Merger::Merger(const MergerOptions & o) :
- _options(o),
+Merger::Merger(const MergerParams & p) :
+ _params(p),
_result(true),
_skip_dir(false)
{
@@ -57,21 +58,21 @@ Merger::~Merger()
bool
Merger::check()
{
- Context context("When checking merge from '" + stringify(_options.image) + "' to '"
- + stringify(_options.root) + "':");
+ Context context("When checking merge from '" + stringify(_params.image) + "' to '"
+ + stringify(_params.root) + "':");
- if (0 != _options.environment->perform_hook(extend_hook(
+ if (0 != _params.environment->perform_hook(extend_hook(
Hook("merger_check_pre")
- ("INSTALL_SOURCE", stringify(_options.image))
- ("INSTALL_DESTINATION", stringify(_options.root)))).max_exit_status)
+ ("INSTALL_SOURCE", stringify(_params.image))
+ ("INSTALL_DESTINATION", stringify(_params.root)))).max_exit_status)
make_check_fail();
- do_dir_recursive(true, _options.image, _options.root);
+ do_dir_recursive(true, _params.image, _params.root);
- if (0 != _options.environment->perform_hook(extend_hook(
+ if (0 != _params.environment->perform_hook(extend_hook(
Hook("merger_check_post")
- ("INSTALL_SOURCE", stringify(_options.image))
- ("INSTALL_DESTINATION", stringify(_options.root)))).max_exit_status)
+ ("INSTALL_SOURCE", stringify(_params.image))
+ ("INSTALL_DESTINATION", stringify(_params.root)))).max_exit_status)
make_check_fail();
return _result;
@@ -86,8 +87,8 @@ Merger::make_check_fail()
void
Merger::merge()
{
- Context context("When performing merge from '" + stringify(_options.image) + "' to '"
- + stringify(_options.root) + "':");
+ Context context("When performing merge from '" + stringify(_params.image) + "' to '"
+ + stringify(_params.root) + "':");
struct SaveUmask
{
@@ -104,21 +105,21 @@ Merger::merge()
}
} old_umask(::umask(0000));
- if (0 != _options.environment->perform_hook(extend_hook(
+ if (0 != _params.environment->perform_hook(extend_hook(
Hook("merger_install_pre")
- ("INSTALL_SOURCE", stringify(_options.image))
- ("INSTALL_DESTINATION", stringify(_options.root)))).max_exit_status)
+ ("INSTALL_SOURCE", stringify(_params.image))
+ ("INSTALL_DESTINATION", stringify(_params.root)))).max_exit_status)
Log::get_instance()->message(ll_warning, lc_context,
- "Merge of '" + stringify(_options.image) + "' to '" + stringify(_options.root) + "' pre hooks returned non-zero");
+ "Merge of '" + stringify(_params.image) + "' to '" + stringify(_params.root) + "' pre hooks returned non-zero");
- do_dir_recursive(false, _options.image, _options.root.realpath());
+ do_dir_recursive(false, _params.image, _params.root.realpath());
- if (0 != _options.environment->perform_hook(extend_hook(
+ if (0 != _params.environment->perform_hook(extend_hook(
Hook("merger_install_post")
- ("INSTALL_SOURCE", stringify(_options.image))
- ("INSTALL_DESTINATION", stringify(_options.root)))).max_exit_status)
+ ("INSTALL_SOURCE", stringify(_params.image))
+ ("INSTALL_DESTINATION", stringify(_params.root)))).max_exit_status)
Log::get_instance()->message(ll_warning, lc_context,
- "Merge of '" + stringify(_options.image) + "' to '" + stringify(_options.root) + "' post hooks returned non-zero");
+ "Merge of '" + stringify(_params.image) + "' to '" + stringify(_params.root) + "' post hooks returned non-zero");
}
EntryType
@@ -156,9 +157,14 @@ Merger::do_dir_recursive(bool is_check, const FSEntry & src, const FSEntry & dst
DirIterator d(src, DirIteratorOptions() + dio_include_dotfiles + dio_inode_sort), d_end;
- if (! is_check && d == d_end && dst != _options.root.realpath())
- Log::get_instance()->message(ll_warning, lc_context) << "Installing empty directory '"
- << stringify(dst) << "'";
+ if (is_check && d == d_end && dst != _params.root.realpath())
+ {
+ if (_params.options[mo_allow_empty_dirs])
+ Log::get_instance()->message(ll_warning, lc_context) << "Installing empty directory '"
+ << stringify(dst) << "'";
+ else
+ on_error(is_check, "Attempted to install empty directory '" + stringify(dst) + "'");
+ }
for ( ; d != d_end ; ++d)
{
@@ -208,7 +214,7 @@ Merger::on_file(bool is_check, const FSEntry & src, const FSEntry & dst)
EntryType m(entry_type(dst / src.basename()));
if (is_check &&
- 0 != _options.environment->perform_hook(extend_hook(
+ 0 != _params.environment->perform_hook(extend_hook(
Hook("merger_check_file_pre")
("INSTALL_SOURCE", stringify(src))
("INSTALL_DESTINATION", stringify(dst / src.basename())))).max_exit_status)
@@ -216,7 +222,7 @@ Merger::on_file(bool is_check, const FSEntry & src, const FSEntry & dst)
if (! is_check)
{
- HookResult hr(_options.environment->perform_hook(extend_hook(
+ HookResult hr(_params.environment->perform_hook(extend_hook(
Hook("merger_install_file_override")
("INSTALL_SOURCE", stringify(src))
("INSTALL_DESTINATION", stringify(dst / src.basename()))
@@ -227,7 +233,7 @@ Merger::on_file(bool is_check, const FSEntry & src, const FSEntry & dst)
<< stringify(src) << "' to '" << stringify(dst) << "' skip hooks returned non-zero";
else if (hr.output == "skip")
{
- std::string tidy(stringify((dst / src.basename()).strip_leading(_options.root.realpath())));
+ std::string tidy(stringify((dst / src.basename()).strip_leading(_params.root.realpath())));
display_override("--- [skp] " + tidy);
return;
}
@@ -265,7 +271,7 @@ Merger::on_file(bool is_check, const FSEntry & src, const FSEntry & dst)
} while (false);
if (is_check &&
- 0 != _options.environment->perform_hook(extend_hook(
+ 0 != _params.environment->perform_hook(extend_hook(
Hook("merger_check_file_post")
("INSTALL_SOURCE", stringify(src))
("INSTALL_DESTINATION", stringify(dst / src.basename())))).max_exit_status)
@@ -280,7 +286,7 @@ Merger::on_dir(bool is_check, const FSEntry & src, const FSEntry & dst)
EntryType m(entry_type(dst / src.basename()));
if (is_check &&
- 0 != _options.environment->perform_hook(extend_hook(
+ 0 != _params.environment->perform_hook(extend_hook(
Hook("merger_check_dir_pre")
("INSTALL_SOURCE", stringify(src))
("INSTALL_DESTINATION", stringify(dst / src.basename())))).max_exit_status)
@@ -288,7 +294,7 @@ Merger::on_dir(bool is_check, const FSEntry & src, const FSEntry & dst)
if (! is_check)
{
- HookResult hr(_options.environment->perform_hook(extend_hook(
+ HookResult hr(_params.environment->perform_hook(extend_hook(
Hook("merger_install_dir_override")
("INSTALL_SOURCE", stringify(src))
("INSTALL_DESTINATION", stringify(dst / src.basename()))
@@ -299,7 +305,7 @@ Merger::on_dir(bool is_check, const FSEntry & src, const FSEntry & dst)
<< stringify(src) << "' to '" << stringify(dst) << "' skip hooks returned non-zero";
else if (hr.output == "skip")
{
- std::string tidy(stringify((dst / src.basename()).strip_leading(_options.root.realpath())));
+ std::string tidy(stringify((dst / src.basename()).strip_leading(_params.root.realpath())));
display_override("--- [skp] " + tidy);
_skip_dir = true;
return;
@@ -339,7 +345,7 @@ Merger::on_dir(bool is_check, const FSEntry & src, const FSEntry & dst)
} while (false);
if (is_check &&
- 0 != _options.environment->perform_hook(extend_hook(
+ 0 != _params.environment->perform_hook(extend_hook(
Hook("merger_check_dir_post")
("INSTALL_SOURCE", stringify(src))
("INSTALL_DESTINATION", stringify(dst / src.basename())))).max_exit_status)
@@ -354,7 +360,7 @@ Merger::on_sym(bool is_check, const FSEntry & src, const FSEntry & dst)
EntryType m(entry_type(dst / src.basename()));
if (is_check &&
- 0 != _options.environment->perform_hook(extend_hook(
+ 0 != _params.environment->perform_hook(extend_hook(
Hook("merger_check_sym_post")
("INSTALL_SOURCE", stringify(src))
("INSTALL_DESTINATION", stringify(dst / src.basename())))).max_exit_status)
@@ -362,7 +368,7 @@ Merger::on_sym(bool is_check, const FSEntry & src, const FSEntry & dst)
if (! is_check)
{
- HookResult hr(_options.environment->perform_hook(extend_hook(
+ HookResult hr(_params.environment->perform_hook(extend_hook(
Hook("merger_install_sym_override")
("INSTALL_SOURCE", stringify(src))
("INSTALL_DESTINATION", stringify(dst / src.basename()))
@@ -373,15 +379,15 @@ Merger::on_sym(bool is_check, const FSEntry & src, const FSEntry & dst)
<< stringify(src) << "' to '" << stringify(dst) << "' skip hooks returned non-zero";
else if (hr.output == "skip")
{
- std::string tidy(stringify((dst / src.basename()).strip_leading(_options.root.realpath())));
+ std::string tidy(stringify((dst / src.basename()).strip_leading(_params.root.realpath())));
display_override("--- [skp] " + tidy);
return;
}
}
else
{
- if (symlink_needs_rewriting(src) && ! _options.rewrite_symlinks)
- throw MergerError("Symlink to image detected at: " + stringify(src) + " (" + src.readlink() + ")");
+ if (symlink_needs_rewriting(src) && ! _params.options[mo_rewrite_symlinks])
+ on_error(is_check, "Symlink to image detected at: " + stringify(src) + " (" + src.readlink() + ")");
}
do
@@ -416,7 +422,7 @@ Merger::on_sym(bool is_check, const FSEntry & src, const FSEntry & dst)
} while (false);
if (is_check &&
- 0 != _options.environment->perform_hook(extend_hook(
+ 0 != _params.environment->perform_hook(extend_hook(
Hook("merger_check_sym_post")
("INSTALL_SOURCE", stringify(src))
("INSTALL_DESTINATION", stringify(dst / src.basename())))).max_exit_status)
@@ -609,7 +615,7 @@ Merger::install_file(const FSEntry & src, const FSEntry & dst_dir, const std::st
+ stringify(dst_name) + "':");
MergeStatusFlags result;
- if (0 != _options.environment->perform_hook(extend_hook(
+ if (0 != _params.environment->perform_hook(extend_hook(
Hook("merger_install_file_pre")
("INSTALL_SOURCE", stringify(src))
("INSTALL_DESTINATION", stringify(dst_dir / src.basename())))).max_exit_status)
@@ -632,10 +638,10 @@ Merger::install_file(const FSEntry & src, const FSEntry & dst_dir, const std::st
uid_t dest_uid(src.owner());
gid_t dest_gid(src.group());
- if (! _options.no_chown)
+ if (! _params.no_chown)
{
- uid_t new_uid(dest_uid == _options.environment->reduced_uid() ? 0 : -1);
- gid_t new_gid(dest_gid == _options.environment->reduced_gid() ? 0 : -1);
+ uid_t new_uid(dest_uid == _params.environment->reduced_uid() ? 0 : -1);
+ gid_t new_gid(dest_gid == _params.environment->reduced_gid() ? 0 : -1);
if (uid_t(-1) != new_uid || gid_t(-1) != new_gid)
{
FSEntry(src).chown(new_uid, new_gid);
@@ -667,7 +673,7 @@ Merger::install_file(const FSEntry & src, const FSEntry & dst_dir, const std::st
if (-1 == output_fd)
throw MergerError("Cannot write '" + stringify(dst) + "': " + stringify(::strerror(errno)));
- if (! _options.no_chown)
+ if (! _params.no_chown)
if (0 != ::fchown(output_fd, dest_uid, dest_gid))
throw MergerError("Cannot fchown '" + stringify(dst) + "': " + stringify(::strerror(errno)));
@@ -688,7 +694,7 @@ Merger::install_file(const FSEntry & src, const FSEntry & dst_dir, const std::st
"rename(" + stringify(dst) + ", " + stringify(dst_real) + ") failed: " + stringify(::strerror(errno)));
}
- if (0 != _options.environment->perform_hook(extend_hook(
+ if (0 != _params.environment->perform_hook(extend_hook(
Hook("merger_install_file_post")
("INSTALL_SOURCE", stringify(src))
("INSTALL_DESTINATION", stringify(dst_dir / src.basename())))).max_exit_status)
@@ -702,7 +708,7 @@ bool
Merger::symlink_needs_rewriting(const FSEntry & sym)
{
std::string target(sym.readlink());
- std::string real_image(stringify(_options.image.realpath()));
+ std::string real_image(stringify(_params.image.realpath()));
return (0 == target.compare(0, real_image.length(), real_image));
}
@@ -715,7 +721,7 @@ Merger::rewrite_symlink_as_needed(const FSEntry & src, const FSEntry & dst_dir)
FSCreateCon createcon(MatchPathCon::get_instance()->match(stringify(dst_dir / src.basename()), S_IFLNK));
- FSEntry real_image(_options.image.realpath());
+ FSEntry real_image(_params.image.realpath());
FSEntry dst(src.readlink());
std::string fixed_dst(stringify(dst.strip_leading(real_image)));
@@ -732,10 +738,10 @@ Merger::record_renamed_dir_recursive(const FSEntry & dst)
{
for (DirIterator d(dst, DirIteratorOptions() + dio_include_dotfiles + dio_inode_sort), d_end ; d != d_end ; ++d)
{
- if (! _options.no_chown)
+ if (! _params.no_chown)
{
- uid_t new_uid(d->owner() == _options.environment->reduced_uid() ? 0 : -1);
- gid_t new_gid(d->group() == _options.environment->reduced_gid() ? 0 : -1);
+ uid_t new_uid(d->owner() == _params.environment->reduced_uid() ? 0 : -1);
+ gid_t new_gid(d->group() == _params.environment->reduced_gid() ? 0 : -1);
if (uid_t(-1) != new_uid || gid_t(-1) != new_gid)
{
FSEntry f(*d);
@@ -806,7 +812,7 @@ Merger::install_dir(const FSEntry & src, const FSEntry & dst_dir)
MergeStatusFlags result;
- if (0 != _options.environment->perform_hook(extend_hook(
+ if (0 != _params.environment->perform_hook(extend_hook(
Hook("merger_install_dir_pre")
("INSTALL_SOURCE", stringify(src))
("INSTALL_DESTINATION", stringify(dst_dir / src.basename())))).max_exit_status)
@@ -820,10 +826,10 @@ Merger::install_dir(const FSEntry & src, const FSEntry & dst_dir)
if (0 != (mode & (S_ISVTX | S_ISUID | S_ISGID)))
result += msi_setid_bits;
- if (! _options.no_chown)
+ if (! _params.no_chown)
{
- uid_t new_uid(dest_uid == _options.environment->reduced_uid() ? 0 : -1);
- gid_t new_gid(dest_gid == _options.environment->reduced_gid() ? 0 : -1);
+ uid_t new_uid(dest_uid == _params.environment->reduced_uid() ? 0 : -1);
+ gid_t new_gid(dest_gid == _params.environment->reduced_gid() ? 0 : -1);
if (uid_t(-1) != new_uid)
mode &= ~S_ISUID;
if (gid_t(-1) != new_gid)
@@ -859,13 +865,13 @@ Merger::install_dir(const FSEntry & src, const FSEntry & dst_dir)
{
Log::get_instance()->message(ll_debug, lc_context, "rename failed. Falling back to recursive copy.");
dst.mkdir(mode);
- if (! _options.no_chown)
+ if (! _params.no_chown)
dst.chown(dest_uid, dest_gid);
/* pick up set*id bits */
dst.chmod(mode);
}
- if (0 != _options.environment->perform_hook(extend_hook(
+ if (0 != _params.environment->perform_hook(extend_hook(
Hook("merger_install_dir_post")
("INSTALL_SOURCE", stringify(src))
("INSTALL_DESTINATION", stringify(dst_dir / src.basename())))).max_exit_status)
@@ -882,15 +888,15 @@ Merger::install_sym(const FSEntry & src, const FSEntry & dst_dir)
MergeStatusFlags result;
- if (0 != _options.environment->perform_hook(extend_hook(
+ if (0 != _params.environment->perform_hook(extend_hook(
Hook("merger_install_sym_pre")
("INSTALL_SOURCE", stringify(src))
("INSTALL_DESTINATION", stringify(dst_dir / src.basename())))).max_exit_status)
Log::get_instance()->message(ll_warning, lc_context,
"Merge of '" + stringify(src) + "' to '" + stringify(dst_dir) + "' pre hooks returned non-zero");
- uid_t dest_uid(src.owner() == _options.environment->reduced_uid() ? 0 : src.owner());
- gid_t dest_gid(src.group() == _options.environment->reduced_gid() ? 0 : src.group());
+ uid_t dest_uid(src.owner() == _params.environment->reduced_uid() ? 0 : src.owner());
+ gid_t dest_gid(src.group() == _params.environment->reduced_gid() ? 0 : src.group());
if (0 != (src.permissions() & (S_ISVTX | S_ISUID | S_ISGID)))
result += msi_setid_bits;
@@ -905,14 +911,14 @@ Merger::install_sym(const FSEntry & src, const FSEntry & dst_dir)
+ stringify(::strerror(errno)));
}
- if (! _options.no_chown)
+ if (! _params.no_chown)
{
if (src.owner() != dest_uid || src.group() != dest_gid)
result += msi_fixed_ownership;
FSEntry(dst_dir / src.basename()).lchown(dest_uid, dest_gid);
}
- if (0 != _options.environment->perform_hook(extend_hook(
+ if (0 != _params.environment->perform_hook(extend_hook(
Hook("merger_install_sym_post")
("INSTALL_SOURCE", stringify(src))
("INSTALL_DESTINATION", stringify(dst_dir / src.basename())))).max_exit_status)
@@ -925,7 +931,7 @@ Merger::install_sym(const FSEntry & src, const FSEntry & dst_dir)
void
Merger::unlink_file(FSEntry d)
{
- if (0 != _options.environment->perform_hook(extend_hook(
+ if (0 != _params.environment->perform_hook(extend_hook(
Hook("merger_unlink_file_pre")
("UNLINK_TARGET", stringify(d)))).max_exit_status)
Log::get_instance()->message(ll_warning, lc_context,
@@ -943,7 +949,7 @@ Merger::unlink_file(FSEntry d)
d.unlink();
- if (0 != _options.environment->perform_hook(extend_hook(
+ if (0 != _params.environment->perform_hook(extend_hook(
Hook("merger_unlink_file_post")
("UNLINK_TARGET", stringify(d)))).max_exit_status)
Log::get_instance()->message(ll_warning, lc_context,
@@ -953,7 +959,7 @@ Merger::unlink_file(FSEntry d)
void
Merger::unlink_sym(FSEntry d)
{
- if (0 != _options.environment->perform_hook(extend_hook(
+ if (0 != _params.environment->perform_hook(extend_hook(
Hook("merger_unlink_sym_pre")
("UNLINK_TARGET", stringify(d)))).max_exit_status)
Log::get_instance()->message(ll_warning, lc_context,
@@ -961,7 +967,7 @@ Merger::unlink_sym(FSEntry d)
d.unlink();
- if (0 != _options.environment->perform_hook(extend_hook(
+ if (0 != _params.environment->perform_hook(extend_hook(
Hook("merger_unlink_sym_post")
("UNLINK_TARGET", stringify(d)))).max_exit_status)
Log::get_instance()->message(ll_warning, lc_context,
@@ -971,7 +977,7 @@ Merger::unlink_sym(FSEntry d)
void
Merger::unlink_dir(FSEntry d)
{
- if (0 != _options.environment->perform_hook(extend_hook(
+ if (0 != _params.environment->perform_hook(extend_hook(
Hook("merger_unlink_dir_pre")
("UNLINK_TARGET", stringify(d)))).max_exit_status)
Log::get_instance()->message(ll_warning, lc_context,
@@ -979,7 +985,7 @@ Merger::unlink_dir(FSEntry d)
d.rmdir();
- if (0 != _options.environment->perform_hook(extend_hook(
+ if (0 != _params.environment->perform_hook(extend_hook(
Hook("merger_unlink_dir_post")
("UNLINK_TARGET", stringify(d)))).max_exit_status)
Log::get_instance()->message(ll_warning, lc_context,
@@ -989,7 +995,7 @@ Merger::unlink_dir(FSEntry d)
void
Merger::unlink_misc(FSEntry d)
{
- if (0 != _options.environment->perform_hook(extend_hook(
+ if (0 != _params.environment->perform_hook(extend_hook(
Hook("merger_unlink_misc_pre")
("UNLINK_TARGET", stringify(d)))).max_exit_status)
Log::get_instance()->message(ll_warning, lc_context,
@@ -997,7 +1003,7 @@ Merger::unlink_misc(FSEntry d)
d.unlink();
- if (0 != _options.environment->perform_hook(extend_hook(
+ if (0 != _params.environment->perform_hook(extend_hook(
Hook("merger_unlink_misc_post")
("UNLINK_TARGET", stringify(d)))).max_exit_status)
Log::get_instance()->message(ll_warning, lc_context,
@@ -1008,7 +1014,7 @@ Hook
Merger::extend_hook(const Hook & h)
{
return h
- ("ROOT", stringify(_options.root))
- ("IMAGE", stringify(_options.image));
+ ("ROOT", stringify(_params.root))
+ ("IMAGE", stringify(_params.image));
}
diff --git a/paludis/merger.hh b/paludis/merger.hh
index 2f05913..1f10903 100644
--- a/paludis/merger.hh
+++ b/paludis/merger.hh
@@ -17,13 +17,14 @@
* Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef PALUDIS_GUARD_PALUDIS_MERGER_MERGER_HH
-#define PALUDIS_GUARD_PALUDIS_MERGER_MERGER_HH 1
+#ifndef PALUDIS_GUARD_PALUDIS_MERGER_HH
+#define PALUDIS_GUARD_PALUDIS_MERGER_HH 1
+#include "merger-fwd.hh"
#include <paludis/util/sr.hh>
#include <paludis/util/fs_entry.hh>
#include <paludis/util/exception.hh>
-#include <paludis/util/options-fwd.hh>
+#include <paludis/util/options.hh>
#include <paludis/merger_entry_type.hh>
#include <iosfwd>
@@ -43,18 +44,9 @@ namespace paludis
class Environment;
class Hook;
-#include <paludis/merger-se.hh>
#include <paludis/merger-sr.hh>
/**
- * Status flags for Merger.
- *
- * \ingroup g_repository
- * \since 0.26
- */
- typedef Options<MergeStatusFlag> MergeStatusFlags;
-
- /**
* Thrown if an error occurs during a Merger operation.
*
* \ingroup g_repository
@@ -83,7 +75,7 @@ namespace paludis
class PALUDIS_VISIBLE Merger
{
private:
- MergerOptions _options;
+ MergerParams _params;
bool _result;
bool _skip_dir;
void record_renamed_dir_recursive(const FSEntry &);
@@ -95,7 +87,7 @@ namespace paludis
///\name Basic operations
///\{
- Merger(const MergerOptions &);
+ Merger(const MergerParams &);
///\}
diff --git a/paludis/merger.se b/paludis/merger.se
index 0ed5dc2..8bfd247 100644
--- a/paludis/merger.se
+++ b/paludis/merger.se
@@ -22,3 +22,21 @@ make_enum_MergeStatusFlag()
END
}
+make_enum_MergerOption()
+{
+ prefix mo
+ want_destringify
+
+ key mo_rewrite_symlinks "Fix symlinks that point into the image directory (otherwise throw an error)"
+ key mo_allow_empty_dirs "Allow merging empty directories"
+
+ doxygen_comment << "END"
+ /**
+ * Boolean options for Merger, used by MergerOptions
+ *
+ * \ingroup g_repository
+ * \since 0.26
+ */
+END
+}
+
diff --git a/paludis/merger.sr b/paludis/merger.sr
index ca9cbd1..9af3522 100644
--- a/paludis/merger.sr
+++ b/paludis/merger.sr
@@ -1,7 +1,7 @@
#!/bin/bash
# vim: set sw=4 sts=4 et :
-make_class_MergerOptions()
+make_class_MergerParams()
{
visible
@@ -9,13 +9,13 @@ make_class_MergerOptions()
key image "FSEntry"
key root "FSEntry"
key no_chown bool
- key rewrite_symlinks bool
+ key options "MergerOptions"
allow_named_args
doxygen_comment << "END"
/**
- * Options for a basic Merger.
+ * Parameters for a basic Merger.
*
* \see Merger
* \ingroup g_repository
diff --git a/paludis/merger_TEST.cc b/paludis/merger_TEST.cc
index 1162286..d1af105 100644
--- a/paludis/merger_TEST.cc
+++ b/paludis/merger_TEST.cc
@@ -21,6 +21,7 @@
#include <paludis/environments/test/test_environment.hh>
#include <paludis/hooker.hh>
#include <paludis/util/wrapped_forward_iterator.hh>
+#include <paludis/util/dir_iterator.hh>
#include <paludis/hook.hh>
#include <test/test_framework.hh>
#include <test/test_runner.hh>
@@ -80,8 +81,8 @@ namespace
struct TestMerger :
Merger
{
- TestMerger(const MergerOptions & opts) :
- Merger(opts)
+ TestMerger(const MergerParams & p) :
+ Merger(p)
{
}
@@ -147,29 +148,28 @@ namespace
root_dir("merger_TEST_dir/" + stringify(src_type) + "_over_" + stringify(dst_type)
+ (0 == n ? "" : "_" + stringify(n)) + "_dir/root"),
env(FSEntry("merger_TEST_dir/hooks")),
- merger(MergerOptions::create()
+ merger(MergerParams::create()
.image(image_dir)
.root(root_dir)
.environment(&env)
.no_chown(true)
- .rewrite_symlinks(true))
+ .options(MergerOptions() + mo_rewrite_symlinks + mo_allow_empty_dirs))
{
}
- MergerTest(const std::string & custom_test) :
+ MergerTest(const std::string & custom_test, const MergerOptions & o = MergerOptions() + mo_rewrite_symlinks + mo_allow_empty_dirs) :
TestCase("merge " + custom_test + " test"),
image_dir("merger_TEST_dir/" + custom_test + "/image"),
root_dir("merger_TEST_dir/" + custom_test + "/root"),
env(FSEntry("merger_TEST_dir/hooks")),
- merger(MergerOptions::create()
+ merger(MergerParams::create()
.image(image_dir)
.root(root_dir)
.environment(&env)
.no_chown(true)
- .rewrite_symlinks(true))
+ .options(o))
{
}
-
};
}
@@ -458,5 +458,55 @@ namespace test_cases
TEST_CHECK((root_dir / "sym_install_me").is_symbolic_link());
}
} test_merger_override;
+
+ struct MergerEmptyDirAllowedTest : MergerTest
+ {
+ MergerEmptyDirAllowedTest() : MergerTest("empty_dir_allowed", MergerOptions() + mo_allow_empty_dirs) { }
+
+ void run()
+ {
+ TEST_CHECK((image_dir / "empty").is_directory());
+ TEST_CHECK(DirIterator(image_dir / "empty", DirIteratorOptions() + dio_include_dotfiles + dio_first_only) == DirIterator());
+
+ TEST_CHECK(merger.check());
+ }
+ } test_merger_empty_dir_allowed;
+
+ struct MergerEmptyDirDisallowedTest : MergerTest
+ {
+ MergerEmptyDirDisallowedTest() : MergerTest("empty_dir_disallowed", MergerOptions()) { }
+
+ void run()
+ {
+ TEST_CHECK((image_dir / "empty").is_directory());
+ TEST_CHECK(DirIterator(image_dir / "empty", DirIteratorOptions() + dio_include_dotfiles + dio_first_only) == DirIterator());
+
+ TEST_CHECK(! merger.check());
+ }
+ } test_merger_empty_dir_disallowed;
+
+ struct MergerEmptyRootAllowedTest : MergerTest
+ {
+ MergerEmptyRootAllowedTest() : MergerTest("empty_root_allowed", MergerOptions() + mo_allow_empty_dirs) { }
+
+ void run()
+ {
+ TEST_CHECK(DirIterator(image_dir, DirIteratorOptions() + dio_include_dotfiles + dio_first_only) == DirIterator());
+
+ TEST_CHECK(merger.check());
+ }
+ } test_merger_empty_root_allowed;
+
+ struct MergerEmptyRootDisallowedTest : MergerTest
+ {
+ MergerEmptyRootDisallowedTest() : MergerTest("empty_root_disallowed", MergerOptions()) { }
+
+ void run()
+ {
+ TEST_CHECK(DirIterator(image_dir, DirIteratorOptions() + dio_include_dotfiles + dio_first_only) == DirIterator());
+
+ TEST_CHECK(! merger.check());
+ }
+ } test_merger_empty_root_disallowed;
}
diff --git a/paludis/merger_TEST_setup.sh b/paludis/merger_TEST_setup.sh
index 954aa5c..22b89cc 100755
--- a/paludis/merger_TEST_setup.sh
+++ b/paludis/merger_TEST_setup.sh
@@ -84,6 +84,8 @@ mkdir override_dir/image/dir_install_me/
ln -s override_dir/image/file_skip_me override_dir/image/sym_skip_me
ln -s override_dir/image/file_install_me override_dir/image/sym_install_me
+mkdir -p empty_{dir,root}_{allowed,disallowed}_dir/{image,root}
+mkdir -p empty_dir_{allowed,disallowed}_dir/image/empty
for d in *_dir; do
ln -s ${d} ${d%_dir}
diff --git a/paludis/ndbam_merger.cc b/paludis/ndbam_merger.cc
index ec3c402..de6c36e 100644
--- a/paludis/ndbam_merger.cc
+++ b/paludis/ndbam_merger.cc
@@ -47,31 +47,31 @@ namespace paludis
template<>
struct Implementation<NDBAMMerger>
{
- NDBAMMergerOptions options;
+ NDBAMMergerParams params;
FSEntry realroot;
tr1::shared_ptr<std::ofstream> contents_file;
std::list<std::string> config_protect;
std::list<std::string> config_protect_mask;
- Implementation(const NDBAMMergerOptions & o) :
- options(o),
- realroot(options.root.realpath())
+ Implementation(const NDBAMMergerParams & p) :
+ params(p),
+ realroot(params.root.realpath())
{
- tokenise_whitespace(o.config_protect, std::back_inserter(config_protect));
- tokenise_whitespace(o.config_protect_mask, std::back_inserter(config_protect_mask));
+ tokenise_whitespace(p.config_protect, std::back_inserter(config_protect));
+ tokenise_whitespace(p.config_protect_mask, std::back_inserter(config_protect_mask));
}
};
}
-NDBAMMerger::NDBAMMerger(const NDBAMMergerOptions & o) :
- Merger(MergerOptions::create()
- .environment(o.environment)
- .image(o.image)
- .root(o.root)
+NDBAMMerger::NDBAMMerger(const NDBAMMergerParams & p) :
+ Merger(MergerParams::create()
+ .environment(p.environment)
+ .image(p.image)
+ .root(p.root)
.no_chown(! getenv_with_default("PALUDIS_NO_CHOWN", "").empty())
- .rewrite_symlinks(true)),
- PrivateImplementationPattern<NDBAMMerger>(new Implementation<NDBAMMerger>(o))
+ .options(p.options)),
+ PrivateImplementationPattern<NDBAMMerger>(new Implementation<NDBAMMerger>(p))
{
}
@@ -82,33 +82,33 @@ NDBAMMerger::~NDBAMMerger()
Hook
NDBAMMerger::extend_hook(const Hook & h)
{
- tr1::shared_ptr<const FSEntrySequence> bashrc_files(_imp->options.environment->bashrc_files());
+ tr1::shared_ptr<const FSEntrySequence> bashrc_files(_imp->params.environment->bashrc_files());
- if (_imp->options.package_id)
+ if (_imp->params.package_id)
{
- std::string cat(stringify(_imp->options.package_id->name().category));
- std::string pn(stringify(_imp->options.package_id->name().package));
- std::string pvr(stringify(_imp->options.package_id->version()));
- std::string pv(stringify(_imp->options.package_id->version().remove_revision()));
- std::string slot(stringify(_imp->options.package_id->slot()));
+ std::string cat(stringify(_imp->params.package_id->name().category));
+ std::string pn(stringify(_imp->params.package_id->name().package));
+ std::string pvr(stringify(_imp->params.package_id->version()));
+ std::string pv(stringify(_imp->params.package_id->version().remove_revision()));
+ std::string slot(stringify(_imp->params.package_id->slot()));
return Merger::extend_hook(h)
("P", pn + "-" + pv)
("PN", pn)
("CATEGORY", cat)
- ("PR", _imp->options.package_id->version().revision_only())
+ ("PR", _imp->params.package_id->version().revision_only())
("PV", pv)
("PVR", pvr)
("PF", pn + "-" + pvr)
("SLOT", slot)
- ("CONFIG_PROTECT", _imp->options.config_protect)
- ("CONFIG_PROTECT_MASK", _imp->options.config_protect_mask)
+ ("CONFIG_PROTECT", _imp->params.config_protect)
+ ("CONFIG_PROTECT_MASK", _imp->params.config_protect_mask)
("PALUDIS_BASHRC_FILES", join(bashrc_files->begin(), bashrc_files->end(), " "));
}
else
return Merger::extend_hook(h)
- ("CONFIG_PROTECT", _imp->options.config_protect)
- ("CONFIG_PROTECT_MASK", _imp->options.config_protect_mask)
+ ("CONFIG_PROTECT", _imp->params.config_protect)
+ ("CONFIG_PROTECT_MASK", _imp->params.config_protect_mask)
("PALUDIS_BASHRC_FILES", join(bashrc_files->begin(), bashrc_files->end(), " "));
}
@@ -312,15 +312,15 @@ NDBAMMerger::make_arrows(const MergeStatusFlags & flags) const
void
NDBAMMerger::merge()
{
- display_override(">>> Merging to " + stringify(_imp->options.root));
- _imp->contents_file.reset(new std::ofstream(stringify(_imp->options.contents_file).c_str()));
+ display_override(">>> Merging to " + stringify(_imp->params.root));
+ _imp->contents_file.reset(new std::ofstream(stringify(_imp->params.contents_file).c_str()));
Merger::merge();
}
bool
NDBAMMerger::check()
{
- std::cout << ">>> Checking whether we can merge to " << _imp->options.root << " ";
+ std::cout << ">>> Checking whether we can merge to " << _imp->params.root << " ";
bool result(Merger::check());
std::cout << std::endl;
return result;
diff --git a/paludis/ndbam_merger.hh b/paludis/ndbam_merger.hh
index 66a552e..2ef824e 100644
--- a/paludis/ndbam_merger.hh
+++ b/paludis/ndbam_merger.hh
@@ -36,7 +36,7 @@ namespace paludis
std::string make_arrows(const MergeStatusFlags &) const;
public:
- NDBAMMerger(const NDBAMMergerOptions &);
+ NDBAMMerger(const NDBAMMergerParams &);
~NDBAMMerger();
virtual Hook extend_hook(const Hook &);
diff --git a/paludis/ndbam_merger.sr b/paludis/ndbam_merger.sr
index 529fa21..7e62760 100644
--- a/paludis/ndbam_merger.sr
+++ b/paludis/ndbam_merger.sr
@@ -1,7 +1,7 @@
#!/bin/bash
# vim: set sw=4 sts=4 et :
-make_class_NDBAMMergerOptions()
+make_class_NDBAMMergerParams()
{
visible
@@ -12,6 +12,7 @@ make_class_NDBAMMergerOptions()
key config_protect std::string
key config_protect_mask std::string
key package_id "tr1::shared_ptr<const PackageID>"
+ key options "MergerOptions"
allow_named_args
}
diff --git a/paludis/repositories/cran/cran_installed_repository.cc b/paludis/repositories/cran/cran_installed_repository.cc
index 8c96361..67818f6 100644
--- a/paludis/repositories/cran/cran_installed_repository.cc
+++ b/paludis/repositories/cran/cran_installed_repository.cc
@@ -595,7 +595,7 @@ CRANInstalledRepository::want_pre_post_phases() const
}
void
-CRANInstalledRepository::merge(const MergeOptions & m)
+CRANInstalledRepository::merge(const MergeParams & m)
{
Context context("When merging '" + stringify(*m.package_id) + "' at '" + stringify(m.image_dir)
+ "' to repository '" + stringify(name()) + "':");
diff --git a/paludis/repositories/cran/cran_installed_repository.hh b/paludis/repositories/cran/cran_installed_repository.hh
index 7c95959..1945b61 100644
--- a/paludis/repositories/cran/cran_installed_repository.hh
+++ b/paludis/repositories/cran/cran_installed_repository.hh
@@ -106,7 +106,7 @@ namespace paludis
virtual bool want_pre_post_phases() const
PALUDIS_ATTRIBUTE((warn_unused_result));
- virtual void merge(const MergeOptions &);
+ virtual void merge(const MergeParams &);
/* Repository */
diff --git a/paludis/repositories/e/e_repository.cc b/paludis/repositories/e/e_repository.cc
index aaa68e4..e311268 100644
--- a/paludis/repositories/e/e_repository.cc
+++ b/paludis/repositories/e/e_repository.cc
@@ -1119,9 +1119,9 @@ ERepository::want_pre_post_phases() const
}
void
-ERepository::merge(const MergeOptions & o)
+ERepository::merge(const MergeParams & p)
{
- _imp->entries_ptr->merge(o);
+ _imp->entries_ptr->merge(p);
}
HookResult
diff --git a/paludis/repositories/e/e_repository.hh b/paludis/repositories/e/e_repository.hh
index fbf5482..3a1be96 100644
--- a/paludis/repositories/e/e_repository.hh
+++ b/paludis/repositories/e/e_repository.hh
@@ -113,7 +113,7 @@ namespace paludis
virtual bool want_pre_post_phases() const
PALUDIS_ATTRIBUTE((warn_unused_result));
- virtual void merge(const MergeOptions &);
+ virtual void merge(const MergeParams &);
virtual void check_qa(
QAReporter &,
diff --git a/paludis/repositories/e/e_repository_entries.hh b/paludis/repositories/e/e_repository_entries.hh
index 1b3d7d6..d006b27 100644
--- a/paludis/repositories/e/e_repository_entries.hh
+++ b/paludis/repositories/e/e_repository_entries.hh
@@ -108,7 +108,7 @@ namespace paludis
/**
* Handle a merge.
*/
- virtual void merge(const MergeOptions &) = 0;
+ virtual void merge(const MergeParams &) = 0;
/**
* Gives the Manifest key for a given package file (for
diff --git a/paludis/repositories/e/eapi.cc b/paludis/repositories/e/eapi.cc
index 3880155..84653f2 100644
--- a/paludis/repositories/e/eapi.cc
+++ b/paludis/repositories/e/eapi.cc
@@ -100,6 +100,16 @@ namespace paludis
iuse_flag_parse_options += destringify<IUseFlagParseOption>(*t);
}
+ MergerOptions merger_options;
+ {
+ std::list<std::string> merger_options_tokens;
+ tokenise_whitespace(k.get("merger_options"), std::back_inserter(merger_options_tokens));
+ for (std::list<std::string>::const_iterator t(merger_options_tokens.begin()),
+ t_end(merger_options_tokens.end()) ;
+ t != t_end ; ++t)
+ merger_options += destringify<MergerOption>(*t);
+ }
+
tr1::shared_ptr<EAPI> eapi(new EAPI(
strip_trailing_string(d->basename(), ".conf"),
k.get("exported_name"),
@@ -108,6 +118,7 @@ namespace paludis
.package_dep_spec_parse_options(package_dep_spec_parse_options)
.dependency_spec_tree_parse_options(dependency_spec_tree_parse_options)
.iuse_flag_parse_options(iuse_flag_parse_options)
+ .merger_options(merger_options)
.breaks_portage(destringify<bool>(k.get("breaks_portage")))
.can_be_pbin(destringify<bool>(k.get("can_be_pbin")))
@@ -137,7 +148,6 @@ namespace paludis
.restrict_fetch(make_shared_ptr(new Set<std::string>))
.restrict_mirror(make_shared_ptr(new Set<std::string>))
.restrict_primaryuri(make_shared_ptr(new Set<std::string>))
- .merge_rewrite_symlinks(destringify<bool>(k.get("merge_rewrite_symlinks")))
.f_function_prefix(k.get("f_function_prefix"))
.ignore_pivot_env_variables(k.get("ignore_pivot_env_variables"))
.ignore_pivot_env_functions(k.get("ignore_pivot_env_functions"))
diff --git a/paludis/repositories/e/eapi.hh b/paludis/repositories/e/eapi.hh
index d07a2bb..71a425a 100644
--- a/paludis/repositories/e/eapi.hh
+++ b/paludis/repositories/e/eapi.hh
@@ -30,6 +30,7 @@
#include <paludis/util/options.hh>
#include <paludis/name.hh>
#include <paludis/dep_spec-fwd.hh>
+#include <paludis/merger-fwd.hh>
namespace paludis
{
diff --git a/paludis/repositories/e/eapi.sr b/paludis/repositories/e/eapi.sr
index 4ffa16c..5ad9ce6 100644
--- a/paludis/repositories/e/eapi.sr
+++ b/paludis/repositories/e/eapi.sr
@@ -181,8 +181,6 @@ make_class_EAPIEbuildOptions()
key ignore_pivot_env_variables std::string
key ignore_pivot_env_functions std::string
- key merge_rewrite_symlinks bool
-
key restrict_fetch "tr1::shared_ptr<Set<std::string> >"
key restrict_mirror "tr1::shared_ptr<Set<std::string> >"
key restrict_primaryuri "tr1::shared_ptr<Set<std::string> >"
@@ -216,6 +214,7 @@ make_class_SupportedEAPI()
key package_dep_spec_parse_options "erepository::PackageDepSpecParseOptions"
key dependency_spec_tree_parse_options "erepository::DependencySpecTreeParseOptions"
key iuse_flag_parse_options IUseFlagParseOptions
+ key merger_options "MergerOptions"
key breaks_portage bool
key can_be_pbin bool
diff --git a/paludis/repositories/e/eapis/0.conf b/paludis/repositories/e/eapis/0.conf
index 6cfe7c3..68e6cd0 100644
--- a/paludis/repositories/e/eapis/0.conf
+++ b/paludis/repositories/e/eapis/0.conf
@@ -7,6 +7,7 @@ can_be_pbin = true
package_dep_spec_parse_options =
dependency_spec_tree_parse_options =
iuse_flag_parse_options =
+merger_options = rewrite_symlinks allow_empty_dirs
breaks_portage = false
rdepend_defaults_to_depend = true
use_expand_separator = _
@@ -16,7 +17,6 @@ support_eclasses = true
support_exlibs = false
utility_path_suffixes =
ebuild_module_suffixes = 0
-merge_rewrite_symlinks = true
f_function_prefix = ebuild_f
vdb_from_env_variables = \
diff --git a/paludis/repositories/e/eapis/exheres-0.conf b/paludis/repositories/e/eapis/exheres-0.conf
index 1b305f9..6daee31 100644
--- a/paludis/repositories/e/eapis/exheres-0.conf
+++ b/paludis/repositories/e/eapis/exheres-0.conf
@@ -9,6 +9,7 @@ package_dep_spec_parse_options = allow_slot_deps allow_square_bracket_deps \
allow_tilde_greater_deps strict_star_operator strict_parsing
dependency_spec_tree_parse_options = disallow_any_use uri_supports_arrow
iuse_flag_parse_options = strict_parsing
+merger_options =
breaks_portage = true
want_portage_emulation_vars = false
require_use_expand_in_iuse = true
@@ -18,7 +19,6 @@ support_exlibs = true
utility_path_suffixes = exheres-0
ebuild_module_suffixes = exheres-0
use_expand_separator = :
-merge_rewrite_symlinks = false
f_function_prefix = exheres_internal
vdb_from_env_variables = \
diff --git a/paludis/repositories/e/eapis/paludis-1.conf b/paludis/repositories/e/eapis/paludis-1.conf
index 34f73c6..6da1c74 100644
--- a/paludis/repositories/e/eapis/paludis-1.conf
+++ b/paludis/repositories/e/eapis/paludis-1.conf
@@ -9,6 +9,7 @@ package_dep_spec_parse_options = allow_slot_deps allow_square_bracket_deps \
allow_repository_deps allow_tilde_greater_deps strict_parsing
dependency_spec_tree_parse_options = disallow_any_use uri_supports_arrow
iuse_flag_parse_options = allow_iuse_defaults
+merger_options = rewrite_symlinks allow_empty_dirs
breaks_portage = true
rdepend_defaults_to_depend = false
want_portage_emulation_vars = false
@@ -18,7 +19,6 @@ support_exlibs = false
utility_path_suffixes =
ebuild_module_suffixes = paludis-1 1 0
use_expand_separator = _
-merge_rewrite_symlinks = true
f_function_prefix = ebuild_f
vdb_from_env_variables = \
diff --git a/paludis/repositories/e/ebuild.hh b/paludis/repositories/e/ebuild.hh
index 57ac3a5..44d070e 100644
--- a/paludis/repositories/e/ebuild.hh
+++ b/paludis/repositories/e/ebuild.hh
@@ -26,6 +26,7 @@
#include <paludis/util/map-fwd.hh>
#include <paludis/package_database.hh>
#include <paludis/action-fwd.hh>
+#include <paludis/merger-fwd.hh>
#include <string>
/** \file
diff --git a/paludis/repositories/e/ebuild.sr b/paludis/repositories/e/ebuild.sr
index 930f8bd..6f7b216 100644
--- a/paludis/repositories/e/ebuild.sr
+++ b/paludis/repositories/e/ebuild.sr
@@ -194,7 +194,7 @@ make_class_WriteBinaryEbuildCommandParams()
key binary_distdir "FSEntry"
key environment_file "FSEntry"
key image "FSEntry"
- key rewrite_symlinks "bool"
+ key merger_options "MergerOptions"
key builddir FSEntry
doxygen_comment << "END"
diff --git a/paludis/repositories/e/ebuild_entries.cc b/paludis/repositories/e/ebuild_entries.cc
index 8364fb5..7eccd92 100644
--- a/paludis/repositories/e/ebuild_entries.cc
+++ b/paludis/repositories/e/ebuild_entries.cc
@@ -541,13 +541,13 @@ EbuildEntries::install(const tr1::shared_ptr<const ERepositoryID> & id,
+ "' because destination does not provide destination_interface");
o[k::destination()]->destination_interface->merge(
- MergeOptions::create()
+ MergeParams::create()
.package_id(id)
.image_dir(_imp->params.builddir / stringify(id->name().category) / (stringify(id->name().package) + "-"
+ stringify(id->version())) / "image")
.environment_file(_imp->params.builddir / stringify(id->name().category) / (stringify(id->name().package) + "-"
+ stringify(id->version())) / "temp" / "loadsaveenv")
- .rewrite_symlinks(id->eapi()->supported->ebuild_options->merge_rewrite_symlinks)
+ .options(id->eapi()->supported->merger_options)
);
}
else if ((! phase->option("prepost")) ||
@@ -726,7 +726,7 @@ EbuildEntries::make_ebuild_entries(
}
void
-EbuildEntries::merge(const MergeOptions & m)
+EbuildEntries::merge(const MergeParams & m)
{
Context context("When merging '" + stringify(*m.package_id) + "' at '" + stringify(m.image_dir)
+ "' to E repository '" + stringify(_imp->e_repository->name()) + "':");
@@ -751,8 +751,8 @@ EbuildEntries::merge(const MergeOptions & m)
.image(m.image_dir)
.destination_repository(_imp->e_repository)
.builddir(_imp->params.builddir)
- .rewrite_symlinks(tr1::static_pointer_cast<const ERepositoryID>(m.package_id)
- ->eapi()->supported->ebuild_options->merge_rewrite_symlinks));
+ .merger_options(tr1::static_pointer_cast<const ERepositoryID>(m.package_id)
+ ->eapi()->supported->merger_options));
write_binary_ebuild_command();
}
diff --git a/paludis/repositories/e/ebuild_entries.hh b/paludis/repositories/e/ebuild_entries.hh
index ba6e3bc..34f56db 100644
--- a/paludis/repositories/e/ebuild_entries.hh
+++ b/paludis/repositories/e/ebuild_entries.hh
@@ -64,7 +64,7 @@ namespace paludis
///\}
- virtual void merge(const MergeOptions &);
+ virtual void merge(const MergeParams &);
virtual bool is_package_file(const QualifiedPackageName &, const FSEntry &) const
PALUDIS_ATTRIBUTE((warn_unused_result));
diff --git a/paludis/repositories/e/exndbam_repository.cc b/paludis/repositories/e/exndbam_repository.cc
index 480641a..075a118 100644
--- a/paludis/repositories/e/exndbam_repository.cc
+++ b/paludis/repositories/e/exndbam_repository.cc
@@ -264,7 +264,7 @@ ExndbamRepository::need_keys_added() const
}
void
-ExndbamRepository::merge(const MergeOptions & m)
+ExndbamRepository::merge(const MergeParams & m)
{
Context context("When merging '" + stringify(*m.package_id) + "' at '" + stringify(m.image_dir)
+ "' to Exndbam repository '" + stringify(name()) + "':");
@@ -327,14 +327,15 @@ ExndbamRepository::merge(const MergeOptions & m)
}
NDBAMMerger merger(
- NDBAMMergerOptions::create()
+ NDBAMMergerParams::create()
.environment(_imp->params.environment)
.image(m.image_dir)
.root(installed_root_key()->value())
.contents_file(target_ver_dir / "contents")
.config_protect(config_protect)
.config_protect_mask(config_protect_mask)
- .package_id(m.package_id));
+ .package_id(m.package_id)
+ .options(m.options));
if (! merger.check())
{
diff --git a/paludis/repositories/e/exndbam_repository.hh b/paludis/repositories/e/exndbam_repository.hh
index 4978b5b..208cd46 100644
--- a/paludis/repositories/e/exndbam_repository.hh
+++ b/paludis/repositories/e/exndbam_repository.hh
@@ -74,7 +74,7 @@ namespace paludis
/* RepositoryDestinationInterface */
- virtual void merge(const MergeOptions &);
+ virtual void merge(const MergeParams &);
/* Repository */
diff --git a/paludis/repositories/e/vdb_merger.cc b/paludis/repositories/e/vdb_merger.cc
index b6882ae..3913cd7 100644
--- a/paludis/repositories/e/vdb_merger.cc
+++ b/paludis/repositories/e/vdb_merger.cc
@@ -47,31 +47,31 @@ namespace paludis
template<>
struct Implementation<VDBMerger>
{
- VDBMergerOptions options;
+ VDBMergerParams params;
FSEntry realroot;
tr1::shared_ptr<std::ofstream> contents_file;
std::list<std::string> config_protect;
std::list<std::string> config_protect_mask;
- Implementation(const VDBMergerOptions & o) :
- options(o),
- realroot(options.root.realpath())
+ Implementation(const VDBMergerParams & p) :
+ params(p),
+ realroot(params.root.realpath())
{
- tokenise_whitespace(o.config_protect, std::back_inserter(config_protect));
- tokenise_whitespace(o.config_protect_mask, std::back_inserter(config_protect_mask));
+ tokenise_whitespace(p.config_protect, std::back_inserter(config_protect));
+ tokenise_whitespace(p.config_protect_mask, std::back_inserter(config_protect_mask));
}
};
}
-VDBMerger::VDBMerger(const VDBMergerOptions & o) :
- Merger(MergerOptions::create()
- .environment(o.environment)
- .image(o.image)
- .root(o.root)
+VDBMerger::VDBMerger(const VDBMergerParams & p) :
+ Merger(MergerParams::create()
+ .environment(p.environment)
+ .image(p.image)
+ .root(p.root)
.no_chown(! getenv_with_default("PALUDIS_NO_CHOWN", "").empty())
- .rewrite_symlinks(o.rewrite_symlinks)),
- PrivateImplementationPattern<VDBMerger>(new Implementation<VDBMerger>(o))
+ .options(p.options)),
+ PrivateImplementationPattern<VDBMerger>(new Implementation<VDBMerger>(p))
{
}
@@ -82,33 +82,33 @@ VDBMerger::~VDBMerger()
Hook
VDBMerger::extend_hook(const Hook & h)
{
- tr1::shared_ptr<const FSEntrySequence> bashrc_files(_imp->options.environment->bashrc_files());
+ tr1::shared_ptr<const FSEntrySequence> bashrc_files(_imp->params.environment->bashrc_files());
- if (_imp->options.package_id)
+ if (_imp->params.package_id)
{
- std::string cat(stringify(_imp->options.package_id->name().category));
- std::string pn(stringify(_imp->options.package_id->name().package));
- std::string pvr(stringify(_imp->options.package_id->version()));
- std::string pv(stringify(_imp->options.package_id->version().remove_revision()));
- std::string slot(stringify(_imp->options.package_id->slot()));
+ std::string cat(stringify(_imp->params.package_id->name().category));
+ std::string pn(stringify(_imp->params.package_id->name().package));
+ std::string pvr(stringify(_imp->params.package_id->version()));
+ std::string pv(stringify(_imp->params.package_id->version().remove_revision()));
+ std::string slot(stringify(_imp->params.package_id->slot()));
return Merger::extend_hook(h)
("P", pn + "-" + pv)
("PN", pn)
("CATEGORY", cat)
- ("PR", _imp->options.package_id->version().revision_only())
+ ("PR", _imp->params.package_id->version().revision_only())
("PV", pv)
("PVR", pvr)
("PF", pn + "-" + pvr)
("SLOT", slot)
- ("CONFIG_PROTECT", _imp->options.config_protect)
- ("CONFIG_PROTECT_MASK", _imp->options.config_protect_mask)
+ ("CONFIG_PROTECT", _imp->params.config_protect)
+ ("CONFIG_PROTECT_MASK", _imp->params.config_protect_mask)
("PALUDIS_BASHRC_FILES", join(bashrc_files->begin(), bashrc_files->end(), " "));
}
else
return Merger::extend_hook(h)
- ("CONFIG_PROTECT", _imp->options.config_protect)
- ("CONFIG_PROTECT_MASK", _imp->options.config_protect_mask)
+ ("CONFIG_PROTECT", _imp->params.config_protect)
+ ("CONFIG_PROTECT_MASK", _imp->params.config_protect_mask)
("PALUDIS_BASHRC_FILES", join(bashrc_files->begin(), bashrc_files->end(), " "));
}
@@ -235,15 +235,15 @@ VDBMerger::make_config_protect_name(const FSEntry & src, const FSEntry & dst)
void
VDBMerger::merge()
{
- display_override(">>> Merging to " + stringify(_imp->options.root));
- _imp->contents_file.reset(new std::ofstream(stringify(_imp->options.contents_file).c_str()));
+ display_override(">>> Merging to " + stringify(_imp->params.root));
+ _imp->contents_file.reset(new std::ofstream(stringify(_imp->params.contents_file).c_str()));
Merger::merge();
}
bool
VDBMerger::check()
{
- std::cout << ">>> Checking whether we can merge to " << _imp->options.root << " ";
+ std::cout << ">>> Checking whether we can merge to " << _imp->params.root << " ";
bool result(Merger::check());
std::cout << std::endl;
return result;
diff --git a/paludis/repositories/e/vdb_merger.hh b/paludis/repositories/e/vdb_merger.hh
index e8bf53b..999bdd2 100644
--- a/paludis/repositories/e/vdb_merger.hh
+++ b/paludis/repositories/e/vdb_merger.hh
@@ -48,7 +48,7 @@ namespace paludis
///\name Basic operations
///\{
- VDBMerger(const VDBMergerOptions &);
+ VDBMerger(const VDBMergerParams &);
~VDBMerger();
///\}
diff --git a/paludis/repositories/e/vdb_merger.sr b/paludis/repositories/e/vdb_merger.sr
index a3fc410..2e6cc11 100644
--- a/paludis/repositories/e/vdb_merger.sr
+++ b/paludis/repositories/e/vdb_merger.sr
@@ -1,7 +1,7 @@
#!/bin/bash
# vim: set sw=4 sts=4 et :
-make_class_VDBMergerOptions()
+make_class_VDBMergerParams()
{
visible
@@ -12,18 +12,19 @@ make_class_VDBMergerOptions()
key config_protect std::string
key config_protect_mask std::string
key package_id "tr1::shared_ptr<const PackageID>"
- key rewrite_symlinks bool
+ key options "MergerOptions"
allow_named_args
doxygen_comment << "END"
/**
- * Options for a VDBMerger.
+ * Parameters for a VDBMerger.
*
* \see VDBMerger
* \ingroup grpmerger
* \ingroup grpvdbrepository
* \nosubgrouping
+ * \since 0.26
*/
END
}
diff --git a/paludis/repositories/e/vdb_merger_TEST.cc b/paludis/repositories/e/vdb_merger_TEST.cc
index 5c7eb78..5e4d36e 100644
--- a/paludis/repositories/e/vdb_merger_TEST.cc
+++ b/paludis/repositories/e/vdb_merger_TEST.cc
@@ -39,8 +39,8 @@ namespace
}
public:
- VDBMergerNoDisplay(const VDBMergerOptions & o) :
- VDBMerger(o)
+ VDBMergerNoDisplay(const VDBMergerParams & p) :
+ VDBMerger(p)
{
}
@@ -75,7 +75,7 @@ namespace
TestCase("merge '" + what + "' test"),
root_dir(FSEntry::cwd() / "vdb_merger_TEST_dir" / what / "root"),
target(what),
- merger(VDBMergerOptions::create()
+ merger(VDBMergerParams::create()
.environment(&env)
.image(FSEntry::cwd() / "vdb_merger_TEST_dir" / what / "image")
.root(root_dir)
@@ -83,7 +83,7 @@ namespace
.config_protect("/protected_file /protected_dir")
.config_protect_mask("/protected_dir/unprotected_file /protected_dir/unprotected_dir")
.package_id(tr1::shared_ptr<PackageID>())
- .rewrite_symlinks(true))
+ .options(MergerOptions() + mo_rewrite_symlinks + mo_allow_empty_dirs))
{
}
};
diff --git a/paludis/repositories/e/vdb_repository.cc b/paludis/repositories/e/vdb_repository.cc
index df716f7..8d6aaa6 100644
--- a/paludis/repositories/e/vdb_repository.cc
+++ b/paludis/repositories/e/vdb_repository.cc
@@ -692,7 +692,7 @@ VDBRepository::category_names_containing_package(const PackageNamePart & p) cons
}
void
-VDBRepository::merge(const MergeOptions & m)
+VDBRepository::merge(const MergeParams & m)
{
Context context("When merging '" + stringify(*m.package_id) + "' at '" + stringify(m.image_dir)
+ "' to VDB repository '" + stringify(name()) + "':");
@@ -735,7 +735,7 @@ VDBRepository::merge(const MergeOptions & m)
vdb_dir /= (stringify(m.package_id->name().package) + "-" + stringify(m.package_id->version()));
VDBMerger merger(
- VDBMergerOptions::create()
+ VDBMergerParams::create()
.environment(_imp->params.environment)
.image(m.image_dir)
.root(installed_root_key()->value())
@@ -743,7 +743,7 @@ VDBRepository::merge(const MergeOptions & m)
.config_protect(config_protect)
.config_protect_mask(config_protect_mask)
.package_id(m.package_id)
- .rewrite_symlinks(m.rewrite_symlinks));
+ .options(m.options));
if (! merger.check())
{
diff --git a/paludis/repositories/e/vdb_repository.hh b/paludis/repositories/e/vdb_repository.hh
index 1c514aa..d7aaae0 100644
--- a/paludis/repositories/e/vdb_repository.hh
+++ b/paludis/repositories/e/vdb_repository.hh
@@ -112,7 +112,7 @@ namespace paludis
/* RepositoryDestinationInterface */
- virtual void merge(const MergeOptions &);
+ virtual void merge(const MergeParams &);
/* Repository */
diff --git a/paludis/repositories/fake/fake_installed_repository.cc b/paludis/repositories/fake/fake_installed_repository.cc
index 1d1f86c..262f4d7 100644
--- a/paludis/repositories/fake/fake_installed_repository.cc
+++ b/paludis/repositories/fake/fake_installed_repository.cc
@@ -133,7 +133,7 @@ FakeInstalledRepository::want_pre_post_phases() const
}
void
-FakeInstalledRepository::merge(const MergeOptions &)
+FakeInstalledRepository::merge(const MergeParams &)
{
}
diff --git a/paludis/repositories/fake/fake_installed_repository.hh b/paludis/repositories/fake/fake_installed_repository.hh
index 0450824..6a99f9a 100644
--- a/paludis/repositories/fake/fake_installed_repository.hh
+++ b/paludis/repositories/fake/fake_installed_repository.hh
@@ -50,7 +50,7 @@ namespace paludis
virtual bool want_pre_post_phases() const
PALUDIS_ATTRIBUTE((warn_unused_result));
- virtual void merge(const MergeOptions &);
+ virtual void merge(const MergeParams &);
/* RepositoryProvidesInterface */
diff --git a/paludis/repositories/gems/installed_gems_repository.cc b/paludis/repositories/gems/installed_gems_repository.cc
index 0feed97..cf0803e 100644
--- a/paludis/repositories/gems/installed_gems_repository.cc
+++ b/paludis/repositories/gems/installed_gems_repository.cc
@@ -276,7 +276,7 @@ InstalledGemsRepository::want_pre_post_phases() const
}
void
-InstalledGemsRepository::merge(const MergeOptions &)
+InstalledGemsRepository::merge(const MergeParams &)
{
throw InternalError(PALUDIS_HERE, "Invalid target for merge");
}
diff --git a/paludis/repositories/gems/installed_gems_repository.hh b/paludis/repositories/gems/installed_gems_repository.hh
index 3b25b9e..f180304 100644
--- a/paludis/repositories/gems/installed_gems_repository.hh
+++ b/paludis/repositories/gems/installed_gems_repository.hh
@@ -75,7 +75,7 @@ namespace paludis
virtual bool want_pre_post_phases() const
PALUDIS_ATTRIBUTE((warn_unused_result));
- virtual void merge(const MergeOptions &) PALUDIS_ATTRIBUTE((noreturn));
+ virtual void merge(const MergeParams &) PALUDIS_ATTRIBUTE((noreturn));
public:
/* Repository */
diff --git a/paludis/repositories/unpackaged/installed_repository.cc b/paludis/repositories/unpackaged/installed_repository.cc
index 6d3b233..259785d 100644
--- a/paludis/repositories/unpackaged/installed_repository.cc
+++ b/paludis/repositories/unpackaged/installed_repository.cc
@@ -219,7 +219,7 @@ InstalledUnpackagedRepository::some_ids_might_support_action(const SupportsActio
}
void
-InstalledUnpackagedRepository::merge(const MergeOptions & m)
+InstalledUnpackagedRepository::merge(const MergeParams & m)
{
Context context("When merging '" + stringify(*m.package_id) + "' at '" + stringify(m.image_dir)
+ "' to InstalledUnpackagedRepository repository '" + stringify(name()) + "':");
@@ -296,14 +296,15 @@ InstalledUnpackagedRepository::merge(const MergeOptions & m)
}
NDBAMMerger merger(
- NDBAMMergerOptions::create()
+ NDBAMMergerParams::create()
.environment(_imp->params.environment)
.image(m.image_dir)
.root(installed_root_key()->value())
.contents_file(target_ver_dir / "contents")
.config_protect(getenv_with_default("CONFIG_PROTECT", ""))
.config_protect_mask(getenv_with_default("CONFIG_PROTECT_MASK", ""))
- .package_id(m.package_id));
+ .package_id(m.package_id)
+ .options(MergerOptions() + mo_rewrite_symlinks + mo_allow_empty_dirs));
if (! merger.check())
{
diff --git a/paludis/repositories/unpackaged/installed_repository.hh b/paludis/repositories/unpackaged/installed_repository.hh
index 0b9bff6..c316015 100644
--- a/paludis/repositories/unpackaged/installed_repository.hh
+++ b/paludis/repositories/unpackaged/installed_repository.hh
@@ -63,7 +63,7 @@ namespace paludis
virtual bool want_pre_post_phases() const
PALUDIS_ATTRIBUTE((warn_unused_result));
- virtual void merge(const MergeOptions &);
+ virtual void merge(const MergeParams &);
void deindex(const QualifiedPackageName &) const;
diff --git a/paludis/repositories/unpackaged/unpackaged_id.cc b/paludis/repositories/unpackaged/unpackaged_id.cc
index 767c881..41ed6ef 100644
--- a/paludis/repositories/unpackaged/unpackaged_id.cc
+++ b/paludis/repositories/unpackaged/unpackaged_id.cc
@@ -306,11 +306,11 @@ UnpackagedID::perform_action(Action & action) const
+ "' because destination does not provide destination_interface");
install_action->options[k::destination()]->destination_interface->merge(
- MergeOptions::create()
+ MergeParams::create()
.package_id(shared_from_this())
.image_dir(fs_location_key()->value())
.environment_file(FSEntry("/dev/null"))
- .rewrite_symlinks(true)
+ .options(MergerOptions() + mo_rewrite_symlinks + mo_allow_empty_dirs)
);
}
diff --git a/paludis/repository-fwd.hh b/paludis/repository-fwd.hh
index e4b0a28..ca968a2 100644
--- a/paludis/repository-fwd.hh
+++ b/paludis/repository-fwd.hh
@@ -56,7 +56,7 @@ namespace paludis
class RepositoryQAInterface;
class RepositoryManifestInterface;
- class MergeOptions;
+ class MergeParams;
/**
* A set of destinations, used to decide whether a PackageID can be
diff --git a/paludis/repository.hh b/paludis/repository.hh
index ae794f9..a78239b 100644
--- a/paludis/repository.hh
+++ b/paludis/repository.hh
@@ -33,8 +33,10 @@
#include <paludis/util/fs_entry.hh>
#include <paludis/util/virtual_constructor.hh>
#include <paludis/util/wrapped_forward_iterator-fwd.hh>
+#include <paludis/util/options.hh>
#include <paludis/version_spec.hh>
#include <paludis/metadata_key-fwd.hh>
+#include <paludis/merger-fwd.hh>
#include <string>
/** \file
@@ -616,7 +618,7 @@ namespace paludis
/**
* Merge a package.
*/
- virtual void merge(const MergeOptions &) = 0;
+ virtual void merge(const MergeParams &) = 0;
///\}
diff --git a/paludis/repository.sr b/paludis/repository.sr
index 5514e0b..b6383a1 100644
--- a/paludis/repository.sr
+++ b/paludis/repository.sr
@@ -97,14 +97,14 @@ make_class_RepositoryVirtualsEntry()
END
}
-make_class_MergeOptions()
+make_class_MergeParams()
{
visible
key package_id "tr1::shared_ptr<const PackageID>"
key image_dir FSEntry
key environment_file FSEntry
- key rewrite_symlinks bool
+ key options MergerOptions
allow_named_args