Commit 7f6a5b6d authored by Valery Sizov's avatar Valery Sizov

Merge branch 'master' of gitlab.com:gitlab-org/gitlab-ee into ce_upstream[ci skip]

parents da404697 0355488d
......@@ -165,6 +165,11 @@ Style/DefWithParentheses:
Style/Documentation:
Enabled: false
# Multi-line method chaining should be done with leading dots.
Style/DotPosition:
Enabled: true
EnforcedStyle: leading
# This cop checks for uses of double negation (!!) to convert something
# to a boolean value. As this is both cryptic and usually redundant, it
# should be avoided.
......
......@@ -88,13 +88,6 @@ Security/YAMLLoad:
Style/BarePercentLiterals:
Enabled: false
# Offense count: 1403
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles.
# SupportedStyles: leading, trailing
Style/DotPosition:
Enabled: false
# Offense count: 5
# Cop supports --auto-correct.
Style/EachWithObject:
......
Please view this file on the master branch, on stable branches it's out of date.
## 9.2.7 (2017-06-21)
- Geo: fixed Dynamic Backoff strategy that was not being used by workers. !2128
- fix Rebase being disabled for unapproved MRs.
## 9.2.6 (2017-06-16)
- Geo: backported fix from 9.3 for big repository sync issues. !2000
......
......@@ -2,6 +2,10 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
## 9.2.7 (2017-06-21)
- Reinstate is_admin flag in users api when authenticated user is an admin. !12211 (rickettm)
## 9.2.6 (2017-06-16)
- Fix the last coverage in trace log should be extracted. !11128 (dosuken123)
......
......@@ -29,7 +29,8 @@
return this.pipeline.triggered || [];
},
triggeredBy() {
return this.pipeline.triggeredBy || [];
const response = this.pipeline.triggered_by;
return response ? [response] : [];
},
hasTriggered() {
return !!this.triggered.length;
......
......@@ -38,7 +38,8 @@ export default {
return this.mr.pipeline.triggered || [];
},
triggeredBy() {
return this.mr.pipeline.triggered_by || [];
const response = this.mr.pipeline.triggered_by;
return response ? [response] : [];
},
},
template: `
......
......@@ -50,27 +50,40 @@ export default {
codeText() {
const { newIssues, resolvedIssues } = this.mr.codeclimateMetrics;
let newIssuesText = '';
let resolvedIssuesText = '';
let text = '';
let newIssuesText;
let resolvedIssuesText;
let text = [];
if (this.hasNoneIssues) {
text = 'No changes to code quality so far.';
text.push('No changes to code quality so far.');
} else if (this.hasIssues) {
if (newIssues.length) {
newIssuesText = `degraded on ${newIssues.length} ${this.pointsText(newIssues)}`;
newIssuesText = ` degraded on ${newIssues.length} ${this.pointsText(newIssues)}`;
}
if (resolvedIssues.length) {
resolvedIssuesText = `improved on ${resolvedIssues.length} ${this.pointsText(resolvedIssues)}`;
resolvedIssuesText = ` improved on ${resolvedIssues.length} ${this.pointsText(resolvedIssues)}`;
}
const connector = this.hasIssues ? 'and' : '';
const connector = (newIssues.length > 0 && resolvedIssues.length > 0) ? ' and' : null;
text = `Code quality ${resolvedIssuesText} ${connector} ${newIssuesText}.`;
text = ['Code quality'];
if (resolvedIssuesText) {
text.push(resolvedIssuesText);
}
if (connector) {
text.push(connector);
}
if (newIssuesText) {
text.push(newIssuesText);
}
text.push('.');
}
return text;
return text.join('');
},
},
......
......@@ -97,8 +97,8 @@ module CreatesCommit
def merge_request_exists?
return @merge_request if defined?(@merge_request)
@merge_request = MergeRequestsFinder.new(current_user, project_id: @project.id).execute.opened.
find_by(source_project_id: @project_to_commit_into, source_branch: @branch_name, target_branch: @start_branch)
@merge_request = MergeRequestsFinder.new(current_user, project_id: @project.id).execute.opened
.find_by(source_project_id: @project_to_commit_into, source_branch: @branch_name, target_branch: @start_branch)
end
def different_project?
......
......@@ -15,8 +15,8 @@ module MembershipActions
end
def destroy
Members::DestroyService.new(membershipable, current_user, params).
execute(:all)
Members::DestroyService.new(membershipable, current_user, params)
.execute(:all)
respond_to do |format|
format.html do
......@@ -44,8 +44,8 @@ module MembershipActions
end
def leave
member = Members::DestroyService.new(membershipable, current_user, user_id: current_user.id).
execute(:all)
member = Members::DestroyService.new(membershipable, current_user, user_id: current_user.id)
.execute(:all)
notice =
if member.request?
......
......@@ -22,8 +22,8 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
end
def starred
@projects = load_projects(params.merge(starred: true)).
includes(:forked_from_project, :tags).page(params[:page])
@projects = load_projects(params.merge(starred: true))
.includes(:forked_from_project, :tags).page(params[:page])
@groups = []
......@@ -45,8 +45,8 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
end
def load_projects(finder_params)
ProjectsFinder.new(params: finder_params, current_user: current_user).
execute.includes(:route, namespace: :route)
ProjectsFinder.new(params: finder_params, current_user: current_user)
.execute.includes(:route, namespace: :route)
end
def load_events
......
module EE
module Projects
module IssuesController
extend ActiveSupport::Concern
included do
before_action :check_export_issues_available!, only: [:export_csv]
end
def export_csv
ExportCsvWorker.perform_async(current_user.id, project.id, filter_params)
index_path = namespace_project_issues_path(project.namespace, project)
redirect_to(index_path, notice: "Your CSV export has started. It will be emailed to #{current_user.notification_email} when complete.")
end
end
end
end
......@@ -49,7 +49,7 @@ class Explore::ProjectsController < Explore::ApplicationController
private
def load_projects
ProjectsFinder.new(current_user: current_user, params: params).
execute.includes(:route, namespace: :route)
ProjectsFinder.new(current_user: current_user, params: params)
.execute.includes(:route, namespace: :route)
end
end
......@@ -11,8 +11,8 @@ class JwtController < ApplicationController
service = SERVICES[params[:service]]
return head :not_found unless service
result = service.new(@authentication_result.project, @authentication_result.actor, auth_params).
execute(authentication_abilities: @authentication_result.authentication_abilities)
result = service.new(@authentication_result.project, @authentication_result.actor, auth_params)
.execute(authentication_abilities: @authentication_result.authentication_abilities)
render json: result, status: result[:http_status]
end
......
......@@ -157,7 +157,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
end
def log_audit_event(user, options = {})
AuditEventService.new(user, user, options).
for_authentication.security_event
AuditEventService.new(user, user, options)
.for_authentication.security_event
end
end
......@@ -49,9 +49,9 @@ class ProfilesController < Profiles::ApplicationController
end
def audit_log
@events = AuditEvent.where(entity_type: "User", entity_id: current_user.id).
order("created_at DESC").
page(params[:page])
@events = AuditEvent.where(entity_type: "User", entity_id: current_user.id)
.order("created_at DESC")
.page(params[:page])
end
def update_username
......
......@@ -53,9 +53,16 @@ class Projects::ApplicationController < ApplicationController
end
end
def check_project_feature_available!(feature)
render_404 unless project.feature_available?(feature, current_user)
end
def method_missing(method_sym, *arguments, &block)
if method_sym.to_s =~ /\Aauthorize_(.*)!\z/
case method_sym.to_s
when /\Aauthorize_(.*)!\z/
authorize_action!($1.to_sym)
when /\Acheck_(.*)_available!\z/
check_project_feature_available!($1.to_sym)
else
super
end
......
......@@ -187,7 +187,7 @@ class Projects::BlobController < Projects::ApplicationController
end
def set_last_commit_sha
@last_commit_sha = Gitlab::Git::Commit.
last_for_path(@repository, @ref, @path).sha
@last_commit_sha = Gitlab::Git::Commit
.last_for_path(@repository, @ref, @path).sha
end
end
......@@ -37,8 +37,8 @@ class Projects::BranchesController < Projects::ApplicationController
redirect_to_autodeploy = project.empty_repo? && project.deployment_services.present?
result = CreateBranchService.new(project, current_user).
execute(branch_name, ref)
result = CreateBranchService.new(project, current_user)
.execute(branch_name, ref)
if params[:issue_iid]
issue = IssuesFinder.new(current_user, project_id: @project.id).find_by(iid: params[:issue_iid])
......
......@@ -18,11 +18,11 @@ class Projects::CommitsController < Projects::ApplicationController
@repository.commits(@ref, path: @path, limit: @limit, offset: @offset)
end
@note_counts = project.notes.where(commit_id: @commits.map(&:id)).
group(:commit_id).count
@note_counts = project.notes.where(commit_id: @commits.map(&:id))
.group(:commit_id).count
@merge_request = MergeRequestsFinder.new(current_user, project_id: @project.id).execute.opened.
find_by(source_project: @project, source_branch: @ref, target_branch: @repository.root_ref)
@merge_request = MergeRequestsFinder.new(current_user, project_id: @project.id).execute.opened
.find_by(source_project: @project, source_branch: @ref, target_branch: @repository.root_ref)
respond_to do |format|
format.html
......
......@@ -61,7 +61,7 @@ class Projects::CompareController < Projects::ApplicationController
end
def merge_request
@merge_request ||= MergeRequestsFinder.new(current_user, project_id: @project.id).execute.opened.
find_by(source_project: @project, source_branch: @head_ref, target_branch: @start_ref)
@merge_request ||= MergeRequestsFinder.new(current_user, project_id: @project.id).execute.opened
.find_by(source_project: @project, source_branch: @head_ref, target_branch: @start_ref)
end
end
......@@ -6,6 +6,8 @@ class Projects::IssuesController < Projects::ApplicationController
include IssuableCollections
include SpammableActions
include ::EE::Projects::IssuesController
prepend_before_action :authenticate_user!, only: [:new, :export_csv]
before_action :redirect_to_external_issue_tracker, only: [:index, :new]
......@@ -156,13 +158,6 @@ class Projects::IssuesController < Projects::ApplicationController
render_conflict_response
end
def export_csv
ExportCsvWorker.perform_async(@current_user.id, @project.id, filter_params)
index_path = namespace_project_issues_path(@project.namespace, @project)
redirect_to(index_path, notice: "Your CSV export has started. It will be emailed to #{current_user.notification_email} when complete.")
end
def referenced_merge_requests
@merge_requests = @issue.referenced_merge_requests(current_user)
@closed_by_merge_requests = @issue.closed_by_merge_requests(current_user)
......
......@@ -147,8 +147,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController
# Get commits from repository
# or from cache if already merged
@commits = @merge_request.commits
@note_counts = Note.where(commit_id: @commits.map(&:id)).
group(:commit_id).count
@note_counts = Note.where(commit_id: @commits.map(&:id))
.group(:commit_id).count
render json: { html: view_to_html_string('projects/merge_requests/show/_commits') }
end
......@@ -196,9 +196,9 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end
begin
MergeRequests::Conflicts::ResolveService.
new(merge_request).
execute(current_user, params)
MergeRequests::Conflicts::ResolveService
.new(merge_request)
.execute(current_user, params)
flash[:notice] = 'All merge conflicts were resolved. The merge request can now be merged.'
......@@ -621,8 +621,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController
@commits = @merge_request.compare_commits.reverse
@commit = @merge_request.diff_head_commit
@note_counts = Note.where(commit_id: @commits.map(&:id)).
group(:commit_id).count
@note_counts = Note.where(commit_id: @commits.map(&:id))
.group(:commit_id).count
@labels = LabelsFinder.new(current_user, project_id: @project.id).execute
......
......@@ -14,8 +14,8 @@ module Projects
def define_runners_variables
@project_runners = @project.runners.ordered
@assignable_runners = current_user.ci_authorized_runners.
assignable_for(project).ordered.page(params[:page]).per(20)
@assignable_runners = current_user.ci_authorized_runners
.assignable_for(project).ordered.page(params[:page]).per(20)
@shared_runners = Ci::Runner.shared.active
@shared_runners_count = @shared_runners.count(:all)
end
......
......@@ -29,8 +29,8 @@ class Projects::TagsController < Projects::ApplicationController
end
def create
result = Tags::CreateService.new(@project, current_user).
execute(params[:tag_name], params[:ref], params[:message], params[:release_description])
result = Tags::CreateService.new(@project, current_user)
.execute(params[:tag_name], params[:ref], params[:message], params[:release_description])
if result[:status] == :success
@tag = result[:tag]
......
......@@ -151,8 +151,8 @@ class SessionsController < Devise::SessionsController
end
def log_audit_event(user, options = {})
AuditEventService.new(user, user, options).
for_authentication.security_event
AuditEventService.new(user, user, options)
.for_authentication.security_event
end
def log_user_activity(user)
......
......@@ -4,8 +4,8 @@ module Sherlock
def find_transaction
if params[:transaction_id]
@transaction = Gitlab::Sherlock.collection.
find_transaction(params[:transaction_id])
@transaction = Gitlab::Sherlock.collection
.find_transaction(params[:transaction_id])
end
end
end
......
......@@ -106,11 +106,11 @@ class UsersController < ApplicationController
def load_events
# Get user activity feed for projects common for both users
@events = user.recent_events.
merge(projects_for_current_user).
references(:project).
with_associations.
limit_recent(20, params[:offset])
@events = user.recent_events
.merge(projects_for_current_user)
.references(:project)
.with_associations
.limit_recent(20, params[:offset])
end
def load_projects
......
......@@ -33,7 +33,8 @@ class EventsFinder
private
def by_current_user_access(events)
events.merge(ProjectsFinder.new(current_user: current_user).execute).references(:project)
events.merge(ProjectsFinder.new(current_user: current_user).execute)
.joins(:project)
end
def by_action(events)
......
......@@ -8,9 +8,9 @@ class GroupMembersFinder
return group_members unless @group.parent
parents_members = GroupMember.non_request.
where(source_id: @group.ancestors.select(:id)).
where.not(user_id: @group.users.select(:id))
parents_members = GroupMember.non_request
.where(source_id: @group.ancestors.select(:id))
.where.not(user_id: @group.users.select(:id))
wheres = ["members.id IN (#{group_members.select(:id).to_sql})"]
wheres << "members.id IN (#{parents_members.select(:id).to_sql})"
......
......@@ -29,35 +29,69 @@ class GroupProjectsFinder < ProjectsFinder
private
def init_collection
only_owned = options.fetch(:only_owned, false)
only_shared = options.fetch(:only_shared, false)
projects = if current_user
collection_with_user
else
collection_without_user
end
projects = []
union(projects)
end
if current_user
if group.users.include?(current_user)
projects << group.projects unless only_shared
projects << group.shared_projects unless only_owned
def collection_with_user
if group.users.include?(current_user)
if only_shared?
[shared_projects]
elsif only_owned?
[owned_projects]
else
unless only_shared
projects << group.projects.visible_to_user(current_user)
projects << group.projects.public_to_user(current_user)
end
unless only_owned
projects << group.shared_projects.visible_to_user(current_user)
projects << group.shared_projects.public_to_user(current_user)
end
[shared_projects, owned_projects]
end
else
projects << group.projects.public_only unless only_shared
projects << group.shared_projects.public_only unless only_owned
if only_shared?
[shared_projects.public_or_visible_to_user(current_user)]
elsif only_owned?
[owned_projects.public_or_visible_to_user(current_user)]
else
[
owned_projects.public_or_visible_to_user(current_user),
shared_projects.public_or_visible_to_user(current_user)
]
end
end
end
projects
def collection_without_user
if only_shared?
[shared_projects.public_only]
elsif only_owned?
[owned_projects.public_only]
else
[shared_projects.public_only, owned_projects.public_only]
end
end
def union(items)
find_union(items, Project)
if items.one?
items.first
else
find_union(items, Project)
end
end
def only_owned?
options.fetch(:only_owned, false)
end
def only_shared?
options.fetch(:only_shared, false)
end
def owned_projects
group.projects
end
def shared_projects
group.shared_projects
end
end
......@@ -28,34 +28,56 @@ class ProjectsFinder < UnionFinder
end
def execute
items = init_collection
items = items.map do |item|
item = by_ids(item)
item = by_personal(item)
item = by_starred(item)
item = by_trending(item)
item = by_visibilty_level(item)
item = by_tags(item)
item = by_search(item)
by_archived(item)
end
items = union(items)
sort(items)
collection = init_collection
collection = by_ids(collection)
collection = by_personal(collection)
collection = by_starred(collection)
collection = by_trending(collection)
collection = by_visibilty_level(collection)
collection = by_tags(collection)
collection = by_search(collection)
collection = by_archived(collection)
sort(collection)
end
private
def init_collection
projects = []
if current_user
collection_with_user
else
collection_without_user
end
end
if params[:owned].present?
projects << current_user.owned_projects if current_user
def collection_with_user
if owned_projects?
current_user.owned_projects
else
projects << current_user.authorized_projects if current_user
projects << Project.unscoped.public_to_user(current_user) unless params[:non_public].present?
if private_only?
current_user.authorized_projects
else
Project.public_or_visible_to_user(current_user)
end
end
end
# Builds a collection for an anonymous user.
def collection_without_user
if private_only? || owned_projects?
Project.none
else
Project.public_to_user
end
end
def owned_projects?
params[:owned].present?
end
projects
def private_only?
params[:non_public].present?
end
def by_ids(items)
......
......@@ -68,7 +68,7 @@ module ApplicationHelper
end
end
def avatar_icon(user_or_email = nil, size = nil, scale = 2)
def avatar_icon(user_or_email = nil, size = nil, scale = 2, only_path: true)
user =
if user_or_email.is_a?(User)
user_or_email
......@@ -77,7 +77,7 @@ module ApplicationHelper
end
if user
user.avatar_url(size: size) || default_avatar
user.avatar_url(size: size, only_path: only_path) || default_avatar
else
gravatar_icon(user_or_email, size, scale)
end
......
......@@ -8,10 +8,10 @@ module FormHelper
content_tag(:div, class: 'alert alert-danger', id: 'error_explanation') do
content_tag(:h4, headline) <<
content_tag(:ul) do
model.errors.full_messages.
map { |msg| content_tag(:li, msg) }.
join.
html_safe
model.errors.full_messages
.map { |msg| content_tag(:li, msg) }
.join
.html_safe
end
end
end
......
......@@ -194,8 +194,8 @@ module ProjectsHelper
end
def load_pipeline_status(projects)
Gitlab::Cache::Ci::ProjectPipelineStatus.
load_in_batch_for_projects(projects)
Gitlab::Cache::Ci::ProjectPipelineStatus
.load_in_batch_for_projects(projects)
end
private
......
......@@ -105,8 +105,8 @@ module SearchHelper
# Autocomplete results for the current user's projects
def projects_autocomplete(term, limit = 5)
current_user.authorized_projects.search_by_title(term).
sorted_by_stars.non_archived.limit(limit).map do |p|
current_user.authorized_projects.search_by_title(term)
.sorted_by_stars.non_archived.limit(limit).map do |p|
{
category: "Projects",
id: p.id,
......
......@@ -6,8 +6,8 @@ module WikiHelper
# Returns a String composed of the capitalized name of each directory and the
# capitalized name of the page itself.
def breadcrumb(page_slug)
page_slug.split('/').
map { |dir_or_page| WikiPage.unhyphenize(dir_or_page).capitalize }.
join(' / ')
page_slug.split('/')
.map { |dir_or_page| WikiPage.unhyphenize(dir_or_page).capitalize }
.join(' / ')
end
end
......@@ -19,9 +19,9 @@ class AwardEmoji < ActiveRecord::Base
class << self
def votes_for_collection(ids, type)
select('name', 'awardable_id', 'COUNT(*) as count').
where('name IN (?) AND awardable_type = ? AND awardable_id IN (?)', [DOWNVOTE_NAME, UPVOTE_NAME], type, ids).
group('name', 'awardable_id')
select('name', 'awardable_id', 'COUNT(*) as count')
.where('name IN (?) AND awardable_type = ? AND awardable_id IN (?)', [DOWNVOTE_NAME, UPVOTE_NAME], type, ids)
.group('name', 'awardable_id')
end
end
......
......@@ -68,8 +68,8 @@ class Burndown
def milestone_closed_issues
@milestone_closed_issues ||=
@milestone.issues.select("closed_at, weight, state").
where("state IN ('reopened', 'closed')").
order("closed_at ASC")
@milestone.issues.select("closed_at, weight, state")
.where("state IN ('reopened', 'closed')")
.order("closed_at ASC")
end
end
......@@ -179,8 +179,8 @@ module Ci
end
def stages_names
statuses.order(:stage_idx).distinct.
pluck(:stage, :stage_idx).map(&:first)
statuses.order(:stage_idx).distinct
.pluck(:stage, :stage_idx).map(&:first)
end
def legacy_stage(name)
......
......@@ -31,8 +31,8 @@ module Ci
scope :assignable_for, ->(project) do
# FIXME: That `to_sql` is needed to workaround a weird Rails bug.
# Without that, placeholders would miss one and couldn't match.
where(locked: false).
where.not("id IN (#{project.runners.select(:id).to_sql})").specific
where(locked: false)
.where.not("id IN (#{project.runners.select(:id).to_sql})").specific
end
validate :tag_constraints
......
......@@ -36,23 +36,28 @@ module Approvable
#
def number_of_potential_approvers
has_access = ['access_level > ?', Member::REPORTER]
users_with_access = { id: project.project_authorizations.where(has_access).select(:user_id) }
all_approvers = all_approvers_including_groups
wheres = [
"id IN (#{project.project_authorizations.where(has_access).select(:user_id).to_sql})"
]
users_relation = User.active.where.not(id: approvals.select(:user_id))
users_relation = users_relation.where.not(id: author.id) if author
# This is an optimisation for large instances. Instead of getting the
# count of all users who meet the conditions in a single query, which
# produces a slow query plan, we get the union of all users with access
# and all users in the approvers list, and count them.
if all_approvers.any?
wheres << "id IN (#{all_approvers.map(&:id).join(', ')})"
end
users = User
.active
.where("(#{wheres.join(' OR ')}) AND id NOT IN (#{approvals.select(:user_id).to_sql})")
specific_approvers = { id: all_approvers.map(&:id) }
users = users.where.not(id: author.id) if author
union = Gitlab::SQL::Union.new([
users_relation.where(users_with_access).select(:id),
users_relation.where(specific_approvers).select(:id)
])
users.count
User.from("(#{union.to_sql}) subquery").count
else
users_relation.where(users_with_access).count
end
end
# Users in the list of approvers who have not already approved this MR.
......
......@@ -164,9 +164,9 @@ module Issuable
#
milestones_due_date = 'MIN(milestones.due_date)'
order_milestone_due_asc.
order_labels_priority(excluded_labels: excluded_labels, extra_select_columns: [milestones_due_date]).
reorder(Gitlab::Database.nulls_last_order(milestones_due_date, 'ASC'),
order_milestone_due_asc
.order_labels_priority(excluded_labels: excluded_labels, extra_select_columns: [milestones_due_date])
.reorder(Gitlab::Database.nulls_last_order(milestones_due_date, 'ASC'),
Gitlab::Database.nulls_last_order('highest_priority', 'ASC'))
end
......@@ -185,9 +185,9 @@ module Issuable
"(#{highest_priority}) AS highest_priority"
] + extra_select_columns
select(select_columns.join(', ')).
group(arel_table[:id]).
reorder(Gitlab::Database.nulls_last_order('highest_priority', 'ASC'))
select(select_columns.join(', '))
.group(arel_table[:id])
.reorder(Gitlab::Database.nulls_last_order('highest_priority', 'ASC'))
end
def with_label(title, sort = nil)
......
......@@ -18,10 +18,10 @@ module RelativePositioning
prev_pos = nil
if self.relative_position
prev_pos = self.class.
in_projects(project.id).
where('relative_position < ?', self.relative_position).
maximum(:relative_position)
prev_pos = self.class
.in_projects(project.id)
.where('relative_position < ?', self.relative_position)
.maximum(:relative_position)
end
prev_pos
......@@ -31,10 +31,10 @@ module RelativePositioning
next_pos = nil
if self.relative_position
next_pos = self.class.
in_projects(project.id).
where('relative_position > ?', self.relative_position).
minimum(:relative_position)
next_pos = self.class
.in_projects(project.id)
.where('relative_position > ?', self.relative_position)
.minimum(:relative_position)
end
next_pos
......
......@@ -39,12 +39,12 @@ module Sortable
private
def highest_label_priority(target_type_column: nil, target_type: nil, target_column:, project_column:, excluded_labels: [])
query = Label.select(LabelPriority.arel_table[:priority].minimum).
left_join_priorities.
joins(:label_links).
where("label_priorities.project_id = #{project_column}").
where("label_links.target_id = #{target_column}").
reorder(nil)
query = Label.select(LabelPriority.arel_table[:priority].minimum)
.left_join_priorities
.joins(:label_links)
.where("label_priorities.project_id = #{project_column}")
.where("label_links.target_id = #{target_column}")
.reorder(nil)
query =
if target_type_column
......
......@@ -27,16 +27,16 @@ module Subscribable
end
def subscribers(project)
subscriptions_available(project).
where(subscribed: true).
map(&:user)
subscriptions_available(project)
.where(subscribed: true)
.map(&:user)
end
def toggle_subscription(user, project = nil)
unsubscribe_from_other_levels(user, project)
find_or_initialize_subscription(user, project).
update(subscribed: !subscribed?(user, project))
find_or_initialize_subscription(user, project)
.update(subscribed: !subscribed?(user, project))
end
def subscribe(user, project = nil)
......@@ -69,14 +69,14 @@ module Subscribable
end
def find_or_initialize_subscription(user, project)
subscriptions.
find_or_initialize_by(user_id: user.id, project_id: project.try(:id))
subscriptions
.find_or_initialize_by(user_id: user.id, project_id: project.try(:id))
end
def subscriptions_available(project)
t = Subscription.arel_table
subscriptions.
where(t[:project_id].eq(nil).or(t[:project_id].eq(project.try(:id))))
subscriptions
.where(t[:project_id].eq(nil).or(t[:project_id].eq(project.try(:id))))
end
end
......@@ -58,10 +58,10 @@ class Deployment < ActiveRecord::Base
def update_merge_request_metrics!
return unless environment.update_merge_request_metrics?
merge_requests = project.merge_requests.
joins(:metrics).
where(target_branch: self.ref, merge_request_metrics: { first_deployed_to_production_at: nil }).
where("merge_request_metrics.merged_at <= ?", self.created_at)
merge_requests = project.merge_requests
.joins(:metrics)
.where(target_branch: self.ref, merge_request_metrics: { first_deployed_to_production_at: nil })
.where("merge_request_metrics.merged_at <= ?", self.created_at)
if previous_deployment
merge_requests = merge_requests.where("merge_request_metrics.merged_at >= ?", previous_deployment.created_at)
......@@ -76,17 +76,17 @@ class Deployment < ActiveRecord::Base
merge_requests.map(&:id)
end
MergeRequest::Metrics.
where(merge_request_id: merge_request_ids, first_deployed_to_production_at: nil).
update_all(first_deployed_to_production_at: self.created_at)
MergeRequest::Metrics
.where(merge_request_id: merge_request_ids, first_deployed_to_production_at: nil)
.update_all(first_deployed_to_production_at: self.created_at)
end
def previous_deployment
@previous_deployment ||=
project.deployments.joins(:environment).
where(environments: { name: self.environment.name }, ref: self.ref).
where.not(id: self.id).
take
project.deployments.joins(:environment)
.where(environments: { name: self.environment.name }, ref: self.ref)
.where.not(id: self.id)
.take
end
def stop_action
......
......@@ -8,32 +8,135 @@ module EE
prepended do
include IgnorableColumn
include Elastic::ProjectsSearch
prepend GeoAwareAvatar
prepend ImportStatusStateMachine
ignore_column :sync_time
before_validation :mark_remote_mirrors_for_removal
after_save :create_mirror_data, if: ->(project) { project.mirror? && project.mirror_changed? }
after_save :destroy_mirror_data, if: ->(project) { !project.mirror? && project.mirror_changed? }
after_update :remove_mirror_repository_reference,
if: ->(project) { project.mirror? && project.import_url_updated? }
belongs_to :mirror_user, foreign_key: 'mirror_user_id', class_name: 'User'
has_one :mirror_data, dependent: :delete, autosave: true, class_name: 'ProjectMirrorData'
has_one :push_rule, dependent: :destroy
has_one :index_status, dependent: :destroy
has_one :jenkins_service, dependent: :destroy
has_one :jenkins_deprecated_service, dependent: :destroy
has_many :approvers, as: :target, dependent: :destroy
has_many :approver_groups, as: :target, dependent: :destroy
has_many :audit_events, as: :entity, dependent: :destroy
has_many :remote_mirrors, inverse_of: :project, dependent: :destroy
has_many :path_locks, dependent: :destroy
scope :with_shared_runners_limit_enabled, -> { with_shared_runners.non_public_only }
scope :mirrors_to_sync, -> do
mirror.joins(:mirror_data).where("next_execution_timestamp <= ? AND import_status NOT IN ('scheduled', 'started')", Time.now).
order_by(:next_execution_timestamp).limit(::Gitlab::Mirror.available_capacity)
mirror.joins(:mirror_data).where("next_execution_timestamp <= ? AND import_status NOT IN ('scheduled', 'started')", Time.now)
.order_by(:next_execution_timestamp).limit(::Gitlab::Mirror.available_capacity)
end
scope :stuck_mirrors, -> do
mirror.joins(:mirror_data).
where("(import_status = 'started' AND project_mirror_data.last_update_started_at < :limit) OR (import_status = 'scheduled' AND project_mirror_data.last_update_scheduled_at < :limit)",
mirror.joins(:mirror_data)
.where("(import_status = 'started' AND project_mirror_data.last_update_started_at < :limit) OR (import_status = 'scheduled' AND project_mirror_data.last_update_scheduled_at < :limit)",
{ limit: 20.minutes.ago })
end
scope :mirror, -> { where(mirror: true) }
scope :with_remote_mirrors, -> { joins(:remote_mirrors).where(remote_mirrors: { enabled: true }).distinct }
scope :with_wiki_enabled, -> { with_feature_enabled(:wiki) }
delegate :shared_runners_minutes, :shared_runners_seconds, :shared_runners_seconds_last_reset,
to: :statistics, allow_nil: true
delegate :actual_shared_runners_minutes_limit,
:shared_runners_minutes_used?, to: :namespace
validates :repository_size_limit,
numericality: { only_integer: true, greater_than_or_equal_to: 0, allow_nil: true }
validates :approvals_before_merge, numericality: true, allow_blank: true
accepts_nested_attributes_for :remote_mirrors,
allow_destroy: true,
reject_if: ->(attrs) { attrs[:id].blank? && attrs[:url].blank? }
with_options if: :mirror? do |project|
project.validates :import_url, presence: true
project.validates :mirror_user, presence: true
end
end
module ClassMethods
def search_by_visibility(level)
where(visibility_level: ::Gitlab::VisibilityLevel.string_options[level])
end
end
def mirror_updated?
mirror? && self.mirror_last_update_at
end
def updating_mirror?
return false unless mirror? && !empty_repo?
return true if import_in_progress?
self.mirror_data.next_execution_timestamp < Time.now
end
def mirror_last_update_status
return unless mirror_updated?
if self.mirror_last_update_at == self.mirror_last_successful_update_at
:success
else
:failed
end
end
def mirror_last_update_success?
mirror_last_update_status == :success
end
def mirror_last_update_failed?
mirror_last_update_status == :failed
end
def mirror_ever_updated_successfully?
mirror_updated? && self.mirror_last_successful_update_at
end
def has_remote_mirror?
remote_mirrors.enabled.exists?
end
def updating_remote_mirror?
remote_mirrors.enabled.started.exists?
end
def update_remote_mirrors
remote_mirrors.each(&:sync)
end
def mark_stuck_remote_mirrors_as_failed!
remote_mirrors.stuck.update_all(
update_status: :failed,
last_error: 'The remote mirror took to long to complete.',
last_update_at: Time.now
)
end
def fetch_mirror
return unless mirror?
repository.fetch_upstream(self.import_url)
end
def shared_runners_available?
......@@ -84,6 +187,150 @@ module EE
end
end
def cache_has_external_issue_tracker
super unless ::Gitlab::Geo.secondary?
end
def cache_has_external_wiki
super unless ::Gitlab::Geo.secondary?
end
def execute_hooks(data, hooks_scope = :push_hooks)
super
if group
group.hooks.send(hooks_scope).each do |hook|
hook.async_execute(data, hooks_scope.to_s)
end
end
end
# No need to have a Kerberos Web url. Kerberos URL will be used only to
# clone
def kerberos_url_to_repo
"#{::Gitlab.config.build_gitlab_kerberos_url + ::Gitlab::Application.routes.url_helpers.namespace_project_path(self.namespace, self)}.git"
end
def group_ldap_synced?
if group
group.ldap_synced?
else
false
end
end
def reference_issue_tracker?
default_issues_tracker? || jira_tracker_active?
end
def approver_ids=(value)
value.split(",").map(&:strip).each do |user_id|
approvers.find_or_create_by(user_id: user_id, target_id: id)
end
end
def approver_group_ids=(value)
value.split(",").map(&:strip).each do |group_id|
approver_groups.find_or_initialize_by(group_id: group_id, target_id: id)
end
end
def find_path_lock(path, exact_match: false, downstream: false)
@path_lock_finder ||= ::Gitlab::PathLocksFinder.new(self)
@path_lock_finder.find(path, exact_match: exact_match, downstream: downstream)
end
def merge_method
if self.merge_requests_ff_only_enabled
:ff
elsif self.merge_requests_rebase_enabled
:rebase_merge
else
:merge
end
end
def merge_method=(method)
case method.to_s
when "ff"
self.merge_requests_ff_only_enabled = true
self.merge_requests_rebase_enabled = true
when "rebase_merge"
self.merge_requests_ff_only_enabled = false
self.merge_requests_rebase_enabled = true
when "merge"
self.merge_requests_ff_only_enabled = false
self.merge_requests_rebase_enabled = false
end
end
def ff_merge_must_be_possible?
self.merge_requests_ff_only_enabled || self.merge_requests_rebase_enabled
end
def import_url_updated?
# check if import_url has been updated and it's not just the first assignment
import_url_changed? && changes['import_url'].first
end
def remove_mirror_repository_reference
repository.remove_remote(Repository::MIRROR_REMOTE)
end
def import_url_availability
if remote_mirrors.find_by(url: import_url)
errors.add(:import_url, 'is already in use by a remote mirror')
end
end
def mark_remote_mirrors_for_removal
remote_mirrors.each(&:mark_for_delete_if_blank_url)
end
def change_repository_storage(new_repository_storage_key)
return if repository_read_only?
return if repository_storage == new_repository_storage_key
raise ArgumentError unless ::Gitlab.config.repositories.storages.keys.include?(new_repository_storage_key)
run_after_commit { ProjectUpdateRepositoryStorageWorker.perform_async(id, new_repository_storage_key) }
self.repository_read_only = true
end
def repository_and_lfs_size
statistics.total_repository_size
end
def above_size_limit?
return false unless size_limit_enabled?
repository_and_lfs_size > actual_size_limit
end
def size_to_remove
repository_and_lfs_size - actual_size_limit
end
def actual_size_limit
return namespace.actual_size_limit if repository_size_limit.nil?
repository_size_limit
end
def size_limit_enabled?
actual_size_limit != 0
end
def changes_will_exceed_size_limit?(size_in_bytes)
size_limit_enabled? &&
(size_in_bytes > actual_size_limit ||
size_in_bytes + repository_and_lfs_size > actual_size_limit)
end
def remove_import_data
super unless mirror?
end
private
def licensed_feature_available?(feature)
......
module EE
module Project
module ImportStatusStateMachine
extend ActiveSupport::Concern
included do
state_machine :import_status, initial: :none do
before_transition [:none, :finished, :failed] => :scheduled do |project, _|
project.mirror_data&.last_update_scheduled_at = Time.now
end
before_transition scheduled: :started do |project, _|
project.mirror_data&.last_update_started_at = Time.now
end
before_transition scheduled: :failed do |project, _|
if project.mirror?
timestamp = Time.now
project.mirror_last_update_at = timestamp
project.mirror_data.next_execution_timestamp = timestamp
end
end
after_transition [:scheduled, :started] => [:finished, :failed] do |project, _|
::Gitlab::Mirror.decrement_capacity(project.id) if project.mirror?
end
before_transition started: :failed do |project, _|
if project.mirror?
project.mirror_last_update_at = Time.now
mirror_data = project.mirror_data
mirror_data.increment_retry_count!
mirror_data.set_next_execution_timestamp!
end
end
before_transition started: :finished do |project, _|
if project.mirror?
timestamp = Time.now
project.mirror_last_update_at = timestamp
project.mirror_last_successful_update_at = timestamp
mirror_data = project.mirror_data
mirror_data.reset_retry_count!
mirror_data.set_next_execution_timestamp!
end
if current_application_settings.elasticsearch_indexing?
ElasticCommitIndexerWorker.perform_async(project.id)
end
end
after_transition [:finished, :failed] => [:scheduled, :started] do |project, _|
::Gitlab::Mirror.increment_capacity(project.id) if project.mirror?
end
end
end
end
end
end
......@@ -56,6 +56,27 @@ module EE
admin? || auditor?
end
def access_level
if auditor?
:auditor
else
super
end
end
def access_level=(new_level)
new_level = new_level.to_s
return unless %w(admin auditor regular).include?(new_level)
self.admin = (new_level == 'admin')
self.auditor = (new_level == 'auditor')
end
# Does the user have access to all private groups & projects?
def has_full_private_access?
admin_or_auditor?
end
def remember_me!
return if ::Gitlab::Geo.secondary?
super
......
......@@ -40,9 +40,9 @@ class Environment < ActiveRecord::Base
scope :stopped, -> { with_state(:stopped) }
scope :order_by_last_deployed_at, -> do
max_deployment_id_sql =
Deployment.select(Deployment.arel_table[:id].maximum).
where(Deployment.arel_table[:environment_id].eq(arel_table[:id])).
to_sql
Deployment.select(Deployment.arel_table[:id].maximum)
.where(Deployment.arel_table[:environment_id].eq(arel_table[:id]))
.to_sql
order(Gitlab::Database.nulls_first_order("(#{max_deployment_id_sql})", 'ASC'))
end
......
......@@ -382,9 +382,9 @@ class Event < ActiveRecord::Base
# At this point it's possible for multiple threads/processes to try to
# update the project. Only one query should actually perform the update,
# hence we add the extra WHERE clause for last_activity_at.
Project.unscoped.where(id: project_id).
where('last_activity_at <= ?', RESET_PROJECT_ACTIVITY_INTERVAL.ago).
update_all(last_activity_at: created_at)
Project.unscoped.where(id: project_id)
.where('last_activity_at <= ?', RESET_PROJECT_ACTIVITY_INTERVAL.ago)
.update_all(last_activity_at: created_at)
end
def authored_by?(user)
......@@ -398,7 +398,7 @@ class Event < ActiveRecord::Base
end
def set_last_repository_updated_at
Project.unscoped.where(id: project_id).
update_all(last_repository_updated_at: created_at)
Project.unscoped.where(id: project_id)
.update_all(last_repository_updated_at: created_at)
end
end
......@@ -250,8 +250,8 @@ class Group < Namespace
end
def refresh_members_authorized_projects
UserProjectAccessChangedService.new(user_ids_for_project_authorizations).
execute
UserProjectAccessChangedService.new(user_ids_for_project_authorizations)
.execute
end
def user_ids_for_project_authorizations
......@@ -269,10 +269,10 @@ class Group < Namespace
def max_member_access_for_user(user)
return GroupMember::OWNER if user.admin?
members_with_parents.
where(user_id: user).
reorder(access_level: :desc).
first&.
members_with_parents
.where(user_id: user)
.reorder(access_level: :desc)
.first&.
access_level || GroupMember::NO_ACCESS
end
......
......@@ -136,8 +136,8 @@ class Issue < ActiveRecord::Base
end
def self.order_by_position_and_priority
order_labels_priority.
reorder(Gitlab::Database.nulls_last_order('relative_position', 'ASC'),
order_labels_priority
.reorder(Gitlab::Database.nulls_last_order('relative_position', 'ASC'),
Gitlab::Database.nulls_last_order('highest_priority', 'ASC'),
"id DESC")
end
......
......@@ -17,9 +17,9 @@ class IssueCollection
# Given all the issue projects we get a list of projects that the current
# user has at least reporter access to.
projects_with_reporter_access = user.
projects_with_reporter_access_limited_to(project_ids).
pluck(:id)
projects_with_reporter_access = user
.projects_with_reporter_access_limited_to(project_ids)
.pluck(:id)
collection.select do |issue|
if projects_with_reporter_access.include?(issue.project_id)
......
......@@ -46,9 +46,9 @@ class Label < ActiveRecord::Base
labels = Label.arel_table
priorities = LabelPriority.arel_table
label_priorities = labels.join(priorities, Arel::Nodes::OuterJoin).
on(labels[:id].eq(priorities[:label_id]).and(priorities[:project_id].eq(project.id))).
join_sources
label_priorities = labels.join(priorities, Arel::Nodes::OuterJoin)
.on(labels[:id].eq(priorities[:label_id]).and(priorities[:project_id].eq(project.id)))
.join_sources
joins(label_priorities).where(priorities[:priority].eq(nil))
end
......@@ -57,9 +57,9 @@ class Label < ActiveRecord::Base
labels = Label.arel_table
priorities = LabelPriority.arel_table
label_priorities = labels.join(priorities, Arel::Nodes::OuterJoin).
on(labels[:id].eq(priorities[:label_id])).
join_sources
label_priorities = labels.join(priorities, Arel::Nodes::OuterJoin)
.on(labels[:id].eq(priorities[:label_id]))
.join_sources
joins(label_priorities)
end
......
......@@ -9,6 +9,7 @@ class License < ActiveRecord::Base
OBJECT_STORAGE_FEATURE = 'GitLab_ObjectStorage'.freeze
ELASTIC_SEARCH_FEATURE = 'GitLab_ElasticSearch'.freeze
RELATED_ISSUES_FEATURE = 'RelatedIssues'.freeze
EXPORT_ISSUES_FEATURE = 'GitLab_ExportIssues'.freeze
FEATURE_CODES = {
geo: GEO_FEATURE,
......@@ -19,7 +20,8 @@ class License < ActiveRecord::Base
related_issues: RELATED_ISSUES_FEATURE,
# Features that make sense to Namespace:
deploy_board: DEPLOY_BOARD_FEATURE,
file_lock: FILE_LOCK_FEATURE
file_lock: FILE_LOCK_FEATURE,
export_issues: EXPORT_ISSUES_FEATURE
}.freeze
STARTER_PLAN = 'starter'.freeze
......@@ -29,7 +31,8 @@ class License < ActiveRecord::Base
EES_FEATURES = [
{ ELASTIC_SEARCH_FEATURE => 1 },
{ RELATED_ISSUES_FEATURE => 1 }
{ RELATED_ISSUES_FEATURE => 1 },
{ EXPORT_ISSUES_FEATURE => 1 }
].freeze
EEP_FEATURES = [
......@@ -61,7 +64,8 @@ class License < ActiveRecord::Base
{ GEO_FEATURE => 1 },
{ AUDITOR_USER_FEATURE => 1 },
{ SERVICE_DESK_FEATURE => 1 },
{ OBJECT_STORAGE_FEATURE => 1 }
{ OBJECT_STORAGE_FEATURE => 1 },
{ EXPORT_ISSUES_FEATURE => 1 }
].freeze
FEATURES_BY_PLAN = {
......@@ -131,6 +135,12 @@ class License < ActiveRecord::Base
self.data = file.read
end
def md5
normalized_data = self.data.gsub("\r\n", "\n").gsub(/\n+$/, '') + "\n"
Digest::MD5.hexdigest(normalized_data)
end
def license
return nil unless self.data
......
......@@ -100,9 +100,9 @@ class Member < ActiveRecord::Base
users = User.arel_table
members = Member.arel_table
member_users = members.join(users, Arel::Nodes::OuterJoin).
on(members[:user_id].eq(users[:id])).
join_sources
member_users = members.join(users, Arel::Nodes::OuterJoin)
.on(members[:user_id].eq(users[:id]))
.join_sources
joins(member_users)
end
......
......@@ -603,8 +603,8 @@ class MergeRequest < ActiveRecord::Base
messages = [title, description]
messages.concat(commits.map(&:safe_message)) if merge_request_diff
Gitlab::ClosingIssueExtractor.new(project, current_user).
closed_by_message(messages.join("\n"))
Gitlab::ClosingIssueExtractor.new(project, current_user)
.closed_by_message(messages.join("\n"))
else
[]
end
......
......@@ -7,9 +7,9 @@ class MergeRequestsClosingIssues < ActiveRecord::Base
class << self
def count_for_collection(ids)
group(:issue_id).
where(issue_id: ids).
pluck('issue_id', 'COUNT(*) as count')
group(:issue_id)
.where(issue_id: ids)
.pluck('issue_id', 'COUNT(*) as count')
end
end
end
......@@ -100,11 +100,11 @@ class Milestone < ActiveRecord::Base
if Gitlab::Database.postgresql?
rel.order(:project_id, :due_date).select('DISTINCT ON (project_id) id')
else
rel.
group(:project_id).
having('due_date = MIN(due_date)').
pluck(:id, :project_id, :due_date).
map(&:first)
rel
.group(:project_id)
.having('due_date = MIN(due_date)')
.pluck(:id, :project_id, :due_date)
.map(&:first)
end
end
......@@ -166,6 +166,41 @@ class Milestone < ActiveRecord::Base
write_attribute(:title, sanitize_title(value)) if value.present?
end
<<<<<<< HEAD
=======
# Sorts the issues for the given IDs.
#
# This method runs a single SQL query using a CASE statement to update the
# position of all issues in the current milestone (scoped to the list of IDs).
#
# Given the ids [10, 20, 30] this method produces a SQL query something like
# the following:
#
# UPDATE issues
# SET position = CASE
# WHEN id = 10 THEN 1
# WHEN id = 20 THEN 2
# WHEN id = 30 THEN 3
# ELSE position
# END
# WHERE id IN (10, 20, 30);
#
# This method expects that the IDs given in `ids` are already Fixnums.
def sort_issues(ids)
pairs = []
ids.each_with_index do |id, index|
pairs << id
pairs << index + 1
end
conditions = 'WHEN id = ? THEN ? ' * ids.length
issues.where(id: ids)
.update_all(["position = CASE #{conditions} ELSE position END", *pairs])
end
>>>>>>> 0355488d4ac038c793dad96da2506b218b44f4a6
private
def milestone_format_reference(format = :iid)
......
......@@ -186,16 +186,16 @@ class Namespace < ActiveRecord::Base
def ancestors
return self.class.none unless parent_id
Gitlab::GroupHierarchy.
new(self.class.where(id: parent_id)).
base_and_ancestors
Gitlab::GroupHierarchy
.new(self.class.where(id: parent_id))
.base_and_ancestors
end
# Returns all the descendants of the current namespace.
def descendants
Gitlab::GroupHierarchy.
new(self.class.where(parent_id: id)).
base_and_descendants
Gitlab::GroupHierarchy
.new(self.class.where(parent_id: id))
.base_and_descendants
end
def user_ids_for_project_authorizations
......@@ -258,10 +258,10 @@ class Namespace < ActiveRecord::Base
end
def refresh_access_of_projects_invited_groups
Group.
joins(project_group_links: :project).
where(projects: { namespace_id: id }).
find_each(&:refresh_members_authorized_projects)
Group
.joins(project_group_links: :project)
.where(projects: { namespace_id: id })
.find_each(&:refresh_members_authorized_projects)
end
def remove_exports!
......
......@@ -139,9 +139,9 @@ class Note < ActiveRecord::Base
end
def count_for_collection(ids, type)
user.select('noteable_id', 'COUNT(*) as count').
group(:noteable_id).
where(noteable_type: type, noteable_id: ids)
user.select('noteable_id', 'COUNT(*) as count')
.group(:noteable_id)
.where(noteable_type: type, noteable_id: ids)
end
end
......
This diff is collapsed.
......@@ -7,9 +7,9 @@ class ProjectAuthorization < ActiveRecord::Base
validates :user, uniqueness: { scope: [:project, :access_level] }, presence: true
def self.select_from_union(union)
select(['project_id', 'MAX(access_level) AS access_level']).
from("(#{union.to_sql}) #{ProjectAuthorization.table_name}").
group(:project_id)
select(['project_id', 'MAX(access_level) AS access_level'])
.from("(#{union.to_sql}) #{ProjectAuthorization.table_name}")
.group(:project_id)
end
def self.insert_authorizations(rows, per_batch = 1000)
......
......@@ -27,6 +27,13 @@ class ProjectFeature < ActiveRecord::Base
"#{feature}_access_level".to_sym
end
def quoted_access_level_column(feature)
attribute = connection.quote_column_name(access_level_attribute(feature))
table = connection.quote_table_name(table_name)
"#{table}.#{attribute}"
end
end
# Default scopes force us to unscope here since a service may need to check
......
......@@ -20,8 +20,8 @@ class MattermostSlashCommandsService < SlashCommandsService
end
def configure(user, params)
token = Mattermost::Command.new(user).
create(command(params))
token = Mattermost::Command.new(user)
.create(command(params))
update(active: true, token: token) if token
rescue Mattermost::Error => e
......
......@@ -174,10 +174,10 @@ class ProjectTeam
return access if user_ids.empty?
users_access = project.project_authorizations.
where(user: user_ids).
group(:user_id).
maximum(:access_level)
users_access = project.project_authorizations
.where(user: user_ids)
.group(:user_id)
.maximum(:access_level)
access.merge!(users_access)
......
......@@ -248,11 +248,11 @@ class Repository
cache.fetch(:"diverging_commit_counts_#{branch.name}") do
# Rugged seems to throw a `ReferenceError` when given branch_names rather
# than SHA-1 hashes
number_commits_behind = raw_repository.
count_commits_between(branch.dereferenced_target.sha, root_ref_hash)
number_commits_behind = raw_repository
.count_commits_between(branch.dereferenced_target.sha, root_ref_hash)
number_commits_ahead = raw_repository.
count_commits_between(root_ref_hash, branch.dereferenced_target.sha)
number_commits_ahead = raw_repository
.count_commits_between(root_ref_hash, branch.dereferenced_target.sha)
{ behind: number_commits_behind, ahead: number_commits_ahead }
end
......
......@@ -70,9 +70,9 @@ class Todo < ActiveRecord::Base
highest_priority = highest_label_priority(params).to_sql
select("#{table_name}.*, (#{highest_priority}) AS highest_priority").
order(Gitlab::Database.nulls_last_order('highest_priority', 'ASC')).
order('todos.created_at')
select("#{table_name}.*, (#{highest_priority}) AS highest_priority")
.order(Gitlab::Database.nulls_last_order('highest_priority', 'ASC'))
.order('todos.created_at')
end
end
......
......@@ -241,13 +241,13 @@ class User < ActiveRecord::Base
scope :order_oldest_sign_in, -> { reorder(Gitlab::Database.nulls_last_order('last_sign_in_at', 'ASC')) }
def self.with_two_factor
joins("LEFT OUTER JOIN u2f_registrations AS u2f ON u2f.user_id = users.id").
where("u2f.id IS NOT NULL OR otp_required_for_login = ?", true).distinct(arel_table[:id])
joins("LEFT OUTER JOIN u2f_registrations AS u2f ON u2f.user_id = users.id")
.where("u2f.id IS NOT NULL OR otp_required_for_login = ?", true).distinct(arel_table[:id])
end
def self.without_two_factor
joins("LEFT OUTER JOIN u2f_registrations AS u2f ON u2f.user_id = users.id").
where("u2f.id IS NULL AND otp_required_for_login = ?", false)
joins("LEFT OUTER JOIN u2f_registrations AS u2f ON u2f.user_id = users.id")
.where("u2f.id IS NULL AND otp_required_for_login = ?", false)
end
#
......@@ -322,9 +322,9 @@ class User < ActiveRecord::Base
pattern = "%#{query}%"
where(
table[:name].matches(pattern).
or(table[:email].matches(pattern)).
or(table[:username].matches(pattern))
table[:name].matches(pattern)
.or(table[:email].matches(pattern))
.or(table[:username].matches(pattern))
)
end
......@@ -339,10 +339,10 @@ class User < ActiveRecord::Base
matched_by_emails_user_ids = email_table.project(email_table[:user_id]).where(email_table[:email].matches(pattern))
where(
table[:name].matches(pattern).
or(table[:email].matches(pattern)).
or(table[:username].matches(pattern)).
or(table[:id].in(matched_by_emails_user_ids))
table[:name].matches(pattern)
.or(table[:email].matches(pattern))
.or(table[:username].matches(pattern))
.or(table[:id].in(matched_by_emails_user_ids))
)
end
......@@ -530,8 +530,8 @@ class User < ActiveRecord::Base
# Returns the groups a user has access to
def authorized_groups
union = Gitlab::SQL::Union.
new([groups.select(:id), authorized_projects.select(:namespace_id)])
union = Gitlab::SQL::Union
.new([groups.select(:id), authorized_projects.select(:namespace_id)])
Group.where("namespaces.id IN (#{union.to_sql})")
end
......@@ -560,8 +560,8 @@ class User < ActiveRecord::Base
projects = super()
if min_access_level
projects = projects.
where('project_authorizations.access_level >= ?', min_access_level)
projects = projects
.where('project_authorizations.access_level >= ?', min_access_level)
end
projects
......@@ -646,9 +646,9 @@ class User < ActiveRecord::Base
next unless project
if project.repository.branch_exists?(event.branch_name)
merge_requests = MergeRequest.where("created_at >= ?", event.created_at).
where(source_project_id: project.id,
source_branch: event.branch_name)
merge_requests = MergeRequest.where("created_at >= ?", event.created_at)
.where(source_project_id: project.id,
source_branch: event.branch_name)
merge_requests.empty?
end
end
......@@ -863,8 +863,8 @@ class User < ActiveRecord::Base
def toggle_star(project)
UsersStarProject.transaction do
user_star_project = users_star_projects.
where(project: project, user: self).lock(true).first
user_star_project = users_star_projects
.where(project: project, user: self).lock(true).first
if user_star_project
user_star_project.destroy
......@@ -900,11 +900,11 @@ class User < ActiveRecord::Base
# ms on a database with a similar size to GitLab.com's database. On the other
# hand, using a subquery means we can get the exact same data in about 40 ms.
def contributed_projects
events = Event.select(:project_id).
contributions.where(author_id: self).
where("created_at > ?", Time.now - 1.year).
uniq.
reorder(nil)
events = Event.select(:project_id)
.contributions.where(author_id: self)
.where("created_at > ?", Time.now - 1.year)
.uniq
.reorder(nil)
Project.where(id: events)
end
......@@ -915,9 +915,9 @@ class User < ActiveRecord::Base
def ci_authorized_runners
@ci_authorized_runners ||= begin
runner_ids = Ci::RunnerProject.
where("ci_runner_projects.project_id IN (#{ci_projects_union.to_sql})").
select(:runner_id)
runner_ids = Ci::RunnerProject
.where("ci_runner_projects.project_id IN (#{ci_projects_union.to_sql})")
.select(:runner_id)
Ci::Runner.specific.where(id: runner_ids)
end
end
......@@ -1003,8 +1003,6 @@ class User < ActiveRecord::Base
def access_level
if admin?
:admin
elsif auditor?
:auditor
else
:regular
end
......@@ -1012,10 +1010,14 @@ class User < ActiveRecord::Base
def access_level=(new_level)
new_level = new_level.to_s
return unless %w(admin auditor regular).include?(new_level)
return unless %w(admin regular).include?(new_level)
self.admin = (new_level == 'admin')
self.auditor = (new_level == 'auditor')
end
# Does the user have access to all private groups & projects?
def has_full_private_access?
admin?
end
def update_two_factor_requirement
......
......@@ -22,16 +22,16 @@ class WikiPage
def self.group_by_directory(pages)
return [] if pages.blank?
pages.sort_by { |page| [page.directory, page.slug] }.
group_by(&:directory).
map do |dir, pages|
pages.sort_by { |page| [page.directory, page.slug] }
.group_by(&:directory)
.map do |dir, pages|
if dir.present?
WikiDirectory.new(dir, pages)
else
pages
end
end.
flatten
end
.flatten
end
def self.unhyphenize(name)
......
......@@ -77,8 +77,8 @@ module Ci
def update_merge_requests_head_pipeline
return unless pipeline.latest?
MergeRequest.where(source_project: @pipeline.project, source_branch: @pipeline.ref).
update_all(head_pipeline_id: @pipeline.id)
MergeRequest.where(source_project: @pipeline.project, source_branch: @pipeline.ref)
.update_all(head_pipeline_id: @pipeline.id)
end
def skip_ci?
......
......@@ -3,8 +3,8 @@ module Ci
def execute(project, trigger, ref, variables = nil)
trigger_request = trigger.trigger_requests.create(variables: variables)
pipeline = Ci::CreatePipelineService.new(project, trigger.owner, ref: ref).
execute(:trigger, ignore_skip_ci: true, trigger_request: trigger_request)
pipeline = Ci::CreatePipelineService.new(project, trigger.owner, ref: ref)
.execute(:trigger, ignore_skip_ci: true, trigger_request: trigger_request)
trigger_request if pipeline.persisted?
end
......
......@@ -32,8 +32,8 @@ module Ci
return error("400 Job has to be running", 400) unless job.running?
return error("400 Variables not supported", 400) if params[:variables].any?
pipeline = Ci::CreatePipelineService.new(project, job.user, ref: params[:ref]).
execute(:pipeline, ignore_skip_ci: true) do |pipeline|
pipeline = Ci::CreatePipelineService.new(project, job.user, ref: params[:ref])
.execute(:pipeline, ignore_skip_ci: true) do |pipeline|
job.sourced_pipelines.create!(
source_pipeline: job.pipeline,
source_project: job.project,
......
......@@ -55,15 +55,15 @@ module Ci
def builds_for_shared_runner
new_builds.
# don't run projects which have not enabled shared runners and builds
joins(:project).where(projects: { shared_runners_enabled: true }).
joins('LEFT JOIN project_features ON ci_builds.project_id = project_features.project_id').
where('project_features.builds_access_level IS NULL or project_features.builds_access_level > 0').
joins(:project).where(projects: { shared_runners_enabled: true })
.joins('LEFT JOIN project_features ON ci_builds.project_id = project_features.project_id')
.where('project_features.builds_access_level IS NULL or project_features.builds_access_level > 0').
# Implement fair scheduling
# this returns builds that are ordered by number of running builds
# we prefer projects that don't use shared runners at all
joins("LEFT JOIN (#{running_builds_for_shared_runners.to_sql}) AS project_builds ON ci_builds.project_id=project_builds.project_id").
order('COALESCE(project_builds.running_builds, 0) ASC', 'ci_builds.id ASC')
joins("LEFT JOIN (#{running_builds_for_shared_runners.to_sql}) AS project_builds ON ci_builds.project_id=project_builds.project_id")
.order('COALESCE(project_builds.running_builds, 0) ASC', 'ci_builds.id ASC')
end
def builds_for_specific_runner
......@@ -71,8 +71,8 @@ module Ci
end
def running_builds_for_shared_runners
Ci::Build.running.where(runner: Ci::Runner.shared).
group(:project_id).select(:project_id, 'count(*) AS running_builds')
Ci::Build.running.where(runner: Ci::Runner.shared)
.group(:project_id).select(:project_id, 'count(*) AS running_builds')
end
def new_builds
......
......@@ -10,9 +10,9 @@ module Issues
def merge_request_to_resolve_discussions_of
return @merge_request_to_resolve_discussions_of if defined?(@merge_request_to_resolve_discussions_of)
@merge_request_to_resolve_discussions_of = MergeRequestsFinder.new(current_user, project_id: project.id).
execute.
find_by(iid: merge_request_to_resolve_discussions_of_iid)
@merge_request_to_resolve_discussions_of = MergeRequestsFinder.new(current_user, project_id: project.id)
.execute
.find_by(iid: merge_request_to_resolve_discussions_of_iid)
end
def discussions_to_resolve
......
......@@ -28,8 +28,8 @@ module Files
end
def last_commit
@last_commit ||= Gitlab::Git::Commit.
last_for_path(@start_project.repository, @start_branch, @file_path)
@last_commit ||= Gitlab::Git::Commit
.last_for_path(@start_project.repository, @start_branch, @file_path)
end
def validate!
......
......@@ -91,8 +91,8 @@ class GitPushService < BaseService
push_commits.last(PROCESS_COMMIT_LIMIT).each do |commit|
if commit.matches_cross_reference_regex?
ProcessCommitWorker.
perform_async(project.id, current_user.id, commit.to_hash, default)
ProcessCommitWorker
.perform_async(project.id, current_user.id, commit.to_hash, default)
end
end
end
......
......@@ -144,8 +144,8 @@ class IssuableBaseService < BaseService
def merge_quick_actions_into_params!(issuable)
description, command_params =
QuickActions::InterpretService.new(project, current_user).
execute(params[:description], issuable)
QuickActions::InterpretService.new(project, current_user)
.execute(params[:description], issuable)
# Avoid a description already set on an issuable to be overwritten by a nil
params[:description] = description if params.key?(:description)
......
......@@ -62,9 +62,9 @@ module Issues
# They take precedence over eachother like this
# passed params > discussion params > template params
def issue_params
@issue_params ||= issue_params_from_template.
merge(issue_params_with_info_from_discussions).
merge(whitelisted_issue_params)
@issue_params ||= issue_params_from_template
.merge(issue_params_with_info_from_discussions)
.merge(whitelisted_issue_params)
end
def whitelisted_issue_params
......
......@@ -30,8 +30,8 @@ module Issues
Discussions::ResolveService.new(project, current_user,
merge_request: merge_request_to_resolve_discussions_of,
follow_up_issue: issue).
execute(discussions_to_resolve)
follow_up_issue: issue)
.execute(discussions_to_resolve)
end
private
......
......@@ -26,29 +26,29 @@ module Labels
private
def label_ids_for_merge(new_label)
LabelsFinder.
new(current_user, title: new_label.title, group_id: project.group.id).
execute(skip_authorization: true).
where.not(id: new_label).
select(:id) # Can't use pluck() to avoid object-creation because of the batching
LabelsFinder
.new(current_user, title: new_label.title, group_id: project.group.id)
.execute(skip_authorization: true)
.where.not(id: new_label)
.select(:id) # Can't use pluck() to avoid object-creation because of the batching
end
def update_issuables(new_label, label_ids)
LabelLink.
where(label: label_ids).
update_all(label_id: new_label)
LabelLink
.where(label: label_ids)
.update_all(label_id: new_label)
end
def update_issue_board_lists(new_label, label_ids)
List.
where(label: label_ids).
update_all(label_id: new_label)
List
.where(label: label_ids)
.update_all(label_id: new_label)
end
def update_priorities(new_label, label_ids)
LabelPriority.
where(label: label_ids).
update_all(label_id: new_label)
LabelPriority
.where(label: label_ids)
.update_all(label_id: new_label)
end
def update_project_labels(label_ids)
......
......@@ -41,16 +41,16 @@ module Labels
end
def group_labels_applied_to_issues
Label.joins(:issues).
where(
Label.joins(:issues)
.where(
issues: { project_id: project.id },
labels: { type: 'GroupLabel', group_id: old_group.id }
)
end
def group_labels_applied_to_merge_requests
Label.joins(:merge_requests).
where(
Label.joins(:merge_requests)
.where(
merge_requests: { target_project_id: project.id },
labels: { type: 'GroupLabel', group_id: old_group.id }
)
......@@ -64,15 +64,15 @@ module Labels
end
def update_label_links(labels, old_label_id:, new_label_id:)
LabelLink.joins(:label).
merge(labels).
where(label_id: old_label_id).
update_all(label_id: new_label_id)
LabelLink.joins(:label)
.merge(labels)
.where(label_id: old_label_id)
.update_all(label_id: new_label_id)
end
def update_label_priorities(old_label_id:, new_label_id:)
LabelPriority.where(project_id: project.id, label_id: old_label_id).
update_all(label_id: new_label_id)
LabelPriority.where(project_id: project.id, label_id: old_label_id)
.update_all(label_id: new_label_id)
end
end
end
......@@ -26,30 +26,30 @@ module Members
def unassign_issues_and_merge_requests(member)
if member.is_a?(GroupMember)
issues = Issue.unscoped.select(1).
joins(:project).
where('issues.id = issue_assignees.issue_id AND projects.namespace_id = ?', member.source_id)
issues = Issue.unscoped.select(1)
.joins(:project)
.where('issues.id = issue_assignees.issue_id AND projects.namespace_id = ?', member.source_id)
# DELETE FROM issue_assignees WHERE user_id = X AND EXISTS (...)
IssueAssignee.unscoped.
where('user_id = :user_id AND EXISTS (:sub)', user_id: member.user_id, sub: issues).
delete_all
IssueAssignee.unscoped
.where('user_id = :user_id AND EXISTS (:sub)', user_id: member.user_id, sub: issues)
.delete_all
MergeRequestsFinder.new(user, group_id: member.source_id, assignee_id: member.user_id).
execute.
update_all(assignee_id: nil)
MergeRequestsFinder.new(user, group_id: member.source_id, assignee_id: member.user_id)
.execute
.update_all(assignee_id: nil)
else
project = member.source
# SELECT 1 FROM issues WHERE issues.id = issue_assignees.issue_id AND issues.project_id = X
issues = Issue.unscoped.select(1).
where('issues.id = issue_assignees.issue_id').
where(project_id: project.id)
issues = Issue.unscoped.select(1)
.where('issues.id = issue_assignees.issue_id')
.where(project_id: project.id)
# DELETE FROM issue_assignees WHERE user_id = X AND EXISTS (...)
IssueAssignee.unscoped.
where('user_id = :user_id AND EXISTS (:sub)', user_id: member.user_id, sub: issues).
delete_all
IssueAssignee.unscoped
.where('user_id = :user_id AND EXISTS (:sub)', user_id: member.user_id, sub: issues)
.delete_all
project.merge_requests.opened.assigned_to(member.user).update_all(assignee_id: nil)
end
......
......@@ -27,10 +27,10 @@ module MergeRequests
tree: merge_index.write_tree(rugged)
}
conflicts_for_resolution.
project.
repository.
resolve_conflicts(current_user, merge_request.source_branch, commit_params)
conflicts_for_resolution
.project
.repository
.resolve_conflicts(current_user, merge_request.source_branch, commit_params)
end
end
......
......@@ -89,8 +89,8 @@ module MergeRequests
MergeRequests::PostMergeService.new(project, current_user).execute(merge_request)
if params[:should_remove_source_branch].present? || @merge_request.force_remove_source_branch?
DeleteBranchService.new(@merge_request.source_project, branch_deletion_user).
execute(merge_request.source_branch)
DeleteBranchService.new(@merge_request.source_project, branch_deletion_user)
.execute(merge_request.source_branch)
end
end
......
......@@ -44,9 +44,9 @@ module MergeRequests
end
filter_merge_requests(merge_requests).each do |merge_request|
MergeRequests::PostMergeService.
new(merge_request.target_project, @current_user).
execute(merge_request)
MergeRequests::PostMergeService
.new(merge_request.target_project, @current_user)
.execute(merge_request)
end
end
......@@ -57,8 +57,8 @@ module MergeRequests
# Refresh merge request diff if we push to source or target branch of merge request
# Note: we should update merge requests from forks too
def reload_merge_requests
merge_requests = @project.merge_requests.opened.
by_source_or_target_branch(@branch_name).to_a
merge_requests = @project.merge_requests.opened
.by_source_or_target_branch(@branch_name).to_a
# Fork merge requests
merge_requests += MergeRequest.opened
......
......@@ -22,8 +22,8 @@ module Notes
def extract_commands(note, options = {})
return [note.note, {}] unless supported?(note)
QuickActions::InterpretService.new(project, current_user, options).
execute(note.note, note.noteable)
QuickActions::InterpretService.new(project, current_user, options)
.execute(note.note, note.noteable)
end
def execute(command_params, note)
......
......@@ -19,8 +19,8 @@ module Tags
if new_tag
if release_description
CreateReleaseService.new(@project, @current_user).
execute(tag_name, release_description)
CreateReleaseService.new(@project, @current_user)
.execute(tag_name, release_description)
end
success.merge(tag: new_tag)
......
......@@ -79,7 +79,7 @@
%span{ style: "font-weight: bold;color:#333333;" } Merge request
%a{ href: merge_request_url(@merge_request), style: "font-weight: bold;color:#3777b0;text-decoration:none" }= @merge_request.to_reference
%span was approved by
%img.avatar{ height: "24", src: avatar_icon(@approved_by, 24), style: "border-radius:12px;margin:-7px 0 -7px 3px;", width: "24", alt: "Avatar" }/
%img.avatar{ height: "24", src: avatar_icon(@approved_by, 24, only_path: false), style: "border-radius:12px;margin:-7px 0 -7px 3px;", width: "24", alt: "Avatar" }/
%a.muted{ href: user_url(@approved_by), style: "color:#333333;text-decoration:none;" }
= @approved_by.name
%tr.spacer
......@@ -117,7 +117,7 @@
%tbody
%tr
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;" }
%img.avatar{ height: "24", src: avatar_icon(@merge_request.author, 24), style: "display:block;border-radius:12px;margin:-2px 0;", width: "24", alt: "Avatar" }/
%img.avatar{ height: "24", src: avatar_icon(@merge_request.author, 24, only_path: false), style: "display:block;border-radius:12px;margin:-2px 0;", width: "24", alt: "Avatar" }/
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;" }
%a.muted{ href: user_url(@merge_request.author), style: "color:#333333;text-decoration:none;" }
= @merge_request.author.name
......@@ -130,7 +130,7 @@
%tbody
%tr
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;" }
%img.avatar{ height: "24", src: avatar_icon(@merge_request.assignee, 24), style: "display:block;border-radius:12px;margin:-2px 0;", width: "24", alt: "Avatar" }/
%img.avatar{ height: "24", src: avatar_icon(@merge_request.assignee, 24, only_path: false), style: "display:block;border-radius:12px;margin:-2px 0;", width: "24", alt: "Avatar" }/
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;" }
%a.muted{ href: user_url(@merge_request.assignee), style: "color:#333333;text-decoration:none;" }
= @merge_request.assignee.name
......
......@@ -60,7 +60,7 @@
%tbody
%tr
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;" }
%img.avatar{ height: "24", src: avatar_icon(commit.author || commit.author_email, 24), style: "display:block;border-radius:12px;margin:-2px 0;", width: "24", alt: "Avatar" }/
%img.avatar{ height: "24", src: avatar_icon(commit.author || commit.author_email, 24, only_path: false), style: "display:block;border-radius:12px;margin:-2px 0;", width: "24", alt: "Avatar" }/
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;" }
- if commit.author
%a.muted{ href: user_url(commit.author), style: "color:#333333;text-decoration:none;" }
......@@ -76,7 +76,7 @@
%tbody
%tr
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;" }
%img.avatar{ height: "24", src: avatar_icon(commit.committer || commit.committer_email, 24), style: "display:block;border-radius:12px;margin:-2px 0;", width: "24", alt: "Avatar" }/
%img.avatar{ height: "24", src: avatar_icon(commit.committer || commit.committer_email, 24, only_path: false), style: "display:block;border-radius:12px;margin:-2px 0;", width: "24", alt: "Avatar" }/
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;" }
- if commit.committer
%a.muted{ href: user_url(commit.committer), style: "color:#333333;text-decoration:none;" }
......@@ -100,7 +100,7 @@
triggered by
- if @pipeline.user
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;padding-left:5px", width: "24" }
%img.avatar{ height: "24", src: avatar_icon(@pipeline.user, 24), style: "display:block;border-radius:12px;margin:-2px 0;", width: "24", alt: "Avatar" }/
%img.avatar{ height: "24", src: avatar_icon(@pipeline.user, 24, only_path: false), style: "display:block;border-radius:12px;margin:-2px 0;", width: "24", alt: "Avatar" }/
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;font-weight:500;line-height:1.4;vertical-align:baseline;" }
%a.muted{ href: user_url(@pipeline.user), style: "color:#333333;text-decoration:none;" }
= @pipeline.user.name
......
......@@ -60,7 +60,7 @@
%tbody
%tr
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;" }
%img.avatar{ height: "24", src: avatar_icon(commit.author || commit.author_email, 24), style: "display:block;border-radius:12px;margin:-2px 0;", width: "24", alt: "Avatar" }/
%img.avatar{ height: "24", src: avatar_icon(commit.author || commit.author_email, 24, only_path: false), style: "display:block;border-radius:12px;margin:-2px 0;", width: "24", alt: "Avatar" }/
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;" }
- if commit.author
%a.muted{ href: user_url(commit.author), style: "color:#333333;text-decoration:none;" }
......@@ -76,7 +76,7 @@
%tbody
%tr
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;" }
%img.avatar{ height: "24", src: avatar_icon(commit.committer || commit.committer_email, 24), style: "display:block;border-radius:12px;margin:-2px 0;", width: "24", alt: "Avatar" }/
%img.avatar{ height: "24", src: avatar_icon(commit.committer || commit.committer_email, 24, only_path: false), style: "display:block;border-radius:12px;margin:-2px 0;", width: "24", alt: "Avatar" }/
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;" }
- if commit.committer
%a.muted{ href: user_url(commit.committer), style: "color:#333333;text-decoration:none;" }
......@@ -100,7 +100,7 @@
triggered by
- if @pipeline.user
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;padding-left:5px", width: "24" }
%img.avatar{ height: "24", src: avatar_icon(@pipeline.user, 24), style: "display:block;border-radius:12px;margin:-2px 0;", width: "24", alt: "Avatar" }/
%img.avatar{ height: "24", src: avatar_icon(@pipeline.user, 24, only_path: false), style: "display:block;border-radius:12px;margin:-2px 0;", width: "24", alt: "Avatar" }/
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;font-weight:500;line-height:1.4;vertical-align:baseline;" }
%a.muted{ href: user_url(@pipeline.user), style: "color:#333333;text-decoration:none;" }
= @pipeline.user.name
......
- if current_user && @project.feature_available?(:export_issues)
%button.csv_download_link.btn.append-right-10.has-tooltip{ title: 'Export as CSV' }
= icon('download')
- return unless current_user && @project.feature_available?(:export_issues)
.issues-export-modal.modal
.modal-dialog
.modal-content
......
......@@ -15,17 +15,18 @@
= auto_discovery_link_tag(:atom, params.merge(rss_url_options), title: "#{@project.name} issues")
- if project_issues(@project).exists?
- if current_user
= render "projects/issues/export_issues/csv_download"
= render 'projects/issues/export_issues/csv_download'
%div{ class: (container_class) }
.top-area
= render 'shared/issuable/nav', type: :issues
.nav-controls.inline
= link_to params.merge(rss_url_options), class: 'btn append-right-10 has-tooltip', title: 'Subscribe' do
= icon('rss')
- if current_user
%button.csv_download_link.btn.append-right-10.has-tooltip{ title: 'Export as CSV' }
= icon('download')
= render 'projects/issues/export_issues/button'
- if @can_bulk_update
= button_tag "Edit Issues", class: "btn btn-default js-bulk-update-toggle"
= link_to new_namespace_project_issue_path(@project.namespace,
......
......@@ -7,7 +7,7 @@ class MergeWorker
current_user = User.find(current_user_id)
merge_request = MergeRequest.find(merge_request_id)
MergeRequests::MergeService.new(merge_request.target_project, current_user, params).
execute(merge_request)
MergeRequests::MergeService.new(merge_request.target_project, current_user, params)
.execute(merge_request)
end
end
......@@ -47,8 +47,8 @@ class ProcessCommitWorker
# therefor we use IssueCollection here and skip the authorization check in
# Issues::CloseService#execute.
IssueCollection.new(issues).updatable_by_user(user).each do |issue|
Issues::CloseService.new(project, author).
close_issue(issue, commit: commit)
Issues::CloseService.new(project, author)
.close_issue(issue, commit: commit)
end
end
......@@ -57,8 +57,8 @@ class ProcessCommitWorker
return if mentioned_issues.empty?
Issue::Metrics.where(issue_id: mentioned_issues.map(&:id), first_mentioned_in_commit_at: nil).
update_all(first_mentioned_in_commit_at: commit.committed_date)
Issue::Metrics.where(issue_id: mentioned_issues.map(&:id), first_mentioned_in_commit_at: nil)
.update_all(first_mentioned_in_commit_at: commit.committed_date)
end
def build_commit(project, hash)
......
......@@ -33,8 +33,8 @@ class ProjectCacheWorker
private
def try_obtain_lease_for(project_id, section)
Gitlab::ExclusiveLease.
new("project_cache_worker:#{project_id}:#{section}", timeout: LEASE_TIMEOUT).
try_obtain
Gitlab::ExclusiveLease
.new("project_cache_worker:#{project_id}:#{section}", timeout: LEASE_TIMEOUT)
.try_obtain
end
end
......@@ -14,8 +14,8 @@ class PropagateServiceTemplateWorker
private
def try_obtain_lease_for(template_id)
Gitlab::ExclusiveLease.
new("propagate_service_template_worker:#{template_id}", timeout: LEASE_TIMEOUT).
try_obtain
Gitlab::ExclusiveLease
.new("propagate_service_template_worker:#{template_id}", timeout: LEASE_TIMEOUT)
.try_obtain
end
end
......@@ -12,9 +12,9 @@ class PruneOldEventsWorker
'(id IN (SELECT id FROM (?) ids_to_remove))',
Event.unscoped.where(
'created_at < ?',
(12.months + 1.day).ago).
select(:id).
limit(10_000)).
delete_all
(12.months + 1.day).ago)
.select(:id)
.limit(10_000))
.delete_all
end
end
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment