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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-02-18 13:34:06 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-02-18 13:34:06 +0300
commit859a6fb938bb9ee2a317c46dfa4fcc1af49608f0 (patch)
treed7f2700abe6b4ffcb2dcfc80631b2d87d0609239 /app/services/groups
parent446d496a6d000c73a304be52587cd9bbc7493136 (diff)
Add latest changes from gitlab-org/gitlab@13-9-stable-eev13.9.0-rc42
Diffstat (limited to 'app/services/groups')
-rw-r--r--app/services/groups/import_export/export_service.rb56
-rw-r--r--app/services/groups/import_export/import_service.rb52
-rw-r--r--app/services/groups/open_issues_count_service.rb64
3 files changed, 126 insertions, 46 deletions
diff --git a/app/services/groups/import_export/export_service.rb b/app/services/groups/import_export/export_service.rb
index abac0ffc5d9..a436aec1b39 100644
--- a/app/services/groups/import_export/export_service.rb
+++ b/app/services/groups/import_export/export_service.rb
@@ -12,40 +12,44 @@ module Groups
end
def async_execute
- GroupExportWorker.perform_async(@current_user.id, @group.id, @params)
+ GroupExportWorker.perform_async(current_user.id, group.id, params)
end
def execute
validate_user_permissions
- remove_existing_export! if @group.export_file_exists?
+ remove_existing_export! if group.export_file_exists?
save!
ensure
- remove_base_tmp_dir
+ remove_archive_tmp_dir
end
private
+ attr_reader :group, :current_user, :params
attr_accessor :shared
def validate_user_permissions
- unless @current_user.can?(:admin_group, @group)
- @shared.error(::Gitlab::ImportExport::Error.permission_error(@current_user, @group))
+ unless current_user.can?(:admin_group, group)
+ shared.error(::Gitlab::ImportExport::Error.permission_error(current_user, group))
notify_error!
end
end
def remove_existing_export!
- import_export_upload = @group.import_export_upload
+ import_export_upload = group.import_export_upload
import_export_upload.remove_export_file!
import_export_upload.save
end
def save!
- if savers.all?(&:save)
+ # We cannot include the file_saver with the other savers because
+ # it removes the tmp dir. This means that if we want to add new savers
+ # in EE the data won't be available.
+ if savers.all?(&:save) && file_saver.save
notify_success
else
notify_error!
@@ -53,36 +57,40 @@ module Groups
end
def savers
- [version_saver, tree_exporter, file_saver]
+ [version_saver, tree_exporter]
end
def tree_exporter
tree_exporter_class.new(
- group: @group,
- current_user: @current_user,
- shared: @shared,
- params: @params
+ group: group,
+ current_user: current_user,
+ shared: shared,
+ params: params
)
end
def tree_exporter_class
- if ::Feature.enabled?(:group_export_ndjson, @group&.parent, default_enabled: true)
+ if ndjson?
Gitlab::ImportExport::Group::TreeSaver
else
Gitlab::ImportExport::Group::LegacyTreeSaver
end
end
+ def ndjson?
+ ::Feature.enabled?(:group_export_ndjson, group&.parent, default_enabled: :yaml)
+ end
+
def version_saver
Gitlab::ImportExport::VersionSaver.new(shared: shared)
end
def file_saver
- Gitlab::ImportExport::Saver.new(exportable: @group, shared: @shared)
+ Gitlab::ImportExport::Saver.new(exportable: group, shared: shared)
end
- def remove_base_tmp_dir
- FileUtils.rm_rf(shared.base_path) if shared&.base_path
+ def remove_archive_tmp_dir
+ FileUtils.rm_rf(shared.archive_path) if shared&.archive_path
end
def notify_error!
@@ -94,22 +102,22 @@ module Groups
def notify_success
@logger.info(
message: 'Group Export succeeded',
- group_id: @group.id,
- group_name: @group.name
+ group_id: group.id,
+ group_name: group.name
)
- notification_service.group_was_exported(@group, @current_user)
+ notification_service.group_was_exported(group, current_user)
end
def notify_error
@logger.error(
message: 'Group Export failed',
- group_id: @group.id,
- group_name: @group.name,
- errors: @shared.errors.join(', ')
+ group_id: group.id,
+ group_name: group.name,
+ errors: shared.errors.join(', ')
)
- notification_service.group_was_not_exported(@group, @current_user, @shared.errors)
+ notification_service.group_was_not_exported(group, current_user, shared.errors)
end
def notification_service
@@ -118,3 +126,5 @@ module Groups
end
end
end
+
+Groups::ImportExport::ExportService.prepend_if_ee('EE::Groups::ImportExport::ExportService')
diff --git a/app/services/groups/import_export/import_service.rb b/app/services/groups/import_export/import_service.rb
index a0ddc50e5e0..bf3f09f22d4 100644
--- a/app/services/groups/import_export/import_service.rb
+++ b/app/services/groups/import_export/import_service.rb
@@ -3,7 +3,7 @@
module Groups
module ImportExport
class ImportService
- attr_reader :current_user, :group, :params
+ attr_reader :current_user, :group, :shared
def initialize(group:, user:)
@group = group
@@ -26,10 +26,10 @@ module Groups
end
def execute
- if valid_user_permissions? && import_file && restorer.restore
+ if valid_user_permissions? && import_file && restorers.all?(&:restore)
notify_success
- @group
+ group
else
notify_error!
end
@@ -43,37 +43,41 @@ module Groups
def import_file
@import_file ||= Gitlab::ImportExport::FileImporter.import(
- importable: @group,
+ importable: group,
archive_file: nil,
- shared: @shared
+ shared: shared
)
end
- def restorer
- @restorer ||=
+ def restorers
+ [tree_restorer]
+ end
+
+ def tree_restorer
+ @tree_restorer ||=
if ndjson?
Gitlab::ImportExport::Group::TreeRestorer.new(
- user: @current_user,
- shared: @shared,
- group: @group
+ user: current_user,
+ shared: shared,
+ group: group
)
else
Gitlab::ImportExport::Group::LegacyTreeRestorer.new(
- user: @current_user,
- shared: @shared,
- group: @group,
+ user: current_user,
+ shared: shared,
+ group: group,
group_hash: nil
)
end
end
def ndjson?
- ::Feature.enabled?(:group_import_ndjson, @group&.parent, default_enabled: true) &&
- File.exist?(File.join(@shared.export_path, 'tree/groups/_all.ndjson'))
+ ::Feature.enabled?(:group_import_ndjson, group&.parent, default_enabled: true) &&
+ File.exist?(File.join(shared.export_path, 'tree/groups/_all.ndjson'))
end
def remove_import_file
- upload = @group.import_export_upload
+ upload = group.import_export_upload
return unless upload&.import_file&.file
@@ -85,7 +89,7 @@ module Groups
if current_user.can?(:admin_group, group)
true
else
- @shared.error(::Gitlab::ImportExport::Error.permission_error(current_user, group))
+ shared.error(::Gitlab::ImportExport::Error.permission_error(current_user, group))
false
end
@@ -93,16 +97,16 @@ module Groups
def notify_success
@logger.info(
- group_id: @group.id,
- group_name: @group.name,
+ group_id: group.id,
+ group_name: group.name,
message: 'Group Import/Export: Import succeeded'
)
end
def notify_error
@logger.error(
- group_id: @group.id,
- group_name: @group.name,
+ group_id: group.id,
+ group_name: group.name,
message: "Group Import/Export: Errors occurred, see '#{Gitlab::ErrorTracking::Logger.file_name}' for details"
)
end
@@ -110,12 +114,14 @@ module Groups
def notify_error!
notify_error
- raise Gitlab::ImportExport::Error.new(@shared.errors.to_sentence)
+ raise Gitlab::ImportExport::Error.new(shared.errors.to_sentence)
end
def remove_base_tmp_dir
- FileUtils.rm_rf(@shared.base_path)
+ FileUtils.rm_rf(shared.base_path)
end
end
end
end
+
+Groups::ImportExport::ImportService.prepend_if_ee('EE::Groups::ImportExport::ImportService')
diff --git a/app/services/groups/open_issues_count_service.rb b/app/services/groups/open_issues_count_service.rb
new file mode 100644
index 00000000000..db1ca09212a
--- /dev/null
+++ b/app/services/groups/open_issues_count_service.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+module Groups
+ # Service class for counting and caching the number of open issues of a group.
+ class OpenIssuesCountService < BaseCountService
+ include Gitlab::Utils::StrongMemoize
+
+ VERSION = 1
+ PUBLIC_COUNT_KEY = 'group_public_open_issues_count'
+ TOTAL_COUNT_KEY = 'group_total_open_issues_count'
+ CACHED_COUNT_THRESHOLD = 1000
+ EXPIRATION_TIME = 24.hours
+
+ attr_reader :group, :user
+
+ def initialize(group, user = nil)
+ @group = group
+ @user = user
+ end
+
+ # Reads count value from cache and return it if present.
+ # If empty or expired, #uncached_count will calculate the issues count for the group and
+ # compare it with the threshold. If it is greater, it will be written to the cache and returned.
+ # If below, it will be returned without being cached.
+ # This results in only caching large counts and calculating the rest with every call to maintain
+ # accuracy.
+ def count
+ cached_count = Rails.cache.read(cache_key)
+ return cached_count unless cached_count.blank?
+
+ refreshed_count = uncached_count
+ update_cache_for_key(cache_key) { refreshed_count } if refreshed_count > CACHED_COUNT_THRESHOLD
+ refreshed_count
+ end
+
+ def cache_key(key = nil)
+ ['groups', 'open_issues_count_service', VERSION, group.id, cache_key_name]
+ end
+
+ private
+
+ def cache_options
+ super.merge({ expires_in: EXPIRATION_TIME })
+ end
+
+ def cache_key_name
+ public_only? ? PUBLIC_COUNT_KEY : TOTAL_COUNT_KEY
+ end
+
+ def public_only?
+ !user_is_at_least_reporter?
+ end
+
+ def user_is_at_least_reporter?
+ strong_memoize(:user_is_at_least_reporter) do
+ group.member?(user, Gitlab::Access::REPORTER)
+ end
+ end
+
+ def relation_for_count
+ IssuesFinder.new(user, group_id: group.id, state: 'opened', non_archived: true, include_subgroups: true, public_only: public_only?).execute
+ end
+ end
+end