buildr 1.3.5-x86-mswin32

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 (186) hide show
  1. data/CHANGELOG +998 -0
  2. data/LICENSE +176 -0
  3. data/NOTICE +26 -0
  4. data/README.rdoc +134 -0
  5. data/Rakefile +45 -0
  6. data/_buildr +29 -0
  7. data/_jbuildr +29 -0
  8. data/addon/buildr/antlr.rb +65 -0
  9. data/addon/buildr/cobertura.rb +22 -0
  10. data/addon/buildr/drb.rb +281 -0
  11. data/addon/buildr/emma.rb +22 -0
  12. data/addon/buildr/hibernate.rb +142 -0
  13. data/addon/buildr/javacc.rb +85 -0
  14. data/addon/buildr/jdepend.rb +60 -0
  15. data/addon/buildr/jetty.rb +248 -0
  16. data/addon/buildr/jibx.rb +86 -0
  17. data/addon/buildr/nailgun.rb +221 -0
  18. data/addon/buildr/openjpa.rb +90 -0
  19. data/addon/buildr/org/apache/buildr/BuildrNail$Main.class +0 -0
  20. data/addon/buildr/org/apache/buildr/BuildrNail.class +0 -0
  21. data/addon/buildr/org/apache/buildr/BuildrNail.java +41 -0
  22. data/addon/buildr/org/apache/buildr/JettyWrapper$1.class +0 -0
  23. data/addon/buildr/org/apache/buildr/JettyWrapper$BuildrHandler.class +0 -0
  24. data/addon/buildr/org/apache/buildr/JettyWrapper.class +0 -0
  25. data/addon/buildr/org/apache/buildr/JettyWrapper.java +144 -0
  26. data/addon/buildr/xmlbeans.rb +93 -0
  27. data/bin/buildr +19 -0
  28. data/buildr.buildfile +58 -0
  29. data/buildr.gemspec +65 -0
  30. data/doc/_config.yml +1 -0
  31. data/doc/_layouts/default.html +88 -0
  32. data/doc/_layouts/preface.html +22 -0
  33. data/doc/artifacts.textile +211 -0
  34. data/doc/building.textile +244 -0
  35. data/doc/contributing.textile +252 -0
  36. data/doc/css/default.css +236 -0
  37. data/doc/css/print.css +101 -0
  38. data/doc/css/syntax.css +23 -0
  39. data/doc/download.textile +79 -0
  40. data/doc/extending.textile +186 -0
  41. data/doc/images/1442160941-frontcover.jpg +0 -0
  42. data/doc/images/asf-logo.gif +0 -0
  43. data/doc/images/asf-logo.png +0 -0
  44. data/doc/images/buildr-hires.png +0 -0
  45. data/doc/images/buildr.png +0 -0
  46. data/doc/images/favicon.png +0 -0
  47. data/doc/images/growl-icon.tiff +0 -0
  48. data/doc/images/note.png +0 -0
  49. data/doc/images/project-structure.png +0 -0
  50. data/doc/images/tip.png +0 -0
  51. data/doc/images/zbuildr.png +0 -0
  52. data/doc/images/zbuildr.tif +0 -0
  53. data/doc/index.textile +69 -0
  54. data/doc/installing.textile +266 -0
  55. data/doc/languages.textile +459 -0
  56. data/doc/mailing_lists.textile +25 -0
  57. data/doc/more_stuff.textile +457 -0
  58. data/doc/packaging.textile +430 -0
  59. data/doc/preface.textile +54 -0
  60. data/doc/projects.textile +271 -0
  61. data/doc/quick_start.textile +210 -0
  62. data/doc/scripts/buildr-git.rb +512 -0
  63. data/doc/scripts/gitflow.rb +296 -0
  64. data/doc/scripts/install-jruby.sh +44 -0
  65. data/doc/scripts/install-linux.sh +72 -0
  66. data/doc/scripts/install-osx.sh +52 -0
  67. data/doc/settings_profiles.textile +280 -0
  68. data/doc/testing.textile +222 -0
  69. data/etc/KEYS +151 -0
  70. data/lib/buildr.rb +36 -0
  71. data/lib/buildr/core.rb +35 -0
  72. data/lib/buildr/core/application.rb +656 -0
  73. data/lib/buildr/core/build.rb +452 -0
  74. data/lib/buildr/core/checks.rb +254 -0
  75. data/lib/buildr/core/common.rb +150 -0
  76. data/lib/buildr/core/compile.rb +608 -0
  77. data/lib/buildr/core/environment.rb +129 -0
  78. data/lib/buildr/core/filter.rb +362 -0
  79. data/lib/buildr/core/generate.rb +195 -0
  80. data/lib/buildr/core/help.rb +119 -0
  81. data/lib/buildr/core/osx.rb +46 -0
  82. data/lib/buildr/core/progressbar.rb +156 -0
  83. data/lib/buildr/core/project.rb +866 -0
  84. data/lib/buildr/core/shell.rb +198 -0
  85. data/lib/buildr/core/test.rb +723 -0
  86. data/lib/buildr/core/transports.rb +559 -0
  87. data/lib/buildr/core/util.rb +449 -0
  88. data/lib/buildr/groovy.rb +19 -0
  89. data/lib/buildr/groovy/bdd.rb +106 -0
  90. data/lib/buildr/groovy/compiler.rb +138 -0
  91. data/lib/buildr/groovy/shell.rb +48 -0
  92. data/lib/buildr/ide.rb +19 -0
  93. data/lib/buildr/ide/eclipse.rb +334 -0
  94. data/lib/buildr/ide/eclipse/java.rb +53 -0
  95. data/lib/buildr/ide/eclipse/plugin.rb +68 -0
  96. data/lib/buildr/ide/eclipse/scala.rb +66 -0
  97. data/lib/buildr/ide/idea.ipr.template +300 -0
  98. data/lib/buildr/ide/idea.rb +190 -0
  99. data/lib/buildr/ide/idea7x.ipr.template +290 -0
  100. data/lib/buildr/ide/idea7x.rb +212 -0
  101. data/lib/buildr/java.rb +23 -0
  102. data/lib/buildr/java/ant.rb +94 -0
  103. data/lib/buildr/java/bdd.rb +459 -0
  104. data/lib/buildr/java/cobertura.rb +274 -0
  105. data/lib/buildr/java/commands.rb +213 -0
  106. data/lib/buildr/java/compiler.rb +349 -0
  107. data/lib/buildr/java/deprecated.rb +141 -0
  108. data/lib/buildr/java/emma.rb +244 -0
  109. data/lib/buildr/java/jruby.rb +117 -0
  110. data/lib/buildr/java/jtestr_runner.rb.erb +116 -0
  111. data/lib/buildr/java/org/apache/buildr/JavaTestFilter.class +0 -0
  112. data/lib/buildr/java/org/apache/buildr/JavaTestFilter.java +137 -0
  113. data/lib/buildr/java/packaging.rb +716 -0
  114. data/lib/buildr/java/pom.rb +174 -0
  115. data/lib/buildr/java/rjb.rb +155 -0
  116. data/lib/buildr/java/test_result.rb +353 -0
  117. data/lib/buildr/java/tests.rb +333 -0
  118. data/lib/buildr/java/version_requirement.rb +172 -0
  119. data/lib/buildr/packaging.rb +24 -0
  120. data/lib/buildr/packaging/archive.rb +488 -0
  121. data/lib/buildr/packaging/artifact.rb +749 -0
  122. data/lib/buildr/packaging/artifact_namespace.rb +972 -0
  123. data/lib/buildr/packaging/artifact_search.rb +140 -0
  124. data/lib/buildr/packaging/gems.rb +102 -0
  125. data/lib/buildr/packaging/package.rb +238 -0
  126. data/lib/buildr/packaging/tar.rb +186 -0
  127. data/lib/buildr/packaging/version_requirement.rb +172 -0
  128. data/lib/buildr/packaging/zip.rb +73 -0
  129. data/lib/buildr/packaging/ziptask.rb +316 -0
  130. data/lib/buildr/resources/buildr.icns +0 -0
  131. data/lib/buildr/scala.rb +25 -0
  132. data/lib/buildr/scala/bdd.rb +109 -0
  133. data/lib/buildr/scala/compiler.rb +195 -0
  134. data/lib/buildr/scala/org/apache/buildr/SpecsSingletonRunner$.class +0 -0
  135. data/lib/buildr/scala/org/apache/buildr/SpecsSingletonRunner.class +0 -0
  136. data/lib/buildr/scala/org/apache/buildr/SpecsSingletonRunner.scala +35 -0
  137. data/lib/buildr/scala/shell.rb +55 -0
  138. data/lib/buildr/scala/tests.rb +157 -0
  139. data/lib/buildr/shell.rb +180 -0
  140. data/rakelib/checks.rake +57 -0
  141. data/rakelib/doc.rake +92 -0
  142. data/rakelib/jekylltask.rb +120 -0
  143. data/rakelib/package.rake +73 -0
  144. data/rakelib/release.rake +149 -0
  145. data/rakelib/rspec.rake +73 -0
  146. data/rakelib/setup.rake +54 -0
  147. data/rakelib/stage.rake +213 -0
  148. data/rakelib/stage.rake~ +213 -0
  149. data/spec/addon/drb_spec.rb +328 -0
  150. data/spec/core/application_spec.rb +502 -0
  151. data/spec/core/build_spec.rb +677 -0
  152. data/spec/core/checks_spec.rb +519 -0
  153. data/spec/core/common_spec.rb +670 -0
  154. data/spec/core/compile_spec.rb +583 -0
  155. data/spec/core/extension_spec.rb +93 -0
  156. data/spec/core/generate_spec.rb +33 -0
  157. data/spec/core/project_spec.rb +762 -0
  158. data/spec/core/test_spec.rb +1098 -0
  159. data/spec/core/transport_spec.rb +537 -0
  160. data/spec/core/util_spec.rb +67 -0
  161. data/spec/groovy/bdd_spec.rb +80 -0
  162. data/spec/groovy/compiler_spec.rb +240 -0
  163. data/spec/ide/eclipse_spec.rb +501 -0
  164. data/spec/ide/idea7x_spec.rb +84 -0
  165. data/spec/java/ant_spec.rb +33 -0
  166. data/spec/java/bdd_spec.rb +382 -0
  167. data/spec/java/cobertura_spec.rb +85 -0
  168. data/spec/java/compiler_spec.rb +446 -0
  169. data/spec/java/emma_spec.rb +119 -0
  170. data/spec/java/java_spec.rb +124 -0
  171. data/spec/java/packaging_spec.rb +1134 -0
  172. data/spec/java/test_coverage_helper.rb +257 -0
  173. data/spec/java/tests_spec.rb +493 -0
  174. data/spec/packaging/archive_spec.rb +527 -0
  175. data/spec/packaging/artifact_namespace_spec.rb +654 -0
  176. data/spec/packaging/artifact_spec.rb +795 -0
  177. data/spec/packaging/packaging_helper.rb +63 -0
  178. data/spec/packaging/packaging_spec.rb +684 -0
  179. data/spec/sandbox.rb +142 -0
  180. data/spec/scala/bdd_spec.rb +119 -0
  181. data/spec/scala/compiler_spec.rb +284 -0
  182. data/spec/scala/scala.rb +38 -0
  183. data/spec/scala/tests_spec.rb +261 -0
  184. data/spec/spec_helpers.rb +340 -0
  185. data/spec/version_requirement_spec.rb +129 -0
  186. metadata +383 -0
