Compare commits

...

42 Commits
v3.1 ... master

Author SHA1 Message Date
Denis Knauf a6f6886e84 README.txt -> README.md + clean up 2013-01-02 14:55:04 +01:00
Sitaram Chamarty 089f0f9d9e on removing a repo...
Not following through on instructions to remove a repo, per [1], is not
sufficient.  Even if you did just the first step, the repo should  no
longer be accessible.  See [2] for discussion.

As a bonus, we get rid of one pesky warning that always confused people.
(In hindsight -- this confusion itself should have been a warning that
something is wrong and needed fixing!)

[1]: http://sitaramc.github.com/gitolite/repos.html
[2]: http://groups.google.com/group/gitolite/browse_thread/thread/a3d4c3e917056abb
2012-12-31 06:23:28 +05:30
Sitaram Chamarty 5aef1adc7b list-dangling-repos: are we there yet?
<sigh>First I forgot @groups that may contain repos and patterns, then I
forgot patterns where the CREATOR token is used (this is the fix here).
2012-12-31 05:48:18 +05:30
Sitaram Chamarty 1fefb1c0d9 v3.3 2012-12-29 13:58:12 +05:30
Sitaram Chamarty ea3d04ea0a perms batch mode confuses; print something to help
What happens is that running

    ssh git@host perms reponame

appears to hang, since it is waiting for STDIN.  I added a message to
help, since we don't want users losing files accidentally!

(The other alternative is to add a specific option for batch mode, but
this is backward incompatible for people who have scripts that may be
doing this).

thanks to Caleb Cushing for catching this

----

The "make sure Ctrl-C gets caught" thing needs some explanation.

