GL_BINDIR2 becomes LOCAL_CODE, allows hook propagation also...
plus a bunch of doc changes
This commit is contained in:
parent
3c0f177481
commit
4373c5c74c
107
doc/cust.mkd
107
doc/cust.mkd
|
@ -5,7 +5,9 @@ not considered "core". This keeps the core simpler, and allows you to enhance
|
||||||
gitolite for your own purposes without too much fuss. (As an extreme example,
|
gitolite for your own purposes without too much fuss. (As an extreme example,
|
||||||
even mirroring is not in core now!)
|
even mirroring is not in core now!)
|
||||||
|
|
||||||
(Also, please see the [developer notes][dev-notes] page).
|
This document will tell you about the types of non-core programs, and
|
||||||
|
how/where to install your own. (Actually *writing* the code is described in
|
||||||
|
the [developer notes][dev-notes] page).
|
||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
|
@ -13,13 +15,13 @@ even mirroring is not in core now!)
|
||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
## types of non-core programs
|
## introduction
|
||||||
|
|
||||||
There are 5 basic types of non-core programs.
|
There are 5 basic types of non-core programs.
|
||||||
|
|
||||||
* *Commands* can be run from the shell command line. Among those, the ones
|
* *Commands* can be run from the shell command line. Among those, the ones
|
||||||
listed in the COMMANDS hash of the rc file can also be run remotely.
|
listed in the COMMANDS hash of the rc file can also be run remotely.
|
||||||
* *Hooks* are standard git hooks; see below.
|
* *Hooks* are standard git hooks.
|
||||||
* *Sugar scripts* change the conf language for your convenience. The word
|
* *Sugar scripts* change the conf language for your convenience. The word
|
||||||
sugar comes from "syntactic sugar".
|
sugar comes from "syntactic sugar".
|
||||||
* *Triggers* are to gitolite what hooks are to git. I just chose a
|
* *Triggers* are to gitolite what hooks are to git. I just chose a
|
||||||
|
@ -29,9 +31,76 @@ There are 5 basic types of non-core programs.
|
||||||
[Here][non-core] is a list of non-core programs shipped with gitolite, with
|
[Here][non-core] is a list of non-core programs shipped with gitolite, with
|
||||||
some description of each.
|
some description of each.
|
||||||
|
|
||||||
## #commands gitolite "commands"
|
## locations
|
||||||
|
|
||||||
Gitolite comes with several commands that users can run. Remote users run the
|
### default/primary location of non-core programs
|
||||||
|
|
||||||
|
Regardless of how you installed gitolite, `gitolite query-rc GL_BINDIR` will
|
||||||
|
tell you where the programs reside. Within that directory, the locations of
|
||||||
|
non-core programs are:
|
||||||
|
|
||||||
|
* `commands` for commands.
|
||||||
|
* `syntactic-sugar` for sugar scripts.
|
||||||
|
* `triggers` and `lib/Gitolite/Triggers` for triggers ([this][triggers] will
|
||||||
|
explain the difference).
|
||||||
|
* `VREF` for [VREFs][vref].
|
||||||
|
|
||||||
|
### #localcode alternate location -- the `LOCAL_CODE` rc variable
|
||||||
|
|
||||||
|
If you want to add new non-core programs to your installation, or override the
|
||||||
|
shipped non-core programs with your own versions, it's easy enough to simply
|
||||||
|
copy your programs to the appropriate directory above, but then they'd get
|
||||||
|
wiped out on the next upgrade.
|
||||||
|
|
||||||
|
A simple, "git-ish", method is to maintain a "local" branch in your clone of
|
||||||
|
the gitolite source repo and make your changes there. Maintain them using
|
||||||
|
rebase or merge when you 'git pull' gitolite itself, then use the rebased or
|
||||||
|
merged "local" as the source for your gitolite upgrades. Works very nicely,
|
||||||
|
and uses nothing but your git knowledge.
|
||||||
|
|
||||||
|
Sadly, it doesn't work for people installing from RPMs/DEBs; their "primary
|
||||||
|
location" has already been setup, so any site-local customisations have to be
|
||||||
|
done elsewhere.
|
||||||
|
|
||||||
|
This is where `LOCAL_CODE` comes in. If you define the `LOCAL_CODE` rc
|
||||||
|
variable, then its value (**please use a FULL path**) describes a location
|
||||||
|
where you can have any or all of these subdirectories:
|
||||||
|
|
||||||
|
* `commands`
|
||||||
|
* `hooks/common`
|
||||||
|
* `syntactic-sugar`
|
||||||
|
* `triggers` and `lib/Gitolite/Triggers`
|
||||||
|
* `VREF`
|
||||||
|
|
||||||
|
You might have noticed there's a new `hooks/common` directory here so you can
|
||||||
|
add hooks also using this mechanism. Unlike the rest of the directories,
|
||||||
|
adding new hooks to `hooks/common` requires that you follow up with `gitolite
|
||||||
|
setup`, or at least `gitolite setup --hooks-only`.
|
||||||
|
|
||||||
|
### #pushcode managing custom code via the gitolite-admin repo
|
||||||
|
|
||||||
|
The location given in `LOCAL_CODE` could be anywhere on disk.
|
||||||
|
|
||||||
|
However, if you point it to someplace inside `$GL_ADMIN_BASE` (i.e.,
|
||||||
|
`$HOME/.gitolite`), then you can version those programs using the
|
||||||
|
gitolite-admin repo.
|
||||||
|
|
||||||
|
I suggest using a directory called "local-code" within the gitolite-admin repo
|
||||||
|
that contains as much of the above directory structure you need. If you do
|
||||||
|
that, then this is what you'd have in the rc file:
|
||||||
|
|
||||||
|
LOCAL_CODE => "$ENV{HOME}/.gitolite/local-code",
|
||||||
|
|
||||||
|
When you do this, gitolite takes care of everything automatically, including
|
||||||
|
running `gitolite setup --hooks-only` when you change any hooks and push.
|
||||||
|
**However, if you do this, anyone who can push changes to the admin repo will
|
||||||
|
effectively be able to run any arbitrary command on the server.**
|
||||||
|
|
||||||
|
## types of non-core programs
|
||||||
|
|
||||||
|
### #commands gitolite "commands"
|
||||||
|
|
||||||
|
Gitolite comes with several commands that users can run. Remote users run
|
||||||
commands by saying:
|
commands by saying:
|
||||||
|
|
||||||
ssh git@host command-name [args...]
|
ssh git@host command-name [args...]
|
||||||
|
@ -46,23 +115,25 @@ checking for the presence of env var `GL_USER`.
|
||||||
You can get a **list of available commands** by using the `help` command.
|
You can get a **list of available commands** by using the `help` command.
|
||||||
Naturally, a remote user will see a much smaller list than the server user.
|
Naturally, a remote user will see a much smaller list than the server user.
|
||||||
|
|
||||||
You add commands to the "allowed from remote" list by adding its name (or
|
You allow a command to be run from remote clients by adding its name to (or
|
||||||
uncommenting it if it's already added but commented out) to the COMMANDS hash
|
uncommenting it if it's already added but commented out) the COMMANDS hash in
|
||||||
in the [rc][] file.
|
the [rc][] file.
|
||||||
|
|
||||||
If you write your own commands, put them in src/commands.
|
### #hooks hooks and gitolite
|
||||||
|
|
||||||
## #hooks hooks and gitolite
|
You can install any hooks except these:
|
||||||
|
|
||||||
Gitolite uses the `update` hook for all repos. In addition, it uses the
|
* (all repos) gitolite reserves the `update` hook. See the "update hook"
|
||||||
`post-update` hook for the gitolite-admin repo.
|
section in [dev-notes][] if you want additional update hook functionality.
|
||||||
|
|
||||||
If you want to add your own hook, it's easy as long as it's not the 'update'
|
* (gitolite-admin repo only) gitolite reserves the `post-update` hook.
|
||||||
hook. Just add it to `$HOME/.gitolite/hooks/common` and run `gitolite setup`.
|
|
||||||
|
|
||||||
The rest is between you and 'man githooks' :-)
|
How/where to install them is described in detail in the "locations" section
|
||||||
|
above, especially [this][localcode] and [this][pushcode]. The summary is that
|
||||||
|
you put them in the "hooks/common" sub-directory within the directory whose
|
||||||
|
name is given in the `LOCAL_CODE` rc variable.
|
||||||
|
|
||||||
## #sugar syntactic sugar
|
### #sugar syntactic sugar
|
||||||
|
|
||||||
Sugar scripts help you change the perceived syntax of the conf language. The
|
Sugar scripts help you change the perceived syntax of the conf language. The
|
||||||
base syntax of the language is very simple, so sugar scripts take something
|
base syntax of the language is very simple, so sugar scripts take something
|
||||||
|
@ -74,10 +145,10 @@ lines), while the parser in the core gitolite engine does not change.
|
||||||
If you want to write your own sugar scripts, please read the "your own sugar"
|
If you want to write your own sugar scripts, please read the "your own sugar"
|
||||||
section in [dev-notes][] first then email me.
|
section in [dev-notes][] first then email me.
|
||||||
|
|
||||||
## triggers
|
### triggers
|
||||||
|
|
||||||
Triggers have their own [document][triggers].
|
Triggers have their own [document][triggers].
|
||||||
|
|
||||||
## VREFs
|
### VREFs
|
||||||
|
|
||||||
VREFs also have their own [document][vref].
|
VREFs also have their own [document][vref].
|
||||||
|
|
|
@ -7,8 +7,9 @@
|
||||||
Gitolite has a huge bunch of existing features that gradually need to moved
|
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.
|
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
|
**This document is about *writing* hooks, commands, triggers, VREFS, and sugar
|
||||||
scripts.
|
scripts. *Installing* them, including "where and how", is described
|
||||||
|
[here][localcode]**.
|
||||||
|
|
||||||
## environment variables and other inputs
|
## environment variables and other inputs
|
||||||
|
|
||||||
|
@ -56,14 +57,19 @@ serve as documentation.
|
||||||
|
|
||||||
## writing your own...
|
## 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
|
### ...hooks
|
||||||
|
|
||||||
#### anything but the update hook
|
#### anything but the update hook
|
||||||
|
|
||||||
If you want to add your own hook, it's easy as long as it's not the 'update'
|
If you want to add any hook other than the update hook, 'man githooks' is all
|
||||||
hook. Just add it to `$HOME/.gitolite/hooks/common` and run `gitolite setup`.
|
you need.
|
||||||
|
|
||||||
The rest is between you and 'man githooks' :-)
|
|
||||||
|
|
||||||
#### update hook
|
#### update hook
|
||||||
|
|
||||||
|
@ -71,7 +77,8 @@ If you want to add additional `update` hook functionality, do this:
|
||||||
|
|
||||||
* Write and test your update hook separately from gitolite.
|
* Write and test your update hook separately from gitolite.
|
||||||
|
|
||||||
* Now add the code to src/VREF. Let's say it is called "foo".
|
* 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
|
* To call your new update hook to all accesses for all repos, add this to
|
||||||
the end of your conf file:
|
the end of your conf file:
|
||||||
|
@ -79,24 +86,13 @@ If you want to add additional `update` hook functionality, do this:
|
||||||
repo @all
|
repo @all
|
||||||
- VREF/foo = @all
|
- VREF/foo = @all
|
||||||
|
|
||||||
As you probably guessed, you can now make your additional update hooks more
|
As you probably guessed, you can make your additional update hooks more
|
||||||
selective, applying them only to some repos / users / combinations.
|
selective, applying them only to some repos / users / combinations.
|
||||||
|
|
||||||
Note: a normal update hook expects 3 arguments (ref, old SHA, new SHA). A
|
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
|
VREF will get those three, followed by at least 4 more. Your VREF should just
|
||||||
ignore the extra args.
|
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
|
||||||
|
|
||||||
Trigger programs run at specific points in gitolite's execution, with specific
|
Trigger programs run at specific points in gitolite's execution, with specific
|
||||||
|
|
|
@ -101,7 +101,7 @@
|
||||||
* the [subconf][] command
|
* the [subconf][] command
|
||||||
* ([link][partial-copy]: faking selective READ control)
|
* ([link][partial-copy]: faking selective READ control)
|
||||||
* using pubkeys obtained [from elsewhere][keysonly]
|
* using pubkeys obtained [from elsewhere][keysonly]
|
||||||
* [updating hooks][pushhook] via the admin repo
|
* ([link][pushcode]: updating code via the admin repo)
|
||||||
|
|
||||||
## interfacing with [external][] tools
|
## interfacing with [external][] tools
|
||||||
|
|
||||||
|
|
23
doc/rc.mkd
23
doc/rc.mkd
|
@ -98,24 +98,7 @@ information.
|
||||||
|
|
||||||
DEFAULT_ROLE_PERMS => "READERS \@all\nWRITERS \@senior_devs",
|
DEFAULT_ROLE_PERMS => "READERS \@all\nWRITERS \@senior_devs",
|
||||||
|
|
||||||
* `GL_BINDIR2`, string
|
* `LOCAL_CODE`, string
|
||||||
|
|
||||||
This is useful when you install gitolite system-wide, but want to add or
|
This is described in more detail [here][localcode]. Please be aware
|
||||||
override commands, VREFs, triggers, etc., by putting them somewhere in the
|
**this must be a FULL path**, not a relative path.
|
||||||
hosting user's home directory (i.e., without requiring root privileges).
|
|
||||||
|
|
||||||
Add a new variable `GL_BINDIR2` to the the rc file. Example:
|
|
||||||
|
|
||||||
GL_BINDIR2 => "$ENV{HOME}/gitolite/src2",
|
|
||||||
|
|
||||||
In that directory, create as much of the following directory structure as
|
|
||||||
you need to add your programs:
|
|
||||||
|
|
||||||
.
|
|
||||||
|-- commands
|
|
||||||
|-- lib
|
|
||||||
| `-- Gitolite
|
|
||||||
| `-- Triggers
|
|
||||||
|-- syntactic-sugar
|
|
||||||
|-- triggers
|
|
||||||
`-- VREF
|
|
||||||
|
|
|
@ -68,41 +68,3 @@ Then write a script that
|
||||||
|
|
||||||
Run this from cron or however you want.
|
Run this from cron or however you want.
|
||||||
|
|
||||||
## #pushhook updating hooks via the admin repo
|
|
||||||
|
|
||||||
Gitolite by default maintains the distinction between someone who can push to
|
|
||||||
the admin repo and someone who has shell access to the server. As a result,
|
|
||||||
you cannot change any hooks merely by pushing the admin repo.
|
|
||||||
|
|
||||||
But some people don't care about this and want to do it anyway. Besides,
|
|
||||||
there *is* one advantage: your hooks can also be versioned now.
|
|
||||||
|
|
||||||
So here's how to add/change hooks when you push the gitolite-admin repo:
|
|
||||||
|
|
||||||
1. Put all common hooks in a new directory called 'common-hooks'.
|
|
||||||
|
|
||||||
2. Create a trigger program called 'propagate-hooks' in 'src/triggers' that
|
|
||||||
contains this:
|
|
||||||
|
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
cd $GL_ADMIN_BASE
|
|
||||||
cp -a common-hooks/* hooks/common
|
|
||||||
|
|
||||||
gitolite setup --hooks-only
|
|
||||||
|
|
||||||
3. Add this to the `POST_COMPILE` trigger list in the rc file.
|
|
||||||
|
|
||||||
And that should be it, pretty much.
|
|
||||||
|
|
||||||
If you have lots of repos this is inefficient -- because the hook fixup will
|
|
||||||
run on *any* change to the admin repo, even if the change has nothing to do
|
|
||||||
with hooks.
|
|
||||||
|
|
||||||
If you're concerned about this, put the script in 'src/commands' instead of
|
|
||||||
'src/triggers'. (You might want to add some access control; see other
|
|
||||||
commands for inspiration, but it's not really needed in this case).
|
|
||||||
|
|
||||||
Then, whenever any hooks have changed, the admin can run
|
|
||||||
|
|
||||||
ssh git@host propagate-hooks
|
|
||||||
|
|
|
@ -323,14 +323,13 @@ sub store_common {
|
||||||
$hook_reset++;
|
$hook_reset++;
|
||||||
}
|
}
|
||||||
|
|
||||||
# propagate user hooks
|
# propagate user-defined (custom) hooks to all repos
|
||||||
|
ln_sf( "$rc{LOCAL_CODE}/hooks/common", "*", "$repo.git/hooks" ) if $rc{LOCAL_CODE};
|
||||||
|
|
||||||
|
# override/propagate gitolite defined hooks for all repos
|
||||||
ln_sf( "$rc{GL_ADMIN_BASE}/hooks/common", "*", "$repo.git/hooks" );
|
ln_sf( "$rc{GL_ADMIN_BASE}/hooks/common", "*", "$repo.git/hooks" );
|
||||||
|
# override/propagate gitolite defined hooks for the admin repo
|
||||||
# propagate admin hook
|
|
||||||
ln_sf( "$rc{GL_ADMIN_BASE}/hooks/gitolite-admin", "*", "$repo.git/hooks" ) if $repo eq 'gitolite-admin';
|
ln_sf( "$rc{GL_ADMIN_BASE}/hooks/gitolite-admin", "*", "$repo.git/hooks" ) if $repo eq 'gitolite-admin';
|
||||||
|
|
||||||
# g2 diff: no "site-wide" hooks (the stuff in between gitolite hooks
|
|
||||||
# and user hooks) anymore. I don't think anyone used them anyway...
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,11 +25,20 @@ sub post_update {
|
||||||
tsh_try("git ls-tree --name-only master");
|
tsh_try("git ls-tree --name-only master");
|
||||||
_die "no files/dirs called 'hooks' or 'logs' are allowed" if tsh_text() =~ /^(hooks|logs)$/m;
|
_die "no files/dirs called 'hooks' or 'logs' are allowed" if tsh_text() =~ /^(hooks|logs)$/m;
|
||||||
|
|
||||||
|
my $hooks_changed = 0;
|
||||||
{
|
{
|
||||||
local $ENV{GIT_WORK_TREE} = $rc{GL_ADMIN_BASE};
|
local $ENV{GIT_WORK_TREE} = $rc{GL_ADMIN_BASE};
|
||||||
|
|
||||||
|
tsh_try("git diff --name-only master");
|
||||||
|
$hooks_changed++ if tsh_text() =~ m(/hooks/common/);
|
||||||
|
# the leading slash ensure that this hooks/common directory is below
|
||||||
|
# some top level directory, not *at* the top. That's LOCAL_CODE, and
|
||||||
|
# it's actual name could be anything but it doesn't matter to us.
|
||||||
|
|
||||||
tsh_try("git checkout -f --quiet master");
|
tsh_try("git checkout -f --quiet master");
|
||||||
}
|
}
|
||||||
_system("gitolite compile");
|
_system("gitolite compile");
|
||||||
|
_system("gitolite setup --hooks-only") if $hooks_changed;
|
||||||
_system("gitolite trigger POST_COMPILE");
|
_system("gitolite trigger POST_COMPILE");
|
||||||
|
|
||||||
exit 0;
|
exit 0;
|
||||||
|
|
|
@ -87,7 +87,7 @@ do $ENV{G3T_RC} if exists $ENV{G3T_RC} and -r $ENV{G3T_RC};
|
||||||
# setup some perl/rc/env vars
|
# setup some perl/rc/env vars
|
||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
|
|
||||||
unshift @INC, "$rc{GL_BINDIR2}/lib" if $rc{GL_BINDIR2};
|
unshift @INC, "$rc{LOCAL_CODE}/lib" if $rc{LOCAL_CODE};
|
||||||
|
|
||||||
$ENV{PATH} = "$ENV{GL_BINDIR}:$ENV{PATH}";
|
$ENV{PATH} = "$ENV{GL_BINDIR}:$ENV{PATH}";
|
||||||
|
|
||||||
|
@ -232,13 +232,13 @@ sub trigger {
|
||||||
}
|
}
|
||||||
|
|
||||||
sub _which {
|
sub _which {
|
||||||
# looks for a file in GL_BINDIR2 or GL_BINDIR. Returns whichever exists
|
# looks for a file in LOCAL_CODE or GL_BINDIR. Returns whichever exists
|
||||||
# (GL_BINDIR2 preferred if defined) or 0 if not found.
|
# (LOCAL_CODE preferred if defined) or 0 if not found.
|
||||||
my $file = shift;
|
my $file = shift;
|
||||||
my $mode = shift; # could be 'x' or 'r'
|
my $mode = shift; # could be 'x' or 'r'
|
||||||
|
|
||||||
my @files = ("$rc{GL_BINDIR}/$file");
|
my @files = ("$rc{GL_BINDIR}/$file");
|
||||||
unshift @files, ("$rc{GL_BINDIR2}/$file") if $rc{GL_BINDIR2};
|
unshift @files, ("$rc{LOCAL_CODE}/$file") if $rc{LOCAL_CODE};
|
||||||
|
|
||||||
for my $f ( @files ) {
|
for my $f ( @files ) {
|
||||||
return $f if -x $f;
|
return $f if -x $f;
|
||||||
|
|
Loading…
Reference in a new issue