Paludis Logo Introduction Hooks general.conf bashrc
Bugs, Requests, Support Syncers keywords.conf / platforms.conf suggestions.conf
Overview Fetchers use.conf / options.conf sets/
FAQ Env Vars licenses.conf / licences.conf repositories/
Clients File Formats mirrors.conf  
Configuration Dep Specs output.conf  
API specpath.conf package_mask.conf  

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:

There are currently five categories of hook execution code:

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:

In general, certain special environment variables will be set:

Ebuild Phase Hooks

The following ebuild phase hooks are available:

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:

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:

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:

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:

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):

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 is name().
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 the DirectedGraph API).
paludis::HookResult
The HookResult constructor takes two arguments: an int, which should be zero if the hook is successful, or positive if not, and a std::string containing any information that should be passed back to the hook's caller (only used if the Hook's output_dest member is hod_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: