You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@buildr.apache.org by bo...@apache.org on 2010/01/24 23:41:43 UTC

svn commit: r902670 - in /buildr/trunk: CHANGELOG lib/buildr/packaging/artifact_namespace.rb spec/packaging/artifact_namespace_spec.rb

Author: boisvert
Date: Sun Jan 24 22:41:43 2010
New Revision: 902670

URL: http://svn.apache.org/viewvc?rev=902670&view=rev
Log:
Add ArtifactNamespace.{keys,clear} methods

Modified:
    buildr/trunk/CHANGELOG
    buildr/trunk/lib/buildr/packaging/artifact_namespace.rb
    buildr/trunk/spec/packaging/artifact_namespace_spec.rb

Modified: buildr/trunk/CHANGELOG
URL: http://svn.apache.org/viewvc/buildr/trunk/CHANGELOG?rev=902670&r1=902669&r2=902670&view=diff
==============================================================================
--- buildr/trunk/CHANGELOG (original)
+++ buildr/trunk/CHANGELOG Sun Jan 24 22:41:43 2010
@@ -14,6 +14,7 @@
           "true" to ignore changes in Buildfile when running tests.
 * Added:  "buildr test=only" will only run tests explicitly specified on the
           command line (and ignore transitive test dependencies)
+* Added:  ArtifactNamespace.{keys,clear} methods
 * Change: Updated to JRuby 1.4.0
 * Change: Updated to JtestR 0.5
 * Change: Updated to JUnit 4.7

Modified: buildr/trunk/lib/buildr/packaging/artifact_namespace.rb
URL: http://svn.apache.org/viewvc/buildr/trunk/lib/buildr/packaging/artifact_namespace.rb?rev=902670&r1=902669&r2=902670&view=diff
==============================================================================
--- buildr/trunk/lib/buildr/packaging/artifact_namespace.rb (original)
+++ buildr/trunk/lib/buildr/packaging/artifact_namespace.rb Sun Jan 24 22:41:43 2010
@@ -18,7 +18,7 @@
 
 
 module Buildr
-  
+
   # 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.
@@ -33,25 +33,25 @@
   #
   # = Avoiding constant polution on buildfile
   #
-  # Each project has its own ArtifactNamespace inheriting the one from the 
+  # 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 diferent artifact combinations and/or versions. Asigning 
+  #
+  # Consider the following snippet, as project grows, each subproject
+  # may need diferent artifact combinations and/or versions. Asigning
   # 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', 
+  #   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', 
+  #   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
@@ -64,11 +64,11 @@
   #     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 bellow and ArtifactNamespace.load).
-  # 
+  #
   #   -- buildfile --
   #   artifact_ns do |ns| # the current namespace (root if called outside a project)
   #     # default artifacts
@@ -83,15 +83,15 @@
   #                     :logging => 'comons-logging:commons-logging:jar:1.1.1'
   #
   #
-  #     # When a child namespace asks for the :log artifact, 
+  #     # 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| 
+  #   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'
@@ -100,8 +100,8 @@
   #     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 'example2' do
   #     define 'one' do
   #       compile.with :spring, :log, :commons # uses weblogic logging
   #     end
@@ -130,7 +130,7 @@
   # 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
@@ -145,14 +145,14 @@
   # 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, 
+  # 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 
+  #       # 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
@@ -174,29 +174,29 @@
   #         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 
+  #         # ' 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 
+  #       # 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.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 
+  #    end
   #
-  # A more advanced example using ArtifactRequirement listeners is included 
+  # 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:
@@ -210,8 +210,8 @@
   #
   #    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 
+  # 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).
   #
   #
@@ -224,7 +224,7 @@
         const_set(:ROOT, new('root'))
       end
 
-      # Populate namespaces from a hash of hashes. 
+      # Populate namespaces from a hash of hashes.
       # The following example uses the profiles yaml to achieve this.
       #
       #   -- profiles.yaml --
@@ -236,7 +236,7 @@
       #         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
