gitlab-org--gitlab-foss/lib/gitlab/git/rugged_impl/tree.rb
Stan Hu 291df05e43 Add Rugged calls to performance bar
This will help diagnose the source of excessive I/O from Rugged
calls. To implement this, we need to obtain the full list of arguments
sent to each request method.
2019-07-23 21:38:05 -07:00

112 lines
3.7 KiB
Ruby

# 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 Tree
module ClassMethods
extend ::Gitlab::Utils::Override
include Gitlab::Git::RuggedImpl::UseRugged
override :tree_entries
def tree_entries(repository, sha, path, recursive)
if use_rugged?(repository, :rugged_tree_entries)
execute_rugged_call(:tree_entries_with_flat_path_from_rugged, repository, sha, path, recursive)
else
super
end
end
def tree_entries_with_flat_path_from_rugged(repository, sha, path, recursive)
tree_entries_from_rugged(repository, sha, path, recursive).tap do |entries|
# This was an optimization to reduce N+1 queries for Gitaly
# (https://gitlab.com/gitlab-org/gitaly/issues/530). It
# used to be done lazily in the view via
# TreeHelper#flatten_tree, so it's possible there's a
# performance impact by loading this eagerly.
rugged_populate_flat_path(repository, sha, path, entries)
end
end
def tree_entries_from_rugged(repository, sha, path, recursive)
current_path_entries = get_tree_entries_from_rugged(repository, sha, path)
ordered_entries = []
current_path_entries.each do |entry|
ordered_entries << entry
if recursive && entry.dir?
ordered_entries.concat(tree_entries_from_rugged(repository, sha, entry.path, true))
end
end
ordered_entries
end
def rugged_populate_flat_path(repository, sha, path, entries)
entries.each do |entry|
entry.flat_path = entry.path
next unless entry.dir?
entry.flat_path =
if path
File.join(path, rugged_flatten_tree(repository, sha, entry, path))
else
rugged_flatten_tree(repository, sha, entry, path)
end
end
end
# Returns the relative path of the first subdir that doesn't have only one directory descendant
def rugged_flatten_tree(repository, sha, tree, root_path)
subtree = tree_entries_from_rugged(repository, sha, tree.path, false)
if subtree.count == 1 && subtree.first.dir?
File.join(tree.name, rugged_flatten_tree(repository, sha, subtree.first, root_path))
else
tree.name
end
end
def get_tree_entries_from_rugged(repository, sha, path)
commit = repository.lookup(sha)
root_tree = commit.tree
tree = if path
id = find_id_by_path(repository, root_tree.oid, path)
if id
repository.lookup(id)
else
[]
end
else
root_tree
end
tree.map do |entry|
current_path = path ? File.join(path, entry[:name]) : entry[:name]
new(
id: entry[:oid],
root_id: root_tree.oid,
name: entry[:name],
type: entry[:type],
mode: entry[:filemode].to_s(8),
path: current_path,
commit_id: sha
)
end
rescue Rugged::ReferenceError
[]
end
end
end
end
end
end