Bring back Rugged implementation of TreeEntry
This brings back some of the changes in https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/20099/diffs For users using Gitaly on top of NFS, accessing the Git data directly via Rugged is more performant than Gitaly. This merge request introduces the feature flag `rugged_tree_entry` to activate the Rugged method. Part of four Rugged changes identified in https://gitlab.com/gitlab-org/gitlab-ce/issues/57317.
This commit is contained in:
parent
28883d8e44
commit
9d3e413aa7
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Bring back Rugged implementation of TreeEntry
|
||||
merge_request: 25706
|
||||
author:
|
||||
type: other
|
|
@ -23,6 +23,10 @@ module Gitlab
|
|||
|
||||
class << self
|
||||
def find(repository, sha, path, limit: MAX_DATA_DISPLAY_SIZE)
|
||||
tree_entry(repository, sha, path, limit)
|
||||
end
|
||||
|
||||
def tree_entry(repository, sha, path, limit)
|
||||
return unless path
|
||||
|
||||
path = path.sub(%r{\A/*}, '')
|
||||
|
@ -179,3 +183,5 @@ module Gitlab
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
Gitlab::Git::Blob.singleton_class.prepend Gitlab::Git::RuggedImpl::Blob::ClassMethods
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# NOTE: This code is legacy. Do not add/modify code here unless you have
|
||||
# discussed with the Gitaly team. See
|
||||
# https://docs.gitlab.com/ee/development/gitaly.html#legacy-rugged-code
|
||||
# for more details.
|
||||
|
||||
module Gitlab
|
||||
module Git
|
||||
module RuggedImpl
|
||||
module Blob
|
||||
module ClassMethods
|
||||
extend ::Gitlab::Utils::Override
|
||||
|
||||
override :tree_entry
|
||||
def tree_entry(repository, sha, path, limit)
|
||||
if Feature.enabled?(:rugged_tree_entry)
|
||||
rugged_tree_entry(repository, sha, path, limit)
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def rugged_tree_entry(repository, sha, path, limit)
|
||||
return unless path
|
||||
|
||||
# Strip any leading / characters from the path
|
||||
path = path.sub(%r{\A/*}, '')
|
||||
|
||||
rugged_commit = repository.lookup(sha)
|
||||
root_tree = rugged_commit.tree
|
||||
|
||||
blob_entry = find_entry_by_path(repository, root_tree.oid, *path.split('/'))
|
||||
|
||||
return nil unless blob_entry
|
||||
|
||||
if blob_entry[:type] == :commit
|
||||
submodule_blob(blob_entry, path, sha)
|
||||
else
|
||||
blob = repository.lookup(blob_entry[:oid])
|
||||
|
||||
if blob
|
||||
new(
|
||||
id: blob.oid,
|
||||
name: blob_entry[:name],
|
||||
size: blob.size,
|
||||
# Rugged::Blob#content is expensive; don't call it if we don't have to.
|
||||
data: limit.zero? ? '' : blob.content(limit),
|
||||
mode: blob_entry[:filemode].to_s(8),
|
||||
path: path,
|
||||
commit_id: sha,
|
||||
binary: blob.binary?
|
||||
)
|
||||
end
|
||||
end
|
||||
rescue Rugged::ReferenceError
|
||||
nil
|
||||
end
|
||||
|
||||
# Recursive search of blob id by path
|
||||
#
|
||||
# Ex.
|
||||
# blog/ # oid: 1a
|
||||
# app/ # oid: 2a
|
||||
# models/ # oid: 3a
|
||||
# file.rb # oid: 4a
|
||||
#
|
||||
#
|
||||
# Blob.find_entry_by_path(repo, '1a', 'blog', 'app', 'file.rb') # => '4a'
|
||||
#
|
||||
def find_entry_by_path(repository, root_id, *path_parts)
|
||||
root_tree = repository.lookup(root_id)
|
||||
|
||||
entry = root_tree.find do |entry|
|
||||
entry[:name] == path_parts[0]
|
||||
end
|
||||
|
||||
return nil unless entry
|
||||
|
||||
if path_parts.size > 1
|
||||
return nil unless entry[:type] == :tree
|
||||
|
||||
path_parts.shift
|
||||
find_entry_by_path(repository, entry[:oid], *path_parts)
|
||||
else
|
||||
[:blob, :commit].include?(entry[:type]) ? entry : nil
|
||||
end
|
||||
end
|
||||
|
||||
def submodule_blob(blob_entry, path, sha)
|
||||
new(
|
||||
id: blob_entry[:oid],
|
||||
name: blob_entry[:name],
|
||||
size: 0,
|
||||
data: '',
|
||||
path: path,
|
||||
commit_id: sha
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -18,7 +18,7 @@ describe Gitlab::Git::Blob, :seed_helper do
|
|||
end
|
||||
end
|
||||
|
||||
describe '.find' do
|
||||
shared_examples '.find' do
|
||||
context 'nil path' do
|
||||
let(:blob) { Gitlab::Git::Blob.find(repository, SeedRepo::Commit::ID, nil) }
|
||||
|
||||
|
@ -128,6 +128,20 @@ describe Gitlab::Git::Blob, :seed_helper do
|
|||
end
|
||||
end
|
||||
|
||||
describe '.find with Gitaly enabled' do
|
||||
it_behaves_like '.find'
|
||||
end
|
||||
|
||||
describe '.find with Rugged enabled', :enable_rugged do
|
||||
it 'calls out to the Rugged implementation' do
|
||||
allow_any_instance_of(Rugged).to receive(:rev_parse).with(SeedRepo::Commit::ID).and_call_original
|
||||
|
||||
described_class.find(repository, SeedRepo::Commit::ID, 'files/images/6049019_460s.jpg')
|
||||
end
|
||||
|
||||
it_behaves_like '.find'
|
||||
end
|
||||
|
||||
describe '.raw' do
|
||||
let(:raw_blob) { Gitlab::Git::Blob.raw(repository, SeedRepo::RubyBlob::ID) }
|
||||
let(:bad_blob) { Gitlab::Git::Blob.raw(repository, SeedRepo::BigCommit::ID) }
|
||||
|
|
Loading…
Reference in New Issue