summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/diff_notes/components/jump_to_discussion.js7
-rw-r--r--app/assets/javascripts/notebook/cells/markdown.vue24
-rw-r--r--app/controllers/concerns/renders_blob.rb4
-rw-r--r--app/controllers/projects/artifacts_controller.rb2
-rw-r--r--app/controllers/projects/blob_controller.rb2
-rw-r--r--app/controllers/projects/snippets_controller.rb2
-rw-r--r--app/controllers/snippets_controller.rb2
-rw-r--r--app/helpers/blob_helper.rb14
-rw-r--r--app/helpers/diff_helper.rb12
-rw-r--r--app/helpers/notes_helper.rb2
-rw-r--r--app/models/application_setting.rb14
-rw-r--r--app/models/audit_event.rb2
-rw-r--r--app/models/blob.rb12
-rw-r--r--app/models/blob_viewer/auxiliary.rb4
-rw-r--r--app/models/blob_viewer/base.rb26
-rw-r--r--app/models/blob_viewer/client_side.rb4
-rw-r--r--app/models/blob_viewer/server_side.rb4
-rw-r--r--app/models/blob_viewer/text.rb4
-rw-r--r--app/models/ci/build.rb36
-rw-r--r--app/models/ci/trigger_request.rb2
-rw-r--r--app/models/concerns/noteable.rb7
-rw-r--r--app/models/diff_discussion.rb1
-rw-r--r--app/models/diff_note.rb24
-rw-r--r--app/models/discussion.rb9
-rw-r--r--app/models/event.rb2
-rw-r--r--app/models/hooks/web_hook_log.rb6
-rw-r--r--app/models/legacy_diff_note.rb2
-rw-r--r--app/models/merge_request.rb28
-rw-r--r--app/models/merge_request_diff.rb4
-rw-r--r--app/models/note.rb2
-rw-r--r--app/models/personal_access_token.rb2
-rw-r--r--app/models/project_import_data.rb2
-rw-r--r--app/models/project_team.rb9
-rw-r--r--app/models/sent_notification.rb2
-rw-r--r--app/models/service.rb2
-rw-r--r--app/models/user.rb3
-rw-r--r--app/services/discussions/update_diff_position_service.rb41
-rw-r--r--app/services/notes/diff_position_update_service.rb33
-rw-r--r--app/uploaders/artifact_uploader.rb28
-rw-r--r--app/uploaders/gitlab_uploader.rb6
-rw-r--r--app/views/admin/dashboard/index.html.haml6
-rw-r--r--app/views/discussions/_jump_to_next.html.haml4
-rw-r--r--app/views/projects/diffs/_content.html.haml2
-rw-r--r--app/views/projects/diffs/_diffs.html.haml4
-rw-r--r--app/views/projects/diffs/_line.html.haml2
-rw-r--r--app/views/projects/registry/repositories/index.html.haml72
46 files changed, 266 insertions, 216 deletions
diff --git a/app/assets/javascripts/diff_notes/components/jump_to_discussion.js b/app/assets/javascripts/diff_notes/components/jump_to_discussion.js
index 8a0fd3bb4a7..37ddca29e71 100644
--- a/app/assets/javascripts/diff_notes/components/jump_to_discussion.js
+++ b/app/assets/javascripts/diff_notes/components/jump_to_discussion.js
@@ -16,6 +16,13 @@ const JumpToDiscussion = Vue.extend({
};
},
computed: {
+ buttonText: function () {
+ if (this.discussionId) {
+ return 'Jump to next unresolved discussion';
+ } else {
+ return 'Jump to first unresolved discussion';
+ }
+ },
allResolved: function () {
return this.unresolvedDiscussionCount === 0;
},
diff --git a/app/assets/javascripts/notebook/cells/markdown.vue b/app/assets/javascripts/notebook/cells/markdown.vue
index 3e8240d10ec..814d2ea92b4 100644
--- a/app/assets/javascripts/notebook/cells/markdown.vue
+++ b/app/assets/javascripts/notebook/cells/markdown.vue
@@ -30,7 +30,7 @@
|
\\s\\$(?!\\$)
)
- (.+?)
+ ((.|\\n)+?)
(
\\s\\\\end{[a-zA-Z]+}$
|
@@ -45,15 +45,25 @@
let inline = false;
if (typeof katex !== 'undefined') {
- const katexString = text.replace(/\\/g, '\\');
- const matches = new RegExp(katexRegexString, 'gi').exec(katexString);
+ const katexString = text.replace(/&/g, '&')
+ .replace(/&=&/g, '\\space=\\space')
+ .replace(/<(\/?)em>/g, '_');
+ const regex = new RegExp(katexRegexString, 'gi');
+ const matchLocation = katexString.search(regex);
+ const numberOfMatches = katexString.match(regex);
- if (matches && matches.length > 0) {
- if (matches[1].trim() === '$' && matches[3].trim() === '$') {
+ if (numberOfMatches && numberOfMatches.length !== 0) {
+ if (matchLocation > 0) {
+ let matches = regex.exec(katexString);
inline = true;
- text = `${katexString.replace(matches[0], '')} ${katex.renderToString(matches[2])}`;
+ while (matches !== null) {
+ const renderedKatex = katex.renderToString(matches[0].replace(/\$/g, ''));
+ text = `${text.replace(matches[0], ` ${renderedKatex}`)}`;
+ matches = regex.exec(katexString);
+ }
} else {
+ const matches = regex.exec(katexString);
text = katex.renderToString(matches[2]);
}
}
@@ -79,7 +89,7 @@
},
computed: {
markdown() {
- return marked(this.cell.source.join(''));
+ return marked(this.cell.source.join('').replace(/\\/g, '\\\\'));
},
},
};
diff --git a/app/controllers/concerns/renders_blob.rb b/app/controllers/concerns/renders_blob.rb
index 1d37e4cb3bd..54dcd7c61ce 100644
--- a/app/controllers/concerns/renders_blob.rb
+++ b/app/controllers/concerns/renders_blob.rb
@@ -18,7 +18,7 @@ module RendersBlob
}
end
- def override_max_blob_size(blob)
- blob.override_max_size! if params[:override_max_size] == 'true'
+ def conditionally_expand_blob(blob)
+ blob.expand! if params[:expanded] == 'true'
end
end
diff --git a/app/controllers/projects/artifacts_controller.rb b/app/controllers/projects/artifacts_controller.rb
index b46a33604ff..ea036b1f705 100644
--- a/app/controllers/projects/artifacts_controller.rb
+++ b/app/controllers/projects/artifacts_controller.rb
@@ -27,7 +27,7 @@ class Projects::ArtifactsController < Projects::ApplicationController
def file
blob = @entry.blob
- override_max_blob_size(blob)
+ conditionally_expand_blob(blob)
respond_to do |format|
format.html do
diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb
index 87721fbe2f5..7025c7a1de6 100644
--- a/app/controllers/projects/blob_controller.rb
+++ b/app/controllers/projects/blob_controller.rb
@@ -35,7 +35,7 @@ class Projects::BlobController < Projects::ApplicationController
end
def show
- override_max_blob_size(@blob)
+ conditionally_expand_blob(@blob)
respond_to do |format|
format.html do
diff --git a/app/controllers/projects/snippets_controller.rb b/app/controllers/projects/snippets_controller.rb
index 3b2b0d9e502..3a97c1e98af 100644
--- a/app/controllers/projects/snippets_controller.rb
+++ b/app/controllers/projects/snippets_controller.rb
@@ -56,7 +56,7 @@ class Projects::SnippetsController < Projects::ApplicationController
def show
blob = @snippet.blob
- override_max_blob_size(blob)
+ conditionally_expand_blob(blob)
respond_to do |format|
format.html do
diff --git a/app/controllers/snippets_controller.rb b/app/controllers/snippets_controller.rb
index 7445f61195d..5b2d143ee79 100644
--- a/app/controllers/snippets_controller.rb
+++ b/app/controllers/snippets_controller.rb
@@ -58,7 +58,7 @@ class SnippetsController < ApplicationController
def show
blob = @snippet.blob
- override_max_blob_size(blob)
+ conditionally_expand_blob(blob)
@note = Note.new(noteable: @snippet)
@noteable = @snippet
diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb
index 11c972c6563..3efa7c36057 100644
--- a/app/helpers/blob_helper.rb
+++ b/app/helpers/blob_helper.rb
@@ -240,14 +240,10 @@ module BlobHelper
def blob_render_error_reason(viewer)
case viewer.render_error
+ when :collapsed
+ "it is larger than #{number_to_human_size(viewer.collapse_limit)}"
when :too_large
- max_size =
- if viewer.can_override_max_size?
- viewer.overridable_max_size
- else
- viewer.max_size
- end
- "it is larger than #{number_to_human_size(max_size)}"
+ "it is larger than #{number_to_human_size(viewer.size_limit)}"
when :server_side_but_stored_externally
case viewer.blob.external_storage
when :lfs
@@ -264,8 +260,8 @@ module BlobHelper
error = viewer.render_error
options = []
- if error == :too_large && viewer.can_override_max_size?
- options << link_to('load it anyway', url_for(params.merge(viewer: viewer.type, override_max_size: true, format: nil)))
+ if error == :collapsed
+ options << link_to('load it anyway', url_for(params.merge(viewer: viewer.type, expanded: true, format: nil)))
end
# If the error is `:server_side_but_stored_externally`, the simple viewer will show the same error,
diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb
index 4c4fbdd4d39..2ae3a616933 100644
--- a/app/helpers/diff_helper.rb
+++ b/app/helpers/diff_helper.rb
@@ -8,8 +8,8 @@ module DiffHelper
[marked_old_line, marked_new_line]
end
- def expand_all_diffs?
- params[:expand_all_diffs].present?
+ def diffs_expanded?
+ params[:expanded].present?
end
def diff_view
@@ -22,10 +22,10 @@ module DiffHelper
end
def diff_options
- options = { ignore_whitespace_change: hide_whitespace?, no_collapse: expand_all_diffs? }
+ options = { ignore_whitespace_change: hide_whitespace?, expanded: diffs_expanded? }
if action_name == 'diff_for_path'
- options[:no_collapse] = true
+ options[:expanded] = true
options[:paths] = params.values_at(:old_path, :new_path)
end
@@ -66,12 +66,12 @@ module DiffHelper
discussions_left = discussions_right = nil
- if left && (left.unchanged? || left.removed?)
+ if left && (left.unchanged? || left.discussable?)
line_code = diff_file.line_code(left)
discussions_left = @grouped_diff_discussions[line_code]
end
- if right && right.added?
+ if right&.discussable?
line_code = diff_file.line_code(right)
discussions_right = @grouped_diff_discussions[line_code]
end
diff --git a/app/helpers/notes_helper.rb b/app/helpers/notes_helper.rb
index 375110b77e2..3d4802290b5 100644
--- a/app/helpers/notes_helper.rb
+++ b/app/helpers/notes_helper.rb
@@ -50,7 +50,7 @@ module NotesHelper
def link_to_reply_discussion(discussion, line_type = nil)
return unless current_user
- data = { discussion_id: discussion.id, line_type: line_type }
+ data = { discussion_id: discussion.reply_id, line_type: line_type }
button_tag 'Reply...', class: 'btn btn-text-field js-discussion-reply-button',
data: data, title: 'Add a reply'
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
index 043f57241a3..3d12f3c306b 100644
--- a/app/models/application_setting.rb
+++ b/app/models/application_setting.rb
@@ -13,13 +13,13 @@ class ApplicationSetting < ActiveRecord::Base
[\r\n] # any number of newline characters
}x
- serialize :restricted_visibility_levels
- serialize :import_sources
- serialize :disabled_oauth_sign_in_sources, Array
- serialize :domain_whitelist, Array
- serialize :domain_blacklist, Array
- serialize :repository_storages
- serialize :sidekiq_throttling_queues, Array
+ serialize :restricted_visibility_levels # rubocop:disable Cop/ActiverecordSerialize
+ serialize :import_sources # rubocop:disable Cop/ActiverecordSerialize
+ serialize :disabled_oauth_sign_in_sources, Array # rubocop:disable Cop/ActiverecordSerialize
+ serialize :domain_whitelist, Array # rubocop:disable Cop/ActiverecordSerialize
+ serialize :domain_blacklist, Array # rubocop:disable Cop/ActiverecordSerialize
+ serialize :repository_storages # rubocop:disable Cop/ActiverecordSerialize
+ serialize :sidekiq_throttling_queues, Array # rubocop:disable Cop/ActiverecordSerialize
cache_markdown_field :sign_in_text
cache_markdown_field :help_page_text
diff --git a/app/models/audit_event.rb b/app/models/audit_event.rb
index 967ffd46db0..46d412fbd72 100644
--- a/app/models/audit_event.rb
+++ b/app/models/audit_event.rb
@@ -1,5 +1,5 @@
class AuditEvent < ActiveRecord::Base
- serialize :details, Hash
+ serialize :details, Hash # rubocop:disable Cop/ActiverecordSerialize
belongs_to :user, foreign_key: :author_id
diff --git a/app/models/blob.rb b/app/models/blob.rb
index e75926241ba..6a42a12891c 100644
--- a/app/models/blob.rb
+++ b/app/models/blob.rb
@@ -102,10 +102,6 @@ class Blob < SimpleDelegator
raw_size == 0
end
- def too_large?
- size && truncated?
- end
-
def external_storage_error?
if external_storage == :lfs
!project&.lfs_enabled?
@@ -160,7 +156,7 @@ class Blob < SimpleDelegator
end
def readable_text?
- text? && !stored_externally? && !too_large?
+ text? && !stored_externally? && !truncated?
end
def simple_viewer
@@ -187,9 +183,9 @@ class Blob < SimpleDelegator
rendered_as_text? && rich_viewer
end
- def override_max_size!
- simple_viewer&.override_max_size = true
- rich_viewer&.override_max_size = true
+ def expand!
+ simple_viewer&.expanded = true
+ rich_viewer&.expanded = true
end
private
diff --git a/app/models/blob_viewer/auxiliary.rb b/app/models/blob_viewer/auxiliary.rb
index 07a207730cf..1bea225f17c 100644
--- a/app/models/blob_viewer/auxiliary.rb
+++ b/app/models/blob_viewer/auxiliary.rb
@@ -7,8 +7,8 @@ module BlobViewer
included do
self.loading_partial_name = 'loading_auxiliary'
self.type = :auxiliary
- self.overridable_max_size = 100.kilobytes
- self.max_size = 100.kilobytes
+ self.collapse_limit = 100.kilobytes
+ self.size_limit = 100.kilobytes
end
def visible_to?(current_user)
diff --git a/app/models/blob_viewer/base.rb b/app/models/blob_viewer/base.rb
index 26a3778c2a3..e6119d25fab 100644
--- a/app/models/blob_viewer/base.rb
+++ b/app/models/blob_viewer/base.rb
@@ -2,14 +2,14 @@ module BlobViewer
class Base
PARTIAL_PATH_PREFIX = 'projects/blob/viewers'.freeze
- class_attribute :partial_name, :loading_partial_name, :type, :extensions, :file_types, :load_async, :binary, :switcher_icon, :switcher_title, :overridable_max_size, :max_size
+ class_attribute :partial_name, :loading_partial_name, :type, :extensions, :file_types, :load_async, :binary, :switcher_icon, :switcher_title, :collapse_limit, :size_limit
self.loading_partial_name = 'loading'
delegate :partial_path, :loading_partial_path, :rich?, :simple?, :text?, :binary?, to: :class
attr_reader :blob
- attr_accessor :override_max_size
+ attr_accessor :expanded
delegate :project, to: :blob
@@ -61,24 +61,16 @@ module BlobViewer
self.class.load_async? && render_error.nil?
end
- def exceeds_overridable_max_size?
- overridable_max_size && blob.raw_size > overridable_max_size
- end
-
- def exceeds_max_size?
- max_size && blob.raw_size > max_size
- end
+ def collapsed?
+ return @collapsed if defined?(@collapsed)
- def can_override_max_size?
- exceeds_overridable_max_size? && !exceeds_max_size?
+ @collapsed = !expanded && collapse_limit && blob.raw_size > collapse_limit
end
def too_large?
- if override_max_size
- exceeds_max_size?
- else
- exceeds_overridable_max_size?
- end
+ return @too_large if defined?(@too_large)
+
+ @too_large = size_limit && blob.raw_size > size_limit
end
# This method is used on the server side to check whether we can attempt to
@@ -95,6 +87,8 @@ module BlobViewer
def render_error
if too_large?
:too_large
+ elsif collapsed?
+ :collapsed
end
end
diff --git a/app/models/blob_viewer/client_side.rb b/app/models/blob_viewer/client_side.rb
index cc68236f92b..079cfbe3616 100644
--- a/app/models/blob_viewer/client_side.rb
+++ b/app/models/blob_viewer/client_side.rb
@@ -4,8 +4,8 @@ module BlobViewer
included do
self.load_async = false
- self.overridable_max_size = 10.megabytes
- self.max_size = 50.megabytes
+ self.collapse_limit = 10.megabytes
+ self.size_limit = 50.megabytes
end
end
end
diff --git a/app/models/blob_viewer/server_side.rb b/app/models/blob_viewer/server_side.rb
index 87884dcd6bf..05a3dd7d913 100644
--- a/app/models/blob_viewer/server_side.rb
+++ b/app/models/blob_viewer/server_side.rb
@@ -4,8 +4,8 @@ module BlobViewer
included do
self.load_async = true
- self.overridable_max_size = 2.megabytes
- self.max_size = 5.megabytes
+ self.collapse_limit = 2.megabytes
+ self.size_limit = 5.megabytes
end
def prepare!
diff --git a/app/models/blob_viewer/text.rb b/app/models/blob_viewer/text.rb
index eddca50b4d4..f68cbb7e212 100644
--- a/app/models/blob_viewer/text.rb
+++ b/app/models/blob_viewer/text.rb
@@ -5,7 +5,7 @@ module BlobViewer
self.partial_name = 'text'
self.binary = false
- self.overridable_max_size = 1.megabyte
- self.max_size = 10.megabytes
+ self.collapse_limit = 1.megabyte
+ self.size_limit = 10.megabytes
end
end
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index c7565c93811..58dfdd87652 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -19,8 +19,8 @@ module Ci
)
end
- serialize :options
- serialize :yaml_variables, Gitlab::Serializer::Ci::Variables
+ serialize :options # rubocop:disable Cop/ActiverecordSerialize
+ serialize :yaml_variables, Gitlab::Serializer::Ci::Variables # rubocop:disable Cop/ActiverecordSerialize
delegate :name, to: :project, prefix: true
@@ -255,38 +255,6 @@ module Ci
Time.now - updated_at > 15.minutes.to_i
end
- ##
- # Deprecated
- #
- # This contains a hotfix for CI build data integrity, see #4246
- #
- # This method is used by `ArtifactUploader` to create a store_dir.
- # Warning: Uploader uses it after AND before file has been stored.
- #
- # This method returns old path to artifacts only if it already exists.
- #
- def artifacts_path
- # We need the project even if it's soft deleted, because whenever
- # we're really deleting the project, we'll also delete the builds,
- # and in order to delete the builds, we need to know where to find
- # the artifacts, which is depending on the data of the project.
- # We need to retain the project in this case.
- the_project = project || unscoped_project
-
- old = File.join(created_at.utc.strftime('%Y_%m'),
- the_project.ci_id.to_s,
- id.to_s)
-
- old_store = File.join(ArtifactUploader.artifacts_path, old)
- return old if the_project.ci_id && File.directory?(old_store)
-
- File.join(
- created_at.utc.strftime('%Y_%m'),
- the_project.id.to_s,
- id.to_s
- )
- end
-
def valid_token?(token)
self.token && ActiveSupport::SecurityUtils.variable_size_secure_compare(token, self.token)
end
diff --git a/app/models/ci/trigger_request.rb b/app/models/ci/trigger_request.rb
index 2b807731d0d..564334ad1ad 100644
--- a/app/models/ci/trigger_request.rb
+++ b/app/models/ci/trigger_request.rb
@@ -6,7 +6,7 @@ module Ci
belongs_to :pipeline, foreign_key: :commit_id
has_many :builds
- serialize :variables
+ serialize :variables # rubocop:disable Cop/ActiverecordSerialize
def user_variables
return [] unless variables
diff --git a/app/models/concerns/noteable.rb b/app/models/concerns/noteable.rb
index dd1e6630642..c7bdc997eca 100644
--- a/app/models/concerns/noteable.rb
+++ b/app/models/concerns/noteable.rb
@@ -43,7 +43,12 @@ module Noteable
end
def resolvable_discussions
- @resolvable_discussions ||= discussion_notes.resolvable.discussions(self)
+ @resolvable_discussions ||=
+ if defined?(@discussions)
+ @discussions.select(&:resolvable?)
+ else
+ discussion_notes.resolvable.discussions(self)
+ end
end
def discussions_resolvable?
diff --git a/app/models/diff_discussion.rb b/app/models/diff_discussion.rb
index 800574d8be0..07c4846e2ac 100644
--- a/app/models/diff_discussion.rb
+++ b/app/models/diff_discussion.rb
@@ -10,6 +10,7 @@ class DiffDiscussion < Discussion
delegate :position,
:original_position,
+ :change_position,
to: :first_note
diff --git a/app/models/diff_note.rb b/app/models/diff_note.rb
index 2a4cff37566..20ef1378500 100644
--- a/app/models/diff_note.rb
+++ b/app/models/diff_note.rb
@@ -6,9 +6,9 @@ class DiffNote < Note
NOTEABLE_TYPES = %w(MergeRequest Commit).freeze
- serialize :original_position, Gitlab::Diff::Position
- serialize :position, Gitlab::Diff::Position
- serialize :change_position, Gitlab::Diff::Position
+ serialize :original_position, Gitlab::Diff::Position # rubocop:disable Cop/ActiverecordSerialize
+ serialize :position, Gitlab::Diff::Position # rubocop:disable Cop/ActiverecordSerialize
+ serialize :change_position, Gitlab::Diff::Position # rubocop:disable Cop/ActiverecordSerialize
validates :original_position, presence: true
validates :position, presence: true
@@ -95,13 +95,21 @@ class DiffNote < Note
return if active?
- Notes::DiffPositionUpdateService.new(
- self.project,
- nil,
+ tracer = Gitlab::Diff::PositionTracer.new(
+ project: self.project,
old_diff_refs: self.position.diff_refs,
- new_diff_refs: noteable.diff_refs,
+ new_diff_refs: self.noteable.diff_refs,
paths: self.position.paths
- ).execute(self)
+ )
+
+ result = tracer.trace(self.position)
+ return unless result
+
+ if result[:outdated]
+ self.change_position = result[:position]
+ else
+ self.position = result[:position]
+ end
end
def verify_supported
diff --git a/app/models/discussion.rb b/app/models/discussion.rb
index 0b6b920ed66..d1cec7613af 100644
--- a/app/models/discussion.rb
+++ b/app/models/discussion.rb
@@ -21,7 +21,8 @@ class Discussion
end
def self.build_collection(notes, context_noteable = nil)
- notes.group_by { |n| n.discussion_id(context_noteable) }.values.map { |notes| build(notes, context_noteable) }
+ grouped_notes = notes.group_by { |n| n.discussion_id(context_noteable) }
+ grouped_notes.values.map { |notes| build(notes, context_noteable) }
end
# Returns an alphanumeric discussion ID based on `build_discussion_id`
@@ -84,6 +85,12 @@ class Discussion
first_note.discussion_id(context_noteable)
end
+ def reply_id
+ # To reply to this discussion, we need the actual discussion_id from the database,
+ # not the potentially overwritten one based on the noteable.
+ first_note.discussion_id
+ end
+
alias_method :to_param, :id
def diff_discussion?
diff --git a/app/models/event.rb b/app/models/event.rb
index e6fad46077a..46e89388bc1 100644
--- a/app/models/event.rb
+++ b/app/models/event.rb
@@ -26,7 +26,7 @@ class Event < ActiveRecord::Base
belongs_to :target, polymorphic: true
# For Hash only
- serialize :data
+ serialize :data # rubocop:disable Cop/ActiverecordSerialize
# Callbacks
after_create :reset_project_activity
diff --git a/app/models/hooks/web_hook_log.rb b/app/models/hooks/web_hook_log.rb
index 2738b229d84..d73cfcf630d 100644
--- a/app/models/hooks/web_hook_log.rb
+++ b/app/models/hooks/web_hook_log.rb
@@ -1,9 +1,9 @@
class WebHookLog < ActiveRecord::Base
belongs_to :web_hook
- serialize :request_headers, Hash
- serialize :request_data, Hash
- serialize :response_headers, Hash
+ serialize :request_headers, Hash # rubocop:disable Cop/ActiverecordSerialize
+ serialize :request_data, Hash # rubocop:disable Cop/ActiverecordSerialize
+ serialize :response_headers, Hash # rubocop:disable Cop/ActiverecordSerialize
validates :web_hook, presence: true
diff --git a/app/models/legacy_diff_note.rb b/app/models/legacy_diff_note.rb
index ebf8fb92ab5..7126de2d488 100644
--- a/app/models/legacy_diff_note.rb
+++ b/app/models/legacy_diff_note.rb
@@ -7,7 +7,7 @@
class LegacyDiffNote < Note
include NoteOnDiff
- serialize :st_diff
+ serialize :st_diff # rubocop:disable Cop/ActiverecordSerialize
validates :line_code, presence: true, line_code: true
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 356af776b8d..dd155252ad5 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -21,7 +21,7 @@ class MergeRequest < ActiveRecord::Base
belongs_to :assignee, class_name: "User"
- serialize :merge_params, Hash
+ serialize :merge_params, Hash # rubocop:disable Cop/ActiverecordSerialize
after_create :ensure_merge_request_diff, unless: :importing?
after_update :reload_diff_if_branch_changed
@@ -220,10 +220,10 @@ class MergeRequest < ActiveRecord::Base
def diffs(diff_options = {})
if compare
- # When saving MR diffs, `no_collapse` is implicitly added (because we need
+ # When saving MR diffs, `expanded` is implicitly added (because we need
# to save the entire contents to the DB), so add that here for
# consistency.
- compare.diffs(diff_options.merge(no_collapse: true))
+ compare.diffs(diff_options.merge(expanded: true))
else
merge_request_diff.diffs(diff_options)
end
@@ -421,7 +421,7 @@ class MergeRequest < ActiveRecord::Base
MergeRequests::MergeRequestDiffCacheService.new.execute(self)
new_diff_refs = self.diff_refs
- update_diff_notes_positions(
+ update_diff_discussion_positions(
old_diff_refs: old_diff_refs,
new_diff_refs: new_diff_refs,
current_user: current_user
@@ -853,19 +853,18 @@ class MergeRequest < ActiveRecord::Base
diff_refs && diff_refs.complete?
end
- def update_diff_notes_positions(old_diff_refs:, new_diff_refs:, current_user: nil)
+ def update_diff_discussion_positions(old_diff_refs:, new_diff_refs:, current_user: nil)
return unless has_complete_diff_refs?
return if new_diff_refs == old_diff_refs
- active_diff_notes = self.notes.new_diff_notes.select do |note|
- note.active?(old_diff_refs)
+ active_diff_discussions = self.notes.new_diff_notes.discussions.select do |discussion|
+ discussion.active?(old_diff_refs)
end
+ return if active_diff_discussions.empty?
- return if active_diff_notes.empty?
+ paths = active_diff_discussions.flat_map { |n| n.diff_file.paths }.uniq
- paths = active_diff_notes.flat_map { |n| n.diff_file.paths }.uniq
-
- service = Notes::DiffPositionUpdateService.new(
+ service = Discussions::UpdateDiffPositionService.new(
self.project,
current_user,
old_diff_refs: old_diff_refs,
@@ -873,11 +872,8 @@ class MergeRequest < ActiveRecord::Base
paths: paths
)
- transaction do
- active_diff_notes.each do |note|
- service.execute(note)
- Gitlab::Timeless.timeless(note, &:save)
- end
+ active_diff_discussions.each do |discussion|
+ service.execute(discussion)
end
end
diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb
index 1bd61c1d465..1c2f335f95e 100644
--- a/app/models/merge_request_diff.rb
+++ b/app/models/merge_request_diff.rb
@@ -11,8 +11,8 @@ class MergeRequestDiff < ActiveRecord::Base
belongs_to :merge_request
- serialize :st_commits
- serialize :st_diffs
+ serialize :st_commits # rubocop:disable Cop/ActiverecordSerialize
+ serialize :st_diffs # rubocop:disable Cop/ActiverecordSerialize
state_machine :state, initial: :empty do
state :collected
diff --git a/app/models/note.rb b/app/models/note.rb
index 60257aac93b..832c68243fb 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -110,7 +110,7 @@ class Note < ActiveRecord::Base
end
def discussions(context_noteable = nil)
- Discussion.build_collection(fresh, context_noteable)
+ Discussion.build_collection(all.includes(:noteable).fresh, context_noteable)
end
def find_discussion(discussion_id)
diff --git a/app/models/personal_access_token.rb b/app/models/personal_access_token.rb
index e8b000ddad6..ae9f71e7747 100644
--- a/app/models/personal_access_token.rb
+++ b/app/models/personal_access_token.rb
@@ -3,7 +3,7 @@ class PersonalAccessToken < ActiveRecord::Base
include TokenAuthenticatable
add_authentication_token_field :token
- serialize :scopes, Array
+ serialize :scopes, Array # rubocop:disable Cop/ActiverecordSerialize
belongs_to :user
diff --git a/app/models/project_import_data.rb b/app/models/project_import_data.rb
index 331123a5a5b..e3cafd4d1c6 100644
--- a/app/models/project_import_data.rb
+++ b/app/models/project_import_data.rb
@@ -10,7 +10,7 @@ class ProjectImportData < ActiveRecord::Base
insecure_mode: true,
algorithm: 'aes-256-cbc'
- serialize :data, JSON
+ serialize :data, JSON # rubocop:disable Cop/ActiverecordSerialize
validates :project, presence: true
diff --git a/app/models/project_team.rb b/app/models/project_team.rb
index 543b9b293e0..e1cc56551ba 100644
--- a/app/models/project_team.rb
+++ b/app/models/project_team.rb
@@ -167,7 +167,7 @@ class ProjectTeam
access = RequestStore.store[key]
end
- # Lookup only the IDs we need
+ # Look up only the IDs we need
user_ids = user_ids - access.keys
return access if user_ids.empty?
@@ -178,6 +178,13 @@ class ProjectTeam
maximum(:access_level)
access.merge!(users_access)
+
+ missing_user_ids = user_ids - users_access.keys
+
+ missing_user_ids.each do |user_id|
+ access[user_id] = Gitlab::Access::NO_ACCESS
+ end
+
access
end
diff --git a/app/models/sent_notification.rb b/app/models/sent_notification.rb
index 0ae5864615a..eed3ca7e179 100644
--- a/app/models/sent_notification.rb
+++ b/app/models/sent_notification.rb
@@ -1,5 +1,5 @@
class SentNotification < ActiveRecord::Base
- serialize :position, Gitlab::Diff::Position
+ serialize :position, Gitlab::Diff::Position # rubocop:disable Cop/ActiverecordSerialize
belongs_to :project
belongs_to :noteable, polymorphic: true
diff --git a/app/models/service.rb b/app/models/service.rb
index 8916f88076e..6a0b0a5c522 100644
--- a/app/models/service.rb
+++ b/app/models/service.rb
@@ -2,7 +2,7 @@
# and implement a set of methods
class Service < ActiveRecord::Base
include Sortable
- serialize :properties, JSON
+ serialize :properties, JSON # rubocop:disable Cop/ActiverecordSerialize
default_value_for :active, false
default_value_for :push_events, true
diff --git a/app/models/user.rb b/app/models/user.rb
index 9aad327b592..8114d0ff88e 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -40,7 +40,7 @@ class User < ActiveRecord::Base
otp_secret_encryption_key: Gitlab::Application.secrets.otp_key_base
devise :two_factor_backupable, otp_number_of_backup_codes: 10
- serialize :otp_backup_codes, JSON
+ serialize :otp_backup_codes, JSON # rubocop:disable Cop/ActiverecordSerialize
devise :lockable, :recoverable, :rememberable, :trackable,
:validatable, :omniauthable, :confirmable, :registerable
@@ -369,6 +369,7 @@ class User < ActiveRecord::Base
# Pattern used to extract `@user` user references from text
def reference_pattern
%r{
+ (?<!\w)
#{Regexp.escape(reference_prefix)}
(?<user>#{Gitlab::PathRegex::FULL_NAMESPACE_FORMAT_REGEX})
}x
diff --git a/app/services/discussions/update_diff_position_service.rb b/app/services/discussions/update_diff_position_service.rb
new file mode 100644
index 00000000000..1ef8d9edbe1
--- /dev/null
+++ b/app/services/discussions/update_diff_position_service.rb
@@ -0,0 +1,41 @@
+module Discussions
+ class UpdateDiffPositionService < BaseService
+ def execute(discussion)
+ result = tracer.trace(discussion.position)
+ return unless result
+
+ position = result[:position]
+ outdated = result[:outdated]
+
+ discussion.notes.each do |note|
+ if outdated
+ note.change_position = position
+ else
+ note.position = position
+ note.change_position = nil
+ end
+ end
+
+ Note.transaction do
+ discussion.notes.each do |note|
+ Gitlab::Timeless.timeless(note, &:save)
+ end
+
+ if outdated && current_user
+ SystemNoteService.diff_discussion_outdated(discussion, project, current_user, position)
+ end
+ end
+ end
+
+ private
+
+ def tracer
+ @tracer ||= Gitlab::Diff::PositionTracer.new(
+ project: project,
+ old_diff_refs: params[:old_diff_refs],
+ new_diff_refs: params[:new_diff_refs],
+ paths: params[:paths]
+ )
+ end
+ end
+end
diff --git a/app/services/notes/diff_position_update_service.rb b/app/services/notes/diff_position_update_service.rb
deleted file mode 100644
index eff7b287269..00000000000
--- a/app/services/notes/diff_position_update_service.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-module Notes
- class DiffPositionUpdateService < BaseService
- def execute(note)
- results = tracer.trace(note.position)
- return unless results
-
- position = results[:position]
- outdated = results[:outdated]
-
- if outdated
- note.change_position = position
-
- if note.persisted? && current_user
- SystemNoteService.diff_discussion_outdated(note.to_discussion, project, current_user, position)
- end
- else
- note.position = position
- note.change_position = nil
- end
- end
-
- private
-
- def tracer
- @tracer ||= Gitlab::Diff::PositionTracer.new(
- project: project,
- old_diff_refs: params[:old_diff_refs],
- new_diff_refs: params[:new_diff_refs],
- paths: params[:paths]
- )
- end
- end
-end
diff --git a/app/uploaders/artifact_uploader.rb b/app/uploaders/artifact_uploader.rb
index 3e36ec91205..3bc0408f557 100644
--- a/app/uploaders/artifact_uploader.rb
+++ b/app/uploaders/artifact_uploader.rb
@@ -1,33 +1,35 @@
class ArtifactUploader < GitlabUploader
storage :file
- attr_accessor :build, :field
+ attr_reader :job, :field
- def self.artifacts_path
+ def self.local_artifacts_store
Gitlab.config.artifacts.path
end
def self.artifacts_upload_path
- File.join(self.artifacts_path, 'tmp/uploads/')
+ File.join(self.local_artifacts_store, 'tmp/uploads/')
end
- def self.artifacts_cache_path
- File.join(self.artifacts_path, 'tmp/cache/')
- end
-
- def initialize(build, field)
- @build, @field = build, field
+ def initialize(job, field)
+ @job, @field = job, field
end
def store_dir
- File.join(self.class.artifacts_path, @build.artifacts_path)
+ default_local_path
end
def cache_dir
- File.join(self.class.artifacts_cache_path, @build.artifacts_path)
+ File.join(self.class.local_artifacts_store, 'tmp/cache')
+ end
+
+ private
+
+ def default_local_path
+ File.join(self.class.local_artifacts_store, default_path)
end
- def filename
- file.try(:filename)
+ def default_path
+ File.join(job.created_at.utc.strftime('%Y_%m'), job.project_id.to_s, job.id.to_s)
end
end
diff --git a/app/uploaders/gitlab_uploader.rb b/app/uploaders/gitlab_uploader.rb
index e0a6c9b4067..02afddb8c6a 100644
--- a/app/uploaders/gitlab_uploader.rb
+++ b/app/uploaders/gitlab_uploader.rb
@@ -10,7 +10,11 @@ class GitlabUploader < CarrierWave::Uploader::Base
delegate :base_dir, to: :class
def file_storage?
- self.class.storage == CarrierWave::Storage::File
+ storage.is_a?(CarrierWave::Storage::File)
+ end
+
+ def file_cache_storage?
+ cache_storage.is_a?(CarrierWave::Storage::File)
end
# Reduce disk IO
diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml
index 53f0a1e7fde..3c9f932a225 100644
--- a/app/views/admin/dashboard/index.html.haml
+++ b/app/views/admin/dashboard/index.html.haml
@@ -79,6 +79,12 @@
= gitlab_pages
%span.light.pull-right
= boolean_to_icon gitlab_pages_enabled
+ - gitlab_shared_runners = 'Shared Runners'
+ - gitlab_shared_runners_enabled = Gitlab.config.gitlab_ci.shared_runners_enabled
+ %p{ "aria-label" => "#{gitlab_shared_runners}: status " + (gitlab_shared_runners_enabled ? "on" : "off") }
+ = gitlab_shared_runners
+ %span.light.pull-right
+ = boolean_to_icon gitlab_shared_runners_enabled
.col-md-4
%h4
diff --git a/app/views/discussions/_jump_to_next.html.haml b/app/views/discussions/_jump_to_next.html.haml
index 69bd416c4de..3db509f24a5 100644
--- a/app/views/discussions/_jump_to_next.html.haml
+++ b/app/views/discussions/_jump_to_next.html.haml
@@ -3,7 +3,7 @@
%jump-to-discussion{ "inline-template" => true, ":discussion-id" => "'#{discussion.try(:id)}'" }
.btn-group{ role: "group", "v-show" => "!allResolved", "v-if" => "showButton" }
%button.btn.btn-default.discussion-next-btn.has-tooltip{ "@click" => "jumpToNextUnresolvedDiscussion",
- title: "Jump to next unresolved discussion",
- "aria-label" => "Jump to next unresolved discussion",
+ ":title" => "buttonText",
+ ":aria-label" => "buttonText",
data: { container: "body" } }
= custom_icon("next_discussion")
diff --git a/app/views/projects/diffs/_content.html.haml b/app/views/projects/diffs/_content.html.haml
index c7e22a0b4ec..59844bc00cd 100644
--- a/app/views/projects/diffs/_content.html.haml
+++ b/app/views/projects/diffs/_content.html.haml
@@ -3,7 +3,7 @@
.diff-content
- if diff_file.too_large?
.nothing-here-block This diff could not be displayed because it is too large.
- - elsif blob.too_large?
+ - elsif blob.truncated?
.nothing-here-block The file could not be displayed because it is too large.
- elsif blob.readable_text?
- if !diff_file.repository.diffable?(blob)
diff --git a/app/views/projects/diffs/_diffs.html.haml b/app/views/projects/diffs/_diffs.html.haml
index 4768438c29e..d538c4c86c8 100644
--- a/app/views/projects/diffs/_diffs.html.haml
+++ b/app/views/projects/diffs/_diffs.html.haml
@@ -5,8 +5,8 @@
.content-block.oneline-block.files-changed
.inline-parallel-buttons
- - if !expand_all_diffs? && diff_files.any? { |diff_file| diff_file.collapsed? }
- = link_to 'Expand all', url_for(params.merge(expand_all_diffs: 1, format: nil)), class: 'btn btn-default'
+ - if !diffs_expanded? && diff_files.any? { |diff_file| diff_file.collapsed? }
+ = link_to 'Expand all', url_for(params.merge(expanded: 1, format: nil)), class: 'btn btn-default'
- if show_whitespace_toggle
- if current_controller?(:commit)
= commit_diff_whitespace_link(diffs.project, @commit, class: 'hidden-xs')
diff --git a/app/views/projects/diffs/_line.html.haml b/app/views/projects/diffs/_line.html.haml
index 7439b8a66f7..43708d22a0c 100644
--- a/app/views/projects/diffs/_line.html.haml
+++ b/app/views/projects/diffs/_line.html.haml
@@ -3,7 +3,7 @@
- discussions = local_assigns.fetch(:discussions, nil)
- type = line.type
- line_code = diff_file.line_code(line)
-- if discussions && !line.meta?
+- if discussions && line.discussable?
- line_discussions = discussions[line_code]
%tr.line_holder{ class: type, id: (line_code unless plain) }
- case type
diff --git a/app/views/projects/registry/repositories/index.html.haml b/app/views/projects/registry/repositories/index.html.haml
index be128e92fa7..5661af01302 100644
--- a/app/views/projects/registry/repositories/index.html.haml
+++ b/app/views/projects/registry/repositories/index.html.haml
@@ -1,26 +1,60 @@
- page_title "Container Registry"
-%hr
-
-%ul.content-list
- %li.light.prepend-top-default
+.row.prepend-top-default.append-bottom-default
+ .col-lg-3
+ %h4.prepend-top-0
+ = page_title
%p
- A 'container image' is a snapshot of a container.
- You can host your container images with GitLab.
- %br
- To start using container images hosted on GitLab you first need to login:
- %pre
- %code
+ With the Docker Container Registry integrated into GitLab, every project
+ can have its own space to store its Docker images.
+ %p.append-bottom-0
+ = succeed '.' do
+ Learn more about
+ = link_to 'Container Registry', help_page_path('user/project/container_registry'), target: '_blank'
+
+ .col-lg-9
+ .panel.panel-default
+ .panel-heading
+ %h4.panel-title
+ How to use the Container Registry
+ .panel-body
+ %p
+ First log in to GitLab&rsquo;s Container Registry using your GitLab username
+ and password. If you have
+ = link_to '2FA enabled', help_page_path('user/profile/account/two_factor_authentication'), target: '_blank'
+ you need to use a
+ = succeed ':' do
+ = link_to 'personal access token', help_page_path('user/profile/account/two_factor_authentication', anchor: 'personal-access-tokens'), target: '_blank'
+ %pre
docker login #{Gitlab.config.registry.host_port}
- %br
- Then you are free to create and upload a container image with build and push commands:
- %pre
- docker build -t #{escape_once(@project.container_registry_url)}/image .
%br
- docker push #{escape_once(@project.container_registry_url)}/image
+ %p
+ Once you log in, you&rsquo;re free to create and upload a container image
+ using the common
+ %code build
+ and
+ %code push
+ commands:
+ %pre
+ :plain
+ docker build -t #{escape_once(@project.container_registry_url)} .
+ docker push #{escape_once(@project.container_registry_url)}
- - if @images.blank?
- .nothing-here-block No container image repositories in Container Registry for this project.
+ %hr
+ %h5.prepend-top-default
+ Use different image names
+ %p.light
+ GitLab supports up to 3 levels of image names. The following
+ examples of images are valid for your project:
+ %pre
+ :plain
+ #{escape_once(@project.container_registry_url)}:tag
+ #{escape_once(@project.container_registry_url)}/optional-image-name:tag
+ #{escape_once(@project.container_registry_url)}/optional-name/optional-image-name:tag
- - else
- = render partial: 'image', collection: @images
+ - if @images.blank?
+ %p.settings-message.text-center.append-bottom-default
+ No container images stored for this project. Add one by following the
+ instructions above.
+ - else
+ = render partial: 'image', collection: @images