Without it, a user could inadvertently lose his gl-perms file if he ran
the command in batch mode.  You'd think that the Ctrl-C would hit the

    for (<>) {

line and bail, but it manages to reach the

    _print( $pf, @a );

line somehow.  Even trapping SIG INT does not help.

I suspect it is to do with how signals are propagated by ssh across a
"no-pty" session, but am not sure.
2012-12-29 13:40:13 +05:30
Sitaram Chamarty 84424e48b9 bug fix: perms propagation to slaves...
Sometime after v3.2, I fixed what looked like an information disclosure
issue, where a user could determine if an arbitrary repo existed or not,
even if he had no rights to see the repo.  This was:

    96cc2ea "new features relating to creating wild repos:"

Unfortunately, this appears to have broken gl-perms propagation to
slaves, because now running "perm -c" on an existing repo dies!

If you run

    git diff 96cc2ea^ <this commit> -- src/commands/perms

you'll see how simple the fix *should* have been :-(
2012-12-29 13:40:13 +05:30
Sitaram Chamarty b303694882 minor bugly...
please remember we make up words here, like refex was a word we created
to mean "a regex that matches a ref".

A "bugly", then, is a bug that's merely ugly (and not a real problem!)
2012-12-29 13:40:13 +05:30
Sitaram Chamarty b9bbb78278 D: allow rm and unlock to be disabled 2012-12-19 07:19:50 +05:30
Sitaram Chamarty 3513f4a153 fix bug in list-dangling-repos
Still, I would advise caution if you use this as a basis for deleting
repos from the file system.  A bug in this program could cause you to
lose important data!
2012-12-19 06:31:11 +05:30
Sitaram Chamarty 4f4658274d CREATOR need only be a "word" in wild repo patterns
this was a v2 compat breakage, caught by Dominik Schäfer
(schaedpq at gmail)
2012-12-19 06:27:24 +05:30
Sitaram Chamarty 2048484578 add more detail to error message
this error normally happens due to some permission issue on the log
file, but we weren't printing the actual cause, so it was confusing
2012-12-14 07:58:14 +05:30
Sitaram Chamarty 8e3ee2f9c1 (minor) macro buglets
- allow parameter-less macros
  - allow macro body to start on next line
2012-12-14 07:58:14 +05:30
Sitaram Chamarty 3103d68a75 new trigger: update-gitweb-daemon-from-options
another way to update gitweb and daemon access lists
2012-12-14 07:58:14 +05:30
Sven Strickroth f89408adb1 Set Content-Type to text/plain for gitolite commands over http
Explicitly set "Content-Type: text/plain" for gitolite commands when
issued over http, so that it is possible to see the output with normal
browsers.

(At least) Apache httpd might set the Content-Type to something
different and triggers a download instead of showing the text directly.

Signed-off-by: Sven Strickroth <email@cs-ware.de>
2012-12-09 08:09:02 +05:30
Sitaram Chamarty fc7ddfc818 (minor) lint had syntax errors
thanks to xcat on #gitolite for catching it
(shows you how often it gets used I guess!)
2012-12-07 17:30:56 +05:30
Sitaram Chamarty f1c69a3ec0 bugfix: don't delete description file when running perms
thanks to drue on #gitolite for catching it
2012-12-05 06:00:00 +05:30
Sitaram Chamarty 2741fadc9d a few minor changes
* minor typos
  * perltidy on Tsh
  * a minor optimisation to "do" in gl-conf
  * remove inapplicable caveat in fork command
2012-12-04 05:43:48 +05:30
Sitaram Chamarty b6d6260dbb prevent empty %groups being created in compiled conf
this would happen if @all was used but no actual groups were defined,
and would in turn cause a parse error on the compiled conf because it
now ends with a 'false'.

thanks to Jelle Raaijmakers
2012-11-28 06:22:55 +05:30
Sitaram Chamarty 72e36f32aa oops; hashes were getting printed twice in certain cases...
harmless but wasteful
2012-11-28 05:49:48 +05:30
Stephen Palmer d2214b06b5 Fixed bug in lock script
the unlock command was not checking the correct hash key to match
the user name
2012-11-27 08:09:46 +05:30
Sitaram Chamarty 96cc2eaf41 new features relating to creating wild repos:
- new 'create' command for explicit creation
  - new 'AutoCreate' trigger to prevent auto-creation on read operations
    or both read and write operations
  - a few related fixups to the perms command
2012-11-22 20:50:20 +05:30
Sebastian Koslowski 96be9503ef sudo command: CLI fix: 2 non-empty args required 2012-11-22 20:50:20 +05:30
Sitaram Chamarty 7cec71b0ef minor fixups to some non-core programs
(following a bit of a doc shakeup)
2012-11-22 15:59:48 +05:30
Sitaram Chamarty cd838411fa 'gitolite mirror' needs to set exit code on push failure 2012-11-21 21:16:01 +05:30
Sitaram Chamarty 2018267a45 (minor) fixes to lint program, mainly usage message 2012-11-21 19:55:12 +05:30
Sitaram Chamarty a26532d635 allow simple macros in conf file 2012-11-19 07:48:41 +05:30
Sitaram Chamarty 5f9789ed8e v3.2 2012-11-14 15:45:45 +05:30
Sitaram Chamarty d3d93961a0 Uggh; horrible inner loop screwing up all performance :-(
This might actually make the redis version unnecessary for most people!
And if it does, well shame on me for not instrumenting things at a more
granular level before going all "oh we need a cache!"

[In my defense, I blame redis for being such a sweet little tool that I
felt compelled to use it somehow!]

----

t/sequence failed because the test itself was in error; fixed.
2012-11-14 15:43:57 +05:30
Sitaram Chamarty 1f96180df0 allow multi-line pubkeys; see code for doc 2012-11-13 08:45:45 +05:30
gitolite tester 57760d7e1b refex-expr: die when admin forgets to add the required line to the rc 2012-11-13 08:09:14 +05:30
gitolite tester 16f2d9b879 gl-conf must be created even if the repo para has only config lines
(i.e., no access rules but only config lines)
2012-11-13 07:00:22 +05:30
Sitaram Chamarty c03d107bac help run some trigger programs in the background 2012-11-10 14:21:52 +05:30
Sitaram Chamarty d491b5384f (minor) add quick and dirty timer code to Common.pm 2012-11-09 18:02:16 +05:30
Sitaram Chamarty 8a9564f171 some minor rearrangements of code...
why?  now that would be telling!
2012-11-08 19:12:20 +05:30
Sitaram Chamarty a509b208e3 move %GL_REPO and %GL_CREATOR substitution into core
see usage example at the end of src/triggers/upstream
2012-11-07 05:36:28 +05:30
Sitaram Chamarty be61cd2d66 make sure gl-perms exists, even if it is empty...
I expect this to help if we optimise the rule generation by caching.
2012-11-06 09:15:55 +05:30
Sitaram Chamarty 70ad045e08 (minor fixups to some non-code parts) 2012-10-31 06:24:44 +05:30
Andrew Page 2aa129bc70 fix for keysubdirs-as-groups sugar script to support "old style multi-keys" for users 2012-10-29 17:15:52 -06:00
Sitaram Chamarty a802071a5e (test suite) stop using 'ls' to test for presence/absence of files/directories
another of those "duh!  what was I thinking" moments, this specific one
being "why test that files/directories are created with the right user
and group IDs?  Shouldn't that be out of your control, as well as
totally unnecessary on a sane system?"
2012-10-27 13:20:55 +05:30
Sitaram Chamarty 4eb8cd4ad1 (minor) bash -> sh changes in some non-core code
/bin/bash is muscle memory for me, although it appears that not too much
of the actual code is bash-specific, so it's reasonably easy to fix.
2012-10-27 07:07:30 +05:30
Sitaram Chamarty 3eefc06551 (minor) clarify that D only works on wild repos 2012-10-10 13:43:17 +05:30
Eugene E. Kashpureff Jr 896ada58c0 Fix spurious error in triggers/upstream
The initial fetch of a new repo which has 'upstream' read-only mirroring
configured will cause a spurious error concerning FETCH_HEAD not yet
existing. This silences the error.
2012-10-10 07:59:52 +00:00
43 changed files with 820 additions and 456 deletions

View File

@ -1,3 +1,33 @@
2012-12-29 v3.3 bug fix: gl-perms propagation to slaves broke sometime
after v3.2 (so if you're only picking up tagged releases
you're OK)
the "D" command now allows rm/unlock to be totally
disabled
new trigger: update-gitweb-daemon-from-options; another
way to update gitweb and daemon access lists
new 'create' command for explicit wild repo creation, and
new AutoCreate trigger to control auto-creation
allow simple macros in conf file
2012-11-14 v3.2 major efficiency boost for large setups
optional support for multi-line pubkeys; see
src/triggers/post-compile/ssh-authkeys-split
bug fix for not creating gl-conf when repo para has only
config lines and no access rules
new 'bg' trigger command to put long jobs started from a
trigger into background
%GL_REPO and %GL_CREATOR now work for 'option's also
test suite now much more BSD friendly
2012-10-05 v3.1 (security) fix path traversal on wild repos
new %GL_CREATOR variable for git-config lines

359
README.md Normal file
View File

@ -0,0 +1,359 @@
Github-users: click the 'wiki' link before sending me anything via github.
Existing users: this is gitolite v3.x. If you are upgrading from v2.x this
file will not suffice; you *must* check the online docs (see below for URL).
------------------------------------------------------------------------
This file contains BASIC DOCUMENTATION ONLY.
* It is suitable for a fresh, ssh-based, installation of gitolite and basic
usage of its most important features.
* It is NOT meant to be exhaustive or detailed.
The COMPLETE DOCUMENTATION is at:
http://sitaramc.github.com/gitolite/master-toc.html
Please go there for what/why/how, concepts, background, troubleshooting, more
details on what is covered here, or advanced features not covered here.
------------------------------------------------------------------------
BASIC DOCUMENTATION FOR GITOLITE
================================
This file contains the following sections:
* INSTALLATION AND SETUP
* ADDING USERS AND REPOS
* HELP FOR YOUR USERS
* BASIC SYNTAX
* ACCESS RULES
* GROUPS
* COMMANDS
* THE 'rc' FILE
* GIT-CONFIG
* GIT-DAEMON
* GITWEB
* CONTACT AND SUPPORT
* LICENSE
------------------------------------------------------------------------
INSTALLATION AND SETUP
----------------------
Server requirements:
* any unix system
* sh
* git 1.6.6+
* perl 5.8.8+
* openssh 5.0+
* a dedicated userid to host the repos (in this document, we assume it
is 'git'), with shell access ONLY by 'su - git' from some other userid
on the same server.
Steps to install:
* login as 'git' as described above
* make sure ~/.ssh/authorized_keys is empty or non-existent
* make sure your ssh public key from your workstation is available at $HOME/YourName.pub
* run the following commands:
git clone git://github.com/sitaramc/gitolite
mkdir -p $HOME/bin
gitolite/install -to $HOME/bin
gitolite setup -pk YourName.pub
If the last command doesn't run perhaps 'bin' in not in your 'PATH'.
You can either add it, or just run:
$HOME/bin/gitolite setup -pk YourName.pub
ADDING USERS AND REPOS
----------------------
Do NOT add new repos or users manually on the server. Gitolite users,
repos, and access rules are maintained by making changes to a special repo
called 'gitolite-admin' and pushing those changes to the server.
----
To administer your gitolite installation, start by doing this on your
workstation (if you have not already done so):
git clone git@host:gitolite-admin
**NOTE**: if you are asked for a password, something has gone wrong.
Now if you 'cd gitolite-admin', you will see two subdirectories in it:
'conf' and 'keydir'.
To add new users alice, bob, and carol, obtain their public keys and add
them to 'keydir' as alice.pub, bob.pub, and carol.pub respectively.
To add a new repo 'foo' and give different levels of access to these
users, edit the file 'conf/gitolite.conf' and add lines like this:
repo foo
RW+ = alice
RW = bob
R = carol
See the 'ACCESS RULES' section later for more details.
Once you have made these changes, do something like this:
git add conf
git add keydir
git commit -m 'added foo, gave access to alice, bob, carol'
git push
When the push completes, gitolite will add the new users to
~/.ssh/authorized_keys on the server, as well as create a new, empty, repo
called 'foo'.
HELP FOR YOUR USERS
-------------------
Once a user has sent you their public key and you have added them as
specified above and given them access, you have to tell them what URL to
access their repos at. This is usually 'git clone git@host:reponame'; see
man git-clone for other forms.
**NOTE**: again, if they are asked for a password, something is wrong.
If they need to know what repos they have access to, they just have to run
'ssh git@host info'; see 'COMMANDS' section later for more on this.
BASIC SYNTAX
------------
The basic syntax of the conf file is very simple.
* Everything is space separated; there are no commas, semicolons, etc.,
in the syntax.
* Comments are in the usual perl/shell style.
* User and repo names are as simple as possible; they must start with an
alphanumeric, but after that they can also contain '.', '_', or '-'.
Usernames can optionally be followed by an '@' and a domainname
containing at least one '.'; this allows you to use an email address
as someone's username.
Reponames can contain '/' characters; this allows you to put your
repos in a tree-structure for convenience.
* There are no continuation lines.
ACCESS RULES
------------
This section is mostly 'by example'.
Gitolite's access rules are very powerful. The simplest use was already
shown above. Here is a slightly more detailed example:
repo foo
RW+ = alice
- master = bob
- refs/tags/v[0-9] = bob
RW = bob
RW refs/tags/v[0-9] = carol
R = dave
For clones and fetches, as long as the user is listed with an R, RW
or RW+ in at least one rule, he is allowed to read the repo.
For pushes, rules are processed in sequence until a rule is found
where the user, the permission (see note 1), and the refex (note 2)
*all* match. At that point, if the permission on the matched rule
was '-', the push is denied, otherwise it is allowed. If no rule
matches, the push is denied.
Note 1: permission matching:
* a permission of RW matches only a fast-forward push or create
* a permission of RW+ matches any type of push
* a permission of '-' matches any type of push
Note 2: refex matching:
(refex = optional regex to match the ref being pushed)
* an empty refex is treated as 'refs/.*'
* a refex that does not start with 'refs/' is prefixed with 'refs/heads/'
* finally, a '^' is prefixed
* the ref being pushed is matched against this resulting refex
With all that background, here's what the example rules say:
* alice can do anything to any branch or tag -- create, push, delete, rewind/overwrite etc.
* bob can create or fast-forward push any branch whose name does
not start with 'master' and create any tag whose name does not
start with 'v'+digit.
* carol can create tags whose names start with 'v'+digit.
* dave can clone/fetch.
GROUPS
------
Gitolite allows you to group users or repos for convenience. Here's an
example that creates two groups of users:
@staff = alice bob carol
@interns = ashok
repo secret
RW = @staff
repo foss
RW+ = @staff
RW = @interns
Group lists accumulate. The following two lines have the same effect as
the earlier definition of @staff above:
@staff = alice bob
@staff = carol
You can also use group names in other group names:
@all-devs = @staff @interns
Finally, @all is a special group name that is often convenient to use if
you really mean 'all repos' or 'all users'.
COMMANDS
--------
Users can run certain commands remotely, using ssh. For example:
ssh git@host help
prints a list of available commands.
The most commonly used command is 'info'. All commands respond to a
single argument of '-h' with suitable information.
If you have shell on the server, you have a lot more commands available to
you; try running 'gitolite help'.
THE 'rc' FILE
--------------
Some of the instructions below may require you to edit the rc file
(~/.gitolite.rc on the server).
The rc file is perl code, but you do NOT need to know perl to edit it.
Just mind the commas, use single quotes unless you know what you're doing,
and make sure the brackets and braces stay matched up.
GIT-CONFIG
----------
Gitolite lets you set git-config values for individual repos without
having to log on to the server and run 'git config' commands:
repo foo
config hooks.mailinglist = foo-commits@example.tld
config hooks.emailprefix = '[foo] '
config foo.bar = ''
config foo.baz =
**WARNING**
The last syntax shown above is the *only* way to *delete* a config
variable once you have added it. Merely removing it from the conf
file will *not* delete it from the repo.git/config file.
**SECURITY NOTE**
Some git-config keys allow arbitrary code to be run on the server.
If all of your gitolite admins already have shell access to the server
account hosting it, you can edit the rc file (~/.gitolite.rc) on the
server, and change the GIT_CONFIG_KEYS line to look like this:
GIT_CONFIG_KEYS => '.*',
Otherwise, give it a space-separated list of regular expressions that
define what git-config keys are allowed. For example, this one allows
only variables whose names start with 'gitweb' or with 'gc' to be
defined:
GIT_CONFIG_KEYS => 'gitweb\..* gc\..*',
GIT-DAEMON
----------
Gitolite creates the 'git-daemon-export-ok' file for any repo that is
readable by a special user called 'daemon', like so:
repo foo
R = daemon
GITWEB
------
Any repo that is readable by a special user called 'gitweb' will be added
to the projects.list file.
repo foo
R = gitweb
Or you can set one or more of the following config variables instead:
repo foo
config gitweb.owner = some person's name
config gitweb.description = some description
config gitweb.category = some category
**NOTE**
You will probably need to change the UMASK in the rc file from the
default (0077) to 0027 and add whatever user your gitweb is running as
to the 'git' group. After that, you need to run a one-time 'chmod -R'
on the already created files and directories.
------------------------------------------------------------------------
CONTACT AND SUPPORT
-------------------
Mailing list for support and general discussion:
gitolite@googlegroups.com
subscribe address: gitolite+subscribe@googlegroups.com
Mailing list for announcements and notices:
subscribe address: gitolite-announce+subscribe@googlegroups.com
IRC: #git and #gitolite on freenode. Note that I live in India (UTC+0530
time zone).
Author: sitaramc@gmail.com, but please DO NOT use this for general support
questions. Subscribe to the list and ask there instead.
LICENSE
-------
The gitolite *code* is released under GPL v2. See COPYING for details.
This documentation, which is part of the source code repository, is
provided under a Creative Commons Attribution-ShareAlike 3.0 Unported
License -- see http://creativecommons.org/licenses/by-sa/3.0/

View File

@ -1,377 +0,0 @@
Github-users: click the 'wiki' link before sending me anything via github.
Existing users: this is gitolite v3.x. If you are upgrading from v2.x this
file will not suffice; you *must* check the online docs (see below for URL).
------------------------------------------------------------------------
This file contains BASIC DOCUMENTATION ONLY.
* It is suitable for a fresh, ssh-based, installation of gitolite and basic
usage of its most important features.
* It is NOT meant to be exhaustive or detailed.
The COMPLETE DOCUMENTATION is at:
http://sitaramc.github.com/gitolite/master-toc.html
Please go there for what/why/how, concepts, background, troubleshooting, more
details on what is covered here, or advanced features not covered here.
------------------------------------------------------------------------
BASIC DOCUMENTATION FOR GITOLITE
================================
This file contains the following sections:
INSTALLATION AND SETUP
ADDING USERS AND REPOS
HELP FOR YOUR USERS
BASIC SYNTAX
ACCESS RULES
GROUPS
COMMANDS
THE 'rc' FILE
GIT-CONFIG
GIT-DAEMON
GITWEB
CONTACT
LICENSE
------------------------------------------------------------------------
INSTALLATION AND SETUP
----------------------
Server requirements:
* any unix system
* sh
* git 1.6.6+
* perl 5.8.8+
* openssh 5.0+
* a dedicated userid to host the repos (in this document, we assume it
is 'git'), with shell access ONLY by 'su - git' from some other userid
on the same server.
Steps to install:
* login as 'git' as described above
* make sure ~/.ssh/authorized_keys is empty or non-existent
* make sure your ssh public key from your workstation is available at
$HOME/YourName.pub
* run the following commands:
git clone git://github.com/sitaramc/gitolite
mkdir -p $HOME/bin
gitolite/install -to $HOME/bin
gitolite setup -pk YourName.pub
If the last command doesn't run perhaps 'bin' in not in your 'PATH'.
You can either add it, or just run:
$HOME/bin/gitolite setup -pk YourName.pub
ADDING USERS AND REPOS
----------------------
Do NOT add new repos or users manually on the server. Gitolite users,
repos, and access rules are maintained by making changes to a special repo
called 'gitolite-admin' and pushing those changes to the server.
----
To administer your gitolite installation, start by doing this on your
workstation (if you have not already done so):
git clone git@host:gitolite-admin
**NOTE**: if you are asked for a password, something has gone wrong.
Now if you 'cd gitolite-admin', you will see two subdirectories in it:
'conf' and 'keydir'.
To add new users alice, bob, and carol, obtain their public keys and add
them to 'keydir' as alice.pub, bob.pub, and carol.pub respectively.
To add a new repo 'foo' and give different levels of access to these
users, edit the file 'conf/gitolite.conf' and add lines like this:
repo foo
RW+ = alice
RW = bob
R = carol
See the 'ACCESS RULES' section later for more details.
Once you have made these changes, do something like this:
git add conf
git add keydir
git commit -m 'added foo, gave access to alice, bob, carol'
git push
When the push completes, gitolite will add the new users to
~/.ssh/authorized_keys on the server, as well as create a new, empty, repo
called 'foo'.
HELP FOR YOUR USERS
-------------------
Once a user has sent you their public key and you have added them as
specified above and given them access, you have to tell them what URL to
access their repos at. This is usually 'git clone git@host:reponame'; see
man git-clone for other forms.
**NOTE**: again, if they are asked for a password, something is wrong.
If they need to know what repos they have access to, they just have to run
'ssh git@host info'; see 'COMMANDS' section later for more on this.
BASIC SYNTAX
------------
The basic syntax of the conf file is very simple.
* Everything is space separated; there are no commas, semicolons, etc.,
in the syntax.
* Comments are in the usual perl/shell style.
* User and repo names are as simple as possible; they must start with an
alphanumeric, but after that they can also contain '.', '_', or '-'.
Usernames can optionally be followed by an '@' and a domainname
containing at least one '.'; this allows you to use an email address
as someone's username.
Reponames can contain '/' characters; this allows you to put your
repos in a tree-structure for convenience.
* There are no continuation lines.
ACCESS RULES
------------
This section is mostly 'by example'.
Gitolite's access rules are very powerful. The simplest use was already
shown above. Here is a slightly more detailed example:
repo foo
RW+ = alice
- master = bob
- refs/tags/v[0-9] = bob
RW = bob
RW refs/tags/v[0-9] = carol
R = dave
For clones and fetches, as long as the user is listed with an R, RW
or RW+ in at least one rule, he is allowed to read the repo.
For pushes, rules are processed in sequence until a rule is found
where the user, the permission (see note 1), and the refex (note 2)
*all* match. At that point, if the permission on the matched rule
was '-', the push is denied, otherwise it is allowed. If no rule
matches, the push is denied.
Note 1: permission matching:
* a permission of RW matches only a fast-forward push or create
* a permission of RW+ matches any type of push
* a permission of '-' matches any type of push
Note 2: refex matching:
(refex = optional regex to match the ref being pushed)
* an empty refex is treated as 'refs/.*'
* a refex that does not start with 'refs/' is prefixed with 'refs/heads/'
* finally, a '^' is prefixed
* the ref being pushed is matched against this resulting refex
With all that background, here's what the example rules say:
* alice can do anything to any branch or tag -- create, push,
delete, rewind/overwrite etc.
* bob can create or fast-forward push any branch whose name does
not start with 'master' and create any tag whose name does not
start with 'v'+digit.
* carol can create tags whose names start with 'v'+digit.
* dave can clone/fetch.
GROUPS
------
Gitolite allows you to groups users or repos for convenience. Here's an
example that creates two groups of users:
@staff = alice bob carol
@interns = ashok
repo secret
RW = @staff
repo foss
RW+ = @staff
RW = @interns
Group lists accumulate. The following two lines have the same effect as
the earlier definition of @staff above:
@staff = alice bob
@staff = carol
You can also use group names in other group names:
@all-devs = @staff @interns
Finally, @all is a special group name that is often convenient to use if
you really mean 'all repos' or 'all users'.
COMMANDS
--------
Users can run certain commands remotely, using ssh. For example:
ssh git@host help
prints a list of available commands.
The most commonly used command is 'info'. All commands respond to a
single argument of '-h' with suitable information.
If you have shell on the server, you have a lot more commands available to
you; try running 'gitolite help'.
THE 'rc' FILE
--------------
Some of the instructions below may require you to edit the rc file
(~/.gitolite.rc on the server).
The rc file is perl code, but you do NOT need to know perl to edit it.
Just mind the commas, use single quotes unless you know what you're doing,
and make sure the brackets and braces stay matched up.
GIT-CONFIG
----------
Gitolite lets you set git-config values for individual repos without
having to log on to the server and run 'git config' commands:
repo foo
config hooks.mailinglist = foo-commits@example.tld
config hooks.emailprefix = '[foo] '
config foo.bar = ''
config foo.baz =
**WARNING**
The last syntax shown above is the *only* way to *delete* a config
variable once you have added it. Merely removing it from the conf
file will *not* delete it from the repo.git/config file.
**SECURITY NOTE**
Some git-config keys allow arbitrary code to be run on the server.
If all of your gitolite admins already have shell access to the server
account hosting it, you can edit the rc file (~/.gitolite.rc) on the
server, and change the GIT_CONFIG_KEYS line to look like this:
GIT_CONFIG_KEYS => '.*',
Otherwise, give it a space-separated list of regular expressions that
define what git-config keys are allowed. For example, this one allows
only variables whose names start with 'gitweb' or with 'gc' to be
defined:
GIT_CONFIG_KEYS => 'gitweb\..* gc\..*',
GIT-DAEMON
----------
Gitolite creates the 'git-daemon-export-ok' file for any repo that is
readable by a special user called 'daemon', like so:
repo foo
R = daemon
GITWEB
------
Any repo that is readable by a special user called 'gitweb' will be added
to the projects.list file.
repo foo
R = gitweb
Or you can set one or more of the following config variables instead:
repo foo
config gitweb.owner = some person's name
config gitweb.description = some description
config gitweb.category = some category
**NOTE**
You will probably need to change the UMASK in the rc file from the
default (0077) to 0027 and add whatever user your gitweb is running as
to the 'git' group. After that, you need to run a one-time 'chmod -R'
on the already created files and directories.
------------------------------------------------------------------------
CONTACT
-------
NOTE: Unless you have very good reasons, please use the mailing list below
instead of mailing me personally. If you have to mail me, use the gmail
address instead of my work address.
Author: sitaramc@gmail.com, sitaram@atc.tcs.com
Mailing list for questions and general discussion:
gitolite@googlegroups.com
subscribe address: gitolite+subscribe@googlegroups.com
Mailing list for announcements and notices:
gitolite-announce@googlegroups.com
subscribe address: gitolite-announce+subscribe@googlegroups.com
IRC: #git and #gitolite on freenode. Note that I live in India (UTC+0530
time zone).
LICENSE
-------
The gitolite *code* is released under GPL v2. See COPYING for details.
This documentation, which is part of the source code repository, is
provided under a Creative Commons Attribution-ShareAlike 3.0 Unported
License -- see http://creativecommons.org/licenses/by-sa/3.0/

View File

@ -1,5 +1,4 @@
#!/bin/bash
# TODO: convert to perl!
#!/bin/sh
# gitolite VREF to count number of changed/new files in a push
@ -34,7 +33,7 @@ nf=
# $oldsha when you update an old feature branch from master and then push it
count=`git log --name-only $nf --format=%n $newtree --not --all | grep . | sort -u | perl -ne '}{print "$."'`
[[ $count -gt $max ]] && {
[ $count -gt $max ] && {
# count has been exceeded. If $9 was NO_SIGNOFF there's still a chance
# for redemption -- if the top commit has a proper signed-off by line
[ "$9" = "NO_SIGNOFF" ] && {

View File

@ -1,5 +1,4 @@
#!/bin/bash
# TODO: convert to perl!
#!/bin/sh
# gitolite VREF to find autogenerated files

View File

@ -1,4 +1,4 @@
#!/bin/bash
#!/bin/sh
# gitolite VREF to count votes before allowing pushes to certain branches.

View File

@ -3,6 +3,8 @@ use strict;
use warnings;
my $rule = $ARGV[7];
die "\n\nFATAL: GL_REFEX_EXPR_ doesn't exist\n(your admin probably forgot the rc file change needed for this to work)\n\n"
unless exists $ENV{"GL_REFEX_EXPR_" . $rule};
my $res = $ENV{"GL_REFEX_EXPR_" . $rule} || 0;
print "$ARGV[6] ($res)\n" if $res;

View File

@ -12,13 +12,17 @@
# - run a cron job to delete old repos based on age (the TRASH_SUFFIX has a
# timestamp); your choice how/how often you do that
# - you can completely disable the 'rm' command by setting an rc variable
# called D_DISABLE_RM to "1".
# ----------------------------------------------------------------------
# ----------------------------------------------------------------------
# Usage: ssh git@host D <subcommand> <argument>
#
# The whimsically named "D" command deletes repos ("D" is a counterpart to the
# "C" permission which lets you create repos!)
# "C" permission which lets you create repos. Which also means that, just
# like "C", it only works for wild repos).
#
# There are two kinds of deletions: 'rm' removes a repo completely, while
# 'trash' moves it to a trashcan which can be recovered later (upto a time
@ -66,6 +70,8 @@ owner_or_die() {
if [ "$cmd" = "rm" ]
then
gitolite query-rc -q D_DISABLE_RM && die "sorry, 'unlock' and 'rm' are disabled"
owner_or_die
[ -f $repo.git/gl-rm-ok ] || die "'$repo' is locked!"
rm -rf $repo.git
@ -81,6 +87,8 @@ then
elif [ "$cmd" = "unlock" ]
then
gitolite query-rc -q D_DISABLE_RM && die "sorry, 'unlock' and 'rm' are disabled"
owner_or_die
touch $repo.git/gl-rm-ok
echo "'$repo' is now unlocked"

15
src/commands/create Executable file
View File

@ -0,0 +1,15 @@
#!/bin/bash
# Usage: ssh git@host create <repo>
#
# Create wild repo.
die() { echo "$@" >&2; exit 1; }
usage() { perl -lne 'print substr($_, 2) if /^# Usage/../^$/' < $0; exit 1; }
[ -z "$1" ] && usage
[ -z "$2" ] || usage
[ "$1" = "-h" ] && usage
[ -z "$GL_USER" ] && die GL_USER not set
# ----------------------------------------------------------------------
exec $GL_BINDIR/commands/perms -c "$@" < /dev/null

View File

@ -10,10 +10,6 @@
# traffic but because it uses git clone's "-l" option to share the object
# store also, so it is likely to be almost instantaneous, regardless of how
# big the repo actually is.
#
# The only caveat is that the repo you cloned *from* must not later become
# unavailable in any way. If you cannot be sure of this, take the scenic
# route (clone repo1, push to repo2).
die() { echo "$@" >&2; exit 1; }
usage() { perl -lne 'print substr($_, 2) if /^# Usage/../^$/' < $0; exit 1; }
@ -48,6 +44,7 @@ echo "$from forked to $to" >&2
cd $GL_REPO_BASE/$to.git
echo $GL_USER > gl-creator
touch gl-perms
if gitolite query-rc -q DEFAULT_ROLE_PERMS
then
gitolite query-rc DEFAULT_ROLE_PERMS > gl-perms

View File

@ -4,6 +4,7 @@ use warnings;
use lib $ENV{GL_LIBDIR};
use Gitolite::Common;
use Gitolite::Conf::Load;
=for usage
Usage: gitolite list-dangling-repos
@ -12,6 +13,9 @@ List all existing repos that no one can access remotely any more. They could
be normal repos that were taken out of "repo" statements in the conf file, or
wildcard repos whose matching "wild" pattern was taken out or changed so it no
longer matches.
I would advise caution if you use this as a basis for deleting repos from the
file system. A bug in this program could cause you to lose important data!
=cut
usage() if @ARGV and $ARGV[0] eq '-h';
@ -21,6 +25,9 @@ usage() if @ARGV and $ARGV[0] eq '-h';
# is to cull %phy_repos of all keys that have a matching key in %repos, where
# "matching" means "string equal" or "regex match".
my %repos = map { chomp; $_ => 1 } `gitolite list-repos`;
for my $r ( grep /^@/, keys %repos ) {
map { chomp; $repos{$_} = 1; } `gitolite list-members $r`;
}
my %phy_repos = map { chomp; $_ => 1 } `gitolite list-phy-repos`;
# Remove exact matches. But for repo names like "gtk+", you could have
@ -34,8 +41,9 @@ for my $pr (keys %phy_repos) {
# Remove regex matches.
for my $pr (keys %phy_repos) {
my $matched = 0;
my $pr2 = Gitolite::Conf::Load::generic_name($pr);
for my $r (keys %repos) {
if ($pr =~ /^$r$/) {
if ($pr =~ /^$r$/ or $pr2 =~ /^$r$/) {
$matched = 1;
next;
}

View File

@ -71,7 +71,7 @@ sub f_unlock {
my ( $repo, $file ) = @_;
my %locks = get_locks();
_die "'$file' not locked by '$ENV{GL_USER}'" if ( $locks{$file} || '' ) ne $ENV{GL_USER};
_die "'$file' not locked by '$ENV{GL_USER}'" if ( $locks{$file}{USER} || '' ) ne $ENV{GL_USER};
delete $locks{$file};
put_locks(%locks);
}

View File

@ -48,15 +48,16 @@ if ( $cmd eq 'push' ) {
if (-f "gl-creator") {
# try to propagate the wild repo, including creator name and gl-perms
my $creator = `cat gl-creator`; chomp($creator);
trace(1, `cat gl-perms 2>/dev/null | ssh $host CREATOR=$creator perms -c \\'$repo\\'`);
trace(1, `cat gl-perms 2>/dev/null | ssh $host CREATOR=$creator perms -c \\'$repo\\' 2>/dev/null`);
}
my $errors = 0;
for (`git push --mirror $host:$repo 2>&1`) {
$errors = 1 if $?;
print STDERR "$_" if -t STDERR or exists $ENV{GL_USER};
chomp;
if (/FATAL/) {
$errors++;
$errors = 1;
gl_log( 'mirror', $_ );
} else {
trace( 1, "mirror: $_" );

View File

@ -43,15 +43,17 @@ if ( $ARGV[0] eq '-l' ) {
getperms(@ARGV); # doesn't return
}
my $generic_error = "repo does not exist, or you are not authorised";
# auto-create the repo if -c passed and repo doesn't exist
if ( $ARGV[0] eq '-c' ) {
shift;
my $repo = $ARGV[0];
my $repo = $ARGV[0] or usage();
_die "invalid repo '$repo'" unless $repo =~ $REPONAME_PATT;
if (not -d "$rc{GL_REPO_BASE}/$repo.git") {
my $ret = access( $repo, $ENV{GL_USER}, '^C', 'any' );
_die $ret if $ret =~ /DENIED/;
_die $generic_error if $ret =~ /DENIED/;
require Gitolite::Conf::Store;
Gitolite::Conf::Store->import;
@ -68,7 +70,7 @@ _system( "gitolite", "trigger", "POST_CREATE", $repo, $ENV{GL_USER}, 'perms' );
sub getperms {
my $repo = shift;
_die "sorry you are not authorised" if repo_missing($repo) or creator($repo) ne $ENV{GL_USER};
_die $generic_error if repo_missing($repo) or creator($repo) ne $ENV{GL_USER};
my $pf = "$rc{GL_REPO_BASE}/$repo.git/gl-perms";
print slurp($pf) if -f $pf;
@ -77,17 +79,20 @@ sub getperms {
}
sub setperms {
_die "sorry you are not authorised" if repo_missing($repo) or creator($repo) ne $ENV{GL_USER};
_die $generic_error if repo_missing($repo) or creator($repo) ne $ENV{GL_USER};
my $pf = "$rc{GL_REPO_BASE}/$repo.git/gl-perms";
if ( not @_ ) {
# legacy mode; pipe data in
print STDERR "'batch' mode started, waiting for input (run with '-h' for details).\n";
print STDERR "Please hit Ctrl-C if you did not intend to do this.\n";
@ARGV = ();
my @a;
for (<>) {
_die "Invalid role '$1'; check the rc file" if /(\S+)/ and not $rc{ROLES}{$1};
push @a, $_;
}
print STDERR "\n"; # make sure Ctrl-C gets caught
_print( $pf, @a );
return;
}

View File

@ -73,7 +73,7 @@ for my $pkf (@pubkeyfiles) {
my $fp = fprint($pkf);
next unless $fp;
msg 1, "$pkfsn appears to be a COPY of $pkf_by_fp{$fp}\n" if $pkf_by_fp{$fp};
$pkf_by_fp{$fp} ||= $pkf;
$pkf_by_fp{$fp} ||= $pkfsn;
my $fpu = ( $seen_fprints{$fp}{user} || 'no access' );
msg 0, "$pkfsn maps to $fpu\n";
}
@ -170,17 +170,20 @@ sub fprint {
sub usage {
print <<EOF;
sshkeys-lint expects
- the contents of an authorized_keys file via STDIN
- one or more pubkey filenames as arguments
Usage: gitolite sshkeys-lint [-q] [optional list of pubkey filenames]
(optionally, STDIN can be a pipe or redirected from a file; see below)
sample use to check all keys on gitolite server:
cd ~/.gitolite/keydir
cat ~/.ssh/authorized_keys | sshkeys-lint `find . -name "*.pub"`
# or supply only one pubkey file to check only that:
cat ~/.ssh/authorized_keys | sshkeys-lint YourName.pub
Look for potential problems in ssh keys.
Note that it runs ssh-keygen -l for each line in the authkeys file and each
sshkeys-lint expects:
- the contents of an authorized_keys file via STDIN, otherwise it uses
\$HOME/.ssh/authorized_keys
- one or more pubkey filenames as arguments, otherwise it uses all the keys
found (recursively) in \$HOME/.gitolite/keydir
The '-q' option will print only warnings instead of all mappings.
Note that this runs ssh-keygen -l for each line in the authkeys file and each
pubkey in the argument list, so be wary of running it on something huge. This
is meant for troubleshooting.

View File

@ -7,7 +7,7 @@
die() { echo "$@" >&2; exit 1; }
usage() { perl -lne 'print substr($_, 2) if /^# Usage/../^$/' < $0; exit 1; }
[ -z "$1" ] && usage
[ -z "$2" ] && usage
[ "$1" = "-h" ] && usage
[ -z "$GL_USER" ] && die GL_USER not set

View File

@ -234,5 +234,6 @@ sub http_print_headers {
print "Expires: Fri, 01 Jan 1980 00:00:00 GMT\r\n";
print "Pragma: no-cache\r\n";
print "Cache-Control: no-cache, max-age=0, must-revalidate\r\n";
print "Content-Type: text/plain\r\n";
print "\r\n";
}

View File

@ -14,6 +14,8 @@ package Gitolite::Common;
gl_log
dd
t_start
t_lap
);
#>>>
use Exporter 'import';
@ -70,6 +72,21 @@ sub dd {
dbg(@_);
}
{
use Time::HiRes;
my %start_times;
sub t_start {
my $name = shift || 'default';
$start_times{$name} = [ Time::HiRes::gettimeofday() ];
}
sub t_lap {
my $name = shift || 'default';
return Time::HiRes::tv_interval( $start_times{$name} );
}
}
sub _warn {
gl_log( 'warn', @_ );
if ( $ENV{D} and $ENV{D} >= 3 ) {
@ -260,7 +277,7 @@ sub gl_log {
my $fh;
logger_plus_stderr( "errors found before logging could be setup", "$msg" ) if not $ENV{GL_LOGFILE};
open my $lfh, ">>", $ENV{GL_LOGFILE}
or logger_plus_stderr( "errors found before logfile could be created", "$msg" );
or logger_plus_stderr( "errors found but logfile could not be created", "$ENV{GL_LOGFILE}: $!", "$msg" );
print $lfh "$ts\t$tid\t$msg\n";
close $lfh;
}

View File

@ -32,6 +32,7 @@ our $data_version = '';
our %repos;
our %one_repo;
our %groups;
our %patterns;
our %configs;
our %one_config;
our %split_conf;
@ -70,8 +71,12 @@ sub access {
_die "invalid user '$user'" if not( $user and $user =~ $USERNAME_PATT );
sanity($repo);
my $deny_rules = option( $repo, 'deny-rules' );
my @rules;
my $deny_rules;
load($repo);
@rules = rules( $repo, $user );
$deny_rules = option( $repo, 'deny-rules' );
# sanity check the only piece the user can control
_die "invalid characters in ref or filename: '$ref'\n" unless $ref =~ $REF_OR_FILENAME_PATT;
@ -89,7 +94,6 @@ sub access {
return "$aa $ref $repo $user DENIED by existence";
}
my @rules = rules( $repo, $user );
trace( 2, scalar(@rules) . " rules found" );
for my $r (@rules) {
my $perm = $r->[1];
@ -164,6 +168,14 @@ sub git_config {
}
}
my($k, $v);
my $creator = creator($repo);
while (($k, $v) = each %ret) {
$v =~ s/%GL_REPO/$repo/g;
$v =~ s/%GL_CREATOR/$creator/g if $creator;
$ret{$k} = $v;
}
trace( 3, map { ( "$_" => "-> $ret{$_}" ) } ( sort keys %ret ) );
return \%ret;
}
@ -234,9 +246,9 @@ sub load_1 {
}
if ( -f "gl-conf" ) {
_warn "split conf not set, gl-conf present for '$repo'" if not $split_conf{$repo};
return if not $split_conf{$repo};
my $cc = "gl-conf";
my $cc = "./gl-conf";
_die "parse '$cc' failed: " . ( $! or $@ ) unless do $cc;
$last_repo = $repo;
@ -296,9 +308,11 @@ sub load_1 {
sub memberships {
trace( 3, @_ );
my ( $type, $base, $repo ) = @_;
$repo ||= '';
my @ret;
my $base2 = '';
my @ret = ( $base, '@all' );
@ret = ( $base, '@all' );
if ( $type eq 'repo' ) {
# first, if a repo, say, pub/sitaram/project, has a gl-creator file
@ -313,8 +327,10 @@ sub memberships {
}
}
for my $i ( keys %groups ) {
if ( $base eq $i or $base =~ /^$i$/ or $base2 and ( $base2 eq $i or $base2 =~ /^$i$/ ) ) {
push @ret, @{ $groups{$base} } if exists $groups{$base};
push @ret, @{ $groups{$base2} } if $base2 and exists $groups{$base2};
for my $i ( keys %{ $patterns{groups} } ) {
if ( $base =~ /^$i$/ or $base2 and ( $base2 =~ /^$i$/ ) ) {
push @ret, @{ $groups{$i} };
}
}
@ -370,6 +386,8 @@ sub user_roles {
for (@roles) {
# READERS u3 u4 @g1
s/^\s+//; s/ +$//; s/=/ /; s/\s+/ /g; s/^\@//;
next if /^#/;
next unless /\S/;
my ( $role, @members ) = split;
# role = READERS, members = u3, u4, @g1
if ( $role ne 'CREATOR' and not $rc{ROLES}{$role} ) {
@ -402,8 +420,7 @@ sub generic_name {
$creator = creator($base);
$base2 = $base;
$base2 =~ s(/$creator/)(/CREATOR/) if $creator;
$base2 =~ s(^$creator/)(CREATOR/) if $creator;
$base2 =~ s(\b$creator\b)(CREATOR) if $creator;
$base2 = '' if $base2 eq $base; # if there was no change
return $base2;

View File

@ -156,7 +156,7 @@ sub new_repos {
# normal repos
my @repos = grep { $_ =~ $REPONAME_PATT and not /^@/ } sort keys %repos;
# add in members of repo groups
map { push @repos, keys %{ $groups{$_} } } grep { /^@/ } keys %repos;
map { push @repos, keys %{ $groups{$_} } } grep { /^@/ and $_ ne '@all' } keys %repos;
for my $repo ( @{ sort_u( \@repos ) } ) {
next unless $repo =~ $REPONAME_PATT; # skip repo patterns
@ -191,7 +191,7 @@ sub new_wild_repo {
trigger( 'PRE_CREATE', $repo, $user, $aa );
new_repo($repo);
_print( "$repo.git/gl-creator", $user );
_print( "$repo.git/gl-perms", "$rc{DEFAULT_ROLE_PERMS}\n" ) if $rc{DEFAULT_ROLE_PERMS};
_print( "$repo.git/gl-perms", ( $rc{DEFAULT_ROLE_PERMS} ? "$rc{DEFAULT_ROLE_PERMS}\n" : "" ) );
trigger( 'POST_CREATE', $repo, $user, $aa );
_chdir( $rc{GL_ADMIN_BASE} );
@ -258,15 +258,18 @@ sub store_1 {
# warning: writes and *deletes* it from %repos and %configs
my ($repo) = shift;
trace( 3, $repo );
return unless $repos{$repo} and -d "$repo.git";
return unless ( $repos{$repo} or $configs{$repo} ) and -d "$repo.git";
my ( %one_repo, %one_config );
open( my $compiled_fh, ">", "$repo.git/gl-conf" ) or return;
$one_repo{$repo} = $repos{$repo};
delete $repos{$repo};
my $dumped_data = Data::Dumper->Dump( [ \%one_repo ], [qw(*one_repo)] );
my $dumped_data = '';
if ($repos{$repo}) {
$one_repo{$repo} = $repos{$repo};
delete $repos{$repo};
$dumped_data = Data::Dumper->Dump( [ \%one_repo ], [qw(*one_repo)] );
}
if ( $configs{$repo} ) {
$one_config{$repo} = $configs{$repo};
@ -285,6 +288,8 @@ sub store_common {
my $cc = "conf/gitolite.conf-compiled.pm";
my $compiled_fh = _open( ">", "$cc.new" );
my %patterns = ();
my $data_version = glrc('current-data-version');
trace( 3, "data_version = $data_version" );
print $compiled_fh Data::Dumper->Dump( [$data_version], [qw(*data_version)] );
@ -298,7 +303,16 @@ sub store_common {
my %groups = %{ inside_out( \%groups ) };
$dumped_data = Data::Dumper->Dump( [ \%groups ], [qw(*groups)] );
print $compiled_fh $dumped_data;
# save patterns in %groups for faster handling of multiple repos, such
# as happens in the various POST_COMPILE scripts
for my $k (keys %groups) {
$patterns{groups}{$k} = 1 unless $k =~ $REPONAME_PATT;
}
}
print $compiled_fh Data::Dumper->Dump( [ \%patterns ], [qw(*patterns)] ) if %patterns;
print $compiled_fh Data::Dumper->Dump( [ \%split_conf ], [qw(*split_conf)] ) if %split_conf;
close $compiled_fh or _die "close compiled-conf failed: $!\n";

View File

@ -58,7 +58,7 @@ $UNSAFE_PATT = qr([`~#\$\&()|;<>]);
# find the rc file and 'do' it
# ----------------------------------------------------------------------
my $current_data_version = "3.0";
my $current_data_version = "3.2";
my $rc = glrc('filename');
if (-r $rc and -s $rc) {
@ -425,7 +425,7 @@ __DATA__
],
# comment out or uncomment as needed
# these will run in sequence after a new wild repo is created
# these will run in sequence after a new repo is created
POST_CREATE =>
[
'post-compile/update-git-configs',

View File

@ -261,7 +261,12 @@ sub rc_lines {
$cmd = shift @cmds;
# is the current command a "testing" command?
my $testing_cmd = ( $cmd =~ m(^ok(?:\s+or\s+(.*))?$) or $cmd =~ m(^!ok(?:\s+or\s+(.*))?$) or $cmd =~ m(^/(.*?)/(?:\s+or\s+(.*))?$) or $cmd =~ m(^!/(.*?)/(?:\s+or\s+(.*))?$) );
my $testing_cmd = (
$cmd =~ m(^ok(?:\s+or\s+(.*))?$)
or $cmd =~ m(^!ok(?:\s+or\s+(.*))?$)
or $cmd =~ m(^/(.*?)/(?:\s+or\s+(.*))?$)
or $cmd =~ m(^!/(.*?)/(?:\s+or\s+(.*))?$)
);
# warn if the previous command failed but rc is not being checked
if ( $rc and not $testing_cmd ) {
@ -474,7 +479,7 @@ sub fail {
sub cmp {
# compare input string with second input string or text()
my $in = shift;
my $in = shift;
my $text = ( @_ ? +shift : text() );
if ( $text eq $in ) {
@ -583,7 +588,7 @@ sub dummy_commits {
test_tick();
next;
}
my $ts = ( $tick ? gmtime($tick+19800) : gmtime() );
my $ts = ( $tick ? gmtime( $tick + 19800 ) : gmtime() );
_sh("echo $f at $ts >> $f && git add $f && git commit -m '$f at $ts'");
}
}

0
src/lib/Gitolite/Triggers/Alias.pm Executable file → Normal file
View File

View File

@ -0,0 +1,24 @@
package Gitolite::Triggers::AutoCreate;
use strict;
use warnings;
# perl trigger set for stuff to do with auto-creating repos
# ----------------------------------------------------------------------
# to deny auto-create on read access, add 'AutoCreate::deny_R' to the
# PRE_CREATE trigger list
sub deny_R {
die "autocreate denied\n" if $_[3] and $_[3] eq 'R';
return;
}
# to deny auto-create on read *and* write access, add 'AutoCreate::deny_RW' to
# the PRE_CREATE trigger list. This means you can only create repos using the
# 'create' command, (which needs to be enabled in the COMMANDS list).
sub deny_RW {
die "autocreate denied\n" if $_[3] and ( $_[3] eq 'R' or $_[3] eq 'W' );
return;
}
1;

3
src/lib/Gitolite/Triggers/CpuTime.pm Executable file → Normal file
View File

@ -10,6 +10,7 @@ use warnings;
# cpu and elapsed times for gitolite+git operations
# ----------------------------------------------------------------------
# uncomment the appropriate lines in the rc file to enable this
# Ideally, you will (a) write your own code with a different filename so later
# gitolite upgrades won't overwrite your copy, (b) add appropriate variables
@ -18,8 +19,6 @@ use warnings;
# ----------------------------------------------------------------------
my $start_time;
# this trigger is not yet documented; it gets called at the start and does not
# receive any arguments.
sub input {
_warn "something wrong with the invocation of CpuTime::input" if $ENV{GL_TID} ne $$;
$start_time = [ Time::HiRes::gettimeofday() ];

View File

@ -9,6 +9,8 @@ use warnings;
# setting a repo specific umask
# ----------------------------------------------------------------------
# this is for people who are too paranoid to trust e.g., gitweb's repo
# exclusion logic, but not paranoid enough to put it on a different server
=for usage

View File

@ -3,6 +3,9 @@ package Gitolite::Triggers::Shell;
# usage notes: this module must be loaded first in the INPUT trigger list. Or
# at least before Mirroring::input anyway.
# documentation is in the ssh troubleshooting and tips document, under the
# section "giving shell access to gitolite users"
use Gitolite::Rc;
use Gitolite::Common;

View File

@ -20,7 +20,7 @@ sub groupnames {
my @out = ();
my %members = ();
for my $pk (`find ../keydir/ -name "*.pub"`) {
next unless $pk =~ m(.*/([^/]+)/([^/]+)\.pub$);
next unless $pk =~ m(.*/([^/]+)/([^/]+?)(?:@[^./]+)?\.pub$);
next if $1 eq 'keydir';
$members{$1} .= " $2";
}

View File

@ -0,0 +1,74 @@
# vim: syn=perl:
# "sugar script" (syntactic sugar helper) for gitolite3
# simple line-wise macro processor
# ----------------------------------------------------------------------
# see documentation at the end of this script
my %macro;
sub sugar_script {
my $lines = shift;
my @out = ();
my $l = join("\n", @$lines);
while ($l =~ s/^macro (\w+)\b(.*?)\nend//ms) {
$macro{$1} = $2;
}
$l =~ s/^((\w+)\b.*)/$macro{$2} ? expand($1) : $1/gem;
$lines = [split "\n", $l];
return $lines;
}
sub expand {
my $l = shift;
my ($word, @arg) = split ' ', $l;
my $v = $macro{$word};
$v =~ s/%(\d+)/$arg[$1-1] or die "macro '$word' needs $1 arguments at '$l'\n"/gem;
return $v;
}
__END__
Documentation is mostly by example.
Setup:
* the line
'macros',
should be added to the SYNTACTIC_SUGAR list in ~/.gitolite.rc
Notes on macro definition:
* the keywords 'macro' and 'end' should start on a new line
* the first word after 'macro' is the name of the macro, and the rest, until
the 'end', is the body
Notes on macro use:
* the macro name should be the first word on a line
* the rest of the line is used as arguments to the macro
Example:
if your conf contains:
macro foo repo aa-%1
RW = u1 %2
R = u2
end
foo 1 alice
foo 2 bob
this will effectively turn into
repo aa-1
RW = u1 alice
R = u2
repo aa-2
RW = u1 bob
R = u2

17
src/triggers/bg Executable file
View File

@ -0,0 +1,17 @@
#!/bin/bash
# quick and dirty program to background any of the triggers programs that are
# taking too long. To use, just replace a line like
# 'post-compile/update-gitweb-access-list',
# with
# 'bg post-compile/update-gitweb-access-list',
# We dump output to a file in the log directory but please keep in mind this
# is not a "log" so much as a redirection of the entire output.
echo `date` $GL_TID "$0: $@" >> $GL_LOGFILE.bg
path=${0%/*}
script=$path/$1; shift
( ( $script "$@" < /dev/null >> $GL_LOGFILE.bg 2>&1 & ) )

View File

@ -0,0 +1,59 @@
#!/bin/bash
# split multi-key files into separate keys like ssh-authkeys likes
# WHY
# ---
#
# Yeah I wonder that too, when it's so much more maintainable to keep the damn
# keys as sitaram@home.pub and sitaram@work.pub or such. But there's no
# accounting for tastes, and some old fogies apparently want to put all of a
# user's keys into a single ".pub" file.
# WARNINGS AND CAVEATS
# --------------------
#
# - assumes no "@" sign in basenames of any multi-key files (single line file
# may still have them)
# - assumes you don't have a subdir in keydir called "__split_keys__"
# - God help you if you try to throw in a putty key in there.
# SUPPORT
# -------
#
# NONE. Mainly because I **know** someone will throw in a putty key. I just
# know it.
# USAGE
# -----
#
# add it to the POST_COMPILE trigger list in the rc file, but *before* the
# ssh-authkeys program entry.
cd $GL_ADMIN_BASE/keydir
rm -rf __split_keys__
mkdir __split_keys__
export SKD=$PWD/__split_keys__
find . -type f -name "*.pub" | while read k
do
# do we need to split?
lines=`wc -l < $k`
[ "$lines" = "1" ] && continue
# is it sane to split?
base=`basename $k .pub`
echo $base | grep '@' >/dev/null && continue
# ok do it
seq=1
while read line
do
echo "$line" > $SKD/$base@$seq.pub
(( seq++ ))
done < $k
# now delete the original file
rm $k
done

View File

@ -1,4 +1,4 @@
#!/bin/bash
#!/bin/sh
# For normal (not "wild") repos, gitolite v3 sets 'gitweb.description' instead
# of putting the text in the "description" file. This is easier because it

View File

@ -49,8 +49,6 @@ sub fixup_config {
while ( my ( $key, $value ) = each( %{$gc} ) ) {
next if $key =~ /^gitolite-options\./;
if ( $value ne "" ) {
$value =~ s/%GL_REPO/$pr/g;
$value =~ s/%GL_CREATOR/$creator/g if $creator;
system( "git", "config", "--file", "$RB/$pr.git/config", $key, $value );
} else {
system( "git", "config", "--file", "$RB/$pr.git/config", "--unset-all", $key );

View File

@ -6,8 +6,10 @@
# ----------------------------------------------------------------------
# delete the 'description' file that 'git init' created if this is run from
# the post-create trigger
[ "$1" = "POST_CREATE" ] && rm -f $GL_REPO_BASE/$2.git/description 2>/dev/null
# the post-create trigger. However, note that POST_CREATE is also called from
# perms (since POST_CREATE doubles as eqvt of POST_COMPILE to propagate ad hoc
# permissions changes for wild repos) and then you should not delete it.
[ "$1" = "POST_CREATE" ] && [ "$4" != "perms" ] && rm -f $GL_REPO_BASE/$2.git/description 2>/dev/null
# ----------------------------------------------------------------------
# skip if arg-1 is POST_CREATE and no arg-3 (user name) exists; this means

View File

@ -0,0 +1,57 @@
#!/bin/sh
# Update git-daemon and gitweb access using 'option' lines instead of special
# usernames.
# To use:
# * enable this combined updater in the rc file by removing the other two
# update-*-access-list entries and inserting this one instead. (This would
# be in the POST_CREATE and POST_COMPILE lists).
# * the add option lines in the conf file, like this:
#
# repo foo @bar
# option daemon = 1
# option gitweb = 1
# Note: don't forget that gitweb can also be enabled by actual config
# variables (gitweb.owner, gitweb.description, gitweb.category)
# This is useful for people who don't like '@all' to be literally *all* users,
# including gitweb and daemon, and can't/won't use deny-rules properly.
# ----------------------------------------------------------------------
# skip if arg-1 is POST_CREATE and no arg-3 (user name) exists; this means
# it's been triggered by a *normal* (not "wild") repo creation, which in turn
# means a POST_COMPILE should be following so there's no need to waste time
# running this once for each new repo
[ "$1" = "POST_CREATE" ] && [ -z "$3" ] && exit 0;
# first do the gitweb stuff
plf=`gitolite query-rc GITWEB_PROJECTS_LIST`
[ -z "$plf" ] && plf=$HOME/projects.list
(
gitolite list-phy-repos | gitolite git-config % gitolite-options.gitweb
gitolite list-phy-repos | gitolite git-config -r % gitweb\\.
) |
cut -f1 | sort -u | sed -e 's/$/.git/' > $plf
# now deal with git-daemon
EO=git-daemon-export-ok
RB=`gitolite query-rc GL_REPO_BASE`
export EO RB
export tmp=$(mktemp -d)
trap "rm -rf $tmp" 0
gitolite list-phy-repos | sort | tee $tmp/all | gitolite git-config % gitolite-options.daemon | cut -f1 > $tmp/daemon
comm -23 $tmp/all $tmp/daemon | perl -lne 'unlink "$ENV{RB}/$_.git/$ENV{EO}"'
cat $tmp/daemon | while read repo
do
> $RB/$repo.git/$EO
done

View File

@ -1,4 +1,4 @@
#!/bin/bash
#!/bin/sh
# manage local, gitolite-controlled, copies of read-only upstream repos.
@ -11,7 +11,7 @@ cd $GL_REPO_BASE/$repo.git || exit 1
[ "$1" != "fetch" ] && {
nice=$(gitolite git-config $repo gitolite-options.upstream.nice)
[ -n "$nice" ] && find FETCH_HEAD -mmin -$nice | grep . >/dev/null && exit 0
[ -n "$nice" ] && find FETCH_HEAD -mmin -$nice 2>/dev/null | grep . >/dev/null && exit 0
}
git fetch -q "$url" '+refs/*:refs/*'
@ -44,3 +44,29 @@ git fetch -q "$url" '+refs/*:refs/*'
# * if the upstream URL changes, just change the conf and push admin repo
# * the 'nice' setting is in minutes and is optional; it is the minimum
# elapsed time between 2 upstream fetches.
# USAGE EXAMPLE:
#
# Let's say you want to keep a read-only local mirror of all your github repos
# on your local gitolite installation. Assuming your github usernames are the
# same as your local usernames, and you have updated GIT_CONFIG_KEYS in the rc
# file to allow 'config' lines, you can do this:
#
# repo github/CREATOR/..*
# C = @all
# R = @all
# option upstream.url = git://github.com/%GL_REPO.git
# option upstream.nice = 120
# config url.git://github.com/.insteadOf = git://github.com/github/
#
# Now you can make local, read-only, clones of all your github repos with
#
# git ls-remote gitolite:github/sitaramc/gitolite
# git ls-remote gitolite:github/sitaramc/hap
# (etc)
#
# and if milki were also a user on this gitolite instance, then
#
# git ls-remote gitolite:github/milki/xclip
# git ls-remote gitolite:github/milki/ircblogger
# (etc)

View File

@ -11,7 +11,7 @@ my $rb = `gitolite query-rc -n GL_REPO_BASE`;
# initial smoke tests
# ----------------------------------------------------------------------
try "plan 73";
try "plan 71";
# basic push admin repo
confreset;confadd '
@ -33,12 +33,11 @@ try "
cd ..
glt clone u1 file://aa u1aa; ok; /Cloning into 'u1aa'.../
/warning: You appear to have cloned an empty repository/
ls -ald --time-style=long-iso u1aa;
ok; /drwxr-xr-x 3 $ENV{USER} $ENV{USER} \\d+ 201.-..-.. ..:.. u1aa/
[ -d u1aa ]; ok
# basic clone deny
glt clone u4 file://aa u4aa; !ok; /R any aa u4 DENIED by fallthru/
ls -ald u4aa; !ok; /ls: cannot access u4aa: No such file or directory/
[ -d u4aa ]; !ok
# basic push
cd u1aa; ok

View File

@ -10,7 +10,7 @@ use Gitolite::Test;
# ----------------------------------------------------------------------
try "
plan 218
plan 217
CHECK_SETUP
# subtest 1
@ -77,7 +77,7 @@ try "
/fatal: The remote end hung up unexpectedly/
CLONE u2 t1; ok; gsh
/warning: You appear to have cloned an empty repository./
ls -al t1; ok; /$ENV{USER}.*$ENV{USER}.*\.git/
[ -d t1/.git ]; ok
cd t1; ok;
# push

View File

@ -61,7 +61,8 @@ try "
my $t;
try "cd $rb; find . -name gl-perms"; $t = md5sum(sort (lines())); cmp $t,
'59b3a74b4d33c7631f08e75e7b60c7ce ./foo/u1/u1a2.git/gl-perms
'd41d8cd98f00b204e9800998ecf8427e ./foo/u1/u1a.git/gl-perms
59b3a74b4d33c7631f08e75e7b60c7ce ./foo/u1/u1a2.git/gl-perms
59b3a74b4d33c7631f08e75e7b60c7ce ./foo/u1/u1e.git/gl-perms
';

View File

@ -9,7 +9,7 @@ use Gitolite::Test;
# merge check -- the M flag
# ----------------------------------------------------------------------
try "plan 57";
try "plan 55";
confreset;confadd '
repo foo
@ -25,7 +25,7 @@ try "ADMIN_PUSH set1; !/FATAL/" or die text();
try "
cd ..
ls -al foo; !ok; /cannot access foo: No such file or directory/
[ -d foo ]; !ok
glt clone u1 file:///foo
ok; /Cloning into/
/You appear to have cloned an empty/
@ -33,7 +33,7 @@ try "
try "
cd foo; ok
ls -Al; ok; /\.git/
[ -d .git ]; ok
test-commit aa; ok; /1 file changed, 1 insertion/
tag start; ok
glt push u1 origin master

View File

@ -55,7 +55,7 @@ try "
confreset;confadd '
@staff = u1 u2 u3
@gfoo = foo/CREATOR/.+
@gfoo = foo/CREATOR/..*
repo @gfoo
C = u1
RW+ = CREATOR
@ -100,7 +100,7 @@ try "
# auto-create using perms fail
echo READERS u5 | glt perms u4 -c foo/u4/baz
!/Initialized empty Git repository in .*/foo/u4/baz.git/
/FATAL: .C any foo/u4/baz u4 DENIED by fallthru/
/FATAL: repo does not exist, or you are not authorised/
# auto-create using perms
echo READERS u2 | glt perms u1 -c foo/u1/baz

View File

@ -9,7 +9,7 @@ use Gitolite::Test;
# VREFs - part 1
# ----------------------------------------------------------------------
try "plan 90";
try "plan 88";
put "conf/gitolite.conf", "
repo gitolite-admin
@ -32,11 +32,11 @@ put "conf/gitolite.conf", "
try "
ADMIN_PUSH vr1a
cd ..
ls -al foo; !ok; /cannot access foo: No such file or directory/
[ -d foo ]; !ok
CLONE u1 foo; ok; /Cloning into/
/You appear to have cloned an empty/
cd foo; ok
ls -Al; ok; /\.git/
[ -d .git ]; ok
# VREF not called for u1
tc a1 a2 a3 a4 a5; ok; /aaf9e8e/

View File

@ -9,7 +9,7 @@ use Gitolite::Test;
# VREFs - part 2
# ----------------------------------------------------------------------
try "plan 74";
try "plan 72";
put "../gitolite-admin/conf/gitolite.conf", "
\@gfoo = foo
@ -32,11 +32,11 @@ try "
ADMIN_PUSH vr2a
cd ..
# setup
ls -al foo; !ok; /cannot access foo: No such file or directory/
[ -d foo ]; !ok
CLONE u1 foo; ok; /Cloning into/
/You appear to have cloned an empty/
cd foo; ok
ls -Al; ok; /\.git/
[ -d .git ]; ok
# u1 push 15 new files
tc a b c d e f g h i j k l m n o