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,972 @@
|
|
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/packaging/version_requirement'
|
18
|
+
|
19
|
+
|
20
|
+
module Buildr
|
21
|
+
|
22
|
+
# An ArtifactNamespace is a hierarchical dictionary used to manage ArtifactRequirements.
|
23
|
+
# It can be used to have different artifact versions per project
|
24
|
+
# or to allow users to select a version for addons or modules.
|
25
|
+
#
|
26
|
+
# Namespaces are opened using the Buildr.artifact_ns method, most important methods are:
|
27
|
+
# [need] Used to create a requirement on the namespace.
|
28
|
+
# [use] Set the artifact version to use for a requirement.
|
29
|
+
# [values_at] Reference requirements by name.
|
30
|
+
# [each] Return each ArtifactRequirement in the namespace.
|
31
|
+
# The method_missing method for instances provides some syntactic sugar to these.
|
32
|
+
# See the following examples, and the methods for ArtifactRequirement.
|
33
|
+
#
|
34
|
+
# = Avoiding constant polution on buildfile
|
35
|
+
#
|
36
|
+
# Each project has its own ArtifactNamespace inheriting the one from the
|
37
|
+
# parent project up to the root namespace.
|
38
|
+
#
|
39
|
+
# Consider the following snippet, as project grows, each subproject
|
40
|
+
# may need diferent artifact combinations and/or versions. Asigning
|
41
|
+
# artifact specifications to constants can make it painful to maintain
|
42
|
+
# their references even if using structs/hashes.
|
43
|
+
#
|
44
|
+
# -- buildfile --
|
45
|
+
# SPRING = 'org.springframework:spring:jar:2.5'
|
46
|
+
# SPRING_OLD = 'org.springframework:spring:jar:1.0'
|
47
|
+
# LOGGING = ['comons-logging:commons-logging:jar:1.1.1',
|
48
|
+
# 'log4j:log4j:jar:1.2.15']
|
49
|
+
# WL_LOGGING = artifact('bea:wlcommons-logging:jar:8.1').from('path/to/wlcommons-logging.jar')
|
50
|
+
# LOGGING_WEBLOGIC = ['comons-logging:commons-logging:jar:1.1.1',
|
51
|
+
# WL_LOGGING]
|
52
|
+
# COMMONS = struct :collections => 'commons-collection:commons-collection:jar:3.1',
|
53
|
+
# :net => 'commons-net:commons-net:jar:1.4.0'
|
54
|
+
#
|
55
|
+
# define 'example1' do
|
56
|
+
# define 'one' do
|
57
|
+
# compile.with SPRING, LOGGING_WEBLOGIC, COMMONS
|
58
|
+
# end
|
59
|
+
# define 'two' do
|
60
|
+
# compile.with SPRING_OLD, LOGGING, COMMONS
|
61
|
+
# end
|
62
|
+
# define 'three' do
|
63
|
+
# compile.with "commons-collections:commons-collections:jar:2.2"
|
64
|
+
# end
|
65
|
+
# end
|
66
|
+
#
|
67
|
+
#
|
68
|
+
# With ArtifactNamespace you can do some more advanced stuff, the following
|
69
|
+
# annotated snipped could still be reduced if default artifact definitions were
|
70
|
+
# loaded from yaml file (see section bellow and ArtifactNamespace.load).
|
71
|
+
#
|
72
|
+
# -- buildfile --
|
73
|
+
# artifact_ns do |ns| # the current namespace (root if called outside a project)
|
74
|
+
# # default artifacts
|
75
|
+
# ns.spring = 'org.springframework:spring:jar:2.5'
|
76
|
+
# # default logger is log4j
|
77
|
+
# ns.logger = 'log4j:log4j:jar:1.2.15'
|
78
|
+
#
|
79
|
+
# # create a sub namespace by calling the #ns method,
|
80
|
+
# # artifacts defined on the sub-namespace can be referenced by
|
81
|
+
# # name :commons_net or by calling commons.net
|
82
|
+
# ns.ns :commons, :net => 'commons-net:commons-net:jar:1.4.0',
|
83
|
+
# :logging => 'comons-logging:commons-logging:jar:1.1.1'
|
84
|
+
#
|
85
|
+
#
|
86
|
+
# # When a child namespace asks for the :log artifact,
|
87
|
+
# # these artifacts will be searched starting from the :current namespace.
|
88
|
+
# ns.virtual :log, :logger, :commons_logging
|
89
|
+
# end
|
90
|
+
#
|
91
|
+
# artifact_ns('example2:one') do |ns| # namespace for the one subproject
|
92
|
+
# ns.logger = artifact('bea:wlcommons-logging:jar:8.1').from('path/to/wlcommons-logging.jar')
|
93
|
+
# end
|
94
|
+
# artifact_ns('example2:two') do |ns|
|
95
|
+
# ns.spring = '1.0' # for project two use an older spring version (just for an example)
|
96
|
+
# end
|
97
|
+
# artifact_ns('example2:three').commons_collections = 2.2'
|
98
|
+
# artifact_ns('example2:four') do |ns|
|
99
|
+
# ns.beanutils = 'commons-beanutils:commons-beanutils:jar:1.5' # just for this project
|
100
|
+
# ns.ns(:compilation).use :commons_logging, :beanutils, :spring # compile time dependencies
|
101
|
+
# ns.ns(:testing).use :log, :beanutils, 'cglib:cglib-nodep:jar:2.1.3' # run time dependencies
|
102
|
+
# end
|
103
|
+
#
|
104
|
+
# define 'example2' do
|
105
|
+
# define 'one' do
|
106
|
+
# compile.with :spring, :log, :commons # uses weblogic logging
|
107
|
+
# end
|
108
|
+
# define 'two' do
|
109
|
+
# compile.with :spring, :log, :commons # will take old spring
|
110
|
+
# end
|
111
|
+
# define 'three' do
|
112
|
+
# compile.with :commons_collections
|
113
|
+
# test.with artifact_ns('example2:two').spring # use spring from project two
|
114
|
+
# end
|
115
|
+
# define 'four' do
|
116
|
+
# compile.with artifact_ns.compilation
|
117
|
+
# test.with artifact_ns.testing
|
118
|
+
# end
|
119
|
+
# task(:down_them_all) do # again, just to fill this space with something ;)
|
120
|
+
# parent.projects.map(&method(:artifact_ns)).map(&:artifacts).map(&:invoke)
|
121
|
+
# end
|
122
|
+
# end
|
123
|
+
#
|
124
|
+
# = Loading from a yaml file (e. profiles.yaml)
|
125
|
+
#
|
126
|
+
# If your projects use lots of jars (after all we are using java ;) you may prefer
|
127
|
+
# to have constant artifact definitions on an external file.
|
128
|
+
# Doing so would allow an external tool (or future Buildr feature) to maintain
|
129
|
+
# an artifacts.yaml for you.
|
130
|
+
# An example usage is documented on the ArtifactNamespace.load method.
|
131
|
+
#
|
132
|
+
# = For addon/plugin writers & Customizing artifact versions
|
133
|
+
#
|
134
|
+
# Sometimes users would need to change the default artifact versions used by some
|
135
|
+
# module, for example, the XMLBeans compiler needs this, because of compatibility
|
136
|
+
# issues. Another example would be to select the groovy version to use on all our
|
137
|
+
# projects so that Buildr modules requiring groovy jars can use user prefered versions.
|
138
|
+
#
|
139
|
+
# To meet this goal, an ArtifactNamespace allows to specify ArgumentRequirement objects.
|
140
|
+
# In fact the only diference with the examples you have already seen is that requirements
|
141
|
+
# have an associated VersionRequirement, so that each time a user tries to select a version,
|
142
|
+
# buildr checks if it satisfies the requirements.
|
143
|
+
#
|
144
|
+
# Requirements are declared using the ArtifactNamespace#need method, but again,
|
145
|
+
# syntactic sugar is provided by ArtifactNamespace#method_missing.
|
146
|
+
#
|
147
|
+
# The following example is taken from the XMLBeans compiler module.
|
148
|
+
# And illustrates how addon authors should specify their requirements,
|
149
|
+
# provide default versions, and document the namespace for users to customize.
|
150
|
+
#
|
151
|
+
# module Buildr::XMLBeans
|
152
|
+
#
|
153
|
+
# # You need to document this constant, giving users some hints
|
154
|
+
# # about when are (maybe some of) these artifacts used. I mean,
|
155
|
+
# # some modules, add jars to the Buildr classpath when its file
|
156
|
+
# # is required, you would need to tell your users, so that they
|
157
|
+
# # can open the namespace and specify their defaults. Of course
|
158
|
+
# # when the requirements are defined, buildr checks if any compatible
|
159
|
+
# # version has been already defined, if so, uses it.
|
160
|
+
# #
|
161
|
+
# # Some things here have been changed to illustrate their meaning.
|
162
|
+
# REQUIRES = ArtifactNamespace.for(self).tap do |ns|
|
163
|
+
#
|
164
|
+
# # This jar requires a >2.0 version, default being 2.3.0
|
165
|
+
# ns.xmlbeans! 'org.apache.xmlbeans:xmlbeans:jar:2.3.0', '>2'
|
166
|
+
#
|
167
|
+
# # Users can customize with Buildr::XMLBeans::REQUIRES.stax_api = '1.2'
|
168
|
+
# # This is a non-flexible requirement, only satisfied by version 1.0.1
|
169
|
+
# ns.stax_api! 'stax:stax-api:jar:1.0.1'
|
170
|
+
#
|
171
|
+
# # This one is not part of XMLBeans, but is just another example
|
172
|
+
# # illustrating an `artifact requirement spec`.
|
173
|
+
#
|
174
|
+
# ns.need " some_name -> ar:ti:fact:3.2.5 -> ( >2 & <4)"
|
175
|
+
#
|
176
|
+
# # As you can see it's just an artifact spec, prefixed with
|
177
|
+
# # ' some_name -> ', this means users can use that name to
|
178
|
+
# # reference the requirement, also this string has a VersionRequirement
|
179
|
+
# # just after another ->.
|
180
|
+
# end
|
181
|
+
#
|
182
|
+
# # The REQUIRES constant is an ArtifactNamespace instance,
|
183
|
+
# # that means we can use it directly. Note that calling
|
184
|
+
# # Buildr.artifact_ns would lead to the currently executing context,
|
185
|
+
# # not the one for this module.
|
186
|
+
# def use
|
187
|
+
# # test if user specified his own version, if so, we could perform some
|
188
|
+
# # functionallity based on this.
|
189
|
+
# REQUIRES.some_name.selected? # => false
|
190
|
+
#
|
191
|
+
# REQUIRES.some_name.satisfied_by?('1.5') # => false
|
192
|
+
# puts REQUIRES.some_name.requirement # => ( >2 & <4 )
|
193
|
+
#
|
194
|
+
# REQUIRES.artifacts # get the Artifact tasks
|
195
|
+
# end
|
196
|
+
#
|
197
|
+
# end
|
198
|
+
#
|
199
|
+
# A more advanced example using ArtifactRequirement listeners is included
|
200
|
+
# in the artifact_namespace_spec.rb description for 'Extension using ArtifactNamespace'
|
201
|
+
# That's it for addon writers, now, users can select their prefered version with
|
202
|
+
# something like:
|
203
|
+
#
|
204
|
+
# require 'buildr/xmlbeans'
|
205
|
+
# Buildr::XMLBeans::REQUIRES.xmlbeans = '2.2.0'
|
206
|
+
#
|
207
|
+
# More advanced stuff, if users really need to select an xmlbeans version
|
208
|
+
# per project, they can do so letting :current (that is, the currently running
|
209
|
+
# namespace) be parent of the REQUIRES namespace:
|
210
|
+
#
|
211
|
+
# Buildr::XMLBeans::REQUIRES.parent = :current
|
212
|
+
#
|
213
|
+
# Now, provided that the compiler does not caches its artifacts, it will
|
214
|
+
# select the correct version. (See the first section for how to select per project
|
215
|
+
# artifacts).
|
216
|
+
#
|
217
|
+
#
|
218
|
+
class ArtifactNamespace
|
219
|
+
class << self
|
220
|
+
# Forget all namespaces, create a new ROOT
|
221
|
+
def clear
|
222
|
+
@instances = nil
|
223
|
+
remove_const(:ROOT) rescue nil
|
224
|
+
const_set(:ROOT, new('root'))
|
225
|
+
end
|
226
|
+
|
227
|
+
# Populate namespaces from a hash of hashes.
|
228
|
+
# The following example uses the profiles yaml to achieve this.
|
229
|
+
#
|
230
|
+
# -- profiles.yaml --
|
231
|
+
# development:
|
232
|
+
# artifacts:
|
233
|
+
# root: # root namespace
|
234
|
+
# spring: org.springframework:spring:jar:2.5
|
235
|
+
# groovy: org.codehaus.groovy:groovy:jar:1.5.4
|
236
|
+
# logging: # define a named group
|
237
|
+
# - log4j:log4j:jar:1.2.15
|
238
|
+
# - commons-logging:commons-logging:1.1.1
|
239
|
+
#
|
240
|
+
# # open Buildr::XMLBeans namespace
|
241
|
+
# Buildr::XMLBeans:
|
242
|
+
# xmlbeans: 2.2
|
243
|
+
#
|
244
|
+
# # for subproject one:oldie
|
245
|
+
# one:oldie:
|
246
|
+
# spring: org.springframework:spring:jar:1.0
|
247
|
+
#
|
248
|
+
# -- buildfile --
|
249
|
+
# ArtifactNamespace.load(Buildr.profile['artifacts'])
|
250
|
+
def load(namespaces = {})
|
251
|
+
namespaces.each_pair { |name, uses| instance(name).use(uses) }
|
252
|
+
end
|
253
|
+
|
254
|
+
# :call-seq:
|
255
|
+
# ArtifactNamespace.instance { |current_ns| ... } -> current_ns
|
256
|
+
# ArtifactNamespace.instance(name) { |ns| ... } -> ns
|
257
|
+
# ArtifactNamespace.instance(:current) { |current_ns| ... } -> current_ns
|
258
|
+
# ArtifactNamespace.instance(:root) { |root_ns| ... } -> root_ns
|
259
|
+
#
|
260
|
+
# Obtain an instance for the given name
|
261
|
+
def instance(name = nil)
|
262
|
+
case name
|
263
|
+
when :root, 'root' then return ROOT
|
264
|
+
when ArtifactNamespace then return name
|
265
|
+
when Array then name = name.join(':')
|
266
|
+
when Module, Project then name = name.name
|
267
|
+
when :current, 'current', nil then
|
268
|
+
task = Thread.current[:rake_chain]
|
269
|
+
task = task.instance_variable_get(:@value) if task
|
270
|
+
name = case task
|
271
|
+
when Project then task.name
|
272
|
+
when Rake::Task then task.scope.join(':')
|
273
|
+
when nil then Buildr.application.current_scope.join(':')
|
274
|
+
end
|
275
|
+
end
|
276
|
+
name = name.to_s
|
277
|
+
return ROOT if name.size == 0
|
278
|
+
name = name.to_s
|
279
|
+
@instances ||= Hash.new { |h, k| h[k] = new(k) }
|
280
|
+
instance = @instances[name]
|
281
|
+
yield(instance) if block_given?
|
282
|
+
instance
|
283
|
+
end
|
284
|
+
|
285
|
+
alias_method :[], :instance
|
286
|
+
alias_method :for, :instance
|
287
|
+
|
288
|
+
# :call-seq:
|
289
|
+
# ArtifactNamespace.root { |ns| ... } -> ns
|
290
|
+
#
|
291
|
+
# Obtain the root namespace, returns the ROOT constant
|
292
|
+
def root
|
293
|
+
yield ROOT if block_given?
|
294
|
+
ROOT
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
module DClone #:nodoc:
|
299
|
+
def dclone
|
300
|
+
clone = self.clone
|
301
|
+
clone.instance_variables.each do |i|
|
302
|
+
value = clone.instance_variable_get(i)
|
303
|
+
value = value.dclone rescue
|
304
|
+
clone.instance_variable_set(i, value)
|
305
|
+
end
|
306
|
+
clone
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
class Registry < Hash #:nodoc:
|
311
|
+
include DClone
|
312
|
+
|
313
|
+
attr_accessor :parent
|
314
|
+
def alias(new_name, old_name)
|
315
|
+
new_name = new_name.to_sym
|
316
|
+
old_name = old_name.to_sym
|
317
|
+
if obj = get(old_name, true)
|
318
|
+
self[new_name] = obj
|
319
|
+
@aliases ||= []
|
320
|
+
group = @aliases.find { |a| a.include?(new_name) }
|
321
|
+
group.delete(new_name) if group
|
322
|
+
group = @aliases.find { |a| a.include?(old_name) }
|
323
|
+
@aliases << (group = [old_name]) unless group
|
324
|
+
group << new_name unless group.include?(new_name)
|
325
|
+
end
|
326
|
+
obj
|
327
|
+
end
|
328
|
+
|
329
|
+
def aliases(name)
|
330
|
+
return [] unless name
|
331
|
+
name = name.to_sym
|
332
|
+
((@aliases ||= []).find { |a| a.include?(name) } || [name]).dup
|
333
|
+
end
|
334
|
+
|
335
|
+
def []=(key, value)
|
336
|
+
return unless key
|
337
|
+
super(key.to_sym, value)
|
338
|
+
end
|
339
|
+
|
340
|
+
def get(key, include_parent = nil)
|
341
|
+
[].tap { |a| aliases(key).select { |n| a[0] = self[n] } }.first ||
|
342
|
+
(include_parent && parent && parent.get(key, include_parent))
|
343
|
+
end
|
344
|
+
|
345
|
+
def keys(include_parent = nil)
|
346
|
+
(super() | (include_parent && parent && parent.keys(include_parent) || [])).uniq
|
347
|
+
end
|
348
|
+
|
349
|
+
def values(include_parent = nil)
|
350
|
+
(super() | (include_parent && parent && parent.values(include_parent) || [])).uniq
|
351
|
+
end
|
352
|
+
|
353
|
+
def key?(key, include_parent = nil)
|
354
|
+
return false unless key
|
355
|
+
super(key.to_sym) || (include_parent && parent && parent.key?(key, include_parent))
|
356
|
+
end
|
357
|
+
|
358
|
+
def delete(key, include_parent = nil)
|
359
|
+
aliases(key).map {|n| super(n) } && include_parent && parent && parent.delete(key, include_parent)
|
360
|
+
end
|
361
|
+
end
|
362
|
+
|
363
|
+
# An artifact requirement is an object that ActsAsArtifact and has
|
364
|
+
# an associated VersionRequirement. It also knows the name (some times equal to the
|
365
|
+
# artifact id) that is used to store it in an ArtifactNamespace.
|
366
|
+
class ArtifactRequirement
|
367
|
+
attr_accessor :version
|
368
|
+
attr_reader :name, :requirement
|
369
|
+
|
370
|
+
include DClone
|
371
|
+
|
372
|
+
# Create a requirement from an `artifact requirement spec`.
|
373
|
+
# This spec has three parts, separated by ->
|
374
|
+
#
|
375
|
+
# some_name -> ar:ti:fact:3.2.5 -> ( >2 & <4)
|
376
|
+
#
|
377
|
+
# As you can see it's just an artifact spec, prefixed with
|
378
|
+
# some_name ->
|
379
|
+
# the :some_name symbol becomes this object's name and
|
380
|
+
# is used to store it on an ArtifactNamespace.
|
381
|
+
#
|
382
|
+
# ar:ti:fact:3.2.5
|
383
|
+
#
|
384
|
+
# The second part is an artifact spec by itself, and specifies
|
385
|
+
# all remaining attributes, the version of this spec becomes
|
386
|
+
# the default version of this requirement.
|
387
|
+
#
|
388
|
+
# The last part consist of a VersionRequirement.
|
389
|
+
# -> ( >2 & <4)
|
390
|
+
#
|
391
|
+
# VersionRequirement supports RubyGem's comparision operators
|
392
|
+
# in adition to parens, logical and, logical or and negation.
|
393
|
+
# See the docs for VersionRequirement for more info on operators.
|
394
|
+
def initialize(spec)
|
395
|
+
self.class.send :include, ActsAsArtifact unless ActsAsArtifact === self
|
396
|
+
if ArtifactRequirement === spec
|
397
|
+
copy_attrs(spec)
|
398
|
+
else
|
399
|
+
spec = requirement_hash(spec)
|
400
|
+
apply_spec(spec[:spec])
|
401
|
+
self.name = spec[:name]
|
402
|
+
@requirement = spec[:requirement]
|
403
|
+
@version = @requirement.default if VersionRequirement.requirement?(@version)
|
404
|
+
end
|
405
|
+
end
|
406
|
+
|
407
|
+
# Copy attributes from other to this object
|
408
|
+
def copy_attrs(other)
|
409
|
+
(ActsAsArtifact::ARTIFACT_ATTRIBUTES + [:name, :requirement]).each do |attr|
|
410
|
+
value = other.instance_variable_get("@#{attr}")
|
411
|
+
value = value.dup if value && !value.kind_of?(Numeric) && !value.kind_of?(Symbol)
|
412
|
+
instance_variable_set("@#{attr}", value)
|
413
|
+
end
|
414
|
+
end
|
415
|
+
|
416
|
+
def name=(name)
|
417
|
+
@name = name.to_s
|
418
|
+
end
|
419
|
+
|
420
|
+
# Set a the requirement, this must be an string formatted for
|
421
|
+
# VersionRequirement#create to parse.
|
422
|
+
def requirement=(version_requirement)
|
423
|
+
@requirement = VersionRequirement.create(version_requirement.to_s)
|
424
|
+
end
|
425
|
+
|
426
|
+
# Return a hash consisting of :name, :spec, :requirement
|
427
|
+
def requirement_hash(spec = self)
|
428
|
+
result = {}
|
429
|
+
if String === spec
|
430
|
+
parts = spec.split(/\s*->\s*/, 3).map(&:strip)
|
431
|
+
case parts.size
|
432
|
+
when 1
|
433
|
+
result[:spec] = Artifact.to_hash(parts.first)
|
434
|
+
when 2
|
435
|
+
if /^\w+$/ === parts.first
|
436
|
+
result[:name] = parts.first
|
437
|
+
result[:spec] = Artifact.to_hash(parts.last)
|
438
|
+
else
|
439
|
+
result[:spec] = Artifact.to_hash(parts.first)
|
440
|
+
result[:requirement] = VersionRequirement.create(parts.last)
|
441
|
+
end
|
442
|
+
when 3
|
443
|
+
result[:name] = parts.first
|
444
|
+
result[:spec] = Artifact.to_hash(parts[1])
|
445
|
+
result[:requirement] = VersionRequirement.create(parts.last)
|
446
|
+
end
|
447
|
+
else
|
448
|
+
result[:spec] = Artifact.to_hash(spec)
|
449
|
+
end
|
450
|
+
result[:name] ||= result[:spec][:id].to_s.to_sym
|
451
|
+
result[:requirement] ||= VersionRequirement.create(result[:spec][:version])
|
452
|
+
result
|
453
|
+
end
|
454
|
+
|
455
|
+
# Test if this requirement is satisfied by an artifact spec.
|
456
|
+
def satisfied_by?(spec)
|
457
|
+
return false unless requirement
|
458
|
+
spec = Artifact.to_hash(spec)
|
459
|
+
hash = to_spec_hash
|
460
|
+
hash.delete(:version)
|
461
|
+
version = spec.delete(:version)
|
462
|
+
hash == spec && requirement.satisfied_by?(version)
|
463
|
+
end
|
464
|
+
|
465
|
+
# Has user selected a version for this requirement?
|
466
|
+
def selected?
|
467
|
+
@selected
|
468
|
+
end
|
469
|
+
|
470
|
+
def selected! #:nodoc:
|
471
|
+
@selected = true
|
472
|
+
@listeners.each { |l| l.call(self) } if @listeners
|
473
|
+
self
|
474
|
+
end
|
475
|
+
|
476
|
+
def add_listener(&callback)
|
477
|
+
(@listeners ||= []) << callback
|
478
|
+
end
|
479
|
+
|
480
|
+
# Return the Artifact object for the currently selected version
|
481
|
+
def artifact
|
482
|
+
::Buildr.artifact(self)
|
483
|
+
end
|
484
|
+
|
485
|
+
# Format this requirement as an `artifact requirement spec`
|
486
|
+
def to_requirement_spec
|
487
|
+
result = to_spec
|
488
|
+
result = "#{name} -> #{result}" if name
|
489
|
+
result = "#{result} -> #{requirement}" if requirement
|
490
|
+
result
|
491
|
+
end
|
492
|
+
|
493
|
+
def to_s #:nodoc:
|
494
|
+
id ? to_requirement_spec : version
|
495
|
+
end
|
496
|
+
|
497
|
+
# Return an artifact spec without the version part.
|
498
|
+
def unversioned_spec
|
499
|
+
str = to_spec
|
500
|
+
return nil if str =~ /^:+/
|
501
|
+
ary = str.split(':')
|
502
|
+
ary = ary[0...-1] if ary.size > 3
|
503
|
+
ary.join(':')
|
504
|
+
end
|
505
|
+
|
506
|
+
class << self
|
507
|
+
# Return an artifact spec without the version part.
|
508
|
+
def unversioned_spec(spec)
|
509
|
+
str = spec.to_s
|
510
|
+
return nil if str =~ /^:+/
|
511
|
+
ary = str.split(':')
|
512
|
+
ary = ary[0...-1] if ary.size > 3
|
513
|
+
if ary.size > 2
|
514
|
+
ary.join(':')
|
515
|
+
else
|
516
|
+
new(spec).unversioned_spec
|
517
|
+
end
|
518
|
+
end
|
519
|
+
end
|
520
|
+
end
|
521
|
+
|
522
|
+
include DClone
|
523
|
+
include Enumerable
|
524
|
+
attr_reader :name
|
525
|
+
|
526
|
+
def initialize(name = nil) #:nodoc:
|
527
|
+
@name = name.to_s if name
|
528
|
+
end
|
529
|
+
clear
|
530
|
+
|
531
|
+
def root
|
532
|
+
ROOT
|
533
|
+
end
|
534
|
+
|
535
|
+
# ROOT namespace has no parent
|
536
|
+
def parent
|
537
|
+
if root?
|
538
|
+
nil
|
539
|
+
elsif @parent.kind_of?(ArtifactNamespace)
|
540
|
+
@parent
|
541
|
+
elsif @parent
|
542
|
+
ArtifactNamespace.instance(@parent)
|
543
|
+
elsif name
|
544
|
+
parent_name = name.gsub(/::?[^:]+$/, '')
|
545
|
+
parent_name == name ? root : ArtifactNamespace.instance(parent_name)
|
546
|
+
else
|
547
|
+
root
|
548
|
+
end
|
549
|
+
end
|
550
|
+
|
551
|
+
# Set the parent for the current namespace, except if it is ROOT
|
552
|
+
def parent=(other)
|
553
|
+
raise 'Cannot set parent of root namespace' if root?
|
554
|
+
@parent = other
|
555
|
+
@registry = nil
|
556
|
+
end
|
557
|
+
|
558
|
+
# Is this the ROOT namespace?
|
559
|
+
def root?
|
560
|
+
ROOT == self
|
561
|
+
end
|
562
|
+
|
563
|
+
# Create a named sub-namespace, sub-namespaces are themselves
|
564
|
+
# ArtifactNamespace instances but cannot be referenced by
|
565
|
+
# the Buildr.artifact_ns, ArtifactNamespace.instance methods.
|
566
|
+
# Reference needs to be through this object using the given +name+
|
567
|
+
#
|
568
|
+
# artifact_ns('foo').ns(:bar).need :thing => 'some:thing:jar:1.0'
|
569
|
+
# artifact_ns('foo').bar # => the sub-namespace 'foo.bar'
|
570
|
+
# artifact_ns('foo').bar.thing # => the some thing artifact
|
571
|
+
#
|
572
|
+
# See the top level ArtifactNamespace documentation for examples
|
573
|
+
def ns(name, *uses, &block)
|
574
|
+
name = name.to_sym
|
575
|
+
sub = registry[name]
|
576
|
+
if sub
|
577
|
+
raise TypeError.new("#{name} is not a sub namespace of #{self}") unless sub.kind_of?(ArtifactNamespace)
|
578
|
+
else
|
579
|
+
sub = ArtifactNamespace.new("#{self.name}.#{name}")
|
580
|
+
sub.parent = self
|
581
|
+
registry[name] = sub
|
582
|
+
end
|
583
|
+
sub.use(*uses)
|
584
|
+
yield sub if block_given?
|
585
|
+
sub
|
586
|
+
end
|
587
|
+
|
588
|
+
# Test if a sub-namespace by the given name exists
|
589
|
+
def ns?(name)
|
590
|
+
sub = registry[name.to_sym]
|
591
|
+
ArtifactNamespace === sub
|
592
|
+
end
|
593
|
+
|
594
|
+
# :call-seq:
|
595
|
+
# artifact_ns.need 'name -> org:foo:bar:jar:~>1.2.3 -> 1.2.5'
|
596
|
+
# artifact_ns.need :name => 'org.foo:bar:jar:1.0'
|
597
|
+
#
|
598
|
+
# Create a new ArtifactRequirement on this namespace.
|
599
|
+
# ArtifactNamespace#method_missing provides syntactic sugar for this.
|
600
|
+
def need(*specs)
|
601
|
+
named = specs.flatten.inject({}) do |seen, spec|
|
602
|
+
if Hash === spec && (spec.keys & ActsAsArtifact::ARTIFACT_ATTRIBUTES).empty?
|
603
|
+
spec.each_pair do |name, spec|
|
604
|
+
if Array === spec # a group
|
605
|
+
seen[name] ||= spec.map { |s| ArtifactRequirement.new(s) }
|
606
|
+
else
|
607
|
+
artifact = ArtifactRequirement.new(spec)
|
608
|
+
artifact.name = name
|
609
|
+
seen[artifact.name] ||= artifact
|
610
|
+
end
|
611
|
+
end
|
612
|
+
else
|
613
|
+
artifact = ArtifactRequirement.new(spec)
|
614
|
+
seen[artifact.name] ||= artifact
|
615
|
+
end
|
616
|
+
seen
|
617
|
+
end
|
618
|
+
named.each_pair do |name, artifact|
|
619
|
+
if Array === artifact # a group
|
620
|
+
artifact.each do |a|
|
621
|
+
unvers = a.unversioned_spec
|
622
|
+
previous = registry[unvers]
|
623
|
+
if previous && previous.selected? && a.satisfied_by?(previous)
|
624
|
+
a.version = previous.version
|
625
|
+
end
|
626
|
+
registry[unvers] = a
|
627
|
+
end
|
628
|
+
group(name, *(artifact.map { |a| a.unversioned_spec } + [{:namespace => self}]))
|
629
|
+
else
|
630
|
+
unvers = artifact.unversioned_spec
|
631
|
+
previous = registry.get(unvers, true)
|
632
|
+
if previous && previous.selected? && artifact.satisfied_by?(previous)
|
633
|
+
artifact.version = previous.version
|
634
|
+
artifact.selected!
|
635
|
+
end
|
636
|
+
registry[unvers] = artifact
|
637
|
+
registry.alias name, unvers unless name.to_s[/^\s*$/]
|
638
|
+
end
|
639
|
+
end
|
640
|
+
self
|
641
|
+
end
|
642
|
+
|
643
|
+
# :call-seq:
|
644
|
+
# artifact_ns.use 'name -> org:foo:bar:jar:1.2.3'
|
645
|
+
# artifact_ns.use :name => 'org:foo:bar:jar:1.2.3'
|
646
|
+
# artifact_ns.use :name => '2.5.6'
|
647
|
+
#
|
648
|
+
# First and second form are equivalent, the third is used when an
|
649
|
+
# ArtifactRequirement has been previously defined with :name, so it
|
650
|
+
# just selects the version.
|
651
|
+
#
|
652
|
+
# ArtifactNamespace#method_missing provides syntactic sugar for this.
|
653
|
+
def use(*specs)
|
654
|
+
named = specs.flatten.inject({}) do |seen, spec|
|
655
|
+
if Hash === spec && (spec.keys & ActsAsArtifact::ARTIFACT_ATTRIBUTES).empty?
|
656
|
+
spec.each_pair do |name, spec|
|
657
|
+
if ArtifactNamespace === spec # create as subnamespace
|
658
|
+
raise ArgumentError.new("Circular reference") if self == spec
|
659
|
+
registry[name.to_sym] = spec
|
660
|
+
elsif Numeric === spec || (String === spec && VersionRequirement.version?(spec))
|
661
|
+
artifact = ArtifactRequirement.allocate
|
662
|
+
artifact.name = name
|
663
|
+
artifact.version = spec.to_s
|
664
|
+
seen[artifact.name] ||= artifact
|
665
|
+
elsif Symbol === spec
|
666
|
+
self.alias name, spec
|
667
|
+
elsif Array === spec # a group
|
668
|
+
seen[name] ||= spec.map { |s| ArtifactRequirement.new(s) }
|
669
|
+
else
|
670
|
+
artifact = ArtifactRequirement.new(spec)
|
671
|
+
artifact.name = name
|
672
|
+
seen[artifact.name] ||= artifact
|
673
|
+
end
|
674
|
+
end
|
675
|
+
else
|
676
|
+
if Symbol === spec
|
677
|
+
artifact = get(spec).dclone
|
678
|
+
else
|
679
|
+
artifact = ArtifactRequirement.new(spec)
|
680
|
+
end
|
681
|
+
seen[artifact.name] ||= artifact
|
682
|
+
end
|
683
|
+
seen
|
684
|
+
end
|
685
|
+
named.each_pair do |name, artifact|
|
686
|
+
is_group = Array === artifact
|
687
|
+
artifact = [artifact].flatten.map do |artifact|
|
688
|
+
unvers = artifact.unversioned_spec
|
689
|
+
previous = get(unvers, false) || get(name, false)
|
690
|
+
if previous # have previous on current namespace
|
691
|
+
if previous.requirement # we must satisfy the requirement
|
692
|
+
unless unvers # we only have the version
|
693
|
+
satisfied = previous.requirement.satisfied_by?(artifact.version)
|
694
|
+
else
|
695
|
+
satisfied = previous.satisfied_by?(artifact)
|
696
|
+
end
|
697
|
+
raise "Unsatisfied dependency #{previous} " +
|
698
|
+
"not satisfied by #{artifact}" unless satisfied
|
699
|
+
previous.version = artifact.version # OK, set new version
|
700
|
+
artifact = previous # use the same object for aliases
|
701
|
+
else # not a requirement, set the new values
|
702
|
+
unless artifact.id == previous.id && name != previous.name
|
703
|
+
previous.copy_attrs(artifact)
|
704
|
+
artifact = previous
|
705
|
+
end
|
706
|
+
end
|
707
|
+
else
|
708
|
+
if unvers.nil? && # we only have the version
|
709
|
+
(previous = get(unvers, true, false, false))
|
710
|
+
version = artifact.version
|
711
|
+
artifact.copy_attrs(previous)
|
712
|
+
artifact.version = version
|
713
|
+
end
|
714
|
+
artifact.requirement = nil
|
715
|
+
end
|
716
|
+
artifact.selected!
|
717
|
+
end
|
718
|
+
artifact = artifact.first unless is_group
|
719
|
+
if is_group
|
720
|
+
names = artifact.map do |art|
|
721
|
+
unv = art.unversioned_spec
|
722
|
+
registry[unv] = art
|
723
|
+
unv
|
724
|
+
end
|
725
|
+
group(name, *(names + [{:namespace => self}]))
|
726
|
+
elsif artifact.id
|
727
|
+
unvers = artifact.unversioned_spec
|
728
|
+
registry[name] = artifact
|
729
|
+
registry.alias unvers, name
|
730
|
+
else
|
731
|
+
registry[name] = artifact
|
732
|
+
end
|
733
|
+
end
|
734
|
+
self
|
735
|
+
end
|
736
|
+
|
737
|
+
# Like Hash#fetch
|
738
|
+
def fetch(name, default = nil, &block)
|
739
|
+
block ||= proc { raise IndexError.new("No artifact found by name #{name.inspect} in namespace #{self}") }
|
740
|
+
real_name = name.to_s[/^[\w\-\.]+$/] ? name : ArtifactRequirement.unversioned_spec(name)
|
741
|
+
get(real_name.to_sym) || default || block.call(name)
|
742
|
+
end
|
743
|
+
|
744
|
+
# :call-seq:
|
745
|
+
# artifact_ns[:name] -> ArtifactRequirement
|
746
|
+
# artifact_ns[:many, :names] -> [ArtifactRequirement]
|
747
|
+
def [](*names)
|
748
|
+
ary = values_at(*names)
|
749
|
+
names.size == 1 ? ary.first : ary
|
750
|
+
end
|
751
|
+
|
752
|
+
# :call-seq:
|
753
|
+
# artifact_ns[:name] = 'some:cool:jar:1.0.2'
|
754
|
+
# artifact_ns[:name] = '1.0.2'
|
755
|
+
#
|
756
|
+
# Just like the use method
|
757
|
+
def []=(*names)
|
758
|
+
values = names.pop
|
759
|
+
values = [values] unless Array === values
|
760
|
+
names.each_with_index do |name, i|
|
761
|
+
use name => (values[i] || values.last)
|
762
|
+
end
|
763
|
+
end
|
764
|
+
|
765
|
+
# yield each ArtifactRequirement
|
766
|
+
def each(&block)
|
767
|
+
values.each(&block)
|
768
|
+
end
|
769
|
+
|
770
|
+
# return Artifact objects for each requirement
|
771
|
+
def artifacts(*names)
|
772
|
+
(names.empty? && values || values_at(*names)).map(&:artifact)
|
773
|
+
end
|
774
|
+
|
775
|
+
# Return all requirements for this namespace
|
776
|
+
def values(include_parents = false, include_groups = true)
|
777
|
+
seen, dict = {}, registry
|
778
|
+
while dict
|
779
|
+
dict.each do |k, v|
|
780
|
+
v = v.call if v.respond_to?(:call)
|
781
|
+
v = v.values if v.kind_of?(ArtifactNamespace)
|
782
|
+
if Array === v && include_groups
|
783
|
+
v.compact.each { |v| seen[v.name] = v unless seen.key?(v.name) }
|
784
|
+
else
|
785
|
+
seen[v.name] = v unless seen.key?(v.name)
|
786
|
+
end
|
787
|
+
end
|
788
|
+
dict = include_parents ? dict.parent : nil
|
789
|
+
end
|
790
|
+
seen.values
|
791
|
+
end
|
792
|
+
|
793
|
+
# Return only the named requirements
|
794
|
+
def values_at(*names)
|
795
|
+
names.map do |name|
|
796
|
+
catch :artifact do
|
797
|
+
unless name.to_s[/^[\w\-\.]+$/]
|
798
|
+
unvers = ArtifactRequirement.unversioned_spec(name)
|
799
|
+
unless unvers.to_s == name.to_s
|
800
|
+
req = ArtifactRequirement.new(name)
|
801
|
+
reg = self
|
802
|
+
while reg
|
803
|
+
candidate = reg.send(:get, unvers, false, false, true)
|
804
|
+
throw :artifact, candidate if req.satisfied_by?(candidate)
|
805
|
+
reg = reg.parent
|
806
|
+
end
|
807
|
+
end
|
808
|
+
end
|
809
|
+
get(name.to_sym)
|
810
|
+
end
|
811
|
+
end
|
812
|
+
end
|
813
|
+
|
814
|
+
def key?(name, include_parents = false)
|
815
|
+
name = ArtifactRequirement.unversioned_spec(name) unless name.to_s[/^[\w\-\.]+$/]
|
816
|
+
registry.key?(name, include_parents)
|
817
|
+
end
|
818
|
+
|
819
|
+
def delete(name, include_parents = false)
|
820
|
+
registry.delete(name, include_parents)
|
821
|
+
self
|
822
|
+
end
|
823
|
+
|
824
|
+
# :call-seq:
|
825
|
+
# group :who, :me, :you
|
826
|
+
# group :them, :me, :you, :namespace => ns
|
827
|
+
#
|
828
|
+
# Create a virtual group on this namespace. When the namespace
|
829
|
+
# is asked for the +who+ artifact, it's value is an array made from
|
830
|
+
# the remaining names. These names are searched by default from the current
|
831
|
+
# namespace.
|
832
|
+
# Second form specified the starting namespace to search from.
|
833
|
+
def group(group_name, *members)
|
834
|
+
namespace = (Hash === members.last && members.pop[:namespace]) || :current
|
835
|
+
registry[group_name] = lambda do
|
836
|
+
artifacts = self.class[namespace].values_at(*members)
|
837
|
+
artifacts = artifacts.first if members.size == 1
|
838
|
+
artifacts
|
839
|
+
end
|
840
|
+
self
|
841
|
+
end
|
842
|
+
|
843
|
+
alias_method :virtual, :group
|
844
|
+
|
845
|
+
# Create an alias for a named requirement.
|
846
|
+
def alias(new_name, old_name)
|
847
|
+
registry.alias(new_name, old_name) or
|
848
|
+
raise NameError.new("Undefined artifact name: #{old_name}")
|
849
|
+
end
|
850
|
+
|
851
|
+
def to_s #:nodoc:
|
852
|
+
name.to_s
|
853
|
+
end
|
854
|
+
|
855
|
+
# :call-seq:
|
856
|
+
# artifact_ns.cool_aid!('cool:aid:jar:2.3.4', '~>2.3') -> artifact_requirement
|
857
|
+
# artifact_ns.cool_aid = '2.3.5'
|
858
|
+
# artifact_ns.cool_aid -> artifact_requirement
|
859
|
+
# artifact_ns.cool_aid? -> true | false
|
860
|
+
#
|
861
|
+
# First form creates an ArtifactRequirement on the namespace.
|
862
|
+
# It is equivalent to providing a requirement_spec to the #need method:
|
863
|
+
# artifact_ns.need "cool_aid -> cool:aid:jar:2.3.4 -> ~>2.3"
|
864
|
+
# the second argument is optional.
|
865
|
+
#
|
866
|
+
# Second form can be used to select an artifact version
|
867
|
+
# and is equivalent to:
|
868
|
+
# artifact_ns.use :cool_aid => '1.0'
|
869
|
+
#
|
870
|
+
# Third form obtains the named ArtifactRequirement, can be
|
871
|
+
# used to test if a named requirement has been defined.
|
872
|
+
# It is equivalent to:
|
873
|
+
# artifact_ns.fetch(:cool_aid) { nil }
|
874
|
+
#
|
875
|
+
# Last form tests if the ArtifactRequirement has been defined
|
876
|
+
# and a version has been selected for use.
|
877
|
+
# It is equivalent to:
|
878
|
+
#
|
879
|
+
# artifact_ns.has_cool_aid?
|
880
|
+
# artifact_ns.values_at(:cool_aid).flatten.all? { |a| a && a.selected? }
|
881
|
+
#
|
882
|
+
def method_missing(name, *args, &block)
|
883
|
+
case name.to_s
|
884
|
+
when /!$/ then
|
885
|
+
name = $`.intern
|
886
|
+
if args.size < 1 || args.size > 2
|
887
|
+
raise ArgumentError.new("wrong number of arguments for #{name}!(spec, version_requirement?)")
|
888
|
+
end
|
889
|
+
need name => args.first
|
890
|
+
get(name).tap { |r| r.requirement = args.last if args.size == 2 }
|
891
|
+
when /=$/ then use $` => args.first
|
892
|
+
when /\?$/ then
|
893
|
+
name = $`.gsub(/^(has|have)_/, '').intern
|
894
|
+
[get(name)].flatten.all? { |a| a && a.selected? }
|
895
|
+
else
|
896
|
+
if block || args.size > 0
|
897
|
+
raise ArgumentError.new("wrong number of arguments #{args.size} for 0 or block given")
|
898
|
+
end
|
899
|
+
get(name)
|
900
|
+
end
|
901
|
+
end
|
902
|
+
|
903
|
+
# Return an anonymous module
|
904
|
+
# # first create a requirement
|
905
|
+
# artifact_ns.cool_aid! 'cool:aid:jar:>=1.0'
|
906
|
+
#
|
907
|
+
# # extend an object as a cool_aid delegator
|
908
|
+
# jars = Object.new.extend(artifact_ns.accessor(:cool_aid))
|
909
|
+
# jars.cool_aid = '2.0'
|
910
|
+
#
|
911
|
+
# artifact_ns.cool_aid.version # -> '2.0'
|
912
|
+
def accessor(*names)
|
913
|
+
ns = self
|
914
|
+
Module.new do
|
915
|
+
names.each do |name|
|
916
|
+
define_method("#{name}") { ns.send("#{name}") }
|
917
|
+
define_method("#{name}?") { ns.send("#{name}?") }
|
918
|
+
define_method("#{name}=") { |vers| ns.send("#{name}=", vers) }
|
919
|
+
end
|
920
|
+
end
|
921
|
+
end
|
922
|
+
|
923
|
+
private
|
924
|
+
def get(name, include_parents = true, include_subs = true, include_self = true) #:nodoc:
|
925
|
+
if include_subs && name.to_s[/_/] # try sub namespaces first
|
926
|
+
sub, parts = self, name.to_s.split('_')
|
927
|
+
sub_name = parts.shift.to_sym
|
928
|
+
until sub != self || parts.empty?
|
929
|
+
if registry[sub_name].kind_of?(ArtifactNamespace)
|
930
|
+
sub = registry[sub_name]
|
931
|
+
artifact = sub[parts.join('_')]
|
932
|
+
else
|
933
|
+
sub_name = [sub_name, parts.shift].join('_').to_sym
|
934
|
+
end
|
935
|
+
end
|
936
|
+
end
|
937
|
+
unless artifact
|
938
|
+
if include_self
|
939
|
+
artifact = registry.get(name, include_parents)
|
940
|
+
elsif include_parents && registry.parent
|
941
|
+
artifact = registry.parent.get(name, true)
|
942
|
+
end
|
943
|
+
end
|
944
|
+
artifact = artifact.call if artifact.respond_to?(:call)
|
945
|
+
artifact
|
946
|
+
end
|
947
|
+
|
948
|
+
def registry
|
949
|
+
@registry ||= Registry.new.tap do |m|
|
950
|
+
m.parent = parent.send(:registry) unless root?
|
951
|
+
end
|
952
|
+
end
|
953
|
+
|
954
|
+
end # ArtifactNamespace
|
955
|
+
|
956
|
+
# :call-seq:
|
957
|
+
# project.artifact_ns -> ArtifactNamespace
|
958
|
+
# Buildr.artifact_ns(name) -> ArtifactNamespace
|
959
|
+
# Buildr.artifact_ns -> ArtifactNamespace for the currently running Project
|
960
|
+
#
|
961
|
+
# Open an ArtifactNamespace.
|
962
|
+
# If a block is provided, the namespace is yielded to it.
|
963
|
+
#
|
964
|
+
# See also ArtifactNamespace.instance
|
965
|
+
def artifact_ns(name = nil, &block)
|
966
|
+
name = self if name.nil? && self.kind_of?(Project)
|
967
|
+
ArtifactNamespace.instance(name, &block)
|
968
|
+
end
|
969
|
+
|
970
|
+
end
|
971
|
+
|
972
|
+
|