6e29365316
I got tired of being told "TL;DR". Now the online versions of most documents fit on a page or two, or at least most of them do. The rest has been split out (and you can see the links to the split out sections right where the text is in the raw Markdown). This is much more pleasant to read, and I've improved the linking so it's much less effort for me to keep the links correct.
134 lines
5.7 KiB
Markdown
134 lines
5.7 KiB
Markdown
# F=hook_prop 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][customhooks] is the
|
|
"lab" version!)
|
|
|
|
## 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][install] 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:
|
|
|
|
1. 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.
|
|
|
|
2. 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!
|
|
|
|
3. 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 in `contrib/adc`. In this case the hooks are
|
|
explicitly copied from the source repo using the `cp` 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.
|
|
|