buildr 1.3.5-x86-mswin32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (186) hide show
  1. data/CHANGELOG +998 -0
  2. data/LICENSE +176 -0
  3. data/NOTICE +26 -0
  4. data/README.rdoc +134 -0
  5. data/Rakefile +45 -0
  6. data/_buildr +29 -0
  7. data/_jbuildr +29 -0
  8. data/addon/buildr/antlr.rb +65 -0
  9. data/addon/buildr/cobertura.rb +22 -0
  10. data/addon/buildr/drb.rb +281 -0
  11. data/addon/buildr/emma.rb +22 -0
  12. data/addon/buildr/hibernate.rb +142 -0
  13. data/addon/buildr/javacc.rb +85 -0
  14. data/addon/buildr/jdepend.rb +60 -0
  15. data/addon/buildr/jetty.rb +248 -0
  16. data/addon/buildr/jibx.rb +86 -0
  17. data/addon/buildr/nailgun.rb +221 -0
  18. data/addon/buildr/openjpa.rb +90 -0
  19. data/addon/buildr/org/apache/buildr/BuildrNail$Main.class +0 -0
  20. data/addon/buildr/org/apache/buildr/BuildrNail.class +0 -0
  21. data/addon/buildr/org/apache/buildr/BuildrNail.java +41 -0
  22. data/addon/buildr/org/apache/buildr/JettyWrapper$1.class +0 -0
  23. data/addon/buildr/org/apache/buildr/JettyWrapper$BuildrHandler.class +0 -0
  24. data/addon/buildr/org/apache/buildr/JettyWrapper.class +0 -0
  25. data/addon/buildr/org/apache/buildr/JettyWrapper.java +144 -0
  26. data/addon/buildr/xmlbeans.rb +93 -0
  27. data/bin/buildr +19 -0
  28. data/buildr.buildfile +58 -0
  29. data/buildr.gemspec +65 -0
  30. data/doc/_config.yml +1 -0
  31. data/doc/_layouts/default.html +88 -0
  32. data/doc/_layouts/preface.html +22 -0
  33. data/doc/artifacts.textile +211 -0
  34. data/doc/building.textile +244 -0
  35. data/doc/contributing.textile +252 -0
  36. data/doc/css/default.css +236 -0
  37. data/doc/css/print.css +101 -0
  38. data/doc/css/syntax.css +23 -0
  39. data/doc/download.textile +79 -0
  40. data/doc/extending.textile +186 -0
  41. data/doc/images/1442160941-frontcover.jpg +0 -0
  42. data/doc/images/asf-logo.gif +0 -0
  43. data/doc/images/asf-logo.png +0 -0
  44. data/doc/images/buildr-hires.png +0 -0
  45. data/doc/images/buildr.png +0 -0
  46. data/doc/images/favicon.png +0 -0
  47. data/doc/images/growl-icon.tiff +0 -0
  48. data/doc/images/note.png +0 -0
  49. data/doc/images/project-structure.png +0 -0
  50. data/doc/images/tip.png +0 -0
  51. data/doc/images/zbuildr.png +0 -0
  52. data/doc/images/zbuildr.tif +0 -0
  53. data/doc/index.textile +69 -0
  54. data/doc/installing.textile +266 -0
  55. data/doc/languages.textile +459 -0
  56. data/doc/mailing_lists.textile +25 -0
  57. data/doc/more_stuff.textile +457 -0
  58. data/doc/packaging.textile +430 -0
  59. data/doc/preface.textile +54 -0
  60. data/doc/projects.textile +271 -0
  61. data/doc/quick_start.textile +210 -0
  62. data/doc/scripts/buildr-git.rb +512 -0
  63. data/doc/scripts/gitflow.rb +296 -0
  64. data/doc/scripts/install-jruby.sh +44 -0
  65. data/doc/scripts/install-linux.sh +72 -0
  66. data/doc/scripts/install-osx.sh +52 -0
  67. data/doc/settings_profiles.textile +280 -0
  68. data/doc/testing.textile +222 -0
  69. data/etc/KEYS +151 -0
  70. data/lib/buildr.rb +36 -0
  71. data/lib/buildr/core.rb +35 -0
  72. data/lib/buildr/core/application.rb +656 -0
  73. data/lib/buildr/core/build.rb +452 -0
  74. data/lib/buildr/core/checks.rb +254 -0
  75. data/lib/buildr/core/common.rb +150 -0
  76. data/lib/buildr/core/compile.rb +608 -0
  77. data/lib/buildr/core/environment.rb +129 -0
  78. data/lib/buildr/core/filter.rb +362 -0
  79. data/lib/buildr/core/generate.rb +195 -0
  80. data/lib/buildr/core/help.rb +119 -0
  81. data/lib/buildr/core/osx.rb +46 -0
  82. data/lib/buildr/core/progressbar.rb +156 -0
  83. data/lib/buildr/core/project.rb +866 -0
  84. data/lib/buildr/core/shell.rb +198 -0
  85. data/lib/buildr/core/test.rb +723 -0
  86. data/lib/buildr/core/transports.rb +559 -0
  87. data/lib/buildr/core/util.rb +449 -0
  88. data/lib/buildr/groovy.rb +19 -0
  89. data/lib/buildr/groovy/bdd.rb +106 -0
  90. data/lib/buildr/groovy/compiler.rb +138 -0
  91. data/lib/buildr/groovy/shell.rb +48 -0
  92. data/lib/buildr/ide.rb +19 -0
  93. data/lib/buildr/ide/eclipse.rb +334 -0
  94. data/lib/buildr/ide/eclipse/java.rb +53 -0
  95. data/lib/buildr/ide/eclipse/plugin.rb +68 -0
  96. data/lib/buildr/ide/eclipse/scala.rb +66 -0
  97. data/lib/buildr/ide/idea.ipr.template +300 -0
  98. data/lib/buildr/ide/idea.rb +190 -0
  99. data/lib/buildr/ide/idea7x.ipr.template +290 -0
  100. data/lib/buildr/ide/idea7x.rb +212 -0
  101. data/lib/buildr/java.rb +23 -0
  102. data/lib/buildr/java/ant.rb +94 -0
  103. data/lib/buildr/java/bdd.rb +459 -0
  104. data/lib/buildr/java/cobertura.rb +274 -0
  105. data/lib/buildr/java/commands.rb +213 -0
  106. data/lib/buildr/java/compiler.rb +349 -0
  107. data/lib/buildr/java/deprecated.rb +141 -0
  108. data/lib/buildr/java/emma.rb +244 -0
  109. data/lib/buildr/java/jruby.rb +117 -0
  110. data/lib/buildr/java/jtestr_runner.rb.erb +116 -0
  111. data/lib/buildr/java/org/apache/buildr/JavaTestFilter.class +0 -0
  112. data/lib/buildr/java/org/apache/buildr/JavaTestFilter.java +137 -0
  113. data/lib/buildr/java/packaging.rb +716 -0
  114. data/lib/buildr/java/pom.rb +174 -0
  115. data/lib/buildr/java/rjb.rb +155 -0
  116. data/lib/buildr/java/test_result.rb +353 -0
  117. data/lib/buildr/java/tests.rb +333 -0
  118. data/lib/buildr/java/version_requirement.rb +172 -0
  119. data/lib/buildr/packaging.rb +24 -0
  120. data/lib/buildr/packaging/archive.rb +488 -0
  121. data/lib/buildr/packaging/artifact.rb +749 -0
  122. data/lib/buildr/packaging/artifact_namespace.rb +972 -0
  123. data/lib/buildr/packaging/artifact_search.rb +140 -0
  124. data/lib/buildr/packaging/gems.rb +102 -0
  125. data/lib/buildr/packaging/package.rb +238 -0
  126. data/lib/buildr/packaging/tar.rb +186 -0
  127. data/lib/buildr/packaging/version_requirement.rb +172 -0
  128. data/lib/buildr/packaging/zip.rb +73 -0
  129. data/lib/buildr/packaging/ziptask.rb +316 -0
  130. data/lib/buildr/resources/buildr.icns +0 -0
  131. data/lib/buildr/scala.rb +25 -0
  132. data/lib/buildr/scala/bdd.rb +109 -0
  133. data/lib/buildr/scala/compiler.rb +195 -0
  134. data/lib/buildr/scala/org/apache/buildr/SpecsSingletonRunner$.class +0 -0
  135. data/lib/buildr/scala/org/apache/buildr/SpecsSingletonRunner.class +0 -0
  136. data/lib/buildr/scala/org/apache/buildr/SpecsSingletonRunner.scala +35 -0
  137. data/lib/buildr/scala/shell.rb +55 -0
  138. data/lib/buildr/scala/tests.rb +157 -0
  139. data/lib/buildr/shell.rb +180 -0
  140. data/rakelib/checks.rake +57 -0
  141. data/rakelib/doc.rake +92 -0
  142. data/rakelib/jekylltask.rb +120 -0
  143. data/rakelib/package.rake +73 -0
  144. data/rakelib/release.rake +149 -0
  145. data/rakelib/rspec.rake +73 -0
  146. data/rakelib/setup.rake +54 -0
  147. data/rakelib/stage.rake +213 -0
  148. data/rakelib/stage.rake~ +213 -0
  149. data/spec/addon/drb_spec.rb +328 -0
  150. data/spec/core/application_spec.rb +502 -0
  151. data/spec/core/build_spec.rb +677 -0
  152. data/spec/core/checks_spec.rb +519 -0
  153. data/spec/core/common_spec.rb +670 -0
  154. data/spec/core/compile_spec.rb +583 -0
  155. data/spec/core/extension_spec.rb +93 -0
  156. data/spec/core/generate_spec.rb +33 -0
  157. data/spec/core/project_spec.rb +762 -0
  158. data/spec/core/test_spec.rb +1098 -0
  159. data/spec/core/transport_spec.rb +537 -0
  160. data/spec/core/util_spec.rb +67 -0
  161. data/spec/groovy/bdd_spec.rb +80 -0
  162. data/spec/groovy/compiler_spec.rb +240 -0
  163. data/spec/ide/eclipse_spec.rb +501 -0
  164. data/spec/ide/idea7x_spec.rb +84 -0
  165. data/spec/java/ant_spec.rb +33 -0
  166. data/spec/java/bdd_spec.rb +382 -0
  167. data/spec/java/cobertura_spec.rb +85 -0
  168. data/spec/java/compiler_spec.rb +446 -0
  169. data/spec/java/emma_spec.rb +119 -0
  170. data/spec/java/java_spec.rb +124 -0
  171. data/spec/java/packaging_spec.rb +1134 -0
  172. data/spec/java/test_coverage_helper.rb +257 -0
  173. data/spec/java/tests_spec.rb +493 -0
  174. data/spec/packaging/archive_spec.rb +527 -0
  175. data/spec/packaging/artifact_namespace_spec.rb +654 -0
  176. data/spec/packaging/artifact_spec.rb +795 -0
  177. data/spec/packaging/packaging_helper.rb +63 -0
  178. data/spec/packaging/packaging_spec.rb +684 -0
  179. data/spec/sandbox.rb +142 -0
  180. data/spec/scala/bdd_spec.rb +119 -0
  181. data/spec/scala/compiler_spec.rb +284 -0
  182. data/spec/scala/scala.rb +38 -0
  183. data/spec/scala/tests_spec.rb +261 -0
  184. data/spec/spec_helpers.rb +340 -0
  185. data/spec/version_requirement_spec.rb +129 -0
  186. metadata +383 -0
@@ -0,0 +1,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
+