diff options
author | Zeger-Jan van de Weg <zegerjan@gitlab.com> | 2018-07-16 14:46:17 +0300 |
---|---|---|
committer | Zeger-Jan van de Weg <zegerjan@gitlab.com> | 2018-07-16 14:46:17 +0300 |
commit | 39d80fd31bfd50a01cefba329d7ddf06432d9aa3 (patch) | |
tree | e9feee30c9df181bec41888bb5915d20806b89a1 | |
parent | a3f6b9aed853a1a9dd2038fbcd474b74644776eb (diff) | |
parent | 4efd6846bfdde9d0c610cf55ccdc0084b992a472 (diff) |
Merge branch 'vendor-gitlab-git-20180713-jv' into 'master'
Vendor gitlab_git at 16b867d8ce6246ad8
See merge request gitlab-org/gitaly!810
-rw-r--r-- | changelogs/unreleased/vendor-gitlab-git-20180713-jv.yml | 5 | ||||
-rw-r--r-- | ruby/lib/gitlab/git/repository.rb | 60 | ||||
-rw-r--r-- | ruby/vendor/gitlab_git/REVISION | 2 | ||||
-rw-r--r-- | ruby/vendor/gitlab_git/lib/gitlab/git/popen.rb | 18 | ||||
-rw-r--r-- | ruby/vendor/gitlab_git/lib/gitlab/git/repository.rb | 163 |
5 files changed, 102 insertions, 146 deletions
diff --git a/changelogs/unreleased/vendor-gitlab-git-20180713-jv.yml b/changelogs/unreleased/vendor-gitlab-git-20180713-jv.yml new file mode 100644 index 000000000..0bf9613d0 --- /dev/null +++ b/changelogs/unreleased/vendor-gitlab-git-20180713-jv.yml @@ -0,0 +1,5 @@ +--- +title: Vendor gitlab_git at 16b867d8ce6246ad8 +merge_request: 810 +author: +type: other diff --git a/ruby/lib/gitlab/git/repository.rb b/ruby/lib/gitlab/git/repository.rb index a8fc54b29..3f65fcad2 100644 --- a/ruby/lib/gitlab/git/repository.rb +++ b/ruby/lib/gitlab/git/repository.rb @@ -449,6 +449,52 @@ module Gitlab rugged_fetch_source_branch(source_repository, source_branch, local_ref) end + # Directly find a branch with a simple name (e.g. master) + # + # force_reload causes a new Rugged repository to be instantiated + # + # This is to work around a bug in libgit2 that causes in-memory refs to + # be stale/invalid when packed-refs is changed. + # See https://gitlab.com/gitlab-org/gitlab-ce/issues/15392#note_14538333 + def find_branch(name, force_reload = false) + reload_rugged if force_reload + + rugged_ref = rugged.branches[name] + 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 + + # Delete the specified branch from the repository + def delete_branch(branch_name) + rugged.branches.delete(branch_name) + rescue Rugged::ReferenceError => e + raise DeleteBranchError, e + end + + def delete_refs(*ref_names) + git_delete_refs(*ref_names) + end + + def delete_all_refs_except(prefixes) + delete_refs(*all_ref_names_except(prefixes)) + end + + # Returns true if the given branch exists + # + # name - The name of the branch as a String. + def branch_exists?(name) + rugged.branches.exists?(name) + + # If the branch name is invalid (e.g. ".foo") Rugged will raise an error. + # Whatever code calls this method shouldn't have to deal with that so + # instead we just return `false` (which is true since a branch doesn't + # exist when it has an invalid name). + rescue Rugged::ReferenceError + false + end + private def uncached_has_local_branches? @@ -533,6 +579,20 @@ module Gitlab def format_git_cat_file_script File.expand_path('../support/format-git-cat-file-input', __FILE__) end + + def git_delete_refs(*ref_names) + instructions = ref_names.map do |ref| + "delete #{ref}\x00\x00" + end + + message, status = run_git(%w[update-ref --stdin -z]) do |stdin| + stdin.write(instructions.join) + end + + unless status.zero? + raise GitError.new("Could not delete refs #{ref_names}: #{message}") + end + end end end end diff --git a/ruby/vendor/gitlab_git/REVISION b/ruby/vendor/gitlab_git/REVISION index a3e915a34..81e9ae533 100644 --- a/ruby/vendor/gitlab_git/REVISION +++ b/ruby/vendor/gitlab_git/REVISION @@ -1 +1 @@ -555afe8971c9ab6f907cfc248842e268109ce367 +16b867d8ce6246ad849642d9f3a5cc505b312a5a diff --git a/ruby/vendor/gitlab_git/lib/gitlab/git/popen.rb b/ruby/vendor/gitlab_git/lib/gitlab/git/popen.rb index f9f24ecc4..7426688fc 100644 --- a/ruby/vendor/gitlab_git/lib/gitlab/git/popen.rb +++ b/ruby/vendor/gitlab_git/lib/gitlab/git/popen.rb @@ -21,6 +21,10 @@ module Gitlab Open3.popen3(vars, *cmd, options) do |stdin, stdout, stderr, wait_thr| stdout.set_encoding(Encoding::ASCII_8BIT) + # stderr and stdout pipes can block if stderr/stdout aren't drained: https://bugs.ruby-lang.org/issues/9082 + # Mimic what Ruby does with capture3: https://github.com/ruby/ruby/blob/1ec544695fa02d714180ef9c34e755027b6a2103/lib/open3.rb#L257-L273 + err_reader = Thread.new { stderr.read } + yield(stdin) if block_given? stdin.close @@ -32,7 +36,7 @@ module Gitlab cmd_output << stdout.read end - cmd_output << stderr.read + cmd_output << err_reader.value cmd_status = wait_thr.value.exitstatus end @@ -55,16 +59,20 @@ module Gitlab rerr, werr = IO.pipe pid = Process.spawn(vars, *cmd, out: wout, err: werr, chdir: path, pgroup: true) + # stderr and stdout pipes can block if stderr/stdout aren't drained: https://bugs.ruby-lang.org/issues/9082 + # Mimic what Ruby does with capture3: https://github.com/ruby/ruby/blob/1ec544695fa02d714180ef9c34e755027b6a2103/lib/open3.rb#L257-L273 + out_reader = Thread.new { rout.read } + err_reader = Thread.new { rerr.read } begin - status = process_wait_with_timeout(pid, timeout) - # close write ends so we could read them wout.close werr.close - cmd_output = rout.readlines.join - cmd_output << rerr.readlines.join # Copying the behaviour of `popen` which merges stderr into output + status = process_wait_with_timeout(pid, timeout) + + cmd_output = out_reader.value + cmd_output << err_reader.value # Copying the behaviour of `popen` which merges stderr into output [cmd_output, status.exitstatus] rescue Timeout::Error => e diff --git a/ruby/vendor/gitlab_git/lib/gitlab/git/repository.rb b/ruby/vendor/gitlab_git/lib/gitlab/git/repository.rb index d50ac2707..fc4711751 100644 --- a/ruby/vendor/gitlab_git/lib/gitlab/git/repository.rb +++ b/ruby/vendor/gitlab_git/lib/gitlab/git/repository.rb @@ -167,24 +167,9 @@ module Gitlab # Directly find a branch with a simple name (e.g. master) # - # force_reload causes a new Rugged repository to be instantiated - # - # This is to work around a bug in libgit2 that causes in-memory refs to - # be stale/invalid when packed-refs is changed. - # See https://gitlab.com/gitlab-org/gitlab-ce/issues/15392#note_14538333 - def find_branch(name, force_reload = false) - gitaly_migrate(:find_branch) do |is_enabled| - if is_enabled - gitaly_ref_client.find_branch(name) - else - reload_rugged if force_reload - - rugged_ref = rugged.branches[name] - 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 find_branch(name) + wrapped_gitaly_errors do + gitaly_ref_client.find_branch(name) end end @@ -196,20 +181,8 @@ module Gitlab # Returns the number of valid branches def branch_count - gitaly_migrate(:branch_names) do |is_enabled| - if is_enabled - gitaly_ref_client.count_branch_names - else - rugged.branches.each(:local).count do |ref| - begin - ref.name && ref.target # ensures the branch is valid - - true - rescue Rugged::ReferenceError - false - end - end - end + wrapped_gitaly_errors do + gitaly_ref_client.count_branch_names end end @@ -232,12 +205,8 @@ module Gitlab # Returns the number of valid tags def tag_count - gitaly_migrate(:tag_names) do |is_enabled| - if is_enabled - gitaly_ref_client.count_tag_names - else - rugged.tags.count - end + wrapped_gitaly_errors do + gitaly_ref_client.count_tag_names end end @@ -260,13 +229,8 @@ module Gitlab # # Ref names must start with `refs/`. def ref_exists?(ref_name) - gitaly_migrate(:ref_exists, - status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) do |is_enabled| - if is_enabled - gitaly_ref_exists?(ref_name) - else - rugged_ref_exists?(ref_name) - end + wrapped_gitaly_errors do + gitaly_ref_exists?(ref_name) end end @@ -274,12 +238,8 @@ module Gitlab # # name - The name of the tag as a String. def tag_exists?(name) - gitaly_migrate(:ref_exists_tags, status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) do |is_enabled| - if is_enabled - gitaly_ref_exists?("refs/tags/#{name}") - else - rugged_tag_exists?(name) - end + wrapped_gitaly_errors do + gitaly_ref_exists?("refs/tags/#{name}") end end @@ -287,12 +247,8 @@ module Gitlab # # name - The name of the branch as a String. def branch_exists?(name) - gitaly_migrate(:ref_exists_branches, status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) do |is_enabled| - if is_enabled - gitaly_ref_exists?("refs/heads/#{name}") - else - rugged_branch_exists?(name) - end + wrapped_gitaly_errors do + gitaly_ref_exists?("refs/heads/#{name}") end end @@ -310,12 +266,8 @@ module Gitlab end def delete_all_refs_except(prefixes) - gitaly_migrate(:ref_delete_refs) do |is_enabled| - if is_enabled - gitaly_ref_client.delete_refs(except_with_prefixes: prefixes) - else - delete_refs(*all_ref_names_except(prefixes)) - end + wrapped_gitaly_errors do + gitaly_ref_client.delete_refs(except_with_prefixes: prefixes) end end @@ -714,25 +666,16 @@ module Gitlab # Delete the specified branch from the repository def delete_branch(branch_name) - gitaly_migrate(:delete_branch, status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) do |is_enabled| - if is_enabled - gitaly_ref_client.delete_branch(branch_name) - else - rugged.branches.delete(branch_name) - end + wrapped_gitaly_errors do + gitaly_ref_client.delete_branch(branch_name) end - rescue Rugged::ReferenceError, CommandError => e + rescue CommandError => e raise DeleteBranchError, e end def delete_refs(*ref_names) - gitaly_migrate(:delete_refs, - status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) do |is_enabled| - if is_enabled - gitaly_delete_refs(*ref_names) - else - git_delete_refs(*ref_names) - end + wrapped_gitaly_errors do + gitaly_delete_refs(*ref_names) end end @@ -742,12 +685,8 @@ module Gitlab # create_branch("feature") # create_branch("other-feature", "master") def create_branch(ref, start_point = "HEAD") - gitaly_migrate(:create_branch, status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) do |is_enabled| - if is_enabled - gitaly_ref_client.create_branch(ref, start_point) - else - rugged_create_branch(ref, start_point) - end + wrapped_gitaly_errors do + gitaly_ref_client.create_branch(ref, start_point) end end @@ -1175,7 +1114,7 @@ module Gitlab end def can_be_merged?(source_sha, target_branch) - if target_sha = find_branch(target_branch, true)&.target + if target_sha = find_branch(target_branch)&.target !gitaly_conflicts_client(source_sha, target_sha).conflicts? else false @@ -1549,52 +1488,10 @@ module Gitlab # Returns true if the given ref name exists # # Ref names must start with `refs/`. - def rugged_ref_exists?(ref_name) - raise ArgumentError, 'invalid refname' unless ref_name.start_with?('refs/') - - rugged.references.exist?(ref_name) - rescue Rugged::ReferenceError - false - end - - # Returns true if the given ref name exists - # - # Ref names must start with `refs/`. def gitaly_ref_exists?(ref_name) gitaly_ref_client.ref_exists?(ref_name) end - # Returns true if the given tag exists - # - # name - The name of the tag as a String. - def rugged_tag_exists?(name) - !!rugged.tags[name] - end - - # Returns true if the given branch exists - # - # name - The name of the branch as a String. - def rugged_branch_exists?(name) - rugged.branches.exists?(name) - - # If the branch name is invalid (e.g. ".foo") Rugged will raise an error. - # Whatever code calls this method shouldn't have to deal with that so - # instead we just return `false` (which is true since a branch doesn't - # exist when it has an invalid name). - rescue Rugged::ReferenceError - false - end - - def rugged_create_branch(ref, start_point) - rugged_ref = rugged.branches.create(ref, start_point) - 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 =~ %r{'refs/heads/#{ref}'} - - raise InvalidRef.new("Invalid reference #{start_point}") - end - def gitaly_copy_gitattributes(revision) gitaly_repository_client.apply_gitattributes(revision) end @@ -1687,20 +1584,6 @@ module Gitlab remote_update(remote_name, url: url) end - def git_delete_refs(*ref_names) - instructions = ref_names.map do |ref| - "delete #{ref}\x00\x00" - end - - message, status = run_git(%w[update-ref --stdin -z]) do |stdin| - stdin.write(instructions.join) - end - - unless status.zero? - raise GitError.new("Could not delete refs #{ref_names}: #{message}") - end - end - def gitaly_delete_refs(*ref_names) gitaly_ref_client.delete_refs(refs: ref_names) if ref_names.any? end |