Compare commits
66 Commits
Author | SHA1 | Date |
---|---|---|
Denis Knauf | a6f6886e84 | |
Sitaram Chamarty | 089f0f9d9e | |
Sitaram Chamarty | 5aef1adc7b | |
Sitaram Chamarty | 1fefb1c0d9 | |
Sitaram Chamarty | ea3d04ea0a | |
Sitaram Chamarty | 84424e48b9 | |
Sitaram Chamarty | b303694882 | |
Sitaram Chamarty | b9bbb78278 | |
Sitaram Chamarty | 3513f4a153 | |
Sitaram Chamarty | 4f4658274d | |
Sitaram Chamarty | 2048484578 | |
Sitaram Chamarty | 8e3ee2f9c1 | |
Sitaram Chamarty | 3103d68a75 | |
Sven Strickroth | f89408adb1 | |
Sitaram Chamarty | fc7ddfc818 | |
Sitaram Chamarty | f1c69a3ec0 | |
Sitaram Chamarty | 2741fadc9d | |
Sitaram Chamarty | b6d6260dbb | |
Sitaram Chamarty | 72e36f32aa | |
Stephen Palmer | d2214b06b5 | |
Sitaram Chamarty | 96cc2eaf41 | |
Sebastian Koslowski | 96be9503ef | |
Sitaram Chamarty | 7cec71b0ef | |
Sitaram Chamarty | cd838411fa | |
Sitaram Chamarty | 2018267a45 | |
Sitaram Chamarty | a26532d635 | |
Sitaram Chamarty | 5f9789ed8e | |
Sitaram Chamarty | d3d93961a0 | |
Sitaram Chamarty | 1f96180df0 | |
gitolite tester | 57760d7e1b | |
gitolite tester | 16f2d9b879 | |
Sitaram Chamarty | c03d107bac | |
Sitaram Chamarty | d491b5384f | |
Sitaram Chamarty | 8a9564f171 | |
Sitaram Chamarty | a509b208e3 | |
Sitaram Chamarty | be61cd2d66 | |
Sitaram Chamarty | 70ad045e08 | |
Andrew Page | 2aa129bc70 | |
Sitaram Chamarty | a802071a5e | |
Sitaram Chamarty | 4eb8cd4ad1 | |
Sitaram Chamarty | 3eefc06551 | |
Eugene E. Kashpureff Jr | 896ada58c0 | |
Sitaram Chamarty | 51ab768e2a | |
Sitaram Chamarty | f636ce3ba3 | |
Sitaram Chamarty | 0d371ac957 | |
Sitaram Chamarty | 2dbaa4d12e | |
Sitaram Chamarty | 6328ec2cbe | |
Sitaram Chamarty | 3fe8ecf974 | |
Sitaram Chamarty | 9606e35528 | |
Sitaram Chamarty | 724c741335 | |
Sitaram Chamarty | e59c3ba9f9 | |
Sitaram Chamarty | aec8c71890 | |
Sitaram Chamarty | ed4862ff96 | |
Sitaram Chamarty | cc9727c42b | |
Sitaram Chamarty | 7409635823 | |
Olof Johansson | ba67f6f9ca | |
Nate Jones | 31166e1e1c | |
Sitaram Chamarty | b2a3509e63 | |
Patrick Westerhoff | 57bea39a1e | |
Sitaram Chamarty | f4eb6dcb53 | |
Sitaram Chamarty | 8ad1eee220 | |
Dave Abrahams | d3279e4ad0 | |
Sitaram Chamarty | fd0778e6d6 | |
Sitaram Chamarty | f35db87efc | |
Sitaram Chamarty | f545bc08f6 | |
Sitaram Chamarty | db2cf23379 |
40
CHANGELOG
40
CHANGELOG
|
@ -1,3 +1,43 @@
|
|||
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
|
||||
|
||||
rsync command to create and send bundles automagically
|
||||
|
||||
migrated 'who-pushed'
|
||||
|
||||
logical expressions on refexes!!!
|
||||
|
||||
2012-06-27 v3.04 documentation graduated and moved out of parents house :)
|
||||
|
||||
new trigger for 'repo specific umask'
|
||||
|
|
|
@ -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/
|
360
README.txt
360
README.txt
|
@ -1,360 +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).
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
|
||||
DOCUMENTATION FOR GITOLITE
|
||||
==========================
|
||||
|
||||
This file contains basic documentation for a fresh, ssh-based, installation of
|
||||
gitolite and basic usage of its most important features.
|
||||
|
||||
If you need more details on any of the topics covered here, or help with some
|
||||
troubleshooting, or just wish to read about the advanced features not covered
|
||||
here, please check the gitolite online documentation at:
|
||||
|
||||
http://sitaramc.github.com/gitolite/master-toc.html
|
||||
|
||||
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 or '-' 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
|
||||
-------
|
||||
|
||||
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
|
||||
-------
|
||||
|
||||
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/
|
|
@ -38,8 +38,9 @@ sub intro {
|
|||
msg( '' => "or that might end up giving *more* access to someone if migrated as-is." );
|
||||
msg( '' => "It does NOT attempt to catch all the differences described in the docs." );
|
||||
msg( '', '' );
|
||||
msg( INFO => "'see docs' usually means doc/g2migr.mkd" );
|
||||
msg( '', => "(online at http://sitaramc.github.com/gitolite/g2migr.html)" );
|
||||
msg( INFO => "'see docs' usually means the pre-migration checklist in" );
|
||||
msg( '', => "'g2migr.html'; to get there, start from the main migration" );
|
||||
msg( '', => "page at http://sitaramc.github.com/gitolite/install.html#migr" );
|
||||
msg( '', '' );
|
||||
}
|
||||
|
||||
|
|
|
@ -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" ] && {
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#!/bin/bash
|
||||
# TODO: convert to perl!
|
||||
#!/bin/sh
|
||||
|
||||
# gitolite VREF to find autogenerated files
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/bash
|
||||
#!/bin/sh
|
||||
|
||||
# gitolite VREF to count votes before allowing pushes to certain branches.
|
||||
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
#!/usr/bin/perl
|
||||
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;
|
||||
|
||||
exit 0;
|
||||
|
||||
__END__
|
||||
|
||||
Documentation for the refex-expression evaluation feature
|
||||
|
||||
First, make sure you have both the VREF and the trigger scripts
|
||||
(src/VREF/refex-expr and src/lib/Gitolite/Triggers/RefexExpr.pm)
|
||||
|
||||
Next, add this to the ACCESS_2 list in the rc file:
|
||||
|
||||
'RefexExpr::access_2',
|
||||
|
||||
For the rest, we'll use this example:
|
||||
|
||||
* user u1 can push foo to some other branch, and anything else to the master
|
||||
branch, but not foo to the master branch
|
||||
|
||||
* user u2 is allowed to push either 'doc/' or 'src/' but not both
|
||||
|
||||
Here's the conf file extract:
|
||||
|
||||
repo testing
|
||||
RW+ master = u1 # line 1
|
||||
RW+ = @all # line 2
|
||||
|
||||
RW+ VREF/NAME/foo = u1
|
||||
RW+ VREF/NAME/doc/ = u2
|
||||
RW+ VREF/NAME/src/ = u2
|
||||
|
||||
# set up 2 refex expressions, named e1, e2
|
||||
option refex-expr.e1 = master and VREF/NAME/foo
|
||||
option refex-expr.e2 = VREF/NAME/doc/ and VREF/NAME/src/
|
||||
|
||||
# now deny users if the corresponding expression is true
|
||||
- VREF/refex-expr/e1 = u1
|
||||
- VREF/refex-expr/e2 = u2
|
||||
|
||||
Here are some IMPORTANT notes:
|
||||
|
||||
* You MUST place VREF/refex-expr rules at the end. (Only 'partial-copy', if
|
||||
you use it, must come later).
|
||||
|
||||
* You MUST explicitly permit the refexes used in your refex expressions. If
|
||||
you have more generic rules, the specific ones must come first.
|
||||
|
||||
For example, without line 1, the refex recorded for user u1 will come from
|
||||
line 2, (so it will be 'refs/.*'), and 'master' in the refex expressions
|
||||
will never have a true value.
|
||||
|
||||
* (corollary) make sure you use the exact same refex in the expression as
|
||||
you did on the original rule line. E.g., a missing slash at the end will
|
||||
mess things up.
|
||||
|
||||
* You can use any logical expression using refexes as operands and using
|
||||
these operators:
|
||||
|
||||
and not xor or
|
||||
|
||||
Parens are not allowed.
|
||||
|
||||
If a refex has passed, it will have a 'true' value, else it will be false.
|
||||
|
||||
The result of the evaluation, after these substitutions, will be the
|
||||
result of the refex-expr VREF.
|
|
@ -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"
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -36,6 +36,7 @@ exit 0;
|
|||
sub list_x {
|
||||
my $d = shift;
|
||||
return unless $d;
|
||||
return unless -d "$d/commands";
|
||||
_chdir "$d/commands";
|
||||
return map { $_ => $d } grep { -x $_ } map { chomp; s(^./)(); $_ } `find . -type f|sort`;
|
||||
return map { $_ => $d } grep { -x $_ } map { chomp; s(^./)(); $_ } `find . -type f -o -type l|sort`;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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: $_" );
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
#!/usr/bin/perl
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use lib $ENV{GL_LIBDIR};
|
||||
use Gitolite::Easy;
|
||||
|
||||
=for admins
|
||||
|
||||
BUNDLE SUPPORT
|
||||
|
||||
(1) For each repo in gitolite.conf for which you want bundle support (or
|
||||
'@all', if you wish), add the following line:
|
||||
|
||||
option bundle = 1
|
||||
|
||||
Or you can say:
|
||||
|
||||
option bundle.ttl = <number>
|
||||
|
||||
A bundle file that is more than <number> seconds old (default value
|
||||
86400, i.e., 1 day) is recreated on the next bundle request. Increase
|
||||
this if your repo is not terribly active.
|
||||
|
||||
Note: a bundle file is also deleted and recreated if it contains a ref
|
||||
that was then either deleted or rewound in the repo. This is checked
|
||||
on every invocation.
|
||||
|
||||
(2) Add 'rsync' to the COMMANDS list in the rc file
|
||||
|
||||
|
||||
GENERIC RSYNC SUPPORT
|
||||
|
||||
TBD
|
||||
|
||||
=cut
|
||||
|
||||
=for usage
|
||||
rsync helper for gitolite
|
||||
|
||||
BUNDLE SUPPORT
|
||||
|
||||
Admins: see src/commands/rsync for setup instructions
|
||||
|
||||
Users:
|
||||
rsync -P git@host:repo.bundle .
|
||||
# downloads a file called "<basename of repo>.bundle"; repeat as
|
||||
# needed till the whole thing is downloaded
|
||||
git clone repo.bundle repo
|
||||
cd repo
|
||||
git remote set-url origin git@host:repo
|
||||
git fetch origin # and maybe git pull, etc. to freshen the clone
|
||||
|
||||
GENERIC RSYNC SUPPORT
|
||||
|
||||
TBD
|
||||
|
||||
=cut
|
||||
|
||||
usage() if not @ARGV or $ARGV[0] eq '-h';
|
||||
|
||||
# rsync driver program. Several things can be done later, but for now it
|
||||
# drives just the 'bundle' transfer.
|
||||
|
||||
if ( $ENV{SSH_ORIGINAL_COMMAND} =~ /^rsync --server --sender (-[-\w=.]+ )+\. (\S+)\.bundle$/ ) {
|
||||
|
||||
my $repo = $2;
|
||||
$repo =~ s/\.git$//;
|
||||
|
||||
# all errors have the same message to avoid leaking info
|
||||
can_read($repo) or _die "you are not authorised";
|
||||
my %config = config( $repo, "gitolite-options.bundle" ) or _die "you are not authorised";
|
||||
|
||||
my $ttl = $config{'gitolite-options.bundle.ttl'} || 86400; # in seconds (default 1 day)
|
||||
|
||||
my $bundle = bundle_create( $repo, $ttl );
|
||||
|
||||
$ENV{SSH_ORIGINAL_COMMAND} =~ s( \S+\.bundle)( $bundle);
|
||||
trace( 1, "rsync bundle", $ENV{SSH_ORIGINAL_COMMAND} );
|
||||
Gitolite::Common::_system( split ' ', $ENV{SSH_ORIGINAL_COMMAND} );
|
||||
exit 0;
|
||||
}
|
||||
|
||||
_warn "invalid rsync command '$ENV{SSH_ORIGINAL_COMMAND}'";
|
||||
usage();
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# helpers
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
sub bundle_create {
|
||||
my ( $repo, $ttl ) = @_;
|
||||
my $bundle = "$repo.bundle";
|
||||
$bundle =~ s(.*/)();
|
||||
my $recreate = 0;
|
||||
|
||||
my ( %b, %r );
|
||||
if ( -f $bundle ) {
|
||||
%b = map { chomp; reverse split; } `git ls-remote --heads --tags $bundle`;
|
||||
%r = map { chomp; reverse split; } `git ls-remote --heads --tags .`;
|
||||
|
||||
for my $ref ( sort keys %b ) {
|
||||
|
||||
my $mtime = ( stat $bundle )[9];
|
||||
if ( time() - $mtime > $ttl ) {
|
||||
trace( 1, "bundle too old" );
|
||||
$recreate++;
|
||||
last;
|
||||
}
|
||||
|
||||
if ( not $r{$ref} ) {
|
||||
trace( 1, "ref '$ref' deleted in repo" );
|
||||
$recreate++;
|
||||
last;
|
||||
}
|
||||
|
||||
if ( $r{$ref} eq $b{$ref} ) {
|
||||
# same on both sides; ignore
|
||||
delete $r{$ref};
|
||||
delete $b{$ref};
|
||||
next;
|
||||
}
|
||||
|
||||
`git rev-list --count --left-right $b{$ref}...$r{$ref}` =~ /^(\d+)\s+(\d+)$/ or _die "git too old";
|
||||
if ($1) {
|
||||
trace( 1, "ref '$ref' rewound in repo" );
|
||||
$recreate++;
|
||||
last;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
trace( 1, "no bundle found" );
|
||||
$recreate++;
|
||||
}
|
||||
|
||||
return $bundle if not $recreate;
|
||||
|
||||
trace( 1, "creating bundle for '$repo'" );
|
||||
-f $bundle and ( unlink $bundle or die "a horrible death" );
|
||||
system("git bundle create $bundle --branches --tags >&2");
|
||||
|
||||
return $bundle;
|
||||
}
|
||||
|
||||
sub trace {
|
||||
Gitolite::Common::trace(@_);
|
||||
}
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
#!/usr/bin/perl
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use lib $ENV{GL_LIBDIR};
|
||||
use Gitolite::Easy;
|
||||
|
||||
=for usage
|
||||
Usage: ssh git@host who-pushed <repo> <SHA>
|
||||
|
||||
Determine who pushed the given commit. The first few hex digits of the SHA
|
||||
should suffice.
|
||||
|
||||
Each line of the output contains the following fields: timestamp, a
|
||||
transaction ID, username, refname, and the old and new SHAs for the ref.
|
||||
|
||||
We assume the logfile names have been left as default, or if changed, in such
|
||||
a way that they come up oldest first when sorted.
|
||||
|
||||
The program searches ALL the log files, in reverse sorted order (i.e., newest
|
||||
first). This means it could take a long time if your log directory is large
|
||||
and contains lots of old log files. Patches to limit the search to an
|
||||
optional date range are welcome.
|
||||
|
||||
Note on the "transaction ID" field: if looking at the log file doesn't help
|
||||
you figure out what its purpose is, please just ignore it.
|
||||
=cut
|
||||
|
||||
usage() if not @ARGV or @ARGV < 2 or $ARGV[0] eq '-h';
|
||||
usage() if $ARGV[1] !~ /^[0-9a-f]+$/i;
|
||||
|
||||
my $repo = shift;
|
||||
my $sha = shift; $sha =~ tr/A-F/a-f/;
|
||||
|
||||
$ENV{GL_USER} and ( can_read($repo) or die "no read permissions on '$repo'" );
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
my $repodir = "$ENV{GL_REPO_BASE}/$repo.git";
|
||||
chdir $repodir or die "repo '$repo' missing";
|
||||
(my $logdir = $ENV{GL_LOGFILE}) =~ s(/[^/]+$)();
|
||||
|
||||
for my $logfile ( reverse glob("$logdir/*") ) {
|
||||
@ARGV = ($logfile);
|
||||
for my $line ( reverse grep { m(\tupdate\t($repo|$repodir)\t) } <> ) {
|
||||
chomp($line);
|
||||
my @fields = split /\t/, $line;
|
||||
my ($ts, $pid, $who, $ref, $d_old, $new) = @fields[ 0, 1, 4, 6, 7, 8];
|
||||
|
||||
# d_old is what you display
|
||||
my $old = $d_old;
|
||||
$old = "" if $d_old eq ("0" x 40);
|
||||
$old = "$old.." if $old;
|
||||
|
||||
system("git rev-list $old$new 2>/dev/null | grep ^$sha >/dev/null && echo '$ts $pid $who $ref $d_old $new'");
|
||||
}
|
||||
}
|
|
@ -168,7 +168,7 @@ sub sanity {
|
|||
my $repo = shift;
|
||||
_die "'$repo' contains bad characters" if $repo !~ $REPONAME_PATT;
|
||||
_die "'$repo' ends with a '/'" if $repo =~ m(/$);
|
||||
_die "'$repo' contains '..'" if $repo =~ m(\.\.$);
|
||||
_die "'$repo' contains '..'" if $repo =~ m(\.\.);
|
||||
}
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
|
@ -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";
|
||||
}
|
||||
|
|
|
@ -12,6 +12,10 @@ package Gitolite::Common;
|
|||
usage tsh_run
|
||||
gen_lfn
|
||||
gl_log
|
||||
|
||||
dd
|
||||
t_start
|
||||
t_lap
|
||||
);
|
||||
#>>>
|
||||
use Exporter 'import';
|
||||
|
@ -63,6 +67,26 @@ sub dbg {
|
|||
}
|
||||
}
|
||||
|
||||
sub dd {
|
||||
local $ENV{D} = 1;
|
||||
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 ) {
|
||||
|
@ -253,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;
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ sub explode {
|
|||
my ( $file, $subconf, $out ) = @_;
|
||||
|
||||
# seed the 'seen' list if it's empty
|
||||
$included{ device_inode("conf/gitolite.conf") }++ unless %included;
|
||||
$included{ device_inode("gitolite.conf") }++ unless %included;
|
||||
|
||||
my $fh = _open( "<", $file );
|
||||
while (<$fh>) {
|
||||
|
|
|
@ -32,6 +32,7 @@ our $data_version = '';
|
|||
our %repos;
|
||||
our %one_repo;
|
||||
our %groups;
|
||||
our %patterns;
|
||||
our %configs;
|
||||
our %one_config;
|
||||
our %split_conf;
|
||||
|
@ -67,10 +68,15 @@ my $last_repo = '';
|
|||
|
||||
sub access {
|
||||
my ( $repo, $user, $aa, $ref ) = @_;
|
||||
_die "invalid repo '$repo'" if not( $repo and $repo =~ $REPOPATT_PATT );
|
||||
_die "invalid user '$user'" if not( $user and $user =~ $USERNAME_PATT );
|
||||
my $deny_rules = option( $repo, 'deny-rules' );
|
||||
sanity($repo);
|
||||
|
||||
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;
|
||||
|
@ -88,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];
|
||||
|
@ -163,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;
|
||||
}
|
||||
|
@ -175,8 +188,18 @@ sub option {
|
|||
return $ret->{$option};
|
||||
}
|
||||
|
||||
sub sanity {
|
||||
my $repo = shift;
|
||||
|
||||
_die "invalid repo '$repo'" if not( $repo and $repo =~ $REPOPATT_PATT );
|
||||
_die "'$repo' ends with a '/'" if $repo =~ m(/$);
|
||||
_die "'$repo' contains '..'" if $repo =~ $REPONAME_PATT and $repo =~ m(\.\.);
|
||||
}
|
||||
|
||||
sub repo_missing {
|
||||
my $repo = shift;
|
||||
sanity($repo);
|
||||
|
||||
return not -d "$rc{GL_REPO_BASE}/$repo.git";
|
||||
}
|
||||
|
||||
|
@ -211,7 +234,7 @@ sub load_1 {
|
|||
trace( 3, $repo );
|
||||
|
||||
if ( repo_missing($repo) ) {
|
||||
trace( 1, "repo '$repo' missing" );
|
||||
trace( 1, "repo '$repo' missing" ) if $repo =~ $REPONAME_PATT;
|
||||
return;
|
||||
}
|
||||
_chdir("$rc{GL_REPO_BASE}/$repo.git");
|
||||
|
@ -223,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;
|
||||
|
@ -255,7 +278,7 @@ sub load_1 {
|
|||
|
||||
for my $r (@repos) {
|
||||
for my $u (@users) {
|
||||
push @rules, @{ $repos{$r}{$u} } if exists $repos{$r}{$u};
|
||||
push @rules, @{ $repos{$r}{$u} } if exists $repos{$r} and exists $repos{$r}{$u};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -285,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
|
||||
|
@ -302,12 +327,16 @@ 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} };
|
||||
}
|
||||
}
|
||||
|
||||
push @ret, @{ ext_grouplist($base) } if $type eq 'user' and $rc{GROUPLIST_PGM};
|
||||
|
||||
if ( $type eq 'user' and $repo and not repo_missing($repo) ) {
|
||||
# find the roles this user has when accessing this repo and add those
|
||||
# in as groupnames he is a member of. You need the already existing
|
||||
|
@ -315,8 +344,6 @@ sub memberships {
|
|||
push @ret, user_roles( $base, $repo, @ret );
|
||||
}
|
||||
|
||||
push @ret, @{ ext_grouplist($base) } if $type eq 'user' and $rc{GROUPLIST_PGM};
|
||||
|
||||
@ret = @{ sort_u( \@ret ) };
|
||||
trace( 3, sort @ret );
|
||||
return @ret;
|
||||
|
@ -359,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} ) {
|
||||
|
@ -391,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;
|
||||
|
@ -400,6 +428,8 @@ sub generic_name {
|
|||
|
||||
sub creator {
|
||||
my $repo = shift;
|
||||
sanity($repo);
|
||||
|
||||
return ( $ENV{GL_USER} || '' ) if repo_missing($repo);
|
||||
my $f = "$rc{GL_REPO_BASE}/$repo.git/gl-creator";
|
||||
my $creator = '';
|
||||
|
|
|
@ -63,12 +63,20 @@ sub add_to_group {
|
|||
}
|
||||
|
||||
sub set_repolist {
|
||||
@repolist = @_;
|
||||
|
||||
@repolist = ();
|
||||
# ...sanity checks
|
||||
for (@repolist) {
|
||||
for (@_) {
|
||||
if ( check_subconf_repo_disallowed( $subconf, $_ ) ) {
|
||||
(my $repo = $_) =~ s/^\@$subconf\./locally modified \@/;
|
||||
$ignored{$subconf}{$repo} = 1;
|
||||
next;
|
||||
}
|
||||
|
||||
_warn "explicit '.git' extension ignored for $_.git" if s/\.git$//;
|
||||
_die "bad reponame '$_'" if $_ !~ $REPOPATT_PATT;
|
||||
|
||||
push @repolist, $_;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,13 +111,6 @@ sub add_rule {
|
|||
|
||||
$nextseq++;
|
||||
for my $repo (@repolist) {
|
||||
if ( check_subconf_repo_disallowed( $subconf, $repo ) ) {
|
||||
my $repo = $repo;
|
||||
$repo =~ s/^\@$subconf\./locally modified \@/;
|
||||
$ignored{$subconf}{$repo} = 1;
|
||||
next;
|
||||
}
|
||||
|
||||
push @{ $repos{$repo}{$user} }, [ $nextseq, $perm, $ref ];
|
||||
}
|
||||
}
|
||||
|
@ -155,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
|
||||
|
@ -190,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} );
|
||||
|
@ -257,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};
|
||||
|
@ -284,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)] );
|
||||
|
@ -297,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";
|
||||
|
|
|
@ -5,6 +5,25 @@ package Gitolite::Easy;
|
|||
# most/all functions in this module test $ENV{GL_USER}'s rights and
|
||||
# permissions so it needs to be set.
|
||||
|
||||
# "use"-ing this module
|
||||
# ----------------------------------------------------------------------
|
||||
# Using this module from within a gitolite trigger or command is easy; you
|
||||
# just need 'use lib $ENV{GL_LIBDIR};' before the 'use Gitolite::Easy;'.
|
||||
#
|
||||
# Using it from something completely outside gitolite requires a bit more
|
||||
# work. First, run 'gitolite query-rc -a' to find the correct values for
|
||||
# GL_BINDIR and GL_LIBDIR in your installation. Then use this code in your
|
||||
# external program, using the paths you just found:
|
||||
#
|
||||
# BEGIN {
|
||||
# $ENV{GL_BINDIR} = "/full/path/to/gitolite/src";
|
||||
# $ENV{GL_LIBDIR} = "/full/path/to/gitolite/src/lib";
|
||||
# }
|
||||
# use lib $ENV{GL_LIBDIR};
|
||||
# use Gitolite::Easy;
|
||||
|
||||
# API documentation
|
||||
# ----------------------------------------------------------------------
|
||||
# documentation for each function is at the top of the function.
|
||||
# Documentation is NOT in pod format; just read the source with a nice syntax
|
||||
# coloring text editor and you'll be happy enough. (I do not like POD; please
|
||||
|
|
|
@ -58,10 +58,10 @@ $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) {
|
||||
if (-r $rc and -s $rc) {
|
||||
do $rc or die $@;
|
||||
}
|
||||
if ( defined($GL_ADMINDIR) ) {
|
||||
|
@ -91,7 +91,7 @@ do $ENV{G3T_RC} if exists $ENV{G3T_RC} and -r $ENV{G3T_RC};
|
|||
|
||||
unshift @INC, "$rc{LOCAL_CODE}/lib" if $rc{LOCAL_CODE};
|
||||
|
||||
$ENV{PATH} = "$ENV{GL_BINDIR}:$ENV{PATH}";
|
||||
$ENV{PATH} = "$ENV{GL_BINDIR}:$ENV{PATH}" unless $ENV{PATH} =~ /^$ENV{GL_BINDIR}:/;
|
||||
|
||||
{
|
||||
$rc{GL_TID} = $ENV{GL_TID} ||= $$;
|
||||
|
@ -326,6 +326,8 @@ __DATA__
|
|||
# word, not a full domain name. See documentation if in doubt
|
||||
# HOSTNAME => 'darkstar',
|
||||
UMASK => 0077,
|
||||
|
||||
# look in the "GIT-CONFIG" section in the README for what to do
|
||||
GIT_CONFIG_KEYS => '',
|
||||
|
||||
# comment out if you don't need all the extra detail in the logfile
|
||||
|
@ -423,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',
|
||||
|
|
|
@ -37,6 +37,12 @@ use warnings;
|
|||
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
# make sure the user is ready for it
|
||||
if (not $ENV{GITOLITE_TEST} or $ENV{GITOLITE_TEST} ne 'y') {
|
||||
print "Bail out! See t/README for information on how to run the tests.\n";
|
||||
exit 255;
|
||||
}
|
||||
|
||||
# required preamble for all tests
|
||||
try "
|
||||
DEF gsh = /TRACE: gsh.SOC=/
|
||||
|
|
|
@ -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,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;
|
|
@ -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() ];
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
package Gitolite::Triggers::RefexExpr;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
# track refexes passed and evaluate expressions on them
|
||||
# ----------------------------------------------------------------------
|
||||
# see instructions for use at the bottom of src/VREF/refex-expr
|
||||
|
||||
use Gitolite::Easy;
|
||||
|
||||
my %passed;
|
||||
my %rules;
|
||||
my $init_done = 0;
|
||||
|
||||
sub access_2 {
|
||||
# get out quick for repos that don't have any rules
|
||||
return if $init_done and not %rules;
|
||||
|
||||
# but we don't really know that the first time, heh!
|
||||
if (not $init_done) {
|
||||
my $repo = $_[1];
|
||||
init($repo);
|
||||
return unless %rules;
|
||||
}
|
||||
|
||||
my $refex = $_[5];
|
||||
return if $refex =~ /DENIED/;
|
||||
|
||||
$passed{$refex}++;
|
||||
|
||||
# evaluate the rules each time; it's not very expensive
|
||||
for my $k (sort keys %rules) {
|
||||
$ENV{"GL_REFEX_EXPR_" . $k} = eval_rule($rules{$k});
|
||||
}
|
||||
}
|
||||
|
||||
sub eval_rule {
|
||||
my $rule = shift;
|
||||
|
||||
my $e;
|
||||
$e = join " ", map { convert($_) } split ' ', $rule;
|
||||
|
||||
my $ret = eval $e;
|
||||
_die "eval '$e' -> '$@'" if $@;
|
||||
Gitolite::Common::trace(1, "RefexExpr", "'$rule' -> '$e' -> '$ret'");
|
||||
|
||||
return "'$rule' -> '$e'" if $ret;
|
||||
}
|
||||
|
||||
my %constant;
|
||||
%constant = map { $_ => $_ } qw(1 not and or xor + - ==);
|
||||
$constant{'-lt'} = '<';
|
||||
$constant{'-gt'} = '>';
|
||||
$constant{'-eq'} = '==';
|
||||
$constant{'-le'} = '<=';
|
||||
$constant{'-ge'} = '>=';
|
||||
$constant{'-ne'} = '!=';
|
||||
|
||||
sub convert {
|
||||
my $i = shift;
|
||||
return $i if $i =~ /^-?\d+$/;
|
||||
return $constant{$i} || $passed{$i} || $passed{"refs/heads/$i"} || 0;
|
||||
}
|
||||
|
||||
# called only once
|
||||
sub init {
|
||||
$init_done = 1;
|
||||
my $repo = shift;
|
||||
|
||||
# find all the rule expressions
|
||||
my %t = config($repo, "^gitolite-options\\.refex-expr\\.");
|
||||
my ($k, $v);
|
||||
# get rid of the cruft and store just the rule name as the key
|
||||
while ( ($k, $v) = each %t) {
|
||||
$k =~ s/^gitolite-options\.refex-expr\.//;
|
||||
$rules{$k} = $v;
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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 & ) )
|
|
@ -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
|
|
@ -0,0 +1,17 @@
|
|||
#!/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
|
||||
# just goes with the flow of setting config variables; nothing special needs
|
||||
# to be done for the description.
|
||||
|
||||
# But this only works for gitweb, not for cgit. Cgit users must therefore add
|
||||
# this line to the POST_COMPILE list in the rc file:
|
||||
# 'post-compile/update-description-file',
|
||||
|
||||
cd $GL_REPO_BASE
|
||||
gitolite list-phy-repos | gitolite git-config % gitweb.description |
|
||||
while read a b c
|
||||
do
|
||||
echo "$c" > $GL_REPO_BASE/$a.git/description
|
||||
done
|
|
@ -43,12 +43,12 @@ for my $pr (@$lpr) {
|
|||
|
||||
sub fixup_config {
|
||||
my $pr = shift;
|
||||
my $creator = creator($pr);
|
||||
|
||||
my $gc = git_config( $pr, '.', 1 );
|
||||
while ( my ( $key, $value ) = each( %{$gc} ) ) {
|
||||
next if $key =~ /^gitolite-options\./;
|
||||
if ( $value ne "" ) {
|
||||
$value =~ s/%GL_REPO/$pr/g;
|
||||
system( "git", "config", "--file", "$RB/$pr.git/config", $key, $value );
|
||||
} else {
|
||||
system( "git", "config", "--file", "$RB/$pr.git/config", "--unset-all", $key );
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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)
|
||||
|
|
|
@ -6,10 +6,12 @@ use warnings;
|
|||
use lib "src/lib";
|
||||
use Gitolite::Test;
|
||||
|
||||
my $rb = `gitolite query-rc -n GL_REPO_BASE`;
|
||||
|
||||
# initial smoke tests
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
try "plan 65";
|
||||
try "plan 71";
|
||||
|
||||
# basic push admin repo
|
||||
confreset;confadd '
|
||||
|
@ -31,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
|
||||
|
@ -75,4 +76,19 @@ try "
|
|||
glt ls-remote u5 file:///cc/1; ok; perl s/TRACE.*//g; !/\\S/
|
||||
glt ls-remote u5 file:///cc/2; !ok; /DENIED by fallthru/
|
||||
glt ls-remote u6 file:///cc/2; !ok; /DENIED by fallthru/
|
||||
|
||||
# command
|
||||
glt perms u4 -c cc/bar/baz/frob + READERS u2;
|
||||
ok; /Initialized empty .*cc/bar/baz/frob.git/
|
||||
|
||||
# path traversal
|
||||
glt ls-remote u4 file:///cc/dd/../ee
|
||||
!ok; /FATAL: 'cc/dd/\\.\\./ee' contains '\\.\\.'/
|
||||
glt ls-remote u5 file:///cc/../../../../../..$rb/gitolite-admin
|
||||
!ok; /FATAL: 'cc/../../../../../..$rb/gitolite-admin' contains '\\.\\.'/
|
||||
|
||||
glt perms u4 -c cc/bar/baz/../frob + READERS u2
|
||||
!ok; /FATAL: 'cc/bar/baz/\\.\\./frob' contains '\\.\\.'/
|
||||
|
||||
|
||||
";
|
||||
|
|
13
t/README
13
t/README
|
@ -1,8 +1,13 @@
|
|||
|
||||
============================================
|
||||
WARNING: THE TEST SUITE DELETES STUFF FIRST!
|
||||
============================================
|
||||
|
||||
Testing gitolite3 is now one command after the clone:
|
||||
Please run the tests ONLY on a userid where it's ok to LOSE DATA.
|
||||
|
||||
prove
|
||||
On such a userid, clone gitolite then run this command in the clone:
|
||||
|
||||
But because it starts by cleaning the slate, it's best to do it on a spare
|
||||
userid that you are ok to lose data on.
|
||||
GITOLITE_TEST=y prove
|
||||
|
||||
http://sitaramc.github.com/gitolite/testing.html has more details. It will
|
||||
also help you try out gitolite if you want to go beyond just the test suite.
|
||||
|
|
|
@ -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
|
||||
|
|
3
t/fork.t
3
t/fork.t
|
@ -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
|
||||
';
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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/
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue