buildr-gemjar 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (252) hide show
  1. data/.braids +8 -0
  2. data/.gitignore +5 -0
  3. data/.rvmrc +1 -0
  4. data/CHANGELOG.md +4 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE +20 -0
  7. data/README.md +98 -0
  8. data/Rakefile +8 -0
  9. data/buildr-gemjar.gemspec +42 -0
  10. data/lib/buildr-gemjar.rb +162 -0
  11. data/lib/buildr-gemjar/version.rb +3 -0
  12. data/meta.rakefile +30 -0
  13. data/spec/buildr-gemjar/version_spec.rb +11 -0
  14. data/spec/buildr-gemjar_spec.rb +179 -0
  15. data/spec/repo_builder.rb +59 -0
  16. data/spec/spec_helper.rb +44 -0
  17. data/vendor/buildr/.gitignore +17 -0
  18. data/vendor/buildr/CHANGELOG +1283 -0
  19. data/vendor/buildr/Gemfile +4 -0
  20. data/vendor/buildr/LICENSE +176 -0
  21. data/vendor/buildr/NOTICE +26 -0
  22. data/vendor/buildr/README.rdoc +134 -0
  23. data/vendor/buildr/Rakefile +44 -0
  24. data/vendor/buildr/_buildr +35 -0
  25. data/vendor/buildr/_jbuildr +35 -0
  26. data/vendor/buildr/addon/buildr/antlr.rb +65 -0
  27. data/vendor/buildr/addon/buildr/bnd.rb +147 -0
  28. data/vendor/buildr/addon/buildr/cobertura.rb +22 -0
  29. data/vendor/buildr/addon/buildr/drb.rb +281 -0
  30. data/vendor/buildr/addon/buildr/emma.rb +22 -0
  31. data/vendor/buildr/addon/buildr/hibernate.rb +149 -0
  32. data/vendor/buildr/addon/buildr/javacc.rb +85 -0
  33. data/vendor/buildr/addon/buildr/jaxb_xjc.rb +72 -0
  34. data/vendor/buildr/addon/buildr/jdepend.rb +60 -0
  35. data/vendor/buildr/addon/buildr/jetty.rb +248 -0
  36. data/vendor/buildr/addon/buildr/jibx.rb +86 -0
  37. data/vendor/buildr/addon/buildr/nailgun.rb +221 -0
  38. data/vendor/buildr/addon/buildr/openjpa.rb +88 -0
  39. data/vendor/buildr/addon/buildr/org/apache/buildr/BuildrNail$Main.class +0 -0
  40. data/vendor/buildr/addon/buildr/org/apache/buildr/BuildrNail.class +0 -0
  41. data/vendor/buildr/addon/buildr/org/apache/buildr/BuildrNail.java +41 -0
  42. data/vendor/buildr/addon/buildr/org/apache/buildr/JettyWrapper$1.class +0 -0
  43. data/vendor/buildr/addon/buildr/org/apache/buildr/JettyWrapper$BuildrHandler.class +0 -0
  44. data/vendor/buildr/addon/buildr/org/apache/buildr/JettyWrapper.class +0 -0
  45. data/vendor/buildr/addon/buildr/org/apache/buildr/JettyWrapper.java +144 -0
  46. data/vendor/buildr/addon/buildr/protobuf.rb +88 -0
  47. data/vendor/buildr/addon/buildr/xmlbeans.rb +93 -0
  48. data/vendor/buildr/all-in-one/_buildr +19 -0
  49. data/vendor/buildr/all-in-one/buildr +368 -0
  50. data/vendor/buildr/all-in-one/buildr.cmd +1 -0
  51. data/vendor/buildr/bin/buildr +19 -0
  52. data/vendor/buildr/buildr.buildfile +58 -0
  53. data/vendor/buildr/buildr.gemspec +74 -0
  54. data/vendor/buildr/doc/_config.yml +1 -0
  55. data/vendor/buildr/doc/_layouts/default.html +90 -0
  56. data/vendor/buildr/doc/_layouts/preface.html +22 -0
  57. data/vendor/buildr/doc/artifacts.textile +217 -0
  58. data/vendor/buildr/doc/building.textile +276 -0
  59. data/vendor/buildr/doc/contributing.textile +268 -0
  60. data/vendor/buildr/doc/css/default.css +236 -0
  61. data/vendor/buildr/doc/css/print.css +101 -0
  62. data/vendor/buildr/doc/css/syntax.css +23 -0
  63. data/vendor/buildr/doc/download.textile +138 -0
  64. data/vendor/buildr/doc/extending.textile +212 -0
  65. data/vendor/buildr/doc/images/1442160941-frontcover.jpg +0 -0
  66. data/vendor/buildr/doc/images/asf-logo.gif +0 -0
  67. data/vendor/buildr/doc/images/asf-logo.png +0 -0
  68. data/vendor/buildr/doc/images/buildr-hires.png +0 -0
  69. data/vendor/buildr/doc/images/buildr.png +0 -0
  70. data/vendor/buildr/doc/images/favicon.png +0 -0
  71. data/vendor/buildr/doc/images/growl-icon.tiff +0 -0
  72. data/vendor/buildr/doc/images/note.png +0 -0
  73. data/vendor/buildr/doc/images/project-structure.png +0 -0
  74. data/vendor/buildr/doc/images/tip.png +0 -0
  75. data/vendor/buildr/doc/images/zbuildr.png +0 -0
  76. data/vendor/buildr/doc/images/zbuildr.tif +0 -0
  77. data/vendor/buildr/doc/index.textile +69 -0
  78. data/vendor/buildr/doc/installing.textile +284 -0
  79. data/vendor/buildr/doc/languages.textile +599 -0
  80. data/vendor/buildr/doc/mailing_lists.textile +29 -0
  81. data/vendor/buildr/doc/more_stuff.textile +845 -0
  82. data/vendor/buildr/doc/packaging.textile +618 -0
  83. data/vendor/buildr/doc/preface.textile +54 -0
  84. data/vendor/buildr/doc/projects.textile +276 -0
  85. data/vendor/buildr/doc/quick_start.textile +210 -0
  86. data/vendor/buildr/doc/releasing.textile +117 -0
  87. data/vendor/buildr/doc/scripts/buildr-git.rb +512 -0
  88. data/vendor/buildr/doc/scripts/gitflow.rb +296 -0
  89. data/vendor/buildr/doc/scripts/install-jruby.sh +44 -0
  90. data/vendor/buildr/doc/scripts/install-linux.sh +73 -0
  91. data/vendor/buildr/doc/scripts/install-osx.sh +52 -0
  92. data/vendor/buildr/doc/settings_profiles.textile +287 -0
  93. data/vendor/buildr/doc/testing.textile +247 -0
  94. data/vendor/buildr/etc/KEYS +189 -0
  95. data/vendor/buildr/lib/buildr.rb +44 -0
  96. data/vendor/buildr/lib/buildr/clojure.rb +34 -0
  97. data/vendor/buildr/lib/buildr/clojure/shell.rb +52 -0
  98. data/vendor/buildr/lib/buildr/core.rb +34 -0
  99. data/vendor/buildr/lib/buildr/core/application.rb +700 -0
  100. data/vendor/buildr/lib/buildr/core/build.rb +516 -0
  101. data/vendor/buildr/lib/buildr/core/cc.rb +166 -0
  102. data/vendor/buildr/lib/buildr/core/checks.rb +253 -0
  103. data/vendor/buildr/lib/buildr/core/common.rb +151 -0
  104. data/vendor/buildr/lib/buildr/core/compile.rb +622 -0
  105. data/vendor/buildr/lib/buildr/core/doc.rb +276 -0
  106. data/vendor/buildr/lib/buildr/core/environment.rb +129 -0
  107. data/vendor/buildr/lib/buildr/core/filter.rb +404 -0
  108. data/vendor/buildr/lib/buildr/core/generate.rb +197 -0
  109. data/vendor/buildr/lib/buildr/core/help.rb +119 -0
  110. data/vendor/buildr/lib/buildr/core/jrebel.rb +42 -0
  111. data/vendor/buildr/lib/buildr/core/linux.rb +30 -0
  112. data/vendor/buildr/lib/buildr/core/osx.rb +46 -0
  113. data/vendor/buildr/lib/buildr/core/progressbar.rb +161 -0
  114. data/vendor/buildr/lib/buildr/core/project.rb +975 -0
  115. data/vendor/buildr/lib/buildr/core/run.rb +43 -0
  116. data/vendor/buildr/lib/buildr/core/shell.rb +137 -0
  117. data/vendor/buildr/lib/buildr/core/test.rb +843 -0
  118. data/vendor/buildr/lib/buildr/core/transports.rb +565 -0
  119. data/vendor/buildr/lib/buildr/core/util.rb +537 -0
  120. data/vendor/buildr/lib/buildr/groovy.rb +20 -0
  121. data/vendor/buildr/lib/buildr/groovy/bdd.rb +106 -0
  122. data/vendor/buildr/lib/buildr/groovy/compiler.rb +153 -0
  123. data/vendor/buildr/lib/buildr/groovy/doc.rb +76 -0
  124. data/vendor/buildr/lib/buildr/groovy/shell.rb +57 -0
  125. data/vendor/buildr/lib/buildr/ide.rb +19 -0
  126. data/vendor/buildr/lib/buildr/ide/eclipse.rb +427 -0
  127. data/vendor/buildr/lib/buildr/ide/eclipse/java.rb +53 -0
  128. data/vendor/buildr/lib/buildr/ide/eclipse/plugin.rb +71 -0
  129. data/vendor/buildr/lib/buildr/ide/eclipse/scala.rb +68 -0
  130. data/vendor/buildr/lib/buildr/ide/idea.rb +576 -0
  131. data/vendor/buildr/lib/buildr/java.rb +25 -0
  132. data/vendor/buildr/lib/buildr/java/ant.rb +94 -0
  133. data/vendor/buildr/lib/buildr/java/bdd.rb +460 -0
  134. data/vendor/buildr/lib/buildr/java/cobertura.rb +297 -0
  135. data/vendor/buildr/lib/buildr/java/commands.rb +223 -0
  136. data/vendor/buildr/lib/buildr/java/compiler.rb +135 -0
  137. data/vendor/buildr/lib/buildr/java/deprecated.rb +141 -0
  138. data/vendor/buildr/lib/buildr/java/doc.rb +86 -0
  139. data/vendor/buildr/lib/buildr/java/ecj.rb +69 -0
  140. data/vendor/buildr/lib/buildr/java/emma.rb +244 -0
  141. data/vendor/buildr/lib/buildr/java/external.rb +73 -0
  142. data/vendor/buildr/lib/buildr/java/jruby.rb +122 -0
  143. data/vendor/buildr/lib/buildr/java/jtestr_result.rb +295 -0
  144. data/vendor/buildr/lib/buildr/java/jtestr_runner.rb.erb +116 -0
  145. data/vendor/buildr/lib/buildr/java/org/apache/buildr/JavaTestFilter.class +0 -0
  146. data/vendor/buildr/lib/buildr/java/org/apache/buildr/JavaTestFilter.java +142 -0
  147. data/vendor/buildr/lib/buildr/java/packaging.rb +734 -0
  148. data/vendor/buildr/lib/buildr/java/pom.rb +178 -0
  149. data/vendor/buildr/lib/buildr/java/rjb.rb +154 -0
  150. data/vendor/buildr/lib/buildr/java/test_result.rb +101 -0
  151. data/vendor/buildr/lib/buildr/java/tests.rb +362 -0
  152. data/vendor/buildr/lib/buildr/java/version_requirement.rb +172 -0
  153. data/vendor/buildr/lib/buildr/packaging.rb +25 -0
  154. data/vendor/buildr/lib/buildr/packaging/archive.rb +535 -0
  155. data/vendor/buildr/lib/buildr/packaging/artifact.rb +903 -0
  156. data/vendor/buildr/lib/buildr/packaging/artifact_namespace.rb +984 -0
  157. data/vendor/buildr/lib/buildr/packaging/artifact_search.rb +140 -0
  158. data/vendor/buildr/lib/buildr/packaging/gems.rb +105 -0
  159. data/vendor/buildr/lib/buildr/packaging/package.rb +249 -0
  160. data/vendor/buildr/lib/buildr/packaging/tar.rb +189 -0
  161. data/vendor/buildr/lib/buildr/packaging/version_requirement.rb +192 -0
  162. data/vendor/buildr/lib/buildr/packaging/zip.rb +178 -0
  163. data/vendor/buildr/lib/buildr/packaging/ziptask.rb +356 -0
  164. data/vendor/buildr/lib/buildr/resources/buildr.icns +0 -0
  165. data/vendor/buildr/lib/buildr/resources/completed.png +0 -0
  166. data/vendor/buildr/lib/buildr/resources/failed.png +0 -0
  167. data/vendor/buildr/lib/buildr/resources/icons-license.txt +17 -0
  168. data/vendor/buildr/lib/buildr/run.rb +195 -0
  169. data/vendor/buildr/lib/buildr/scala.rb +26 -0
  170. data/vendor/buildr/lib/buildr/scala/bdd.rb +118 -0
  171. data/vendor/buildr/lib/buildr/scala/compiler.rb +242 -0
  172. data/vendor/buildr/lib/buildr/scala/doc.rb +142 -0
  173. data/vendor/buildr/lib/buildr/scala/org/apache/buildr/SpecsSingletonRunner.class +0 -0
  174. data/vendor/buildr/lib/buildr/scala/org/apache/buildr/SpecsSingletonRunner.java +57 -0
  175. data/vendor/buildr/lib/buildr/scala/shell.rb +52 -0
  176. data/vendor/buildr/lib/buildr/scala/tests.rb +171 -0
  177. data/vendor/buildr/lib/buildr/shell.rb +185 -0
  178. data/vendor/buildr/lib/buildr/version.rb +18 -0
  179. data/vendor/buildr/rakelib/all-in-one.rake +113 -0
  180. data/vendor/buildr/rakelib/checks.rake +57 -0
  181. data/vendor/buildr/rakelib/doc.rake +137 -0
  182. data/vendor/buildr/rakelib/metrics.rake +39 -0
  183. data/vendor/buildr/rakelib/package.rake +73 -0
  184. data/vendor/buildr/rakelib/release.rake +161 -0
  185. data/vendor/buildr/rakelib/rspec.rake +101 -0
  186. data/vendor/buildr/rakelib/setup.rake +66 -0
  187. data/vendor/buildr/rakelib/stage.rake +220 -0
  188. data/vendor/buildr/spec/addon/bnd_spec.rb +330 -0
  189. data/vendor/buildr/spec/addon/drb_spec.rb +328 -0
  190. data/vendor/buildr/spec/addon/jaxb_xjc_spec.rb +125 -0
  191. data/vendor/buildr/spec/core/application_spec.rb +631 -0
  192. data/vendor/buildr/spec/core/build_spec.rb +837 -0
  193. data/vendor/buildr/spec/core/cc_spec.rb +224 -0
  194. data/vendor/buildr/spec/core/checks_spec.rb +519 -0
  195. data/vendor/buildr/spec/core/common_spec.rb +725 -0
  196. data/vendor/buildr/spec/core/compile_spec.rb +658 -0
  197. data/vendor/buildr/spec/core/doc_spec.rb +195 -0
  198. data/vendor/buildr/spec/core/extension_spec.rb +201 -0
  199. data/vendor/buildr/spec/core/generate_spec.rb +33 -0
  200. data/vendor/buildr/spec/core/project_spec.rb +772 -0
  201. data/vendor/buildr/spec/core/run_spec.rb +93 -0
  202. data/vendor/buildr/spec/core/shell_spec.rb +146 -0
  203. data/vendor/buildr/spec/core/test_spec.rb +1320 -0
  204. data/vendor/buildr/spec/core/transport_spec.rb +544 -0
  205. data/vendor/buildr/spec/core/util_spec.rb +141 -0
  206. data/vendor/buildr/spec/groovy/bdd_spec.rb +80 -0
  207. data/vendor/buildr/spec/groovy/compiler_spec.rb +251 -0
  208. data/vendor/buildr/spec/groovy/doc_spec.rb +65 -0
  209. data/vendor/buildr/spec/ide/eclipse_spec.rb +739 -0
  210. data/vendor/buildr/spec/ide/idea_spec.rb +1144 -0
  211. data/vendor/buildr/spec/java/ant_spec.rb +37 -0
  212. data/vendor/buildr/spec/java/bdd_spec.rb +374 -0
  213. data/vendor/buildr/spec/java/cobertura_spec.rb +112 -0
  214. data/vendor/buildr/spec/java/commands_spec.rb +93 -0
  215. data/vendor/buildr/spec/java/compiler_spec.rb +252 -0
  216. data/vendor/buildr/spec/java/doc_spec.rb +56 -0
  217. data/vendor/buildr/spec/java/ecj_spec.rb +115 -0
  218. data/vendor/buildr/spec/java/emma_spec.rb +121 -0
  219. data/vendor/buildr/spec/java/external_spec.rb +56 -0
  220. data/vendor/buildr/spec/java/java_spec.rb +132 -0
  221. data/vendor/buildr/spec/java/packaging_spec.rb +1270 -0
  222. data/vendor/buildr/spec/java/run_spec.rb +78 -0
  223. data/vendor/buildr/spec/java/test_coverage_helper.rb +257 -0
  224. data/vendor/buildr/spec/java/tests_spec.rb +497 -0
  225. data/vendor/buildr/spec/packaging/archive_spec.rb +775 -0
  226. data/vendor/buildr/spec/packaging/artifact_namespace_spec.rb +743 -0
  227. data/vendor/buildr/spec/packaging/artifact_spec.rb +1066 -0
  228. data/vendor/buildr/spec/packaging/packaging_helper.rb +63 -0
  229. data/vendor/buildr/spec/packaging/packaging_spec.rb +719 -0
  230. data/vendor/buildr/spec/sandbox.rb +165 -0
  231. data/vendor/buildr/spec/scala/bdd_spec.rb +124 -0
  232. data/vendor/buildr/spec/scala/compiler_spec.rb +289 -0
  233. data/vendor/buildr/spec/scala/doc_spec.rb +88 -0
  234. data/vendor/buildr/spec/scala/scala.rb +38 -0
  235. data/vendor/buildr/spec/scala/tests_spec.rb +283 -0
  236. data/vendor/buildr/spec/spec_helpers.rb +369 -0
  237. data/vendor/buildr/spec/version_requirement_spec.rb +143 -0
  238. data/vendor/buildr/spec/xpath_matchers.rb +121 -0
  239. data/vendor/buildr/tests/BUILDR-320/Buildfile +29 -0
  240. data/vendor/buildr/tests/JavaSystemProperty/Buildfile +18 -0
  241. data/vendor/buildr/tests/JavaSystemProperty/src/test/java/FooTest.java +24 -0
  242. data/vendor/buildr/tests/compile_with_parent/Buildfile +18 -0
  243. data/vendor/buildr/tests/compile_with_parent/child/src/main/java/Foo.java +23 -0
  244. data/vendor/buildr/tests/helloWorld/Buildfile +20 -0
  245. data/vendor/buildr/tests/helloWorld/src/main/java/HelloWorld.java +23 -0
  246. data/vendor/buildr/tests/integration_testing.rb +56 -0
  247. data/vendor/buildr/tests/junit3/Buildfile +9 -0
  248. data/vendor/buildr/tests/junit3/src/main/java/Foo.java +23 -0
  249. data/vendor/buildr/tests/junit3/src/test/java/FooTest.java +28 -0
  250. data/vendor/buildr/tests/package_war_as_jar/Buildfile +15 -0
  251. data/vendor/buildr/tests/package_war_as_jar/src/main/java/Foo.java +19 -0
  252. metadata +524 -0
