Basic Mercurial support
authorBruce Williams <bruce@codefluency.com>
Sat, 13 Mar 2010 23:19:39 +0000 (15:19 -0800)
committerBruce Williams <bruce@codefluency.com>
Sat, 13 Mar 2010 23:19:39 +0000 (15:19 -0800)
examples/cvs/init.pp [moved from examples/cvs.pp with 100% similarity]
examples/git/init.pp [moved from examples/git.pp with 100% similarity]
examples/hg/init.pp [new file with mode: 0644]
examples/svn/init.pp [moved from examples/svn.pp with 100% similarity]
lib/puppet/provider/vcsrepo/cvs.rb
lib/puppet/provider/vcsrepo/git.rb
lib/puppet/provider/vcsrepo/hg.rb [new file with mode: 0644]
lib/puppet/provider/vcsrepo/svn.rb
spec/fixtures/hg_parents.txt [new file with mode: 0644]
spec/unit/puppet/provider/vcsrepo/hg_spec.rb [new file with mode: 0644]

similarity index 100%
rename from examples/cvs.pp
rename to examples/cvs/init.pp
similarity index 100%
rename from examples/git.pp
rename to examples/git/init.pp
diff --git a/examples/hg/init.pp b/examples/hg/init.pp
new file mode 100644 (file)
index 0000000..620806e
--- /dev/null
@@ -0,0 +1,11 @@
+vcsrepo { "/tmp/vcstest-hg-init":
+  ensure => present,
+  provider => hg
+}
+
+vcsrepo { "/tmp/vcstest-hg-clone":
+  ensure => present,
+  provider => hg,
+  source => "http://hg.basho.com/riak/",
+  revision => '34e6012c783a'
+} 
similarity index 100%
rename from examples/svn.pp
rename to examples/svn/init.pp
index 58018d3..99faa54 100644 (file)
@@ -1,4 +1,4 @@
-require 'puppet/provider/vcsrepo'
+require File.join(File.dirname(__FILE__), '..', 'vcsrepo')
 
 Puppet::Type.type(:vcsrepo).provide(:cvs, :parent => Puppet::Provider::Vcsrepo) do
   desc "Supports CVS repositories/workspaces"
index 99477a0..eeecac3 100644 (file)
@@ -1,4 +1,4 @@
-require 'puppet/provider/vcsrepo'
+require File.join(File.dirname(__FILE__), '..', 'vcsrepo')
 
 Puppet::Type.type(:vcsrepo).provide(:git, :parent => Puppet::Provider::Vcsrepo) do
   desc "Supports Git repositories"
diff --git a/lib/puppet/provider/vcsrepo/hg.rb b/lib/puppet/provider/vcsrepo/hg.rb
new file mode 100644 (file)
index 0000000..7263b4f
--- /dev/null
@@ -0,0 +1,59 @@
+require File.join(File.dirname(__FILE__), '..', 'vcsrepo')
+
+Puppet::Type.type(:vcsrepo).provide(:hg, :parent => Puppet::Provider::Vcsrepo) do
+  desc "Supports Mercurial repositories"
+
+  commands   :hg => 'hg'
+  defaultfor :hg => :exists
+
+  def create
+    if !@resource.value(:source)
+      create_repository(@resource.value(:path))
+    else
+      clone_repository(@resource.value(:revision))
+    end
+  end
+
+  def exists?
+    File.directory?(File.join(@resource.value(:path), '.hg'))
+  end
+
+  def destroy
+    FileUtils.rm_rf(@resource.value(:path))
+  end
+  
+  def revision
+    at_path do
+      hg('parents')[/^changeset:\s+(?:-?\d+):(\S+)/m, 1]
+    end
+  end
+
+  def revision=(desired)
+    at_path do
+      hg('pull')
+      begin
+        hg('merge')
+      rescue Puppet::ExecutionFailure
+        # If there's nothing to merge, just skip
+      end
+      hg('update', '--clean', '-r', desired)
+    end
+  end
+
+  private
+
+  def create_repository(path)
+    hg('init', path)
+  end
+
+  def clone_repository(revision)
+    args = ['clone']
+    if revision
+      args.push('-u', revision)
+    end
+    args.push(@resource.value(:source),
+              @resource.value(:path))
+    hg(*args)
+  end
+
+end
index 97c7fcb..09fdd0e 100644 (file)
@@ -1,4 +1,4 @@
-require 'puppet/provider/vcsrepo'
+require File.join(File.dirname(__FILE__), '..', 'vcsrepo')
 
 Puppet::Type.type(:vcsrepo).provide(:svn, :parent => Puppet::Provider::Vcsrepo) do
   desc "Supports Subversion repositories"
