allow partitioning image

This adds a new function `expart' which allows partitioning the image into
separate parts.  This information is then provided to the merge to record.

Signed-off-by: Saleem Abdulrasool <compnerd@compnerd.org>
This commit is contained in:
Saleem Abdulrasool 2013-02-22 19:58:18 -08:00
parent b62787ab8a
commit 0e6261448e
38 changed files with 553 additions and 25 deletions

@ -18,6 +18,7 @@
*/
#include <paludis/contents.hh>
#include <paludis/util/make_null_shared_ptr.hh>
#include <paludis/util/pimp-impl.hh>
#include <paludis/util/wrapped_forward_iterator-impl.hh>
#include <paludis/literal_metadata_key.hh>
@ -62,9 +63,38 @@ ContentsEntry::location_key() const
return _imp->location_key;
}
ContentsFileEntry::ContentsFileEntry(const FSPath & our_name) :
ContentsEntry(our_name)
namespace paludis
{
template <>
struct Imp<ContentsFileEntry>
{
const std::shared_ptr<const MetadataValueKey<std::string> > part_key;
Imp(const std::string & part) :
part_key(part.empty()
? make_null_shared_ptr()
: std::make_shared<LiteralMetadataValueKey<std::string>>("part", "part", mkt_normal, part))
{
}
};
}
ContentsFileEntry::ContentsFileEntry(const FSPath & our_name,
const std::string & our_part) :
ContentsEntry(our_name), _imp(our_part)
{
if (_imp->part_key)
add_metadata_key(_imp->part_key);
}
ContentsFileEntry::~ContentsFileEntry()
{
}
const std::shared_ptr<const MetadataValueKey<std::string> >
ContentsFileEntry::part_key() const
{
return _imp->part_key;
}
ContentsDirEntry::ContentsDirEntry(const FSPath & our_name) :
@ -83,19 +113,26 @@ namespace paludis
struct Imp<ContentsSymEntry>
{
const std::shared_ptr<const MetadataValueKey<std::string> > target_key;
const std::shared_ptr<const MetadataValueKey<std::string> > part_key;
Imp(const std::string & t) :
target_key(std::make_shared<LiteralMetadataValueKey<std::string>>("target", "target", mkt_normal, t))
Imp(const std::string & target, const std::string & part) :
target_key(std::make_shared<LiteralMetadataValueKey<std::string>>("target", "target", mkt_normal, target)),
part_key(part.empty()
? make_null_shared_ptr()
: std::make_shared<LiteralMetadataValueKey<std::string>>("part", "part", mkt_normal, part))
{
}
};
}
ContentsSymEntry::ContentsSymEntry(const FSPath & our_name, const std::string & our_target) :
ContentsEntry(our_name),
_imp(our_target)
ContentsSymEntry::ContentsSymEntry(const FSPath & our_name,
const std::string & our_target,
const std::string & our_part) :
ContentsEntry(our_name), _imp(our_target, our_part)
{
add_metadata_key(_imp->target_key);
if (_imp->part_key)
add_metadata_key(_imp->part_key);
}
ContentsSymEntry::~ContentsSymEntry()
@ -108,6 +145,12 @@ ContentsSymEntry::target_key() const
return _imp->target_key;
}
const std::shared_ptr<const MetadataValueKey<std::string> >
ContentsSymEntry::part_key() const
{
return _imp->part_key;
}
namespace paludis
{
template<>
@ -155,6 +198,7 @@ namespace paludis
template class Pimp<Contents>;
template class Pimp<ContentsEntry>;
template class Pimp<ContentsSymEntry>;
template class Pimp<ContentsFileEntry>;
template class WrappedForwardIterator<Contents::ConstIteratorTag, const std::shared_ptr<const ContentsEntry> >;
}

@ -107,11 +107,23 @@ namespace paludis
public ContentsEntry,
public ImplementAcceptMethods<ContentsEntry, ContentsFileEntry>
{
private:
Pimp<ContentsFileEntry> _imp;
public:
///\name Basic operations
///\{
ContentsFileEntry(const FSPath &);
ContentsFileEntry(const FSPath &, const std::string &);
~ContentsFileEntry();
///\}
///\name Specific metadata keys
///\{
const std::shared_ptr<const MetadataValueKey<std::string> >
part_key() const;
///\}
};
@ -172,7 +184,8 @@ namespace paludis
///\name Basic operations
///\{
ContentsSymEntry(const FSPath &, const std::string & target);
ContentsSymEntry(const FSPath &, const std::string &,
const std::string &);
~ContentsSymEntry();
///\}
@ -187,6 +200,9 @@ namespace paludis
*/
const std::shared_ptr<const MetadataValueKey<std::string> > target_key() const;
const std::shared_ptr<const MetadataValueKey<std::string> >
part_key() const;
///\}
};
@ -234,6 +250,7 @@ namespace paludis
extern template class Pimp<Contents>;
extern template class Pimp<ContentsEntry>;
extern template class Pimp<ContentsSymEntry>;
extern template class Pimp<ContentsFileEntry>;
extern template class PALUDIS_VISIBLE WrappedForwardIterator<Contents::ConstIteratorTag, const std::shared_ptr<const ContentsEntry> >;
}

@ -82,6 +82,7 @@ add(`package_id', `hh', `cc', `fwd', `se')
add(`paludis', `hh')
add(`paludislike_options_conf', `hh', `cc', `fwd')
add(`partially_made_package_dep_spec', `hh', `cc', `fwd', `se')
add(`partitioning', `hh', `cc', `fwd', `gtest')
add(`permitted_choice_value_parameter_values', `hh', `cc', `fwd')
add(`pretty_print_options', `hh', `cc', `fwd', `se')
add(`pretty_printer', `hh', `cc', `fwd')

@ -29,6 +29,7 @@
#include <paludis/merger.hh>
#include <paludis/environment-fwd.hh>
#include <paludis/hook-fwd.hh>
#include <paludis/partitioning-fwd.hh>
#include <iosfwd>
#include <sys/stat.h>
#include <sys/types.h>
@ -58,6 +59,7 @@ namespace paludis
typedef Name<struct name_merged_entries> merged_entries;
typedef Name<struct name_no_chown> no_chown;
typedef Name<struct name_options> options;
typedef Name<struct name_parts> parts;
typedef Name<struct name_permit_destination> permit_destination;
typedef Name<struct name_root> root;
}
@ -106,6 +108,8 @@ namespace paludis
NamedValue<n::no_chown, bool> no_chown;
NamedValue<n::options, MergerOptions> options;
NamedValue<n::parts, std::shared_ptr<const Partitioning> > parts;
///\since 0.66
NamedValue<n::permit_destination, PermitDestinationFn> permit_destination;

@ -175,6 +175,7 @@ namespace
n::merged_entries() = std::make_shared<FSPathSet>(),
n::no_chown() = true,
n::options() = MergerOptions() + mo_rewrite_symlinks + mo_allow_empty_dirs,
n::parts() = make_null_shared_ptr(),
n::permit_destination() = std::bind(return_literal_function(true)),
n::root() = root_dir.realpath()
))
@ -198,6 +199,7 @@ namespace
n::merged_entries() = std::make_shared<FSPathSet>(),
n::no_chown() = true,
n::options() = o,
n::parts() = make_null_shared_ptr(),
n::permit_destination() = std::bind(return_literal_function(true)),
n::root() = root_dir.realpath()
))

@ -131,6 +131,17 @@ namespace paludis
typedef WrappedValue<SetNameTag> SetName;
typedef Set<SetName> SetNameSet;
class PartNameTag;
class PartNameError;
template <> struct WrappedValueTraits<PartNameTag>;
/**
* A PartName holds a std::string that is a valid name for a part.
*
* \ingroup g_names
*/
typedef WrappedValue<PartNameTag> PartName;
}
#endif

@ -41,6 +41,7 @@ namespace paludis
template class WrappedValue<SlotNameTag>;
template class WrappedValue<KeywordNameTag>;
template class WrappedValue<SetNameTag>;
template class WrappedValue<PartNameTag>;
template class PALUDIS_VISIBLE Sequence<RepositoryName>;
template class PALUDIS_VISIBLE WrappedForwardIterator<Sequence<RepositoryName>::ConstIteratorTag, const RepositoryName>;
@ -79,6 +80,7 @@ template PALUDIS_VISIBLE std::ostream & paludis::operator<< (std::ostream &, con
template PALUDIS_VISIBLE std::ostream & paludis::operator<< (std::ostream &, const WrappedValue<SlotNameTag> &);
template PALUDIS_VISIBLE std::ostream & paludis::operator<< (std::ostream &, const WrappedValue<KeywordNameTag> &);
template PALUDIS_VISIBLE std::ostream & paludis::operator<< (std::ostream &, const WrappedValue<SetNameTag> &);
template PALUDIS_VISIBLE std::ostream & paludis::operator<< (std::ostream &, const WrappedValue<PartNameTag> &);
std::ostream &
paludis::operator<< (std::ostream & s, const QualifiedPackageName & q)
@ -337,6 +339,22 @@ SetNameError::SetNameError(const std::string & name) throw () :
{
}
PartNameError::PartNameError(const std::string & name) throw () :
NameError(name, "part")
{
}
bool
WrappedValueTraits<PartNameTag>::validate(const std::string & name)
{
static const std::string allowed_chars(
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789-+_");
return name.find_first_not_of(allowed_chars) == std::string::npos;
}
std::size_t
QualifiedPackageName::hash() const
{

@ -244,10 +244,37 @@ namespace paludis
static bool validate(const std::string &) PALUDIS_ATTRIBUTE((warn_unused_result));
};
/**
* A PartNameError is thrown if an invalid value is assigned to a PartName.
*
* \ingroup g_exceptions
* \ingroup g_names
*/
class PALUDIS_VISIBLE PartNameError : public NameError
{
public:
/**
* Constructor
*/
PartNameError(const std::string & name) throw ();
};
template <>
struct PALUDIS_VISIBLE WrappedValueTraits<PartNameTag>
{
typedef std::string UnderlyingType;
typedef void ValidationParamsType;
typedef PartNameError ExceptionType;
static bool validate(const std::string &)
PALUDIS_ATTRIBUTE((warn_unused_result));
};
extern template class PALUDIS_VISIBLE WrappedValue<RepositoryNameTag>;
extern template class PALUDIS_VISIBLE WrappedValue<SlotNameTag>;
extern template class PALUDIS_VISIBLE WrappedValue<KeywordNameTag>;
extern template class PALUDIS_VISIBLE WrappedValue<SetNameTag>;
extern template class PALUDIS_VISIBLE WrappedValue<PartNameTag>;
extern template class PALUDIS_VISIBLE Set<QualifiedPackageName>;
extern template class PALUDIS_VISIBLE WrappedForwardIterator<Set<QualifiedPackageName>::ConstIteratorTag, const QualifiedPackageName>;

@ -544,6 +544,10 @@ NDBAM::parse_contents(const PackageID & id,
}
std::string md5(tokens.find("md5")->second);
std::string part;
if (tokens.count("part"))
part = tokens.find("part")->second;
if (! tokens.count("mtime"))
{
Log::get_instance()->message("ndbam.contents.no_key.mtime", ll_warning, lc_context) <<
@ -552,7 +556,7 @@ NDBAM::parse_contents(const PackageID & id,
}
time_t mtime(destringify<time_t>(tokens.find("mtime")->second));
std::shared_ptr<ContentsFileEntry> entry(std::make_shared<ContentsFileEntry>(FSPath(path)));
std::shared_ptr<ContentsFileEntry> entry(std::make_shared<ContentsFileEntry>(FSPath(path), part));
entry->add_metadata_key(std::make_shared<LiteralMetadataValueKey<std::string>>("md5", "md5", mkt_normal, md5));
entry->add_metadata_key(std::make_shared<LiteralMetadataTimeKey>("mtime", "mtime", mkt_normal, Timestamp(mtime, 0)));
on_file(entry);
@ -580,7 +584,11 @@ NDBAM::parse_contents(const PackageID & id,
}
time_t mtime(destringify<time_t>(tokens.find("mtime")->second));
std::shared_ptr<ContentsSymEntry> entry(std::make_shared<ContentsSymEntry>(FSPath(path), target));
std::string part;
if (tokens.count("part"))
part = tokens.find("part")->second;
std::shared_ptr<ContentsSymEntry> entry(std::make_shared<ContentsSymEntry>(FSPath(path), target, part));
entry->add_metadata_key(std::make_shared<LiteralMetadataTimeKey>("mtime", "mtime", mkt_normal, Timestamp(mtime, 0)));
on_sym(entry);
}

@ -43,6 +43,7 @@
#include <paludis/ndbam_merger.hh>
#include <paludis/metadata_key.hh>
#include <paludis/version_spec.hh>
#include <paludis/partitioning.hh>
#include <paludis/slot.hh>
#include <iomanip>
@ -84,6 +85,7 @@ NDBAMMerger::NDBAMMerger(const NDBAMMergerParams & p) :
n::merged_entries() = p.merged_entries(),
n::no_chown() = ! getenv_with_default(env_vars::no_chown, "").empty(),
n::options() = p.options(),
n::parts() = p.parts(),
n::permit_destination() = p.permit_destination(),
n::root() = p.root()
)),
@ -177,10 +179,16 @@ NDBAMMerger::record_install_file(const FSPath & src, const FSPath & dst_dir, con
line.append(" (" + FSPath(tidy).basename() + ")");
display_override(line);
std::string part;
if (_imp->params.parts())
part = _imp->params.parts()->classify(FSPath(tidy)).value();
*_imp->contents_file << "type=file";
*_imp->contents_file << " path=" << escape(tidy_real);
*_imp->contents_file << " md5=" << md5.hexsum();
*_imp->contents_file << " mtime=" << timestamp;
if (!part.empty())
*_imp->contents_file << " part=" << part;
*_imp->contents_file << std::endl;
}

@ -24,6 +24,7 @@
#include <paludis/package_id-fwd.hh>
#include <paludis/util/named_value.hh>
#include <paludis/output_manager-fwd.hh>
#include <paludis/partitioning-fwd.hh>
#include <functional>
namespace paludis
@ -43,6 +44,7 @@ namespace paludis
typedef Name<struct name_options> options;
typedef Name<struct name_output_manager> output_manager;
typedef Name<struct name_package_id> package_id;
typedef Name<struct name_parts> parts;
typedef Name<struct name_permit_destination> permit_destination;
typedef Name<struct name_root> root;
}
@ -62,6 +64,7 @@ namespace paludis
NamedValue<n::options, MergerOptions> options;
NamedValue<n::output_manager, std::shared_ptr<OutputManager> > output_manager;
NamedValue<n::package_id, std::shared_ptr<const PackageID> > package_id;
NamedValue<n::parts, std::shared_ptr<const Partitioning> > parts;
NamedValue<n::permit_destination, PermitDestinationFn> permit_destination;
NamedValue<n::root, FSPath> root;
};

@ -0,0 +1,28 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
* Copyright (c) 2013 Saleem Abdulrasool <compnerd@compnerd.org>
*
* 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_PARTITIONING_FWD_HH
#define PALUDIS_GUARD_PALUDIS_PARTITIONING_FWD_HH 1
namespace paludis
{
class Partitioning;
}
#endif

64
paludis/partitioning.cc Normal file

@ -0,0 +1,64 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
* Copyright (c) 2013 Saleem Abdulrasool <compnerd@compnerd.org>
*
* 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/name.hh>
#include <paludis/partitioning.hh>
#include <paludis/util/pimp-impl.hh>
#include <map>
#include <utility>
#include <algorithm>
using namespace paludis;
namespace paludis
{
template <>
struct Imp<Partitioning>
{
std::vector<std::pair<FSPath, PartName>> parts;
};
}
Partitioning::Partitioning() :
_imp()
{
}
Partitioning::~Partitioning() = default;
void
Partitioning::mark(const std::vector<FSPath> & paths, const PartName & name)
{
for (auto path = paths.begin(), path_end = paths.end();
path != path_end; ++path)
_imp->parts.push_back(std::make_pair(*path, name));
}
PartName
Partitioning::classify(const FSPath & path) const
{
for (auto part = _imp->parts.rbegin(), end = _imp->parts.rend();
part != end; ++part)
if (path.starts_with(part->first))
return part->second;
return PartName("");
}

83
paludis/partitioning.hh Normal file

@ -0,0 +1,83 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
* Copyright (c) 2013 Saleem Abdulrasool <compnerd@compnerd.org>
*
* 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_PARTITIONING_HH
#define PALUDIS_GUARD_PALUDIS_PARTITIONING_HH 1
#include <paludis/name-fwd.hh>
#include <paludis/partitioning-fwd.hh>
#include <paludis/util/exception.hh>
#include <paludis/util/fs_path.hh>
#include <paludis/util/pimp.hh>
#include <string>
#include <vector>
/** \file
* Declarations for the Partitioning class.
*
* \ingroup g_contents
*/
namespace paludis
{
/**
* Package partitioning as defined by the package installation metadata.
*
* \ingroup g_contents
* \since 1.1.0
*/
class PALUDIS_VISIBLE Partitioning
{
private:
Pimp<Partitioning> _imp;
public:
///\name Basic operations
///\{
Partitioning();
~Partitioning();
///\}
/**
* Mark a set of paths as belonging to a partition.
*
* \arg [in] paths the paths to partition
* \arg [in] name the partition name (or empty to indicate core)
*
* \since 1.1.0
*/
void mark(const std::vector<FSPath> &, const PartName &);
/**
* Classify a path into a partition.
*
* \arg [in] path the path to classify
*
* \return the partition the path was classified into, empty if none
*
* \since 1.1.0
*/
PartName classify(const FSPath &) const;
};
}
#endif

@ -0,0 +1,77 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
* Copyright (c) 2013 Saleem Abdulrasool <compnerd@compnerd.org>
*
* 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/name.hh>
#include <paludis/partitioning.hh>
#include <paludis/util/fs_path.hh>
#include <gtest/gtest.h>
#include <memory>
using namespace paludis;
namespace
{
const FSPath kBin("/bin");
const FSPath kLib("/lib");
const FSPath kTest("test");
const PartName kBinaries("binaries");
const PartName kCore("");
}
TEST(Partitioning, DefaultParts)
{
auto parts(std::make_shared<Partitioning>());
parts->mark(std::vector<FSPath>{ kBin }, kBinaries);
ASSERT_EQ(kBinaries, parts->classify(kBin));
ASSERT_EQ(kCore, parts->classify(kLib));
}
TEST(Partitioning, PartsExludes)
{
auto parts(std::make_shared<Partitioning>());
parts->mark(std::vector<FSPath>{ kBin }, kBinaries);
parts->mark(std::vector<FSPath>{ kBin / kTest }, kCore);
ASSERT_EQ(kBinaries, parts->classify(kBin));
ASSERT_EQ(kCore, parts->classify(kBin / kTest));
}
TEST(Partitioning, PartsOrder)
{
auto parts(std::make_shared<Partitioning>());
parts->mark(std::vector<FSPath>{ kBin / kTest }, kCore);
parts->mark(std::vector<FSPath>{ kBin }, kBinaries);
ASSERT_EQ(kBinaries, parts->classify(kBin));
ASSERT_EQ(kBinaries, parts->classify(kBin / kTest));
}
TEST(Partitioning, NameValidation)
{
ASSERT_THROW(PartName(" "), PartNameError);
ASSERT_THROW(PartName(","), PartNameError);
}

@ -480,6 +480,7 @@ AccountsID::perform_action(Action & action) const
n::options() = MergerOptions() + mo_rewrite_symlinks + mo_allow_empty_dirs,
n::output_manager() = output_manager,
n::package_id() = shared_from_this(),
n::parts() = make_null_shared_ptr(),
n::perform_uninstall() = install_action->options.perform_uninstall(),
n::permit_destination() = std::bind(return_literal_function(true)),
n::replacing() = install_action->options.replacing(),

@ -195,6 +195,7 @@ paludis::erepository::do_fetch_action(
n::maybe_output_manager() = output_manager,
n::package_builddir() = package_builddir,
n::package_id() = id,
n::parts() = make_null_shared_ptr(),
n::permitted_directories() = make_null_shared_ptr(),
n::portdir() =
(params.master_repositories() && ! params.master_repositories()->empty())
@ -244,6 +245,7 @@ paludis::erepository::do_fetch_action(
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::parts() = make_null_shared_ptr(),
n::permitted_directories() = make_null_shared_ptr(),
n::portdir() = (repo->params().master_repositories() && ! repo->params().master_repositories()->empty()) ?
(*repo->params().master_repositories()->begin())->params().location() : repo->params().location(),

@ -104,6 +104,7 @@ paludis::erepository::do_info_action(
n::maybe_output_manager() = output_manager,
n::package_builddir() = params.builddir() / (stringify(id->name().category()) + "-" + stringify(id->name().package()) + "-" + stringify(id->version()) + "-info"),
n::package_id() = id,
n::parts() = make_null_shared_ptr(),
n::permitted_directories() = make_null_shared_ptr(),
n::portdir() =
(params.master_repositories() && ! params.master_repositories()->empty())

@ -48,6 +48,7 @@
#include <paludis/choice.hh>
#include <paludis/elike_choices.hh>
#include <paludis/output_manager.hh>
#include <paludis/partitioning.hh>
#include <paludis/slot.hh>
#include <vector>
@ -216,6 +217,7 @@ paludis::erepository::do_install_action(
}
}
auto parts(std::make_shared<Partitioning>());
auto choices(id->choices_key()->parse_value());
auto work_choice(choices->find_by_name_with_prefix(ELikeWorkChoiceValue::canonical_name_with_prefix()));
@ -283,8 +285,12 @@ paludis::erepository::do_install_action(
n::options() = id->eapi()->supported()->merger_options() | extra_merger_options,
n::output_manager() = output_manager,
n::package_id() = id,
n::parts() = parts,
n::perform_uninstall() = install_action.options.perform_uninstall(),
n::permit_destination() = std::bind(&PermittedDirectories::permit, permitted_directories, std::placeholders::_1),
n::permit_destination() =
std::bind(&PermittedDirectories::permit,
permitted_directories,
std::placeholders::_1),
n::replacing() = install_action.options.replacing(),
n::used_this_for_config_protect() = std::bind(
&used_this_for_config_protect, std::ref(used_config_protect), std::placeholders::_1),
@ -375,6 +381,7 @@ paludis::erepository::do_install_action(
n::maybe_output_manager() = output_manager,
n::package_builddir() = package_builddir,
n::package_id() = id,
n::parts() = parts,
n::permitted_directories() = permitted_directories,
n::portdir() =
(params.master_repositories() && ! params.master_repositories()->empty()) ?
@ -436,6 +443,7 @@ paludis::erepository::do_install_action(
n::maybe_output_manager() = output_manager,
n::package_builddir() = package_builddir,
n::package_id() = id,
n::parts() = parts,
n::permitted_directories() = permitted_directories,
n::portdir() =
(params.master_repositories() && ! params.master_repositories()->empty())

@ -121,6 +121,7 @@ paludis::erepository::do_pretend_action(
n::maybe_output_manager() = output_manager,
n::package_builddir() = params.builddir() / (stringify(id->name().category()) + "-" + stringify(id->name().package()) + "-" + stringify(id->version()) + "-bad_options"),
n::package_id() = id,
n::parts() = make_null_shared_ptr(),
n::permitted_directories() = make_null_shared_ptr(),
n::portdir() =
(params.master_repositories() && ! params.master_repositories()->empty()) ?
@ -186,6 +187,7 @@ paludis::erepository::do_pretend_action(
n::maybe_output_manager() = output_manager,
n::package_builddir() = params.builddir() / (stringify(id->name().category()) + "-" + stringify(id->name().package()) + "-" + stringify(id->version()) + "-bad_options"),
n::package_id() = id,
n::parts() = make_null_shared_ptr(),
n::permitted_directories() = make_null_shared_ptr(),
n::portdir() =
(params.master_repositories() && ! params.master_repositories()->empty())
@ -250,6 +252,7 @@ paludis::erepository::do_pretend_action(
n::maybe_output_manager() = output_manager,
n::package_builddir() = params.builddir() / (stringify(id->name().category()) + "-" + stringify(id->name().package()) + "-" + stringify(id->version()) + "-pretend"),
n::package_id() = id,
n::parts() = make_null_shared_ptr(),
n::permitted_directories() = make_null_shared_ptr(),
n::portdir() =
(params.master_repositories() && ! params.master_repositories()->empty())

@ -268,6 +268,7 @@ EInstalledRepository::perform_config(
n::maybe_output_manager() = output_manager,
n::package_builddir() = _imp->params.builddir() / (stringify(id->name().category()) + "-" + stringify(id->name().package()) + "-" + stringify(id->version()) + "-config"),
n::package_id() = id,
n::parts() = make_null_shared_ptr(),
n::permitted_directories() = make_null_shared_ptr(),
n::portdir() = ver_dir,
n::root() = stringify(_imp->params.root()),
@ -376,6 +377,7 @@ EInstalledRepository::perform_info(
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::parts() = make_null_shared_ptr(),
n::permitted_directories() = make_null_shared_ptr(),
n::portdir() = ver_dir,
n::root() = stringify(_imp->params.root()),

@ -1749,6 +1749,7 @@ ERepository::get_environment_variable(
n::maybe_output_manager() = make_null_shared_ptr(),
n::package_builddir() = _imp->params.builddir() / (stringify(id->name().category()) + "-" + stringify(id->name().package()) + "-" + stringify(id->version()) + "-variable"),
n::package_id() = id,
n::parts() = make_null_shared_ptr(),
n::permitted_directories() = make_null_shared_ptr(),
n::portdir() =
(_imp->params.master_repositories() && ! _imp->params.master_repositories()->empty()) ?

@ -146,8 +146,14 @@ EbuildCommand::operator() ()
using namespace std::placeholders;
process.pipe_command_handler("PALUDIS_PIPE_COMMAND", std::bind(&pipe_command_handler, params.environment(),
params.package_id(), params.permitted_directories(), in_metadata_generation(), _1, params.maybe_output_manager()));
process.pipe_command_handler("PALUDIS_PIPE_COMMAND",
std::bind(&pipe_command_handler,
params.environment(),
params.package_id(),
params.permitted_directories(),
params.parts(),
in_metadata_generation(), _1,
params.maybe_output_manager()));
std::shared_ptr<const FSPathSequence> syncers_dirs(params.environment()->syncers_dirs());
std::shared_ptr<const FSPathSequence> bashrc_files(params.environment()->bashrc_files());
@ -1056,8 +1062,13 @@ WriteVDBEntryCommand::operator() ()
params.package_id()->eapi()->supported()->ebuild_environment_variables()->env_ebuild_phase_func())
.setenv("PALUDIS_PIPE_COMMANDS_SUPPORTED", "yes")
.setenv("PALUDIS_PIPE_COMMANDS_STATUS_SUPPORTED", "yes")
.pipe_command_handler("PALUDIS_PIPE_COMMAND", std::bind(&pipe_command_handler, params.environment(),
params.package_id(), make_null_shared_ptr(), false, _1, params.maybe_output_manager()));
.pipe_command_handler("PALUDIS_PIPE_COMMAND",
std::bind(&pipe_command_handler,
params.environment(),
params.package_id(),
make_null_shared_ptr(),
make_null_shared_ptr(), false, _1,
params.maybe_output_manager()));
if (! params.package_id()->eapi()->supported()->ebuild_metadata_variables()->iuse_effective()->name().empty())
if (params.package_id()->raw_iuse_effective_key())
@ -1315,8 +1326,13 @@ WriteBinaryEbuildCommand::operator() ()
params.package_id()->eapi()->supported()->ebuild_environment_variables()->env_ebuild_phase_func())
.setenv("PALUDIS_PIPE_COMMANDS_SUPPORTED", "yes")
.setenv("PALUDIS_PIPE_COMMANDS_STATUS_SUPPORTED", "yes")
.pipe_command_handler("PALUDIS_PIPE_COMMAND", std::bind(&pipe_command_handler, params.environment(),
params.package_id(), make_null_shared_ptr(), false, _1, params.maybe_output_manager()));
.pipe_command_handler("PALUDIS_PIPE_COMMAND",
std::bind(&pipe_command_handler,
params.environment(),
params.package_id(),
make_null_shared_ptr(),
make_null_shared_ptr(), false, _1,
params.maybe_output_manager()));
if (! params.package_id()->eapi()->supported()->ebuild_metadata_variables()->scm_revision()->name().empty())
if (params.package_id()->scm_revision_key())

@ -33,6 +33,7 @@
#include <paludis/output_manager-fwd.hh>
#include <paludis/repository-fwd.hh>
#include <paludis/package_id-fwd.hh>
#include <paludis/partitioning-fwd.hh>
#include <paludis/merger.hh>
#include <string>
@ -85,6 +86,7 @@ namespace paludis
typedef Name<struct name_output_directory> output_directory;
typedef Name<struct name_package_builddir> package_builddir;
typedef Name<struct name_package_id> package_id;
typedef Name<struct name_parts> parts;
typedef Name<struct name_permitted_directories> permitted_directories;
typedef Name<struct name_portdir> portdir;
typedef Name<struct name_profiles> profiles;
@ -131,6 +133,7 @@ namespace paludis
NamedValue<n::maybe_output_manager, std::shared_ptr<OutputManager> > maybe_output_manager;
NamedValue<n::package_builddir, FSPath> package_builddir;
NamedValue<n::package_id, std::shared_ptr<const erepository::ERepositoryID> > package_id;
NamedValue<n::parts, std::shared_ptr<Partitioning> > parts;
NamedValue<n::permitted_directories, std::shared_ptr<erepository::PermittedDirectories> > permitted_directories;
NamedValue<n::portdir, FSPath> portdir;
NamedValue<n::root, std::string> root;

@ -49,4 +49,8 @@ exdirectory()
paludis_pipe_command PERMIT_DIRECTORY "$EAPI" "$@" >/dev/null
}
expart()
{
paludis_pipe_command PARTITION "$EAPI" "$@" >/dev/null
}

@ -317,6 +317,7 @@ EbuildID::need_non_xml_keys_added() const
n::maybe_output_manager() = make_null_shared_ptr(),
n::package_builddir() = e_repo->params().builddir() / (stringify(name().category()) + "-" + stringify(name().package()) + "-" + stringify(version()) + "-metadata"),
n::package_id() = shared_from_this(),
n::parts() = make_null_shared_ptr(),
n::permitted_directories() = make_null_shared_ptr(),
n::portdir() =
(e_repo->params().master_repositories() && ! e_repo->params().master_repositories()->empty()) ?

@ -447,6 +447,7 @@ ExndbamRepository::merge(const MergeParams & m)
n::options() = m.options(),
n::output_manager() = m.output_manager(),
n::package_id() = m.package_id(),
n::parts() = m.parts(),
n::permit_destination() = m.permit_destination(),
n::root() = installed_root_key()->parse_value()
));
@ -636,6 +637,7 @@ ExndbamRepository::perform_uninstall(
n::maybe_output_manager() = output_manager,
n::package_builddir() = package_builddir,
n::package_id() = id,
n::parts() = make_null_shared_ptr(),
n::permitted_directories() = make_null_shared_ptr(),
n::portdir() = _imp->params.location(),
n::root() = stringify(_imp->params.root()),

@ -3,6 +3,7 @@
/*
* Copyright (c) 2007, 2008, 2009, 2010, 2011 Ciaran McCreesh
* Copyright (c) 2009 Ingmar Vanhassel
* Copyright (c) 2013 Saleem Abdulrasool <compnerd@compnerd.org>
*
* 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
@ -52,9 +53,11 @@
#include <paludis/dep_spec_annotations.hh>
#include <paludis/unformatted_pretty_printer.hh>
#include <paludis/version_spec.hh>
#include <paludis/partitioning.hh>
#include <paludis/repository.hh>
#include <paludis/elike_choices.hh>
#include <list>
#include <vector>
#include <limits>
#include <sstream>
@ -180,6 +183,7 @@ std::string
paludis::erepository::pipe_command_handler(const Environment * const environment,
const std::shared_ptr<const ERepositoryID> & package_id,
const std::shared_ptr<PermittedDirectories> & maybe_permitted_directories,
const std::shared_ptr<Partitioning> & maybe_partitioning,
bool in_metadata_generation,
const std::string & s, const std::shared_ptr<OutputManager> & maybe_output_manager)
{
@ -564,6 +568,55 @@ paludis::erepository::pipe_command_handler(const Environment * const environment
maybe_permitted_directories->add(FSPath(tokens[3]), permit);
return "O0;";
}
else if (tokens[0] == "PARTITION")
{
bool exclude(false);
std::shared_ptr<const EAPI> eapi =
EAPIData::get_instance()->eapi_from_string(tokens[1]);
if (! eapi->supported())
return "EPARTITION EAPI " + tokens[1] + " unsupported";
if (tokens.size() < 4 ||
((exclude = (tokens[2] == "--exclude")) && tokens.size() < 5))
{
Log::get_instance()->message("e.pipe_commands.partition.bad",
ll_warning, lc_context)
<< "Got bad PARTITION pipe command";
return "Ebad PARTITION command";
}
const std::string partition_id(tokens[2]);
std::vector<FSPath> contents;
for (auto token = tokens.begin() + (exclude ? 3 : 2),
last = tokens.end();
token != last; ++token)
contents.push_back(FSPath(*token));
try
{
if (maybe_partitioning == NULL)
{
Log::get_instance()->message("e.pipe_commands.partitioning.unsupported",
ll_warning, lc_context)
<< "parts not supported by destination repository";
return "EPARTITION EXPART not supported by destination repository";
}
else
{
maybe_partitioning->mark(contents,
exclude ? PartName("")
: PartName(partition_id));
}
return "O0;";
}
catch (const Exception & e)
{
return "Egot error '" + e.message() + "' (" + e.what() + ") "
"when trying to create partition";
}
}
else if (tokens[0] == "REWRITE_VAR")
{
if (tokens.size() < 4)

@ -24,6 +24,7 @@
#include <paludis/environment-fwd.hh>
#include <paludis/package_id-fwd.hh>
#include <paludis/output_manager-fwd.hh>
#include <paludis/partitioning-fwd.hh>
#include <functional>
#include <string>
@ -36,6 +37,7 @@ namespace paludis
std::string pipe_command_handler(const Environment * const,
const std::shared_ptr<const ERepositoryID> &,
const std::shared_ptr<PermittedDirectories> &,
const std::shared_ptr<Partitioning> &,
bool in_metadata_generation,
const std::string & s,
const std::shared_ptr<OutputManager> & maybe_output_manager);

@ -64,6 +64,9 @@ VDBID::contents_filename() const
const std::shared_ptr<const Contents>
VDBID::contents() const
{
// NOTE(compnerd) VDB does not support parts
static const std::string kNoPart = "";
FSPath contents_location(fs_location_key()->parse_value() / "CONTENTS");
Context context("When creating contents from '" + stringify(contents_location) + "':");
@ -94,7 +97,8 @@ VDBID::contents() const
if ("obj" == tokens.at(0))
{
std::shared_ptr<ContentsEntry> e(std::make_shared<ContentsFileEntry>(FSPath(tokens.at(1))));
auto e(std::make_shared<ContentsFileEntry>(FSPath(tokens.at(1)),
kNoPart));
e->add_metadata_key(std::make_shared<LiteralMetadataTimeKey>("mtime", "mtime", mkt_normal,
Timestamp(destringify<time_t>(tokens.at(3)), 0)));
e->add_metadata_key(std::make_shared<LiteralMetadataValueKey<std::string>>("md5", "md5", mkt_normal, tokens.at(2)));
@ -107,7 +111,8 @@ VDBID::contents() const
}
else if ("sym" == tokens.at(0))
{
std::shared_ptr<ContentsEntry> e(std::make_shared<ContentsSymEntry>(FSPath(tokens.at(1)), tokens.at(2)));
auto e(std::make_shared<ContentsSymEntry>(FSPath(tokens.at(1)),
tokens.at(2), kNoPart));
e->add_metadata_key(std::make_shared<LiteralMetadataTimeKey>("mtime", "mtime", mkt_normal,
Timestamp(destringify<time_t>(tokens.at(3)), 0)));
value->add(e);

@ -30,6 +30,7 @@
#include <paludis/util/strip.hh>
#include <paludis/util/options.hh>
#include <paludis/util/make_named_values.hh>
#include <paludis/util/make_null_shared_ptr.hh>
#include <paludis/util/enum_iterator.hh>
#include <paludis/util/timestamp.hh>
#include <paludis/util/env_var_names.hh>
@ -98,6 +99,7 @@ VDBMerger::VDBMerger(const VDBMergerParams & p) :
n::merged_entries() = p.merged_entries(),
n::no_chown() = ! getenv_with_default(env_vars::no_chown, "").empty(),
n::options() = p.options(),
n::parts() = make_null_shared_ptr(),
n::permit_destination() = p.permit_destination(),
n::root() = p.root()
)),

@ -508,6 +508,7 @@ VDBRepository::perform_uninstall(
n::maybe_output_manager() = output_manager,
n::package_builddir() = package_builddir,
n::package_id() = id,
n::parts() = make_null_shared_ptr(),
n::permitted_directories() = make_null_shared_ptr(),
n::portdir() = _imp->params.location(),
n::root() = stringify(_imp->params.root()),

@ -229,6 +229,7 @@ UnavailableRepositoryID::perform_action(Action & action) const
n::options() = MergerOptions(),
n::output_manager() = output_manager,
n::package_id() = shared_from_this(),
n::parts() = make_null_shared_ptr(),
n::perform_uninstall() = install_action->options.perform_uninstall(),
n::permit_destination() = std::bind(return_literal_function(true)),
n::replacing() = install_action->options.replacing(),

@ -380,6 +380,7 @@ InstalledUnpackagedRepository::merge(const MergeParams & m)
n::options() = m.options(),
n::output_manager() = m.output_manager(),
n::package_id() = m.package_id(),
n::parts() = m.parts(),
n::permit_destination() = m.permit_destination(),
n::root() = installed_root_key()->parse_value().realpath()
));

@ -415,6 +415,7 @@ UnpackagedID::perform_action(Action & action) const
| extra_merger_options,
n::output_manager() = output_manager,
n::package_id() = shared_from_this(),
n::parts() = make_null_shared_ptr(),
n::perform_uninstall() = install_action->options.perform_uninstall(),
n::permit_destination() = std::bind(return_literal_function(true)),
n::replacing() = install_action->options.replacing(),

@ -26,6 +26,7 @@
#include <paludis/spec_tree-fwd.hh>
#include <paludis/name.hh>
#include <paludis/package_id-fwd.hh>
#include <paludis/partitioning-fwd.hh>
#include <paludis/util/attributes.hh>
#include <paludis/util/exception.hh>
#include <paludis/util/fs_path.hh>
@ -70,6 +71,7 @@ namespace paludis
typedef Name<struct name_options> options;
typedef Name<struct name_output_manager> output_manager;
typedef Name<struct name_package_id> package_id;
typedef Name<struct name_parts> parts;
typedef Name<struct name_path> path;
typedef Name<struct name_perform_uninstall> perform_uninstall;
typedef Name<struct name_permit_destination> permit_destination;
@ -133,6 +135,12 @@ namespace paludis
NamedValue<n::output_manager, std::shared_ptr<OutputManager> > output_manager;
NamedValue<n::package_id, std::shared_ptr<const PackageID> > package_id;
/**
* Package partioning.
* \since 1.1.0
*/
NamedValue<n::parts, std::shared_ptr<Partitioning> > parts;
/**
* Some merges need to do an uninstall mid-way through the merge process.
*

@ -1,13 +1,21 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
const auto fs_file = make_format_string_fetcher("contents/file", 1)
<< c::bold_blue_or_pink() << param<'s'>() << c::normal();
<< c::bold_blue_or_pink() << param<'s'>()
<< param_if<'p'>()
<< c::yellow() << " [" << param<'p'>() << "]"
<< param_endif<'p'>()
<< c::normal();
const auto fs_dir = make_format_string_fetcher("contents/dir", 1)
<< c::blue_or_pink() << param<'s'>() << c::normal();
const auto fs_sym = make_format_string_fetcher("contents/sym", 1)
<< c::bold_green_or_pink() << param<'s'>() << c::normal() << " -> " << param<'t'>();
<< c::bold_green_or_pink() << param<'s'>()
<< c::normal() << " -> " << param<'t'>()
<< param_if<'p'>()
<< c::yellow() << " [" << param<'p'>() << "]" << c::normal()
<< param_endif<'p'>();
const auto fs_other = make_format_string_fetcher("contents/other", 1)
<< c::bold_yellow() << param<'s'>() << c::normal();

@ -82,7 +82,11 @@ namespace
{
std::string visit(const ContentsFileEntry & e) const
{
return fuc(fs_file(), fv<'s'>(stringify(e.location_key()->parse_value())));
return fuc(fs_file(),
fv<'p'>(e.part_key()
? stringify(e.part_key()->parse_value())
: ""),
fv<'s'>(stringify(e.location_key()->parse_value())));
}
std::string visit(const ContentsDirEntry & e) const
@ -93,8 +97,11 @@ namespace
std::string visit(const ContentsSymEntry & e) const
{
return fuc(fs_sym(),
fv<'s'>(stringify(e.location_key()->parse_value())),
fv<'t'>(stringify(e.target_key()->parse_value())));
fv<'p'>(e.part_key()
? stringify(e.part_key()->parse_value())
: ""),
fv<'s'>(stringify(e.location_key()->parse_value())),
fv<'t'>(stringify(e.target_key()->parse_value())));
}
std::string visit(const ContentsOtherEntry & e) const