summaryrefslogtreecommitdiff
path: root/lib/gitlab/git/repository.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gitlab/git/repository.rb')
-rw-r--r--lib/gitlab/git/repository.rb326
1 files changed, 129 insertions, 197 deletions
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
index e51966313d4..63eebadff2e 100644
--- a/lib/gitlab/git/repository.rb
+++ b/lib/gitlab/git/repository.rb
@@ -80,16 +80,10 @@ module Gitlab
end
# Returns an Array of Branches
- def branches(filter: nil, sort_by: nil)
- branches = rugged.branches.each(filter).map do |rugged_ref|
- begin
- Gitlab::Git::Branch.new(self, rugged_ref.name, rugged_ref.target)
- rescue Rugged::ReferenceError
- # Omit invalid branch
- end
- end.compact
-
- sort_branches(branches, sort_by)
+ #
+ # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/389
+ def branches(sort_by: nil)
+ branches_filter(sort_by: sort_by)
end
def reload_rugged
@@ -107,7 +101,10 @@ module Gitlab
reload_rugged if force_reload
rugged_ref = rugged.branches[name]
- Gitlab::Git::Branch.new(self, rugged_ref.name, rugged_ref.target) if rugged_ref
+ if rugged_ref
+ target_commit = Gitlab::Git::Commit.find(self, rugged_ref.target)
+ Gitlab::Git::Branch.new(self, rugged_ref.name, rugged_ref.target, target_commit)
+ end
end
def local_branches(sort_by: nil)
@@ -115,7 +112,7 @@ module Gitlab
if is_enabled
gitaly_ref_client.local_branches(sort_by: sort_by)
else
- branches(filter: :local, sort_by: sort_by)
+ branches_filter(filter: :local, sort_by: sort_by)
end
end
end
@@ -162,6 +159,8 @@ module Gitlab
end
# Returns an Array of Tags
+ #
+ # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/390
def tags
rugged.references.each("refs/tags/*").map do |ref|
message = nil
@@ -174,7 +173,8 @@ module Gitlab
end
end
- Gitlab::Git::Tag.new(self, ref.name, ref.target, message)
+ target_commit = Gitlab::Git::Commit.find(self, ref.target)
+ Gitlab::Git::Tag.new(self, ref.name, ref.target, target_commit, message)
end.sort_by(&:name)
end
@@ -204,13 +204,6 @@ module Gitlab
branch_names + tag_names
end
- # Deprecated. Will be removed in 5.2
- def heads
- rugged.references.each("refs/heads/*").map do |head|
- Gitlab::Git::Ref.new(self, head.name, head.target)
- end.sort_by(&:name)
- end
-
def has_commits?
!empty?
end
@@ -297,28 +290,6 @@ module Gitlab
(size.to_f / 1024).round(2)
end
- # Returns an array of BlobSnippets for files at the specified +ref+ that
- # contain the +query+ string.
- def search_files(query, ref = nil)
- greps = []
- ref ||= root_ref
-
- populated_index(ref).each do |entry|
- # Discard submodules
- next if submodule?(entry)
-
- blob = Gitlab::Git::Blob.raw(self, entry[:oid])
-
- # Skip binary files
- next if blob.data.encoding == Encoding::ASCII_8BIT
-
- blob.load_all_data!(self)
- greps += build_greps(blob.data, query, ref, entry[:path])
- end
-
- greps
- end
-
# Use the Rugged Walker API to build an array of commits.
#
# Usage.
@@ -331,85 +302,10 @@ module Gitlab
# )
#
def log(options)
- default_options = {
- limit: 10,
- offset: 0,
- path: nil,
- follow: false,
- skip_merges: false,
- disable_walk: false,
- after: nil,
- before: nil
- }
-
- options = default_options.merge(options)
- options[:limit] ||= 0
- options[:offset] ||= 0
- actual_ref = options[:ref] || root_ref
- begin
- sha = sha_from_ref(actual_ref)
- rescue Rugged::OdbError, Rugged::InvalidError, Rugged::ReferenceError
- # Return an empty array if the ref wasn't found
- return []
- end
-
- if log_using_shell?(options)
- log_by_shell(sha, options)
- else
- log_by_walk(sha, options)
- end
- end
-
- def log_using_shell?(options)
- options[:path].present? ||
- options[:disable_walk] ||
- options[:skip_merges] ||
- options[:after] ||
- options[:before]
- end
-
- def log_by_walk(sha, options)
- walk_options = {
- show: sha,
- sort: Rugged::SORT_NONE,
- limit: options[:limit],
- offset: options[:offset]
- }
- Rugged::Walker.walk(rugged, walk_options).to_a
- end
-
- def log_by_shell(sha, options)
- limit = options[:limit].to_i
- offset = options[:offset].to_i
- use_follow_flag = options[:follow] && options[:path].present?
-
- # We will perform the offset in Ruby because --follow doesn't play well with --skip.
- # See: https://gitlab.com/gitlab-org/gitlab-ce/issues/3574#note_3040520
- offset_in_ruby = use_follow_flag && options[:offset].present?
- limit += offset if offset_in_ruby
-
- cmd = %W[#{Gitlab.config.git.bin_path} --git-dir=#{path} log]
- cmd << "--max-count=#{limit}"
- cmd << '--format=%H'
- cmd << "--skip=#{offset}" unless offset_in_ruby
- cmd << '--follow' if use_follow_flag
- cmd << '--no-merges' if options[:skip_merges]
- cmd << "--after=#{options[:after].iso8601}" if options[:after]
- cmd << "--before=#{options[:before].iso8601}" if options[:before]
- cmd << sha
-
- # :path can be a string or an array of strings
- if options[:path].present?
- cmd << '--'
- cmd += Array(options[:path])
- end
-
- raw_output = IO.popen(cmd) { |io| io.read }
- lines = offset_in_ruby ? raw_output.lines.drop(offset) : raw_output.lines
-
- lines.map! { |c| Rugged::Commit.new(rugged, c.strip) }
+ raw_log(options).map { |c| Commit.decorate(c) }
end
+ # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/382
def count_commits(options)
cmd = %W[#{Gitlab.config.git.bin_path} --git-dir=#{path} rev-list]
cmd << "--after=#{options[:after].iso8601}" if options[:after]
@@ -454,7 +350,7 @@ module Gitlab
# Counts the amount of commits between `from` and `to`.
def count_commits_between(from, to)
- commits_between(from, to).size
+ Commit.between(self, from, to).size
end
# Returns the SHA of the most recent common ancestor of +from+ and +to+
@@ -553,6 +449,7 @@ module Gitlab
# @repository.submodule_url_for('master', 'rack')
# # => git@localhost:rack.git
#
+ # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/329
def submodule_url_for(ref, path)
Gitlab::GitalyClient.migrate(:submodule_url_for) do |is_enabled|
if is_enabled
@@ -567,6 +464,8 @@ module Gitlab
end
# Return total commits count accessible from passed ref
+ #
+ # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/330
def commit_count(ref)
gitaly_migrate(:commit_count) do |is_enabled|
if is_enabled
@@ -779,7 +678,8 @@ module Gitlab
# create_branch("other-feature", "master")
def create_branch(ref, start_point = "HEAD")
rugged_ref = rugged.branches.create(ref, start_point)
- Gitlab::Git::Branch.new(self, rugged_ref.name, rugged_ref.target)
+ target_commit = Gitlab::Git::Commit.find(self, rugged_ref.target)
+ Gitlab::Git::Branch.new(self, rugged_ref.name, rugged_ref.target, target_commit)
rescue Rugged::ReferenceError => e
raise InvalidRef.new("Branch #{ref} already exists") if e.to_s =~ /'refs\/heads\/#{ref}'/
raise InvalidRef.new("Invalid reference #{start_point}")
@@ -838,6 +738,7 @@ module Gitlab
# Ex.
# repo.ls_files('master')
#
+ # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/327
def ls_files(ref)
actual_ref = ref || root_ref
@@ -864,6 +765,7 @@ module Gitlab
raw_output.compact
end
+ # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/328
def copy_gitattributes(ref)
begin
commit = lookup(ref)
@@ -905,8 +807,113 @@ module Gitlab
Gitlab::GitalyClient::Util.repository(@storage, @relative_path)
end
+ def gitaly_ref_client
+ @gitaly_ref_client ||= Gitlab::GitalyClient::RefService.new(self)
+ end
+
+ def gitaly_commit_client
+ @gitaly_commit_client ||= Gitlab::GitalyClient::CommitService.new(self)
+ end
+
private
+ # Gitaly note: JV: Trying to get rid of the 'filter' option so we can implement this with 'git'.
+ def branches_filter(filter: nil, sort_by: nil)
+ branches = rugged.branches.each(filter).map do |rugged_ref|
+ begin
+ target_commit = Gitlab::Git::Commit.find(self, rugged_ref.target)
+ Gitlab::Git::Branch.new(self, rugged_ref.name, rugged_ref.target, target_commit)
+ rescue Rugged::ReferenceError
+ # Omit invalid branch
+ end
+ end.compact
+
+ sort_branches(branches, sort_by)
+ end
+
+ def raw_log(options)
+ default_options = {
+ limit: 10,
+ offset: 0,
+ path: nil,
+ follow: false,
+ skip_merges: false,
+ disable_walk: false,
+ after: nil,
+ before: nil
+ }
+
+ options = default_options.merge(options)
+ options[:limit] ||= 0
+ options[:offset] ||= 0
+ actual_ref = options[:ref] || root_ref
+ begin
+ sha = sha_from_ref(actual_ref)
+ rescue Rugged::OdbError, Rugged::InvalidError, Rugged::ReferenceError
+ # Return an empty array if the ref wasn't found
+ return []
+ end
+
+ if log_using_shell?(options)
+ log_by_shell(sha, options)
+ else
+ log_by_walk(sha, options)
+ end
+ end
+
+ def log_using_shell?(options)
+ options[:path].present? ||
+ options[:disable_walk] ||
+ options[:skip_merges] ||
+ options[:after] ||
+ options[:before]
+ end
+
+ def log_by_walk(sha, options)
+ walk_options = {
+ show: sha,
+ sort: Rugged::SORT_NONE,
+ limit: options[:limit],
+ offset: options[:offset]
+ }
+ Rugged::Walker.walk(rugged, walk_options).to_a
+ end
+
+ # Gitaly note: JV: although #log_by_shell shells out to Git I think the
+ # complexity is such that we should migrate it as Ruby before trying to
+ # do it in Go.
+ def log_by_shell(sha, options)
+ limit = options[:limit].to_i
+ offset = options[:offset].to_i
+ use_follow_flag = options[:follow] && options[:path].present?
+
+ # We will perform the offset in Ruby because --follow doesn't play well with --skip.
+ # See: https://gitlab.com/gitlab-org/gitlab-ce/issues/3574#note_3040520
+ offset_in_ruby = use_follow_flag && options[:offset].present?
+ limit += offset if offset_in_ruby
+
+ cmd = %W[#{Gitlab.config.git.bin_path} --git-dir=#{path} log]
+ cmd << "--max-count=#{limit}"
+ cmd << '--format=%H'
+ cmd << "--skip=#{offset}" unless offset_in_ruby
+ cmd << '--follow' if use_follow_flag
+ cmd << '--no-merges' if options[:skip_merges]
+ cmd << "--after=#{options[:after].iso8601}" if options[:after]
+ cmd << "--before=#{options[:before].iso8601}" if options[:before]
+ cmd << sha
+
+ # :path can be a string or an array of strings
+ if options[:path].present?
+ cmd << '--'
+ cmd += Array(options[:path])
+ end
+
+ raw_output = IO.popen(cmd) { |io| io.read }
+ lines = offset_in_ruby ? raw_output.lines.drop(offset) : raw_output.lines
+
+ lines.map! { |c| Rugged::Commit.new(rugged, c.strip) }
+ end
+
# We are trying to deprecate this method because it does a lot of work
# but it seems to be used only to look up submodule URL's.
# https://gitlab.com/gitlab-org/gitaly/issues/329
@@ -930,7 +937,7 @@ module Gitlab
return unless commit_object && commit_object.type == :COMMIT
- gitmodules = gitaly_commit_client.tree_entry(ref, '.gitmodules', Blob::MAX_DATA_DISPLAY_SIZE)
+ gitmodules = gitaly_commit_client.tree_entry(ref, '.gitmodules', Gitlab::Git::Blob::MAX_DATA_DISPLAY_SIZE)
found_module = GitmodulesParser.new(gitmodules.data).parse[path]
found_module && found_module['url']
@@ -1078,73 +1085,6 @@ module Gitlab
index
end
- # Return an array of BlobSnippets for lines in +file_contents+ that match
- # +query+
- def build_greps(file_contents, query, ref, filename)
- # The file_contents string is potentially huge so we make sure to loop
- # through it one line at a time. This gives Ruby the chance to GC lines
- # we are not interested in.
- #
- # We need to do a little extra work because we are not looking for just
- # the lines that matches the query, but also for the context
- # (surrounding lines). We will use Enumerable#each_cons to efficiently
- # loop through the lines while keeping surrounding lines on hand.
- #
- # First, we turn "foo\nbar\nbaz" into
- # [
- # [nil, -3], [nil, -2], [nil, -1],
- # ['foo', 0], ['bar', 1], ['baz', 3],
- # [nil, 4], [nil, 5], [nil, 6]
- # ]
- lines_with_index = Enumerator.new do |yielder|
- # Yield fake 'before' lines for the first line of file_contents
- (-SEARCH_CONTEXT_LINES..-1).each do |i|
- yielder.yield [nil, i]
- end
-
- # Yield the actual file contents
- count = 0
- file_contents.each_line do |line|
- line.chomp!
- yielder.yield [line, count]
- count += 1
- end
-
- # Yield fake 'after' lines for the last line of file_contents
- (count + 1..count + SEARCH_CONTEXT_LINES).each do |i|
- yielder.yield [nil, i]
- end
- end
-
- greps = []
-
- # Loop through consecutive blocks of lines with indexes
- lines_with_index.each_cons(2 * SEARCH_CONTEXT_LINES + 1) do |line_block|
- # Get the 'middle' line and index from the block
- line, _ = line_block[SEARCH_CONTEXT_LINES]
-
- next unless line && line.match(/#{Regexp.escape(query)}/i)
-
- # Yay, 'line' contains a match!
- # Get an array with just the context lines (no indexes)
- match_with_context = line_block.map(&:first)
- # Remove 'nil' lines in case we are close to the first or last line
- match_with_context.compact!
-
- # Get the line number (1-indexed) of the first context line
- first_context_line_number = line_block[0][1] + 1
-
- greps << Gitlab::Git::BlobSnippet.new(
- ref,
- match_with_context,
- first_context_line_number,
- filename
- )
- end
-
- greps
- end
-
# Return the Rugged patches for the diff between +from+ and +to+.
def diff_patches(from, to, options = {}, *paths)
options ||= {}
@@ -1173,14 +1113,6 @@ module Gitlab
end
end
- def gitaly_ref_client
- @gitaly_ref_client ||= Gitlab::GitalyClient::Ref.new(self)
- end
-
- def gitaly_commit_client
- @gitaly_commit_client ||= Gitlab::GitalyClient::Commit.new(self)
- end
-
def gitaly_migrate(method, &block)
Gitlab::GitalyClient.migrate(method, &block)
rescue GRPC::NotFound => e