Fix detached head state
authorTravis Fields <travis@puppetlabs.com>
Thu, 15 May 2014 23:47:24 +0000 (16:47 -0700)
committerTravis Fields <travis@puppetlabs.com>
Thu, 15 May 2014 23:47:24 +0000 (16:47 -0700)
lib/puppet/provider/vcsrepo/git.rb
spec/unit/puppet/provider/vcsrepo/git_spec.rb

index fafe4bf..b4bafbf 100644 (file)
@@ -79,12 +79,18 @@ Puppet::Type.type(:vcsrepo).provide(:git, :parent => Puppet::Provider::Vcsrepo)
 
   def revision=(desired)
     checkout(desired)
-    if local_branch_revision?(desired)
+    if local_branch_revision?
       # reset instead of pull to avoid merge conflicts. assuming remote is
       # authoritative.
       # might be worthwhile to have an allow_local_changes param to decide
       # whether to reset or pull when we're ensuring latest.
-      at_path { git_with_identity('reset', '--hard', "#{@resource.value(:remote)}/#{desired}") }
+      at_path {
+        git_with_identity('reset', '--hard', "#{@resource.value(:remote)}/#{@resource.value(:revision)}")
+        if detached?
+          git_with_identity('checkout', "#{@resource.value(:revision)}")
+          git_with_identity('pull')
+        end
+      }
     end
     if @resource.value(:ensure) != :bare
       update_submodules
@@ -259,7 +265,16 @@ Puppet::Type.type(:vcsrepo).provide(:git, :parent => Puppet::Provider::Vcsrepo)
   end
 
   def on_branch?
-    at_path { git_with_identity('rev-parse', '--abbrev-ref', 'HEAD').chomp }
+    at_path {
+      matches = git_with_identity('branch', '--list').match /\*\s+(.*)/
+      matches[1] unless matches[1].match /detached/
+    }
+  end
+
+  def detached?
+    at_path {
+      git_with_identity('branch', '--list').match /\*\s+\(detached from.*\)/
+    }
   end
 
   def tags
index ad6ed08..20aa084 100644 (file)
@@ -261,6 +261,7 @@ describe Puppet::Type.type(:vcsrepo).provider(:git_provider) do
       it "should use 'git fetch' and 'git reset'" do
         resource[:revision] = 'feature/foo'
         provider.expects(:update_submodules)
+        provider.expects(:git).with('branch','--list').returns("* master")
         provider.expects(:git).with('branch', '-a').returns(resource.value(:revision))
         provider.expects(:git).with('checkout', '--force', resource.value(:revision))
         provider.expects(:git).with('branch', '-a').returns(resource.value(:revision))
@@ -272,6 +273,7 @@ describe Puppet::Type.type(:vcsrepo).provider(:git_provider) do
       it "should use 'git fetch' and 'git reset'" do
         resource[:revision] = 'only/remote'
         provider.expects(:update_submodules)
+        provider.expects(:git).with('branch','--list').returns("* master")
         provider.expects(:git).with('branch', '-a').returns(resource.value(:revision))
         provider.expects(:git).with('checkout', '--force', resource.value(:revision))
         provider.expects(:git).with('branch', '-a').returns(resource.value(:revision))
@@ -341,7 +343,7 @@ describe Puppet::Type.type(:vcsrepo).provider(:git_provider) do
   context "retrieving the current revision" do
     before do
       expects_chdir
-      provider.expects(:git).with('rev-parse', '--abbrev-ref', 'HEAD').returns("foo\n")
+      provider.expects(:git).with('branch','--list').returns("* foo")
     end
 
     it "will strip trailing newlines" do
@@ -377,19 +379,20 @@ describe Puppet::Type.type(:vcsrepo).provider(:git_provider) do
     end
     context 'on master' do
       it do
-        provider.expects(:git).with('rev-parse', '--abbrev-ref', 'HEAD').returns(fixture(:git_branch_a))
+        provider.expects(:git).with('branch','--list').returns("* master")
         provider.latest.should == 'master'
       end
     end
     context 'no branch' do
       it do
-        provider.expects(:git).with('rev-parse', '--abbrev-ref', 'HEAD').returns(fixture(:git_branch_none))
+        provider.expects(:git).with('branch','--list').returns("* master")
+
         provider.latest.should == 'master'
       end
     end
     context 'feature/bar' do
       it do
-        provider.expects(:git).with('rev-parse', '--abbrev-ref', 'HEAD').returns(fixture(:git_branch_feature_bar))
+        provider.expects(:git).with('branch','--list').returns("* master")
         provider.latest.should == 'master'
       end
     end