aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2007-03-29 21:57:28 +0000
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2007-03-29 21:57:28 +0000
commit79bc9a55a40ae0eb2e40399b519ba63636a05a29 (patch)
tree4aa1ec392bafea8951e965c238c16bab57702910
parent1d076a592f297cf35fd7833f74a24f21739f75c4 (diff)
downloadpaludis-79bc9a55a40ae0eb2e40399b519ba63636a05a29.tar.gz
paludis-79bc9a55a40ae0eb2e40399b519ba63636a05a29.tar.xz
Common hook code for PaludisEnvironment and PortageEnvironment
-rw-r--r--paludis/environments/paludis/paludis_environment.cc189
-rw-r--r--paludis/environments/portage/portage_environment.cc131
-rw-r--r--paludis/environments/portage/portage_environment.hh14
-rw-r--r--paludis/files.m41
-rw-r--r--paludis/hooker.cc132
-rw-r--r--paludis/hooker.hh45
6 files changed, 367 insertions, 145 deletions
diff --git a/paludis/environments/paludis/paludis_environment.cc b/paludis/environments/paludis/paludis_environment.cc
index a7d9c7d..4f20d65 100644
--- a/paludis/environments/paludis/paludis_environment.cc
+++ b/paludis/environments/paludis/paludis_environment.cc
@@ -17,9 +17,8 @@
* Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <list>
#include <paludis/config_file.hh>
-#include <paludis/hashed_containers.hh>
+#include <paludis/hooker.hh>
#include <paludis/environments/paludis/paludis_config.hh>
#include <paludis/environments/paludis/paludis_environment.hh>
#include <paludis/match_package.hh>
@@ -35,27 +34,70 @@
#include <paludis/util/system.hh>
#include <paludis/util/tokeniser.hh>
#include <paludis/util/dir_iterator.hh>
+
+#include <list>
#include <vector>
+#include <tr1/functional>
+#include <functional>
+#include <algorithm>
using namespace paludis;
-typedef MakeHashedMap<std::string, bool>::Type HookPresentCache;
-
namespace paludis
{
template<>
struct Implementation<PaludisEnvironment>
{
- mutable HookPresentCache hook_cache;
+ mutable bool done_hooks;
+ mutable std::tr1::shared_ptr<Hooker> hooker;
+ mutable std::list<FSEntry> hook_dirs;
+
std::tr1::shared_ptr<PaludisConfig> config;
std::string paludis_command;
std::list<UseConfigEntry> forced_use;
Implementation(std::tr1::shared_ptr<PaludisConfig> c) :
+ done_hooks(false),
config(c),
paludis_command("paludis")
{
}
+
+ void add_one_hook(const FSEntry & r) const
+ {
+ try
+ {
+ if (r.is_directory())
+ {
+ Log::get_instance()->message(ll_debug, lc_no_context, "Adding hook directory '"
+ + stringify(r) + "'");
+ hook_dirs.push_back(r);
+ }
+ else
+ Log::get_instance()->message(ll_debug, lc_no_context, "Skipping hook directory candidate '"
+ + stringify(r) + "'");
+ }
+ catch (const FSError & e)
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context, "Caught exception '" +
+ e.message() + "' (" + e.what() + ") when checking hook "
+ "directory '" + stringify(r) + "'");
+ }
+ }
+
+ void need_hook_dirs(const FSEntry & c) const
+ {
+ if (! done_hooks)
+ {
+ add_one_hook(c / "hooks");
+ if (getenv_with_default("PALUDIS_NO_GLOBAL_HOOKS", "").empty())
+ {
+ add_one_hook(FSEntry(LIBEXECDIR) / "paludis" / "hooks");
+ add_one_hook(FSEntry(DATADIR) / "paludis" / "hooks");
+ }
+ done_hooks = true;
+ }
+ }
};
}
@@ -543,146 +585,27 @@ PaludisEnvironment::set_paludis_command(const std::string & s)
_imp->paludis_command = s;
}
-namespace
-{
- void add_one_hook(const std::string & base, std::list<FSEntry> & result)
- {
- try
- {
- FSEntry r(base);
- if (r.is_directory())
- {
- Log::get_instance()->message(ll_debug, lc_no_context, "Adding hook directory '"
- + base + "'");
- result.push_back(r);
- }
- else
- Log::get_instance()->message(ll_debug, lc_no_context, "Skipping hook directory candidate '"
- + base + "'");
- }
- catch (const FSError & e)
- {
- Log::get_instance()->message(ll_warning, lc_no_context, "Caught exception '" +
- e.message() + "' (" + e.what() + ") when checking hook "
- "directory '" + base + "'");
- }
- }
-
- const std::list<FSEntry> & get_hook_dirs(const std::string & c)
- {
- static std::list<FSEntry> result;
- static bool done_hooks(false);
- if (! done_hooks)
- {
- add_one_hook(c + "/hooks", result);
- if (getenv_with_default("PALUDIS_NO_GLOBAL_HOOKS", "").empty())
- {
- add_one_hook(LIBEXECDIR "/paludis/hooks", result);
- add_one_hook(DATADIR "/paludis/hooks", result);
- }
- done_hooks = true;
- }
- return result;
- }
-
- struct Hooker
- {
- Hook hook;
- std::string paludis_command;
- std::string root;
- std::string reduced_gid;
- std::string reduced_uid;
-
- Hooker(const Hook & h, const std::string & p, const std::string & r,
- const std::string & g, const std::string & u) :
- hook(h),
- paludis_command(p),
- root(r),
- reduced_gid(g),
- reduced_uid(u)
- {
- }
-
- int operator() (const FSEntry & f) const;
- };
-
- int
- Hooker::operator() (const FSEntry & f) const
- {
- Context context("When running hook script '" + stringify(f) +
- "' for hook '" + hook.name() + "':");
- Log::get_instance()->message(ll_debug, lc_no_context, "Starting hook script '" +
- stringify(f) + "' for '" + hook.name() + "'");
-
- Command cmd(Command("bash '" + stringify(f) + "'")
- .with_setenv("ROOT", root)
- .with_setenv("HOOK", hook.name())
- .with_setenv("HOOK_LOG_LEVEL", stringify(Log::get_instance()->log_level()))
- .with_setenv("PALUDIS_EBUILD_DIR", getenv_with_default("PALUDIS_EBUILD_DIR", LIBEXECDIR "/paludis"))
- .with_setenv("PALUDIS_REDUCED_GID", reduced_gid)
- .with_setenv("PALUDIS_REDUCED_UID", reduced_uid)
- .with_setenv("PALUDIS_COMMAND", paludis_command));
-
- for (Hook::Iterator h(hook.begin()), h_end(hook.end()) ; h != h_end ; ++h)
- cmd.with_setenv(h->first, h->second);
-
- int exit_status(run_command(cmd));
- if (0 == exit_status)
- Log::get_instance()->message(ll_debug, lc_no_context, "Hook '" + stringify(f)
- + "' returned success '" + stringify(exit_status) + "'");
- else
- Log::get_instance()->message(ll_warning, lc_no_context, "Hook '" + stringify(f)
- + "' returned failure '" + stringify(exit_status) + "'");
- return exit_status;
- }
-}
-
int
PaludisEnvironment::perform_hook(const Hook & hook) const
{
- HookPresentCache::iterator cache_entry(_imp->hook_cache.end());
- if (_imp->hook_cache.end() != ((cache_entry = _imp->hook_cache.find(hook.name()))))
- if (! cache_entry->second)
- return 0;
+ using namespace std::tr1::placeholders;
- Context context("When triggering hook '" + hook.name() + "'");
- Log::get_instance()->message(ll_debug, lc_no_context, "Starting hook '" + hook.name() + "'");
-
- const std::list<FSEntry> & hook_dirs_ref(get_hook_dirs(_imp->config->config_dir()));
-
- bool had_hook(false);
- int max_exit_status(0);
- for (std::list<FSEntry>::const_iterator h(hook_dirs_ref.begin()),
- h_end(hook_dirs_ref.end()) ; h != h_end ; ++h)
+ if (! _imp->hooker)
{
- FSEntry hh(*h / hook.name());
- if (! hh.is_directory())
- continue;
-
- std::list<FSEntry> hooks;
- std::copy(DirIterator(hh), DirIterator(),
- filter_inserter(std::back_inserter(hooks), IsFileWithExtension(".bash")));
-
- if (! hooks.empty())
- had_hook = true;
-
- for (std::list<FSEntry>::const_iterator hk(hooks.begin()),
- hk_end(hooks.end()) ; hk != hk_end ; ++hk)
- max_exit_status = std::max(max_exit_status, Hooker(hook, paludis_command(),
- stringify(root()), stringify(reduced_gid()), stringify(reduced_uid()))(*hk));
+ _imp->need_hook_dirs(_imp->config->config_dir());
+ _imp->hooker.reset(new Hooker(this));
+ std::for_each(_imp->hook_dirs.begin(), _imp->hook_dirs.end(),
+ std::tr1::bind(std::tr1::mem_fn(&Hooker::add_dir), _imp->hooker.get(), _1));
}
- if (_imp->hook_cache.end() == cache_entry)
- _imp->hook_cache.insert(std::make_pair(hook.name(), had_hook));
-
- return max_exit_status;
+ return _imp->hooker->perform_hook(hook);
}
std::string
PaludisEnvironment::hook_dirs() const
{
- const std::list<FSEntry> & hook_dirs_ref(get_hook_dirs(_imp->config->config_dir()));
- return join(hook_dirs_ref.begin(), hook_dirs_ref.end(), " ");
+ _imp->need_hook_dirs(_imp->config->config_dir());
+ return join(_imp->hook_dirs.begin(), _imp->hook_dirs.end(), " ");
}
std::string
diff --git a/paludis/environments/portage/portage_environment.cc b/paludis/environments/portage/portage_environment.cc
index 120ec43..84acda7 100644
--- a/paludis/environments/portage/portage_environment.cc
+++ b/paludis/environments/portage/portage_environment.cc
@@ -27,7 +27,11 @@
#include <paludis/util/strip.hh>
#include <paludis/repositories/repository_maker.hh>
#include <paludis/config_file.hh>
+#include <paludis/hooker.hh>
#include <paludis/match_package.hh>
+#include <algorithm>
+#include <tr1/functional>
+#include <functional>
#include <set>
#include <vector>
@@ -62,11 +66,50 @@ namespace paludis
PackageMask package_mask;
PackageUnmask package_unmask;
+ mutable bool done_hooks;
+ mutable std::tr1::shared_ptr<Hooker> hooker;
+ mutable std::list<FSEntry> hook_dirs;
+
Implementation(const std::string & s) :
conf_dir(FSEntry(s.empty() ? "/" : s) / SYSCONFDIR),
- paludis_command("paludis")
+ paludis_command("paludis"),
+ done_hooks(false)
+ {
+ }
+
+ void add_one_hook(const FSEntry & r) const
{
+ try
+ {
+ if (r.is_directory())
+ {
+ Log::get_instance()->message(ll_debug, lc_no_context, "Adding hook directory '"
+ + stringify(r) + "'");
+ hook_dirs.push_back(r);
+ }
+ else
+ Log::get_instance()->message(ll_debug, lc_no_context, "Skipping hook directory candidate '"
+ + stringify(r) + "'");
+ }
+ catch (const FSError & e)
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context, "Caught exception '" +
+ e.message() + "' (" + e.what() + ") when checking hook "
+ "directory '" + stringify(r) + "'");
+ }
}
+
+ void need_hook_dirs() const
+ {
+ if (! done_hooks)
+ {
+ if (getenv_with_default("PALUDIS_NO_GLOBAL_HOOKS", "").empty())
+ add_one_hook(FSEntry(LIBEXECDIR) / "paludis" / "hooks");
+
+ done_hooks = true;
+ }
+ }
+
};
}
@@ -101,9 +144,10 @@ PortageEnvironment::PortageEnvironment(const std::string & s) :
Context context("When creating PortageEnvironment using config root '" + s + "':");
Log::get_instance()->message(ll_warning, lc_no_context,
- "Use of PortageEnvironment will lead to sub-optimal performance and loss of "
+ "Use of Portage configuration files will lead to sub-optimal performance and loss of "
"functionality. Full support for Portage configuration formats is not "
- "guaranteed. You are strongly encouraged to migrate to PaludisEnvironment.");
+ "guaranteed; issues should be reported via trac. You are strongly encouraged "
+ "to migrate to a Paludis configuration.");
_imp->vars.reset(new KeyValueConfigFile(FSEntry("/dev/null"), &getenv_with_default, &is_incremental));
_load_profile((_imp->conf_dir / "make.profile").realpath());
@@ -421,3 +465,84 @@ PortageEnvironment::root() const
return FSEntry(_imp->vars->get("ROOT"));
}
+bool
+PortageEnvironment::query_user_masks(const PackageDatabaseEntry & e) const
+{
+ for (PackageMask::const_iterator i(_imp->package_mask.begin()), i_end(_imp->package_mask.end()) ;
+ i != i_end ; ++i)
+ if (match_package(*this, **i, e))
+ return true;
+
+ return false;
+}
+
+bool
+PortageEnvironment::query_user_unmasks(const PackageDatabaseEntry & e) const
+{
+ for (PackageMask::const_iterator i(_imp->package_mask.begin()), i_end(_imp->package_mask.end()) ;
+ i != i_end ; ++i)
+ if (match_package(*this, **i, e))
+ return true;
+
+ return false;
+}
+
+std::tr1::shared_ptr<const UseFlagNameCollection>
+PortageEnvironment::known_use_expand_names(const UseFlagName & prefix,
+ const PackageDatabaseEntry * pde) const
+{
+ Context context("When loading known use expand names for prefix '" + stringify(prefix) + ":");
+
+ std::tr1::shared_ptr<UseFlagNameCollection> result(new UseFlagNameCollection::Concrete);
+ std::string prefix_lower;
+ std::transform(prefix.data().begin(), prefix.data().end(), std::back_inserter(prefix_lower), &::tolower);
+
+ for (std::set<std::string>::const_iterator i(_imp->use_with_expands.begin()),
+ i_end(_imp->use_with_expands.end()) ; i != i_end ; ++i)
+ if (0 == i->compare(0, prefix_lower.length(), prefix_lower, 0, prefix_lower.length()))
+ result->insert(UseFlagName(*i));
+
+ if (pde)
+ {
+ for (PackageUse::const_iterator i(_imp->package_use.begin()), i_end(_imp->package_use.end()) ;
+ i != i_end ; ++i)
+ {
+ if (! match_package(*this, *i->first, *pde))
+ continue;
+
+ if (0 == i->second.compare(0, prefix_lower.length(), prefix_lower, 0, prefix_lower.length()))
+ result->insert(UseFlagName(i->second));
+ }
+ }
+
+ Log::get_instance()->message(ll_debug, lc_no_context, "PortageEnvironment::known_use_expand_names("
+ + stringify(prefix) + ", " + (pde ? stringify(*pde) : stringify("0")) + ") -> ("
+ + join(result->begin(), result->end(), ", ") + ")");
+
+ return result;
+}
+
+int
+PortageEnvironment::perform_hook(const Hook & hook) const
+{
+ using namespace std::tr1::placeholders;
+
+ if (! _imp->hooker)
+ {
+ _imp->need_hook_dirs();
+ _imp->hooker.reset(new Hooker(this));
+ std::for_each(_imp->hook_dirs.begin(), _imp->hook_dirs.end(),
+ std::tr1::bind(std::tr1::mem_fn(&Hooker::add_dir), _imp->hooker.get(), _1));
+ }
+
+ return _imp->hooker->perform_hook(hook);
+}
+
+
+std::string
+PortageEnvironment::hook_dirs() const
+{
+ _imp->need_hook_dirs();
+ return join(_imp->hook_dirs.begin(), _imp->hook_dirs.end(), " ");
+}
+
diff --git a/paludis/environments/portage/portage_environment.hh b/paludis/environments/portage/portage_environment.hh
index 7ed7951..0f9a899 100644
--- a/paludis/environments/portage/portage_environment.hh
+++ b/paludis/environments/portage/portage_environment.hh
@@ -64,13 +64,9 @@ namespace paludis
const bool override_tilde_keywords = false) const
PALUDIS_ATTRIBUTE((warn_unused_result));
-#if 0
virtual std::tr1::shared_ptr<const UseFlagNameCollection> known_use_expand_names(const UseFlagName &,
const PackageDatabaseEntry *) const
PALUDIS_ATTRIBUTE((warn_unused_result));
-#endif
-
-#if 0
virtual bool query_user_masks(const PackageDatabaseEntry &) const
PALUDIS_ATTRIBUTE((warn_unused_result));
@@ -78,11 +74,6 @@ namespace paludis
virtual bool query_user_unmasks(const PackageDatabaseEntry &) const
PALUDIS_ATTRIBUTE((warn_unused_result));
- virtual std::string bashrc_files() const
- PALUDIS_ATTRIBUTE((warn_unused_result));
-
-#endif
-
virtual std::string paludis_command() const
PALUDIS_ATTRIBUTE((warn_unused_result));
@@ -98,6 +89,11 @@ namespace paludis
virtual FSEntry root() const
PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual int perform_hook(const Hook & hook) const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual std::string hook_dirs() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
};
}
diff --git a/paludis/files.m4 b/paludis/files.m4
index fa2b3e7..8f1d02b 100644
--- a/paludis/files.m4
+++ b/paludis/files.m4
@@ -17,6 +17,7 @@ add(`dep_spec_pretty_printer', `hh', `cc')
add(`dep_tag', `hh', `cc', `sr')
add(`environment', `hh', `cc')
add(`hashed_containers', `hhx', `cc', `test')
+add(`hooker', `hh', `cc')
add(`host_tuple_name', `hh', `cc', `sr', `test')
add(`mask_reasons', `hh', `cc', `se')
add(`match_package', `hh', `cc')
diff --git a/paludis/hooker.cc b/paludis/hooker.cc
new file mode 100644
index 0000000..a774e89
--- /dev/null
+++ b/paludis/hooker.cc
@@ -0,0 +1,132 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.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 "hooker.hh"
+#include <paludis/environment.hh>
+#include <paludis/hashed_containers.hh>
+#include <paludis/util/collection_concrete.hh>
+#include <paludis/util/log.hh>
+#include <paludis/util/dir_iterator.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/is_file_with_extension.hh>
+#include <paludis/util/system.hh>
+#include <list>
+
+using namespace paludis;
+
+typedef MakeHashedMap<std::string, bool>::Type HookPresentCache;
+
+namespace paludis
+{
+ template<>
+ struct Implementation<Hooker>
+ {
+ const Environment * const env;
+ mutable HookPresentCache hook_cache;
+ std::list<FSEntry> dirs;
+
+ Implementation(const Environment * const e) :
+ env(e)
+ {
+ }
+ };
+}
+
+Hooker::Hooker(const Environment * const e) :
+ PrivateImplementationPattern<Hooker>(new Implementation<Hooker>(e))
+{
+}
+
+Hooker::~Hooker()
+{
+}
+
+void
+Hooker::add_dir(const FSEntry & dir)
+{
+ _imp->hook_cache.clear();
+ _imp->dirs.push_back(dir);
+}
+
+int
+Hooker::perform_hook(const Hook & hook) const
+{
+ HookPresentCache::iterator cache_entry(_imp->hook_cache.end());
+
+ if (_imp->hook_cache.end() != ((cache_entry = _imp->hook_cache.find(hook.name()))))
+ if (! cache_entry->second)
+ return 0;
+
+ Context context("When triggering hook '" + hook.name() + "'");
+ Log::get_instance()->message(ll_debug, lc_no_context, "Starting hook '" + hook.name() + "'");
+
+ bool had_hook(false);
+ int max_exit_status(0);
+ for (std::list<FSEntry>::const_iterator h(_imp->dirs.begin()), h_end(_imp->dirs.end()) ;
+ h != h_end ; ++h)
+ {
+ FSEntry hh(*h / hook.name());
+ if (! hh.is_directory())
+ continue;
+
+ std::list<FSEntry> hooks;
+ std::copy(DirIterator(hh), DirIterator(),
+ filter_inserter(std::back_inserter(hooks), IsFileWithExtension(".bash")));
+
+ if (! hooks.empty())
+ had_hook = true;
+
+ for (std::list<FSEntry>::const_iterator hk(hooks.begin()),
+ hk_end(hooks.end()) ; hk != hk_end ; ++hk)
+ {
+ Context c("When running hook script '" + stringify(hh) +
+ "' for hook '" + hook.name() + "':");
+ Log::get_instance()->message(ll_debug, lc_no_context, "Starting hook script '" +
+ stringify(hh) + "' for '" + hook.name() + "'");
+
+ Command cmd(Command("bash '" + stringify(*hk) + "'")
+ .with_setenv("ROOT", stringify(_imp->env->root()))
+ .with_setenv("HOOK", hook.name())
+ .with_setenv("HOOK_LOG_LEVEL", stringify(Log::get_instance()->log_level()))
+ .with_setenv("PALUDIS_EBUILD_DIR", getenv_with_default("PALUDIS_EBUILD_DIR", LIBEXECDIR "/paludis"))
+ .with_setenv("PALUDIS_REDUCED_GID", stringify(_imp->env->reduced_gid()))
+ .with_setenv("PALUDIS_REDUCED_UID", stringify(_imp->env->reduced_uid()))
+ .with_setenv("PALUDIS_COMMAND", _imp->env->paludis_command()));
+
+ for (Hook::Iterator x(hook.begin()), x_end(hook.end()) ; x != x_end ; ++x)
+ cmd.with_setenv(x->first, x->second);
+
+ int exit_status(run_command(cmd));
+ if (0 == exit_status)
+ Log::get_instance()->message(ll_debug, lc_no_context, "Hook '" + stringify(*hk)
+ + "' returned success '" + stringify(exit_status) + "'");
+ else
+ Log::get_instance()->message(ll_warning, lc_no_context, "Hook '" + stringify(*hk)
+ + "' returned failure '" + stringify(exit_status) + "'");
+
+ max_exit_status = std::max(max_exit_status, exit_status);
+ }
+ }
+
+ if (_imp->hook_cache.end() == cache_entry)
+ _imp->hook_cache.insert(std::make_pair(hook.name(), had_hook));
+
+ return max_exit_status;
+}
+
diff --git a/paludis/hooker.hh b/paludis/hooker.hh
new file mode 100644
index 0000000..e02877b
--- /dev/null
+++ b/paludis/hooker.hh
@@ -0,0 +1,45 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.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_HOOKER_HH
+#define PALUDIS_GUARD_PALUDIS_HOOKER_HH 1
+
+#include <paludis/util/instantiation_policy.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+
+namespace paludis
+{
+ class FSEntry;
+ class Environment;
+ class Hook;
+
+ class Hooker :
+ private PrivateImplementationPattern<Hooker>,
+ private InstantiationPolicy<Hooker, instantiation_method::NonCopyableTag>
+ {
+ public:
+ Hooker(const Environment * const) PALUDIS_ATTRIBUTE((nonnull(1)));
+ ~Hooker();
+
+ int perform_hook(const Hook &) const;
+ void add_dir(const FSEntry &);
+ };
+}
+
+#endif