summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorFilipa Lacerda <filipa@gitlab.com>2017-12-15 21:25:23 +0000
committerFilipa Lacerda <filipa@gitlab.com>2017-12-15 21:25:23 +0000
commit223cb3788a744f9b1b92959d3337000358db108b (patch)
tree77858e7ec0e2a731ddb7791f99d75ef4c23b4b54 /lib
parentb3606cff38b9defc764706ed6529a9e27dcf4847 (diff)
parenta1a323392d4f0cb59eab2e215fa4010b84fc122d (diff)
downloadgitlab-ce-41117-empty-state.tar.gz
Merge branch 'master' into 41117-empty-state41117-empty-state
* master: (71 commits) Update CHANGELOG.md for 10.2.5 Change CI config to use new base image fix issue #39843 Incorrect guidance stating blocked users will be removed from groups and projects as members Add changelog entry Update tests for toggle design change Update toggle styles to use icons Use icons instead of string labels for toggles Fix Rubocop offense in QA project specs Add SAST docs Fix UX issues in system info page Update svg package version Make sure user email is read only when synced with LDAP Add note about automatic pipelines when enabling Auto DevOps Backport changes from EE Docs update documentation guidelines Don't use Markdown cache for stubbed settings in specs Fix remaining calls to GitLab QA factories Rename QA scenarios to make factory concept explicit Export JS classes as modules Make rubocop happy ...
Diffstat (limited to 'lib')
-rw-r--r--lib/api/helpers.rb10
-rw-r--r--lib/api/helpers/internal_helpers.rb16
-rw-r--r--lib/api/tags.rb7
-rw-r--r--lib/extracts_path.rb16
-rw-r--r--lib/feature.rb9
-rw-r--r--lib/gitlab/cache/request_cache.rb6
-rw-r--r--lib/gitlab/ci/charts.rb2
-rw-r--r--lib/gitlab/ci/config/entry/configurable.rb12
-rw-r--r--lib/gitlab/ci/config/entry/node.rb6
-rw-r--r--lib/gitlab/ci/config/entry/validatable.rb2
-rw-r--r--lib/gitlab/conflict/file_collection.rb6
-rw-r--r--lib/gitlab/current_settings.rb2
-rw-r--r--lib/gitlab/cycle_analytics/base_event_fetcher.rb4
-rw-r--r--lib/gitlab/cycle_analytics/base_query.rb4
-rw-r--r--lib/gitlab/cycle_analytics/code_event_fetcher.rb6
-rw-r--r--lib/gitlab/cycle_analytics/issue_allowed.rb9
-rw-r--r--lib/gitlab/cycle_analytics/issue_event_fetcher.rb6
-rw-r--r--lib/gitlab/cycle_analytics/merge_request_allowed.rb9
-rw-r--r--lib/gitlab/cycle_analytics/plan_event_fetcher.rb4
-rw-r--r--lib/gitlab/cycle_analytics/production_helper.rb4
-rw-r--r--lib/gitlab/cycle_analytics/review_event_fetcher.rb8
-rw-r--r--lib/gitlab/cycle_analytics/staging_event_fetcher.rb4
-rw-r--r--lib/gitlab/database/rename_reserved_paths_migration/v1/migration_classes.rb4
-rw-r--r--lib/gitlab/emoji.rb10
-rw-r--r--lib/gitlab/git/conflict/resolver.rb59
-rw-r--r--lib/gitlab/git/gitlab_projects.rb258
-rw-r--r--lib/gitlab/git/operation_service.rb2
-rw-r--r--lib/gitlab/git/popen.rb12
-rw-r--r--lib/gitlab/git/repository.rb38
-rw-r--r--lib/gitlab/gitaly_client/repository_service.rb10
-rw-r--r--lib/gitlab/import_export/command_line_util.rb2
-rw-r--r--lib/gitlab/ldap/user.rb4
-rw-r--r--lib/gitlab/metrics/influx_db.rb2
-rw-r--r--lib/gitlab/metrics/prometheus.rb17
-rw-r--r--lib/gitlab/o_auth/provider.rb12
-rw-r--r--lib/gitlab/o_auth/user.rb38
-rw-r--r--lib/gitlab/shell.rb113
-rw-r--r--lib/gitlab/slash_commands/presenters/issue_base.rb14
-rw-r--r--lib/tasks/gettext.rake1
-rw-r--r--lib/tasks/gitlab/task_helpers.rb17
40 files changed, 580 insertions, 185 deletions
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index 686bf7a3c2b..9ba15893f55 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -32,6 +32,11 @@ module API
end
end
+ # rubocop:disable Gitlab/ModuleWithInstanceVariables
+ # We can't rewrite this with StrongMemoize because `sudo!` would
+ # actually write to `@current_user`, and `sudo?` would immediately
+ # call `current_user` again which reads from `@current_user`.
+ # We should rewrite this in a way that using StrongMemoize is possible
def current_user
return @current_user if defined?(@current_user)
@@ -45,6 +50,7 @@ module API
@current_user
end
+ # rubocop:enable Gitlab/ModuleWithInstanceVariables
def sudo?
initial_current_user != current_user
@@ -415,6 +421,7 @@ module API
private
+ # rubocop:disable Gitlab/ModuleWithInstanceVariables
def initial_current_user
return @initial_current_user if defined?(@initial_current_user)
@@ -424,6 +431,7 @@ module API
unauthorized!
end
end
+ # rubocop:enable Gitlab/ModuleWithInstanceVariables
def sudo!
return unless sudo_identifier
@@ -443,7 +451,7 @@ module API
sudoed_user = find_user(sudo_identifier)
not_found!("User with ID or username '#{sudo_identifier}'") unless sudoed_user
- @current_user = sudoed_user
+ @current_user = sudoed_user # rubocop:disable Gitlab/ModuleWithInstanceVariables
end
def sudo_identifier
diff --git a/lib/api/helpers/internal_helpers.rb b/lib/api/helpers/internal_helpers.rb
index d6dea4c30e3..eff1c5b70ea 100644
--- a/lib/api/helpers/internal_helpers.rb
+++ b/lib/api/helpers/internal_helpers.rb
@@ -6,18 +6,16 @@ module API
'git-upload-pack' => [:ssh_upload_pack, Gitlab::GitalyClient::MigrationStatus::OPT_OUT]
}.freeze
+ attr_reader :redirected_path
+
def wiki?
- set_project unless defined?(@wiki)
- @wiki
+ set_project unless defined?(@wiki) # rubocop:disable Gitlab/ModuleWithInstanceVariables
+ @wiki # rubocop:disable Gitlab/ModuleWithInstanceVariables
end
def project
- set_project unless defined?(@project)
- @project
- end
-
- def redirected_path
- @redirected_path
+ set_project unless defined?(@project) # rubocop:disable Gitlab/ModuleWithInstanceVariables
+ @project # rubocop:disable Gitlab/ModuleWithInstanceVariables
end
def ssh_authentication_abilities
@@ -69,6 +67,7 @@ module API
private
+ # rubocop:disable Gitlab/ModuleWithInstanceVariables
def set_project
if params[:gl_repository]
@project, @wiki = Gitlab::GlRepository.parse(params[:gl_repository])
@@ -77,6 +76,7 @@ module API
@project, @wiki, @redirected_path = Gitlab::RepoPath.parse(params[:project])
end
end
+ # rubocop:enable Gitlab/ModuleWithInstanceVariables
# Project id to pass between components that don't share/don't have
# access to the same filesystem mounts
diff --git a/lib/api/tags.rb b/lib/api/tags.rb
index 0d394a7b441..5e0afc6a7e4 100644
--- a/lib/api/tags.rb
+++ b/lib/api/tags.rb
@@ -14,10 +14,15 @@ module API
success Entities::Tag
end
params do
+ optional :sort, type: String, values: %w[asc desc], default: 'desc',
+ desc: 'Return tags sorted in updated by `asc` or `desc` order.'
+ optional :order_by, type: String, values: %w[name updated], default: 'updated',
+ desc: 'Return tags ordered by `name` or `updated` fields.'
use :pagination
end
get ':id/repository/tags' do
- tags = ::Kaminari.paginate_array(user_project.repository.tags.sort_by(&:name).reverse)
+ tags = ::Kaminari.paginate_array(::TagsFinder.new(user_project.repository, sort: "#{params[:order_by]}_#{params[:sort]}").execute)
+
present paginate(tags), with: Entities::Tag, project: user_project
end
diff --git a/lib/extracts_path.rb b/lib/extracts_path.rb
index 721ed97bb6b..d8aca3304c5 100644
--- a/lib/extracts_path.rb
+++ b/lib/extracts_path.rb
@@ -40,7 +40,7 @@ module ExtractsPath
def extract_ref(id)
pair = ['', '']
- return pair unless @project
+ return pair unless @project # rubocop:disable Gitlab/ModuleWithInstanceVariables
if id =~ /^(\h{40})(.+)/
# If the ref appears to be a SHA, we're done, just split the string
@@ -104,6 +104,7 @@ module ExtractsPath
#
# Automatically renders `not_found!` if a valid tree path could not be
# resolved (e.g., when a user inserts an invalid path or ref).
+ # rubocop:disable Gitlab/ModuleWithInstanceVariables
def assign_ref_vars
# assign allowed options
allowed_options = ["filter_ref"]
@@ -127,13 +128,18 @@ module ExtractsPath
@hex_path = Digest::SHA1.hexdigest(@path)
@logs_path = logs_file_project_ref_path(@project, @ref, @path)
-
rescue RuntimeError, NoMethodError, InvalidPathError
render_404
end
+ # rubocop:enable Gitlab/ModuleWithInstanceVariables
def tree
- @tree ||= @repo.tree(@commit.id, @path)
+ @tree ||= @repo.tree(@commit.id, @path) # rubocop:disable Gitlab/ModuleWithInstanceVariables
+ end
+
+ def lfs_blob_ids
+ blob_ids = tree.blobs.map(&:id)
+ @lfs_blob_ids = Gitlab::Git::Blob.batch_lfs_pointers(@project.repository, blob_ids).map(&:id) # rubocop:disable Gitlab/ModuleWithInstanceVariables
end
private
@@ -146,8 +152,8 @@ module ExtractsPath
end
def ref_names
- return [] unless @project
+ return [] unless @project # rubocop:disable Gitlab/ModuleWithInstanceVariables
- @ref_names ||= @project.repository.ref_names
+ @ref_names ||= @project.repository.ref_names # rubocop:disable Gitlab/ModuleWithInstanceVariables
end
end
diff --git a/lib/feature.rb b/lib/feature.rb
index ac3bc65c0d5..8e9ba5c530a 100644
--- a/lib/feature.rb
+++ b/lib/feature.rb
@@ -1,5 +1,3 @@
-require 'flipper/adapters/active_record'
-
class Feature
# Classes to override flipper table names
class FlipperFeature < Flipper::Adapters::ActiveRecord::Feature
@@ -62,12 +60,7 @@ class Feature
end
def flipper
- @flipper ||= begin
- adapter = Flipper::Adapters::ActiveRecord.new(
- feature_class: FlipperFeature, gate_class: FlipperGate)
-
- Flipper.new(adapter)
- end
+ @flipper ||= Flipper.instance
end
# This method is called from config/initializers/flipper.rb and can be used
diff --git a/lib/gitlab/cache/request_cache.rb b/lib/gitlab/cache/request_cache.rb
index 754a45c3257..ecc85f847d4 100644
--- a/lib/gitlab/cache/request_cache.rb
+++ b/lib/gitlab/cache/request_cache.rb
@@ -45,11 +45,13 @@ module Gitlab
klass.prepend(extension)
end
+ attr_accessor :request_cache_key_block
+
def request_cache_key(&block)
if block_given?
- @request_cache_key = block
+ self.request_cache_key_block = block
else
- @request_cache_key
+ request_cache_key_block
end
end
diff --git a/lib/gitlab/ci/charts.rb b/lib/gitlab/ci/charts.rb
index 7df7b542d91..525563a97f5 100644
--- a/lib/gitlab/ci/charts.rb
+++ b/lib/gitlab/ci/charts.rb
@@ -6,7 +6,7 @@ module Gitlab
query
.group("DATE(#{::Ci::Pipeline.table_name}.created_at)")
.count(:created_at)
- .transform_keys { |date| date.strftime(@format) }
+ .transform_keys { |date| date.strftime(@format) } # rubocop:disable Gitlab/ModuleWithInstanceVariables
end
def interval_step
diff --git a/lib/gitlab/ci/config/entry/configurable.rb b/lib/gitlab/ci/config/entry/configurable.rb
index 68b6742385a..db47c2f6185 100644
--- a/lib/gitlab/ci/config/entry/configurable.rb
+++ b/lib/gitlab/ci/config/entry/configurable.rb
@@ -29,15 +29,15 @@ module Gitlab
self.class.nodes.each do |key, factory|
factory
- .value(@config[key])
+ .value(config[key])
.with(key: key, parent: self)
- @entries[key] = factory.create!
+ entries[key] = factory.create!
end
yield if block_given?
- @entries.each_value do |entry|
+ entries.each_value do |entry|
entry.compose!(deps)
end
end
@@ -59,13 +59,13 @@ module Gitlab
def helpers(*nodes)
nodes.each do |symbol|
define_method("#{symbol}_defined?") do
- @entries[symbol]&.specified?
+ entries[symbol]&.specified?
end
define_method("#{symbol}_value") do
- return unless @entries[symbol] && @entries[symbol].valid?
+ return unless entries[symbol] && entries[symbol].valid?
- @entries[symbol].value
+ entries[symbol].value
end
end
end
diff --git a/lib/gitlab/ci/config/entry/node.rb b/lib/gitlab/ci/config/entry/node.rb
index c868943c42e..1fba0b2db0b 100644
--- a/lib/gitlab/ci/config/entry/node.rb
+++ b/lib/gitlab/ci/config/entry/node.rb
@@ -90,6 +90,12 @@ module Gitlab
def self.aspects
@aspects ||= []
end
+
+ private
+
+ def entries
+ @entries
+ end
end
end
end
diff --git a/lib/gitlab/ci/config/entry/validatable.rb b/lib/gitlab/ci/config/entry/validatable.rb
index 5ced778d311..e45787773a8 100644
--- a/lib/gitlab/ci/config/entry/validatable.rb
+++ b/lib/gitlab/ci/config/entry/validatable.rb
@@ -13,7 +13,7 @@ module Gitlab
end
def errors
- @validator.messages + descendants.flat_map(&:errors)
+ @validator.messages + descendants.flat_map(&:errors) # rubocop:disable Gitlab/ModuleWithInstanceVariables
end
class_methods do
diff --git a/lib/gitlab/conflict/file_collection.rb b/lib/gitlab/conflict/file_collection.rb
index b9099ce256a..76aee5a3deb 100644
--- a/lib/gitlab/conflict/file_collection.rb
+++ b/lib/gitlab/conflict/file_collection.rb
@@ -4,11 +4,11 @@ module Gitlab
attr_reader :merge_request, :resolver
def initialize(merge_request)
- source_repo = merge_request.source_project.repository.raw
our_commit = merge_request.source_branch_head.raw
their_commit = merge_request.target_branch_head.raw
target_repo = merge_request.target_project.repository.raw
- @resolver = Gitlab::Git::Conflict::Resolver.new(source_repo, our_commit, target_repo, their_commit)
+ @source_repo = merge_request.source_project.repository.raw
+ @resolver = Gitlab::Git::Conflict::Resolver.new(target_repo, our_commit.id, their_commit.id)
@merge_request = merge_request
end
@@ -18,7 +18,7 @@ module Gitlab
target_branch: merge_request.target_branch,
commit_message: commit_message || default_commit_message
}
- resolver.resolve_conflicts(user, files, args)
+ resolver.resolve_conflicts(@source_repo, user, files, args)
ensure
@merge_request.clear_memoized_shas
end
diff --git a/lib/gitlab/current_settings.rb b/lib/gitlab/current_settings.rb
index 642f0944354..91fd9cc7631 100644
--- a/lib/gitlab/current_settings.rb
+++ b/lib/gitlab/current_settings.rb
@@ -53,7 +53,7 @@ module Gitlab
end
def in_memory_application_settings
- @in_memory_application_settings ||= ::ApplicationSetting.new(::ApplicationSetting.defaults)
+ @in_memory_application_settings ||= ::ApplicationSetting.new(::ApplicationSetting.defaults) # rubocop:disable Gitlab/ModuleWithInstanceVariables
rescue ActiveRecord::StatementInvalid, ActiveRecord::UnknownAttributeError
# In case migrations the application_settings table is not created yet,
# we fallback to a simple OpenStruct
diff --git a/lib/gitlab/cycle_analytics/base_event_fetcher.rb b/lib/gitlab/cycle_analytics/base_event_fetcher.rb
index ab115afcaa5..e3e3767cc75 100644
--- a/lib/gitlab/cycle_analytics/base_event_fetcher.rb
+++ b/lib/gitlab/cycle_analytics/base_event_fetcher.rb
@@ -56,7 +56,9 @@ module Gitlab
end
def allowed_ids
- nil
+ @allowed_ids ||= allowed_ids_finder_class
+ .new(@options[:current_user], project_id: @project.id)
+ .execute.where(id: event_result_ids).pluck(:id)
end
def event_result_ids
diff --git a/lib/gitlab/cycle_analytics/base_query.rb b/lib/gitlab/cycle_analytics/base_query.rb
index 58729d3ced8..dcbdf9a64b0 100644
--- a/lib/gitlab/cycle_analytics/base_query.rb
+++ b/lib/gitlab/cycle_analytics/base_query.rb
@@ -14,9 +14,9 @@ module Gitlab
def stage_query
query = mr_closing_issues_table.join(issue_table).on(issue_table[:id].eq(mr_closing_issues_table[:issue_id]))
.join(issue_metrics_table).on(issue_table[:id].eq(issue_metrics_table[:issue_id]))
- .where(issue_table[:project_id].eq(@project.id))
+ .where(issue_table[:project_id].eq(@project.id)) # rubocop:disable Gitlab/ModuleWithInstanceVariables
.where(issue_table[:deleted_at].eq(nil))
- .where(issue_table[:created_at].gteq(@options[:from]))
+ .where(issue_table[:created_at].gteq(@options[:from])) # rubocop:disable Gitlab/ModuleWithInstanceVariables
# Load merge_requests
query = query.join(mr_table, Arel::Nodes::OuterJoin)
diff --git a/lib/gitlab/cycle_analytics/code_event_fetcher.rb b/lib/gitlab/cycle_analytics/code_event_fetcher.rb
index d5bf6149749..06357c9b377 100644
--- a/lib/gitlab/cycle_analytics/code_event_fetcher.rb
+++ b/lib/gitlab/cycle_analytics/code_event_fetcher.rb
@@ -1,8 +1,6 @@
module Gitlab
module CycleAnalytics
class CodeEventFetcher < BaseEventFetcher
- include MergeRequestAllowed
-
def initialize(*args)
@projections = [mr_table[:title],
mr_table[:iid],
@@ -20,6 +18,10 @@ module Gitlab
def serialize(event)
AnalyticsMergeRequestSerializer.new(project: @project).represent(event)
end
+
+ def allowed_ids_finder_class
+ MergeRequestsFinder
+ end
end
end
end
diff --git a/lib/gitlab/cycle_analytics/issue_allowed.rb b/lib/gitlab/cycle_analytics/issue_allowed.rb
deleted file mode 100644
index a7652a70641..00000000000
--- a/lib/gitlab/cycle_analytics/issue_allowed.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-module Gitlab
- module CycleAnalytics
- module IssueAllowed
- def allowed_ids
- @allowed_ids ||= IssuesFinder.new(@options[:current_user], project_id: @project.id).execute.where(id: event_result_ids).pluck(:id)
- end
- end
- end
-end
diff --git a/lib/gitlab/cycle_analytics/issue_event_fetcher.rb b/lib/gitlab/cycle_analytics/issue_event_fetcher.rb
index 3df9cbdcfce..1754f91dccb 100644
--- a/lib/gitlab/cycle_analytics/issue_event_fetcher.rb
+++ b/lib/gitlab/cycle_analytics/issue_event_fetcher.rb
@@ -1,8 +1,6 @@
module Gitlab
module CycleAnalytics
class IssueEventFetcher < BaseEventFetcher
- include IssueAllowed
-
def initialize(*args)
@projections = [issue_table[:title],
issue_table[:iid],
@@ -18,6 +16,10 @@ module Gitlab
def serialize(event)
AnalyticsIssueSerializer.new(project: @project).represent(event)
end
+
+ def allowed_ids_finder_class
+ IssuesFinder
+ end
end
end
end
diff --git a/lib/gitlab/cycle_analytics/merge_request_allowed.rb b/lib/gitlab/cycle_analytics/merge_request_allowed.rb
deleted file mode 100644
index 28f6db44759..00000000000
--- a/lib/gitlab/cycle_analytics/merge_request_allowed.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-module Gitlab
- module CycleAnalytics
- module MergeRequestAllowed
- def allowed_ids
- @allowed_ids ||= MergeRequestsFinder.new(@options[:current_user], project_id: @project.id).execute.where(id: event_result_ids).pluck(:id)
- end
- end
- end
-end
diff --git a/lib/gitlab/cycle_analytics/plan_event_fetcher.rb b/lib/gitlab/cycle_analytics/plan_event_fetcher.rb
index 9230894877f..086203b9ccc 100644
--- a/lib/gitlab/cycle_analytics/plan_event_fetcher.rb
+++ b/lib/gitlab/cycle_analytics/plan_event_fetcher.rb
@@ -18,6 +18,10 @@ module Gitlab
private
+ def allowed_ids
+ nil
+ end
+
def merge_request_diff_commits
@merge_request_diff_commits ||=
MergeRequestDiffCommit
diff --git a/lib/gitlab/cycle_analytics/production_helper.rb b/lib/gitlab/cycle_analytics/production_helper.rb
index d693443bfa4..7a889b3877f 100644
--- a/lib/gitlab/cycle_analytics/production_helper.rb
+++ b/lib/gitlab/cycle_analytics/production_helper.rb
@@ -2,7 +2,9 @@ module Gitlab
module CycleAnalytics
module ProductionHelper
def stage_query
- super.where(mr_metrics_table[:first_deployed_to_production_at].gteq(@options[:from]))
+ super
+ .where(mr_metrics_table[:first_deployed_to_production_at]
+ .gteq(@options[:from])) # rubocop:disable Gitlab/ModuleWithInstanceVariables
end
end
end
diff --git a/lib/gitlab/cycle_analytics/review_event_fetcher.rb b/lib/gitlab/cycle_analytics/review_event_fetcher.rb
index 4c7b3f4467f..dada819a2a8 100644
--- a/lib/gitlab/cycle_analytics/review_event_fetcher.rb
+++ b/lib/gitlab/cycle_analytics/review_event_fetcher.rb
@@ -1,8 +1,6 @@
module Gitlab
module CycleAnalytics
class ReviewEventFetcher < BaseEventFetcher
- include MergeRequestAllowed
-
def initialize(*args)
@projections = [mr_table[:title],
mr_table[:iid],
@@ -14,9 +12,15 @@ module Gitlab
super(*args)
end
+ private
+
def serialize(event)
AnalyticsMergeRequestSerializer.new(project: @project).represent(event)
end
+
+ def allowed_ids_finder_class
+ MergeRequestsFinder
+ end
end
end
end
diff --git a/lib/gitlab/cycle_analytics/staging_event_fetcher.rb b/lib/gitlab/cycle_analytics/staging_event_fetcher.rb
index 36c0260dbfe..2f014153ca5 100644
--- a/lib/gitlab/cycle_analytics/staging_event_fetcher.rb
+++ b/lib/gitlab/cycle_analytics/staging_event_fetcher.rb
@@ -22,6 +22,10 @@ module Gitlab
private
+ def allowed_ids
+ nil
+ end
+
def serialize(event)
AnalyticsBuildSerializer.new.represent(event['build'])
end
diff --git a/lib/gitlab/database/rename_reserved_paths_migration/v1/migration_classes.rb b/lib/gitlab/database/rename_reserved_paths_migration/v1/migration_classes.rb
index 7e492938eac..fd4a8832ec2 100644
--- a/lib/gitlab/database/rename_reserved_paths_migration/v1/migration_classes.rb
+++ b/lib/gitlab/database/rename_reserved_paths_migration/v1/migration_classes.rb
@@ -6,7 +6,7 @@ module Gitlab
module Routable
def full_path
if route && route.path.present?
- @full_path ||= route.path
+ @full_path ||= route.path # rubocop:disable Gitlab/ModuleWithInstanceVariables
else
update_route if persisted?
@@ -30,7 +30,7 @@ module Gitlab
def prepare_route
route || build_route(source: self)
route.path = build_full_path
- @full_path = nil
+ @full_path = nil # rubocop:disable Gitlab/ModuleWithInstanceVariables
end
end
diff --git a/lib/gitlab/emoji.rb b/lib/gitlab/emoji.rb
index e3e36b35ce9..89cf659bce4 100644
--- a/lib/gitlab/emoji.rb
+++ b/lib/gitlab/emoji.rb
@@ -31,8 +31,7 @@ module Gitlab
end
def emoji_unicode_version(name)
- @emoji_unicode_versions_by_name ||= JSON.parse(File.read(Rails.root.join('fixtures', 'emojis', 'emoji-unicode-version-map.json')))
- @emoji_unicode_versions_by_name[name]
+ emoji_unicode_versions_by_name[name]
end
def normalize_emoji_name(name)
@@ -56,5 +55,12 @@ module Gitlab
ActionController::Base.helpers.content_tag('gl-emoji', emoji_info['moji'], title: emoji_info['description'], data: data)
end
+
+ private
+
+ def emoji_unicode_versions_by_name
+ @emoji_unicode_versions_by_name ||=
+ JSON.parse(File.read(Rails.root.join('fixtures', 'emojis', 'emoji-unicode-version-map.json')))
+ end
end
end
diff --git a/lib/gitlab/git/conflict/resolver.rb b/lib/gitlab/git/conflict/resolver.rb
index de8cce41b6d..03e5c0fcd6f 100644
--- a/lib/gitlab/git/conflict/resolver.rb
+++ b/lib/gitlab/git/conflict/resolver.rb
@@ -5,38 +5,31 @@ module Gitlab
ConflictSideMissing = Class.new(StandardError)
ResolutionError = Class.new(StandardError)
- def initialize(repository, our_commit, target_repository, their_commit)
- @repository = repository
- @our_commit = our_commit.rugged_commit
+ def initialize(target_repository, our_commit_oid, their_commit_oid)
@target_repository = target_repository
- @their_commit = their_commit.rugged_commit
+ @our_commit_oid = our_commit_oid
+ @their_commit_oid = their_commit_oid
end
def conflicts
@conflicts ||= begin
- target_index = @target_repository.rugged.merge_commits(@our_commit, @their_commit)
+ target_index = @target_repository.rugged.merge_commits(@our_commit_oid, @their_commit_oid)
# We don't need to do `with_repo_branch_commit` here, because the target
# project always fetches source refs when creating merge request diffs.
- target_index.conflicts.map do |conflict|
- raise ConflictSideMissing unless conflict[:theirs] && conflict[:ours]
-
- Gitlab::Git::Conflict::File.new(
- @target_repository,
- @our_commit.oid,
- conflict,
- target_index.merge_file(conflict[:ours][:path])[:data]
- )
- end
+ conflict_files(@target_repository, target_index)
end
end
- def resolve_conflicts(user, files, source_branch:, target_branch:, commit_message:)
- @repository.with_repo_branch_commit(@target_repository, target_branch) do
+ def resolve_conflicts(source_repository, user, files, source_branch:, target_branch:, commit_message:)
+ source_repository.with_repo_branch_commit(@target_repository, target_branch) do
+ index = source_repository.rugged.merge_commits(@our_commit_oid, @their_commit_oid)
+ conflicts = conflict_files(source_repository, index)
+
files.each do |file_params|
- conflict_file = conflict_for_path(file_params[:old_path], file_params[:new_path])
+ conflict_file = conflict_for_path(conflicts, file_params[:old_path], file_params[:new_path])
- write_resolved_file_to_index(conflict_file, file_params)
+ write_resolved_file_to_index(source_repository, index, conflict_file, file_params)
end
unless index.conflicts.empty?
@@ -47,14 +40,14 @@ module Gitlab
commit_params = {
message: commit_message,
- parents: [@our_commit, @their_commit].map(&:oid)
+ parents: [@our_commit_oid, @their_commit_oid]
}
- @repository.commit_index(user, source_branch, index, commit_params)
+ source_repository.commit_index(user, source_branch, index, commit_params)
end
end
- def conflict_for_path(old_path, new_path)
+ def conflict_for_path(conflicts, old_path, new_path)
conflicts.find do |conflict|
conflict.their_path == old_path && conflict.our_path == new_path
end
@@ -62,15 +55,20 @@ module Gitlab
private
- # We can only write when getting the merge index from the source
- # project, because we will write to that project. We don't use this all
- # the time because this fetches a ref into the source project, which
- # isn't needed for reading.
- def index
- @index ||= @repository.rugged.merge_commits(@our_commit, @their_commit)
+ def conflict_files(repository, index)
+ index.conflicts.map do |conflict|
+ raise ConflictSideMissing unless conflict[:theirs] && conflict[:ours]
+
+ Gitlab::Git::Conflict::File.new(
+ repository,
+ @our_commit_oid,
+ conflict,
+ index.merge_file(conflict[:ours][:path])[:data]
+ )
+ end
end
- def write_resolved_file_to_index(file, params)
+ def write_resolved_file_to_index(repository, index, file, params)
if params[:sections]
resolved_lines = file.resolve_lines(params[:sections])
new_file = resolved_lines.map { |line| line[:full_line] }.join("\n")
@@ -82,7 +80,8 @@ module Gitlab
our_path = file.our_path
- index.add(path: our_path, oid: @repository.rugged.write(new_file, :blob), mode: file.our_mode)
+ oid = repository.rugged.write(new_file, :blob)
+ index.add(path: our_path, oid: oid, mode: file.our_mode)
index.conflict_remove(our_path)
end
end
diff --git a/lib/gitlab/git/gitlab_projects.rb b/lib/gitlab/git/gitlab_projects.rb
new file mode 100644
index 00000000000..d948d7895ed
--- /dev/null
+++ b/lib/gitlab/git/gitlab_projects.rb
@@ -0,0 +1,258 @@
+module Gitlab
+ module Git
+ class GitlabProjects
+ include Gitlab::Git::Popen
+
+ # Absolute path to directory where repositories are stored.
+ # Example: /home/git/repositories
+ attr_reader :shard_path
+
+ # Relative path is a directory name for repository with .git at the end.
+ # Example: gitlab-org/gitlab-test.git
+ attr_reader :repository_relative_path
+
+ # Absolute path to the repository.
+ # Example: /home/git/repositorities/gitlab-org/gitlab-test.git
+ attr_reader :repository_absolute_path
+
+ # This is the path at which the gitlab-shell hooks directory can be found.
+ # It's essential for integration between git and GitLab proper. All new
+ # repositories should have their hooks directory symlinked here.
+ attr_reader :global_hooks_path
+
+ attr_reader :logger
+
+ def initialize(shard_path, repository_relative_path, global_hooks_path:, logger:)
+ @shard_path = shard_path
+ @repository_relative_path = repository_relative_path
+
+ @logger = logger
+ @global_hooks_path = global_hooks_path
+ @repository_absolute_path = File.join(shard_path, repository_relative_path)
+ @output = StringIO.new
+ end
+
+ def output
+ io = @output.dup
+ io.rewind
+ io.read
+ end
+
+ def rm_project
+ logger.info "Removing repository <#{repository_absolute_path}>."
+ FileUtils.rm_rf(repository_absolute_path)
+ end
+
+ # Move repository from one directory to another
+ #
+ # Example: gitlab/gitlab-ci.git -> randx/six.git
+ #
+ # Won't work if target namespace directory does not exist
+ #
+ def mv_project(new_path)
+ new_absolute_path = File.join(shard_path, new_path)
+
+ # verify that the source repo exists
+ unless File.exist?(repository_absolute_path)
+ logger.error "mv-project failed: source path <#{repository_absolute_path}> does not exist."
+ return false
+ end
+
+ # ...and that the target repo does not exist
+ if File.exist?(new_absolute_path)
+ logger.error "mv-project failed: destination path <#{new_absolute_path}> already exists."
+ return false
+ end
+
+ logger.info "Moving repository from <#{repository_absolute_path}> to <#{new_absolute_path}>."
+ FileUtils.mv(repository_absolute_path, new_absolute_path)
+ end
+
+ # 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
+ 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)
+ from_path = repository_absolute_path
+ to_path = File.join(new_shard_path, new_repository_relative_path)
+
+ # The repository cannot already exist
+ if File.exist?(to_path)
+ logger.error "fork-repository failed: destination repository <#{to_path}> already exists."
+ return false
+ end
+
+ # Ensure the namepsace / hashed storage directory exists
+ FileUtils.mkdir_p(File.dirname(to_path), mode: 0770)
+
+ logger.info "Forking repository from <#{from_path}> to <#{to_path}>."
+ cmd = %W(git clone --bare --no-local -- #{from_path} #{to_path})
+
+ run(cmd, nil) && Gitlab::Git::Repository.create_hooks(to_path, global_hooks_path)
+ end
+
+ def fetch_remote(name, timeout, force:, tags:, ssh_key: nil, known_hosts: nil)
+ tags_option = tags ? '--tags' : '--no-tags'
+
+ logger.info "Fetching remote #{name} for repository #{repository_absolute_path}."
+ cmd = %W(git fetch #{name} --prune --quiet)
+ cmd << '--force' if force
+ cmd << tags_option
+
+ setup_ssh_auth(ssh_key, known_hosts) do |env|
+ success = run_with_timeout(cmd, timeout, repository_absolute_path, env)
+
+ unless success
+ logger.error "Fetching remote #{name} for repository #{repository_absolute_path} failed."
+ end
+
+ success
+ end
+ end
+
+ def push_branches(remote_name, timeout, force, branch_names)
+ logger.info "Pushing branches from #{repository_absolute_path} to remote #{remote_name}: #{branch_names}"
+ cmd = %w(git push)
+ cmd << '--force' if force
+ cmd += %W(-- #{remote_name}).concat(branch_names)
+
+ success = run_with_timeout(cmd, timeout, repository_absolute_path)
+
+ unless success
+ logger.error("Pushing branches to remote #{remote_name} failed.")
+ end
+
+ success
+ end
+
+ def delete_remote_branches(remote_name, branch_names)
+ branches = branch_names.map { |branch_name| ":#{branch_name}" }
+
+ logger.info "Pushing deleted branches from #{repository_absolute_path} to remote #{remote_name}: #{branch_names}"
+ cmd = %W(git push -- #{remote_name}).concat(branches)
+
+ success = run(cmd, repository_absolute_path)
+
+ unless success
+ logger.error("Pushing deleted branches to remote #{remote_name} failed.")
+ end
+
+ success
+ end
+
+ protected
+
+ def run(*args)
+ output, exitstatus = popen(*args)
+ @output << output
+
+ exitstatus&.zero?
+ end
+
+ def run_with_timeout(*args)
+ output, exitstatus = popen_with_timeout(*args)
+ @output << output
+
+ exitstatus&.zero?
+ rescue Timeout::Error
+ @output.puts('Timed out')
+
+ false
+ end
+
+ def mask_password_in_url(url)
+ result = URI(url)
+ result.password = "*****" unless result.password.nil?
+ result.user = "*****" unless result.user.nil? # it's needed for oauth access_token
+ result
+ rescue
+ url
+ end
+
+ def remove_origin_in_repo
+ cmd = %w(git remote rm origin)
+ run(cmd, repository_absolute_path)
+ end
+
+ # Builds a small shell script that can be used to execute SSH with a set of
+ # custom options.
+ #
+ # Options are expanded as `'-oKey="Value"'`, so SSH will correctly interpret
+ # paths with spaces in them. We trust the user not to embed single or double
+ # quotes in the key or value.
+ def custom_ssh_script(options = {})
+ args = options.map { |k, v| %Q{'-o#{k}="#{v}"'} }.join(' ')
+
+ [
+ "#!/bin/sh",
+ "exec ssh #{args} \"$@\""
+ ].join("\n")
+ end
+
+ # Known hosts data and private keys can be passed to gitlab-shell in the
+ # environment. If present, this method puts them into temporary files, writes
+ # a script that can substitute as `ssh`, setting the options to respect those
+ # files, and yields: { "GIT_SSH" => "/tmp/myScript" }
+ def setup_ssh_auth(key, known_hosts)
+ options = {}
+
+ if key
+ key_file = Tempfile.new('gitlab-shell-key-file')
+ key_file.chmod(0o400)
+ key_file.write(key)
+ key_file.close
+
+ options['IdentityFile'] = key_file.path
+ options['IdentitiesOnly'] = 'yes'
+ end
+
+ if known_hosts
+ known_hosts_file = Tempfile.new('gitlab-shell-known-hosts')
+ known_hosts_file.chmod(0o400)
+ known_hosts_file.write(known_hosts)
+ known_hosts_file.close
+
+ options['StrictHostKeyChecking'] = 'yes'
+ options['UserKnownHostsFile'] = known_hosts_file.path
+ end
+
+ return yield({}) if options.empty?
+
+ script = Tempfile.new('gitlab-shell-ssh-wrapper')
+ script.chmod(0o755)
+ script.write(custom_ssh_script(options))
+ script.close
+
+ yield('GIT_SSH' => script.path)
+ ensure
+ key_file&.close!
+ known_hosts_file&.close!
+ script&.close!
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/git/operation_service.rb b/lib/gitlab/git/operation_service.rb
index 7e8fe173056..ef5bdbaf819 100644
--- a/lib/gitlab/git/operation_service.rb
+++ b/lib/gitlab/git/operation_service.rb
@@ -126,7 +126,7 @@ module Gitlab
oldrev = branch.target
- if oldrev == repository.rugged.merge_base(newrev, branch.target)
+ if oldrev == repository.merge_base(newrev, branch.target)
oldrev
else
raise Gitlab::Git::CommitError.new('Branch diverged')
diff --git a/lib/gitlab/git/popen.rb b/lib/gitlab/git/popen.rb
index d41fe78daa1..1ccca13ce2f 100644
--- a/lib/gitlab/git/popen.rb
+++ b/lib/gitlab/git/popen.rb
@@ -16,8 +16,8 @@ module Gitlab
vars['PWD'] = path
options = { chdir: path }
- @cmd_output = ""
- @cmd_status = 0
+ cmd_output = ""
+ cmd_status = 0
Open3.popen3(vars, *cmd, options) do |stdin, stdout, stderr, wait_thr|
yield(stdin) if block_given?
stdin.close
@@ -25,14 +25,14 @@ module Gitlab
if lazy_block
return lazy_block.call(stdout.lazy)
else
- @cmd_output << stdout.read
+ cmd_output << stdout.read
end
- @cmd_output << stderr.read
- @cmd_status = wait_thr.value.exitstatus
+ cmd_output << stderr.read
+ cmd_status = wait_thr.value.exitstatus
end
- [@cmd_output, @cmd_status]
+ [cmd_output, cmd_status]
end
def popen_with_timeout(cmd, timeout, path, vars = {})
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
index 0e0a1987c7d..848a782446a 100644
--- a/lib/gitlab/git/repository.rb
+++ b/lib/gitlab/git/repository.rb
@@ -39,10 +39,31 @@ module Gitlab
repo = Rugged::Repository.init_at(repo_path, bare)
repo.close
- if symlink_hooks_to.present?
- hooks_path = File.join(repo_path, 'hooks')
- FileUtils.rm_rf(hooks_path)
- FileUtils.ln_s(symlink_hooks_to, hooks_path)
+ create_hooks(repo_path, symlink_hooks_to) if symlink_hooks_to.present?
+
+ true
+ end
+
+ def create_hooks(repo_path, global_hooks_path)
+ local_hooks_path = File.join(repo_path, 'hooks')
+ real_local_hooks_path = :not_found
+
+ begin
+ real_local_hooks_path = File.realpath(local_hooks_path)
+ rescue Errno::ENOENT
+ # real_local_hooks_path == :not_found
+ end
+
+ # Do nothing if hooks already exist
+ unless real_local_hooks_path == File.realpath(global_hooks_path)
+ # Move the existing hooks somewhere safe
+ FileUtils.mv(
+ local_hooks_path,
+ "#{local_hooks_path}.old.#{Time.now.to_i}"
+ ) if File.exist?(local_hooks_path)
+
+ # Create the hooks symlink
+ FileUtils.ln_sf(global_hooks_path, local_hooks_path)
end
true
@@ -517,8 +538,15 @@ module Gitlab
# Returns the SHA of the most recent common ancestor of +from+ and +to+
def merge_base_commit(from, to)
- rugged.merge_base(from, to)
+ gitaly_migrate(:merge_base) do |is_enabled|
+ if is_enabled
+ gitaly_repository_client.find_merge_base(from, to)
+ else
+ rugged.merge_base(from, to)
+ end
+ end
end
+ alias_method :merge_base, :merge_base_commit
# Gitaly note: JV: check gitlab-ee before removing this method.
def rugged_is_ancestor?(ancestor_id, descendant_id)
diff --git a/lib/gitlab/gitaly_client/repository_service.rb b/lib/gitlab/gitaly_client/repository_service.rb
index a477d618f63..c1f95396878 100644
--- a/lib/gitlab/gitaly_client/repository_service.rb
+++ b/lib/gitlab/gitaly_client/repository_service.rb
@@ -69,6 +69,16 @@ module Gitlab
response.value
end
+ def find_merge_base(*revisions)
+ request = Gitaly::FindMergeBaseRequest.new(
+ repository: @gitaly_repo,
+ revisions: revisions.map { |r| GitalyClient.encode(r) }
+ )
+
+ response = GitalyClient.call(@storage, :repository_service, :find_merge_base, request)
+ response.base.presence
+ end
+
def fetch_source_branch(source_repository, source_branch, local_ref)
request = Gitaly::FetchSourceBranchRequest.new(
repository: @gitaly_repo,
diff --git a/lib/gitlab/import_export/command_line_util.rb b/lib/gitlab/import_export/command_line_util.rb
index 90942774a2e..0135b3c6f22 100644
--- a/lib/gitlab/import_export/command_line_util.rb
+++ b/lib/gitlab/import_export/command_line_util.rb
@@ -32,7 +32,7 @@ module Gitlab
def execute(cmd)
output, status = Gitlab::Popen.popen(cmd)
- @shared.error(Gitlab::ImportExport::Error.new(output.to_s)) unless status.zero?
+ @shared.error(Gitlab::ImportExport::Error.new(output.to_s)) unless status.zero? # rubocop:disable Gitlab/ModuleWithInstanceVariables
status.zero?
end
diff --git a/lib/gitlab/ldap/user.rb b/lib/gitlab/ldap/user.rb
index 3945df27eed..84ee94e38e4 100644
--- a/lib/gitlab/ldap/user.rb
+++ b/lib/gitlab/ldap/user.rb
@@ -36,10 +36,6 @@ module Gitlab
ldap_config.block_auto_created_users
end
- def sync_profile_from_provider?
- true
- end
-
def allowed?
Gitlab::LDAP::Access.allowed?(gl_user)
end
diff --git a/lib/gitlab/metrics/influx_db.rb b/lib/gitlab/metrics/influx_db.rb
index bdf7910b7c7..6ea132fc5bf 100644
--- a/lib/gitlab/metrics/influx_db.rb
+++ b/lib/gitlab/metrics/influx_db.rb
@@ -154,6 +154,7 @@ module Gitlab
# When enabled this should be set before being used as the usual pattern
# "@foo ||= bar" is _not_ thread-safe.
+ # rubocop:disable Gitlab/ModuleWithInstanceVariables
def pool
if influx_metrics_enabled?
if @pool.nil?
@@ -170,6 +171,7 @@ module Gitlab
@pool
end
end
+ # rubocop:enable Gitlab/ModuleWithInstanceVariables
end
end
end
diff --git a/lib/gitlab/metrics/prometheus.rb b/lib/gitlab/metrics/prometheus.rb
index 09103b4ca2d..b0b8e8436db 100644
--- a/lib/gitlab/metrics/prometheus.rb
+++ b/lib/gitlab/metrics/prometheus.rb
@@ -4,6 +4,7 @@ module Gitlab
module Metrics
module Prometheus
include Gitlab::CurrentSettings
+ include Gitlab::Utils::StrongMemoize
REGISTRY_MUTEX = Mutex.new
PROVIDER_MUTEX = Mutex.new
@@ -17,16 +18,18 @@ module Gitlab
end
def prometheus_metrics_enabled?
- return @prometheus_metrics_enabled if defined?(@prometheus_metrics_enabled)
-
- @prometheus_metrics_enabled = prometheus_metrics_enabled_unmemoized
+ strong_memoize(:prometheus_metrics_enabled) do
+ prometheus_metrics_enabled_unmemoized
+ end
end
def registry
- return @registry if @registry
-
- REGISTRY_MUTEX.synchronize do
- @registry ||= ::Prometheus::Client.registry
+ strong_memoize(:registry) do
+ REGISTRY_MUTEX.synchronize do
+ strong_memoize(:registry) do
+ ::Prometheus::Client.registry
+ end
+ end
end
end
diff --git a/lib/gitlab/o_auth/provider.rb b/lib/gitlab/o_auth/provider.rb
index ac9d66c836d..657db29c85a 100644
--- a/lib/gitlab/o_auth/provider.rb
+++ b/lib/gitlab/o_auth/provider.rb
@@ -19,6 +19,18 @@ module Gitlab
name.to_s.start_with?('ldap')
end
+ def self.sync_profile_from_provider?(provider)
+ return true if ldap_provider?(provider)
+
+ providers = Gitlab.config.omniauth.sync_profile_from_provider
+
+ if providers.is_a?(Array)
+ providers.include?(provider)
+ else
+ providers
+ end
+ end
+
def self.config_for(name)
name = name.to_s
if ldap_provider?(name)
diff --git a/lib/gitlab/o_auth/user.rb b/lib/gitlab/o_auth/user.rb
index 552133234a3..d33f33d192f 100644
--- a/lib/gitlab/o_auth/user.rb
+++ b/lib/gitlab/o_auth/user.rb
@@ -12,7 +12,7 @@ module Gitlab
def initialize(auth_hash)
self.auth_hash = auth_hash
- update_profile if sync_profile_from_provider?
+ update_profile
add_or_update_user_identities
end
@@ -195,29 +195,31 @@ module Gitlab
end
def sync_profile_from_provider?
- providers = Gitlab.config.omniauth.sync_profile_from_provider
-
- if providers.is_a?(Array)
- providers.include?(auth_hash.provider)
- else
- providers
- end
+ Gitlab::OAuth::Provider.sync_profile_from_provider?(auth_hash.provider)
end
def update_profile
- user_synced_attributes_metadata = gl_user.user_synced_attributes_metadata || gl_user.build_user_synced_attributes_metadata
-
- UserSyncedAttributesMetadata::SYNCABLE_ATTRIBUTES.each do |key|
- if auth_hash.has_attribute?(key) && gl_user.sync_attribute?(key)
- gl_user[key] = auth_hash.public_send(key) # rubocop:disable GitlabSecurity/PublicSend
- user_synced_attributes_metadata.set_attribute_synced(key, true)
- else
- user_synced_attributes_metadata.set_attribute_synced(key, false)
+ return unless sync_profile_from_provider? || creating_linked_ldap_user?
+
+ metadata = gl_user.user_synced_attributes_metadata || gl_user.build_user_synced_attributes_metadata
+
+ if sync_profile_from_provider?
+ UserSyncedAttributesMetadata::SYNCABLE_ATTRIBUTES.each do |key|
+ if auth_hash.has_attribute?(key) && gl_user.sync_attribute?(key)
+ gl_user[key] = auth_hash.public_send(key) # rubocop:disable GitlabSecurity/PublicSend
+ metadata.set_attribute_synced(key, true)
+ else
+ metadata.set_attribute_synced(key, false)
+ end
end
+
+ metadata.provider = auth_hash.provider
end
- user_synced_attributes_metadata.provider = auth_hash.provider
- gl_user.user_synced_attributes_metadata = user_synced_attributes_metadata
+ if creating_linked_ldap_user? && gl_user.email == ldap_person.email.first
+ metadata.set_attribute_synced(:email, true)
+ metadata.provider = ldap_person.provider
+ end
end
def log
diff --git a/lib/gitlab/shell.rb b/lib/gitlab/shell.rb
index a22a63665be..9cdd3d22f18 100644
--- a/lib/gitlab/shell.rb
+++ b/lib/gitlab/shell.rb
@@ -66,7 +66,7 @@ module Gitlab
# Init new repository
#
# storage - project's storage name
- # name - project path with namespace
+ # name - project disk path
#
# Ex.
# add_repository("/path/to/storage", "gitlab/gitlab-ci")
@@ -94,23 +94,28 @@ module Gitlab
# Import repository
#
# storage - project's storage path
- # name - project path with namespace
+ # name - project disk path
+ # url - URL to import from
#
# Ex.
- # import_repository("/path/to/storage", "gitlab/gitlab-ci", "https://github.com/randx/six.git")
+ # import_repository("/path/to/storage", "gitlab/gitlab-ci", "https://gitlab.com/gitlab-org/gitlab-test.git")
#
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/387
def import_repository(storage, name, url)
# The timeout ensures the subprocess won't hang forever
- cmd = [gitlab_shell_projects_path, 'import-project',
- storage, "#{name}.git", url, "#{Gitlab.config.gitlab_shell.git_timeout}"]
- gitlab_shell_fast_execute_raise_error(cmd)
+ cmd = gitlab_projects(storage, "#{name}.git")
+ success = cmd.import_project(url, git_timeout)
+
+ raise Error, cmd.output unless success
+
+ success
end
# Fetch remote for repository
#
# repository - an instance of Git::Repository
# remote - remote name
+ # ssh_auth - SSH known_hosts data and a private key to use for public-key authentication
# forced - should we use --force flag?
# no_tags - should we use --no-tags flag?
#
@@ -131,16 +136,15 @@ module Gitlab
# Move repository
# storage - project's storage path
- # path - project path with namespace
- # new_path - new project path with namespace
+ # path - project disk path
+ # new_path - new project disk path
#
# Ex.
# mv_repository("/path/to/storage", "gitlab/gitlab-ci", "randx/gitlab-ci-new")
#
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/387
def mv_repository(storage, path, new_path)
- gitlab_shell_fast_execute([gitlab_shell_projects_path, 'mv-project',
- storage, "#{path}.git", "#{new_path}.git"])
+ gitlab_projects(storage, "#{path}.git").mv_project("#{new_path}.git")
end
# Fork repository to new path
@@ -154,30 +158,21 @@ module Gitlab
#
# Gitaly note: JV: not easy to migrate because this involves two Gitaly servers, not one.
def fork_repository(forked_from_storage, forked_from_disk_path, forked_to_storage, forked_to_disk_path)
- gitlab_shell_fast_execute(
- [
- gitlab_shell_projects_path,
- 'fork-repository',
- forked_from_storage,
- "#{forked_from_disk_path}.git",
- forked_to_storage,
- "#{forked_to_disk_path}.git"
- ]
- )
+ gitlab_projects(forked_from_storage, "#{forked_from_disk_path}.git")
+ .fork_repository(forked_to_storage, "#{forked_to_disk_path}.git")
end
# Remove repository from file system
#
# storage - project's storage path
- # name - project path with namespace
+ # name - project disk path
#
# Ex.
# remove_repository("/path/to/storage", "gitlab/gitlab-ci")
#
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/387
def remove_repository(storage, name)
- gitlab_shell_fast_execute([gitlab_shell_projects_path,
- 'rm-project', storage, "#{name}.git"])
+ gitlab_projects(storage, "#{name}.git").rm_project
end
# Add new key to gitlab-shell
@@ -311,6 +306,47 @@ module Gitlab
end
end
+ # Push branch to remote repository
+ #
+ # storage - project's storage path
+ # project_name - project's disk path
+ # remote_name - remote name
+ # branch_names - remote branch names to push
+ # forced - should we use --force flag
+ #
+ # Ex.
+ # push_remote_branches('/path/to/storage', 'gitlab-org/gitlab-test' 'upstream', ['feature'])
+ #
+ def push_remote_branches(storage, project_name, remote_name, branch_names, forced: true)
+ cmd = gitlab_projects(storage, "#{project_name}.git")
+
+ success = cmd.push_branches(remote_name, git_timeout, forced, branch_names)
+
+ raise Error, cmd.output unless success
+
+ success
+ end
+
+ # Delete branch from remote repository
+ #
+ # storage - project's storage path
+ # project_name - project's disk path
+ # remote_name - remote name
+ # branch_names - remote branch names
+ #
+ # Ex.
+ # delete_remote_branches('/path/to/storage', 'gitlab-org/gitlab-test', 'upstream', ['feature'])
+ #
+ def delete_remote_branches(storage, project_name, remote_name, branch_names)
+ cmd = gitlab_projects(storage, "#{project_name}.git")
+
+ success = cmd.delete_remote_branches(remote_name, branch_names)
+
+ raise Error, cmd.output unless success
+
+ success
+ end
+
protected
def gitlab_shell_path
@@ -341,24 +377,35 @@ module Gitlab
private
- def local_fetch_remote(storage, name, remote, ssh_auth: nil, forced: false, no_tags: false)
- args = [gitlab_shell_projects_path, 'fetch-remote', storage, name, remote, "#{Gitlab.config.gitlab_shell.git_timeout}"]
- args << '--force' if forced
- args << '--no-tags' if no_tags
+ def gitlab_projects(shard_path, disk_path)
+ Gitlab::Git::GitlabProjects.new(
+ shard_path,
+ disk_path,
+ global_hooks_path: Gitlab.config.gitlab_shell.hooks_path,
+ logger: Rails.logger
+ )
+ end
- vars = {}
+ def local_fetch_remote(storage_path, repository_relative_path, remote, ssh_auth: nil, forced: false, no_tags: false)
+ vars = { force: forced, tags: !no_tags }
if ssh_auth&.ssh_import?
if ssh_auth.ssh_key_auth? && ssh_auth.ssh_private_key.present?
- vars['GITLAB_SHELL_SSH_KEY'] = ssh_auth.ssh_private_key
+ vars[:ssh_key] = ssh_auth.ssh_private_key
end
if ssh_auth.ssh_known_hosts.present?
- vars['GITLAB_SHELL_KNOWN_HOSTS'] = ssh_auth.ssh_known_hosts
+ vars[:known_hosts] = ssh_auth.ssh_known_hosts
end
end
- gitlab_shell_fast_execute_raise_error(args, vars)
+ cmd = gitlab_projects(storage_path, repository_relative_path)
+
+ success = cmd.fetch_remote(remote, git_timeout, vars)
+
+ raise Error, cmd.output unless success
+
+ success
end
def gitlab_shell_fast_execute(cmd)
@@ -394,6 +441,10 @@ module Gitlab
Gitlab::GitalyClient::NamespaceService.new(storage)
end
+ def git_timeout
+ Gitlab.config.gitlab_shell.git_timeout
+ end
+
def gitaly_migrate(method, &block)
Gitlab::GitalyClient.migrate(method, &block)
rescue GRPC::NotFound, GRPC::BadStatus => e
diff --git a/lib/gitlab/slash_commands/presenters/issue_base.rb b/lib/gitlab/slash_commands/presenters/issue_base.rb
index 341f2aabdd0..31c1e97efba 100644
--- a/lib/gitlab/slash_commands/presenters/issue_base.rb
+++ b/lib/gitlab/slash_commands/presenters/issue_base.rb
@@ -11,32 +11,36 @@ module Gitlab
end
def project
- @resource.project
+ resource.project
end
def author
- @resource.author
+ resource.author
end
def fields
[
{
title: "Assignee",
- value: @resource.assignees.any? ? @resource.assignees.first.name : "_None_",
+ value: resource.assignees.any? ? resource.assignees.first.name : "_None_",
short: true
},
{
title: "Milestone",
- value: @resource.milestone ? @resource.milestone.title : "_None_",
+ value: resource.milestone ? resource.milestone.title : "_None_",
short: true
},
{
title: "Labels",
- value: @resource.labels.any? ? @resource.label_names.join(', ') : "_None_",
+ value: resource.labels.any? ? resource.label_names.join(', ') : "_None_",
short: true
}
]
end
+
+ private
+
+ attr_reader :resource
end
end
end
diff --git a/lib/tasks/gettext.rake b/lib/tasks/gettext.rake
index 35ba729c156..247d7be7d78 100644
--- a/lib/tasks/gettext.rake
+++ b/lib/tasks/gettext.rake
@@ -23,6 +23,7 @@ namespace :gettext do
desc 'Lint all po files in `locale/'
task lint: :environment do
require 'simple_po_parser'
+ require 'gitlab/utils'
FastGettext.silence_errors
files = Dir.glob(Rails.root.join('locale/*/gitlab.po'))
diff --git a/lib/tasks/gitlab/task_helpers.rb b/lib/tasks/gitlab/task_helpers.rb
index 8a63f486fa3..6723662703c 100644
--- a/lib/tasks/gitlab/task_helpers.rb
+++ b/lib/tasks/gitlab/task_helpers.rb
@@ -1,10 +1,13 @@
require 'rainbow/ext/string'
+require 'gitlab/utils/strong_memoize'
module Gitlab
TaskFailedError = Class.new(StandardError)
TaskAbortedByUserError = Class.new(StandardError)
module TaskHelpers
+ include Gitlab::Utils::StrongMemoize
+
extend self
# Ask if the user wants to continue
@@ -105,16 +108,16 @@ module Gitlab
end
def gitlab_user?
- return @is_gitlab_user unless @is_gitlab_user.nil?
-
- current_user = run_command(%w(whoami)).chomp
- @is_gitlab_user = current_user == gitlab_user
+ strong_memoize(:is_gitlab_user) do
+ current_user = run_command(%w(whoami)).chomp
+ current_user == gitlab_user
+ end
end
def warn_user_is_not_gitlab
- return if @warned_user_not_gitlab
+ return if gitlab_user?
- unless gitlab_user?
+ strong_memoize(:warned_user_not_gitlab) do
current_user = run_command(%w(whoami)).chomp
puts " Warning ".color(:black).background(:yellow)
@@ -122,8 +125,6 @@ module Gitlab
puts " Things may work\/fail for the wrong reasons."
puts " For correct results you should run this as user #{gitlab_user.color(:magenta)}."
puts ""
-
- @warned_user_not_gitlab = true
end
end