Skip to content
Snippets Groups Projects
Commit 67948368 authored by Alfredo Sumaran's avatar Alfredo Sumaran
Browse files

Merge branch 'master' into sidebar-sizing-higher-viewport

parents 60801262 7c809985
No related branches found
No related tags found
No related merge requests found
Showing
with 429 additions and 33 deletions
Loading
Loading
@@ -69,7 +69,7 @@ class Projects::LabelsController < Projects::ApplicationController
end
 
def label_params
params.require(:label).permit(:title, :color)
params.require(:label).permit(:title, :description, :color)
end
 
def label
Loading
Loading
Loading
Loading
@@ -34,6 +34,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController
@merge_requests = @merge_requests.page(params[:page]).per(PER_PAGE)
@merge_requests = @merge_requests.preload(:target_project)
 
@label = @project.labels.find_by(title: params[:label_name])
respond_to do |format|
format.html
format.json do
Loading
Loading
@@ -179,6 +181,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController
return
end
 
TodoService.new.merge_merge_request(merge_request, current_user)
@merge_request.update(merge_error: nil)
 
if params[:merge_when_build_succeeds].present? && @merge_request.ci_commit && @merge_request.ci_commit.active?
Loading
Loading
Loading
Loading
@@ -35,6 +35,7 @@ class Projects::MilestonesController < Projects::ApplicationController
@issues = @milestone.issues
@users = @milestone.participants.uniq
@merge_requests = @milestone.merge_requests
@labels = @milestone.labels
end
 
def create
Loading
Loading
Loading
Loading
@@ -11,7 +11,9 @@ class Projects::RepositoriesController < Projects::ApplicationController
end
 
def archive
render json: ArchiveRepositoryService.new(@project, params[:ref], params[:format]).execute
RepositoryArchiveCacheWorker.perform_async
headers.store(*Gitlab::Workhorse.send_git_archive(@project, params[:ref], params[:format]))
head :ok
rescue => ex
logger.error("#{self.class.name}: #{ex}")
return git_not_found!
Loading
Loading
Loading
Loading
@@ -236,7 +236,7 @@ class ProjectsController < ApplicationController
Emoji.emojis.map do |name, emoji|
{
name: name,
path: view_context.image_url("emoji/#{emoji["unicode"]}.png")
path: view_context.image_url("#{emoji["unicode"]}.png")
}
end
end
Loading
Loading
Loading
Loading
@@ -119,6 +119,20 @@ class IssuableFinder
labels? && params[:label_name] == Label::None.title
end
 
def labels
return @labels if defined?(@labels)
if labels? && !filter_by_no_label?
@labels = Label.where(title: label_names)
if projects
@labels = @labels.where(project: projects)
end
else
@labels = Label.none
end
end
def assignee?
params[:assignee_id].present?
end
Loading
Loading
@@ -253,8 +267,6 @@ class IssuableFinder
joins("LEFT OUTER JOIN label_links ON label_links.target_type = '#{klass.name}' AND label_links.target_id = #{klass.table_name}.id").
where(label_links: { id: nil })
else
label_names = params[:label_name].split(",")
items = items.joins(:labels).where(labels: { title: label_names })
 
if projects
Loading
Loading
@@ -266,6 +278,10 @@ class IssuableFinder
items
end
 
def label_names
params[:label_name].split(',')
end
def current_user_related?
params[:scope] == 'created-by-me' || params[:scope] == 'authored' || params[:scope] == 'assigned-to-me'
end
Loading
Loading
# TodosFinder
#
# Used to filter Todos by set of params
#
# Arguments:
# current_user - which user use
# params:
# action_id: integer
# author_id: integer
# project_id; integer
# state: 'pending' or 'done'
# type: 'Issue' or 'MergeRequest'
#
class TodosFinder
NONE = '0'
attr_accessor :current_user, :params
def initialize(current_user, params)
@current_user = current_user
@params = params
end
def execute
items = current_user.todos
items = by_action_id(items)
items = by_author(items)
items = by_project(items)
items = by_state(items)
items = by_type(items)
items
end
private
def action_id?
action_id.present? && [Todo::ASSIGNED, Todo::MENTIONED].include?(action_id.to_i)
end
def action_id
params[:action_id]
end
def author?
params[:author_id].present?
end
def author
return @author if defined?(@author)
@author =
if author? && params[:author_id] != NONE
User.find(params[:author_id])
else
nil
end
end
def project?
params[:project_id].present?
end
def project
return @project if defined?(@project)
if project?
@project = Project.find(params[:project_id])
unless Ability.abilities.allowed?(current_user, :read_project, @project)
@project = nil
end
else
@project = nil
end
@project
end
def type?
type.present? && ['Issue', 'MergeRequest'].include?(type)
end
def type
params[:type]
end
def by_action_id(items)
if action_id?
items = items.where(action: action_id)
end
items
end
def by_author(items)
if author?
items = items.where(author_id: author.try(:id))
end
items
end
def by_project(items)
if project?
items = items.where(project: project)
end
items
end
def by_state(items)
case params[:state]
when 'done'
items.done
else
items.pending
end
end
def by_type(items)
if type?
items = items.where(target_type: type)
end
items
end
end
Loading
Loading
@@ -118,12 +118,6 @@ module ApplicationHelper
grouped_options_for_select(options, @ref || @project.default_branch)
end
 
