jbox-gitolite 1.2.0 → 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +7 -7
  3. data/Guardfile +2 -2
  4. data/README.md +3 -2
  5. data/Rakefile +26 -8
  6. data/gitolite.gemspec +3 -3
  7. data/lib/gitolite.rb +5 -2
  8. data/lib/gitolite/config.rb +181 -152
  9. data/lib/gitolite/config/group.rb +11 -0
  10. data/lib/gitolite/config/repo.rb +22 -9
  11. data/lib/gitolite/dirty_proxy.rb +3 -0
  12. data/lib/gitolite/gitolite_admin.rb +0 -2
  13. data/lib/gitolite/ssh_key.rb +52 -38
  14. data/lib/gitolite/version.rb +1 -1
  15. data/spec/config_spec.rb +18 -11
  16. data/spec/dirty_proxy_spec.rb +4 -1
  17. data/spec/fixtures/configs/complicated.conf +311 -0
  18. data/spec/fixtures/configs/simple.conf +5 -0
  19. data/spec/{keys/bob-ins@zilla-site.com@desktop.pub → fixtures/keys/bob+joe@test.zilla.com@desktop.pub} +0 -0
  20. data/spec/{keys/bob.joe@test.zilla.com@desktop.pub → fixtures/keys/bob-ins@zilla-site.com@desktop.pub} +0 -0
  21. data/spec/{keys/bob@zilla.com@desktop.pub → fixtures/keys/bob.joe@test.zilla.com@desktop.pub} +0 -0
  22. data/spec/{keys → fixtures/keys}/bob.pub +0 -0
  23. data/spec/{keys → fixtures/keys}/bob@desktop.pub +0 -0
  24. data/spec/{keys → fixtures/keys}/bob@foo-bar.pub +0 -0
  25. data/spec/{keys → fixtures/keys}/bob@zilla.com.pub +0 -0
  26. data/spec/{keys/joe-bob@god-zilla.com@desktop.pub → fixtures/keys/bob@zilla.com@desktop.pub} +0 -0
  27. data/spec/{keys → fixtures/keys}/jakub123.pub +0 -0
  28. data/spec/{keys → fixtures/keys}/jakub123@foo.net.pub +0 -0
  29. data/spec/fixtures/keys/joe-bob@god-zilla.com@desktop.pub +1 -0
  30. data/spec/{keys → fixtures/keys}/joe@sch.ool.edu.pub +0 -0
  31. data/spec/{keys → fixtures/keys}/joe@sch.ool.edu@desktop.pub +0 -0
  32. data/spec/gitolite_admin_spec.rb +6 -8
  33. data/spec/group_spec.rb +0 -1
  34. data/spec/repo_spec.rb +0 -1
  35. data/spec/spec_helper.rb +2 -2
  36. data/spec/ssh_key_spec.rb +15 -10
  37. metadata +39 -37
@@ -1,9 +1,11 @@
1
1
  module Gitolite
2
2
  class Config
3
+
3
4
  # Represents a group inside the gitolite configuration. The name and users
4
5
  # options are all encapsulated in this class. All users are stored as
5
6
  # Strings!
6
7
  class Group
8
+
7
9
  attr_accessor :name, :users
8
10
 
9
11
  PREPEND_CHAR = '@'
@@ -15,37 +17,46 @@ module Gitolite
15
17
  @users = []
16
18
  end
17
19
 
20
+
18
21
  def empty!
19
22
  @users.clear
20
23
  end
21
24
 
25
+
22
26
  def add_user(user)
23
27
  return if has_user?(user)
24
28
  @users.push(user.to_s).sort!
25
29
  end
26
30
 
31
+
27
32
  def add_users(*users)
28
33
  fixed_users = users.flatten.map{ |u| u.to_s }
29
34
  @users.concat(fixed_users).sort!.uniq!
30
35
  end
31
36
 
37
+
32
38
  def rm_user(user)
33
39
  @users.delete(user.to_s)
34
40
  end
35
41
 