@@ -0,0 +1,984 @@
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 pollution 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 different artifact combinations and/or versions. Assigning
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 below 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 ArtifactRequirement objects.
140
+ # In fact the only difference 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:jar: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.settings.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
+ if name.size == 0
278
+ instance = ROOT
279
+ else
280
+ name = name.to_s
281
+ @instances ||= Hash.new { |h, k| h[k] = new(k) }
282
+ instance = @instances[name]
283
+ end
284
+ yield(instance) if block_given?
285
+ instance
286
+ end
287
+
288
+ alias_method :[], :instance
289
+ alias_method :for, :instance
290
+
291
+ # :call-seq:
292
+ # ArtifactNamespace.root { |ns| ... } -> ns
293
+ #
294
+ # Obtain the root namespace, returns the ROOT constant
295
+ def root
296
+ yield ROOT if block_given?
297
+ ROOT
298
+ end
299
+ end
300
+
301
+ module DClone #:nodoc:
302
+ def dclone
303
+ clone = self.clone
304
+ clone.instance_variables.each do |i|
305
+ value = clone.instance_variable_get(i)
306
+ value = value.dclone rescue
307
+ clone.instance_variable_set(i, value)
308
+ end
309
+ clone
310
+ end
311
+ end
312
+
313
+ class Registry < Hash #:nodoc:
314
+ include DClone
315
+
316
+ attr_accessor :parent
317
+ def alias(new_name, old_name)
318
+ new_name = new_name.to_sym
319
+ old_name = old_name.to_sym
320
+ if obj = get(old_name, true)
321
+ self[new_name] = obj
322
+ @aliases ||= []
323
+ group = @aliases.find { |a| a.include?(new_name) }
324
+ group.delete(new_name) if group
325
+ group = @aliases.find { |a| a.include?(old_name) }
326
+ @aliases << (group = [old_name]) unless group
327
+ group << new_name unless group.include?(new_name)
328
+ end
329
+ obj
330
+ end
331
+
332
+ def aliases(name)
333
+ return [] unless name
334
+ name = name.to_sym
335
+ ((@aliases ||= []).find { |a| a.include?(name) } || [name]).dup
336
+ end
337
+
338
+ def []=(key, value)
339
+ return unless key
340
+ super(key.to_sym, value)
341
+ end
342
+
343
+ def get(key, include_parent = nil)
344
+ [].tap { |a| aliases(key).select { |n| a[0] = self[n] } }.first ||
345
+ (include_parent && parent && parent.get(key, include_parent))
346
+ end
347
+
348
+ def keys(include_parent = nil)
349
+ (super() | (include_parent && parent && parent.keys(include_parent) || [])).uniq
350
+ end
351
+
352
+ def values(include_parent = nil)
353
+ (super() | (include_parent && parent && parent.values(include_parent) || [])).uniq
354
+ end
355
+
356
+ def key?(key, include_parent = nil)
357
+ return false unless key
358
+ super(key.to_sym) || (include_parent && parent && parent.key?(key, include_parent))
359
+ end
360
+
361
+ def delete(key, include_parent = nil)
362
+ aliases(key).map {|n| super(n) } && include_parent && parent && parent.delete(key, include_parent)
363
+ end
364
+ end
365
+
366
+ # An artifact requirement is an object that ActsAsArtifact and has
367
+ # an associated VersionRequirement. It also knows the name (some times equal to the
368
+ # artifact id) that is used to store it in an ArtifactNamespace.
369
+ class ArtifactRequirement
370
+ attr_accessor :version
371
+ attr_reader :name, :requirement
372
+
373
+ include DClone
374
+
375
+ # Create a requirement from an `artifact requirement spec`.
376
+ # This spec has three parts, separated by ->
377
+ #
378
+ # some_name -> ar:ti:fact:3.2.5 -> ( >2 & <4)
379
+ #
380
+ # As you can see it's just an artifact spec, prefixed with
381
+ # some_name ->
382
+ # the :some_name symbol becomes this object's name and
383
+ # is used to store it on an ArtifactNamespace.
384
+ #
385
+ # ar:ti:fact:3.2.5
386
+ #
387
+ # The second part is an artifact spec by itself, and specifies
388
+ # all remaining attributes, the version of this spec becomes
389
+ # the default version of this requirement.
390
+ #
391
+ # The last part consist of a VersionRequirement.
392
+ # -> ( >2 & <4)
393
+ #
394
+ # VersionRequirement supports RubyGem's comparision operators
395
+ # in adition to parens, logical and, logical or and negation.
396
+ # See the docs for VersionRequirement for more info on operators.
397
+ def initialize(spec)
398
+ self.class.send :include, ActsAsArtifact unless ActsAsArtifact === self
399
+ if ArtifactRequirement === spec
400
+ copy_attrs(spec)
401
+ else
402
+ spec = requirement_hash(spec)
403
+ apply_spec(spec[:spec])
404
+ self.name = spec[:name]
405
+ @requirement = spec[:requirement]
406
+ @version = @requirement.default if VersionRequirement.requirement?(@version)
407
+ end
408
+ end
409
+
410
+ # Copy attributes from other to this object
411
+ def copy_attrs(other)
412
+ (ActsAsArtifact::ARTIFACT_ATTRIBUTES + [:name, :requirement]).each do |attr|
413
+ value = other.instance_variable_get("@#{attr}")
414
+ value = value.dup if value && !value.kind_of?(Numeric) && !value.kind_of?(Symbol)
415
+ instance_variable_set("@#{attr}", value)
416
+ end
417
+ end
418
+
419
+ def name=(name)
420
+ @name = name.to_s
421
+ end
422
+
423
+ # Set a the requirement, this must be an string formatted for
424
+ # VersionRequirement#create to parse.
425
+ def requirement=(version_requirement)
426
+ @requirement = VersionRequirement.create(version_requirement.to_s)
427
+ end
428
+
429
+ # Return a hash consisting of :name, :spec, :requirement
430
+ def requirement_hash(spec = self)
431
+ result = {}
432
+ if String === spec
433
+ parts = spec.split(/\s*->\s*/, 3).map(&:strip)
434
+ case parts.size
435
+ when 1
436
+ result[:spec] = Artifact.to_hash(parts.first)
437
+ when 2
438
+ if /^\w+$/ === parts.first
439
+ result[:name] = parts.first
440
+ result[:spec] = Artifact.to_hash(parts.last)
441
+ else
442
+ result[:spec] = Artifact.to_hash(parts.first)
443
+ result[:requirement] = VersionRequirement.create(parts.last)
444
+ end
445
+ when 3
446
+ result[:name] = parts.first
447
+ result[:spec] = Artifact.to_hash(parts[1])
448
+ result[:requirement] = VersionRequirement.create(parts.last)
449
+ end
450
+ else
451
+ result[:spec] = Artifact.to_hash(spec)
452
+ end
453
+ result[:name] ||= result[:spec][:id].to_s.to_sym
454
+ result[:requirement] ||= VersionRequirement.create(result[:spec][:version])
455
+ result
456
+ end
457
+
458
+ # Test if this requirement is satisfied by an artifact spec.
459
+ def satisfied_by?(spec)
460
+ return false unless requirement
461
+ spec = Artifact.to_hash(spec)
462
+ hash = to_spec_hash
463
+ hash.delete(:version)
464
+ version = spec.delete(:version)
465
+ hash == spec && requirement.satisfied_by?(version)
466
+ end
467
+
468
+ # Has user selected a version for this requirement?
469
+ def selected?
470
+ @selected
471
+ end
472
+
473
+ def selected! #:nodoc:
474
+ @selected = true
475
+ @listeners.each { |l| l.call(self) } if @listeners
476
+ self
477
+ end
478
+
479
+ def add_listener(&callback)
480
+ (@listeners ||= []) << callback
481
+ end
482
+
483
+ # Return the Artifact object for the currently selected version
484
+ def artifact
485
+ ::Buildr.artifact(self)
486
+ end
487
+
488
+ # Format this requirement as an `artifact requirement spec`
489
+ def to_requirement_spec
490
+ result = to_spec
491
+ result = "#{name} -> #{result}" if name
492
+ result = "#{result} -> #{requirement}" if requirement
493
+ result
494
+ end
495
+
496
+ def to_s #:nodoc:
497
+ id ? to_requirement_spec : version
498
+ end
499
+
500
+ # Return an artifact spec without the version part.
501
+ def unversioned_spec
502
+ str = to_spec
503
+ return nil if str =~ /^:+/
504
+ ary = str.split(':')
505
+ ary = ary[0...-1] if ary.size > 3
506
+ ary.join(':')
507
+ end
508
+
509
+ class << self
510
+ # Return an artifact spec without the version part.
511
+ def unversioned_spec(spec)
512
+ str = spec.to_s
513
+ return nil if str =~ /^:+/
514
+ ary = str.split(':')
515
+ ary = ary[0...-1] if ary.size > 3
516
+ if ary.size > 2
517
+ ary.join(':')
518
+ else
519
+ new(spec).unversioned_spec
520
+ end
521
+ end
522
+ end
523
+ end
524
+
525
+ include DClone
526
+ include Enumerable
527
+ attr_reader :name
528
+
529
+ def initialize(name = nil) #:nodoc:
530
+ @name = name.to_s if name
531
+ end
532
+ clear
533
+
534
+ def root
535
+ yield ROOT if block_given?
536
+ ROOT
537
+ end
538
+
539
+ # ROOT namespace has no parent
540
+ def parent
541
+ if root?
542
+ nil
543
+ elsif @parent.kind_of?(ArtifactNamespace)
544
+ @parent
545
+ elsif @parent
546
+ ArtifactNamespace.instance(@parent)
547
+ elsif name
548
+ parent_name = name.gsub(/::?[^:]+$/, '')
549
+ parent_name == name ? root : ArtifactNamespace.instance(parent_name)
550
+ else
551
+ root
552
+ end
553
+ end
554
+
555
+ # Set the parent for the current namespace, except if it is ROOT
556
+ def parent=(other)
557
+ raise 'Cannot set parent of root namespace' if root?
558
+ @parent = other
559
+ @registry = nil
560
+ end
561
+
562
+ # Is this the ROOT namespace?
563
+ def root?
564
+ ROOT == self
565
+ end
566
+
567
+ # Create a named sub-namespace, sub-namespaces are themselves
568
+ # ArtifactNamespace instances but cannot be referenced by
569
+ # the Buildr.artifact_ns, ArtifactNamespace.instance methods.
570
+ # Reference needs to be through this object using the given +name+
571
+ #
572
+ # artifact_ns('foo').ns(:bar).need :thing => 'some:thing:jar:1.0'
573
+ # artifact_ns('foo').bar # => the sub-namespace 'foo.bar'
574
+ # artifact_ns('foo').bar.thing # => the some thing artifact
575
+ #
576
+ # See the top level ArtifactNamespace documentation for examples
577
+ def ns(name, *uses, &block)
578
+ name = name.to_sym
579
+ sub = registry[name]
580
+ if sub
581
+ raise TypeError.new("#{name} is not a sub namespace of #{self}") unless sub.kind_of?(ArtifactNamespace)
582
+ else
583
+ sub = ArtifactNamespace.new("#{self.name}.#{name}")
584
+ sub.parent = self
585
+ registry[name] = sub
586
+ end
587
+ sub.use(*uses)
588
+ yield sub if block_given?
589
+ sub
590
+ end
591
+
592
+ # Test if a sub-namespace by the given name exists
593
+ def ns?(name)
594
+ sub = registry[name.to_sym]
595
+ ArtifactNamespace === sub
596
+ end
597
+
598
+ # :call-seq:
599
+ # artifact_ns.need 'name -> org:foo:bar:jar:~>1.2.3 -> 1.2.5'
600
+ # artifact_ns.need :name => 'org.foo:bar:jar:1.0'
601
+ #
602
+ # Create a new ArtifactRequirement on this namespace.
603
+ # ArtifactNamespace#method_missing provides syntactic sugar for this.
604
+ def need(*specs)
605
+ named = specs.flatten.inject({}) do |seen, spec|
606
+ if Hash === spec && (spec.keys & ActsAsArtifact::ARTIFACT_ATTRIBUTES).empty?
607
+ spec.each_pair do |name, spec|
608
+ if Array === spec # a group
609
+ seen[name] ||= spec.map { |s| ArtifactRequirement.new(s) }
610
+ else
611
+ artifact = ArtifactRequirement.new(spec)
612
+ artifact.name = name
613
+ seen[artifact.name] ||= artifact
614
+ end
615
+ end
616
+ else
617
+ artifact = ArtifactRequirement.new(spec)
618
+ seen[artifact.name] ||= artifact
619
+ end
620
+ seen
621
+ end
622
+ named.each_pair do |name, artifact|
623
+ if Array === artifact # a group
624
+ artifact.each do |a|
625
+ unvers = a.unversioned_spec
626
+ previous = registry[unvers]
627
+ if previous && previous.selected? && a.satisfied_by?(previous)
628
+ a.version = previous.version
629
+ end
630
+ registry[unvers] = a
631
+ end
632
+ group(name, *(artifact.map { |a| a.unversioned_spec } + [{:namespace => self}]))
633
+ else
634
+ unvers = artifact.unversioned_spec
635
+ previous = registry.get(unvers, true)
636
+ if previous && previous.selected? && artifact.satisfied_by?(previous)
637
+ artifact.version = previous.version
638
+ artifact.selected!
639
+ end
640
+ registry[unvers] = artifact
641
+ registry.alias name, unvers unless name.to_s[/^\s*$/]
642
+ end
643
+ end
644
+ self
645
+ end
646
+
647
+ # :call-seq:
648
+ # artifact_ns.use 'name -> org:foo:bar:jar:1.2.3'
649
+ # artifact_ns.use :name => 'org:foo:bar:jar:1.2.3'
650
+ # artifact_ns.use :name => '2.5.6'
651
+ #
652
+ # First and second form are equivalent, the third is used when an
653
+ # ArtifactRequirement has been previously defined with :name, so it
654
+ # just selects the version.
655
+ #
656
+ # ArtifactNamespace#method_missing provides syntactic sugar for this.
657
+ def use(*specs)
658
+ named = specs.flatten.inject({}) do |seen, spec|
659
+ if Hash === spec && (spec.keys & ActsAsArtifact::ARTIFACT_ATTRIBUTES).empty?
660
+ spec.each_pair do |name, spec|
661
+ if ArtifactNamespace === spec # create as subnamespace
662
+ raise ArgumentError.new("Circular reference") if self == spec
663
+ registry[name.to_sym] = spec
664
+ elsif Numeric === spec || (String === spec && VersionRequirement.version?(spec))
665
+ artifact = ArtifactRequirement.allocate
666
+ artifact.name = name
667
+ artifact.version = spec.to_s
668
+ seen[artifact.name] ||= artifact
669
+ elsif Symbol === spec
670
+ self.alias name, spec
671
+ elsif Array === spec # a group
672
+ seen[name] ||= spec.map { |s| ArtifactRequirement.new(s) }
673
+ else
674
+ artifact = ArtifactRequirement.new(spec)
675
+ artifact.name = name
676
+ seen[artifact.name] ||= artifact
677
+ end
678
+ end
679
+ else
680
+ if Symbol === spec
681
+ artifact = get(spec).dclone
682
+ else
683
+ artifact = ArtifactRequirement.new(spec)
684
+ end
685
+ seen[artifact.name] ||= artifact
686
+ end
687
+ seen
688
+ end
689
+ named.each_pair do |name, artifact|
690
+ is_group = Array === artifact
691
+ artifact = [artifact].flatten.map do |artifact|
692
+ unvers = artifact.unversioned_spec
693
+ previous = get(unvers, false) || get(name, false)
694
+ if previous # have previous on current namespace
695
+ if previous.requirement # we must satisfy the requirement
696
+ unless unvers # we only have the version
697
+ satisfied = previous.requirement.satisfied_by?(artifact.version)
698
+ else
699
+ satisfied = previous.satisfied_by?(artifact)
700
+ end
701
+ raise "Unsatisfied dependency #{previous} " +
702
+ "not satisfied by #{artifact}" unless satisfied
703
+ previous.version = artifact.version # OK, set new version
704
+ artifact = previous # use the same object for aliases
705
+ else # not a requirement, set the new values
706
+ unless artifact.id == previous.id && name != previous.name
707
+ previous.copy_attrs(artifact)
708
+ artifact = previous
709
+ end
710
+ end
711
+ else
712
+ if unvers.nil? && # we only have the version
713
+ (previous = get(unvers, true, false, false))
714
+ version = artifact.version
715
+ artifact.copy_attrs(previous)
716
+ artifact.version = version
717
+ end
718
+ artifact.requirement = nil
719
+ end
720
+ artifact.selected!
721
+ end
722
+ artifact = artifact.first unless is_group
723
+ if is_group
724
+ names = artifact.map do |art|
725
+ unv = art.unversioned_spec
726
+ registry[unv] = art
727
+ unv
728
+ end
729
+ group(name, *(names + [{:namespace => self}]))
730
+ elsif artifact.id
731
+ unvers = artifact.unversioned_spec
732
+ registry[name] = artifact
733
+ registry.alias unvers, name
734
+ else
735
+ registry[name] = artifact
736
+ end
737
+ end
738
+ self
739
+ end
740
+
741
+ # Like Hash#fetch
742
+ def fetch(name, default = nil, &block)
743
+ block ||= proc { raise IndexError.new("No artifact found by name #{name.inspect} in namespace #{self}") }
744
+ real_name = name.to_s[/^[\w\-\.]+$/] ? name : ArtifactRequirement.unversioned_spec(name)
745
+ get(real_name.to_sym) || default || block.call(name)
746
+ end
747
+
748
+ # :call-seq:
749
+ # artifact_ns[:name] -> ArtifactRequirement
750
+ # artifact_ns[:many, :names] -> [ArtifactRequirement]
751
+ def [](*names)
752
+ ary = values_at(*names)
753
+ names.size == 1 ? ary.first : ary
754
+ end
755
+
756
+ # :call-seq:
757
+ # artifact_ns[:name] = 'some:cool:jar:1.0.2'
758
+ # artifact_ns[:name] = '1.0.2'
759
+ #
760
+ # Just like the use method
761
+ def []=(*names)
762
+ values = names.pop
763
+ values = [values] unless Array === values
764
+ names.each_with_index do |name, i|
765
+ use name => (values[i] || values.last)
766
+ end
767
+ end
768
+
769
+ # yield each ArtifactRequirement
770
+ def each(&block)
771
+ values.each(&block)
772
+ end
773
+
774
+ # return Artifact objects for each requirement
775
+ def artifacts(*names)
776
+ (names.empty? && values || values_at(*names)).map(&:artifact)
777
+ end
778
+
779
+ # Return all requirements for this namespace
780
+ def values(include_parents = false, include_groups = true)
781
+ seen, dict = {}, registry
782
+ while dict
783
+ dict.each do |k, v|
784
+ v = v.call if v.respond_to?(:call)
785
+ v = v.values if v.kind_of?(ArtifactNamespace)
786
+ if Array === v && include_groups
787
+ v.compact.each { |v| seen[v.name] = v unless seen.key?(v.name) }
788
+ else
789
+ seen[v.name] = v unless seen.key?(v.name)
790
+ end
791
+ end
792
+ dict = include_parents ? dict.parent : nil
793
+ end
794
+ seen.values
795
+ end
796
+
797
+ # Return only the named requirements
798
+ def values_at(*names)
799
+ names.map do |name|
800
+ catch :artifact do
801
+ unless name.to_s[/^[\w\-\.]+$/]
802
+ unvers = ArtifactRequirement.unversioned_spec(name)
803
+ unless unvers.to_s == name.to_s
804
+ req = ArtifactRequirement.new(name)
805
+ reg = self
806
+ while reg
807
+ candidate = reg.send(:get, unvers, false, false, true)
808
+ throw :artifact, candidate if req.satisfied_by?(candidate)
809
+ reg = reg.parent
810
+ end
811
+ end
812
+ end
813
+ get(name.to_sym)
814
+ end
815
+ end
816
+ end
817
+
818
+ def key?(name, include_parents = false)
819
+ name = ArtifactRequirement.unversioned_spec(name) unless name.to_s[/^[\w\-\.]+$/]
820
+ registry.key?(name, include_parents)
821
+ end
822
+
823
+ def keys
824
+ values.map(&:name)
825
+ end
826
+
827
+ def delete(name, include_parents = false)
828
+ registry.delete(name, include_parents)
829
+ self
830
+ end
831
+
832
+ def clear
833
+ keys.each { |k| delete(k) }
834
+ end
835
+
836
+ # :call-seq:
837
+ # group :who, :me, :you
838
+ # group :them, :me, :you, :namespace => ns
839
+ #
840
+ # Create a virtual group on this namespace. When the namespace
841
+ # is asked for the +who+ artifact, it's value is an array made from
842
+ # the remaining names. These names are searched by default from the current
843
+ # namespace.
844
+ # Second form specified the starting namespace to search from.
845
+ def group(group_name, *members)
846
+ namespace = (Hash === members.last && members.pop[:namespace]) || :current
847
+ registry[group_name] = lambda do
848
+ artifacts = self.class[namespace].values_at(*members)
849
+ artifacts = artifacts.first if members.size == 1
850
+ artifacts
851
+ end
852
+ self
853
+ end
854
+
855
+ alias_method :virtual, :group
856
+
857
+ # Create an alias for a named requirement.
858
+ def alias(new_name, old_name)
859
+ registry.alias(new_name, old_name) or
860
+ raise NameError.new("Undefined artifact name: #{old_name}")
861
+ end
862
+
863
+ def to_s #:nodoc:
864
+ name.to_s
865
+ end
866
+
867
+ # :call-seq:
868
+ # artifact_ns.cool_aid!('cool:aid:jar:2.3.4', '~>2.3') -> artifact_requirement
869
+ # artifact_ns.cool_aid = '2.3.5'
870
+ # artifact_ns.cool_aid -> artifact_requirement
871
+ # artifact_ns.cool_aid? -> true | false
872
+ #
873
+ # First form creates an ArtifactRequirement on the namespace.
874
+ # It is equivalent to providing a requirement_spec to the #need method:
875
+ # artifact_ns.need "cool_aid -> cool:aid:jar:2.3.4 -> ~>2.3"
876
+ # the second argument is optional.
877
+ #
878
+ # Second form can be used to select an artifact version
879
+ # and is equivalent to:
880
+ # artifact_ns.use :cool_aid => '1.0'
881
+ #
882
+ # Third form obtains the named ArtifactRequirement, can be
883
+ # used to test if a named requirement has been defined.
884
+ # It is equivalent to:
885
+ # artifact_ns.fetch(:cool_aid) { nil }
886
+ #
887
+ # Last form tests if the ArtifactRequirement has been defined
888
+ # and a version has been selected for use.
889
+ # It is equivalent to:
890
+ #
891
+ # artifact_ns.has_cool_aid?
892
+ # artifact_ns.values_at(:cool_aid).flatten.all? { |a| a && a.selected? }
893
+ #
894
+ def method_missing(name, *args, &block)
895
+ case name.to_s
896
+ when /!$/ then
897
+ name = $`.intern
898
+ if args.size < 1 || args.size > 2
899
+ raise ArgumentError.new("wrong number of arguments for #{name}!(spec, version_requirement?)")
900
+ end
901
+ need name => args.first
902
+ get(name).tap { |r| r.requirement = args.last if args.size == 2 }
903
+ when /=$/ then use $` => args.first
904
+ when /\?$/ then
905
+ name = $`.gsub(/^(has|have)_/, '').intern
906
+ [get(name)].flatten.all? { |a| a && a.selected? }
907
+ else
908
+ if block || args.size > 0
909
+ raise ArgumentError.new("wrong number of arguments #{args.size} for 0 or block given")
910
+ end
911
+ get(name)
912
+ end
913
+ end
914
+
915
+ # Return an anonymous module
916
+ # # first create a requirement
917
+ # artifact_ns.cool_aid! 'cool:aid:jar:>=1.0'
918
+ #
919
+ # # extend an object as a cool_aid delegator
920
+ # jars = Object.new.extend(artifact_ns.accessor(:cool_aid))
921
+ # jars.cool_aid = '2.0'
922
+ #
923
+ # artifact_ns.cool_aid.version # -> '2.0'
924
+ def accessor(*names)
925
+ ns = self
926
+ Module.new do
927
+ names.each do |name|
928
+ define_method("#{name}") { ns.send("#{name}") }
929
+ define_method("#{name}?") { ns.send("#{name}?") }
930
+ define_method("#{name}=") { |vers| ns.send("#{name}=", vers) }
931
+ end
932
+ end
933
+ end
934
+
935
+ private
936
+ def get(name, include_parents = true, include_subs = true, include_self = true) #:nodoc:
937
+ if include_subs && name.to_s[/_/] # try sub namespaces first
938
+ sub, parts = self, name.to_s.split('_')
939
+ sub_name = parts.shift.to_sym
940
+ until sub != self || parts.empty?
941
+ if registry[sub_name].kind_of?(ArtifactNamespace)
942
+ sub = registry[sub_name]
943
+ artifact = sub[parts.join('_')]
944
+ else
945
+ sub_name = [sub_name, parts.shift].join('_').to_sym
946
+ end
947
+ end
948
+ end
949
+ unless artifact
950
+ if include_self
951
+ artifact = registry.get(name, include_parents)
952
+ elsif include_parents && registry.parent
953
+ artifact = registry.parent.get(name, true)
954
+ end
955
+ end
956
+ artifact = artifact.call if artifact.respond_to?(:call)
957
+ artifact
958
+ end
959
+
960
+ def registry
961
+ @registry ||= Registry.new.tap do |m|
962
+ m.parent = parent.send(:registry) unless root?
963
+ end
964
+ end
965
+
966
+ end # ArtifactNamespace
967
+
968
+ # :call-seq:
969
+ # project.artifact_ns -> ArtifactNamespace
970
+ # Buildr.artifact_ns(name) -> ArtifactNamespace
971
+ # Buildr.artifact_ns -> ArtifactNamespace for the currently running Project
972
+ #
973
+ # Open an ArtifactNamespace.
974
+ # If a block is provided, the namespace is yielded to it.
975
+ #
976
+ # See also ArtifactNamespace.instance
977
+ def artifact_ns(name = nil, &block)
978
+ name = self if name.nil? && self.kind_of?(Project)
979
+ ArtifactNamespace.instance(name, &block)
980
+ end
981
+
982
+ end
983
+
984
+