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>2020-05-13 21:08:47 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-05-13 21:08:47 +0300
commite689e858ede41a34b1e9132eba6a602632e6885e (patch)
tree57f173714a177a70aa6631d77f10d5628d42cd90 /app/services/design_management/save_designs_service.rb
parent868e4e69bba7d3ddc2bf4899ee45d6c377a8e536 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/services/design_management/save_designs_service.rb')
-rw-r--r--app/services/design_management/save_designs_service.rb114
1 files changed, 114 insertions, 0 deletions
diff --git a/app/services/design_management/save_designs_service.rb b/app/services/design_management/save_designs_service.rb
new file mode 100644
index 00000000000..a09c19bc885
--- /dev/null
+++ b/app/services/design_management/save_designs_service.rb
@@ -0,0 +1,114 @@
+# frozen_string_literal: true
+
+module DesignManagement
+ class SaveDesignsService < DesignService
+ include RunsDesignActions
+ include OnSuccessCallbacks
+
+ MAX_FILES = 10
+
+ def initialize(project, user, params = {})
+ super
+
+ @files = params.fetch(:files)
+ end
+
+ def execute
+ return error("Not allowed!") unless can_create_designs?
+ return error("Only #{MAX_FILES} files are allowed simultaneously") if files.size > MAX_FILES
+
+ uploaded_designs, version = upload_designs!
+ skipped_designs = designs - uploaded_designs
+
+ success({ designs: uploaded_designs, version: version, skipped_designs: skipped_designs })
+ rescue ::ActiveRecord::RecordInvalid => e
+ error(e.message)
+ end
+
+ private
+
+ attr_reader :files
+
+ def upload_designs!
+ ::DesignManagement::Version.with_lock(project.id, repository) do
+ actions = build_actions
+
+ [actions.map(&:design), actions.presence && run_actions(actions)]
+ end
+ end
+
+ # Returns `Design` instances that correspond with `files`.
+ # New `Design`s will be created where a file name does not match
+ # an existing `Design`
+ def designs
+ @designs ||= files.map do |file|
+ collection.find_or_create_design!(filename: file.original_filename)
+ end
+ end
+
+ def build_actions
+ files.zip(designs).flat_map do |(file, design)|
+ Array.wrap(build_design_action(file, design))
+ end
+ end
+
+ def build_design_action(file, design)
+ content = file_content(file, design.full_path)
+ return if design_unchanged?(design, content)
+
+ action = new_file?(design) ? :create : :update
+ on_success { ::Gitlab::UsageDataCounters::DesignsCounter.count(action) }
+
+ DesignManagement::DesignAction.new(design, action, content)
+ end
+
+ # Returns true if the design file is the same as its latest version
+ def design_unchanged?(design, content)
+ content == existing_blobs[design]&.data
+ end
+
+ def commit_message
+ <<~MSG
+ Updated #{files.size} #{'designs'.pluralize(files.size)}
+
+ #{formatted_file_list}
+ MSG
+ end
+
+ def formatted_file_list
+ filenames.map { |name| "- #{name}" }.join("\n")
+ end
+
+ def filenames
+ @filenames ||= files.map(&:original_filename)
+ end
+
+ def can_create_designs?
+ Ability.allowed?(current_user, :create_design, issue)
+ end
+
+ def new_file?(design)
+ !existing_blobs[design]
+ end
+
+ def file_content(file, full_path)
+ transformer = ::Lfs::FileTransformer.new(project, repository, target_branch)
+ transformer.new_file(full_path, file.to_io).content
+ end
+
+ # Returns the latest blobs for the designs as a Hash of `{ Design => Blob }`
+ def existing_blobs
+ @existing_blobs ||= begin
+ items = designs.map { |d| ['HEAD', d.full_path] }
+
+ repository.blobs_at(items).each_with_object({}) do |blob, h|
+ design = designs.find { |d| d.full_path == blob.path }
+
+ h[design] = blob
+ end
+ end
+ end
+ end
+end
+
+DesignManagement::SaveDesignsService.prepend_if_ee('EE::DesignManagement::SaveDesignsService')