42
+
36
43
  def has_user?(user)
37
44
  @users.include? user.to_s
38
45
  end
39
46
 
47
+
40
48
  def size
41
49
  @users.length
42
50
  end
43
51
 
52
+
44
53
  def to_s
45
54
  members = @users.join(' ')
46
55
  name = "#{PREPEND_CHAR}#{@name}"
47
56
  "#{name.ljust(20)}= #{members}\n"
48
57
  end
58
+
49
59
  end
60
+
50
61
  end
51
62
  end
@@ -1,28 +1,32 @@
1
1
  module Gitolite
2
2
  class Config
3
- #Represents a repo inside the gitolite configuration. The name, permissions, and git config
4
- #options are all encapsulated in this class
3
+
4
+ # Represents a repo inside the gitolite configuration. The name, permissions, and git config
5
+ # options are all encapsulated in this class
5
6
  class Repo
7
+
6
8
  ALLOWED_PERMISSIONS = /-|C|R|RW\+?(?:C?D?|D?C?)M?/
7
9
 
8
10
  attr_accessor :permissions, :name, :config, :options, :owner, :description
9
11
 
10
12
  def initialize(name)
11
- #Store the perm hash in a lambda since we have to create a new one on every deny rule
12
- #The perm hash is stored as a 2D hash, with individual permissions being the first
13
- #degree and individual refexes being the second degree. Both Hashes must respect order
13
+ # Store the perm hash in a lambda since we have to create a new one on every deny rule
14
+ # The perm hash is stored as a 2D hash, with individual permissions being the first
15
+ # degree and individual refexes being the second degree. Both Hashes must respect order
14
16
  @perm_hash_lambda = lambda { Hash.new {|k,v| k[v] = Hash.new{|k2, v2| k2[v2] = [] }} }
15
17
  @permissions = Array.new.push(@perm_hash_lambda.call)
16
18
 
17
19
  @name = name
18
- @config = {} #git config
19
- @options = {} #gitolite config
20
+ @config = {} # git config
21
+ @options = {} # gitolite config
20
22
  end
21
23
 
24
+
22
25
  def clean_permissions
23
26
  @permissions = Array.new.push(@perm_hash_lambda.call)
24
27
  end
25
28
 
29
+
26
30
  def add_permission(perm, refex = "", *users)
27
31
  if perm =~ ALLOWED_PERMISSIONS
28
32
  #Handle deny rules
@@ -37,22 +41,27 @@ module Gitolite
37
41
  end
38
42
  end
39
43
 
44
+
40
45
  def set_git_config(key, value)
41
46
  @config[key] = value
42
47
  end
43
48
 
49
+
44
50
  def unset_git_config(key)
45
51
  @config.delete(key)
46
52
  end
47
53
 
54
+
48
55
  def set_gitolite_option(key, value)
49
56
  @options[key] = value
50
57
  end
51
58
 
59
+
52
60
  def unset_gitolite_option(key)
53
61
  @options.delete(key)
54
62
  end
55
63
 
64
+
56
65
  def to_s
57
66
  repo = "repo #{@name}\n"
58
67
 
@@ -75,6 +84,7 @@ module Gitolite
75
84
  repo
76
85
  end
77
86
 
87
+
78
88
  def gitweb_description
79
89
  if @description.nil?
80
90
  nil
@@ -85,10 +95,13 @@ module Gitolite
85
95
  end
86
96
  end
87
97
 
88
- #Gets raised if a permission that isn't in the allowed
89
- #list is passed in
98
+
99
+ # Gets raised if a permission that isn't in the allowed
100
+ # list is passed in
90
101
  class InvalidPermissionError < ArgumentError
91
102
  end
103
+
92
104
  end
105
+
93
106
  end
94
107
  end
@@ -1,4 +1,5 @@
1
1
  module Gitolite
2
+
2
3
  # Very simple proxy object for checking if the proxied object was modified
3
4
  # since the last clean_up! method called. It works correctly only for objects
4
5
  # with proper hash method!
