summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-05-01 12:15:33 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2023-05-01 12:15:59 +0000
commit2b427d3361e2cfeedea1c81c9262e68512116625 (patch)
tree0803ea4075ba6fec686d3411d926fdc576c61009
parent5dbeb2d1625c3dcd46a67220ddce250d9bc3f7bd (diff)
downloadgitlab-ce-2b427d3361e2cfeedea1c81c9262e68512116625.tar.gz
Add latest changes from gitlab-org/security/gitlab@15-9-stable-ee
-rw-r--r--lib/gitlab/git/repository.rb26
-rw-r--r--spec/lib/gitlab/git/repository_spec.rb70
2 files changed, 94 insertions, 2 deletions
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
index e054b6df98f..e1399b6642b 100644
--- a/lib/gitlab/git/repository.rb
+++ b/lib/gitlab/git/repository.rb
@@ -262,7 +262,11 @@ module Gitlab
def archive_metadata(ref, storage_path, project_path, format = "tar.gz", append_sha:, path: nil)
ref ||= root_ref
- commit = Gitlab::Git::Commit.find(self, ref)
+
+ commit_id = extract_commit_id_from_ref(ref)
+ return {} if commit_id.nil?
+
+ commit = Gitlab::Git::Commit.find(self, commit_id)
return {} if commit.nil?
prefix = archive_prefix(ref, commit.id, project_path, append_sha: append_sha, path: path)
@@ -1233,6 +1237,26 @@ module Gitlab
def gitaly_delete_refs(*ref_names)
gitaly_ref_client.delete_refs(refs: ref_names) if ref_names.any?
end
+
+ # The order is based on git priority to resolve ambiguous references
+ #
+ # `git show <ref>`
+ #
+ # In case of name clashes, it uses this order:
+ # 1. Commit
+ # 2. Tag
+ # 3. Branch
+ def extract_commit_id_from_ref(ref)
+ return ref if Gitlab::Git.commit_id?(ref)
+
+ tag = find_tag(ref)
+ return tag.dereferenced_target.sha if tag
+
+ branch = find_branch(ref)
+ return branch.dereferenced_target.sha if branch
+
+ ref
+ end
end
end
end
diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb
index 72043ba2a21..a8423703716 100644
--- a/spec/lib/gitlab/git/repository_spec.rb
+++ b/spec/lib/gitlab/git/repository_spec.rb
@@ -116,7 +116,8 @@ RSpec.describe Gitlab::Git::Repository, feature_category: :source_code_managemen
let(:expected_extension) { 'tar.gz' }
let(:expected_filename) { "#{expected_prefix}.#{expected_extension}" }
let(:expected_path) { File.join(storage_path, cache_key, "@v2", expected_filename) }
- let(:expected_prefix) { "gitlab-git-test-#{ref}-#{TestEnv::BRANCH_SHA['master']}" }
+ let(:expected_prefix) { "gitlab-git-test-#{ref.tr('/', '-')}-#{expected_prefix_sha}" }
+ let(:expected_prefix_sha) { TestEnv::BRANCH_SHA['master'] }
subject(:metadata) { repository.archive_metadata(ref, storage_path, 'gitlab-git-test', format, append_sha: append_sha, path: path) }
@@ -173,6 +174,73 @@ RSpec.describe Gitlab::Git::Repository, feature_category: :source_code_managemen
it { expect(metadata['ArchivePath']).to eq(expected_path) }
end
end
+
+ context 'when references are ambiguous' do
+ let_it_be(:ambiguous_project) { create(:project, :repository) }
+ let_it_be(:repository) { ambiguous_project.repository.raw }
+ let_it_be(:branch_merged_commit_id) { ambiguous_project.repository.find_branch('branch-merged').dereferenced_target.id }
+ let_it_be(:branch_master_commit_id) { ambiguous_project.repository.find_branch('master').dereferenced_target.id }
+ let_it_be(:tag_1_0_0_commit_id) { ambiguous_project.repository.find_tag('v1.0.0').dereferenced_target.id }
+
+ context 'when tag is ambiguous' do
+ before do
+ ambiguous_project.repository.add_tag(user, ref, 'master', 'foo')
+ end
+
+ after do
+ ambiguous_project.repository.rm_tag(user, ref)
+ end
+
+ where(:ref, :expected_commit_id, :desc) do
+ 'refs/heads/branch-merged' | ref(:branch_master_commit_id) | 'when tag looks like a branch'
+ 'branch-merged' | ref(:branch_master_commit_id) | 'when tag has the same name as a branch'
+ ref(:branch_merged_commit_id) | ref(:branch_merged_commit_id) | 'when tag looks like a commit id'
+ 'v0.0.0' | ref(:branch_master_commit_id) | 'when tag looks like a normal tag'
+ end
+
+ with_them do
+ it 'selects the correct commit' do
+ expect(metadata['CommitId']).to eq(expected_commit_id)
+ end
+ end
+ end
+
+ context 'when branch is ambiguous' do
+ before do
+ ambiguous_project.repository.add_branch(user, ref, 'master')
+ end
+
+ where(:ref, :expected_commit_id, :desc) do
+ 'refs/tags/v1.0.0' | ref(:branch_master_commit_id) | 'when branch looks like a tag'
+ 'v1.0.0' | ref(:tag_1_0_0_commit_id) | 'when branch has the same name as a tag'
+ ref(:branch_merged_commit_id) | ref(:branch_merged_commit_id) | 'when branch looks like a commit id'
+ 'just-a-normal-branch' | ref(:branch_master_commit_id) | 'when branch looks like a normal branch'
+ end
+
+ with_them do
+ it 'selects the correct commit' do
+ expect(metadata['CommitId']).to eq(expected_commit_id)
+ end
+ end
+ end
+
+ context 'when ref is HEAD' do
+ let(:ref) { 'HEAD' }
+
+ it 'selects commit id from HEAD ref' do
+ expect(metadata['CommitId']).to eq(branch_master_commit_id)
+ expect(metadata['ArchivePrefix']).to eq(expected_prefix)
+ end
+ end
+
+ context 'when ref is not found' do
+ let(:ref) { 'unknown-ref-cannot-be-found' }
+
+ it 'returns empty metadata' do
+ expect(metadata).to eq({})
+ end
+ end
+ end
end
describe '#size' do