buildr 1.3.5-x86-mswin32
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|