6.7 KiB
hook propagation in gitolite
Some users like to know how hooks propagate, and when, and why there appear to be two places to put them, and so on. I'll try and set out the logic here.
Note: This is not the document to read if you just want to install a new custom hook; treat it as more "theory" than "lab". (Here is the "lab" version!)
In this document:
hooks used by gitolite
Gitolite uses only 2 hooks. All repos have an update
hook, without
which there is no write-level access control (per-branch permissions). The
special gitolite-admin repo has a special post-update
hook, which is
required to do its, umm, special things, like running the "compile" script,
etc.
In addition there is a "sentinel file" -- an empty file called "gitolite-hooked". We'll see later what this does.
The final objective of all this is that each repo's hooks/
directory should
get all the hooks that it is meant to get.
where do I (the admin) put the hooks?
In general, all hooks go into the hooks/common
directory. Only the
special post-update
hook meant for the admin repo goes into
hooks/gitolite-admin
.
Now we'll discuss the locations of these hooks/common
and
hooks/gitolite-admin
directories. This depends on which install method you
used.
(Please refer to doc/1-INSTALL.mkd for what these "methods" are).
the GL_PACKAGE_HOOKS
directory
You might recall that the "root", and "non-root" methods run a command called
gl-system-install
, the third argument of which is some directory of your
choice (like maybe /usr/share/gitolite/hooks
). Even though it is not
necessary to know this, internally this becomes the value of the
$GL_PACKAGE_HOOKS
variable, so in this document we will refer to that
variable instead of the location (because you might choose any location you
like for it).
The "package" method also has the same property, except that the packager has
already decided what that location is, and the package creation/install
process does the equivalent of gl-system-install
.
So now we know there's a location called $GL_PACKAGE_HOOKS
where you can
place your hooks.
the $HOME/.gitolite
directory
You might also recall that, in these three methods, each hosting user has
to run gl-setup
. This sets up, among other things, $HOME/.gitolite
directory, which also contains a hooks/
directory.
So now there are two places you can put your hooks, apparently.
why two places?
Just think of the "package" and "root" methods for now, even if you're using the "non-root" method.
In these two methods, it is reasonable to assume that the entire site (or
server) has certain policies that they want to implement using hooks. They
want to enforce these hooks on each hosting user. These hooks go into
$GL_PACKAGE_HOOKS
.
Each hosting user then has the discretion to add his own hooks (modulo name
clashes, which may necessitate hook chaining, etc., like we already do for the
hooks that gitolite cares about). He adds these hooks to his
$HOME/.gitolite/hooks
directory.
When hooks propagate, the ones in $GL_PACKAGE_HOOKS
override/overwrite the
ones in $HOME/.gitolite/hooks
. Otherwise it wouldn't make sense; you
wouldn't be able to enforce site-wide hooks.
[NOTE: due to a minor quirk, the site-wide hooks in $GL_PACKAGE_HOOKS
also
get copied to $HOME/.gitolite/hooks
when you "install". I need to fix and
thoroughly test this later; for now, just ignore the extra files you see in
there; they're harmless/redundant (TODO)]
special case: the "non-root" method
This method was created later, just piggy-backing on everything that already
existed to cater to the "package" and "root" methods. In this method, the
$GL_PACKAGE_HOOKS
is as accessible or under your control as
$HOME/.gitolite
, so it doesn't matter where you put your hooks.
when do hooks propagate?
First: realise that gitolite wants to make sure that all the hooks in your
hooks/common
directory get copied (symlinked, actually) to every repo that
gets created. Not doing so is generally a security risk; because the
primary purpose of gitolite is access control, people generally want hooks
to run.
Here's how/when hooks are created/propagated:
-
anytime you do an install, gitolite trawls through all existing repos (using the unix
find
command) and force-links all the hooks in all the repos so they all get the latest and greatest hooks. -
anytime you do a "compile" (meaning push changes to the admin repo), gitolite looks through all the repos named in the config. It first checks if the repo exists, creating it if needed. It then looks for a sentinel file called "gitolite-hooked" (an empty file in the hooks directory). If it doesn't find it, it will assume that hooks need to be propagated.
This is because people often copy a repo from elsewhere, add it to the config, and expect things to work. Without this step, those repos don't get the hooks, which is bad -- the access control would have failed silently!
-
anytime a new repo is created, the same force-linking of hooks happens. The 3 places a new repo is created are:
-
the "compile" case mentioned above, where the admin added a normal repo to the config and pushed
-
the wildrepos case, where you have "C" permissions and the repo does not already exist
-
the
fork
command incontrib/adc
. In this case the hooks are explicitly copied from the source repo using thecp
command, not using the code internal to gitolite.
-
For people who do not want certain hooks to run for certain repos, one simple
solution that will work right now is to check the value of $GL_REPO
at the
start of the hook, and exit 0
based on what it contains/matches.