realityforge-buildr 1.5.9

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.
Files changed (85) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +5 -0
  3. data/LICENSE +176 -0
  4. data/NOTICE +26 -0
  5. data/README.md +3 -0
  6. data/Rakefile +50 -0
  7. data/addon/buildr/checkstyle-report.xsl +104 -0
  8. data/addon/buildr/checkstyle.rb +254 -0
  9. data/addon/buildr/git_auto_version.rb +36 -0
  10. data/addon/buildr/gpg.rb +90 -0
  11. data/addon/buildr/gwt.rb +413 -0
  12. data/addon/buildr/jacoco.rb +161 -0
  13. data/addon/buildr/pmd.rb +185 -0
  14. data/addon/buildr/single_intermediate_layout.rb +71 -0
  15. data/addon/buildr/spotbugs.rb +265 -0
  16. data/addon/buildr/top_level_generate_dir.rb +37 -0
  17. data/addon/buildr/wsgen.rb +192 -0
  18. data/bin/buildr +20 -0
  19. data/buildr.gemspec +61 -0
  20. data/lib/buildr.rb +86 -0
  21. data/lib/buildr/core/application.rb +705 -0
  22. data/lib/buildr/core/assets.rb +96 -0
  23. data/lib/buildr/core/build.rb +587 -0
  24. data/lib/buildr/core/common.rb +167 -0
  25. data/lib/buildr/core/compile.rb +599 -0
  26. data/lib/buildr/core/console.rb +124 -0
  27. data/lib/buildr/core/doc.rb +275 -0
  28. data/lib/buildr/core/environment.rb +128 -0
  29. data/lib/buildr/core/filter.rb +405 -0
  30. data/lib/buildr/core/help.rb +114 -0
  31. data/lib/buildr/core/progressbar.rb +161 -0
  32. data/lib/buildr/core/project.rb +994 -0
  33. data/lib/buildr/core/test.rb +776 -0
  34. data/lib/buildr/core/transports.rb +456 -0
  35. data/lib/buildr/core/util.rb +77 -0
  36. data/lib/buildr/ide/idea.rb +1664 -0
  37. data/lib/buildr/java/commands.rb +230 -0
  38. data/lib/buildr/java/compiler.rb +85 -0
  39. data/lib/buildr/java/custom_pom.rb +300 -0
  40. data/lib/buildr/java/doc.rb +62 -0
  41. data/lib/buildr/java/packaging.rb +393 -0
  42. data/lib/buildr/java/pom.rb +191 -0
  43. data/lib/buildr/java/test_result.rb +54 -0
  44. data/lib/buildr/java/tests.rb +111 -0
  45. data/lib/buildr/packaging/archive.rb +586 -0
  46. data/lib/buildr/packaging/artifact.rb +1113 -0
  47. data/lib/buildr/packaging/artifact_namespace.rb +1010 -0
  48. data/lib/buildr/packaging/artifact_search.rb +138 -0
  49. data/lib/buildr/packaging/package.rb +237 -0
  50. data/lib/buildr/packaging/version_requirement.rb +189 -0
  51. data/lib/buildr/packaging/zip.rb +189 -0
  52. data/lib/buildr/packaging/ziptask.rb +387 -0
  53. data/lib/buildr/version.rb +18 -0
  54. data/rakelib/release.rake +99 -0
  55. data/spec/addon/checkstyle_spec.rb +58 -0
  56. data/spec/core/application_spec.rb +576 -0
  57. data/spec/core/build_spec.rb +922 -0
  58. data/spec/core/common_spec.rb +670 -0
  59. data/spec/core/compile_spec.rb +656 -0
  60. data/spec/core/console_spec.rb +65 -0
  61. data/spec/core/doc_spec.rb +194 -0
  62. data/spec/core/extension_spec.rb +200 -0
  63. data/spec/core/project_spec.rb +736 -0
  64. data/spec/core/test_spec.rb +1131 -0
  65. data/spec/core/transport_spec.rb +452 -0
  66. data/spec/core/util_spec.rb +154 -0
  67. data/spec/ide/idea_spec.rb +1952 -0
  68. data/spec/java/commands_spec.rb +79 -0
  69. data/spec/java/compiler_spec.rb +274 -0
  70. data/spec/java/custom_pom_spec.rb +165 -0
  71. data/spec/java/doc_spec.rb +55 -0
  72. data/spec/java/packaging_spec.rb +786 -0
  73. data/spec/java/pom_spec.rb +162 -0
  74. data/spec/java/test_coverage_helper.rb +257 -0
  75. data/spec/java/tests_spec.rb +224 -0
  76. data/spec/packaging/archive_spec.rb +686 -0
  77. data/spec/packaging/artifact_namespace_spec.rb +757 -0
  78. data/spec/packaging/artifact_spec.rb +1351 -0
  79. data/spec/packaging/packaging_helper.rb +63 -0
  80. data/spec/packaging/packaging_spec.rb +690 -0
  81. data/spec/sandbox.rb +166 -0
  82. data/spec/spec_helpers.rb +420 -0
  83. data/spec/version_requirement_spec.rb +145 -0
  84. data/spec/xpath_matchers.rb +123 -0
  85. metadata +295 -0
