buildr 1.3.3 → 1.3.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (144) hide show
  1. data/CHANGELOG +76 -0
  2. data/NOTICE +1 -1
  3. data/README.rdoc +9 -21
  4. data/Rakefile +20 -37
  5. data/_buildr +3 -12
  6. data/{doc/print.toc.yaml → _jbuildr} +14 -14
  7. data/addon/buildr/cobertura.rb +5 -219
  8. data/addon/buildr/drb.rb +281 -0
  9. data/addon/buildr/emma.rb +5 -221
  10. data/addon/buildr/nailgun.rb +93 -689
  11. data/bin/buildr +0 -9
  12. data/buildr.buildfile +4 -4
  13. data/buildr.gemspec +27 -21
  14. data/doc/_layouts/default.html +82 -0
  15. data/doc/_layouts/preface.html +22 -0
  16. data/doc/{pages/artifacts.textile → artifacts.textile} +82 -42
  17. data/doc/{pages/building.textile → building.textile} +89 -47
  18. data/doc/{pages/contributing.textile → contributing.textile} +53 -45
  19. data/doc/css/default.css +6 -5
  20. data/doc/css/print.css +17 -24
  21. data/doc/css/syntax.css +7 -36
  22. data/doc/download.textile +78 -0
  23. data/doc/{pages/extending.textile → extending.textile} +45 -24
  24. data/doc/{pages/getting_started.textile → getting_started.textile} +146 -88
  25. data/doc/images/asf-logo.gif +0 -0
  26. data/doc/images/note.png +0 -0
  27. data/doc/index.textile +47 -0
  28. data/doc/{pages/languages.textile → languages.textile} +108 -54
  29. data/doc/mailing_lists.textile +25 -0
  30. data/doc/{pages/more_stuff.textile → more_stuff.textile} +152 -73
  31. data/doc/{pages/packaging.textile → packaging.textile} +181 -96
  32. data/doc/preface.textile +28 -0
  33. data/doc/{pages/projects.textile → projects.textile} +55 -40
  34. data/doc/scripts/buildr-git.rb +364 -264
  35. data/doc/scripts/gitflow.rb +296 -0
  36. data/doc/scripts/install-jruby.sh +2 -2
  37. data/doc/scripts/install-linux.sh +6 -6
  38. data/doc/scripts/install-osx.sh +2 -2
  39. data/doc/{pages/settings_profiles.textile → settings_profiles.textile} +83 -45
  40. data/doc/{pages/testing.textile → testing.textile} +77 -41
  41. data/lib/buildr.rb +5 -5
  42. data/lib/buildr/core.rb +2 -0
  43. data/lib/buildr/core/application.rb +321 -151
  44. data/lib/buildr/core/build.rb +298 -167
  45. data/lib/buildr/core/checks.rb +4 -132
  46. data/lib/buildr/core/common.rb +1 -5
  47. data/lib/buildr/core/compile.rb +3 -9
  48. data/lib/buildr/core/environment.rb +12 -3
  49. data/lib/buildr/core/filter.rb +20 -18
  50. data/lib/buildr/core/generate.rb +36 -36
  51. data/lib/buildr/core/help.rb +2 -1
  52. data/lib/buildr/core/osx.rb +46 -0
  53. data/lib/buildr/core/progressbar.rb +1 -1
  54. data/lib/buildr/core/project.rb +7 -34
  55. data/lib/buildr/core/test.rb +12 -6
  56. data/lib/buildr/core/transports.rb +13 -11
  57. data/lib/buildr/core/util.rb +14 -23
  58. data/lib/buildr/groovy/bdd.rb +3 -2
  59. data/lib/buildr/groovy/compiler.rb +1 -1
  60. data/lib/buildr/ide/eclipse.rb +31 -21
  61. data/lib/buildr/ide/idea.rb +3 -2
  62. data/lib/buildr/ide/idea7x.rb +6 -4
  63. data/lib/buildr/java/ant.rb +3 -1
  64. data/lib/buildr/java/bdd.rb +9 -7
  65. data/lib/buildr/java/cobertura.rb +243 -0
  66. data/lib/buildr/java/compiler.rb +5 -4
  67. data/lib/buildr/java/emma.rb +244 -0
  68. data/lib/buildr/java/packaging.rb +11 -8
  69. data/lib/buildr/java/pom.rb +0 -4
  70. data/lib/buildr/java/rjb.rb +1 -1
  71. data/lib/buildr/java/test_result.rb +5 -7
  72. data/lib/buildr/java/tests.rb +17 -11
  73. data/lib/buildr/packaging.rb +5 -2
  74. data/lib/buildr/packaging/archive.rb +488 -0
  75. data/lib/buildr/packaging/artifact.rb +48 -29
  76. data/lib/buildr/packaging/artifact_namespace.rb +6 -6
  77. data/lib/buildr/packaging/gems.rb +4 -4
  78. data/lib/buildr/packaging/package.rb +3 -2
  79. data/lib/buildr/packaging/tar.rb +85 -3
  80. data/lib/buildr/packaging/version_requirement.rb +172 -0
  81. data/lib/buildr/packaging/zip.rb +24 -682
  82. data/lib/buildr/packaging/ziptask.rb +313 -0
  83. data/lib/buildr/scala.rb +5 -0
  84. data/lib/buildr/scala/bdd.rb +100 -0
  85. data/lib/buildr/scala/compiler.rb +45 -4
  86. data/lib/buildr/scala/tests.rb +12 -59
  87. data/rakelib/checks.rake +57 -0
  88. data/rakelib/doc.rake +58 -68
  89. data/rakelib/jekylltask.rb +110 -0
  90. data/rakelib/package.rake +35 -37
  91. data/rakelib/release.rake +119 -35
  92. data/rakelib/rspec.rake +29 -39
  93. data/rakelib/setup.rake +21 -59
  94. data/rakelib/stage.rake +184 -26
  95. data/spec/addon/drb_spec.rb +328 -0
  96. data/spec/core/application_spec.rb +32 -25
  97. data/spec/core/build_spec.rb +336 -126
  98. data/spec/core/checks_spec.rb +292 -310
  99. data/spec/core/common_spec.rb +8 -2
  100. data/spec/core/compile_spec.rb +17 -1
  101. data/spec/core/generate_spec.rb +3 -3
  102. data/spec/core/project_spec.rb +18 -10
  103. data/spec/core/test_spec.rb +8 -1
  104. data/spec/core/transport_spec.rb +40 -3
  105. data/spec/core/util_spec.rb +67 -0
  106. data/spec/ide/eclipse_spec.rb +96 -28
  107. data/spec/ide/idea7x_spec.rb +84 -0
  108. data/spec/java/ant.rb +5 -0
  109. data/spec/java/bdd_spec.rb +12 -3
  110. data/spec/{addon → java}/cobertura_spec.rb +6 -6
  111. data/spec/{addon → java}/emma_spec.rb +5 -6
  112. data/spec/java/java_spec.rb +12 -2
  113. data/spec/java/packaging_spec.rb +31 -2
  114. data/spec/{addon → java}/test_coverage_spec.rb +3 -3
  115. data/spec/java/tests_spec.rb +5 -0
  116. data/spec/packaging/archive_spec.rb +11 -1
  117. data/spec/{core → packaging}/artifact_namespace_spec.rb +10 -2
  118. data/spec/packaging/artifact_spec.rb +44 -3
  119. data/spec/packaging/packaging_spec.rb +1 -1
  120. data/spec/sandbox.rb +17 -14
  121. data/spec/scala/bdd_spec.rb +150 -0
  122. data/spec/scala/compiler_spec.rb +27 -0
  123. data/spec/scala/scala.rb +38 -0
  124. data/spec/scala/tests_spec.rb +78 -33
  125. data/spec/spec_helpers.rb +29 -5
  126. data/spec/version_requirement_spec.rb +6 -0
  127. metadata +175 -171
  128. data/DISCLAIMER +0 -7
  129. data/doc/images/apache-incubator-logo.png +0 -0
  130. data/doc/pages/download.textile +0 -51
  131. data/doc/pages/index.textile +0 -42
  132. data/doc/pages/mailing_lists.textile +0 -17
  133. data/doc/pages/recipes.textile +0 -103
  134. data/doc/pages/troubleshooting.textile +0 -103
  135. data/doc/pages/whats_new.textile +0 -323
  136. data/doc/print.haml +0 -51
  137. data/doc/site.haml +0 -56
  138. data/doc/site.toc.yaml +0 -47
  139. data/etc/git-svn-authors +0 -16
  140. data/lib/buildr/core/application_cli.rb +0 -139
  141. data/rakelib/apache.rake +0 -191
  142. data/rakelib/changelog.rake +0 -57
  143. data/rakelib/rubyforge.rake +0 -53
  144. data/rakelib/scm.rake +0 -49
