From 8a58caef1fe6b2c301f321cd0d52e42cc58f5f6b Mon Sep 17 00:00:00 2001 From: Joshua Hoblitt Date: Tue, 16 Jul 2013 16:25:09 -0700 Subject: fix git provider checkout of a remote ref on an existing repo Per discussion of https://github.com/puppetlabs/puppetlabs-vcsrepo/issues/51 in the git channel on freenode, EugeneKay stated that `git rev-parse` is not capable of inspecting remote refs but that `git ls-remote` is. This patch makes a second attempt to resolve the ref with `ls-remote` if `rev-parse` fails. The git provider also appears to support several type features that are not tagged under `has_features`. It's not clear if this is the best way to resolve this issue or if the provider should be refactored to work with different type features. Demonstration of the problem with changing refs (branches and tags) $ git --version git version 1.7.1 $ cat master.pp branch.pp vcsrepo { '/tmp/vcsrepo': ensure => present, provider => git, source => 'https://github.com/puppetlabs/puppetlabs-vcsrepo.git', revision => 'master', } vcsrepo { '/tmp/vcsrepo': ensure => present, provider => git, source => 'https://github.com/puppetlabs/puppetlabs-vcsrepo.git', revision => 'feature/cvs', } $ puppet apply --modulepath=`pwd`/.. master.pp Notice: /Stage[main]//Vcsrepo[/tmp/vcsrepo]/ensure: Creating repository from present Notice: /Stage[main]//Vcsrepo[/tmp/vcsrepo]/ensure: created Notice: Finished catalog run in 2.19 seconds $ puppet apply --modulepath=`pwd`/.. branch.pp Error: /Stage[main]//Vcsrepo[/tmp/vcsrepo]: Could not evaluate: Execution of '/usr/bin/git rev-parse feature/cvs' returned 128: fatal: ambiguous argument 'feature/cvs': unknown revision or path not in the working tree. Use '--' to separate paths from revisions feature/cvs Notice: Finished catalog run in 1.69 seconds --- spec/unit/puppet/provider/vcsrepo/git_spec.rb | 30 ++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) (limited to 'spec') diff --git a/spec/unit/puppet/provider/vcsrepo/git_spec.rb b/spec/unit/puppet/provider/vcsrepo/git_spec.rb index cb6c0c6..e10fd1e 100644 --- a/spec/unit/puppet/provider/vcsrepo/git_spec.rb +++ b/spec/unit/puppet/provider/vcsrepo/git_spec.rb @@ -132,7 +132,7 @@ describe_provider :vcsrepo, :git, :resource => {:path => '/tmp/vcsrepo'} do provider.expects(:git).with('config', 'remote.origin.url').returns('') provider.expects(:git).with('fetch', 'origin') # FIXME provider.expects(:git).with('fetch', '--tags', 'origin') - provider.expects(:git).with('rev-parse', resource.value(:revision)).returns('currentsha') + provider.expects(:git).with('rev-parse', '--revs-only', resource.value(:revision)).returns('currentsha') provider.expects(:git).with('tag', '-l').returns("Hello") provider.revision.should == resource.value(:revision) end @@ -143,12 +143,36 @@ describe_provider :vcsrepo, :git, :resource => {:path => '/tmp/vcsrepo'} do provider.expects(:git).with('config', 'remote.origin.url').returns('') provider.expects(:git).with('fetch', 'origin') # FIXME provider.expects(:git).with('fetch', '--tags', 'origin') - provider.expects(:git).with('rev-parse', resource.value(:revision)).returns('othersha') + provider.expects(:git).with('rev-parse', '--revs-only', resource.value(:revision)).returns('othersha') provider.expects(:git).with('tag', '-l').returns("Hello") provider.revision.should == 'currentsha' end end + context "when its a ref to a remote head" do + it "should return the revision" do + provider.expects(:git).with('config', 'remote.origin.url').returns('') + provider.expects(:git).with('fetch', 'origin') # FIXME + provider.expects(:git).with('fetch', '--tags', 'origin') + provider.expects(:git).with('tag', '-l').returns("Hello") + provider.expects(:git).with('rev-parse', '--revs-only', resource.value(:revision)).returns('') + provider.expects(:git).with('ls-remote', '--heads', '--tags', 'origin', resource.value(:revision)).returns("newsha refs/heads/#{resource.value(:revision)}") + provider.revision.should == 'currentsha' + end + end + + context "when its a ref to non existant remote head" do + it "should fail" do + provider.expects(:git).with('config', 'remote.origin.url').returns('') + provider.expects(:git).with('fetch', 'origin') # FIXME + provider.expects(:git).with('fetch', '--tags', 'origin') + provider.expects(:git).with('tag', '-l').returns("Hello") + provider.expects(:git).with('rev-parse', '--revs-only', resource.value(:revision)).returns('') + provider.expects(:git).with('ls-remote', '--heads', '--tags', 'origin', resource.value(:revision)).returns('') + expect { provider.revision }.should raise_error(Puppet::Error, /not a local or remote ref$/) + end + end + context "when the source is modified" do resource_with :source => 'git://git@foo.com/bar.git' do it "should update the origin url" do @@ -156,7 +180,7 @@ describe_provider :vcsrepo, :git, :resource => {:path => '/tmp/vcsrepo'} do provider.expects(:git).with('config', 'remote.origin.url', 'git://git@foo.com/bar.git') provider.expects(:git).with('fetch', 'origin') # FIXME provider.expects(:git).with('fetch', '--tags', 'origin') - provider.expects(:git).with('rev-parse', resource.value(:revision)).returns('currentsha') + provider.expects(:git).with('rev-parse', '--revs-only', resource.value(:revision)).returns('currentsha') provider.expects(:git).with('tag', '-l').returns("Hello") provider.revision.should == resource.value(:revision) end -- cgit v1.2.3