Skip to content

fetch tags to local, if different to remote #1371

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion lib/r10k/git/rugged/working_repository.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand Down
7 changes: 6 additions & 1 deletion lib/r10k/git/shellgit/thin_repository.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
13 changes: 12 additions & 1 deletion lib/r10k/git/shellgit/working_repository.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
7 changes: 7 additions & 0 deletions lib/r10k/git/stateful_repository.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
39 changes: 39 additions & 0 deletions spec/shared-examples/git/working_repository.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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