Basic SVN provider
authorBruce Williams <bruce@codefluency.com>
Sat, 13 Mar 2010 01:44:19 +0000 (17:44 -0800)
committerBruce Williams <bruce@codefluency.com>
Sat, 13 Mar 2010 01:44:19 +0000 (17:44 -0800)
lib/puppet/provider/vcsrepo/git.rb
lib/puppet/provider/vcsrepo/svn.rb [new file with mode: 0644]
lib/puppet/type/vcsrepo.rb
spec/fixtures/svn_info.txt [new file with mode: 0644]
spec/spec_helper.rb
spec/unit/puppet/provider/vcsrepo/svn_spec.rb

index 298d1dc..7290387 100644 (file)
@@ -42,8 +42,6 @@ Puppet::Type.type(:vcsrepo).provide(:git) do
   private
 
   def clone_repository(source, path)
-    parent = File.dirname(path)
-    FileUtils.mkdir_p(parent)
     git('clone', source, path)
   end
 
diff --git a/lib/puppet/provider/vcsrepo/svn.rb b/lib/puppet/provider/vcsrepo/svn.rb
new file mode 100644 (file)
index 0000000..fef7b62
--- /dev/null
@@ -0,0 +1,71 @@
+Puppet::Type.type(:vcsrepo).provide(:svn) do
+  desc "Supports Subversion repositories"
+
+  commands :svn      => 'svn',
+           :svnadmin => 'svnadmin'
+
+  def create
+    if !@resource.value(:source)
+      create_repository(@resource.value(:path))
+    else
+      checkout_repository(@resource.value(:source),
+                          @resource.value(:path),
+                          @resource.value(:revision))
+    end
+  end
+
+  def exists?
+    File.directory?(@resource.value(:path))
+  end
+
+  def destroy
+    FileUtils.rm_rf(@resource.value(:path))
+  end
+  
+  def revision
+    at_path do
+      svn('info')[/^Revision:\s+(\d+)/m, 1]
+    end
+  end
+
+  def revision=(desired)
+    at_path do
+      svn('update', '-r', desired)
+    end
+  end
+
+  private
+
+  def checkout_repository(source, path, revision = nil)
+    args = ['checkout']
+    if revision
+      args.push('-r', revision)
+    end
+    args.push(source, path)
+    svn(*args)
+  end
+
+  def create_repository(path)
+    args = ['create']
+    if @resource.value(:fstype)
+      args.push('--fs-type', @resource.value(:fstype))
+    end
+    args << path
+    svnadmin(*args)
+  end
+
+  def reset(desired)
+    at_path do
+      git('reset', '--hard', desired)
+    end
+  end
+
+  def at_path(&block)
+    value = nil
+    Dir.chdir(@resource.value(:path)) do
+      value = yield
+    end
+    value
+  end
+
+end
index 7db571e..04c48a3 100644 (file)
@@ -23,6 +23,10 @@ Puppet::Type.newtype(:vcsrepo) do
     end
   end
 
+  newparam(:fstype) do
+    desc "Filesystem type (for providers that support it, eg subversion)"
+  end
+
   newproperty(:revision) do
     desc "The revision of the repository"
     newvalue(/^\S+$/)
diff --git a/spec/fixtures/svn_info.txt b/spec/fixtures/svn_info.txt
new file mode 100644 (file)
index 0000000..d2a975b
--- /dev/null
@@ -0,0 +1,10 @@
+Path: .
+URL: http://example.com/svn/trunk
+Repository Root: http://example.com/svn
+Repository UUID: 75246ace-e253-0410-96dd-a7613ca8dc81
+Revision: 4
+Node Kind: directory
+Schedule: normal
+Last Changed Author: jon
+Last Changed Rev: 3
+Last Changed Date: 2008-08-07 11:34:25 -0700 (Thu, 07 Aug 2008)
index a4aeeae..1938658 100644 (file)
@@ -7,8 +7,17 @@ require 'puppet'
 gem 'rspec', '=1.2.9'
 require 'spec/autorun'
 
