Support different create and revision= operations depending on the revision type in Git (commit, tag, or local/remote branch)

This commit is contained in:
Bruce Williams 2010-03-18 14:46:12 -07:00
parent dc64158c8c
commit 463779ca3d
3 changed files with 143 additions and 18 deletions

View File

@ -16,7 +16,7 @@ Puppet::Type.type(:vcsrepo).provide(:git, :parent => Puppet::Provider::Vcsrepo)
if @resource.value(:ensure) == :bare
notice "Ignoring revision for bare repository"
else
reset(@resource.value(:revision))
checkout_branch_or_reset
end
end
if @resource.value(:ensure) != :bare
@ -41,9 +41,24 @@ Puppet::Type.type(:vcsrepo).provide(:git, :parent => Puppet::Provider::Vcsrepo)
def revision=(desired)
fetch
reset(desired)
unless @resource.value(:ensure) == :bare
if local_revision_branch?(desired)
at_path do
git('checkout', desired)
git('pull', 'origin')
end
update_submodules
elsif remote_revision_branch?(desired)
at_path do
git('checkout',
'-b', @resource.value(:revision),
'--track', "origin/#{@resource.value(:revision)}")
end
update_submodules
else
reset(desired)
if @resource.value(:ensure) != :bare
update_submodules
end
end
end
@ -90,6 +105,12 @@ Puppet::Type.type(:vcsrepo).provide(:git, :parent => Puppet::Provider::Vcsrepo)
end
end
def pull
at_path do
git('pull', 'origin')
end
end
def init_repository(path)
if @resource.value(:ensure) == :bare && working_copy_exists?
convert_working_copy_to_bare
@ -150,6 +171,16 @@ Puppet::Type.type(:vcsrepo).provide(:git, :parent => Puppet::Provider::Vcsrepo)
false
end
def checkout_branch_or_reset
if remote_revision_branch?
at_path do
git('checkout', '-b', @resource.value(:revision), '--track', "origin/#{@resource.value(:revision)}")
end
else
reset(@resource.value(:revision))
end
end
def reset(desired)
at_path do
git('reset', '--hard', desired)
@ -163,4 +194,20 @@ Puppet::Type.type(:vcsrepo).provide(:git, :parent => Puppet::Provider::Vcsrepo)
end
end
def remote_branch_revision?(revision = @resource.value(:revision))
at_path do
branches.include?("origin/#{revision}")
end
end
def local_branch_revision?(revision = @resource.value(:revision))
at_path do
branches.include?(revision)
end
end
def branches
at_path { git('branch', '-a') }.gsub('*', ' ').split(/\n/).map { |line| line.strip }
end
end

14
spec/fixtures/git_branch_a.txt vendored Normal file
View File

@ -0,0 +1,14 @@
feature/foo
feature/bar
feature/baz
feature/quux
only/local
* master
refactor/foo
origin/HEAD
origin/feature/foo
origin/feature/bar
origin/feature/baz
origin/feature/quux
origin/only/remote
origin/master

View File

