summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean McGivern <sean@gitlab.com>2019-03-07 15:57:06 +0000
committerSean McGivern <sean@gitlab.com>2019-03-07 15:57:06 +0000
commitb63efb09a5c864047924cd2d84527b47dd563d5f (patch)
tree410918e53075de56796cf2865ec936ce2abf7883
parent5e0beb39bb40f567ea2b13511076d70e847831b4 (diff)
parent8a68f912296983772a1034f60de7f763f167ccec (diff)
downloadgitlab-ce-b63efb09a5c864047924cd2d84527b47dd563d5f.tar.gz
Merge branch 'sh-rugged-get-tree-entry' into 'master'
Bring back Rugged implementation of TreeEntry See merge request gitlab-org/gitlab-ce!25706
-rw-r--r--changelogs/unreleased/sh-rugged-get-tree-entry.yml5
-rw-r--r--lib/gitlab/git/blob.rb6
-rw-r--r--lib/gitlab/git/rugged_impl/blob.rb106
-rw-r--r--spec/lib/gitlab/git/blob_spec.rb16
4 files changed, 132 insertions, 1 deletions
diff --git a/changelogs/unreleased/sh-rugged-get-tree-entry.yml b/changelogs/unreleased/sh-rugged-get-tree-entry.yml
new file mode 100644
index 00000000000..4d46b764022
--- /dev/null
+++ b/changelogs/unreleased/sh-rugged-get-tree-entry.yml
@@ -0,0 +1,5 @@
+---
+title: Bring back Rugged implementation of TreeEntry
+merge_request: 25706
+author:
+type: other
diff --git a/lib/gitlab/git/blob.rb b/lib/gitlab/git/blob.rb
index 259a2b7911a..10df4ed72d9 100644
--- a/lib/gitlab/git/blob.rb
+++ b/lib/gitlab/git/blob.rb
@@ -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
diff --git a/lib/gitlab/git/rugged_impl/blob.rb b/lib/gitlab/git/rugged_impl/blob.rb
new file mode 100644
index 00000000000..11ee4ebda4b
--- /dev/null
+++ b/lib/gitlab/git/rugged_impl/blob.rb
@@ -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 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 unless entry
+
+ if path_parts.size > 1
+ return 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
diff --git a/spec/lib/gitlab/git/blob_spec.rb b/spec/lib/gitlab/git/blob_spec.rb
index a1b5cea88c0..10bc82e24d1 100644
--- a/spec/lib/gitlab/git/blob_spec.rb
+++ b/spec/lib/gitlab/git/blob_spec.rb
@@ -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) }