summaryrefslogtreecommitdiff
path: root/app/models
diff options
context:
space:
mode:
Diffstat (limited to 'app/models')
-rw-r--r--app/models/blob.rb2
-rw-r--r--app/models/ci/build.rb2
-rw-r--r--app/models/ci/pipeline.rb2
-rw-r--r--app/models/concerns/milestoneish.rb8
-rw-r--r--app/models/project.rb47
5 files changed, 47 insertions, 14 deletions
diff --git a/app/models/blob.rb b/app/models/blob.rb
index 19ad110db58..71c974b4c09 100644
--- a/app/models/blob.rb
+++ b/app/models/blob.rb
@@ -160,7 +160,7 @@ class Blob < SimpleDelegator
if stored_externally?
if rich_viewer
rich_viewer.binary?
- elsif Linguist::Language.find_by_filename(name).any?
+ elsif Linguist::Language.find_by_extension(name).any?
false
elsif _mime_type
_mime_type.binary?
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index ee987949080..b230b7f47ef 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -467,7 +467,7 @@ module Ci
if cache && project.jobs_cache_index
cache = cache.merge(
- key: "#{cache[:key]}_#{project.jobs_cache_index}")
+ key: "#{cache[:key]}-#{project.jobs_cache_index}")
end
[cache]
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index 2abe90dd181..a72a815bfe8 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -13,7 +13,7 @@ module Ci
belongs_to :pipeline_schedule, class_name: 'Ci::PipelineSchedule'
has_many :stages
- has_many :statuses, class_name: 'CommitStatus', foreign_key: :commit_id
+ has_many :statuses, class_name: 'CommitStatus', foreign_key: :commit_id, inverse_of: :pipeline
has_many :builds, foreign_key: :commit_id
has_many :trigger_requests, dependent: :destroy, foreign_key: :commit_id # rubocop:disable Cop/ActiveRecordDependent
has_many :variables, class_name: 'Ci::PipelineVariable'
diff --git a/app/models/concerns/milestoneish.rb b/app/models/concerns/milestoneish.rb
index fd6703831e4..caf8afa97f9 100644
--- a/app/models/concerns/milestoneish.rb
+++ b/app/models/concerns/milestoneish.rb
@@ -94,6 +94,14 @@ module Milestoneish
Gitlab::TimeTrackingFormatter.output(total_issue_time_spent)
end
+ def total_issue_time_estimate
+ @total_issue_time_estimate ||= issues.sum(:time_estimate)
+ end
+
+ def human_total_issue_time_estimate
+ Gitlab::TimeTrackingFormatter.output(total_issue_time_estimate)
+ end
+
private
def count_issues_by_state(user)
diff --git a/app/models/project.rb b/app/models/project.rb
index 2ba6a863500..4ad6f025e5c 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -15,6 +15,7 @@ class Project < ActiveRecord::Base
include ValidAttribute
include ProjectFeaturesCompatibility
include SelectForProjectAuthorization
+ include Presentable
include Routable
include GroupDescendant
include Gitlab::SQL::Pattern
@@ -316,18 +317,42 @@ class Project < ActiveRecord::Base
# Returns a collection of projects that is either public or visible to the
# logged in user.
- def self.public_or_visible_to_user(user = nil)
- if user
- authorized = user
- .project_authorizations
- .select(1)
- .where('project_authorizations.project_id = projects.id')
-
- levels = Gitlab::VisibilityLevel.levels_for_user(user)
-
- where('EXISTS (?) OR projects.visibility_level IN (?)', authorized, levels)
+ #
+ # A caller may pass in a block to modify individual parts of
+ # the query, e.g. to apply .with_feature_available_for_user on top of it.
+ # This is useful for performance as we can stick those additional filters
+ # at the bottom of e.g. the UNION.
+ #
+ # Optionally, turning `use_where_in` off leads to returning a
+ # relation using #from instead of #where. This can perform much better
+ # but leads to trouble when used in conjunction with AR's #merge method.
+ def self.public_or_visible_to_user(user = nil, use_where_in: true, &block)
+ # If we don't get a block passed, use identity to avoid if/else repetitions
+ block = ->(part) { part } unless block_given?
+
+ return block.call(public_to_user) unless user
+
+ # If the user is allowed to see all projects,
+ # we can shortcut and just return.
+ return block.call(all) if user.full_private_access?
+
+ authorized = user
+ .project_authorizations
+ .select(1)
+ .where('project_authorizations.project_id = projects.id')
+ authorized_projects = block.call(where('EXISTS (?)', authorized))
+
+ levels = Gitlab::VisibilityLevel.levels_for_user(user)
+ visible_projects = block.call(where(visibility_level: levels))
+
+ # We use a UNION here instead of OR clauses since this results in better
+ # performance.
+ union = Gitlab::SQL::Union.new([authorized_projects.select('projects.id'), visible_projects.select('projects.id')])
+
+ if use_where_in
+ where("projects.id IN (#{union.to_sql})") # rubocop:disable GitlabSecurity/SqlInjection
else
- public_to_user
+ from("(#{union.to_sql}) AS #{table_name}")
end
end