diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-02-28 18:09:07 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-02-28 18:09:07 +0000 |
commit | 1c8fa70f9d0818e2a82089c8643a6e455bca47fd (patch) | |
tree | f339f97de0425270bdd909e2f4d378927b6e0a18 /app/models/snippet_repository.rb | |
parent | 736d36d8597d0d1ec1b47644e6d091c3f4a78f45 (diff) | |
download | gitlab-ce-1c8fa70f9d0818e2a82089c8643a6e455bca47fd.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/models/snippet_repository.rb')
-rw-r--r-- | app/models/snippet_repository.rb | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/app/models/snippet_repository.rb b/app/models/snippet_repository.rb index ba2a061a5f4..10580c51098 100644 --- a/app/models/snippet_repository.rb +++ b/app/models/snippet_repository.rb @@ -3,11 +3,76 @@ class SnippetRepository < ApplicationRecord include Shardable + DEFAULT_EMPTY_FILE_NAME = 'snippetfile' + EMPTY_FILE_PATTERN = /^#{DEFAULT_EMPTY_FILE_NAME}(\d)\.txt$/.freeze + + CommitError = Class.new(StandardError) + belongs_to :snippet, inverse_of: :snippet_repository + delegate :repository, to: :snippet + class << self def find_snippet(disk_path) find_by(disk_path: disk_path)&.snippet end end + + def multi_files_action(user, files = [], **options) + return if files.nil? || files.empty? + + lease_key = "multi_files_action:#{snippet_id}" + + lease = Gitlab::ExclusiveLease.new(lease_key, timeout: 120) + raise CommitError, 'Snippet is already being updated' unless uuid = lease.try_obtain + + options[:actions] = transform_file_entries(files) + + capture_git_error { repository.multi_action(user, **options) } + ensure + Gitlab::ExclusiveLease.cancel(lease_key, uuid) + end + + private + + def capture_git_error(&block) + yield block + rescue Gitlab::Git::Index::IndexError, + Gitlab::Git::CommitError, + Gitlab::Git::PreReceiveError, + Gitlab::Git::CommandError => e + raise CommitError, e.message + end + + def transform_file_entries(files) + last_index = get_last_empty_file_index + + files.each do |file_entry| + file_entry[:action] = infer_action(file_entry) unless file_entry[:action] + + if file_entry[:file_path].blank? + file_entry[:file_path] = build_empty_file_name(last_index) + last_index += 1 + end + end + end + + def infer_action(file_entry) + return :create if file_entry[:previous_path].blank? + + file_entry[:previous_path] != file_entry[:file_path] ? :move : :update + end + + def get_last_empty_file_index + last_file = repository.ls_files(nil) + .map! { |file| file.match(EMPTY_FILE_PATTERN) } + .compact + .max_by { |element| element[1] } + + last_file ? (last_file[1].to_i + 1) : 1 + end + + def build_empty_file_name(index) + "#{DEFAULT_EMPTY_FILE_NAME}#{index}.txt" + end end |