summaryrefslogtreecommitdiff
path: root/lib/gitlab/git
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gitlab/git')
-rw-r--r--lib/gitlab/git/blob.rb6
-rw-r--r--lib/gitlab/git/commit.rb20
-rw-r--r--lib/gitlab/git/hook.rb22
-rw-r--r--lib/gitlab/git/lfs_changes.rb3
-rw-r--r--lib/gitlab/git/lfs_pointer_file.rb25
-rw-r--r--lib/gitlab/git/popen.rb2
-rw-r--r--lib/gitlab/git/repository.rb80
-rw-r--r--lib/gitlab/git/rev_list.rb63
-rw-r--r--lib/gitlab/git/wiki.rb26
9 files changed, 139 insertions, 108 deletions
diff --git a/lib/gitlab/git/blob.rb b/lib/gitlab/git/blob.rb
index 4828301dbb9..b2fca2c16de 100644
--- a/lib/gitlab/git/blob.rb
+++ b/lib/gitlab/git/blob.rb
@@ -53,11 +53,7 @@ module Gitlab
def batch(repository, blob_references, blob_size_limit: MAX_DATA_DISPLAY_SIZE)
Gitlab::GitalyClient.migrate(:list_blobs_by_sha_path) do |is_enabled|
if is_enabled
- Gitlab::GitalyClient.allow_n_plus_1_calls do
- blob_references.map do |sha, path|
- find_by_gitaly(repository, sha, path, limit: blob_size_limit)
- end
- end
+ repository.gitaly_blob_client.get_blobs(blob_references, blob_size_limit).to_a
else
blob_references.map do |sha, path|
find_by_rugged(repository, sha, path, limit: blob_size_limit)
diff --git a/lib/gitlab/git/commit.rb b/lib/gitlab/git/commit.rb
index 768617e2cae..d95561fe1b2 100644
--- a/lib/gitlab/git/commit.rb
+++ b/lib/gitlab/git/commit.rb
@@ -402,15 +402,6 @@ module Gitlab
end
end
- # Get a collection of Rugged::Reference objects for this commit.
- #
- # Ex.
- # commit.ref(repo)
- #
- def refs(repo)
- repo.refs_hash[id]
- end
-
# Get ref names collection
#
# Ex.
@@ -418,7 +409,7 @@ module Gitlab
#
def ref_names(repo)
refs(repo).map do |ref|
- ref.name.sub(%r{^refs/(heads|remotes|tags)/}, "")
+ ref.sub(%r{^refs/(heads|remotes|tags)/}, "")
end
end
@@ -553,6 +544,15 @@ module Gitlab
date: Google::Protobuf::Timestamp.new(seconds: author_or_committer[:time].to_i)
)
end
+
+ # Get a collection of Gitlab::Git::Ref objects for this commit.
+ #
+ # Ex.
+ # commit.ref(repo)
+ #
+ def refs(repo)
+ repo.refs_hash[id]
+ end
end
end
end
diff --git a/lib/gitlab/git/hook.rb b/lib/gitlab/git/hook.rb
index e29a1f7afa1..24f027d8da4 100644
--- a/lib/gitlab/git/hook.rb
+++ b/lib/gitlab/git/hook.rb
@@ -82,14 +82,20 @@ module Gitlab
end
def call_update_hook(gl_id, gl_username, oldrev, newrev, ref)
- Dir.chdir(repo_path) do
- env = {
- 'GL_ID' => gl_id,
- 'GL_USERNAME' => gl_username
- }
- stdout, stderr, status = Open3.capture3(env, path, ref, oldrev, newrev)
- [status.success?, (stderr.presence || stdout).gsub(/\R/, "<br>").html_safe]
- end
+ env = {
+ 'GL_ID' => gl_id,
+ 'GL_USERNAME' => gl_username,
+ 'PWD' => repo_path
+ }
+
+ options = {
+ chdir: repo_path
+ }
+
+ args = [ref, oldrev, newrev]
+
+ stdout, stderr, status = Open3.capture3(env, path, *args, options)
+ [status.success?, (stderr.presence || stdout).gsub(/\R/, "<br>").html_safe]
end
def retrieve_error_message(stderr, stdout)
diff --git a/lib/gitlab/git/lfs_changes.rb b/lib/gitlab/git/lfs_changes.rb
index 732dd5d998a..48434047fce 100644
--- a/lib/gitlab/git/lfs_changes.rb
+++ b/lib/gitlab/git/lfs_changes.rb
@@ -25,8 +25,7 @@ module Gitlab
private
def rev_list
- ::Gitlab::Git::RevList.new(path_to_repo: @repository.path_to_repo,
- newrev: @newrev)
+ Gitlab::Git::RevList.new(@repository, newrev: @newrev)
end
end
end
diff --git a/lib/gitlab/git/lfs_pointer_file.rb b/lib/gitlab/git/lfs_pointer_file.rb
new file mode 100644
index 00000000000..da12ed7d125
--- /dev/null
+++ b/lib/gitlab/git/lfs_pointer_file.rb
@@ -0,0 +1,25 @@
+module Gitlab
+ module Git
+ class LfsPointerFile
+ def initialize(data)
+ @data = data
+ end
+
+ def pointer
+ @pointer ||= <<~FILE
+ version https://git-lfs.github.com/spec/v1
+ oid sha256:#{sha256}
+ size #{size}
+ FILE
+ end
+
+ def size
+ @size ||= @data.bytesize
+ end
+
+ def sha256
+ @sha256 ||= Digest::SHA256.hexdigest(@data)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/git/popen.rb b/lib/gitlab/git/popen.rb
index e0bd2bbe47b..c1767046ff0 100644
--- a/lib/gitlab/git/popen.rb
+++ b/lib/gitlab/git/popen.rb
@@ -25,7 +25,7 @@ module Gitlab
stdin.close
if lazy_block
- return lazy_block.call(stdout.lazy)
+ return [lazy_block.call(stdout.lazy), 0]
else
cmd_output << stdout.read
end
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
index ab1362a3bb0..5f014e43c6f 100644
--- a/lib/gitlab/git/repository.rb
+++ b/lib/gitlab/git/repository.rb
@@ -128,6 +128,10 @@ module Gitlab
raise NoRepository.new('no repository for such path')
end
+ def cleanup
+ @rugged&.close
+ end
+
def circuit_breaker
@circuit_breaker ||= Gitlab::Git::Storage::CircuitBreaker.for_storage(storage)
end
@@ -627,21 +631,18 @@ module Gitlab
end
end
- # Get refs hash which key is SHA1
- # and value is a Rugged::Reference
+ # Get refs hash which key is is the commit id
+ # and value is a Gitlab::Git::Tag or Gitlab::Git::Branch
+ # Note that both inherit from Gitlab::Git::Ref
def refs_hash
- # Initialize only when first call
- if @refs_hash.nil?
- @refs_hash = Hash.new { |h, k| h[k] = [] }
-
- rugged.references.each do |r|
- # Symbolic/remote references may not have an OID; skip over them
- target_oid = r.target.try(:oid)
- if target_oid
- sha = rev_parse_target(target_oid).oid
- @refs_hash[sha] << r
- end
- end
+ return @refs_hash if @refs_hash
+
+ @refs_hash = Hash.new { |h, k| h[k] = [] }
+
+ (tags + branches).each do |ref|
+ next unless ref.target && ref.name
+
+ @refs_hash[ref.dereferenced_target.id] << ref.name
end
@refs_hash
@@ -1427,6 +1428,26 @@ module Gitlab
end
end
+ def rev_list(including: [], excluding: [], objects: false, &block)
+ args = ['rev-list']
+
+ args.push(*rev_list_param(including))
+
+ exclude_param = *rev_list_param(excluding)
+ if exclude_param.any?
+ args.push('--not')
+ args.push(*exclude_param)
+ end
+
+ args.push('--objects') if objects
+
+ run_git!(args, lazy_block: block)
+ end
+
+ def missed_ref(oldrev, newrev)
+ run_git!(['rev-list', '--max-count=1', oldrev, "^#{newrev}"])
+ end
+
private
def local_write_ref(ref_path, ref, old_ref: nil, shell: true)
@@ -1475,7 +1496,7 @@ module Gitlab
Rails.logger.error "Unable to create #{ref_path} reference for repository #{path}: #{ex}"
end
- def run_git(args, chdir: path, env: {}, nice: false, &block)
+ def run_git(args, chdir: path, env: {}, nice: false, lazy_block: nil, &block)
cmd = [Gitlab.config.git.bin_path, *args]
cmd.unshift("nice") if nice
@@ -1485,12 +1506,12 @@ module Gitlab
end
circuit_breaker.perform do
- popen(cmd, chdir, env, &block)
+ popen(cmd, chdir, env, lazy_block: lazy_block, &block)
end
end
- def run_git!(args, chdir: path, env: {}, nice: false, &block)
- output, status = run_git(args, chdir: chdir, env: env, nice: nice, &block)
+ def run_git!(args, chdir: path, env: {}, nice: false, lazy_block: nil, &block)
+ output, status = run_git(args, chdir: chdir, env: env, nice: nice, lazy_block: lazy_block, &block)
raise GitError, output unless status.zero?
@@ -1593,17 +1614,14 @@ module Gitlab
# 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)
- # n+1: https://gitlab.com/gitlab-org/gitlab-ce/issues/37464
- branches = Gitlab::GitalyClient.allow_n_plus_1_calls do
- 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
- end
+ 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
@@ -2372,6 +2390,10 @@ module Gitlab
rescue Rugged::ReferenceError
0
end
+
+ def rev_list_param(spec)
+ spec == :all ? ['--all'] : spec
+ end
end
end
end
diff --git a/lib/gitlab/git/rev_list.rb b/lib/gitlab/git/rev_list.rb
index f8b2e7e0e21..38c3a55f96f 100644
--- a/lib/gitlab/git/rev_list.rb
+++ b/lib/gitlab/git/rev_list.rb
@@ -5,17 +5,17 @@ module Gitlab
class RevList
include Gitlab::Git::Popen
- attr_reader :oldrev, :newrev, :path_to_repo
+ attr_reader :oldrev, :newrev, :repository
- def initialize(path_to_repo:, newrev:, oldrev: nil)
+ def initialize(repository, newrev:, oldrev: nil)
@oldrev = oldrev
@newrev = newrev
- @path_to_repo = path_to_repo
+ @repository = repository
end
# This method returns an array of new commit references
def new_refs
- execute([*base_args, newrev, '--not', '--all'])
+ repository.rev_list(including: newrev, excluding: :all).split("\n")
end
# Finds newly added objects
@@ -28,66 +28,39 @@ module Gitlab
# When given a block it will yield objects as a lazy enumerator so
# the caller can limit work done instead of processing megabytes of data
def new_objects(require_path: nil, not_in: nil, &lazy_block)
- args = [*base_args, newrev, *not_in_refs(not_in), '--objects']
+ opts = {
+ including: newrev,
+ excluding: not_in.nil? ? :all : not_in,
+ require_path: require_path
+ }
- get_objects(args, require_path: require_path, &lazy_block)
+ get_objects(opts, &lazy_block)
end
def all_objects(require_path: nil, &lazy_block)
- args = [*base_args, '--all', '--objects']
-
- get_objects(args, require_path: require_path, &lazy_block)
+ get_objects(including: :all, require_path: require_path, &lazy_block)
end
# This methods returns an array of missed references
#
# Should become obsolete after https://gitlab.com/gitlab-org/gitaly/issues/348.
def missed_ref
- execute([*base_args, '--max-count=1', oldrev, "^#{newrev}"])
+ repository.missed_ref(oldrev, newrev).split("\n")
end
private
- def not_in_refs(references)
- return ['--not', '--all'] unless references
- return [] if references.empty?
-
- references.prepend('--not')
- end
-
def execute(args)
- output, status = popen(args, nil, Gitlab::Git::Env.to_env_hash)
-
- unless status.zero?
- raise "Got a non-zero exit code while calling out `#{args.join(' ')}`: #{output}"
- end
-
- output.split("\n")
- end
-
- def lazy_execute(args, &lazy_block)
- popen(args, nil, Gitlab::Git::Env.to_env_hash, lazy_block: lazy_block)
- end
-
- def base_args
- [
- Gitlab.config.git.bin_path,
- "--git-dir=#{path_to_repo}",
- 'rev-list'
- ]
+ repository.rev_list(args).split("\n")
end
- def get_objects(args, require_path: nil)
- if block_given?
- lazy_execute(args) do |lazy_output|
- objects = objects_from_output(lazy_output, require_path: require_path)
+ def get_objects(including: [], excluding: [], require_path: nil)
+ opts = { including: including, excluding: excluding, objects: true }
- yield(objects)
- end
- else
- object_output = execute(args)
+ repository.rev_list(opts) do |lazy_output|
+ objects = objects_from_output(lazy_output, require_path: require_path)
- objects_from_output(object_output, require_path: require_path)
+ yield(objects)
end
end
diff --git a/lib/gitlab/git/wiki.rb b/lib/gitlab/git/wiki.rb
index daa17fc72cf..ac12271a87e 100644
--- a/lib/gitlab/git/wiki.rb
+++ b/lib/gitlab/git/wiki.rb
@@ -25,9 +25,8 @@ module Gitlab
@repository.exists?
end
- # Disabled because of https://gitlab.com/gitlab-org/gitaly/merge_requests/539
def write_page(name, format, content, commit_details)
- @repository.gitaly_migrate(:wiki_write_page, status: Gitlab::GitalyClient::MigrationStatus::DISABLED) do |is_enabled|
+ @repository.gitaly_migrate(:wiki_write_page) do |is_enabled|
if is_enabled
gitaly_write_page(name, format, content, commit_details)
gollum_wiki.clear_cache
@@ -48,9 +47,8 @@ module Gitlab
end
end
- # Disable because of https://gitlab.com/gitlab-org/gitlab-ce/issues/42094
def update_page(page_path, title, format, content, commit_details)
- @repository.gitaly_migrate(:wiki_update_page, status: Gitlab::GitalyClient::MigrationStatus::DISABLED) do |is_enabled|
+ @repository.gitaly_migrate(:wiki_update_page) do |is_enabled|
if is_enabled
gitaly_update_page(page_path, title, format, content, commit_details)
gollum_wiki.clear_cache
@@ -96,11 +94,23 @@ module Gitlab
# :per_page - The number of items per page.
# :limit - Total number of items to return.
def page_versions(page_path, options = {})
- current_page = gollum_page_by_path(page_path)
+ @repository.gitaly_migrate(:wiki_page_versions) do |is_enabled|
+ if is_enabled
+ versions = gitaly_wiki_client.page_versions(page_path, options)
+
+ # Gitaly uses gollum-lib to get the versions. Gollum defaults to 20
+ # per page, but also fetches 20 if `limit` or `per_page` < 20.
+ # Slicing returns an array with the expected number of items.
+ slice_bound = options[:limit] || options[:per_page] || Gollum::Page.per_page
+ versions[0..slice_bound]
+ else
+ current_page = gollum_page_by_path(page_path)
- commits_from_page(current_page, options).map do |gitlab_git_commit|
- gollum_page = gollum_wiki.page(current_page.title, gitlab_git_commit.id)
- Gitlab::Git::WikiPageVersion.new(gitlab_git_commit, gollum_page&.format)
+ commits_from_page(current_page, options).map do |gitlab_git_commit|
+ gollum_page = gollum_wiki.page(current_page.title, gitlab_git_commit.id)
+ Gitlab::Git::WikiPageVersion.new(gitlab_git_commit, gollum_page&.format)
+ end
+ end
end
end