diff --git a/lib/r10k/git/rugged/working_repository.rb b/lib/r10k/git/rugged/working_repository.rb index ed1d82e4a..7e6e01fe3 100644 --- a/lib/r10k/git/rugged/working_repository.rb +++ b/lib/r10k/git/rugged/working_repository.rb @@ -90,7 +90,7 @@ def fetch(remote_name = 'origin') proxy = R10K::Git.get_proxy_for_remote(remote) options = {:credentials => credentials, :proxy_url => proxy, :prune => true} - refspecs = ["+refs/heads/*:refs/remotes/#{remote_name}/*"] + refspecs = ["+refs/heads/*:refs/remotes/#{remote_name}/*", '+refs/tags/*:refs/tags/*'] results = nil @@ -136,6 +136,26 @@ def dirty?(exclude_spec=true) end end + def updatedtags? + with_repo do |repo| + localtags = repo.tags.each_name.to_a + + options = { :credentials => credentials } + remote = repo.remotes['origin'] + remotetags = [] + remote.ls(**options) do |hash| + if hash[:name].start_with?('refs/tags/') && !hash[:name].include?('^{}') + remotetags << hash[:name].split('/').last + end + end + + return false unless remotetags.sort != localtags.sort + + logger.debug(_("Found different tags in local and remote in %{file_path}" % {file_path: @path})) + return true + end + end + private def with_repo diff --git a/lib/r10k/git/shellgit/thin_repository.rb b/lib/r10k/git/shellgit/thin_repository.rb index e748e78f3..87b0b2ebd 100644 --- a/lib/r10k/git/shellgit/thin_repository.rb +++ b/lib/r10k/git/shellgit/thin_repository.rb @@ -31,7 +31,12 @@ def clone(remote, opts = {}) # Fetch refs from the backing bare Git repository. def fetch(remote = 'cache') - git ['fetch', remote, '--prune'], :path => @path.to_s + git ['fetch', remote, '--prune', '--tags', '--prune-tags'], :path => @path.to_s + end + + # Prune deleted branches + def prune + git ['fetch', '--prune'], :path => @path.to_s end # @return [String] The origin remote URL diff --git a/lib/r10k/git/shellgit/working_repository.rb b/lib/r10k/git/shellgit/working_repository.rb index e4ad915c5..026ca51e3 100644 --- a/lib/r10k/git/shellgit/working_repository.rb +++ b/lib/r10k/git/shellgit/working_repository.rb @@ -64,7 +64,7 @@ def fetch(remote_name='origin') proxy = R10K::Git.get_proxy_for_remote(remote) R10K::Git.with_proxy(proxy) do - git ['fetch', remote_name, '--prune'], :path => @path.to_s + git ['fetch', remote_name, '--prune', '--tags', '--prune-tags'], :path => @path.to_s end end @@ -109,4 +109,15 @@ def dirty?(exclude_spec=true) return false end end + + def updatedtags? + result = git(['ls-remote', '--tags', '--refs', 'origin'], :path => @path.to_s, :raise_on_fail => false) + remotetags = result.stdout.scan(/refs\/tags\/(\S+)$/).flatten + result = git(['tag'], :path => @path.to_s, :raise_on_fail => false) + localtags = result.stdout.scan(/(\S+)$/).flatten + return false unless remotetags.sort != localtags.sort + + logger.debug(_("Found different tags in local and remote in %{file_path}" % {file_path: @path})) + return true + end end diff --git a/lib/r10k/git/stateful_repository.rb b/lib/r10k/git/stateful_repository.rb index 7a2f76637..7108e482a 100644 --- a/lib/r10k/git/stateful_repository.rb +++ b/lib/r10k/git/stateful_repository.rb @@ -63,11 +63,16 @@ def sync(ref, force=true, exclude_spec=true) if force logger.warn(_("Overwriting local modifications to %{repo_path}") % {repo_path: @repo.path}) logger.debug(_("Updating %{repo_path} to %{ref}") % {repo_path: @repo.path, ref: ref }) + @repo.prune + @repo.fetch @repo.checkout(sha, {:force => force}) else logger.warn(_("Skipping %{repo_path} due to local modifications") % {repo_path: @repo.path}) updated = false end + when :updatedtags + logger.debug(_("Updating tags in %{repo_path}") % {repo_path: @repo.path}) + @repo.fetch else logger.debug(_("%{repo_path} is already at Git ref %{ref}") % {repo_path: @repo.path, ref: ref }) updated = false @@ -94,6 +99,8 @@ def status(ref, exclude_spec=true) :outdated elsif @cache.ref_type(ref) == :branch && !@cache.synced? :outdated + elsif @repo.updatedtags? + :updatedtags else :insync end diff --git a/spec/shared-examples/git/working_repository.rb b/spec/shared-examples/git/working_repository.rb index 00a55ff57..83253a996 100644 --- a/spec/shared-examples/git/working_repository.rb +++ b/spec/shared-examples/git/working_repository.rb @@ -206,4 +206,43 @@ end end end + + shared_examples "unequal tags" do + it "reports tags as unequal" do + expect(subject.logger).to receive(:debug).with(/found different tags in local and remote in/i) + expect(subject.updatedtags?).to be true + end + end + + describe "checking if tags are different" do + let(:tag_090) { subject.git_dir + 'refs' + 'tags' + '0.9.0' } + let(:packed_refs) { subject.git_dir + 'packed-refs' } + + before(:each) do + subject.clone(remote) + end + + context "with equal tags local and remote" do + it "reports tags as equal" do + expect(subject.updatedtags?).to be false + end + end + + context "with missing local tag" do + before do + tag_090.delete if tag_090.exist? + packed_refs.delete if packed_refs.exist? + end + + it_behaves_like "unequal tags" + end + + context "with additional local tag" do + before(:each) do + File.open(File.join(subject.git_dir, 'packed-refs'), 'a') { |f| f.write('157011a4eaa27f1202a9d94335ee4876b26d377e refs/tags/1.0.2') } + end + + it_behaves_like "unequal tags" + end + end end