@ -1,27 +1,34 @@
require 'pathname'; Pathname.new(__FILE__).realpath.ascend { |x| begin; require (x + 'spec_helper.rb'); break; rescue LoadError; end }
describe_provider :vcsrepo, :git, :resource => {:path => '/tmp/vcsrepo'} do
context 'creating' do
resource_with :source do
resource_with :ensure => :present do
resource_with :revision do
it "should execute 'git clone' and 'git reset --hard'" do
context "with a revision that is a remote branch", :resource => {:revision => 'only/remote'} do
it "should execute 'git clone' and 'git checkout -b'" do
provider.expects('git').with('clone', resource.value(:source), resource.value(:path))
expects_chdir
provider.expects('git').with('reset', '--hard', resource.value(:revision))
provider.expects(:git).with('submodule', 'init')
provider.expects(:git).with('submodule', 'update')
provider.expects(:remote_revision_branch?).returns(true)
provider.expects(:git).with('checkout', '-b', resource.value(:revision), '--track', "origin/#{resource.value(:revision)}")
provider.expects(:update_submodules)
provider.create
end
end
context "with a revision that is not a remote branch", :resource => {:revision => 'a-commit-or-tag'} do
it "should execute 'git clone' and 'git reset --hard'" do
provider.expects('git').with('clone', resource.value(:source), resource.value(:path))
expects_chdir
provider.expects(:remote_revision_branch?).returns(false)
provider.expects('git').with('reset', '--hard', resource.value(:revision))
provider.expects(:update_submodules)
provider.create
end
end
resource_without :revision do
it "should execute 'git clone' and submodule commands" do
provider.expects(:git).with('clone', resource.value(:source), resource.value(:path))
expects_chdir
provider.expects(:git).with('submodule', 'init')
provider.expects(:git).with('submodule', 'update')
provider.expects(:update_submodules)
provider.create
end
end
@ -137,14 +144,40 @@ describe_provider :vcsrepo, :git, :resource => {:path => '/tmp/vcsrepo'} do
end
context "setting the revision property" do
it "should use 'git fetch' and 'git reset'" do
before do
expects_chdir
provider.expects(:git).with('fetch', 'origin')
provider.expects(:git).with('reset', '--hard', 'carcar')
provider.expects(:git).with('submodule', 'init')
provider.expects(:git).with('submodule', 'update')
provider.revision = 'carcar'
end
context "when it's an existing local branch", :resource => {:revision => 'feature/foo'} do
it "should use 'git fetch' and 'git reset'" do
provider.expects(:local_revision_branch?).returns(true)
provider.expects(:git).with('checkout', resource.value(:revision))
provider.expects(:git).with('pull', 'origin')
provider.expects(:update_submodules)
provider.revision = resource.value(:revision)
end
end
context "when it's a remote branch", :resource => {:revision => 'only/remote'} do
it "should use 'git fetch' and 'git reset'" do
provider.expects(:local_revision_branch?).returns(false)
provider.expects(:remote_revision_branch?).returns(true)
provider.expects(:git).with('checkout',
'-b', resource.value(:revision),
'--track', "origin/#{resource.value(:revision)}")
provider.expects(:update_submodules)
provider.revision = resource.value(:revision)
end
end
context "when it's a commit or tag", :resource => {:revision => 'a-commit-or-tag'} do
it "should use 'git fetch' and 'git reset'" do
provider.expects(:local_revision_branch?).returns(false)
provider.expects(:remote_revision_branch?).returns(false)
provider.expects(:git).with('reset', '--hard', resource.value(:revision))
provider.expects(:git).with('submodule', 'init')
provider.expects(:git).with('submodule', 'update')
provider.revision = resource.value(:revision)
end
end
end
context "updating references" do
@ -154,5 +187,36 @@ describe_provider :vcsrepo, :git, :resource => {:path => '/tmp/vcsrepo'} do
provider.update_references
end
end
context "checking if revision" do
before do
expects_chdir
provider.expects(:git).with('branch', '-a').returns(fixture(:git_branch_a))
end
context "is a local branch" do
context "when it's listed in 'git branch -a'", :resource => {:revision => 'feature/foo'} do
it "should return true" do
provider.should be_local_branch_revision
end
end
context "when it's not listed in 'git branch -a'" , :resource => {:revision => 'feature/notexist'}do
it "should return false" do
provider.should_not be_local_branch_revision
end
end
end
context "is a remote branch" do
context "when it's listed in 'git branch -a' with an 'origin/' prefix", :resource => {:revision => 'only/remote'} do
it "should return true" do
provider.should be_remote_branch_revision
end
end
context "when it's not listed in 'git branch -a' with an 'origin/' prefix" , :resource => {:revision => 'only/local'}do
it "should return false" do
provider.should_not be_remote_branch_revision
end
end
end
end
end