Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitaly.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Steinhardt <psteinhardt@gitlab.com>2022-11-02 16:01:28 +0300
committerPatrick Steinhardt <psteinhardt@gitlab.com>2022-11-02 16:01:28 +0300
commit04667f8e0c885d87da491e179cd0283bc3b966c9 (patch)
tree24cd9fdb3ea804f9c64f955ee37efecb2436d378
parentbd8c3c94e2d9eb61ffedd91ea34902a9e89e9448 (diff)
parent0d2baa826945678103c49f76645e276e3cd1633b (diff)
Merge branch 'qmnguyen0711/remove-rugged-in-gitaly' into 'master'
Remove rugged wrappers in Gitaly See merge request https://gitlab.com/gitlab-org/gitaly/-/merge_requests/4992 Merged-by: Patrick Steinhardt <psteinhardt@gitlab.com> Approved-by: Patrick Steinhardt <psteinhardt@gitlab.com> Approved-by: Toon Claes <toon@gitlab.com> Co-authored-by: Quang-Minh Nguyen <qmnguyen@gitlab.com>
-rw-r--r--internal/gitaly/rubyserver/rubyserver.go48
-rw-r--r--ruby/.rubocop_todo.yml7
-rw-r--r--ruby/Gemfile7
-rw-r--r--ruby/Gemfile.lock4
-rwxr-xr-xruby/bin/gitaly-ruby2
-rw-r--r--ruby/lib/gitaly_server.rb39
-rw-r--r--ruby/lib/gitaly_server/client.rb28
-rw-r--r--ruby/lib/gitaly_server/feature_flags.rb59
-rw-r--r--ruby/lib/gitaly_server/repository_service.rb6
-rw-r--r--ruby/lib/gitaly_server/rugged_interceptor.rb27
-rw-r--r--ruby/lib/gitlab/encoding_helper.rb98
-rw-r--r--ruby/lib/gitlab/git.rb99
-rw-r--r--ruby/lib/gitlab/git/branch.rb11
-rw-r--r--ruby/lib/gitlab/git/commit.rb250
-rw-r--r--ruby/lib/gitlab/git/hook.rb141
-rw-r--r--ruby/lib/gitlab/git/hooks_service.rb40
-rw-r--r--ruby/lib/gitlab/git/operation_service.rb121
-rw-r--r--ruby/lib/gitlab/git/popen.rb51
-rw-r--r--ruby/lib/gitlab/git/push_options.rb27
-rw-r--r--ruby/lib/gitlab/git/ref.rb53
-rw-r--r--ruby/lib/gitlab/git/repository.rb282
-rw-r--r--ruby/lib/gitlab/git/tag.rb49
-rw-r--r--ruby/lib/gitlab/git/user.rb36
-rw-r--r--ruby/lib/gitlab/git_logger.rb7
-rw-r--r--ruby/lib/gitlab/rails_logger.rb10
-rw-r--r--ruby/lib/gitlab/utils/strong_memoize.rb41
-rw-r--r--ruby/spec/factories/gitaly/commit_author.rb9
-rw-r--r--ruby/spec/factories/sequences.rb4
-rw-r--r--ruby/spec/lib/gitaly_server/feature_flags_spec.rb49
-rw-r--r--ruby/spec/lib/gitaly_server/rugged_interceptor_spec.rb38
-rw-r--r--ruby/spec/lib/gitlab/git/branch_spec.rb19
-rw-r--r--ruby/spec/lib/gitlab/git/commit_spec.rb207
-rw-r--r--ruby/spec/lib/gitlab/git/hook_spec.rb144
-rw-r--r--ruby/spec/lib/gitlab/git/popen_spec.rb108
-rw-r--r--ruby/spec/lib/gitlab/git/push_options_spec.rb32
-rw-r--r--ruby/spec/lib/gitlab/git/repository_spec.rb249
-rw-r--r--ruby/spec/lib/gitlab/git/user_spec.rb47
-rw-r--r--ruby/spec/spec_helper.rb1
-rw-r--r--ruby/spec/test_repo_helper.rb60
39 files changed, 16 insertions, 2494 deletions
diff --git a/internal/gitaly/rubyserver/rubyserver.go b/internal/gitaly/rubyserver/rubyserver.go
index 551bf784b..7e661954a 100644
--- a/internal/gitaly/rubyserver/rubyserver.go
+++ b/internal/gitaly/rubyserver/rubyserver.go
@@ -208,38 +208,6 @@ func (s *Server) start() error {
return nil
}
-// CommitServiceClient returns a CommitServiceClient instance that is
-// configured to connect to the running Ruby server. This assumes Start()
-// has been called already.
-func (s *Server) CommitServiceClient(ctx context.Context) (gitalypb.CommitServiceClient, error) {
- conn, err := s.getConnection(ctx)
- return gitalypb.NewCommitServiceClient(conn), err
-}
-
-// DiffServiceClient returns a DiffServiceClient instance that is
-// configured to connect to the running Ruby server. This assumes Start()
-// has been called already.
-func (s *Server) DiffServiceClient(ctx context.Context) (gitalypb.DiffServiceClient, error) {
- conn, err := s.getConnection(ctx)
- return gitalypb.NewDiffServiceClient(conn), err
-}
-
-// RefServiceClient returns a RefServiceClient instance that is
-// configured to connect to the running Ruby server. This assumes Start()
-// has been called already.
-func (s *Server) RefServiceClient(ctx context.Context) (gitalypb.RefServiceClient, error) {
- conn, err := s.getConnection(ctx)
- return gitalypb.NewRefServiceClient(conn), err
-}
-
-// OperationServiceClient returns a OperationServiceClient instance that is
-// configured to connect to the running Ruby server. This assumes Start()
-// has been called already.
-func (s *Server) OperationServiceClient(ctx context.Context) (gitalypb.OperationServiceClient, error) {
- conn, err := s.getConnection(ctx)
- return gitalypb.NewOperationServiceClient(conn), err
-}
-
// RepositoryServiceClient returns a RefServiceClient instance that is
// configured to connect to the running Ruby server. This assumes Start()
// has been called already.
@@ -248,22 +216,6 @@ func (s *Server) RepositoryServiceClient(ctx context.Context) (gitalypb.Reposito
return gitalypb.NewRepositoryServiceClient(conn), err
}
-// RemoteServiceClient returns a RemoteServiceClient instance that is
-// configured to connect to the running Ruby server. This assumes Start()
-// has been called already.
-func (s *Server) RemoteServiceClient(ctx context.Context) (gitalypb.RemoteServiceClient, error) {
- conn, err := s.getConnection(ctx)
- return gitalypb.NewRemoteServiceClient(conn), err
-}
-
-// BlobServiceClient returns a BlobServiceClient instance that is
-// configured to connect to the running Ruby server. This assumes Start()
-// has been called already.
-func (s *Server) BlobServiceClient(ctx context.Context) (gitalypb.BlobServiceClient, error) {
- conn, err := s.getConnection(ctx)
- return gitalypb.NewBlobServiceClient(conn), err
-}
-
func (s *Server) getConnection(ctx context.Context) (*grpc.ClientConn, error) {
s.clientConnMu.Lock()
conn := s.clientConn
diff --git a/ruby/.rubocop_todo.yml b/ruby/.rubocop_todo.yml
index 87453d9e6..b0e943dcb 100644
--- a/ruby/.rubocop_todo.yml
+++ b/ruby/.rubocop_todo.yml
@@ -219,13 +219,6 @@ Style/RaiseArgs:
- 'lib/gitlab/git/operation_service.rb'
- 'lib/gitlab/git/remote_repository.rb'
-# Offense count: 5
-# Cop supports --auto-correct.
-Style/RedundantSelf:
- Exclude:
- - 'lib/gitlab/git.rb'
- - 'lib/gitlab/git/blob.rb'
-
# Offense count: 14
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
diff --git a/ruby/Gemfile b/ruby/Gemfile
index 91c724113..89bafb90f 100644
--- a/ruby/Gemfile
+++ b/ruby/Gemfile
@@ -4,10 +4,8 @@ gem 'rugged', '~> 1.2'
gem 'github-linguist', '~> 7.20.0', require: 'linguist'
gem 'gitlab-markup', '~> 1.7.1'
gem 'activesupport', '~> 6.1.6.1'
-gem 'rdoc', '~> 6.0'
gem 'grpc', '~> 1.42.0' # keep in lock-step with grpc-tools
gem 'sentry-raven', '~> 3.0', require: false
-gem 'faraday', '~> 1.0'
gem 'rbtrace', require: false
# The Gitaly Gem contains the Protobuf and gRPC definitions required by the
@@ -23,11 +21,6 @@ gem 'licensee', '~> 9.15'
gem 'google-protobuf', '~> 3.21.9'
-# Rails is currently blocked on the upgrade to the new major version for Redis,
-# so we don't upgrade either until the issue is resolved. This is an indirect
-# dependency and can thus be removed when the version constraint is gone.
-gem 'redis', '~> 4.7.1'
-
group :development, :test do
gem 'rubocop', '~> 0.69', require: false
gem 'rspec', require: false
diff --git a/ruby/Gemfile.lock b/ruby/Gemfile.lock
index ccd124f08..9c80b436f 100644
--- a/ruby/Gemfile.lock
+++ b/ruby/Gemfile.lock
@@ -134,7 +134,6 @@ GEM
ffi (>= 1.0.6)
msgpack (>= 0.4.3)
optimist (>= 3.0.0)
- rdoc (6.3.2)
redis (4.7.1)
regexp_parser (1.8.1)
reverse_markdown (1.4.0)
@@ -205,7 +204,6 @@ PLATFORMS
DEPENDENCIES
activesupport (~> 6.1.6.1)
factory_bot
- faraday (~> 1.0)
gitaly (~> 15.5.0)
github-linguist (~> 7.20.0)
gitlab-labkit (~> 0.28)
@@ -216,8 +214,6 @@ DEPENDENCIES
licensee (~> 9.15)
pry (~> 0.12.2)
rbtrace
- rdoc (~> 6.0)
- redis (~> 4.7.1)
rspec
rspec-parameterized
rubocop (~> 0.69)
diff --git a/ruby/bin/gitaly-ruby b/ruby/bin/gitaly-ruby
index 5b5f537a6..11cfa231b 100755
--- a/ruby/bin/gitaly-ruby
+++ b/ruby/bin/gitaly-ruby
@@ -20,7 +20,6 @@ require 'rugged'
require_relative '../lib/gitaly_server.rb'
require_relative '../lib/gitaly_server/sentry_interceptor.rb'
require_relative '../lib/gitaly_server/exception_sanitizer_interceptor.rb'
-require_relative '../lib/gitaly_server/rugged_interceptor.rb'
SHUTDOWN_TIMEOUT = 600
@@ -132,7 +131,6 @@ def build_server_interceptor_chain
chain << GitalyServer::SentryInterceptor.new
chain << Labkit::Tracing::GRPC::ServerInterceptor.new if Labkit::Tracing.enabled?
chain << GitalyServer::ExceptionSanitizerInterceptor.new
- chain << GitalyServer::RuggedInterceptor.new
chain
end
diff --git a/ruby/lib/gitaly_server.rb b/ruby/lib/gitaly_server.rb
index dcd54dfd8..17f303ac0 100644
--- a/ruby/lib/gitaly_server.rb
+++ b/ruby/lib/gitaly_server.rb
@@ -1,45 +1,32 @@
$:.unshift(File.expand_path('../proto', __dir__))
require 'gitaly'
-require_relative 'gitlab/git.rb'
+require 'linguist/blob_helper'
+require 'securerandom'
+require 'gitlab-labkit'
+require 'rugged'
+
+require 'active_support/core_ext/object/blank'
+require 'active_support/core_ext/numeric/bytes'
+require 'active_support/core_ext/numeric/time'
+require 'active_support/core_ext/integer/time'
+require 'active_support/core_ext/module/delegation'
+require 'active_support/core_ext/enumerable'
+
+require_relative './gitlab/config.rb'
-require_relative 'gitaly_server/client.rb'
require_relative 'gitaly_server/utils.rb'
require_relative 'gitaly_server/repository_service.rb'
require_relative 'gitaly_server/health_service.rb'
-require_relative 'gitaly_server/feature_flags.rb'
module GitalyServer
- STORAGE_PATH_HEADER = 'gitaly-storage-path'.freeze
REPO_PATH_HEADER = 'gitaly-repo-path'.freeze
- GL_REPOSITORY_HEADER = 'gitaly-gl-repository'.freeze
- REPO_ALT_DIRS_HEADER = 'gitaly-repo-alt-dirs'.freeze
GITALY_SERVERS_HEADER = 'gitaly-servers'.freeze
- def self.storage_path(call)
- call.metadata.fetch(STORAGE_PATH_HEADER)
- end
-
def self.repo_path(call)
call.metadata.fetch(REPO_PATH_HEADER)
end
- def self.gl_repository(call)
- call.metadata.fetch(GL_REPOSITORY_HEADER)
- end
-
- def self.repo_alt_dirs(call)
- call.metadata.fetch(REPO_ALT_DIRS_HEADER)
- end
-
- def self.feature_flags(call)
- FeatureFlags.new(call.metadata)
- end
-
- def self.client(call)
- Client.new(call.metadata[GITALY_SERVERS_HEADER])
- end
-
def self.register_handlers(server)
server.handle(RepositoryService.new)
server.handle(HealthService.new)
diff --git a/ruby/lib/gitaly_server/client.rb b/ruby/lib/gitaly_server/client.rb
deleted file mode 100644
index 49fab89ce..000000000
--- a/ruby/lib/gitaly_server/client.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-require 'base64'
-require 'json'
-
-module GitalyServer
- class Client
- ServerLookupError = Class.new(StandardError)
-
- def initialize(encoded_servers)
- @servers = encoded_servers.present? ? JSON.parse(Base64.strict_decode64(encoded_servers)) : {}
- end
-
- def shared_secret(storage)
- server(storage)['token']
- end
-
- def address(storage)
- server(storage)['address']
- end
-
- private
-
- def server(storage)
- raise ServerLookupError.new("cannot find gitaly address for storage #{storage.inspect}") unless @servers.has_key?(storage)
-
- @servers[storage]
- end
- end
-end
diff --git a/ruby/lib/gitaly_server/feature_flags.rb b/ruby/lib/gitaly_server/feature_flags.rb
deleted file mode 100644
index da6718a84..000000000
--- a/ruby/lib/gitaly_server/feature_flags.rb
+++ /dev/null
@@ -1,59 +0,0 @@
-# frozen_string_literal: true
-
-module GitalyServer
- # Interface to Ruby-specific feature flags passed to the Gitaly Ruby server
- # via headers.
- class FeatureFlags
- # Only headers prefixed with this String will be made available
- HEADER_PREFIX = 'gitaly-feature-ruby-'
-
- def initialize(metadata)
- @flags = metadata.select do |key, _|
- key.start_with?(HEADER_PREFIX)
- end
- end
-
- # Check if a given flag is enabled
- #
- # The `gitaly-feature-ruby-` prefix is optional, and underscores are
- # translated to hyphens automatically.
- #
- # Examples
- #
- # enabled?('gitaly-feature-ruby-my-flag')
- # => true
- #
- # enabled?(:my_flag)
- # => true
- #
- # enabled?('my-flag')
- # => true
- #
- # enabled?(:unknown_flag)
- # => false
- def enabled?(flag, on_by_default: false)
- flag = normalize_flag(flag)
-
- @flags.fetch(flag, on_by_default.to_s) == 'true'
- end
-
- def disabled?(flag, on_by_default: false)
- !enabled?(flag, on_by_default: on_by_default)
- end
-
- def inspect
- pairs = @flags.map { |name, value| "#{name}=#{value}" }
- pairs.unshift(self.class.name)
-
- "#<#{pairs.join(' ')}>"
- end
-
- private
-
- def normalize_flag(flag)
- flag = flag.to_s.delete_prefix(HEADER_PREFIX).tr('_', '-')
-
- "#{HEADER_PREFIX}#{flag}"
- end
- end
-end
diff --git a/ruby/lib/gitaly_server/repository_service.rb b/ruby/lib/gitaly_server/repository_service.rb
index 98cb8b748..9cb39fd5d 100644
--- a/ruby/lib/gitaly_server/repository_service.rb
+++ b/ruby/lib/gitaly_server/repository_service.rb
@@ -4,11 +4,11 @@ module GitalyServer
class RepositoryService < Gitaly::RepositoryService::Service
include Utils
- def find_license(request, call)
- repo = Gitlab::Git::Repository.from_gitaly(request.repository, call)
+ def find_license(_request, call)
+ path = GitalyServer.repo_path(call)
begin
- project = ::Licensee.project(repo.path)
+ project = ::Licensee.project(path)
return Gitaly::FindLicenseResponse.new(license_short_name: "") unless project&.license
license = project.license
diff --git a/ruby/lib/gitaly_server/rugged_interceptor.rb b/ruby/lib/gitaly_server/rugged_interceptor.rb
deleted file mode 100644
index 72af71f11..000000000
--- a/ruby/lib/gitaly_server/rugged_interceptor.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-require 'grpc'
-
-module GitalyServer
- class RuggedInterceptor < GRPC::ServerInterceptor
- # Intercept a unary request response call
- %i[request_response server_streamer client_streamer bidi_streamer].each do |meth|
- define_method(meth) do |**, &blk|
- init_rugged_reference_list
-
- blk.call
-
- cleanup_rugged_references
- end
- end
-
- def init_rugged_reference_list
- Thread.current[::Gitlab::Git::Repository::RUGGED_KEY] = []
- end
-
- def cleanup_rugged_references
- repos = Thread.current[::Gitlab::Git::Repository::RUGGED_KEY]
- repos.compact.map(&:close)
- end
- end
-end
diff --git a/ruby/lib/gitlab/encoding_helper.rb b/ruby/lib/gitlab/encoding_helper.rb
deleted file mode 100644
index 039b0cda4..000000000
--- a/ruby/lib/gitlab/encoding_helper.rb
+++ /dev/null
@@ -1,98 +0,0 @@
-module Gitlab
- module EncodingHelper
- extend self
-
- # This threshold is carefully tweaked to prevent usage of encodings detected
- # by CharlockHolmes with low confidence. If CharlockHolmes confidence is low,
- # we're better off sticking with utf8 encoding.
- # Reason: git diff can return strings with invalid utf8 byte sequences if it
- # truncates a diff in the middle of a multibyte character. In this case
- # CharlockHolmes will try to guess the encoding and will likely suggest an
- # obscure encoding with low confidence.
- # There is a lot more info with this merge request:
- # https://gitlab.com/gitlab-org/gitlab_git/merge_requests/77#note_4754193
- ENCODING_CONFIDENCE_THRESHOLD = 50
-
- def encode!(message)
- message = force_encode_utf8(message)
- return message if message.valid_encoding?
-
- # return message if message type is binary
- detect = CharlockHolmes::EncodingDetector.detect(message)
- return message.force_encoding("BINARY") if detect_binary?(message, detect)
-
- if detect && detect[:encoding] && detect[:confidence] > ENCODING_CONFIDENCE_THRESHOLD
- # force detected encoding if we have sufficient confidence.
- message.force_encoding(detect[:encoding])
- end
-
- # encode and clean the bad chars
- message.replace clean(message)
- rescue ArgumentError => e
- return unless e.message.include?('unknown encoding name')
-
- encoding = detect ? detect[:encoding] : "unknown"
- "--broken encoding: #{encoding}"
- end
-
- def detect_binary?(data, detect = nil)
- detect ||= CharlockHolmes::EncodingDetector.detect(data)
- detect && detect[:type] == :binary && detect[:confidence] == 100
- end
-
- def detect_libgit2_binary?(data)
- # EncodingDetector checks the first 1024 * 1024 bytes for NUL byte, libgit2 checks
- # only the first 8000 (https://github.com/libgit2/libgit2/blob/2ed855a9e8f9af211e7274021c2264e600c0f86b/src/filter.h#L15),
- # which is what we use below to keep a consistent behavior.
- detect = CharlockHolmes::EncodingDetector.new(8000).detect(data)
- detect && detect[:type] == :binary
- end
-
- def encode_utf8(message)
- message = force_encode_utf8(message)
- return message if message.valid_encoding?
-
- detect = CharlockHolmes::EncodingDetector.detect(message)
- if detect && detect[:encoding]
- begin
- CharlockHolmes::Converter.convert(message, detect[:encoding], 'UTF-8')
- rescue ArgumentError => e
- Rails.logger.warn("Ignoring error converting #{detect[:encoding]} into UTF8: #{e.message}")
-
- ''
- end
- else
- clean(message)
- end
- rescue ArgumentError
- nil
- end
-
- def encode_binary(str)
- return "" if str.nil?
-
- str.dup.force_encoding(Encoding::ASCII_8BIT)
- end
-
- def binary_stringio(str)
- StringIO.new(str.freeze || '').tap { |io| io.set_encoding(Encoding::ASCII_8BIT) }
- end
-
- private
-
- def force_encode_utf8(message)
- raise ArgumentError unless message.respond_to?(:force_encoding)
- return message if message.encoding == Encoding::UTF_8 && message.valid_encoding?
-
- message = message.dup if message.respond_to?(:frozen?) && message.frozen?
-
- message.force_encoding("UTF-8")
- end
-
- def clean(message)
- message.encode("UTF-16BE", undef: :replace, invalid: :replace, replace: "".encode("UTF-16BE"))
- .encode("UTF-8")
- .gsub("\0".encode("UTF-8"), "")
- end
- end
-end
diff --git a/ruby/lib/gitlab/git.rb b/ruby/lib/gitlab/git.rb
deleted file mode 100644
index 1f99646ee..000000000
--- a/ruby/lib/gitlab/git.rb
+++ /dev/null
@@ -1,99 +0,0 @@
-# External dependencies of Gitlab::Git
-require 'rugged'
-require 'linguist/blob_helper'
-require 'securerandom'
-require 'gitlab-labkit'
-
-# Ruby on Rails mix-ins that GitLab::Git code relies on
-require 'active_support/core_ext/object/blank'
-require 'active_support/core_ext/numeric/bytes'
-require 'active_support/core_ext/numeric/time'
-require 'active_support/core_ext/integer/time'
-require 'active_support/core_ext/module/delegation'
-require 'active_support/core_ext/enumerable'
-
-require_relative 'git_logger.rb'
-require_relative 'rails_logger.rb'
-require_relative 'config.rb'
-
-dir = __dir__
-
-# Some later requires are order-sensitive. Manually require whatever we need.
-require_relative "#{dir}/encoding_helper.rb"
-require_relative "#{dir}/utils/strong_memoize.rb"
-require_relative "#{dir}/git/popen.rb"
-
-# Require all .rb files we can find in the gitlab lib directory
-Dir["#{dir}/**/*.rb"].sort.each do |ruby_file|
- require File.expand_path(ruby_file)
-end
-
-class String
- # Because we are not rendering HTML, this is a no-op in gitaly-ruby.
- def html_safe
- self
- end
-end
-
-module Gitlab
- module Git
- # The ID of empty tree.
- # See http://stackoverflow.com/a/40884093/1856239 and
- # https://github.com/git/git/blob/3ad8b5bf26362ac67c9020bf8c30eee54a84f56d/cache.h#L1011-L1012
- EMPTY_TREE_ID = '4b825dc642cb6eb9a060e54bf8d69288fbee4904'.freeze
- BLANK_SHA = ('0' * 40).freeze
- TAG_REF_PREFIX = "refs/tags/".freeze
- BRANCH_REF_PREFIX = "refs/heads/".freeze
-
- BaseError = Class.new(StandardError)
- CommandError = Class.new(BaseError)
- CommitError = Class.new(BaseError)
- PreReceiveError = Class.new(BaseError)
-
- class << self
- include Gitlab::EncodingHelper
-
- def ref_name(ref)
- encode!(ref).sub(%r{\Arefs/(tags|heads|remotes)/}, '')
- end
-
- def branch_name(ref)
- ref = ref.to_s
- self.ref_name(ref) if self.branch_ref?(ref)
- end
-
- def tag_name(ref)
- ref = ref.to_s
- self.ref_name(ref) if self.tag_ref?(ref)
- end
-
- def tag_ref?(ref)
- ref.start_with?(TAG_REF_PREFIX)
- end
-
- def branch_ref?(ref)
- ref.start_with?(BRANCH_REF_PREFIX)
- end
-
- def blank_ref?(ref)
- ref == BLANK_SHA
- end
-
- def version
- Gitlab::Git::Version.git_version
- end
- end
- end
-end
-
-module Gitlab
- module GlId
- def self.gl_id(user)
- user.gl_id
- end
-
- def self.gl_id_from_id_value(id)
- "user-#{id}"
- end
- end
-end
diff --git a/ruby/lib/gitlab/git/branch.rb b/ruby/lib/gitlab/git/branch.rb
deleted file mode 100644
index 9618b5fef..000000000
--- a/ruby/lib/gitlab/git/branch.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-require_relative 'ref'
-
-module Gitlab
- module Git
- class Branch < Ref
- def initialize(repository, name, target, target_commit)
- super(repository, name, target, target_commit)
- end
- end
- end
-end
diff --git a/ruby/lib/gitlab/git/commit.rb b/ruby/lib/gitlab/git/commit.rb
deleted file mode 100644
index 5235b1c46..000000000
--- a/ruby/lib/gitlab/git/commit.rb
+++ /dev/null
@@ -1,250 +0,0 @@
-module Gitlab
- module Git
- class Commit
- include Gitlab::EncodingHelper
-
- attr_accessor :raw_commit, :head
-
- MAX_COMMIT_MESSAGE_DISPLAY_SIZE = 10.megabytes
- MIN_SHA_LENGTH = 7
- SERIALIZE_KEYS = %i[
- id message parent_ids
- authored_date author_name author_email
- committed_date committer_name committer_email trailers
- ].freeze
-
- attr_accessor *SERIALIZE_KEYS # rubocop:disable Lint/AmbiguousOperator
-
- def ==(other)
- return false unless other.is_a?(Gitlab::Git::Commit)
-
- id && id == other.id
- end
-
- class << self
- # Get single commit
- #
- # Ex.
- # Commit.find(repo, '29eda46b')
- #
- # Commit.find(repo, 'master')
- #
- def find(repo, commit_id = "HEAD")
- # Already a commit?
- return commit_id if commit_id.is_a?(Gitlab::Git::Commit)
-
- # A rugged reference?
- commit_id = Gitlab::Git::Ref.dereference_object(commit_id)
- return decorate(repo, commit_id) if commit_id.is_a?(Rugged::Commit)
-
- # Some weird thing?
- return nil unless commit_id.is_a?(String)
-
- # This saves us an RPC round trip.
- return nil if commit_id.include?(':')
-
- commit = rugged_find(repo, commit_id)
-
- decorate(repo, commit) if commit
- rescue Rugged::ReferenceError, Rugged::InvalidError, Rugged::ObjectError,
- Gitlab::Git::CommandError, Gitlab::Git::Repository::NoRepository,
- Rugged::OdbError, Rugged::TreeError, ArgumentError
- nil
- end
-
- def rugged_find(repo, commit_id)
- obj = repo.rev_parse_target(commit_id)
-
- obj.is_a?(Rugged::Commit) ? obj : nil
- end
-
- def decorate(repository, commit, ref = nil)
- Gitlab::Git::Commit.new(repository, commit, ref)
- end
-
- def shas_with_signatures(repository, shas)
- shas.select do |sha|
- begin
- Rugged::Commit.extract_signature(repository.rugged, sha)
- rescue Rugged::OdbError
- false
- end
- end
- end
- end
-
- def initialize(repository, raw_commit, head = nil)
- raise "Nil as raw commit passed" unless raw_commit
-
- @repository = repository
- @head = head
-
- case raw_commit
- when Hash
- init_from_hash(raw_commit)
- when Rugged::Commit
- init_from_rugged(raw_commit)
- when Gitaly::GitCommit
- init_from_gitaly(raw_commit)
- else
- raise "Invalid raw commit type: #{raw_commit.class}"
- end
- end
-
- def sha
- id
- end
-
- def short_id(length = 10)
- id.to_s[0..length]
- end
-
- def safe_message
- @safe_message ||= message
- end
-
- def no_commit_message
- "--no commit message"
- end
-
- def to_hash
- serialize_keys.map.with_object({}) do |key, hash|
- hash[key] = send(key)
- end
- end
-
- def date
- committed_date
- end
-
- def parents
- parent_ids.map { |oid| self.class.find(@repository, oid) }.compact
- end
-
- def message
- encode! @message
- end
-
- def author_name
- encode! @author_name
- end
-
- def author_email
- encode! @author_email
- end
-
- def committer_name
- encode! @committer_name
- end
-
- def committer_email
- encode! @committer_email
- end
-
- def rugged_commit
- @rugged_commit ||= if raw_commit.is_a?(Rugged::Commit)
- raw_commit
- else
- @repository.rev_parse_target(id)
- end
- end
-
- def merge_commit?
- parent_ids.size > 1
- end
-
- def to_gitaly_commit
- return raw_commit if raw_commit.is_a?(Gitaly::GitCommit)
-
- message_split = raw_commit.message.split("\n", 2)
- Gitaly::GitCommit.new(
- id: raw_commit.oid,
- subject: message_split[0] ? message_split[0].chomp.b : "",
- body: raw_commit.message.b,
- parent_ids: raw_commit.parent_ids,
- author: gitaly_commit_author_from_rugged(raw_commit.author),
- committer: gitaly_commit_author_from_rugged(raw_commit.committer),
- trailers: gitaly_trailers_from_rugged(raw_commit)
- )
- end
-
- private
-
- def init_from_hash(hash)
- raw_commit = hash.symbolize_keys
-
- serialize_keys.each do |key|
- send("#{key}=", raw_commit[key])
- end
- end
-
- def init_from_rugged(commit)
- author = commit.author
- committer = commit.committer
-
- @raw_commit = commit
- @id = commit.oid
- @message = commit.message
- @authored_date = author[:time]
- @committed_date = committer[:time]
- @author_name = author[:name]
- @author_email = author[:email]
- @committer_name = committer[:name]
- @committer_email = committer[:email]
- @parent_ids = commit.parents.map(&:oid)
- @trailers = Hash[commit.trailers]
- end
-
- def init_from_gitaly(commit)
- @raw_commit = commit
- @id = commit.id
- # TODO: Once gitaly "takes over" Rugged consider separating the
- # subject from the message to make it clearer when there's one
- # available but not the other.
- @message = message_from_gitaly_body
- @authored_date = init_date_from_gitaly(commit.author)
- @author_name = commit.author.name.dup
- @author_email = commit.author.email.dup
- @committed_date = init_date_from_gitaly(commit.committer)
- @committer_name = commit.committer.name.dup
- @committer_email = commit.committer.email.dup
- @parent_ids = Array(commit.parent_ids)
- @trailers = Hash[commit.trailers.map { |t| [t.key, t.value] }]
- end
-
- # Gitaly provides a UNIX timestamp in author.date.seconds, and a timezone
- # offset in author.timezone. If the latter isn't present, assume UTC.
- def init_date_from_gitaly(author)
- if author.timezone.present?
- Time.strptime("#{author.date.seconds} #{author.timezone}", '%s %z')
- else
- Time.at(author.date.seconds).utc
- end
- end
-
- def serialize_keys
- SERIALIZE_KEYS
- end
-
- def gitaly_commit_author_from_rugged(author_or_committer)
- Gitaly::CommitAuthor.new(
- name: author_or_committer[:name].b,
- email: author_or_committer[:email].b,
- date: Google::Protobuf::Timestamp.new(seconds: author_or_committer[:time].to_i)
- )
- end
-
- def gitaly_trailers_from_rugged(rugged_commit)
- rugged_commit.trailers.map do |(key, value)|
- Gitaly::CommitTrailer.new(key: key, value: value)
- end
- end
-
- def message_from_gitaly_body
- return @raw_commit.subject.dup if @raw_commit.body_size.zero?
-
- @raw_commit.body.dup
- end
- end
- end
-end
diff --git a/ruby/lib/gitlab/git/hook.rb b/ruby/lib/gitlab/git/hook.rb
deleted file mode 100644
index 8084cd74c..000000000
--- a/ruby/lib/gitlab/git/hook.rb
+++ /dev/null
@@ -1,141 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Git
- class Hook
- def self.directory
- Gitlab.config.git.hooks_directory
- end
-
- GL_PROTOCOL = 'web'
- attr_reader :name, :path, :repository
-
- def initialize(name, repository)
- @name = name
- @repository = repository
- @path = File.join(self.class.directory, name)
- end
-
- def repo_path
- repository.path
- end
-
- def exists?
- File.exist?(path)
- end
-
- def trigger(gl_id, gl_username, oldrev, newrev, ref, push_options: nil, transaction: nil)
- return [true, nil] unless exists?
-
- Bundler.with_unbundled_env do
- case name
- when "pre-receive", "post-receive"
- call_receive_hook(gl_id, gl_username, oldrev, newrev, ref, push_options, transaction)
- when "reference-transaction"
- call_reference_transaction_hook(gl_id, gl_username, oldrev, newrev, ref, transaction)
- when "update"
- call_update_hook(gl_id, gl_username, oldrev, newrev, ref, transaction)
- end
- end
- end
-
- private
-
- def call_stdin_hook(args, input, env)
- exit_status = false
- exit_message = nil
-
- options = {
- chdir: repo_path
- }
-
- Open3.popen3(env, path, *args, options) do |stdin, stdout, stderr, wait_thr|
- exit_status = true
- stdin.sync = true
-
- # in git, hooks may just exit without reading stdin. We catch the
- # exception to avoid a broken pipe warning
- begin
- input.lines do |line|
- stdin.puts line
- end
- rescue Errno::EPIPE
- end
-
- stdin.close
-
- unless wait_thr.value == 0
- exit_status = false
- exit_message = retrieve_error_message(stderr, stdout)
- end
- end
-
- [exit_status, exit_message]
- end
-
- def call_receive_hook(gl_id, gl_username, oldrev, newrev, ref, push_options, transaction)
- changes = [oldrev, newrev, ref].join(" ")
-
- vars = env_base_vars(gl_id, gl_username, transaction)
- vars.merge!(push_options.env_data) if push_options
-
- call_stdin_hook([], changes, vars)
- end
-
- def call_reference_transaction_hook(gl_id, gl_username, oldrev, newrev, ref, transaction)
- changes = [oldrev, newrev, ref].join(" ")
-
- vars = env_base_vars(gl_id, gl_username, transaction)
-
- call_stdin_hook(["prepared"], changes, vars)
- end
-
- def call_update_hook(gl_id, gl_username, oldrev, newrev, ref, transaction)
- options = {
- chdir: repo_path
- }
-
- args = [ref, oldrev, newrev]
-
- vars = env_base_vars(gl_id, gl_username, transaction)
-
- stdout, stderr, status = Open3.capture3(vars, path, *args, options)
- [status.success?, stderr.presence || stdout]
- end
-
- def retrieve_error_message(stderr, stdout)
- err_message = stderr.read
- err_message = err_message.blank? ? stdout.read : err_message
- err_message
- end
-
- def hooks_payload(gl_id, gl_username, transaction)
- payload = {
- repository: repository.gitaly_repository.to_json,
- binary_directory: Gitlab.config.gitaly.bin_dir,
- git_path: Gitlab.config.git.bin_path,
- internal_socket: Gitlab.config.gitaly.internal_socket,
- internal_socket_token: ENV['GITALY_TOKEN'],
- user_details: {
- userid: gl_id,
- username: gl_username,
- protocol: GL_PROTOCOL
- }
- }
-
- payload.merge!(transaction.payload) if transaction
-
- Base64.strict_encode64(payload.to_json)
- end
-
- def env_base_vars(gl_id, gl_username, transaction = nil)
- {
- 'GITALY_HOOKS_PAYLOAD' => hooks_payload(gl_id, gl_username, transaction),
- 'GITALY_LOG_DIR' => Gitlab.config.logging.dir,
- 'PWD' => repo_path,
- 'GIT_DIR' => repo_path
- }
- end
- end
- end
-end
diff --git a/ruby/lib/gitlab/git/hooks_service.rb b/ruby/lib/gitlab/git/hooks_service.rb
deleted file mode 100644
index baccaa5c0..000000000
--- a/ruby/lib/gitlab/git/hooks_service.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-module Gitlab
- module Git
- class HooksService
- attr_accessor :oldrev, :newrev, :ref
-
- def execute(pusher, repository, oldrev, newrev, ref, push_options:, transaction: nil)
- @repository = repository
- @gl_id = pusher.gl_id
- @gl_username = pusher.username
- @oldrev = oldrev
- @newrev = newrev
- @ref = ref
- @push_options = push_options
- @transaction = transaction
-
- %w[pre-receive update reference-transaction].each do |hook_name|
- status, message = run_hook(hook_name)
-
- raise PreReceiveError, message unless status
- end
-
- yield(self).tap do
- status, message = run_hook('reference-transaction')
- Gitlab::GitLogger.error("reference-transaction committed hook: #{message}") unless status
-
- status, message = run_hook('post-receive')
-
- Gitlab::GitLogger.error("post-receive hook: #{message}") unless status
- end
- end
-
- private
-
- def run_hook(name)
- hook = Gitlab::Git::Hook.new(name, @repository)
- hook.trigger(@gl_id, @gl_username, oldrev, newrev, ref, push_options: @push_options, transaction: @transaction)
- end
- end
- end
-end
diff --git a/ruby/lib/gitlab/git/operation_service.rb b/ruby/lib/gitlab/git/operation_service.rb
deleted file mode 100644
index 902a707ad..000000000
--- a/ruby/lib/gitlab/git/operation_service.rb
+++ /dev/null
@@ -1,121 +0,0 @@
-module Gitlab
- module Git
- class OperationService
- include Gitlab::Git::Popen
-
- BranchUpdate = Struct.new(:newrev, :repo_created, :branch_created) do
- alias_method :repo_created?, :repo_created
- alias_method :branch_created?, :branch_created
-
- def self.from_gitaly(branch_update)
- return if branch_update.nil?
-
- new(
- branch_update.commit_id,
- branch_update.repo_created,
- branch_update.branch_created
- )
- end
- end
-
- attr_reader :user, :repository
-
- def initialize(user, new_repository)
- @user = user
- @repository = new_repository
- end
-
- # Execute the block with the tip commit referenced by the given branch.
- # The branch must exist before calling this function.
- def with_branch(branch_name, &block)
- if !repository.empty? && !repository.branch_exists?(branch_name)
- raise ArgumentError, "Cannot find branch '#{branch_name}'"
- end
-
- update_branch_with_hooks(branch_name) do
- repository.with_repo_branch_commit(branch_name, &block)
- end
- end
-
- private
-
- # Returns [newrev, should_run_after_create, should_run_after_create_branch]
- def update_branch_with_hooks(branch_name)
- was_empty = repository.empty?
-
- # Make commit
- newrev = yield
-
- raise Gitlab::Git::CommitError.new('Failed to create commit') unless newrev
-
- branch = repository.find_branch(branch_name)
- oldrev = find_oldrev_from_branch(newrev, branch)
-
- ref = Gitlab::Git::BRANCH_REF_PREFIX + branch_name
- update_ref_in_hooks(ref, newrev, oldrev)
-
- BranchUpdate.new(newrev, was_empty, was_empty || Gitlab::Git.blank_ref?(oldrev))
- end
-
- def find_oldrev_from_branch(newrev, branch)
- return Gitlab::Git::BLANK_SHA unless branch
-
- oldrev = branch.target
-
- merge_base = repository.merge_base(newrev, branch.target)
- raise Gitlab::Git::Repository::InvalidRef unless merge_base
-
- if oldrev == merge_base
- oldrev
- else
- raise Gitlab::Git::CommitError.new('Branch diverged')
- end
- end
-
- def update_ref_in_hooks(ref, newrev, oldrev, push_options: nil, transaction: nil)
- with_hooks(ref, newrev, oldrev, push_options: push_options, transaction: transaction) do
- update_ref(ref, newrev, oldrev)
- end
- end
-
- def with_hooks(ref, newrev, oldrev, push_options: nil, transaction: nil)
- Gitlab::Git::HooksService.new.execute(
- user,
- repository,
- oldrev,
- newrev,
- ref,
- push_options: push_options,
- transaction: transaction
- ) do |service|
- yield(service)
- end
- end
-
- def update_ref(ref, newrev, oldrev)
- # We use 'git update-ref' because libgit2/rugged currently does not
- # offer 'compare and swap' ref updates. Without compare-and-swap we can
- # (and have!) accidentally reset the ref to an earlier state, clobbering
- # commits. See also https://github.com/libgit2/libgit2/issues/1534.
- command = %W[#{Gitlab.config.git.bin_path} update-ref --stdin -z]
-
- output, status = popen(
- command,
- repository.path
- ) do |stdin|
- stdin.write("update #{ref}\x00#{newrev}\x00#{oldrev}\x00")
- end
-
- unless status.zero?
- Gitlab::GitLogger.error("'git update-ref' in #{repository.path}: #{output}")
- ref_name = Gitlab::Git.branch_name(ref) || ref
-
- raise Gitlab::Git::CommitError.new(
- "Could not update #{ref_name}." \
- " Please refresh and try again."
- )
- end
- end
- end
- end
-end
diff --git a/ruby/lib/gitlab/git/popen.rb b/ruby/lib/gitlab/git/popen.rb
deleted file mode 100644
index 5d8218eb1..000000000
--- a/ruby/lib/gitlab/git/popen.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-require 'open3'
-
-module Gitlab
- module Git
- module Popen
- FAST_GIT_PROCESS_TIMEOUT = 15.seconds
-
- def popen(cmd, path, vars = {}, include_stderr: true, lazy_block: nil)
- raise "System commands must be given as an array of strings" unless cmd.is_a?(Array)
-
- path ||= Dir.pwd
- vars['PWD'] = path
- options = { chdir: path }
-
- cmd_output = ""
- cmd_status = 0
- Open3.popen3(vars, *cmd, options) do |stdin, stdout, stderr, wait_thr|
- stdout.set_encoding(Encoding::ASCII_8BIT)
- stderr.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 }
-
- begin
- yield(stdin) if block_given?
- stdin.close
-
- if lazy_block
- cmd_output = lazy_block.call(stdout.lazy)
- cmd_status = 0
- break
- else
- cmd_output << stdout.read
- end
-
- cmd_output << err_reader.value if include_stderr
- cmd_status = wait_thr.value.exitstatus
- ensure
- # When Popen3.open3 returns, the stderr reader gets closed, which causes
- # an exception in the err_reader thread. Kill the thread before
- # returning from Popen3.open3.
- err_reader.kill
- end
- end
-
- [cmd_output, cmd_status]
- end
- end
- end
-end
diff --git a/ruby/lib/gitlab/git/push_options.rb b/ruby/lib/gitlab/git/push_options.rb
deleted file mode 100644
index a3829cc9d..000000000
--- a/ruby/lib/gitlab/git/push_options.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Git
- class PushOptions
- attr_accessor :options
-
- def initialize(options)
- @options = options
- end
-
- def env_data
- return {} if options.empty?
-
- data = {
- 'GIT_PUSH_OPTION_COUNT' => options.count.to_s
- }
-
- options.each_with_index do |opt, index|
- data["GIT_PUSH_OPTION_#{index}"] = opt
- end
-
- data
- end
- end
- end
-end
diff --git a/ruby/lib/gitlab/git/ref.rb b/ruby/lib/gitlab/git/ref.rb
deleted file mode 100644
index e45bec404..000000000
--- a/ruby/lib/gitlab/git/ref.rb
+++ /dev/null
@@ -1,53 +0,0 @@
-# Gitaly note: JV: probably no RPC's here (just one interaction with Rugged).
-
-module Gitlab
- module Git
- class Ref
- include Gitlab::EncodingHelper
-
- # Canonical refname, including `refs/heads|tags/` prefix
- attr_reader :refname
-
- # Branch or tag name
- # without "refs/tags|heads" prefix
- attr_reader :name
-
- # Target sha.
- # Usually it is commit sha but in case
- # when tag reference on other tag it can be tag sha
- attr_reader :target
-
- # Dereferenced target
- # Commit object to which the Ref points to
- attr_reader :dereferenced_target
-
- # Extract branch name from full ref path
- #
- # Ex.
- # Ref.extract_branch_name('refs/heads/master') #=> 'master'
- def self.extract_branch_name(str)
- str.gsub(%r{\Arefs/heads/}, '')
- end
-
- # Gitaly: this method will probably be migrated indirectly via its call sites.
- def self.dereference_object(object)
- object = object.target while object.is_a?(Rugged::Tag::Annotation)
-
- object
- end
-
- def initialize(_repository, name, target, dereferenced_target)
- @refname = name
- @name = Gitlab::Git.ref_name(name)
- @dereferenced_target = dereferenced_target
- @target = if target.respond_to?(:oid)
- target.oid
- elsif target.respond_to?(:name)
- target.name
- elsif target.is_a? String
- target
- end
- end
- end
- end
-end
diff --git a/ruby/lib/gitlab/git/repository.rb b/ruby/lib/gitlab/git/repository.rb
deleted file mode 100644
index cbe5bde19..000000000
--- a/ruby/lib/gitlab/git/repository.rb
+++ /dev/null
@@ -1,282 +0,0 @@
-require 'securerandom'
-
-module Gitlab
- module Git
- # These are monkey patches on top of the vendored version of Repository.
- class Repository
- include Gitlab::Git::Popen
- include Gitlab::EncodingHelper
- include Gitlab::Utils::StrongMemoize
-
- GITALY_INTERNAL_URL = 'ssh://gitaly/internal.git'.freeze
- RUGGED_KEY = :rugged_list
- GIT_ALLOW_SHA_UPLOAD = 'uploadpack.allowAnySHA1InWant=true'.freeze
-
- NoRepository = Class.new(StandardError)
- InvalidRef = Class.new(StandardError)
- GitError = Class.new(StandardError)
-
- class << self
- def from_gitaly(gitaly_repository, call)
- new(
- gitaly_repository,
- GitalyServer.repo_path(call),
- GitalyServer.gl_repository(call),
- GitalyServer.repo_alt_dirs(call),
- GitalyServer.feature_flags(call)
- )
- end
-
- def from_gitaly_with_block(gitaly_repository, call)
- repository = from_gitaly(gitaly_repository, call)
-
- result = yield repository
-
- repository.cleanup
-
- result
- end
- end
-
- attr_reader :path
-
- # Directory name of repo
- attr_reader :name
-
- attr_reader :storage, :gl_repository, :gl_project_path, :relative_path
-
- def initialize(gitaly_repository, path, gl_repository, combined_alt_dirs = "", feature_flags = GitalyServer::FeatureFlags.new({}))
- @gitaly_repository = gitaly_repository
-
- @alternate_object_directories = combined_alt_dirs
- .split(File::PATH_SEPARATOR)
- .map { |d| File.join(path, d) }
-
- @storage = gitaly_repository.storage_name
- @relative_path = gitaly_repository.relative_path
- @path = path
- @gl_repository = gl_repository
- @gl_project_path = gitaly_repository.gl_project_path
- @feature_flags = feature_flags
- end
-
- def ==(other)
- [storage, relative_path] == [other.storage, other.relative_path]
- end
-
- attr_reader :gitaly_repository
-
- attr_reader :alternate_object_directories
-
- def sort_branches(branches, sort_by)
- case sort_by
- when 'name'
- branches.sort_by(&:name)
- when 'updated_desc'
- branches.sort do |a, b|
- b.dereferenced_target.committed_date <=> a.dereferenced_target.committed_date
- end
- when 'updated_asc'
- branches.sort do |a, b|
- a.dereferenced_target.committed_date <=> b.dereferenced_target.committed_date
- end
- else
- branches
- end
- end
-
- def exists?
- File.exist?(File.join(path, 'refs'))
- end
-
- def root_ref
- @root_ref ||= discover_default_branch
- end
-
- def rugged
- @rugged ||= begin
- # Open in bare mode, for a slight performance gain
- # https://github.com/libgit2/rugged/blob/654ff2fe12041e09707ba0647307abcb6348a7fb/ext/rugged/rugged_repo.c#L276-L278
- Rugged::Repository.bare(path, alternates: alternate_object_directories).tap do |repo|
- Thread.current[RUGGED_KEY] << repo if Thread.current[RUGGED_KEY]
- end
- end
- rescue Rugged::RepositoryError, Rugged::OSError
- raise NoRepository, 'no repository for such path'
- end
-
- def branch_names
- branches.map(&:name)
- end
-
- def branches
- branches_filter
- end
-
- # Git repository can contains some hidden refs like:
- # /refs/notes/*
- # /refs/git-as-svn/*
- # /refs/pulls/*
- # This refs by default not visible in project page and not cloned to client side.
- def has_visible_content?
- strong_memoize(:has_visible_content) do
- branches_filter(filter: :local).any? do |ref|
- begin
- ref.name && ref.target # ensures the branch is valid
-
- true
- rescue Rugged::ReferenceError
- false
- end
- end
- end
- end
-
- def tags
- rugged.references.each("refs/tags/*").map do |ref|
- message = nil
-
- if ref.target.is_a?(Rugged::Tag::Annotation)
- tag_message = ref.target.message
-
- message = tag_message.chomp if tag_message.respond_to?(:chomp)
- end
-
- target_commit = Gitlab::Git::Commit.find(self, ref.target)
- Gitlab::Git::Tag.new(self,
- name: ref.canonical_name,
- target: ref.target,
- target_commit: target_commit,
- message: message)
- end.sort_by(&:name)
- end
-
- # Discovers the default branch based on the repository's available branches
- #
- # - If no branches are present, returns nil
- # - If one branch is present, returns its name
- # - If two or more branches are present, returns current HEAD or master or first branch
- def discover_default_branch
- names = branch_names
-
- return if names.empty?
-
- return names[0] if names.length == 1
-
- if rugged_head
- extracted_name = Ref.extract_branch_name(rugged_head.name)
-
- return extracted_name if names.include?(extracted_name)
- end
-
- if names.include?('master')
- 'master'
- else
- names[0]
- end
- end
-
- def with_repo_branch_commit(start_ref)
- if empty?
- yield nil
- else
- # Directly return the commit from this repository
- yield commit(start_ref)
- end
- 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.ref("refs/heads/" + name)
- if rugged_ref
- target_commit = Gitlab::Git::Commit.find(self, rugged_ref.target)
- Gitlab::Git::Branch.new(self, rugged_ref.canonical_name, rugged_ref.target, target_commit)
- end
- 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
-
- def merge_base(from, to)
- rugged.merge_base(from, to)
- rescue Rugged::ReferenceError
- nil
- end
-
- # Lookup for rugged object by oid or ref name
- def lookup(oid_or_ref_name)
- rugged.rev_parse(oid_or_ref_name)
- end
-
- # Return the object that +revspec+ points to. If +revspec+ is an
- # annotated tag, then return the tag's target instead.
- def rev_parse_target(revspec)
- obj = rugged.rev_parse(revspec)
- Ref.dereference_object(obj)
- end
-
- def commit(ref = nil)
- ref ||= root_ref
- Gitlab::Git::Commit.find(self, ref)
- end
-
- def empty?
- !has_visible_content?
- end
-
- def cleanup
- # Opening a repository may be expensive, and we only need to close it
- # if it's been open.
- rugged&.close if defined?(@rugged)
- end
-
- def head_symbolic_ref
- head = rugged.ref('HEAD')
-
- return 'main' if head.type != :symbolic
-
- Ref.extract_branch_name(head.target_id)
- end
-
- private
-
- 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.canonical_name, rugged_ref.target, target_commit)
- rescue Rugged::ReferenceError
- # Omit invalid branch
- end
- end.compact
-
- sort_branches(branches, sort_by)
- end
-
- def rugged_head
- rugged.head
- rescue Rugged::ReferenceError
- nil
- end
- end
- end
-end
diff --git a/ruby/lib/gitlab/git/tag.rb b/ruby/lib/gitlab/git/tag.rb
deleted file mode 100644
index 1d7c8e5d2..000000000
--- a/ruby/lib/gitlab/git/tag.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-require_relative 'ref'
-
-module Gitlab
- module Git
- class Tag < Ref
- extend Gitlab::EncodingHelper
-
- attr_reader :object_sha, :repository
-
- SERIALIZE_KEYS = %i[name target target_commit message].freeze
-
- attr_accessor *SERIALIZE_KEYS # rubocop:disable Lint/AmbiguousOperator
-
- def initialize(repository, raw_tag)
- @repository = repository
- @raw_tag = raw_tag
-
- case raw_tag
- when Hash
- init_from_hash
- when Gitaly::Tag
- init_from_gitaly
- end
-
- super(repository, name, target, target_commit)
- end
-
- def init_from_hash
- raw_tag = @raw_tag.symbolize_keys
-
- SERIALIZE_KEYS.each do |key|
- send("#{key}=", raw_tag[key])
- end
- end
-
- def init_from_gitaly
- @name = encode!(@raw_tag.name.dup)
- @target = @raw_tag.id
- @message = @raw_tag.message.dup
-
- @target_commit = Gitlab::Git::Commit.decorate(repository, @raw_tag.target_commit) if @raw_tag.target_commit.present?
- end
-
- def message
- encode! @message
- end
- end
- end
-end
diff --git a/ruby/lib/gitlab/git/user.rb b/ruby/lib/gitlab/git/user.rb
deleted file mode 100644
index ebb317430..000000000
--- a/ruby/lib/gitlab/git/user.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-module Gitlab
- module Git
- class User
- attr_reader :username, :name, :email, :gl_id
-
- def self.from_gitaly(gitaly_user)
- new(
- gitaly_user.gl_username,
- Gitlab::EncodingHelper.encode!(gitaly_user.name),
- Gitlab::EncodingHelper.encode!(gitaly_user.email),
- gitaly_user.gl_id
- )
- end
-
- def initialize(username, name, email, gl_id)
- @username = username
- @name = name
- @email = email
- @gl_id = gl_id
- end
-
- def ==(other)
- [username, name, email, gl_id] == [other.username, other.name, other.email, other.gl_id]
- end
-
- def git_env(timestamp = nil)
- {
- 'GIT_COMMITTER_NAME' => name,
- 'GIT_COMMITTER_EMAIL' => email,
- 'GIT_COMMITTER_DATE' => timestamp ? "#{timestamp.seconds} +0000" : nil,
- 'GL_ID' => Gitlab::GlId.gl_id(self)
- }.reject { |_, v| v.nil? }
- end
- end
- end
-end
diff --git a/ruby/lib/gitlab/git_logger.rb b/ruby/lib/gitlab/git_logger.rb
deleted file mode 100644
index 23a163ba6..000000000
--- a/ruby/lib/gitlab/git_logger.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-require 'logger'
-
-module Gitlab
- GitLogger = Logger.new(STDOUT)
- GitLogger.progname = 'githost.log'
- GitLogger.level = 'info'
-end
diff --git a/ruby/lib/gitlab/rails_logger.rb b/ruby/lib/gitlab/rails_logger.rb
deleted file mode 100644
index 917bbb487..000000000
--- a/ruby/lib/gitlab/rails_logger.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-require 'logger'
-
-module Rails
- LOGGER = Logger.new(STDOUT)
- LOGGER.level = 'info'
-
- def self.logger
- LOGGER
- end
-end
diff --git a/ruby/lib/gitlab/utils/strong_memoize.rb b/ruby/lib/gitlab/utils/strong_memoize.rb
deleted file mode 100644
index fe091f461..000000000
--- a/ruby/lib/gitlab/utils/strong_memoize.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-module Gitlab
- module Utils
- module StrongMemoize
- # Instead of writing patterns like this:
- #
- # def trigger_from_token
- # return @trigger if defined?(@trigger)
- #
- # @trigger = Ci::Trigger.find_by_token(params[:token].to_s)
- # end
- #
- # We could write it like:
- #
- # include Gitlab::Utils::StrongMemoize
- #
- # def trigger_from_token
- # strong_memoize(:trigger) do
- # Ci::Trigger.find_by_token(params[:token].to_s)
- # end
- # end
- #
- def strong_memoize(name)
- if instance_variable_defined?(ivar(name))
- instance_variable_get(ivar(name))
- else
- instance_variable_set(ivar(name), yield)
- end
- end
-
- def clear_memoization(name)
- remove_instance_variable(ivar(name)) if instance_variable_defined?(ivar(name))
- end
-
- private
-
- def ivar(name)
- "@#{name}"
- end
- end
- end
-end
diff --git a/ruby/spec/factories/gitaly/commit_author.rb b/ruby/spec/factories/gitaly/commit_author.rb
deleted file mode 100644
index aaf634ce0..000000000
--- a/ruby/spec/factories/gitaly/commit_author.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-FactoryBot.define do
- factory :gitaly_commit_author, class: Gitaly::CommitAuthor do
- skip_create
-
- name { generate(:name) }
- email { generate(:email) }
- date { Google::Protobuf::Timestamp.new(seconds: Time.now.to_i) }
- end
-end
diff --git a/ruby/spec/factories/sequences.rb b/ruby/spec/factories/sequences.rb
deleted file mode 100644
index 16a05b1ca..000000000
--- a/ruby/spec/factories/sequences.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-FactoryBot.define do
- sequence(:name) { |n| "John Doe#{n}" }
- sequence(:email) { |n| "user#{n}@example.org" }
-end
diff --git a/ruby/spec/lib/gitaly_server/feature_flags_spec.rb b/ruby/spec/lib/gitaly_server/feature_flags_spec.rb
deleted file mode 100644
index 40e24a024..000000000
--- a/ruby/spec/lib/gitaly_server/feature_flags_spec.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-describe GitalyServer::FeatureFlags do
- describe '#enabled?' do
- let(:metadata) do
- {
- "#{described_class::HEADER_PREFIX}some-feature" => 'true',
- 'gitaly-storage-path' => 'foo',
- 'gitaly-repo-path' => 'bar'
- }
- end
-
- subject { described_class.new(metadata) }
-
- it 'returns true for an enabled flag' do
- expect(subject.enabled?(:some_feature)).to eq(true)
- end
-
- it 'returns true for a missing flag that is on by default' do
- expect(subject.enabled?(:feature_default_on, on_by_default: true)).to eq(true)
- end
-
- it 'returns false for an unknown flag' do
- expect(subject.enabled?(:missing_feature)).to eq(false)
- end
-
- it 'removes the prefix if provided' do
- expect(subject.enabled?(metadata.keys.first)).to eq(true)
- end
-
- it 'translates underscores' do
- expect(subject.enabled?('some-feature')).to eq(true)
- end
- end
-
- describe '#disabled?' do
- it 'is the inverse of `enabled?`' do
- instance = described_class.new({})
-
- expect(instance).to receive(:enabled?)
- .with(:some_feature, on_by_default: false)
- .and_return(false)
-
- expect(instance.disabled?(:some_feature)).to eq(true)
- end
- end
-end
diff --git a/ruby/spec/lib/gitaly_server/rugged_interceptor_spec.rb b/ruby/spec/lib/gitaly_server/rugged_interceptor_spec.rb
deleted file mode 100644
index 879ba1bae..000000000
--- a/ruby/spec/lib/gitaly_server/rugged_interceptor_spec.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-require 'spec_helper'
-
-require_relative '../../../lib/gitaly_server/rugged_interceptor.rb'
-
-describe GitalyServer::RuggedInterceptor do
- include TestRepo
-
- let(:meth) { GitalyServer::RepositoryService.instance_method(:find_license) }
- let(:call) { double(metadata: {}) }
-
- subject do
- described_class.new.server_streamer(call: call, method: meth) {}
- end
-
- context 'no Rugged repositories initialized' do
- it 'does not clean up any repositories' do
- expect(Rugged::Repository).not_to receive(:new)
-
- subject
- end
- end
-
- context 'Rugged repository initialized' do
- let(:rugged) { rugged_from_gitaly(test_repo_read_only) }
-
- let(:streamer) do
- described_class.new.server_streamer(call: call, method: meth) do
- Thread.current[Gitlab::Git::Repository::RUGGED_KEY] = [rugged]
- end
- end
-
- it 'cleans up repositories' do
- expect(rugged).to receive(:close).and_call_original
-
- streamer
- end
- end
-end
diff --git a/ruby/spec/lib/gitlab/git/branch_spec.rb b/ruby/spec/lib/gitlab/git/branch_spec.rb
deleted file mode 100644
index 3381fc230..000000000
--- a/ruby/spec/lib/gitlab/git/branch_spec.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-require "spec_helper"
-
-describe Gitlab::Git::Branch do
- include TestRepo
-
- let(:repository) { gitlab_git_from_gitaly(git_test_repo_read_only) }
-
- subject { repository.branches }
-
- it { is_expected.to be_an(Array) }
-
- describe '#size' do
- subject { super().size }
-
- it { is_expected.to eq(SeedRepo::Repo::BRANCHES.size) }
- end
-
- it { expect(repository.branches.size).to eq(SeedRepo::Repo::BRANCHES.size) }
-end
diff --git a/ruby/spec/lib/gitlab/git/commit_spec.rb b/ruby/spec/lib/gitlab/git/commit_spec.rb
deleted file mode 100644
index bd2b5aeeb..000000000
--- a/ruby/spec/lib/gitlab/git/commit_spec.rb
+++ /dev/null
@@ -1,207 +0,0 @@
-require "spec_helper"
-
-describe Gitlab::Git::Commit do
- include TestRepo
-
- let(:repository) { gitlab_git_from_gitaly(new_mutable_test_repo) }
- let(:rugged_repo) { Rugged::Repository.new(repository.path) }
- let(:commit) { described_class.find(repository, SeedRepo::Commit::ID) }
- let(:rugged_commit) { rugged_repo.lookup(SeedRepo::Commit::ID) }
-
- describe "Commit info" do
- let(:committer) do
- {
- email: 'mike@smith.com',
- name: "Mike Smith",
- time: Time.new(2000, 1, 1, 0, 0, 0, "+08:00")
- }
- end
- let(:author) do
- {
- email: 'john@smith.com',
- name: "John Smith",
- time: Time.new(2000, 1, 1, 0, 0, 0, "-08:00")
- }
- end
- let(:parents) { [rugged_repo.head.target] }
- let(:gitlab_parents) do
- parents.map { |c| described_class.find(repository, c.oid) }
- end
- let(:tree) { parents.first.tree }
- let(:sha) do
- Rugged::Commit.create(
- rugged_repo,
- author: author,
- committer: committer,
- tree: tree,
- parents: parents,
- message: "Refactoring specs",
- update_ref: "HEAD"
- )
- end
- let(:rugged_commit) { rugged_repo.lookup(sha) }
- let(:commit) { described_class.find(repository, sha) }
-
- it { expect(commit.short_id).to eq(rugged_commit.oid[0..10]) }
- it { expect(commit.id).to eq(rugged_commit.oid) }
- it { expect(commit.sha).to eq(rugged_commit.oid) }
- it { expect(commit.safe_message).to eq(rugged_commit.message) }
- it { expect(commit.date).to eq(rugged_commit.committer[:time]) }
- it { expect(commit.author_email).to eq(author[:email]) }
- it { expect(commit.author_name).to eq(author[:name]) }
- it { expect(commit.committer_name).to eq(committer[:name]) }
- it { expect(commit.committer_email).to eq(committer[:email]) }
- it { expect(commit.parents).to eq(gitlab_parents) }
- it { expect(commit.no_commit_message).to eq("--no commit message") }
- end
-
- describe "Commit info from gitaly commit" do
- let(:subject) { "My commit".b }
- let(:body) { subject + "My body".b }
- let(:body_size) { body.length }
- let(:gitaly_commit) { build(:gitaly_commit, subject: subject, body: body, body_size: body_size) }
- let(:id) { gitaly_commit.id }
- let(:committer) { gitaly_commit.committer }
- let(:author) { gitaly_commit.author }
- let(:commit) { described_class.new(repository, gitaly_commit) }
-
- it { expect(commit.short_id).to eq(id[0..10]) }
- it { expect(commit.id).to eq(id) }
- it { expect(commit.sha).to eq(id) }
- it { expect(commit.safe_message).to eq(body) }
- it { expect(commit.author_email).to eq(author.email) }
- it { expect(commit.author_name).to eq(author.name) }
- it { expect(commit.committer_name).to eq(committer.name) }
- it { expect(commit.committer_email).to eq(committer.email) }
- it { expect(commit.parent_ids).to eq(gitaly_commit.parent_ids) }
-
- context 'non-UTC dates' do
- let(:seconds) { Time.now.to_i }
-
- it 'sets timezones correctly' do
- gitaly_commit.author.date.seconds = seconds
- gitaly_commit.author.timezone = '-0800'
- gitaly_commit.committer.date.seconds = seconds
- gitaly_commit.committer.timezone = '+0800'
-
- expect(commit.authored_date).to eq(Time.at(seconds, in: '-08:00'))
- expect(commit.committed_date).to eq(Time.at(seconds, in: '+08:00'))
- end
- end
-
- context 'body_size != body.size' do
- let(:body) { "".b }
-
- context 'zero body_size' do
- it { expect(commit.safe_message).to eq(subject) }
- end
- end
- end
-
- context 'Class methods' do
- describe '.find' do
- it "returns an array of parent ids" do
- expect(described_class.find(repository, SeedRepo::Commit::ID).parent_ids).to be_an(Array)
- end
-
- it "should return valid commit for tag" do
- expect(described_class.find(repository, 'v1.0.0').id).to eq('6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9')
- end
-
- it "should return nil for non-commit ids" do
- blob_id = repository.lookup("#{SeedRepo::Commit::ID}:files/ruby/popen.rb")
- expect(described_class.find(repository, blob_id)).to be_nil
- end
-
- it "should return nil for parent of non-commit object" do
- blob_id = repository.lookup("#{SeedRepo::Commit::ID}:files/ruby/popen.rb")
- expect(described_class.find(repository, "#{blob_id}^")).to be_nil
- end
-
- it "should return nil for nonexisting ids" do
- expect(described_class.find(repository, "+123_4532530XYZ")).to be_nil
- end
-
- context 'with broken repo' do
- let(:repository) { gitlab_git_from_gitaly(new_broken_test_repo) }
-
- it 'returns nil' do
- expect(described_class.find(repository, SeedRepo::Commit::ID)).to be_nil
- end
- end
- end
-
- describe '.shas_with_signatures' do
- let(:signed_shas) { %w[5937ac0a7beb003549fc5fd26fc247adbce4a52e 570e7b2abdd848b95f2f578043fc23bd6f6fd24d] }
- let(:unsigned_shas) { %w[19e2e9b4ef76b422ce1154af39a91323ccc57434 c642fe9b8b9f28f9225d7ea953fe14e74748d53b] }
- let(:first_signed_shas) { %w[5937ac0a7beb003549fc5fd26fc247adbce4a52e c642fe9b8b9f28f9225d7ea953fe14e74748d53b] }
-
- it 'has 2 signed shas' do
- ret = described_class.shas_with_signatures(repository, signed_shas)
- expect(ret).to eq(signed_shas)
- end
-
- it 'has 0 signed shas' do
- ret = described_class.shas_with_signatures(repository, unsigned_shas)
- expect(ret).to eq([])
- end
-
- it 'has 1 signed sha' do
- ret = described_class.shas_with_signatures(repository, first_signed_shas)
- expect(ret).to contain_exactly(first_signed_shas.first)
- end
- end
- end
-
- describe '#init_from_rugged' do
- let(:gitlab_commit) { described_class.new(repository, rugged_commit) }
- subject { gitlab_commit }
-
- describe '#id' do
- subject { super().id }
- it { is_expected.to eq(SeedRepo::Commit::ID) }
- end
- end
-
- describe '#init_from_hash' do
- let(:commit) { described_class.new(repository, sample_commit_hash) }
- subject { commit }
-
- describe '#id' do
- subject { super().id }
- it { is_expected.to eq(sample_commit_hash[:id]) }
- end
-
- describe '#message' do
- subject { super().message }
- it { is_expected.to eq(sample_commit_hash[:message]) }
- end
- end
-
- describe '#to_hash' do
- let(:hash) { commit.to_hash }
- subject { hash }
-
- it { is_expected.to be_kind_of Hash }
-
- describe '#keys' do
- subject { super().keys.sort }
- it { is_expected.to match(sample_commit_hash.keys.sort) }
- end
- end
-
- def sample_commit_hash
- {
- author_email: "dmitriy.zaporozhets@gmail.com",
- author_name: "Dmitriy Zaporozhets",
- authored_date: "2012-02-27 20:51:12 +0200",
- committed_date: "2012-02-27 20:51:12 +0200",
- committer_email: "dmitriy.zaporozhets@gmail.com",
- committer_name: "Dmitriy Zaporozhets",
- id: SeedRepo::Commit::ID,
- message: "tree css fixes",
- parent_ids: ["874797c3a73b60d2187ed6e2fcabd289ff75171e"],
- trailers: []
- }
- end
-end
diff --git a/ruby/spec/lib/gitlab/git/hook_spec.rb b/ruby/spec/lib/gitlab/git/hook_spec.rb
deleted file mode 100644
index 1d5454728..000000000
--- a/ruby/spec/lib/gitlab/git/hook_spec.rb
+++ /dev/null
@@ -1,144 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::Git::Hook do
- include TestRepo
-
- describe '.directory' do
- it 'does not raise an KeyError' do
- expect { described_class.directory }.not_to raise_error
- end
- end
-
- describe '#trigger' do
- let(:tmp_dir) { Dir.mktmpdir }
- let(:hook_names) { %w[pre-receive post-receive update] }
- let(:repo) { gitlab_git_from_gitaly(test_repo_read_only) }
- let(:push_options) do
- Gitlab::Git::PushOptions.new(['ci.skip'])
- end
-
- def trigger_with_stub_data(hook, push_options)
- hook.trigger('user-1', 'admin', '0' * 40, 'a' * 40, 'master', push_options: push_options)
- end
-
- before do
- hook_names.each do |f|
- path = File.join(tmp_dir, f)
- File.write(path, script)
- FileUtils.chmod("u+x", path)
- end
-
- allow(Gitlab.config.git).to receive(:hooks_directory).and_return(tmp_dir)
- end
-
- after do
- FileUtils.remove_entry(tmp_dir)
- end
-
- context 'when the hooks require environment variables' do
- let(:vars) do
- {
- 'GITALY_HOOKS_PAYLOAD' => Base64.strict_encode64({
- repository: repo.gitaly_repository.to_json,
- binary_directory: Gitlab.config.gitaly.bin_dir,
- git_path: Gitlab.config.git.bin_path,
- internal_socket: Gitlab.config.gitaly.internal_socket,
- internal_socket_token: nil,
- user_details: {
- userid: 'user-123',
- username: 'janedoe',
- protocol: 'web'
- }
- }.to_json),
- 'PWD' => repo.path,
- 'GIT_DIR' => repo.path
- }
- end
-
- let(:script) do
- [
- "#!/bin/sh",
- vars.map do |key, value|
- <<-SCRIPT
- if [ x$#{key} != x#{value} ]; then
- echo "unexpected value: #{key}=$#{key}"
- exit 1
- fi
- SCRIPT
- end.join,
- "exit 0"
- ].join("\n")
- end
-
- it 'returns true' do
- hook_names.each do |hook|
- trigger_result = described_class.new(hook, repo)
- .trigger('user-123', 'janedoe', '0' * 40, 'a' * 40, 'master', push_options: push_options)
-
- expect(trigger_result.first).to be(true), "#{hook} failed: #{trigger_result.last}"
- end
- end
- end
-
- context 'when the hooks are successful' do
- let(:script) { "#!/bin/sh\nexit 0\n" }
-
- it 'returns true' do
- hook_names.each do |hook|
- trigger_result = described_class.new(hook, repo)
- .trigger('user-456', 'admin', '0' * 40, 'a' * 40, 'master', push_options: push_options)
-
- expect(trigger_result.first).to be(true)
- end
- end
- end
-
- context 'when the hooks fail' do
- let(:script) { "#!/bin/sh\nexit 1\n" }
-
- it 'returns false' do
- hook_names.each do |name|
- hook = described_class.new(name, repo)
- trigger_result = trigger_with_stub_data(hook, push_options)
-
- expect(trigger_result.first).to be(false)
- end
- end
- end
-
- context 'when push options are passed' do
- let(:script) do
- <<~HOOK
- #!/usr/bin/env ruby
- unless ENV['GIT_PUSH_OPTION_COUNT'] == '1' && ENV['GIT_PUSH_OPTION_0'] == 'ci.skip'
- abort 'missing GIT_PUSH_OPTION env vars'
- end
- HOOK
- end
-
- context 'for pre-receive and post-receive hooks' do
- let(:hooks) do
- %w[pre-receive post-receive].map { |name| described_class.new(name, repo) }
- end
-
- it 'sets the push options environment variables' do
- hooks.each do |hook|
- trigger_result = trigger_with_stub_data(hook, push_options)
-
- expect(trigger_result.first).to be(true)
- end
- end
- end
-
- context 'for update hook' do
- let(:hook) { described_class.new('update', repo) }
-
- it 'does not set the push options environment variables' do
- trigger_result = trigger_with_stub_data(hook, push_options)
-
- expect(trigger_result.first).to be(false)
- end
- end
- end
- end
-end
diff --git a/ruby/spec/lib/gitlab/git/popen_spec.rb b/ruby/spec/lib/gitlab/git/popen_spec.rb
deleted file mode 100644
index 6272b7c17..000000000
--- a/ruby/spec/lib/gitlab/git/popen_spec.rb
+++ /dev/null
@@ -1,108 +0,0 @@
-require 'spec_helper'
-
-describe 'Gitlab::Git::Popen' do
- let(:path) { Dir.mktmpdir }
-
- let(:klass) do
- Class.new(Object) do
- include Gitlab::Git::Popen
- end
- end
-
- after do
- FileUtils.remove_entry path
- end
-
- context 'popen' do
- context 'zero status' do
- let(:result) { klass.new.popen(%w(ls), path) }
- let(:status) { result.last }
-
- it { expect(status).to be_zero }
- end
-
- context 'non-zero status' do
- let(:result) { klass.new.popen(%w(cat NOTHING), path) }
- let(:output) { result.first }
- let(:status) { result.last }
-
- it { expect(status).to eq(1) }
- it { expect(output).to include('No such file or directory') }
- end
-
- context 'when stderr is not included' do
- let(:result) { klass.new.popen(%w(cat NOTHING), path, include_stderr: false) }
- let(:output) { result.first }
- let(:status) { result.last }
-
- it { expect(status).to eq(1) }
- it { expect(output).to eq('') }
- end
-
- context 'when stderr is included' do
- let(:result) { klass.new.popen(['ruby', '-e', 'warn "hello world"'], path, include_stderr: true) }
- let(:output) { result.first }
- let(:status) { result.last }
-
- it { expect(status).to eq(0) }
- it { expect(output).to eq("hello world\n") }
- end
-
- context 'unsafe string command' do
- it 'raises an error when it gets called with a string argument' do
- expect { klass.new.popen('ls', path) }.to raise_error(RuntimeError)
- end
- end
-
- context 'with custom options' do
- let(:vars) { { 'foobar' => 123, 'PWD' => path } }
- let(:options) { { chdir: path } }
-
- it 'calls popen3 with the provided environment variables' do
- expect(Open3).to receive(:popen3).with(vars, 'ls', options)
-
- klass.new.popen(%w(ls), path, { 'foobar' => 123 }) # rubocop:disable Style/BracesAroundHashParameters:
- end
- end
-
- context 'use stdin' do
- let(:result) { klass.new.popen(%w[cat], path) { |stdin| stdin.write 'hello' } }
- let(:output) { result.first }
- let(:status) { result.last }
-
- it { expect(status).to be_zero }
- it { expect(output).to eq('hello') }
- end
-
- context 'with lazy block' do
- it 'yields a lazy io' do
- expect_lazy_io = lambda do |io|
- expect(io).to be_a Enumerator::Lazy
- expect(io.inspect).to include('#<IO:fd')
- end
-
- klass.new.popen(%w[ls], path, lazy_block: expect_lazy_io)
- end
-
- it "doesn't wait for process exit" do
- Timeout.timeout(2) do
- klass.new.popen(%w[yes], path, lazy_block: ->(io) {})
- end
- end
- end
-
- context 'with non ASCII output' do
- let(:stdin) { StringIO.new }
- let(:stdout) { StringIO.new("Preparando \xC3\xA1rbol de trabajo") }
- let(:stderr) { StringIO.new("UTF-8 error é").set_encoding('UTF-8') }
- let(:process_status) { double('Process::Status', exitstatus: 0) }
- let(:wait_thr) { double('Process::Waiter', value: process_status) }
-
- it "handles the output correctly" do
- expect(Open3).to receive(:popen3).and_yield(stdin, stdout, stderr, wait_thr)
-
- klass.new.popen(%w[ls], path)
- end
- end
- end
-end
diff --git a/ruby/spec/lib/gitlab/git/push_options_spec.rb b/ruby/spec/lib/gitlab/git/push_options_spec.rb
deleted file mode 100644
index d2c74f399..000000000
--- a/ruby/spec/lib/gitlab/git/push_options_spec.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-describe Gitlab::Git::PushOptions do
- subject { described_class.new(options) }
-
- describe '#env_data' do
- context 'when push options are set' do
- let(:options) { ['ci.skip', 'test=value'] }
-
- it 'sets GIT_PUSH_OPTION environment variables' do
- env_data = subject.env_data
-
- expect(env_data.count).to eq(3)
- expect(env_data['GIT_PUSH_OPTION_COUNT']).to eq('2')
- expect(env_data['GIT_PUSH_OPTION_0']).to eq('ci.skip')
- expect(env_data['GIT_PUSH_OPTION_1']).to eq('test=value')
- end
- end
-
- context 'when push options are not set' do
- let(:options) { [] }
-
- it 'does not set any variable' do
- env_data = subject.env_data
-
- expect(env_data).to eq({})
- end
- end
- end
-end
diff --git a/ruby/spec/lib/gitlab/git/repository_spec.rb b/ruby/spec/lib/gitlab/git/repository_spec.rb
deleted file mode 100644
index 573058b25..000000000
--- a/ruby/spec/lib/gitlab/git/repository_spec.rb
+++ /dev/null
@@ -1,249 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::Git::Repository do # rubocop:disable Metrics/BlockLength
- include TestRepo
- include Gitlab::EncodingHelper
- using RSpec::Parameterized::TableSyntax
-
- let(:mutable_repository) { gitlab_git_from_gitaly(new_mutable_git_test_repo) }
- let(:repository) { gitlab_git_from_gitaly(git_test_repo_read_only) }
- let(:repository_path) { repository.path }
- let(:repository_rugged) { Rugged::Repository.new(repository_path) }
- let(:storage_path) { DEFAULT_STORAGE_DIR }
- let(:user) { Gitlab::Git::User.new('johndone', 'John Doe', 'johndoe@mail.com', 'user-1') }
-
- describe '.from_gitaly_with_block' do
- let(:call_metadata) do
- {
- 'user-agent' => 'grpc-go/1.9.1',
- 'gitaly-storage-path' => DEFAULT_STORAGE_DIR,
- 'gitaly-repo-path' => TEST_REPO_PATH,
- 'gitaly-gl-repository' => 'project-52',
- 'gitaly-repo-alt-dirs' => ''
- }
- end
- let(:call) { double(metadata: call_metadata) }
-
- it 'cleans up the repository' do
- described_class.from_gitaly_with_block(test_repo_read_only, call) do |repository|
- expect(repository.rugged).to receive(:close)
- end
- end
-
- it 'returns the passed result of the block passed' do
- result = described_class.from_gitaly_with_block(test_repo_read_only, call) { 'Hello world' }
-
- expect(result).to eq('Hello world')
- end
- end
-
- describe "Respond to" do
- subject { repository }
-
- it { is_expected.to respond_to(:root_ref) }
- it { is_expected.to respond_to(:tags) }
- end
-
- describe '#root_ref' do
- it 'calls #discover_default_branch' do
- expect(repository).to receive(:discover_default_branch)
- repository.root_ref
- end
- end
-
- describe '#branch_names' do
- subject { repository.branch_names }
-
- it 'has SeedRepo::Repo::BRANCHES.size elements' do
- expect(subject.size).to eq(SeedRepo::Repo::BRANCHES.size)
- end
-
- it { is_expected.to include("master") }
- it { is_expected.not_to include("branch-from-space") }
- end
-
- describe '#tags' do
- describe 'first tag' do
- let(:tag) { repository.tags.first }
-
- it { expect(tag.name).to eq("v1.0.0") }
- it { expect(tag.target).to eq("f4e6814c3e4e7a0de82a9e7cd20c626cc963a2f8") }
- it { expect(tag.dereferenced_target.sha).to eq("6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9") }
- it { expect(tag.message).to eq("Release") }
- end
-
- describe 'last tag' do
- let(:tag) { repository.tags.last }
-
- it { expect(tag.name).to eq("v1.2.1") }
- it { expect(tag.target).to eq("2ac1f24e253e08135507d0830508febaaccf02ee") }
- it { expect(tag.dereferenced_target.sha).to eq("fa1b1e6c004a68b7d8763b86455da9e6b23e36d6") }
- it { expect(tag.message).to eq("Version 1.2.1") }
- end
-
- it { expect(repository.tags.size).to eq(SeedRepo::Repo::TAGS.size) }
- end
-
- describe '#empty?' do
- it { expect(repository).not_to be_empty }
- end
-
- describe '#merge_base' do
- where(:from, :to, :result) do
- '570e7b2abdd848b95f2f578043fc23bd6f6fd24d' | '40f4a7a617393735a95a0bb67b08385bc1e7c66d' | '570e7b2abdd848b95f2f578043fc23bd6f6fd24d'
- '40f4a7a617393735a95a0bb67b08385bc1e7c66d' | '570e7b2abdd848b95f2f578043fc23bd6f6fd24d' | '570e7b2abdd848b95f2f578043fc23bd6f6fd24d'
- '40f4a7a617393735a95a0bb67b08385bc1e7c66d' | 'foobar' | nil
- 'foobar' | '40f4a7a617393735a95a0bb67b08385bc1e7c66d' | nil
- end
-
- with_them do
- it { expect(repository.merge_base(from, to)).to eq(result) }
- end
- end
-
- describe '#find_branch' do
- it 'should return a Branch for master' do
- branch = repository.find_branch('master')
-
- expect(branch).to be_a_kind_of(Gitlab::Git::Branch)
- expect(branch.name).to eq('master')
- end
-
- it 'should handle non-existent branch' do
- branch = repository.find_branch('this-is-garbage')
-
- expect(branch).to eq(nil)
- end
- end
-
- describe '#branches' do
- subject { repository.branches }
-
- context 'with local and remote branches' do
- let(:repository) { mutable_repository }
-
- before do
- create_remote_branch('joe', 'remote_branch', 'master')
- create_branch(repository, 'local_branch', 'master')
- end
-
- it 'returns the local and remote branches' do
- expect(subject.any? { |b| b.name == 'joe/remote_branch' }).to eq(true)
- expect(subject.any? { |b| b.name == 'local_branch' }).to eq(true)
- end
- end
- end
-
- describe '#branch_exists?' do
- it 'returns true for an existing branch' do
- expect(repository.branch_exists?('master')).to eq(true)
- end
-
- it 'returns false for a non-existing branch' do
- expect(repository.branch_exists?('kittens')).to eq(false)
- end
-
- it 'returns false when using an invalid branch name' do
- expect(repository.branch_exists?('.bla')).to eq(false)
- end
- end
-
- describe '#with_repo_branch_commit' do
- context 'when repository is empty' do
- let(:repository) { gitlab_git_from_gitaly(new_empty_test_repo) }
-
- it 'yields nil' do
- expect do |block|
- repository.with_repo_branch_commit('master', &block)
- end.to yield_with_args(nil)
- end
- end
-
- context 'when repository is not empty' do
- let(:start_commit) { repository.commit }
-
- it 'yields the commit for the SHA' do
- expect do |block|
- repository.with_repo_branch_commit(start_commit.sha, &block)
- end.to yield_with_args(start_commit)
- end
-
- it 'yields the commit for the branch' do
- expect do |block|
- repository.with_repo_branch_commit('master', &block)
- end.to yield_with_args(start_commit)
- end
- end
- end
-
- describe '#cleanup' do
- context 'when Rugged has been called' do
- it 'calls close on Rugged::Repository' do
- rugged = repository.rugged
-
- expect(rugged).to receive(:close).and_call_original
-
- repository.cleanup
- end
- end
-
- context 'when Rugged has not been called' do
- it 'does not call close on Rugged::Repository' do
- expect(repository).not_to receive(:rugged)
-
- repository.cleanup
- end
- end
- end
-
- describe '#rugged' do
- after do
- Thread.current[described_class::RUGGED_KEY] = nil
- end
-
- it 'stores reference in Thread.current' do
- Thread.current[described_class::RUGGED_KEY] = []
-
- 2.times do
- rugged = repository.rugged
-
- expect(rugged).to be_a(Rugged::Repository)
- expect(Thread.current[described_class::RUGGED_KEY]).to eq([rugged])
- end
- end
-
- it 'does not store reference if Thread.current is not set up' do
- rugged = repository.rugged
-
- expect(rugged).to be_a(Rugged::Repository)
- expect(Thread.current[described_class::RUGGED_KEY]).to be_nil
- end
- end
-
- describe '#head_symbolic_ref' do
- subject { repository.head_symbolic_ref }
-
- it 'returns the symbolic ref in HEAD' do
- expect(subject).to eq('master')
- end
-
- context 'when repo is empty' do
- let(:repository) { gitlab_git_from_gitaly(new_empty_test_repo) }
-
- it 'returns the symbolic ref in HEAD' do
- repository.rugged.head = 'refs/heads/foo'
-
- expect(subject).to eq('foo')
- end
- end
- end
-
- def create_remote_branch(remote_name, branch_name, source_branch_name)
- source_branch = repository.branches.find { |branch| branch.name == source_branch_name }
- repository_rugged.references.create("refs/remotes/#{remote_name}/#{branch_name}", source_branch.dereferenced_target.sha)
- end
-
- def create_branch(repository, branch_name, start_point = 'HEAD')
- repository.rugged.branches.create(branch_name, start_point)
- end
-end
diff --git a/ruby/spec/lib/gitlab/git/user_spec.rb b/ruby/spec/lib/gitlab/git/user_spec.rb
deleted file mode 100644
index 778fc3c80..000000000
--- a/ruby/spec/lib/gitlab/git/user_spec.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::Git::User do
- let(:username) { 'janedoe' }
- let(:name) { 'Jane Doé' }
- let(:email) { 'janedoé@example.com' }
- let(:gl_id) { 'user-123' }
- let(:user) do
- described_class.new(username, name, email, gl_id)
- end
-
- subject { described_class.new(username, name, email, gl_id) }
-
- describe '.from_gitaly' do
- let(:gitaly_user) do
- Gitaly::User.new(gl_username: username, name: name.b, email: email.b, gl_id: gl_id)
- end
-
- subject { described_class.from_gitaly(gitaly_user) }
-
- it { expect(subject).to eq(user) }
- end
-
- describe '#==' do
- def eq_other(username, name, email, gl_id)
- eq(described_class.new(username, name, email, gl_id))
- end
-
- it { expect(subject).to eq_other(username, name, email, gl_id) }
-
- it { expect(subject).not_to eq_other(nil, nil, nil, nil) }
- it { expect(subject).not_to eq_other(username + 'x', name, email, gl_id) }
- it { expect(subject).not_to eq_other(username, name + 'x', email, gl_id) }
- it { expect(subject).not_to eq_other(username, name, email + 'x', gl_id) }
- it { expect(subject).not_to eq_other(username, name, email, gl_id + 'x') }
- end
-
- describe '#git_env' do
- let(:git_env) { subject.git_env }
-
- it 'returns the user environment variables' do
- expect(git_env['GIT_COMMITTER_NAME']).to eq(name)
- expect(git_env['GIT_COMMITTER_EMAIL']).to eq(email)
- expect(git_env['GL_ID']).to eq(gl_id)
- end
- end
-end
diff --git a/ruby/spec/spec_helper.rb b/ruby/spec/spec_helper.rb
index dcd20550e..d65ae3b22 100644
--- a/ruby/spec/spec_helper.rb
+++ b/ruby/spec/spec_helper.rb
@@ -1,5 +1,4 @@
require_relative '../lib/gitaly_server.rb'
-require_relative '../lib/gitlab/git.rb'
require_relative 'support/sentry.rb'
require 'timecop'
require 'rspec-parameterized'
diff --git a/ruby/spec/test_repo_helper.rb b/ruby/spec/test_repo_helper.rb
index e8fd142a2..a71c763f2 100644
--- a/ruby/spec/test_repo_helper.rb
+++ b/ruby/spec/test_repo_helper.rb
@@ -48,43 +48,10 @@ module TestRepo
end
end
- def git_test_repo_read_only
- Gitaly::Repository.new(storage_name: DEFAULT_STORAGE_NAME, relative_path: File.basename(GIT_TEST_REPO_PATH))
- end
-
def test_repo_read_only
Gitaly::Repository.new(storage_name: DEFAULT_STORAGE_NAME, relative_path: File.basename(TEST_REPO_PATH))
end
- def new_mutable_test_repo
- relative_path = random_repository_relative_path(:mutable)
- TestRepo.clone_new_repo!(TEST_REPO_ORIGIN, File.join(DEFAULT_STORAGE_DIR, relative_path))
- Gitaly::Repository.new(storage_name: DEFAULT_STORAGE_NAME, relative_path: relative_path)
- end
-
- def new_mutable_git_test_repo
- relative_path = random_repository_relative_path(:mutable)
- TestRepo.clone_new_repo!(GIT_TEST_REPO_ORIGIN, File.join(DEFAULT_STORAGE_DIR, relative_path))
- Gitaly::Repository.new(storage_name: DEFAULT_STORAGE_NAME, relative_path: relative_path)
- end
-
- def new_broken_test_repo
- relative_path = random_repository_relative_path(:broken)
- repo_path = File.join(DEFAULT_STORAGE_DIR, relative_path)
- TestRepo.clone_new_repo!(TEST_REPO_ORIGIN, repo_path)
-
- refs_path = File.join(repo_path, 'refs')
- FileUtils.rm_r(refs_path)
-
- Gitaly::Repository.new(storage_name: DEFAULT_STORAGE_NAME, relative_path: relative_path)
- end
-
- def new_empty_test_repo
- relative_path = random_repository_relative_path(:mutable)
- TestRepo.init_new_repo!(File.join(DEFAULT_STORAGE_DIR, relative_path))
- Gitaly::Repository.new(storage_name: DEFAULT_STORAGE_NAME, relative_path: relative_path)
- end
-
def rugged_from_gitaly(gitaly_repo)
Rugged::Repository.new(repo_path_from_gitaly(gitaly_repo))
end
@@ -96,21 +63,6 @@ module TestRepo
File.join(DEFAULT_STORAGE_DIR, gitaly_repo.relative_path)
end
- def gitlab_git_from_gitaly(gitaly_repo)
- Gitlab::Git::Repository.new(
- gitaly_repo,
- repo_path_from_gitaly(gitaly_repo),
- 'project-123',
- ''
- )
- end
-
- def repository_from_relative_path(relative_path)
- gitlab_git_from_gitaly(
- Gitaly::Repository.new(storage_name: DEFAULT_STORAGE_NAME, relative_path: relative_path)
- )
- end
-
def self.clone_new_repo!(origin, destination)
env = {}
env['GIT_EXEC_PATH'] = GIT_EXEC_PATH if defined?(GIT_EXEC_PATH)
@@ -119,18 +71,6 @@ module TestRepo
abort "Failed to clone test repo. Try running 'make prepare-tests' and try again."
end
-
- def self.init_new_repo!(destination)
- return if system(Gitlab.config.git.bin_path, "-c", "init.templateDir=", "init", "--quiet", "--bare", destination.to_s)
-
- abort "Failed to init test repo."
- end
-
- private
-
- def random_repository_relative_path(prefix)
- "#{prefix}-#{SecureRandom.hex(6)}.git"
- end
end
TestRepo.prepare_test_repository