def emoji_autocomplete_source
# should be an array of strings
# so to_s can be called, because it is sufficient and to_json is too slow
Emoji.names.to_s
end
# Define whenever show last push event
# with suggestion to create MR
def show_last_push_widget?(event)
Loading
Loading
Loading
Loading
@@ -127,10 +127,6 @@ module BlobHelper
end
end
 
def blob_svg?(blob)
blob.language && blob.language.name == 'SVG'
end
# SVGs can contain malicious JavaScript; only include whitelisted
# elements and attributes. Note that this whitelist is by no means complete
# and may omit some elements.
Loading
Loading
Loading
Loading
@@ -123,6 +123,37 @@ module CommitsHelper
)
end
 
def revert_commit_link(commit, continue_to_path, btn_class: nil)
return unless current_user
tooltip = "Revert this #{revert_commit_type(commit)} in a new merge request"
if can_collaborate_with_project?
content_tag :span, 'data-toggle' => 'modal', 'data-target' => '#modal-revert-commit' do
link_to 'Revert', '#modal-revert-commit', 'data-toggle' => 'tooltip', 'data-container' => 'body', title: tooltip, class: "btn btn-default btn-grouped btn-#{btn_class}"
end
elsif can?(current_user, :fork_project, @project)
continue_params = {
to: continue_to_path,
notice: edit_in_new_fork_notice + ' Try to revert this commit again.',
notice_now: edit_in_new_fork_notice_now
}
fork_path = namespace_project_forks_path(@project.namespace, @project,
namespace_key: current_user.namespace.id,
continue: continue_params)
link_to 'Revert', fork_path, class: 'btn btn-grouped btn-close', method: :post, 'data-toggle' => 'tooltip', 'data-container' => 'body', title: tooltip
end
end
def revert_commit_type(commit)
if commit.merged_merge_request
'merge request'
else
'commit'
end
end
protected
 
# Private: Returns a link to a person. If the person has a matching user and
Loading
Loading
Loading
Loading
@@ -69,7 +69,7 @@ module DiffHelper
end
 
def line_comments
@line_comments ||= @line_notes.select(&:active?).group_by(&:line_code)
@line_comments ||= @line_notes.select(&:active?).sort_by(&:created_at).group_by(&:line_code)
end
 
def organize_comments(type_left, type_right, line_code_left, line_code_right)
Loading
Loading
@@ -137,7 +137,7 @@ module DiffHelper
# Always use HTML to handle case where JSON diff rendered this button
params_copy.delete(:format)
 
link_to url_for(params_copy), id: "#{name}-diff-btn", class: (selected ? 'btn active' : 'btn') do
link_to url_for(params_copy), id: "#{name}-diff-btn", class: (selected ? 'btn active' : 'btn'), data: { view_type: name } do
title
end
end
Loading
Loading
Loading
Loading
@@ -23,6 +23,7 @@ module NavHelper
if current_path?('merge_requests#show') ||
current_path?('merge_requests#diffs') ||
current_path?('merge_requests#commits') ||
current_path?('merge_requests#builds') ||
current_path?('issues#show')
if cookies[:collapsed_gutter] == 'true'
"page-gutter right-sidebar-collapsed"
Loading
Loading
Loading
Loading
@@ -11,6 +11,8 @@ module SortingHelper
sort_value_largest_repo => sort_title_largest_repo,
sort_value_recently_signin => sort_title_recently_signin,
sort_value_oldest_signin => sort_title_oldest_signin,
sort_value_downvotes => sort_title_downvotes,
sort_value_upvotes => sort_title_upvotes
}
end
 
Loading
Loading
@@ -54,6 +56,14 @@ module SortingHelper
'Oldest sign in'
end
 
