From 8d9ff62229b4ade936255719635b5fa74a85958a Mon Sep 17 00:00:00 2001 From: Sean Reinhardt Date: Sun, 10 May 2020 14:09:07 -0700 Subject: [PATCH] [Git] update regex match for branch commit --- CHANGELOG.md | 4 ++- lib/cocoapods-downloader/git.rb | 23 ++++++++++++++-- spec/git_spec.rb | 47 +++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dce17fb..57ec7de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,9 @@ ##### Bug Fixes -* None. +* Improves handling of multiple results from `git ls-remote` by using branch name in commit regex match. + [Sean Reinhardt](https://github.com/seanreinhardtapps) + [#88](https://github.com/CocoaPods/cocoapods-downloader/issues/88) ## 1.3.0 (2019-11-14) diff --git a/lib/cocoapods-downloader/git.rb b/lib/cocoapods-downloader/git.rb index 497b0a3..e42de23 100644 --- a/lib/cocoapods-downloader/git.rb +++ b/lib/cocoapods-downloader/git.rb @@ -27,16 +27,35 @@ def self.preprocess_options(options) options[:git], options[:branch]] output = Git.execute_command('git', command) - match = /^([a-z0-9]*)\t.*/.match(output) + match = commit_from_ls_remote output, options[:branch] return options if match.nil? - options[:commit] = match[1] + options[:commit] = match options.delete(:branch) options end + # Matches a commit from the brances reported by git ls-remote. + # + # @note When there is a branch and tag with the same name, it will match + # the branch, since `refs/heads` is sorted before `refs/tags`. + # + # @param [String] output + # The output from git ls-remote. + # + # @param [String] branch_name + # The desired branch to match a commit to. + # + def self.commit_from_ls_remote(output, branch_name) + return nil if branch_name.nil? + match = %r{([a-z0-9]*)\trefs\/(heads|tags)\/#{Regexp.quote(branch_name)}}.match(output) + match[1] unless match.nil? + end + + private_class_method :commit_from_ls_remote + private # @!group Base class hooks diff --git a/spec/git_spec.rb b/spec/git_spec.rb index 8bab70f..d518f59 100644 --- a/spec/git_spec.rb +++ b/spec/git_spec.rb @@ -217,6 +217,53 @@ def ensure_only_one_ref(folder) end end + describe ':commit_from_ls_remote' do + it 'finds commit for a branch' do + test_commit = 'abcde' + test_branch = 'stable' + test_output = "#{test_commit}\trefs/heads/#{test_branch}" + result = Git.send(:commit_from_ls_remote, test_output, test_branch) + result.should == test_commit + end + it 'returns nil for no match' do + test_commit = 'abcde' + test_branch = 'stable' + test_output = "#{test_commit}\trefs/heads/other_branch" + result = Git.send(:commit_from_ls_remote, test_output, test_branch) + result.should.nil? + end + it 'can match a commit for a tag' do + test_commit = '12345' + test_branch = 'stable' + test_output = "#{test_commit}\trefs/tags/#{test_branch}" + result = Git.send(:commit_from_ls_remote, test_output, test_branch) + result.should == test_commit + end + it 'finds correct commit from multiple ls-remote branches' do + test_commit1 = 'abcde' + test_branch1 = 'stable' + test_commit2 = '12345' + test_branch2 = 'release/stable' + test_output = "#{test_commit1}\trefs/heads/#{test_branch1}\n#{test_commit2}\trefs/heads/#{test_branch2}" + result1 = Git.send(:commit_from_ls_remote, test_output, test_branch1) + result1.should == test_commit1 + result2 = Git.send(:commit_from_ls_remote, test_output, test_branch2) + result2.should == test_commit2 + end + it 'returns a branch over a tag' do + test_commit1 = 'abcde' + test_branch = 'stable' + test_commit2 = '12345' + test_output = "#{test_commit1}\trefs/heads/#{test_branch}\n#{test_commit2}\trefs/tags/#{test_branch}" + result = Git.send(:commit_from_ls_remote, test_output, test_branch) + result.should == test_commit1 + end + it 'handles nil inputs' do + Git.send(:commit_from_ls_remote, nil, 'test_branch').should.nil? + Git.send(:commit_from_ls_remote, "123\trefs/heads/abc", nil).should.nil? + end + end + describe '::preprocess_options' do it 'skips non-branch requests' do options = { :git => fixture_url('git-repo'), :commit => 'aaaa' }