gitolite-rugged 1.2.pre.devel

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/.gemtest +0 -0
  3. data/.gitignore +9 -0
  4. data/.travis.yml +14 -0
  5. data/Gemfile +5 -0
  6. data/Guardfile +13 -0
  7. data/LICENSE.txt +26 -0
  8. data/README.md +108 -0
  9. data/Rakefile +59 -0
  10. data/gitolite.gemspec +36 -0
  11. data/lib/gitolite/config/group.rb +62 -0
  12. data/lib/gitolite/config/repo.rb +107 -0
  13. data/lib/gitolite/config.rb +284 -0
  14. data/lib/gitolite/dirty_proxy.rb +32 -0
  15. data/lib/gitolite/gitolite_admin.rb +276 -0
  16. data/lib/gitolite/ssh_key.rb +103 -0
  17. data/lib/gitolite/version.rb +3 -0
  18. data/lib/gitolite.rb +10 -0
  19. data/spec/config_spec.rb +498 -0
  20. data/spec/dirty_proxy_spec.rb +66 -0
  21. data/spec/fixtures/configs/complicated-output.conf +72 -0
  22. data/spec/fixtures/configs/complicated.conf +311 -0
  23. data/spec/fixtures/configs/simple.conf +5 -0
  24. data/spec/fixtures/keys/bob+joe@test.zilla.com@desktop.pub +1 -0
  25. data/spec/fixtures/keys/bob-ins@zilla-site.com@desktop.pub +1 -0
  26. data/spec/fixtures/keys/bob.joe@test.zilla.com@desktop.pub +1 -0
  27. data/spec/fixtures/keys/bob.pub +1 -0
  28. data/spec/fixtures/keys/bob@desktop.pub +1 -0
  29. data/spec/fixtures/keys/bob@foo-bar.pub +1 -0
  30. data/spec/fixtures/keys/bob@zilla.com.pub +1 -0
  31. data/spec/fixtures/keys/bob@zilla.com@desktop.pub +1 -0
  32. data/spec/fixtures/keys/jakub123.pub +1 -0
  33. data/spec/fixtures/keys/jakub123@foo.net.pub +1 -0
  34. data/spec/fixtures/keys/joe-bob@god-zilla.com@desktop.pub +1 -0
  35. data/spec/fixtures/keys/joe@sch.ool.edu.pub +1 -0
  36. data/spec/fixtures/keys/joe@sch.ool.edu@desktop.pub +1 -0
  37. data/spec/gitolite_admin_spec.rb +40 -0
  38. data/spec/group_spec.rb +125 -0
  39. data/spec/repo_spec.rb +202 -0
  40. data/spec/spec_helper.rb +21 -0
  41. data/spec/ssh_key_spec.rb +355 -0
  42. metadata +280 -0