@@ -25,5 +26,7 @@ module Gitolite
25
26
  def clean_up!
26
27
  @clean_hash = @target.hash
27
28
  end
29
+
28
30
  end
31
+
29
32
  end
@@ -1,5 +1,3 @@
1
- require File.join(File.dirname(__FILE__), "dirty_proxy")
2
-
3
1
  module Gitolite
4
2
  class GitoliteAdmin
5
3
 
@@ -1,63 +1,73 @@
1
1
  module Gitolite
2
- #Models an SSH key within gitolite
3
- #provides support for multikeys
2
+
3
+ # Models an SSH key within gitolite
4
+ # provides support for multikeys
4
5
  #
5
- #Types of multi keys:
6
- # bob.pub => username: bob
7
- # bob@desktop.pub => username: bob, location: desktop
8
- # bob@email.com.pub => username: bob@email.com
9
- # bob@email.com@desktop.pub => username: bob@email.com, location: desktop
6
+ # Types of multi keys:
7
+ # bob.pub => username: bob
8
+ # bob@desktop.pub => username: bob, location: desktop
9
+ # bob@email.com.pub => username: bob@email.com
10
+ # bob@email.com@desktop.pub => username: bob@email.com, location: desktop
10
11
 
11
12
  class SSHKey
13
+
12
14
  attr_accessor :owner, :location, :type, :blob, :email
13
15
 
14
- def initialize(type, blob, email, owner = nil, location = "")
15
- @type = type
16
- @blob = blob
17
- @email = email
16
+ class << self
18
17
 
19
- @owner = owner || email
20
- @location = location
21
- end
18
+ def from_file(key)
19
+ raise "#{key} does not exist!" unless File.exists?(key)
22
20
 
23
- def self.from_file(key)
24
- raise "#{key} does not exist!" unless File.exists?(key)
21
+ # Get our owner and location
22
+ File.basename(key) =~ /^([\+\w\.-]+(?:@(?:[\w-]+\.)+\D{2,4})?)(?:@([\w-]+))?.pub$/i
23
+ owner = $1
24
+ location = $2 || ""
25
25
 
26
- #Get our owner and location
27
- File.basename(key) =~ /^([\w\.-]+(?:@(?:[\w-]+\.)+\D{2,4})?)(?:@([\w-]+))?.pub$/i
28
- owner = $1
29
- location = $2 || ""
26
+ # Use string key constructor
27
+ self.from_string(File.read(key), owner, location)
28
+ end
30
29
 
31
- # Use string key constructor
32
- self.from_string(File.read(key), owner, location)
33
- end
34
30
 
35
- # Construct a SSHKey from a string
36
- def self.from_string(key_string, owner, location = "")
37
- if owner.nil?
38
- raise ArgumentError, "owner was nil, you must specify an owner"
39
- end
31
+ # Construct a SSHKey from a string
32
+ def from_string(key_string, owner, location = "")
33
+ if owner.nil?
34
+ raise ArgumentError, "owner was nil, you must specify an owner"
35
+ end
40
36
 
41
- #Get parts of the key
42
- type, blob, email = key_string.split
37
+ # Get parts of the key
38
+ type, blob, email = key_string.split
43
39
 
44
- # We need at least a type or blob
45
- if type.nil? || blob.nil?
46
- raise ArgumentError, "'#{key_string}' is not a valid SSH key string"
47
- end
40
+ # We need at least a type or blob
41
+ if type.nil? || blob.nil?
42
+ raise ArgumentError, "'#{key_string}' is not a valid SSH key string"
43
+ end
44
+
45
+ # If the key didn't have an email, just use the owner
46
+ if email.nil?
47
+ email = owner
48
+ end
48
49
 
49
- #If the key didn't have an email, just use the owner
50
- if email.nil?
51
- email = owner
50
+ self.new(type, blob, email, owner, location)
52
51
  end
53
52
 
54
- self.new(type, blob, email, owner, location)
55
53
  end
56
54
 
