hgbook

changeset 38:b49a7dd4e564

More content for hook chapter.
Overview of hooks.
Description of hook security implications.
author Bryan O'Sullivan <bos@serpentine.com>
date Wed Jul 19 00:06:21 2006 -0700 (2006-07-19)
parents 9fd0c59b009a
children 576fef93bb49
files en/99defs.tex en/hook.tex
line diff
     1.1 --- a/en/99defs.tex	Mon Jul 17 00:01:01 2006 -0700
     1.2 +++ b/en/99defs.tex	Wed Jul 19 00:06:21 2006 -0700
     1.3 @@ -1,5 +1,8 @@
     1.4  % Bug ID.
     1.5 -\newcommand{\bug}[1]{\index{Mercurial issue!no.~#1}\href{http://www.selenic.com/mercurial/bts/issue#1}{Mercurial issue no.~#1}}
     1.6 +\newcommand{\bug}[1]{\index{Mercurial bug
     1.7 +    database!\href{http://www.selenic.com/mercurial/bts/issue#1}{bug
     1.8 +      ~#1}}\href{http://www.selenic.com/mercurial/bts/issue#1}{Mercurial
     1.9 +    bug no.~#1}}
    1.10  
    1.11  % File name in the user's home directory.
    1.12  \newcommand{\tildefile}[1]{\texttt{\~{}/#1}}
     2.1 --- a/en/hook.tex	Mon Jul 17 00:01:01 2006 -0700
     2.2 +++ b/en/hook.tex	Wed Jul 19 00:06:21 2006 -0700
     2.3 @@ -9,6 +9,175 @@
     2.4  Hooks are called ``triggers'' in some revision control systems, but
     2.5  the two names refer to the same idea.
     2.6  
     2.7 +\section{An overview of hooks in Mercurial}
     2.8 +
     2.9 +Here is a brief list of the hooks that Mercurial supports. For each
    2.10 +hook, we indicate when it is run, and a few examples of common tasks
    2.11 +you can use it for.  We will revisit each of these hooks in more
    2.12 +detail later.
    2.13 +\begin{itemize}
    2.14 +\item[\small\hook{changegroup}] This is run after a group of
    2.15 +  changesets has been brought into the repository from elsewhere.  In
    2.16 +  other words, it is run after a \hgcmd{pull} or \hgcmd{push} into a
    2.17 +  repository, but not after a \hgcmd{commit}.  You can use this for
    2.18 +  performing an action once for the entire group of newly arrived
    2.19 +  changesets.  For example, you could use this hook to send out email
    2.20 +  notifications, or kick off an automated build or test.
    2.21 +\item[\small\hook{commit}] This is run after a new changeset has been
    2.22 +  created in the local repository, typically using the \hgcmd{commit}
    2.23 +  command.
    2.24 +\item[\small\hook{incoming}] This is run once for each new changeset
    2.25 +  that is brought into the repository from elsewhere.  Notice the
    2.26 +  difference from \hook{changegroup}, which is run once per
    2.27 +  \emph{group} of changesets brought in.  You can use this for the
    2.28 +  same purposes as the \hook{changegroup} hook; it's simply more
    2.29 +  convenient sometimes to run a hook once per group of changesets,
    2.30 +  while othher times it's handier once per changeset.
    2.31 +\item[\small\hook{outgoing}] This is run after a group of changesets
    2.32 +  has been transmitted from this repository to another.  You can use
    2.33 +  this, for example, to notify subscribers every time changes are
    2.34 +  cloned or pulled from the repository.
    2.35 +\item[\small\hook{prechangegroup}] This is run before starting to
    2.36 +  bring a group of changesets into the repository.  It cannot see the
    2.37 +  actual changesets, because they have not yet been transmitted.  If
    2.38 +  it fails, the changesets will not be transmitted.  You can use this
    2.39 +  hook to ``lock down'' a repository against incoming changes.
    2.40 +\item[\small\hook{precommit}] This is run before starting a commit.
    2.41 +  It cannot tell what files are included in the commit, or any other
    2.42 +  information about the commit.  If it fails, the commit will not be
    2.43 +  allowed to start.  You can use this to perform a build and require
    2.44 +  it to complete successfully before a commit can proceed, or
    2.45 +  automatically enforce a requirement that modified files pass your
    2.46 +  coding style guidelines.
    2.47 +\item[\small\hook{preoutgoing}] This is run before starting to
    2.48 +  transmit a group of changesets from this repository.  You can use
    2.49 +  this to lock a repository against clones or pulls from remote
    2.50 +  clients.
    2.51 +\item[\small\hook{pretag}] This is run before creating a tag.  If it
    2.52 +  fails, the tag will not be created.  You can use this to enforce a
    2.53 +  uniform tag naming convention.
    2.54 +\item[\small\hook{pretxnchangegroup}] This is run after a group of
    2.55 +  changesets has been brought into the local repository from another,
    2.56 +  but before the transaction completes that will make the changes
    2.57 +  permanent in the repository.  If it fails, the transaction will be
    2.58 +  rolled back and the changes will disappear from the local
    2.59 +  repository.  You can use this to automatically check newly arrived
    2.60 +  changes and, for example, roll them back if the group as a whole
    2.61 +  does not build or pass your test suite.
    2.62 +\item[\small\hook{pretxncommit}] This is run after a new changeset has
    2.63 +  been created in the local repository, but before the transaction
    2.64 +  completes that will make it permanent.  Unlike the \hook{precommit}
    2.65 +  hook, this hook can see which changes are present in the changeset,
    2.66 +  and it can also see all other changeset metadata, such as the commit
    2.67 +  message.  You can use this to require that a commit message follows
    2.68 +  your local conventions, or that a changeset builds cleanly.
    2.69 +\item[\small\hook{preupdate}] This is run before starting an update or
    2.70 +  merge of the working directory.
    2.71 +\item[\small\hook{tag}] This is run after a tag is created.
    2.72 +\item[\small\hook{update}] This is run after an update or merge of the
    2.73 +  working directory has finished.
    2.74 +\end{itemize}
    2.75 +Each of the hooks with a ``\texttt{pre}'' prefix has the ability to
    2.76 +\emph{control} an activity.  If the hook succeeds, the activity may
    2.77 +proceed; if it fails, the activity is either not permitted or undone,
    2.78 +depending on the hook.
    2.79 +
    2.80 +\section{Hooks and security}
    2.81 +
    2.82 +\subsection{Hooks are run with your privileges}
    2.83 +
    2.84 +When you run a Mercurial command in a repository, and the command
    2.85 +causes a hook to run, that hook runs on your system, under your user
    2.86 +account, with your privilege level.  Since hooks are arbitrary pieces
    2.87 +of executable code, you should treat them with an appropriate level of
    2.88 +suspicion.  Do not install a hook unless you are confident that you
    2.89 +know who created it and what it does.
    2.90 +
    2.91 +In some cases, you may be exposed to hooks that you did not install
    2.92 +yourself.  If you work with Mercurial on an unfamiliar system,
    2.93 +Mercurial will run hooks defined in that system's global \hgrc\ file.
    2.94 +
    2.95 +If you are working with a repository owned by another user, Mercurial
    2.96 +will run hooks defined in that repository.  For example, if you
    2.97 +\hgcmd{pull} from that repository, and its \sfilename{.hg/hgrc}
    2.98 +defines a local \hook{outgoing} hook, that hook will run under your
    2.99 +user account, even though you don't own that repository.
   2.100 +
   2.101 +\begin{note}
   2.102 +  This only applies if you are pulling from a repository on a local or
   2.103 +  network filesystem.  If you're pulling over http or ssh, any
   2.104 +  \hook{outgoing} hook will run under the account of the server
   2.105 +  process, on the server.
   2.106 +\end{note}
   2.107 +
   2.108 +XXX To see what hooks are defined in a repository, use the
   2.109 +\hgcmdargs{config}{hooks} command.  If you are working in one
   2.110 +repository, but talking to another that you do not own (e.g.~using
   2.111 +\hgcmd{pull} or \hgcmd{incoming}), remember that it is the other
   2.112 +repository's hooks you should be checking, not your own.
   2.113 +
   2.114 +\subsection{Hooks do not propagate}
   2.115 +
   2.116 +In Mercurial, hooks are not revision controlled, and do not propagate
   2.117 +when you clone, or pull from, a repository.  The reason for this is
   2.118 +simple: a hook is a completely arbitrary piece of executable code.  It
   2.119 +runs under your user identity, with your privilege level, on your
   2.120 +machine.
   2.121 +
   2.122 +It would be extremely reckless for any distributed revision control
   2.123 +system to implement revision-controlled hooks, as this would offer an
   2.124 +easily exploitable way to subvert the accounts of users of the
   2.125 +revision control system.
   2.126 +
   2.127 +Since Mercurial does not propagate hooks, if you are collaborating
   2.128 +with other people on a common project, you should not assume that they
   2.129 +are using the same Mercurial hooks as you are, or that theirs are
   2.130 +correctly configured.  You should document the hooks you expect people
   2.131 +to use.
   2.132 +
   2.133 +In a corporate intranet, this is somewhat easier to control, as you
   2.134 +can for example provide a ``standard'' installation of Mercurial on an
   2.135 +NFS filesystem, and use a site-wide \hgrc\ file to define hooks that
   2.136 +all users will see.  However, this too has its limits; see below.
   2.137 +
   2.138 +\subsection{Hooks can be overridden}
   2.139 +
   2.140 +Mercurial allows you to override a hook definition by redefining the
   2.141 +hook.  You can disable it by setting its value to the empty string, or
   2.142 +change its behaviour as you wish.
   2.143 +
   2.144 +If you deploy a system-~or site-wide \hgrc\ file that defines some
   2.145 +hooks, you should thus understand that your users can disable or
   2.146 +override those hooks.
   2.147 +
   2.148 +\subsection{Ensuring that critical hooks are run}
   2.149 +
   2.150 +Sometimes you may want to enforce a policy that you do not want others
   2.151 +to be able to work around.  For example, you may have a requirement
   2.152 +that every changeset must pass a rigorous set of tests.  Defining this
   2.153 +requirement via a hook in a site-wide \hgrc\ won't work for remote
   2.154 +users on laptops, and of course local users can subvert it at will by
   2.155 +overriding the hook.
   2.156 +
   2.157 +Instead, you can set up your policies for use of Mercurial so that
   2.158 +people are expected to propagate changes through a well-known
   2.159 +``canonical'' server that you have locked down and configured
   2.160 +appropriately.
   2.161 +
   2.162 +One way to do this is via a combination of social engineering and
   2.163 +technology.  Set up a restricted-access account; users can push
   2.164 +changes over the network to repositories managed by this account, but
   2.165 +they cannot log into the account and run normal shell commands.  In
   2.166 +this scenario, a user can commit a changeset that contains any old
   2.167 +garbage they want.
   2.168 +
   2.169 +When someone pushes a changeset to the server that everyone pulls
   2.170 +from, the server will test the changeset before it accepts it as
   2.171 +permanent, and reject it if it fails to pass the test suite.  If
   2.172 +people only pull changes from this filtering server, it will serve to
   2.173 +ensure that all changes that people pull have been automatically
   2.174 +vetted.
   2.175 +
   2.176  \section{A short tutorial on using hooks}
   2.177  \label{sec:hook:simple}
   2.178