Class: Buildr::ArtifactNamespace
- Includes:
- DClone, Enumerable
- Defined in:
- lib/buildr/packaging/artifact_namespace.rb
Overview
An ArtifactNamespace is a hierarchical dictionary used to manage ArtifactRequirements. It can be used to have different artifact versions per project or to allow users to select a version for addons or modules.
Namespaces are opened using the Buildr.artifact_ns method, most important methods are:
- need
-
Used to create a requirement on the namespace.
- use
-
Set the artifact version to use for a requirement.
- values_at
-
Reference requirements by name.
- each
-
Return each ArtifactRequirement in the namespace.
The method_missing method for instances provides some syntactic sugar to these. See the following examples, and the methods for ArtifactRequirement.
Avoiding constant pollution on buildfile
Each project has its own ArtifactNamespace inheriting the one from the parent project up to the root namespace.
Consider the following snippet, as project grows, each subproject may need different artifact combinations and/or versions. Assigning artifact specifications to constants can make it painful to maintain their references even if using structs/hashes.
-- buildfile --
SPRING = 'org.springframework:spring:jar:2.5'
SPRING_OLD = 'org.springframework:spring:jar:1.0'
LOGGING = ['comons-logging:commons-logging:jar:1.1.1',
'log4j:log4j:jar:1.2.15']
WL_LOGGING = artifact('bea:wlcommons-logging:jar:8.1').from('path/to/wlcommons-logging.jar')
LOGGING_WEBLOGIC = ['comons-logging:commons-logging:jar:1.1.1',
WL_LOGGING]
COMMONS = struct :collections => 'commons-collection:commons-collection:jar:3.1',
:net => 'commons-net:commons-net:jar:1.4.0'
define 'example1' do
define 'one' do
compile.with SPRING, LOGGING_WEBLOGIC, COMMONS
end
define 'two' do
compile.with SPRING_OLD, LOGGING, COMMONS
end
define 'three' do
compile.with "commons-collections:commons-collections:jar:2.2"
end
end
With ArtifactNamespace you can do some more advanced stuff, the following annotated snipped could still be reduced if default artifact definitions were loaded from yaml file (see section below and ArtifactNamespace.load).
-- buildfile --
artifact_ns do |ns| # the current namespace (root if called outside a project)
# default artifacts
ns.spring = 'org.springframework:spring:jar:2.5'
# default logger is log4j
ns.logger = 'log4j:log4j:jar:1.2.15'
# create a sub namespace by calling the #ns method,
# artifacts defined on the sub-namespace can be referenced by
# name :commons_net or by calling commons.net
ns.ns :commons, :net => 'commons-net:commons-net:jar:1.4.0',
:logging => 'comons-logging:commons-logging:jar:1.1.1'
# When a child namespace asks for the :log artifact,
# these artifacts will be searched starting from the :current namespace.
ns.virtual :log, :logger, :commons_logging
end
artifact_ns('example2:one') do |ns| # namespace for the one subproject
ns.logger = artifact('bea:wlcommons-logging:jar:8.1').from('path/to/wlcommons-logging.jar')
end
artifact_ns('example2:two') do |ns|
ns.spring = '1.0' # for project two use an older spring version (just for an example)
end
artifact_ns('example2:three').commons_collections = 2.2'
artifact_ns('example2:four') do |ns|
ns.beanutils = 'commons-beanutils:commons-beanutils:jar:1.5' # just for this project
ns.ns(:compilation).use :commons_logging, :beanutils, :spring # compile time dependencies
ns.ns(:testing).use :log, :beanutils, 'cglib:cglib-nodep:jar:2.1.3' # run time dependencies
end
define 'example2' do
define 'one' do
compile.with :spring, :log, :commons # uses weblogic logging
end
define 'two' do
compile.with :spring, :log, :commons # will take old spring
end
define 'three' do
compile.with :commons_collections
test.with artifact_ns('example2:two').spring # use spring from project two
end
define 'four' do
compile.with artifact_ns.compilation
test.with artifact_ns.testing
end
task(:down_them_all) do # again, just to fill this space with something ;)
parent.projects.map(&method(:artifact_ns)).map(&:artifacts).map(&:invoke)
end
end
Loading from a yaml file (e. profiles.yaml)
If your projects use lots of jars (after all we are using java ;) you may prefer to have constant artifact definitions on an external file. Doing so would allow an external tool (or future Buildr feature) to maintain an artifacts.yaml for you. An example usage is documented on the ArtifactNamespace.load method.
For addon/plugin writers & Customizing artifact versions
Sometimes users would need to change the default artifact versions used by some module, for example, the XMLBeans compiler needs this, because of compatibility issues. Another example would be to select the groovy version to use on all our projects so that Buildr modules requiring groovy jars can use user prefered versions.
To meet this goal, an ArtifactNamespace allows to specify ArtifactRequirement objects. In fact the only difference with the examples you have already seen is that requirements have an associated VersionRequirement, so that each time a user tries to select a version, buildr checks if it satisfies the requirements.
Requirements are declared using the ArtifactNamespace#need method, but again, syntactic sugar is provided by ArtifactNamespace#method_missing.
The following example is taken from the XMLBeans compiler module. And illustrates how addon authors should specify their requirements, provide default versions, and document the namespace for users to customize.
module Buildr::XMLBeans
# You need to document this constant, giving users some hints
# about when are (maybe some of) these artifacts used. I mean,
# some modules, add jars to the Buildr classpath when its file
# is required, you would need to tell your users, so that they
# can open the namespace and specify their defaults. Of course
# when the requirements are defined, buildr checks if any compatible
# version has been already defined, if so, uses it.
#
# Some things here have been changed to illustrate their meaning.
REQUIRES = ArtifactNamespace.for(self).tap do |ns|
# This jar requires a >2.0 version, default being 2.3.0
ns.xmlbeans! 'org.apache.xmlbeans:xmlbeans:jar:2.3.0', '>2'
# Users can customize with Buildr::XMLBeans::REQUIRES.stax_api = '1.2'
# This is a non-flexible requirement, only satisfied by version 1.0.1
ns.stax_api! 'stax:stax-api:jar:1.0.1'
# This one is not part of XMLBeans, but is just another example
# illustrating an `artifact requirement spec`.
ns.need " some_name -> ar:ti:fact:3.2.5 -> ( >2 & <4)"
# As you can see it's just an artifact spec, prefixed with
# ' some_name -> ', this means users can use that name to
# reference the requirement, also this string has a VersionRequirement
# just after another ->.
end
# The REQUIRES constant is an ArtifactNamespace instance,
# that means we can use it directly. Note that calling
# Buildr.artifact_ns would lead to the currently executing context,
# not the one for this module.
def use
# test if user specified his own version, if so, we could perform some
# functionallity based on this.
REQUIRES.some_name.selected? # => false
REQUIRES.some_name.satisfied_by?('1.5') # => false
puts REQUIRES.some_name.requirement # => ( >2 & <4 )
REQUIRES.artifacts # get the Artifact tasks
end
end
A more advanced example using ArtifactRequirement listeners is included in the artifact_namespace_spec.rb description for ‘Extension using ArtifactNamespace’ That’s it for addon writers, now, users can select their prefered version with something like:
require 'buildr/xmlbeans'
Buildr::XMLBeans::REQUIRES.xmlbeans = '2.2.0'
More advanced stuff, if users really need to select an xmlbeans version per project, they can do so letting :current (that is, the currently running namespace) be parent of the REQUIRES namespace:
Buildr::XMLBeans::REQUIRES.parent = :current
Now, provided that the compiler does not caches its artifacts, it will select the correct version. (See the first section for how to select per project artifacts).
Defined Under Namespace
Modules: DClone Classes: ArtifactRequirement, Registry
Instance Attribute Summary collapse
-
#name ⇒ Object
readonly
Returns the value of attribute name.
Class Method Summary collapse
-
.clear ⇒ Object
Forget all namespaces, create a new ROOT.
-
.instance(name = nil) {|instance| ... } ⇒ Object
(also: [], for)
:call-seq: ArtifactNamespace.instance { |current_ns| … } -> current_ns ArtifactNamespace.instance(name) { |ns| … } -> ns ArtifactNamespace.instance(:current) { |current_ns| … } -> current_ns ArtifactNamespace.instance(:root) { |root_ns| … } -> root_ns.
-
.load(namespaces = {}) ⇒ Object
Populate namespaces from a hash of hashes.
-
.root {|ROOT| ... } ⇒ Object
:call-seq: ArtifactNamespace.root { |ns| … } -> ns.
-
.to_hash(spec) ⇒ Object
Differs from Artifact.to_hash in that 1) it does not choke when version isn’t present and 2) it assumes that if an artifact spec ends with a colon, e.g.
Instance Method Summary collapse
-
#[](*names) ⇒ Object
:call-seq: artifact_ns -> ArtifactRequirement artifact_ns[:many, :names] -> [ArtifactRequirement].
-
#[]=(*names) ⇒ Object
:call-seq: artifact_ns = ‘some:cool:jar:1.0.2’ artifact_ns = ‘1.0.2’.
-
#accessor(*names) ⇒ Object
Return an anonymous module # first create a requirement artifact_ns.cool_aid! ‘cool:aid:jar:>=1.0’.
-
#alias(new_name, old_name) ⇒ Object
Create an alias for a named requirement.
-
#artifacts(*names) ⇒ Object
return Artifact objects for each requirement.
- #clear ⇒ Object
- #delete(name, include_parents = false) ⇒ Object
-
#each(&block) ⇒ Object
yield each ArtifactRequirement.
-
#fetch(name, default = nil, &block) ⇒ Object
Like Hash#fetch.
-
#group(group_name, *members) ⇒ Object
(also: #virtual)
:call-seq: group :who, :me, :you group :them, :me, :you, :namespace => ns.
-
#initialize(name = nil) ⇒ ArtifactNamespace
constructor
:nodoc:.
- #key?(name, include_parents = false) ⇒ Boolean
- #keys ⇒ Object
-
#method_missing(name, *args, &block) ⇒ Object
:call-seq: artifact_ns.cool_aid!(‘cool:aid:jar:2.3.4’, ‘~>2.3’) -> artifact_requirement artifact_ns.cool_aid = ‘2.3.5’ artifact_ns.cool_aid -> artifact_requirement artifact_ns.cool_aid? -> true | false.
-
#need(*specs) ⇒ Object
:call-seq: artifact_ns.need ‘name -> org:foo:bar:jar:~>1.2.3 -> 1.2.5’ artifact_ns.need :name => ‘org.foo:bar:jar:1.0’.
-
#ns(name, *uses) {|sub| ... } ⇒ Object
Create a named sub-namespace, sub-namespaces are themselves ArtifactNamespace instances but cannot be referenced by the Buildr.artifact_ns, ArtifactNamespace.instance methods.
-
#ns?(name) ⇒ Boolean
Test if a sub-namespace by the given name exists.
-
#parent ⇒ Object
ROOT namespace has no parent.
-
#parent=(other) ⇒ Object
Set the parent for the current namespace, except if it is ROOT.
- #root {|ROOT| ... } ⇒ Object
-
#root? ⇒ Boolean
Is this the ROOT namespace?.
-
#to_s ⇒ Object
:nodoc:.
-
#use(*specs) ⇒ Object
:call-seq: artifact_ns.use ‘name -> org:foo:bar:jar:1.2.3’ artifact_ns.use :name => ‘org:foo:bar:jar:1.2.3’ artifact_ns.use :name => ‘2.5.6’.
-
#values(include_parents = false, include_groups = true) ⇒ Object
Return all requirements for this namespace.
-
#values_at(*names) ⇒ Object
Return only the named requirements.
Methods included from DClone
Constructor Details
#initialize(name = nil) ⇒ ArtifactNamespace
:nodoc:
556 557 558 |
# File 'lib/buildr/packaging/artifact_namespace.rb', line 556 def initialize(name = nil) #:nodoc: @name = name.to_s if name end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(name, *args, &block) ⇒ Object
:call-seq:
artifact_ns.cool_aid!('cool:aid:jar:2.3.4', '~>2.3') -> artifact_requirement
artifact_ns.cool_aid = '2.3.5'
artifact_ns.cool_aid -> artifact_requirement
artifact_ns.cool_aid? -> true | false
First form creates an ArtifactRequirement on the namespace. It is equivalent to providing a requirement_spec to the #need method:
artifact_ns.need "cool_aid -> cool:aid:jar:2.3.4 -> ~>2.3"
the second argument is optional.
Second form can be used to select an artifact version and is equivalent to:
artifact_ns.use :cool_aid => '1.0'
Third form obtains the named ArtifactRequirement, can be used to test if a named requirement has been defined. It is equivalent to:
artifact_ns.fetch(:cool_aid) { nil }
Last form tests if the ArtifactRequirement has been defined and a version has been selected for use. It is equivalent to:
artifact_ns.has_cool_aid?
artifact_ns.values_at(:cool_aid).flatten.all? { |a| a && a.selected? }
921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 |
# File 'lib/buildr/packaging/artifact_namespace.rb', line 921 def method_missing(name, *args, &block) case name.to_s when /!$/ then name = $`.intern if args.size < 1 || args.size > 2 raise ArgumentError.new("wrong number of arguments for #{name}!(spec, version_requirement?)") end need name => args.first get(name).tap { |r| r.requirement = args.last if args.size == 2 } when /=$/ then use $` => args.first when /\?$/ then name = $`.gsub(/^(has|have)_/, '').intern [get(name)].flatten.all? { |a| a && a.selected? } else if block || args.size > 0 raise ArgumentError.new("wrong number of arguments #{args.size} for 0 or block given") end get(name) end end |
Instance Attribute Details
#name ⇒ Object (readonly)
Returns the value of attribute name.
554 555 556 |
# File 'lib/buildr/packaging/artifact_namespace.rb', line 554 def name @name end |
Class Method Details
.clear ⇒ Object
Forget all namespaces, create a new ROOT
217 218 219 220 221 |
# File 'lib/buildr/packaging/artifact_namespace.rb', line 217 def clear @instances = nil remove_const(:ROOT) rescue nil const_set(:ROOT, new('root')) end |
.instance(name = nil) {|instance| ... } ⇒ Object Also known as: [], for
:call-seq:
ArtifactNamespace.instance { |current_ns| ... } -> current_ns
ArtifactNamespace.instance(name) { |ns| ... } -> ns
ArtifactNamespace.instance(:current) { |current_ns| ... } -> current_ns
ArtifactNamespace.instance(:root) { |root_ns| ... } -> root_ns
Obtain an instance for the given name
283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 |
# File 'lib/buildr/packaging/artifact_namespace.rb', line 283 def instance(name = nil) case name when :root, 'root' then return ROOT when ArtifactNamespace then return name when Array then name = name.join(':') when Module, Project then name = name.name when :current, 'current', nil then task = Thread.current[:rake_chain] task = task.instance_variable_get(:@value) if task name = case task when Project then task.name when Rake::Task then task.scope.join(':') when nil then Buildr.application.current_scope.join(':') end end name = name.to_s if name.size == 0 instance = ROOT else name = name.to_s @instances ||= Hash.new { |h, k| h[k] = new(k) } instance = @instances[name] end yield(instance) if block_given? instance end |
.load(namespaces = {}) ⇒ Object
Populate namespaces from a hash of hashes. The following example uses the profiles yaml to achieve this.
-- profiles.yaml --
development:
artifacts:
root: # root namespace
spring: org.springframework:spring:jar:2.5
groovy: org.codehaus.groovy:groovy:jar:1.5.4
logging: # define a named group
- log4j:log4j:jar:1.2.15
- commons-logging:commons-logging:jar:1.1.1
# open Buildr::XMLBeans namespace
Buildr::XMLBeans:
xmlbeans: 2.2
# for subproject one:oldie
one:oldie:
spring: org.springframework:spring:jar:1.0
-- buildfile --
ArtifactNamespace.load(Buildr.settings.profile['artifacts'])
272 273 274 |
# File 'lib/buildr/packaging/artifact_namespace.rb', line 272 def load(namespaces = {}) namespaces.each_pair { |name, uses| instance(name).use(uses) } end |
.root {|ROOT| ... } ⇒ Object
:call-seq:
ArtifactNamespace.root { |ns| ... } -> ns
Obtain the root namespace, returns the ROOT constant
317 318 319 320 |
# File 'lib/buildr/packaging/artifact_namespace.rb', line 317 def root yield ROOT if block_given? ROOT end |
.to_hash(spec) ⇒ Object
Differs from Artifact.to_hash in that 1) it does not choke when version isn’t present and 2) it assumes that if an artifact spec ends with a colon, e.g. “org.example:library:jdk5:” it indicates the last segment (“jdk5”) is a classifier.
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 |
# File 'lib/buildr/packaging/artifact_namespace.rb', line 226 def to_hash(spec) if spec.respond_to?(:to_spec) to_hash spec.to_spec elsif Hash === spec return spec elsif String === spec || Symbol === spec spec = spec.to_s if spec[-1,1] == ':' group, id, type, classifier, *rest = spec.split(':').map { |part| part.empty? ? nil : part } else group, id, type, version, *rest = spec.split(':').map { |part| part.empty? ? nil : part } unless rest.empty? # Optional classifier comes before version. classifier, version = version, rest.shift end end fail "Expecting <group:id:type:version> or <group:id:type:classifier:version>, found <#{spec}>" unless rest.empty? { :group => group, :id => id, :type => type, :version => version, :classifier => classifier }.reject { |k,v| v == nil } else fail "Unexpected artifact spec: #{spec.inspect}" end end |
Instance Method Details
#[](*names) ⇒ Object
:call-seq:
artifact_ns[:name] -> ArtifactRequirement
artifact_ns[:many, :names] -> [ArtifactRequirement]
778 779 780 781 |
# File 'lib/buildr/packaging/artifact_namespace.rb', line 778 def [](*names) ary = values_at(*names) names.size == 1 ? ary.first : ary end |
#[]=(*names) ⇒ Object
:call-seq:
artifact_ns[:name] = 'some:cool:jar:1.0.2'
artifact_ns[:name] = '1.0.2'
Just like the use method
788 789 790 791 792 793 794 |
# File 'lib/buildr/packaging/artifact_namespace.rb', line 788 def []=(*names) values = names.pop values = [values] unless Array === values names.each_with_index do |name, i| use name => (values[i] || values.last) end end |
#accessor(*names) ⇒ Object
Return an anonymous module
# first create a requirement
artifact_ns.cool_aid! 'cool:aid:jar:>=1.0'
# extend an object as a cool_aid delegator
jars = Object.new.extend(artifact_ns.accessor(:cool_aid))
jars.cool_aid = '2.0'
artifact_ns.cool_aid.version # -> '2.0'
951 952 953 954 955 956 957 958 959 960 |
# File 'lib/buildr/packaging/artifact_namespace.rb', line 951 def accessor(*names) ns = self Module.new do names.each do |name| define_method("#{name}") { ns.send("#{name}") } define_method("#{name}?") { ns.send("#{name}?") } define_method("#{name}=") { |vers| ns.send("#{name}=", vers) } end end end |
#alias(new_name, old_name) ⇒ Object
Create an alias for a named requirement.
885 886 887 888 |
# File 'lib/buildr/packaging/artifact_namespace.rb', line 885 def alias(new_name, old_name) registry.alias(new_name, old_name) or raise NameError.new("Undefined artifact name: #{old_name}") end |
#artifacts(*names) ⇒ Object
return Artifact objects for each requirement
802 803 804 |
# File 'lib/buildr/packaging/artifact_namespace.rb', line 802 def artifacts(*names) (names.empty? && values || values_at(*names)).map(&:artifact) end |
#clear ⇒ Object
859 860 861 |
# File 'lib/buildr/packaging/artifact_namespace.rb', line 859 def clear keys.each { |k| delete(k) } end |
#delete(name, include_parents = false) ⇒ Object
854 855 856 857 |
# File 'lib/buildr/packaging/artifact_namespace.rb', line 854 def delete(name, include_parents = false) registry.delete(name, include_parents) self end |
#each(&block) ⇒ Object
yield each ArtifactRequirement
797 798 799 |
# File 'lib/buildr/packaging/artifact_namespace.rb', line 797 def each(&block) values.each(&block) end |
#fetch(name, default = nil, &block) ⇒ Object
Like Hash#fetch
769 770 771 772 773 |
# File 'lib/buildr/packaging/artifact_namespace.rb', line 769 def fetch(name, default = nil, &block) block ||= proc { raise IndexError.new("No artifact found by name #{name.inspect} in namespace #{self}") } real_name = name.to_s[/^[\w\-\.]+$/] ? name : ArtifactRequirement.unversioned_spec(name) get(real_name.to_sym) || default || block.call(name) end |
#group(group_name, *members) ⇒ Object Also known as: virtual
:call-seq:
group :who, :me, :you
group :them, :me, :you, :namespace => ns
Create a virtual group on this namespace. When the namespace is asked for the who
artifact, it’s value is an array made from the remaining names. These names are searched by default from the current namespace. Second form specified the starting namespace to search from.
872 873 874 875 876 877 878 879 880 |
# File 'lib/buildr/packaging/artifact_namespace.rb', line 872 def group(group_name, *members) namespace = (Hash === members.last && members.pop[:namespace]) || :current registry[group_name] = lambda do artifacts = self.class[namespace].values_at(*members) artifacts = artifacts.first if members.size == 1 artifacts end self end |
#key?(name, include_parents = false) ⇒ Boolean
845 846 847 848 |
# File 'lib/buildr/packaging/artifact_namespace.rb', line 845 def key?(name, include_parents = false) name = ArtifactRequirement.unversioned_spec(name) unless name.to_s[/^[\w\-\.]+$/] registry.key?(name, include_parents) end |
#keys ⇒ Object
850 851 852 |
# File 'lib/buildr/packaging/artifact_namespace.rb', line 850 def keys values.map(&:name) end |
#need(*specs) ⇒ Object
:call-seq:
artifact_ns.need 'name -> org:foo:bar:jar:~>1.2.3 -> 1.2.5'
artifact_ns.need :name => 'org.foo:bar:jar:1.0'
Create a new ArtifactRequirement on this namespace. ArtifactNamespace#method_missing provides syntactic sugar for this.
631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 |
# File 'lib/buildr/packaging/artifact_namespace.rb', line 631 def need(*specs) named = specs.flatten.inject({}) do |seen, spec| if Hash === spec && (spec.keys & ActsAsArtifact::ARTIFACT_ATTRIBUTES).empty? spec.each_pair do |name, spec| if Array === spec # a group seen[name] ||= spec.map { |s| ArtifactRequirement.new(s) } else artifact = ArtifactRequirement.new(spec) artifact.name = name seen[artifact.name] ||= artifact end end else artifact = ArtifactRequirement.new(spec) seen[artifact.name] ||= artifact end seen end named.each_pair do |name, artifact| if Array === artifact # a group artifact.each do |a| unvers = a.unversioned_spec previous = registry[unvers] if previous && previous.selected? && a.satisfied_by?(previous) a.version = previous.version end registry[unvers] = a end group(name, *(artifact.map { |a| a.unversioned_spec } + [{:namespace => self}])) else unvers = artifact.unversioned_spec previous = registry.get(unvers, true) if previous && previous.selected? && artifact.satisfied_by?(previous) artifact.version = previous.version artifact.selected! end registry[unvers] = artifact registry.alias name, unvers unless name.to_s[/^\s*$/] end end self end |
#ns(name, *uses) {|sub| ... } ⇒ Object
Create a named sub-namespace, sub-namespaces are themselves ArtifactNamespace instances but cannot be referenced by the Buildr.artifact_ns, ArtifactNamespace.instance methods. Reference needs to be through this object using the given name
artifact_ns('foo').ns(:bar).need :thing => 'some:thing:jar:1.0'
artifact_ns('foo'). # => the sub-namespace 'foo.bar'
artifact_ns('foo')..thing # => the some thing artifact
See the top level ArtifactNamespace documentation for examples
604 605 606 607 608 609 610 611 612 613 614 615 616 617 |
# File 'lib/buildr/packaging/artifact_namespace.rb', line 604 def ns(name, *uses, &block) name = name.to_sym sub = registry[name] if sub raise TypeError.new("#{name} is not a sub namespace of #{self}") unless sub.kind_of?(ArtifactNamespace) else sub = ArtifactNamespace.new("#{self.name}.#{name}") sub.parent = self registry[name] = sub end sub.use(*uses) yield sub if block_given? sub end |
#ns?(name) ⇒ Boolean
Test if a sub-namespace by the given name exists
620 621 622 623 |
# File 'lib/buildr/packaging/artifact_namespace.rb', line 620 def ns?(name) sub = registry[name.to_sym] ArtifactNamespace === sub end |
#parent ⇒ Object
ROOT namespace has no parent
567 568 569 570 571 572 573 574 575 576 577 578 579 580 |
# File 'lib/buildr/packaging/artifact_namespace.rb', line 567 def parent if root? nil elsif @parent.kind_of?(ArtifactNamespace) @parent elsif @parent ArtifactNamespace.instance(@parent) elsif name parent_name = name.gsub(/::?[^:]+$/, '') parent_name == name ? root : ArtifactNamespace.instance(parent_name) else root end end |
#parent=(other) ⇒ Object
Set the parent for the current namespace, except if it is ROOT
583 584 585 586 587 |
# File 'lib/buildr/packaging/artifact_namespace.rb', line 583 def parent=(other) raise 'Cannot set parent of root namespace' if root? @parent = other @registry = nil end |
#root {|ROOT| ... } ⇒ Object
561 562 563 564 |
# File 'lib/buildr/packaging/artifact_namespace.rb', line 561 def root yield ROOT if block_given? ROOT end |
#root? ⇒ Boolean
Is this the ROOT namespace?
590 591 592 |
# File 'lib/buildr/packaging/artifact_namespace.rb', line 590 def root? ROOT == self end |
#to_s ⇒ Object
:nodoc:
890 891 892 |
# File 'lib/buildr/packaging/artifact_namespace.rb', line 890 def to_s #:nodoc: name.to_s end |
#use(*specs) ⇒ Object
:call-seq:
artifact_ns.use 'name -> org:foo:bar:jar:1.2.3'
artifact_ns.use :name => 'org:foo:bar:jar:1.2.3'
artifact_ns.use :name => '2.5.6'
First and second form are equivalent, the third is used when an ArtifactRequirement has been previously defined with :name, so it just selects the version.
ArtifactNamespace#method_missing provides syntactic sugar for this.
684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 |
# File 'lib/buildr/packaging/artifact_namespace.rb', line 684 def use(*specs) named = specs.flatten.inject({}) do |seen, spec| if Hash === spec && (spec.keys & ActsAsArtifact::ARTIFACT_ATTRIBUTES).empty? spec.each_pair do |name, spec| if ArtifactNamespace === spec # create as subnamespace raise ArgumentError.new("Circular reference") if self == spec registry[name.to_sym] = spec elsif Numeric === spec || (String === spec && VersionRequirement.version?(spec)) artifact = ArtifactRequirement.allocate artifact.name = name artifact.version = spec.to_s seen[artifact.name] ||= artifact elsif Symbol === spec self.alias name, spec elsif Array === spec # a group seen[name] ||= spec.map { |s| ArtifactRequirement.new(s) } else artifact = ArtifactRequirement.new(spec) artifact.name = name seen[artifact.name] ||= artifact end end else if Symbol === spec artifact = get(spec).dclone else artifact = ArtifactRequirement.new(spec) end seen[artifact.name] ||= artifact end seen end named.each_pair do |name, artifact| is_group = Array === artifact artifact = [artifact].flatten.map do |artifact| unvers = artifact.unversioned_spec previous = get(unvers, false) || get(name, false) if previous # have previous on current namespace if previous.requirement # we must satisfy the requirement unless unvers # we only have the version satisfied = previous.requirement.satisfied_by?(artifact.version) else satisfied = previous.satisfied_by?(artifact) end raise "Unsatisfied dependency #{previous} " + "not satisfied by #{artifact}" unless satisfied previous.version = artifact.version # OK, set new version artifact = previous # use the same object for aliases else # not a requirement, set the new values unless artifact.id == previous.id && name != previous.name previous.copy_attrs(artifact) artifact = previous end end else if unvers.nil? && # we only have the version (previous = get(unvers, true, false, false)) version = artifact.version artifact.copy_attrs(previous) artifact.version = version end artifact.requirement = nil end artifact.selected! end artifact = artifact.first unless is_group if is_group names = artifact.map do |art| unv = art.unversioned_spec registry[unv] = art unv end group(name, *(names + [{:namespace => self}])) elsif artifact.id unvers = artifact.unversioned_spec registry[name] = artifact registry.alias unvers, name else registry[name] = artifact end end self end |
#values(include_parents = false, include_groups = true) ⇒ Object
Return all requirements for this namespace
807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 |
# File 'lib/buildr/packaging/artifact_namespace.rb', line 807 def values(include_parents = false, include_groups = true) seen, dict = {}, registry while dict dict.each do |k, v| v = v.call if v.respond_to?(:call) v = v.values if v.kind_of?(ArtifactNamespace) if Array === v && include_groups v.compact.each { |v| seen[v.name] = v unless seen.key?(v.name) } else seen[v.name] = v unless seen.key?(v.name) end end dict = include_parents ? dict.parent : nil end seen.values end |
#values_at(*names) ⇒ Object
Return only the named requirements
825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 |
# File 'lib/buildr/packaging/artifact_namespace.rb', line 825 def values_at(*names) names.map do |name| catch :artifact do unless name.to_s[/^[\w\-\.]+$/] unvers = ArtifactRequirement.unversioned_spec(name) unless unvers.to_s == name.to_s req = ArtifactRequirement.new(name) reg = self while reg candidate = reg.send(:get, unvers, false, false, true) throw :artifact, candidate if req.satisfied_by?(candidate) reg = reg.parent end end end get(name.to_sym) end end end |