Merge pull request #237 from cmurphy/rspec-puppet-2
[puppet_vcsrepo.git] / lib / puppet / provider / vcsrepo / git.rb
index 13e0793..8101253 100644 (file)
@@ -5,7 +5,7 @@ Puppet::Type.type(:vcsrepo).provide(:git, :parent => Puppet::Provider::Vcsrepo)
 
   commands :git => 'git'
 
-  has_features :bare_repositories, :reference_tracking, :ssh_identity, :multiple_remotes, :user, :depth, :submodules
+  has_features :bare_repositories, :reference_tracking, :ssh_identity, :multiple_remotes, :user, :depth, :branch, :submodules
 
   def create
     if @resource.value(:revision) and @resource.value(:ensure) == :bare
@@ -14,13 +14,16 @@ Puppet::Type.type(:vcsrepo).provide(:git, :parent => Puppet::Provider::Vcsrepo)
     if !@resource.value(:source)
       init_repository(@resource.value(:path))
     else
-      clone_repository(@resource.value(:source), @resource.value(:path))
+      clone_repository(default_url, @resource.value(:path))
+      update_remotes
+
       if @resource.value(:revision)
         checkout
       end
       if @resource.value(:ensure) != :bare && @resource.value(:submodules) == :true
         update_submodules
       end
+
     end
     update_owner_and_excludes
   end
@@ -82,9 +85,25 @@ Puppet::Type.type(:vcsrepo).provide(:git, :parent => Puppet::Provider::Vcsrepo)
     bare_git_config_exists? && !working_copy_exists?
   end
 
+  # If :source is set to a hash (for supporting multiple remotes),
+  # we search for the URL for :remote. If it doesn't exist,
+  # we throw an error. If :source is just a string, we use that
+  # value for the default URL.
+  def default_url
+    if @resource.value(:source).is_a?(Hash)
+      if @resource.value(:source).has_key?(@resource.value(:remote))
+        @resource.value(:source)[@resource.value(:remote)]
+      else
+        fail("You must specify the URL for #{@resource.value(:remote)} in the :source hash")
+      end
+    else
+      @resource.value(:source)
+    end
+  end
+
   def working_copy_exists?
     if @resource.value(:source) and File.exists?(File.join(@resource.value(:path), '.git', 'config'))
-      File.readlines(File.join(@resource.value(:path), '.git', 'config')).grep(/#{@resource.value(:source)}/).any?
+      File.readlines(File.join(@resource.value(:path), '.git', 'config')).grep(/#{default_url}/).any?
     else
       File.directory?(File.join(@resource.value(:path), '.git'))
     end
@@ -94,18 +113,54 @@ Puppet::Type.type(:vcsrepo).provide(:git, :parent => Puppet::Provider::Vcsrepo)
     working_copy_exists? || bare_exists?
   end
 
-  def update_remote_origin_url
-    current = git_with_identity('config', "remote.#{@resource.value(:remote)}.url")
-    unless @resource.value(:source).nil?
-      if current.nil? or current.strip != @resource.value(:source)
-        git_with_identity('config', "remote.#{@resource.value(:remote)}.url", @resource.value(:source))
+  def update_remote_url(remote_name, remote_url)
+    do_update = false
+    current = git_with_identity('config', '-l')
+
+    unless remote_url.nil?
+      # Check if remote exists at all, regardless of URL.
+      # If remote doesn't exist, add it
+      if not current.include? "remote.#{remote_name}.url"
+        git_with_identity('remote','add', remote_name, remote_url)
+        return true
+
+      # If remote exists, but URL doesn't match, update URL
+      elsif not current.include? "remote.#{remote_name}.url=#{remote_url}"
+        git_with_identity('remote','set-url', remote_name, remote_url)
+        return true
+      else
+        return false
+      end
+    end
+
+  end
+
+  def update_remotes
+    do_update = false
+
+    # If supplied source is a hash of remote name and remote url pairs, then
+    # we loop around the hash. Otherwise, we assume single url specified
+    # in source property
+    if @resource.value(:source).is_a?(Hash)
+      @resource.value(:source).keys.sort.each do |remote_name|
+        remote_url = @resource.value(:source)[remote_name]
+        at_path { do_update |= update_remote_url(remote_name, remote_url) }
       end
+    else
+      at_path { do_update |= update_remote_url(@resource.value(:remote), @resource.value(:source)) }
+    end
+
+    # If at least one remote was added or updated, then we must
+    # call the 'git remote update' command
+    if do_update == true
+      at_path { git_with_identity('remote','update') }
     end
+
   end
 
   def update_references
     at_path do
-      update_remote_origin_url
+      update_remotes
       git_with_identity('fetch', @resource.value(:remote))
       git_with_identity('fetch', '--tags', @resource.value(:remote))
       update_owner_and_excludes
@@ -126,6 +181,9 @@ Puppet::Type.type(:vcsrepo).provide(:git, :parent => Puppet::Provider::Vcsrepo)
     if @resource.value(:depth) and @resource.value(:depth).to_i > 0
       args.push('--depth', @resource.value(:depth).to_s)
     end
+    if @resource.value(:branch)
+      args.push('--branch', @resource.value(:branch).to_s)
+    end
     if @resource.value(:ensure) == :bare
       args << '--bare'
     end