@@ -0,0 +1,749 @@
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 'buildr/core/project'
18
+ require 'buildr/core/transports'
19
+ require 'buildr/packaging/artifact_namespace'
20
+
21
+
22
+ module Buildr
23
+
24
+ desc 'Download all artifacts'
25
+ task 'artifacts'
26
+
27
+ desc "Download all artifacts' sources"
28
+ task 'artifacts:sources'
29
+
30
+ # Mixin with a task to make it behave like an artifact. Implemented by the packaging tasks.
31
+ #
32
+ # An artifact has an identifier, group identifier, type, version number and
33
+ # optional classifier. All can be used to locate it in the local repository,
34
+ # download from or upload to a remote repository.
35
+ #
36
+ # The #to_spec and #to_hash methods allow it to be used everywhere an artifact is
37
+ # accepted.
38
+ module ActsAsArtifact
39
+
40
+ ARTIFACT_ATTRIBUTES = [:group, :id, :type, :classifier, :version]
41
+
42
+ class << self
43
+ private
44
+ def included(mod)
45
+ mod.extend self
46
+ end
47
+ end
48
+
49
+ # The artifact identifier.
50
+ attr_reader :id
51
+ # The group identifier.
52
+ attr_reader :group
53
+ # The file type. (Symbol)
54
+ attr_reader :type
55
+ # The version number.
56
+ attr_reader :version
57
+ # Optional artifact classifier.
58
+ attr_reader :classifier
59
+
60
+ def snapshot?
61
+ version =~ /-SNAPSHOT$/
62
+ end
63
+
64
+ # :call-seq:
65
+ # to_spec_hash => Hash
66
+ #
67
+ # Returns the artifact specification as a hash. For example:
68
+ # com.example:app:jar:1.2
69
+ # becomes:
70
+ # { :group=>'com.example',
71
+ # :id=>'app',
72
+ # :type=>:jar,
73
+ # :version=>'1.2' }
74
+ def to_spec_hash
75
+ base = { :group=>group, :id=>id, :type=>type, :version=>version }
76
+ classifier ? base.merge(:classifier=>classifier) : base
77
+ end
78
+ alias_method :to_hash, :to_spec_hash
79
+
80
+ # :call-seq:
81
+ # to_spec => String
82
+ #
83
+ # Returns the artifact specification, in the structure:
84
+ # <group>:<artifact>:<type>:<version>
85
+ # or
86
+ # <group>:<artifact>:<type>:<classifier>:<version>
87
+ def to_spec
88
+ classifier ? "#{group}:#{id}:#{type}:#{classifier}:#{version}" : "#{group}:#{id}:#{type}:#{version}"
89
+ end
90
+
91
+ # :call-seq:
92
+ # pom => Artifact
93
+ #
94
+ # Convenience method that returns a POM artifact.
95
+ def pom
96
+ return self if type == :pom
97
+ Buildr.artifact(:group=>group, :id=>id, :version=>version, :type=>:pom)
98
+ end
99
+
100
+ # :call-seq:
101
+ # sources_artifact => Artifact
102
+ #
103
+ # Convenience method that returns a sources artifact.
104
+ def sources_artifact
105
+ sources_spec = to_spec_hash.merge(:classifier=>'sources')
106
+ sources_task = OptionalArtifact.define_task(Buildr.repositories.locate(sources_spec))
107
+ sources_task.send :apply_spec, sources_spec
108
+ sources_task
109
+ end
110
+
111
+ # :call-seq:
112
+ # pom_xml => string
113
+ #
114
+ # Creates POM XML for this artifact.
115
+ def pom_xml
116
+ xml = Builder::XmlMarkup.new(:indent=>2)
117
+ xml.instruct!
118
+ xml.project do
119
+ xml.modelVersion '4.0.0'
120
+ xml.groupId group
121
+ xml.artifactId id
122
+ xml.version version
123
+ xml.classifier classifier if classifier
124
+ end
125
+ end
126
+
127
+ def install
128
+ pom.install if pom && pom != self
129
+ invoke
130
+ installed = Buildr.repositories.locate(self)
131
+ unless installed == name # If not already in local repository.
132
+ mkpath File.dirname(installed)
133
+ cp name, installed
134
+ info "Installed #{installed}"
135
+ end
136
+ end
137
+
138
+ def uninstall
139
+ installed = Buildr.repositories.locate(self)
140
+ rm installed if File.exist?(installed)
141
+ pom.uninstall if pom && pom != self
142
+ end
143
+
144
+ # :call-seq:
145
+ # upload
146
+ # upload(url)
147
+ # upload(options)
148
+ #
149
+ # Uploads the artifact, its POM and digital signatures to remote server.
150
+ #
151
+ # In the first form, uses the upload options specified by repositories.release_to.
152
+ # In the second form, uses a URL that includes all the relevant information.
153
+ # In the third form, uses a hash with the options :url, :username, :password,
154
+ # and :permissions. All but :url are optional.
155
+ def upload(upload_to = nil)
156
+ # Where do we release to?
157
+ upload_to ||= Buildr.repositories.release_to
158
+ upload_to = { :url=>upload_to } unless Hash === upload_to
159
+ raise ArgumentError, 'Don\'t know where to upload, perhaps you forgot to set repositories.release_to' unless upload_to[:url]
160
+ invoke # Make sure we exist.
161
+
162
+ # Upload POM ahead of package, so we don't fail and find POM-less package (the horror!)
163
+ pom.upload(upload_to) if pom && pom != self
164
+
165
+ # Set the upload URI, including mandatory slash (we expect it to be the base directory).
166
+ # Username/password may be part of URI, or separate entities.
167
+ uri = URI.parse(upload_to[:url].clone)
168
+ uri.path = uri.path + '/' unless uri.path[-1] == '/'
169
+ uri.user = upload_to[:username] if upload_to[:username]
170
+ uri.password = upload_to[:password] if upload_to[:password]
171
+
172
+ # Upload artifact relative to base URL, need to create path before uploading.
173
+ info "Deploying #{to_spec}"
174
+ path = group.gsub('.', '/') + "/#{id}/#{version}/#{File.basename(name)}"
175
+ URI.upload uri + path, name, :permissions=>upload_to[:permissions]
176
+ end
177
+
178
+ protected
179
+
180
+ # Apply specification to this artifact.
181
+ def apply_spec(spec)
182
+ spec = Artifact.to_hash(spec)
183
+ ARTIFACT_ATTRIBUTES.each { |key| instance_variable_set("@#{key}", spec[key]) }
184
+ self
185
+ end
186
+
187
+ def group_path
188
+ group.gsub('.', '/')
189
+ end
190
+
191
+ end
192
+
193
+
194
+ # A file task referencing an artifact in the local repository.
195
+ #
196
+ # This task includes all the artifact attributes (group, id, version, etc). It points
197
+ # to the artifact's path in the local repository. When invoked, it will download the
198
+ # artifact into the local repository if the artifact does not already exist.
199
+ #
200
+ # Note: You can enhance this task to create the artifact yourself, e.g. download it from
201
+ # a site that doesn't have a remote repository structure, copy it from a different disk, etc.
202
+ class Artifact < Rake::FileCreationTask
203
+
204
+ # The default artifact type.
205
+ DEFAULT_TYPE = :jar
206
+
207
+ include ActsAsArtifact
208
+
209
+ class << self
210
+
211
+ # :call-seq:
212
+ # lookup(spec) => Artifact
213
+ #
214
+ # Lookup a previously registered artifact task based on its specification (String or Hash).
215
+ def lookup(spec)
216
+ @artifacts ||= {}
217
+ @artifacts[to_spec(spec)]
218
+ end
219
+
220
+ # :call-seq:
221
+ # list => specs
222
+ #
223
+ # Returns an array of specs for all the registered artifacts. (Anything created from artifact, or package).
224
+ def list
225
+ @artifacts ||= {}
226
+ @artifacts.keys
227
+ end
228
+
229
+ # :call-seq:
230
+ # register(artifacts) => artifacts
231
+ #
232
+ # Register an artifact task(s) for later lookup (see #lookup).
233
+ def register(*tasks)
234
+ @artifacts ||= {}
235
+ fail 'You can only register an artifact task, one of the arguments is not a Task that responds to to_spec' unless
236
+ tasks.all? { |task| task.respond_to?(:to_spec) && task.respond_to?(:invoke) }
237
+ tasks.each { |task| @artifacts[task.to_spec] = task }
238
+ tasks
239
+ end
240
+
241
+ # :call-seq:
242
+ # to_hash(spec_hash) => spec_hash
243
+ # to_hash(spec_string) => spec_hash
244
+ # to_hash(artifact) => spec_hash
245
+ #
246
+ # Turn a spec into a hash. This method accepts a String, Hash or any object that responds to
247
+ # the method to_spec. There are several reasons to use this method:
248
+ # * You can pass anything that could possibly be a spec, and get a hash.
249
+ # * It will check that the spec includes the group identifier, artifact
250
+ # identifier and version number and set the file type, if missing.
251
+ # * It will always return a new specs hash.
252
+ def to_hash(spec)
253
+ if spec.respond_to?(:to_spec)
254
+ to_hash spec.to_spec
255
+ elsif Hash === spec
256
+ rake_check_options spec, :id, :group, :type, :classifier, :version
257
+ # Sanitize the hash and check it's valid.
258
+ spec = ARTIFACT_ATTRIBUTES.inject({}) { |h, k| h[k] = spec[k].to_s if spec[k] ; h }
259
+ fail "Missing group identifier for #{spec.inspect}" unless spec[:group]
260
+ fail "Missing artifact identifier for #{spec.inspect}" unless spec[:id]
261
+ fail "Missing version for #{spec.inspect}" unless spec[:version]
262
+ spec[:type] = (spec[:type] || DEFAULT_TYPE).to_sym
263
+ spec
264
+ elsif String === spec
265
+ group, id, type, version, *rest = spec.split(':').map { |part| part.empty? ? nil : part }
266
+ unless rest.empty?
267
+ # Optional classifier comes before version.
268
+ classifier, version = version, rest.shift
269
+ fail "Expecting <group:id:type:version> or <group:id:type:classifier:version>, found <#{spec}>" unless rest.empty?
270
+ end
271
+ to_hash :group=>group, :id=>id, :type=>type, :version=>version, :classifier=>classifier
272
+ else
273
+ fail 'Expecting a String, Hash or object that responds to to_spec'
274
+ end
275
+ end
276
+
277
+ # :call-seq:
278
+ # to_spec(spec_hash) => spec_string
279
+ #
280
+ # Convert a hash back to a spec string. This method accepts
281
+ # a string, hash or any object that responds to to_spec.
282
+ def to_spec(hash)
283
+ hash = to_hash(hash) unless Hash === hash
284
+ version = ":#{hash[:version]}" if hash[:version]
285
+ classifier = ":#{hash[:classifier]}" if hash[:classifier]
286
+ "#{hash[:group]}:#{hash[:id]}:#{hash[:type] || DEFAULT_TYPE}#{classifier}#{version}"
287
+ end
288
+
289
+ # :call-seq:
290
+ # hash_to_file_name(spec_hash) => file_name
291
+ #
292
+ # Convert a hash spec to a file name.
293
+ def hash_to_file_name(hash)
294
+ version = "-#{hash[:version]}" if hash[:version]
295
+ classifier = "-#{hash[:classifier]}" if hash[:classifier]
296
+ "#{hash[:id]}#{version}#{classifier}.#{hash[:type] || DEFAULT_TYPE}"
297
+ end
298
+
299
+ end
300
+
301
+ def initialize(*args) #:nodoc:
302
+ super
303
+ enhance do |task|
304
+ # Default behavior: download the artifact from one of the remote repositories
305
+ # if the file does not exist. But this default behavior is counter productive
306
+ # if the artifact knows how to build itself (e.g. download from a different location),
307
+ # so don't perform it if the task found a different way to create the artifact.
308
+ task.enhance do
309
+ unless File.exist?(name)
310
+ info "Downloading #{to_spec}"
311
+ download
312
+ pom.invoke rescue nil if pom && pom != self
313
+ end
314
+ end
315
+ end
316
+ end
317
+
318
+ # :call-seq:
319
+ # from(path) => self
320
+ #
321
+ # Use this when you want to install or upload an artifact from a given file, for example:
322
+ # test = artifact('group:id:jar:1.0').from('test.jar')
323
+ # install test
324
+ # See also Buildr#install and Buildr#upload.
325
+ def from(path)
326
+ path = File.expand_path(path.to_s)
327
+ enhance [path] do
328
+ mkpath File.dirname(name)
329
+ pom.invoke unless type == :pom
330
+ cp path, name
331
+ info "Installed #{path} as #{to_spec}"
332
+ end
333
+ unless type == :pom
334
+ pom.enhance do
335
+ mkpath File.dirname(pom.name)
336
+ File.open(pom.name, 'w') { |file| file.write pom.pom_xml }
337
+ end
338
+ end
339
+ self
340
+ end
341
+
342
+ protected
343
+
344
+ # :call-seq:
345
+ # download
346
+ #
347
+ # Downloads an artifact from one of the remote repositories, and stores it in the local
348
+ # repository. Raises an exception if the artifact is not found.
349
+ #
350
+ # This method attempts to download the artifact from each repository in the order in
351
+ # which they are returned from #remote, until successful.
352
+ def download
353
+ trace "Downloading #{to_spec}"
354
+ remote = Buildr.repositories.remote.map { |repo_url| URI === repo_url ? repo_url : URI.parse(repo_url) }
355
+ remote = remote.each { |repo_url| repo_url.path += '/' unless repo_url.path[-1] == '/' }
356
+ fail 'No remote repositories defined!' if remote.empty?
357
+ exact_success = remote.find do |repo_url|
358
+ begin
359
+ path = "#{group_path}/#{id}/#{version}/#{File.basename(name)}"
360
+ URI.download repo_url + path, name
361
+ true
362
+ rescue URI::NotFoundError
363
+ false
364
+ rescue Exception=>error
365
+ info error
366
+ trace error.backtrace.join("\n")
367
+ false
368
+ end
369
+ end
370
+
371
+ if exact_success
372
+ return
373
+ elsif snapshot?
374
+ download_m2_snapshot(remote)
375
+ else
376
+ fail_download(remote)
377
+ end
378
+ end
379
+
380
+ def download_m2_snapshot(remote_uris)
381
+ remote_uris.find do |repo_url|
382
+ snapshot_url = current_snapshot_repo_url(repo_url)
383
+ if snapshot_url
384
+ begin
385
+ URI.download snapshot_url, name
386
+ rescue URI::NotFoundError
387
+ false
388
+ end
389
+ else
390
+ false
391
+ end
392
+ end or fail_download(remote_uris)
393
+ end
394
+
395
+ def current_snapshot_repo_url(repo_url)
396
+ begin
397
+ metadata_path = "#{group_path}/#{id}/#{version}/maven-metadata.xml"
398
+ metadata_xml = StringIO.new
399
+ URI.download repo_url + metadata_path, metadata_xml
400
+ metadata = REXML::Document.new(metadata_xml.string).root
401
+ timestamp = REXML::XPath.first(metadata, '//timestamp').text
402
+ build_number = REXML::XPath.first(metadata, '//buildNumber').text
403
+ snapshot_of = version[0, version.size - 9]
404
+ repo_url + "#{group_path}/#{id}/#{version}/#{id}-#{snapshot_of}-#{timestamp}-#{build_number}.#{type}"
405
+ rescue URI::NotFoundError
406
+ nil
407
+ end
408
+ end
409
+
410
+ def fail_download(remote_uris)
411
+ fail "Failed to download #{to_spec}, tried the following repositories:\n#{remote_uris.join("\n")}"
412
+ end
413
+ end
414
+
415
+
416
+ # An artifact that is optional.
417
+ # If downloading fails, the user will be informed but it will not raise an exception.
418
+ class OptionalArtifact < Artifact
419
+
420
+ protected
421
+
422
+ # If downloading fails, the user will be informed but it will not raise an exception.
423
+ def download
424
+ super
425
+ rescue
426
+ info "Failed to download #{to_spec}. Skipping it."
427
+ end
428
+
429
+ end
430
+
431
+
432
+ # Holds the path to the local repository, URLs for remote repositories, and settings for release server.
433
+ #
434
+ # You can access this object from the #repositories method. For example:
435
+ # puts repositories.local
436
+ # repositories.remote << 'http://example.com/repo'
437
+ # repositories.release_to = 'sftp://example.com/var/www/public/repo'
438
+ class Repositories
439
+ include Singleton
440
+
441
+ # :call-seq:
442
+ # local => path
443
+ #
444
+ # Returns the path to the local repository.
445
+ #
446
+ # The default path is .m2/repository relative to the home directory.
447
+ # You can set this using the M2_REPO environment variable or the repositories/local
448
+ # value in your settings.yaml file.
449
+ def local
450
+ @local ||= File.expand_path(ENV['M2_REPO'] || ENV['local_repo'] ||
451
+ (Buildr.settings.user['repositories'] && Buildr.settings.user['repositories']['local']) ||
452
+ File.join(ENV['HOME'], '.m2/repository'))
453
+ end
454
+
455
+ # :call-seq:
456
+ # local = path
457
+ #
458
+ # Sets the path to the local repository.
459
+ #
460
+ # The best place to set the local repository path is from a buildr.rb file
461
+ # located in your home directory. That way all your projects will share the same
462
+ # path, without affecting other developers collaborating on these projects.
463
+ def local=(dir)
464
+ @local = dir ? File.expand_path(dir) : nil
465
+ end
466
+
467
+ # :call-seq:
468
+ # locate(spec) => path
469
+ #
470
+ # Locates an artifact in the local repository based on its specification, and returns
471
+ # a file path.
472
+ #
473
+ # For example:
474
+ # locate :group=>'log4j', :id=>'log4j', :version=>'1.1'
475
+ # => ~/.m2/repository/log4j/log4j/1.1/log4j-1.1.jar
476
+ def locate(spec)
477
+ spec = Artifact.to_hash(spec)
478
+ File.join(local, spec[:group].split('.'), spec[:id], spec[:version], Artifact.hash_to_file_name(spec))
479
+ end
480
+
481
+ # :call-seq:
482
+ # remote => Array
483
+ #
484
+ # Returns an array of all the remote repository URLs.
485
+ #
486
+ # When downloading artifacts, repositories are accessed in the order in which they appear here.
487
+ # The best way is to add repositories individually, for example:
488
+ # repositories.remote << 'http://example.com/repo'
489
+ #
490
+ # You can also specify remote repositories in the settings.yaml (per user) and build.yaml (per build)
491
+ # files. Both sets of URLs are loaded by default into this array, URLs from the personal setting
492
+ # showing first.
493
+ #
494
+ # For example:
495
+ # repositories:
496
+ # remote:
497
+ # - http://example.com/repo
498
+ # - http://elsewhere.com/repo
499
+ def remote
500
+ unless @remote
501
+ @remote = [Buildr.settings.user, Buildr.settings.build].inject([]) { |repos, hash|
502
+ repos | Array(hash['repositories'] && hash['repositories']['remote'])
503
+ }
504
+ end
505
+ @remote
506
+ end
507
+
508
+ # :call-seq:
509
+ # remote = Array
510
+ # remote = url
511
+ # remote = nil
512
+ #
513
+ # With a String argument, clears the array and set it to that single URL.
514
+ #
515
+ # With an Array argument, clears the array and set it to these specific URLs.
516
+ #
517
+ # With nil, clears the array.
518
+ def remote=(urls)
519
+ case urls
520
+ when nil then @remote = nil
521
+ when Array then @remote = urls.dup
522
+ else @remote = [urls.to_s]
523
+ end
524
+ end
525
+
526
+ # :call-seq:
527
+ # release_to = url
528
+ # release_to = hash
529
+ #
530
+ # Specifies the release server. Accepts a Hash with different repository settings
531
+ # (e.g. url, username, password), or a String to only set the repository URL.
532
+ #
533
+ # Besides the URL, all other settings depend on the transport protocol in use.
534
+ #
535
+ # For example:
536
+ # repositories.release_to = 'sftp://john:secret@example.com/var/www/repo/'
537
+ #
538
+ # repositories.release_to = { :url=>'sftp://example.com/var/www/repo/',
539
+ # :username='john', :password=>'secret' }
540
+ # Or in the settings.yaml file:
541
+ # repositories:
542
+ # release_to: sftp://john:secret@example.com/var/www/repo/
543
+ #
544
+ # repositories:
545
+ # release_to:
546
+ # url: sftp://example.com/var/www/repo/
547
+ # username: john
548
+ # password: secret
549
+ def release_to=(options)
550
+ options = { :url=>options } unless Hash === options
551
+ @release_to = options
552
+ end
553
+
554
+ # :call-seq:
555
+ # release_to => hash
556
+ #
557
+ # Returns the current release server setting as a Hash. This is a more convenient way to
558
+ # configure the settings, as it allows you to specify the settings progressively.
559
+ #
560
+ # For example, the Buildfile will contain the repository URL used by all developers:
561
+ # repositories.release_to[:url] ||= 'sftp://example.com/var/www/repo'
562
+ # Your private buildr.rb will contain your credentials:
563
+ # repositories.release_to[:username] = 'john'
564
+ # repositories.release_to[:password] = 'secret'
565
+ def release_to
566
+ unless @release_to
567
+ value = Buildr.settings.user['repositories'] && Buildr.settings.user['repositories']['release_to']
568
+ @release_to = Hash === value ? value.inject({}) { |hash, (key, value)| hash.update(key.to_sym=>value) } : { :url=>Array(value).first }
569
+ end
570
+ @release_to
571
+ end
572
+
573
+ end
574
+
575
+ # :call-seq:
576
+ # repositories => Repositories
577
+ #
578
+ # Returns an object you can use for setting the local repository path, remote repositories
579
+ # URL and release server settings.
580
+ #
581
+ # See Repositories.
582
+ def repositories
583
+ Repositories.instance
584
+ end
585
+
586
+ # :call-seq:
587
+ # artifact(spec) => Artifact
588
+ # artifact(spec) { |task| ... } => Artifact
589
+ #
590
+ # Creates a file task to download and install the specified artifact in the local repository.
591
+ #
592
+ # You can use a String or a Hash for the artifact specification. The file task will point at
593
+ # the artifact's path inside the local repository. You can then use this tasks as a prerequisite
594
+ # for other tasks.
595
+ #
596
+ # This task will download and install the artifact only once. In fact, it will download and
597
+ # install the artifact if the artifact does not already exist. You can enhance it if you have
598
+ # a different way of creating the artifact in the local repository. See Artifact for more details.
599
+ #
600
+ # For example, to specify an artifact:
601
+ # artifact('log4j:log4j:jar:1.1')
602
+ #
603
+ # To use the artifact in a task:
604
+ # compile.with artifact('log4j:log4j:jar:1.1')
605
+ #
606
+ # To specify an artifact and the means for creating it:
607
+ # download(artifact('dojo:dojo-widget:zip:2.0')=>
608
+ # 'http://download.dojotoolkit.org/release-2.0/dojo-2.0-widget.zip')
609
+ def artifact(spec, &block) #:yields:task
610
+ spec = artifact_ns.fetch(spec) if spec.kind_of?(Symbol)
611
+ spec = Artifact.to_hash(spec)
612
+ unless task = Artifact.lookup(spec)
613
+ task = Artifact.define_task(repositories.locate(spec))
614
+ task.send :apply_spec, spec
615
+ Rake::Task['rake:artifacts'].enhance [task]
616
+ Artifact.register(task)
617
+ Rake::Task['artifacts:sources'].enhance [task.sources_artifact] unless spec[:type] == :pom
618
+ end
619
+ task.enhance &block
620
+ end
621
+
622
+ # :call-seq:
623
+ # artifacts(*spec) => artifacts
624
+ #
625
+ # Handles multiple artifacts at a time. This method is the plural equivalent of
626
+ # #artifact, but can do more things.
627
+ #
628
+ # Returns an array of artifacts built using the supplied
629
+ # specifications, each of which can be:
630
+ # * An artifact specification (String or Hash). Returns the appropriate Artifact task.
631
+ # * An artifact of any other task. Returns the task as is.
632
+ # * A project. Returns all artifacts created (packaged) by that project.
633
+ # * A string. Returns that string, assumed to be a file name.
634
+ # * An array of artifacts or a Struct.
635
+ # * A symbol. Returns the named artifact from the current ArtifactNamespace
636
+ #
637
+ # For example, handling a collection of artifacts:
638
+ # xml = [ xerces, xalan, jaxp ]
639
+ # ws = [ axis, jax-ws, jaxb ]
640
+ # db = [ jpa, mysql, sqltools ]
641
+ # artifacts(xml, ws, db)
642
+ #
643
+ # Using artifacts created by a project:
644
+ # artifacts project('my-app') # All packages
645
+ # artifacts project('my-app').package(:war) # Only the WAR
646
+ def artifacts(*specs, &block)
647
+ specs.flatten.inject([]) do |set, spec|
648
+ case spec
649
+ when ArtifactNamespace
650
+ set |= spec.artifacts
651
+ when Symbol, Hash
652
+ set |= [artifact(spec)]
653
+ when /([^:]+:){2,4}/ # A spec as opposed to a file name.
654
+ set |= [artifact(spec)]
655
+ when String # Must always expand path.
656
+ set |= [File.expand_path(spec)]
657
+ when Project
658
+ set |= artifacts(spec.packages)
659
+ when Rake::Task
660
+ set |= [spec]
661
+ when Struct
662
+ set |= artifacts(spec.values)
663
+ else
664
+ fail "Invalid artifact specification in #{specs.inspect}"
665
+ end
666
+ end
667
+ end
668
+
669
+ def transitive(*specs)
670
+ specs.flatten.inject([]) do |set, spec|
671
+ case spec
672
+ when /([^:]+:){2,4}/ # A spec as opposed to a file name.
673
+ artifact = artifact(spec)
674
+ set |= [artifact] unless artifact.type == :pom
675
+ set |= POM.load(artifact.pom).dependencies.map { |spec| artifact(spec) }
676
+ when Hash
677
+ set |= [transitive(spec)]
678
+ when String # Must always expand path.
679
+ set |= transitive(file(File.expand_path(spec)))
680
+ when Project
681
+ set |= transitive(spec.packages)
682
+ when Rake::Task
683
+ set |= spec.respond_to?(:to_spec) ? transitive(spec.to_spec) : [spec]
684
+ when Struct
685
+ set |= transitive(spec.values)
686
+ else
687
+ fail "Invalid artifact specification in: #{specs.to_s}"
688
+ end
689
+ end
690
+ end
691
+
692
+ # :call-seq:
693
+ # group(ids, :under=>group_name, :version=>number) => artifacts
694
+ #
695
+ # Convenience method for defining multiple artifacts that belong to the same group, type and version.
696
+ # Accepts multiple artifact identifiers followed by two or three hash values:
697
+ # * :under -- The group identifier
698
+ # * :version -- The version number
699
+ # * :type -- The artifact type (optional)
700
+ #
701
+ # For example:
702
+ # group 'xbean', 'xbean_xpath', 'xmlpublic', :under=>'xmlbeans', :version=>'2.1.0'
703
+ # Or:
704
+ # group %w{xbean xbean_xpath xmlpublic}, :under=>'xmlbeans', :version=>'2.1.0'
705
+ def group(*args)
706
+ hash = args.pop
707
+ args.flatten.map { |id| artifact :group=>hash[:under], :type=>hash[:type], :version=>hash[:version], :id=>id }
708
+ end
709
+
710
+ # :call-seq:
711
+ # install(artifacts)
712
+ #
713
+ # Installs the specified artifacts in the local repository as part of the install task.
714
+ #
715
+ # You can use this to install various files in the local repository, for example:
716
+ # install artifact('group:id:jar:1.0').from('some_jar.jar')
717
+ # $ buildr install
718
+ def install(*args, &block)
719
+ artifacts = artifacts(args)
720
+ raise ArgumentError, 'This method can only install artifacts' unless artifacts.all? { |f| f.respond_to?(:to_spec) }
721
+ all = (artifacts + artifacts.map { |artifact| artifact.pom }).uniq
722
+ task('install').tap do |task|
723
+ task.enhance all, &block
724
+ task 'uninstall' do
725
+ all.map(&:to_s ).each { |file| rm file if File.exist?(file) }
726
+ end
727
+ end
728
+ end
729
+
730
+ # :call-seq:
731
+ # upload(artifacts)
732
+ #
733
+ # Uploads the specified artifacts to the release server as part of the upload task.
734
+ #
735
+ # You can use this to upload various files to the release server, for example:
736
+ # upload artifact('group:id:jar:1.0').from('some_jar.jar')
737
+ # $ buildr upload
738
+ def upload(*args, &block)
739
+ artifacts = artifacts(args)
740
+ raise ArgumentError, 'This method can only upload artifacts' unless artifacts.all? { |f| f.respond_to?(:to_spec) }
741
+ task('upload').tap do |task|
742
+ task.enhance &block if block
743
+ task.enhance artifacts do
744
+ artifacts.each { |artifact| artifact.upload }
745
+ end
746
+ end
747
+ end
748
+
749
+ end