jbox-gitolite 1.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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