def sort_title_downvotes
'Least popular'
end
def sort_title_upvotes
'Most popular'
end
def sort_value_oldest_updated
'updated_asc'
end
Loading
Loading
@@ -93,4 +103,12 @@ module SortingHelper
def sort_value_oldest_signin
'oldest_sign_in'
end
def sort_value_downvotes
'downvotes_desc'
end
def sort_value_upvotes
'upvotes_desc'
end
end
module TodosHelper
def todos_pending_count
current_user.todos.pending.count
end
def todos_done_count
current_user.todos.done.count
end
def todo_action_name(todo)
case todo.action
when Todo::ASSIGNED then 'assigned you'
when Todo::MENTIONED then 'mentioned you on'
end
end
def todo_target_link(todo)
target = todo.target_type.titleize.downcase
link_to "#{target} #{todo.target.to_reference}", todo_target_path(todo)
end
def todo_target_path(todo)
anchor = dom_id(todo.note) if todo.note.present?
polymorphic_path([todo.project.namespace.becomes(Namespace),
todo.project, todo.target], anchor: anchor)
end
def todos_filter_params
{
state: params[:state],
project_id: params[:project_id],
author_id: params[:author_id],
type: params[:type],
action_id: params[:action_id],
}
end
def todos_filter_path(options = {})
without = options.delete(:without)
options = todos_filter_params.merge(options)
if without.present?
without.each do |key|
options.delete(key)
end
end
path = request.path
path << "?#{options.to_param}"
path
end
def todo_actions_options
actions = [
OpenStruct.new(id: '', title: 'Any Action'),
OpenStruct.new(id: Todo::ASSIGNED, title: 'Assigned'),
OpenStruct.new(id: Todo::MENTIONED, title: 'Mentioned')
]
options_from_collection_for_select(actions, 'id', 'title', params[:action_id])
end
def todo_projects_options
projects = current_user.authorized_projects.sorted_by_activity.non_archived
projects = projects.includes(:namespace)
projects = projects.map do |project|
OpenStruct.new(id: project.id, title: project.name_with_namespace)
end
projects.unshift(OpenStruct.new(id: '', title: 'Any Project'))
options_from_collection_for_select(projects, 'id', 'title', params[:project_id])
end
def todo_types_options
types = [
OpenStruct.new(title: 'Any Type', name: ''),
OpenStruct.new(title: 'Issue', name: 'Issue'),
OpenStruct.new(title: 'Merge Request', name: 'MergeRequest')
]
options_from_collection_for_select(types, 'name', 'title', params[:type])
end
end
Loading
Loading
@@ -56,8 +56,7 @@ module TreeHelper
 
return false unless on_top_of_branch?(project, ref)
 
can?(current_user, :push_code, project) ||
(current_user && current_user.already_forked?(project))
can_collaborate_with_project?(project)
end
 
def tree_edit_branch(project = @project, ref = @ref)
Loading
Loading
# Blob is a Rails-specific wrapper around Gitlab::Git::Blob objects
class Blob < SimpleDelegator
# Wrap a Gitlab::Git::Blob object, or return nil when given nil
#
# This method prevents the decorated object from evaluating to "truthy" when
# given a nil value. For example:
#
# blob = Blob.new(nil)
# puts "truthy" if blob # => "truthy"
#
# blob = Blob.decorate(nil)
# puts "truthy" if blob # No output
def self.decorate(blob)
return if blob.nil?
new(blob)
end
def svg?
text? && language && language.name == 'SVG'
end
def to_partial_path
if lfs_pointer?
'download'
elsif image? || svg?
'image'
elsif text?
'text'
else
'download'
end
end
end
Loading
Loading
@@ -31,15 +31,19 @@
# artifacts_file :text
# gl_project_id :integer
# artifacts_metadata :text
# erased_by_id :integer
# erased_at :datetime
#
 
module Ci
class Build < CommitStatus
include Gitlab::Application.routes.url_helpers
LAZY_ATTRIBUTES = ['trace']
 
belongs_to :runner, class_name: 'Ci::Runner'
belongs_to :trigger_request, class_name: 'Ci::TriggerRequest'
belongs_to :erased_by, class_name: 'User'
 
serialize :options
 
Loading
Loading
@@ -103,23 +107,22 @@ module Ci
end
 
state_machine :status, initial: :pending do
after_transition pending: :running do |build, transition|
after_transition pending: :running do |build|
build.execute_hooks
end
 
after_transition any => [:success, :failed, :canceled] do |build, transition|
return unless build.project
# We use around_transition to create builds for next stage as soon as possible, before the `after_*` is executed
around_transition any => [:success, :failed, :canceled] do |build, block|
block.call
build.commit.create_next_builds(build) if build.commit
end
 
after_transition any => [:success, :failed, :canceled] do |build|
build.update_coverage
build.commit.create_next_builds(build)
build.execute_hooks
end
end
 
def ignored?
failed? && allow_failure?
end
def retryable?
project.builds_enabled? && commands.present?
end
Loading
Loading
@@ -179,6 +182,7 @@ module Ci
end
 