@@ -56,10 +56,8 @@ module Buildr
56
56
  project.recursive_task 'build'
57
57
  project.recursive_task 'clean'
58
58
  project.clean do
59
- verbose(true) do
60
- rm_rf project.path_to(:target)
61
- rm_rf project.path_to(:reports)
62
- end
59
+ rm_rf project.path_to(:target)
60
+ rm_rf project.path_to(:reports)
63
61
  end
64
62
  end
65
63
 
@@ -109,198 +107,331 @@ module Buildr
109
107
  end
110
108
 
111
109
 
112
- class Svn
110
+ module Git #:nodoc:
113
111
 
114
- class << self
115
- def commit(file, message)
116
- svn 'commit', '-m', message, file
117
- end
118
-
119
- def copy(dir, url, message)
120
- svn 'copy', dir, url, '-m', message
121
- end
122
-
123
- # Return the current SVN URL
124
- def repo_url
125
- svn('info').scan(/URL: (.*)/)[0][0]
126
- end
127
-
128
- def remove(url, message)
129
- svn 'remove', url, '-m', message
130
- end
131
-
132
- # Status check reveals modified files, but also SVN externals which we can safely ignore.
133
- def uncommitted_files
134
- svn('status', '--ignore-externals').reject { |line| line =~ /^X\s/ }
135
- end
136
-
137
- # :call-seq:
138
- # svn(*args)
139
- #
140
- # Executes SVN command and returns the output.
141
- def svn(*args)
142
- cmd = 'svn ' + args.map { |arg| arg[' '] ? %Q{"#{arg}"} : arg }.join(' ')
143
- trace cmd
144
- `#{cmd}`.tap { fail 'SVN command failed' unless $?.exitstatus == 0 }
145
- end
112
+ module_function
113
+
114
+ # :call-seq:
115
+ # git(*args)
116
+ #
117
+ # Executes a Git command and returns the output. Throws exception if the exit status
118
+ # is not zero. For example:
119
+ # git 'commit'
120
+ # git 'remote', 'show', 'origin'
121
+ def git(*args)
122
+ cmd = "git #{args.shift} #{args.map { |arg| arg.inspect }.join(' ')}"
123
+ output = `#{cmd}`
124
+ fail "GIT command \"#{cmd}\" failed with status #{$?.exitstatus}\n#{output}" unless $?.exitstatus == 0
125
+ return output
126
+ end
127
+
128
+ # Returns list of uncommited/untracked files as reported by git status.
129
+ def uncommitted_files
130
+ `git status`.scan(/^#\s{7}(\S.*)$/).map { |match| match.first.split.last }
131
+ end
132
+
133
+ # Commit the given file with a message.
134
+ # The file has to be known to Git meaning that it has either to have been already committed in the past
135
+ # or freshly added to the index. Otherwise it will fail.
136
+ def commit(file, message)
137
+ git 'commit', '-m', message, file
138
+ end
139
+
140
+ # Update the remote refs using local refs
141
+ #
142
+ # By default, the "remote" destination of the push is the the remote repo linked to the current branch.
143
+ # The default remote branch is the current local branch.
144
+ def push(remote_repo = remote, remote_branch = current_branch)
145
+ git 'push', remote, current_branch
146
146
  end
147
+
148
+ # Return the name of the remote repository whose branch the current local branch tracks,
149
+ # or nil if none.
150
+ def remote(branch = current_branch)
151
+ remote = git('config', '--get', "branch.#{branch}.remote").strip
152
+ remote if git('remote').include?(remote)
153
+ rescue
154
+ nil
155
+ end
156
+
157
+ # Return the name of the current branch
158
+ def current_branch
159
+ git('branch')[/^\* (.*)$/, 1]
160
+ end
161
+
162
+ end
163
+
164
+
165
+ module Svn #:nodoc:
166
+
167
+ module_function
168
+
169
+ # :call-seq:
170
+ # svn(*args)
171
+ #
172
+ # Executes a SVN command and returns the output. Throws exception if the exit status
173
+ # is not zero. For example:
174
+ # svn 'commit'
175
+ def svn(*args)
176
+ output = `svn #{args.shift} #{args.map { |arg| arg.inspect }.join(' ')}`
177
+ fail "SVN command failed with status #{$?.exitstatus}" unless $?.exitstatus == 0
178
+ return output
179
+ end
180
+
181
+ def tag(tag_name)
182
+ url = tag_url repo_url, tag_name
183
+ remove url, 'Removing old copy' rescue nil
184
+ copy Dir.pwd, url, "Release #{tag_name}"
185
+ end
186
+
187
+ # Status check reveals modified files, but also SVN externals which we can safely ignore.
188
+ def uncommitted_files
189
+ svn('status', '--ignore-externals').split("\n").reject { |line| line =~ /^X\s/ }
190
+ end
191
+
192
+ def commit(file, message)
193
+ svn 'commit', '-m', message, file
194
+ end
195
+
196
+ # :call-seq:
197
+ # tag_url(svn_url, version) => tag_url
198
+ #
199
+ # Returns the SVN url for the tag.
200
+ # Can tag from the trunk or from branches.
201
+ # Can handle the two standard repository layouts.
202
+ # - http://my.repo/foo/trunk => http://my.repo/foo/tags/1.0.0
203
+ # - http://my.repo/trunk/foo => http://my.repo/tags/foo/1.0.0
204
+ def tag_url(svn_url, tag)
205
+ trunk_or_branches = Regexp.union(%r{^(.*)/trunk(.*)$}, %r{^(.*)/branches(.*)/([^/]*)$})
206
+ match = trunk_or_branches.match(svn_url)
207
+ prefix = match[1] || match[3]
208
+ suffix = match[2] || match[4]
209
+ prefix + '/tags' + suffix + '/' + tag
210
+ end
211
+
212
+ # Return the current SVN URL
213
+ def repo_url
214
+ svn('info', '--xml')[/<url>(.*?)<\/url>/, 1].strip
215
+ end
216
+
217
+ def copy(dir, url, message)
218
+ svn 'copy', dir, url, '-m', message
219
+ end
220
+
221
+ def remove(url, message)
222
+ svn 'remove', url, '-m', message
223
+ end
224
+
147
225
  end
148
226
 
149
-
150
- class Release
227
+
228
+ class Release #:nodoc:
151
229
 
152
230
  THIS_VERSION_PATTERN = /(THIS_VERSION|VERSION_NUMBER)\s*=\s*(["'])(.*)\2/
153
231
 
154
232
  class << self
155
233
 
156
- # Use this to specify a different tag name for tagging the release in source control.
157
- # You can set the tag name or a proc that will be called with the version number,
158
- # for example:
159
- # Release.tag_name = lambda { |ver| "foo-#{ver}" }
160
- attr_accessor :tag_name
161
-
162
234
  # :call-seq:
163
- # make()
235
+ # add(MyReleaseClass)
164
236
  #
165
- # Make a release.
166
- def make
167
- check
168
- with_release_candidate_version do |release_candidate_buildfile|
169
- options = ['--buildfile', release_candidate_buildfile, 'DEBUG=no']
170
- options << '--environment' << Buildr.environment unless Buildr.environment.to_s.empty?
171
- buildr %w{clean upload}, options
172
- end
173
- tag_release
174
- commit_new_snapshot
237
+ # Add a Release implementation to the list of available Release classes.
238
+ def add(release)
239
+ @list ||= []
240
+ @list |= [release]
175
241
  end
242
+ alias :<< :add
176
243
 
177
- # :call-seq:
178
- # extract_version() => this_version
179
- #
180
- # Extract the current version number from the buildfile.
181
- # Raise an error if not found.
182
- def extract_version
183
- buildfile = File.read(Buildr.application.buildfile.to_s)
184
- buildfile.scan(THIS_VERSION_PATTERN)[0][2]
185
- rescue
186
- fail 'Looking for THIS_VERSION = "..." in your Buildfile, none found'
187
- end
188
-
189
- # :call-seq:
190
- # tag_url(svn_url, version) => tag_url
191
- #
192
- # Returns the SVN url for the tag.
193
- # Can tag from the trunk or from branches.
194
- # Can handle the two standard repository layouts.
195
- # - http://my.repo/foo/trunk => http://my.repo/foo/tags/1.0.0
196
- # - http://my.repo/trunk/foo => http://my.repo/tags/foo/1.0.0
197
- def tag_url(svn_url, version)
198
- trunk_or_branches = Regexp.union(%r{^(.*)/trunk(.*)$}, %r{^(.*)/branches(.*)/([^/]*)$})
199
- match = trunk_or_branches.match(svn_url)
200
- prefix = match[1] || match[3]
201
- suffix = match[2] || match[4]
202
- tag = tag_name || version
203
- tag = tag.call(version) if Proc === tag
204
- prefix + '/tags' + suffix + '/' + tag
205
- end
206
-
207
- # :call-seq:
208
- # check()
209
- #
210
- # Check that we don't have any local changes in the working copy. Fails if it finds anything
211
- # in the working copy that is not checked into source control.
212
- def check
213
- fail "SVN URL must contain 'trunk' or 'branches/...'" unless Svn.repo_url =~ /(trunk)|(branches.*)$/
214
- fail "Uncommitted SVN files violate the First Principle Of Release!\n#{Svn.uncommitted_files}" unless Svn.uncommitted_files.empty?
244
+ # The list of supported Release implementations
245
+ def list
246
+ @list ||= []
215
247
  end
216
248
 
217
- protected
249
+ end
250
+
251
+ # Use this to specify a different tag name for tagging the release in source control.
252
+ # You can set the tag name or a proc that will be called with the version number,
253
+ # for example:
254
+ # Release.tag_name = lambda { |ver| "foo-#{ver}" }
255
+ attr_accessor :tag_name
256
+
257
+ # Use this to specify a different commit message to commit the buildfile with the next version in source control.
258
+ # You can set the commit message or a proc that will be called with the next version number,
259
+ # for example:
260
+ # Release.commit_message = lambda { |ver| "Changed version number to #{ver}" }
261
+ attr_accessor :commit_message
218
262
 
219
- # :call-seq:
220
- # buildr(tasks, options)
221
- #
222
- # Calls another instance of buildr.
223
- def buildr(tasks, options)
224
- sh "#{command} _#{Buildr::VERSION}_ #{tasks.join(' ')} #{options.join(' ')}"
263
+ # :call-seq:
264
+ # make()
265
+ #
266
+ # Make a release.
267
+ def make
268
+ check
269
+ with_release_candidate_version do |release_candidate_buildfile|
270
+ args = '-S', 'buildr', "_#{Buildr::VERSION}_", '--buildfile', release_candidate_buildfile
271
+ args << '--environment' << Buildr.environment unless Buildr.environment.to_s.empty?
272
+ args << 'clean' << 'upload' << 'DEBUG=no'
273
+ ruby *args
225
274
  end
226
-
227
- def command #:nodoc:
228
- Config::CONFIG['arch'] =~ /dos|win32/i ? $PROGRAM_NAME.ext('cmd') : $PROGRAM_NAME
275
+ tag_release resolve_tag
276
+ update_version_to_next
277
+ end
278
+
279
+ # :call-seq:
280
+ # extract_version() => this_versin
281
+ #
282
+ # Extract the current version number from the buildfile.
283
+ # Raise an error if not found.
284
+ def extract_version
285
+ buildfile = File.read(Buildr.application.buildfile.to_s)
286
+ buildfile.scan(THIS_VERSION_PATTERN)[0][2]
287
+ rescue
288
+ fail 'Looking for THIS_VERSION = "..." in your Buildfile, none found'
289
+ end
290
+
291
+ protected
292
+
293
+ # :call-seq:
294
+ # with_release_candidate_version() { |filename| ... }
295
+ #
296
+ # Yields to block with release candidate buildfile, before committing to use it.
297
+ #
298
+ # We need a Buildfile with upgraded version numbers to run the build, but we don't want the
299
+ # Buildfile modified unless the build succeeds. So this method updates the version number in
300
+ # a separate (Buildfile.next) file, yields to the block with that filename, and if successful
301
+ # copies the new file over the existing one.
302
+ #
303
+ # The release version is the current version without '-SNAPSHOT'. So:
304
+ # THIS_VERSION = 1.1.0-SNAPSHOT
305
+ # becomes:
306
+ # THIS_VERSION = 1.1.0
307
+ # for the release buildfile.
308
+ def with_release_candidate_version
309
+ release_candidate_buildfile = Buildr.application.buildfile.to_s + '.next'
310
+ release_candidate_buildfile_contents = change_version { |version| version[-1] = version[-1].to_i }
311
+ File.open(release_candidate_buildfile, 'w') { |file| file.write release_candidate_buildfile_contents }
312
+ begin
313
+ yield release_candidate_buildfile
314
+ mv release_candidate_buildfile, Buildr.application.buildfile.to_s
315
+ ensure
316
+ rm release_candidate_buildfile rescue nil
229
317
  end
318
+ end
230
319
 
231
- # :call-seq:
232
- # with_release_candidate_version() { |filename| ... }
233
- #
234
- # Yields to block with release candidate buildfile, before committing to use it.
235
- #
236
- # We need a Buildfile with upgraded version numbers to run the build, but we don't want the
237
- # Buildfile modified unless the build succeeds. So this method updates the version number in
238
- # a separate (Buildfile.next) file, yields to the block with that filename, and if successful
239
- # copies the new file over the existing one.
240
- #
241
- # The release version is the current version without '-SNAPSHOT'. So:
242
- # THIS_VERSION = 1.1.0-SNAPSHOT
243
- # becomes:
244
- # THIS_VERSION = 1.1.0
245
- # for the release buildfile.
246
- def with_release_candidate_version
247
- release_candidate_buildfile = Buildr.application.buildfile.to_s + '.next'
248
- release_candidate_buildfile_contents = change_version { |version| version[-1] = version[-1].to_i }
249
- File.open(release_candidate_buildfile, 'w') { |file| file.write release_candidate_buildfile_contents }
250
- begin
251
- yield release_candidate_buildfile
252
- mv release_candidate_buildfile, Buildr.application.buildfile.to_s
253
- ensure
254
- rm release_candidate_buildfile rescue nil
255
- end
256
- end
320
+ # :call-seq:
321
+ # change_version() { |this_version| ... } => buildfile
322
+ #
323
+ # Change version number in the current Buildfile, but without writing a new file (yet).
324
+ # Returns the contents of the Buildfile with the modified version number.
325
+ #
326
+ # This method yields to the block with the current (this) version number as an array and expects
327
+ # the block to update it.
328
+ def change_version
329
+ this_version = extract_version
330
+ new_version = this_version.split('.')
331
+ yield(new_version)
332
+ new_version = new_version.join('.')
333
+ buildfile = File.read(Buildr.application.buildfile.to_s)
334
+ buildfile.gsub(THIS_VERSION_PATTERN) { |ver| ver.sub(/(["']).*\1/, %Q{"#{new_version}"}) }
335
+ end
257
336
 
258
- # :call-seq:
259
- # change_version() { |this_version| ... } => buildfile
260
- #
261
- # Change version number in the current Buildfile, but without writing a new file (yet).
262
- # Returns the contents of the Buildfile with the modified version number.
263
- #
264
- # This method yields to the block with the current (this) version number as an array and expects
265
- # the block to update it.
266
- def change_version
267
- this_version = extract_version
268
- new_version = this_version.split('.')
269
- yield(new_version)
270
- new_version = new_version.join('.')
271
- buildfile = File.read(Buildr.application.buildfile.to_s)
272
- buildfile.gsub(THIS_VERSION_PATTERN) { |ver| ver.sub(/(["']).*\1/, %Q{"#{new_version}"}) }
273
- end
337
+ # Return the name of the tag to tag the release with.
338
+ def resolve_tag
339
+ version = extract_version
340
+ tag = tag_name || version
341
+ tag = tag.call(version) if Proc === tag
342
+ tag
343
+ end
274
344
 
275
- # :call-seq:
276
- # tag_release()
277
- #
278
- # Tags the current working copy with the release version number.
279
- def tag_release
280
- version = extract_version
281
- info "Tagging release #{version}"
282
- url = tag_url Svn.repo_url, version
283
- Svn.remove url, 'Removing old copy' rescue nil
284
- Svn.copy Dir.pwd, url, "Release #{version}"
285
- end
345
+ # Move the version to next and save the updated buildfile
346
+ def update_buildfile
347
+ buildfile = change_version { |version| version[-1] = (version[-1].to_i + 1).to_s + '-SNAPSHOT' }
348
+ File.open(Buildr.application.buildfile.to_s, 'w') { |file| file.write buildfile }
349
+ end
286
350
 
287
- # :call-seq:
288
- # commit_new_snapshot()
289
- #
290
- # Last, we commit what we currently have in the working copy with an upgraded version number.
291
- def commit_new_snapshot
292
- buildfile = change_version { |version| version[-1] = (version[-1].to_i + 1).to_s + '-SNAPSHOT' }
293
- File.open(Buildr.application.buildfile.to_s, 'w') { |file| file.write buildfile }
294
- Svn.commit Buildr.application.buildfile.to_s, "Changed version number to #{extract_version}"
295
- info "Current version is now #{extract_version}"
351
+ # Return the message to use to cimmit the buildfile with the next version
352
+ def message
353
+ version = extract_version
354
+ msg = commit_message || "Changed version number to #{version}"
355
+ msg = msg.call(version) if Proc === msg
356
+ msg
357
+ end
358
+
359
+ def update_version_to_next
360
+ update_buildfile
361
+ end
362
+ end
363
+
364
+
365
+ class GitRelease < Release
366
+ class << self
367
+ def applies_to?(directory = '.')
368
+ File.exist? File.join(directory, '.git/config')
296
369
  end
297
370
  end
371
+
372
+ # Fails if one of theses 2 conditions are not met:
373
+ # 1. the repository is clean: no content staged or unstaged
374
+ # 2. some remote repositories are defined but the current branch does not track any
375
+ def check
376
+ uncommitted = Git.uncommitted_files
377
+ fail "Uncommitted files violate the First Principle Of Release!\n#{uncommitted.join("\n")}" unless uncommitted.empty?
378
+ fail "You are releasing from a local branch that does not track a remote!" unless Git.remote
379
+ end
380
+
381
+ # Add a tag reference in .git/refs/tags and push it to the remote if any.
382
+ # If a tag with the same name already exists it will get deleted (in both local and remote repositories).
383
+ def tag_release(tag)
384
+ info "Committing buildfile with version number #{extract_version}"
385
+ Git.commit File.basename(Buildr.application.buildfile.to_s), message
386
+ Git.push if Git.remote
387
+ info "Tagging release #{tag}"
388
+ Git.git 'tag', '-d', tag rescue nil
389
+ Git.git 'push', Git.remote, ":refs/tags/#{tag}" rescue nil if Git.remote
390
+ Git.git 'tag', '-a', tag, '-m', "[buildr] Cutting release #{tag}"
391
+ Git.git 'push', Git.remote, 'tag', tag if Git.remote
392
+ end
393
+
394
+ def update_version_to_next
395
+ super
396
+ info "Current version is now #{extract_version}"
397
+ Git.commit File.basename(Buildr.application.buildfile.to_s), message
398
+ Git.push if Git.remote
399
+ end
298
400
  end
401
+
299
402
 
403
+ class SvnRelease < Release
404
+ class << self
405
+ def applies_to?(directory = '.')
406
+ File.exist? File.join(directory, '.svn')
407
+ end
408
+ end
409
+
410
+ def check
411
+ fail "Uncommitted files violate the First Principle Of Release!\n"+Svn.uncommitted_files.join("\n") unless Svn.uncommitted_files.empty?
412
+ fail "SVN URL must contain 'trunk' or 'branches/...'" unless Svn.repo_url =~ /(trunk)|(branches.*)$/
413
+ end
414
+
415
+ def tag_release(tag)
416
+ info "Tagging release #{tag}"
417
+ Svn.tag tag
418
+ end
419
+
420
+ def update_version_to_next
421
+ super
422
+ info "Current version is now #{extract_version}"
423
+ Svn.commit Buildr.application.buildfile.to_s, message
424
+ end
425
+ end
300
426
 
427
+ Release.add SvnRelease
428
+ Release.add GitRelease
429
+
301
430
  desc 'Make a release'
302
431
  task 'release' do |task|
303
- Release.make
432
+ klass = Release.list.detect { |impl| impl.applies_to? }
433
+ fail 'Unable to detect the Version Control System.' unless klass
434
+ klass.new.make
304
435
  end
305
436
 
306
437
  end