hgbook
changeset 38:b49a7dd4e564
More content for hook chapter.
Overview of hooks.
Description of hook security implications.
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