diff --git a/spec/fixtures/hg_parents.txt b/spec/fixtures/hg_parents.txt
new file mode 100644 (file)
index 0000000..46173df
--- /dev/null
@@ -0,0 +1,6 @@
+changeset:   3:34e6012c783a
+parent:      2:21ea4598c962
+parent:      1:9d0ff0028458
+user:        Test User <test.user@example.com>
+date:        Fri Aug 07 13:13:02 2009 -0400
+summary:     merge
diff --git a/spec/unit/puppet/provider/vcsrepo/hg_spec.rb b/spec/unit/puppet/provider/vcsrepo/hg_spec.rb
new file mode 100644 (file)
index 0000000..56189a3
--- /dev/null
@@ -0,0 +1,96 @@
+require 'pathname'; Pathname.new(__FILE__).realpath.ascend { |x| begin; require (x + 'spec_helper.rb'); break; rescue LoadError; end }
+
+provider_class = Puppet::Type.type(:vcsrepo).provider(:hg)
+
+describe provider_class do
+
+  before :each do
+    @resource = stub("resource")
+    @provider = provider_class.new(@resource)
+    @path = '/tmp/vcsrepo'
+  end
+
+  describe 'when creating' do
+    before do
+      @resource.expects(:value).with(:path).returns(@path).at_least_once
+    end
+    context "when a source is given" do
+      before do
+        @source = 'http://example.com/hg/repo'
+        @resource.expects(:value).with(:source).returns(@source).at_least_once
+      end
+      context "and when a revision is given" do
+        before do
+          @revision = '6aa99e9b3ac2'
+          @resource.expects(:value).with(:revision).returns(@revision).at_least_once
+        end
+        it "should execute 'hg clone -u' with the revision" do
+          @provider.expects(:hg).with('clone', '-u', @revision, @source, @path)
+          @provider.create
+        end        
+      end
+      context "and when a revision is not given" do
+        before do
+          @resource.expects(:value).with(:revision).returns(nil).at_least_once
+        end
+        it "should just execute 'hg clone' without a revision" do
+          @provider.expects(:hg).with('clone', @source, @path)
+          @provider.create
+        end        
+      end
+    end
+    context "when a source is not given" do
+      before do
+        @resource.expects(:value).with(:source).returns(nil).at_least_once
+      end
+      it "should execute 'hg init'" do
+        @provider.expects(:hg).with('init', @path)
+        @provider.create
+      end
+    end
+  end
+
+  describe '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
+
+  describe "when checking existence" do
+    before do
+      @resource.expects(:value).with(:path).returns(@path)
+    end
+    it "should check for the directory" do
+      File.expects(:directory?).with(File.join(@path, '.hg'))
+      @provider.exists?
+    end
+  end
+
+  describe "when checking the revision property" do
+    before do
+      @resource.expects(:value).with(:path).returns(@path)
+    end
+    it "should use 'hg tip'" do
+      @provider.expects('hg').with('parents').returns(fixture(:hg_parents))
+      Dir.expects(:chdir).with(@path).yields
+      @provider.revision.should == '34e6012c783a'
+    end
+  end
+  
+  describe "when setting the revision property" do
+    before do
+      @resource.expects(:value).with(:path).returns(@path).at_least_once
+      @revision = '6aa99e9b3ab1'
+    end
+    it "should use 'hg update ---clean -r'" do
+      Dir.expects(:chdir).with(@path).yields
+      @provider.expects('hg').with('pull')
+      @provider.expects('hg').with('merge')
+      @provider.expects('hg').with('update', '--clean', '-r', @revision)
+      @provider.revision = @revision
+    end
+  end
+
+end