summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/api/circuit_breakers.rb4
-rw-r--r--lib/api/deploy_keys.rb65
-rw-r--r--lib/api/deployments.rb4
-rw-r--r--lib/api/entities.rb12
-rw-r--r--lib/api/helpers/common_helpers.rb6
-rw-r--r--lib/api/jobs.rb1
-rw-r--r--lib/api/project_milestones.rb9
-rw-r--r--lib/api/services.rb2
-rw-r--r--lib/api/v3/builds.rb1
-rw-r--r--lib/api/v3/deploy_keys.rb46
-rw-r--r--lib/api/v3/entities.rb5
-rw-r--r--lib/api/v3/services.rb2
-rw-r--r--lib/backup/manager.rb9
-rw-r--r--lib/banzai/filter/relative_link_filter.rb15
-rw-r--r--lib/banzai/filter/wiki_link_filter/rewriter.rb4
-rw-r--r--lib/gitlab/auth/blocked_user_tracker.rb36
-rw-r--r--lib/gitlab/auth/user_auth_finders.rb4
-rw-r--r--lib/gitlab/background_migration/prepare_untracked_uploads.rb10
-rw-r--r--lib/gitlab/bare_repository_import/repository.rb10
-rw-r--r--lib/gitlab/ci/config/entry/validators.rb16
-rw-r--r--lib/gitlab/ci/pipeline/chain/skip.rb6
-rw-r--r--lib/gitlab/ci/stage/seed.rb6
-rw-r--r--lib/gitlab/ci/status/build/action.rb5
-rw-r--r--lib/gitlab/git/commit.rb37
-rw-r--r--lib/gitlab/git/conflict/resolver.rb2
-rw-r--r--lib/gitlab/git/gitlab_projects.rb64
-rw-r--r--lib/gitlab/git/repository.rb109
-rw-r--r--lib/gitlab/git/rev_list.rb2
-rw-r--r--lib/gitlab/gitaly_client/commit_service.rb2
-rw-r--r--lib/gitlab/gitaly_client/conflict_files_stitcher.rb47
-rw-r--r--lib/gitlab/gitaly_client/conflicts_service.rb38
-rw-r--r--lib/gitlab/gitaly_client/operation_service.rb28
-rw-r--r--lib/gitlab/gitaly_client/repository_service.rb32
-rw-r--r--lib/gitlab/github_import/client.rb6
-rw-r--r--lib/gitlab/import_export/file_importer.rb6
-rw-r--r--lib/gitlab/import_export/saver.rb2
-rw-r--r--lib/gitlab/import_export/shared.rb14
-rw-r--r--lib/gitlab/kubernetes/helm/install_command.rb6
-rw-r--r--lib/gitlab/kubernetes/helm/pod.rb39
-rw-r--r--lib/gitlab/o_auth.rb6
-rw-r--r--lib/gitlab/o_auth/user.rb11
-rw-r--r--lib/gitlab/performance_bar.rb1
-rw-r--r--lib/gitlab/project_search_results.rb13
-rw-r--r--lib/gitlab/regex.rb2
-rw-r--r--lib/gitlab/user_access.rb10
-rw-r--r--lib/gitlab/utils.rb4
-rw-r--r--lib/gitlab/utils/override.rb111
-rw-r--r--lib/tasks/dev.rake5
-rw-r--r--lib/tasks/gitlab/shell.rake10
-rw-r--r--lib/tasks/lint.rake12
50 files changed, 674 insertions, 223 deletions
diff --git a/lib/api/circuit_breakers.rb b/lib/api/circuit_breakers.rb
index 598c76f6168..c13154dc0ec 100644
--- a/lib/api/circuit_breakers.rb
+++ b/lib/api/circuit_breakers.rb
@@ -17,11 +17,11 @@ module API
end
def storage_health
- @failing_storage_health ||= Gitlab::Git::Storage::Health.for_all_storages
+ @storage_health ||= Gitlab::Git::Storage::Health.for_all_storages
end
end
- desc 'Get all failing git storages' do
+ desc 'Get all git storages' do
detail 'This feature was introduced in GitLab 9.5'
success Entities::RepositoryStorageHealth
end
diff --git a/lib/api/deploy_keys.rb b/lib/api/deploy_keys.rb
index 281269b1190..b0b7b50998f 100644
--- a/lib/api/deploy_keys.rb
+++ b/lib/api/deploy_keys.rb
@@ -4,6 +4,16 @@ module API
before { authenticate! }
+ helpers do
+ def add_deploy_keys_project(project, attrs = {})
+ project.deploy_keys_projects.create(attrs)
+ end
+
+ def find_by_deploy_key(project, key_id)
+ project.deploy_keys_projects.find_by!(deploy_key: key_id)
+ end
+ end
+
desc 'Return all deploy keys'
params do
use :pagination
@@ -21,28 +31,31 @@ module API
before { authorize_admin_project }
desc "Get a specific project's deploy keys" do
- success Entities::SSHKey
+ success Entities::DeployKeysProject
end
params do
use :pagination
end
get ":id/deploy_keys" do
- present paginate(user_project.deploy_keys), with: Entities::SSHKey
+ keys = user_project.deploy_keys_projects.preload(:deploy_key)
+
+ present paginate(keys), with: Entities::DeployKeysProject
end
desc 'Get single deploy key' do
- success Entities::SSHKey
+ success Entities::DeployKeysProject
end
params do
requires :key_id, type: Integer, desc: 'The ID of the deploy key'
end
get ":id/deploy_keys/:key_id" do
- key = user_project.deploy_keys.find params[:key_id]
- present key, with: Entities::SSHKey
+ key = find_by_deploy_key(user_project, params[:key_id])
+
+ present key, with: Entities::DeployKeysProject
end
desc 'Add new deploy key to currently authenticated user' do
- success Entities::SSHKey
+ success Entities::DeployKeysProject
end
params do
requires :key, type: String, desc: 'The new deploy key'
@@ -53,24 +66,31 @@ module API
params[:key].strip!
# Check for an existing key joined to this project
- key = user_project.deploy_keys.find_by(key: params[:key])
+ key = user_project.deploy_keys_projects
+ .joins(:deploy_key)
+ .find_by(keys: { key: params[:key] })
+
if key
- present key, with: Entities::SSHKey
+ present key, with: Entities::DeployKeysProject
break
end
# Check for available deploy keys in other projects
key = current_user.accessible_deploy_keys.find_by(key: params[:key])
if key
- user_project.deploy_keys << key
- present key, with: Entities::SSHKey
+ added_key = add_deploy_keys_project(user_project, deploy_key: key, can_push: !!params[:can_push])
+
+ present added_key, with: Entities::DeployKeysProject
break
end
# Create a new deploy key
- key = DeployKey.new(declared_params(include_missing: false))
- if key.valid? && user_project.deploy_keys << key
- present key, with: Entities::SSHKey
+ key_attributes = { can_push: !!params[:can_push],
+ deploy_key_attributes: declared_params.except(:can_push) }
+ key = add_deploy_keys_project(user_project, key_attributes)
+
+ if key.valid?
+ present key, with: Entities::DeployKeysProject
else
render_validation_error!(key)
end
@@ -86,14 +106,21 @@ module API
at_least_one_of :title, :can_push
end
put ":id/deploy_keys/:key_id" do
- key = DeployKey.find(params.delete(:key_id))
+ deploy_keys_project = find_by_deploy_key(user_project, params[:key_id])
- authorize!(:update_deploy_key, key)
+ authorize!(:update_deploy_key, deploy_keys_project.deploy_key)
- if key.update_attributes(declared_params(include_missing: false))
- present key, with: Entities::SSHKey
+ can_push = params[:can_push].nil? ? deploy_keys_project.can_push : params[:can_push]
+ title = params[:title] || deploy_keys_project.deploy_key.title
+
+ result = deploy_keys_project.update_attributes(can_push: can_push,
+ deploy_key_attributes: { id: params[:key_id],
+ title: title })
+
+ if result
+ present deploy_keys_project, with: Entities::DeployKeysProject
else
- render_validation_error!(key)
+ render_validation_error!(deploy_keys_project)
end
end
@@ -122,7 +149,7 @@ module API
requires :key_id, type: Integer, desc: 'The ID of the deploy key'
end
delete ":id/deploy_keys/:key_id" do
- key = user_project.deploy_keys_projects.find_by(deploy_key_id: params[:key_id])
+ key = user_project.deploy_keys.find(params[:key_id])
not_found!('Deploy Key') unless key
destroy_conditionally!(key)
diff --git a/lib/api/deployments.rb b/lib/api/deployments.rb
index 1efee9a1324..184fae0eb76 100644
--- a/lib/api/deployments.rb
+++ b/lib/api/deployments.rb
@@ -15,11 +15,13 @@ module API
end
params do
use :pagination
+ optional :order_by, type: String, values: %w[id iid created_at ref], default: 'id', desc: 'Return deployments ordered by `id` or `iid` or `created_at` or `ref`'
+ optional :sort, type: String, values: %w[asc desc], default: 'asc', desc: 'Sort by asc (ascending) or desc (descending)'
end
get ':id/deployments' do
authorize! :read_deployment, user_project
- present paginate(user_project.deployments), with: Entities::Deployment
+ present paginate(user_project.deployments.order(params[:order_by] => params[:sort])), with: Entities::Deployment
end
desc 'Gets a specific deployment' do
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index c4ef2c74658..971cb83a2d9 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -554,13 +554,18 @@ module API
end
class SSHKey < Grape::Entity
- expose :id, :title, :key, :created_at, :can_push
+ expose :id, :title, :key, :created_at
end
class SSHKeyWithUser < SSHKey
expose :user, using: Entities::UserPublic
end
+ class DeployKeysProject < Grape::Entity
+ expose :deploy_key, merge: true, using: Entities::SSHKey
+ expose :can_push
+ end
+
class GPGKey < Grape::Entity
expose :id, :key, :created_at
end
@@ -714,10 +719,7 @@ module API
expose :job_events
# Expose serialized properties
expose :properties do |service, options|
- field_names = service.fields
- .select { |field| options[:include_passwords] || field[:type] != 'password' }
- .map { |field| field[:name] }
- service.properties.slice(*field_names)
+ service.properties.slice(*service.api_field_names)
end
end
diff --git a/lib/api/helpers/common_helpers.rb b/lib/api/helpers/common_helpers.rb
index 322624c6092..9993caa5249 100644
--- a/lib/api/helpers/common_helpers.rb
+++ b/lib/api/helpers/common_helpers.rb
@@ -3,8 +3,10 @@ module API
module CommonHelpers
def convert_parameters_from_legacy_format(params)
params.tap do |params|
- if params[:assignee_id].present?
- params[:assignee_ids] = [params.delete(:assignee_id)]
+ assignee_id = params.delete(:assignee_id)
+
+ if assignee_id.present?
+ params[:assignee_ids] = [assignee_id]
end
end
end
diff --git a/lib/api/jobs.rb b/lib/api/jobs.rb
index a116ab3c9bd..9c205514b3a 100644
--- a/lib/api/jobs.rb
+++ b/lib/api/jobs.rb
@@ -38,6 +38,7 @@ module API
builds = user_project.builds.order('id DESC')
builds = filter_builds(builds, params[:scope])
+ builds = builds.preload(:user, :job_artifacts_archive, :runner, pipeline: :project)
present paginate(builds), with: Entities::Job
end
diff --git a/lib/api/project_milestones.rb b/lib/api/project_milestones.rb
index 0cb209a02d0..306dc0e63d7 100644
--- a/lib/api/project_milestones.rb
+++ b/lib/api/project_milestones.rb
@@ -60,6 +60,15 @@ module API
update_milestone_for(user_project)
end
+ desc 'Remove a project milestone'
+ delete ":id/milestones/:milestone_id" do
+ authorize! :admin_milestone, user_project
+
+ user_project.milestones.find(params[:milestone_id]).destroy
+
+ status(204)
+ end
+
desc 'Get all issues for a single project milestone' do
success Entities::IssueBasic
end
diff --git a/lib/api/services.rb b/lib/api/services.rb
index a7f44e2869c..51e33e2c686 100644
--- a/lib/api/services.rb
+++ b/lib/api/services.rb
@@ -785,7 +785,7 @@ module API
service_params = declared_params(include_missing: false).merge(active: true)
if service.update_attributes(service_params)
- present service, with: Entities::ProjectService, include_passwords: current_user.admin?
+ present service, with: Entities::ProjectService
else
render_api_error!('400 Bad Request', 400)
end
diff --git a/lib/api/v3/builds.rb b/lib/api/v3/builds.rb
index fa0bef39602..ac76fece931 100644
--- a/lib/api/v3/builds.rb
+++ b/lib/api/v3/builds.rb
@@ -36,6 +36,7 @@ module API
builds = user_project.builds.order('id DESC')
builds = filter_builds(builds, params[:scope])
+ builds = builds.preload(:user, :job_artifacts_archive, :runner, pipeline: :project)
present paginate(builds), with: ::API::V3::Entities::Build
end
diff --git a/lib/api/v3/deploy_keys.rb b/lib/api/v3/deploy_keys.rb
index b90e2061da3..47e54ca85a5 100644
--- a/lib/api/v3/deploy_keys.rb
+++ b/lib/api/v3/deploy_keys.rb
@@ -3,6 +3,16 @@ module API
class DeployKeys < Grape::API
before { authenticate! }
+ helpers do
+ def add_deploy_keys_project(project, attrs = {})
+ project.deploy_keys_projects.create(attrs)
+ end
+
+ def find_by_deploy_key(project, key_id)
+ project.deploy_keys_projects.find_by!(deploy_key: key_id)
+ end
+ end
+
get "deploy_keys" do
authenticated_as_admin!
@@ -18,25 +28,28 @@ module API
%w(keys deploy_keys).each do |path|
desc "Get a specific project's deploy keys" do
- success ::API::Entities::SSHKey
+ success ::API::Entities::DeployKeysProject
end
get ":id/#{path}" do
- present user_project.deploy_keys, with: ::API::Entities::SSHKey
+ keys = user_project.deploy_keys_projects.preload(:deploy_key)
+
+ present keys, with: ::API::Entities::DeployKeysProject
end
desc 'Get single deploy key' do
- success ::API::Entities::SSHKey
+ success ::API::Entities::DeployKeysProject
end
params do
requires :key_id, type: Integer, desc: 'The ID of the deploy key'
end
get ":id/#{path}/:key_id" do
- key = user_project.deploy_keys.find params[:key_id]
- present key, with: ::API::Entities::SSHKey
+ key = find_by_deploy_key(user_project, params[:key_id])
+
+ present key, with: ::API::Entities::DeployKeysProject
end
desc 'Add new deploy key to currently authenticated user' do
- success ::API::Entities::SSHKey
+ success ::API::Entities::DeployKeysProject
end
params do
requires :key, type: String, desc: 'The new deploy key'
@@ -47,24 +60,31 @@ module API
params[:key].strip!
# Check for an existing key joined to this project
- key = user_project.deploy_keys.find_by(key: params[:key])
+ key = user_project.deploy_keys_projects
+ .joins(:deploy_key)
+ .find_by(keys: { key: params[:key] })
+
if key
- present key, with: ::API::Entities::SSHKey
+ present key, with: ::API::Entities::DeployKeysProject
break
end
# Check for available deploy keys in other projects
key = current_user.accessible_deploy_keys.find_by(key: params[:key])
if key
- user_project.deploy_keys << key
- present key, with: ::API::Entities::SSHKey
+ added_key = add_deploy_keys_project(user_project, deploy_key: key, can_push: !!params[:can_push])
+
+ present added_key, with: ::API::Entities::DeployKeysProject
break
end
# Create a new deploy key
- key = DeployKey.new(declared_params(include_missing: false))
- if key.valid? && user_project.deploy_keys << key
- present key, with: ::API::Entities::SSHKey
+ key_attributes = { can_push: !!params[:can_push],
+ deploy_key_attributes: declared_params.except(:can_push) }
+ key = add_deploy_keys_project(user_project, key_attributes)
+
+ if key.valid?
+ present key, with: ::API::Entities::DeployKeysProject
else
render_validation_error!(key)
end
diff --git a/lib/api/v3/entities.rb b/lib/api/v3/entities.rb
index 64758dae7d3..2ccbb9da1c5 100644
--- a/lib/api/v3/entities.rb
+++ b/lib/api/v3/entities.rb
@@ -257,10 +257,7 @@ module API
expose :job_events, as: :build_events
# Expose serialized properties
expose :properties do |service, options|
- field_names = service.fields
- .select { |field| options[:include_passwords] || field[:type] != 'password' }
- .map { |field| field[:name] }
- service.properties.slice(*field_names)
+ service.properties.slice(*service.api_field_names)
end
end
diff --git a/lib/api/v3/services.rb b/lib/api/v3/services.rb
index 44ed94d2869..20ca1021c71 100644
--- a/lib/api/v3/services.rb
+++ b/lib/api/v3/services.rb
@@ -622,7 +622,7 @@ module API
end
get ":id/services/:service_slug" do
service = user_project.find_or_initialize_service(params[:service_slug].underscore)
- present service, with: Entities::ProjectService, include_passwords: current_user.admin?
+ present service, with: Entities::ProjectService
end
end
diff --git a/lib/backup/manager.rb b/lib/backup/manager.rb
index 05aa79dc160..f27ce4d2b2b 100644
--- a/lib/backup/manager.rb
+++ b/lib/backup/manager.rb
@@ -108,7 +108,10 @@ module Backup
$progress.puts "Please make sure that file name ends with #{FILE_NAME_SUFFIX}"
exit 1
elsif backup_file_list.many? && ENV["BACKUP"].nil?
- $progress.puts 'Found more than one backup, please specify which one you want to restore:'
+ $progress.puts 'Found more than one backup:'
+ # print list of available backups
+ $progress.puts " " + available_timestamps.join("\n ")
+ $progress.puts 'Please specify which one you want to restore:'
$progress.puts 'rake gitlab:backup:restore BACKUP=timestamp_of_backup'
exit 1
end
@@ -169,6 +172,10 @@ module Backup
@backup_file_list ||= Dir.glob("*#{FILE_NAME_SUFFIX}")
end
+ def available_timestamps
+ @backup_file_list.map {|item| item.gsub("#{FILE_NAME_SUFFIX}", "")}
+ end
+
def connect_to_remote_directory(connection_settings)
# our settings use string keys, but Fog expects symbols
connection = ::Fog::Storage.new(connection_settings.symbolize_keys)
diff --git a/lib/banzai/filter/relative_link_filter.rb b/lib/banzai/filter/relative_link_filter.rb
index 5c197afd782..f6169b2c85d 100644
--- a/lib/banzai/filter/relative_link_filter.rb
+++ b/lib/banzai/filter/relative_link_filter.rb
@@ -50,15 +50,22 @@ module Banzai
end
def process_link_to_upload_attr(html_attr)
- uri_parts = [html_attr.value]
+ path_parts = [html_attr.value]
if group
- uri_parts.unshift(relative_url_root, 'groups', group.full_path, '-')
+ path_parts.unshift(relative_url_root, 'groups', group.full_path, '-')
elsif project
- uri_parts.unshift(relative_url_root, project.full_path)
+ path_parts.unshift(relative_url_root, project.full_path)
end
- html_attr.value = File.join(*uri_parts)
+ path = File.join(*path_parts)
+
+ html_attr.value =
+ if context[:only_path]
+ path
+ else
+ URI.join(Gitlab.config.gitlab.base_url, path).to_s
+ end
end
def process_link_to_repository_attr(html_attr)
diff --git a/lib/banzai/filter/wiki_link_filter/rewriter.rb b/lib/banzai/filter/wiki_link_filter/rewriter.rb
index e7a1ec8457d..072d24e5a11 100644
--- a/lib/banzai/filter/wiki_link_filter/rewriter.rb
+++ b/lib/banzai/filter/wiki_link_filter/rewriter.rb
@@ -9,6 +9,10 @@ module Banzai
end
def apply_rules
+ # Special case: relative URLs beginning with `/uploads/` refer to
+ # user-uploaded files and will be handled elsewhere.
+ return @uri.to_s if @uri.relative? && @uri.path.starts_with?('/uploads/')
+
apply_file_link_rules!
apply_hierarchical_link_rules!
apply_relative_link_rules!
diff --git a/lib/gitlab/auth/blocked_user_tracker.rb b/lib/gitlab/auth/blocked_user_tracker.rb
new file mode 100644
index 00000000000..dae03a179e4
--- /dev/null
+++ b/lib/gitlab/auth/blocked_user_tracker.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+module Gitlab
+ module Auth
+ class BlockedUserTracker
+ ACTIVE_RECORD_REQUEST_PARAMS = 'action_dispatch.request.request_parameters'
+
+ def self.log_if_user_blocked(env)
+ message = env.dig('warden.options', :message)
+
+ # Devise calls User#active_for_authentication? on the User model and then
+ # throws an exception to Warden with User#inactive_message:
+ # https://github.com/plataformatec/devise/blob/v4.2.1/lib/devise/hooks/activatable.rb#L8
+ #
+ # Since Warden doesn't pass the user record to the failure handler, we
+ # need to do a database lookup with the username. We can limit the
+ # lookups to happen when the user was blocked by checking the inactive
+ # message passed along by Warden.
+ return unless message == User::BLOCKED_MESSAGE
+
+ login = env.dig(ACTIVE_RECORD_REQUEST_PARAMS, 'user', 'login')
+
+ return unless login.present?
+
+ user = User.by_login(login)
+
+ return unless user&.blocked?
+
+ Gitlab::AppLogger.info("Failed login for blocked user: user=#{user.username} ip=#{env['REMOTE_ADDR']}")
+ SystemHooksService.new.execute_hooks_for(user, :failed_login)
+
+ true
+ rescue TypeError
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/auth/user_auth_finders.rb b/lib/gitlab/auth/user_auth_finders.rb
index b4114a3ac96..cf02030c577 100644
--- a/lib/gitlab/auth/user_auth_finders.rb
+++ b/lib/gitlab/auth/user_auth_finders.rb
@@ -96,9 +96,7 @@ module Gitlab
end
def ensure_action_dispatch_request(request)
- return request if request.is_a?(ActionDispatch::Request)
-
- ActionDispatch::Request.new(request.env)
+ ActionDispatch::Request.new(request.env.dup)
end
def current_request
diff --git a/lib/gitlab/background_migration/prepare_untracked_uploads.rb b/lib/gitlab/background_migration/prepare_untracked_uploads.rb
index 476c46341ae..4e0121ca34d 100644
--- a/lib/gitlab/background_migration/prepare_untracked_uploads.rb
+++ b/lib/gitlab/background_migration/prepare_untracked_uploads.rb
@@ -7,6 +7,7 @@ module Gitlab
class PrepareUntrackedUploads # rubocop:disable Metrics/ClassLength
# For bulk_queue_background_migration_jobs_by_range
include Database::MigrationHelpers
+ include ::Gitlab::Utils::StrongMemoize
FIND_BATCH_SIZE = 500
RELATIVE_UPLOAD_DIR = "uploads".freeze
@@ -142,7 +143,9 @@ module Gitlab
end
def postgresql?
- @postgresql ||= Gitlab::Database.postgresql?
+ strong_memoize(:postgresql) do
+ Gitlab::Database.postgresql?
+ end
end
def can_bulk_insert_and_ignore_duplicates?
@@ -150,8 +153,9 @@ module Gitlab
end
def postgresql_pre_9_5?
- @postgresql_pre_9_5 ||= postgresql? &&
- Gitlab::Database.version.to_f < 9.5
+ strong_memoize(:postgresql_pre_9_5) do
+ postgresql? && Gitlab::Database.version.to_f < 9.5
+ end
end
def schedule_populate_untracked_uploads_jobs
diff --git a/lib/gitlab/bare_repository_import/repository.rb b/lib/gitlab/bare_repository_import/repository.rb
index 85b79362196..c0c666dfb7b 100644
--- a/lib/gitlab/bare_repository_import/repository.rb
+++ b/lib/gitlab/bare_repository_import/repository.rb
@@ -1,6 +1,8 @@
module Gitlab
module BareRepositoryImport
class Repository
+ include ::Gitlab::Utils::StrongMemoize
+
attr_reader :group_path, :project_name, :repo_path
def initialize(root_path, repo_path)
@@ -41,11 +43,15 @@ module Gitlab
private
def wiki?
- @wiki ||= repo_path.end_with?('.wiki.git')
+ strong_memoize(:wiki) do
+ repo_path.end_with?('.wiki.git')
+ end
end
def hashed?
- @hashed ||= repo_relative_path.include?('@hashed')
+ strong_memoize(:hashed) do
+ repo_relative_path.include?('@hashed')
+ end
end
def repo_relative_path
diff --git a/lib/gitlab/ci/config/entry/validators.rb b/lib/gitlab/ci/config/entry/validators.rb
index eb606b57667..55658900628 100644
--- a/lib/gitlab/ci/config/entry/validators.rb
+++ b/lib/gitlab/ci/config/entry/validators.rb
@@ -64,10 +64,24 @@ module Gitlab
include LegacyValidationHelpers
def validate_each(record, attribute, value)
- unless validate_string(value)
+ if validate_string(value)
+ validate_path(record, attribute, value)
+ else
record.errors.add(attribute, 'should be a string or symbol')
end
end
+
+ private
+
+ def validate_path(record, attribute, value)
+ path = CGI.unescape(value.to_s)
+
+ if path.include?('/')
+ record.errors.add(attribute, 'cannot contain the "/" character')
+ elsif path == '.' || path == '..'
+ record.errors.add(attribute, 'cannot be "." or ".."')
+ end
+ end
end
class RegexpValidator < ActiveModel::EachValidator
diff --git a/lib/gitlab/ci/pipeline/chain/skip.rb b/lib/gitlab/ci/pipeline/chain/skip.rb
index 9a72de87bab..32cbb7ca6af 100644
--- a/lib/gitlab/ci/pipeline/chain/skip.rb
+++ b/lib/gitlab/ci/pipeline/chain/skip.rb
@@ -3,6 +3,8 @@ module Gitlab
module Pipeline
module Chain
class Skip < Chain::Base
+ include ::Gitlab::Utils::StrongMemoize
+
SKIP_PATTERN = /\[(ci[ _-]skip|skip[ _-]ci)\]/i
def perform!
@@ -24,7 +26,9 @@ module Gitlab
def commit_message_skips_ci?
return false unless @pipeline.git_commit_message
- @skipped ||= !!(@pipeline.git_commit_message =~ SKIP_PATTERN)
+ strong_memoize(:commit_message_skips_ci) do
+ !!(@pipeline.git_commit_message =~ SKIP_PATTERN)
+ end
end
end
end
diff --git a/lib/gitlab/ci/stage/seed.rb b/lib/gitlab/ci/stage/seed.rb
index bc97aa63b02..f33c87f554d 100644
--- a/lib/gitlab/ci/stage/seed.rb
+++ b/lib/gitlab/ci/stage/seed.rb
@@ -2,6 +2,8 @@ module Gitlab
module Ci
module Stage
class Seed
+ include ::Gitlab::Utils::StrongMemoize
+
attr_reader :pipeline
delegate :project, to: :pipeline
@@ -50,7 +52,9 @@ module Gitlab
private
def protected_ref?
- @protected_ref ||= project.protected_for?(pipeline.ref)
+ strong_memoize(:protected_ref) do
+ project.protected_for?(pipeline.ref)
+ end
end
end
end
diff --git a/lib/gitlab/ci/status/build/action.rb b/lib/gitlab/ci/status/build/action.rb
index 45fd0d4aa07..6c9125647ad 100644
--- a/lib/gitlab/ci/status/build/action.rb
+++ b/lib/gitlab/ci/status/build/action.rb
@@ -2,6 +2,9 @@ module Gitlab
module Ci
module Status
module Build
+ ##
+ # Extended status for playable manual actions.
+ #
class Action < Status::Extended
def label
if has_action?
@@ -12,7 +15,7 @@ module Gitlab
end
def self.matches?(build, user)
- build.action?
+ build.playable?
end
end
end
diff --git a/lib/gitlab/git/commit.rb b/lib/gitlab/git/commit.rb
index 016437b2419..46e0c0e82a2 100644
--- a/lib/gitlab/git/commit.rb
+++ b/lib/gitlab/git/commit.rb
@@ -436,6 +436,16 @@ module Gitlab
parent_ids.size > 1
end
+ def tree_entry(path)
+ @repository.gitaly_migrate(:commit_tree_entry) do |is_migrated|
+ if is_migrated
+ gitaly_tree_entry(path)
+ else
+ rugged_tree_entry(path)
+ end
+ end
+ end
+
def to_gitaly_commit
return raw_commit if raw_commit.is_a?(Gitaly::GitCommit)
@@ -450,11 +460,6 @@ module Gitlab
)
end
- # Is this the same as Blob.find_entry_by_path ?
- def rugged_tree_entry(path)
- rugged_commit.tree.path(path)
- end
-
private
def init_from_hash(hash)
@@ -501,6 +506,28 @@ module Gitlab
SERIALIZE_KEYS
end
+ def gitaly_tree_entry(path)
+ # We're only interested in metadata, so limit actual data to 1 byte
+ # since Gitaly doesn't support "send no data" option.
+ entry = @repository.gitaly_commit_client.tree_entry(id, path, 1)
+ return unless entry
+
+ # To be compatible with the rugged format
+ entry = entry.to_h
+ entry.delete(:data)
+ entry[:name] = File.basename(path)
+ entry[:type] = entry[:type].downcase
+
+ entry
+ end
+
+ # Is this the same as Blob.find_entry_by_path ?
+ def rugged_tree_entry(path)
+ rugged_commit.tree.path(path)
+ rescue Rugged::TreeError
+ nil
+ end
+
def gitaly_commit_author_from_rugged(author_or_committer)
Gitaly::CommitAuthor.new(
name: author_or_committer[:name].b,
diff --git a/lib/gitlab/git/conflict/resolver.rb b/lib/gitlab/git/conflict/resolver.rb
index 74c9874d590..07b7e811a34 100644
--- a/lib/gitlab/git/conflict/resolver.rb
+++ b/lib/gitlab/git/conflict/resolver.rb
@@ -15,7 +15,7 @@ module Gitlab
@conflicts ||= begin
@target_repository.gitaly_migrate(:conflicts_list_conflict_files) do |is_enabled|
if is_enabled
- gitaly_conflicts_client(@target_repository).list_conflict_files
+ gitaly_conflicts_client(@target_repository).list_conflict_files.to_a
else
rugged_list_conflict_files
end
diff --git a/lib/gitlab/git/gitlab_projects.rb b/lib/gitlab/git/gitlab_projects.rb
index 976fa1ddfe6..e5a747cb987 100644
--- a/lib/gitlab/git/gitlab_projects.rb
+++ b/lib/gitlab/git/gitlab_projects.rb
@@ -44,29 +44,13 @@ module Gitlab
# Import project via git clone --bare
# URL must be publicly cloneable
def import_project(source, timeout)
- # Skip import if repo already exists
- return false if File.exist?(repository_absolute_path)
-
- masked_source = mask_password_in_url(source)
-
- logger.info "Importing project from <#{masked_source}> to <#{repository_absolute_path}>."
- cmd = %W(git clone --bare -- #{source} #{repository_absolute_path})
-
- success = run_with_timeout(cmd, timeout, nil)
-
- unless success
- logger.error("Importing project from <#{masked_source}> to <#{repository_absolute_path}> failed.")
- FileUtils.rm_rf(repository_absolute_path)
- return false
+ Gitlab::GitalyClient.migrate(:import_repository) do |is_enabled|
+ if is_enabled
+ gitaly_import_repository(source)
+ else
+ git_import_repository(source, timeout)
+ end
end
-
- Gitlab::Git::Repository.create_hooks(repository_absolute_path, global_hooks_path)
-
- # The project was imported successfully.
- # Remove the origin URL since it may contain password.
- remove_origin_in_repo
-
- true
end
def fork_repository(new_shard_path, new_repository_relative_path)
@@ -231,6 +215,42 @@ module Gitlab
raise(ShardNameNotFoundError, "no shard found for path '#{shard_path}'")
end
+ def git_import_repository(source, timeout)
+ # Skip import if repo already exists
+ return false if File.exist?(repository_absolute_path)
+
+ masked_source = mask_password_in_url(source)
+
+ logger.info "Importing project from <#{masked_source}> to <#{repository_absolute_path}>."
+ cmd = %W(git clone --bare -- #{source} #{repository_absolute_path})
+
+ success = run_with_timeout(cmd, timeout, nil)
+
+ unless success
+ logger.error("Importing project from <#{masked_source}> to <#{repository_absolute_path}> failed.")
+ FileUtils.rm_rf(repository_absolute_path)
+ return false
+ end
+
+ Gitlab::Git::Repository.create_hooks(repository_absolute_path, global_hooks_path)
+
+ # The project was imported successfully.
+ # Remove the origin URL since it may contain password.
+ remove_origin_in_repo
+
+ true
+ end
+
+ def gitaly_import_repository(source)
+ raw_repository = Gitlab::Git::Repository.new(shard_name, repository_relative_path, nil)
+
+ Gitlab::GitalyClient::RepositoryService.new(raw_repository).import_repository(source)
+ true
+ rescue GRPC::BadStatus => e
+ @output << e.message
+ false
+ end
+
def git_fork_repository(new_shard_path, new_repository_relative_path)
from_path = repository_absolute_path
to_path = File.join(new_shard_path, new_repository_relative_path)
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
index 6ada9a145db..c5d5c3a72c0 100644
--- a/lib/gitlab/git/repository.rb
+++ b/lib/gitlab/git/repository.rb
@@ -621,37 +621,6 @@ module Gitlab
end
end
- # Returns branch names collection that contains the special commit(SHA1
- # or name)
- #
- # Ex.
- # repo.branch_names_contains('master')
- #
- def branch_names_contains(commit)
- branches_contains(commit).map { |c| c.name }
- end
-
- # Returns branch collection that contains the special commit(SHA1 or name)
- #
- # Ex.
- # repo.branch_names_contains('master')
- #
- def branches_contains(commit)
- commit_obj = rugged.rev_parse(commit)
- parent = commit_obj.parents.first unless commit_obj.parents.empty?
-
- walker = Rugged::Walker.new(rugged)
-
- rugged.branches.select do |branch|
- walker.push(branch.target_id)
- walker.hide(parent) if parent
- result = walker.any? { |c| c.oid == commit_obj.oid }
- walker.reset
-
- result
- end
- end
-
# Get refs hash which key is SHA1
# and value is a Rugged::Reference
def refs_hash
@@ -1236,33 +1205,31 @@ module Gitlab
end
def rebase(user, rebase_id, branch:, branch_sha:, remote_repository:, remote_branch:)
- rebase_path = worktree_path(REBASE_WORKTREE_PREFIX, rebase_id)
- env = git_env_for_user(user)
-
- if remote_repository.is_a?(RemoteRepository)
- env.merge!(remote_repository.fetch_env)
- remote_repo_path = GITALY_INTERNAL_URL
- else
- remote_repo_path = remote_repository.path
- end
-
- with_worktree(rebase_path, branch, env: env) do
- run_git!(
- %W(pull --rebase #{remote_repo_path} #{remote_branch}),
- chdir: rebase_path, env: env
- )
-
- rebase_sha = run_git!(%w(rev-parse HEAD), chdir: rebase_path, env: env).strip
-
- Gitlab::Git::OperationService.new(user, self)
- .update_branch(branch, rebase_sha, branch_sha)
-
- rebase_sha
+ gitaly_migrate(:rebase) do |is_enabled|
+ if is_enabled
+ gitaly_rebase(user, rebase_id,
+ branch: branch,
+ branch_sha: branch_sha,
+ remote_repository: remote_repository,
+ remote_branch: remote_branch)
+ else
+ git_rebase(user, rebase_id,
+ branch: branch,
+ branch_sha: branch_sha,
+ remote_repository: remote_repository,
+ remote_branch: remote_branch)
+ end
end
end
def rebase_in_progress?(rebase_id)
- fresh_worktree?(worktree_path(REBASE_WORKTREE_PREFIX, rebase_id))
+ gitaly_migrate(:rebase_in_progress) do |is_enabled|
+ if is_enabled
+ gitaly_repository_client.rebase_in_progress?(rebase_id)
+ else
+ fresh_worktree?(worktree_path(REBASE_WORKTREE_PREFIX, rebase_id))
+ end
+ end
end
def squash(user, squash_id, branch:, start_sha:, end_sha:, author:, message:)
@@ -2039,6 +2006,40 @@ module Gitlab
tree_id
end
+ def gitaly_rebase(user, rebase_id, branch:, branch_sha:, remote_repository:, remote_branch:)
+ gitaly_operation_client.user_rebase(user, rebase_id,
+ branch: branch,
+ branch_sha: branch_sha,
+ remote_repository: remote_repository,
+ remote_branch: remote_branch)
+ end
+
+ def git_rebase(user, rebase_id, branch:, branch_sha:, remote_repository:, remote_branch:)
+ rebase_path = worktree_path(REBASE_WORKTREE_PREFIX, rebase_id)
+ env = git_env_for_user(user)
+
+ if remote_repository.is_a?(RemoteRepository)
+ env.merge!(remote_repository.fetch_env)
+ remote_repo_path = GITALY_INTERNAL_URL
+ else
+ remote_repo_path = remote_repository.path
+ end
+
+ with_worktree(rebase_path, branch, env: env) do
+ run_git!(
+ %W(pull --rebase #{remote_repo_path} #{remote_branch}),
+ chdir: rebase_path, env: env
+ )
+
+ rebase_sha = run_git!(%w(rev-parse HEAD), chdir: rebase_path, env: env).strip
+
+ Gitlab::Git::OperationService.new(user, self)
+ .update_branch(branch, rebase_sha, branch_sha)
+
+ rebase_sha
+ end
+ end
+
def local_fetch_ref(source_path, source_ref:, target_ref:)
args = %W(fetch --no-tags -f #{source_path} #{source_ref}:#{target_ref})
run_git(args)
diff --git a/lib/gitlab/git/rev_list.rb b/lib/gitlab/git/rev_list.rb
index 4974205b8fd..f8b2e7e0e21 100644
--- a/lib/gitlab/git/rev_list.rb
+++ b/lib/gitlab/git/rev_list.rb
@@ -95,7 +95,7 @@ module Gitlab
object_output.map do |output_line|
sha, path = output_line.split(' ', 2)
- next if require_path && path.blank?
+ next if require_path && path.to_s.empty?
sha
end.reject(&:nil?)
diff --git a/lib/gitlab/gitaly_client/commit_service.rb b/lib/gitlab/gitaly_client/commit_service.rb
index fed05bb6c64..71b212023d6 100644
--- a/lib/gitlab/gitaly_client/commit_service.rb
+++ b/lib/gitlab/gitaly_client/commit_service.rb
@@ -177,7 +177,7 @@ module Gitlab
response = GitalyClient.call(@repository.storage, :commit_service, :list_commits_by_oid, request, timeout: GitalyClient.medium_timeout)
consume_commits_response(response)
- rescue GRPC::Unknown # If no repository is found, happens mainly during testing
+ rescue GRPC::NotFound # If no repository is found, happens mainly during testing
[]
end
diff --git a/lib/gitlab/gitaly_client/conflict_files_stitcher.rb b/lib/gitlab/gitaly_client/conflict_files_stitcher.rb
new file mode 100644
index 00000000000..97c13d1fdb0
--- /dev/null
+++ b/lib/gitlab/gitaly_client/conflict_files_stitcher.rb
@@ -0,0 +1,47 @@
+module Gitlab
+ module GitalyClient
+ class ConflictFilesStitcher
+ include Enumerable
+
+ def initialize(rpc_response)
+ @rpc_response = rpc_response
+ end
+
+ def each
+ current_file = nil
+
+ @rpc_response.each do |msg|
+ msg.files.each do |gitaly_file|
+ if gitaly_file.header
+ yield current_file if current_file
+
+ current_file = file_from_gitaly_header(gitaly_file.header)
+ else
+ current_file.content << gitaly_file.content
+ end
+ end
+ end
+
+ yield current_file if current_file
+ end
+
+ private
+
+ def file_from_gitaly_header(header)
+ Gitlab::Git::Conflict::File.new(
+ Gitlab::GitalyClient::Util.git_repository(header.repository),
+ header.commit_oid,
+ conflict_from_gitaly_file_header(header),
+ ''
+ )
+ end
+
+ def conflict_from_gitaly_file_header(header)
+ {
+ ours: { path: header.our_path, mode: header.our_mode },
+ theirs: { path: header.their_path }
+ }
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/gitaly_client/conflicts_service.rb b/lib/gitlab/gitaly_client/conflicts_service.rb
index 40f032cf873..2565d537aff 100644
--- a/lib/gitlab/gitaly_client/conflicts_service.rb
+++ b/lib/gitlab/gitaly_client/conflicts_service.rb
@@ -20,7 +20,11 @@ module Gitlab
)
response = GitalyClient.call(@repository.storage, :conflicts_service, :list_conflict_files, request)
- files_from_response(response).to_a
+ GitalyClient::ConflictFilesStitcher.new(response)
+ end
+
+ def conflicts?
+ list_conflict_files.any?
end
def resolve_conflicts(target_repository, resolution, source_branch, target_branch)
@@ -58,38 +62,6 @@ module Gitlab
user: Gitlab::Git::User.from_gitlab(resolution.user).to_gitaly
)
end
-
- def files_from_response(response)
- files = []
-
- response.each do |msg|
- msg.files.each do |gitaly_file|
- if gitaly_file.header
- files << file_from_gitaly_header(gitaly_file.header)
- else
- files.last.content << gitaly_file.content
- end
- end
- end
-
- files
- end
-
- def file_from_gitaly_header(header)
- Gitlab::Git::Conflict::File.new(
- Gitlab::GitalyClient::Util.git_repository(header.repository),
- header.commit_oid,
- conflict_from_gitaly_file_header(header),
- ''
- )
- end
-
- def conflict_from_gitaly_file_header(header)
- {
- ours: { path: header.our_path, mode: header.our_mode },
- theirs: { path: header.their_path }
- }
- end
end
end
end
diff --git a/lib/gitlab/gitaly_client/operation_service.rb b/lib/gitlab/gitaly_client/operation_service.rb
index 37ba1af8d6f..7319de69d13 100644
--- a/lib/gitlab/gitaly_client/operation_service.rb
+++ b/lib/gitlab/gitaly_client/operation_service.rb
@@ -147,6 +147,34 @@ module Gitlab
start_repository: start_repository)
end
+ def user_rebase(user, rebase_id, branch:, branch_sha:, remote_repository:, remote_branch:)
+ request = Gitaly::UserRebaseRequest.new(
+ repository: @gitaly_repo,
+ user: Gitlab::Git::User.from_gitlab(user).to_gitaly,
+ rebase_id: rebase_id.to_s,
+ branch: encode_binary(branch),
+ branch_sha: branch_sha,
+ remote_repository: remote_repository.gitaly_repository,
+ remote_branch: encode_binary(remote_branch)
+ )
+
+ response = GitalyClient.call(
+ @repository.storage,
+ :operation_service,
+ :user_rebase,
+ request,
+ remote_storage: remote_repository.storage
+ )
+
+ if response.pre_receive_error.presence
+ raise Gitlab::Git::HooksService::PreReceiveError, response.pre_receive_error
+ elsif response.git_error.presence
+ raise Gitlab::Git::Repository::GitError, response.git_error
+ else
+ response.rebase_sha
+ end
+ end
+
private
def call_cherry_pick_or_revert(rpc, user:, commit:, branch_name:, message:, start_branch_name:, start_repository:)
diff --git a/lib/gitlab/gitaly_client/repository_service.rb b/lib/gitlab/gitaly_client/repository_service.rb
index 66006f5dc5b..12016aee2a6 100644
--- a/lib/gitlab/gitaly_client/repository_service.rb
+++ b/lib/gitlab/gitaly_client/repository_service.rb
@@ -100,6 +100,38 @@ module Gitlab
)
end
+ def import_repository(source)
+ request = Gitaly::CreateRepositoryFromURLRequest.new(
+ repository: @gitaly_repo,
+ url: source
+ )
+
+ GitalyClient.call(
+ @storage,
+ :repository_service,
+ :create_repository_from_url,
+ request,
+ timeout: GitalyClient.default_timeout
+ )
+ end
+
+ def rebase_in_progress?(rebase_id)
+ request = Gitaly::IsRebaseInProgressRequest.new(
+ repository: @gitaly_repo,
+ rebase_id: rebase_id.to_s
+ )
+
+ response = GitalyClient.call(
+ @storage,
+ :repository_service,
+ :is_rebase_in_progress,
+ request,
+ timeout: GitalyClient.default_timeout
+ )
+
+ response.in_progress
+ end
+
def fetch_source_branch(source_repository, source_branch, local_ref)
request = Gitaly::FetchSourceBranchRequest.new(
repository: @gitaly_repo,
diff --git a/lib/gitlab/github_import/client.rb b/lib/gitlab/github_import/client.rb
index 5da9befa08e..4f160e4a447 100644
--- a/lib/gitlab/github_import/client.rb
+++ b/lib/gitlab/github_import/client.rb
@@ -14,6 +14,8 @@ module Gitlab
# puts label.name
# end
class Client
+ include ::Gitlab::Utils::StrongMemoize
+
attr_reader :octokit
# A single page of data and the corresponding page number.
@@ -173,7 +175,9 @@ module Gitlab
end
def rate_limiting_enabled?
- @rate_limiting_enabled ||= api_endpoint.include?('.github.com')
+ strong_memoize(:rate_limiting_enabled) do
+ api_endpoint.include?('.github.com')
+ end
end
def api_endpoint
diff --git a/lib/gitlab/import_export/file_importer.rb b/lib/gitlab/import_export/file_importer.rb
index 989342389bc..5c971564a73 100644
--- a/lib/gitlab/import_export/file_importer.rb
+++ b/lib/gitlab/import_export/file_importer.rb
@@ -17,12 +17,16 @@ module Gitlab
def import
mkdir_p(@shared.export_path)
+ remove_symlinks!
+
wait_for_archived_file do
decompress_archive
end
rescue => e
@shared.error(e)
false
+ ensure
+ remove_symlinks!
end
private
@@ -43,7 +47,7 @@ module Gitlab
raise Projects::ImportService::Error.new("Unable to decompress #{@archive_file} into #{@shared.export_path}") unless result
- remove_symlinks!
+ result
end
def remove_symlinks!
diff --git a/lib/gitlab/import_export/saver.rb b/lib/gitlab/import_export/saver.rb
index 6130c124dd1..2daeba90a51 100644
--- a/lib/gitlab/import_export/saver.rb
+++ b/lib/gitlab/import_export/saver.rb
@@ -37,7 +37,7 @@ module Gitlab
end
def archive_file
- @archive_file ||= File.join(@shared.export_path, '..', Gitlab::ImportExport.export_filename(project: @project))
+ @archive_file ||= File.join(@shared.archive_path, Gitlab::ImportExport.export_filename(project: @project))
end
end
end
diff --git a/lib/gitlab/import_export/shared.rb b/lib/gitlab/import_export/shared.rb
index 9fd0b709ef2..d03cbc880fd 100644
--- a/lib/gitlab/import_export/shared.rb
+++ b/lib/gitlab/import_export/shared.rb
@@ -9,7 +9,11 @@ module Gitlab
end
def export_path
- @export_path ||= Gitlab::ImportExport.export_path(relative_path: opts[:relative_path])
+ @export_path ||= Gitlab::ImportExport.export_path(relative_path: relative_path)
+ end
+
+ def archive_path
+ @archive_path ||= Gitlab::ImportExport.export_path(relative_path: relative_archive_path)
end
def error(error)
@@ -21,6 +25,14 @@ module Gitlab
private
+ def relative_path
+ File.join(opts[:relative_path], SecureRandom.hex)
+ end
+
+ def relative_archive_path
+ File.join(opts[:relative_path], '..')
+ end
+
def error_out(message, caller)
Rails.logger.error("Import/Export error raised on #{caller}: #{message}")
end
diff --git a/lib/gitlab/kubernetes/helm/install_command.rb b/lib/gitlab/kubernetes/helm/install_command.rb
index 8d8c441a4b1..bf6981035f4 100644
--- a/lib/gitlab/kubernetes/helm/install_command.rb
+++ b/lib/gitlab/kubernetes/helm/install_command.rb
@@ -36,7 +36,11 @@ module Gitlab
def complete_command(namespace_name)
return unless chart
- "helm install #{chart} --name #{name} --namespace #{namespace_name} >/dev/null"
+ if chart_values_file
+ "helm install #{chart} --name #{name} --namespace #{namespace_name} -f /data/helm/#{name}/config/values.yaml >/dev/null"
+ else
+ "helm install #{chart} --name #{name} --namespace #{namespace_name} >/dev/null"
+ end
end
def install_dps_command
diff --git a/lib/gitlab/kubernetes/helm/pod.rb b/lib/gitlab/kubernetes/helm/pod.rb
index 97ad3c97e95..a3216759cae 100644
--- a/lib/gitlab/kubernetes/helm/pod.rb
+++ b/lib/gitlab/kubernetes/helm/pod.rb
@@ -10,9 +10,10 @@ module Gitlab
def generate
spec = { containers: [container_specification], restartPolicy: 'Never' }
+
if command.chart_values_file
- generate_config_map
- spec['volumes'] = volumes_specification
+ create_config_map
+ spec[:volumes] = volumes_specification
end
::Kubeclient::Resource.new(metadata: metadata, spec: spec)
@@ -35,19 +36,39 @@ module Gitlab
end
def labels
- { 'gitlab.org/action': 'install', 'gitlab.org/application': command.name }
+ {
+ 'gitlab.org/action': 'install',
+ 'gitlab.org/application': command.name
+ }
end
def metadata
- { name: command.pod_name, namespace: namespace_name, labels: labels }
+ {
+ name: command.pod_name,
+ namespace: namespace_name,
+ labels: labels
+ }
end
def volume_mounts_specification
- [{ name: 'config-volume', mountPath: '/etc/config' }]
+ [
+ {
+ name: 'configuration-volume',
+ mountPath: "/data/helm/#{command.name}/config"
+ }
+ ]
end
def volumes_specification
- [{ name: 'config-volume', configMap: { name: 'values-config' } }]
+ [
+ {
+ name: 'configuration-volume',
+ configMap: {
+ name: 'values-content-configuration',
+ items: [{ key: 'values', path: 'values.yaml' }]
+ }
+ }
+ ]
end
def generate_pod_env(command)
@@ -58,10 +79,10 @@ module Gitlab
}.map { |key, value| { name: key, value: value } }
end
- def generate_config_map
+ def create_config_map
resource = ::Kubeclient::Resource.new
- resource.metadata = { name: 'values-config', namespace: namespace_name }
- resource.data = YAML.load_file(command.chart_values_file)
+ resource.metadata = { name: 'values-content-configuration', namespace: namespace_name, labels: { name: 'values-content-configuration' } }
+ resource.data = { values: File.read(command.chart_values_file) }
kubeclient.create_config_map(resource)
end
end
diff --git a/lib/gitlab/o_auth.rb b/lib/gitlab/o_auth.rb
new file mode 100644
index 00000000000..5ad8d83bd6e
--- /dev/null
+++ b/lib/gitlab/o_auth.rb
@@ -0,0 +1,6 @@
+module Gitlab
+ module OAuth
+ SignupDisabledError = Class.new(StandardError)
+ SigninDisabledForProviderError = Class.new(StandardError)
+ end
+end
diff --git a/lib/gitlab/o_auth/user.rb b/lib/gitlab/o_auth/user.rb
index d33f33d192f..fff9360ea27 100644
--- a/lib/gitlab/o_auth/user.rb
+++ b/lib/gitlab/o_auth/user.rb
@@ -5,8 +5,6 @@
#
module Gitlab
module OAuth
- SignupDisabledError = Class.new(StandardError)
-
class User
attr_accessor :auth_hash, :gl_user
@@ -29,7 +27,8 @@ module Gitlab
end
def save(provider = 'OAuth')
- unauthorized_to_create unless gl_user
+ raise SigninDisabledForProviderError if oauth_provider_disabled?
+ raise SignupDisabledError unless gl_user
block_after_save = needs_blocking?
@@ -226,8 +225,10 @@ module Gitlab
Gitlab::AppLogger
end
- def unauthorized_to_create
- raise SignupDisabledError
+ def oauth_provider_disabled?
+ Gitlab::CurrentSettings.current_application_settings
+ .disabled_oauth_sign_in_sources
+ .include?(auth_hash.provider)
end
end
end
diff --git a/lib/gitlab/performance_bar.rb b/lib/gitlab/performance_bar.rb
index e73245b82c1..e29e168fc5a 100644
--- a/lib/gitlab/performance_bar.rb
+++ b/lib/gitlab/performance_bar.rb
@@ -6,6 +6,7 @@ module Gitlab
EXPIRY_TIME = 5.minutes
def self.enabled?(user = nil)
+ return true if Rails.env.development?
return false unless user && allowed_group_id
allowed_user_ids.include?(user.id)
diff --git a/lib/gitlab/project_search_results.rb b/lib/gitlab/project_search_results.rb
index e2662fc362b..7771b15069b 100644
--- a/lib/gitlab/project_search_results.rb
+++ b/lib/gitlab/project_search_results.rb
@@ -44,25 +44,20 @@ module Gitlab
ref = nil
filename = nil
basename = nil
+ data = ""
startline = 0
- result.each_line.each_with_index do |line, index|
- matches = line.match(/^(?<ref>[^:]*):(?<filename>.*):(?<startline>\d+):/)
- if matches
+ result.strip.each_line.each_with_index do |line, index|
+ prefix ||= line.match(/^(?<ref>[^:]*):(?<filename>.*)\x00(?<startline>\d+)\x00/)&.tap do |matches|
ref = matches[:ref]
filename = matches[:filename]
startline = matches[:startline]
startline = startline.to_i - index
extname = Regexp.escape(File.extname(filename))
basename = filename.sub(/#{extname}$/, '')
- break
end
- end
-
- data = ""
- result.each_line do |line|
- data << line.sub(ref, '').sub(filename, '').sub(/^:-\d+-/, '').sub(/^::\d+:/, '')
+ data << line.sub(prefix.to_s, '')
end
FoundBlob.new(
diff --git a/lib/gitlab/regex.rb b/lib/gitlab/regex.rb
index 0002c7da8f1..7ab85e1c35c 100644
--- a/lib/gitlab/regex.rb
+++ b/lib/gitlab/regex.rb
@@ -67,7 +67,7 @@ module Gitlab
end
def build_trace_section_regex
- @build_trace_section_regexp ||= /section_((?:start)|(?:end)):(\d+):([^\r]+)\r\033\[0K/.freeze
+ @build_trace_section_regexp ||= /section_((?:start)|(?:end)):(\d+):([a-zA-Z0-9_.-]+)\r\033\[0K/.freeze
end
end
end
diff --git a/lib/gitlab/user_access.rb b/lib/gitlab/user_access.rb
index d9a5af09f08..f357488ac61 100644
--- a/lib/gitlab/user_access.rb
+++ b/lib/gitlab/user_access.rb
@@ -16,8 +16,10 @@ module Gitlab
def can_do_action?(action)
return false unless can_access_git?
- @permission_cache ||= {}
- @permission_cache[action] ||= user.can?(action, project)
+ permission_cache[action] =
+ permission_cache.fetch(action) do
+ user.can?(action, project)
+ end
end
def cannot_do_action?(action)
@@ -88,6 +90,10 @@ module Gitlab
private
+ def permission_cache
+ @permission_cache ||= {}
+ end
+
def can_access_git?
user && user.can?(:access_git)
end
diff --git a/lib/gitlab/utils.rb b/lib/gitlab/utils.rb
index b3baaf036d8..fa22f0e37b2 100644
--- a/lib/gitlab/utils.rb
+++ b/lib/gitlab/utils.rb
@@ -27,6 +27,10 @@ module Gitlab
.gsub(/(\A-+|-+\z)/, '')
end
+ def remove_line_breaks(str)
+ str.gsub(/\r?\n/, '')
+ end
+
def to_boolean(value)
return value if [true, false].include?(value)
return true if value =~ /^(true|t|yes|y|1|on)$/i
diff --git a/lib/gitlab/utils/override.rb b/lib/gitlab/utils/override.rb
new file mode 100644
index 00000000000..8bf6bcb1fe2
--- /dev/null
+++ b/lib/gitlab/utils/override.rb
@@ -0,0 +1,111 @@
+module Gitlab
+ module Utils
+ module Override
+ class Extension
+ def self.verify_class!(klass, method_name)
+ instance_method_defined?(klass, method_name) ||
+ raise(
+ NotImplementedError.new(
+ "#{klass}\##{method_name} doesn't exist!"))
+ end
+
+ def self.instance_method_defined?(klass, name, include_super: true)
+ klass.instance_methods(include_super).include?(name) ||
+ klass.private_instance_methods(include_super).include?(name)
+ end
+
+ attr_reader :subject
+
+ def initialize(subject)
+ @subject = subject
+ end
+
+ def add_method_name(method_name)
+ method_names << method_name
+ end
+
+ def add_class(klass)
+ classes << klass
+ end
+
+ def verify!
+ classes.each do |klass|
+ index = klass.ancestors.index(subject)
+ parents = klass.ancestors.drop(index + 1)
+
+ method_names.each do |method_name|
+ parents.any? do |parent|
+ self.class.instance_method_defined?(
+ parent, method_name, include_super: false)
+ end ||
+ raise(
+ NotImplementedError.new(
+ "#{klass}\##{method_name} doesn't exist!"))
+ end
+ end
+ end
+
+ private
+
+ def method_names
+ @method_names ||= []
+ end
+
+ def classes
+ @classes ||= []
+ end
+ end
+
+ # Instead of writing patterns like this:
+ #
+ # def f
+ # raise NotImplementedError unless defined?(super)
+ #
+ # true
+ # end
+ #
+ # We could write it like:
+ #
+ # extend ::Gitlab::Utils::Override
+ #
+ # override :f
+ # def f
+ # true
+ # end
+ #
+ # This would make sure we're overriding something. See:
+ # https://gitlab.com/gitlab-org/gitlab-ee/issues/1819
+ def override(method_name)
+ return unless ENV['STATIC_VERIFICATION']
+
+ if is_a?(Class)
+ Extension.verify_class!(self, method_name)
+ else # We delay the check for modules
+ Override.extensions[self] ||= Extension.new(self)
+ Override.extensions[self].add_method_name(method_name)
+ end
+ end
+
+ def included(base = nil)
+ return super if base.nil? # Rails concern, ignoring it
+
+ super
+
+ if base.is_a?(Class) # We could check for Class in `override`
+ # This could be `nil` if `override` was never called
+ Override.extensions[self]&.add_class(base)
+ end
+ end
+
+ alias_method :prepended, :included
+
+ def self.extensions
+ @extensions ||= {}
+ end
+
+ def self.verify!
+ extensions.values.each(&:verify!)
+ end
+ end
+ end
+end
diff --git a/lib/tasks/dev.rake b/lib/tasks/dev.rake
index e65609d7001..4beb94eeb8e 100644
--- a/lib/tasks/dev.rake
+++ b/lib/tasks/dev.rake
@@ -7,4 +7,9 @@ namespace :dev do
Rake::Task["gitlab:setup"].invoke
Rake::Task["gitlab:shell:setup"].invoke
end
+
+ desc "GitLab | Eager load application"
+ task load: :environment do
+ Rails.application.eager_load!
+ end
end
diff --git a/lib/tasks/gitlab/shell.rake b/lib/tasks/gitlab/shell.rake
index 0e6aed32c52..12ae4199b69 100644
--- a/lib/tasks/gitlab/shell.rake
+++ b/lib/tasks/gitlab/shell.rake
@@ -54,16 +54,6 @@ namespace :gitlab do
# (Re)create hooks
Rake::Task['gitlab:shell:create_hooks'].invoke
- # Required for debian packaging with PKGR: Setup .ssh/environment with
- # the current PATH, so that the correct ruby version gets loaded
- # Requires to set "PermitUserEnvironment yes" in sshd config (should not
- # be an issue since it is more than likely that there are no "normal"
- # user accounts on a gitlab server). The alternative is for the admin to
- # install a ruby (1.9.3+) in the global path.
- File.open(File.join(user_home, ".ssh", "environment"), "w+") do |f|
- f.puts "PATH=#{ENV['PATH']}"
- end
-
Gitlab::Shell.ensure_secret_token!
end
diff --git a/lib/tasks/lint.rake b/lib/tasks/lint.rake
index 7b63e93db0e..3ab406eff2c 100644
--- a/lib/tasks/lint.rake
+++ b/lib/tasks/lint.rake
@@ -1,5 +1,17 @@
unless Rails.env.production?
namespace :lint do
+ task :static_verification_env do
+ ENV['STATIC_VERIFICATION'] = 'true'
+ end
+
+ desc "GitLab | lint | Static verification"
+ task static_verification: %w[
+ lint:static_verification_env
+ dev:load
+ ] do
+ Gitlab::Utils::Override.verify!
+ end
+
desc "GitLab | lint | Lint JavaScript files using ESLint"
task :javascript do
Rake::Task['eslint'].invoke