166 lines
6.2 KiB
Markdown
166 lines
6.2 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.
|
|
|
|
Here are some random notes on developing hooks, commands, triggers, and sugar
|
|
scripts.
|
|
|
|
## 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...
|
|
|
|
### ...hooks
|
|
|
|
#### anything but the update hook
|
|
|
|
If you want to add your own hook, it's easy as long as it's not the 'update'
|
|
hook. Just add it to `$HOME/.gitolite/hooks/common` and run `gitolite setup`.
|
|
|
|
The rest is between you and 'man githooks' :-)
|
|
|
|
#### 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 to src/VREF. Let's say it is called "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 now 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.
|
|
|
|
### ...commands
|
|
|
|
You can add your own commands. You can run them on the server (example,
|
|
`gitolite access`). Then you can enable certain commands to be allowed to run
|
|
by a remote user by adding them to the "COMMANDS" hash of the [rc][] file.
|
|
|
|
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.
|
|
|
|
### ...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].
|