def update_coverage
return unless project
coverage_regex = project.build_coverage_regex
return unless coverage_regex
coverage = extract_coverage(trace, coverage_regex)
Loading
Loading
@@ -203,6 +207,10 @@ module Ci
end
end
 
def has_trace?
raw_trace.present?
end
def raw_trace
if File.file?(path_to_trace)
File.read(path_to_trace)
Loading
Loading
@@ -330,6 +338,7 @@ module Ci
end
 
def execute_hooks
return unless project
build_data = Gitlab::BuildDataBuilder.build(self)
project.execute_hooks(build_data.dup, :build_hooks)
project.execute_services(build_data.dup, :build_hooks)
Loading
Loading
@@ -359,6 +368,33 @@ module Ci
Gitlab::Ci::Build::Artifacts::Metadata.new(artifacts_metadata.path, path, **options).to_entry
end
 
def erase(opts = {})
return false unless erasable?
remove_artifacts_file!
remove_artifacts_metadata!
erase_trace!
update_erased!(opts[:erased_by])
end
def erasable?
complete? && (artifacts? || has_trace?)
end
def erased?
!self.erased_at.nil?
end
private
def erase_trace!
self.trace = nil
end
def update_erased!(user = nil)
self.update(erased_by: user, erased_at: Time.now)
end
private
 
def yaml_variables
Loading
Loading
Loading
Loading
@@ -22,6 +22,7 @@ module Ci
extend Ci::Model
 
LAST_CONTACT_TIME = 5.minutes.ago
AVAILABLE_SCOPES = ['specific', 'shared', 'active', 'paused', 'online']
has_many :builds, class_name: 'Ci::Build'
has_many :runner_projects, dependent: :destroy, class_name: 'Ci::RunnerProject'
Loading
Loading
@@ -38,6 +39,11 @@ module Ci
scope :online, ->() { where('contacted_at > ?', LAST_CONTACT_TIME) }
scope :ordered, ->() { order(id: :desc) }
 
scope :owned_or_shared, ->(project_id) do
joins('LEFT JOIN ci_runner_projects ON ci_runner_projects.runner_id = ci_runners.id')
.where("ci_runner_projects.gl_project_id = :project_id OR ci_runners.is_shared = true", project_id: project_id)
end
acts_as_taggable
 
def self.search(query)
Loading
Loading
Loading
Loading
@@ -215,6 +215,44 @@ class Commit
ci_commit.try(:status) || :not_found
end
 
def revert_branch_name
"revert-#{short_id}"
end
def revert_description
if merged_merge_request
"This reverts merge request #{merged_merge_request.to_reference}"
else
"This reverts commit #{sha}"
end
end
def revert_message
%Q{Revert "#{title}"\n\n#{revert_description}}
end
def reverts_commit?(commit)
description? && description.include?(commit.revert_description)
end
def merge_commit?
parents.size > 1
end
def merged_merge_request
return @merged_merge_request if defined?(@merged_merge_request)
@merged_merge_request = project.merge_requests.find_by(merge_commit_sha: id) if merge_commit?
end
def has_been_reverted?(current_user = nil, noteable = self)
Gitlab::ReferenceExtractor.lazily do
noteable.notes.system.flat_map do |note|
note.all_references(current_user).commits
end
end.any? { |commit_ref| commit_ref.reverts_commit?(self) }
end
private
 
def repo_changes
Loading
Loading
Loading
Loading
@@ -75,16 +75,16 @@ class CommitStatus < ActiveRecord::Base
transition [:pending, :running] => :canceled
end
 
after_transition pending: :running do |build, transition|
build.update_attributes started_at: Time.now
after_transition pending: :running do |commit_status|
commit_status.update_attributes started_at: Time.now
end
 
after_transition any => [:success, :failed, :canceled] do |build, transition|
build.update_attributes finished_at: Time.now
after_transition any => [:success, :failed, :canceled] do |commit_status|
commit_status.update_attributes finished_at: Time.now
end
 
after_transition [:pending, :running] => :success do |build, transition|
MergeRequests::MergeWhenBuildSucceedsService.new(build.commit.project, nil).trigger(build)
after_transition [:pending, :running] => :success do |commit_status|
MergeRequests::MergeWhenBuildSucceedsService.new(commit_status.commit.project, nil).trigger(commit_status)
end
 
state :pending, value: 'pending'
Loading
Loading
@@ -113,6 +113,10 @@ class CommitStatus < ActiveRecord::Base
canceled? || success? || failed?
end
 
def ignored?
failed? && allow_failure?
end
def duration
if started_at && finished_at
finished_at - started_at
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment