gitolite/doc/dev-notes.mkd
Sitaram Chamarty 4373c5c74c GL_BINDIR2 becomes LOCAL_CODE, allows hook propagation also...
plus a bunch of doc changes
2012-06-14 19:22:12 +05:30

162 lines
6 KiB
Markdown

# notes for developers
[[TOC]]
----
Gitolite has a huge bunch of existing features that gradually need to moved
over. Plus you may want to write your own programs to interact with it.
**This document is about *writing* hooks, commands, triggers, VREFS, and sugar
scripts. *Installing* them, including "where and how", is described
[here][localcode]**.
## environment variables and other inputs
In general, the following environment variables should always be available:
GL_BINDIR
GL_REPO_BASE
GL_ADMIN_BASE
Commands invoked by a remote client will also have `GL_USER` set. Hooks will
have `GL_REPO` also set.
Finally, note that triggers get a lot of relevant information from gitolite as
arguments; see [here][triggers] for details.
## APIs
### the shell API
The following commands exist to help you write shell scripts that interact
easily with gitolite. Each of them responds to `-h` so please run that for
more info.
* `gitolite access` to check access rights given repo, user, type of access
(R, W, ...) and refname (optional). Example use: src/commands/desc.
* `gitolite creator` to get/check the creator of a repo. Example use:
src/commands/desc.
* `gitolite git-config` to check gitolite options or git config variables
directly from gitolite's "compiled" output, (i.e., without looking at the
actual `repo.git/config` file or using the `git config` command). Example
use: src/triggers/post-compile/update-gitweb-access-list.
* `gitolite query-rc` to check the value of an RC variable. Example use:
src/commands/desc.
In addition, you can also look at the comments in src/lib/Gitolite/Easy.pm
(the perl API module) for ideas.
### the perl API
...is implemented by Gitolite::Easy; the comments in src/lib/Gitolite/Easy.pm
serve as documentation.
## writing your own...
### ...commands
Commands are standalone programs, in any language you like. They simply
receive the arguments you append. In addition, the env var `GL_USER` is
available if it is being run remotely. src/commands/desc is the best example
at present.
### ...hooks
#### anything but the update hook
If you want to add any hook other than the update hook, 'man githooks' is all
you need.
#### update hook
If you want to add additional `update` hook functionality, do this:
* Write and test your update hook separately from gitolite.
* Now add the code as a VREF (see [here][localcode] for details). Let's say
you called it "foo".
* To call your new update hook to all accesses for all repos, add this to
the end of your conf file:
repo @all
- VREF/foo = @all
As you probably guessed, you can make your additional update hooks more
selective, applying them only to some repos / users / combinations.
Note: a normal update hook expects 3 arguments (ref, old SHA, new SHA). A
VREF will get those three, followed by at least 4 more. Your VREF should just
ignore the extra args.
### ...trigger programs
Trigger programs run at specific points in gitolite's execution, with specific
arguments being passed to them. See the [triggers][] page for details.
You can write programs that are both manually runnable as well as callable by
trigger events, especially if they don't *need* any arguments.
### ..."sugar"
Syntactic sugar helpers are NOT complete, standalone, programs. They must
include a perl sub called `sugar_script` that takes in a listref, and returns
a listref. The listrefs point to a list that contains the entire conf file
(with all [include][] processing already done). You create a new list with
contents modified as you like and return a ref to it.
There are a couple of examples in src/syntactic-sugar.
## appendix 1: notes on the INPUT trigger
Note: some of this won't make sense if you haven't read about [triggers][].
The INPUT trigger sequence is designed to set or change environment variables
or the argument list. (Side note: this means INPUT triggers have to be
written as perl modules; they cannot be standalone scripts). This is a very
powerful idea so an extended description may be useful.
Sshd invokes gitolite-shell with the SSH\_ORIGINAL\_COMMAND env var containing
the git/gitolite command and one argument: the gitolite username.
* see [this][glssh] for details on the latter
* the *first* thing gitolite does in smart http mode is to use the
REMOTE\_USER and the CGI variables that apache provides to *construct*
a fake argument list and a fake SSH\_ORIGINAL\_COMMAND env var, so the
rest of the code can stay the same
The INPUT trigger is then run. The purpose of the input trigger is to ensure
that the first argument *is* the gitolite username, and that the
SSH\_ORIGINAL\_COMMAND env var contains the actual command to execute. It can
also be used to set up any other environment variables that you may decide you
need.
Wait... didn't we say that's what gitolite-shell gets anyway, just now?
Well, we lied a bit there; it's not always true!
For example, if [this][giving-shell] feature is used, the first argument *may*
be "-s", with the username in the *second* argument. Shell.pm deals with
that. <font color="gray">(Order matters. If you use this feature, put the
`'Shell::input',` line ahead of the others, since it is the only one prepared
to deal with username not being the first argument).</font>
If you look at CpuTime.pm, you'll see that it's `input()` function doesn't set
or change anything, but does set a package variable to record the start time.
Later, when the same module's `post_git()` function is invoked, it uses this
variable to determine elapsed time.
*(This is a very nice and simple example of how you can implement features by
latching onto multiple events and sharing data to do something)*.
You can even change the reponame the user sees, behind his back. Alias.pm
handles that.
Finally, as an exercise for the reader, consider how you would create a brand
new env var that contains the *comment* field of the ssh pubkey that was used
to gain access, using the information [here][kfn].