summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.CVS.markdown42
-rw-r--r--lib/puppet/provider/vcsrepo/cvs.rb87
-rw-r--r--lib/puppet/provider/vcsrepo/svn.rb6
-rw-r--r--lib/puppet/type/vcsrepo.rb32
-rw-r--r--spec/unit/puppet/provider/vcsrepo/cvs_spec.rb137
5 files changed, 289 insertions, 15 deletions
diff --git a/README.CVS.markdown b/README.CVS.markdown
new file mode 100644
index 0000000..7f9647e
--- /dev/null
+++ b/README.CVS.markdown
@@ -0,0 +1,42 @@
+Using vcsrepo with CVS
+======================
+
+To create a blank repository
+----------------------------
+
+Define a `vcsrepo` without a `source` or `revision`:
+
+ vcsrepo { "/path/to/repo":
+ ensure => present,
+ provider => cvs
+ }
+
+To checkout/update from a repository
+------------------------------------
+
+To get the current mainline:
+
+ vcsrepo { "/path/to/workspace":
+ ensure => present,
+ provider => cvs,
+ source => ":pserver:anonymous@example.com:/sources/myproj"
+ }
+
+You can use the `compression` parameter (it works like CVS `-z`):
+
+ vcsrepo { "/path/to/workspace":
+ ensure => present,
+ provider => cvs,
+ compression => 3,
+ source => ":pserver:anonymous@example.com:/sources/myproj"
+ }
+
+For a specific tag, use `revision`:
+
+ vcsrepo { "/path/to/workspace":
+ ensure => present,
+ provider => cvs,
+ compression => 3,
+ source => ":pserver:anonymous@example.com:/sources/myproj",
+ revision => "SOMETAG"
+ }
diff --git a/lib/puppet/provider/vcsrepo/cvs.rb b/lib/puppet/provider/vcsrepo/cvs.rb
new file mode 100644
index 0000000..68d22c1
--- /dev/null
+++ b/lib/puppet/provider/vcsrepo/cvs.rb
@@ -0,0 +1,87 @@
+Puppet::Type.type(:vcsrepo).provide(:cvs) do
+ desc "Supports CVS repositories/workspaces"
+
+ commands :cvs => 'cvs'
+ defaultfor :cvs => :exists
+
+ def create
+ if !@resource.value(:source)
+ create_repository(@resource.value(:path))
+ else
+ checkout_repository
+ end
+ end
+
+ def exists?
+ if @resource.value(:source)
+ directory = File.join(@resource.value(:path), 'CVS')
+ else
+ directory = File.join(@resource.value(:path), 'CVSROOT')
+ end
+ File.directory?(directory)
+ end
+
+ def destroy
+ FileUtils.rm_rf(@resource.value(:path))
+ end
+
+ def revision
+ if File.exist?(tag_file)
+ contents = File.read(tag_file)
+ # Note: Doesn't differentiate between N and T entries
+ contents[1..-1]
+ else
+ 'MAIN'
+ end
+ end
+
+ def revision=(desired)
+ at_path do
+ cvs('update', '-r', desired, '.')
+ end
+ end
+
+ private
+
+ def tag_file
+ File.join(@resource.value(:path), 'CVS', 'Tag')
+ end
+
+ def checkout_repository
+ dirname, basename = File.split(@resource.value(:path))
+ Dir.chdir(dirname) do
+ args = ['-d', @resource.value(:source)]
+ if @resource.value(:compression)
+ args.push('-z', @resource.value(:compression))
+ end
+ args.push('checkout', '-d', basename, module_name)
+ cvs(*args)
+ end
+ if @resource.value(:revision)
+ self.revision = @resource.value(:revision)
+ end
+ end
+
+ # When the source:
+ # * Starts with ':' (eg, :pserver:...)
+ def module_name
+ if (source = @resource.value(:source))
+ source[0, 1] == ':' ? File.basename(source) : '.'
+ end
+ end
+
+ def create_repository(path)
+ cvs('-d', path, 'init')
+ end
+
+ # Note: We don't rely on Dir.chdir's behavior of automatically returning the
+ # value of the last statement -- for easier stubbing.
+ def at_path(&block) #:nodoc:
+ value = nil
+ Dir.chdir(@resource.value(:path)) do
+ value = yield
+ end
+ value
+ end
+
+end
diff --git a/lib/puppet/provider/vcsrepo/svn.rb b/lib/puppet/provider/vcsrepo/svn.rb
index 226cc63..c85ffa4 100644
--- a/lib/puppet/provider/vcsrepo/svn.rb
+++ b/lib/puppet/provider/vcsrepo/svn.rb
@@ -56,12 +56,6 @@ Puppet::Type.type(:vcsrepo).provide(:svn) do
svnadmin(*args)
end
- def reset(desired)
- at_path do
- git('reset', '--hard', desired)
- end
- end
-
# Note: We don't rely on Dir.chdir's behavior of automatically returning the
# value of the last statement -- for easier stubbing.
def at_path(&block) #:nodoc:
diff --git a/lib/puppet/type/vcsrepo.rb b/lib/puppet/type/vcsrepo.rb
index b093910..7616f41 100644
--- a/lib/puppet/type/vcsrepo.rb
+++ b/lib/puppet/type/vcsrepo.rb
@@ -13,12 +13,20 @@ Puppet::Type.newtype(:vcsrepo) do
def retrieve
prov = @resource.provider
if prov
- if prov.respond_to?(:working_copy_exists?) && prov.working_copy_exists?
- :present
- elsif prov.respond_to?(:bare_exists?) && prov.bare_exists?
- :bare
+ if prov.respond_to?(:bare_exists?)
+ if prov.respond_to?(:working_copy_exists?) && prov.working_copy_exists?
+ :present
+ elsif prov.respond_to?(:bare_exists?) && prov.bare_exists?
+ :bare
+ else
+ :absent
+ end
else
- :absent
+ if prov.exists?
+ :present
+ else
+ :absent
+ end
end
else
:absent
@@ -39,10 +47,7 @@ Puppet::Type.newtype(:vcsrepo) do
end
newparam(:source) do
- desc "The source URL for the repository"
- validate do |value|
- URI.parse(value)
- end
+ desc "The source URI for the repository"
end
newparam(:fstype) do
@@ -54,4 +59,13 @@ Puppet::Type.newtype(:vcsrepo) do
newvalue(/^\S+$/)
end
+ newparam :compression do
+ desc "Compression level (used by CVS)"
+ validate do |amount|
+ unless Integer(amount).between?(0, 6)
+ raise ArgumentError, "Unsupported compression level: #{amount} (expected 0-6)"
+ end
+ end
+ end
+
end
diff --git a/spec/unit/puppet/provider/vcsrepo/cvs_spec.rb b/spec/unit/puppet/provider/vcsrepo/cvs_spec.rb
new file mode 100644
index 0000000..c0c2dbc
--- /dev/null
+++ b/spec/unit/puppet/provider/vcsrepo/cvs_spec.rb
@@ -0,0 +1,137 @@
+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(:cvs)
+
+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 = ":pserver:anonymous@example.com:/sources/myproj"
+ @resource.expects(:value).with(:source).returns(@source).at_least_once
+ Dir.expects(:chdir).with(File.dirname(@path)).yields
+ end
+ context "and when a revision is given" do
+ before do
+ @tag = 'SOMETAG'
+ @resource.expects(:value).with(:revision).returns(@tag).at_least_once
+ @resource.expects(:value).with(:compression).returns(nil).at_least_once
+ end
+ it "should execute 'cvs checkout' and 'cvs update -r'" do
+ @provider.expects(:cvs).with('-d', @source, 'checkout', '-d', File.basename(@path), File.basename(@source))
+ Dir.expects(:chdir).with(@path).yields
+ @provider.expects(:cvs).with('update', '-r', @tag, '.')
+ @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
+ @resource.expects(:value).with(:compression).returns(nil).at_least_once
+ end
+ it "should just execute 'cvs checkout' without a revision" do
+ @provider.expects(:cvs).with('-d', @source, 'checkout', '-d', File.basename(@path), File.basename(@source))
+ @provider.create
+ end
+ end
+ context "when a compression level is given" do
+ before do
+ @resource.expects(:value).with(:revision).returns(nil).at_least_once
+ @resource.expects(:value).with(:compression).returns('3').at_least_once
+ end
+ it "should just execute 'cvs checkout' without a revision" do
+ @provider.expects(:cvs).with('-d', @source, '-z', '3', 'checkout', '-d', File.basename(@path), File.basename(@source))
+ @provider.create
+ end
+ end
+ end
+ context "when a source is not given" do
+ before do
+ @resource.expects(:value).with(:source).returns(nil)
+ end
+ it "should execute 'cvs init'" do
+ @provider.expects(:cvs).with('-d', @path, 'init')
+ @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
+ context "when a source is provided" do
+ before do
+ @resource.expects(:value).with(:source).returns(":pserver:anonymous@example.com:/sources/myproj")
+ end
+ it "should check for the CVS directory" do
+ File.expects(:directory?).with(File.join(@path, 'CVS'))
+ @provider.exists?
+ end
+ end
+ context "when a source is not provided" do
+ before do
+ @resource.expects(:value).with(:source).returns(nil)
+ end
+ it "should check for the CVSROOT directory" do
+ File.expects(:directory?).with(File.join(@path, 'CVSROOT'))
+ @provider.exists?
+ end
+ end
+ end
+
+ describe "when checking the revision property" do
+ before do
+ @resource.expects(:value).with(:path).returns(@path).at_least_once
+ @tag_file = File.join(@path, 'CVS', 'Tag')
+ end
+ context "when CVS/Tag exists" do
+ before do
+ @tag = 'HEAD'
+ File.expects(:exist?).with(@tag_file).returns(true)
+ end
+ it "should read CVS/Tag" do
+ File.expects(:read).with(@tag_file).returns("T#{@tag}")
+ @provider.revision.should == @tag
+ end
+ end
+ context "when CVS/Tag does not exist" do
+ before do
+ File.expects(:exist?).with(@tag_file).returns(false)
+ end
+ it "assumes MAIN" do
+ @provider.revision.should == 'MAIN'
+ end
+ end
+ end
+
+ describe "when setting the revision property" do
+ before do
+ @resource.expects(:value).with(:path).returns(@path).at_least_once
+ @tag = 'SOMETAG'
+ end
+ it "should use 'cvs update -r'" do
+ Dir.expects(:chdir).with(@path).yields
+ @provider.expects('cvs').with('update', '-r', @tag, '.')
+ @provider.revision = @tag
+ end
+ end
+
+end