gitolite/doc/dev-notes.mkd

6.2 KiB

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. (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).

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].