@@ -250,7 +250,7 @@
       def load(namespaces = {})
         namespaces.each_pair { |name, uses| instance(name).use(uses) }
       end
-      
+
       # :call-seq:
       #   ArtifactNamespace.instance { |current_ns| ... } -> current_ns
       #   ArtifactNamespace.instance(name) { |ns| ... } -> ns
@@ -284,7 +284,7 @@
 
       alias_method :[], :instance
       alias_method :for, :instance
-      
+
       # :call-seq:
       #   ArtifactNamespace.root { |ns| ... } -> ns
       #
@@ -296,9 +296,9 @@
     end
 
     module DClone #:nodoc:
-      def dclone 
+      def dclone
         clone = self.clone
-        clone.instance_variables.each do |i| 
+        clone.instance_variables.each do |i|
           value = clone.instance_variable_get(i)
           value = value.dclone rescue
           clone.instance_variable_set(i, value)
@@ -325,7 +325,7 @@
         end
         obj
       end
-      
+
       def aliases(name)
         return [] unless name
         name = name.to_sym
@@ -338,7 +338,7 @@
       end
 
       def get(key, include_parent = nil)
-        [].tap { |a| aliases(key).select { |n| a[0] = self[n] } }.first || 
+        [].tap { |a| aliases(key).select { |n| a[0] = self[n] } }.first ||
           (include_parent && parent && parent.get(key, include_parent))
       end
 
@@ -361,17 +361,17 @@
     end
 
     # An artifact requirement is an object that ActsAsArtifact and has
-    # an associated VersionRequirement. It also knows the name (some times equal to the 
+    # an associated VersionRequirement. It also knows the name (some times equal to the
     # artifact id) that is used to store it in an ArtifactNamespace.
     class ArtifactRequirement
       attr_accessor :version
       attr_reader :name, :requirement
 
       include DClone
-  
+
       # Create a requirement from an `artifact requirement spec`.
-      # This spec has three parts, separated by  -> 
-      # 
+      # This spec has three parts, separated by  ->
+      #
       #     some_name ->  ar:ti:fact:3.2.5 ->  ( >2 & <4)
       #
       # As you can see it's just an artifact spec, prefixed with
@@ -387,7 +387,7 @@
       #
       # The last part consist of a VersionRequirement.
       #                                     ->  ( >2 & <4)
-      #                        
+      #
       # VersionRequirement supports RubyGem's comparision operators
       # in adition to parens, logical and, logical or and negation.
       # See the docs for VersionRequirement for more info on operators.
@@ -416,7 +416,7 @@
       def name=(name)
         @name = name.to_s
       end
-      
+
       # Set a the requirement, this must be an string formatted for
       # VersionRequirement#create to parse.
       def requirement=(version_requirement)
@@ -426,7 +426,7 @@
       # Return a hash consisting of :name, :spec, :requirement
       def requirement_hash(spec = self)
         result = {}
-        if String === spec 
+        if String === spec
           parts = spec.split(/\s*->\s*/, 3).map(&:strip)
           case parts.size
           when 1
@@ -451,7 +451,7 @@
         result[:requirement] ||= VersionRequirement.create(result[:spec][:version])
         result
       end
-      
+
       # Test if this requirement is satisfied by an artifact spec.
       def satisfied_by?(spec)
         return false unless requirement
@@ -502,7 +502,7 @@
         ary = ary[0...-1] if ary.size > 3
         ary.join(':')
       end
-    
+
       class << self
         # Return an artifact spec without the version part.
         def unversioned_spec(spec)
@@ -522,16 +522,16 @@
     include DClone
     include Enumerable
     attr_reader :name
-    
+
     def initialize(name = nil) #:nodoc:
       @name = name.to_s if name
     end
     clear
-    
+
     def root
       ROOT
     end
-    
+
     # ROOT namespace has no parent
     def parent
       if root?
@@ -547,22 +547,22 @@
         root
       end
     end
-    
+
     # Set the parent for the current namespace, except if it is ROOT
     def parent=(other)
       raise 'Cannot set parent of root namespace' if root?
       @parent = other
       @registry = nil
     end
