Mercurial > hgbook
diff en/hook.tex @ 37:9fd0c59b009a
Add to hook chapter.
Document each macro in 99defs.tex.
author | Bryan O'Sullivan <bos@serpentine.com> |
---|---|
date | Mon, 17 Jul 2006 00:01:01 -0700 |
parents | c0979ed1eabd |
children | b49a7dd4e564 |
line wrap: on
line diff
--- a/en/hook.tex Mon Jul 17 00:00:12 2006 -0700 +++ b/en/hook.tex Mon Jul 17 00:01:01 2006 -0700 @@ -95,11 +95,18 @@ comment contains a bug ID. If it does, the commit can complete. If not, the commit is rolled back. -\section{Choosing how to write a hook} -\label{sec:hook:impl} +\section{Writing your own hooks} + +When you are writing a hook, you might find it useful to run Mercurial +either with the \hggopt{-v} option, or the \rcitem{ui}{verbose} config +item set to ``true''. When you do so, Mercurial will print a message +before it calls each hook. + +\subsection{Choosing how your hook should run} +\label{sec:hook:lang} You can write a hook either as a normal program---typically a shell -script---or as a Python function that is called within the Mercurial +script---or as a Python function that is executed within the Mercurial process. Writing a hook as an external program has the advantage that it @@ -119,7 +126,7 @@ performance (probably the majority of hooks), a shell script is perfectly fine. -\section{Hook parameters} +\subsection{Hook parameters} \label{sec:hook:param} Mercurial calls each hook with a set of well-defined parameters. In @@ -128,9 +135,82 @@ environment variable. Whether your hook is written in Python or as a shell script, the -parameter names and values will be the same. A boolean parameter will -be represented as a boolean value in Python, but as the number 1 (for -``true'') or 0 (for ``false'') +hook-specific parameter names and values will be the same. A boolean +parameter will be represented as a boolean value in Python, but as the +number 1 (for ``true'') or 0 (for ``false'') as an environment +variable for an external hook. If a hook parameter is named +\texttt{foo}, the keyword argument for a Python hook will also be +named \texttt{foo} Python, while the environment variable for an +external hook will be named \texttt{HG\_FOO}. + +\subsection{Hook return values and activity control} + +A hook that executes successfully must exit with a status of zero if +external, or return boolean ``false'' if in-process. Failure is +indicated with a non-zero exit status from an external hook, or an +in-process hook returning boolean ``true''. If an in-process hook +raises an exception, the hook is considered to have failed. + +For a hook that controls whether an activity can proceed, zero/false +means ``allow'', while non-zero/true/exception means ``deny''. + +\subsection{Writing an external hook} + +When you define an external hook in your \hgrc\ and the hook is run, +its value is passed to your shell, which interprets it. This means +that you can use normal shell constructs in the body of the hook. + +An executable hook is always run with its current directory set to a +repository's root directory. + +Each hook parameter is passed in as an environment variable; the name +is upper-cased, and prefixed with the string ``\texttt{HG\_}''. + +With the exception of hook parameters, Mercurial does not set or +modify any environment variables when running a hook. This is useful +to remember if you are writing a site-wide hook that may be run by a +number of different users with differing environment variables set. +In multi-user situations, you should not rely on environment variables +being set to the values you have in your environment when testing the +hook. + +\subsection{Telling Mercurial to use an in-process hook} + +The \hgrc\ syntax for defining an in-process hook is slightly +different than for an executable hook. The value of the hook must +start with the text ``\texttt{python:}'', and continue with the +fully-qualified name of a callable object to use as the hook's value. + +The module in which a hook lives is automatically imported when a hook +is run. So long as you have the module name and \envar{PYTHONPATH} +right, it should ``just work''. + +The following \hgrc\ example snippet illustrates the syntax and +meaning of the notions we just described. +\begin{codesample2} + [hooks] + commit.example = python:mymodule.submodule.myhook +\end{codesample2} +When Mercurial runs the \texttt{commit.example} hook, it imports +\texttt{mymodule.submodule}, looks for the callable object named +\texttt{myhook}, and calls it. + +\subsection{Writing an in-process hook} + +The simplest in-process hook does nothing, but illustrates the basic +shape of the hook API: +\begin{codesample2} + def myhook(ui, repo, **kwargs): + pass +\end{codesample2} +The first argument to a Python hook is always a +\pymodclass{mercurial.ui}{ui} object. The second is a repository object; +at the moment, it is always an instance of +\pymodclass{mercurial.localrepo}{localrepository}. Following these two +arguments are other keyword arguments. Which ones are passed in +depends on the hook being called, but a hook can ignore arguments it +doesn't care about by dropping them into a keyword argument dict, as +with \texttt{**kwargs} above. %%% Local Variables: