Skip to content
Browse files

Q: all doc stuff

  • Loading branch information...
1 parent efb29ed commit 4f7d3d86515099774d6f1df869e40e89aa635119 @sitaramc committed Mar 16, 2012
View
34 doc/add.mkd
@@ -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
View
26 doc/commands.mkd
@@ -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.
View
31 doc/conf.mkd
@@ -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.
View
23 doc/cust.mkd
@@ -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).
View
116 doc/dev-notes.mkd
@@ -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.
+
View
35 doc/dev-status.mkd
@@ -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
View
89 doc/extras/auth.mkd
@@ -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.
+
View
145 doc/extras/gitolite-and-ssh.mkd
@@ -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.
View
64 doc/extras/nagp.mkd
@@ -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...
View
34 doc/extras/regex.mkd
@@ -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.)
+
View
427 doc/extras/ssh-troubleshooting.mkd
@@ -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.
View
11 doc/extras/ssh.mkd
@@ -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.
View
6 doc/extras/unique.mkd
@@ -0,0 +1,6 @@
+# unique setups
+
+This page is for unique setups that I support. At present there is only one
+-- Fedora.
+
+
View
10 doc/g2alt.mkd
@@ -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.
View
2 doc/g2dropped.mkd
@@ -0,0 +1,2 @@
+## #g2dropped g2 features dropped
+
View
35 doc/g2incompat.mkd
@@ -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.
View
122 doc/g2migr.mkd
@@ -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`
View
97 doc/g3why.mkd
@@ -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.
View
32 doc/group.mkd
@@ -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".
View
9 doc/hooks.mkd
@@ -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' :-)
View
67 doc/index.mkd
@@ -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/).
View
58 doc/install.mkd
@@ -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...
View
43 doc/list
@@ -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
View
32 doc/minreq.mkd
@@ -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.
View
80 doc/misc.mkd
@@ -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.
View
88 doc/mkdoc
@@ -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>
View
45 doc/pw.mkd
@@ -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!
View
26 doc/qi.mkd
@@ -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].
View
20 doc/rc.mkd
@@ -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].
View
30 doc/refex.mkd
@@ -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
View
23 doc/repo.mkd
@@ -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
View
82 doc/rules.mkd
@@ -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.
+
View
11 doc/sugar.mkd
@@ -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.
View
31 doc/testing.mkd
@@ -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.
View
90 doc/triggers.mkd
@@ -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.
View
96 doc/users.mkd
@@ -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`.
View
254 doc/vref.mkd
@@ -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.)