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.
- data/CHANGELOG +998 -0
- data/LICENSE +176 -0
- data/NOTICE +26 -0
- data/README.rdoc +134 -0
- data/Rakefile +45 -0
- data/_buildr +29 -0
- data/_jbuildr +29 -0
- data/addon/buildr/antlr.rb +65 -0
- data/addon/buildr/cobertura.rb +22 -0
- data/addon/buildr/drb.rb +281 -0
- data/addon/buildr/emma.rb +22 -0
- data/addon/buildr/hibernate.rb +142 -0
- data/addon/buildr/javacc.rb +85 -0
- data/addon/buildr/jdepend.rb +60 -0
- data/addon/buildr/jetty.rb +248 -0
- data/addon/buildr/jibx.rb +86 -0
- data/addon/buildr/nailgun.rb +221 -0
- data/addon/buildr/openjpa.rb +90 -0
- data/addon/buildr/org/apache/buildr/BuildrNail$Main.class +0 -0
- data/addon/buildr/org/apache/buildr/BuildrNail.class +0 -0
- data/addon/buildr/org/apache/buildr/BuildrNail.java +41 -0
- data/addon/buildr/org/apache/buildr/JettyWrapper$1.class +0 -0
- data/addon/buildr/org/apache/buildr/JettyWrapper$BuildrHandler.class +0 -0
- data/addon/buildr/org/apache/buildr/JettyWrapper.class +0 -0
- data/addon/buildr/org/apache/buildr/JettyWrapper.java +144 -0
- data/addon/buildr/xmlbeans.rb +93 -0
- data/bin/buildr +19 -0
- data/buildr.buildfile +58 -0
- data/buildr.gemspec +65 -0
- data/doc/_config.yml +1 -0
- data/doc/_layouts/default.html +88 -0
- data/doc/_layouts/preface.html +22 -0
- data/doc/artifacts.textile +211 -0
- data/doc/building.textile +244 -0
- data/doc/contributing.textile +252 -0
- data/doc/css/default.css +236 -0
- data/doc/css/print.css +101 -0
- data/doc/css/syntax.css +23 -0
- data/doc/download.textile +79 -0
- data/doc/extending.textile +186 -0
- data/doc/images/1442160941-frontcover.jpg +0 -0
- data/doc/images/asf-logo.gif +0 -0
- data/doc/images/asf-logo.png +0 -0
- data/doc/images/buildr-hires.png +0 -0
- data/doc/images/buildr.png +0 -0
- data/doc/images/favicon.png +0 -0
- data/doc/images/growl-icon.tiff +0 -0
- data/doc/images/note.png +0 -0
- data/doc/images/project-structure.png +0 -0
- data/doc/images/tip.png +0 -0
- data/doc/images/zbuildr.png +0 -0
- data/doc/images/zbuildr.tif +0 -0
- data/doc/index.textile +69 -0
- data/doc/installing.textile +266 -0
- data/doc/languages.textile +459 -0
- data/doc/mailing_lists.textile +25 -0
- data/doc/more_stuff.textile +457 -0
- data/doc/packaging.textile +430 -0
- data/doc/preface.textile +54 -0
- data/doc/projects.textile +271 -0
- data/doc/quick_start.textile +210 -0
- data/doc/scripts/buildr-git.rb +512 -0
- data/doc/scripts/gitflow.rb +296 -0
- data/doc/scripts/install-jruby.sh +44 -0
- data/doc/scripts/install-linux.sh +72 -0
- data/doc/scripts/install-osx.sh +52 -0
- data/doc/settings_profiles.textile +280 -0
- data/doc/testing.textile +222 -0
- data/etc/KEYS +151 -0
- data/lib/buildr.rb +36 -0
- data/lib/buildr/core.rb +35 -0
- data/lib/buildr/core/application.rb +656 -0
- data/lib/buildr/core/build.rb +452 -0
- data/lib/buildr/core/checks.rb +254 -0
- data/lib/buildr/core/common.rb +150 -0
- data/lib/buildr/core/compile.rb +608 -0
- data/lib/buildr/core/environment.rb +129 -0
- data/lib/buildr/core/filter.rb +362 -0
- data/lib/buildr/core/generate.rb +195 -0
- data/lib/buildr/core/help.rb +119 -0
- data/lib/buildr/core/osx.rb +46 -0
- data/lib/buildr/core/progressbar.rb +156 -0
- data/lib/buildr/core/project.rb +866 -0
- data/lib/buildr/core/shell.rb +198 -0
- data/lib/buildr/core/test.rb +723 -0
- data/lib/buildr/core/transports.rb +559 -0
- data/lib/buildr/core/util.rb +449 -0
- data/lib/buildr/groovy.rb +19 -0
- data/lib/buildr/groovy/bdd.rb +106 -0
- data/lib/buildr/groovy/compiler.rb +138 -0
- data/lib/buildr/groovy/shell.rb +48 -0
- data/lib/buildr/ide.rb +19 -0
- data/lib/buildr/ide/eclipse.rb +334 -0
- data/lib/buildr/ide/eclipse/java.rb +53 -0
- data/lib/buildr/ide/eclipse/plugin.rb +68 -0
- data/lib/buildr/ide/eclipse/scala.rb +66 -0
- data/lib/buildr/ide/idea.ipr.template +300 -0
- data/lib/buildr/ide/idea.rb +190 -0
- data/lib/buildr/ide/idea7x.ipr.template +290 -0
- data/lib/buildr/ide/idea7x.rb +212 -0
- data/lib/buildr/java.rb +23 -0
- data/lib/buildr/java/ant.rb +94 -0
- data/lib/buildr/java/bdd.rb +459 -0
- data/lib/buildr/java/cobertura.rb +274 -0
- data/lib/buildr/java/commands.rb +213 -0
- data/lib/buildr/java/compiler.rb +349 -0
- data/lib/buildr/java/deprecated.rb +141 -0
- data/lib/buildr/java/emma.rb +244 -0
- data/lib/buildr/java/jruby.rb +117 -0
- data/lib/buildr/java/jtestr_runner.rb.erb +116 -0
- data/lib/buildr/java/org/apache/buildr/JavaTestFilter.class +0 -0
- data/lib/buildr/java/org/apache/buildr/JavaTestFilter.java +137 -0
- data/lib/buildr/java/packaging.rb +716 -0
- data/lib/buildr/java/pom.rb +174 -0
- data/lib/buildr/java/rjb.rb +155 -0
- data/lib/buildr/java/test_result.rb +353 -0
- data/lib/buildr/java/tests.rb +333 -0
- data/lib/buildr/java/version_requirement.rb +172 -0
- data/lib/buildr/packaging.rb +24 -0
- data/lib/buildr/packaging/archive.rb +488 -0
- data/lib/buildr/packaging/artifact.rb +749 -0
- data/lib/buildr/packaging/artifact_namespace.rb +972 -0
- data/lib/buildr/packaging/artifact_search.rb +140 -0
- data/lib/buildr/packaging/gems.rb +102 -0
- data/lib/buildr/packaging/package.rb +238 -0
- data/lib/buildr/packaging/tar.rb +186 -0
- data/lib/buildr/packaging/version_requirement.rb +172 -0
- data/lib/buildr/packaging/zip.rb +73 -0
- data/lib/buildr/packaging/ziptask.rb +316 -0
- data/lib/buildr/resources/buildr.icns +0 -0
- data/lib/buildr/scala.rb +25 -0
- data/lib/buildr/scala/bdd.rb +109 -0
- data/lib/buildr/scala/compiler.rb +195 -0
- data/lib/buildr/scala/org/apache/buildr/SpecsSingletonRunner$.class +0 -0
- data/lib/buildr/scala/org/apache/buildr/SpecsSingletonRunner.class +0 -0
- data/lib/buildr/scala/org/apache/buildr/SpecsSingletonRunner.scala +35 -0
- data/lib/buildr/scala/shell.rb +55 -0
- data/lib/buildr/scala/tests.rb +157 -0
- data/lib/buildr/shell.rb +180 -0
- data/rakelib/checks.rake +57 -0
- data/rakelib/doc.rake +92 -0
- data/rakelib/jekylltask.rb +120 -0
- data/rakelib/package.rake +73 -0
- data/rakelib/release.rake +149 -0
- data/rakelib/rspec.rake +73 -0
- data/rakelib/setup.rake +54 -0
- data/rakelib/stage.rake +213 -0
- data/rakelib/stage.rake~ +213 -0
- data/spec/addon/drb_spec.rb +328 -0
- data/spec/core/application_spec.rb +502 -0
- data/spec/core/build_spec.rb +677 -0
- data/spec/core/checks_spec.rb +519 -0
- data/spec/core/common_spec.rb +670 -0
- data/spec/core/compile_spec.rb +583 -0
- data/spec/core/extension_spec.rb +93 -0
- data/spec/core/generate_spec.rb +33 -0
- data/spec/core/project_spec.rb +762 -0
- data/spec/core/test_spec.rb +1098 -0
- data/spec/core/transport_spec.rb +537 -0
- data/spec/core/util_spec.rb +67 -0
- data/spec/groovy/bdd_spec.rb +80 -0
- data/spec/groovy/compiler_spec.rb +240 -0
- data/spec/ide/eclipse_spec.rb +501 -0
- data/spec/ide/idea7x_spec.rb +84 -0
- data/spec/java/ant_spec.rb +33 -0
- data/spec/java/bdd_spec.rb +382 -0
- data/spec/java/cobertura_spec.rb +85 -0
- data/spec/java/compiler_spec.rb +446 -0
- data/spec/java/emma_spec.rb +119 -0
- data/spec/java/java_spec.rb +124 -0
- data/spec/java/packaging_spec.rb +1134 -0
- data/spec/java/test_coverage_helper.rb +257 -0
- data/spec/java/tests_spec.rb +493 -0
- data/spec/packaging/archive_spec.rb +527 -0
- data/spec/packaging/artifact_namespace_spec.rb +654 -0
- data/spec/packaging/artifact_spec.rb +795 -0
- data/spec/packaging/packaging_helper.rb +63 -0
- data/spec/packaging/packaging_spec.rb +684 -0
- data/spec/sandbox.rb +142 -0
- data/spec/scala/bdd_spec.rb +119 -0
- data/spec/scala/compiler_spec.rb +284 -0
- data/spec/scala/scala.rb +38 -0
- data/spec/scala/tests_spec.rb +261 -0
- data/spec/spec_helpers.rb +340 -0
- data/spec/version_requirement_spec.rb +129 -0
- 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
|