Q: all doc stuff
This commit is contained in:
parent
efb29ed135
commit
4f7d3d8651
34
doc/add.mkd
Normal file
34
doc/add.mkd
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
# adding users and repos
|
||||||
|
|
||||||
|
Do NOT add repos directly on the server. Clone the 'gitolite-admin' repo to
|
||||||
|
your workstation, make changes to it, then add, commit, and push. When the
|
||||||
|
push hits the server, the server "acts" upon your changes.
|
||||||
|
|
||||||
|
Full documentation on the conf file is [here][conf].
|
||||||
|
|
||||||
|
Here's a sample sequence, on your workstation, after your install is done
|
||||||
|
|
||||||
|
git clone git@host:gitolite-admin
|
||||||
|
cd gitolite-admin
|
||||||
|
vi conf/gitolite.conf
|
||||||
|
|
||||||
|
# now add lines like these:
|
||||||
|
repo foo
|
||||||
|
RW+ = me
|
||||||
|
RW = alice
|
||||||
|
R = wally
|
||||||
|
# now save the file and add it
|
||||||
|
git add conf
|
||||||
|
|
||||||
|
# add a couple of users; get their pubkeys by email or something, then:
|
||||||
|
cp /some/where/alice.pub keydir
|
||||||
|
cp /else/where/wally.pub keydir
|
||||||
|
git add keydir
|
||||||
|
|
||||||
|
# now commit and push
|
||||||
|
git commit -m 'added repo foo'
|
||||||
|
git push
|
||||||
|
|
||||||
|
# at this point gitolite will create the new repo 'foo' (if it did not
|
||||||
|
# already exist) then update the authorized keys file to include alice and
|
||||||
|
# wally's pubkeys
|
26
doc/commands.mkd
Normal file
26
doc/commands.mkd
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
# gitolite "commands"
|
||||||
|
|
||||||
|
Gitolite comes with several commands that users can run. Remote user run the
|
||||||
|
commands by saying:
|
||||||
|
|
||||||
|
ssh git@host command-name [args...]
|
||||||
|
|
||||||
|
while on the server you can run
|
||||||
|
|
||||||
|
gitolite command [args...]
|
||||||
|
|
||||||
|
Very few commands are designed to be run both ways, but it can be done, by
|
||||||
|
checking for the presence of env var `GL_USER`.
|
||||||
|
|
||||||
|
You can get a **list of available commands** by using the `help` command.
|
||||||
|
Naturally, a remote user will see only a subset of what the server user will
|
||||||
|
see.
|
||||||
|
|
||||||
|
You add commands to the "allowed from remote" list by adding its name (or
|
||||||
|
uncommenting it if it's already added but commented out) to the COMMANDS hash
|
||||||
|
in the [rc][] file.
|
||||||
|
|
||||||
|
If you write your own commands, put them in src/commands.
|
||||||
|
|
||||||
|
**Note that this is also the place that all triggered programs go**. In fact,
|
||||||
|
all standalone programs related to gitolite go here.
|
31
doc/conf.mkd
Normal file
31
doc/conf.mkd
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
# the gitolite.conf file
|
||||||
|
|
||||||
|
This file is the crux of all of gitolite's access control. The basic syntax
|
||||||
|
is very simple.
|
||||||
|
|
||||||
|
Note: `<user>+` means one or more user or user group names, `<repo>+` means
|
||||||
|
one or more repo or repo group names, and `<refex>*` means zero or more
|
||||||
|
refexes.
|
||||||
|
|
||||||
|
* [group][group] definitions (optional, for convenience)
|
||||||
|
|
||||||
|
@<group> = <user>+
|
||||||
|
@<group> = <repo>+
|
||||||
|
|
||||||
|
* [repo][repo] definitions and access [rules][]
|
||||||
|
|
||||||
|
repo <repo>+
|
||||||
|
<perm> <refex>* = <user>+
|
||||||
|
# one or more such lines
|
||||||
|
|
||||||
|
* [gitolite options][options] that apply to the repo(s) in the last
|
||||||
|
"repo ..." line, for example:
|
||||||
|
|
||||||
|
option deny-rules = 1
|
||||||
|
|
||||||
|
* [git config][git-config] keys and values that also apply to the last named
|
||||||
|
repo(s), for example:
|
||||||
|
|
||||||
|
config hooks.emailprefix = '[%GL_REPO] '
|
||||||
|
|
||||||
|
In addition, you can also have [include][] statements.
|
23
doc/cust.mkd
Normal file
23
doc/cust.mkd
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
# customising gitolite
|
||||||
|
|
||||||
|
Here are the ways you can customise gitolite on the server.
|
||||||
|
|
||||||
|
First, learn about:
|
||||||
|
|
||||||
|
* [git hooks][hooks] and [virtual refs][vref]
|
||||||
|
|
||||||
|
* [commands][] for your [users][] to run own][dev-notes]
|
||||||
|
|
||||||
|
* [triggers][] to be run by gitolite as various points in its execution
|
||||||
|
|
||||||
|
* [syntactic sugar][sugar] to change the conf language for your convenience
|
||||||
|
|
||||||
|
For all of the above:
|
||||||
|
|
||||||
|
* [edit the rc file][rc] to enable optional features that are shipped in a
|
||||||
|
disabled state
|
||||||
|
|
||||||
|
* [write your own][dev-notes]
|
||||||
|
|
||||||
|
(Note: "trigger" is the same concept as "hook", applied to gitolite; I just
|
||||||
|
chose a different name to avoid constant ambiguity in documentation).
|
116
doc/dev-notes.mkd
Normal file
116
doc/dev-notes.mkd
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
# notes for developers
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
Hints for developers wishing to help migrate features over from g2 are
|
||||||
|
[here][dev-hints].
|
||||||
|
|
||||||
|
Here are some random notes on developing hooks, commands, triggers, and sugar
|
||||||
|
scripts.
|
||||||
|
|
||||||
|
## environment variables
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
## 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: none yet
|
||||||
|
|
||||||
|
* `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/Gitolite/Easy.pm (the
|
||||||
|
perl API module) for ideas.
|
||||||
|
|
||||||
|
### the perl API
|
||||||
|
|
||||||
|
...is implemented by Gitolite::Easy; see src/Gitolite/Easy.pm. This is a work
|
||||||
|
in progress; for example it does not yet have the equivalent of `gitolite
|
||||||
|
git-config`. I'll add it when I or someone else needs it.
|
||||||
|
|
||||||
|
## 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.
|
||||||
|
|
||||||
|
## your own 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.
|
||||||
|
|
||||||
|
## your own trigger programs
|
||||||
|
|
||||||
|
Trigger programs are just commands whose names have been added to the
|
||||||
|
appropriate list in the [rc][] file. Triggers get specific arguments
|
||||||
|
depending on when they are called; see [here][triggers] 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.
|
||||||
|
|
||||||
|
Look in the distributed [rc][] file for example programs; at this point there
|
||||||
|
aren't many.
|
||||||
|
|
||||||
|
## your own "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.
|
||||||
|
|
35
doc/dev-status.mkd
Normal file
35
doc/dev-status.mkd
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
## #dev-status g3 development status
|
||||||
|
|
||||||
|
Not yet done (will be tackled in this order unless someone asks):
|
||||||
|
|
||||||
|
* detailed documentation for new features
|
||||||
|
* querying the outside world for group info (see gl-get-membership-program
|
||||||
|
in g2)
|
||||||
|
* mirroring
|
||||||
|
* pulling in documentation for things that are the same in g2
|
||||||
|
* "unrestricted arguments" for some ADCs (like git-annexe)
|
||||||
|
* smart http
|
||||||
|
* special features (no-create-repos, shell-access, gl-all-read-all, etc)
|
||||||
|
|
||||||
|
Help needed:
|
||||||
|
|
||||||
|
* I'd like distro packagers to play with it and help with migration advice
|
||||||
|
for distro-upgrades
|
||||||
|
* [rsync][pw2], htpasswd
|
||||||
|
* git-annexe support (but this has a pre-requisite in the previous list)
|
||||||
|
|
||||||
|
Won't be done unless someone asks (saw no evidence that anyone used them in g2
|
||||||
|
anyway!):
|
||||||
|
|
||||||
|
* mob branches
|
||||||
|
* password access
|
||||||
|
* specific ADCs -- there are too many for me to bother without applying
|
||||||
|
Pareto somewhere, so I choose to not do any and wait for people to ask :-)
|
||||||
|
|
||||||
|
Done:
|
||||||
|
|
||||||
|
* core code
|
||||||
|
* test suite
|
||||||
|
* some documentation
|
||||||
|
* distro packaging instructions
|
||||||
|
* migration advice for common cases
|
89
doc/extras/auth.mkd
Normal file
89
doc/extras/auth.mkd
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
# authentication versus authorisation
|
||||||
|
|
||||||
|
This document will explain why an "ssh issue" is almost never a "gitolite
|
||||||
|
issue", and, indirectly, why I dont get too excited about the former.
|
||||||
|
|
||||||
|
Note: for actual ssh troubleshooting see [this][ssh-troubleshooting].
|
||||||
|
|
||||||
|
Here is a fundamental point: <font color="red">**Gitolite does not do
|
||||||
|
authentication. It only does authorisation**.</font>
|
||||||
|
|
||||||
|
So first, let's loosely define these words:
|
||||||
|
|
||||||
|
> **Authentication** is the process of verifying that you are who you claim
|
||||||
|
> to be. An authentication system will establish that I am the user
|
||||||
|
> "sitaram" on my work system. The one behind gmail will similarly
|
||||||
|
> establish that I am "sitaramc". And so on...
|
||||||
|
|
||||||
|
> **Authorisation** is the process of asking what you want to do and
|
||||||
|
> deciding if you're allowed to do it or not.
|
||||||
|
|
||||||
|
Now, if you managed to read about [gitolite and ssh][gitolite-and-ssh], you
|
||||||
|
know that gitolite is meant to be invoked as:
|
||||||
|
|
||||||
|
/full/path/to/gl-auth-command some-authenticated-gitolite-username
|
||||||
|
|
||||||
|
(where the "gitolite username" is a "virtual" username; it does not have to
|
||||||
|
be, and usually *isn't*, an actual *unix* username).
|
||||||
|
|
||||||
|
As you can see, authentication happens before gitolite is called.
|
||||||
|
|
||||||
|
## but... but... you have all that ssh stuff in there!
|
||||||
|
|
||||||
|
The default mode of using gitolite does use ssh keys, but all it's doing is
|
||||||
|
helping you **setup** ssh-based authentication **as a convenience to you**.
|
||||||
|
|
||||||
|
You don't have to use it, though. And many people don't. The examples I know
|
||||||
|
are [smart http][http], and ldap-backed sshd. In both cases, gitolite has no
|
||||||
|
role to play in creating users, setting up their passwords/keys, etc. There's
|
||||||
|
even a `GL_NO_SETUP_AUTHKEYS` option to make sure gitolite doesn't meddle with
|
||||||
|
the authkeys file in such installations.
|
||||||
|
|
||||||
|
## so you're basically saying you won't support "X"
|
||||||
|
|
||||||
|
(where "X" is some ssh related behaviour change or feature)
|
||||||
|
|
||||||
|
Well, if it's not a security issue I *probably* won't. I'm willing to change
|
||||||
|
my mind if enough people convince me they need it. (There's a mailing list if
|
||||||
|
you want to find others who also need the same thing.)
|
||||||
|
|
||||||
|
While we're on the subject, locking someone out is *not* a security issue.
|
||||||
|
Even if you locked yourself (the admin) out, the docs tell you how to recover
|
||||||
|
from such errors. You do need some password based method to get a shell
|
||||||
|
command line on the server, of course.
|
||||||
|
|
||||||
|
## appendix: how to use other authentication systems with gitolite
|
||||||
|
|
||||||
|
The bottom line in terms of how to invoke gitolite has been described above,
|
||||||
|
and as long as you manage to do that gitolite won't even know how the
|
||||||
|
authentication was done. Which in turn means you can use whatever
|
||||||
|
authentication scheme you want.
|
||||||
|
|
||||||
|
It also expects the `SSH_ORIGINAL_COMMAND` environment variable to contain the
|
||||||
|
full command (typically starting with git-receive-pack or git-upload-pack)
|
||||||
|
that the client sent. Also, when using [smart http][http], things are somewhat
|
||||||
|
different: gitolite uses certain environment variables that it expects httpd
|
||||||
|
to have set up. Even the user name comes from the `REMOTE_USER` environment
|
||||||
|
variable instead of as a command line argument in this case.
|
||||||
|
|
||||||
|
However, it has to be an authentication system that is compatible with sshd or
|
||||||
|
httpd in some form. Why? Because the git *client* accessing the server only
|
||||||
|
knows those 2 protocols to "speak git". (Well, the `git://` protocol is
|
||||||
|
unauthenticated, and `file://` doesn't really apply to this discussion, so
|
||||||
|
we're ignoring those).
|
||||||
|
|
||||||
|
For example, let's say you have an LDAP-based authentication system somewhere.
|
||||||
|
It is possible to make apache use that to authenticate users, so when a user
|
||||||
|
accesses a git url using `http://sitaram:password@git.example.com/repo`, it is
|
||||||
|
LDAP that does the actual authentication. [I wouldn't know how to do it but I
|
||||||
|
know it is possible. Patches to this doc explaining how are welcome!]
|
||||||
|
|
||||||
|
There are also ssh daemons that use LDAP to store the authorised keys (instead
|
||||||
|
of putting them all in `~/.ssh/authorized_keys`). The clients will still need
|
||||||
|
to generate keypairs and send them to the admin, but they can be more
|
||||||
|
centrally stored and perhaps used by other programs or tools simultaneously,
|
||||||
|
which can be useful.
|
||||||
|
|
||||||
|
Finally, gitolite allows you to store *group* information externally too. See
|
||||||
|
[here][ldap] for more on this.
|
||||||
|
|
145
doc/extras/gitolite-and-ssh.mkd
Normal file
145
doc/extras/gitolite-and-ssh.mkd
Normal file
|
@ -0,0 +1,145 @@
|
||||||
|
## #glssh how gitolite uses ssh
|
||||||
|
|
||||||
|
Although other forms of authentications exist (see the document on
|
||||||
|
[authentication versus authorisation][auth]), ssh is the one that most git
|
||||||
|
users use.
|
||||||
|
|
||||||
|
***Therefore, gitolite is (usually) heavily dependent on ssh***.
|
||||||
|
|
||||||
|
Most people didn't realise this, and even if they did they don't know ssh
|
||||||
|
well enough to help themselves. If you don't understand how ssh public key
|
||||||
|
authentication works, or how the `~/.ssh/authorized_keys` file can be used to
|
||||||
|
restrict users, etc., you will have endless amounts of trouble getting
|
||||||
|
gitolite to work, because you'll be attacking the wrong problem.
|
||||||
|
|
||||||
|
So please please please understand this before tearing your hair out and
|
||||||
|
blaming ***git/gitolite*** for whatever is going wrong with your setup :-)
|
||||||
|
|
||||||
|
### ssh basics
|
||||||
|
|
||||||
|
Let's start with some basics, focusing *only* on the pieces relevant to
|
||||||
|
`gitolite`. If this is not detailed enough, please use google and learn more
|
||||||
|
from somewhere, or maybe buy the OReilly ssh book.
|
||||||
|
|
||||||
|
* You can login to an ssh server by typing a password, but ssh can also use
|
||||||
|
***public-private keys*** (also called "key pairs") for authentication.
|
||||||
|
`gitolite` *requires* you to use this mechanism for your users -- they
|
||||||
|
cannot log in using passwords. Hopefully by the time you finish reading
|
||||||
|
this document you will understand why :-)
|
||||||
|
|
||||||
|
The way you set this up is you generate a key pair on your workstation,
|
||||||
|
and give the server the public key. (I need not add that the "private"
|
||||||
|
key must be, well, kept *private*!)
|
||||||
|
|
||||||
|
* **generating a key pair on your workstation** is done by running the
|
||||||
|
command `ssh-keygen -t rsa`. This produces two files in `~/.ssh`. One is
|
||||||
|
`id_rsa`; this is the **private** key -- ***never*** let it out of your
|
||||||
|
machine. The other is `id_rsa.pub`, which is the corresponding public
|
||||||
|
key. This public key is usually just one long line of text.
|
||||||
|
|
||||||
|
* on Windows machines with msysgit installed, you should do this from
|
||||||
|
within a "git bash" window. The command will report the full path where
|
||||||
|
the files have been written; make a note of this, and use those files in
|
||||||
|
any of the description that follows
|
||||||
|
|
||||||
|
* **adding your public key to the server**'s `~/.ssh/authorized_keys`
|
||||||
|
file is how ssh uses pubkeys to authenticate users. Let's say
|
||||||
|
sita@work.station is trying to log in as git@serv.er. What you have to do
|
||||||
|
is take the `~/.ssh/id_rsa.pub` file for user sita on work.station and
|
||||||
|
append its contents (remember it's only one line) to
|
||||||
|
`~/.ssh/authorized_keys` for user git on serv.er.
|
||||||
|
|
||||||
|
The `authorized_keys` file can have multiple public keys (from many
|
||||||
|
different people) added to it so any of them can log in to git@serv.er.
|
||||||
|
|
||||||
|
In the normal case (not gitolite, but your normal everyday shell access),
|
||||||
|
there's a command that does this, `ssh-copy-id`, which also fixes up
|
||||||
|
permissions etc., as needed, since sshd is a little picky about allowing
|
||||||
|
pubkey access if permissions on the server are loose. Or you can do it
|
||||||
|
manually, as long as you know what you're doing and you're careful not to
|
||||||
|
erase or overwrite the existing contents of `~/.ssh/authorized_keys` on
|
||||||
|
the server!
|
||||||
|
|
||||||
|
But in the gitolite case, it's different; we'll get to that in a minute.
|
||||||
|
|
||||||
|
* **troubleshooting pubkey authentication failures**: if you are unable to
|
||||||
|
get ssh access to the server after doing all this, you'll have to look
|
||||||
|
in `/var/log/secure` or `/var/log/auth.log` or some such file on the
|
||||||
|
server to see what specific error `sshd` is complaining about.
|
||||||
|
|
||||||
|
* **restricting users to specific commands** is very important for gitolite.
|
||||||
|
If you read `man sshd` and look for `authorized_keys file format`, you'll
|
||||||
|
see a lot of options you can add to the public key line, which restrict
|
||||||
|
the incoming user in various ways. In particular, note the `command=`
|
||||||
|
option, which means "regardless of what the incoming user is asking to do,
|
||||||
|
forcibly run this command instead".
|
||||||
|
|
||||||
|
Also note that when there are many public keys (i.e., lines) in the
|
||||||
|
`authorized_keys` file, each line can have a *different* set of options
|
||||||
|
and `command=` values.
|
||||||
|
|
||||||
|
Without this `command=` option, the ssh daemon will simply give you a
|
||||||
|
shell, which is not what we want for our gitolite keys (although we may
|
||||||
|
well have other keys which we use to get a shell).
|
||||||
|
|
||||||
|
**This is the backbone of what makes gitolite work; please make sure you
|
||||||
|
understand this**.
|
||||||
|
|
||||||
|
### how does gitolite use all this ssh magic?
|
||||||
|
|
||||||
|
These are two different questions you ought to be having by now:
|
||||||
|
|
||||||
|
* how does it distinguish between me and someone else, since we're all
|
||||||
|
logging in as the same remote user "git"
|
||||||
|
* how does it restrict what I can do within a repository
|
||||||
|
|
||||||
|
#### restricting shell access/distinguishing one user from another
|
||||||
|
|
||||||
|
The answer to the first question is the `command=` we talked about before. If
|
||||||
|
you look in the `authorized_keys` file, you'll see entries like this (I chopped
|
||||||
|
off the ends of course; they're pretty long lines):
|
||||||
|
|
||||||
|
command="[path]/gl-auth-command sitaram",[more options] ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA18S2t...
|
||||||
|
command="[path]/gl-auth-command usertwo",[more options] ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEArXtCT...
|
||||||
|
|
||||||
|
First, it finds out which of the public keys in this file match the incoming
|
||||||
|
login. That's crypto stuff, and I won't go into it. Once the match has been
|
||||||
|
found, it will run the command given on that line; e.g., if I logged in, it
|
||||||
|
would run `[path]/gl-auth-command sitaram`. So the first thing to note is
|
||||||
|
that such users do not get "shell access", which is good!
|
||||||
|
|
||||||
|
Before running the command, however, sshd sets up an environment variable
|
||||||
|
called `SSH_ORIGINAL_COMMAND` which contains the actual git command that your
|
||||||
|
workstation sent out. This is the command that *would have run* if you did
|
||||||
|
not have the `command=` part in the authorised keys file.
|
||||||
|
|
||||||
|
When `gl-auth-command` gets control, it looks at the first argument
|
||||||
|
("sitaram", "usertwo", etc) to determine who you are. It then looks at the
|
||||||
|
`SSH_ORIGINAL_COMMAND` variable to find out which repository you want to
|
||||||
|
access, and whether you're reading or writing.
|
||||||
|
|
||||||
|
Now that it has a user, repository, and access requested (read/write), gitolite looks
|
||||||
|
at its config file, and either allows or rejects the request.
|
||||||
|
|
||||||
|
But this cannot differentiate between different branches within a repo; that
|
||||||
|
has to be done separately.
|
||||||
|
|
||||||
|
#### restricting branch level actions
|
||||||
|
|
||||||
|
[If you look inside the git source tree, there's a file among the "howto"s in
|
||||||
|
there called `update-hook-example.txt`, which was the inspiration for this
|
||||||
|
part of gitolite.]
|
||||||
|
|
||||||
|
Git allows you to specify many "hooks", which get control as various events
|
||||||
|
happen -- see `git help hooks` for details. One of those hooks is the
|
||||||
|
`update` hook, which, if it is present, is invoked just before a branch or a
|
||||||
|
tag is about to be updated. The hook is passed the name of the branch or tag,
|
||||||
|
the old SHA1 value, and the new SHA1 value, as arguments. Hooks that are
|
||||||
|
called *before* an action happens are allowed to prevent that action from
|
||||||
|
happening by returning an error code.
|
||||||
|
|
||||||
|
When gitolite is told to create a new repository (by the admin), it installs
|
||||||
|
a special update hook. This hook takes all the information presented, looks
|
||||||
|
at the config file, and decides to allow or reject the update.
|
||||||
|
|
||||||
|
And that's basically it.
|
64
doc/extras/nagp.mkd
Normal file
64
doc/extras/nagp.mkd
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
# not a gitolite problem
|
||||||
|
|
||||||
|
These are issues I do not want to be emailed about. That does not mean you
|
||||||
|
cannot get help -- in all cases, you're welcome to ask on [irc or the mailing
|
||||||
|
list][contact]. Irc especially has people with much more patience than I
|
||||||
|
have, God bless them...
|
||||||
|
|
||||||
|
## specific clients, or specific server OSs
|
||||||
|
|
||||||
|
These are things I can not support. That does not mean they will not work
|
||||||
|
with gitolite -- on the contrary, lots of people are using them.
|
||||||
|
|
||||||
|
But I personally don't use them, and I won't use them, and in my admittedly
|
||||||
|
limited experience they have given me good reason to stay well away.
|
||||||
|
|
||||||
|
Please ask for help on the [mailing list or IRC][contact]. Please do not
|
||||||
|
email me directly.
|
||||||
|
|
||||||
|
* putty/plink
|
||||||
|
* jgit/Eclipse
|
||||||
|
* Mac OS client or server
|
||||||
|
* windows as a server
|
||||||
|
* ...probably some more I forgot; will update this list as I remember...
|
||||||
|
|
||||||
|
## ssh
|
||||||
|
|
||||||
|
The *superstar* of the "not a gitolite problem" category is actually ssh.
|
||||||
|
|
||||||
|
Surprised? It is so common that it has [its own document][auth] to tell
|
||||||
|
you why it is *not* a gitolite problem, while [another one][ssh] tries to
|
||||||
|
help you anyway!
|
||||||
|
|
||||||
|
Everything I know is in that latter link. Please email me about ssh ONLY if
|
||||||
|
you find something wrong or missing in those documents.
|
||||||
|
|
||||||
|
## git
|
||||||
|
|
||||||
|
Example 1: when a first `git push` to a new repo fails, it is not because of
|
||||||
|
gitolite, it is because you need to say `git push origin master` or something.
|
||||||
|
This is a git issue.
|
||||||
|
|
||||||
|
There are several such examples. Gitolite is designed to look like just
|
||||||
|
another bare repo server to a client (except requiring public keys -- no
|
||||||
|
passwords allowed). It is *completely transparent* when there is no
|
||||||
|
authorisation failure (i.e., when the access is allowed, the remote client has
|
||||||
|
no way of knowing gitolite was even installed!)
|
||||||
|
|
||||||
|
Even "on disk", apart from reserving the `update` hook for itself, gitolite
|
||||||
|
does nothing to your bare repos unless you tell it to (for example, adding
|
||||||
|
'gitweb.owner' and such to the config file).
|
||||||
|
|
||||||
|
BEFORE you think gitolite is a problem, try the same thing with a normal bare
|
||||||
|
repo. In most cases you can play with it just by doing something like this:
|
||||||
|
|
||||||
|
mkdir /tmp/throwaway
|
||||||
|
cd /tmp/throwaway
|
||||||
|
git clone --mirror <some repo you have a URL for> bare.git
|
||||||
|
git clone bare.git worktree
|
||||||
|
cd worktree
|
||||||
|
<...try stuff>
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
In addition, the original nagp has more funny stuff...
|
34
doc/extras/regex.mkd
Normal file
34
doc/extras/regex.mkd
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
# extremely brief regex overview
|
||||||
|
|
||||||
|
Regexes are powerful. Gitolite uses that power as much as it can. If you
|
||||||
|
can't handle that power, hire someone who can and become a manager.
|
||||||
|
|
||||||
|
That said, here's a very quick overview of the highlights.
|
||||||
|
|
||||||
|
`^` and `$` are called "anchors". They anchor the match to the beginning and
|
||||||
|
end of the string respectively.
|
||||||
|
|
||||||
|
^foo matches any string starting with 'foo'
|
||||||
|
foo$ matches any string ending with 'foo'
|
||||||
|
^foo$ matches exact string 'foo'.
|
||||||
|
|
||||||
|
To be precise, the last one is "any string starting and ending with *the same*
|
||||||
|
'foo'". "foofoo" does not match.
|
||||||
|
|
||||||
|
`[0-9]` is an example of a character class; it matches any single digit.
|
||||||
|
`[a-z]` matches any lower case alpha, and `[0-9a-f]` is the range of hex
|
||||||
|
characters. You should now guess what `[a-zA-Z0-9_]` does.
|
||||||
|
|
||||||
|
`.` (the period) is special -- it matches any character. If you want to match
|
||||||
|
an actual period, you need to say `\.`.
|
||||||
|
|
||||||
|
`*`, `?`, and `+` are quantifiers. They apply to the previous token. `a*`
|
||||||
|
means "zero or more 'a' characters". Similarly `a+` means "one or more", and
|
||||||
|
`a?` means "zero or one".
|
||||||
|
|
||||||
|
As a result, `.*` means "any number (including zero) of any character".
|
||||||
|
|
||||||
|
The previous token need not be a single character; you can use parens to make
|
||||||
|
it longer. `(foo)+` matches one or more "foo", (like "foo", "foofoo",
|
||||||
|
"foofoofoo", etc.)
|
||||||
|
|
427
doc/extras/ssh-troubleshooting.mkd
Normal file
427
doc/extras/ssh-troubleshooting.mkd
Normal file
|
@ -0,0 +1,427 @@
|
||||||
|
## #sshts ssh troubleshooting
|
||||||
|
|
||||||
|
**This document must be read in full the first time. If you start from some
|
||||||
|
nice looking section in the middle it may not help you unless you're already
|
||||||
|
an expert at ssh**.
|
||||||
|
|
||||||
|
This document should help you troubleshoot ssh-related problems in installing
|
||||||
|
and accessing gitolite.
|
||||||
|
|
||||||
|
### IMPORTANT -- READ THIS FIRST
|
||||||
|
|
||||||
|
#### caveats
|
||||||
|
|
||||||
|
* Before reading this document, it is **mandatory** to read and **completely
|
||||||
|
understand** [this][ssh], which is a very detailed look at how gitolite
|
||||||
|
uses ssh's features on the server side. Don't assume you know all that;
|
||||||
|
if you knew it, you wouldn't be needing *this* document either!
|
||||||
|
|
||||||
|
* This document, and others linked from this, together comprise all the help
|
||||||
|
I can give you in terms of the ssh aspect of using gitolite. If you're
|
||||||
|
installing gitolite, you're a "system admin", like it or not. Ssh is
|
||||||
|
therefore a necessary skill. Please take the time to learn at least
|
||||||
|
enough to get passwordless access working.
|
||||||
|
|
||||||
|
* Please note that authentication is not really gitolite's job at all. I'd
|
||||||
|
rather spend time on actual gitolite features, code, and documentation
|
||||||
|
than authentication (i.e., ssh, in the common case).
|
||||||
|
|
||||||
|
Surprised? [This][auth] might help explain better.
|
||||||
|
|
||||||
|
#### naming conventions used
|
||||||
|
|
||||||
|
* Your workstation is the **client**. Your userid on the client does not
|
||||||
|
matter, and it has no relation to your gitolite username.
|
||||||
|
|
||||||
|
* the server is called **server** and the "hosting user" is **git**. If
|
||||||
|
this is an RPM/DEB install, the hosting user is probably called
|
||||||
|
"gitolite", however we will use "git" in this document.
|
||||||
|
|
||||||
|
#### taking stock -- relevant files and directories
|
||||||
|
|
||||||
|
* the client has a `~/.ssh` containing a few keypairs. It may also have a
|
||||||
|
`config` file.
|
||||||
|
|
||||||
|
* the client also has a clone of the "gitolite-admin" repo, which contains a
|
||||||
|
bunch of `*.pub` files in `keydir`. We assume this clone is in `$HOME`;
|
||||||
|
if it is not, adjust instructions accordingly when needed.
|
||||||
|
|
||||||
|
* The git user on the server has a `~/.ssh/authorized_keys` file that the
|
||||||
|
ssh daemon uses to authenticate incoming users. We often call this file
|
||||||
|
**authkeys** to save typing, and it always means the one on the server
|
||||||
|
(we're not interested in this file on the client side).
|
||||||
|
|
||||||
|
* the server also has a `~/.gitolite/keydir` which contains a bunch of
|
||||||
|
`*.pub` files.
|
||||||
|
|
||||||
|
#### normal gitolite key handling
|
||||||
|
|
||||||
|
Here's how normal gitolite key handling works:
|
||||||
|
|
||||||
|
* (on client) pub key changes like adding new ones, deleting old ones, etc.,
|
||||||
|
are done in the `keydir` directory in the gitolite-admin repo clone. Then
|
||||||
|
the admin `git add`s and `git commit`s those changes, then `git push`es
|
||||||
|
them to the server.
|
||||||
|
|
||||||
|
* (on server) a successful push from the client makes git invoke the
|
||||||
|
post-update hook in the gitolite-admin repo. This hook is installed by
|
||||||
|
gitolite, and it does a bunch of things which are quite transparent to
|
||||||
|
the admin, but we'll describe briefly here:
|
||||||
|
|
||||||
|
* the pubkey files from this push are checked-out into
|
||||||
|
`~/.gitolite/keydir` (and similarly the config files into
|
||||||
|
`~/.gitolite/conf`)
|
||||||
|
|
||||||
|
* the "compile" script then runs, which uses these files to populate
|
||||||
|
`~/.ssh/authorized_keys` on the server
|
||||||
|
|
||||||
|
The authkeys file may have other, (non-gitolite) keys also. Those
|
||||||
|
lines are preserved. Gitolite only touches lines that are found
|
||||||
|
between gitolite's "marker" lines (`# gitolite start` and `# gitolite
|
||||||
|
end`).
|
||||||
|
|
||||||
|
### (Other resources)
|
||||||
|
|
||||||
|
People who think installing gitolite is too hard should take a look at this
|
||||||
|
[tutorial][tut] to **see how simple it *actually* is**.
|
||||||
|
|
||||||
|
### common ssh problems
|
||||||
|
|
||||||
|
Since I'm pretty sure at least some of you didn't bother to read the
|
||||||
|
"IMPORTANT: PLEASE READ FIRST" section above, let me take a minute to point
|
||||||
|
you there again. Especially the first bullet.
|
||||||
|
|
||||||
|
Done? OK, read on...
|
||||||
|
|
||||||
|
The following problem(s) indicate that pubkey access is not working at all, so
|
||||||
|
you should start with [appendix 1][stsapp1_]. If that doesn't fix the problem, continue
|
||||||
|
with the other appendices in sequence.
|
||||||
|
|
||||||
|
* running any git clone/fetch/ls-remote or just `ssh git@server info` asks
|
||||||
|
you for a password.
|
||||||
|
|
||||||
|
The following problem(s) indicate that your pubkey is bypassing gitolite and
|
||||||
|
going straight to a shell. You should start with [appendix 2][stsapp2_] and continue with
|
||||||
|
the rest in sequence. [Appendix 5][stsapp5_] has some background info.
|
||||||
|
|
||||||
|
* running `ssh git@server info` gets you the output of the GNU 'info'
|
||||||
|
command instead of gitolite's version and access info.
|
||||||
|
|
||||||
|
* running `git clone git@server:repositories/reponame` (note presence of
|
||||||
|
`repositories/` in URL) works.
|
||||||
|
|
||||||
|
[A proper gitolite key will only let you `git clone git@server:reponame`
|
||||||
|
(note absence of `repositories/`)]
|
||||||
|
|
||||||
|
* you are able to clone repositories but are unable to push changes back
|
||||||
|
(the error complains about the `GL_RC` environment variable not being set,
|
||||||
|
and the `hooks/update` failing in some way).
|
||||||
|
|
||||||
|
[If you run `git remote -v` you will find that your clone URL included the
|
||||||
|
`repositories/` described above!]
|
||||||
|
|
||||||
|
* conversely, using the correct syntax, `git clone git@server:reponame`
|
||||||
|
(note absence of `repositories/` in the URL), gets you `fatal: 'reponame'
|
||||||
|
does not appear to be a git repository`, and yet you are sure 'reponame'
|
||||||
|
exists, you haven't mis-spelled it, etc.
|
||||||
|
|
||||||
|
### step by step
|
||||||
|
|
||||||
|
Since I'm pretty sure at least some of you didn't bother to read the
|
||||||
|
"IMPORTANT: PLEASE READ FIRST" section above, let me take a minute to point
|
||||||
|
you there again. Especially the first bullet.
|
||||||
|
|
||||||
|
Done? OK, now the general outline for ssh troubleshooting is this:
|
||||||
|
|
||||||
|
* make sure the server's overall setup even *allows* pubkey based login.
|
||||||
|
I.e., check that git fetch/clone/ls-remote commands or a plain `ssh
|
||||||
|
git@server info` do NOT ask for a password. If you do get asked for a
|
||||||
|
password, see [appendix 1][stsapp1_].
|
||||||
|
|
||||||
|
* match client-side pubkeys (`~/.ssh/*.pub`) with the server's authkeys
|
||||||
|
file. To do this, run `sshkeys-lint`, which tells you in detail what key
|
||||||
|
has what access. See [appendix 2][stsapp2_].
|
||||||
|
|
||||||
|
* at this point, we know that we have the right key, and that if sshd
|
||||||
|
receives that key, things will work. But we're not done yet. We still
|
||||||
|
need to make sure that this specific key is being offered/sent by the
|
||||||
|
client, instead of the default key. See [appendix 3][stsapp3_] and [appendix 4][sshhostaliases].
|
||||||
|
|
||||||
|
### random tips, tricks, and notes
|
||||||
|
|
||||||
|
#### giving shell access to gitolite users
|
||||||
|
|
||||||
|
We've managed (thanks to an idea from Jesse Keating) to make it possible for a
|
||||||
|
single key to allow both gitolite access *and* shell access.
|
||||||
|
|
||||||
|
This is done by copying the pubkey (to which you want to give shell access) to
|
||||||
|
the server and running
|
||||||
|
|
||||||
|
gl-tool add-shell-user ~/foo.pub
|
||||||
|
|
||||||
|
**IMPORTANT UPGRADE NOTE**: previous implementations of this feature were
|
||||||
|
crap. There was no easy/elegant way to ensure that someone who had repo admin
|
||||||
|
access would not manage to get himself shell access.
|
||||||
|
|
||||||
|
Giving someone shell access requires that you should have shell access in the
|
||||||
|
first place, so the simplest way is to enable it from the server side only.
|
||||||
|
|
||||||
|
#### losing your admin key
|
||||||
|
|
||||||
|
If you lost the admin key, and need to re-establish ownership of the
|
||||||
|
gitolite-admin repository with a fresh key, get a shell on the server and use
|
||||||
|
the program called `gl-admin-push` that comes with gitolite. See instructions
|
||||||
|
[here][adminpush].
|
||||||
|
|
||||||
|
#### simulating ssh-copy-id
|
||||||
|
|
||||||
|
don't have `ssh-copy-id`? This is broadly what that command does, if you want
|
||||||
|
to replicate it manually. The input is your pubkey, typically
|
||||||
|
`~/.ssh/id_rsa.pub` from your client/workstation.
|
||||||
|
|
||||||
|
* it copies it to the server as some file
|
||||||
|
|
||||||
|
* it appends that file to `~/.ssh/authorized_keys` on the server
|
||||||
|
(creating it if it doesn't already exist)
|
||||||
|
|
||||||
|
* it then makes sure that all these files/directories have go-w perms
|
||||||
|
set (assuming user is "git"):
|
||||||
|
|
||||||
|
/home/git/.ssh/authorized_keys
|
||||||
|
/home/git/.ssh
|
||||||
|
/home/git
|
||||||
|
|
||||||
|
[Actually, `sshd` requires that even directories *above* `~` (`/`, `/home`,
|
||||||
|
typically) also must be `go-w`, but that needs root. And typically
|
||||||
|
they're already set that way anyway. (Or if they're not, you've got
|
||||||
|
bigger problems than gitolite install not working!)]
|
||||||
|
|
||||||
|
#### problems with using non-openssh public keys
|
||||||
|
|
||||||
|
Gitolite accepts public keys only in openssh format. Trying to use an "ssh2"
|
||||||
|
key (used by proprietary SSH software) results in:
|
||||||
|
|
||||||
|
WARNING: a pubkey file can only have one line (key); ignoring YourName.pub
|
||||||
|
|
||||||
|
To convert ssh2-compatible keys to openssh run:
|
||||||
|
|
||||||
|
ssh-keygen -i -f /tmp/ssh2/YourName.pub > /tmp/openssh/YourName.pub
|
||||||
|
|
||||||
|
then use the resulting pubkey as you normally would in gitolite.
|
||||||
|
|
||||||
|
#### windows issues
|
||||||
|
|
||||||
|
On windows, I have only used msysgit, and the openssh that comes with it.
|
||||||
|
Over time, I have grown to distrust putty/plink due to the number of people
|
||||||
|
who seem to have trouble when those beasts are involved (I myself have never
|
||||||
|
used them for any kind of git access). If you have unusual ssh problems that
|
||||||
|
just don't seem to have any explanation, try removing all traces of
|
||||||
|
putty/plink, including environment variables, etc., and then try again.
|
||||||
|
|
||||||
|
Thankfully, someone contributed [contrib/putty.mkd][contrib_putty].
|
||||||
|
|
||||||
|
### #stsapp1_ appendix 1: ssh daemon asks for a password
|
||||||
|
|
||||||
|
> **NOTE**: This section should be useful to anyone trying to get
|
||||||
|
> password-less access working. It is not necessarily specific to gitolite,
|
||||||
|
> so keep that in mind if the wording feels a little more general than you
|
||||||
|
> were expecting.
|
||||||
|
|
||||||
|
You have generated a keypair on your workstation (`ssh-keygen`) and copied the
|
||||||
|
public part of it (`~/.ssh/id_rsa.pub`, by default) to the server.
|
||||||
|
|
||||||
|
On the server you have appended this file to `~/.ssh/authorized_keys`. Or you
|
||||||
|
ran something, like the `gl-setup` step during a gitolite install, which
|
||||||
|
should have done that for you.
|
||||||
|
|
||||||
|
You now expect to log in without having to type in a password, but when you
|
||||||
|
try, you are being asked for a password.
|
||||||
|
|
||||||
|
This is a quick checklist:
|
||||||
|
|
||||||
|
* make sure you're being asked for a password and not a pass*phrase*. Do
|
||||||
|
not confuse or mistake a prompt saying `Enter passphrase for key
|
||||||
|
'/home/sitaram/.ssh/id_rsa':` for a password prompt from the remote
|
||||||
|
server!
|
||||||
|
|
||||||
|
When you create an ssh keypair using `ssh-keygen`, you have the option of
|
||||||
|
protecting it with a passphrase. When you subsequently use that keypair
|
||||||
|
to access a remote host, your *local* ssh client needs to unlock the
|
||||||
|
corresponding private key, and ssh will probably ask for the passphrase
|
||||||
|
you set when you created the keypair.
|
||||||
|
|
||||||
|
You have two choices to avoid this prompt every time you try to use the
|
||||||
|
private key. The first is to create keypairs *without* a passphrase (just
|
||||||
|
hit enter when prompted for one). **Be sure to add a passphrase later,
|
||||||
|
once everything is working, using `ssh-keygen -p`**.
|
||||||
|
|
||||||
|
The second is to use `ssh-agent` (or `keychain`, which in turn uses
|
||||||
|
`ssh-agent`) or something like that to manage your keys. Other than
|
||||||
|
discussing one more potential trouble-spot with ssh-agent (see below),
|
||||||
|
further discussion of ssh-agent/keychain is out of scope of this document.
|
||||||
|
|
||||||
|
* ssh is very sensitive to permissions. An extremely conservative setup is
|
||||||
|
given below, but be sure to do this on **both the client and the server**:
|
||||||
|
|
||||||
|
cd $HOME
|
||||||
|
chmod go-rwx .
|
||||||
|
chmod -R go-rwx .ssh
|
||||||
|
|
||||||
|
* actually, every component of the path to `~/.ssh/authorized_keys` all the
|
||||||
|
way upto the root directory must be at least `chmod go-w`. So be sure to
|
||||||
|
check `/` and `/home` also.
|
||||||
|
|
||||||
|
* while you're doing this, make sure the owner and group info for each of
|
||||||
|
these components are correct. `ls -ald ~ ~/.ssh ~/.ssh/authorized_keys`
|
||||||
|
will tell you what they are.
|
||||||
|
|
||||||
|
* you may also want to check `/etc/ssh/sshd_config` to see if the "git" user
|
||||||
|
is allowed to login at all. For example, if that file contains an
|
||||||
|
`AllowUsers` config entry, then only users mentioned in that line are
|
||||||
|
allowed to log in!
|
||||||
|
|
||||||
|
* some OSs/distributions require that the "git" user should have a password
|
||||||
|
and/or not be a locked account. You may want to check that as well.
|
||||||
|
|
||||||
|
* if all that fails, log onto the server as root, `cd /var/log`, and look
|
||||||
|
for a file called `auth.log` or `secure` or some such name. Look inside
|
||||||
|
this file for messages matching the approximate time of your last attempt
|
||||||
|
to login, to see if they tell you what is the problem.
|
||||||
|
|
||||||
|
### #stsapp2_ appendix 2: which key is which -- running sshkeys-lint
|
||||||
|
|
||||||
|
Follow these steps on the client:
|
||||||
|
|
||||||
|
* get a copy of `~/.ssh/authorized_keys` from the server and put it in
|
||||||
|
`/tmp/foo` or something
|
||||||
|
|
||||||
|
* cd to `~/.ssh`
|
||||||
|
|
||||||
|
* run `sshkeys-lint *.pub < /tmp/foo`
|
||||||
|
|
||||||
|
This tells you, for each pubkey, what type of access (if any) it has to the
|
||||||
|
server.
|
||||||
|
|
||||||
|
Note that it is not trying to log in or anything -- it's just comparing bits
|
||||||
|
of text (the contents of STDIN taken as an authkeys file, and the contents of
|
||||||
|
each of the `*.pub` files one by one).
|
||||||
|
|
||||||
|
> Note: It's also a stand-alone program, so even if your gitolite version is
|
||||||
|
> old, you can safely bring over just this program from a more recent
|
||||||
|
> gitolite and use it, without having to upgrade gitolite itself.
|
||||||
|
|
||||||
|
If the pubkey file you're interested in appears to have the correct access to
|
||||||
|
the server, you're done with this step.
|
||||||
|
|
||||||
|
Otherwise you have to rename some keypairs and try again to get the effect you
|
||||||
|
need. Be careful:
|
||||||
|
|
||||||
|
* do not just rename the ".pub" file; you will have to rename the
|
||||||
|
corresponding private key also (the one with the same basename but without
|
||||||
|
an extension)
|
||||||
|
|
||||||
|
* if you're running ssh-agent, you may have to delete (using `ssh-add -D`)
|
||||||
|
and re-add identities for it to pick up the renamed ones correctly
|
||||||
|
|
||||||
|
#### typical cause(s)
|
||||||
|
|
||||||
|
The admin often has passwordless shell access to `git@server` already, and
|
||||||
|
then used that same key to get access to gitolite (i.e., copied that same
|
||||||
|
pubkey as YourName.pub and ran `gl-setup` on it).
|
||||||
|
|
||||||
|
As a result, the same key appears twice in the authkeys file now, and since
|
||||||
|
the ssh server will always use the first match, the second occurrence (which
|
||||||
|
invokes gitolite) is ignored.
|
||||||
|
|
||||||
|
To fix this, you have to use a different keypair for gitolite access. The
|
||||||
|
best way to do this is to create a new keypair, copy the pubkey to the server
|
||||||
|
as YourName.pub, then run `gl-setup YourName.pub` on the server. Remember to
|
||||||
|
adjust your agent identities using ssh-add -D and ssh-add if you're using
|
||||||
|
ssh-agent, otherwise these new keys may not work.
|
||||||
|
|
||||||
|
### #stsapp3_ appendix 3: ssh client may not be offering the right key
|
||||||
|
|
||||||
|
* make sure the right private key is being offered. Run ssh in very
|
||||||
|
verbose mode and look for the word "Offering", like so:
|
||||||
|
|
||||||
|
ssh -vvv user@host pwd 2> >(grep -i offer)
|
||||||
|
|
||||||
|
If some keys *are* being offered, but not the key that was supposed to be
|
||||||
|
used, you may be using ssh-agent (next bullet). You may also need to
|
||||||
|
create some host aliases in `~/.ssh/config` ([appendix 4][sshhostaliases]).
|
||||||
|
|
||||||
|
* (ssh-agent issues) If `ssh-add -l` responds with either "The agent has no
|
||||||
|
identities." or "Could not open a connection to your authentication
|
||||||
|
agent.", then you can skip this bullet.
|
||||||
|
|
||||||
|
However, if `ssh-add -l` lists *any* keys at all, then something weird
|
||||||
|
happens. Due to a quirk in ssh-agent, ssh will now *only* use one of
|
||||||
|
those keys, *even if you explicitly ask* for some other key to be used.
|
||||||
|
|
||||||
|
In that case, add the key you want using `ssh-add ~/.ssh/YourName` and try
|
||||||
|
the access again.
|
||||||
|
|
||||||
|
### F=sshhostaliases appendix 4: host aliases
|
||||||
|
|
||||||
|
(or "making git use the right options for ssh")
|
||||||
|
|
||||||
|
The ssh command has several options for non-default items to be specified.
|
||||||
|
Two common examples are `-p` for the port number if it is not 22, and `-i` for
|
||||||
|
the public key file if you do not want to use just `~/.ssh/id_rsa` or such.
|
||||||
|
|
||||||
|
Git has two ssh-based URL syntaxes, but neither allows specifying a
|
||||||
|
non-default public key file. And a port number is only allowed in one of
|
||||||
|
them. (See `man git-clone` for details). Finally, hosts often have to be
|
||||||
|
referred with IP addresses (such is life), or the name is very long, or hard
|
||||||
|
to remember.
|
||||||
|
|
||||||
|
Using a "host" para in `~/.ssh/config` lets you nicely encapsulate all this
|
||||||
|
within ssh and give it a short, easy-to-remember, name. Example:
|
||||||
|
|
||||||
|
host gitolite
|
||||||
|
user git
|
||||||
|
hostname a.long.server.name.or.annoying.IP.address
|
||||||
|
port 22
|
||||||
|
identityfile ~/.ssh/id_rsa
|
||||||
|
|
||||||
|
Now you can simply use the one word `gitolite` (which is the host alias we
|
||||||
|
defined here) and ssh will infer all those details defined under it -- just
|
||||||
|
say `ssh gitolite` and `git clone gitolite:reponame` and things will work.
|
||||||
|
|
||||||
|
(By the way, the 'port' and 'identityfile' lines are needed only if you have
|
||||||
|
non-default values, although I put them in anyway just to be complete).
|
||||||
|
|
||||||
|
If you have *more than one* pubkey with access to the *same* server, you
|
||||||
|
**must** use this method to make git pick up the right key. There is no other
|
||||||
|
way to do this, as far as I know.
|
||||||
|
|
||||||
|
[tut]: http://sites.google.com/site/senawario/home/gitolite-tutorial
|
||||||
|
|
||||||
|
### #stsapp5_ appendix 5: why bypassing gitolite causes a problem
|
||||||
|
|
||||||
|
When you bypass gitolite, you end up running your normal shell instead of the
|
||||||
|
special gitolite entry point script `gl-auth-command`.
|
||||||
|
|
||||||
|
This means commands (like 'info') are interpreted by the shell instead of
|
||||||
|
gitolite.
|
||||||
|
|
||||||
|
It also means git operations look for repos in `$HOME`.
|
||||||
|
|
||||||
|
However, gitolite places all your repos in a subdirectory pointed to by
|
||||||
|
`$REPO_BASE` in the rc file (default: `repositories`), and internally prefixes
|
||||||
|
this before calling the actual git command you invoked. Thus, the pathname of
|
||||||
|
the repo that you use on the client is almost never the correct pathname on
|
||||||
|
the server. (This is by design. Don't argue...)
|
||||||
|
|
||||||
|
This means that, you get 2 kinds of errors if you bypass gitolite
|
||||||
|
|
||||||
|
* when you use `git@server:reponame` with a key that bypasses gitolite
|
||||||
|
(i.e., gets you a shell), this prefixing does not happen, and so the repo
|
||||||
|
is not found. Neither a clone/fetch nor a push will work.
|
||||||
|
|
||||||
|
* conversely, consider `git@server:repositories/reponame.git`. The clone
|
||||||
|
operation will work -- you're using the full Unix path, (assuming default
|
||||||
|
`$REPO_BASE` setting), and so the shell finds the repo where you said it
|
||||||
|
would be. However, when you push, gitolite's **update hook** kicks in,
|
||||||
|
and fails to run because some of the environment variables it is expecting
|
||||||
|
are not present.
|
11
doc/extras/ssh.mkd
Normal file
11
doc/extras/ssh.mkd
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
# ssh
|
||||||
|
|
||||||
|
There are two documents you need to read, in order:
|
||||||
|
|
||||||
|
* [gitolite and ssh][glssh] -- this explains how gitolite uses openssh's
|
||||||
|
features to provide any number of virtual users over just one actual
|
||||||
|
(unix) user, and so on
|
||||||
|
|
||||||
|
* [ssh troubleshooting][sshts] -- this is a rather long document but as far
|
||||||
|
as I know almost every known ssh related issue is in here. If you find
|
||||||
|
something missing, send me an email with details.
|
6
doc/extras/unique.mkd
Normal file
6
doc/extras/unique.mkd
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
# unique setups
|
||||||
|
|
||||||
|
This page is for unique setups that I support. At present there is only one
|
||||||
|
-- Fedora.
|
||||||
|
|
||||||
|
|
10
doc/g2alt.mkd
Normal file
10
doc/g2alt.mkd
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
## #g2alt alternate implementations for some g2 features
|
||||||
|
|
||||||
|
The following g2 features have been dropped but suitable (or better)
|
||||||
|
alternatives exist.
|
||||||
|
|
||||||
|
### gl-time for performance measurement
|
||||||
|
|
||||||
|
Take a look at the 'cpu-time' program that you can set to run from the
|
||||||
|
`POST_GIT` trigger. Just set it to run as the last program in that sequence
|
||||||
|
so it covers all previous programs.
|
2
doc/g2dropped.mkd
Normal file
2
doc/g2dropped.mkd
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
## #g2dropped g2 features dropped
|
||||||
|
|
35
doc/g2incompat.mkd
Normal file
35
doc/g2incompat.mkd
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
## #g2incompat compatibility with g2
|
||||||
|
|
||||||
|
The following incompatibilities exist, in vaguely decreasing order of
|
||||||
|
severity. **The ones in the first section are IMPORTANT because they allow
|
||||||
|
access that was previously not allowed -- please fix your config before using
|
||||||
|
the new gitolite!**
|
||||||
|
|
||||||
|
### fallthru in NAME rules
|
||||||
|
|
||||||
|
Fallthru on all VREFs is "success" now, so any NAME/ rules you have **MUST**
|
||||||
|
change the ruleset in some way. The simplest is to add the following line to
|
||||||
|
the end of each repo's rule list:
|
||||||
|
|
||||||
|
- NAME/ = @all
|
||||||
|
|
||||||
|
### subconf command in admin repo
|
||||||
|
|
||||||
|
(This is also affected by the previous issue, 'fallthru in NAME rules'; please
|
||||||
|
read that as well).
|
||||||
|
|
||||||
|
If you're using delegation in your admin conf setup, please add the following
|
||||||
|
lines to the end of the gitolite-admin rules in your conf/gitolite.conf file:
|
||||||
|
|
||||||
|
repo gitolite-admin
|
||||||
|
- NAME/ = @all
|
||||||
|
|
||||||
|
subconf "fragments/*.conf"
|
||||||
|
|
||||||
|
The first part compensates for fallthru now being a success when processing
|
||||||
|
[VREF][vref] rules (NAME rules are just one specific VREF). Although,
|
||||||
|
**ideally**, you should change your ruleset so that you no longer require that
|
||||||
|
line. As the [vref documentation][vref] says:
|
||||||
|
|
||||||
|
> **Virtual refs are best used as additional "deny" rules**, performing
|
||||||
|
> extra checks that core gitolite cannot.
|
122
doc/g2migr.mkd
Normal file
122
doc/g2migr.mkd
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
## #g2migr migrating from g2
|
||||||
|
|
||||||
|
<font color="red">
|
||||||
|
|
||||||
|
**This document is a *MUST* read if you are currently using g2 and want to
|
||||||
|
move to g3.**
|
||||||
|
|
||||||
|
</font>
|
||||||
|
|
||||||
|
First things first: g2 will be supported for a good long time. My current
|
||||||
|
*expert* users do not cause me any load anyway.
|
||||||
|
|
||||||
|
Migration should be straightforward, but it is not automatic. When you first
|
||||||
|
run "gitolite setup [...]", gitolite3 will try to detect at least the big
|
||||||
|
problems. However, converting the RC file and the conf files is (as of now)
|
||||||
|
still a manual exercise, though not very difficult.
|
||||||
|
|
||||||
|
You must first read about [incompatible][g2incompat] features and
|
||||||
|
[dropped][g2dropped] features. Some features have been replaced with
|
||||||
|
[alternatives][g2alt].
|
||||||
|
|
||||||
|
Since the majority of changes are in the rc file, we list them all here.
|
||||||
|
|
||||||
|
### rc file differences
|
||||||
|
|
||||||
|
**DROPPED** variables (possible high impact): these could be show-stoppers for
|
||||||
|
migration, at least for now.
|
||||||
|
|
||||||
|
* `BIG_INFO_CAP` -- if you think you must have this, try it without and see
|
||||||
|
if there's a difference. If you *know* you need this, convince me.
|
||||||
|
|
||||||
|
* `GL_ALL_READ_ALL` -- same
|
||||||
|
|
||||||
|
* `GL_NO_CREATE_REPOS` -- if you think you need this, email me. I know one
|
||||||
|
group who does need this so I will be putting it in eventually but not
|
||||||
|
right away.
|
||||||
|
|
||||||
|
* `HTPASSWD_FILE`, `RSYNC_BASE`, `SVNSERVE` -- need work. Email me if you
|
||||||
|
are using any of these.
|
||||||
|
|
||||||
|
* `GL_GET_MEMBERSHIPS_PGM` -- is on my todo list
|
||||||
|
|
||||||
|
* `GL_LOGT` -- is now fixed; you can't change it. Email me if this is a
|
||||||
|
problem.
|
||||||
|
|
||||||
|
**DROPPED** variables (medium impact): these have alternative implementations
|
||||||
|
or mechanisms, but you have to do some setup work.
|
||||||
|
|
||||||
|
* `GL_ADMINDIR` -- this is now at a fixed location: `~/.gitolite`. If you
|
||||||
|
want it somewhere else go ahead and move it, then place a symlink from the
|
||||||
|
assumed location to the real one.
|
||||||
|
|
||||||
|
* `REPO_BASE` -- this is now at a fixed location: `~/repositories`. If you
|
||||||
|
want it somewhere else go ahead and move it, then place a symlink from the
|
||||||
|
assumed location to the real one.
|
||||||
|
|
||||||
|
* `PROJECTS_LIST` -- it's called `GITWEB_PROJECTS_LIST` now, but more
|
||||||
|
importantly, it is only used by update-gitweb-access-list in
|
||||||
|
src/commands/post-compile. This variable now has nothing to do with
|
||||||
|
gitolite core, and the rc is just helping to store settings for external
|
||||||
|
programs like that one.
|
||||||
|
|
||||||
|
`WEB_INTERFACE` and `GITWEB_URI_ESCAPE` are also gone; patches to the
|
||||||
|
update program to directly do those things are welcome.
|
||||||
|
|
||||||
|
* `GL_NO_DAEMON_NO_GITWEB` -- uncomment the appropriate lines in the rc
|
||||||
|
file, in both the `POST_COMPILE` and `POST_CREATE` trigger sections.
|
||||||
|
|
||||||
|
* `NICE_VALUE` -- use the `PRE_GIT` trigger to attach a program that renices
|
||||||
|
the pid given by $GL_TID (that's the pid of the initial gitolite entry
|
||||||
|
point, usually gitolite-shell, and propagates from there once set).
|
||||||
|
|
||||||
|
You may have to add this list to the rc file; if you don't know perl use
|
||||||
|
one of the others as a model or ask me.
|
||||||
|
|
||||||
|
* `GIT_PATH` -- gone, not needed. Just add these lines to the end of the rc
|
||||||
|
file:
|
||||||
|
|
||||||
|
$ENV{PATH}="...whatever you want...";
|
||||||
|
1;
|
||||||
|
|
||||||
|
* `GL_NO_SETUP_AUTHKEYS` -- comment out the lines that call ssh-authkeys, in
|
||||||
|
the rc file.
|
||||||
|
|
||||||
|
* `GL_WILDREPOS_DEFPERMS` -- if you need this, add a `POST_CREATE` script
|
||||||
|
that does it. Or email me and I will write it for you.
|
||||||
|
|
||||||
|
* `UPDATE_CHAINS_TO` -- use a [vref][] instead. You can directly use the
|
||||||
|
chained-to script as a VREF; it'll work.
|
||||||
|
|
||||||
|
* `ADMIN_POST_UPDATE_CHAINS_TO` -- add your script to the `POST_COMPILE`
|
||||||
|
trigger chain. You won't be getting any arguments but for the admin repo
|
||||||
|
the only argument that ever comes in is "refs/heads/master" anyway.
|
||||||
|
|
||||||
|
* `GL_ADC_PATH` -- obsolete; use [commands][] or add [your own][dev-notes].
|
||||||
|
|
||||||
|
* `GL_ALL_INCLUDES_SPECIAL` -- obsolete; @all always includes gitweb and
|
||||||
|
daemon now. Use [deny-rules][] if you want to say `R = @all` but not have
|
||||||
|
it be visible to gitweb or daemon.
|
||||||
|
|
||||||
|
* `GL_PERFLOGT` -- see the entry for "gl-time" in the [alternative
|
||||||
|
implementations][g2alt] page.
|
||||||
|
|
||||||
|
**DROPPED** variables (no impact/low impact): these variables should not
|
||||||
|
actually affect anything anyway, so even if you had them set you should not
|
||||||
|
feel their loss.
|
||||||
|
|
||||||
|
* `GL_CONF`, `GL_KEYDIR`, and `GL_CONF_COMPILED` -- you had no business
|
||||||
|
touching these anyway; if you did, move them into the expected default
|
||||||
|
locations before attempting to run `gitolite setup`
|
||||||
|
* `GL_PACKAGE_HOOKS` -- not needed anymore, but check if you had any custom
|
||||||
|
hooks set there and copy them across.
|
||||||
|
* `GL_WILDREPOS` -- dropped; this feature is default now.
|
||||||
|
* `GL_BIG_CONFIG` -- dropped; this feature is default now.
|
||||||
|
|
||||||
|
**RENAMED** variables (no impact): these are functionally the same but are
|
||||||
|
renamed.
|
||||||
|
|
||||||
|
* `REPO_UMASK` is now `UMASK`
|
||||||
|
* `GL_GITCONFIG_KEYS` is now `GITCONFIG_KEYS`
|
||||||
|
* `GL_WILDREPOS_PERM_CATS` is now the ROLES hash in the rc file
|
||||||
|
* `GL_SITE_INFO` is not `SITE_INFO`
|
97
doc/g3why.mkd
Normal file
97
doc/g3why.mkd
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
# why a completely new version?
|
||||||
|
|
||||||
|
Gitolite started life as 400 lines of perl written on a weekend because I was
|
||||||
|
quickly losing control of my projects at work, exacerbated by git newbies
|
||||||
|
doing all the wrong things. I really needed it!
|
||||||
|
|
||||||
|
That little 400 line thing is now a huge bunch of programs that do all sorts
|
||||||
|
of things (I mean, rsync access control in a git related program? WTF!),
|
||||||
|
because it kinda just *grew* while I wasn't looking.
|
||||||
|
|
||||||
|
So, briefly, here are the advantages of g3:
|
||||||
|
|
||||||
|
* compile versus everything else
|
||||||
|
|
||||||
|
g2's "compile" script was doing way, way too much. For example, dealing
|
||||||
|
with gitweb and git-daemon was a good chunk of code in g2. In contrast,
|
||||||
|
here's how g3 generates gitweb's projects.list file:
|
||||||
|
|
||||||
|
(
|
||||||
|
gitolite list-phy-repos | gitolite access % gitweb R any | grep -v DENIED
|
||||||
|
gitolite list-phy-repos | gitolite git-config -r % gitweb\\.
|
||||||
|
) |
|
||||||
|
cut -f1 | sort -u | sed -e 's/$/.git/' > $plf
|
||||||
|
|
||||||
|
* core versus non-core
|
||||||
|
|
||||||
|
That's just the tip of the iceberg. The commands above run from a script
|
||||||
|
that is itself outside gitolite, and can be enabled and disabled from the
|
||||||
|
rc file. There are six different "events" within gitolite that can
|
||||||
|
trigger external programs, with specific arguments passed to them, much
|
||||||
|
like git's own hooks. The example you saw is called from the
|
||||||
|
"POST_COMPILE" trigger.
|
||||||
|
|
||||||
|
And as you can see, these programs be in any language.
|
||||||
|
|
||||||
|
* get/set perms/desc, and ADCs
|
||||||
|
|
||||||
|
I've always wanted to kick setperms out of core and make it an ADC.
|
||||||
|
Sadly, it couldn't be done because when you update your repo's permissions
|
||||||
|
using setperms, that can affect gitweb/daemon access, which -- you guessed
|
||||||
|
right -- feeds back into the main code in complex ways. It *had* to be an
|
||||||
|
"inside job".
|
||||||
|
|
||||||
|
But now, the new 'perms' program is quite external to gitolite. And how
|
||||||
|
does it fix up gitweb/daemon permissions after it is done updating the
|
||||||
|
"gl-perms" file?
|
||||||
|
|
||||||
|
system("gitolite", "trigger", "POST_CREATE");
|
||||||
|
|
||||||
|
* syntax versus semantics
|
||||||
|
|
||||||
|
I got tired of people asking things like "why can't I have
|
||||||
|
backslash-escaped continuation lines?" I designed it differently because
|
||||||
|
I don't like them but perhaps it's reasonable for some people.
|
||||||
|
|
||||||
|
Someone else wanted to use subdirectories of 'keydir' as group names. Why
|
||||||
|
not?
|
||||||
|
|
||||||
|
G3 comes with a stackable set of "syntactic sugar" helpers. And you can
|
||||||
|
write your own, though they do have to be in perl (because they're not
|
||||||
|
standalone programs).
|
||||||
|
|
||||||
|
Once the code is written and placed in the right place, all a site has to
|
||||||
|
do to enable it is to uncomment some lines in the rc file:
|
||||||
|
|
||||||
|
# these will run in sequence during the conf file parse
|
||||||
|
SYNTACTIC_SUGAR =>
|
||||||
|
[
|
||||||
|
# 'continuation-lines',
|
||||||
|
# 'keysubdirs-as-groups',
|
||||||
|
<etc>
|
||||||
|
|
||||||
|
* roll your own
|
||||||
|
|
||||||
|
Having a decent shell API helps enormously. You saw an example above but
|
||||||
|
how about if your boss asks you "I need a list of everyone who *currently*
|
||||||
|
has read access to the 'foo' repo"?
|
||||||
|
|
||||||
|
Sure you could look in conf/gitolite.conf, all its include files (if you
|
||||||
|
have any), and if the repo is user-created, then in its gl-perms.
|
||||||
|
|
||||||
|
Or you could do something like this:
|
||||||
|
|
||||||
|
gitolite list-users | gitolite access foo % R any | cut -f1
|
||||||
|
|
||||||
|
* over-engineered
|
||||||
|
|
||||||
|
g2 was, to some extent, over-engineered. One of the best examples is the
|
||||||
|
documentation on hook-propagation in g2, which required even a *picture*
|
||||||
|
to make clear (always a bad sign). In g3, the [hooks][] section is 4
|
||||||
|
sentences.
|
||||||
|
|
||||||
|
Anyway you get the idea.
|
||||||
|
|
||||||
|
The point is not that you can do all these cool tricks. The point is they are
|
||||||
|
possible because of the redesign. There is no way on God's green earth I
|
||||||
|
could have done this with the old code.
|
32
doc/group.mkd
Normal file
32
doc/group.mkd
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
# parts of the conf file
|
||||||
|
|
||||||
|
## #group group definitions
|
||||||
|
|
||||||
|
You can group repos or users for convenience. The syntax is the same for both
|
||||||
|
and does not distinguish; until you *use* the group name it could really be
|
||||||
|
either.
|
||||||
|
|
||||||
|
Here's an example:
|
||||||
|
|
||||||
|
@developers = dilbert alice wally
|
||||||
|
|
||||||
|
Group definitions accumulate; this is the same as the above:
|
||||||
|
|
||||||
|
@developers = dilbert
|
||||||
|
@developers = alice
|
||||||
|
@developers = wally
|
||||||
|
|
||||||
|
You can use one group in another group definition; the values will be expanded
|
||||||
|
right there (meaning later additions will not appear in the second group).
|
||||||
|
|
||||||
|
@developers = dilbert alice
|
||||||
|
@interns = ashok
|
||||||
|
@staff = @interns @developers
|
||||||
|
@developers = wally
|
||||||
|
|
||||||
|
# wally is NOT part of @staff
|
||||||
|
|
||||||
|
### special group `@all`
|
||||||
|
|
||||||
|
`@all` is a special group name that is often convenient to use if you really
|
||||||
|
mean "all repos" or "all users".
|
9
doc/hooks.mkd
Normal file
9
doc/hooks.mkd
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# hooks and gitolite
|
||||||
|
|
||||||
|
Gitolite uses the `update` hook for all repos. In addition, it uses the
|
||||||
|
`post-update` hook for the gitolite-admin repo.
|
||||||
|
|
||||||
|
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' :-)
|
67
doc/index.mkd
Normal file
67
doc/index.mkd
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
# Hosting git repositories
|
||||||
|
|
||||||
|
Gitolite allows you to setup git hosting on a central server, with
|
||||||
|
fine-grained access control and many more powerful features.
|
||||||
|
|
||||||
|
Here's more on [what][] it is and [why][] you might need it.
|
||||||
|
|
||||||
|
For current gitolite (call it "g2" for convenience) users,
|
||||||
|
|
||||||
|
* [Why][g3why] I rewrote gitolite.
|
||||||
|
* Development [status][dev-status] (**should change often for a while**)
|
||||||
|
* Specific migration [issues and steps][g2migr].
|
||||||
|
|
||||||
|
Quick links:
|
||||||
|
|
||||||
|
* [Minimum requirements][minreq].
|
||||||
|
* Here's how to [get started][qi] installing and setting it up
|
||||||
|
* Don't know ssh well enough? [Learn][ssh]. It's **IMPORTANT**.
|
||||||
|
* [Add users and repos][add].
|
||||||
|
* Learn about fine-grained access control with the [conf][] file
|
||||||
|
* Explain gitolite to your [users][].
|
||||||
|
|
||||||
|
Not so "quick" links:
|
||||||
|
|
||||||
|
* The "master table of contents" link at the top of each page is the
|
||||||
|
**first** place you should check when looking for anything.
|
||||||
|
|
||||||
|
* Want to do more than just add users and repos and control their access?
|
||||||
|
Here's how to [customise][cust] your server installation.
|
||||||
|
|
||||||
|
Additional reading for Unix newbies:
|
||||||
|
|
||||||
|
* [Regular Expressions][regex]
|
||||||
|
|
||||||
|
## #what What is gitolite?
|
||||||
|
|
||||||
|
Gitolite is an access control layer on top of git. Here are the features that
|
||||||
|
most people see:
|
||||||
|
|
||||||
|
* use a single unix user ("real" user) on the server
|
||||||
|
* provide access to many gitolite users
|
||||||
|
* they are not "real" users
|
||||||
|
* they do not get shell access
|
||||||
|
* control access to many git repositories
|
||||||
|
* read access controlled at the repo level
|
||||||
|
* write access controlled at the branch/tag/file/directory level,
|
||||||
|
including who can rewind, create, and delete branches/tags
|
||||||
|
* can be installed without root access, assuming git and perl are already
|
||||||
|
installed
|
||||||
|
* authentication is most commonly done using sshd, but you can also use
|
||||||
|
httpd if you prefer (this may require root access).
|
||||||
|
|
||||||
|
## #contact contact
|
||||||
|
|
||||||
|
* author: sitaramc@gmail.com, sitaram@atc.tcs.com
|
||||||
|
* mailing list: gitolite@googlegroups.com
|
||||||
|
* list subscribe address : gitolite+subscribe@googlegroups.com
|
||||||
|
* IRC: #git and #gitolite on freenode. Note that I live in India (UTC+0530
|
||||||
|
time zone).
|
||||||
|
|
||||||
|
## #license license
|
||||||
|
|
||||||
|
The gitolite *code* is released under GPL v2. See COPYING for details.
|
||||||
|
|
||||||
|
The gitolite documentation is provided under a [Creative Commons
|
||||||
|
Attribution-NonCommercial-ShareAlike 3.0 Unported
|
||||||
|
License](http://creativecommons.org/licenses/by-nc-sa/3.0/).
|
58
doc/install.mkd
Normal file
58
doc/install.mkd
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
# different ways to install gitolite
|
||||||
|
|
||||||
|
Gitolite has only one server side "command" now, much like git itself. And
|
||||||
|
it's been designed so that you don't even really have to *install* it, as you
|
||||||
|
will see.
|
||||||
|
|
||||||
|
## simplest
|
||||||
|
|
||||||
|
1. Put all of `src` in one place, doesn't matter where; let's call it
|
||||||
|
/foo/bar.
|
||||||
|
|
||||||
|
2. Use the full path to run any gitolite commands, for example:
|
||||||
|
|
||||||
|
/foo/bar/gitolite setup -pk sitaram.pub
|
||||||
|
|
||||||
|
## almost as simple
|
||||||
|
|
||||||
|
1. (same as above)
|
||||||
|
|
||||||
|
2. Symlink /foo/bar/gitolite to some directory that is on your PATH. For
|
||||||
|
example:
|
||||||
|
|
||||||
|
ln -sf /foo/bar/gitolite ~/bin
|
||||||
|
|
||||||
|
Now you can just say
|
||||||
|
|
||||||
|
gitolite setup -pk sitaram.pub
|
||||||
|
|
||||||
|
## packagers
|
||||||
|
|
||||||
|
1. Put src/Gitolite in `/usr/share/perl5/vendor_perl` or some such place.
|
||||||
|
|
||||||
|
2. Put the rest of src anywhere your distro policy allows. (Fedora keeps
|
||||||
|
git's 150 executables in /usr/libexec/git-core, so maybe
|
||||||
|
/usr/libexec/gitolite?)
|
||||||
|
|
||||||
|
3. Symlink 'gitolite' to /usr/bin or something, similar to step 2 above,
|
||||||
|
|
||||||
|
OR
|
||||||
|
|
||||||
|
Put it directly in /usr/bin, and hardcode `GL_BINDIR` into it to tell it
|
||||||
|
where the others are. I'd prefer it if you did not do this but you can.
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
Bottom line:
|
||||||
|
|
||||||
|
* `GL_BINDIR` must point to a place that contains `commands`, `VREF`, and
|
||||||
|
`syntactic-sugar` (so they must all be sibling directories).
|
||||||
|
* The `Gitolite` directory can also be there, or it can be anywhere in
|
||||||
|
perl's `@INC` path.
|
||||||
|
|
||||||
|
## upgrading
|
||||||
|
|
||||||
|
Just put the new version on top of wherever you kept the old one. That's it.
|
||||||
|
|
||||||
|
If you feel it should require a little more effort, pretend I said "you have
|
||||||
|
to then run `gitolite setup`". Can't hurt...
|
43
doc/list
Normal file
43
doc/list
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
|
||||||
|
index.mkd
|
||||||
|
why.mkd
|
||||||
|
|
||||||
|
g3why.mkd
|
||||||
|
dev-status.mkd
|
||||||
|
g2migr.mkd
|
||||||
|
g2incompat.mkd
|
||||||
|
g2dropped.mkd
|
||||||
|
g2alt.mkd
|
||||||
|
|
||||||
|
minreq.mkd
|
||||||
|
qi.mkd
|
||||||
|
install.mkd
|
||||||
|
add.mkd
|
||||||
|
conf.mkd
|
||||||
|
users.mkd
|
||||||
|
|
||||||
|
rc.mkd
|
||||||
|
cust.mkd
|
||||||
|
|
||||||
|
group.mkd
|
||||||
|
repo.mkd
|
||||||
|
rules.mkd
|
||||||
|
refex.mkd
|
||||||
|
write-types.mkd
|
||||||
|
|
||||||
|
dev-notes.mkd
|
||||||
|
commands.mkd
|
||||||
|
hooks.mkd
|
||||||
|
triggers.mkd
|
||||||
|
sugar.mkd
|
||||||
|
vref.mkd
|
||||||
|
|
||||||
|
misc.mkd
|
||||||
|
pw.mkd
|
||||||
|
testing.mkd
|
||||||
|
extras/auth.mkd
|
||||||
|
extras/nagp.mkd
|
||||||
|
extras/regex.mkd
|
||||||
|
extras/ssh.mkd
|
||||||
|
extras/gitolite-and-ssh.mkd
|
||||||
|
extras/ssh-troubleshooting.mkd
|
32
doc/minreq.mkd
Normal file
32
doc/minreq.mkd
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
# minimum requirements for gitolite
|
||||||
|
|
||||||
|
**Client**:
|
||||||
|
|
||||||
|
* git 1.6.6 or greater
|
||||||
|
* an ssh client that can talk to an openssh server, and can generate keys in
|
||||||
|
openssh's default format (the pubkey is just one long line). Gitolite
|
||||||
|
will [not currently][pw1] convert such keys.
|
||||||
|
|
||||||
|
For people still using Windows, msysgit works fine. If you're using
|
||||||
|
[putty/plink][ens], God bless you. (It'll work, but I still want him to bless
|
||||||
|
you).
|
||||||
|
|
||||||
|
TODO: when smart http support works, ssh will no longer be a *requirement*,
|
||||||
|
merely a *strong* suggestion :-)
|
||||||
|
|
||||||
|
**Server**
|
||||||
|
|
||||||
|
* git 1.6.6 or greater
|
||||||
|
* perl 5.8.8 or greater
|
||||||
|
* an ssh server compatible with openssh, especially it's authorized keys
|
||||||
|
file format and features.
|
||||||
|
* any Unix or Unix like OS. That said, I've occasionally had some weird
|
||||||
|
reports from [Mac OSX servers][ens]; good luck.
|
||||||
|
* a single, dedicated, userid to host it (usually 'git' or 'gitolite').
|
||||||
|
|
||||||
|
These version numbers are subject to fine-tuning as I get feedback and make
|
||||||
|
fixes where possible and needed.
|
||||||
|
|
||||||
|
Sshd must be configured so that each users authkeys file is in the user's
|
||||||
|
`$HOME`, inside `.ssh/authorized_keys`, and not in some central
|
||||||
|
/var/something.
|
80
doc/misc.mkd
Normal file
80
doc/misc.mkd
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
# odds and ends
|
||||||
|
|
||||||
|
Most of these items don't fit anywhere or fit in more than one place or are of
|
||||||
|
the nature of background information.
|
||||||
|
|
||||||
|
## #include include files
|
||||||
|
|
||||||
|
Gitolite allows you to break up the configuration into multiple files and
|
||||||
|
include them in the main file for convenience.
|
||||||
|
|
||||||
|
include "foo.conf"
|
||||||
|
|
||||||
|
will include the contents of the file "foo.conf" from the "conf" directory.
|
||||||
|
|
||||||
|
Details:
|
||||||
|
|
||||||
|
* You can also use a glob (`include "*.conf"`), or put your include files
|
||||||
|
into subdirectories of "conf" (`include "foo/bar.conf"`), or both
|
||||||
|
(`include "repos/*.conf"`).
|
||||||
|
|
||||||
|
* Included files are always searched relative to the gitolite-admin repo's
|
||||||
|
"conf/" directory.
|
||||||
|
|
||||||
|
* If you ended up recursing, files that have been already processed once are
|
||||||
|
skipped, with a warning.
|
||||||
|
|
||||||
|
<font color="gray">Advanced users: `subconf`, a command that is very closely
|
||||||
|
related to `include`, is documented [here][subconf].</font>
|
||||||
|
|
||||||
|
## #deny-rules applying deny rules at the pre-git access check
|
||||||
|
|
||||||
|
The access [rules][] rules section describes the problem. To recap, you want
|
||||||
|
this:
|
||||||
|
|
||||||
|
@staff = alice bob wally ashok
|
||||||
|
|
||||||
|
repo foo
|
||||||
|
RW+ = alice # line 1
|
||||||
|
RW+ dev = bob # line 2
|
||||||
|
- = wally # line 3
|
||||||
|
RW temp/ = @staff # line 4
|
||||||
|
|
||||||
|
to deny Wally even *read* access.
|
||||||
|
|
||||||
|
The way to do this is to add this line to the repo:
|
||||||
|
|
||||||
|
option deny-rules = 1
|
||||||
|
|
||||||
|
If you want this for all your repos, just add this somewhere at the top of
|
||||||
|
your conf file
|
||||||
|
|
||||||
|
repo @all
|
||||||
|
option deny-rules = 1
|
||||||
|
|
||||||
|
## #rule-accum rule accumulation
|
||||||
|
|
||||||
|
Gitolite was meant to collect rules from multiple places and apply them all.
|
||||||
|
For example, this:
|
||||||
|
|
||||||
|
repo foo
|
||||||
|
RW = u1
|
||||||
|
|
||||||
|
@gr1 = foo bar
|
||||||
|
|
||||||
|
repo @gr1
|
||||||
|
RW = u2
|
||||||
|
R = u3
|
||||||
|
|
||||||
|
repo @all
|
||||||
|
R = gitweb
|
||||||
|
|
||||||
|
is effectively the same as this, for repo foo:
|
||||||
|
|
||||||
|
repo foo
|
||||||
|
RW = u1
|
||||||
|
RW = u2
|
||||||
|
R = u3
|
||||||
|
R = gitweb
|
||||||
|
|
||||||
|
This extends to patterns also, but I'll leave an example for later.
|
88
doc/mkdoc
Executable file
88
doc/mkdoc
Executable file
|
@ -0,0 +1,88 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
|
||||||
|
my $MKD = "$ENV{HOME}/Markdown.pl";
|
||||||
|
|
||||||
|
# run this like so:
|
||||||
|
|
||||||
|
# $0 *.mkd >mt.mkd 2>mf
|
||||||
|
|
||||||
|
use 5.10.0;
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
chomp(@ARGV = `cat list`) if not @ARGV;
|
||||||
|
@ARGV = grep { $_ ne 'master-toc.mkd' and /./ } @ARGV;
|
||||||
|
my @save = @ARGV;
|
||||||
|
my $css = join("", <DATA>);
|
||||||
|
|
||||||
|
my $mt = "# gitolite master table of contents/index\n";
|
||||||
|
my $mf = '';
|
||||||
|
my $fh;
|
||||||
|
|
||||||
|
while (<>) {
|
||||||
|
$ARGV =~ /^(?:.*\/)?([^\/]+)\.mkd$/;
|
||||||
|
my $b = $1;
|
||||||
|
|
||||||
|
if (/^(#+) (?:#(\S+) )?(.*)/) {
|
||||||
|
if ( length($1) == 1 ) {
|
||||||
|
$mt .= "\n";
|
||||||
|
$mt .= " * [$3][$b]\n";
|
||||||
|
$mf .= "[$b]: $b.html\n";
|
||||||
|
} else {
|
||||||
|
$mt .= " " x ( 4 * ( length($1) - 1 ) );
|
||||||
|
$mt .= " * ";
|
||||||
|
$mt .= (
|
||||||
|
$2
|
||||||
|
? "[$3][$2]"
|
||||||
|
: "$3"
|
||||||
|
);
|
||||||
|
$mt .= "\n";
|
||||||
|
$mf .= "[$2]: $b.html#$2\n" if $2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open($fh, ">", "master-toc.mkd")
|
||||||
|
and print $fh $mt
|
||||||
|
and close $fh;
|
||||||
|
|
||||||
|
# after this, do this for every mkd (including the master-toc.mkd)
|
||||||
|
|
||||||
|
# cat $css_block > $base.html
|
||||||
|
# cat $base.mkd $mf | $MKD >> $base.html
|
||||||
|
|
||||||
|
for my $mkd ("master-toc.mkd", @save) {
|
||||||
|
$mkd =~ /^(?:.*\/)?([^\/]+)\.mkd$/;
|
||||||
|
my $b = $1;
|
||||||
|
|
||||||
|
open($fh, ">", "../html/$b.html")
|
||||||
|
and print $fh $css
|
||||||
|
and close $fh;
|
||||||
|
|
||||||
|
my $mkt = `cat $mkd`;
|
||||||
|
$mkt =~ s/^(#+) #(\S+) /$1 <a name="$2"><\/a> /mg;
|
||||||
|
open($fh, "|-", "$MKD >> ../html/$b.html")
|
||||||
|
and print $fh $mkt, $mf
|
||||||
|
and close $fh;
|
||||||
|
}
|
||||||
|
|
||||||
|
__DATA__
|
||||||
|
|
||||||
|
<head><style>
|
||||||
|
body { background: #fff; margin-left: 40px; font-size: 0.9em; font-family: sans-serif; max-width: 800px; }
|
||||||
|
h1 { background: #ffb; margin-left: -30px; border-top: 5px solid #ccc; }
|
||||||
|
h2 { background: #ffb; margin-left: -20px; border-top: 3px solid #ddd; }
|
||||||
|
h3 { background: #ffb; margin-left: -10px; }
|
||||||
|
h4 { background: #ffb; }
|
||||||
|
code { font-size: 1.1em; background: #ddf; }
|
||||||
|
pre { margin-left: 2em; background: #ddf; }
|
||||||
|
pre code { font-size: 1.1em; background: #ddf; }
|
||||||
|
</style></head>
|
||||||
|
|
||||||
|
<p style="text-align:center">
|
||||||
|
<a href="master-toc.html">master TOC</a>
|
||||||
|
|
|
||||||
|
<a href="index.html">main page</a>
|
||||||
|
|
|
||||||
|
<a href="index.html#license">license</a>
|
||||||
|
</p>
|
45
doc/pw.mkd
Normal file
45
doc/pw.mkd
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
# patches welcome :-)
|
||||||
|
|
||||||
|
These are places where I could use some help, with hints about how you would
|
||||||
|
go about it. In addition, any of the items in [dev-status][] are up for
|
||||||
|
grabs, if you wish to jump in. But let me know before you start, and how you
|
||||||
|
plan to go about it.
|
||||||
|
|
||||||
|
## #pw2 rsync
|
||||||
|
|
||||||
|
The crux of the old rsync ADC was an access check to a repo whose name starts
|
||||||
|
with EXTCMD. g2 would treat repos whose names start with EXTCMD as "don't
|
||||||
|
create this repo". g3 makes no such distinctions, but you can get the same
|
||||||
|
effect by using a repo group name that does not exist:
|
||||||
|
|
||||||
|
repo @rsync-set1
|
||||||
|
...rules...
|
||||||
|
|
||||||
|
and check that in the script. (It might mean adding one more function to
|
||||||
|
Gitolite::Easy but that's... easy!)
|
||||||
|
|
||||||
|
## #pw1 converting non-openssh pubkeys automatically
|
||||||
|
|
||||||
|
Gitolite's [triggers][] has can be used to fix this. Here's pseudo-code:
|
||||||
|
|
||||||
|
chdir $(gitolite query-rc -n GL_ADMIN_BASE)/keydir
|
||||||
|
for each *.pub file in this directory and its subdirectories
|
||||||
|
detect its format and convert it
|
||||||
|
# just overwrite it; the original is saved in git anyway
|
||||||
|
|
||||||
|
Let's say the program is called "convert-non-openssh-keys". You send it to me
|
||||||
|
and I add it to src/commands/post-compile/. Then I update the default rc file
|
||||||
|
to look at least like this instead
|
||||||
|
|
||||||
|
POST_COMPILE =>
|
||||||
|
[
|
||||||
|
# 'post-compile/convert-non-openssh-keys',
|
||||||
|
'post-compile/ssh-authkeys',
|
||||||
|
...
|
||||||
|
...
|
||||||
|
],
|
||||||
|
|
||||||
|
making sure to place it *before* ssh-authkeys, and anyone who needs it can
|
||||||
|
just uncomment it.
|
||||||
|
|
||||||
|
Done!
|
26
doc/qi.mkd
Normal file
26
doc/qi.mkd
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
# getting started
|
||||||
|
|
||||||
|
The quickest install, assuming your `$PATH` contains `$HOME/bin`, is:
|
||||||
|
|
||||||
|
* get the software
|
||||||
|
|
||||||
|
git clone git://github.com/sitaramc/gitolite
|
||||||
|
|
||||||
|
# (until this becomes "master")
|
||||||
|
cd gitolite
|
||||||
|
git checkout -f g3
|
||||||
|
|
||||||
|
* install it
|
||||||
|
|
||||||
|
ln -sf $PWD/src/gitolite $HOME/bin
|
||||||
|
|
||||||
|
If you don't like that, there are [other install methods][install].
|
||||||
|
|
||||||
|
Once the install is done, setup:
|
||||||
|
|
||||||
|
gitolite setup -pk your-name.pub
|
||||||
|
|
||||||
|
And that's it.
|
||||||
|
|
||||||
|
Next steps are usually [adding][add] users and repos and learning about
|
||||||
|
[access control][conf].
|
20
doc/rc.mkd
Normal file
20
doc/rc.mkd
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# the "rc" file ($HOME/.gitolite.rc)
|
||||||
|
|
||||||
|
The rc file for g3 is quite different from that of g2. It has been designed
|
||||||
|
to be (a) the only thing unique to your site, for most installations and (b)
|
||||||
|
easy to extend when new needs show up, without having to touch core gitolite.
|
||||||
|
|
||||||
|
g2 had a nasty rc file where every variable had to be declared. As a result,
|
||||||
|
ADCs that needed their own settings could not use it.
|
||||||
|
|
||||||
|
Now it's a perl hash, and you can add any keys you want.
|
||||||
|
|
||||||
|
Please look at the rc file that gets installed when you setup gitolite. As
|
||||||
|
you can see there are 3 types of variables in it:
|
||||||
|
|
||||||
|
* simple variables (like UMASK)
|
||||||
|
* lists (like `POST_COMPILE`, `POST_CREATE`)
|
||||||
|
* hashes (like `ROLES`, `COMMANDS`)
|
||||||
|
|
||||||
|
Their purposes are to be found in each of their individual documentation files
|
||||||
|
around; start with [customising gitolite][cust].
|
30
doc/refex.mkd
Normal file
30
doc/refex.mkd
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
## #refex matching a ref and a refex
|
||||||
|
|
||||||
|
A refex is a word I made up to mean "a regex that matches a ref". If you know
|
||||||
|
[regular expressions][regex] you're halfway there.
|
||||||
|
|
||||||
|
The only extra info you need is:
|
||||||
|
|
||||||
|
* for convenience, a refex not starting with `refs/` is assumed to start
|
||||||
|
with `refs/heads/`. This means normal branches can be referred to like
|
||||||
|
this:
|
||||||
|
|
||||||
|
RW master = alice
|
||||||
|
# becomes 'refs/heads/master' internally
|
||||||
|
|
||||||
|
while tags will need to be fully qualified
|
||||||
|
|
||||||
|
RW refs/tags/v[0-9] = bob
|
||||||
|
|
||||||
|
* a refex is implicitly anchored at the start, but not at the end. In
|
||||||
|
regular expression lingo, a `^` is assumed at the start (but no `$` at the
|
||||||
|
end is assumed). So a refex of `master` will allow all these:
|
||||||
|
|
||||||
|
refs/heads/master
|
||||||
|
refs/heads/master1
|
||||||
|
refs/heads/master2
|
||||||
|
refs/heads/master/full
|
||||||
|
|
||||||
|
If you want to restrict to just the one specific ref, use
|
||||||
|
|
||||||
|
RW master$ = alice
|
23
doc/repo.mkd
Normal file
23
doc/repo.mkd
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
## #repo repo definitions
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
repo gitolite tsh gitpod
|
||||||
|
RW+ = sitaram
|
||||||
|
RW dev = alice bob
|
||||||
|
R = @all
|
||||||
|
|
||||||
|
The "repo" line can have any number of repo names or repo group names in it.
|
||||||
|
However, it can only be one line; this will not work
|
||||||
|
|
||||||
|
repo foo
|
||||||
|
repo bar # WRONG; 'foo' is now forgotten
|
||||||
|
RW = alice
|
||||||
|
|
||||||
|
If you have too many, use a group name:
|
||||||
|
|
||||||
|
@myrepos = foo
|
||||||
|
@myrepos = bar
|
||||||
|
|
||||||
|
repo @myrepos
|
||||||
|
RW = alice
|
82
doc/rules.mkd
Normal file
82
doc/rules.mkd
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
## #rules access rules
|
||||||
|
|
||||||
|
This is arguably the most complex part of day-to-day gitolite. There are
|
||||||
|
several interconnected ideas that make this hard to lay out easily if you're
|
||||||
|
totally new to this, so read carefully.
|
||||||
|
|
||||||
|
We will use this as a running example:
|
||||||
|
|
||||||
|
@staff = dilbert alice wally bob
|
||||||
|
|
||||||
|
repo foo
|
||||||
|
RW+ = dilbert # line 1
|
||||||
|
RW+ dev = alice # line 2
|
||||||
|
- = wally # line 3
|
||||||
|
RW temp/ = @staff # line 4
|
||||||
|
R = ashok # line 5
|
||||||
|
|
||||||
|
### when does gitolite check access
|
||||||
|
|
||||||
|
The "pre-git" check is before git is invoked. Gitolite knows the repo name,
|
||||||
|
user name, and attempted access (R or W), but no ref name.
|
||||||
|
|
||||||
|
The "update" check is only for write operations, and it is just before git
|
||||||
|
updates a ref. This time gitolite knows the refname also.
|
||||||
|
|
||||||
|
### how is a particular rule line matched
|
||||||
|
|
||||||
|
For the **pre-git check**, any permission that contains "R" matches a read
|
||||||
|
operation, and any permission that contains "W" matches a write operation.
|
||||||
|
This is because we simply don't know enough to make finer distinctions at this
|
||||||
|
point.
|
||||||
|
|
||||||
|
In addition, *gitolite ignores deny rules during the pre-git check*. <font
|
||||||
|
color="gray">(You can [change this][deny-rules] if you wish, though it's
|
||||||
|
rarely needed)</font>. This means line 3 is ignored, and so Wally in our
|
||||||
|
example will pass the pre-git check.
|
||||||
|
|
||||||
|
For the **update check**, git gives us all the information we need. Then:
|
||||||
|
|
||||||
|
* all the rules for a repo are [accumulated][rule-accum]
|
||||||
|
|
||||||
|
* then the rules pertaining to this repo *and* this user (or to a group to
|
||||||
|
which they belong, respectively) are kept; the rest are ignored
|
||||||
|
|
||||||
|
* these rules are examined *in the sequence they appeared in the conf file*.
|
||||||
|
For each rule:
|
||||||
|
|
||||||
|
* if the ref does not match the [refex][], the rule is skipped
|
||||||
|
* if it's a deny rule (the permissions field is a `-`), access is
|
||||||
|
**rejected** and the matching stops
|
||||||
|
* if the permission field matches the specific [type of
|
||||||
|
write][write-types] operation, access is **allowed** and the matching
|
||||||
|
stops
|
||||||
|
|
||||||
|
* if no rule ends with a decision, ("fallthru"), access is **rejected**.
|
||||||
|
|
||||||
|
Now you need to understand how [refex][] matching happens and how the
|
||||||
|
permissions match the various [types of write operations][write-types].
|
||||||
|
|
||||||
|
Using these, you can see, in our example, that:
|
||||||
|
|
||||||
|
* everyone, even wally, can read the repo.
|
||||||
|
* dilbert can push, rewind, or delete any ref.
|
||||||
|
* alice can push, rewind, or delete any ref whose name starts with 'dev';
|
||||||
|
see [refex][] for details.
|
||||||
|
* alice can also push (but not rewind or delete) any ref whose name starts
|
||||||
|
with 'temp/'. This applies to bob also.
|
||||||
|
* if it weren't for line 3, the previous statement would apply to wally
|
||||||
|
also.
|
||||||
|
|
||||||
|
Interestingly, wally can get past the pre-git check because gitolite ignores
|
||||||
|
deny rules for pre-git, but having got past it, he can't actually do anything.
|
||||||
|
That's by design, and as I said if you don't like it you can ask gitolite to
|
||||||
|
[deny at pre-git][deny-rules].
|
||||||
|
|
||||||
|
### summary of permissions
|
||||||
|
|
||||||
|
The full set of permissions, in regex syntax: `-|R|RW+?C?D?M?`. This expands
|
||||||
|
to one of `-`, `R`, `RW`, `RW+`, `RWC`, `RW+C`, `RWD`, `RW+D`, `RWCD`, or
|
||||||
|
`RW+CD`, all but the first one optionally followed by an `M`. And by now you
|
||||||
|
know what they all mean.
|
||||||
|
|
11
doc/sugar.mkd
Normal file
11
doc/sugar.mkd
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
# syntactic sugar
|
||||||
|
|
||||||
|
Sugar scripts help you change the perceived syntax of the conf language. The
|
||||||
|
base syntax of the language is as described [here][conf], so sugar scripts
|
||||||
|
take something *else* and convert it into that.
|
||||||
|
|
||||||
|
That way, the admin sees additional features (like allowing continuation
|
||||||
|
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"
|
||||||
|
section in [dev-notes][] first then email me.
|
31
doc/testing.mkd
Normal file
31
doc/testing.mkd
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
# testing gitolite
|
||||||
|
|
||||||
|
Here's how to *run* the tests:
|
||||||
|
|
||||||
|
git clone git://github.com/sitaramc/gitolite
|
||||||
|
cd gitolite
|
||||||
|
git checkout -f g3
|
||||||
|
|
||||||
|
# if you're not ok with your ~/.ssh getting clobbered
|
||||||
|
prove
|
||||||
|
|
||||||
|
# if you're ok with your ~/.ssh getting clobbered
|
||||||
|
# prove t/*.t t/ssh*
|
||||||
|
|
||||||
|
Gitolite's test suite is mostly written using [tsh][] -- the "testing shell".
|
||||||
|
Take a look at some of the scripts and you will see what it looks like. It
|
||||||
|
has a few quirks and nuances; if you really care, email me.
|
||||||
|
|
||||||
|
[tsh]: http://github.com/sitaramc/tsh
|
||||||
|
|
||||||
|
The tests also use a somewhat convoluted system of environment variables in
|
||||||
|
order to run *entirely* as a local user, without going through ssh at all.
|
||||||
|
This lets a complete test suite run in about a fifth or less of the time it
|
||||||
|
would otherwise take.
|
||||||
|
|
||||||
|
If you think that defeats the purpose of the testing, you haven't read
|
||||||
|
[this][auth] yet.
|
||||||
|
|
||||||
|
There are 2 specific tests that deal with ssh though, which are run only on
|
||||||
|
request, as you can see above, because they clobber your `~/.ssh`. You have
|
||||||
|
been warned.
|
90
doc/triggers.mkd
Normal file
90
doc/triggers.mkd
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
# gitolite triggers
|
||||||
|
|
||||||
|
## intro and sample rc excerpt
|
||||||
|
|
||||||
|
Gitolite fires off external commands at six different times. The [rc][] file
|
||||||
|
specifies what commands to run at each trigger point, but for illustration,
|
||||||
|
here's an excerpt:
|
||||||
|
|
||||||
|
%RC = (
|
||||||
|
|
||||||
|
<...several lines later...>
|
||||||
|
|
||||||
|
# comment out or uncomment as needed
|
||||||
|
# these will run in sequence after post-update
|
||||||
|
POST_COMPILE =>
|
||||||
|
[
|
||||||
|
'post-compile/ssh-authkeys',
|
||||||
|
'post-compile/update-git-configs',
|
||||||
|
'post-compile/update-gitweb-access-list',
|
||||||
|
'post-compile/update-git-daemon-access-list',
|
||||||
|
],
|
||||||
|
|
||||||
|
# comment out or uncomment as needed
|
||||||
|
# these will run in sequence after a new wild repo is created
|
||||||
|
POST_CREATE =>
|
||||||
|
[
|
||||||
|
'post-compile/update-git-configs',
|
||||||
|
'post-compile/update-gitweb-access-list',
|
||||||
|
'post-compile/update-git-daemon-access-list',
|
||||||
|
],
|
||||||
|
|
||||||
|
(As you can see, post-create runs 3 programs that also run from post-compile.
|
||||||
|
This is perfectly fine, by the way)
|
||||||
|
|
||||||
|
## manually firing triggers
|
||||||
|
|
||||||
|
...from the server command line is easy. For example:
|
||||||
|
|
||||||
|
gitolite trigger POST_COMPILE
|
||||||
|
|
||||||
|
However if the triggered code depends on arguments (see next section) this
|
||||||
|
won't work. (The `POST_COMPILE` trigger programs all just happen to not
|
||||||
|
require any arguments, so it works).
|
||||||
|
|
||||||
|
## triggers and arguments
|
||||||
|
|
||||||
|
All triggers receive the name of the trigger as a string (example,
|
||||||
|
`"POST_COMPILE"`) as the first argument, so they can know who invoked them.
|
||||||
|
(This allows you to write the same program and fire it from more than one
|
||||||
|
trigger, as above). In addition, they may receive other arguments pertaining
|
||||||
|
to the event that happened.
|
||||||
|
|
||||||
|
* `ACCESS_CHECK`: this fires once after each access check. The first is
|
||||||
|
just before invoking git-receive-pack or git-upload-pack. The second,
|
||||||
|
which only applies to "write" operations, is from git's own 'update' hook.
|
||||||
|
|
||||||
|
Arguments: repo name, user name, [attempted access][perm], the ref being
|
||||||
|
updated, and the result of the access check.
|
||||||
|
|
||||||
|
The 'ref' is `any` for the first check, because at that point we don't
|
||||||
|
know what the actual ref is. For the second check it could be, say,
|
||||||
|
`refs/heads/master` or some such.
|
||||||
|
|
||||||
|
The result is a text field that the `access()` function returned.
|
||||||
|
Programmatically, the only thing you should rely on is that if it contains
|
||||||
|
the upper case word "DENIED" then access was denied, otherwise it was
|
||||||
|
allowed.
|
||||||
|
|
||||||
|
* `PRE_GIT`: before running the git command.
|
||||||
|
|
||||||
|
Arguments: repo name, user name, [attempted access][perm], the string
|
||||||
|
`any`, and the git command ('git-receive-pack', 'git-upload-pack', or
|
||||||
|
'git-upload-archive') being invoked.
|
||||||
|
|
||||||
|
* `POST_GIT`: after the git command returns.
|
||||||
|
|
||||||
|
Arguments: same as for `PRE_GIT`, followed by the output of the perl
|
||||||
|
function "times" (i.e., 4 CPU times: user, system, cumulative user,
|
||||||
|
cumulative system)
|
||||||
|
|
||||||
|
* `POST_COMPILE`: after an admin push has successfully "compiled" the config
|
||||||
|
file. By default, the next thing is to update the ssh authkeys file, then
|
||||||
|
all the 'git-config's, gitweb access, and daemon access.
|
||||||
|
|
||||||
|
Programs run by this trigger receive no extra arguments.
|
||||||
|
|
||||||
|
* `PRE_CREATE` and `POST_CREATE`: before and after a new "[wild][]" repo is
|
||||||
|
created by user action.
|
||||||
|
|
||||||
|
Arguments: repo name, user name.
|
96
doc/users.mkd
Normal file
96
doc/users.mkd
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
# what users (not admins) need to know about gitolite
|
||||||
|
|
||||||
|
...written for the one guy in the world no one will think of as "just a normal
|
||||||
|
user" ;-)
|
||||||
|
|
||||||
|
This document has some text, and a lot of links. Most of this info *is*
|
||||||
|
available in the rest of the documentation, but it's scattered and sparse.
|
||||||
|
Collecting all of it, or at least links to it, in one place sounds useful.
|
||||||
|
|
||||||
|
## accessing gitolite
|
||||||
|
|
||||||
|
The most common setup is based on ssh, where your admin asks you to send him
|
||||||
|
your public key, and uses that to setup your access.
|
||||||
|
|
||||||
|
Your actual access is either a git command (like `git clone
|
||||||
|
git@server:reponame`, and we won't be discussing these any more in this
|
||||||
|
document), or an ssh command (like `ssh git@server info`).
|
||||||
|
|
||||||
|
Note that you do *not* get a shell on the server -- the whole point of
|
||||||
|
gitolite is to prevent that!
|
||||||
|
|
||||||
|
## #info the info command
|
||||||
|
|
||||||
|
The only command that is *always* available to every user is the `info`
|
||||||
|
command (run `ssh git@host info -h` for help), which tells you what version of
|
||||||
|
gitolite and git are on the server, and what repositories you have access to.
|
||||||
|
The list of repos is very useful if you have doubts about the spelling of some
|
||||||
|
new repo that you know was setup.
|
||||||
|
|
||||||
|
## digression: two kinds of repos
|
||||||
|
|
||||||
|
Gitolite has two kinds of repos. Normal repos are specified by their full
|
||||||
|
names in the config file. "Wildcard" repos are specified by a regex in the
|
||||||
|
config file. Try the [`info` command][info] and see if it shows any lines
|
||||||
|
that look like regex patterns, (with a "C" permission in addition to the "R"
|
||||||
|
and the "W").
|
||||||
|
|
||||||
|
If you see any, it means you are allowed to create brand new repos whose names
|
||||||
|
fit that pattern. When you create such a repo, your "ownership" of it (as far
|
||||||
|
as gitolite is concerned) is *automatically* recorded by gitolite.
|
||||||
|
|
||||||
|
## other commands
|
||||||
|
|
||||||
|
### #perms set/get additional permissions for repos you created
|
||||||
|
|
||||||
|
The gitolite config may have several permissions lines for your repo, like so:
|
||||||
|
|
||||||
|
repo pub/CREATOR/..*
|
||||||
|
RW+ = CREATOR
|
||||||
|
RW = user1 user2
|
||||||
|
R = user3
|
||||||
|
|
||||||
|
If that's all it had, you really can't do much. Any changes to access must be
|
||||||
|
done by the administrator. (Note that "CREATOR" is a reserved word that gets
|
||||||
|
expanded to your userid in some way, so the admin can literally add just the
|
||||||
|
first two lines, and *every* authenticated user now has his own personal repo
|
||||||
|
namespace, starting with `pub/<username>/`).
|
||||||
|
|
||||||
|
To give some flexibility to users, the admin could add rules like this:
|
||||||
|
|
||||||
|
RW = WRITERS
|
||||||
|
R = READERS
|
||||||
|
|
||||||
|
(he could also add other roles but then he needs to read the documentation).
|
||||||
|
|
||||||
|
Once he does this, you can then use the `perms` command (run `ssh git@host
|
||||||
|
perms -h` for help) to set permissions for other users by specifying which
|
||||||
|
users are in the list of "READERS", and which in "WRITERS".
|
||||||
|
|
||||||
|
If you think of READERS and WRITERS as "roles", it will help. You can't
|
||||||
|
change what access a role has, but you *can* say which users have that role.
|
||||||
|
|
||||||
|
**Note**: there isn't a way for you to see the actual rule set unless you're
|
||||||
|
given read access to the special 'gitolite-admin' repo. Sorry. The idea is
|
||||||
|
that your admin will tell you what "roles" he added into rules for your repos,
|
||||||
|
and what permissions those roles have.
|
||||||
|
|
||||||
|
### #desc adding a description to repos you created
|
||||||
|
|
||||||
|
The `desc` command is extremely simple. Run `ssh git@host desc -h` for help.
|
||||||
|
|
||||||
|
## "site-local" commands
|
||||||
|
|
||||||
|
The main purpose of gitolite is to prevent you from getting a shell. But
|
||||||
|
there are commands that you often need to run on the server (i.e., cannot be
|
||||||
|
done by pushing something to a repo).
|
||||||
|
|
||||||
|
To enable this, gitolite allows the admin to setup scripts in a special
|
||||||
|
directory that users can then run. Gitolite comes with a set of working
|
||||||
|
scripts that your admin may install, or may use as a starting point for his
|
||||||
|
own, if he chooses.
|
||||||
|
|
||||||
|
Think of these commands as equivalent to those in `COMMAND_DIR` in `man
|
||||||
|
git-shell`.
|
||||||
|
|
||||||
|
You can get a list of available commands by running `ssh git@host help`.
|
254
doc/vref.mkd
Normal file
254
doc/vref.mkd
Normal file
|
@ -0,0 +1,254 @@
|
||||||
|
# virtual refs
|
||||||
|
|
||||||
|
Here's an example to start you off.
|
||||||
|
|
||||||
|
repo r1
|
||||||
|
RW+ = lead_dev dev2 dev3
|
||||||
|
- VREF/COUNT/9 = dev2 dev3
|
||||||
|
- VREF/COUNT/3/NEWFILES = dev2 dev3
|
||||||
|
|
||||||
|
Now dev2 and dev3 cannot push changes that affect more than 9 files at a time,
|
||||||
|
nor those that have more than 3 new files.
|
||||||
|
|
||||||
|
Another example is detecting duplicate pubkeys in a push to the admin repo:
|
||||||
|
|
||||||
|
repo gitolite-admin
|
||||||
|
# ... normal rules ...
|
||||||
|
- VREF/DUPKEYS = @all
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
## rule matching recap
|
||||||
|
|
||||||
|
You won't get any joy out of this if you don't understand at least
|
||||||
|
[refex][]es and how [rules][] are processed.
|
||||||
|
|
||||||
|
But VREFs have one **very important difference** from normal rules. With
|
||||||
|
VREFs, a **fallthru results in success**. You'll see why this is more
|
||||||
|
convenient as you read on.
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
## what is a virtual ref
|
||||||
|
|
||||||
|
A ref like `refs/heads/master` is the main property of a push that gitolite
|
||||||
|
uses to make its yes/no decision. I call this a "real" ref.
|
||||||
|
|
||||||
|
Any *other* property of the push that you want to use to help in the decision
|
||||||
|
is therefore a *virtual* ref. This could be a property that git knows about,
|
||||||
|
like in the example above, or comes from outside git like, say, the current
|
||||||
|
time; see examples section later for some ideas.
|
||||||
|
|
||||||
|
## fallthru is success here
|
||||||
|
|
||||||
|
Notice that you didn't need to add an `RW+ VREF/...` rule for user `lead_dev`
|
||||||
|
in our example. This section explains why.
|
||||||
|
|
||||||
|
**Virtual refs are best used as additional "deny" rules**, performing extra
|
||||||
|
checks that core gitolite cannot.
|
||||||
|
|
||||||
|
Making fallthru be a "fail" forces you to add rules for all users, instead of
|
||||||
|
just the ones who should have those extra checks. Worse, since every virtual
|
||||||
|
ref involves calling an external program, many of these calls may be wasted.
|
||||||
|
|
||||||
|
There's another advantage to doing it this way: a VREF can choose to simply
|
||||||
|
die if things look bad, and it will have the same effect, assuming you used
|
||||||
|
the VREF only in [deny][] rules.
|
||||||
|
|
||||||
|
This in turn means any existing update hook can be used as a VREF *as-is*, as
|
||||||
|
long as it (a) prints nothing on success and (b) dies on failure. See the
|
||||||
|
email-check and dupkeys examples later.
|
||||||
|
|
||||||
|
## how it works -- overview
|
||||||
|
|
||||||
|
Briefly, a refex starting with `VREF/FOO` triggers a call to a program called
|
||||||
|
`FOO` in `$GL_BINDIR/VREF`.
|
||||||
|
|
||||||
|
That program is expected to print zero or more lines to its STDOUT; each line
|
||||||
|
is taken by gitolite as a new "ref" to be matched against all the refexes for
|
||||||
|
this user in the config. Including the refex that caused the vref call, of
|
||||||
|
course.
|
||||||
|
|
||||||
|
Normally, you send back the refex itself, if the test determines that the rule
|
||||||
|
should be matched, otherwise nothing. So, in our example, we print
|
||||||
|
`VREF/COUNT/9` if the count was indeed greater than 9. Otherwise we just
|
||||||
|
exit.
|
||||||
|
|
||||||
|
## how it works -- details
|
||||||
|
|
||||||
|
* the VREF code is only called if there are any VREF rules for the user,
|
||||||
|
which means when the lead developer pushes, the VREF is not called at all.
|
||||||
|
|
||||||
|
Side note: this is enormously more efficient than adding additional
|
||||||
|
`update` hooks, which will get executed whether they are needed or not,
|
||||||
|
for every repo and every user!
|
||||||
|
|
||||||
|
* when dev2 or dev3 push, gitolite first checks the real ref
|
||||||
|
(`ref/heads/master` or whatever). After this it looks at VREF rules, and
|
||||||
|
calls an external program for every one it finds. Specifically, in a line
|
||||||
|
like
|
||||||
|
|
||||||
|
- VREF/COUNT/3/NEWFILES = user
|
||||||
|
|
||||||
|
COUNT is the vref name, so the program called is
|
||||||
|
`$GL_BINDIR/VREF/COUNT`.
|
||||||
|
|
||||||
|
The program is passed **nine arguments** in this case (see next section
|
||||||
|
for details).
|
||||||
|
|
||||||
|
* the script can print anything it wants to STDOUT; the first word in each
|
||||||
|
such line will be treated as a virtual ref to be matched against all the
|
||||||
|
rules, while the rest, if any, is a message to be added to the standard
|
||||||
|
"...DENIED..." message that gitolite prints if that refex matches.
|
||||||
|
|
||||||
|
Usually it only makes sense to either
|
||||||
|
|
||||||
|
* print nothing -- if you don't want the rule that triggered it to match
|
||||||
|
(ie., whatever condition being tested was not violated; like if the
|
||||||
|
count of changed files did not exceed 9, in our earlier example)
|
||||||
|
* print the refex itself (plus an optional message), so that it matches
|
||||||
|
the line which invoked it
|
||||||
|
|
||||||
|
### arguments passed to the vref code
|
||||||
|
|
||||||
|
* arguments **1, 2, 3**: the 'ref', 'oldsha', and 'newsha' that git passed
|
||||||
|
to the update hook (see 'man githooks')
|
||||||
|
|
||||||
|
This, combined with the fact that non-zero exits are detected, mean that
|
||||||
|
you can simply use an existing update.secondary as a new VREF as-is, no
|
||||||
|
changes needed.
|
||||||
|
|
||||||
|
* arguments **4 and 5**: the 'oldtree' and 'newtree' SHAs. These are the
|
||||||
|
same as the oldsha and newsha values, except if one of them is all-0.
|
||||||
|
(indicating a ref creation or deletion). In that case the corresponding
|
||||||
|
'tree' SHA is set (by gitolite, as a courtesy) to the special SHA
|
||||||
|
`4b825dc642cb6eb9a060e54bf8d69288fbee4904`, which is the hash of an empty
|
||||||
|
tree.
|
||||||
|
|
||||||
|
(None of these shenanigans would have been needed if `git diff $oldsha
|
||||||
|
$newsha` would not error out when passed an all-0 SHA.)
|
||||||
|
|
||||||
|
* argument **6**: the attempted access flag. Typically `W` or `+`, but
|
||||||
|
could also be `C`, `D`, or any of these 4 followed by `M`. If you have to
|
||||||
|
ask what they mean, you haven't read enough gitolite documentation to be
|
||||||
|
able to make virtual refs work.
|
||||||
|
|
||||||
|
* argument **7**: is the entire refex; in our example
|
||||||
|
`VREF/COUNT/3/NEWFILES`.
|
||||||
|
|
||||||
|
* arguments **8 onward**: are the split out (by `/`) portions of the refex,
|
||||||
|
excluding the first two components. In our example they would be `3`
|
||||||
|
followed by `NEWFILES`.
|
||||||
|
|
||||||
|
Yes, argument 7 is redundant if you have 8 and 9. It's meant to make it easy
|
||||||
|
to write vref scripts in any language. See script examples in source.
|
||||||
|
|
||||||
|
## what (else) can the vref code pass back
|
||||||
|
|
||||||
|
Actually, the vref code can pass anything back; each line in its output will
|
||||||
|
be matched against all the rules as usual (with the exception that fallthru is
|
||||||
|
not failure).
|
||||||
|
|
||||||
|
For example, you could have a ruleset like this:
|
||||||
|
|
||||||
|
repo r1
|
||||||
|
# ... normal rules ...
|
||||||
|
|
||||||
|
- VREF/TIME/WEEKEND = @interns
|
||||||
|
- VREF/TIME/WEEKNIGHT = @interns
|
||||||
|
- VREF/TIME/HOLIDAY = @interns
|
||||||
|
|
||||||
|
and you could write the TIME vref code to passback any or all
|
||||||
|
of the times that match. Then if an intern tried to access the system, each
|
||||||
|
rule would trigger a call to gl-bindir/VREF/TIME.
|
||||||
|
|
||||||
|
The script should send back any of the applicable times (even more than one,
|
||||||
|
or none at all, as the case may be). So even if it was invoked using the
|
||||||
|
first rule, it might pass back (to gitolite) a virtual ref saying
|
||||||
|
'VREF/TIME/HOLIDAY', which would promptly cause the request to be denied.
|
||||||
|
|
||||||
|
## VREFs shipped with gitolite
|
||||||
|
|
||||||
|
### number of new files
|
||||||
|
|
||||||
|
If a dev pushes more than 2 *new* files, the top commit needs to have a
|
||||||
|
signed-off by line in its commit message. For example if he has 4 new files
|
||||||
|
this text should be:
|
||||||
|
|
||||||
|
4 new files signed-off by: <top commit author's email>
|
||||||
|
|
||||||
|
The config entry for this is below (`NO_SIGNOFF` applies only to, and thus
|
||||||
|
implies, `NEWFILES`):
|
||||||
|
|
||||||
|
RW+ VREF/COUNT/2/NO_SIGNOFF = sitaram
|
||||||
|
- VREF/COUNT/2/NO_SIGNOFF = @all
|
||||||
|
|
||||||
|
Notice how the refex in both cases is *exactly* the same. If you make it
|
||||||
|
different (even change the number on my access line), things won't work.
|
||||||
|
|
||||||
|
Junior devs can't push more than 10 new files, even with a signed-off by line:
|
||||||
|
|
||||||
|
- VREF/COUNT/10/NEWFILES = @junior_devs
|
||||||
|
|
||||||
|
### advanced filetype detection
|
||||||
|
|
||||||
|
Note: this is more for illustration than use; it's rather specific to one of
|
||||||
|
the projects I manage but the idea is the important thing.
|
||||||
|
|
||||||
|
Sometimes a file has a standard extension (that cannot be 'gitignore'd), but
|
||||||
|
it is actually automatically generated. Here's one way to catch it:
|
||||||
|
|
||||||
|
- VREF/FILETYPE/AUTOGENERATED = @all
|
||||||
|
|
||||||
|
You can look at `src/VREF/FILETYPE` to see how it handles the
|
||||||
|
'AUTOGENERATED' option. You could also have a more generic option, like
|
||||||
|
perhaps BINARY, and handle that in the FILETYPE vref too.
|
||||||
|
|
||||||
|
### checking author email
|
||||||
|
|
||||||
|
Some people want to ensure that "you can only push your own commits".
|
||||||
|
|
||||||
|
If you force it on everyone, this is a very silly idea (see "Philosophical
|
||||||
|
Notes" section of `src/VREF/EMAIL-CHECK`).
|
||||||
|
|
||||||
|
But there may be value in enforcing it just for the junior developers.
|
||||||
|
|
||||||
|
The neat thing is that the existing `contrib/update.email-check` was just
|
||||||
|
copied to `src/VREF/EMAIL-CHECK` and it works, because VREFs get
|
||||||
|
the same first 3 arguments and those are all that it cares about. (Note: you
|
||||||
|
have to change one subroutine in that script if you want to use it)
|
||||||
|
|
||||||
|
### catching duplicate pubkeys
|
||||||
|
|
||||||
|
We covered this as a teaser example at the start.
|
||||||
|
|
||||||
|
## other ideas -- code welcome!
|
||||||
|
|
||||||
|
### "no non-merge first-parents"
|
||||||
|
|
||||||
|
Shruggar on #gitolite wanted this. Possible code to implement it would be
|
||||||
|
something like this (untested)
|
||||||
|
|
||||||
|
[ -z "$(git rev-list --first-parent --no-merges $2..$3)" ]
|
||||||
|
|
||||||
|
This can be implemented using `src/VREF/MERGE-CHECK` as a model.
|
||||||
|
That script does what the 'in core' feature called [merge check][mergecheck]
|
||||||
|
does, although the syntax to be used in conf/gitolite will be quite different.
|
||||||
|
|
||||||
|
### other ideas for VREFs
|
||||||
|
|
||||||
|
Here are some more ideas:
|
||||||
|
|
||||||
|
* number of commits (`git rev-list --count $old $new`)
|
||||||
|
* number of binary files in commit (currently I only know to count
|
||||||
|
occurrences of ` Bin ` in the output of `git diff --stat`
|
||||||
|
* number of *new* binary files (count ` Bin 0 ->` in `git diff --stat`
|
||||||
|
output)
|
||||||
|
* time of day/day of week (see example snippet somewhere above)
|
||||||
|
* IP address
|
||||||
|
* phase of the moon
|
||||||
|
|
||||||
|
Note that pretty much anything that involves `$oldsha..$newsha` will have to
|
||||||
|
deal with the issue that when you push a new tag or branch, the "old" part
|
||||||
|
is all 0's, and unless you consider `--all` existing branches and tags it
|
||||||
|
becomes meaningless in terms of "number of new files" etc.
|
46
doc/why.mkd
Normal file
46
doc/why.mkd
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
# Why is gitolite needed?
|
||||||
|
|
||||||
|
Gitolite is separate from git, and needs to be installed and configured. So...
|
||||||
|
why do we bother?
|
||||||
|
|
||||||
|
Gitolite is useful in any server that is going to host multiple git
|
||||||
|
repositories, each with many developers, where some sort of access control is
|
||||||
|
required.
|
||||||
|
|
||||||
|
In theory, this can be done with plain old Unix permissions: each user is a
|
||||||
|
member of one or more groups, each group "owns" one or more repositories, and
|
||||||
|
using unix permissions (especially the setgid bit -- `chmod g+s`) you can
|
||||||
|
allow/disallow users access to repos.
|
||||||
|
|
||||||
|
But there are several disadvantages here:
|
||||||
|
|
||||||
|
* every user needs a userid and password on the server. This is usually a
|
||||||
|
killer, especially in tightly controlled environments
|
||||||
|
* adding/removing access rights involves complex `usermod -G ...` mumblings
|
||||||
|
which most admins would rather not deal with
|
||||||
|
* *viewing* (aka auditing) the current set of permissions requires running
|
||||||
|
multiple commands to list directories and their permissions/ownerships,
|
||||||
|
users and their group memberships, and then correlating all these manually
|
||||||
|
* auditing historical permissions or permission changes is pretty much
|
||||||
|
impossible without extraneous tools
|
||||||
|
* errors or omissions in setting the permissions exactly can cause problems
|
||||||
|
of either kind: false accepts or false rejects
|
||||||
|
* without going into ACLs it is not possible to give some people read-only
|
||||||
|
access while some others have read-write access to a repo (unless you make
|
||||||
|
it world-readable). Group access just doesn't have enough granularity
|
||||||
|
* it is absolutely impossible to restrict pushing by branch name or tag
|
||||||
|
name.
|
||||||
|
|
||||||
|
Gitolite does away with all this:
|
||||||
|
|
||||||
|
* it uses ssh magic to remove the need to give actual unix userids to
|
||||||
|
developers
|
||||||
|
* it uses a simple but powerful config file format to specify access rights
|
||||||
|
* access control changes are affected by modifying this file, adding or
|
||||||
|
removing user's public keys, and "compiling" the configuration
|
||||||
|
* this also makes auditing trivial -- all the data is in one place, and
|
||||||
|
changes to the configuration are also logged, so you can audit them.
|
||||||
|
* finally, the config file allows distinguishing between read-only and
|
||||||
|
read-write access, not only at the repository level, but at the branch
|
||||||
|
level within repositories.
|
||||||
|
|
31
doc/write-types.mkd
Normal file
31
doc/write-types.mkd
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
## #write-types different types of write operations
|
||||||
|
|
||||||
|
Git supplies enough information to the update hook to be able to distinguish
|
||||||
|
several types of writes.
|
||||||
|
|
||||||
|
The most common are:
|
||||||
|
|
||||||
|
* `RW` -- create a ref or fast-forward push a ref. No rewinds or deletes.
|
||||||
|
* `RW+` -- create, fast-forward push, rewind push, or delete a ref.
|
||||||
|
|
||||||
|
Sometimes you want to allow people to push, but not *create* a ref. Or
|
||||||
|
rewind, but not *delete* a ref. The `C` and `D` qualifiers help here.
|
||||||
|
|
||||||
|
* when a rule specifies `RWC` or `RW+C`, then *rules that do NOT have the C
|
||||||
|
qualifier will no longer permit **creating** a ref*
|
||||||
|
|
||||||
|
<font color="gray">Please do not confuse this with the standalone `C`
|
||||||
|
permission that allows someone to [create][] a **repo**</font>
|
||||||
|
|
||||||
|
* when a rule specifies `RWD` or `RW+D`, then *rules that do NOT have the C
|
||||||
|
qualifier will no longer permit **deleting** a ref*
|
||||||
|
|
||||||
|
Note: These two can be combined, so you can have `RWCD` and `RW+CD` as well.
|
||||||
|
|
||||||
|
One very rare need is to reject merge commits (a commit series that is not a
|
||||||
|
straight line of commits). The `M` qualifier helps here:
|
||||||
|
|
||||||
|
* When a rule has `M` appended to the permissions, *rules that do NOT have
|
||||||
|
it will reject a commit sequence that contains a merge commit* (i.e., they
|
||||||
|
only accept a straight line series of commits).
|
||||||
|
|
31
dot.pl
Normal file
31
dot.pl
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
my @a = `grep -r use.Gitolite . | grep -i '^./gitolite'`;
|
||||||
|
|
||||||
|
# chomp(@a);
|
||||||
|
open( my $fh, "|-", "tee module-tree.gv | dot -Tpng | tee module-tree.png | display" );
|
||||||
|
|
||||||
|
@a = map {
|
||||||
|
print $fh "#$_";
|
||||||
|
s/^\.\/gitolite\///i;
|
||||||
|
s/-/_/g;
|
||||||
|
s/\.\///;
|
||||||
|
s/\//_/g;
|
||||||
|
s/\.pm:/ -> /;
|
||||||
|
s/use Gitolite:://;
|
||||||
|
s/::/_/g;
|
||||||
|
s/:/ -> /;
|
||||||
|
s/;//;
|
||||||
|
s/^(\S+) -> \1$//;
|
||||||
|
s/.* -> Rc//;
|
||||||
|
s/.* -> Common//;
|
||||||
|
$_;
|
||||||
|
} @a;
|
||||||
|
|
||||||
|
# open(my $fh, "|-", "cat > /tmp/junkg3");
|
||||||
|
print $fh "digraph G {\n";
|
||||||
|
print $fh $_ for @a;
|
||||||
|
print $fh "}\n";
|
||||||
|
close $fh;
|
Loading…
Reference in a new issue