55
+
56
+ def initialize(type, blob, email, owner = nil, location = "")
57
+ @type = type
58
+ @blob = blob
59
+ @email = email
60
+
61
+ @owner = owner || email
62
+ @location = location
63
+ end
64
+
65
+
57
66
  def to_s
58
67
  [@type, @blob, @email].join(' ')
59
68
  end
60
69
 
70
+
61
71
  def to_file(path)
62
72
  key_file = File.join(path, self.filename)
63
73
  File.open(key_file, "w") do |f|
@@ -67,12 +77,14 @@ module Gitolite
67
77
  key_file
68
78
  end
69
79
 
80
+
70
81
  def filename
71
82
  file = @owner
72
83
  file += "@#{@location}" unless @location.empty?
73
84
  file += ".pub"
74
85
  end
75
86
 
87
+
76
88
  def ==(key)
77
89
  @type == key.type &&
78
90
  @blob == key.blob &&
@@ -81,8 +93,10 @@ module Gitolite
81
93
  @location == key.location
82
94
  end
83
95
 
96
+
84
97
  def hash
85
98
  [@owner, @location, @type, @blob, @email].hash
86
99
  end
100
+
87
101
  end
88
102
  end
@@ -1,3 +1,3 @@
1
1
  module Gitolite
2
- VERSION = "1.2.0"
2
+ VERSION = "1.2.1"
3
3
  end
data/spec/config_spec.rb CHANGED
@@ -1,9 +1,10 @@
1
- require 'gratr'
2
- require 'gitolite/config'
3
1
  require 'spec_helper'
4
2
 
5
3
  describe Gitolite::Config do
6
- conf_dir = File.join(File.dirname(__FILE__),'configs')
4
+
5
+ conf_dir = File.join(File.dirname(__FILE__), 'fixtures', 'configs')
6
+ output_dir = '/tmp'
7
+ # output_dir = File.join(File.dirname(File.dirname(__FILE__)), 'tmp')
7
8
 
8
9
  describe "#new" do
9
10
  it 'should read a simple configuration' do
@@ -15,7 +16,7 @@ describe Gitolite::Config do
15
16
  it 'should read a complex configuration' do
16
17
  c = Gitolite::Config.new(File.join(conf_dir, 'complicated.conf'))
17
18
  c.groups.length.should == 5
18
- c.repos.length.should == 12
19
+ c.repos.length.should == 13
19
20
  end
20
21
 
21
22
  describe 'gitweb operations' do
@@ -327,17 +328,23 @@ describe Gitolite::Config do
327
328
  describe "#to_file" do
328
329
  it 'should create a file at the given path with the config\'s file name' do
329
330
  c = Gitolite::Config.init
330
- file = c.to_file('/tmp')
331
- File.file?(File.join('/tmp', c.filename)).should be true
331
+ file = c.to_file(output_dir)
332
+ File.file?(File.join(output_dir, c.filename)).should be true
332
333
  File.unlink(file)
333
334
  end
334
335
 
336
+ it 'should create a file at the given path with the config file passed' do
337
+ c = Gitolite::Config.new(File.join(conf_dir, 'complicated.conf'))
338
+ file = c.to_file(output_dir)
339
+ File.file?(File.join(output_dir, c.filename)).should be true
340
+ end
341
+
335
342
  it 'should create a file at the given path when a different filename is specified' do
336
343
  filename = "test.conf"
337
344
  c = Gitolite::Config.init
338
345
  c.filename = filename
339
- file = c.to_file('/tmp')
340
- File.file?(File.join('/tmp', filename)).should be true
346
+ file = c.to_file(output_dir)
347
+ File.file?(File.join(output_dir, filename)).should be true
341
348
  File.unlink(file)
342
349
  end
343
350
 
@@ -373,7 +380,7 @@ describe Gitolite::Config do
373
380
  c.add_group(g)
374
381
 
375
382
  # Write the config to a file
376
- file = c.to_file('/tmp')
383
+ file = c.to_file(output_dir)
377
384
 
378
385
  # Read the conf and make sure our order is correct
