summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/ide/components/repo_tab.vue2
-rw-r--r--app/assets/javascripts/u2f/authenticate.js8
-rw-r--r--app/assets/stylesheets/framework/header.scss2
-rw-r--r--app/helpers/projects_helper.rb8
-rw-r--r--app/models/ci/pipeline.rb6
-rw-r--r--app/models/merge_request.rb17
-rw-r--r--app/models/merge_request_diff.rb27
-rw-r--r--app/models/project.rb4
-rw-r--r--app/models/project_auto_devops.rb4
-rw-r--r--app/services/merge_requests/delete_non_latest_diffs_service.rb18
-rw-r--r--app/services/merge_requests/merge_request_diff_cache_service.rb17
-rw-r--r--app/services/merge_requests/post_merge_service.rb5
-rw-r--r--app/services/merge_requests/reload_diffs_service.rb43
-rw-r--r--app/services/web_hook_service.rb2
-rw-r--r--app/views/layouts/header/_current_user_dropdown.html.haml5
-rw-r--r--app/views/layouts/nav/sidebar/_project.html.haml6
-rw-r--r--app/views/profiles/keys/_form.html.haml6
-rw-r--r--app/views/profiles/keys/index.html.haml9
-rw-r--r--app/views/projects/merge_requests/diffs/_diffs.html.haml2
-rw-r--r--app/views/u2f/_authenticate.html.haml3
-rw-r--r--app/workers/all_queues.yml1
-rw-r--r--app/workers/delete_diff_files_worker.rb17
22 files changed, 156 insertions, 56 deletions
diff --git a/app/assets/javascripts/ide/components/repo_tab.vue b/app/assets/javascripts/ide/components/repo_tab.vue
index 1ad52c1bd83..03772ae4a4c 100644
--- a/app/assets/javascripts/ide/components/repo_tab.vue
+++ b/app/assets/javascripts/ide/components/repo_tab.vue
@@ -44,6 +44,8 @@ export default {
methods: {
...mapActions(['closeFile', 'updateDelayViewerUpdated', 'openPendingTab']),
clickFile(tab) {
+ if (tab.active) return;
+
this.updateDelayViewerUpdated(true);
if (tab.pending) {
diff --git a/app/assets/javascripts/u2f/authenticate.js b/app/assets/javascripts/u2f/authenticate.js
index 96af6d2fcca..78fd7ad441f 100644
--- a/app/assets/javascripts/u2f/authenticate.js
+++ b/app/assets/javascripts/u2f/authenticate.js
@@ -11,7 +11,6 @@ export default class U2FAuthenticate {
constructor(container, form, u2fParams, fallbackButton, fallbackUI) {
this.u2fUtils = null;
this.container = container;
- this.renderNotSupported = this.renderNotSupported.bind(this);
this.renderAuthenticated = this.renderAuthenticated.bind(this);
this.renderError = this.renderError.bind(this);
this.renderInProgress = this.renderInProgress.bind(this);
@@ -41,7 +40,6 @@ export default class U2FAuthenticate {
this.signRequests = u2fParams.sign_requests.map(request => _(request).omit('challenge'));
this.templates = {
- notSupported: '#js-authenticate-u2f-not-supported',
setup: '#js-authenticate-u2f-setup',
inProgress: '#js-authenticate-u2f-in-progress',
error: '#js-authenticate-u2f-error',
@@ -55,7 +53,7 @@ export default class U2FAuthenticate {
this.u2fUtils = utils;
this.renderInProgress();
})
- .catch(() => this.renderNotSupported());
+ .catch(() => this.switchToFallbackUI());
}
authenticate() {
@@ -96,10 +94,6 @@ export default class U2FAuthenticate {
this.fallbackButton.classList.add('hidden');
}
- renderNotSupported() {
- return this.renderTemplate('notSupported');
- }
-
switchToFallbackUI() {
this.fallbackButton.classList.add('hidden');
this.container[0].classList.add('hidden');
diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss
index 2fa71b23314..91a9b956d9d 100644
--- a/app/assets/stylesheets/framework/header.scss
+++ b/app/assets/stylesheets/framework/header.scss
@@ -527,7 +527,7 @@
.header-user {
.dropdown-menu {
width: auto;
- min-width: 160px;
+ min-width: unset;
margin-top: 4px;
color: $gl-text-color;
left: auto;
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index be3958c40a4..f479ed0f54c 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -506,6 +506,14 @@ module ProjectsHelper
end
end
+ def sidebar_projects_paths
+ %w[
+ projects#show
+ projects#activity
+ cycle_analytics#show
+ ]
+ end
+
def sidebar_settings_paths
%w[
projects#edit
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index f430f18ca9a..e5caa3ffa41 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -561,9 +561,9 @@ module Ci
.append(key: 'CI_PIPELINE_IID', value: iid.to_s)
.append(key: 'CI_CONFIG_PATH', value: ci_yaml_file_path)
.append(key: 'CI_PIPELINE_SOURCE', value: source.to_s)
- .append(key: 'CI_COMMIT_MESSAGE', value: git_commit_message)
- .append(key: 'CI_COMMIT_TITLE', value: git_commit_full_title)
- .append(key: 'CI_COMMIT_DESCRIPTION', value: git_commit_description)
+ .append(key: 'CI_COMMIT_MESSAGE', value: git_commit_message.to_s)
+ .append(key: 'CI_COMMIT_TITLE', value: git_commit_full_title.to_s)
+ .append(key: 'CI_COMMIT_DESCRIPTION', value: git_commit_description.to_s)
end
def queued_duration
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 3df1130a6e2..f112c06e26f 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -378,6 +378,10 @@ class MergeRequest < ActiveRecord::Base
end
end
+ def non_latest_diffs
+ merge_request_diffs.where.not(id: merge_request_diff.id)
+ end
+
def diff_size
# Calling `merge_request_diff.diffs.real_size` will also perform
# highlighting, which we don't need here.
@@ -619,18 +623,7 @@ class MergeRequest < ActiveRecord::Base
def reload_diff(current_user = nil)
return unless open?
- old_diff_refs = self.diff_refs
- new_diff = create_merge_request_diff
-
- MergeRequests::MergeRequestDiffCacheService.new.execute(self, new_diff)
-
- new_diff_refs = self.diff_refs
-
- update_diff_discussion_positions(
- old_diff_refs: old_diff_refs,
- new_diff_refs: new_diff_refs,
- current_user: current_user
- )
+ MergeRequests::ReloadDiffsService.new(self, current_user).execute
end
def check_if_can_be_merged
diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb
index 06aa67c600f..3d72c447b4b 100644
--- a/app/models/merge_request_diff.rb
+++ b/app/models/merge_request_diff.rb
@@ -3,6 +3,7 @@ class MergeRequestDiff < ActiveRecord::Base
include Importable
include ManualInverseAssociation
include IgnorableColumn
+ include EachBatch
# Don't display more than 100 commits at once
COMMITS_SAFE_SIZE = 100
@@ -17,8 +18,14 @@ class MergeRequestDiff < ActiveRecord::Base
has_many :merge_request_diff_commits, -> { order(:merge_request_diff_id, :relative_order) }
state_machine :state, initial: :empty do
+ event :clean do
+ transition any => :without_files
+ end
+
state :collected
state :overflow
+ # Diff files have been deleted by the system
+ state :without_files
# Deprecated states: these are no longer used but these values may still occur
# in the database.
state :timeout
@@ -27,6 +34,7 @@ class MergeRequestDiff < ActiveRecord::Base
state :overflow_diff_lines_limit
end
+ scope :with_files, -> { without_states(:without_files, :empty) }
scope :viewable, -> { without_state(:empty) }
scope :by_commit_sha, ->(sha) do
joins(:merge_request_diff_commits).where(merge_request_diff_commits: { sha: sha }).reorder(nil)
@@ -42,6 +50,10 @@ class MergeRequestDiff < ActiveRecord::Base
find_by(start_commit_sha: diff_refs.start_sha, head_commit_sha: diff_refs.head_sha, base_commit_sha: diff_refs.base_sha)
end
+ def viewable?
+ collected? || without_files? || overflow?
+ end
+
# Collect information about commits and diff from repository
# and save it to the database as serialized data
def save_git_content
@@ -170,6 +182,21 @@ class MergeRequestDiff < ActiveRecord::Base
end
def diffs(diff_options = nil)
+ if without_files? && comparison = diff_refs.compare_in(project)
+ # It should fetch the repository when diffs are cleaned by the system.
+ # We don't keep these for storage overload purposes.
+ # See https://gitlab.com/gitlab-org/gitlab-ce/issues/37639
+ comparison.diffs(diff_options)
+ else
+ diffs_collection(diff_options)
+ end
+ end
+
+ # Should always return the DB persisted diffs collection
+ # (e.g. Gitlab::Diff::FileCollection::MergeRequestDiff.
+ # It's useful when trying to invalidate old caches through
+ # FileCollection::MergeRequestDiff#clear_cache!
+ def diffs_collection(diff_options = nil)
Gitlab::Diff::FileCollection::MergeRequestDiff.new(self, diff_options: diff_options)
end
diff --git a/app/models/project.rb b/app/models/project.rb
index 0d777515536..d91d7dcfe9a 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -2019,6 +2019,10 @@ class Project < ActiveRecord::Base
end
request_cache(:any_lfs_file_locks?) { self.id }
+ def auto_cancel_pending_pipelines?
+ auto_cancel_pending_pipelines == 'enabled'
+ end
+
private
def storage
diff --git a/app/models/project_auto_devops.rb b/app/models/project_auto_devops.rb
index d7d6aaceb27..faa831b1949 100644
--- a/app/models/project_auto_devops.rb
+++ b/app/models/project_auto_devops.rb
@@ -29,8 +29,8 @@ class ProjectAutoDevops < ActiveRecord::Base
end
if manual?
- variables.append(key: 'STAGING_ENABLED', value: 1)
- variables.append(key: 'INCREMENTAL_ROLLOUT_ENABLED', value: 1)
+ variables.append(key: 'STAGING_ENABLED', value: '1')
+ variables.append(key: 'INCREMENTAL_ROLLOUT_ENABLED', value: '1')
end
end
end
diff --git a/app/services/merge_requests/delete_non_latest_diffs_service.rb b/app/services/merge_requests/delete_non_latest_diffs_service.rb
new file mode 100644
index 00000000000..40079b21189
--- /dev/null
+++ b/app/services/merge_requests/delete_non_latest_diffs_service.rb
@@ -0,0 +1,18 @@
+module MergeRequests
+ class DeleteNonLatestDiffsService
+ BATCH_SIZE = 10
+
+ def initialize(merge_request)
+ @merge_request = merge_request
+ end
+
+ def execute
+ diffs = @merge_request.non_latest_diffs.with_files
+
+ diffs.each_batch(of: BATCH_SIZE) do |relation, index|
+ ids = relation.pluck(:id).map { |id| [id] }
+ DeleteDiffFilesWorker.bulk_perform_in(index * 5.minutes, ids)
+ end
+ end
+ end
+end
diff --git a/app/services/merge_requests/merge_request_diff_cache_service.rb b/app/services/merge_requests/merge_request_diff_cache_service.rb
deleted file mode 100644
index 10aa9ae609c..00000000000
--- a/app/services/merge_requests/merge_request_diff_cache_service.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-module MergeRequests
- class MergeRequestDiffCacheService
- def execute(merge_request, new_diff)
- # Executing the iteration we cache all the highlighted diff information
- merge_request.diffs.diff_files.to_a
-
- # Remove cache for all diffs on this MR. Do not use the association on the
- # model, as that will interfere with other actions happening when
- # reloading the diff.
- MergeRequestDiff.where(merge_request: merge_request).each do |merge_request_diff|
- next if merge_request_diff == new_diff
-
- merge_request_diff.diffs.clear_cache!
- end
- end
- end
-end
diff --git a/app/services/merge_requests/post_merge_service.rb b/app/services/merge_requests/post_merge_service.rb
index c78e78afcd1..5b160ffba67 100644
--- a/app/services/merge_requests/post_merge_service.rb
+++ b/app/services/merge_requests/post_merge_service.rb
@@ -15,6 +15,7 @@ module MergeRequests
execute_hooks(merge_request, 'merge')
invalidate_cache_counts(merge_request, users: merge_request.assignees)
merge_request.update_project_counter_caches
+ delete_non_latest_diffs(merge_request)
end
private
@@ -31,6 +32,10 @@ module MergeRequests
end
end
+ def delete_non_latest_diffs(merge_request)
+ DeleteNonLatestDiffsService.new(merge_request).execute
+ end
+
def create_merge_event(merge_request, current_user)
EventCreateService.new.merge_mr(merge_request, current_user)
end
diff --git a/app/services/merge_requests/reload_diffs_service.rb b/app/services/merge_requests/reload_diffs_service.rb
new file mode 100644
index 00000000000..2ec7b403903
--- /dev/null
+++ b/app/services/merge_requests/reload_diffs_service.rb
@@ -0,0 +1,43 @@
+module MergeRequests
+ class ReloadDiffsService
+ def initialize(merge_request, current_user)
+ @merge_request = merge_request
+ @current_user = current_user
+ end
+
+ def execute
+ old_diff_refs = merge_request.diff_refs
+ new_diff = merge_request.create_merge_request_diff
+
+ clear_cache(new_diff)
+ update_diff_discussion_positions(old_diff_refs)
+ end
+
+ private
+
+ attr_reader :merge_request, :current_user
+
+ def update_diff_discussion_positions(old_diff_refs)
+ new_diff_refs = merge_request.diff_refs
+
+ merge_request.update_diff_discussion_positions(old_diff_refs: old_diff_refs,
+ new_diff_refs: new_diff_refs,
+ current_user: current_user)
+ end
+
+ def clear_cache(new_diff)
+ # Executing the iteration we cache highlighted diffs for each diff file of
+ # MergeRequestDiff.
+ new_diff.diffs_collection.diff_files.to_a
+
+ # Remove cache for all diffs on this MR. Do not use the association on the
+ # model, as that will interfere with other actions happening when
+ # reloading the diff.
+ MergeRequestDiff.where(merge_request: merge_request).each do |merge_request_diff|
+ next if merge_request_diff == new_diff
+
+ merge_request_diff.diffs_collection.clear_cache!
+ end
+ end
+ end
+end
diff --git a/app/services/web_hook_service.rb b/app/services/web_hook_service.rb
index 7ec52b6ce2b..8a86e47f0ea 100644
--- a/app/services/web_hook_service.rb
+++ b/app/services/web_hook_service.rb
@@ -82,7 +82,7 @@ class WebHookService
post_url = hook.url.gsub("#{parsed_url.userinfo}@", '')
basic_auth = {
username: CGI.unescape(parsed_url.user),
- password: CGI.unescape(parsed_url.password)
+ password: CGI.unescape(parsed_url.password.presence || '')
}
make_request(post_url, basic_auth)
end
diff --git a/app/views/layouts/header/_current_user_dropdown.html.haml b/app/views/layouts/header/_current_user_dropdown.html.haml
index 24b6c490a5a..cdfd45fceb1 100644
--- a/app/views/layouts/header/_current_user_dropdown.html.haml
+++ b/app/views/layouts/header/_current_user_dropdown.html.haml
@@ -17,6 +17,11 @@
= link_to _("Help"), help_path
- if current_user_menu?(:help) || current_user_menu?(:settings) || current_user_menu?(:profile)
%li.divider
+ %li
+ = link_to "https://about.gitlab.com/contributing", target: '_blank', class: 'text-nowrap' do
+ = _("Contribute to GitLab")
+ = icon('external-link')
+ %li.divider
- if current_user_menu?(:sign_out)
%li
= link_to _("Sign out"), destroy_user_session_path, class: "sign-out-link"
diff --git a/app/views/layouts/nav/sidebar/_project.html.haml b/app/views/layouts/nav/sidebar/_project.html.haml
index 9f8b3b86474..33416bf76d7 100644
--- a/app/views/layouts/nav/sidebar/_project.html.haml
+++ b/app/views/layouts/nav/sidebar/_project.html.haml
@@ -8,7 +8,7 @@
.sidebar-context-title
= @project.name
%ul.sidebar-top-level-items
- = nav_link(path: ['projects#show', 'projects#activity', 'cycle_analytics#show'], html_options: { class: 'home' }) do
+ = nav_link(path: sidebar_projects_paths, html_options: { class: 'home' }) do
= link_to project_path(@project), class: 'shortcuts-project' do
.nav-icon-container
= sprite_icon('project')
@@ -29,13 +29,13 @@
= link_to activity_project_path(@project), title: _('Activity'), class: 'shortcuts-project-activity' do
%span= _('Activity')
+ = render_if_exists 'projects/sidebar/security_dashboard'
+
- if can?(current_user, :read_cycle_analytics, @project)
= nav_link(path: 'cycle_analytics#show') do
= link_to project_cycle_analytics_path(@project), title: _('Cycle Analytics'), class: 'shortcuts-project-cycle-analytics' do
%span= _('Cycle Analytics')
- = render_if_exists 'projects/sidebar/security_dashboard'
-
- if project_nav_tab? :files
= nav_link(controller: sidebar_repository_paths) do
= link_to project_tree_path(@project), class: 'shortcuts-tree' do
diff --git a/app/views/profiles/keys/_form.html.haml b/app/views/profiles/keys/_form.html.haml
index 6ea358d9f63..c14700794ce 100644
--- a/app/views/profiles/keys/_form.html.haml
+++ b/app/views/profiles/keys/_form.html.haml
@@ -4,10 +4,12 @@
.form-group
= f.label :key, class: 'label-light'
- = f.text_area :key, class: "form-control", rows: 8, required: true, placeholder: "Don't paste the private part of the SSH key. Paste the public part, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'."
+ %p= _("Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key.")
+ = f.text_area :key, class: "form-control", rows: 8, required: true, placeholder: 'Typically starts with "ssh-rsa …"'
.form-group
= f.label :title, class: 'label-light'
- = f.text_field :title, class: "form-control", required: true
+ = f.text_field :title, class: "form-control", required: true, placeholder: 'e.g. My MacBook key'
+ %p.form-text.text-muted= _('Name your individual key via a title')
.prepend-top-default
= f.submit 'Add key', class: "btn btn-create"
diff --git a/app/views/profiles/keys/index.html.haml b/app/views/profiles/keys/index.html.haml
index 1e206def7ee..55ca8d0ebd4 100644
--- a/app/views/profiles/keys/index.html.haml
+++ b/app/views/profiles/keys/index.html.haml
@@ -11,10 +11,11 @@
%h5.prepend-top-0
Add an SSH key
%p.profile-settings-content
- Before you can add an SSH key you need to
- = link_to "generate one", help_page_path("ssh/README", anchor: 'generating-a-new-ssh-key-pair')
- or use an
- = link_to "existing key.", help_page_path("ssh/README", anchor: 'locating-an-existing-ssh-key-pair')
+ - generate_link_url = help_page_path("ssh/README", anchor: 'generating-a-new-ssh-key-pair')
+ - existing_link_url = help_page_path("ssh/README", anchor: 'locating-an-existing-ssh-key-pair')
+ - generate_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: generate_link_url }
+ - existing_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: existing_link_url }
+ = _('To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}.').html_safe % { generate_link_start: generate_link_start, existing_link_start: existing_link_start, link_end: '</a>'.html_safe }
= render 'form'
%hr
%h5
diff --git a/app/views/projects/merge_requests/diffs/_diffs.html.haml b/app/views/projects/merge_requests/diffs/_diffs.html.haml
index 19659fe5140..bf3df0abf86 100644
--- a/app/views/projects/merge_requests/diffs/_diffs.html.haml
+++ b/app/views/projects/merge_requests/diffs/_diffs.html.haml
@@ -16,6 +16,6 @@
%span.ref-name= @merge_request.target_branch
.text-center= link_to 'Create commit', project_new_blob_path(@project, @merge_request.source_branch), class: 'btn btn-save'
- else
- - diff_viewable = @merge_request_diff ? @merge_request_diff.collected? || @merge_request_diff.overflow? : true
+ - diff_viewable = @merge_request_diff ? @merge_request_diff.viewable? : true
- if diff_viewable
= render "projects/diffs/diffs", diffs: @diffs, environment: @environment, merge_request: true
diff --git a/app/views/u2f/_authenticate.html.haml b/app/views/u2f/_authenticate.html.haml
index 7eb221620ad..1c788b9a737 100644
--- a/app/views/u2f/_authenticate.html.haml
+++ b/app/views/u2f/_authenticate.html.haml
@@ -2,9 +2,6 @@
%a.btn.btn-block.btn-info#js-login-2fa-device{ href: '#' } Sign in via 2FA code
-# haml-lint:disable InlineJavaScript
-%script#js-authenticate-u2f-not-supported{ type: "text/template" }
- %p Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer).
-
%script#js-authenticate-u2f-in-progress{ type: "text/template" }
%p Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now.
diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml
index 30b6796a7d6..026f756582d 100644
--- a/app/workers/all_queues.yml
+++ b/app/workers/all_queues.yml
@@ -118,3 +118,4 @@
- web_hook
- repository_update_remote_mirror
- create_note_diff_file
+- delete_diff_files
diff --git a/app/workers/delete_diff_files_worker.rb b/app/workers/delete_diff_files_worker.rb
new file mode 100644
index 00000000000..bb8fbb9c373
--- /dev/null
+++ b/app/workers/delete_diff_files_worker.rb
@@ -0,0 +1,17 @@
+class DeleteDiffFilesWorker
+ include ApplicationWorker
+
+ def perform(merge_request_diff_id)
+ merge_request_diff = MergeRequestDiff.find(merge_request_diff_id)
+
+ return if merge_request_diff.without_files?
+
+ MergeRequestDiff.transaction do
+ merge_request_diff.clean!
+
+ MergeRequestDiffFile
+ .where(merge_request_diff_id: merge_request_diff.id)
+ .delete_all
+ end
+ end
+end