diff --git a/lib/puppet/provider/vcsrepo/cvs.rb b/lib/puppet/provider/vcsrepo/cvs.rb index 3b0064f..651dc78 100644 --- a/lib/puppet/provider/vcsrepo/cvs.rb +++ b/lib/puppet/provider/vcsrepo/cvs.rb @@ -1,157 +1,157 @@ # frozen_string_literal: true require File.join(File.dirname(__FILE__), '..', 'vcsrepo') Puppet::Type.type(:vcsrepo).provide(:cvs, parent: Puppet::Provider::Vcsrepo) do desc 'Supports CVS repositories/workspaces' commands cvs: 'cvs' has_features :gzip_compression, :reference_tracking, :modules, :cvs_rsh, :user def create check_force if !@resource.value(:source) create_repository(@resource.value(:path)) else checkout_repository end update_owner end - def exist? + def exists? working_copy_exists? end def working_copy_exists? if @resource.value(:source) directory = File.join(@resource.value(:path), 'CVS') return false unless File.directory?(directory) begin at_path { runcvs('-nq', 'status', '-l') } true rescue Puppet::ExecutionFailure false end else directory = File.join(@resource.value(:path), 'CVSROOT') return false unless File.directory?(directory) config = File.join(@resource.value(:path), 'CVSROOT', 'config,v') return false unless File.exist?(config) true end end def destroy FileUtils.rm_rf(@resource.value(:path)) end def latest? Puppet.debug "Checking for updates because 'ensure => latest'" at_path do # We cannot use -P to prune empty dirs, otherwise # CVS would report those as "missing", regardless # if they have contents or updates. is_current = (runcvs('-nq', 'update', '-d').strip == '') unless is_current then Puppet.debug "There are updates available on the checkout's current branch/tag." end return is_current end end def latest # CVS does not have a conecpt like commit-IDs or change # sets, so we can only have the current branch name (or the # requested one, if that differs) as the "latest" revision. should = @resource.value(:revision) current = revision (should != current) ? should : current end def revision unless @rev if File.exist?(tag_file) contents = File.read(tag_file).strip # NOTE: Doesn't differentiate between N and T entries @rev = contents[1..-1] else @rev = 'HEAD' end Puppet.debug "Checkout is on branch/tag '#{@rev}'" end @rev end def revision=(desired) at_path do runcvs('update', '-dr', desired, '.') update_owner @rev = desired end end def source File.read(File.join(@resource.value(:path), 'CVS', 'Root')).chomp end def source=(_desired) create # recreate end def module File.read(File.join(@resource.value(:path), 'CVS', 'Repository')).chomp end def module=(_desired) create # recreate 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') if @resource.value(:revision) args.push('-r', @resource.value(:revision)) end args.push('-d', basename, module_name) runcvs(*args) end end # If no module is provided, use '.', the root of the repo def module_name @resource.value(:module) || '.' end def create_repository(path) runcvs('-d', path, 'init') end def update_owner set_ownership if @resource.value(:owner) || @resource.value(:group) end def runcvs(*args) if @resource.value(:cvs_rsh) Puppet.debug 'Using CVS_RSH = ' + @resource.value(:cvs_rsh) e = { CVS_RSH: @resource.value(:cvs_rsh) } else e = {} end if @resource.value(:user) && @resource.value(:user) != Facter['id'].value Puppet.debug 'Running as user ' + @resource.value(:user) Puppet::Util::Execution.execute([:cvs, *args], uid: @resource.value(:user), custom_environment: e, combine: true, failonfail: true) else Puppet::Util::Execution.execute([:cvs, *args], custom_environment: e, combine: true, failonfail: true) end end end diff --git a/spec/unit/puppet/provider/vcsrepo/cvs_spec.rb b/spec/unit/puppet/provider/vcsrepo/cvs_spec.rb index 3f981bb..6ebd727 100644 --- a/spec/unit/puppet/provider/vcsrepo/cvs_spec.rb +++ b/spec/unit/puppet/provider/vcsrepo/cvs_spec.rb @@ -1,163 +1,163 @@ # frozen_string_literal: true require 'spec_helper' describe Puppet::Type.type(:vcsrepo).provider(:cvs) do let(:resource) do Puppet::Type.type(:vcsrepo).new(name: 'test', ensure: :present, provider: :cvs, revision: '2634', source: ':pserver:anonymous@cvs.sv.gnu.org:/sources/cvs/', path: '/tmp/test') end let(:provider) { resource.provider } before :each do allow(Puppet::Util).to receive(:which).with('cvs').and_return('/usr/bin/cvs') end describe 'creating' do context 'with a source' do it "executes 'cvs checkout'" do resource[:source] = ':ext:source@example.com:/foo/bar' resource[:revision] = 'an-unimportant-value' expect_chdir('/tmp') expect(Puppet::Util::Execution).to receive(:execute).with([:cvs, '-d', resource.value(:source), 'checkout', '-r', 'an-unimportant-value', '-d', 'test', '.'], custom_environment: {}, combine: true, failonfail: true) provider.create end it "executes 'cvs checkout' as user 'muppet'" do resource[:source] = ':ext:source@example.com:/foo/bar' resource[:revision] = 'an-unimportant-value' resource[:user] = 'muppet' expect_chdir('/tmp') expect(Puppet::Util::Execution).to receive(:execute).with([:cvs, '-d', resource.value(:source), 'checkout', '-r', 'an-unimportant-value', '-d', 'test', '.'], uid: 'muppet', custom_environment: {}, combine: true, failonfail: true) provider.create end it "justs execute 'cvs checkout' without a revision" do resource[:source] = ':ext:source@example.com:/foo/bar' resource.delete(:revision) expect(Puppet::Util::Execution).to receive(:execute).with([:cvs, '-d', resource.value(:source), 'checkout', '-d', File.basename(resource.value(:path)), '.'], custom_environment: {}, combine: true, failonfail: true) provider.create end end context 'with a compression' do it "justs execute 'cvs checkout' without a revision" do resource[:source] = ':ext:source@example.com:/foo/bar' resource[:compression] = '3' resource.delete(:revision) expect(Puppet::Util::Execution).to receive(:execute).with([:cvs, '-d', resource.value(:source), '-z', '3', 'checkout', '-d', File.basename(resource.value(:path)), '.'], custom_environment: {}, combine: true, failonfail: true) provider.create end end context 'when a source is not given' do it "executes 'cvs init'" do resource.delete(:source) expect(Puppet::Util::Execution).to receive(:execute).with([:cvs, '-d', resource.value(:path), 'init'], custom_environment: {}, combine: true, failonfail: true) provider.create end end end describe 'destroying' do it 'removes the directory' do provider.destroy end end describe 'checking existence' do context 'with a source value' do it "runs 'cvs status'" do resource[:source] = ':ext:source@example.com:/foo/bar' expect(File).to receive(:directory?).with(File.join(resource.value(:path), 'CVS')).and_return(true) expect_chdir expect(Puppet::Util::Execution).to receive(:execute).with([:cvs, '-nq', 'status', '-l'], custom_environment: {}, combine: true, failonfail: true) - provider.exist? + provider.exists? end end context 'without a source value' do it 'checks for the CVSROOT directory and config file' do resource.delete(:source) expect(File).to receive(:directory?).with(File.join(resource.value(:path), 'CVSROOT')).and_return(true) expect(File).to receive(:exist?).with(File.join(resource.value(:path), 'CVSROOT', 'config,v')).and_return(true) - provider.exist? + provider.exists? end end end describe 'checking the revision property' do let(:tag_file) { File.join(resource.value(:path), 'CVS', 'Tag') } context 'when CVS/Tag exists' do let(:tag) { 'TAG' } before(:each) do allow(File).to receive(:exist?).with(tag_file).and_return(true) end it 'reads CVS/Tag' do expect(File).to receive(:read).with(tag_file).and_return("T#{tag}") expect(provider.revision).to eq(tag) end end context 'when CVS/Tag does not exist' do before(:each) do allow(File).to receive(:exist?).with(tag_file).and_return(false) end it 'assumes HEAD' do expect(provider.revision).to eq('HEAD') end end end describe 'when setting the revision property' do let(:tag) { 'SOMETAG' } it "uses 'cvs update -dr'" do expect_chdir expect(Puppet::Util::Execution).to receive(:execute).with([:cvs, 'update', '-dr', tag, '.'], custom_environment: {}, combine: true, failonfail: true) provider.revision = tag end end describe 'checking the source property' do it "reads the contents of file 'CVS/Root'" do expect(File).to receive(:read).with(File.join(resource.value(:path), 'CVS', 'Root')) .and_return(':pserver:anonymous@cvs.sv.gnu.org:/sources/cvs/') expect(provider.source).to eq(resource.value(:source)) end end describe 'setting the source property' do it "calls 'create'" do expect(provider).to receive(:create) provider.source = resource.value(:source) end end describe 'checking the module property' do before(:each) do resource[:module] = 'ccvs' end it "reads the contents of file 'CVS/Repository'" do expect(File).to receive(:read).with(File.join(resource.value(:path), 'CVS', 'Repository')) .and_return('ccvs') expect(provider.module).to eq(resource.value(:module)) end end describe 'setting the module property' do it "calls 'create'" do expect(provider).to receive(:create) provider.module = resource.value(:module) end end end