-    
+
     # Is this the ROOT namespace?
     def root?
       ROOT == self
     end
 
-    # Create a named sub-namespace, sub-namespaces are themselves 
+    # Create a named sub-namespace, sub-namespaces are themselves
     # ArtifactNamespace instances but cannot be referenced by
-    # the Buildr.artifact_ns, ArtifactNamespace.instance methods. 
+    # 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'
@@ -617,7 +617,7 @@
       end
       named.each_pair do |name, artifact|
         if Array === artifact # a group
-          artifact.each do |a| 
+          artifact.each do |a|
             unvers = a.unversioned_spec
             previous = registry[unvers]
             if previous && previous.selected? && a.satisfied_by?(previous)
@@ -645,7 +645,7 @@
     #   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 
+    # 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.
     #
@@ -686,7 +686,7 @@
         is_group = Array === artifact
         artifact = [artifact].flatten.map do |artifact|
           unvers = artifact.unversioned_spec
-          previous = get(unvers, false) || get(name, false) 
+          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
@@ -697,7 +697,7 @@
               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  
+              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)
@@ -711,13 +711,13 @@
               artifact.copy_attrs(previous)
               artifact.version = version
             end
-            artifact.requirement = nil  
+            artifact.requirement = nil
           end
           artifact.selected!
         end
         artifact = artifact.first unless is_group
         if is_group
-          names = artifact.map do |art| 
+          names = artifact.map do |art|
             unv = art.unversioned_spec
             registry[unv] = art
             unv
@@ -792,7 +792,7 @@
 
     # Return only the named requirements
     def values_at(*names)
-      names.map do |name| 
+      names.map do |name|
         catch :artifact do
           unless name.to_s[/^[\w\-\.]+$/]
             unvers = ArtifactRequirement.unversioned_spec(name)
@@ -816,11 +816,19 @@
       registry.key?(name, include_parents)
     end
 
+    def keys
+      values.map(&:name)
+    end
+
     def delete(name, include_parents = false)
       registry.delete(name, include_parents)
       self
     end
-    
+
+    def clear
+      keys.each { |k| delete(k) }
+    end
+
     # :call-seq:
     #   group :who, :me, :you
     #   group :them, :me, :you, :namespace => ns
@@ -828,7 +836,7 @@
     # 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. 
+    # namespace.
     # Second form specified the starting namespace to search from.
     def group(group_name, *members)
       namespace = (Hash === members.last && members.pop[:namespace]) || :current
@@ -867,7 +875,7 @@
     # and is equivalent to:
     #   artifact_ns.use :cool_aid => '1.0'
     #
