jbox-gitolite 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,3 @@
1
+ module Gitolite
2
+ VERSION = "1.1.2"
3
+ end
@@ -0,0 +1,2 @@
1
+ #require 'gitolite'
2
+ #require 'spec_helper'
@@ -0,0 +1,491 @@
1
+ require 'gratr'
2
+ require 'gitolite/config'
3
+ require 'spec_helper'
4
+
5
+ describe Gitolite::Config do
6
+ conf_dir = File.join(File.dirname(__FILE__),'configs')
7
+
8
+ describe "#new" do
9
+ it 'should read a simple configuration' do
10
+ c = Gitolite::Config.new(File.join(conf_dir, 'simple.conf'))
11
+ c.repos.length.should == 2
12
+ c.groups.length.should == 0
13
+ end
14
+
15
+ it 'should read a complex configuration' do
16
+ c = Gitolite::Config.new(File.join(conf_dir, 'complicated.conf'))
17
+ c.groups.length.should == 5
18
+ c.repos.length.should == 12
19
+ end
20
+
21
+ describe 'gitweb operations' do
22
+ before :all do
23
+ @config = Gitolite::Config.new(File.join(conf_dir, 'complicated.conf'))
24
+ end
25
+
26
+ it 'should correctly read gitweb options for an existing repo' do
27
+ r = @config.get_repo('gitolite')
28
+ r.owner.should == "Sitaram Chamarty"
29
+ r.description.should == "fast, secure, access control for git in a corporate environment"
30
+ end
31
+
32
+ it 'should correctly read a gitweb option with no owner for an existing repo' do
33
+ r = @config.get_repo('foo')
34
+ r.owner.should be nil
35
+ r.description.should == "Foo is a nice test repo"
36
+ end
37
+
38
+ it 'should correctly read gitweb options for a new repo' do
39
+ r = @config.get_repo('foobar')
40
+ r.owner.should == "Bob Zilla"
41
+ r.description.should == "Foobar is top secret"
42
+ end
43
+
44
+ it 'should correctly read gitweb options with no owner for a new repo' do
45
+ r = @config.get_repo('bar')
46
+ r.owner.should be nil
47
+ r.description.should == "A nice place to get drinks"
48
+ end
49
+
50
+ it 'should raise a ParseError when a description is not specified' do
51
+ t = Tempfile.new('bad_conf.conf')
52
+ t.write('gitolite "Bob Zilla"')
53
+ t.close
54
+
55
+ lambda { Gitolite::Config.new(t.path) }.should raise_error(Gitolite::Config::ParseError)
56
+
57
+ t.unlink
58
+ end
59
+
60
+ it 'should raise a ParseError when a Gitweb description is specified for a group' do
61
+ t = Tempfile.new('bad_conf.conf')
62
+ t.write('@gitolite "Bob Zilla" = "Test description"')
63
+ t.close
64
+
65
+ lambda { Gitolite::Config.new(t.path) }.should raise_error(Gitolite::Config::ParseError)
66
+
67
+ t.unlink
68
+ end
69
+ end
70
+
71
+ describe "git config settings" do
72
+ before :all do
73
+ @config = Gitolite::Config.new(File.join(conf_dir, 'complicated.conf'))
74
+ end
75
+
76
+ it 'should correctly read in git config settings' do
77
+ r = @config.get_repo(:gitolite)
78
+ r.config.length.should == 4
79
+ end
80
+ end
81
+
82
+ describe "gitolite options" do
83
+ before :all do
84
+ @config = Gitolite::Config.new(File.join(conf_dir, 'complicated.conf'))
85
+ end
86
+
87
+ it 'should correctly read in gitolite options' do
88
+ r = @config.get_repo(:foo)
89
+ r.options.length.should == 3
90
+ end
91
+
92
+ it 'should raise a ParseError when a value is not specified' do
93
+ t = Tempfile.new('bad_conf.conf')
94
+ t.write("repo foobar\n option mirror.master =")
95
+ t.close
96
+
97
+ lambda { Gitolite::Config.new(t.path) }.should raise_error(Gitolite::Config::ParseError)
98
+
99
+ t.unlink
100
+ end
101
+ end
102
+ end
103
+
104
+ describe "#init" do
105
+ it 'should create a valid, blank Gitolite::Config' do
106
+ c = Gitolite::Config.init
107
+
108
+ c.should be_an_instance_of Gitolite::Config
109
+ c.repos.should_not be nil
110
+ c.repos.length.should be 0
111
+ c.groups.should_not be nil
112
+ c.groups.length.should be 0
113
+ c.filename.should == "gitolite.conf"
114
+ end
115
+
116
+ it 'should create a valid, blank Gitolite::Config with the given filename' do
117
+ filename = "test.conf"
118
+ c = Gitolite::Config.init(filename)
119
+
120
+ c.should be_an_instance_of Gitolite::Config
121
+ c.repos.should_not be nil
122
+ c.repos.length.should be 0
123
+ c.groups.should_not be nil
124
+ c.groups.length.should be 0
125
+ c.filename.should == filename
126
+ end
127
+ end
128
+
129
+ describe "repo management" do
130
+ before :each do
131
+ @config = Gitolite::Config.new(File.join(conf_dir, 'complicated.conf'))
132
+ end
133
+
134
+ describe "#get_repo" do
135
+ it 'should fetch a repo by a string containing the name' do
136
+ @config.get_repo('gitolite').should be_an_instance_of Gitolite::Config::Repo
137
+ end
138
+
139
+ it 'should fetch a repo via a symbol representing the name' do
140
+ @config.get_repo(:gitolite).should be_an_instance_of Gitolite::Config::Repo
141
+ end
142
+
143
+ it 'should return nil for a repo that does not exist' do
144
+ @config.get_repo(:glite).should be nil
145
+ end
146
+ end
147
+
148
+ describe "#has_repo?" do
149
+ it 'should return false for a repo that does not exist' do
150
+ @config.has_repo?(:glite).should be false
151
+ end
152
+
153
+ it 'should check for the existance of a repo given a repo object' do
154
+ r = @config.repos["gitolite"]
155
+ @config.has_repo?(r).should be true
156
+ end
157
+
158
+ it 'should check for the existance of a repo given a string containing the name' do
159
+ @config.has_repo?('gitolite').should be true
160
+ end
161
+
162
+ it 'should check for the existance of a repo given a symbol representing the name' do
163
+ @config.has_repo?(:gitolite).should be true
164
+ end
165
+ end
166
+
167
+ describe "#add_repo" do
168
+ it 'should throw an ArgumentError for non-Gitolite::Config::Repo objects passed in' do
169
+ lambda{ @config.add_repo("not-a-repo") }.should raise_error(ArgumentError)
170
+ end
171
+
172
+ it 'should add a given repo to the list of repos' do
173
+ r = Gitolite::Config::Repo.new('cool_repo')
174
+ nrepos = @config.repos.size
175
+ @config.add_repo(r)
176
+
177
+ @config.repos.size.should == nrepos + 1
178
+ @config.has_repo?(:cool_repo).should be true
179
+ end
180
+
181
+ it 'should merge a given repo with an existing repo' do
182
+ #Make two new repos
183
+ repo1 = Gitolite::Config::Repo.new('cool_repo')
184
+ repo2 = Gitolite::Config::Repo.new('cool_repo')
185
+
186
+ #Add some perms to those repos
187
+ repo1.add_permission("RW+", "", "bob", "joe", "sam")
188
+ repo1.add_permission("R", "", "sue", "jen", "greg")
189
+ repo1.add_permission("-", "refs/tags/test[0-9]", "@students", "jessica")
190
+ repo1.add_permission("RW", "refs/tags/test[0-9]", "@teachers", "bill", "todd")
191
+ repo1.add_permission("R", "refs/tags/test[0-9]", "@profs")
192
+
193
+ repo2.add_permission("RW+", "", "jim", "cynthia", "arnold")
194
+ repo2.add_permission("R", "", "daniel", "mary", "ben")
195
+ repo2.add_permission("-", "refs/tags/test[0-9]", "@more_students", "stephanie")
196
+ repo2.add_permission("RW", "refs/tags/test[0-9]", "@student_teachers", "mike", "judy")
197
+ repo2.add_permission("R", "refs/tags/test[0-9]", "@leaders")
198
+
199
+ #Add the repos
200
+ @config.add_repo(repo1)
201
+ @config.add_repo(repo2)
202
+
203
+ #Make sure perms were properly merged
204
+ end
205
+
206
+ it 'should overwrite an existing repo when overwrite = true' do
207
+ #Make two new repos
208
+ repo1 = Gitolite::Config::Repo.new('cool_repo')
209
+ repo2 = Gitolite::Config::Repo.new('cool_repo')
210
+
211
+ #Add some perms to those repos
212
+ repo1.add_permission("RW+", "", "bob", "joe", "sam")
213
+ repo1.add_permission("R", "", "sue", "jen", "greg")
214
+ repo2.add_permission("RW+", "", "jim", "cynthia", "arnold")
215
+ repo2.add_permission("R", "", "daniel", "mary", "ben")
216
+
217
+ #Add the repos
218
+ @config.add_repo(repo1)
219
+ @config.add_repo(repo2, true)
220
+
221
+ #Make sure repo2 overwrote repo1
222
+ end
223
+ end
224
+
225
+ describe "#rm_repo" do
226
+ it 'should remove a repo for the Gitolite::Config::Repo object given' do
227
+ r = @config.get_repo(:gitolite)
228
+ r2 = @config.rm_repo(r)
229
+ r2.name.should == r.name
230
+ r2.permissions.length.should == r.permissions.length
231
+ r2.owner.should == r.owner
232
+ r2.description.should == r.description
233
+ end
234
+
235
+ it 'should remove a repo given a string containing the name' do
236
+ r = @config.get_repo(:gitolite)
237
+ r2 = @config.rm_repo('gitolite')
238
+ r2.name.should == r.name
239
+ r2.permissions.length.should == r.permissions.length
240
+ r2.owner.should == r.owner
241
+ r2.description.should == r.description
242
+ end
243
+
244
+ it 'should remove a repo given a symbol representing the name' do
245
+ r = @config.get_repo(:gitolite)
246
+ r2 = @config.rm_repo(:gitolite)
247
+ r2.name.should == r.name
248
+ r2.permissions.length.should == r.permissions.length
249
+ r2.owner.should == r.owner
250
+ r2.description.should == r.description
251
+ end
252
+ end
253
+ end
254
+
255
+ describe "group management" do
256
+ before :each do
257
+ @config = Gitolite::Config.new(File.join(conf_dir, 'complicated.conf'))
258
+ end
259
+
260
+ describe "#has_group?" do
261
+ it 'should find the staff group using a symbol' do
262
+ @config.has_group?(:staff).should be true
263
+ end
264
+
265
+ it 'should find the staff group using a string' do
266
+ @config.has_group?('staff').should be true
267
+ end
268
+
269
+ it 'should find the staff group using a Gitolite::Config::Group object' do
270
+ g = Gitolite::Config::Group.new("staff")
271
+ @config.has_group?(g).should be true
272
+ end
273
+ end
274
+
275
+ describe "#get_group" do
276
+ it 'should return the Gitolite::Config::Group object for the group name String' do
277
+ g = @config.get_group("staff")
278
+ g.is_a?(Gitolite::Config::Group).should be true
279
+ g.size.should == 6
280
+ end
281
+
282
+ it 'should return the Gitolite::Config::Group object for the group name Symbol' do
283
+ g = @config.get_group(:staff)
284
+ g.is_a?(Gitolite::Config::Group).should be true
285
+ g.size.should == 6
286
+ end
287
+ end
288
+
289
+ describe "#add_group" do
290
+ it 'should throw an ArgumentError for non-Gitolite::Config::Group objects passed in' do
291
+ lambda{ @config.add_group("not-a-group") }.should raise_error(ArgumentError)
292
+ end
293
+
294
+ it 'should add a given group to the groups list' do
295
+ g = Gitolite::Config::Group.new('cool_group')
296
+ ngroups = @config.groups.size
297
+ @config.add_group(g)
298
+ @config.groups.size.should be ngroups + 1
299
+ @config.has_group?(:cool_group).should be true
300
+ end
301
+
302
+ end
303
+
304
+ describe "#rm_group" do
305
+ it 'should remove a group for the Gitolite::Config::Group object given' do
306
+ g = @config.get_group(:oss_repos)
307
+ g2 = @config.rm_group(g)
308
+ g.should_not be nil
309
+ g2.name.should == g.name
310
+ end
311
+
312
+ it 'should remove a group given a string containing the name' do
313
+ g = @config.get_group(:oss_repos)
314
+ g2 = @config.rm_group('oss_repos')
315
+ g2.name.should == g.name
316
+ end
317
+
318
+ it 'should remove a group given a symbol representing the name' do
319
+ g = @config.get_group(:oss_repos)
320
+ g2 = @config.rm_group(:oss_repos)
321
+ g2.name.should == g.name
322
+ end
323
+ end
324
+
325
+ end
326
+
327
+ describe "#to_file" do
328
+ it 'should create a file at the given path with the config\'s file name' do
329
+ c = Gitolite::Config.init
330
+ file = c.to_file('/tmp')
331
+ File.file?(File.join('/tmp', c.filename)).should be true
332
+ File.unlink(file)
333
+ end
334
+
335
+ it 'should create a file at the given path when a different filename is specified' do
336
+ filename = "test.conf"
337
+ c = Gitolite::Config.init
338
+ c.filename = filename
339
+ file = c.to_file('/tmp')
340
+ File.file?(File.join('/tmp', filename)).should be true
341
+ File.unlink(file)
342
+ end
343
+
344
+ it 'should raise an ArgumentError when an invalid path is specified' do
345
+ c = Gitolite::Config.init
346
+ lambda { c.to_file('/does/not/exist') }.should raise_error(ArgumentError)
347
+ end
348
+
349
+ it 'should raise an ArgumentError when a filename is specified in the path' do
350
+ c = Gitolite::Config.init
351
+ lambda{ c.to_file('/home/test.rb') }.should raise_error(ArgumentError)
352
+ end
353
+
354
+ it 'should resolve group dependencies such that all groups are defined before they are used' do
355
+ c = Gitolite::Config.init
356
+ c.filename = "test_deptree.conf"
357
+
358
+ # Build some groups out of order
359
+ g = Gitolite::Config::Group.new "groupa"
360
+ g.add_users "bob", "@groupb"
361
+ c.add_group(g)
362
+
363
+ g = Gitolite::Config::Group.new "groupb"
364
+ g.add_users "joe", "sam", "susan", "andrew"
365
+ c.add_group(g)
366
+
367
+ g = Gitolite::Config::Group.new "groupc"
368
+ g.add_users "jane", "@groupb", "brandon"
369
+ c.add_group(g)
370
+
371
+ g = Gitolite::Config::Group.new "groupd"
372
+ g.add_users "larry", "@groupc"
373
+ c.add_group(g)
374
+
375
+ # Write the config to a file
376
+ file = c.to_file('/tmp')
377
+
378
+ # Read the conf and make sure our order is correct
379
+ f = File.read(file)
380
+ lines = f.lines.map {|l| l.strip}
381
+
382
+ # Compare the file lines. Spacing is important here since we are doing a direct comparision
383
+ lines[0].should == "@groupb = andrew joe sam susan"
384
+ lines[1].should == "@groupc = @groupb brandon jane"
385
+ lines[2].should == "@groupd = @groupc larry"
386
+ lines[3].should == "@groupa = @groupb bob"
387
+
388
+ # Cleanup
389
+ File.unlink(file)
390
+ end
391
+
392
+ it 'should raise a GroupDependencyError if there is a cyclic dependency' do
393
+ c = Gitolite::Config.init
394
+ c.filename = "test_deptree.conf"
395
+
396
+ # Build some groups out of order
397
+ g = Gitolite::Config::Group.new "groupa"
398
+ g.add_users "bob", "@groupb"
399
+ c.add_group(g)
400
+
401
+ g = Gitolite::Config::Group.new "groupb"
402
+ g.add_users "joe", "sam", "susan", "@groupc"
403
+ c.add_group(g)
404
+
405
+ g = Gitolite::Config::Group.new "groupc"
406
+ g.add_users "jane", "@groupa", "brandon"
407
+ c.add_group(g)
408
+
409
+ g = Gitolite::Config::Group.new "groupd"
410
+ g.add_users "larry", "@groupc"
411
+ c.add_group(g)
412
+
413
+ # Attempt to write the config file
414
+ lambda{ c.to_file('/tmp')}.should raise_error(Gitolite::Config::GroupDependencyError)
415
+ end
416
+
417
+ it 'should resolve group dependencies even when there are disconnected portions of the graph' do
418
+ c = Gitolite::Config.init
419
+ c.filename = "test_deptree.conf"
420
+
421
+ # Build some groups out of order
422
+ g = Gitolite::Config::Group.new "groupa"
423
+ g.add_users "bob", "timmy", "stephanie"
424
+ c.add_group(g)
425
+
426
+ g = Gitolite::Config::Group.new "groupb"
427
+ g.add_users "joe", "sam", "susan", "andrew"
428
+ c.add_group(g)
429
+
430
+ g = Gitolite::Config::Group.new "groupc"
431
+ g.add_users "jane", "earl", "brandon", "@groupa"
432
+ c.add_group(g)
433
+
434
+ g = Gitolite::Config::Group.new "groupd"
435
+ g.add_users "larry", "chris", "emily"
436
+ c.add_group(g)
437
+
438
+ # Write the config to a file
439
+ file = c.to_file('/tmp')
440
+
441
+ # Read the conf and make sure our order is correct
442
+ f = File.read(file)
443
+ lines = f.lines.map {|l| l.strip}
444
+
445
+ # Compare the file lines. Spacing is important here since we are doing a direct comparision
446
+ lines[0].should == "@groupd = chris emily larry"
447
+ lines[1].should == "@groupb = andrew joe sam susan"
448
+ lines[2].should == "@groupa = bob stephanie timmy"
449
+ lines[3].should == "@groupc = @groupa brandon earl jane"
450
+
451
+ # Cleanup
452
+ File.unlink(file)
453
+ end
454
+ end
455
+
456
+ describe "#cleanup_config_line" do
457
+ before(:each) do
458
+ @config = Gitolite::Config.init
459
+ end
460
+
461
+ it 'should remove comments' do
462
+ s = "#comment"
463
+ @config.instance_eval { cleanup_config_line(s) }.empty?.should == true
464
+ end
465
+
466
+ it 'should remove inline comments, keeping content before the comment' do
467
+ s = "blablabla #comment"
468
+ @config.instance_eval { cleanup_config_line(s) }.should == "blablabla"
469
+ end
470
+
471
+ it 'should pad = with spaces on each side' do
472
+ s = "bob=joe"
473
+ @config.instance_eval { cleanup_config_line(s) }.should == "bob = joe"
474
+ end
475
+
476
+ it 'should replace multiple space characters with a single space' do
477
+ s = "bob = joe"
478
+ @config.instance_eval { cleanup_config_line(s) }.should == "bob = joe"
479
+ end
480
+
481
+ it 'should cleanup whitespace at the beginning and end of lines' do
482
+ s = " bob = joe "
483
+ @config.instance_eval { cleanup_config_line(s) }.should == "bob = joe"
484
+ end
485
+
486
+ it 'should cleanup whitespace and comments effectively' do
487
+ s = " bob = joe #comment"
488
+ @config.instance_eval { cleanup_config_line(s) }.should == "bob = joe"
489
+ end
490
+ end
491
+ end