diff options
Diffstat (limited to 'app/models')
-rw-r--r-- | app/models/application_setting.rb | 26 | ||||
-rw-r--r-- | app/models/ci/runner.rb | 6 | ||||
-rw-r--r-- | app/models/concerns/has_variable.rb | 4 | ||||
-rw-r--r-- | app/models/concerns/issuable.rb | 9 | ||||
-rw-r--r-- | app/models/email.rb | 1 | ||||
-rw-r--r-- | app/models/group.rb | 14 | ||||
-rw-r--r-- | app/models/merge_request.rb | 55 | ||||
-rw-r--r-- | app/models/merge_request_diff.rb | 72 | ||||
-rw-r--r-- | app/models/milestone.rb | 6 | ||||
-rw-r--r-- | app/models/namespace.rb | 6 | ||||
-rw-r--r-- | app/models/note.rb | 5 | ||||
-rw-r--r-- | app/models/project.rb | 15 | ||||
-rw-r--r-- | app/models/protected_branch.rb | 4 | ||||
-rw-r--r-- | app/models/protected_tag.rb | 4 | ||||
-rw-r--r-- | app/models/snippet.rb | 11 | ||||
-rw-r--r-- | app/models/storage/hashed_project.rb | 1 | ||||
-rw-r--r-- | app/models/user.rb | 24 |
17 files changed, 105 insertions, 158 deletions
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index 01455a52d2a..3117c98c846 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -172,6 +172,27 @@ class ApplicationSetting < ActiveRecord::Base end end + validates :gitaly_timeout_default, + presence: true, + numericality: { only_integer: true, greater_than_or_equal_to: 0 } + + validates :gitaly_timeout_medium, + presence: true, + numericality: { only_integer: true, greater_than_or_equal_to: 0 } + validates :gitaly_timeout_medium, + numericality: { less_than_or_equal_to: :gitaly_timeout_default }, + if: :gitaly_timeout_default + validates :gitaly_timeout_medium, + numericality: { greater_than_or_equal_to: :gitaly_timeout_fast }, + if: :gitaly_timeout_fast + + validates :gitaly_timeout_fast, + presence: true, + numericality: { only_integer: true, greater_than_or_equal_to: 0 } + validates :gitaly_timeout_fast, + numericality: { less_than_or_equal_to: :gitaly_timeout_default }, + if: :gitaly_timeout_default + SUPPORTED_KEY_TYPES.each do |type| validates :"#{type}_key_restriction", presence: true, key_restriction: { type: type } end @@ -308,7 +329,10 @@ class ApplicationSetting < ActiveRecord::Base two_factor_grace_period: 48, user_default_external: false, polling_interval_multiplier: 1, - usage_ping_enabled: Settings.gitlab['usage_ping_enabled'] + usage_ping_enabled: Settings.gitlab['usage_ping_enabled'], + gitaly_timeout_fast: 10, + gitaly_timeout_medium: 30, + gitaly_timeout_default: 55 } end diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb index c6509f89117..d39610a8995 100644 --- a/app/models/ci/runner.rb +++ b/app/models/ci/runner.rb @@ -1,6 +1,7 @@ module Ci class Runner < ActiveRecord::Base extend Gitlab::Ci::Model + include Gitlab::SQL::Pattern RUNNER_QUEUE_EXPIRY_TIME = 60.minutes ONLINE_CONTACT_TIMEOUT = 1.hour @@ -59,10 +60,7 @@ module Ci # # Returns an ActiveRecord::Relation. def self.search(query) - t = arel_table - pattern = "%#{query}%" - - where(t[:token].matches(pattern).or(t[:description].matches(pattern))) + fuzzy_search(query, [:token, :description]) end def self.contact_time_deadline diff --git a/app/models/concerns/has_variable.rb b/app/models/concerns/has_variable.rb index 9585b5583dc..8a241e4374a 100644 --- a/app/models/concerns/has_variable.rb +++ b/app/models/concerns/has_variable.rb @@ -16,6 +16,10 @@ module HasVariable key: Gitlab::Application.secrets.db_key_base, algorithm: 'aes-256-cbc' + def key=(new_key) + super(new_key.to_s.strip) + end + def to_runner_variable { key: key, value: value, public: false } end diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index 27cd3118f81..5ca4a7086cb 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -122,9 +122,7 @@ module Issuable # # Returns an ActiveRecord::Relation. def search(query) - title = to_fuzzy_arel(:title, query) - - where(title) + fuzzy_search(query, [:title]) end # Searches for records with a matching title or description. @@ -135,10 +133,7 @@ module Issuable # # Returns an ActiveRecord::Relation. def full_search(query) - title = to_fuzzy_arel(:title, query) - description = to_fuzzy_arel(:description, query) - - where(title&.or(description)) + fuzzy_search(query, [:title, :description]) end def sort(method, excluded_labels: []) diff --git a/app/models/email.rb b/app/models/email.rb index 2da8b050149..d6516761f0a 100644 --- a/app/models/email.rb +++ b/app/models/email.rb @@ -1,5 +1,6 @@ class Email < ActiveRecord::Base include Sortable + include Gitlab::SQL::Pattern belongs_to :user diff --git a/app/models/group.rb b/app/models/group.rb index dc4500360b9..76262acf50c 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -50,20 +50,6 @@ class Group < Namespace Gitlab::Database.postgresql? end - # Searches for groups matching the given query. - # - # This method uses ILIKE on PostgreSQL and LIKE on MySQL. - # - # query - The search query as a String - # - # Returns an ActiveRecord::Relation. - def search(query) - table = Namespace.arel_table - pattern = "%#{query}%" - - where(table[:name].matches(pattern).or(table[:path].matches(pattern))) - end - def sort(method) if method == 'storage_size_desc' # storage_size is a virtual column so we need to diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index e4d8f486c77..bbc01e9677c 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -283,9 +283,9 @@ class MergeRequest < ActiveRecord::Base if persisted? merge_request_diff.commit_shas elsif compare_commits - compare_commits.reverse.map(&:sha) + compare_commits.to_a.reverse.map(&:sha) else - [] + Array(diff_head_sha) end end @@ -364,16 +364,28 @@ class MergeRequest < ActiveRecord::Base # We use these attributes to force these to the intended values. attr_writer :target_branch_sha, :source_branch_sha + def source_branch_ref + return @source_branch_sha if @source_branch_sha + return unless source_branch + + Gitlab::Git::BRANCH_REF_PREFIX + source_branch + end + + def target_branch_ref + return @target_branch_sha if @target_branch_sha + return unless target_branch + + Gitlab::Git::BRANCH_REF_PREFIX + target_branch + end + def source_branch_head return unless source_project - source_branch_ref = @source_branch_sha || source_branch source_project.repository.commit(source_branch_ref) if source_branch_ref end def target_branch_head - target_branch_ref = @target_branch_sha || target_branch - target_project.repository.commit(target_branch_ref) if target_branch_ref + target_project.repository.commit(target_branch_ref) end def branch_merge_base_commit @@ -482,7 +494,7 @@ class MergeRequest < ActiveRecord::Base def merge_request_diff_for(diff_refs_or_sha) @merge_request_diffs_by_diff_refs_or_sha ||= Hash.new do |h, diff_refs_or_sha| - diffs = merge_request_diffs.viewable.select_without_diff + diffs = merge_request_diffs.viewable h[diff_refs_or_sha] = if diff_refs_or_sha.is_a?(Gitlab::Diff::DiffRefs) diffs.find_by_diff_refs(diff_refs_or_sha) @@ -887,7 +899,8 @@ class MergeRequest < ActiveRecord::Base def compute_diverged_commits_count return 0 unless source_branch_sha && target_branch_sha - Gitlab::Git::Commit.between(target_project.repository.raw_repository, source_branch_sha, target_branch_sha).size + target_project.repository + .count_commits_between(source_branch_sha, target_branch_sha) end private :compute_diverged_commits_count @@ -906,28 +919,18 @@ class MergeRequest < ActiveRecord::Base # Note that this could also return SHA from now dangling commits # def all_commit_shas - if persisted? - # MySQL doesn't support LIMIT in a subquery. - diffs_relation = - if Gitlab::Database.postgresql? - merge_request_diffs.order(id: :desc).limit(100) - else - merge_request_diffs - end + return commit_shas unless persisted? - column_shas = MergeRequestDiffCommit - .where(merge_request_diff: diffs_relation) - .limit(10_000) - .pluck('sha') + diffs_relation = merge_request_diffs - serialised_shas = merge_request_diffs.where.not(st_commits: nil).flat_map(&:commit_shas) + # MySQL doesn't support LIMIT in a subquery. + diffs_relation = diffs_relation.recent if Gitlab::Database.postgresql? - (column_shas + serialised_shas).uniq - elsif compare_commits - compare_commits.to_a.reverse.map(&:id) - else - [diff_head_sha] - end + MergeRequestDiffCommit + .where(merge_request_diff: diffs_relation) + .limit(10_000) + .pluck('sha') + .uniq end def merge_commit diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb index 9ee561b5161..c37aa0a594b 100644 --- a/app/models/merge_request_diff.rb +++ b/app/models/merge_request_diff.rb @@ -1,14 +1,14 @@ class MergeRequestDiff < ActiveRecord::Base include Sortable include Importable - include Gitlab::EncodingHelper include ManualInverseAssociation + include IgnorableColumn - # Prevent store of diff if commits amount more then 500 + # Don't display more than 100 commits at once COMMITS_SAFE_SIZE = 100 - # Valid types of serialized diffs allowed by Gitlab::Git::Diff - VALID_CLASSES = [Hash, Rugged::Patch, Rugged::Diff::Delta].freeze + ignore_column :st_commits, + :st_diffs belongs_to :merge_request manual_inverse_association :merge_request, :merge_request_diff @@ -16,9 +16,6 @@ class MergeRequestDiff < ActiveRecord::Base has_many :merge_request_diff_files, -> { order(:merge_request_diff_id, :relative_order) } has_many :merge_request_diff_commits, -> { order(:merge_request_diff_id, :relative_order) } - serialize :st_commits # rubocop:disable Cop/ActiveRecordSerialize - serialize :st_diffs # rubocop:disable Cop/ActiveRecordSerialize - state_machine :state, initial: :empty do state :collected state :overflow @@ -32,6 +29,8 @@ class MergeRequestDiff < ActiveRecord::Base scope :viewable, -> { without_state(:empty) } + scope :recent, -> { order(id: :desc).limit(100) } + # All diff information is collected from repository after object is created. # It allows you to override variables like head_commit_sha before getting diff. after_create :save_git_content, unless: :importing? @@ -40,14 +39,6 @@ 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 self.select_without_diff - select(column_names - ['st_diffs']) - end - - def st_commits - super || [] - end - # Collect information about commits and diff from repository # and save it to the database as serialized data def save_git_content @@ -129,11 +120,7 @@ class MergeRequestDiff < ActiveRecord::Base end def commit_shas - if st_commits.present? - st_commits.map { |commit| commit[:id] } - else - merge_request_diff_commits.map(&:sha) - end + merge_request_diff_commits.map(&:sha) end def diff_refs=(new_diff_refs) @@ -208,34 +195,11 @@ class MergeRequestDiff < ActiveRecord::Base end def commits_count - if st_commits.present? - st_commits.size - else - merge_request_diff_commits.size - end - end - - def utf8_st_diffs - return [] if st_diffs.blank? - - st_diffs.map do |diff| - diff.each do |k, v| - diff[k] = encode_utf8(v) if v.respond_to?(:encoding) - end - end + merge_request_diff_commits.size end private - # Old GitLab implementations may have generated diffs as ["--broken-diff"]. - # Avoid an error 500 by ignoring bad elements. See: - # https://gitlab.com/gitlab-org/gitlab-ce/issues/20776 - def valid_raw_diff?(raw) - return false unless raw.respond_to?(:each) - - raw.any? { |element| VALID_CLASSES.include?(element.class) } - end - def create_merge_request_diff_files(diffs) rows = diffs.map.with_index do |diff, index| diff_hash = diff.to_hash.merge( @@ -259,9 +223,7 @@ class MergeRequestDiff < ActiveRecord::Base end def load_diffs(options) - return Gitlab::Git::DiffCollection.new([]) unless diffs_from_database - - raw = diffs_from_database + raw = merge_request_diff_files.map(&:to_hash) if paths = options[:paths] raw = raw.select do |diff| @@ -272,22 +234,8 @@ class MergeRequestDiff < ActiveRecord::Base Gitlab::Git::DiffCollection.new(raw, options) end - def diffs_from_database - return @diffs_from_database if defined?(@diffs_from_database) - - @diffs_from_database = - if st_diffs.present? - if valid_raw_diff?(st_diffs) - st_diffs - end - elsif merge_request_diff_files.present? - merge_request_diff_files.map(&:to_hash) - end - end - def load_commits - commits = st_commits.presence || merge_request_diff_commits - commits = commits.map { |commit| Commit.from_hash(commit.to_hash, project) } + commits = merge_request_diff_commits.map { |commit| Commit.from_hash(commit.to_hash, project) } CommitCollection .new(merge_request.source_project, commits, merge_request.source_branch) diff --git a/app/models/milestone.rb b/app/models/milestone.rb index 01458120cda..c06ee8083f0 100644 --- a/app/models/milestone.rb +++ b/app/models/milestone.rb @@ -13,6 +13,7 @@ class Milestone < ActiveRecord::Base include Referable include StripAttribute include Milestoneish + include Gitlab::SQL::Pattern cache_markdown_field :title, pipeline: :single_line cache_markdown_field :description @@ -73,10 +74,7 @@ class Milestone < ActiveRecord::Base # # Returns an ActiveRecord::Relation. def search(query) - t = arel_table - pattern = "%#{query}%" - - where(t[:title].matches(pattern).or(t[:description].matches(pattern))) + fuzzy_search(query, [:title, :description]) end def filter_by_state(milestones, state) diff --git a/app/models/namespace.rb b/app/models/namespace.rb index 4d401e7ba18..fa76729a702 100644 --- a/app/models/namespace.rb +++ b/app/models/namespace.rb @@ -9,6 +9,7 @@ class Namespace < ActiveRecord::Base include Routable include AfterCommitQueue include Storage::LegacyNamespace + include Gitlab::SQL::Pattern # Prevent users from creating unreasonably deep level of nesting. # The number 20 was taken based on maximum nesting level of @@ -86,10 +87,7 @@ class Namespace < ActiveRecord::Base # # Returns an ActiveRecord::Relation def search(query) - t = arel_table - pattern = "%#{query}%" - - where(t[:name].matches(pattern).or(t[:path].matches(pattern))) + fuzzy_search(query, [:name, :path]) end def clean_path(path) diff --git a/app/models/note.rb b/app/models/note.rb index 50c9caf8529..340fe087f82 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -14,6 +14,7 @@ class Note < ActiveRecord::Base include ResolvableNote include IgnorableColumn include Editable + include Gitlab::SQL::Pattern module SpecialRole FIRST_TIME_CONTRIBUTOR = :first_time_contributor @@ -167,6 +168,10 @@ class Note < ActiveRecord::Base def has_special_role?(role, note) note.special_role == role end + + def search(query) + fuzzy_search(query, [:note]) + end end def cross_reference? diff --git a/app/models/project.rb b/app/models/project.rb index e276bd2422d..5a3f591c2e7 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -273,8 +273,9 @@ class Project < ActiveRecord::Base scope :pending_delete, -> { where(pending_delete: true) } scope :without_deleted, -> { where(pending_delete: false) } - scope :with_hashed_storage, -> { where('storage_version >= 1') } - scope :with_legacy_storage, -> { where(storage_version: [nil, 0]) } + scope :with_storage_feature, ->(feature) { where('storage_version >= :version', version: HASHED_STORAGE_FEATURES[feature]) } + scope :without_storage_feature, ->(feature) { where('storage_version < :version OR storage_version IS NULL', version: HASHED_STORAGE_FEATURES[feature]) } + scope :with_unmigrated_storage, -> { where('storage_version < :version OR storage_version IS NULL', version: LATEST_STORAGE_VERSION) } scope :sorted_by_activity, -> { reorder(last_activity_at: :desc) } scope :sorted_by_stars, -> { reorder('projects.star_count DESC') } @@ -425,17 +426,11 @@ class Project < ActiveRecord::Base # # query - The search query as a String. def search(query) - pattern = to_pattern(query) - - where( - arel_table[:path].matches(pattern) - .or(arel_table[:name].matches(pattern)) - .or(arel_table[:description].matches(pattern)) - ) + fuzzy_search(query, [:path, :name, :description]) end def search_by_title(query) - non_archived.where(arel_table[:name].matches(to_pattern(query))) + non_archived.fuzzy_search(query, [:name]) end def visibility_levels diff --git a/app/models/protected_branch.rb b/app/models/protected_branch.rb index 89bfc5f9a9c..d28fed11ca8 100644 --- a/app/models/protected_branch.rb +++ b/app/models/protected_branch.rb @@ -10,7 +10,9 @@ class ProtectedBranch < ActiveRecord::Base def self.protected?(project, ref_name) return true if project.empty_repo? && default_branch_protected? - self.matching(ref_name, protected_refs: project.protected_branches).present? + refs = project.protected_branches.select(:name) + + self.matching(ref_name, protected_refs: refs).present? end def self.default_branch_protected? diff --git a/app/models/protected_tag.rb b/app/models/protected_tag.rb index f38109c0e52..42a9bcf7723 100644 --- a/app/models/protected_tag.rb +++ b/app/models/protected_tag.rb @@ -5,6 +5,8 @@ class ProtectedTag < ActiveRecord::Base protected_ref_access_levels :create def self.protected?(project, ref_name) - self.matching(ref_name, protected_refs: project.protected_tags).present? + refs = project.protected_tags.select(:name) + + self.matching(ref_name, protected_refs: refs).present? end end diff --git a/app/models/snippet.rb b/app/models/snippet.rb index 2a5f07a15c4..05a16f11b59 100644 --- a/app/models/snippet.rb +++ b/app/models/snippet.rb @@ -9,6 +9,7 @@ class Snippet < ActiveRecord::Base include Mentionable include Spammable include Editable + include Gitlab::SQL::Pattern extend Gitlab::CurrentSettings @@ -135,10 +136,7 @@ class Snippet < ActiveRecord::Base # # Returns an ActiveRecord::Relation. def search(query) - t = arel_table - pattern = "%#{query}%" - - where(t[:title].matches(pattern).or(t[:file_name].matches(pattern))) + fuzzy_search(query, [:title, :file_name]) end # Searches for snippets with matching content. @@ -149,10 +147,7 @@ class Snippet < ActiveRecord::Base # # Returns an ActiveRecord::Relation. def search_code(query) - table = Snippet.arel_table - pattern = "%#{query}%" - - where(table[:content].matches(pattern)) + fuzzy_search(query, [:content]) end end end diff --git a/app/models/storage/hashed_project.rb b/app/models/storage/hashed_project.rb index f025f40994e..fae1b64961a 100644 --- a/app/models/storage/hashed_project.rb +++ b/app/models/storage/hashed_project.rb @@ -4,7 +4,6 @@ module Storage delegate :gitlab_shell, :repository_storage_path, to: :project ROOT_PATH_PREFIX = '@hashed'.freeze - STORAGE_VERSION = 1 def initialize(project) @project = project diff --git a/app/models/user.rb b/app/models/user.rb index cf6b36559a8..14941fd7f98 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -313,9 +313,6 @@ class User < ActiveRecord::Base # # Returns an ActiveRecord::Relation. def search(query) - table = arel_table - pattern = User.to_pattern(query) - order = <<~SQL CASE WHEN users.name = %{query} THEN 0 @@ -325,11 +322,8 @@ class User < ActiveRecord::Base END SQL - where( - table[:name].matches(pattern) - .or(table[:email].matches(pattern)) - .or(table[:username].matches(pattern)) - ).reorder(order % { query: ActiveRecord::Base.connection.quote(query) }, :name) + fuzzy_search(query, [:name, :email, :username]) + .reorder(order % { query: ActiveRecord::Base.connection.quote(query) }, :name) end # searches user by given pattern @@ -337,16 +331,16 @@ class User < ActiveRecord::Base # This method uses ILIKE on PostgreSQL and LIKE on MySQL. def search_with_secondary_emails(query) - table = arel_table email_table = Email.arel_table - pattern = "%#{query}%" - matched_by_emails_user_ids = email_table.project(email_table[:user_id]).where(email_table[:email].matches(pattern)) + matched_by_emails_user_ids = email_table + .project(email_table[:user_id]) + .where(Email.fuzzy_arel_match(:email, query)) where( - table[:name].matches(pattern) - .or(table[:email].matches(pattern)) - .or(table[:username].matches(pattern)) - .or(table[:id].in(matched_by_emails_user_ids)) + fuzzy_arel_match(:name, query) + .or(fuzzy_arel_match(:email, query)) + .or(fuzzy_arel_match(:username, query)) + .or(arel_table[:id].in(matched_by_emails_user_ids)) ) end |