Hooks
Overview
This document describes the Paludis hooks interface. A hook is a piece of code that is executed when a particular well defined action occurs.
There are currently four categories of hooks:
- General hooks. These have access to a limited environment. If a hook returns a non-zero exit code, the action will be aborted. See General Hooks.
- Ebuild phase hooks. These have
ebuild
in the hook name, and have full access to the ebuild environment (including the ability to calldie
), but are only used for ebuild-based activities. See Ebuild Phase Hooks. - Ebuild message hooks. These are special hooks that are called for
einfo
,ewarn
etc. See Ebuild Message Hooks. - Merger / Unmerger hooks. These are used when installing and uninstalling content to the live filesystem. If a check hook returns a non-zero exit code, the action will be aborted. See Merger / Unmerger Hooks.
There are currently five categories of hook execution code:
.bash
hooks. These are simple.bash
files that are executed with a particular environment. See Bash Hooks for details..hook
hooks. These are alsobash
files, but rather than containing the relevant code in global scope, they make use of functions to perform hook actions. They also support specifying execution order dependencies upon other hooks. See Hook Hooks for details..py
hooks. These are much like .hook hooks, but written in Python and with additional power given by Python bindings and access to the current Environment. See Python Hooks for details..so
hooks. These are written in C++ and compiled into shared libraries, and run inside the Paludis process. See .so Hooks for details.- Repository hooks. These are implemented internally by
Repository
classes.
Not all hook execution code methods are available for all hook categories. The following table indicates availability:
.bash |
.hook |
.py |
.so |
Repository | |
---|---|---|---|---|---|
General | yes | yes | yes | yes | yes |
Ebuild Phase | yes | ||||
Ebuild Message | yes | ||||
Merger | yes | yes | yes | yes | yes |
Where there is a choice, .hook
hooks should be favoured over .bash
hooks.
Available Hooks
General Hooks
The following general normal hooks are available:
install_pre
install_fail
install_post
install_all_pre
install_all_post
install_pretend_pre
install_pretend_post
install_pretend_display_item_pre
install_pretend_display_item_post
install_task_execute_pre
install_task_execute_post
uninstall_pre
uninstall_fail
uninstall_post
uninstall_all_pre
uninstall_all_post
clean_pre
clean_post
clean_fail
clean_all_pre
clean_all_post
sync_pre
sync_fail
sync_post
sync_all_pre
sync_all_post
fetch_pre
fetch_post
fetch_all_pre
fetch_all_post
In general, certain special environment variables will be set:
HOOK
will contain the name of the hook.- For
all
hooks,TARGETS
will contain the targets for the operation. - For non-
all
hooks,TARGET
will contain the current target. - The
PALUDIS_CMDLINE
variables described below are also available. - For the
install_pretend_display_item
hooks, theKIND
variable will also be of interest. - For the
install_task_execute_pre
andinstall_task_execute_post
hooks,PRETEND
,FETCH_ONLY
andSUCCESS
may be useful.
Ebuild Phase Hooks
The following ebuild phase hooks are available:
ebuild_metadata_pre
ebuild_metadata_fail
ebuild_metadata_post
ebuild_variable_pre
ebuild_variable_fail
ebuild_variable_post
ebuild_init_pre
ebuild_init_fail
ebuild_init_post
ebuild_initmisc_pre
ebuild_initmisc_fail
ebuild_initmisc_post
ebuild_fetch_extra_pre
ebuild_fetch_extra_fail
ebuild_fetch_extra_post
ebuild_tidyup_pre
ebuild_tidyup_fail
ebuild_tidyup_post
ebuild_unpack_pre
ebuild_unpack_fail
ebuild_unpack_post
ebuild_prepare_pre
ebuild_prepare_fail
ebuild_prepare_post
ebuild_configure_pre
ebuild_configure_fail
ebuild_configure_post
ebuild_compile_pre
ebuild_compile_fail
ebuild_compile_post
ebuild_install_pre
ebuild_install_fail
ebuild_install_post
ebuild_test_pre
ebuild_test_fail
ebuild_test_post
ebuild_test_expensive_pre
ebuild_test_expensive_fail
ebuild_test_expensive_post
ebuild_pretend_pre
ebuild_pretend_fail
ebuild_pretend_post
ebuild_bad_options_pre
ebuild_bad_options_fail
ebuild_bad_options_post
ebuild_bad_required_use_pre
ebuild_bad_required_use_fail
ebuild_bad_required_use_post
ebuild_setup_pre
ebuild_setup_fail
ebuild_setup_post
ebuild_config_pre
ebuild_config_fail
ebuild_config_post
ebuild_nofetch_pre
ebuild_nofetch_fail
ebuild_nofetch_post
ebuild_preinst_pre
ebuild_preinst_fail
ebuild_preinst_post
ebuild_postinst_pre
ebuild_postinst_fail
ebuild_postinst_post
ebuild_prerm_pre
ebuild_prerm_fail
ebuild_prerm_post
ebuild_postrm_pre
ebuild_postrm_fail
ebuild_postrm_post
ebuild_info_pre
ebuild_info_fail
ebuild_info_post
ebuild_infovars_pre
ebuild_infovars_fail
ebuild_infovars_post
ebuild_pivotbin_pre
ebuild_pivotbin_fail
ebuild_pivotbin_post
ebuild_installbin_pre
ebuild_installbin_fail
ebuild_installbin_post
ebuild_saveenv_pre
ebuild_saveenv_fail
ebuild_saveenv_post
ebuild_loadenv_pre
ebuild_loadenv_fail
ebuild_loadenv_post
ebuild_killold_pre
ebuild_killold_fail
ebuild_killold_post
ebuild_tidyup_pre
ebuild_tidyup_fail
ebuild_tidyup_post
These are called before and after the corresponding src_
,
pkg_
or builtin_
phase functions (in particular,
note src_configure
versus pkg_config
).
As well as the full ebuild environment, the HOOK
environment
variable will contain the name of the hook being called. The
PALUDIS_CMDLINE
variables described below are also available.
Ebuild hooks will not necessarily be called if an ebuild does not define the function in question.
Ebuild Message Hooks
The following ebuild message hooks are available:
einfo
ewarn
eerror
elog
The HOOK
environment variable will contain the name of the hook
being called, and the MESSAGE
environment variable will contain
the message being passed to the function. The PALUDIS_CMDLINE
variables described below are also available.
Merger / Unmerger Hooks
The merger runs in two stages, for safety. First it checks that it can probably install safely, then it does the actual install. Note that calculating the md5, timestamp etc for VDB CONTENTS is done after the install_post hooks are called.
In each of the following subcategories, the hooks that do not name a specific type of object are called before or after the entire process; those that do are called once for each relevant item.
The following merger check hooks are available:
merger_check_pre
merger_check_post
merger_check_file_pre
merger_check_file_post
merger_check_sym_pre
merger_check_sym_post
merger_check_dir_pre
merger_check_dir_post
The INSTALL_SOURCE
and INSTALL_DESTINATION
environment variables contain the target source and destination. The
ROOT
variable contains the filesystem root. The IMAGE
variable contains the image root.
The following merger hooks are available:
merger_install_pre
merger_install_post
merger_install_file_pre
merger_install_file_post
merger_install_sym_pre
merger_install_sym_post
merger_install_dir_pre
merger_install_dir_post
merger_unlink_file_pre
merger_unlink_file_post
merger_unlink_dir_pre
merger_unlink_dir_post
merger_unlink_sym_pre
merger_unlink_sym_post
merger_unlink_misc_pre
merger_unlink_misc_post
Again, ROOT
and IMAGE
are available. For
install hooks, INSTALL_SOURCE
, INSTALL_DESTINATION
are
set, and for uninstall hooks, UNLINK_TARGET
.
The unmerger hooks are used for uninstalling a package, but not when existing things have to be removed for an install (the merger does that). The following unmerger hooks are available:
unmerger_unlink_pre
unmerger_unlink_post
unmerger_unlink_file_pre
unmerger_unlink_file_post
unmerger_unlink_dir_pre
unmerger_unlink_dir_post
unmerger_unlink_sym_pre
unmerger_unlink_sym_post
unmerger_unlink_misc_pre
unmerger_unlink_misc_post
The UNLINK_TARGET
environment variable specifies the file about
to be unlinked, and ROOT
is the filesystem root.
User Defined Hooks
User defined hooks should be files named *.bash
, *.hook
,
*.py
or *.so
. .bash
and .hook
scripts should be executable (chmod a+x
). They can live in three locations
(or be symlinked there, to allow a single script to be shared between hooks):
confdir/hooks/hookname/
, whereconfdir
is the directory in whichuse.conf
et al. reside.DATADIR/paludis/hooks/hookname/
. On most systems,DATADIR
is/usr/share
.LIBEXECDIR/paludis/hooks/hookname/
. On most systems,LIBEXECDIR
is/usr/libexec
.
For .hook
and .so
hooks, rather than using hookname
, the
auto
directory may be used. In this case, Paludis will ask the hook for which hook names it should be
run.
Bash Hooks
A .bash
hook is merely executed when the associated action is
triggered. There is no guarantee as to execution order.
Hook Hooks
A .hook
hook is more powerful. It must not run anything in
global scope, but instead defines all its actions in functions. It must, at
minimum, define a function called hook_run_$HOOK
for each hook
that it can handle. It may also define functions called hook_depend_$HOOK
,
which should output names of any other hooks upon which it depends, and
hook_after_$HOOK
, which is similar but indicates an ordering
rather than hard dependency (the named hooks not existing is not an error).
For example:
#!/usr/bin/env bash hook_run_install_all_post() { # ensure that einfo etc are available export PATH="$(${PALUDIS_EBUILD_DIR}/utils/canonicalise ${PALUDIS_EBUILD_DIR}/utils/ ):${PATH}" source ${PALUDIS_EBUILD_DIR}/echo_functions.bash echo einfo "Checking for monkeys..." if [[ -d "${ROOT}/var/lib/monkeys" ]] ; then for m in "${ROOT}"/var/lib/monkeys/* ; do ewarn "Found monkey $(basename "${m}" )" done else einfo "No monkeys found" fi } hook_depend_install_all_post() { # we need to run after the Paludis standard eselect_env_update hook echo eselect_env_update } hook_after_install_all_post() { # if checking for rabbits or squirrels, do those first echo check_for_rabbits check_for_squirrels }
If the hook is located in an auto
directory, the hook_auto_names
function must also be
provided. This function should output the hook names under which the hook should be run. For example:
hook_auto_names() { echo install_all_pre install_all_post }
Note that the hook_depend_
, hook_after_
and hook_auto_names
functions are
cached, and are generally only called once per session, so the output should not vary based upon outside parameters.
Python Hooks
A .py
hook is much like .hook
hook, but written
in Python and with full access to the current Paludis environment through
Python bindings. For each hook it can handle it must, at minimum, define
a function named hook_run_$HOOK
which accepts exactly two positional
arguments: the current Environment used by Paludis, and the additional Hook environment variables
represented by a Python dictionary. It may also define the hook_depend_$HOOK
and hook_after_$HOOK
functions which must take exactly one argument,
the Hook environment, and return a list of strings.
For example:
def hook_run_install_all_post(env, hook_env): from paludis import * print "* Checking for monkeys..." if list(env[Selection.SomeArbitraryVersion(Generator.Package("nice/monkey"))]): print "Found a monkey!" else: print "No monkeys found" def hook_depend_install_all_post(hook_env): # we need to run after the Paludis standard eselect_env_update hook return ["eselect_env_update"] def hook_after_install_all_post(hook_env): # if checking for rabbits or squirrels, do those first return ["check_for_rabbits", "check_for_squirrels"]
.so Hooks
A .so
hook is written in C++ and has full access to the Paludis public API.
The hook takes the form of a shared library with a filename ending in .so.N
,
where N is the first component of the Paludis version number multiplied by 100,
plus the second component of the version number (for example, 26 for Paludis 0.26.x,
or 102 for Paludis 1.2.y). The library must export a function with prototype
paludis::HookResult paludis_hook_run_3(const paludis::Environment *,
const paludis::Hook &, const std::shared_ptr<paludis::OutputManager> &)
that performs the action, and optionally one with prototype
void paludis_hook_add_dependencies(const paludis::Environment *, const paludis::Hook &,
paludis::DirectedGraph<std::string, int> &)
if it needs to define ordering dependencies with other hooks. If the hook is to be placed in an auto
directory, it must also define const std::tr1::shared_ptr<const Sequence<std::string> >
paludis_hook_auto_phases(const paludis::Environment *)
. All functions are
declared in the header <paludis/hook.hh>
, including any necessary
extern
or visibility declarations.
The parameters and return values have the following meanings:
const paludis::Environment *
- The usual
Environment
, as used by all Paludis clients. const paludis::Hook &
- Contains information about the hook being called. In
paludis_hook_add_dependencies
, the only useful member isname()
. const std::shared_ptr<paludis::OutputManager> &
- The output manager being used when the hook is run. Will sometimes be a null pointer, as not all hooks are run with output managed -- in this case, use of stdout is normal.
paludis::DirectedGraph<std::string, int> &
- A graph containing, as nodes, all named hooks that will be executed along with
this one. The
paludis_hook_add_dependencies
function should add any edges required to indicate its desired execution order relative to the other hooks, as follows:g.add_edge("after", "before", 0);
(the 0 is not significant, but required by theDirectedGraph
API). paludis::HookResult
- The
HookResult
constructor takes two arguments: anint
, which should be zero if the hook is successful, or positive if not, and astd::string
containing any information that should be passed back to the hook's caller (only used if theHook
'soutput_dest
member ishod_grab
).
Package Manager Defined Hooks
Paludis places some of its own hooks in
LIBEXECDIR/hooks/hookname
. These directories are
not for end user use.
The PALUDIS_CMDLINE
Variables
Sometimes hooks need access to the commandline used to invoke
paludis
. However, manual parsing of the commandline by hooks will
lead to bugs when people forget to emulate certain behaviour (say, short
options, aliases or --
support). To work around this issue,
Paludis provides environment variables prefixed PALUDIS_CMDLINE_
that specify the parsed command line:
- The
PALUDIS_CMDLINE_PARAMS
variable contains the parameters (that is, the parts that aren't-x
or--blah
or values for these). - For each
--param-name
,PALUDIS_CMDLINE_param_name
(note the case and the underscores) is set. If--param-name
takes an argument, this argument is used for the environment variable's value. - For short options (
-x
) and aliases, the appropriate long option's variable is set instead.