379
386
  f = File.read(file)
@@ -411,7 +418,7 @@ describe Gitolite::Config do
411
418
  c.add_group(g)
412
419
 
413
420
  # Attempt to write the config file
414
- lambda{ c.to_file('/tmp')}.should raise_error(Gitolite::Config::GroupDependencyError)
421
+ lambda{ c.to_file(output_dir)}.should raise_error(Gitolite::Config::GroupDependencyError)
415
422
  end
416
423
 
417
424
  it 'should resolve group dependencies even when there are disconnected portions of the graph' do
@@ -436,7 +443,7 @@ describe Gitolite::Config do
436
443
  c.add_group(g)
437
444
 
438
445
  # Write the config to a file
439
- file = c.to_file('/tmp')
446
+ file = c.to_file(output_dir)
440
447
 
441
448
  # Read the conf and make sure our order is correct
442
449
  f = File.read(file)
@@ -1,4 +1,3 @@
1
- require 'gitolite/dirty_proxy'
2
1
  require 'spec_helper'
3
2
 
4
3
  describe Gitolite::DirtyProxy do
@@ -7,9 +6,11 @@ describe Gitolite::DirtyProxy do
7
6
  Gitolite::DirtyProxy.new([]).should_not be_nil
8
7
  end
9
8
 
9
+
10
10
  let(:target) { ['foo', 'bar'] }
11
11
  let(:proxy) { Gitolite::DirtyProxy.new(target) }
12
12
 
13
+
13
14
  describe 'delegating to the target object' do
14
15
  it 'should act as instance of the target' do
15
16
  proxy.should be_instance_of target.class
@@ -24,6 +25,7 @@ describe Gitolite::DirtyProxy do
24
25
  end
25
26
  end
26
27
 
28
+
27
29
  describe 'dirty checking methods' do
28
30
  it 'should respond to clean_up!' do
29
31
  proxy.respond_to?(:clean_up!).should be_true
@@ -60,4 +62,5 @@ describe Gitolite::DirtyProxy do
60
62
  include_examples 'dirty? clean_up!'
61
63
  end
62
64
  end
65
+
63
66
  end