@@ -0,0 +1,498 @@
1
+ require 'spec_helper'
2
+
3
+ describe Gitolite::Config do
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')
8
+
9
+ describe "#new" do
10
+ it 'should read a simple configuration' do
11
+ c = Gitolite::Config.new(File.join(conf_dir, 'simple.conf'))
12
+ c.repos.length.should == 2
13
+ c.groups.length.should == 0
14
+ end
15
+
16
+ it 'should read a complex configuration' do
17
+ c = Gitolite::Config.new(File.join(conf_dir, 'complicated.conf'))
18
+ c.groups.length.should == 5
19
+ c.repos.length.should == 13
20
+ end
21
+
22
+ describe 'gitweb operations' do
23
+ before :all do
24
+ @config = Gitolite::Config.new(File.join(conf_dir, 'complicated.conf'))
25
+ end
26
+
27
+ it 'should correctly read gitweb options for an existing repo' do
28
+ r = @config.get_repo('gitolite')
29
+ r.owner.should == "Sitaram Chamarty"
30
+ r.description.should == "fast, secure, access control for git in a corporate environment"
31
+ end
32
+
33
+ it 'should correctly read a gitweb option with no owner for an existing repo' do
34
+ r = @config.get_repo('foo')
35
+ r.owner.should be nil
36
+ r.description.should == "Foo is a nice test repo"
37
+ end
38
+
39
+ it 'should correctly read gitweb options for a new repo' do
40
+ r = @config.get_repo('foobar')
41
+ r.owner.should == "Bob Zilla"
42
+ r.description.should == "Foobar is top secret"
43
+ end
44
+
45
+ it 'should correctly read gitweb options with no owner for a new repo' do
46
+ r = @config.get_repo('bar')
47
+ r.owner.should be nil
48
+ r.description.should == "A nice place to get drinks"
49
+ end
50
+
51
+ it 'should raise a ParseError when a description is not specified' do
52
+ t = Tempfile.new('bad_conf.conf')
53
+ t.write('gitolite "Bob Zilla"')
54
+ t.close
55
+
56
+ lambda { Gitolite::Config.new(t.path) }.should raise_error(Gitolite::Config::ParseError)
57
+
58
+ t.unlink
59
+ end
60
+
61
+ it 'should raise a ParseError when a Gitweb description is specified for a group' do
62
+ t = Tempfile.new('bad_conf.conf')
63
+ t.write('@gitolite "Bob Zilla" = "Test description"')
64
+ t.close
65
+
66
+ lambda { Gitolite::Config.new(t.path) }.should raise_error(Gitolite::Config::ParseError)
67
+
68
+ t.unlink
69
+ end
70
+ end
71
+
72
+ describe "git config settings" do
73
+ before :all do
74
+ @config = Gitolite::Config.new(File.join(conf_dir, 'complicated.conf'))
75
+ end
76
+
77
+ it 'should correctly read in git config settings' do
78
+ r = @config.get_repo(:gitolite)
79
+ r.config.length.should == 4
80
+ end
81
+ end
82
+
83
+ describe "gitolite options" do
84
+ before :all do
85
+ @config = Gitolite::Config.new(File.join(conf_dir, 'complicated.conf'))
86
+ end
87
+
88
+ it 'should correctly read in gitolite options' do
89
+ r = @config.get_repo(:foo)
90
+ r.options.length.should == 3
91
+ end
92
+
93
+ it 'should raise a ParseError when a value is not specified' do
94
+ t = Tempfile.new('bad_conf.conf')
95
+ t.write("repo foobar\n option mirror.master =")
96
+ t.close
97
+
98
+ lambda { Gitolite::Config.new(t.path) }.should raise_error(Gitolite::Config::ParseError)
99
+
100
+ t.unlink
101
+ end
102
+ end
103
+ end
104
+
105
+ describe "#init" do
106
+ it 'should create a valid, blank Gitolite::Config' do
107
+ c = Gitolite::Config.init
108
+
109
+ c.should be_an_instance_of Gitolite::Config
110
+ c.repos.should_not be nil
111
+ c.repos.length.should be 0
112
+ c.groups.should_not be nil
113
+ c.groups.length.should be 0
114
+ c.filename.should == "gitolite.conf"
115
+ end
116
+
117
+ it 'should create a valid, blank Gitolite::Config with the given filename' do
118
+ filename = "test.conf"
119
+ c = Gitolite::Config.init(filename)
120
+
121
+ c.should be_an_instance_of Gitolite::Config
122
+ c.repos.should_not be nil
123
+ c.repos.length.should be 0
124
+ c.groups.should_not be nil
125
+ c.groups.length.should be 0
126
+ c.filename.should == filename
127
+ end
128
+ end
129
+
130
+ describe "repo management" do
131
+ before :each do
132
+ @config = Gitolite::Config.new(File.join(conf_dir, 'complicated.conf'))
133
+ end
134
+
135
+ describe "#get_repo" do
136
+ it 'should fetch a repo by a string containing the name' do
137
+ @config.get_repo('gitolite').should be_an_instance_of Gitolite::Config::Repo
138
+ end
139
+
140
+ it 'should fetch a repo via a symbol representing the name' do
141
+ @config.get_repo(:gitolite).should be_an_instance_of Gitolite::Config::Repo
142
+ end
143
+
144
+ it 'should return nil for a repo that does not exist' do
145
+ @config.get_repo(:glite).should be nil
146
+ end
147
+ end
148
+
149
+ describe "#has_repo?" do
150
+ it 'should return false for a repo that does not exist' do
151
+ @config.has_repo?(:glite).should be false
152
+ end
153
+
154
+ it 'should check for the existance of a repo given a repo object' do
155
+ r = @config.repos["gitolite"]
156
+ @config.has_repo?(r).should be true
157
+ end
158
+
159
+ it 'should check for the existance of a repo given a string containing the name' do
160
+ @config.has_repo?('gitolite').should be true
161
+ end
162
+
163
+ it 'should check for the existance of a repo given a symbol representing the name' do
164
+ @config.has_repo?(:gitolite).should be true
165
+ end
166
+ end
167
+
168
+ describe "#add_repo" do
169
+ it 'should throw an ArgumentError for non-Gitolite::Config::Repo objects passed in' do
170
+ lambda{ @config.add_repo("not-a-repo") }.should raise_error(ArgumentError)
171
+ end
172
+
173
+ it 'should add a given repo to the list of repos' do
174
+ r = Gitolite::Config::Repo.new('cool_repo')
175
+ nrepos = @config.repos.size
176
+ @config.add_repo(r)
177
+
178
+ @config.repos.size.should == nrepos + 1
179
+ @config.has_repo?(:cool_repo).should be true
180
+ end
181
+
182
+ it 'should merge a given repo with an existing repo' do
183
+ #Make two new repos
184
+ repo1 = Gitolite::Config::Repo.new('cool_repo')
185
+ repo2 = Gitolite::Config::Repo.new('cool_repo')
186
+
187
+ #Add some perms to those repos
188
+ repo1.add_permission("RW+", "", "bob", "joe", "sam")
189
+ repo1.add_permission("R", "", "sue", "jen", "greg")
190
+ repo1.add_permission("-", "refs/tags/test[0-9]", "@students", "jessica")
191
+ repo1.add_permission("RW", "refs/tags/test[0-9]", "@teachers", "bill", "todd")
192
+ repo1.add_permission("R", "refs/tags/test[0-9]", "@profs")
193
+
194
+ repo2.add_permission("RW+", "", "jim", "cynthia", "arnold")
195
+ repo2.add_permission("R", "", "daniel", "mary", "ben")
196
+ repo2.add_permission("-", "refs/tags/test[0-9]", "@more_students", "stephanie")
197
+ repo2.add_permission("RW", "refs/tags/test[0-9]", "@student_teachers", "mike", "judy")
198
+ repo2.add_permission("R", "refs/tags/test[0-9]", "@leaders")
199
+
200
+ #Add the repos
201
+ @config.add_repo(repo1)
202
+ @config.add_repo(repo2)
203
+
204
+ #Make sure perms were properly merged
205
+ end
206
+
207
+ it 'should overwrite an existing repo when overwrite = true' do
208
+ #Make two new repos
209
+ repo1 = Gitolite::Config::Repo.new('cool_repo')
210
+ repo2 = Gitolite::Config::Repo.new('cool_repo')
211
+
212
+ #Add some perms to those repos
213
+ repo1.add_permission("RW+", "", "bob", "joe", "sam")
214
+ repo1.add_permission("R", "", "sue", "jen", "greg")
215
+ repo2.add_permission("RW+", "", "jim", "cynthia", "arnold")
216
+ repo2.add_permission("R", "", "daniel", "mary", "ben")
217
+
218
+ #Add the repos
219
+ @config.add_repo(repo1)
220
+ @config.add_repo(repo2, true)
221
+
222
+ #Make sure repo2 overwrote repo1
223
+ end
224
+ end
225
+
226
+ describe "#rm_repo" do
227
+ it 'should remove a repo for the Gitolite::Config::Repo object given' do
228
+ r = @config.get_repo(:gitolite)
229
+ r2 = @config.rm_repo(r)
230
+ r2.name.should == r.name
231
+ r2.permissions.length.should == r.permissions.length
232
+ r2.owner.should == r.owner
233
+ r2.description.should == r.description
234
+ end
235
+
236
+ it 'should remove a repo given a string containing the name' do
237
+ r = @config.get_repo(:gitolite)
238
+ r2 = @config.rm_repo('gitolite')
239
+ r2.name.should == r.name
240
+ r2.permissions.length.should == r.permissions.length
241
+ r2.owner.should == r.owner
242
+ r2.description.should == r.description
243
+ end
244
+
245
+ it 'should remove a repo given a symbol representing the name' do
246
+ r = @config.get_repo(:gitolite)
247
+ r2 = @config.rm_repo(:gitolite)
248
+ r2.name.should == r.name
249
+ r2.permissions.length.should == r.permissions.length
250
+ r2.owner.should == r.owner
251
+ r2.description.should == r.description
252
+ end
253
+ end
254
+ end
255
+
256
+ describe "group management" do
257
+ before :each do
258
+ @config = Gitolite::Config.new(File.join(conf_dir, 'complicated.conf'))
259
+ end
260
+
261
+ describe "#has_group?" do
262
+ it 'should find the staff group using a symbol' do
263
+ @config.has_group?(:staff).should be true
264
+ end
265
+
266
+ it 'should find the staff group using a string' do
267
+ @config.has_group?('staff').should be true
268
+ end
269
+
270
+ it 'should find the staff group using a Gitolite::Config::Group object' do
271
+ g = Gitolite::Config::Group.new("staff")
272
+ @config.has_group?(g).should be true
273
+ end
274
+ end
275
+
276
+ describe "#get_group" do
277
+ it 'should return the Gitolite::Config::Group object for the group name String' do
278
+ g = @config.get_group("staff")
279
+ g.is_a?(Gitolite::Config::Group).should be true
280
+ g.size.should == 6
281
+ end
282
+
283
+ it 'should return the Gitolite::Config::Group object for the group name Symbol' do
284
+ g = @config.get_group(:staff)
285
+ g.is_a?(Gitolite::Config::Group).should be true
286
+ g.size.should == 6
287
+ end
288
+ end
289
+
290
+ describe "#add_group" do
291
+ it 'should throw an ArgumentError for non-Gitolite::Config::Group objects passed in' do
292
+ lambda{ @config.add_group("not-a-group") }.should raise_error(ArgumentError)
293
+ end
294
+
295
+ it 'should add a given group to the groups list' do
296
+ g = Gitolite::Config::Group.new('cool_group')
297
+ ngroups = @config.groups.size
298
+ @config.add_group(g)
299
+ @config.groups.size.should be ngroups + 1
300
+ @config.has_group?(:cool_group).should be true
301
+ end
302
+
303
+ end
304
+
305
+ describe "#rm_group" do
306
+ it 'should remove a group for the Gitolite::Config::Group object given' do
307
+ g = @config.get_group(:oss_repos)
308
+ g2 = @config.rm_group(g)
309
+ g.should_not be nil
310
+ g2.name.should == g.name
311
+ end
312
+
313
+ it 'should remove a group given a string containing the name' do
314
+ g = @config.get_group(:oss_repos)
315
+ g2 = @config.rm_group('oss_repos')
316
+ g2.name.should == g.name
317
+ end
318
+
319
+ it 'should remove a group given a symbol representing the name' do
320
+ g = @config.get_group(:oss_repos)
321
+ g2 = @config.rm_group(:oss_repos)
322
+ g2.name.should == g.name
323
+ end
324
+ end
325
+
326
+ end
327
+
328
+ describe "#to_file" do
329
+ it 'should create a file at the given path with the config\'s file name' do
330
+ c = Gitolite::Config.init
331
+ file = c.to_file(output_dir)
332
+ File.file?(File.join(output_dir, c.filename)).should be true
333
+ File.unlink(file)
334
+ end
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
+
342
+ it 'should create a file at the given path when a different filename is specified' do
343
+ filename = "test.conf"
344
+ c = Gitolite::Config.init
345
+ c.filename = filename
346
+ file = c.to_file(output_dir)
347
+ File.file?(File.join(output_dir, filename)).should be true
348
+ File.unlink(file)
349
+ end
350
+
351
+ it 'should raise an ArgumentError when an invalid path is specified' do
352
+ c = Gitolite::Config.init
353
+ lambda { c.to_file('/does/not/exist') }.should raise_error(ArgumentError)
354
+ end
355
+
356
+ it 'should raise an ArgumentError when a filename is specified in the path' do
357
+ c = Gitolite::Config.init
358
+ lambda{ c.to_file('/home/test.rb') }.should raise_error(ArgumentError)
359
+ end
360
+
361
+ it 'should resolve group dependencies such that all groups are defined before they are used' do
362
+ c = Gitolite::Config.init
363
+ c.filename = "test_deptree.conf"
364
+
365
+ # Build some groups out of order
366
+ g = Gitolite::Config::Group.new "groupa"
367
+ g.add_users "bob", "@groupb"
368
+ c.add_group(g)
369
+
370
+ g = Gitolite::Config::Group.new "groupb"
371
+ g.add_users "joe", "sam", "susan", "andrew"
372
+ c.add_group(g)
373
+
374
+ g = Gitolite::Config::Group.new "groupc"
375
+ g.add_users "jane", "@groupb", "brandon"
376
+ c.add_group(g)
377
+
378
+ g = Gitolite::Config::Group.new "groupd"
379
+ g.add_users "larry", "@groupc"
380
+ c.add_group(g)
381
+
382
+ # Write the config to a file
383
+ file = c.to_file(output_dir)
384
+
385
+ # Read the conf and make sure our order is correct
386
+ f = File.read(file)
387
+ lines = f.lines.map {|l| l.strip}
388
+
389
+ # Compare the file lines. Spacing is important here since we are doing a direct comparision
390
+ lines[0].should == "@groupb = andrew joe sam susan"
391
+ lines[1].should == "@groupc = @groupb brandon jane"
392
+ lines[2].should == "@groupd = @groupc larry"
393
+ lines[3].should == "@groupa = @groupb bob"
394
+
395
+ # Cleanup
396
+ File.unlink(file)
397
+ end
398
+
399
+ it 'should raise a GroupDependencyError if there is a cyclic dependency' do
400
+ c = Gitolite::Config.init
401
+ c.filename = "test_deptree.conf"
402
+
403
+ # Build some groups out of order
404
+ g = Gitolite::Config::Group.new "groupa"
405
+ g.add_users "bob", "@groupb"
406
+ c.add_group(g)
407
+
408
+ g = Gitolite::Config::Group.new "groupb"
409
+ g.add_users "joe", "sam", "susan", "@groupc"
410
+ c.add_group(g)
411
+
412
+ g = Gitolite::Config::Group.new "groupc"
413
+ g.add_users "jane", "@groupa", "brandon"
414
+ c.add_group(g)
415
+
416
+ g = Gitolite::Config::Group.new "groupd"
417
+ g.add_users "larry", "@groupc"
418
+ c.add_group(g)
419
+
420
+ # Attempt to write the config file
421
+ lambda{ c.to_file(output_dir)}.should raise_error(Gitolite::Config::GroupDependencyError)
422
+ end
423
+
424
+ it 'should resolve group dependencies even when there are disconnected portions of the graph' do
425
+ c = Gitolite::Config.init
426
+ c.filename = "test_deptree.conf"
427
+
428
+ # Build some groups out of order
429
+ g = Gitolite::Config::Group.new "groupa"
430
+ g.add_users "bob", "timmy", "stephanie"
431
+ c.add_group(g)
432
+
433
+ g = Gitolite::Config::Group.new "groupb"
434
+ g.add_users "joe", "sam", "susan", "andrew"
435
+ c.add_group(g)
436
+
437
+ g = Gitolite::Config::Group.new "groupc"
438
+ g.add_users "jane", "earl", "brandon", "@groupa"
439
+ c.add_group(g)
440
+
441
+ g = Gitolite::Config::Group.new "groupd"
442
+ g.add_users "larry", "chris", "emily"
443
+ c.add_group(g)
444
+
445
+ # Write the config to a file
446
+ file = c.to_file(output_dir)
447
+
448
+ # Read the conf and make sure our order is correct
449
+ f = File.read(file)
450
+ lines = f.lines.map {|l| l.strip}
451
+
452
+ # Compare the file lines. Spacing is important here since we are doing a direct comparision
453
+ lines[0].should == "@groupd = chris emily larry"
454
+ lines[1].should == "@groupb = andrew joe sam susan"
455
+ lines[2].should == "@groupa = bob stephanie timmy"
456
+ lines[3].should == "@groupc = @groupa brandon earl jane"
457
+
458
+ # Cleanup
459
+ File.unlink(file)
460
+ end
461
+ end
462
+
463
+ describe "#cleanup_config_line" do
464
+ before(:each) do
465
+ @config = Gitolite::Config.init
466
+ end
467
+
468
+ it 'should remove comments' do
469
+ s = "#comment"
470
+ @config.instance_eval { cleanup_config_line(s) }.empty?.should == true
471
+ end
472
+
473
+ it 'should remove inline comments, keeping content before the comment' do
474
+ s = "blablabla #comment"
475
+ @config.instance_eval { cleanup_config_line(s) }.should == "blablabla"
476
+ end
477
+
478
+ it 'should pad = with spaces on each side' do
479
+ s = "bob=joe"
480
+ @config.instance_eval { cleanup_config_line(s) }.should == "bob = joe"
481
+ end
482
+
483
+ it 'should replace multiple space characters with a single space' do
484
+ s = "bob = joe"
485
+ @config.instance_eval { cleanup_config_line(s) }.should == "bob = joe"
486
+ end
487
+
488
+ it 'should cleanup whitespace at the beginning and end of lines' do
489
+ s = " bob = joe "
490
+ @config.instance_eval { cleanup_config_line(s) }.should == "bob = joe"
491
+ end
492
+
493
+ it 'should cleanup whitespace and comments effectively' do
494
+ s = " bob = joe #comment"
495
+ @config.instance_eval { cleanup_config_line(s) }.should == "bob = joe"
496
+ end
497
+ end
498
+ end
@@ -0,0 +1,66 @@
1
+ require 'spec_helper'
2
+
3
+ describe Gitolite::DirtyProxy do
4
+
5
+ it "should create a new instance given valid attributes" do
6
+ Gitolite::DirtyProxy.new([]).should_not be_nil
7
+ end
8
+
9
+
10
+ let(:target) { ['foo', 'bar'] }
11
+ let(:proxy) { Gitolite::DirtyProxy.new(target) }
12
+
13
+
14
+ describe 'delegating to the target object' do
15
+ it 'should act as instance of the target' do
16
+ proxy.should be_instance_of target.class
17
+ end
18
+
19
+ it 'should respond to all methods of the target' do
20
+ proxy.should respond_to(*target.methods)
21
+ end
22
+
23
+ it 'should equal the target' do
24
+ expect(proxy).to eql(target)
25
+ end
26
+ end
27
+
28
+
29
+ describe 'dirty checking methods' do
30
+ it 'should respond to clean_up!' do
31
+ proxy.respond_to?(:clean_up!).should be_true
32
+ end
33
+
34
+ it 'should respond to dirty?' do
35
+ proxy.respond_to?(:dirty?).should be_true
36
+ end
37
+
38
+ context 'when just initialized' do
39
+ it 'should be clean' do
40
+ proxy.dirty?.should be_false
41
+ end
42
+ end
43
+
44
+ shared_examples 'dirty? clean_up!' do
45
+ it 'should be dirty' do
46
+ proxy.dirty?.should be_true
47
+ end
48
+
49
+ it 'should be clean again after clean_up!' do
50
+ proxy.clean_up!
51
+ proxy.dirty?.should be_false
52
+ end
53
+ end
54
+
55
+ context 'when target object has changed directly' do
56
+ before(:each) { proxy << 'baz' }
57
+ include_examples 'dirty? clean_up!'
58
+ end
59
+
60
+ context 'when target object has changed in depth' do
61
+ before(:each) { proxy[0] << 'ooo' }
62
+ include_examples 'dirty? clean_up!'
63
+ end
64
+ end
65
+
66
+ end
@@ -0,0 +1,72 @@
1
+ @admins = admin2 sitaram
2
+ @important = QA_done master$ refs/tags/v[0-9]
3
+ @oss_repos = entrans git gitolite linux perl rakudo vkc
4
+ @interns = han indy james
5
+ @staff = @interns another-dev au.thor bob sitaram some_dev
6
+
7
+ repo @all
8
+ RW+ = @admins
9
+
10
+ repo @oss_repos
11
+ R = @all daemon
12
+
13
+ repo EXTCMD/rsync
14
+ RW NAME/ = sitaram
15
+ RW NAME/foo/ = user1
16
+ RW NAME/baz/.*/*.c = user3
17
+ R NAME/bar/ = user2
18
+
19
+ repo bar
20
+
21
+ repo foo
22
+ RW+ = lead_dev
23
+ RW = dev1 dev2 dev3 dev4
24
+ RW NAME/ = lead_dev
25
+ RW NAME/doc/ = dev1 dev2
26
+ RW NAME/src/ = dev1 dev2 dev3 dev4
27
+ option mirror.master = mars
28
+ option mirror.slaves = phobos deimos
29
+ option mirror.redirectOK = all
30
+
31
+ repo foo2
32
+ RW+ = @all-devs
33
+ - VREF/COUNT/5 = @junior-devs
34
+ - VREF/NAME/Makefile = @junior-devs
35
+
36
+ repo foobar
37
+
38
+ repo git
39
+ RW = bobzilla
40
+ RW master = junio
41
+ RW cogito$ = pasky
42
+ RW bw/ = linus
43
+ RW tmp/ = @all
44
+ RW refs/tags/v[0-9] = junio
45
+ RW+ pu = junio
46
+ - refs/tags/v[0-9] = linus pasky @others
47
+ RW refs/tags/ = junio linus pasky @others
48
+
49
+ repo gitolite
50
+ R = @staff
51
+ RW+ = sitaram
52
+ config hooks.mailinglist = gitolite-commits@example.tld
53
+ config hooks.emailprefix = "[gitolite] "
54
+ config foo.bar = ""
55
+ config foo.baz =
56
+
57
+ repo gitolite-admin
58
+ RW+ = @admins
59
+
60
+ repo linux
61
+ R = gitweb
62
+
63
+ repo perl
64
+ R = gitweb
65
+
66
+ repo testing
67
+ RW+ = @all
68
+
69
+ bar = "A nice place to get drinks"
70
+ foo = "Foo is a nice test repo"
71
+ foobar "Bob Zilla" = "Foobar is top secret"
72
+ gitolite "Sitaram Chamarty" = "fast, secure, access control for git in a corporate environment"