@@ -0,0 +1,922 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with this
3
+ # work for additional information regarding copyright ownership. The ASF
4
+ # licenses this file to you under the Apache License, Version 2.0 (the
5
+ # "License"); you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ # License for the specific language governing permissions and limitations under
14
+ # the License.
15
+
16
+
17
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helpers'))
18
+
19
+ RSpec.shared_examples 'local task' do
20
+ it "should execute task for project in current directory" do
21
+ define 'foobar'
22
+ lambda { @task.invoke }.should run_task("foobar:#{@task.name}")
23
+ end
24
+
25
+ it "should not execute task for projects in other directory" do
26
+ define 'foobar', :base_dir=>'elsewhere'
27
+ lambda { task('build').invoke }.should_not run_task('foobar:build')
28
+ end
29
+ end
30
+
31
+
32
+ describe 'build task' do
33
+ it_should_behave_like 'local task'
34
+ before(:each) { @task = task('build') }
35
+ end
36
+
37
+ describe 'clean task' do
38
+ it_should_behave_like 'local task'
39
+ before(:each) { @task = task('clean') }
40
+ end
41
+
42
+ describe 'package task' do
43
+ it_should_behave_like 'local task'
44
+ before(:each) { @task = task('package') }
45
+
46
+ it 'should execute build task as prerequisite' do
47
+ lambda { @task.invoke }.should run_task('build')
48
+ end
49
+ end
50
+
51
+ describe 'install task' do
52
+ it_should_behave_like 'local task'
53
+ before(:each) { @task = task('install') }
54
+
55
+ it 'should execute package task as prerequisite' do
56
+ lambda { @task.invoke }.should run_task('package')
57
+ end
58
+ end
59
+
60
+ describe 'uninstall task' do
61
+ it_should_behave_like 'local task'
62
+ before(:each) { @task = task('uninstall') }
63
+ end
64
+
65
+ describe 'upload task' do
66
+ it_should_behave_like 'local task'
67
+ before(:each) { @task = task('upload') }
68
+
69
+ it 'should execute package task as prerequisite' do
70
+ lambda { @task.invoke }.should run_task('package')
71
+ end
72
+ end
73
+
74
+
75
+ describe Project, '#build' do
76
+ it 'should return the project\'s build task' do
77
+ define('foo').build.should eql(task('foo:build'))
78
+ end
79
+
80
+ it 'should enhance the project\'s build task' do
81
+ task 'prereq'
82
+ task 'action'
83
+ define 'foo' do
84
+ build 'prereq' do
85
+ task('action').invoke
86
+ end
87
+ end
88
+ lambda { project('foo').build.invoke }.should run_tasks('prereq', 'action')
89
+ end
90
+
91
+ it 'should execute build task for sub-project' do
92
+ define 'foo' do
93
+ define 'bar'
94
+ end
95
+ lambda { task('foo:build').invoke }.should run_task('foo:bar:build')
96
+ end
97
+
98
+ it 'should not execute build task of other projects' do
99
+ define 'foo'
100
+ define 'bar'
101
+ lambda { task('foo:build').invoke }.should_not run_task('bar:build')
102
+ end
103
+ end
104
+
105
+
106
+ describe Project, '#clean' do
107
+ it 'should return the project\'s clean task' do
108
+ define('foo').clean.should eql(task('foo:clean'))
109
+ end
110
+
111
+ it 'should enhance the project\'s clean task' do
112
+ task 'prereq'
113
+ task 'action'
114
+ define 'foo' do
115
+ clean 'prereq' do
116
+ task('action').invoke
117
+ end
118
+ end
119
+ lambda { project('foo').clean.invoke }.should run_tasks('prereq', 'action')
120
+ end
121
+
122
+ it 'should remove target directory' do
123
+ define 'foo' do
124
+ self.layout[:target] = 'targeted'
125
+ end
126
+ mkpath 'targeted'
127
+ lambda { project('foo').clean.invoke }.should change { File.exist?('targeted') }.from(true).to(false)
128
+ end
129
+
130
+ it 'should remove reports directory' do
131
+ define 'foo' do
132
+ self.layout[:reports] = 'reported'
133
+ end
134
+ mkpath 'reported'
135
+ lambda { project('foo').clean.invoke }.should change { File.exist?('reported') }.from(true).to(false)
136
+ end
137
+
138
+ it 'should execute clean task for sub-project' do
139
+ define 'foo' do
140
+ define 'bar'
141
+ end
142
+ lambda { task('foo:clean').invoke }.should run_task('foo:bar:clean')
143
+ end
144
+
145
+ it 'should not execute clean task of other projects' do
146
+ define 'foo'
147
+ define 'bar'
148
+ lambda { task('foo:clean').invoke }.should_not run_task('bar:clean')
149
+ end
150
+ end
151
+
152
+ describe Hg do
153
+ describe '#current_branch' do
154
+ it 'should return the correct branch' do
155
+ Hg.should_receive(:hg).with('branch').and_return("default\n")
156
+ Hg.send(:current_branch).should == 'default'
157
+ end
158
+ end
159
+
160
+ describe '#uncommitted_files' do
161
+ it 'should return an array of modified files' do
162
+ Hg.should_receive(:`).with('hg status').and_return <<-EOF
163
+ M abc.txt
164
+ M xyz.txt
165
+ R hello
166
+ R removed
167
+ ! conflict
168
+ A README
169
+ ? ignore.txt
170
+ EOF
171
+ Hg.uncommitted_files.should include('abc.txt', 'xyz.txt', 'hello', 'README', 'conflict', 'ignore.txt')
172
+ end
173
+ end
174
+
175
+ describe '#uncommitted_files' do
176
+ it 'should return an empty array on a clean repository' do
177
+ Hg.should_receive(:`).with('hg status').and_return "\n"
178
+ Hg.uncommitted_files.should be_empty
179
+ end
180
+ end
181
+
182
+ describe '#remote' do
183
+ it 'should return the aliases of the default remote repositories' do
184
+ Hg.should_receive(:hg).with('paths').and_return <<-EOF
185
+ default = https://hg.apache.org/repo/my-repo
186
+ EOF
187
+ Hg.send(:remote).should include('https://hg.apache.org/repo/my-repo')
188
+ end
189
+
190
+ it 'should return the aliases of the default push remote repositories' do
191
+ Hg.should_receive(:hg).with('paths').and_return <<-EOF
192
+ default-push = https://hg.apache.org/repo/my-repo
193
+ EOF
194
+ Hg.send(:remote).should include('https://hg.apache.org/repo/my-repo')
195
+ end
196
+
197
+ it 'should return empty array when no remote repositories found' do
198
+ Hg.should_receive(:hg).with('paths').and_return "\n"
199
+ Hg.send(:remote).should be_empty
200
+ end
201
+
202
+ it 'should return empty array when no default-push remote repository found' do
203
+ Hg.should_receive(:hg).with('paths').and_return <<-EOF
204
+ blah = https://bitbucket.org/sample-repo
205
+ EOF
206
+ Hg.send(:remote).should be_empty
207
+ end
208
+ end
209
+ end # end of Hg
210
+
211
+
212
+ describe Git do
213
+ describe '#uncommitted_files' do
214
+ it 'should return an empty array on a clean repository' do
215
+ Git.should_receive(:`).with('git status').and_return <<-EOF
216
+ # On branch master
217
+ nothing to commit (working directory clean)
218
+ EOF
219
+ Git.uncommitted_files.should be_empty
220
+ end
221
+
222
+ it 'should reject a dirty repository, Git 1.4.2 or former' do
223
+ Git.should_receive(:`).with('git status').and_return <<-EOF
224
+ # On branch master
225
+ #
226
+ # Changed but not updated:
227
+ # (use "git add <file>..." to update what will be committed)
228
+ # (use "git checkout -- <file>..." to discard changes in working directory)
229
+ #
230
+ # modified: lib/buildr.rb
231
+ # modified: spec/buildr_spec.rb
232
+ #
233
+ # Untracked files:
234
+ # (use "git add <file>..." to include in what will be committed)
235
+ #
236
+ # error.log
237
+ EOF
238
+ Git.uncommitted_files.should include('lib/buildr.rb', 'error.log')
239
+ end
240
+
241
+ it 'should reject a dirty repository, Git 1.4.3 or higher' do
242
+ Git.should_receive(:`).with('git status').and_return <<-EOF
243
+ # On branch master
244
+ # Changed but not updated:
245
+ # (use "git add <file>..." to update what will be committed)
246
+ #
247
+ #\tmodified: lib/buildr.rb
248
+ #\tmodified: spec/buildr_spec.rb
249
+ #
250
+ # Untracked files:
251
+ # (use "git add <file>..." to include in what will be committed)
252
+ #
253
+ #\terror.log
254
+ no changes added to commit (use "git add" and/or "git commit -a")
255
+ EOF
256
+ Git.uncommitted_files.should include('lib/buildr.rb', 'error.log')
257
+ end
258
+ end
259
+
260
+ describe '#remote' do
261
+ it 'should return the name of the corresponding remote' do
262
+ Git.should_receive(:git).with('config', '--get', 'branch.master.remote').and_return "origin\n"
263
+ Git.should_receive(:git).with('remote').and_return "upstream\norigin\n"
264
+ Git.send(:remote, 'master').should == 'origin'
265
+ end
266
+
267
+ it 'should return nil if no remote for the given branch' do
268
+ Git.should_receive(:git).with('config', '--get', 'branch.master.remote').and_return "\n"
269
+ Git.should_not_receive(:git).with('remote')
270
+ Git.send(:remote, 'master').should be_nil
271
+ end
272
+ end
273
+
274
+ describe '#current_branch' do
275
+ it 'should return the current branch' do
276
+ Git.should_receive(:git).with('branch').and_return(" master\n* a-clever-idea\n ze-great-idea")
277
+ Git.send(:current_branch).should == 'a-clever-idea'
278
+ end
279
+ end
280
+
281
+ end # of Git
282
+
283
+
284
+ describe Svn do
285
+ describe '#tag' do
286
+ it 'should remove any existing tag with the same name' do
287
+ Svn.stub(:repo_url).and_return('http://my.repo.org/foo/trunk')
288
+ Svn.stub(:copy)
289
+ Svn.should_receive(:remove).with('http://my.repo.org/foo/tags/1.0.0', 'Removing old copy')
290
+
291
+ Svn.tag '1.0.0'
292
+ end
293
+
294
+ it 'should do an svn copy with the release version' do
295
+ Svn.stub(:repo_url).and_return('http://my.repo.org/foo/trunk')
296
+ Svn.stub(:remove)
297
+ Svn.should_receive(:copy).with(Dir.pwd, 'http://my.repo.org/foo/tags/1.0.0', 'Release 1.0.0')
298
+
299
+ Svn.tag '1.0.0'
300
+ end
301
+ end
302
+
303
+ # Reference: http://svnbook.red-bean.com/en/1.4/svn.reposadmin.planning.html#svn.reposadmin.projects.chooselayout
304
+ describe '#tag_url' do
305
+ it 'should accept to tag foo/trunk' do
306
+ Svn.tag_url('http://my.repo.org/foo/trunk', '1.0.0').should == 'http://my.repo.org/foo/tags/1.0.0'
307
+ end
308
+
309
+ it 'should accept to tag foo/branches/1.0' do
310
+ Svn.tag_url('http://my.repo.org/foo/branches/1.0', '1.0.1').should == 'http://my.repo.org/foo/tags/1.0.1'
311
+ end
312
+
313
+ it 'should accept to tag trunk/foo' do
314
+ Svn.tag_url('http://my.repo.org/trunk/foo', '1.0.0').should == 'http://my.repo.org/tags/foo/1.0.0'
315
+ end
316
+
317
+ it 'should accept to tag branches/foo/1.0' do
318
+ Svn.tag_url('http://my.repo.org/branches/foo/1.0', '1.0.0').should == 'http://my.repo.org/tags/foo/1.0.0'
319
+ end
320
+
321
+ describe '#repo_url' do
322
+ it 'should extract the SVN URL from svn info' do
323
+ Svn.should_receive(:svn).and_return <<-XML
324
+ <?xml version="1.0"?>
325
+ <info>
326
+ <entry
327
+ kind="dir"
328
+ path="."
329
+ revision="724987">
330
+ <url>http://my.repo.org/foo/trunk</url>
331
+ <repository>
332
+ <root>http://my.repo.org</root>
333
+ <uuid>13f79535-47bb-0310-9956-ffa450edef68</uuid>
334
+ </repository>
335
+ <wc-info>
336
+ <schedule>normal</schedule>
337
+ <depth>infinity</depth>
338
+ </wc-info>
339
+ <commit
340
+ revision="724955">
341
+ <author>boisvert</author>
342
+ <date>2008-12-10T01:53:51.240936Z</date>
343
+ </commit>
344
+ </entry>
345
+ </info>
346
+ XML
347
+ Svn.repo_url.should == 'http://my.repo.org/foo/trunk'
348
+ end
349
+ end
350
+
351
+ end
352
+
353
+ end # of Buildr::Svn
354
+
355
+
356
+ describe Release do
357
+ describe 'find' do
358
+ it 'should return HgRelease if project uses Hg' do
359
+ write '.hg/requires'
360
+ Release.find.should be_instance_of(HgRelease)
361
+ end
362
+
363
+ it 'should return GitRelease if project uses Git' do
364
+ write '.git/config'
365
+ Release.find.should be_instance_of(GitRelease)
366
+ end
367
+
368
+ it 'should return SvnRelease if project uses SVN' do
369
+ write '.svn/xml'
370
+ Release.find.should be_instance_of(SvnRelease)
371
+ end
372
+
373
+ # TravisCI seems to place the tmp directory
374
+ # sub-ordinate to git repository so this will not work
375
+ unless ENV['TRAVIS_BUILD_ID']
376
+ it 'should return nil if no known release process' do
377
+ Dir.chdir(Dir.tmpdir) do
378
+ Release.find.should be_nil
379
+ end
380
+ end
381
+ end
382
+
383
+ after :each do
384
+ Release.instance_exec { @release = nil }
385
+ end
386
+ end
387
+ end
388
+
389
+
390
+ RSpec.shared_examples 'a release process' do
391
+
392
+ describe '#make' do
393
+ before do
394
+ write 'buildfile', "VERSION_NUMBER = '1.0.0-SNAPSHOT'"
395
+ # Prevent a real call to a spawned buildr process.
396
+ @release.stub(:buildr)
397
+ @release.stub(:check)
398
+ @release.should_receive(:sh).with('buildr', '--buildfile', File.expand_path('buildfile.next'),
399
+ '--environment', 'development', 'clean', 'upload', 'DEBUG=no')
400
+ end
401
+
402
+ it 'should tag a release with the release version' do
403
+ @release.stub(:update_version_to_next)
404
+ @release.should_receive(:tag_release).with('1.0.0')
405
+ @release.make
406
+ end
407
+
408
+ it 'should not alter the buildfile before tagging' do
409
+ @release.stub(:update_version_to_next)
410
+ @release.should_receive(:tag_release).with('1.0.0')
411
+ @release.make
412
+ file('buildfile').should contain('VERSION_NUMBER = "1.0.0"')
413
+ end
414
+
415
+ it 'should update the buildfile with the next version number' do
416
+ @release.stub(:tag_release)
417
+ @release.make
418
+ file('buildfile').should contain('VERSION_NUMBER = "1.0.1-SNAPSHOT"')
419
+ end
420
+
421
+ it 'should keep leading zeros in the next version number' do
422
+ write 'buildfile', "VERSION_NUMBER = '1.0.001-SNAPSHOT'"
423
+ @release.stub(:tag_release)
424
+ @release.make
425
+ file('buildfile').should contain('VERSION_NUMBER = "1.0.002-SNAPSHOT"')
426
+ end
427
+
428
+ it 'should commit the updated buildfile' do
429
+ @release.stub(:tag_release)
430
+ @release.make
431
+ file('buildfile').should contain('VERSION_NUMBER = "1.0.1-SNAPSHOT"')
432
+ end
433
+
434
+ it 'should not consider "-rc" as "-SNAPSHOT"' do
435
+ write 'buildfile', "VERSION_NUMBER = '1.0.0-rc1'"
436
+ @release.stub(:tag_release)
437
+ @release.make
438
+ file('buildfile').should contain('VERSION_NUMBER = "1.0.0-rc1"')
439
+ end
440
+
441
+ it 'should only commit the updated buildfile if the version changed' do
442
+ write 'buildfile', "VERSION_NUMBER = '1.0.0-rc1'"
443
+ @release.should_not_receive(:update_version_to_next)
444
+ @release.stub(:tag_release)
445
+ @release.make
446
+ end
447
+ end
448
+
449
+ describe '#resolve_next_version' do
450
+
451
+ it 'should increment the version number if SNAPSHOT' do
452
+ @release.send(:resolve_next_version, "1.0.0-SNAPSHOT").should == '1.0.1-SNAPSHOT'
453
+ end
454
+
455
+ it 'should NOT increment the version number if no SNAPSHOT' do
456
+ @release.send(:resolve_next_version, "1.0.0").should == '1.0.0'
457
+ end
458
+
459
+ it 'should return the version specified by NEXT_VERSION env var' do
460
+ ENV['NEXT_VERSION'] = "version_from_env"
461
+ @release.send(:resolve_next_version, "1.0.0").should == 'version_from_env'
462
+ end
463
+
464
+ it 'should return the version specified by next_version' do
465
+ Release.next_version = "ze_next_version"
466
+ @release.send(:resolve_next_version, "1.0.0").should == 'ze_next_version'
467
+ end
468
+
469
+ it 'should return the version specified by next_version if next_version is a proc' do
470
+ Release.next_version = lambda {|version| "#{version}++"}
471
+ @release.send(:resolve_next_version, "1.0.0").should == '1.0.0++'
472
+ end
473
+
474
+ it "should return the version specified by 'NEXT_VERSION' env var even if next_version is non nil" do
475
+ ENV['NEXT_VERSION'] = "ze_version_from_env"
476
+ Release.next_version = lambda {|version| "#{version}++"}
477
+ @release.send(:resolve_next_version, "1.0.0").should == 'ze_version_from_env'
478
+ end
479
+
480
+ it "should return the version specified by 'next_version' env var even if next_version is non nil" do
481
+ ENV['NEXT_VERSION'] = nil
482
+ ENV['next_version'] = "ze_version_from_env_lowercase"
483
+ Release.next_version = lambda {|version| "#{version}++"}
484
+ @release.send(:resolve_next_version, "1.0.0").should == 'ze_version_from_env_lowercase'
485
+ end
486
+ after {
487
+ Release.next_version = nil
488
+ ENV['NEXT_VERSION'] = nil
489
+ ENV['next_version'] = nil
490
+ }
491
+ end
492
+
493
+ describe '#resolve_next_version' do
494
+
495
+ it 'should increment the version number if SNAPSHOT' do
496
+ @release.send(:resolve_next_version, "1.0.0-SNAPSHOT").should == '1.0.1-SNAPSHOT'
497
+ end
498
+
499
+ it 'should NOT increment the version number if no SNAPSHOT' do
500
+ @release.send(:resolve_next_version, "1.0.0").should == '1.0.0'
501
+ end
502
+
503
+ it 'should return the version specified by NEXT_VERSION env var' do
504
+ ENV['NEXT_VERSION'] = "version_from_env"
505
+ @release.send(:resolve_next_version, "1.0.0").should == 'version_from_env'
506
+ end
507
+
508
+ it 'should return the version specified by next_version' do
509
+ Release.next_version = "ze_next_version"
510
+ @release.send(:resolve_next_version, "1.0.0").should == 'ze_next_version'
511
+ end
512
+
513
+ it 'should return the version specified by next_version if next_version is a proc' do
514
+ Release.next_version = lambda {|version| "#{version}++"}
515
+ @release.send(:resolve_next_version, "1.0.0").should == '1.0.0++'
516
+ end
517
+
518
+ it "should return the version specified by 'NEXT_VERSION' env var even if next_version is non nil" do
519
+ ENV['NEXT_VERSION'] = "ze_version_from_env"
520
+ Release.next_version = lambda {|version| "#{version}++"}
521
+ @release.send(:resolve_next_version, "1.0.0").should == 'ze_version_from_env'
522
+ end
523
+
524
+ it "should return the version specified by 'next_version' env var even if next_version is non nil" do
525
+ ENV['NEXT_VERSION'] = nil
526
+ ENV['next_version'] = "ze_version_from_env_lowercase"
527
+ Release.next_version = lambda {|version| "#{version}++"}
528
+ @release.send(:resolve_next_version, "1.0.0").should == 'ze_version_from_env_lowercase'
529
+ end
530
+ after {
531
+ Release.next_version = nil
532
+ ENV['NEXT_VERSION'] = nil
533
+ ENV['next_version'] = nil
534
+ }
535
+ end
536
+
537
+ describe '#resolve_next_version' do
538
+
539
+ it 'should increment the version number if SNAPSHOT' do
540
+ @release.send(:resolve_next_version, "1.0.0-SNAPSHOT").should == '1.0.1-SNAPSHOT'
541
+ end
542
+
543
+ it 'should NOT increment the version number if no SNAPSHOT' do
544
+ @release.send(:resolve_next_version, "1.0.0").should == '1.0.0'
545
+ end
546
+
547
+ it 'should return the version specified by NEXT_VERSION env var' do
548
+ ENV['NEXT_VERSION'] = "version_from_env"
549
+ @release.send(:resolve_next_version, "1.0.0").should == 'version_from_env'
550
+ end
551
+
552
+ it 'should return the version specified by next_version' do
553
+ Release.next_version = "ze_next_version"
554
+ @release.send(:resolve_next_version, "1.0.0").should == 'ze_next_version'
555
+ end
556
+
557
+ it 'should return the version specified by next_version if next_version is a proc' do
558
+ Release.next_version = lambda {|version| "#{version}++"}
559
+ @release.send(:resolve_next_version, "1.0.0").should == '1.0.0++'
560
+ end
561
+
562
+ it "should return the version specified by 'NEXT_VERSION' env var even if next_version is non nil" do
563
+ ENV['NEXT_VERSION'] = "ze_version_from_env"
564
+ Release.next_version = lambda {|version| "#{version}++"}
565
+ @release.send(:resolve_next_version, "1.0.0").should == 'ze_version_from_env'
566
+ end
567
+
568
+ it "should return the version specified by 'next_version' env var even if next_version is non nil" do
569
+ ENV['NEXT_VERSION'] = nil
570
+ ENV['next_version'] = "ze_version_from_env_lowercase"
571
+ Release.next_version = lambda {|version| "#{version}++"}
572
+ @release.send(:resolve_next_version, "1.0.0").should == 'ze_version_from_env_lowercase'
573
+ end
574
+ after {
575
+ Release.next_version = nil
576
+ ENV['NEXT_VERSION'] = nil
577
+ ENV['next_version'] = nil
578
+ }
579
+ end
580
+
581
+ describe '#resolve_tag' do
582
+ before do
583
+ @release.stub(:extract_version).and_return('1.0.0')
584
+ end
585
+
586
+ it 'should return tag specified by tag_name' do
587
+ Release.tag_name = 'first'
588
+ @release.send(:resolve_tag).should == 'first'
589
+ end
590
+
591
+ it 'should use tag returned by tag_name if tag_name is a proc' do
592
+ Release.tag_name = lambda { |version| "buildr-#{version}" }
593
+ @release.send(:resolve_tag).should == 'buildr-1.0.0'
594
+ end
595
+ after { Release.tag_name = nil }
596
+ end
597
+
598
+ describe '#tag_release' do
599
+ it 'should inform the user' do
600
+ @release.stub(:extract_version).and_return('1.0.0')
601
+ lambda { @release.tag_release('1.0.0') }.should show_info('Tagging release 1.0.0')
602
+ end
603
+ end
604
+
605
+ describe '#extract_version' do
606
+ it 'should extract VERSION_NUMBER with single quotes' do
607
+ write 'buildfile', "VERSION_NUMBER = '1.0.0-SNAPSHOT'"
608
+ @release.extract_version.should == '1.0.0-SNAPSHOT'
609
+ end
610
+
611
+ it 'should extract VERSION_NUMBER with double quotes' do
612
+ write 'buildfile', %{VERSION_NUMBER = "1.0.1-SNAPSHOT"}
613
+ @release.extract_version.should == '1.0.1-SNAPSHOT'
614
+ end
615
+
616
+ it 'should extract VERSION_NUMBER without any spaces' do
617
+ write 'buildfile', "VERSION_NUMBER='1.0.2-SNAPSHOT'"
618
+ @release.extract_version.should == '1.0.2-SNAPSHOT'
619
+ end
620
+
621
+ it 'should extract THIS_VERSION as an alternative to VERSION_NUMBER' do
622
+ write 'buildfile', "THIS_VERSION = '1.0.3-SNAPSHOT'"
623
+ @release.extract_version.should == '1.0.3-SNAPSHOT'
624
+ end
625
+
626
+ it 'should complain if no current version number' do
627
+ write 'buildfile', 'define foo'
628
+ lambda { @release.extract_version }.should raise_error('Looking for THIS_VERSION = "..." in your Buildfile, none found')
629
+ end
630
+
631
+ it 'should use version.rb instead of buildfile, if present' do
632
+ write 'version.rb', "VERSION_NUMBER = '1.0.0-SNAPSHOT'"
633
+ @release.extract_version.should == '1.0.0-SNAPSHOT'
634
+ end
635
+
636
+ it 'should complain if there is a version.rb file, but it contains no version number' do
637
+ write 'version.rb', "#SOMETHING SOMETHING"
638
+ lambda { @release.extract_version }.should raise_error('Looking for THIS_VERSION = "..." in your Buildfile, none found')
639
+ end
640
+ end
641
+
642
+ describe '#with_release_candidate_version' do
643
+ before do
644
+ Buildr.application.stub(:buildfile).and_return(file('buildfile'))
645
+ write 'buildfile', "THIS_VERSION = '1.1.0-SNAPSHOT'"
646
+ end
647
+
648
+ it 'should yield the name of the release candidate buildfile' do
649
+ @release.send :with_release_candidate_version do |new_filename|
650
+ File.read(new_filename).should == %{THIS_VERSION = "1.1.0"}
651
+ end
652
+ end
653
+
654
+ it 'should yield a name different from the original buildfile' do
655
+ @release.send :with_release_candidate_version do |new_filename|
656
+ new_filename.should_not point_to_path('buildfile')
657
+ end
658
+ end
659
+ end
660
+
661
+ describe '#update_version_to_next' do
662
+ before do
663
+ write 'buildfile', "VERSION_NUMBER = '1.0.5-SNAPSHOT'"
664
+ @release.send(:this_version=, "1.0.5-SNAPSHOT")
665
+ end
666
+
667
+ it 'should update the buildfile with a new version number' do
668
+ @release.send :update_version_to_next
669
+ `cp buildfile /tmp/out`
670
+ file('buildfile').should contain('VERSION_NUMBER = "1.0.6-SNAPSHOT"')
671
+ end
672
+
673
+ it 'should commit the new buildfile on the trunk' do
674
+ @release.should_receive(:message).and_return('Changed version number to 1.0.1-SNAPSHOT')
675
+ @release.update_version_to_next
676
+ end
677
+
678
+ it 'should use the commit message specified by commit_message' do
679
+ Release.commit_message = 'Here is my custom message'
680
+ @release.should_receive(:message).and_return('Here is my custom message')
681
+ @release.update_version_to_next
682
+ end
683
+
684
+ it 'should use the commit message returned by commit_message if commit_message is a proc' do
685
+ Release.commit_message = lambda { |new_version|
686
+ new_version.should == '1.0.1-SNAPSHOT'
687
+ "increment version number to #{new_version}"
688
+ }
689
+ @release.should_receive(:message).and_return('increment version number to 1.0.1-SNAPSHOT')
690
+ @release.update_version_to_next
691
+ end
692
+
693
+ it 'should inform the user of the new version' do
694
+ lambda { @release.update_version_to_next }.should show_info('Current version is now 1.0.6-SNAPSHOT')
695
+ end
696
+ after { Release.commit_message = nil }
697
+ end
698
+
699
+
700
+ describe '#check' do
701
+ before { @release.send(:this_version=, "1.0.0-SNAPSHOT") }
702
+ it 'should fail if THIS_VERSION equals the next_version' do
703
+ @release.stub(:resolve_next_version).and_return('1.0.0-SNAPSHOT')
704
+ lambda { @release.check }.should raise_error("The next version can't be equal to the current version 1.0.0-SNAPSHOT.\nUpdate THIS_VERSION/VERSION_NUMBER, specify Release.next_version or use NEXT_VERSION env var")
705
+ end
706
+ end
707
+ end
708
+
709
+
710
+ describe HgRelease do
711
+ it_should_behave_like 'a release process'
712
+
713
+ before do
714
+ write 'buildfile', "VERSION_NUMBER = '1.0.0-SNAPSHOT'"
715
+ @release = HgRelease.new
716
+ Hg.stub(:hg)
717
+ Hg.stub(:remote).and_return('https://bitbucket.org/sample-repo')
718
+ Hg.stub(:current_branch).and_return('default')
719
+ end
720
+
721
+ describe '#applies_to?' do
722
+ it 'should reject a non-hg repo' do
723
+ Dir.chdir(Dir.tmpdir) do
724
+ HgRelease.applies_to?.should be_false
725
+ end
726
+ end
727
+
728
+ it 'should accept a hg repo' do
729
+ FileUtils.mkdir '.hg'
730
+ FileUtils.touch File.join('.hg', 'requires')
731
+ HgRelease.applies_to?.should be_true
732
+ end
733
+ end
734
+
735
+ describe '#check' do
736
+ before do
737
+ @release = HgRelease.new
738
+ @release.send(:this_version=, '1.0.0-SNAPSHOT')
739
+ end
740
+
741
+ it 'should accept a clean repo' do
742
+ Hg.should_receive(:uncommitted_files).and_return([])
743
+ Hg.should_receive(:remote).and_return(["http://bitbucket.org/sample-repo"])
744
+ lambda { @release.check }.should_not raise_error
745
+ end
746
+
747
+ it 'should reject a dirty repo' do
748
+ Hg.should_receive(:uncommitted_files).and_return(['dirty_file.txt'])
749
+ lambda { @release.check }.should raise_error(RuntimeError, /uncommitted files/i)
750
+ end
751
+
752
+ it 'should reject a local branch not tracking a remote repo' do
753
+ Hg.should_receive(:uncommitted_files).and_return([])
754
+ Hg.should_receive(:remote).and_return([])
755
+ lambda{ @release.check }.should raise_error(RuntimeError,
756
+ "You are releasing from a local branch that does not track a remote!")
757
+ end
758
+ end
759
+ end
760
+
761
+
762
+ describe GitRelease do
763
+ it_should_behave_like 'a release process'
764
+
765
+ before do
766
+ write 'buildfile', "VERSION_NUMBER = '1.0.0-SNAPSHOT'"
767
+ @release = GitRelease.new
768
+ Git.stub(:git)
769
+ Git.stub(:current_branch).and_return('master')
770
+ end
771
+
772
+ describe '#applies_to?' do
773
+
774
+ # TravisCI seems to place the tmp directory
775
+ # sub-ordinate to git repository so this will not work
776
+ unless ENV['TRAVIS_BUILD_ID']
777
+ it 'should reject a non-git repo' do
778
+ Dir.chdir(Dir.tmpdir) do
779
+ GitRelease.applies_to?.should be_false
780
+ end
781
+ end
782
+ end
783
+
784
+ it 'should accept a git repo' do
785
+ FileUtils.mkdir '.git'
786
+ FileUtils.touch File.join('.git', 'config')
787
+ GitRelease.applies_to?.should be_true
788
+ end
789
+ end
790
+
791
+ describe '#check' do
792
+ before do
793
+ @release = GitRelease.new
794
+ @release.send(:this_version=, '1.0.0-SNAPSHOT')
795
+ end
796
+
797
+ it 'should accept a clean repository' do
798
+ Git.should_receive(:`).with('git status').and_return <<-EOF
799
+ # On branch master
800
+ nothing to commit (working directory clean)
801
+ EOF
802
+ Git.should_receive(:remote).and_return('master')
803
+ lambda { @release.check }.should_not raise_error
804
+ end
805
+
806
+ it 'should reject a dirty repository' do
807
+ Git.should_receive(:`).with('git status').and_return <<-EOF
808
+ # On branch master
809
+ # Untracked files:
810
+ # (use "git add <file>..." to include in what will be committed)
811
+ #
812
+ # foo.temp
813
+ EOF
814
+ lambda { @release.check }.should raise_error(RuntimeError, /uncommitted files/i)
815
+ end
816
+
817
+ it 'should reject a repository not tracking remote branch' do
818
+ Git.should_receive(:uncommitted_files).and_return([])
819
+ Git.should_receive(:remote).and_return(nil)
820
+ lambda{ @release.check }.should raise_error(RuntimeError,
821
+ "You are releasing from a local branch that does not track a remote!")
822
+ end
823
+ end
824
+
825
+ describe '#tag_release' do
826
+ before do
827
+ @release = GitRelease.new
828
+ @release.stub(:extract_version).and_return('1.0.1')
829
+ @release.stub(:resolve_tag).and_return('TEST_TAG')
830
+ Git.stub(:git).with('tag', '-a', 'TEST_TAG', '-m', '[buildr] Cutting release TEST_TAG')
831
+ Git.stub(:git).with('push', 'origin', 'tag', 'TEST_TAG')
832
+ Git.stub(:commit)
833
+ Git.stub(:push)
834
+ Git.stub(:remote).and_return('origin')
835
+ end
836
+
837
+ it 'should delete any existing tag with the same name' do
838
+ Git.should_receive(:git).with('tag', '-d', 'TEST_TAG')
839
+ Git.should_receive(:git).with('push', 'origin', ':refs/tags/TEST_TAG')
840
+ @release.tag_release 'TEST_TAG'
841
+ end
842
+
843
+ it 'should commit the buildfile before tagging' do
844
+ Git.should_receive(:commit).with(File.basename(Buildr.application.buildfile.to_s), "Changed version number to 1.0.1")
845
+ @release.tag_release 'TEST_TAG'
846
+ end
847
+
848
+ it 'should push the tag if a remote is tracked' do
849
+ Git.should_receive(:git).with('tag', '-d', 'TEST_TAG')
850
+ Git.should_receive(:git).with('push', 'origin', ':refs/tags/TEST_TAG')
851
+ Git.should_receive(:git).with('tag', '-a', 'TEST_TAG', '-m', '[buildr] Cutting release TEST_TAG')
852
+ Git.should_receive(:git).with('push', 'origin', 'tag', 'TEST_TAG')
853
+ @release.tag_release 'TEST_TAG'
854
+ end
855
+
856
+ it 'should NOT push the tag if no remote is tracked' do
857
+ Git.stub(:remote).and_return(nil)
858
+ Git.should_not_receive(:git).with('push', 'origin', 'tag', 'TEST_TAG')
859
+ @release.tag_release 'TEST_TAG'
860
+ end
861
+ end
862
+ end
863
+
864
+
865
+ describe SvnRelease do
866
+ it_should_behave_like 'a release process'
867
+
868
+ before do
869
+ write 'buildfile', "VERSION_NUMBER = '1.0.0-SNAPSHOT'"
870
+ @release = SvnRelease.new
871
+ Svn.stub(:svn)
872
+ Svn.stub(:repo_url).and_return('http://my.repo.org/foo/trunk')
873
+ Svn.stub(:tag)
874
+ end
875
+
876
+ describe '#applies_to?' do
877
+ it 'should reject a non-git repo' do
878
+ SvnRelease.applies_to?.should be_false
879
+ end
880
+
881
+ it 'should accept a git repo' do
882
+ FileUtils.touch '.svn'
883
+ SvnRelease.applies_to?.should be_true
884
+ end
885
+ end
886
+
887
+ describe '#check' do
888
+ before do
889
+ Svn.stub(:uncommitted_files).and_return([])
890
+ @release = SvnRelease.new
891
+ @release.send(:this_version=, "1.0.0-SNAPSHOT")
892
+ end
893
+
894
+ it 'should accept to release from the trunk' do
895
+ Svn.stub(:repo_url).and_return('http://my.repo.org/foo/trunk')
896
+ lambda { @release.check }.should_not raise_error
897
+ end
898
+
899
+ it 'should accept to release from a branch' do
900
+ Svn.stub(:repo_url).and_return('http://my.repo.org/foo/branches/1.0')
901
+ lambda { @release.check }.should_not raise_error
902
+ end
903
+
904
+ it 'should reject releasing from a tag' do
905
+ Svn.stub(:repo_url).and_return('http://my.repo.org/foo/tags/1.0.0')
906
+ lambda { @release.check }.should raise_error(RuntimeError, "SVN URL must contain 'trunk' or 'branches/...'")
907
+ end
908
+
909
+ it 'should reject a non standard repository layout' do
910
+ Svn.stub(:repo_url).and_return('http://my.repo.org/foo/bar')
911
+ lambda { @release.check }.should raise_error(RuntimeError, "SVN URL must contain 'trunk' or 'branches/...'")
912
+ end
913
+
914
+ it 'should reject an uncommitted file' do
915
+ Svn.stub(:repo_url).and_return('http://my.repo.org/foo/trunk')
916
+ Svn.stub(:uncommitted_files).and_return(['foo.rb'])
917
+ lambda { @release.check }.should raise_error(RuntimeError,
918
+ "Uncommitted files violate the First Principle Of Release!\n" +
919
+ "foo.rb")
920
+ end
921
+ end
922
+ end