summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--changelogs/unreleased/sh-rugged-commit-is-ancestor.yml5
-rw-r--r--lib/gitlab/git/repository.rb2
-rw-r--r--lib/gitlab/git/rugged_impl/repository.rb27
-rw-r--r--spec/models/repository_spec.rb16
4 files changed, 47 insertions, 3 deletions
diff --git a/changelogs/unreleased/sh-rugged-commit-is-ancestor.yml b/changelogs/unreleased/sh-rugged-commit-is-ancestor.yml
new file mode 100644
index 00000000000..0f62176b4a5
--- /dev/null
+++ b/changelogs/unreleased/sh-rugged-commit-is-ancestor.yml
@@ -0,0 +1,5 @@
+---
+title: Bring back Rugged implementation of CommitIsAncestor
+merge_request: 25702
+author:
+type: other
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
index b6c7a12de35..20bfcde39bd 100644
--- a/lib/gitlab/git/repository.rb
+++ b/lib/gitlab/git/repository.rb
@@ -9,7 +9,7 @@ module Gitlab
include Gitlab::Git::WrapsGitalyErrors
include Gitlab::EncodingHelper
include Gitlab::Utils::StrongMemoize
- include Gitlab::Git::RuggedImpl::Repository
+ prepend Gitlab::Git::RuggedImpl::Repository
SEARCH_CONTEXT_LINES = 3
REV_LIST_COMMIT_LIMIT = 2_000
diff --git a/lib/gitlab/git/rugged_impl/repository.rb b/lib/gitlab/git/rugged_impl/repository.rb
index 135c47017b3..d4500573235 100644
--- a/lib/gitlab/git/rugged_impl/repository.rb
+++ b/lib/gitlab/git/rugged_impl/repository.rb
@@ -10,7 +10,9 @@ module Gitlab
module Git
module RuggedImpl
module Repository
- FEATURE_FLAGS = %i(rugged_find_commit).freeze
+ extend ::Gitlab::Utils::Override
+
+ FEATURE_FLAGS = %i(rugged_find_commit rugged_tree_entries rugged_tree_entry rugged_commit_is_ancestor).freeze
def alternate_object_directories
relative_object_directories.map { |d| File.join(path, d) }
@@ -41,6 +43,29 @@ module Gitlab
obj = rugged.rev_parse(revspec)
Ref.dereference_object(obj)
end
+
+ override :ancestor?
+ def ancestor?(from, to)
+ if Feature.enabled?(:rugged_commit_is_ancestor)
+ rugged_is_ancestor?(from, to)
+ else
+ super
+ end
+ end
+
+ def rugged_is_ancestor?(ancestor_id, descendant_id)
+ return false if ancestor_id.nil? || descendant_id.nil?
+
+ rugged_merge_base(ancestor_id, descendant_id) == ancestor_id
+ rescue Rugged::OdbError
+ false
+ end
+
+ def rugged_merge_base(from, to)
+ rugged.merge_base(from, to)
+ rescue Rugged::ReferenceError
+ nil
+ end
end
end
end
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index fbf8f330d6d..b138201f2a8 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -2247,7 +2247,7 @@ describe Repository do
rugged.references.create("refs/remotes/#{remote_name}/#{branch_name}", target.id)
end
- describe '#ancestor?' do
+ shared_examples '#ancestor?' do
let(:commit) { repository.commit }
let(:ancestor) { commit.parents.first }
@@ -2281,6 +2281,20 @@ describe Repository do
end
end
+ describe '#ancestor? with Gitaly enabled' do
+ it_behaves_like "#ancestor?"
+ end
+
+ describe '#ancestor? with Rugged enabled', :enable_rugged do
+ it 'calls out to the Rugged implementation' do
+ allow_any_instance_of(Rugged).to receive(:merge_base).with(repository.commit.id, Gitlab::Git::BLANK_SHA).and_call_original
+
+ repository.ancestor?(repository.commit.id, Gitlab::Git::BLANK_SHA)
+ end
+
+ it_behaves_like '#ancestor?'
+ end
+
describe '#archive_metadata' do
let(:ref) { 'master' }
let(:storage_path) { '/tmp' }