-    # Third form obtains the named ArtifactRequirement, can be 
+    # 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 }
@@ -892,7 +900,7 @@
       when /\?$/ then
         name = $`.gsub(/^(has|have)_/, '').intern
         [get(name)].flatten.all? { |a| a && a.selected? }
-      else 
+      else
         if block || args.size > 0
           raise ArgumentError.new("wrong number of arguments #{args.size} for 0 or block given")
         end
@@ -900,7 +908,7 @@
       end
     end
 
-    # Return an anonymous module 
+    # Return an anonymous module
     #   # first create a requirement
     #   artifact_ns.cool_aid! 'cool:aid:jar:>=1.0'
     #
@@ -911,7 +919,7 @@
     #   artifact_ns.cool_aid.version # -> '2.0'
     def accessor(*names)
       ns = self
-      Module.new do 
+      Module.new do
         names.each do |name|
           define_method("#{name}") { ns.send("#{name}") }
           define_method("#{name}?") { ns.send("#{name}?") }
@@ -950,7 +958,7 @@
         m.parent = parent.send(:registry) unless root?
       end
     end
-     
+
   end # ArtifactNamespace
 
   # :call-seq:
@@ -966,7 +974,7 @@
     name = self if name.nil? && self.kind_of?(Project)
     ArtifactNamespace.instance(name, &block)
   end
-  
+
 end
 
 

Modified: buildr/trunk/spec/packaging/artifact_namespace_spec.rb
URL: http://svn.apache.org/viewvc/buildr/trunk/spec/packaging/artifact_namespace_spec.rb?rev=902670&r1=902669&r2=902670&view=diff
==============================================================================
--- buildr/trunk/spec/packaging/artifact_namespace_spec.rb (original)
+++ buildr/trunk/spec/packaging/artifact_namespace_spec.rb Sun Jan 24 22:41:43 2010
@@ -26,46 +26,46 @@
     Object.send :remove_const, :A
   end
 
-  describe '.root' do 
+  describe '.root' do
     it 'should return the top level namespace' do
       Buildr::ArtifactNamespace.root.should be_root
     end
-    
+
     it 'should yield the namespace if a block is given' do
       Buildr::ArtifactNamespace.root { |ns| ns.should be_root }
     end
   end
 
-  describe '.instance' do 
+  describe '.instance' do
     it 'should return the top level namespace when invoked outside a project definition' do
       artifact_ns.should be_root
     end
 
-    it 'should return the namespace for the receiving project' do 
+    it 'should return the namespace for the receiving project' do
       define('foo') { }
       project('foo').artifact_ns.name.should == 'foo'
     end
-    
+
     it 'should return the current project namespace when invoked inside a project' do
       define 'foo' do
         artifact_ns.should_not be_root
         artifact_ns.name.should == 'foo'
-        task :doit do 
+        task :doit do
           artifact_ns.should_not be_root
           artifact_ns.name.should == 'foo'
         end.invoke
       end
     end
-  
+
     it 'should return the root namespace if given :root' do
       artifact_ns(:root).should be_root
     end
-    
-    it 'should return the namespace for the given name' do 
+
+    it 'should return the namespace for the given name' do
       artifact_ns(:foo).name.should == 'foo'
       artifact_ns('foo:bar').name.should == 'foo:bar'
       artifact_ns(['foo', 'bar', 'baz']).name.should == 'foo:bar:baz'
-      abc_module do 
+      abc_module do
         artifact_ns(A::B::C).name.should == 'A::B::C'
       end
       artifact_ns(:root).should be_root
@@ -79,12 +79,12 @@
     end
   end
 
-  describe '#parent' do 
-    it 'should be nil for root namespace' do 
+  describe '#parent' do
+    it 'should be nil for root namespace' do
       artifact_ns(:root).parent.should be_nil
     end
-    
-    it 'should be the parent namespace for nested modules' do 
+
+    it 'should be the parent namespace for nested modules' do
       abc_module do
         artifact_ns(A::B::C).parent.should == artifact_ns(A::B)
         artifact_ns(A::B).parent.should == artifact_ns(A)
@@ -93,8 +93,8 @@
     end
 
     it 'should be the parent namespace for nested projects' do
-      define 'a' do 
-        define 'b' do 
+      define 'a' do
+        define 'b' do
           define 'c' do
             artifact_ns.parent.should == artifact_ns(parent)
           end
@@ -104,9 +104,9 @@
       end
     end
   end
-  
+
   describe '#parent=' do
-    it 'should reject to set parent for root namespace' do 
+    it 'should reject to set parent for root namespace' do
       lambda { artifact_ns(:root).parent = :foo }.should raise_error(Exception, /cannot set parent/i)
     end
 
@@ -118,10 +118,10 @@
     end
 
     it 'should allow to set parent to :current' do
-      abc_module do 
+      abc_module do
         mod = A::B
         artifact_ns(mod).parent = :current
-        def mod.stuff 
+        def mod.stuff
           Buildr::artifact_ns(self)
         end
         define 'a' do
@@ -133,14 +133,14 @@
       end
     end
   end
-  
-  describe '#need' do 
+
+  describe '#need' do
     it 'should accept an artifact spec' do
       define 'one' do
         artifact_ns.need 'a:b:c:1'
         # referenced by spec
         artifact_ns['a:b:c'].should_not be_selected
-        
+
         # referenced by name
         artifact_ns[:b].should_not be_selected
         artifact_ns[:b].should be_satisfied_by('a:b:c:1')
@@ -155,7 +155,7 @@
         artifact_ns.need 'thing -> a:b:c:2.1 -> ~>2.0'
         # referenced by spec
         artifact_ns['a:b:c'].should_not be_selected
-        
+
         # referenced by name
         artifact_ns.key?(:b).should be_false
         artifact_ns[:thing].should_not be_selected
@@ -165,7 +165,7 @@
       end
     end
 
-    it 'should accept a hash :name -> requirement_spec' do 
+    it 'should accept a hash :name -> requirement_spec' do
       define 'one' do
         artifact_ns.need :thing => 'a:b:c:2.1 -> ~>2.0'
         artifact_ns[:thing].should be_satisfied_by('a:b:c:2.5')
@@ -181,8 +181,8 @@
       end
     end
 
-    it 'should take a hash :name -> specs_array' do 
-      define 'one' do 
+    it 'should take a hash :name -> specs_array' do
+      define 'one' do
         artifact_ns.need :things => ['foo:bar:jar:1.0',
                                      'foo:baz:jar:2.0',]
         artifact_ns['foo:bar:jar'].should_not be_selected
@@ -194,8 +194,8 @@
       end
     end
 
-    it 'should select best matching version if defined' do 
-      define 'one' do 
+    it 'should select best matching version if defined' do
+      define 'one' do
         artifact_ns.use :a => 'foo:bar:jar:1.5'
         artifact_ns.use :b => 'foo:baz:jar:2.0'
         define 'two' do
@@ -205,7 +205,7 @@
           artifact_ns.need :c => 'foo:bat:jar:3.0'
           artifact_ns['foo:bat:jar'].should_not be_selected
           artifact_ns[:c].should_not be_selected
-          
+
           artifact_ns.need :one => 'foo:bar:jar:>=1.0'
           artifact_ns[:one].version.should == '1.5'
           artifact_ns[:one].should be_selected
@@ -220,7 +220,7 @@
     end
   end
 
-  describe '#use' do 
+  describe '#use' do
     it 'should register the artifact on namespace' do
       define 'one' do
         artifact_ns.use :thing => 'a:b:c:1'
@@ -232,7 +232,7 @@
           artifact_ns[:thing].requirement.should be_nil
           artifact_ns[:thing].version.should == '2'
           artifact_ns[:thing].id.should == 'd'
-          
+
           artifact_ns.use :copied => artifact_ns.parent[:thing]
           artifact_ns[:copied].should_not == artifact_ns.parent[:thing]
           artifact_ns[:copied].requirement.should be_nil
@@ -258,7 +258,7 @@
         artifact_ns['a:b:c'].version.should == '2'
       end
     end
-    
+
     it 'should complain if namespace requirement is not satisfied' do
       define 'one' do
         artifact_ns.need :bar => 'foo:bar:baz:~>1.5'
@@ -266,7 +266,7 @@
       end
     end
 
-    it 'should be able to register a group' do 
+    it 'should be able to register a group' do
       specs = ['its:me:here:1', 'its:you:there:2']
       artifact_ns.use :them => specs
       artifact_ns[:them].map(&:to_spec).should == specs
@@ -274,7 +274,7 @@
       artifact_ns[:you].should be_nil
     end
 
-    it 'should be able to assign sub namespaces' do 
+    it 'should be able to assign sub namespaces' do
       artifact_ns(:foo).bar = "foo:bar:baz:0"
       artifact_ns(:moo).foo = artifact_ns(:foo)
       artifact_ns(:moo).foo.should == artifact_ns(:foo)
@@ -291,13 +291,13 @@
 
   end
 
-  describe '#values' do 
-    it 'returns the artifacts defined on namespace' do 
+  describe '#values' do
+    it 'returns the artifacts defined on namespace' do
       define 'foo' do
         artifact_ns.use 'foo:one:baz:1.0'
         define 'bar' do
           artifact_ns.use 'foo:two:baz:1.0'
-          
+
           specs = artifact_ns.values.map(&:to_spec)
           specs.should include('foo:two:baz:1.0')
           specs.should_not include('foo:one:baz:1.0')
@@ -309,13 +309,13 @@
     end
   end
 
-  describe '#values_at' do 
-    it 'returns the named artifacts' do 
+  describe '#values_at' do
+    it 'returns the named artifacts' do
       define 'foo' do
         artifact_ns.use 'foo:one:baz:1.0'
         define 'bar' do
           artifact_ns.use :foo_baz => 'foo:two:baz:1.0'
-          
+
           specs = artifact_ns.values_at('one').map(&:to_spec)
           specs.should include('foo:one:baz:1.0')
           specs.should_not include('foo:two:baz:1.0')
@@ -332,7 +332,7 @@
         artifact_ns.use 'foo:one:baz:2.0'
         define 'bar' do
           artifact_ns.use :older => 'foo:one:baz:1.0'
-          
+
           specs = artifact_ns.values_at('foo:one:baz').map(&:to_spec)
           specs.should include('foo:one:baz:1.0')
           specs.should_not include('foo:one:baz:2.0')
@@ -348,7 +348,7 @@
         artifact_ns.use 'foo:one:baz:2.0'
         define 'bar' do
           artifact_ns.use :older => 'foo:one:baz:1.0'
-          
+
           specs = artifact_ns.values_at('foo:one:baz:>1.0').map(&:to_spec)
           specs.should include('foo:one:baz:2.0')
           specs.should_not include('foo:one:baz:1.0')
@@ -356,14 +356,57 @@
       end
     end
   end
-  
-  describe '#method_missing' do 
-    it 'should use cool_aid! to create a requirement' do 
+
+  describe '#artifacts' do
+    it 'returns artifacts in namespace' do
+      define 'one' do
+        artifact_ns[:foo] = 'group:foo:jar:1'
+        artifact_ns[:bar] = 'group:bar:jar:1'
+        artifact_ns.artifacts.map{|a| a.to_spec}.should include('group:foo:jar:1', 'group:bar:jar:1')
+      end
+    end
+  end
+
+  describe '#keys' do
+    it 'returns names in namespace' do
+      define 'one' do
+        artifact_ns[:foo] = 'group:foo:jar:1'
+        artifact_ns[:bar] = 'group:bar:jar:1'
+        artifact_ns.keys.should include('foo', 'bar')
+      end
+    end
+  end
+
+  describe '#delete' do
+    it 'deletes corresponding artifact requirement' do
+      define 'one' do
+        artifact_ns[:foo] = 'group:foo:jar:1'
+        artifact_ns[:bar] = 'group:bar:jar:1'
+        artifact_ns.delete :bar
+        artifact_ns.artifacts.map{|a| a.to_spec}.should include('group:foo:jar:1')
+        artifact_ns[:foo].to_spec.should eql('group:foo:jar:1')
+      end
+    end
+  end
+
+  describe '#clear' do
+    it 'clears all artifact requirements in namespace' do
+      define 'one' do
+        artifact_ns[:foo] = 'group:foo:jar:1'
+        artifact_ns[:bar] = 'group:bar:jar:1'
+        artifact_ns.clear
+        artifact_ns.artifacts.should be_empty
+      end
+    end
+  end
+
+  describe '#method_missing' do
+    it 'should use cool_aid! to create a requirement' do
       define 'foo' do
         artifact_ns.cool_aid!('cool:aid:jar:2').should be_kind_of(ArtifactNamespace::ArtifactRequirement)
         artifact_ns[:cool_aid].version.should == '2'
         artifact_ns[:cool_aid].should_not be_selected
-        define 'bar' do 
+        define 'bar' do
           artifact_ns.cool_aid! 'cool:aid:man:3', '>2'
           artifact_ns[:cool_aid].version.should == '3'
           artifact_ns[:cool_aid].requirement.should be_satisfied_by('2.5')
@@ -372,11 +415,11 @@
       end
     end
 
-    it 'should use cool_aid= as shorhand for [:cool_aid]=' do 
+    it 'should use cool_aid= as shorhand for [:cool_aid]=' do
       artifact_ns.cool_aid = 'cool:aid:jar:1'
       artifact_ns[:cool_aid].should be_selected
     end
-    
+
     it 'should use cool_aid as shorthand for [:cool_aid]' do
       artifact_ns.need :cool_aid => 'cool:aid:jar:1'
       artifact_ns.cool_aid.should_not be_selected
@@ -391,25 +434,25 @@
     end
   end
 
-  describe '#ns' do 
+  describe '#ns' do
     it 'should create a sub namespace' do
       artifact_ns.ns :foo
       artifact_ns[:foo].should be_kind_of(ArtifactNamespace)
       artifact_ns(:foo).should_not === artifact_ns.foo
       artifact_ns.foo.parent.should == artifact_ns
     end
-    
+
     it 'should take any use arguments' do
       artifact_ns.ns :foo, :bar => 'foo:bar:jar:0', :baz => 'foo:baz:jar:0'
       artifact_ns.foo.bar.should be_selected
       artifact_ns.foo[:baz].should be_selected
     end
-    
-    it 'should access sub artifacts using with foo_bar like syntax' do 
+
+    it 'should access sub artifacts using with foo_bar like syntax' do
       artifact_ns.ns :foo, :bar => 'foo:bar:jar:0', :baz => 'foo:baz:jar:0'
       artifact_ns[:foo_baz].should be_selected
       artifact_ns.foo_bar.should be_selected
-      
+
       artifact_ns.foo.ns :bat, 'bat:man:jar:>1'
       batman = artifact_ns.foo.bat.man
       batman.should be_selected
@@ -418,7 +461,7 @@
       artifact_ns[:foo_bat_man].version.should == '3'
     end
 
-    it 'should include sub artifacts when calling #values' do 
+    it 'should include sub artifacts when calling #values' do
       artifact_ns.ns :bat, 'bat:man:jar:>1'
       artifact_ns.values.should_not be_empty
       artifact_ns.values.first.unversioned_spec.should == 'bat:man:jar'
@@ -435,13 +478,13 @@
       lambda { artifact_ns.ns(:foo) }.should raise_error(TypeError, /not a sub/i)
     end
 
-    it 'should clone artifacts when assigned' do 
+    it 'should clone artifacts when assigned' do
       artifact_ns(:foo).bar = "foo:bar:jar:0"
       artifact_ns(:moo).ns :muu, :miu => artifact_ns(:foo).bar
       artifact_ns(:moo).muu.miu.should_not == artifact_ns(:foo).bar
       artifact_ns(:moo).muu.miu.to_spec.should == artifact_ns(:foo).bar.to_spec
     end
-    
+
     it 'should clone parent artifacts by name' do
       define 'foo' do
         artifact_ns.bar = "foo:bar:jar:0"
@@ -465,9 +508,9 @@
 describe Buildr do
   before(:each) { Buildr::ArtifactNamespace.clear }
 
-  describe '.artifacts' do 
+  describe '.artifacts' do
     it 'should take ruby symbols and ask the current namespace for them' do
-      define 'foo' do 
+      define 'foo' do
         artifact_ns.cool = 'cool:aid:jar:1.0'
         artifact_ns.use 'some:other:jar:1.0'
         artifact_ns.use 'bat:man:jar:1.0'
@@ -475,8 +518,8 @@
         compile.dependencies.map(&:to_spec).should include('cool:aid:jar:1.0', 'some:other:jar:1.0', 'bat:man:jar:1.0')
       end
     end
-    
-    it 'should take a namespace' do 
+
+    it 'should take a namespace' do
       artifact_ns(:moo).muu = 'moo:muu:jar:1.0'
       define 'foo' do
         compile.with artifact_ns(:moo)
@@ -484,28 +527,28 @@
       end
     end
   end
-  
+
   describe '.artifact' do
-    it 'should search current namespace if given a symbol' do 
-      define 'foo' do 
+    it 'should search current namespace if given a symbol' do
+      define 'foo' do
         artifact_ns.use :cool => 'cool:aid:jar:1.0'
         define 'bar' do
           artifact(:cool).should == artifact_ns[:cool].artifact
         end
       end
     end
-    
-    it 'should search current namespace if given a symbol spec' do 
-      define 'foo' do 
+
+    it 'should search current namespace if given a symbol spec' do
+      define 'foo' do
         artifact_ns.use 'cool:aid:jar:1.0'
         define 'bar' do
           artifact(:'cool:aid:jar').should == artifact_ns[:aid].artifact
         end
       end
     end
-    
+
     it 'should fail when no artifact by that name is found' do
-      define 'foo' do 
+      define 'foo' do
         artifact_ns.use 'cool:aid:jar:1.0'
         define 'bar' do
           lambda { artifact(:cool) }.should raise_error(IndexError, /artifact/)
@@ -524,12 +567,12 @@
   ensure
     Object.send :remove_const, :A
   end
-  
+
   it 'can register namespace listeners' do
     abc_module do
       # An example extension to illustrate namespace listeners and method forwarding
       class A::Example
-        
+
         module Ext
           include Buildr::Extension
           def example; @example ||= A::Example.new; end
@@ -537,22 +580,22 @@
             Rake::Task.define_task('example') { p.example.doit }
           end
         end
-        
+
         REQUIRES = ArtifactNamespace.for(self) do |ns|
           ns.xmlbeans! 'org.apache.xmlbeans:xmlbeans:jar:2.3.0', '>2'
           ns.stax_api! 'stax:stax-api:jar:>=1.0.1'
         end
 
         attr_reader :options, :requires
-        
+
         def initialize
           # We could actually use the REQUIRES namespace, but to make things
-          # a bit more interesting, suppose each Example instance can have its 
+          # a bit more interesting, suppose each Example instance can have its
           # own artifact requirements in adition to those specified on REQUIRES.
           # To achieve this we create an anonymous namespace.
           @requires = ArtifactNamespace.new # a namespace per instance
           REQUIRES.each { |requirement| @requires.need requirement }
-          
+
           # For user convenience, we make the options object respond to
           #    :xmlbeans, :xmlbeans=, :xmlbeans?
           # forwarding them to the namespace.
@@ -573,7 +616,7 @@
         end
 
         include Spec::Matchers # for assertions
-        
+
         # Called with the ArtifactRequirement that has just been selected
         # by a user. This allows extension author to selectively perform
         # some action by inspecting the requirement state.
@@ -591,20 +634,20 @@
           # Now call ant task with our selected artifact and options
           classpath = requires.map(&:artifact).map(&:to_s).join(File::PATH_SEPARATOR)
           lambda { ant('thing') { |ant| ant.classpath classpath, :math => options[:math] } }
-          
+
           # We are not a Project instance, hence we have no artifact_ns
           lambda { artifact_ns }.should raise_error(NameError)
 
           # Extension authors may NOT rely project's namespaces.
-          # However the ruby-way gives you power and at the same time 
+          # However the ruby-way gives you power and at the same time
           # makes you dangerous, (think open-modules, monkey-patching)
           # Given that buildr is pure ruby, consider it a sharp-edged sword.
-          # Having said that, you may actually inspect a project's 
+          # Having said that, you may actually inspect a project's
           # namespace, but don't write on it without letting your users
           # know you will.
           # This example obtains the current project namespace to make
           # some assertions.
-          
+
           # To obtain a project's namespace we need either
           # 1) a reference to the project, and call artifact_ns on it
           #      project.artifact_ns  # the namespace for project
@@ -627,7 +670,7 @@
           end
         end
       end
-      
+
       define 'foo' do
         define 'bar' do
           extend A::Example::Ext
@@ -643,7 +686,7 @@
 
       project('foo:bar').example.requires.should_not == project('foo:baz').example.requires
       project('foo:bar').example.requires.xmlbeans.should_not == project('foo:baz').example.requires.xmlbeans
-      
+
       # current namespace outside a project is :root, see the stax callback
       project('foo:baz').example.options.stax_api = '1.6180'
       # we call the task outside the project, see #doit