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
path: root/app
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-05-26 21:08:20 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-05-26 21:08:20 +0300
commit6ee98e127334fd235f251c4a4a76a396f301ee77 (patch)
tree7c66eb437214b600ee7abc7a73d10160283c3030 /app
parentc9d79ef3b5b67792e331a4cc8e6325f3b4a04760 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/clusters/components/application_row.vue63
-rw-r--r--app/assets/javascripts/clusters/components/update_application_confirmation_modal.vue65
-rw-r--r--app/controllers/projects/alert_management_controller.rb2
-rw-r--r--app/graphql/types/release_assets_type.rb20
-rw-r--r--app/graphql/types/release_link_type.rb19
-rw-r--r--app/graphql/types/release_source_type.rb14
-rw-r--r--app/graphql/types/release_type.rb2
-rw-r--r--app/models/draft_note.rb122
-rw-r--r--app/models/merge_request.rb17
-rw-r--r--app/models/note.rb1
-rw-r--r--app/models/project.rb1
-rw-r--r--app/models/review.rb30
-rw-r--r--app/models/snippet_input_action.rb10
-rw-r--r--app/models/snippet_input_action_collection.rb2
-rw-r--r--app/models/user.rb2
-rw-r--r--app/policies/releases/link_policy.rb7
-rw-r--r--app/policies/releases/source_policy.rb13
-rw-r--r--app/presenters/release_presenter.rb2
-rw-r--r--app/services/snippets/base_service.rb6
-rw-r--r--app/services/snippets/create_service.rb8
-rw-r--r--app/services/snippets/update_service.rb33
-rw-r--r--app/views/users/_deletion_guidance.html.haml2
22 files changed, 405 insertions, 36 deletions
diff --git a/app/assets/javascripts/clusters/components/application_row.vue b/app/assets/javascripts/clusters/components/application_row.vue
index dcc0fa501a3..a4ca2a6c857 100644
--- a/app/assets/javascripts/clusters/components/application_row.vue
+++ b/app/assets/javascripts/clusters/components/application_row.vue
@@ -8,8 +8,9 @@ import identicon from '../../vue_shared/components/identicon.vue';
import loadingButton from '../../vue_shared/components/loading_button.vue';
import UninstallApplicationButton from './uninstall_application_button.vue';
import UninstallApplicationConfirmationModal from './uninstall_application_confirmation_modal.vue';
+import UpdateApplicationConfirmationModal from './update_application_confirmation_modal.vue';
-import { APPLICATION_STATUS } from '../constants';
+import { APPLICATION_STATUS, ELASTIC_STACK } from '../constants';
export default {
components: {
@@ -18,6 +19,7 @@ export default {
GlLink,
UninstallApplicationButton,
UninstallApplicationConfirmationModal,
+ UpdateApplicationConfirmationModal,
},
directives: {
GlModalDirective,
@@ -233,6 +235,17 @@ export default {
return label;
},
+ updatingNeedsConfirmation() {
+ if (this.version) {
+ const majorVersion = parseInt(this.version.split('.')[0], 10);
+
+ if (!Number.isNaN(majorVersion)) {
+ return this.id === ELASTIC_STACK && majorVersion < 3;
+ }
+ }
+
+ return false;
+ },
isUpdating() {
// Since upgrading is handled asynchronously on the backend we need this check to prevent any delay on the frontend
return this.status === APPLICATION_STATUS.UPDATING;
@@ -248,6 +261,12 @@ export default {
title: this.title,
});
},
+ updateModalId() {
+ return `update-${this.id}`;
+ },
+ uninstallModalId() {
+ return `uninstall-${this.id}`;
+ },
},
watch: {
updateSuccessful(updateSuccessful) {
@@ -268,7 +287,7 @@ export default {
params: this.installApplicationRequestParams,
});
},
- updateClicked() {
+ updateConfirmed() {
eventHub.$emit('updateApplication', {
id: this.id,
params: this.installApplicationRequestParams,
@@ -356,14 +375,36 @@ export default {
>
{{ updateFailureDescription }}
</div>
- <loading-button
- v-if="updateAvailable || updateFailed || isUpdating"
- class="btn btn-primary js-cluster-application-update-button mt-2"
- :loading="isUpdating"
- :disabled="isUpdating"
- :label="updateButtonLabel"
- @click="updateClicked"
- />
+ <template v-if="updateAvailable || updateFailed || isUpdating">
+ <template v-if="updatingNeedsConfirmation">
+ <loading-button
+ v-gl-modal-directive="updateModalId"
+ class="btn btn-primary js-cluster-application-update-button mt-2"
+ :loading="isUpdating"
+ :disabled="isUpdating"
+ :label="updateButtonLabel"
+ data-qa-selector="update_button_with_confirmation"
+ :data-qa-application="id"
+ />
+
+ <update-application-confirmation-modal
+ :application="id"
+ :application-title="title"
+ @confirm="updateConfirmed()"
+ />
+ </template>
+
+ <loading-button
+ v-else
+ class="btn btn-primary js-cluster-application-update-button mt-2"
+ :loading="isUpdating"
+ :disabled="isUpdating"
+ :label="updateButtonLabel"
+ data-qa-selector="update_button"
+ :data-qa-application="id"
+ @click="updateConfirmed"
+ />
+ </template>
</div>
</div>
<div
@@ -389,7 +430,7 @@ export default {
/>
<uninstall-application-button
v-if="displayUninstallButton"
- v-gl-modal-directive="'uninstall-' + id"
+ v-gl-modal-directive="uninstallModalId"
:status="status"
data-qa-selector="uninstall_button"
:data-qa-application="id"
diff --git a/app/assets/javascripts/clusters/components/update_application_confirmation_modal.vue b/app/assets/javascripts/clusters/components/update_application_confirmation_modal.vue
new file mode 100644
index 00000000000..04aa28e9b74
--- /dev/null
+++ b/app/assets/javascripts/clusters/components/update_application_confirmation_modal.vue
@@ -0,0 +1,65 @@
+<script>
+import { GlModal } from '@gitlab/ui';
+import { sprintf, s__ } from '~/locale';
+import { ELASTIC_STACK } from '../constants';
+
+const CUSTOM_APP_WARNING_TEXT = {
+ [ELASTIC_STACK]: s__(
+ 'ClusterIntegration|Your Elasticsearch cluster will be re-created during this upgrade. Your logs will be re-indexed, and you will lose historical logs from hosts terminated in the last 30 days.',
+ ),
+};
+
+export default {
+ components: {
+ GlModal,
+ },
+ props: {
+ application: {
+ type: String,
+ required: true,
+ },
+ applicationTitle: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ title() {
+ return sprintf(s__('ClusterIntegration|Update %{appTitle}'), {
+ appTitle: this.applicationTitle,
+ });
+ },
+ warningText() {
+ return sprintf(
+ s__('ClusterIntegration|You are about to update %{appTitle} on your cluster.'),
+ {
+ appTitle: this.applicationTitle,
+ },
+ );
+ },
+ customAppWarningText() {
+ return CUSTOM_APP_WARNING_TEXT[this.application];
+ },
+ modalId() {
+ return `update-${this.application}`;
+ },
+ },
+ methods: {
+ confirmUpdate() {
+ this.$emit('confirm');
+ },
+ },
+};
+</script>
+<template>
+ <gl-modal
+ ok-variant="danger"
+ cancel-variant="light"
+ :ok-title="title"
+ :modal-id="modalId"
+ :title="title"
+ @ok="confirmUpdate()"
+ >
+ {{ warningText }} <span v-html="customAppWarningText"></span>
+ </gl-modal>
+</template>
diff --git a/app/controllers/projects/alert_management_controller.rb b/app/controllers/projects/alert_management_controller.rb
index f425582da4d..1b5d42ffcc7 100644
--- a/app/controllers/projects/alert_management_controller.rb
+++ b/app/controllers/projects/alert_management_controller.rb
@@ -3,7 +3,7 @@
class Projects::AlertManagementController < Projects::ApplicationController
before_action :authorize_read_alert_management_alert!
before_action do
- push_frontend_feature_flag(:alert_management_create_alert_issue)
+ push_frontend_feature_flag(:alert_management_create_alert_issue, project)
push_frontend_feature_flag(:alert_assignee, project)
end
diff --git a/app/graphql/types/release_assets_type.rb b/app/graphql/types/release_assets_type.rb
new file mode 100644
index 00000000000..58ad05b5365
--- /dev/null
+++ b/app/graphql/types/release_assets_type.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+module Types
+ class ReleaseAssetsType < BaseObject
+ graphql_name 'ReleaseAssets'
+
+ authorize :read_release
+
+ alias_method :release, :object
+
+ present_using ReleasePresenter
+
+ field :assets_count, GraphQL::INT_TYPE, null: true,
+ description: 'Number of assets of the release'
+ field :links, Types::ReleaseLinkType.connection_type, null: true,
+ description: 'Asset links of the release'
+ field :sources, Types::ReleaseSourceType.connection_type, null: true,
+ description: 'Sources of the release'
+ end
+end
diff --git a/app/graphql/types/release_link_type.rb b/app/graphql/types/release_link_type.rb
new file mode 100644
index 00000000000..c7a1d3f3767
--- /dev/null
+++ b/app/graphql/types/release_link_type.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Types
+ class ReleaseLinkType < BaseObject
+ graphql_name 'ReleaseLink'
+
+ authorize :read_release
+
+ field :id, GraphQL::ID_TYPE, null: false,
+ description: 'ID of the link'
+ field :name, GraphQL::STRING_TYPE, null: true,
+ description: 'Name of the link'
+ field :url, GraphQL::STRING_TYPE, null: true,
+ description: 'URL of the link'
+
+ field :external, GraphQL::BOOLEAN_TYPE, null: true, method: :external?,
+ description: 'Indicates the link points to an external resource'
+ end
+end
diff --git a/app/graphql/types/release_source_type.rb b/app/graphql/types/release_source_type.rb
new file mode 100644
index 00000000000..0ec1ad85a39
--- /dev/null
+++ b/app/graphql/types/release_source_type.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module Types
+ class ReleaseSourceType < BaseObject
+ graphql_name 'ReleaseSource'
+
+ authorize :read_release_sources
+
+ field :format, GraphQL::STRING_TYPE, null: true,
+ description: 'Format of the source'
+ field :url, GraphQL::STRING_TYPE, null: true,
+ description: 'Download URL of the source'
+ end
+end
diff --git a/app/graphql/types/release_type.rb b/app/graphql/types/release_type.rb
index 632351be5d3..30c496f646d 100644
--- a/app/graphql/types/release_type.rb
+++ b/app/graphql/types/release_type.rb
@@ -23,6 +23,8 @@ module Types
description: 'Timestamp of when the release was created'
field :released_at, Types::TimeType, null: true,
description: 'Timestamp of when the release was released'
+ field :assets, Types::ReleaseAssetsType, null: true, method: :itself,
+ description: 'Assets of the release'
field :milestones, Types::MilestoneType.connection_type, null: true,
description: 'Milestones associated to the release'
diff --git a/app/models/draft_note.rb b/app/models/draft_note.rb
new file mode 100644
index 00000000000..febede9beba
--- /dev/null
+++ b/app/models/draft_note.rb
@@ -0,0 +1,122 @@
+# frozen_string_literal: true
+class DraftNote < ApplicationRecord
+ include DiffPositionableNote
+ include Gitlab::Utils::StrongMemoize
+ include Sortable
+ include ShaAttribute
+
+ PUBLISH_ATTRS = %i(noteable_id noteable_type type note).freeze
+ DIFF_ATTRS = %i(position original_position change_position commit_id).freeze
+
+ sha_attribute :commit_id
+
+ # Attribute used to store quick actions changes and users referenced.
+ attr_accessor :commands_changes
+ attr_accessor :users_referenced
+
+ # Text with quick actions filtered out
+ attr_accessor :rendered_note
+
+ attr_accessor :review
+
+ belongs_to :author, class_name: 'User'
+ belongs_to :merge_request
+
+ validates :merge_request_id, presence: true
+ validates :author_id, presence: true, uniqueness: { scope: [:merge_request_id, :discussion_id] }, if: :discussion_id?
+ validates :discussion_id, allow_nil: true, format: { with: /\A\h{40}\z/ }
+
+ scope :authored_by, ->(u) { where(author_id: u.id) }
+
+ delegate :file_path, :file_hash, :file_identifier_hash, to: :diff_file, allow_nil: true
+
+ def self.positions
+ where.not(position: nil)
+ .select(:position)
+ .map(&:position)
+ end
+
+ def project
+ merge_request.target_project
+ end
+
+ # noteable_id and noteable_type methods
+ # are used to generate discussion_id on Discussion.discussion_id
+ def noteable_id
+ merge_request_id
+ end
+
+ def noteable
+ merge_request
+ end
+
+ def noteable_type
+ "MergeRequest"
+ end
+
+ def for_commit?
+ commit_id.present?
+ end
+
+ def importing?
+ false
+ end
+
+ def resolvable?
+ false
+ end
+
+ def emoji_awardable?
+ false
+ end
+
+ def on_diff?
+ position&.complete?
+ end
+
+ def type
+ return 'DiffNote' if on_diff?
+ return 'DiscussionNote' if discussion_id.present?
+
+ 'Note'
+ end
+
+ def references
+ {
+ users: users_referenced,
+ commands: commands_changes
+ }
+ end
+
+ def line_code
+ @line_code ||= diff_file&.line_code_for_position(original_position)
+ end
+
+ def publish_params
+ attrs = PUBLISH_ATTRS.dup
+ attrs.concat(DIFF_ATTRS) if on_diff?
+ params = slice(*attrs)
+ params[:in_reply_to_discussion_id] = discussion_id if discussion_id.present?
+ params[:review_id] = review.id if review.present?
+
+ params
+ end
+
+ def self.preload_author(draft_notes)
+ ActiveRecord::Associations::Preloader.new.preload(draft_notes, { author: :status })
+ end
+
+ def diff_file
+ strong_memoize(:diff_file) do
+ file = original_position&.diff_file(project.repository)
+
+ file&.unfold_diff_lines(original_position)
+
+ file
+ end
+ end
+
+ def commit
+ @commit ||= project.commit(commit_id) if commit_id.present?
+ end
+end
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index b4d0b729454..8c3e042cd10 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -88,6 +88,9 @@ class MergeRequest < ApplicationRecord
has_many :deployments,
through: :deployment_merge_requests
+ has_many :draft_notes
+ has_many :reviews, inverse_of: :merge_request
+
KNOWN_MERGE_PARAMS = [
:auto_merge_strategy,
:should_remove_source_branch,
@@ -541,13 +544,21 @@ class MergeRequest < ApplicationRecord
merge_request_diffs.where.not(id: merge_request_diff.id)
end
- # Overwritten in EE
- def note_positions_for_paths(paths, _user = nil)
+ def note_positions_for_paths(paths, user = nil)
positions = notes.new_diff_notes.joins(:note_diff_file)
.where('note_diff_files.old_path IN (?) OR note_diff_files.new_path IN (?)', paths, paths)
.positions
- Gitlab::Diff::PositionCollection.new(positions, diff_head_sha)
+ collection = Gitlab::Diff::PositionCollection.new(positions, diff_head_sha)
+
+ return collection unless user
+
+ positions = draft_notes
+ .authored_by(user)
+ .positions
+ .select { |pos| paths.include?(pos.file_path) }
+
+ collection.concat(positions)
end
def preloads_discussion_diff_highlighting?
diff --git a/app/models/note.rb b/app/models/note.rb
index d174ba8fe83..ec1a59ca383 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -72,6 +72,7 @@ class Note < ApplicationRecord
belongs_to :author, class_name: "User"
belongs_to :updated_by, class_name: "User"
belongs_to :last_edited_by, class_name: 'User'
+ belongs_to :review, inverse_of: :notes
has_many :todos
diff --git a/app/models/project.rb b/app/models/project.rb
index 99ac8a08ae3..b63096adae7 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -329,6 +329,7 @@ class Project < ApplicationRecord
has_many :repository_storage_moves, class_name: 'ProjectRepositoryStorageMove'
has_many :webide_pipelines, -> { webide_source }, class_name: 'Ci::Pipeline', inverse_of: :project
+ has_many :reviews, inverse_of: :project
accepts_nested_attributes_for :variables, allow_destroy: true
accepts_nested_attributes_for :project_feature, update_only: true
diff --git a/app/models/review.rb b/app/models/review.rb
new file mode 100644
index 00000000000..5a30e2963c8
--- /dev/null
+++ b/app/models/review.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+class Review < ApplicationRecord
+ include Participable
+ include Mentionable
+
+ belongs_to :author, class_name: 'User', foreign_key: :author_id, inverse_of: :reviews
+ belongs_to :merge_request, inverse_of: :reviews
+ belongs_to :project, inverse_of: :reviews
+
+ has_many :notes, -> { order(:id) }, inverse_of: :review
+
+ delegate :name, to: :author, prefix: true
+
+ participant :author
+
+ def all_references(current_user = nil, extractor: nil)
+ ext = super
+
+ notes.each do |note|
+ note.all_references(current_user, extractor: ext)
+ end
+
+ ext
+ end
+
+ def user_mentions
+ merge_request.user_mentions.where.not(note_id: nil)
+ end
+end
diff --git a/app/models/snippet_input_action.rb b/app/models/snippet_input_action.rb
index 50de1b0c04e..64276085682 100644
--- a/app/models/snippet_input_action.rb
+++ b/app/models/snippet_input_action.rb
@@ -28,9 +28,17 @@ class SnippetInputAction
def to_commit_action
{
action: action&.to_sym,
- previous_path: previous_path,
+ previous_path: build_previous_path,
file_path: file_path,
content: content
}
end
+
+ private
+
+ def build_previous_path
+ return previous_path unless update_action?
+
+ previous_path.presence || file_path
+ end
end
diff --git a/app/models/snippet_input_action_collection.rb b/app/models/snippet_input_action_collection.rb
index bf20bce5b0a..56c32c376c4 100644
--- a/app/models/snippet_input_action_collection.rb
+++ b/app/models/snippet_input_action_collection.rb
@@ -5,7 +5,7 @@ class SnippetInputActionCollection
attr_reader :actions
- delegate :empty?, to: :actions
+ delegate :empty?, :any?, :[], to: :actions
def initialize(actions = [])
@actions = actions.map { |action| SnippetInputAction.new(action) }
diff --git a/app/models/user.rb b/app/models/user.rb
index f6d945101b6..6f58dcbda68 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -180,6 +180,8 @@ class User < ApplicationRecord
has_one :user_highest_role
has_one :user_canonical_email
+ has_many :reviews, foreign_key: :author_id, inverse_of: :author
+
#
# Validations
#
diff --git a/app/policies/releases/link_policy.rb b/app/policies/releases/link_policy.rb
new file mode 100644
index 00000000000..4a662fafb2f
--- /dev/null
+++ b/app/policies/releases/link_policy.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+module Releases
+ class LinkPolicy < BasePolicy
+ delegate { @subject.release.project }
+ end
+end
diff --git a/app/policies/releases/source_policy.rb b/app/policies/releases/source_policy.rb
new file mode 100644
index 00000000000..8b86b925589
--- /dev/null
+++ b/app/policies/releases/source_policy.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Releases
+ class SourcePolicy < BasePolicy
+ delegate { @subject.project }
+
+ rule { can?(:public_access) | can?(:reporter_access) }.policy do
+ enable :read_release_sources
+ end
+
+ rule { ~can?(:read_release) }.prevent :read_release_sources
+ end
+end
diff --git a/app/presenters/release_presenter.rb b/app/presenters/release_presenter.rb
index ea46f0a234b..7b0a3d1e7b9 100644
--- a/app/presenters/release_presenter.rb
+++ b/app/presenters/release_presenter.rb
@@ -5,7 +5,7 @@ class ReleasePresenter < Gitlab::View::Presenter::Delegated
presents :release
- delegate :project, :tag, to: :release
+ delegate :project, :tag, :assets_count, to: :release
def commit_path
return unless release.commit && can_download_code?
diff --git a/app/services/snippets/base_service.rb b/app/services/snippets/base_service.rb
index 60ba9ff6683..5d1fe815d83 100644
--- a/app/services/snippets/base_service.rb
+++ b/app/services/snippets/base_service.rb
@@ -72,11 +72,11 @@ module Snippets
message
end
- def files_to_commit
- snippet_files.to_commit_actions.presence || build_actions_from_params
+ def files_to_commit(snippet)
+ snippet_files.to_commit_actions.presence || build_actions_from_params(snippet)
end
- def build_actions_from_params
+ def build_actions_from_params(snippet)
raise NotImplementedError
end
end
diff --git a/app/services/snippets/create_service.rb b/app/services/snippets/create_service.rb
index b3af2d91e5c..434541a9097 100644
--- a/app/services/snippets/create_service.rb
+++ b/app/services/snippets/create_service.rb
@@ -43,9 +43,7 @@ module Snippets
def create_params
return params if snippet_files.empty?
- first_file = snippet_files.actions.first
-
- params.merge(content: first_file.content, file_name: first_file.file_path)
+ params.merge(content: snippet_files[0].content, file_name: snippet_files[0].file_path)
end
def save_and_commit
@@ -88,7 +86,7 @@ module Snippets
message: 'Initial commit'
}
- @snippet.snippet_repository.multi_files_action(current_user, files_to_commit, commit_attrs)
+ @snippet.snippet_repository.multi_files_action(current_user, files_to_commit(@snippet), commit_attrs)
end
def move_temporary_files
@@ -99,7 +97,7 @@ module Snippets
end
end
- def build_actions_from_params
+ def build_actions_from_params(_snippet)
[{ file_path: params[:file_name], content: params[:content] }]
end
end
diff --git a/app/services/snippets/update_service.rb b/app/services/snippets/update_service.rb
index 45b047af3d0..211ebb836cb 100644
--- a/app/services/snippets/update_service.rb
+++ b/app/services/snippets/update_service.rb
@@ -7,11 +7,13 @@ module Snippets
UpdateError = Class.new(StandardError)
def execute(snippet)
+ return invalid_params_error(snippet) unless valid_params?
+
if visibility_changed?(snippet) && !visibility_allowed?(snippet, visibility_level)
return forbidden_visibility_error(snippet)
end
- snippet.assign_attributes(params)
+ update_snippet_attributes(snippet)
spam_check(snippet, current_user)
if save_and_commit(snippet)
@@ -29,6 +31,19 @@ module Snippets
visibility_level && visibility_level.to_i != snippet.visibility_level
end
+ def update_snippet_attributes(snippet)
+ # We can remove the following condition once
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/217801
+ # is implemented.
+ # Once we can perform different operations through this service
+ # we won't need to keep track of the `content` and `file_name` fields
+ if snippet_files.any?
+ params.merge!(content: snippet_files[0].content, file_name: snippet_files[0].file_path)
+ end
+
+ snippet.assign_attributes(params)
+ end
+
def save_and_commit(snippet)
return false unless snippet.save
@@ -81,13 +96,7 @@ module Snippets
message: 'Update snippet'
}
- snippet.snippet_repository.multi_files_action(current_user, snippet_files(snippet), commit_attrs)
- end
-
- def snippet_files(snippet)
- [{ previous_path: snippet.file_name_on_repo,
- file_path: params[:file_name],
- content: params[:content] }]
+ snippet.snippet_repository.multi_files_action(current_user, files_to_commit(snippet), commit_attrs)
end
# Because we are removing repositories we don't want to remove
@@ -99,7 +108,13 @@ module Snippets
end
def committable_attributes?
- (params.stringify_keys.keys & COMMITTABLE_ATTRIBUTES).present?
+ (params.stringify_keys.keys & COMMITTABLE_ATTRIBUTES).present? || snippet_files.any?
+ end
+
+ def build_actions_from_params(snippet)
+ [{ previous_path: snippet.file_name_on_repo,
+ file_path: params[:file_name],
+ content: params[:content] }]
end
end
end
diff --git a/app/views/users/_deletion_guidance.html.haml b/app/views/users/_deletion_guidance.html.haml
index 7169aebea74..0024801dbf6 100644
--- a/app/views/users/_deletion_guidance.html.haml
+++ b/app/views/users/_deletion_guidance.html.haml
@@ -8,4 +8,4 @@
- personal_projects_count = user.personal_projects.count
- unless personal_projects_count.zero?
%li
- = n_('personal project will be removed and cannot be restored', '%d personal projects will be removed and cannot be restored', personal_projects_count)
+ = n_('%d personal project will be removed and cannot be restored.', '%d personal projects will be removed and cannot be restored.', personal_projects_count) % personal_projects_count