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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gitlab')
-rw-r--r--lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits.rb14
-rw-r--r--lib/gitlab/background_migration/migrate_stage_status.rb77
-rw-r--r--lib/gitlab/database/migration_helpers.rb5
-rw-r--r--lib/gitlab/git/repository.rb154
-rw-r--r--lib/gitlab/git_access.rb19
-rw-r--r--lib/gitlab/gitaly_client/blob_service.rb13
-rw-r--r--lib/gitlab/gitaly_client/commit_service.rb22
-rw-r--r--lib/gitlab/gitaly_client/ref_service.rb8
-rw-r--r--lib/gitlab/gitaly_client/repository_service.rb5
-rw-r--r--lib/gitlab/import_export/import_export.yml3
-rw-r--r--lib/gitlab/import_export/merge_request_parser.rb2
-rw-r--r--lib/gitlab/job_waiter.rb57
-rw-r--r--lib/gitlab/logger.rb8
-rw-r--r--lib/gitlab/regex.rb3
-rw-r--r--lib/gitlab/sidekiq_status.rb9
-rw-r--r--lib/gitlab/sidekiq_throttler.rb2
-rw-r--r--lib/gitlab/string_range_marker.rb34
17 files changed, 325 insertions, 110 deletions
diff --git a/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits.rb b/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits.rb
index 310a69a4bd4..3fde1b09efb 100644
--- a/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits.rb
+++ b/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits.rb
@@ -81,12 +81,15 @@ module Gitlab
relative_order: index
)
- # Compatibility with old diffs created with Psych.
diff_hash.tap do |hash|
diff_text = hash[:diff]
hash[:too_large] = !!hash[:too_large]
+ hash[:a_mode] ||= guess_mode(hash[:new_file], hash[:diff])
+ hash[:b_mode] ||= guess_mode(hash[:deleted_file], hash[:diff])
+
+ # Compatibility with old diffs created with Psych.
if diff_text.encoding == Encoding::BINARY && !diff_text.ascii_only?
hash[:binary] = true
hash[:diff] = [diff_text].pack('m0')
@@ -97,6 +100,15 @@ module Gitlab
[commit_rows, file_rows]
end
+ # This doesn't have to be 100% accurate, because it's only used for
+ # display - it won't change file modes in the repository. Submodules are
+ # created as 600, regular files as 644.
+ def guess_mode(file_missing, diff)
+ return '0' if file_missing
+
+ diff.include?('Subproject commit') ? '160000' : '100644'
+ end
+
# Unlike MergeRequestDiff#valid_raw_diff?, don't count Rugged objects as
# valid, because we don't render them usefully anyway.
def valid_raw_diffs?(diffs)
diff --git a/lib/gitlab/background_migration/migrate_stage_status.rb b/lib/gitlab/background_migration/migrate_stage_status.rb
new file mode 100644
index 00000000000..b1ff0900709
--- /dev/null
+++ b/lib/gitlab/background_migration/migrate_stage_status.rb
@@ -0,0 +1,77 @@
+module Gitlab
+ module BackgroundMigration
+ class MigrateStageStatus
+ STATUSES = { created: 0, pending: 1, running: 2, success: 3,
+ failed: 4, canceled: 5, skipped: 6, manual: 7 }.freeze
+
+ class Build < ActiveRecord::Base
+ self.table_name = 'ci_builds'
+
+ scope :latest, -> { where(retried: [false, nil]) }
+ scope :created, -> { where(status: 'created') }
+ scope :running, -> { where(status: 'running') }
+ scope :pending, -> { where(status: 'pending') }
+ scope :success, -> { where(status: 'success') }
+ scope :failed, -> { where(status: 'failed') }
+ scope :canceled, -> { where(status: 'canceled') }
+ scope :skipped, -> { where(status: 'skipped') }
+ scope :manual, -> { where(status: 'manual') }
+
+ scope :failed_but_allowed, -> do
+ where(allow_failure: true, status: [:failed, :canceled])
+ end
+
+ scope :exclude_ignored, -> do
+ where("allow_failure = ? OR status IN (?)",
+ false, %w[created pending running success skipped])
+ end
+
+ def self.status_sql
+ scope_relevant = latest.exclude_ignored
+ scope_warnings = latest.failed_but_allowed
+
+ builds = scope_relevant.select('count(*)').to_sql
+ created = scope_relevant.created.select('count(*)').to_sql
+ success = scope_relevant.success.select('count(*)').to_sql
+ manual = scope_relevant.manual.select('count(*)').to_sql
+ pending = scope_relevant.pending.select('count(*)').to_sql
+ running = scope_relevant.running.select('count(*)').to_sql
+ skipped = scope_relevant.skipped.select('count(*)').to_sql
+ canceled = scope_relevant.canceled.select('count(*)').to_sql
+ warnings = scope_warnings.select('count(*) > 0').to_sql
+
+ <<-SQL.strip_heredoc
+ (CASE
+ WHEN (#{builds}) = (#{skipped}) AND (#{warnings}) THEN #{STATUSES[:success]}
+ WHEN (#{builds}) = (#{skipped}) THEN #{STATUSES[:skipped]}
+ WHEN (#{builds}) = (#{success}) THEN #{STATUSES[:success]}
+ WHEN (#{builds}) = (#{created}) THEN #{STATUSES[:created]}
+ WHEN (#{builds}) = (#{success}) + (#{skipped}) THEN #{STATUSES[:success]}
+ WHEN (#{builds}) = (#{success}) + (#{skipped}) + (#{canceled}) THEN #{STATUSES[:canceled]}
+ WHEN (#{builds}) = (#{created}) + (#{skipped}) + (#{pending}) THEN #{STATUSES[:pending]}
+ WHEN (#{running}) + (#{pending}) > 0 THEN #{STATUSES[:running]}
+ WHEN (#{manual}) > 0 THEN #{STATUSES[:manual]}
+ WHEN (#{created}) > 0 THEN #{STATUSES[:running]}
+ ELSE #{STATUSES[:failed]}
+ END)
+ SQL
+ end
+ end
+
+ def perform(start_id, stop_id)
+ status_sql = Build
+ .where('ci_builds.commit_id = ci_stages.pipeline_id')
+ .where('ci_builds.stage = ci_stages.name')
+ .status_sql
+
+ sql = <<-SQL
+ UPDATE ci_stages SET status = (#{status_sql})
+ WHERE ci_stages.status IS NULL
+ AND ci_stages.id BETWEEN #{start_id.to_i} AND #{stop_id.to_i}
+ SQL
+
+ ActiveRecord::Base.connection.execute(sql)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/migration_helpers.rb b/lib/gitlab/database/migration_helpers.rb
index 69ca9aa596b..b83e633c7ed 100644
--- a/lib/gitlab/database/migration_helpers.rb
+++ b/lib/gitlab/database/migration_helpers.rb
@@ -606,6 +606,11 @@ module Gitlab
Arel::Nodes::SqlLiteral.new(replace.to_sql)
end
end
+
+ def remove_foreign_key_without_error(*args)
+ remove_foreign_key(*args)
+ rescue ArgumentError
+ end
end
end
end
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
index 1d5ca68137a..eb3731ba35a 100644
--- a/lib/gitlab/git/repository.rb
+++ b/lib/gitlab/git/repository.rb
@@ -64,7 +64,6 @@ module Gitlab
end
delegate :empty?,
- :bare?,
to: :rugged
delegate :exists?, to: :gitaly_repository_client
@@ -126,6 +125,8 @@ module Gitlab
# 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
+ #
+ # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/474
def find_branch(name, force_reload = false)
reload_rugged if force_reload
@@ -204,21 +205,26 @@ module Gitlab
#
# name - The name of the tag as a String.
def tag_exists?(name)
- !!rugged.tags[name]
+ gitaly_migrate(:ref_exists_tags) do |is_enabled|
+ if is_enabled
+ gitaly_ref_exists?("refs/tags/#{name}")
+ else
+ rugged_tag_exists?(name)
+ end
+ 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
+ gitaly_migrate(:ref_exists_branches) do |is_enabled|
+ if is_enabled
+ gitaly_ref_exists?("refs/heads/#{name}")
+ else
+ rugged_branch_exists?(name)
+ end
+ end
end
# Returns an Array of branch and tag names
@@ -226,10 +232,6 @@ module Gitlab
branch_names + tag_names
end
- def has_commits?
- !empty?
- end
-
# Discovers the default branch based on the repository's available branches
#
# - If no branches are present, returns nil
@@ -569,6 +571,8 @@ module Gitlab
end
# Delete the specified branch from the repository
+ #
+ # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/476
def delete_branch(branch_name)
rugged.branches.delete(branch_name)
end
@@ -578,6 +582,8 @@ module Gitlab
# Examples:
# create_branch("feature")
# create_branch("other-feature", "master")
+ #
+ # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/476
def create_branch(ref, start_point = "HEAD")
rugged_ref = rugged.branches.create(ref, start_point)
target_commit = Gitlab::Git::Commit.find(self, rugged_ref.target)
@@ -587,38 +593,26 @@ module Gitlab
raise InvalidRef.new("Invalid reference #{start_point}")
end
- # Return an array of this repository's remote names
- def remote_names
- rugged.remotes.each_name.to_a
- end
-
# Delete the specified remote from this repository.
def remote_delete(remote_name)
rugged.remotes.delete(remote_name)
+ nil
end
- # Add a new remote to this repository. Returns a Rugged::Remote object
+ # Add a new remote to this repository.
def remote_add(remote_name, url)
rugged.remotes.create(remote_name, url)
+ nil
end
# Update the specified remote using the values in the +options+ hash
#
# Example
# repo.update_remote("origin", url: "path/to/repo")
- def remote_update(remote_name, options = {})
+ def remote_update(remote_name, url:)
# TODO: Implement other remote options
- rugged.remotes.set_url(remote_name, options[:url]) if options[:url]
- end
-
- # Fetch the specified remote
- def fetch(remote_name)
- rugged.remotes[remote_name].fetch
- end
-
- # Push +*refspecs+ to the remote identified by +remote_name+.
- def push(remote_name, *refspecs)
- rugged.remotes[remote_name].push(refspecs)
+ rugged.remotes.set_url(remote_name, url)
+ nil
end
AUTOCRLF_VALUES = {
@@ -653,33 +647,15 @@ module Gitlab
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/328
def copy_gitattributes(ref)
- begin
- commit = lookup(ref)
- rescue Rugged::ReferenceError
- raise InvalidRef.new("Ref #{ref} is invalid")
- end
-
- # Create the paths
- info_dir_path = File.join(path, 'info')
- info_attributes_path = File.join(info_dir_path, 'attributes')
-
- begin
- # Retrieve the contents of the blob
- gitattributes_content = blob_content(commit, '.gitattributes')
- rescue InvalidBlobName
- # No .gitattributes found. Should now remove any info/attributes and return
- File.delete(info_attributes_path) if File.exist?(info_attributes_path)
- return
- end
-
- # Create the info directory if needed
- Dir.mkdir(info_dir_path) unless File.directory?(info_dir_path)
-
- # Write the contents of the .gitattributes file to info/attributes
- # Use binary mode to prevent Rails from converting ASCII-8BIT to UTF-8
- File.open(info_attributes_path, "wb") do |file|
- file.write(gitattributes_content)
+ Gitlab::GitalyClient.migrate(:apply_gitattributes) do |is_enabled|
+ if is_enabled
+ gitaly_copy_gitattributes(ref)
+ else
+ rugged_copy_gitattributes(ref)
+ end
end
+ rescue GRPC::InvalidArgument
+ raise InvalidRef
end
# Returns the Git attributes for the given file path.
@@ -1012,6 +988,68 @@ module Gitlab
raw_output.compact
end
+
+ # Returns true if the given ref name exists
+ #
+ # Ref names must start with `refs/`.
+ def gitaly_ref_exists?(ref_name)
+ gitaly_ref_client.ref_exists?(ref_name)
+ end
+
+ # Returns true if the given tag exists
+ #
+ # name - The name of the tag as a String.
+ def rugged_tag_exists?(name)
+ !!rugged.tags[name]
+ end
+
+ # Returns true if the given branch exists
+ #
+ # name - The name of the branch as a String.
+ def rugged_branch_exists?(name)
+ rugged.branches.exists?(name)
+
+ # If the branch name is invalid (e.g. ".foo") Rugged will raise an error.
+ # Whatever code calls this method shouldn't have to deal with that so
+ # instead we just return `false` (which is true since a branch doesn't
+ # exist when it has an invalid name).
+ rescue Rugged::ReferenceError
+ false
+ end
+
+ def gitaly_copy_gitattributes(revision)
+ gitaly_repository_client.apply_gitattributes(revision)
+ end
+
+ def rugged_copy_gitattributes(ref)
+ begin
+ commit = lookup(ref)
+ rescue Rugged::ReferenceError
+ raise InvalidRef.new("Ref #{ref} is invalid")
+ end
+
+ # Create the paths
+ info_dir_path = File.join(path, 'info')
+ info_attributes_path = File.join(info_dir_path, 'attributes')
+
+ begin
+ # Retrieve the contents of the blob
+ gitattributes_content = blob_content(commit, '.gitattributes')
+ rescue InvalidBlobName
+ # No .gitattributes found. Should now remove any info/attributes and return
+ File.delete(info_attributes_path) if File.exist?(info_attributes_path)
+ return
+ end
+
+ # Create the info directory if needed
+ Dir.mkdir(info_dir_path) unless File.directory?(info_dir_path)
+
+ # Write the contents of the .gitattributes file to info/attributes
+ # Use binary mode to prevent Rails from converting ASCII-8BIT to UTF-8
+ File.open(info_attributes_path, "wb") do |file|
+ file.write(gitattributes_content)
+ end
+ end
end
end
end
diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb
index 0b62911958d..3e8b83c0f90 100644
--- a/lib/gitlab/git_access.rb
+++ b/lib/gitlab/git_access.rb
@@ -4,6 +4,7 @@ module Gitlab
class GitAccess
UnauthorizedError = Class.new(StandardError)
NotFoundError = Class.new(StandardError)
+ ProjectMovedError = Class.new(NotFoundError)
ERROR_MESSAGES = {
upload: 'You are not allowed to upload code for this project.',
@@ -90,18 +91,18 @@ module Gitlab
end
def check_project_moved!
- if redirected_path
- url = protocol == 'ssh' ? project.ssh_url_to_repo : project.http_url_to_repo
- message = <<-MESSAGE.strip_heredoc
- Project '#{redirected_path}' was moved to '#{project.full_path}'.
+ return unless redirected_path
- Please update your Git remote and try again:
+ url = protocol == 'ssh' ? project.ssh_url_to_repo : project.http_url_to_repo
+ message = <<-MESSAGE.strip_heredoc
+ Project '#{redirected_path}' was moved to '#{project.full_path}'.
- git remote set-url origin #{url}
- MESSAGE
+ Please update your Git remote and try again:
- raise NotFoundError, message
- end
+ git remote set-url origin #{url}
+ MESSAGE
+
+ raise ProjectMovedError, message
end
def check_command_disabled!(cmd)
diff --git a/lib/gitlab/gitaly_client/blob_service.rb b/lib/gitlab/gitaly_client/blob_service.rb
index 7ea8e8d0857..a250eb75bd4 100644
--- a/lib/gitlab/gitaly_client/blob_service.rb
+++ b/lib/gitlab/gitaly_client/blob_service.rb
@@ -13,10 +13,17 @@ module Gitlab
)
response = GitalyClient.call(@gitaly_repo.storage_name, :blob_service, :get_blob, request)
- blob = response.first
- return unless blob.oid.present?
+ data = ''
+ blob = nil
+ response.each do |msg|
+ if blob.nil?
+ blob = msg
+ end
- data = response.reduce(blob.data.dup) { |memo, msg| memo << msg.data.dup }
+ data << msg.data
+ end
+
+ return nil if blob.oid.blank?
Gitlab::Git::Blob.new(
id: blob.oid,
diff --git a/lib/gitlab/gitaly_client/commit_service.rb b/lib/gitlab/gitaly_client/commit_service.rb
index 93268d9f33c..2d58fb0186e 100644
--- a/lib/gitlab/gitaly_client/commit_service.rb
+++ b/lib/gitlab/gitaly_client/commit_service.rb
@@ -60,22 +60,28 @@ module Gitlab
)
response = GitalyClient.call(@repository.storage, :commit_service, :tree_entry, request)
- entry = response.first
- return unless entry.oid.present?
- if entry.type == :BLOB
- rest_of_data = response.reduce("") { |memo, msg| memo << msg.data }
- entry.data += rest_of_data
+ entry = nil
+ data = ''
+ response.each do |msg|
+ if entry.nil?
+ entry = msg
+
+ break unless entry.type == :BLOB
+ end
+
+ data << msg.data
end
+ entry.data = data
- entry
+ entry unless entry.oid.blank?
end
def tree_entries(repository, revision, path)
request = Gitaly::GetTreeEntriesRequest.new(
repository: @gitaly_repo,
- revision: revision,
- path: path.presence || '.'
+ revision: GitalyClient.encode(revision),
+ path: path.present? ? GitalyClient.encode(path) : '.'
)
response = GitalyClient.call(@repository.storage, :commit_service, :get_tree_entries, request)
diff --git a/lib/gitlab/gitaly_client/ref_service.rb b/lib/gitlab/gitaly_client/ref_service.rb
index 919fb68b8c7..cdcfed36740 100644
--- a/lib/gitlab/gitaly_client/ref_service.rb
+++ b/lib/gitlab/gitaly_client/ref_service.rb
@@ -70,6 +70,14 @@ module Gitlab
consume_tags_response(response)
end
+ def ref_exists?(ref_name)
+ request = Gitaly::RefExistsRequest.new(repository: @gitaly_repo, ref: ref_name)
+ response = GitalyClient.call(@storage, :ref_service, :ref_exists, request)
+ response.value
+ rescue GRPC::InvalidArgument => e
+ raise ArgumentError, e.message
+ end
+
private
def consume_refs_response(response)
diff --git a/lib/gitlab/gitaly_client/repository_service.rb b/lib/gitlab/gitaly_client/repository_service.rb
index 6ad97e62941..a74a6dc6e78 100644
--- a/lib/gitlab/gitaly_client/repository_service.rb
+++ b/lib/gitlab/gitaly_client/repository_service.rb
@@ -32,6 +32,11 @@ module Gitlab
request = Gitaly::RepositorySizeRequest.new(repository: @gitaly_repo)
GitalyClient.call(@storage, :repository_service, :repository_size, request).size
end
+
+ def apply_gitattributes(revision)
+ request = Gitaly::ApplyGitattributesRequest.new(repository: @gitaly_repo, revision: revision)
+ GitalyClient.call(@storage, :repository_service, :apply_gitattributes, request)
+ end
end
end
end
diff --git a/lib/gitlab/import_export/import_export.yml b/lib/gitlab/import_export/import_export.yml
index 9d9ebcb389a..e5d4bb686e7 100644
--- a/lib/gitlab/import_export/import_export.yml
+++ b/lib/gitlab/import_export/import_export.yml
@@ -98,6 +98,7 @@ excluded_attributes:
- :last_activity_at
- :last_repository_updated_at
- :last_repository_check_at
+ - :storage_version
snippets:
- :expired_at
merge_request_diff:
@@ -133,5 +134,7 @@ methods:
- :utf8_diff
merge_requests:
- :diff_head_sha
+ - :source_branch_sha
+ - :target_branch_sha
project:
- :description_html
diff --git a/lib/gitlab/import_export/merge_request_parser.rb b/lib/gitlab/import_export/merge_request_parser.rb
index c20adc20bfd..81a213e8321 100644
--- a/lib/gitlab/import_export/merge_request_parser.rb
+++ b/lib/gitlab/import_export/merge_request_parser.rb
@@ -30,7 +30,7 @@ module Gitlab
end
def branch_exists?(branch_name)
- @project.repository.branch_exists?(branch_name)
+ @project.repository.raw.branch_exists?(branch_name)
end
def fork_merge_request?
diff --git a/lib/gitlab/job_waiter.rb b/lib/gitlab/job_waiter.rb
index 208f0e1bbea..4d6bbda15f3 100644
--- a/lib/gitlab/job_waiter.rb
+++ b/lib/gitlab/job_waiter.rb
@@ -1,12 +1,31 @@
module Gitlab
# JobWaiter can be used to wait for a number of Sidekiq jobs to complete.
+ #
+ # Its use requires the cooperation of the sidekiq jobs themselves. Set up the
+ # waiter, then start the jobs, passing them its `key`. Their `perform` methods
+ # should look like:
+ #
+ # def perform(args, notify_key)
+ # # do work
+ # ensure
+ # ::Gitlab::JobWaiter.notify(notify_key, jid)
+ # end
+ #
+ # The JobWaiter blocks popping items from a Redis array. All the sidekiq jobs
+ # push to that array when done. Once the waiter has popped `count` items, it
+ # knows all the jobs are done.
class JobWaiter
- # The sleep interval between checking keys, in seconds.
- INTERVAL = 0.1
+ def self.notify(key, jid)
+ Gitlab::Redis::SharedState.with { |redis| redis.lpush(key, jid) }
+ end
+
+ attr_reader :key, :jobs_remaining, :finished
- # jobs - The job IDs to wait for.
- def initialize(jobs)
- @jobs = jobs
+ # jobs_remaining - the number of jobs left to wait for
+ def initialize(jobs_remaining)
+ @key = "gitlab:job_waiter:#{SecureRandom.uuid}"
+ @jobs_remaining = jobs_remaining
+ @finished = []
end
# Waits for all the jobs to be completed.
@@ -15,13 +34,33 @@ module Gitlab
# ensures we don't indefinitely block a caller in case a job takes
# long to process, or is never processed.
def wait(timeout = 10)
- start = Time.current
+ deadline = Time.now.utc + timeout
+
+ Gitlab::Redis::SharedState.with do |redis|
+ # Fallback key expiry: allow a long grace period to reduce the chance of
+ # a job pushing to an expired key and recreating it
+ redis.expire(key, [timeout * 2, 10.minutes.to_i].max)
+
+ while jobs_remaining > 0
+ # Redis will not take fractional seconds. Prefer waiting too long over
+ # not waiting long enough
+ seconds_left = (deadline - Time.now.utc).ceil
- while (Time.current - start) <= timeout
- break if SidekiqStatus.all_completed?(@jobs)
+ # Redis interprets 0 as "wait forever", so skip the final `blpop` call
+ break if seconds_left <= 0
- sleep(INTERVAL) # to not overload Redis too much.
+ list, jid = redis.blpop(key, timeout: seconds_left)
+ break unless list && jid # timed out
+
+ @finished << jid
+ @jobs_remaining -= 1
+ end
+
+ # All jobs have finished, so expire the key immediately
+ redis.expire(key, 0) if jobs_remaining == 0
end
+
+ finished
end
end
end
diff --git a/lib/gitlab/logger.rb b/lib/gitlab/logger.rb
index 59b21149a9a..6bffd410ed0 100644
--- a/lib/gitlab/logger.rb
+++ b/lib/gitlab/logger.rb
@@ -14,13 +14,9 @@ module Gitlab
def self.read_latest
path = Rails.root.join("log", file_name)
- self.build unless File.exist?(path)
- tail_output, _ = Gitlab::Popen.popen(%W(tail -n 2000 #{path}))
- tail_output.split("\n")
- end
- def self.read_latest_for(filename)
- path = Rails.root.join("log", filename)
+ return [] unless File.readable?(path)
+
tail_output, _ = Gitlab::Popen.popen(%W(tail -n 2000 #{path}))
tail_output.split("\n")
end
diff --git a/lib/gitlab/regex.rb b/lib/gitlab/regex.rb
index 1adc5ec952a..58f6245579a 100644
--- a/lib/gitlab/regex.rb
+++ b/lib/gitlab/regex.rb
@@ -53,7 +53,8 @@ module Gitlab
end
def kubernetes_namespace_regex_message
- "can contain only letters, digits or '-', and cannot start or end with '-'"
+ "can contain only lowercase letters, digits, and '-'. " \
+ "Must start with a letter, and cannot end with '-'"
end
def environment_slug_regex
diff --git a/lib/gitlab/sidekiq_status.rb b/lib/gitlab/sidekiq_status.rb
index ca8d3271541..a0a2769cf9e 100644
--- a/lib/gitlab/sidekiq_status.rb
+++ b/lib/gitlab/sidekiq_status.rb
@@ -90,9 +90,14 @@ module Gitlab
#
# Returns an array of completed JIDs
def self.completed_jids(job_ids)
- Sidekiq.redis do |redis|
- job_ids.reject { |jid| redis.exists(key_for(jid)) }
+ statuses = job_status(job_ids)
+
+ completed = []
+ job_ids.zip(statuses).each do |job_id, status|
+ completed << job_id unless status
end
+
+ completed
end
def self.key_for(jid)
diff --git a/lib/gitlab/sidekiq_throttler.rb b/lib/gitlab/sidekiq_throttler.rb
index d4d39a888e7..5512afa45a8 100644
--- a/lib/gitlab/sidekiq_throttler.rb
+++ b/lib/gitlab/sidekiq_throttler.rb
@@ -3,6 +3,8 @@ module Gitlab
class << self
def execute!
if Gitlab::CurrentSettings.sidekiq_throttling_enabled?
+ require 'sidekiq-limit_fetch'
+
Gitlab::CurrentSettings.current_application_settings.sidekiq_throttling_queues.each do |queue|
Sidekiq::Queue[queue].limit = queue_limit
end
diff --git a/lib/gitlab/string_range_marker.rb b/lib/gitlab/string_range_marker.rb
index 94fba0a221a..11aeec1ebfa 100644
--- a/lib/gitlab/string_range_marker.rb
+++ b/lib/gitlab/string_range_marker.rb
@@ -1,21 +1,31 @@
module Gitlab
class StringRangeMarker
- attr_accessor :raw_line, :rich_line
-
- def initialize(raw_line, rich_line = raw_line)
- @raw_line = raw_line
- @rich_line = ERB::Util.html_escape(rich_line)
+ attr_accessor :raw_line, :rich_line, :html_escaped
+
+ def initialize(raw_line, rich_line = nil)
+ @raw_line = raw_line.dup
+ if rich_line.nil?
+ @rich_line = raw_line.dup
+ @html_escaped = false
+ else
+ @rich_line = ERB::Util.html_escape(rich_line)
+ @html_escaped = true
+ end
end
def mark(marker_ranges)
return rich_line unless marker_ranges
- rich_marker_ranges = []
- marker_ranges.each do |range|
- # Map the inline-diff range based on the raw line to character positions in the rich line
- rich_positions = position_mapping[range].flatten
- # Turn the array of character positions into ranges
- rich_marker_ranges.concat(collapse_ranges(rich_positions))
+ if html_escaped
+ rich_marker_ranges = []
+ marker_ranges.each do |range|
+ # Map the inline-diff range based on the raw line to character positions in the rich line
+ rich_positions = position_mapping[range].flatten
+ # Turn the array of character positions into ranges
+ rich_marker_ranges.concat(collapse_ranges(rich_positions))
+ end
+ else
+ rich_marker_ranges = marker_ranges
end
offset = 0
@@ -31,7 +41,7 @@ module Gitlab
offset += text.length - original_text.length
end
- rich_line.html_safe
+ @html_escaped ? rich_line.html_safe : rich_line
end
private