diff options
author | Jacob Vosmaer (GitLab) <jacob@gitlab.com> | 2018-07-11 18:51:24 +0300 |
---|---|---|
committer | Alejandro Rodríguez <alejorro70@gmail.com> | 2018-07-11 18:51:24 +0300 |
commit | 4e9ef2fe45b8a5b1459495083e3709287af7ee8a (patch) | |
tree | 2d4d9b4290daf99ecf309d983efb1fce4ca0a885 /ruby/vendor | |
parent | 1161e9e476d36f005eef3842cd60edacf057df1d (diff) |
Stop vendoring some gitlab_git files we don't need
Diffstat (limited to 'ruby/vendor')
13 files changed, 0 insertions, 957 deletions
diff --git a/ruby/vendor/gitlab_git/lib/gitlab/git/blob_snippet.rb b/ruby/vendor/gitlab_git/lib/gitlab/git/blob_snippet.rb deleted file mode 100644 index 68116e775..000000000 --- a/ruby/vendor/gitlab_git/lib/gitlab/git/blob_snippet.rb +++ /dev/null @@ -1,34 +0,0 @@ -# Gitaly note: JV: no RPC's here. - -module Gitlab - module Git - class BlobSnippet - include Linguist::BlobHelper - - attr_accessor :ref - attr_accessor :lines - attr_accessor :filename - attr_accessor :startline - - def initialize(ref, lines, startline, filename) - @ref, @lines, @startline, @filename = ref, lines, startline, filename - end - - def data - lines&.join("\n") - end - - def name - filename - end - - def size - data.length - end - - def mode - nil - end - end - end -end diff --git a/ruby/vendor/gitlab_git/lib/gitlab/git/compare.rb b/ruby/vendor/gitlab_git/lib/gitlab/git/compare.rb deleted file mode 100644 index 7cb842256..000000000 --- a/ruby/vendor/gitlab_git/lib/gitlab/git/compare.rb +++ /dev/null @@ -1,45 +0,0 @@ -# Gitaly note: JV: no RPC's here. - -module Gitlab - module Git - class Compare - attr_reader :head, :base, :straight - - def initialize(repository, base, head, straight: false) - @repository = repository - @straight = straight - - unless base && head - @commits = [] - return - end - - @base = Gitlab::Git::Commit.find(repository, base.try(:strip)) - @head = Gitlab::Git::Commit.find(repository, head.try(:strip)) - - @commits = [] unless @base && @head - @commits = [] if same - end - - def same - @base && @head && @base.id == @head.id - end - - def commits - return @commits if defined?(@commits) - - @commits = Gitlab::Git::Commit.between(@repository, @base.id, @head.id) - end - - def diffs(options = {}) - unless @head && @base - return Gitlab::Git::DiffCollection.new([]) - end - - paths = options.delete(:paths) || [] - options[:straight] = @straight - Gitlab::Git::Diff.between(@repository, @head.id, @base.id, options, *paths) - end - end - end -end diff --git a/ruby/vendor/gitlab_git/lib/gitlab/git/diff_collection.rb b/ruby/vendor/gitlab_git/lib/gitlab/git/diff_collection.rb deleted file mode 100644 index 219c69893..000000000 --- a/ruby/vendor/gitlab_git/lib/gitlab/git/diff_collection.rb +++ /dev/null @@ -1,154 +0,0 @@ -# Gitaly note: JV: no RPC's here. - -module Gitlab - module Git - class DiffCollection - include Enumerable - - DEFAULT_LIMITS = { max_files: 100, max_lines: 5000 }.freeze - - attr_reader :limits - - delegate :max_files, :max_lines, :max_bytes, :safe_max_files, :safe_max_lines, :safe_max_bytes, to: :limits - - def self.collection_limits(options = {}) - limits = {} - limits[:max_files] = options.fetch(:max_files, DEFAULT_LIMITS[:max_files]) - limits[:max_lines] = options.fetch(:max_lines, DEFAULT_LIMITS[:max_lines]) - limits[:max_bytes] = limits[:max_files] * 5.kilobytes # Average 5 KB per file - limits[:safe_max_files] = [limits[:max_files], DEFAULT_LIMITS[:max_files]].min - limits[:safe_max_lines] = [limits[:max_lines], DEFAULT_LIMITS[:max_lines]].min - limits[:safe_max_bytes] = limits[:safe_max_files] * 5.kilobytes # Average 5 KB per file - - OpenStruct.new(limits) - end - - def initialize(iterator, options = {}) - @iterator = iterator - @limits = self.class.collection_limits(options) - @enforce_limits = !!options.fetch(:limits, true) - @expanded = !!options.fetch(:expanded, true) - - @line_count = 0 - @byte_count = 0 - @overflow = false - @empty = true - @array = Array.new - end - - def each(&block) - @array.each(&block) - - return if @overflow - return if @iterator.nil? - - if @iterator.is_a?(Gitlab::GitalyClient::DiffStitcher) - each_gitaly_patch(&block) - else - each_serialized_patch(&block) - end - - @populated = true - - # Allow iterator to be garbage-collected. It cannot be reused anyway. - @iterator = nil - end - - def empty? - any? # Make sure the iterator has been exercised - @empty - end - - def overflow? - populate! - !!@overflow - end - - def size - @size ||= count # forces a loop using each method - end - - def real_size - populate! - - if @overflow - "#{size}+" - else - size.to_s - end - end - - def decorate! - collection = each_with_index do |element, i| - @array[i] = yield(element) - end - collection - end - - alias_method :to_ary, :to_a - - private - - def populate! - return if @populated - - each { nil } # force a loop through all diffs - nil - end - - def over_safe_limits?(files) - files >= safe_max_files || @line_count > safe_max_lines || @byte_count >= safe_max_bytes - end - - def each_gitaly_patch - i = @array.length - - @iterator.each do |raw| - diff = Gitlab::Git::Diff.new(raw, expanded: !@enforce_limits || @expanded) - - if raw.overflow_marker - @overflow = true - break - end - - yield @array[i] = diff - i += 1 - end - end - - def each_serialized_patch - i = @array.length - - @iterator.each do |raw| - @empty = false - - if @enforce_limits && i >= max_files - @overflow = true - break - end - - expanded = !@enforce_limits || @expanded - - diff = Gitlab::Git::Diff.new(raw, expanded: expanded) - - if !expanded && over_safe_limits?(i) && diff.line_count > 0 - diff.collapse! - end - - @line_count += diff.line_count - @byte_count += diff.diff.bytesize - - if @enforce_limits && (@line_count >= max_lines || @byte_count >= max_bytes) - # This last Diff instance pushes us over the lines limit. We stop and - # discard it. - @overflow = true - break - end - - yield @array[i] = diff - i += 1 - end - end - end - end -end diff --git a/ruby/vendor/gitlab_git/lib/gitlab/git/gitmodules_parser.rb b/ruby/vendor/gitlab_git/lib/gitlab/git/gitmodules_parser.rb deleted file mode 100644 index 4b505312f..000000000 --- a/ruby/vendor/gitlab_git/lib/gitlab/git/gitmodules_parser.rb +++ /dev/null @@ -1,81 +0,0 @@ -# Gitaly note: JV: no RPC's here. - -module Gitlab - module Git - class GitmodulesParser - def initialize(content) - @content = content - end - - # Parses the contents of a .gitmodules file and returns a hash of - # submodule information, indexed by path. - def parse - reindex_by_path(get_submodules_by_name) - end - - private - - class State - def initialize - @result = {} - @current_submodule = nil - end - - def start_section(section) - # In some .gitmodules files (e.g. nodegit's), a header - # with the same name appears multiple times; we want to - # accumulate the configs across these - @current_submodule = @result[section] || { 'name' => section } - @result[section] = @current_submodule - end - - def set_attribute(attr, value) - @current_submodule[attr] = value - end - - def section_started? - !@current_submodule.nil? - end - - def submodules_by_name - @result - end - end - - def get_submodules_by_name - iterator = State.new - - @content.split("\n").each_with_object(iterator) do |text, iterator| - text.chomp! - - next if text =~ /^\s*#/ - - if text =~ /\A\[submodule "(?<name>[^"]+)"\]\z/ - iterator.start_section($~[:name]) - else - next unless iterator.section_started? - - next unless text =~ /\A\s*(?<key>\w+)\s*=\s*(?<value>.*)\z/ - - value = $~[:value] - iterator.set_attribute($~[:key], value) - end - end - - iterator.submodules_by_name - end - - def reindex_by_path(submodules_by_name) - # Convert from an indexed by name to an array indexed by path - # If a submodule doesn't have a path, it is considered bogus - # and is ignored - submodules_by_name.each_with_object({}) do |(name, data), results| - path = data.delete 'path' - next unless path - - results[path] = data - end - end - end - end -end diff --git a/ruby/vendor/gitlab_git/lib/gitlab/git/storage.rb b/ruby/vendor/gitlab_git/lib/gitlab/git/storage.rb deleted file mode 100644 index 5933312b0..000000000 --- a/ruby/vendor/gitlab_git/lib/gitlab/git/storage.rb +++ /dev/null @@ -1,25 +0,0 @@ -module Gitlab - module Git - module Storage - class Inaccessible < StandardError - attr_reader :retry_after - - def initialize(message = nil, retry_after = nil) - super(message) - @retry_after = retry_after - end - end - - CircuitOpen = Class.new(Inaccessible) - Misconfiguration = Class.new(Inaccessible) - Failing = Class.new(Inaccessible) - - REDIS_KEY_PREFIX = 'storage_accessible:'.freeze - REDIS_KNOWN_KEYS = "#{REDIS_KEY_PREFIX}known_keys_set".freeze - - def self.redis - Gitlab::Redis::SharedState - end - end - end -end diff --git a/ruby/vendor/gitlab_git/lib/gitlab/git/storage/checker.rb b/ruby/vendor/gitlab_git/lib/gitlab/git/storage/checker.rb deleted file mode 100644 index 391f0d705..000000000 --- a/ruby/vendor/gitlab_git/lib/gitlab/git/storage/checker.rb +++ /dev/null @@ -1,120 +0,0 @@ -module Gitlab - module Git - module Storage - class Checker - include CircuitBreakerSettings - - attr_reader :storage_path, :storage, :hostname, :logger - METRICS_MUTEX = Mutex.new - STORAGE_TIMING_BUCKETS = [0.1, 0.15, 0.25, 0.33, 0.5, 1, 1.5, 2.5, 5, 10, 15].freeze - - def self.check_all(logger = Rails.logger) - threads = Gitlab.config.repositories.storages.keys.map do |storage_name| - Thread.new do - Thread.current[:result] = new(storage_name, logger).check_with_lease - end - end - - threads.map do |thread| - thread.join - thread[:result] - end - end - - def self.check_histogram - @check_histogram ||= - METRICS_MUTEX.synchronize do - @check_histogram || Gitlab::Metrics.histogram(:circuitbreaker_storage_check_duration_seconds, - 'Storage check time in seconds', - {}, - STORAGE_TIMING_BUCKETS - ) - end - end - - def initialize(storage, logger = Rails.logger) - @storage = storage - config = Gitlab.config.repositories.storages[@storage] - @storage_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access { config.legacy_disk_path } - @logger = logger - - @hostname = Gitlab::Environment.hostname - end - - def check_with_lease - lease_key = "storage_check:#{cache_key}" - lease = Gitlab::ExclusiveLease.new(lease_key, timeout: storage_timeout) - result = { storage: storage, success: nil } - - if uuid = lease.try_obtain - result[:success] = check - - Gitlab::ExclusiveLease.cancel(lease_key, uuid) - else - logger.warn("#{hostname}: #{storage}: Skipping check, previous check still running") - end - - result - end - - def check - if perform_access_check - track_storage_accessible - true - else - track_storage_inaccessible - logger.error("#{hostname}: #{storage}: Not accessible.") - false - end - end - - private - - def perform_access_check - start_time = Gitlab::Metrics::System.monotonic_time - - Gitlab::Git::Storage::ForkedStorageCheck.storage_available?(storage_path, storage_timeout, access_retries) - ensure - execution_time = Gitlab::Metrics::System.monotonic_time - start_time - self.class.check_histogram.observe({ storage: storage }, execution_time) - end - - def track_storage_inaccessible - first_failure = current_failure_info.first_failure || Time.now - last_failure = Time.now - - Gitlab::Git::Storage.redis.with do |redis| - redis.pipelined do - redis.hset(cache_key, :first_failure, first_failure.to_i) - redis.hset(cache_key, :last_failure, last_failure.to_i) - redis.hincrby(cache_key, :failure_count, 1) - redis.expire(cache_key, failure_reset_time) - maintain_known_keys(redis) - end - end - end - - def track_storage_accessible - Gitlab::Git::Storage.redis.with do |redis| - redis.pipelined do - redis.hset(cache_key, :first_failure, nil) - redis.hset(cache_key, :last_failure, nil) - redis.hset(cache_key, :failure_count, 0) - maintain_known_keys(redis) - end - end - end - - def maintain_known_keys(redis) - expire_time = Time.now.to_i + failure_reset_time - redis.zadd(Gitlab::Git::Storage::REDIS_KNOWN_KEYS, expire_time, cache_key) - redis.zremrangebyscore(Gitlab::Git::Storage::REDIS_KNOWN_KEYS, '-inf', Time.now.to_i) - end - - def current_failure_info - FailureInfo.load(cache_key) - end - end - end - end -end diff --git a/ruby/vendor/gitlab_git/lib/gitlab/git/storage/circuit_breaker.rb b/ruby/vendor/gitlab_git/lib/gitlab/git/storage/circuit_breaker.rb deleted file mode 100644 index 62427ac9c..000000000 --- a/ruby/vendor/gitlab_git/lib/gitlab/git/storage/circuit_breaker.rb +++ /dev/null @@ -1,78 +0,0 @@ -module Gitlab - module Git - module Storage - class CircuitBreaker - include CircuitBreakerSettings - - attr_reader :storage, - :hostname - - delegate :last_failure, :failure_count, :no_failures?, - to: :failure_info - - def self.for_storage(storage) - cached_circuitbreakers = RequestStore.fetch(:circuitbreaker_cache) do - Hash.new do |hash, storage_name| - hash[storage_name] = build(storage_name) - end - end - - cached_circuitbreakers[storage] - end - - def self.build(storage, hostname = Gitlab::Environment.hostname) - config = Gitlab.config.repositories.storages[storage] - Gitlab::GitalyClient::StorageSettings.allow_disk_access do - if !config.present? - NullCircuitBreaker.new(storage, hostname, error: Misconfiguration.new("Storage '#{storage}' is not configured")) - elsif !config.legacy_disk_path.present? - NullCircuitBreaker.new(storage, hostname, error: Misconfiguration.new("Path for storage '#{storage}' is not configured")) - else - new(storage, hostname) - end - end - end - - def initialize(storage, hostname) - @storage = storage - @hostname = hostname - end - - def perform - return yield unless enabled? - - check_storage_accessible! - - yield - end - - def circuit_broken? - return false if no_failures? - - failure_count > failure_count_threshold - end - - private - - # The circuitbreaker can be enabled for the entire fleet using a Feature - # flag. - # - # Enabling it for a single host can be done setting the - # `GIT_STORAGE_CIRCUIT_BREAKER` environment variable. - def enabled? - ENV['GIT_STORAGE_CIRCUIT_BREAKER'].present? || Feature.enabled?('git_storage_circuit_breaker') - end - - def failure_info - @failure_info ||= FailureInfo.load(cache_key) - end - - def check_storage_accessible! - if circuit_broken? - raise Gitlab::Git::Storage::CircuitOpen.new("Circuit for #{storage} is broken", failure_reset_time) - end - end - end - end - end -end diff --git a/ruby/vendor/gitlab_git/lib/gitlab/git/storage/circuit_breaker_settings.rb b/ruby/vendor/gitlab_git/lib/gitlab/git/storage/circuit_breaker_settings.rb deleted file mode 100644 index c9e225f18..000000000 --- a/ruby/vendor/gitlab_git/lib/gitlab/git/storage/circuit_breaker_settings.rb +++ /dev/null @@ -1,37 +0,0 @@ -module Gitlab - module Git - module Storage - module CircuitBreakerSettings - def failure_count_threshold - application_settings.circuitbreaker_failure_count_threshold - end - - def failure_reset_time - application_settings.circuitbreaker_failure_reset_time - end - - def storage_timeout - application_settings.circuitbreaker_storage_timeout - end - - def access_retries - application_settings.circuitbreaker_access_retries - end - - def check_interval - application_settings.circuitbreaker_check_interval - end - - def cache_key - @cache_key ||= "#{Gitlab::Git::Storage::REDIS_KEY_PREFIX}#{storage}:#{hostname}" - end - - private - - def application_settings - Gitlab::CurrentSettings.current_application_settings - end - end - end - end -end diff --git a/ruby/vendor/gitlab_git/lib/gitlab/git/storage/failure_info.rb b/ruby/vendor/gitlab_git/lib/gitlab/git/storage/failure_info.rb deleted file mode 100644 index 387279c11..000000000 --- a/ruby/vendor/gitlab_git/lib/gitlab/git/storage/failure_info.rb +++ /dev/null @@ -1,39 +0,0 @@ -module Gitlab - module Git - module Storage - class FailureInfo - attr_accessor :first_failure, :last_failure, :failure_count - - def self.reset_all! - Gitlab::Git::Storage.redis.with do |redis| - all_storage_keys = redis.zrange(Gitlab::Git::Storage::REDIS_KNOWN_KEYS, 0, -1) - redis.del(*all_storage_keys) unless all_storage_keys.empty? - end - - RequestStore.delete(:circuitbreaker_cache) - end - - def self.load(cache_key) - first_failure, last_failure, failure_count = Gitlab::Git::Storage.redis.with do |redis| - redis.hmget(cache_key, :first_failure, :last_failure, :failure_count) - end - - last_failure = Time.at(last_failure.to_i) if last_failure.present? - first_failure = Time.at(first_failure.to_i) if first_failure.present? - - new(first_failure, last_failure, failure_count.to_i) - end - - def initialize(first_failure, last_failure, failure_count) - @first_failure = first_failure - @last_failure = last_failure - @failure_count = failure_count - end - - def no_failures? - first_failure.blank? && last_failure.blank? && failure_count == 0 - end - end - end - end -end diff --git a/ruby/vendor/gitlab_git/lib/gitlab/git/storage/forked_storage_check.rb b/ruby/vendor/gitlab_git/lib/gitlab/git/storage/forked_storage_check.rb deleted file mode 100644 index 0a4e557b5..000000000 --- a/ruby/vendor/gitlab_git/lib/gitlab/git/storage/forked_storage_check.rb +++ /dev/null @@ -1,65 +0,0 @@ -module Gitlab - module Git - module Storage - module ForkedStorageCheck - extend self - - def storage_available?(path, timeout_seconds = 5, retries = 1) - partial_timeout = timeout_seconds / retries - status = timeout_check(path, partial_timeout) - - # If the status check did not succeed the first time, we retry a few - # more times to avoid one-off failures - current_attempts = 1 - while current_attempts < retries && !status.success? - status = timeout_check(path, partial_timeout) - current_attempts += 1 - end - - status.success? - end - - def timeout_check(path, timeout_seconds) - filesystem_check_pid = check_filesystem_in_process(path) - - deadline = timeout_seconds.seconds.from_now.utc - wait_time = 0.01 - status = nil - - while status.nil? - - if deadline > Time.now.utc - sleep(wait_time) - _pid, status = Process.wait2(filesystem_check_pid, Process::WNOHANG) - else - Process.kill('KILL', filesystem_check_pid) - # Blocking wait, so we are sure the process is gone before continuing - _pid, status = Process.wait2(filesystem_check_pid) - end - end - - status - end - - # This will spawn a new 2 processes to do the check: - # The outer child (waiter) will spawn another child process (stater). - # - # The stater is the process is performing the actual filesystem check - # the check might hang if the filesystem is acting up. - # In this case we will send a `KILL` to the waiter, which will still - # be responsive while the stater is hanging. - def check_filesystem_in_process(path) - spawn('ruby', '-e', ruby_check, path, [:out, :err] => '/dev/null') - end - - def ruby_check - <<~RUBY_FILESYSTEM_CHECK - inner_pid = fork { File.stat(ARGV.first) } - Process.waitpid(inner_pid) - exit $?.exitstatus - RUBY_FILESYSTEM_CHECK - end - end - end - end -end diff --git a/ruby/vendor/gitlab_git/lib/gitlab/git/storage/health.rb b/ruby/vendor/gitlab_git/lib/gitlab/git/storage/health.rb deleted file mode 100644 index 90bbe85fd..000000000 --- a/ruby/vendor/gitlab_git/lib/gitlab/git/storage/health.rb +++ /dev/null @@ -1,90 +0,0 @@ -module Gitlab - module Git - module Storage - class Health - attr_reader :storage_name, :info - - def self.prefix_for_storage(storage_name) - "#{Gitlab::Git::Storage::REDIS_KEY_PREFIX}#{storage_name}:" - end - - def self.for_all_storages - storage_names = Gitlab.config.repositories.storages.keys - results_per_storage = nil - - Gitlab::Git::Storage.redis.with do |redis| - keys_per_storage = all_keys_for_storages(storage_names, redis) - results_per_storage = load_for_keys(keys_per_storage, redis) - end - - results_per_storage.map do |name, info| - info.each { |i| i[:failure_count] = i[:failure_count].value.to_i } - new(name, info) - end - end - - private_class_method def self.all_keys_for_storages(storage_names, redis) - keys_per_storage = {} - all_keys = redis.zrange(Gitlab::Git::Storage::REDIS_KNOWN_KEYS, 0, -1) - - storage_names.each do |storage_name| - prefix = prefix_for_storage(storage_name) - - keys_per_storage[storage_name] = all_keys.select { |key| key.starts_with?(prefix) } - end - - keys_per_storage - end - - private_class_method def self.load_for_keys(keys_per_storage, redis) - info_for_keys = {} - - redis.pipelined do - keys_per_storage.each do |storage_name, keys_future| - info_for_storage = keys_future.map do |key| - { name: key, failure_count: redis.hget(key, :failure_count) } - end - - info_for_keys[storage_name] = info_for_storage - end - end - - info_for_keys - end - - def self.for_failing_storages - for_all_storages.select(&:failing?) - end - - def initialize(storage_name, info) - @storage_name = storage_name - @info = info - end - - def failing_info - @failing_info ||= info.select { |info_for_host| info_for_host[:failure_count] > 0 } - end - - def failing? - failing_info.any? - end - - def failing_on_hosts - @failing_on_hosts ||= failing_info.map do |info_for_host| - info_for_host[:name].split(':').last - end - end - - def failing_circuit_breakers - @failing_circuit_breakers ||= failing_on_hosts.map do |hostname| - CircuitBreaker.build(storage_name, hostname) - end - end - - def total_failures - @total_failures ||= failing_info.sum { |info_for_host| info_for_host[:failure_count] } - end - end - end - end -end diff --git a/ruby/vendor/gitlab_git/lib/gitlab/git/storage/null_circuit_breaker.rb b/ruby/vendor/gitlab_git/lib/gitlab/git/storage/null_circuit_breaker.rb deleted file mode 100644 index 261c936c6..000000000 --- a/ruby/vendor/gitlab_git/lib/gitlab/git/storage/null_circuit_breaker.rb +++ /dev/null @@ -1,50 +0,0 @@ -module Gitlab - module Git - module Storage - class NullCircuitBreaker - include CircuitBreakerSettings - - # These will have actual values - attr_reader :storage, - :hostname - - # These will always have nil values - attr_reader :storage_path - - delegate :last_failure, :failure_count, :no_failures?, - to: :failure_info - - def initialize(storage, hostname, error: nil) - @storage = storage - @hostname = hostname - @error = error - end - - def perform - @error ? raise(@error) : yield - end - - def circuit_broken? - !!@error - end - - def backing_off? - false - end - - def failure_info - @failure_info ||= - if circuit_broken? - Gitlab::Git::Storage::FailureInfo.new(Time.now, - Time.now, - failure_count_threshold) - else - Gitlab::Git::Storage::FailureInfo.new(nil, - nil, - 0) - end - end - end - end - end -end diff --git a/ruby/vendor/gitlab_git/lib/gitlab/git/tree.rb b/ruby/vendor/gitlab_git/lib/gitlab/git/tree.rb deleted file mode 100644 index cb851b76a..000000000 --- a/ruby/vendor/gitlab_git/lib/gitlab/git/tree.rb +++ /dev/null @@ -1,139 +0,0 @@ -module Gitlab - module Git - class Tree - include Gitlab::EncodingHelper - - attr_accessor :id, :root_id, :name, :path, :flat_path, :type, - :mode, :commit_id, :submodule_url - - class << self - # Get list of tree objects - # for repository based on commit sha and path - # Uses rugged for raw objects - # - # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/320 - def where(repository, sha, path = nil, recursive = false) - path = nil if path == '' || path == '/' - - repository.wrapped_gitaly_errors do - repository.gitaly_commit_client.tree_entries(repository, sha, path, recursive) - end - end - - private - - # Recursive search of tree id for path - # - # Ex. - # blog/ # oid: 1a - # app/ # oid: 2a - # models/ # oid: 3a - # views/ # oid: 4a - # - # - # Tree.find_id_by_path(repo, '1a', 'app/models') # => '3a' - # - def find_id_by_path(repository, root_id, path) - root_tree = repository.lookup(root_id) - path_arr = path.split('/') - - entry = root_tree.find do |entry| - entry[:name] == path_arr[0] && entry[:type] == :tree - end - - return nil unless entry - - if path_arr.size > 1 - path_arr.shift - find_id_by_path(repository, entry[:oid], path_arr.join('/')) - else - entry[:oid] - end - end - - def tree_entries_from_rugged(repository, sha, path, recursive) - current_path_entries = get_tree_entries_from_rugged(repository, sha, path) - ordered_entries = [] - - current_path_entries.each do |entry| - ordered_entries << entry - - if recursive && entry.dir? - ordered_entries.concat(tree_entries_from_rugged(repository, sha, entry.path, true)) - end - end - - ordered_entries - end - - def get_tree_entries_from_rugged(repository, sha, path) - commit = repository.lookup(sha) - root_tree = commit.tree - - tree = if path - id = find_id_by_path(repository, root_tree.oid, path) - if id - repository.lookup(id) - else - [] - end - else - root_tree - end - - tree.map do |entry| - new( - id: entry[:oid], - root_id: root_tree.oid, - name: entry[:name], - type: entry[:type], - mode: entry[:filemode].to_s(8), - path: path ? File.join(path, entry[:name]) : entry[:name], - commit_id: sha - ) - end - rescue Rugged::ReferenceError - [] - end - end - - def initialize(options) - %w(id root_id name path flat_path type mode commit_id).each do |key| - self.send("#{key}=", options[key.to_sym]) # rubocop:disable GitlabSecurity/PublicSend - end - end - - def name - encode! @name - end - - def path - encode! @path - end - - def flat_path - encode! @flat_path - end - - def dir? - type == :tree - end - - def file? - type == :blob - end - - def submodule? - type == :commit - end - - def readme? - name =~ /^readme/i - end - - def contributing? - name =~ /^contributing/i - end - end - end -end |