+module Helpers
+
+  def fixture(name, ext = '.txt')
+    File.read(File.join(File.dirname(__FILE__), 'fixtures', name.to_s + ext))
+  end
+  
+end
+
 Spec::Runner.configure do |config|
-    config.mock_with :mocha
+  config.mock_with :mocha
+  config.include(Helpers)
 end
 
 # We need this because the RAL uses 'should' as a method.  This
index 657913b..3af06f2 100644 (file)
@@ -4,13 +4,89 @@ provider_class = Puppet::Type.type(:vcsrepo).provider(:svn)
 
 describe provider_class do
 
-  before do
+  before :each do
     @resource = stub("resource")
     @provider = provider_class.new(@resource)
+    @path = '/tmp/vcsrepo'
   end
 
-  describe 'when creating'
-  describe 'when updating'
-  describe 'when destroying'
+  context 'when creating' do
+    context "when a source is given" do
+      context "and when a revision is given" do
+        it "should execute 'svn checkout' with a revision" do
+          @resource.expects(:value).with(:path).returns(@path).at_least_once
+          @resource.expects(:value).with(:source).returns('svn://example.com/repo').at_least_once
+          @resource.expects(:value).with(:revision).returns('1234').at_least_once
+          @provider.expects(:svn).with('checkout', '-r', '1234', 'svn://example.com/repo', @path)
+          @provider.create
+        end        
+      end
+      context "and when a revision is not given" do
+        it "should just execute 'svn checkout' without a revision" do
+          @resource.expects(:value).with(:path).returns(@path).at_least_once
+          @resource.expects(:value).with(:source).returns('svn://example.com/repo').at_least_once
+          @resource.expects(:value).with(:revision).returns(nil).at_least_once
+          @provider.expects(:svn).with('checkout','svn://example.com/repo', @path)
+          @provider.create
+        end        
+      end
+    end
+    context "when a source is not given" do
+      context "when a fstype is given" do
+        it "should execute 'svnadmin create' with an '--fs-type' option" do
+          @resource.expects(:value).with(:path).returns(@path).at_least_once
+          @resource.expects(:value).with(:fstype).returns('fsfs').at_least_once
+          @resource.expects(:value).with(:source).returns(nil)
+          @provider.expects(:svnadmin).with('create', '--fs-type', 'fsfs', @path)
+          @provider.create
+        end
+      end
+      context "when a fstype is not given" do
+        it "should execute 'svnadmin create' without an '--fs-type' option" do
+          @resource.expects(:value).with(:path).returns(@path).at_least_once
+          @resource.expects(:value).with(:source).returns(nil)
+          @resource.expects(:value).with(:fstype).returns(nil).at_least_once
+          @provider.expects(:svnadmin).with('create', @path)
+          @provider.create
+        end
+      end
+    end
+  end
+
+  context 'when destroying' do
+    it "it should remove the directory" do
+      @resource.expects(:value).with(:path).returns(@path).at_least_once
+      FileUtils.expects(:rm_rf).with(@path)
+      @provider.destroy
+    end
+  end
+
+  context "when checking existence" do
+    it "should check for the directory" do
+      @resource.expects(:value).with(:path).returns(@path)
+      File.expects(:directory?).with(@path)
+      @provider.exists?
+    end
+  end
+
+  describe "revision property" do
+    context "when checking" do
+      it "should use 'svn info'" do
+        @resource.expects(:value).with(:path).returns(@path)
+        p fixture(:svn_info)[/^Revision:\s+(\d+)/m, 1]
+        @provider.expects('svn').with('info').returns(fixture(:svn_info))
+        Dir.expects(:chdir).with(@path).yields
+        @provider.revision.should == '4'
+      end
+    end
+    context "when setting" do
+      it "should use 'svn update'" do
+        @resource.expects(:value).with(:path).returns(@path)
+        @provider.expects('svn').with('update', '-r', '30')
+        Dir.expects(:chdir).with(@path).yields
+        @provider.revision = '30'
+      end
+    end
+  end
 
 end