hgbook
annotate en/hook.tex @ 307:fb5c0d56d7f1
Fix test 'tour'.
Executing 'tour' test now creates some files in /tmp to store the
revision numbers as they are created on the fly and appear in the output
files. When SVG files are to be converted to PNG or EPS files within the
Makefile, a tool 'fixsvg' will be invoked to substitute some placeholder
markup by the real version number which fits to the test output, before
the final conversion takes place.
Executing 'tour' test now creates some files in /tmp to store the
revision numbers as they are created on the fly and appear in the output
files. When SVG files are to be converted to PNG or EPS files within the
Makefile, a tool 'fixsvg' will be invoked to substitute some placeholder
markup by the real version number which fits to the test output, before
the final conversion takes place.
author | Guido Ostkamp <hg@ostkamp.fastmail.fm> |
---|---|
date | Wed Aug 20 22:15:35 2008 +0200 (2008-08-20) |
parents | 5f35a333ab9b |
children | a168daed199b |
rev | line source |
---|---|
bos@34 | 1 \chapter{Handling repository events with hooks} |
bos@34 | 2 \label{chap:hook} |
bos@34 | 3 |
bos@34 | 4 Mercurial offers a powerful mechanism to let you perform automated |
bos@34 | 5 actions in response to events that occur in a repository. In some |
bos@34 | 6 cases, you can even control Mercurial's response to those events. |
bos@34 | 7 |
bos@34 | 8 The name Mercurial uses for one of these actions is a \emph{hook}. |
bos@34 | 9 Hooks are called ``triggers'' in some revision control systems, but |
bos@34 | 10 the two names refer to the same idea. |
bos@34 | 11 |
bos@38 | 12 \section{An overview of hooks in Mercurial} |
bos@38 | 13 |
bos@41 | 14 Here is a brief list of the hooks that Mercurial supports. We will |
bos@41 | 15 revisit each of these hooks in more detail later, in |
bos@41 | 16 section~\ref{sec:hook:ref}. |
bos@41 | 17 |
bos@38 | 18 \begin{itemize} |
bos@38 | 19 \item[\small\hook{changegroup}] This is run after a group of |
bos@41 | 20 changesets has been brought into the repository from elsewhere. |
bos@38 | 21 \item[\small\hook{commit}] This is run after a new changeset has been |
bos@41 | 22 created in the local repository. |
bos@38 | 23 \item[\small\hook{incoming}] This is run once for each new changeset |
bos@38 | 24 that is brought into the repository from elsewhere. Notice the |
bos@38 | 25 difference from \hook{changegroup}, which is run once per |
bos@41 | 26 \emph{group} of changesets brought in. |
bos@38 | 27 \item[\small\hook{outgoing}] This is run after a group of changesets |
bos@41 | 28 has been transmitted from this repository. |
bos@38 | 29 \item[\small\hook{prechangegroup}] This is run before starting to |
bos@41 | 30 bring a group of changesets into the repository. |
bos@41 | 31 \item[\small\hook{precommit}] Controlling. This is run before starting |
bos@41 | 32 a commit. |
bos@41 | 33 \item[\small\hook{preoutgoing}] Controlling. This is run before |
bos@41 | 34 starting to transmit a group of changesets from this repository. |
bos@41 | 35 \item[\small\hook{pretag}] Controlling. This is run before creating a tag. |
bos@41 | 36 \item[\small\hook{pretxnchangegroup}] Controlling. This is run after a |
bos@41 | 37 group of changesets has been brought into the local repository from |
bos@41 | 38 another, but before the transaction completes that will make the |
bos@41 | 39 changes permanent in the repository. |
bos@41 | 40 \item[\small\hook{pretxncommit}] Controlling. This is run after a new |
bos@41 | 41 changeset has been created in the local repository, but before the |
bos@41 | 42 transaction completes that will make it permanent. |
bos@41 | 43 \item[\small\hook{preupdate}] Controlling. This is run before starting |
bos@41 | 44 an update or merge of the working directory. |
bos@38 | 45 \item[\small\hook{tag}] This is run after a tag is created. |
bos@38 | 46 \item[\small\hook{update}] This is run after an update or merge of the |
bos@38 | 47 working directory has finished. |
bos@38 | 48 \end{itemize} |
bos@41 | 49 Each of the hooks whose description begins with the word |
bos@41 | 50 ``Controlling'' has the ability to determine whether an activity can |
bos@41 | 51 proceed. If the hook succeeds, the activity may proceed; if it fails, |
bos@41 | 52 the activity is either not permitted or undone, depending on the hook. |
bos@38 | 53 |
bos@38 | 54 \section{Hooks and security} |
bos@38 | 55 |
bos@38 | 56 \subsection{Hooks are run with your privileges} |
bos@38 | 57 |
bos@38 | 58 When you run a Mercurial command in a repository, and the command |
bos@41 | 59 causes a hook to run, that hook runs on \emph{your} system, under |
bos@41 | 60 \emph{your} user account, with \emph{your} privilege level. Since |
bos@41 | 61 hooks are arbitrary pieces of executable code, you should treat them |
bos@41 | 62 with an appropriate level of suspicion. Do not install a hook unless |
bos@41 | 63 you are confident that you know who created it and what it does. |
bos@38 | 64 |
bos@38 | 65 In some cases, you may be exposed to hooks that you did not install |
bos@38 | 66 yourself. If you work with Mercurial on an unfamiliar system, |
bos@38 | 67 Mercurial will run hooks defined in that system's global \hgrc\ file. |
bos@38 | 68 |
bos@38 | 69 If you are working with a repository owned by another user, Mercurial |
bos@41 | 70 can run hooks defined in that user's repository, but it will still run |
bos@41 | 71 them as ``you''. For example, if you \hgcmd{pull} from that |
bos@41 | 72 repository, and its \sfilename{.hg/hgrc} defines a local |
bos@41 | 73 \hook{outgoing} hook, that hook will run under your user account, even |
bos@41 | 74 though you don't own that repository. |
bos@38 | 75 |
bos@38 | 76 \begin{note} |
bos@38 | 77 This only applies if you are pulling from a repository on a local or |
bos@38 | 78 network filesystem. If you're pulling over http or ssh, any |
bos@41 | 79 \hook{outgoing} hook will run under whatever account is executing |
bos@41 | 80 the server process, on the server. |
bos@38 | 81 \end{note} |
bos@38 | 82 |
bos@38 | 83 XXX To see what hooks are defined in a repository, use the |
bos@38 | 84 \hgcmdargs{config}{hooks} command. If you are working in one |
bos@38 | 85 repository, but talking to another that you do not own (e.g.~using |
bos@38 | 86 \hgcmd{pull} or \hgcmd{incoming}), remember that it is the other |
bos@38 | 87 repository's hooks you should be checking, not your own. |
bos@38 | 88 |
bos@38 | 89 \subsection{Hooks do not propagate} |
bos@38 | 90 |
bos@38 | 91 In Mercurial, hooks are not revision controlled, and do not propagate |
bos@38 | 92 when you clone, or pull from, a repository. The reason for this is |
bos@38 | 93 simple: a hook is a completely arbitrary piece of executable code. It |
bos@38 | 94 runs under your user identity, with your privilege level, on your |
bos@38 | 95 machine. |
bos@38 | 96 |
bos@38 | 97 It would be extremely reckless for any distributed revision control |
bos@38 | 98 system to implement revision-controlled hooks, as this would offer an |
bos@38 | 99 easily exploitable way to subvert the accounts of users of the |
bos@38 | 100 revision control system. |
bos@38 | 101 |
bos@38 | 102 Since Mercurial does not propagate hooks, if you are collaborating |
bos@38 | 103 with other people on a common project, you should not assume that they |
bos@38 | 104 are using the same Mercurial hooks as you are, or that theirs are |
bos@38 | 105 correctly configured. You should document the hooks you expect people |
bos@38 | 106 to use. |
bos@38 | 107 |
bos@38 | 108 In a corporate intranet, this is somewhat easier to control, as you |
bos@38 | 109 can for example provide a ``standard'' installation of Mercurial on an |
bos@38 | 110 NFS filesystem, and use a site-wide \hgrc\ file to define hooks that |
bos@38 | 111 all users will see. However, this too has its limits; see below. |
bos@38 | 112 |
bos@38 | 113 \subsection{Hooks can be overridden} |
bos@38 | 114 |
bos@38 | 115 Mercurial allows you to override a hook definition by redefining the |
bos@38 | 116 hook. You can disable it by setting its value to the empty string, or |
bos@38 | 117 change its behaviour as you wish. |
bos@38 | 118 |
bos@38 | 119 If you deploy a system-~or site-wide \hgrc\ file that defines some |
bos@38 | 120 hooks, you should thus understand that your users can disable or |
bos@38 | 121 override those hooks. |
bos@38 | 122 |
bos@38 | 123 \subsection{Ensuring that critical hooks are run} |
bos@38 | 124 |
bos@38 | 125 Sometimes you may want to enforce a policy that you do not want others |
bos@38 | 126 to be able to work around. For example, you may have a requirement |
bos@38 | 127 that every changeset must pass a rigorous set of tests. Defining this |
bos@38 | 128 requirement via a hook in a site-wide \hgrc\ won't work for remote |
bos@38 | 129 users on laptops, and of course local users can subvert it at will by |
bos@38 | 130 overriding the hook. |
bos@38 | 131 |
bos@38 | 132 Instead, you can set up your policies for use of Mercurial so that |
bos@38 | 133 people are expected to propagate changes through a well-known |
bos@38 | 134 ``canonical'' server that you have locked down and configured |
bos@38 | 135 appropriately. |
bos@38 | 136 |
bos@38 | 137 One way to do this is via a combination of social engineering and |
bos@38 | 138 technology. Set up a restricted-access account; users can push |
bos@38 | 139 changes over the network to repositories managed by this account, but |
bos@38 | 140 they cannot log into the account and run normal shell commands. In |
bos@38 | 141 this scenario, a user can commit a changeset that contains any old |
bos@38 | 142 garbage they want. |
bos@38 | 143 |
bos@38 | 144 When someone pushes a changeset to the server that everyone pulls |
bos@38 | 145 from, the server will test the changeset before it accepts it as |
bos@38 | 146 permanent, and reject it if it fails to pass the test suite. If |
bos@38 | 147 people only pull changes from this filtering server, it will serve to |
bos@38 | 148 ensure that all changes that people pull have been automatically |
bos@38 | 149 vetted. |
bos@38 | 150 |
bos@134 | 151 \section{Care with \texttt{pretxn} hooks in a shared-access repository} |
bos@41 | 152 |
wbunaarfubss@247 | 153 If you want to use hooks to do some automated work in a repository |
bos@54 | 154 that a number of people have shared access to, you need to be careful |
bos@41 | 155 in how you do this. |
bos@41 | 156 |
bos@41 | 157 Mercurial only locks a repository when it is writing to the |
bos@41 | 158 repository, and only the parts of Mercurial that write to the |
bos@41 | 159 repository pay attention to locks. Write locks are necessary to |
bos@41 | 160 prevent multiple simultaneous writers from scribbling on each other's |
bos@41 | 161 work, corrupting the repository. |
bos@41 | 162 |
bos@41 | 163 Because Mercurial is careful with the order in which it reads and |
bos@41 | 164 writes data, it does not need to acquire a lock when it wants to read |
bos@41 | 165 data from the repository. The parts of Mercurial that read from the |
bos@41 | 166 repository never pay attention to locks. This lockless reading scheme |
bos@41 | 167 greatly increases performance and concurrency. |
bos@41 | 168 |
bos@41 | 169 With great performance comes a trade-off, though, one which has the |
bos@41 | 170 potential to cause you trouble unless you're aware of it. To describe |
bos@41 | 171 this requires a little detail about how Mercurial adds changesets to a |
bos@41 | 172 repository and reads those changes. |
bos@41 | 173 |
bos@41 | 174 When Mercurial \emph{writes} metadata, it writes it straight into the |
bos@41 | 175 destination file. It writes file data first, then manifest data |
bos@41 | 176 (which contains pointers to the new file data), then changelog data |
bos@41 | 177 (which contains pointers to the new manifest data). Before the first |
bos@41 | 178 write to each file, it stores a record of where the end of the file |
bos@41 | 179 was in its transaction log. If the transaction must be rolled back, |
bos@54 | 180 Mercurial simply truncates each file back to the size it was before the |
bos@41 | 181 transaction began. |
bos@41 | 182 |
bos@41 | 183 When Mercurial \emph{reads} metadata, it reads the changelog first, |
bos@41 | 184 then everything else. Since a reader will only access parts of the |
bos@41 | 185 manifest or file metadata that it can see in the changelog, it can |
bos@41 | 186 never see partially written data. |
bos@41 | 187 |
bos@41 | 188 Some controlling hooks (\hook{pretxncommit} and |
bos@41 | 189 \hook{pretxnchangegroup}) run when a transaction is almost complete. |
bos@41 | 190 All of the metadata has been written, but Mercurial can still roll the |
bos@41 | 191 transaction back and cause the newly-written data to disappear. |
bos@41 | 192 |
bos@134 | 193 If one of these hooks runs for long, it opens a window of time during |
bos@134 | 194 which a reader can see the metadata for changesets that are not yet |
bos@134 | 195 permanent, and should not be thought of as ``really there''. The |
bos@134 | 196 longer the hook runs, the longer that window is open. |
bos@134 | 197 |
bos@134 | 198 \subsection{The problem illustrated} |
bos@134 | 199 |
bos@134 | 200 In principle, a good use for the \hook{pretxnchangegroup} hook would |
bos@134 | 201 be to automatically build and test incoming changes before they are |
bos@134 | 202 accepted into a central repository. This could let you guarantee that |
bos@134 | 203 nobody can push changes to this repository that ``break the build''. |
bos@134 | 204 But if a client can pull changes while they're being tested, the |
bos@134 | 205 usefulness of the test is zero; an unsuspecting someone can pull |
bos@134 | 206 untested changes, potentially breaking their build. |
bos@134 | 207 |
bos@134 | 208 The safest technological answer to this challenge is to set up such a |
bos@134 | 209 ``gatekeeper'' repository as \emph{unidirectional}. Let it take |
bos@134 | 210 changes pushed in from the outside, but do not allow anyone to pull |
bos@134 | 211 changes from it (use the \hook{preoutgoing} hook to lock it down). |
bos@134 | 212 Configure a \hook{changegroup} hook so that if a build or test |
bos@134 | 213 succeeds, the hook will push the new changes out to another repository |
bos@134 | 214 that people \emph{can} pull from. |
bos@134 | 215 |
bos@134 | 216 In practice, putting a centralised bottleneck like this in place is |
bos@134 | 217 not often a good idea, and transaction visibility has nothing to do |
bos@134 | 218 with the problem. As the size of a project---and the time it takes to |
bos@134 | 219 build and test---grows, you rapidly run into a wall with this ``try |
bos@134 | 220 before you buy'' approach, where you have more changesets to test than |
bos@134 | 221 time in which to deal with them. The inevitable result is frustration |
bos@134 | 222 on the part of all involved. |
bos@134 | 223 |
bos@134 | 224 An approach that scales better is to get people to build and test |
bos@134 | 225 before they push, then run automated builds and tests centrally |
bos@134 | 226 \emph{after} a push, to be sure all is well. The advantage of this |
bos@134 | 227 approach is that it does not impose a limit on the rate at which the |
bos@134 | 228 repository can accept changes. |
bos@41 | 229 |
bos@34 | 230 \section{A short tutorial on using hooks} |
bos@34 | 231 \label{sec:hook:simple} |
bos@34 | 232 |
bos@34 | 233 It is easy to write a Mercurial hook. Let's start with a hook that |
bos@34 | 234 runs when you finish a \hgcmd{commit}, and simply prints the hash of |
bos@34 | 235 the changeset you just created. The hook is called \hook{commit}. |
bos@34 | 236 |
bos@34 | 237 \begin{figure}[ht] |
bos@34 | 238 \interaction{hook.simple.init} |
bos@34 | 239 \caption{A simple hook that runs when a changeset is committed} |
bos@34 | 240 \label{ex:hook:init} |
bos@34 | 241 \end{figure} |
bos@34 | 242 |
bos@34 | 243 All hooks follow the pattern in example~\ref{ex:hook:init}. You add |
bos@34 | 244 an entry to the \rcsection{hooks} section of your \hgrc\. On the left |
bos@34 | 245 is the name of the event to trigger on; on the right is the action to |
bos@34 | 246 take. As you can see, you can run an arbitrary shell command in a |
bos@34 | 247 hook. Mercurial passes extra information to the hook using |
bos@34 | 248 environment variables (look for \envar{HG\_NODE} in the example). |
bos@34 | 249 |
bos@34 | 250 \subsection{Performing multiple actions per event} |
bos@34 | 251 |
bos@34 | 252 Quite often, you will want to define more than one hook for a |
bos@34 | 253 particular kind of event, as shown in example~\ref{ex:hook:ext}. |
bos@34 | 254 Mercurial lets you do this by adding an \emph{extension} to the end of |
bos@34 | 255 a hook's name. You extend a hook's name by giving the name of the |
bos@34 | 256 hook, followed by a full stop (the ``\texttt{.}'' character), followed |
bos@34 | 257 by some more text of your choosing. For example, Mercurial will run |
bos@34 | 258 both \texttt{commit.foo} and \texttt{commit.bar} when the |
bos@34 | 259 \texttt{commit} event occurs. |
bos@34 | 260 |
bos@34 | 261 \begin{figure}[ht] |
bos@34 | 262 \interaction{hook.simple.ext} |
bos@34 | 263 \caption{Defining a second \hook{commit} hook} |
bos@34 | 264 \label{ex:hook:ext} |
bos@34 | 265 \end{figure} |
bos@34 | 266 |
bos@34 | 267 To give a well-defined order of execution when there are multiple |
bos@34 | 268 hooks defined for an event, Mercurial sorts hooks by extension, and |
bos@34 | 269 executes the hook commands in this sorted order. In the above |
bos@34 | 270 example, it will execute \texttt{commit.bar} before |
bos@34 | 271 \texttt{commit.foo}, and \texttt{commit} before both. |
bos@34 | 272 |
bos@34 | 273 It is a good idea to use a somewhat descriptive extension when you |
bos@34 | 274 define a new hook. This will help you to remember what the hook was |
bos@34 | 275 for. If the hook fails, you'll get an error message that contains the |
bos@34 | 276 hook name and extension, so using a descriptive extension could give |
bos@34 | 277 you an immediate hint as to why the hook failed (see |
bos@34 | 278 section~\ref{sec:hook:perm} for an example). |
bos@34 | 279 |
bos@34 | 280 \subsection{Controlling whether an activity can proceed} |
bos@34 | 281 \label{sec:hook:perm} |
bos@34 | 282 |
bos@34 | 283 In our earlier examples, we used the \hook{commit} hook, which is |
bos@34 | 284 run after a commit has completed. This is one of several Mercurial |
bos@34 | 285 hooks that run after an activity finishes. Such hooks have no way of |
bos@34 | 286 influencing the activity itself. |
bos@34 | 287 |
bos@34 | 288 Mercurial defines a number of events that occur before an activity |
bos@34 | 289 starts; or after it starts, but before it finishes. Hooks that |
bos@34 | 290 trigger on these events have the added ability to choose whether the |
bos@34 | 291 activity can continue, or will abort. |
bos@34 | 292 |
bos@34 | 293 The \hook{pretxncommit} hook runs after a commit has all but |
bos@34 | 294 completed. In other words, the metadata representing the changeset |
bos@34 | 295 has been written out to disk, but the transaction has not yet been |
bos@34 | 296 allowed to complete. The \hook{pretxncommit} hook has the ability to |
bos@34 | 297 decide whether the transaction can complete, or must be rolled back. |
bos@34 | 298 |
bos@34 | 299 If the \hook{pretxncommit} hook exits with a status code of zero, the |
bos@34 | 300 transaction is allowed to complete; the commit finishes; and the |
bos@34 | 301 \hook{commit} hook is run. If the \hook{pretxncommit} hook exits with |
bos@34 | 302 a non-zero status code, the transaction is rolled back; the metadata |
bos@34 | 303 representing the changeset is erased; and the \hook{commit} hook is |
bos@34 | 304 not run. |
bos@34 | 305 |
bos@34 | 306 \begin{figure}[ht] |
bos@34 | 307 \interaction{hook.simple.pretxncommit} |
bos@34 | 308 \caption{Using the \hook{pretxncommit} hook to control commits} |
bos@34 | 309 \label{ex:hook:pretxncommit} |
bos@34 | 310 \end{figure} |
bos@34 | 311 |
bos@34 | 312 The hook in example~\ref{ex:hook:pretxncommit} checks that a commit |
bos@34 | 313 comment contains a bug ID. If it does, the commit can complete. If |
bos@34 | 314 not, the commit is rolled back. |
bos@34 | 315 |
bos@37 | 316 \section{Writing your own hooks} |
bos@37 | 317 |
bos@37 | 318 When you are writing a hook, you might find it useful to run Mercurial |
bos@37 | 319 either with the \hggopt{-v} option, or the \rcitem{ui}{verbose} config |
bos@37 | 320 item set to ``true''. When you do so, Mercurial will print a message |
bos@37 | 321 before it calls each hook. |
bos@37 | 322 |
bos@37 | 323 \subsection{Choosing how your hook should run} |
bos@37 | 324 \label{sec:hook:lang} |
bos@34 | 325 |
bos@34 | 326 You can write a hook either as a normal program---typically a shell |
bos@37 | 327 script---or as a Python function that is executed within the Mercurial |
bos@34 | 328 process. |
bos@34 | 329 |
bos@34 | 330 Writing a hook as an external program has the advantage that it |
bos@34 | 331 requires no knowledge of Mercurial's internals. You can call normal |
bos@34 | 332 Mercurial commands to get any added information you need. The |
bos@34 | 333 trade-off is that external hooks are slower than in-process hooks. |
bos@34 | 334 |
bos@34 | 335 An in-process Python hook has complete access to the Mercurial API, |
bos@34 | 336 and does not ``shell out'' to another process, so it is inherently |
bos@34 | 337 faster than an external hook. It is also easier to obtain much of the |
bos@34 | 338 information that a hook requires by using the Mercurial API than by |
bos@34 | 339 running Mercurial commands. |
bos@34 | 340 |
bos@34 | 341 If you are comfortable with Python, or require high performance, |
bos@34 | 342 writing your hooks in Python may be a good choice. However, when you |
bos@34 | 343 have a straightforward hook to write and you don't need to care about |
bos@34 | 344 performance (probably the majority of hooks), a shell script is |
bos@34 | 345 perfectly fine. |
bos@34 | 346 |
bos@37 | 347 \subsection{Hook parameters} |
bos@34 | 348 \label{sec:hook:param} |
bos@34 | 349 |
bos@34 | 350 Mercurial calls each hook with a set of well-defined parameters. In |
bos@34 | 351 Python, a parameter is passed as a keyword argument to your hook |
bos@34 | 352 function. For an external program, a parameter is passed as an |
bos@34 | 353 environment variable. |
bos@34 | 354 |
bos@34 | 355 Whether your hook is written in Python or as a shell script, the |
bos@37 | 356 hook-specific parameter names and values will be the same. A boolean |
bos@37 | 357 parameter will be represented as a boolean value in Python, but as the |
bos@37 | 358 number 1 (for ``true'') or 0 (for ``false'') as an environment |
bos@37 | 359 variable for an external hook. If a hook parameter is named |
bos@37 | 360 \texttt{foo}, the keyword argument for a Python hook will also be |
bos@51 | 361 named \texttt{foo}, while the environment variable for an external |
bos@51 | 362 hook will be named \texttt{HG\_FOO}. |
bos@37 | 363 |
bos@37 | 364 \subsection{Hook return values and activity control} |
bos@37 | 365 |
bos@37 | 366 A hook that executes successfully must exit with a status of zero if |
bos@37 | 367 external, or return boolean ``false'' if in-process. Failure is |
bos@37 | 368 indicated with a non-zero exit status from an external hook, or an |
bos@37 | 369 in-process hook returning boolean ``true''. If an in-process hook |
bos@37 | 370 raises an exception, the hook is considered to have failed. |
bos@37 | 371 |
bos@37 | 372 For a hook that controls whether an activity can proceed, zero/false |
bos@37 | 373 means ``allow'', while non-zero/true/exception means ``deny''. |
bos@37 | 374 |
bos@37 | 375 \subsection{Writing an external hook} |
bos@37 | 376 |
bos@37 | 377 When you define an external hook in your \hgrc\ and the hook is run, |
bos@37 | 378 its value is passed to your shell, which interprets it. This means |
bos@37 | 379 that you can use normal shell constructs in the body of the hook. |
bos@37 | 380 |
bos@37 | 381 An executable hook is always run with its current directory set to a |
bos@37 | 382 repository's root directory. |
bos@37 | 383 |
bos@37 | 384 Each hook parameter is passed in as an environment variable; the name |
bos@37 | 385 is upper-cased, and prefixed with the string ``\texttt{HG\_}''. |
bos@37 | 386 |
bos@37 | 387 With the exception of hook parameters, Mercurial does not set or |
bos@37 | 388 modify any environment variables when running a hook. This is useful |
bos@37 | 389 to remember if you are writing a site-wide hook that may be run by a |
bos@37 | 390 number of different users with differing environment variables set. |
bos@37 | 391 In multi-user situations, you should not rely on environment variables |
bos@37 | 392 being set to the values you have in your environment when testing the |
bos@37 | 393 hook. |
bos@37 | 394 |
bos@37 | 395 \subsection{Telling Mercurial to use an in-process hook} |
bos@37 | 396 |
bos@37 | 397 The \hgrc\ syntax for defining an in-process hook is slightly |
bos@37 | 398 different than for an executable hook. The value of the hook must |
bos@37 | 399 start with the text ``\texttt{python:}'', and continue with the |
bos@37 | 400 fully-qualified name of a callable object to use as the hook's value. |
bos@37 | 401 |
bos@37 | 402 The module in which a hook lives is automatically imported when a hook |
bos@37 | 403 is run. So long as you have the module name and \envar{PYTHONPATH} |
bos@37 | 404 right, it should ``just work''. |
bos@37 | 405 |
bos@37 | 406 The following \hgrc\ example snippet illustrates the syntax and |
bos@37 | 407 meaning of the notions we just described. |
bos@37 | 408 \begin{codesample2} |
bos@37 | 409 [hooks] |
bos@37 | 410 commit.example = python:mymodule.submodule.myhook |
bos@37 | 411 \end{codesample2} |
bos@37 | 412 When Mercurial runs the \texttt{commit.example} hook, it imports |
bos@37 | 413 \texttt{mymodule.submodule}, looks for the callable object named |
bos@37 | 414 \texttt{myhook}, and calls it. |
bos@37 | 415 |
bos@37 | 416 \subsection{Writing an in-process hook} |
bos@37 | 417 |
bos@37 | 418 The simplest in-process hook does nothing, but illustrates the basic |
bos@37 | 419 shape of the hook API: |
bos@37 | 420 \begin{codesample2} |
bos@37 | 421 def myhook(ui, repo, **kwargs): |
bos@37 | 422 pass |
bos@37 | 423 \end{codesample2} |
bos@37 | 424 The first argument to a Python hook is always a |
bos@37 | 425 \pymodclass{mercurial.ui}{ui} object. The second is a repository object; |
bos@37 | 426 at the moment, it is always an instance of |
bos@37 | 427 \pymodclass{mercurial.localrepo}{localrepository}. Following these two |
bos@37 | 428 arguments are other keyword arguments. Which ones are passed in |
bos@37 | 429 depends on the hook being called, but a hook can ignore arguments it |
bos@37 | 430 doesn't care about by dropping them into a keyword argument dict, as |
bos@37 | 431 with \texttt{**kwargs} above. |
bos@34 | 432 |
bos@44 | 433 \section{Some hook examples} |
bos@44 | 434 |
bos@49 | 435 \subsection{Writing meaningful commit messages} |
bos@49 | 436 |
bos@49 | 437 It's hard to imagine a useful commit message being very short. The |
bos@155 | 438 simple \hook{pretxncommit} hook of figure~\ref{ex:hook:msglen.go} |
bos@49 | 439 will prevent you from committing a changeset with a message that is |
bos@49 | 440 less than ten bytes long. |
bos@49 | 441 |
bos@49 | 442 \begin{figure}[ht] |
bos@155 | 443 \interaction{hook.msglen.go} |
bos@49 | 444 \caption{A hook that forbids overly short commit messages} |
bos@155 | 445 \label{ex:hook:msglen.go} |
bos@49 | 446 \end{figure} |
bos@49 | 447 |
bos@49 | 448 \subsection{Checking for trailing whitespace} |
bos@44 | 449 |
bos@44 | 450 An interesting use of a commit-related hook is to help you to write |
bos@44 | 451 cleaner code. A simple example of ``cleaner code'' is the dictum that |
bos@44 | 452 a change should not add any new lines of text that contain ``trailing |
bos@44 | 453 whitespace''. Trailing whitespace is a series of space and tab |
bos@44 | 454 characters at the end of a line of text. In most cases, trailing |
bos@44 | 455 whitespace is unnecessary, invisible noise, but it is occasionally |
bos@49 | 456 problematic, and people often prefer to get rid of it. |
bos@44 | 457 |
bos@44 | 458 You can use either the \hook{precommit} or \hook{pretxncommit} hook to |
bos@44 | 459 tell whether you have a trailing whitespace problem. If you use the |
bos@44 | 460 \hook{precommit} hook, the hook will not know which files you are |
bos@44 | 461 committing, so it will have to check every modified file in the |
bos@44 | 462 repository for trailing white space. If you want to commit a change |
bos@44 | 463 to just the file \filename{foo}, but the file \filename{bar} contains |
bos@44 | 464 trailing whitespace, doing a check in the \hook{precommit} hook will |
bos@44 | 465 prevent you from committing \filename{foo} due to the problem with |
bos@44 | 466 \filename{bar}. This doesn't seem right. |
bos@44 | 467 |
bos@44 | 468 Should you choose the \hook{pretxncommit} hook, the check won't occur |
bos@44 | 469 until just before the transaction for the commit completes. This will |
bos@44 | 470 allow you to check for problems only the exact files that are being |
bos@44 | 471 committed. However, if you entered the commit message interactively |
bos@44 | 472 and the hook fails, the transaction will roll back; you'll have to |
bos@44 | 473 re-enter the commit message after you fix the trailing whitespace and |
bos@44 | 474 run \hgcmd{commit} again. |
bos@44 | 475 |
bos@44 | 476 \begin{figure}[ht] |
bos@44 | 477 \interaction{hook.ws.simple} |
bos@44 | 478 \caption{A simple hook that checks for trailing whitespace} |
bos@44 | 479 \label{ex:hook:ws.simple} |
bos@44 | 480 \end{figure} |
bos@44 | 481 |
bos@44 | 482 Figure~\ref{ex:hook:ws.simple} introduces a simple \hook{pretxncommit} |
bos@44 | 483 hook that checks for trailing whitespace. This hook is short, but not |
bos@44 | 484 very helpful. It exits with an error status if a change adds a line |
bos@44 | 485 with trailing whitespace to any file, but does not print any |
bos@49 | 486 information that might help us to identify the offending file or |
bos@49 | 487 line. It also has the nice property of not paying attention to |
bos@49 | 488 unmodified lines; only lines that introduce new trailing whitespace |
bos@49 | 489 cause problems. |
bos@49 | 490 |
bos@49 | 491 \begin{figure}[ht] |
bos@49 | 492 \interaction{hook.ws.better} |
bos@49 | 493 \caption{A better trailing whitespace hook} |
bos@49 | 494 \label{ex:hook:ws.better} |
bos@49 | 495 \end{figure} |
bos@49 | 496 |
bos@49 | 497 The example of figure~\ref{ex:hook:ws.better} is much more complex, |
bos@49 | 498 but also more useful. It parses a unified diff to see if any lines |
bos@49 | 499 add trailing whitespace, and prints the name of the file and the line |
bos@49 | 500 number of each such occurrence. Even better, if the change adds |
bos@49 | 501 trailing whitespace, this hook saves the commit comment and prints the |
bos@49 | 502 name of the save file before exiting and telling Mercurial to roll the |
bos@49 | 503 transaction back, so you can use |
bos@49 | 504 \hgcmdargs{commit}{\hgopt{commit}{-l}~\emph{filename}} to reuse the |
bos@49 | 505 saved commit message once you've corrected the problem. |
bos@49 | 506 |
bos@49 | 507 As a final aside, note in figure~\ref{ex:hook:ws.better} the use of |
bos@49 | 508 \command{perl}'s in-place editing feature to get rid of trailing |
bos@49 | 509 whitespace from a file. This is concise and useful enough that I will |
bos@49 | 510 reproduce it here. |
bos@49 | 511 \begin{codesample2} |
bos@54 | 512 perl -pi -e 's,\\s+\$,,' filename |
bos@49 | 513 \end{codesample2} |
bos@49 | 514 |
bos@49 | 515 \section{Bundled hooks} |
bos@49 | 516 |
bos@49 | 517 Mercurial ships with several bundled hooks. You can find them in the |
bos@49 | 518 \dirname{hgext} directory of a Mercurial source tree. If you are |
bos@49 | 519 using a Mercurial binary package, the hooks will be located in the |
bos@49 | 520 \dirname{hgext} directory of wherever your package installer put |
bos@49 | 521 Mercurial. |
bos@49 | 522 |
bos@49 | 523 \subsection{\hgext{acl}---access control for parts of a repository} |
bos@49 | 524 |
bos@49 | 525 The \hgext{acl} extension lets you control which remote users are |
bos@49 | 526 allowed to push changesets to a networked server. You can protect any |
bos@49 | 527 portion of a repository (including the entire repo), so that a |
bos@49 | 528 specific remote user can push changes that do not affect the protected |
bos@49 | 529 portion. |
bos@49 | 530 |
bos@49 | 531 This extension implements access control based on the identity of the |
bos@49 | 532 user performing a push, \emph{not} on who committed the changesets |
bos@62 | 533 they're pushing. It makes sense to use this hook only if you have a |
bos@62 | 534 locked-down server environment that authenticates remote users, and |
bos@62 | 535 you want to be sure that only specific users are allowed to push |
bos@62 | 536 changes to that server. |
bos@62 | 537 |
bos@62 | 538 \subsubsection{Configuring the \hook{acl} hook} |
bos@62 | 539 |
bos@62 | 540 In order to manage incoming changesets, the \hgext{acl} hook must be |
bos@62 | 541 used as a \hook{pretxnchangegroup} hook. This lets it see which files |
bos@62 | 542 are modified by each incoming changeset, and roll back a group of |
bos@62 | 543 changesets if they modify ``forbidden'' files. Example: |
bos@62 | 544 \begin{codesample2} |
bos@62 | 545 [hooks] |
bos@62 | 546 pretxnchangegroup.acl = python:hgext.acl.hook |
bos@62 | 547 \end{codesample2} |
bos@62 | 548 |
bos@62 | 549 The \hgext{acl} extension is configured using three sections. |
bos@62 | 550 |
bos@62 | 551 The \rcsection{acl} section has only one entry, \rcitem{acl}{sources}, |
bos@62 | 552 which lists the sources of incoming changesets that the hook should |
bos@62 | 553 pay attention to. You don't normally need to configure this section. |
bos@62 | 554 \begin{itemize} |
bos@64 | 555 \item[\rcitem{acl}{serve}] Control incoming changesets that are arriving |
bos@62 | 556 from a remote repository over http or ssh. This is the default |
bos@62 | 557 value of \rcitem{acl}{sources}, and usually the only setting you'll |
bos@62 | 558 need for this configuration item. |
bos@64 | 559 \item[\rcitem{acl}{pull}] Control incoming changesets that are |
bos@64 | 560 arriving via a pull from a local repository. |
bos@64 | 561 \item[\rcitem{acl}{push}] Control incoming changesets that are |
bos@64 | 562 arriving via a push from a local repository. |
bos@64 | 563 \item[\rcitem{acl}{bundle}] Control incoming changesets that are |
bos@64 | 564 arriving from another repository via a bundle. |
bos@62 | 565 \end{itemize} |
bos@62 | 566 |
bos@62 | 567 The \rcsection{acl.allow} section controls the users that are allowed to |
bos@62 | 568 add changesets to the repository. If this section is not present, all |
bos@62 | 569 users that are not explicitly denied are allowed. If this section is |
bos@62 | 570 present, all users that are not explicitly allowed are denied (so an |
bos@62 | 571 empty section means that all users are denied). |
bos@62 | 572 |
bos@62 | 573 The \rcsection{acl.deny} section determines which users are denied |
bos@62 | 574 from adding changesets to the repository. If this section is not |
bos@62 | 575 present or is empty, no users are denied. |
bos@62 | 576 |
bos@62 | 577 The syntaxes for the \rcsection{acl.allow} and \rcsection{acl.deny} |
bos@62 | 578 sections are identical. On the left of each entry is a glob pattern |
bos@62 | 579 that matches files or directories, relative to the root of the |
bos@62 | 580 repository; on the right, a user name. |
bos@62 | 581 |
bos@62 | 582 In the following example, the user \texttt{docwriter} can only push |
bos@62 | 583 changes to the \dirname{docs} subtree of the repository, while |
bos@62 | 584 \texttt{intern} can push changes to any file or directory except |
bos@62 | 585 \dirname{source/sensitive}. |
bos@62 | 586 \begin{codesample2} |
bos@62 | 587 [acl.allow] |
bos@62 | 588 docs/** = docwriter |
bos@62 | 589 |
bos@62 | 590 [acl.deny] |
bos@62 | 591 source/sensitive/** = intern |
bos@62 | 592 \end{codesample2} |
bos@62 | 593 |
bos@62 | 594 \subsubsection{Testing and troubleshooting} |
bos@62 | 595 |
bos@62 | 596 If you want to test the \hgext{acl} hook, run it with Mercurial's |
bos@62 | 597 debugging output enabled. Since you'll probably be running it on a |
bos@62 | 598 server where it's not convenient (or sometimes possible) to pass in |
bos@62 | 599 the \hggopt{--debug} option, don't forget that you can enable |
bos@62 | 600 debugging output in your \hgrc: |
bos@62 | 601 \begin{codesample2} |
bos@62 | 602 [ui] |
bos@62 | 603 debug = true |
bos@62 | 604 \end{codesample2} |
bos@62 | 605 With this enabled, the \hgext{acl} hook will print enough information |
bos@62 | 606 to let you figure out why it is allowing or forbidding pushes from |
bos@62 | 607 specific users. |
bos@62 | 608 |
bos@62 | 609 \subsection{\hgext{bugzilla}---integration with Bugzilla} |
bos@62 | 610 |
bos@62 | 611 The \hgext{bugzilla} extension adds a comment to a Bugzilla bug |
bos@62 | 612 whenever it finds a reference to that bug ID in a commit comment. You |
bos@62 | 613 can install this hook on a shared server, so that any time a remote |
bos@62 | 614 user pushes changes to this server, the hook gets run. |
bos@62 | 615 |
bos@62 | 616 It adds a comment to the bug that looks like this (you can configure |
bos@62 | 617 the contents of the comment---see below): |
bos@62 | 618 \begin{codesample2} |
bos@62 | 619 Changeset aad8b264143a, made by Joe User <joe.user@domain.com> in |
bos@62 | 620 the frobnitz repository, refers to this bug. |
bos@62 | 621 |
bos@62 | 622 For complete details, see |
bos@62 | 623 http://hg.domain.com/frobnitz?cmd=changeset;node=aad8b264143a |
bos@62 | 624 |
bos@62 | 625 Changeset description: |
bos@62 | 626 Fix bug 10483 by guarding against some NULL pointers |
bos@62 | 627 \end{codesample2} |
bos@62 | 628 The value of this hook is that it automates the process of updating a |
bos@62 | 629 bug any time a changeset refers to it. If you configure the hook |
bos@62 | 630 properly, it makes it easy for people to browse straight from a |
bos@62 | 631 Bugzilla bug to a changeset that refers to that bug. |
bos@62 | 632 |
bos@62 | 633 You can use the code in this hook as a starting point for some more |
bos@62 | 634 exotic Bugzilla integration recipes. Here are a few possibilities: |
bos@62 | 635 \begin{itemize} |
bos@62 | 636 \item Require that every changeset pushed to the server have a valid |
bos@62 | 637 bug~ID in its commit comment. In this case, you'd want to configure |
bos@62 | 638 the hook as a \hook{pretxncommit} hook. This would allow the hook |
bos@62 | 639 to reject changes that didn't contain bug IDs. |
bos@62 | 640 \item Allow incoming changesets to automatically modify the |
bos@62 | 641 \emph{state} of a bug, as well as simply adding a comment. For |
bos@62 | 642 example, the hook could recognise the string ``fixed bug 31337'' as |
bos@62 | 643 indicating that it should update the state of bug 31337 to |
bos@62 | 644 ``requires testing''. |
bos@62 | 645 \end{itemize} |
bos@62 | 646 |
bos@62 | 647 \subsubsection{Configuring the \hook{bugzilla} hook} |
bos@62 | 648 \label{sec:hook:bugzilla:config} |
bos@62 | 649 |
bos@62 | 650 You should configure this hook in your server's \hgrc\ as an |
bos@62 | 651 \hook{incoming} hook, for example as follows: |
bos@62 | 652 \begin{codesample2} |
bos@62 | 653 [hooks] |
bos@62 | 654 incoming.bugzilla = python:hgext.bugzilla.hook |
bos@62 | 655 \end{codesample2} |
bos@62 | 656 |
bos@62 | 657 Because of the specialised nature of this hook, and because Bugzilla |
bos@62 | 658 was not written with this kind of integration in mind, configuring |
bos@62 | 659 this hook is a somewhat involved process. |
bos@62 | 660 |
bos@62 | 661 Before you begin, you must install the MySQL bindings for Python on |
bos@62 | 662 the host(s) where you'll be running the hook. If this is not |
bos@62 | 663 available as a binary package for your system, you can download it |
bos@62 | 664 from~\cite{web:mysql-python}. |
bos@62 | 665 |
bos@62 | 666 Configuration information for this hook lives in the |
bos@62 | 667 \rcsection{bugzilla} section of your \hgrc. |
bos@62 | 668 \begin{itemize} |
bos@64 | 669 \item[\rcitem{bugzilla}{version}] The version of Bugzilla installed on |
bos@64 | 670 the server. The database schema that Bugzilla uses changes |
bos@62 | 671 occasionally, so this hook has to know exactly which schema to use. |
bos@62 | 672 At the moment, the only version supported is \texttt{2.16}. |
bos@64 | 673 \item[\rcitem{bugzilla}{host}] The hostname of the MySQL server that |
bos@64 | 674 stores your Bugzilla data. The database must be configured to allow |
bos@64 | 675 connections from whatever host you are running the \hook{bugzilla} |
bos@64 | 676 hook on. |
bos@64 | 677 \item[\rcitem{bugzilla}{user}] The username with which to connect to |
bos@64 | 678 the MySQL server. The database must be configured to allow this |
bos@64 | 679 user to connect from whatever host you are running the |
bos@64 | 680 \hook{bugzilla} hook on. This user must be able to access and |
bos@64 | 681 modify Bugzilla tables. The default value of this item is |
bos@64 | 682 \texttt{bugs}, which is the standard name of the Bugzilla user in a |
bos@64 | 683 MySQL database. |
bos@64 | 684 \item[\rcitem{bugzilla}{password}] The MySQL password for the user you |
bos@62 | 685 configured above. This is stored as plain text, so you should make |
bos@62 | 686 sure that unauthorised users cannot read the \hgrc\ file where you |
bos@62 | 687 store this information. |
bos@64 | 688 \item[\rcitem{bugzilla}{db}] The name of the Bugzilla database on the |
bos@64 | 689 MySQL server. The default value of this item is \texttt{bugs}, |
bos@64 | 690 which is the standard name of the MySQL database where Bugzilla |
bos@64 | 691 stores its data. |
bos@64 | 692 \item[\rcitem{bugzilla}{notify}] If you want Bugzilla to send out a |
bos@64 | 693 notification email to subscribers after this hook has added a |
bos@64 | 694 comment to a bug, you will need this hook to run a command whenever |
bos@64 | 695 it updates the database. The command to run depends on where you |
bos@64 | 696 have installed Bugzilla, but it will typically look something like |
bos@64 | 697 this, if you have Bugzilla installed in |
bos@64 | 698 \dirname{/var/www/html/bugzilla}: |
bos@62 | 699 \begin{codesample4} |
bos@62 | 700 cd /var/www/html/bugzilla && ./processmail %s nobody@nowhere.com |
bos@62 | 701 \end{codesample4} |
bos@62 | 702 The Bugzilla \texttt{processmail} program expects to be given a |
bos@62 | 703 bug~ID (the hook replaces ``\texttt{\%s}'' with the bug~ID) and an |
bos@62 | 704 email address. It also expects to be able to write to some files in |
bos@62 | 705 the directory that it runs in. If Bugzilla and this hook are not |
bos@62 | 706 installed on the same machine, you will need to find a way to run |
bos@62 | 707 \texttt{processmail} on the server where Bugzilla is installed. |
bos@62 | 708 \end{itemize} |
bos@62 | 709 |
bos@62 | 710 \subsubsection{Mapping committer names to Bugzilla user names} |
bos@62 | 711 |
bos@62 | 712 By default, the \hgext{bugzilla} hook tries to use the email address |
bos@62 | 713 of a changeset's committer as the Bugzilla user name with which to |
bos@62 | 714 update a bug. If this does not suit your needs, you can map committer |
bos@62 | 715 email addresses to Bugzilla user names using a \rcsection{usermap} |
bos@62 | 716 section. |
bos@62 | 717 |
bos@62 | 718 Each item in the \rcsection{usermap} section contains an email address |
bos@62 | 719 on the left, and a Bugzilla user name on the right. |
bos@62 | 720 \begin{codesample2} |
bos@62 | 721 [usermap] |
bos@62 | 722 jane.user@example.com = jane |
bos@62 | 723 \end{codesample2} |
bos@62 | 724 You can either keep the \rcsection{usermap} data in a normal \hgrc, or |
bos@62 | 725 tell the \hgext{bugzilla} hook to read the information from an |
bos@62 | 726 external \filename{usermap} file. In the latter case, you can store |
bos@62 | 727 \filename{usermap} data by itself in (for example) a user-modifiable |
bos@62 | 728 repository. This makes it possible to let your users maintain their |
bos@64 | 729 own \rcitem{bugzilla}{usermap} entries. The main \hgrc\ file might |
bos@64 | 730 look like this: |
bos@62 | 731 \begin{codesample2} |
bos@62 | 732 # regular hgrc file refers to external usermap file |
bos@62 | 733 [bugzilla] |
bos@62 | 734 usermap = /home/hg/repos/userdata/bugzilla-usermap.conf |
bos@62 | 735 \end{codesample2} |
bos@62 | 736 While the \filename{usermap} file that it refers to might look like |
bos@62 | 737 this: |
bos@62 | 738 \begin{codesample2} |
bos@62 | 739 # bugzilla-usermap.conf - inside a hg repository |
bos@62 | 740 [usermap] |
bos@62 | 741 stephanie@example.com = steph |
bos@62 | 742 \end{codesample2} |
bos@62 | 743 |
bos@62 | 744 \subsubsection{Configuring the text that gets added to a bug} |
bos@62 | 745 |
bos@62 | 746 You can configure the text that this hook adds as a comment; you |
bos@62 | 747 specify it in the form of a Mercurial template. Several \hgrc\ |
bos@62 | 748 entries (still in the \rcsection{bugzilla} section) control this |
bos@62 | 749 behaviour. |
bos@62 | 750 \begin{itemize} |
bos@62 | 751 \item[\texttt{strip}] The number of leading path elements to strip |
bos@62 | 752 from a repository's path name to construct a partial path for a URL. |
bos@62 | 753 For example, if the repositories on your server live under |
bos@62 | 754 \dirname{/home/hg/repos}, and you have a repository whose path is |
bos@62 | 755 \dirname{/home/hg/repos/app/tests}, then setting \texttt{strip} to |
bos@62 | 756 \texttt{4} will give a partial path of \dirname{app/tests}. The |
bos@62 | 757 hook will make this partial path available when expanding a |
bos@62 | 758 template, as \texttt{webroot}. |
bos@62 | 759 \item[\texttt{template}] The text of the template to use. In addition |
bos@62 | 760 to the usual changeset-related variables, this template can use |
bos@62 | 761 \texttt{hgweb} (the value of the \texttt{hgweb} configuration item |
bos@62 | 762 above) and \texttt{webroot} (the path constructed using |
bos@62 | 763 \texttt{strip} above). |
bos@62 | 764 \end{itemize} |
bos@62 | 765 |
bos@64 | 766 In addition, you can add a \rcitem{web}{baseurl} item to the |
bos@64 | 767 \rcsection{web} section of your \hgrc. The \hgext{bugzilla} hook will |
bos@64 | 768 make this available when expanding a template, as the base string to |
bos@64 | 769 use when constructing a URL that will let users browse from a Bugzilla |
bos@64 | 770 comment to view a changeset. Example: |
bos@64 | 771 \begin{codesample2} |
bos@64 | 772 [web] |
bos@64 | 773 baseurl = http://hg.domain.com/ |
bos@64 | 774 \end{codesample2} |
bos@64 | 775 |
bos@62 | 776 Here is an example set of \hgext{bugzilla} hook config information. |
bos@62 | 777 \begin{codesample2} |
bos@62 | 778 [bugzilla] |
bos@62 | 779 host = bugzilla.example.com |
bos@62 | 780 password = mypassword |
bos@62 | 781 version = 2.16 |
bos@62 | 782 # server-side repos live in /home/hg/repos, so strip 4 leading |
bos@62 | 783 # separators |
bos@62 | 784 strip = 4 |
bos@62 | 785 hgweb = http://hg.example.com/ |
bos@62 | 786 usermap = /home/hg/repos/notify/bugzilla.conf |
bos@62 | 787 template = Changeset \{node|short\}, made by \{author\} in the \{webroot\} |
bos@62 | 788 repo, refers to this bug.\\nFor complete details, see |
bos@62 | 789 \{hgweb\}\{webroot\}?cmd=changeset;node=\{node|short\}\\nChangeset |
bos@62 | 790 description:\\n\\t\{desc|tabindent\} |
bos@62 | 791 \end{codesample2} |
bos@62 | 792 |
bos@62 | 793 \subsubsection{Testing and troubleshooting} |
bos@62 | 794 |
bos@62 | 795 The most common problems with configuring the \hgext{bugzilla} hook |
bos@62 | 796 relate to running Bugzilla's \filename{processmail} script and mapping |
bos@62 | 797 committer names to user names. |
bos@62 | 798 |
bos@62 | 799 Recall from section~\ref{sec:hook:bugzilla:config} above that the user |
bos@62 | 800 that runs the Mercurial process on the server is also the one that |
bos@62 | 801 will run the \filename{processmail} script. The |
bos@62 | 802 \filename{processmail} script sometimes causes Bugzilla to write to |
bos@62 | 803 files in its configuration directory, and Bugzilla's configuration |
bos@62 | 804 files are usually owned by the user that your web server runs under. |
bos@62 | 805 |
bos@62 | 806 You can cause \filename{processmail} to be run with the suitable |
bos@62 | 807 user's identity using the \command{sudo} command. Here is an example |
bos@62 | 808 entry for a \filename{sudoers} file. |
bos@62 | 809 \begin{codesample2} |
bos@62 | 810 hg_user = (httpd_user) NOPASSWD: /var/www/html/bugzilla/processmail-wrapper %s |
bos@62 | 811 \end{codesample2} |
bos@62 | 812 This allows the \texttt{hg\_user} user to run a |
bos@62 | 813 \filename{processmail-wrapper} program under the identity of |
bos@62 | 814 \texttt{httpd\_user}. |
bos@62 | 815 |
bos@62 | 816 This indirection through a wrapper script is necessary, because |
bos@62 | 817 \filename{processmail} expects to be run with its current directory |
bos@62 | 818 set to wherever you installed Bugzilla; you can't specify that kind of |
bos@62 | 819 constraint in a \filename{sudoers} file. The contents of the wrapper |
bos@62 | 820 script are simple: |
bos@62 | 821 \begin{codesample2} |
bos@62 | 822 #!/bin/sh |
bos@62 | 823 cd `dirname $0` && ./processmail "$1" nobody@example.com |
bos@62 | 824 \end{codesample2} |
bos@62 | 825 It doesn't seem to matter what email address you pass to |
bos@62 | 826 \filename{processmail}. |
bos@62 | 827 |
bos@62 | 828 If your \rcsection{usermap} is not set up correctly, users will see an |
bos@62 | 829 error message from the \hgext{bugzilla} hook when they push changes |
bos@62 | 830 to the server. The error message will look like this: |
bos@62 | 831 \begin{codesample2} |
bos@62 | 832 cannot find bugzilla user id for john.q.public@example.com |
bos@62 | 833 \end{codesample2} |
bos@62 | 834 What this means is that the committer's address, |
bos@62 | 835 \texttt{john.q.public@example.com}, is not a valid Bugzilla user name, |
bos@62 | 836 nor does it have an entry in your \rcsection{usermap} that maps it to |
bos@62 | 837 a valid Bugzilla user name. |
bos@62 | 838 |
bos@62 | 839 \subsection{\hgext{notify}---send email notifications} |
bos@62 | 840 |
bos@62 | 841 Although Mercurial's built-in web server provides RSS feeds of changes |
bos@62 | 842 in every repository, many people prefer to receive change |
bos@62 | 843 notifications via email. The \hgext{notify} hook lets you send out |
bos@62 | 844 notifications to a set of email addresses whenever changesets arrive |
bos@62 | 845 that those subscribers are interested in. |
bos@62 | 846 |
bos@62 | 847 As with the \hgext{bugzilla} hook, the \hgext{notify} hook is |
bos@62 | 848 template-driven, so you can customise the contents of the notification |
bos@62 | 849 messages that it sends. |
bos@62 | 850 |
bos@62 | 851 By default, the \hgext{notify} hook includes a diff of every changeset |
bos@63 | 852 that it sends out; you can limit the size of the diff, or turn this |
bos@62 | 853 feature off entirely. It is useful for letting subscribers review |
bos@62 | 854 changes immediately, rather than clicking to follow a URL. |
bos@62 | 855 |
bos@62 | 856 \subsubsection{Configuring the \hgext{notify} hook} |
bos@62 | 857 |
bos@62 | 858 You can set up the \hgext{notify} hook to send one email message per |
bos@62 | 859 incoming changeset, or one per incoming group of changesets (all those |
bos@62 | 860 that arrived in a single pull or push). |
bos@62 | 861 \begin{codesample2} |
bos@62 | 862 [hooks] |
bos@62 | 863 # send one email per group of changes |
bos@62 | 864 changegroup.notify = python:hgext.notify.hook |
bos@62 | 865 # send one email per change |
bos@62 | 866 incoming.notify = python:hgext.notify.hook |
bos@62 | 867 \end{codesample2} |
bos@62 | 868 |
bos@62 | 869 Configuration information for this hook lives in the |
bos@62 | 870 \rcsection{notify} section of a \hgrc\ file. |
bos@62 | 871 \begin{itemize} |
bos@62 | 872 \item[\rcitem{notify}{test}] By default, this hook does not send out |
bos@62 | 873 email at all; instead, it prints the message that it \emph{would} |
bos@62 | 874 send. Set this item to \texttt{false} to allow email to be sent. |
bos@62 | 875 The reason that sending of email is turned off by default is that it |
bos@62 | 876 takes several tries to configure this extension exactly as you would |
bos@62 | 877 like, and it would be bad form to spam subscribers with a number of |
bos@62 | 878 ``broken'' notifications while you debug your configuration. |
bos@62 | 879 \item[\rcitem{notify}{config}] The path to a configuration file that |
bos@63 | 880 contains subscription information. This is kept separate from the |
bos@62 | 881 main \hgrc\ so that you can maintain it in a repository of its own. |
bos@62 | 882 People can then clone that repository, update their subscriptions, |
bos@62 | 883 and push the changes back to your server. |
bos@62 | 884 \item[\rcitem{notify}{strip}] The number of leading path separator |
bos@62 | 885 characters to strip from a repository's path, when deciding whether |
bos@62 | 886 a repository has subscribers. For example, if the repositories on |
bos@62 | 887 your server live in \dirname{/home/hg/repos}, and \hgext{notify} is |
bos@62 | 888 considering a repository named \dirname{/home/hg/repos/shared/test}, |
bos@62 | 889 setting \rcitem{notify}{strip} to \texttt{4} will cause |
bos@62 | 890 \hgext{notify} to trim the path it considers down to |
bos@62 | 891 \dirname{shared/test}, and it will match subscribers against that. |
bos@62 | 892 \item[\rcitem{notify}{template}] The template text to use when sending |
bos@62 | 893 messages. This specifies both the contents of the message header |
bos@62 | 894 and its body. |
bos@62 | 895 \item[\rcitem{notify}{maxdiff}] The maximum number of lines of diff |
bos@62 | 896 data to append to the end of a message. If a diff is longer than |
bos@62 | 897 this, it is truncated. By default, this is set to 300. Set this to |
bos@62 | 898 \texttt{0} to omit diffs from notification emails. |
bos@62 | 899 \item[\rcitem{notify}{sources}] A list of sources of changesets to |
bos@62 | 900 consider. This lets you limit \hgext{notify} to only sending out |
bos@62 | 901 email about changes that remote users pushed into this repository |
bos@62 | 902 via a server, for example. See section~\ref{sec:hook:sources} for |
bos@62 | 903 the sources you can specify here. |
bos@62 | 904 \end{itemize} |
bos@62 | 905 |
bos@62 | 906 If you set the \rcitem{web}{baseurl} item in the \rcsection{web} |
bos@62 | 907 section, you can use it in a template; it will be available as |
bos@62 | 908 \texttt{webroot}. |
bos@62 | 909 |
bos@62 | 910 Here is an example set of \hgext{notify} configuration information. |
bos@62 | 911 \begin{codesample2} |
bos@62 | 912 [notify] |
bos@62 | 913 # really send email |
bos@62 | 914 test = false |
bos@62 | 915 # subscriber data lives in the notify repo |
bos@62 | 916 config = /home/hg/repos/notify/notify.conf |
bos@62 | 917 # repos live in /home/hg/repos on server, so strip 4 "/" chars |
bos@62 | 918 strip = 4 |
timonator@285 | 919 template = X-Hg-Repo: \{webroot\} |
timonator@285 | 920 Subject: \{webroot\}: \{desc|firstline|strip\} |
timonator@285 | 921 From: \{author\} |
timonator@285 | 922 |
timonator@285 | 923 changeset \{node|short\} in \{root\} |
timonator@285 | 924 details: \{baseurl\}\{webroot\}?cmd=changeset;node=\{node|short\} |
timonator@285 | 925 description: |
timonator@285 | 926 \{desc|tabindent|strip\} |
bos@62 | 927 |
bos@62 | 928 [web] |
bos@62 | 929 baseurl = http://hg.example.com/ |
bos@62 | 930 \end{codesample2} |
bos@62 | 931 |
bos@62 | 932 This will produce a message that looks like the following: |
bos@62 | 933 \begin{codesample2} |
bos@62 | 934 X-Hg-Repo: tests/slave |
bos@62 | 935 Subject: tests/slave: Handle error case when slave has no buffers |
bos@62 | 936 Date: Wed, 2 Aug 2006 15:25:46 -0700 (PDT) |
bos@62 | 937 |
bos@62 | 938 changeset 3cba9bfe74b5 in /home/hg/repos/tests/slave |
bos@62 | 939 details: http://hg.example.com/tests/slave?cmd=changeset;node=3cba9bfe74b5 |
bos@62 | 940 description: |
bos@62 | 941 Handle error case when slave has no buffers |
bos@62 | 942 diffs (54 lines): |
bos@62 | 943 |
bos@62 | 944 diff -r 9d95df7cf2ad -r 3cba9bfe74b5 include/tests.h |
bos@62 | 945 --- a/include/tests.h Wed Aug 02 15:19:52 2006 -0700 |
bos@62 | 946 +++ b/include/tests.h Wed Aug 02 15:25:26 2006 -0700 |
bos@62 | 947 @@ -212,6 +212,15 @@ static __inline__ void test_headers(void *h) |
bos@62 | 948 [...snip...] |
bos@62 | 949 \end{codesample2} |
bos@62 | 950 |
bos@62 | 951 \subsubsection{Testing and troubleshooting} |
bos@62 | 952 |
bos@62 | 953 Do not forget that by default, the \hgext{notify} extension \emph{will |
bos@62 | 954 not send any mail} until you explicitly configure it to do so, by |
bos@62 | 955 setting \rcitem{notify}{test} to \texttt{false}. Until you do that, |
bos@62 | 956 it simply prints the message it \emph{would} send. |
bos@44 | 957 |
bos@64 | 958 \section{Information for writers of hooks} |
bos@41 | 959 \label{sec:hook:ref} |
bos@39 | 960 |
bos@39 | 961 \subsection{In-process hook execution} |
bos@39 | 962 |
bos@39 | 963 An in-process hook is called with arguments of the following form: |
bos@39 | 964 \begin{codesample2} |
bos@39 | 965 def myhook(ui, repo, **kwargs): |
bos@39 | 966 pass |
bos@39 | 967 \end{codesample2} |
bos@39 | 968 The \texttt{ui} parameter is a \pymodclass{mercurial.ui}{ui} object. |
bos@39 | 969 The \texttt{repo} parameter is a |
bos@39 | 970 \pymodclass{mercurial.localrepo}{localrepository} object. The |
bos@39 | 971 names and values of the \texttt{**kwargs} parameters depend on the |
bos@39 | 972 hook being invoked, with the following common features: |
bos@39 | 973 \begin{itemize} |
bos@39 | 974 \item If a parameter is named \texttt{node} or |
bos@39 | 975 \texttt{parent\emph{N}}, it will contain a hexadecimal changeset ID. |
bos@39 | 976 The empty string is used to represent ``null changeset ID'' instead |
bos@39 | 977 of a string of zeroes. |
bos@62 | 978 \item If a parameter is named \texttt{url}, it will contain the URL of |
bos@62 | 979 a remote repository, if that can be determined. |
bos@39 | 980 \item Boolean-valued parameters are represented as Python |
bos@39 | 981 \texttt{bool} objects. |
bos@39 | 982 \end{itemize} |
bos@39 | 983 |
bos@39 | 984 An in-process hook is called without a change to the process's working |
bos@39 | 985 directory (unlike external hooks, which are run in the root of the |
bos@62 | 986 repository). It must not change the process's working directory, or |
bos@62 | 987 it will cause any calls it makes into the Mercurial API to fail. |
bos@62 | 988 |
bos@62 | 989 If a hook returns a boolean ``false'' value, it is considered to have |
bos@62 | 990 succeeded. If it returns a boolean ``true'' value or raises an |
bos@62 | 991 exception, it is considered to have failed. A useful way to think of |
bos@62 | 992 the calling convention is ``tell me if you fail''. |
bos@62 | 993 |
bos@62 | 994 Note that changeset IDs are passed into Python hooks as hexadecimal |
bos@62 | 995 strings, not the binary hashes that Mercurial's APIs normally use. To |
bos@62 | 996 convert a hash from hex to binary, use the |
bos@62 | 997 \pymodfunc{mercurial.node}{bin} function. |
bos@39 | 998 |
bos@39 | 999 \subsection{External hook execution} |
bos@39 | 1000 |
bos@62 | 1001 An external hook is passed to the shell of the user running Mercurial. |
bos@62 | 1002 Features of that shell, such as variable substitution and command |
bos@39 | 1003 redirection, are available. The hook is run in the root directory of |
bos@62 | 1004 the repository (unlike in-process hooks, which are run in the same |
bos@62 | 1005 directory that Mercurial was run in). |
bos@39 | 1006 |
bos@39 | 1007 Hook parameters are passed to the hook as environment variables. Each |
bos@39 | 1008 environment variable's name is converted in upper case and prefixed |
bos@39 | 1009 with the string ``\texttt{HG\_}''. For example, if the name of a |
bos@39 | 1010 parameter is ``\texttt{node}'', the name of the environment variable |
bos@39 | 1011 representing that parameter will be ``\texttt{HG\_NODE}''. |
bos@39 | 1012 |
bos@39 | 1013 A boolean parameter is represented as the string ``\texttt{1}'' for |
bos@39 | 1014 ``true'', ``\texttt{0}'' for ``false''. If an environment variable is |
bos@39 | 1015 named \envar{HG\_NODE}, \envar{HG\_PARENT1} or \envar{HG\_PARENT2}, it |
bos@39 | 1016 contains a changeset ID represented as a hexadecimal string. The |
bos@39 | 1017 empty string is used to represent ``null changeset ID'' instead of a |
bos@62 | 1018 string of zeroes. If an environment variable is named |
bos@62 | 1019 \envar{HG\_URL}, it will contain the URL of a remote repository, if |
bos@62 | 1020 that can be determined. |
bos@39 | 1021 |
bos@39 | 1022 If a hook exits with a status of zero, it is considered to have |
bos@39 | 1023 succeeded. If it exits with a non-zero status, it is considered to |
bos@39 | 1024 have failed. |
bos@39 | 1025 |
bos@62 | 1026 \subsection{Finding out where changesets come from} |
bos@62 | 1027 |
bos@62 | 1028 A hook that involves the transfer of changesets between a local |
bos@62 | 1029 repository and another may be able to find out information about the |
bos@62 | 1030 ``far side''. Mercurial knows \emph{how} changes are being |
bos@62 | 1031 transferred, and in many cases \emph{where} they are being transferred |
bos@62 | 1032 to or from. |
bos@62 | 1033 |
bos@62 | 1034 \subsubsection{Sources of changesets} |
bos@62 | 1035 \label{sec:hook:sources} |
bos@62 | 1036 |
bos@62 | 1037 Mercurial will tell a hook what means are, or were, used to transfer |
bos@62 | 1038 changesets between repositories. This is provided by Mercurial in a |
bos@62 | 1039 Python parameter named \texttt{source}, or an environment variable named |
bos@62 | 1040 \envar{HG\_SOURCE}. |
bos@62 | 1041 |
bos@62 | 1042 \begin{itemize} |
bos@62 | 1043 \item[\texttt{serve}] Changesets are transferred to or from a remote |
bos@62 | 1044 repository over http or ssh. |
bos@62 | 1045 \item[\texttt{pull}] Changesets are being transferred via a pull from |
bos@62 | 1046 one repository into another. |
bos@62 | 1047 \item[\texttt{push}] Changesets are being transferred via a push from |
bos@62 | 1048 one repository into another. |
bos@62 | 1049 \item[\texttt{bundle}] Changesets are being transferred to or from a |
bos@62 | 1050 bundle. |
bos@62 | 1051 \end{itemize} |
bos@62 | 1052 |
bos@62 | 1053 \subsubsection{Where changes are going---remote repository URLs} |
bos@62 | 1054 \label{sec:hook:url} |
bos@62 | 1055 |
bos@62 | 1056 When possible, Mercurial will tell a hook the location of the ``far |
bos@62 | 1057 side'' of an activity that transfers changeset data between |
bos@62 | 1058 repositories. This is provided by Mercurial in a Python parameter |
bos@62 | 1059 named \texttt{url}, or an environment variable named \envar{HG\_URL}. |
bos@62 | 1060 |
bos@62 | 1061 This information is not always known. If a hook is invoked in a |
bos@62 | 1062 repository that is being served via http or ssh, Mercurial cannot tell |
bos@62 | 1063 where the remote repository is, but it may know where the client is |
bos@62 | 1064 connecting from. In such cases, the URL will take one of the |
bos@62 | 1065 following forms: |
bos@62 | 1066 \begin{itemize} |
bos@62 | 1067 \item \texttt{remote:ssh:\emph{ip-address}}---remote ssh client, at |
bos@62 | 1068 the given IP address. |
bos@62 | 1069 \item \texttt{remote:http:\emph{ip-address}}---remote http client, at |
bos@62 | 1070 the given IP address. If the client is using SSL, this will be of |
bos@62 | 1071 the form \texttt{remote:https:\emph{ip-address}}. |
bos@62 | 1072 \item Empty---no information could be discovered about the remote |
bos@62 | 1073 client. |
bos@62 | 1074 \end{itemize} |
bos@62 | 1075 |
bos@64 | 1076 \section{Hook reference} |
bos@64 | 1077 |
bos@64 | 1078 \subsection{\hook{changegroup}---after remote changesets added} |
bos@39 | 1079 \label{sec:hook:changegroup} |
bos@39 | 1080 |
bos@40 | 1081 This hook is run after a group of pre-existing changesets has been |
bos@40 | 1082 added to the repository, for example via a \hgcmd{pull} or |
bos@40 | 1083 \hgcmd{unbundle}. This hook is run once per operation that added one |
bos@41 | 1084 or more changesets. This is in contrast to the \hook{incoming} hook, |
bos@41 | 1085 which is run once per changeset, regardless of whether the changesets |
bos@41 | 1086 arrive in a group. |
bos@41 | 1087 |
bos@41 | 1088 Some possible uses for this hook include kicking off an automated |
bos@41 | 1089 build or test of the added changesets, updating a bug database, or |
bos@41 | 1090 notifying subscribers that a repository contains new changes. |
bos@40 | 1091 |
bos@40 | 1092 Parameters to this hook: |
bos@40 | 1093 \begin{itemize} |
bos@40 | 1094 \item[\texttt{node}] A changeset ID. The changeset ID of the first |
bos@40 | 1095 changeset in the group that was added. All changesets between this |
bos@40 | 1096 and \index{tags!\texttt{tip}}\texttt{tip}, inclusive, were added by |
bos@40 | 1097 a single \hgcmd{pull}, \hgcmd{push} or \hgcmd{unbundle}. |
bos@62 | 1098 \item[\texttt{source}] A string. The source of these changes. See |
bos@62 | 1099 section~\ref{sec:hook:sources} for details. |
bos@62 | 1100 \item[\texttt{url}] A URL. The location of the remote repository, if |
bos@62 | 1101 known. See section~\ref{sec:hook:url} for more information. |
bos@40 | 1102 \end{itemize} |
bos@40 | 1103 |
bos@40 | 1104 See also: \hook{incoming} (section~\ref{sec:hook:incoming}), |
bos@40 | 1105 \hook{prechangegroup} (section~\ref{sec:hook:prechangegroup}), |
bos@40 | 1106 \hook{pretxnchangegroup} (section~\ref{sec:hook:pretxnchangegroup}) |
bos@39 | 1107 |
bos@64 | 1108 \subsection{\hook{commit}---after a new changeset is created} |
bos@39 | 1109 \label{sec:hook:commit} |
bos@39 | 1110 |
bos@40 | 1111 This hook is run after a new changeset has been created. |
bos@40 | 1112 |
bos@40 | 1113 Parameters to this hook: |
bos@40 | 1114 \begin{itemize} |
bos@40 | 1115 \item[\texttt{node}] A changeset ID. The changeset ID of the newly |
bos@40 | 1116 committed changeset. |
bos@40 | 1117 \item[\texttt{parent1}] A changeset ID. The changeset ID of the first |
bos@40 | 1118 parent of the newly committed changeset. |
bos@40 | 1119 \item[\texttt{parent2}] A changeset ID. The changeset ID of the second |
bos@40 | 1120 parent of the newly committed changeset. |
bos@40 | 1121 \end{itemize} |
bos@40 | 1122 |
bos@40 | 1123 See also: \hook{precommit} (section~\ref{sec:hook:precommit}), |
bos@40 | 1124 \hook{pretxncommit} (section~\ref{sec:hook:pretxncommit}) |
bos@40 | 1125 |
bos@64 | 1126 \subsection{\hook{incoming}---after one remote changeset is added} |
bos@40 | 1127 \label{sec:hook:incoming} |
bos@40 | 1128 |
bos@40 | 1129 This hook is run after a pre-existing changeset has been added to the |
bos@40 | 1130 repository, for example via a \hgcmd{push}. If a group of changesets |
bos@40 | 1131 was added in a single operation, this hook is called once for each |
bos@40 | 1132 added changeset. |
bos@40 | 1133 |
bos@41 | 1134 You can use this hook for the same purposes as the \hook{changegroup} |
bos@41 | 1135 hook (section~\ref{sec:hook:changegroup}); it's simply more convenient |
bos@54 | 1136 sometimes to run a hook once per group of changesets, while other |
bos@41 | 1137 times it's handier once per changeset. |
bos@41 | 1138 |
bos@40 | 1139 Parameters to this hook: |
bos@40 | 1140 \begin{itemize} |
bos@40 | 1141 \item[\texttt{node}] A changeset ID. The ID of the newly added |
bos@39 | 1142 changeset. |
bos@62 | 1143 \item[\texttt{source}] A string. The source of these changes. See |
bos@62 | 1144 section~\ref{sec:hook:sources} for details. |
bos@62 | 1145 \item[\texttt{url}] A URL. The location of the remote repository, if |
bos@62 | 1146 known. See section~\ref{sec:hook:url} for more information. |
bos@40 | 1147 \end{itemize} |
bos@40 | 1148 |
bos@40 | 1149 See also: \hook{changegroup} (section~\ref{sec:hook:changegroup}) \hook{prechangegroup} (section~\ref{sec:hook:prechangegroup}), \hook{pretxnchangegroup} (section~\ref{sec:hook:pretxnchangegroup}) |
bos@40 | 1150 |
bos@64 | 1151 \subsection{\hook{outgoing}---after changesets are propagated} |
bos@40 | 1152 \label{sec:hook:outgoing} |
bos@40 | 1153 |
bos@40 | 1154 This hook is run after a group of changesets has been propagated out |
bos@40 | 1155 of this repository, for example by a \hgcmd{push} or \hgcmd{bundle} |
bos@40 | 1156 command. |
bos@40 | 1157 |
bos@41 | 1158 One possible use for this hook is to notify administrators that |
bos@41 | 1159 changes have been pulled. |
bos@41 | 1160 |
bos@40 | 1161 Parameters to this hook: |
bos@40 | 1162 \begin{itemize} |
bos@40 | 1163 \item[\texttt{node}] A changeset ID. The changeset ID of the first |
bos@40 | 1164 changeset of the group that was sent. |
bos@62 | 1165 \item[\texttt{source}] A string. The source of the of the operation |
bos@62 | 1166 (see section~\ref{sec:hook:sources}). If a remote client pulled |
bos@62 | 1167 changes from this repository, \texttt{source} will be |
bos@62 | 1168 \texttt{serve}. If the client that obtained changes from this |
bos@62 | 1169 repository was local, \texttt{source} will be \texttt{bundle}, |
bos@62 | 1170 \texttt{pull}, or \texttt{push}, depending on the operation the |
bos@62 | 1171 client performed. |
bos@62 | 1172 \item[\texttt{url}] A URL. The location of the remote repository, if |
bos@62 | 1173 known. See section~\ref{sec:hook:url} for more information. |
bos@40 | 1174 \end{itemize} |
bos@40 | 1175 |
bos@40 | 1176 See also: \hook{preoutgoing} (section~\ref{sec:hook:preoutgoing}) |
bos@40 | 1177 |
bos@64 | 1178 \subsection{\hook{prechangegroup}---before starting to add remote changesets} |
bos@40 | 1179 \label{sec:hook:prechangegroup} |
bos@40 | 1180 |
bos@41 | 1181 This controlling hook is run before Mercurial begins to add a group of |
bos@41 | 1182 changesets from another repository. |
bos@41 | 1183 |
bos@41 | 1184 This hook does not have any information about the changesets to be |
bos@41 | 1185 added, because it is run before transmission of those changesets is |
bos@41 | 1186 allowed to begin. If this hook fails, the changesets will not be |
bos@41 | 1187 transmitted. |
bos@41 | 1188 |
bos@41 | 1189 One use for this hook is to prevent external changes from being added |
bos@62 | 1190 to a repository. For example, you could use this to ``freeze'' a |
bos@62 | 1191 server-hosted branch temporarily or permanently so that users cannot |
bos@62 | 1192 push to it, while still allowing a local administrator to modify the |
bos@62 | 1193 repository. |
bos@62 | 1194 |
bos@62 | 1195 Parameters to this hook: |
bos@62 | 1196 \begin{itemize} |
bos@62 | 1197 \item[\texttt{source}] A string. The source of these changes. See |
bos@62 | 1198 section~\ref{sec:hook:sources} for details. |
bos@62 | 1199 \item[\texttt{url}] A URL. The location of the remote repository, if |
bos@62 | 1200 known. See section~\ref{sec:hook:url} for more information. |
bos@62 | 1201 \end{itemize} |
bos@40 | 1202 |
bos@40 | 1203 See also: \hook{changegroup} (section~\ref{sec:hook:changegroup}), |
bos@40 | 1204 \hook{incoming} (section~\ref{sec:hook:incoming}), , |
bos@40 | 1205 \hook{pretxnchangegroup} (section~\ref{sec:hook:pretxnchangegroup}) |
bos@40 | 1206 |
bos@64 | 1207 \subsection{\hook{precommit}---before starting to commit a changeset} |
bos@40 | 1208 \label{sec:hook:precommit} |
bos@40 | 1209 |
bos@41 | 1210 This hook is run before Mercurial begins to commit a new changeset. |
bos@41 | 1211 It is run before Mercurial has any of the metadata for the commit, |
bos@41 | 1212 such as the files to be committed, the commit message, or the commit |
bos@41 | 1213 date. |
bos@41 | 1214 |
bos@41 | 1215 One use for this hook is to disable the ability to commit new |
bos@41 | 1216 changesets, while still allowing incoming changesets. Another is to |
bos@41 | 1217 run a build or test, and only allow the commit to begin if the build |
bos@41 | 1218 or test succeeds. |
bos@40 | 1219 |
bos@40 | 1220 Parameters to this hook: |
bos@40 | 1221 \begin{itemize} |
bos@40 | 1222 \item[\texttt{parent1}] A changeset ID. The changeset ID of the first |
bos@40 | 1223 parent of the working directory. |
bos@40 | 1224 \item[\texttt{parent2}] A changeset ID. The changeset ID of the second |
bos@40 | 1225 parent of the working directory. |
bos@40 | 1226 \end{itemize} |
bos@40 | 1227 If the commit proceeds, the parents of the working directory will |
bos@40 | 1228 become the parents of the new changeset. |
bos@40 | 1229 |
bos@40 | 1230 See also: \hook{commit} (section~\ref{sec:hook:commit}), |
bos@40 | 1231 \hook{pretxncommit} (section~\ref{sec:hook:pretxncommit}) |
bos@40 | 1232 |
bos@64 | 1233 \subsection{\hook{preoutgoing}---before starting to propagate changesets} |
bos@40 | 1234 \label{sec:hook:preoutgoing} |
bos@40 | 1235 |
bos@40 | 1236 This hook is invoked before Mercurial knows the identities of the |
bos@40 | 1237 changesets to be transmitted. |
bos@40 | 1238 |
bos@41 | 1239 One use for this hook is to prevent changes from being transmitted to |
bos@41 | 1240 another repository. |
bos@41 | 1241 |
bos@40 | 1242 Parameters to this hook: |
bos@40 | 1243 \begin{itemize} |
bos@40 | 1244 \item[\texttt{source}] A string. The source of the operation that is |
bos@62 | 1245 attempting to obtain changes from this repository (see |
bos@62 | 1246 section~\ref{sec:hook:sources}). See the documentation for the |
bos@62 | 1247 \texttt{source} parameter to the \hook{outgoing} hook, in |
bos@62 | 1248 section~\ref{sec:hook:outgoing}, for possible values of this |
bos@62 | 1249 parameter. |
bos@62 | 1250 \item[\texttt{url}] A URL. The location of the remote repository, if |
bos@62 | 1251 known. See section~\ref{sec:hook:url} for more information. |
bos@40 | 1252 \end{itemize} |
bos@40 | 1253 |
bos@40 | 1254 See also: \hook{outgoing} (section~\ref{sec:hook:outgoing}) |
bos@40 | 1255 |
bos@64 | 1256 \subsection{\hook{pretag}---before tagging a changeset} |
bos@40 | 1257 \label{sec:hook:pretag} |
bos@40 | 1258 |
bos@41 | 1259 This controlling hook is run before a tag is created. If the hook |
bos@41 | 1260 succeeds, creation of the tag proceeds. If the hook fails, the tag is |
bos@41 | 1261 not created. |
bos@41 | 1262 |
bos@40 | 1263 Parameters to this hook: |
bos@40 | 1264 \begin{itemize} |
bos@40 | 1265 \item[\texttt{local}] A boolean. Whether the tag is local to this |
bos@244 | 1266 repository instance (i.e.~stored in \sfilename{.hg/localtags}) or |
bos@244 | 1267 managed by Mercurial (stored in \sfilename{.hgtags}). |
bos@40 | 1268 \item[\texttt{node}] A changeset ID. The ID of the changeset to be tagged. |
bos@40 | 1269 \item[\texttt{tag}] A string. The name of the tag to be created. |
bos@40 | 1270 \end{itemize} |
bos@40 | 1271 |
bos@40 | 1272 If the tag to be created is revision-controlled, the \hook{precommit} |
bos@40 | 1273 and \hook{pretxncommit} hooks (sections~\ref{sec:hook:commit} |
bos@40 | 1274 and~\ref{sec:hook:pretxncommit}) will also be run. |
bos@40 | 1275 |
bos@40 | 1276 See also: \hook{tag} (section~\ref{sec:hook:tag}) |
bos@40 | 1277 |
bos@64 | 1278 \subsection{\hook{pretxnchangegroup}---before completing addition of |
bos@64 | 1279 remote changesets} |
bos@40 | 1280 \label{sec:hook:pretxnchangegroup} |
bos@40 | 1281 |
bos@41 | 1282 This controlling hook is run before a transaction---that manages the |
bos@41 | 1283 addition of a group of new changesets from outside the |
bos@41 | 1284 repository---completes. If the hook succeeds, the transaction |
bos@41 | 1285 completes, and all of the changesets become permanent within this |
bos@41 | 1286 repository. If the hook fails, the transaction is rolled back, and |
bos@41 | 1287 the data for the changesets is erased. |
bos@41 | 1288 |
bos@41 | 1289 This hook can access the metadata associated with the almost-added |
bos@41 | 1290 changesets, but it should not do anything permanent with this data. |
bos@41 | 1291 It must also not modify the working directory. |
bos@41 | 1292 |
bos@41 | 1293 While this hook is running, if other Mercurial processes access this |
bos@41 | 1294 repository, they will be able to see the almost-added changesets as if |
bos@41 | 1295 they are permanent. This may lead to race conditions if you do not |
bos@41 | 1296 take steps to avoid them. |
bos@41 | 1297 |
bos@41 | 1298 This hook can be used to automatically vet a group of changesets. If |
bos@41 | 1299 the hook fails, all of the changesets are ``rejected'' when the |
bos@41 | 1300 transaction rolls back. |
bos@41 | 1301 |
bos@62 | 1302 Parameters to this hook: |
bos@62 | 1303 \begin{itemize} |
bos@62 | 1304 \item[\texttt{node}] A changeset ID. The changeset ID of the first |
bos@62 | 1305 changeset in the group that was added. All changesets between this |
bos@62 | 1306 and \index{tags!\texttt{tip}}\texttt{tip}, inclusive, were added by |
bos@62 | 1307 a single \hgcmd{pull}, \hgcmd{push} or \hgcmd{unbundle}. |
bos@62 | 1308 \item[\texttt{source}] A string. The source of these changes. See |
bos@62 | 1309 section~\ref{sec:hook:sources} for details. |
bos@62 | 1310 \item[\texttt{url}] A URL. The location of the remote repository, if |
bos@62 | 1311 known. See section~\ref{sec:hook:url} for more information. |
bos@62 | 1312 \end{itemize} |
bos@40 | 1313 |
bos@40 | 1314 See also: \hook{changegroup} (section~\ref{sec:hook:changegroup}), |
bos@40 | 1315 \hook{incoming} (section~\ref{sec:hook:incoming}), |
bos@40 | 1316 \hook{prechangegroup} (section~\ref{sec:hook:prechangegroup}) |
bos@40 | 1317 |
bos@64 | 1318 \subsection{\hook{pretxncommit}---before completing commit of new changeset} |
bos@40 | 1319 \label{sec:hook:pretxncommit} |
bos@40 | 1320 |
bos@41 | 1321 This controlling hook is run before a transaction---that manages a new |
bos@41 | 1322 commit---completes. If the hook succeeds, the transaction completes |
bos@41 | 1323 and the changeset becomes permanent within this repository. If the |
bos@41 | 1324 hook fails, the transaction is rolled back, and the commit data is |
bos@41 | 1325 erased. |
bos@41 | 1326 |
bos@41 | 1327 This hook can access the metadata associated with the almost-new |
bos@41 | 1328 changeset, but it should not do anything permanent with this data. It |
bos@41 | 1329 must also not modify the working directory. |
bos@41 | 1330 |
bos@41 | 1331 While this hook is running, if other Mercurial processes access this |
bos@41 | 1332 repository, they will be able to see the almost-new changeset as if it |
bos@41 | 1333 is permanent. This may lead to race conditions if you do not take |
bos@41 | 1334 steps to avoid them. |
bos@41 | 1335 |
bos@62 | 1336 Parameters to this hook: |
bos@62 | 1337 \begin{itemize} |
bos@62 | 1338 \item[\texttt{node}] A changeset ID. The changeset ID of the newly |
bos@62 | 1339 committed changeset. |
bos@62 | 1340 \item[\texttt{parent1}] A changeset ID. The changeset ID of the first |
bos@62 | 1341 parent of the newly committed changeset. |
bos@62 | 1342 \item[\texttt{parent2}] A changeset ID. The changeset ID of the second |
bos@62 | 1343 parent of the newly committed changeset. |
bos@62 | 1344 \end{itemize} |
bos@40 | 1345 |
bos@40 | 1346 See also: \hook{precommit} (section~\ref{sec:hook:precommit}) |
bos@40 | 1347 |
bos@64 | 1348 \subsection{\hook{preupdate}---before updating or merging working directory} |
bos@40 | 1349 \label{sec:hook:preupdate} |
bos@40 | 1350 |
bos@41 | 1351 This controlling hook is run before an update or merge of the working |
bos@41 | 1352 directory begins. It is run only if Mercurial's normal pre-update |
bos@41 | 1353 checks determine that the update or merge can proceed. If the hook |
bos@41 | 1354 succeeds, the update or merge may proceed; if it fails, the update or |
bos@41 | 1355 merge does not start. |
bos@41 | 1356 |
bos@40 | 1357 Parameters to this hook: |
bos@40 | 1358 \begin{itemize} |
bos@40 | 1359 \item[\texttt{parent1}] A changeset ID. The ID of the parent that the |
bos@40 | 1360 working directory is to be updated to. If the working directory is |
bos@40 | 1361 being merged, it will not change this parent. |
bos@40 | 1362 \item[\texttt{parent2}] A changeset ID. Only set if the working |
bos@40 | 1363 directory is being merged. The ID of the revision that the working |
bos@40 | 1364 directory is being merged with. |
bos@40 | 1365 \end{itemize} |
bos@40 | 1366 |
bos@40 | 1367 See also: \hook{update} (section~\ref{sec:hook:update}) |
bos@40 | 1368 |
bos@64 | 1369 \subsection{\hook{tag}---after tagging a changeset} |
bos@40 | 1370 \label{sec:hook:tag} |
bos@40 | 1371 |
bos@41 | 1372 This hook is run after a tag has been created. |
bos@41 | 1373 |
bos@62 | 1374 Parameters to this hook: |
bos@62 | 1375 \begin{itemize} |
bos@62 | 1376 \item[\texttt{local}] A boolean. Whether the new tag is local to this |
bos@244 | 1377 repository instance (i.e.~stored in \sfilename{.hg/localtags}) or |
bos@244 | 1378 managed by Mercurial (stored in \sfilename{.hgtags}). |
bos@62 | 1379 \item[\texttt{node}] A changeset ID. The ID of the changeset that was |
bos@62 | 1380 tagged. |
bos@62 | 1381 \item[\texttt{tag}] A string. The name of the tag that was created. |
bos@62 | 1382 \end{itemize} |
bos@40 | 1383 |
bos@40 | 1384 If the created tag is revision-controlled, the \hook{commit} hook |
bos@41 | 1385 (section~\ref{sec:hook:commit}) is run before this hook. |
bos@40 | 1386 |
bos@40 | 1387 See also: \hook{pretag} (section~\ref{sec:hook:pretag}) |
bos@40 | 1388 |
bos@64 | 1389 \subsection{\hook{update}---after updating or merging working directory} |
bos@40 | 1390 \label{sec:hook:update} |
bos@40 | 1391 |
bos@41 | 1392 This hook is run after an update or merge of the working directory |
bos@41 | 1393 completes. Since a merge can fail (if the external \command{hgmerge} |
bos@41 | 1394 command fails to resolve conflicts in a file), this hook communicates |
bos@41 | 1395 whether the update or merge completed cleanly. |
bos@41 | 1396 |
bos@40 | 1397 \begin{itemize} |
bos@40 | 1398 \item[\texttt{error}] A boolean. Indicates whether the update or |
bos@40 | 1399 merge completed successfully. |
bos@40 | 1400 \item[\texttt{parent1}] A changeset ID. The ID of the parent that the |
bos@40 | 1401 working directory was updated to. If the working directory was |
bos@40 | 1402 merged, it will not have changed this parent. |
bos@40 | 1403 \item[\texttt{parent2}] A changeset ID. Only set if the working |
bos@40 | 1404 directory was merged. The ID of the revision that the working |
bos@40 | 1405 directory was merged with. |
bos@40 | 1406 \end{itemize} |
bos@40 | 1407 |
bos@40 | 1408 See also: \hook{preupdate} (section~\ref{sec:hook:preupdate}) |
bos@34 | 1409 |
bos@34 | 1410 %%% Local Variables: |
bos@34 | 1411 %%% mode: latex |
bos@34 | 1412 %%% TeX-master: "00book" |
bos@34 | 1413 %%% End: |