diff --git a/lib/puppet/provider/package/gem.rb b/lib/puppet/provider/package/gem.rb index 19414cec4..64544db4e 100755 --- a/lib/puppet/provider/package/gem.rb +++ b/lib/puppet/provider/package/gem.rb @@ -1,124 +1,125 @@ require 'puppet/provider/package' require 'uri' +require 'pp' # Ruby gems support. Puppet::Type.type(:package).provide :gem, :parent => Puppet::Provider::Package do desc "Ruby Gem support. If a URL is passed via `source`, then that URL is used as the remote gem repository; if a source is present but is not a valid URL, it will be interpreted as the path to a local gem file. If source is not present at all, the gem will be installed from the default gem repositories." has_feature :versionable commands :gemcmd => "gem" def self.gemlist(hash) command = [command(:gemcmd), "list"] if hash[:local] command << "--local" else command << "--remote" end if name = hash[:justme] - command << name + command << name + "$" end begin list = execute(command).split("\n").collect do |set| if gemhash = gemsplit(set) gemhash[:provider] = :gem gemhash else nil end end.compact rescue Puppet::ExecutionFailure => detail raise Puppet::Error, "Could not list gems: #{detail}" end if hash[:justme] return list.shift else return list end end def self.gemsplit(desc) case desc when /^\*\*\*/, /^\s*$/, /^\s+/; return nil when /^(\S+)\s+\((.+)\)/ name = $1 version = $2.split(/,\s*/)[0] return { :name => name, :ensure => version } else Puppet.warning "Could not match #{desc}" nil end end def self.instances(justme = false) gemlist(:local => true).collect do |hash| new(hash) end end def install(useversion = true) command = [command(:gemcmd), "install"] command << "-v" << resource[:ensure] if (! resource[:ensure].is_a? Symbol) and useversion # Always include dependencies command << "--include-dependencies" if source = resource[:source] begin uri = URI.parse(source) rescue => detail fail "Invalid source '#{uri}': #{detail}" end case uri.scheme when nil # no URI scheme => interpret the source as a local file command << source when /file/i command << uri.path when 'puppet' # we don't support puppet:// URLs (yet) raise Puppet::Error.new("puppet:// URLs are not supported as gem sources") else # interpret it as a gem repository command << "--source" << "#{source}" << resource[:name] end else - command << resource[:name] + command << "--no-rdoc" << "--no-ri" << resource[:name] end output = execute(command) # Apparently some stupid gem versions don't exit non-0 on failure self.fail "Could not install: #{output.chomp}" if output.include?("ERROR") end def latest # This always gets the latest version available. hash = self.class.gemlist(:justme => resource[:name]) hash[:ensure] end def query self.class.gemlist(:justme => resource[:name], :local => true) end def uninstall gemcmd "uninstall", "-x", "-a", resource[:name] end def update self.install(false) end end diff --git a/spec/unit/provider/package/gem_spec.rb b/spec/unit/provider/package/gem_spec.rb index 063e1474b..32c067a60 100644 --- a/spec/unit/provider/package/gem_spec.rb +++ b/spec/unit/provider/package/gem_spec.rb @@ -1,87 +1,97 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../../../spec_helper' provider_class = Puppet::Type.type(:package).provider(:gem) describe provider_class do it "should have an install method" do @provider = provider_class.new @provider.should respond_to(:install) end describe "when installing" do before do # Create a mock resource @resource = stub 'resource' # A catch all; no parameters set @resource.stubs(:[]).returns nil # We have to set a name, though @resource.stubs(:[]).with(:name).returns "myresource" @resource.stubs(:[]).with(:ensure).returns :installed @provider = provider_class.new @provider.stubs(:resource).returns @resource end it "should use the path to the gem" do provider_class.stubs(:command).with(:gemcmd).returns "/my/gem" @provider.expects(:execute).with { |args| args[0] == "/my/gem" }.returns "" @provider.install end it "should specify that the gem is being installed" do @provider.expects(:execute).with { |args| args[1] == "install" }.returns "" @provider.install end it "should specify that dependencies should be included" do @provider.expects(:execute).with { |args| args[2] == "--include-dependencies" }.returns "" @provider.install end + it "should specify that documentation should not be included" do + @provider.expects(:execute).with { |args| args[3] == "--no-rdoc" }.returns "" + @provider.install + end + + it "should specify that RI should not be included" do + @provider.expects(:execute).with { |args| args[4] == "--no-ri" }.returns "" + @provider.install + end + it "should specify the package name" do - @provider.expects(:execute).with { |args| args[3] == "myresource" }.returns "" + @provider.expects(:execute).with { |args| args[5] == "myresource" }.returns "" @provider.install end describe "when a source is specified" do describe "as a normal file" do it "should use the file name instead of the gem name" do @resource.stubs(:[]).with(:source).returns "/my/file" @provider.expects(:execute).with { |args| args[3] == "/my/file" }.returns "" @provider.install end end describe "as a file url" do it "should use the file name instead of the gem name" do @resource.stubs(:[]).with(:source).returns "file:///my/file" @provider.expects(:execute).with { |args| args[3] == "/my/file" }.returns "" @provider.install end end describe "as a puppet url" do it "should fail" do @resource.stubs(:[]).with(:source).returns "puppet://my/file" lambda { @provider.install }.should raise_error(Puppet::Error) end end describe "as a non-file and non-puppet url" do it "should treat the source as a gem repository" do @resource.stubs(:[]).with(:source).returns "http://host/my/file" @provider.expects(:execute).with { |args| args[3..5] == ["--source", "http://host/my/file", "myresource"] }.returns "" @provider.install end end describe "with an invalid uri" do it "should fail" do URI.expects(:parse).raises(ArgumentError) @resource.stubs(:[]).with(:source).returns "http:::::uppet:/:/my/file" lambda { @provider.install }.should raise_error(Puppet::Error) end end end end end