@@ -0,0 +1,311 @@
1
+ # example conf file for gitolite
2
+
3
+ # ----------------------------------------------------------------------------
4
+ # overall syntax:
5
+ # - everything is space-separated; no commas, semicolons, etc (except in
6
+ # the description string for gitweb)
7
+ # - comments in the normal shell-ish style; no surprises there
8
+ # - there are NO continuation lines of any kind
9
+ # - user/repo names as simple as possible; they must start with an
10
+ # alphanumeric, but after that they can also contain ".", "_", "-".
11
+ # - usernames can optionally be followed by an "@" and a domainname
12
+ # containing at least one "." (this allows you to use an email
13
+ # address as someone's username)
14
+ # - reponames can contain "/" characters (this allows you to
15
+ # put your repos in a tree-structure for convenience)
16
+
17
+ # objectives, over and above gitosis:
18
+ # - simpler syntax
19
+ # - easier gitweb/daemon control
20
+ # - specify who can push a branch/tag
21
+ # - specify who can rewind a branch/rewrite a tag
22
+
23
+ # ----------------------------------------------------------------------------
24
+
25
+ # GROUPS
26
+ # ------
27
+
28
+ # syntax:
29
+ # @groupname = [one or more names]
30
+
31
+ # groups let you club (user or group) names together for convenience
32
+
33
+ # * a group is like a #define in C except that it can *accumulate* values
34
+ # * the config file is parsed in a single-pass, so later *additions* to a
35
+ # group name cannot affect earlier *uses* of it
36
+
37
+ # The following examples should illustrate all this:
38
+
39
+ # you can have a group of people...
40
+ @staff = sitaram some_dev another-dev
41
+
42
+ # ...or a group of repos
43
+ @oss_repos = gitolite linux git perl rakudo entrans vkc
44
+
45
+ # ...or even a group of refexes
46
+ @important = master$ QA_done refs/tags/v[0-9]
47
+ # (see later for what "refex"s are; I'm only mentioning it
48
+ # here to emphasise that you can group them too)
49
+
50
+ # even sliced and diced differently
51
+ @admins = sitaram admin2
52
+ # notice that sitaram is in 2 groups (staff and admins)
53
+
54
+ # if you repeat a group name in another definition line, the
55
+ # new ones get added to the old ones (they accumulate)
56
+ @staff = au.thor
57
+ # so now "@staff" expands to all 4 names
58
+
59
+ # groups can include other groups, and the included group will
60
+ # be expanded to whatever value it currently has
61
+ @interns = indy james
62
+ @staff = bob @interns
63
+ # "@staff" expands to 7 names now
64
+ @interns = han
65
+ # "@interns" now has 3 names in it, but note that this does
66
+ # not change @staff
67
+
68
+ # REPO AND BRANCH PERMISSIONS
69
+ # ---------------------------
70
+
71
+ # syntax:
72
+ # start line:
73
+ # repo [one or more repos and/or repo groups]
74
+ # followed by one or more permissions lines:
75
+ # (C|R|RW|RW+|RWC|RW+C|RWD|RW+D|RWCD|RW+CD) [zero or more refexes] = [one or more users]
76
+
77
+ # there are 6 types of permissions: R, RW, and RW+ are simple (the "+" means
78
+ # permission to "rewind" -- force push a non-fast forward to -- a branch).
79
+ # The *standalone* C permission pertains to creating a REPO and is described
80
+ # in doc/wildcard-repositories.mkd. The C and D *suffixes* to the RW/RW+
81
+ # permissions pertain to creating or deleting a BRANCH, and are described in
82
+ # doc/3-faq-tips-etc.mkd, in the sections on "separating push and create
83
+ # rights" and "separating delete and rewind rights" respectively.
84
+
85
+ # how permissions are matched:
86
+ # - user, repo, and access (W or +) are known. For that combination, if
87
+ # any of the refexes match the refname being updated, the push succeeds.
88
+ # If none of them match, it fails
89
+
90
+ # what's a refex? a regex to match against the ref being updated (get it?)
91
+ # See next section for more on refexes
92
+
93
+ # BASIC PERMISSIONS (repo level only; apply to all branches/tags in repo)
94
+
95
+ # most important rule of all -- specify who can make changes
96
+ # to *this* file take effect
97
+ repo gitolite-admin
98
+ RW+ = @admins
99
+
100
+ # "@all" is a special, predefined, group name of all users
101
+ # (everyone who has a pubkey in keydir)
102
+ repo testing
103
+ RW+ = @all
104
+
105
+ # this repo is visible to staff but only sitaram can write to it
106
+ repo gitolite
107
+ R = @staff
108
+ RW+ = sitaram
109
+
110
+ # you can split up access rules for a repo for convenience
111
+ # (notice that @oss_repos contains gitolite also)
112
+ repo @oss_repos
113
+ R = @all
114
+
115
+ # set permissions to all repos. *Please* do see
116
+ # doc/3-faq-tips-etc.mkd for notes on this feature
117
+ repo @all
118
+ RW+ = @admins
119
+
120
+ # SPECIFYING AND USING A REFEX
121
+
122
+ # - refexes are specified in perl regex syntax
123
+ # - refexes are prefix-matched (they are internally anchored with "^"
124
+ # before being used), which means a refex like "refs/tags/v[0-9]"
125
+ # matches anything *starting with* that pattern. There may be text
126
+ # after it (example: refs/tags/v4-r3/p7), and it will still match
127
+
128
+ # ADVANCED PERMISSIONS USING REFEXES
129
+
130
+ # - if no refex appears, the rule applies to all refs in that repo
131
+ # - a refex is automatically prefixed by "refs/heads/" if it doesn't start
132
+ # with "refs/" (so tags have to be explicitly named as
133
+ # refs/tags/pattern)
134
+
135
+ # here's the example from
136
+ # Documentation/howto/update-hook-example.txt:
137
+
138
+ # refs/heads/master junio
139
+ # +refs/heads/pu junio
140
+ # refs/heads/cogito$ pasky
141
+ # refs/heads/bw/.* linus
142
+ # refs/heads/tmp/.* .*
143
+ # refs/tags/v[0-9].* junio
144
+
145
+ # and here're the equivalent gitolite refexes
146
+ repo git
147
+ RW = bobzilla
148
+ RW master = junio
149
+ RW+ pu = junio
150
+ RW cogito$ = pasky
151
+ RW bw/ = linus
152
+ RW tmp/ = @all
153
+ RW refs/tags/v[0-9] = junio
154
+
155
+ # DENY/EXCLUDE RULES
156
+
157
+ # ***IMPORTANT NOTES ABOUT "DENY" RULES***:
158
+
159
+ # - deny rules do NOT affect read access. They only apply to write access.
160
+ #
161
+ # - when using deny rules, the order of your rules starts to matter, where
162
+ # earlier it did not. The first matching rule applies, where "matching" is
163
+ # defined as either permitting the operation you're attempting (`W` or `+`),
164
+ # which results in success, or a "deny" (`-`), which results in failure.
165
+ # (As before, a fallthrough also results in failure).
166
+
167
+ # in the example above, you cannot easily say "anyone can write any tag,
168
+ # except version tags can only be written by junio". The following might look
169
+ # like it works but it doesn't:
170
+
171
+ # RW refs/tags/v[0-9] = junio
172
+ # RW refs/tags/ = junio linus pasky @others
173
+
174
+ # if you use "deny" rules, however, you can do this (a "deny" rule just uses
175
+ # "-" instead of "R" or "RW" or "RW+" in the permission field)
176
+
177
+ RW refs/tags/v[0-9] = junio
178
+ - refs/tags/v[0-9] = linus pasky @others
179
+ RW refs/tags/ = junio linus pasky @others
180
+
181
+ # FILE/DIR NAME BASED RESTRICTIONS
182
+ # --------------------------------
183
+
184
+ # Here's a hopefully self-explanatory example. Assume the project has the
185
+ # following contents at the top level: a README, a "doc/" directory, and an
186
+ # "src/" directory.
187
+
188
+ repo foo
189
+ RW+ = lead_dev # rule 1
190
+ RW = dev1 dev2 dev3 dev4 # rule 2
191
+
192
+ RW NAME/ = lead_dev # rule 3
193
+ RW NAME/doc/ = dev1 dev2 # rule 4
194
+ RW NAME/src/ = dev1 dev2 dev3 dev4 # rule 5
195
+ option mirror.master = mars
196
+ option mirror.slaves = phobos deimos
197
+ option mirror.redirectOK = all
198
+
199
+
200
+ repo foo2
201
+ RW+ = @all-devs
202
+ - VREF/COUNT/5 = @junior-devs
203
+ - VREF/NAME/Makefile = @junior-devs
204
+
205
+ # Notes
206
+
207
+ # - the "NAME/" is part of the syntax; think of it as a keyword if you like.
208
+ # The rest of it is treated as a refex to match against each file being
209
+ # touched (see "SPECIFYING AND USING A REFEX" above for details)
210
+
211
+ # - file/dir NAME-based restrictions are *in addition* to normal (branch-name
212
+ # based) restrictions; they are not a *replacement* for them. This is why
213
+ # rule #2 (or something like it, maybe with a more specific branch-name) is
214
+ # needed; without it, dev1/2/3/4 cannot push any branches.
215
+
216
+ # - if a repo has *any* NAME/ rules, then NAME-based restrictions are checked
217
+ # for *all* users. This is why rule 3 is needed, even though we don't
218
+ # actually have any NAME-based restrictions on lead_dev. Notice the pattern
219
+ # on rule 3.
220
+
221
+ # - *each* file touched by the commits being pushed is checked against those
222
+ # rules. So, lead_dev can push changes to any files, dev1/2 can push
223
+ # changes to files in "doc/" and "src/" (but not the top level README), and
224
+ # dev3/4 can only push changes to files in "src/".
225
+
226
+ # GITWEB AND DAEMON STUFF
227
+ # -----------------------
228
+
229
+ # No specific syntax for gitweb and daemon access; just make the repo readable
230
+ # ("R" access) to the special users "gitweb" and "daemon"
231
+
232
+ # make "@oss_repos" (all 7 of them!) accessible via git daemon
233
+ repo @oss_repos
234
+ R = daemon
235
+
236
+ # make the two *large* repos accessible via gitweb
237
+ repo linux perl
238
+ R = gitweb
239
+
240
+ # REPO OWNER/DESCRIPTION LINE FOR GITWEB
241
+
242
+ # syntax, one of:
243
+ # reponame = "some description string in double quotes"
244
+ # reponame "owner name" = "some description string in double quotes"
245
+
246
+ # note: setting a description also gives gitweb access; you do not have to
247
+ # give gitweb access as described above if you're specifying a description
248
+
249
+ gitolite "Sitaram Chamarty" = "fast, secure, access control for git in a corporate environment"
250
+ foo = "Foo is a nice test repo"
251
+ foobar "Bob Zilla" = "Foobar is top secret"
252
+ bar = "A nice place to get drinks"
253
+
254
+ # REPO SPECIFIC GITCONFIG
255
+ # -----------------------
256
+
257
+ # update 2010-02-06; this won't work unless the rc file has the right
258
+ # settings; please see comments around the variable $GL_GITCONFIG_KEYS in
259
+ # conf/example.gitolite.rc for details and security information.
260
+
261
+ # (Thanks to teemu dot matilainen at iki dot fi)
262
+
263
+ # this should be specified within a "repo" stanza
264
+
265
+ # syntax:
266
+ # config sectionname.keyname = [optional value_string]
267
+
268
+ # example usage: if you placed a hook in hooks/common that requires
269
+ # configuration information that is specific to each repo, you could do this:
270
+
271
+ repo gitolite
272
+ config hooks.mailinglist = gitolite-commits@example.tld
273
+ config hooks.emailprefix = "[gitolite] "
274
+ config foo.bar = ""
275
+ config foo.baz =
276
+
277
+ # This does either a plain "git config section.key value" (for the first 3
278
+ # examples above) or "git config --unset-all section.key" (for the last
279
+ # example). Other forms (--add, the value_regex, etc) are not supported.
280
+
281
+ # INCLUDE SOME OTHER FILE
282
+ # -----------------------
283
+
284
+ include "foo.conf"
285
+ subconf "bar.conf"
286
+
287
+ # this includes the contents of $GL_ADMINDIR/conf/foo.conf here
288
+
289
+ # Notes:
290
+ # - the include statement is not allowed inside delegated fragments for
291
+ # security reasons.
292
+ # - you can also use an absolute path if you like, although in the interests
293
+ # of cloning the admin-repo sanely you should avoid doing this!
294
+
295
+ # EXTERNAL COMMAND HELPERS -- RSYNC
296
+ # ---------------------------------
297
+
298
+ # If $RSYNC_BASE is non-empty, the following config entries come into play
299
+ # (otherwise they are ignored):
300
+
301
+ # a "fake" git repository to collect rsync rules. Gitolite does not
302
+ # auto-create any repo whose name starts with EXTCMD/
303
+ repo EXTCMD/rsync
304
+ # grant permissions to files/dirs within the $RSYNC_BASE tree. A leading
305
+ # NAME/ is required as a prefix; the actual path starts after that. Matching
306
+ # follows the same rules as given in "FILE/DIR NAME BASED RESTRICTIONS" above
307
+ RW NAME/ = sitaram
308
+ RW NAME/foo/ = user1
309
+ R NAME/bar/ = user2
310
+ # just to remind you that these are perl regexes, not shell globs
311
+ RW NAME/baz/.*/*.c = user3