Commit 69c4e0a1 authored by James Lopez's avatar James Lopez

Merge branch 'master' of gitlab.com:gitlab-org/gitlab-ce into hotfix/ruby-21-broken-update

parents 902baa2e 88e16c3d
Please view this file on the master branch, on stable branches it's out of date. Please view this file on the master branch, on stable branches it's out of date.
v 8.5.0 (unreleased) v 8.5.0 (unreleased)
- Ensure rake tasks that don't need a DB connection can be run without one
- Add "visibility" flag to GET /projects api endpoint - Add "visibility" flag to GET /projects api endpoint
- Ignore binary files in code search to prevent Error 500 (Stan Hu) - Ignore binary files in code search to prevent Error 500 (Stan Hu)
- Upgrade gitlab_git to 7.2.23 to fix commit message mentions in first branch push - Upgrade gitlab_git to 7.2.23 to fix commit message mentions in first branch push
...@@ -14,6 +15,8 @@ v 8.5.0 (unreleased) ...@@ -14,6 +15,8 @@ v 8.5.0 (unreleased)
- Track project import failure - Track project import failure
- Fix visibility level text in admin area (Zeger-Jan van de Weg) - Fix visibility level text in admin area (Zeger-Jan van de Weg)
- Update the ExternalIssue regex pattern (Blake Hitchcock) - Update the ExternalIssue regex pattern (Blake Hitchcock)
- Deprecate API "merge_request/:merge_request_id/comments". Use "merge_requests/:merge_request_id/notes" instead
- Deprecate API "merge_request/:merge_request_id/...". Use "merge_requests/:merge_request_id/..." instead
v 8.4.2 v 8.4.2
- Bump required gitlab-workhorse version to bring in a fix for missing - Bump required gitlab-workhorse version to bring in a fix for missing
......
...@@ -50,6 +50,7 @@ class @Issue ...@@ -50,6 +50,7 @@ class @Issue
new Flash(issueFailMessage, 'alert') new Flash(issueFailMessage, 'alert')
success: (data, textStatus, jqXHR) -> success: (data, textStatus, jqXHR) ->
if data.saved if data.saved
$(document).trigger('issuable:change');
if isClose if isClose
$('a.btn-close').addClass('hidden') $('a.btn-close').addClass('hidden')
$('a.btn-reopen').removeClass('hidden') $('a.btn-reopen').removeClass('hidden')
......
...@@ -64,6 +64,9 @@ class @Notes ...@@ -64,6 +64,9 @@ class @Notes
# fetch notes when tab becomes visible # fetch notes when tab becomes visible
$(document).on "visibilitychange", @visibilityChange $(document).on "visibilitychange", @visibilityChange
# when issue status changes, we need to refresh data
$(document).on "issuable:change", @refresh
cleanBinding: -> cleanBinding: ->
$(document).off "ajax:success", ".js-main-target-form" $(document).off "ajax:success", ".js-main-target-form"
$(document).off "ajax:success", ".js-discussion-note-form" $(document).off "ajax:success", ".js-discussion-note-form"
......
...@@ -9,11 +9,13 @@ class @ProjectsList ...@@ -9,11 +9,13 @@ class @ProjectsList
$(".projects-list-filter").keyup -> $(".projects-list-filter").keyup ->
terms = $(this).val() terms = $(this).val()
uiBox = $('div.projects-list-holder') uiBox = $('div.projects-list-holder')
filterSelector = $(this).data('filter-selector') || 'span.filter-title'
if terms == "" || terms == undefined if terms == "" || terms == undefined
uiBox.find("ul.projects-list li").show() uiBox.find("ul.projects-list li").show()
else else
uiBox.find("ul.projects-list li").each (index) -> uiBox.find("ul.projects-list li").each (index) ->
name = $(this).find("span.filter-title").text() name = $(this).find(filterSelector).text()
if name.toLowerCase().search(terms.toLowerCase()) == -1 if name.toLowerCase().search(terms.toLowerCase()) == -1
$(this).hide() $(this).hide()
......
...@@ -115,7 +115,7 @@ ...@@ -115,7 +115,7 @@
ul, ol { ul, ol {
padding: 0; padding: 0;
margin: 6px 0 6px 18px !important; margin: 6px 0 6px 28px !important;
} }
li { li {
......
...@@ -564,3 +564,53 @@ pre.light-well { ...@@ -564,3 +564,53 @@ pre.light-well {
color: #E62958; color: #E62958;
margin-top: 2px; margin-top: 2px;
} }
/*
* Forks list rendered on Project's forks page
*/
.forks-top-block {
padding: 16px 0;
}
.projects-search-form {
.dropdown-toggle.btn {
margin-top: -3px;
}
&.fork-search-form {
margin: 0;
margin-top: -$gl-padding;
padding-bottom: 0;
input {
/* Small devices (tablets, 768px and up) */
@media (min-width: $screen-sm-min) { width: 180px; }
/* Medium devices (desktops, 992px and up) */
@media (min-width: $screen-md-min) { width: 350px; }
/* Large devices (large desktops, 1200px and up) */
@media (min-width: $screen-lg-min) { width: 400px; }
}
.sort-forks {
width: 160px;
}
.fork-link {
float: right;
margin-left: $gl-padding;
}
}
}
.private-forks-notice .private-fork-icon {
i:nth-child(1) {
color: #2AA056;
}
i:nth-child(2) {
color: #FFFFFF;
}
}
...@@ -298,7 +298,8 @@ class ApplicationController < ActionController::Base ...@@ -298,7 +298,8 @@ class ApplicationController < ActionController::Base
end end
def set_filters_params def set_filters_params
params[:sort] ||= 'id_desc' set_default_sort
params[:scope] = 'all' if params[:scope].blank? params[:scope] = 'all' if params[:scope].blank?
params[:state] = 'opened' if params[:state].blank? params[:state] = 'opened' if params[:state].blank?
...@@ -405,4 +406,24 @@ class ApplicationController < ActionController::Base ...@@ -405,4 +406,24 @@ class ApplicationController < ActionController::Base
current_user.nil? && root_path == request.path current_user.nil? && root_path == request.path
end end
private
def set_default_sort
key = if is_a_listing_page_for?('issues') || is_a_listing_page_for?('merge_requests')
'issuable_sort'
end
cookies[key] = params[:sort] if key && params[:sort].present?
params[:sort] = cookies[key] if key
params[:sort] ||= 'id_desc'
end
def is_a_listing_page_for?(page_type)
controller_name, action_name = params.values_at(:controller, :action)
(controller_name == "projects/#{page_type}" && action_name == 'index') ||
(controller_name == 'groups' && action_name == page_type) ||
(controller_name == 'dashboard' && action_name == page_type)
end
end end
...@@ -3,6 +3,15 @@ class Projects::ForksController < Projects::ApplicationController ...@@ -3,6 +3,15 @@ class Projects::ForksController < Projects::ApplicationController
before_action :require_non_empty_project before_action :require_non_empty_project
before_action :authorize_download_code! before_action :authorize_download_code!
def index
@sort = params[:sort] || 'id_desc'
@all_forks = project.forks.includes(:creator).order_by(@sort)
@public_forks, @protected_forks = @all_forks.partition do |project|
can?(current_user, :read_project, project)
end
end
def new def new
@namespaces = current_user.manageable_namespaces @namespaces = current_user.manageable_namespaces
@namespaces.delete(@project.namespace) @namespaces.delete(@project.namespace)
...@@ -10,7 +19,7 @@ class Projects::ForksController < Projects::ApplicationController ...@@ -10,7 +19,7 @@ class Projects::ForksController < Projects::ApplicationController
def create def create
namespace = Namespace.find(params[:namespace_key]) namespace = Namespace.find(params[:namespace_key])
@forked_project = namespace.projects.find_by(path: project.path) @forked_project = namespace.projects.find_by(path: project.path)
@forked_project = nil unless @forked_project && @forked_project.forked_from_project == project @forked_project = nil unless @forked_project && @forked_project.forked_from_project == project
......
...@@ -36,8 +36,7 @@ module BlobHelper ...@@ -36,8 +36,7 @@ module BlobHelper
notice: edit_in_new_fork_notice, notice: edit_in_new_fork_notice,
notice_now: edit_in_new_fork_notice_now notice_now: edit_in_new_fork_notice_now
} }
fork_path = namespace_project_fork_path(project.namespace, project, namespace_key: current_user.namespace.id, fork_path = namespace_project_forks_path(project.namespace, project, namespace_key: current_user.namespace.id, continue: continue_params)
continue: continue_params)
link_to "Edit", fork_path, class: 'btn', method: :post link_to "Edit", fork_path, class: 'btn', method: :post
end end
...@@ -62,8 +61,7 @@ module BlobHelper ...@@ -62,8 +61,7 @@ module BlobHelper
notice: edit_in_new_fork_notice + " Try to #{action} this file again.", notice: edit_in_new_fork_notice + " Try to #{action} this file again.",
notice_now: edit_in_new_fork_notice_now notice_now: edit_in_new_fork_notice_now
} }
fork_path = namespace_project_fork_path(project.namespace, project, namespace_key: current_user.namespace.id, fork_path = namespace_project_forks_path(project.namespace, project, namespace_key: current_user.namespace.id, continue: continue_params)
continue: continue_params)
link_to label, fork_path, class: "btn btn-#{btn_class}", method: :post link_to label, fork_path, class: "btn btn-#{btn_class}", method: :post
end end
......
...@@ -7,7 +7,7 @@ module IconsHelper ...@@ -7,7 +7,7 @@ module IconsHelper
# font-awesome-rails gem, but should we ever use a different icon pack in the # font-awesome-rails gem, but should we ever use a different icon pack in the
# future we won't have to change hundreds of method calls. # future we won't have to change hundreds of method calls.
def icon(names, options = {}) def icon(names, options = {})
fa_icon(names, options) options.include?(:base) ? fa_stacked_icon(names, options) : fa_icon(names, options)
end end
def spinner(text = nil, visible = false) def spinner(text = nil, visible = false)
......
...@@ -116,7 +116,7 @@ module ProjectsHelper ...@@ -116,7 +116,7 @@ module ProjectsHelper
private private
def get_project_nav_tabs(project, current_user) def get_project_nav_tabs(project, current_user)
nav_tabs = [:home] nav_tabs = [:home, :forks]
if !project.empty_repo? && can?(current_user, :download_code, project) if !project.empty_repo? && can?(current_user, :download_code, project)
nav_tabs << [:files, :commits, :network, :graphs] nav_tabs << [:files, :commits, :network, :graphs]
......
...@@ -19,7 +19,7 @@ require 'file_size_validator' ...@@ -19,7 +19,7 @@ require 'file_size_validator'
class Group < Namespace class Group < Namespace
include Gitlab::ConfigHelper include Gitlab::ConfigHelper
include Referable include Referable
has_many :group_members, dependent: :destroy, as: :source, class_name: 'GroupMember' has_many :group_members, dependent: :destroy, as: :source, class_name: 'GroupMember'
alias_method :members, :group_members alias_method :members, :group_members
has_many :users, through: :group_members has_many :users, through: :group_members
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
.pull-right .pull-right
.dropdown.inline .dropdown.inline
%a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"} %a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
%span.light sort: %span.light
- if @sort.present? - if @sort.present?
= sort_options_hash[@sort] = sort_options_hash[@sort]
- else - else
......
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
.controls .controls
.dropdown.inline .dropdown.inline
%button.dropdown-toggle.btn.btn-sm{type: 'button', 'data-toggle' => 'dropdown'} %button.dropdown-toggle.btn.btn-sm{type: 'button', 'data-toggle' => 'dropdown'}
%span.light sort: %span.light
- if @sort.present? - if @sort.present?
= sort_options_hash[@sort] = sort_options_hash[@sort]
- else - else
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
.pull-right .pull-right
.dropdown.inline .dropdown.inline
%a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"} %a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
%span.light sort: %span.light
- if @sort.present? - if @sort.present?
= sort_options_hash[@sort] = sort_options_hash[@sort]
- else - else
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
.pull-right .pull-right
.dropdown.inline .dropdown.inline
%button.dropdown-toggle.btn{type: 'button', 'data-toggle' => 'dropdown'} %button.dropdown-toggle.btn{type: 'button', 'data-toggle' => 'dropdown'}
%span.light sort: %span.light
- if @sort.present? - if @sort.present?
= sort_options_hash[@sort] = sort_options_hash[@sort]
- else - else
......
.dropdown.inline .dropdown.inline
%button.dropdown-toggle.btn{type: 'button', 'data-toggle' => 'dropdown'} %button.dropdown-toggle.btn{type: 'button', 'data-toggle' => 'dropdown'}
%span.light sort: %span.light
- if @sort.present? - if @sort.present?
= sort_options_hash[@sort] = sort_options_hash[@sort]
- elsif current_page?(trending_explore_projects_path) || current_page?(explore_root_path) - elsif current_page?(trending_explore_projects_path) || current_page?(explore_root_path)
...@@ -24,4 +24,3 @@ ...@@ -24,4 +24,3 @@
= sort_title_recently_updated = sort_title_recently_updated
= link_to explore_projects_filter_path(sort: sort_value_oldest_updated) do = link_to explore_projects_filter_path(sort: sort_value_oldest_updated) do
= sort_title_oldest_updated = sort_title_oldest_updated
...@@ -98,6 +98,13 @@ ...@@ -98,6 +98,13 @@
%span %span
Wiki Wiki
- if project_nav_tab? :forks
= nav_link(controller: :forks, action: :index) do
= link_to namespace_project_forks_path(@project.namespace, @project), title: 'Forks' do
= icon('code-fork fw')
%span
Forks
- if project_nav_tab? :snippets - if project_nav_tab? :snippets
= nav_link(controller: :snippets) do = nav_link(controller: :snippets) do
= link_to namespace_project_snippets_path(@project.namespace, @project), title: 'Snippets', class: 'shortcuts-snippets' do = link_to namespace_project_snippets_path(@project.namespace, @project), title: 'Snippets', class: 'shortcuts-snippets' do
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
&nbsp; &nbsp;
.dropdown.inline .dropdown.inline
%button.dropdown-toggle.btn{type: 'button', 'data-toggle' => 'dropdown'} %button.dropdown-toggle.btn{type: 'button', 'data-toggle' => 'dropdown'}
%span.light sort: %span.light
- if @sort.present? - if @sort.present?
= @sort.humanize = @sort.humanize
- else - else
......
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
- continue_params = { to: namespace_project_new_blob_path(@project.namespace, @project, @project.default_branch || 'master'), - continue_params = { to: namespace_project_new_blob_path(@project.namespace, @project, @project.default_branch || 'master'),
notice: edit_in_new_fork_notice, notice: edit_in_new_fork_notice,
notice_now: edit_in_new_fork_notice_now } notice_now: edit_in_new_fork_notice_now }
- fork_path = namespace_project_fork_path(@project.namespace, @project, namespace_key: current_user.namespace.id, - fork_path = namespace_project_forks_path(@project.namespace, @project, namespace_key: current_user.namespace.id,
continue: continue_params) continue: continue_params)
= link_to fork_path, method: :post do = link_to fork_path, method: :post do
= icon('file fw') = icon('file fw')
......
.gray-content-block.top-block.clearfix.white.forks-top-block
.pull-left
- public_count = @public_forks.size
- protected_count = @protected_forks.size
- full_count_title = "#{public_count} public and #{protected_count} private"
== #{pluralize(@all_forks.size, 'fork')}: #{full_count_title}
.pull-right
.projects-search-form.fork-search-form
= search_field_tag :filter_projects, nil, placeholder: 'Search forks', class: 'projects-list-filter form-control',
spellcheck: false, data: { 'filter-selector' => 'span.namespace-name' }
.dropdown.inline.prepend-left-10
%button.dropdown-toggle.btn.sort-forks{type: 'button', 'data-toggle' => 'dropdown'}
%span.light sort:
- if @sort.present?
= sort_options_hash[@sort]
- else
= sort_title_recently_created
%b.caret
%ul.dropdown-menu.dropdown-menu-align-right
%li
- excluded_filters = [:state, :scope, :label_name, :milestone_id, :assignee_id, :author_id]
= link_to page_filter_path(sort: sort_value_recently_created, without: excluded_filters) do
= sort_title_recently_created
= link_to page_filter_path(sort: sort_value_oldest_created, without: excluded_filters) do
= sort_title_oldest_created
= link_to page_filter_path(sort: sort_value_recently_updated, without: excluded_filters) do
= sort_title_recently_updated
= link_to page_filter_path(sort: sort_value_oldest_updated, without: excluded_filters) do
= sort_title_oldest_updated
.fork-link.inline
- if current_user.already_forked?(@project) && current_user.manageable_namespaces.size < 2
= link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: 'Go to your fork', class: 'pull-right btn btn-new' do
= icon('code-fork fw')
Fork
- else
= link_to new_namespace_project_fork_path(@project.namespace, @project), title: "Fork project", class: 'pull-right btn btn-new' do
= icon('code-fork fw')
Fork
.projects-list-holder
- if @public_forks.blank?
%ul.content-list
%li
.nothing-here-block No forks to show
- else
= render 'shared/projects/list', projects: @public_forks, use_creator_avatar: true,
forks: true, show_last_commit_as_description: true
- if protected_count > 0
%ul.projects-list.private-forks-notice
%li.project-row
= icon('lock fw', base: 'circle', class: 'fa-lg private-fork-icon')
%strong= pluralize(protected_count, 'private fork')
%span you have no access to.
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
- else - else
.fork-thumbnail .fork-thumbnail
= link_to namespace_project_fork_path(@project.namespace, @project, namespace_key: namespace.id), title: "Fork here", method: "POST", class: 'has_tooltip' do = link_to namespace_project_forks_path(@project.namespace, @project, namespace_key: namespace.id), title: "Fork here", method: "POST", class: 'has_tooltip' do
= image_tag namespace_icon(namespace, 100) = image_tag namespace_icon(namespace, 100)
.caption .caption
%strong %strong
......
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
- continue_params = { to: namespace_project_new_blob_path(@project.namespace, @project, @id), - continue_params = { to: namespace_project_new_blob_path(@project.namespace, @project, @id),
notice: edit_in_new_fork_notice, notice: edit_in_new_fork_notice,
notice_now: edit_in_new_fork_notice_now } notice_now: edit_in_new_fork_notice_now }
- fork_path = namespace_project_fork_path(@project.namespace, @project, namespace_key: current_user.namespace.id, - fork_path = namespace_project_forks_path(@project.namespace, @project, namespace_key: current_user.namespace.id,
continue: continue_params) continue: continue_params)
= link_to fork_path, method: :post do = link_to fork_path, method: :post do
= icon('pencil fw') = icon('pencil fw')
...@@ -49,7 +49,7 @@ ...@@ -49,7 +49,7 @@
- continue_params = { to: request.fullpath, - continue_params = { to: request.fullpath,
notice: edit_in_new_fork_notice + " Try to upload a file again.", notice: edit_in_new_fork_notice + " Try to upload a file again.",
notice_now: edit_in_new_fork_notice_now } notice_now: edit_in_new_fork_notice_now }
- fork_path = namespace_project_fork_path(@project.namespace, @project, namespace_key: current_user.namespace.id, - fork_path = namespace_project_forks_path(@project.namespace, @project, namespace_key: current_user.namespace.id,
continue: continue_params) continue: continue_params)
= link_to fork_path, method: :post do = link_to fork_path, method: :post do
= icon('file fw') = icon('file fw')
...@@ -58,7 +58,7 @@ ...@@ -58,7 +58,7 @@
- continue_params = { to: request.fullpath, - continue_params = { to: request.fullpath,
notice: edit_in_new_fork_notice + " Try to create a new directory again.", notice: edit_in_new_fork_notice + " Try to create a new directory again.",
notice_now: edit_in_new_fork_notice_now } notice_now: edit_in_new_fork_notice_now }
- fork_path = namespace_project_fork_path(@project.namespace, @project, namespace_key: current_user.namespace.id, - fork_path = namespace_project_forks_path(@project.namespace, @project, namespace_key: current_user.namespace.id,
continue: continue_params) continue: continue_params)
= link_to fork_path, method: :post do = link_to fork_path, method: :post do
= icon('folder fw') = icon('folder fw')
......
.dropdown.inline.prepend-left-10 .dropdown.inline.prepend-left-10
%button.dropdown-toggle.btn{type: 'button', 'data-toggle' => 'dropdown'} %button.dropdown-toggle.btn{type: 'button', 'data-toggle' => 'dropdown'}
%span.light sort: %span.light
- if @sort.present? - if @sort.present?
= sort_options_hash[@sort] = sort_options_hash[@sort]
- else - else
......
- projects_limit = 20 unless local_assigns[:projects_limit] - projects_limit = 20 unless local_assigns[:projects_limit]
- avatar = true unless local_assigns[:avatar] == false - avatar = true unless local_assigns[:avatar] == false
- use_creator_avatar = false unless local_assigns[:use_creator_avatar] == true
- stars = true unless local_assigns[:stars] == false - stars = true unless local_assigns[:stars] == false
- forks = false unless local_assigns[:forks] == true
- ci = false unless local_assigns[:ci] == true - ci = false unless local_assigns[:ci] == true
- skip_namespace = false unless local_assigns[:skip_namespace] == true - skip_namespace = false unless local_assigns[:skip_namespace] == true
- show_last_commit_as_description = false unless local_assigns[:show_last_commit_as_description] == true
%ul.projects-list %ul.projects-list
- projects.each_with_index do |project, i| - projects.each_with_index do |project, i|
- css_class = (i >= projects_limit) ? 'hide' : nil - css_class = (i >= projects_limit) ? 'hide' : nil
= render "shared/projects/project", project: project, skip_namespace: skip_namespace, = render "shared/projects/project", project: project, skip_namespace: skip_namespace,
avatar: avatar, stars: stars, css_class: css_class, ci: ci avatar: avatar, stars: stars, css_class: css_class, ci: ci, use_creator_avatar: use_creator_avatar,
forks: forks, show_last_commit_as_description: show_last_commit_as_description
- if projects.size > projects_limit - if projects.size > projects_limit
%li.bottom.center %li.bottom.center
......
- avatar = true unless local_assigns[:avatar] == false - avatar = true unless local_assigns[:avatar] == false
- stars = true unless local_assigns[:stars] == false - stars = true unless local_assigns[:stars] == false
- forks = false unless local_assigns[:forks] == true
- ci = false unless local_assigns[:ci] == true - ci = false unless local_assigns[:ci] == true
- skip_namespace = false unless local_assigns[:skip_namespace] == true - skip_namespace = false unless local_assigns[:skip_namespace] == true
- css_class = '' unless local_assigns[:css_class] - css_class = '' unless local_assigns[:css_class]
- css_class += " no-description" unless project.description.present? - show_last_commit_as_description = false unless local_assigns[:show_last_commit_as_description] == true
- css_class += " no-description" if project.description.blank? && !show_last_commit_as_description
- ci_commit = project.ci_commit(project.commit.sha) if ci && !project.empty_repo? && project.commit - ci_commit = project.ci_commit(project.commit.sha) if ci && !project.empty_repo? && project.commit
- cache_key = [project.namespace, project, controller.controller_name, controller.action_name, current_application_settings, 'v2.2'] - cache_key = [project.namespace, project, controller.controller_name, controller.action_name, current_application_settings, 'v2.2']
- cache_key.push(ci_commit.status) if ci_commit - cache_key.push(ci_commit.status) if ci_commit
...@@ -13,7 +15,10 @@ ...@@ -13,7 +15,10 @@
= link_to project_path(project), class: dom_class(project) do = link_to project_path(project), class: dom_class(project) do
- if avatar - if avatar
.dash-project-avatar .dash-project-avatar
= project_icon(project, alt: '', class: 'avatar project-avatar s46') - if use_creator_avatar
= image_tag avatar_icon(project.creator.email, 46), class: "avatar s46", alt:''
- else
= project_icon(project, alt: '', class: 'avatar project-avatar s46')
%span.project-full-name %span.project-full-name
%span.namespace-name %span.namespace-name
- if project.namespace && !skip_namespace - if project.namespace && !skip_namespace
...@@ -26,10 +31,18 @@ ...@@ -26,10 +31,18 @@
- if ci_commit - if ci_commit
= render_ci_status(ci_commit) = render_ci_status(ci_commit)
&nbsp; &nbsp;
- if forks
%span
= icon('code-fork')
= project.forks_count
- if stars - if stars
%span %span
%i.fa.fa-star = icon('star')
= project.star_count = project.star_count
- if project.description.present? - if show_last_commit_as_description
.project-description
= link_to_gfm project.commit.title, namespace_project_commit_path(project.namespace, project, project.commit),
class: "commit-row-message"
- elsif project.description.present?
.project-description .project-description
= markdown(project.description, pipeline: :description) = markdown(project.description, pipeline: :description)
...@@ -554,7 +554,7 @@ Rails.application.routes.draw do ...@@ -554,7 +554,7 @@ Rails.application.routes.draw do
end end
end end
resource :fork, only: [:new, :create] resources :forks, only: [:index, :new, :create]
resource :import, only: [:new, :create, :show] resource :import, only: [:new, :create, :show]
resources :refs, only: [] do resources :refs, only: [] do
......
...@@ -60,7 +60,7 @@ Parameters: ...@@ -60,7 +60,7 @@ Parameters:
Shows information about a single merge request. Shows information about a single merge request.
``` ```
GET /projects/:id/merge_request/:merge_request_id GET /projects/:id/merge_requests/:merge_request_id
``` ```
Parameters: Parameters:
...@@ -105,7 +105,7 @@ Parameters: ...@@ -105,7 +105,7 @@ Parameters:
Get a list of merge request commits. Get a list of merge request commits.
``` ```
GET /projects/:id/merge_request/:merge_request_id/commits GET /projects/:id/merge_requests/:merge_request_id/commits
``` ```
Parameters: Parameters:
...@@ -142,7 +142,7 @@ Parameters: ...@@ -142,7 +142,7 @@ Parameters:
Shows information about the merge request including its files and changes. Shows information about the merge request including its files and changes.
``` ```
GET /projects/:id/merge_request/:merge_request_id/changes GET /projects/:id/merge_requests/:merge_request_id/changes
``` ```
Parameters: Parameters:
...@@ -264,7 +264,7 @@ If an error occurs, an error number and a message explaining the reason is retur ...@@ -264,7 +264,7 @@ If an error occurs, an error number and a message explaining the reason is retur
Updates an existing merge request. You can change the target branch, title, or even close the MR. Updates an existing merge request. You can change the target branch, title, or even close the MR.
``` ```
PUT /projects/:id/merge_request/:merge_request_id PUT /projects/:id/merge_requests/:merge_request_id
``` ```
Parameters: Parameters:
...@@ -323,7 +323,7 @@ If merge request is already merged or closed - you get 405 and error message 'Me ...@@ -323,7 +323,7 @@ If merge request is already merged or closed - you get 405 and error message 'Me
If you don't have permissions to accept this merge request - you'll get a 401 If you don't have permissions to accept this merge request - you'll get a 401
``` ```
PUT /projects/:id/merge_request/:merge_request_id/merge PUT /projects/:id/merge_requests/:merge_request_id/merge
``` ```
Parameters: Parameters:
...@@ -373,7 +373,7 @@ If the merge request is already merged or closed - you get 405 and error message ...@@ -373,7 +373,7 @@ If the merge request is already merged or closed - you get 405 and error message
In case the merge request is not set to be merged when the build succeeds, you'll also get a 406 error. In case the merge request is not set to be merged when the build succeeds, you'll also get a 406 error.
``` ```
PUT /projects/:id/merge_request/:merge_request_id/cancel_merge_when_build_succeeds PUT /projects/:id/merge_requests/:merge_request_id/cancel_merge_when_build_succeeds
``` ```
Parameters: Parameters:
...@@ -409,66 +409,6 @@ Parameters: ...@@ -409,66 +409,6 @@ Parameters:
} }
``` ```
## Post comment to MR
Adds a comment to a merge request.
```
POST /projects/:id/merge_request/:merge_request_id/comments
```
Parameters:
- `id` (required) - The ID of a project
- `merge_request_id` (required) - ID of merge request
- `note` (required) - Text of comment
```json
{
"note": "text1"
}
```
## Get the comments on a MR
Gets all the comments associated with a merge request.
```
GET /projects/:id/merge_request/:merge_request_id/comments
```
Parameters:
- `id` (required) - The ID of a project
- `merge_request_id` (required) - ID of merge request
```json
[
{
"note": "this is the 1st comment on the 2merge merge request",
"author": {
"id": 11,
"username": "admin",
"email": "admin@example.com",
"name": "Administrator",
"state": "active",
"created_at": "2014-03-06T08:17:35.000Z"
}
},
{
"note": "Status changed to closed",
"author": {
"id": 11,
"username": "admin",
"email": "admin@example.com",
"name": "Administrator",
"state": "active",
"created_at": "2014-03-06T08:17:35.000Z"
}
}
]
```
## Comments on merge requets ## Comments on merge requets
Comments are done via the notes resource. Comments are done via the [notes](notes.md) resource.
...@@ -41,3 +41,33 @@ Feature: Dashboard ...@@ -41,3 +41,33 @@ Feature: Dashboard
And user with name "John Doe" left project "Shop" And user with name "John Doe" left project "Shop"
When I visit dashboard activity page When I visit dashboard activity page
Then I should see "John Doe left project Shop" event Then I should see "John Doe left project Shop" event
@javascript
Scenario: Sorting Issues
Given I visit dashboard issues page
And I sort the list by "Oldest updated"
And I visit dashboard activity page
And I visit dashboard issues page
Then The list should be sorted by "Oldest updated"
@javascript
Scenario: Visiting Project's issues after sorting
Given I visit dashboard issues page
And I sort the list by "Oldest updated"
And I visit project "Shop" issues page
Then The list should be sorted by "Oldest updated"
@javascript
Scenario: Sorting Merge Requests
Given I visit dashboard merge requests page
And I sort the list by "Oldest updated"
And I visit dashboard activity page
And I visit dashboard merge requests page
Then The list should be sorted by "Oldest updated"
@javascript
Scenario: Visiting Project's merge requests after sorting
Given I visit dashboard merge requests page
And I sort the list by "Oldest updated"
And I visit project "Shop" merge requests page
Then The list should be sorted by "Oldest updated"
...@@ -25,3 +25,18 @@ Feature: Project Fork ...@@ -25,3 +25,18 @@ Feature: Project Fork
Then I should see "New merge request" Then I should see "New merge request"
And I click link "New merge request" And I click link "New merge request"
Then I should see the new merge request page for my namespace Then I should see the new merge request page for my namespace
Scenario: Viewing forks of a Project
Given I click link "Fork"
When I fork to my namespace
And I visit the forks page of the "Shop" project
Then I should see my fork on the list
Scenario: Viewing private forks of a Project
Given There is an existent fork of the "Shop" project
And I click link "Fork"
When I fork to my namespace
And I visit the forks page of the "Shop" project
Then I should see my fork on the list
And I should not see the other fork listed
And I should see a private fork notice
...@@ -59,6 +59,28 @@ Feature: Project Issues ...@@ -59,6 +59,28 @@ Feature: Project Issues
And I sort the list by "Last updated" And I sort the list by "Last updated"
Then I should see "Release 0.4" at the top Then I should see "Release 0.4" at the top
@javascript
Scenario: Visiting Issues after being sorted the list
Given I visit project "Shop" issues page
And I sort the list by "Oldest updated"
And I visit my project's home page
And I visit project "Shop" issues page
Then The list should be sorted by "Oldest updated"
@javascript
Scenario: Visiting Merge Requests after being sorted the list
Given I visit project "Shop" issues page
And I sort the list by "Oldest updated"
And I visit project "Shop" merge requests page
Then The list should be sorted by "Oldest updated"
@javascript
Scenario: Visiting Merge Requests from a differente Project after sorting
Given I visit project "Shop" merge requests page
And I sort the list by "Oldest updated"
And I visit dashboard merge requests page
Then The list should be sorted by "Oldest updated"
@javascript @javascript
Scenario: I search issue Scenario: I search issue
Given I fill in issue search with "Re" Given I fill in issue search with "Re"
......
...@@ -84,6 +84,28 @@ Feature: Project Merge Requests ...@@ -84,6 +84,28 @@ Feature: Project Merge Requests
And I sort the list by "Last updated" And I sort the list by "Last updated"
Then I should see "Bug NS-04" at the top Then I should see "Bug NS-04" at the top
@javascript
Scenario: Visiting Merge Requests after being sorted the list
Given I visit project "Shop" merge requests page
And I sort the list by "Oldest updated"
And I visit my project's home page
And I visit project "Shop" merge requests page
Then The list should be sorted by "Oldest updated"
@javascript
Scenario: Visiting Issues after being sorted the list
Given I visit project "Shop" merge requests page
And I sort the list by "Oldest updated"
And I visit project "Shop" issues page
Then The list should be sorted by "Oldest updated"
@javascript
Scenario: Visiting Merge Requests from a differente Project after sorting
Given I visit project "Shop" merge requests page
And I sort the list by "Oldest updated"
And I visit dashboard merge requests page
Then The list should be sorted by "Oldest updated"
@javascript @javascript
Scenario: Visiting Merge Requests after commenting on diffs Scenario: Visiting Merge Requests after commenting on diffs
Given project "Shop" have "Bug NS-05" open merge request with diffs inside Given project "Shop" have "Bug NS-05" open merge request with diffs inside
......
...@@ -2,6 +2,7 @@ class Spinach::Features::Dashboard < Spinach::FeatureSteps ...@@ -2,6 +2,7 @@ class Spinach::Features::Dashboard < Spinach::FeatureSteps
include SharedAuthentication include SharedAuthentication
include SharedPaths include SharedPaths
include SharedProject include SharedProject
include SharedIssuable
step 'I should see "New Project" link' do step 'I should see "New Project" link' do
expect(page).to have_link "New project" expect(page).to have_link "New project"
......
...@@ -49,4 +49,29 @@ class Spinach::Features::ProjectFork < Spinach::FeatureSteps ...@@ -49,4 +49,29 @@ class Spinach::Features::ProjectFork < Spinach::FeatureSteps
step 'I should see the new merge request page for my namespace' do step 'I should see the new merge request page for my namespace' do
current_path.should have_content(/#{current_user.namespace.name}/i) current_path.should have_content(/#{current_user.namespace.name}/i)
end end
step 'I visit the forks page of the "Shop" project' do
@project = Project.where(name: 'Shop').last
visit namespace_project_forks_path(@project.namespace, @project)
end
step 'I should see my fork on the list' do
page.within('.projects-list-holder') do
project = @user.fork_of(@project)
expect(page).to have_content("#{project.namespace.human_name} / #{project.name}")
end
end
step 'There is an existent fork of the "Shop" project' do
user = create(:user, name: 'Mike')
@forked_project = Projects::ForkService.new(@project, user).execute
end
step 'I should not see the other fork listed' do
expect(page).not_to have_content("#{@forked_project.namespace.human_name} / #{@forked_project.name}")
end
step 'I should see a private fork notice' do
expect(page).to have_content("1 private fork")
end
end end
...@@ -43,7 +43,9 @@ class Spinach::Features::ProjectForkedMergeRequests < Spinach::FeatureSteps ...@@ -43,7 +43,9 @@ class Spinach::Features::ProjectForkedMergeRequests < Spinach::FeatureSteps
expect(page).to have_css("h3.page-title", text: "New Merge Request") expect(page).to have_css("h3.page-title", text: "New Merge Request")
fill_in "merge_request_title", with: "Merge Request On Forked Project" page.within 'form#new_merge_request' do
fill_in "merge_request_title", with: "Merge Request On Forked Project"
end
end end
step 'I submit the merge request' do step 'I submit the merge request' do
......
...@@ -106,6 +106,19 @@ module SharedIssuable ...@@ -106,6 +106,19 @@ module SharedIssuable
edit_issuable edit_issuable
end end
step 'I sort the list by "Oldest updated"' do
find('button.dropdown-toggle.btn').click
page.within('ul.dropdown-menu.dropdown-menu-align-right li') do
click_link "Oldest updated"
end
end
step 'The list should be sorted by "Oldest updated"' do
page.within('div.dropdown.inline.prepend-left-10') do
expect(page.find('button.dropdown-toggle.btn')).to have_content('Oldest updated')
end
end
def create_issuable_for_project(project_name:, title:, type: :issue) def create_issuable_for_project(project_name:, title:, type: :issue)
project = Project.find_by(name: project_name) project = Project.find_by(name: project_name)
......
...@@ -59,55 +59,6 @@ module API ...@@ -59,55 +59,6 @@ module API
present paginate(merge_requests), with: Entities::MergeRequest present paginate(merge_requests), with: Entities::MergeRequest
end end
# Show MR
#
# Parameters:
# id (required) - The ID of a project
# merge_request_id (required) - The ID of MR
#
# Example:
# GET /projects/:id/merge_request/:merge_request_id
#
get ":id/merge_request/:merge_request_id" do
merge_request = user_project.merge_requests.find(params[:merge_request_id])
authorize! :read_merge_request, merge_request
present merge_request, with: Entities::MergeRequest
end
# Show MR commits
#
# Parameters:
# id (required) - The ID of a project
# merge_request_id (required) - The ID of MR
#
# Example:
# GET /projects/:id/merge_request/:merge_request_id/commits
#
get ':id/merge_request/:merge_request_id/commits' do
merge_request = user_project.merge_requests.
find(params[:merge_request_id])
authorize! :read_merge_request, merge_request
present merge_request.commits, with: Entities::RepoCommit
end
# Show MR changes
#
# Parameters:
# id (required) - The ID of a project
# merge_request_id (required) - The ID of MR
#
# Example:
# GET /projects/:id/merge_request/:merge_request_id/changes
#
get ':id/merge_request/:merge_request_id/changes' do
merge_request = user_project.merge_requests.
find(params[:merge_request_id])
authorize! :read_merge_request, merge_request
present merge_request, with: Entities::MergeRequestChanges
end
# Create MR # Create MR
# #
# Parameters: # Parameters:
...@@ -148,146 +99,206 @@ module API ...@@ -148,146 +99,206 @@ module API
end end
end end
# Update MR # Routing "merge_request/:merge_request_id/..." is DEPRECATED and WILL BE REMOVED in version 9.0
# Use "merge_requests/:merge_request_id/..." instead.
# #
# Parameters: [":id/merge_request/:merge_request_id", ":id/merge_requests/:merge_request_id"].each do |path|
# id (required) - The ID of a project # Show MR
# merge_request_id (required) - ID of MR #
# target_branch - The target branch # Parameters:
# assignee_id - Assignee user ID # id (required) - The ID of a project
# title - Title of MR # merge_request_id (required) - The ID of MR
# state_event - Status of MR. (close|reopen|merge) #
# description - Description of MR # Example:
# labels (optional) - Labels for a MR as a comma-separated list # GET /projects/:id/merge_requests/:merge_request_id
# Example: #
# PUT /projects/:id/merge_request/:merge_request_id get path do
# merge_request = user_project.merge_requests.find(params[:merge_request_id])
put ":id/merge_request/:merge_request_id" do
attrs = attributes_for_keys [:target_branch, :assignee_id, :title, :state_event, :description] authorize! :read_merge_request, merge_request
merge_request = user_project.merge_requests.find(params[:merge_request_id])
authorize! :update_merge_request, merge_request
# Ensure source_branch is not specified
if params[:source_branch].present?
render_api_error!('Source branch cannot be changed', 400)
end
# Validate label names in advance
if (errors = validate_label_params(params)).any?
render_api_error!({ labels: errors }, 400)
end
merge_request = ::MergeRequests::UpdateService.new(user_project, current_user, attrs).execute(merge_request)
if merge_request.valid?
# Find or create labels and attach to issue
unless params[:labels].nil?
merge_request.remove_labels
merge_request.add_labels_by_names(params[:labels].split(","))
end
present merge_request, with: Entities::MergeRequest present merge_request, with: Entities::MergeRequest
else
handle_merge_request_errors! merge_request.errors
end end
end
# Merge MR
#
# Parameters:
# id (required) - The ID of a project
# merge_request_id (required) - ID of MR
# merge_commit_message (optional) - Custom merge commit message
# should_remove_source_branch (optional) - When true, the source branch will be deleted if possible
# merge_when_build_succeeds (optional) - When true, this MR will be merged when the build succeeds
# Example:
# PUT /projects/:id/merge_request/:merge_request_id/merge
#
put ":id/merge_request/:merge_request_id/merge" do
merge_request = user_project.merge_requests.find(params[:merge_request_id])
# Merge request can not be merged
# because user dont have permissions to push into target branch
unauthorized! unless merge_request.can_be_merged_by?(current_user)
not_allowed! if !merge_request.open? || merge_request.work_in_progress?
merge_request.check_if_can_be_merged # Show MR commits
#
render_api_error!('Branch cannot be merged', 406) unless merge_request.can_be_merged? # Parameters:
# id (required) - The ID of a project
merge_params = { # merge_request_id (required) - The ID of MR
commit_message: params[:merge_commit_message], #
should_remove_source_branch: params[:should_remove_source_branch] # Example:
} # GET /projects/:id/merge_requests/:merge_request_id/commits
#
if parse_boolean(params[:merge_when_build_succeeds]) && merge_request.ci_commit && merge_request.ci_commit.active? get "#{path}/commits" do
::MergeRequests::MergeWhenBuildSucceedsService.new(merge_request.target_project, current_user, merge_params). merge_request = user_project.merge_requests.
execute(merge_request) find(params[:merge_request_id])
else authorize! :read_merge_request, merge_request
::MergeRequests::MergeService.new(merge_request.target_project, current_user, merge_params). present merge_request.commits, with: Entities::RepoCommit
execute(merge_request)
end end
present merge_request, with: Entities::MergeRequest # Show MR changes
end #
# Parameters:
# id (required) - The ID of a project
# merge_request_id (required) - The ID of MR
#
# Example:
# GET /projects/:id/merge_requests/:merge_request_id/changes
#
get "#{path}/changes" do
merge_request = user_project.merge_requests.
find(params[:merge_request_id])
authorize! :read_merge_request, merge_request
present merge_request, with: Entities::MergeRequestChanges
end
# Cancel Merge if Merge When build succeeds is enabled # Update MR
# Parameters: #
# id (required) - The ID of a project # Parameters:
# merge_request_id (required) - ID of MR # id (required) - The ID of a project
# # merge_request_id (required) - ID of MR
post ":id/merge_request/:merge_request_id/cancel_merge_when_build_succeeds" do # target_branch - The target branch
merge_request = user_project.merge_requests.find(params[:merge_request_id]) # assignee_id - Assignee user ID
# title - Title of MR
# state_event - Status of MR. (close|reopen|merge)
# description - Description of MR
# labels (optional) - Labels for a MR as a comma-separated list
# Example:
# PUT /projects/:id/merge_requests/:merge_request_id
#
put path do
attrs = attributes_for_keys [:target_branch, :assignee_id, :title, :state_event, :description]
merge_request = user_project.merge_requests.find(params[:merge_request_id])
authorize! :update_merge_request, merge_request
# Ensure source_branch is not specified
if params[:source_branch].present?
render_api_error!('Source branch cannot be changed', 400)
end
unauthorized! unless merge_request.can_cancel_merge_when_build_succeeds?(current_user) # Validate label names in advance
if (errors = validate_label_params(params)).any?
render_api_error!({ labels: errors }, 400)
end
::MergeRequest::MergeWhenBuildSucceedsService.new(merge_request.target_project, current_user).cancel(merge_request) merge_request = ::MergeRequests::UpdateService.new(user_project, current_user, attrs).execute(merge_request)
end
# Get a merge request's comments if merge_request.valid?
# # Find or create labels and attach to issue
# Parameters: unless params[:labels].nil?
# id (required) - The ID of a project merge_request.remove_labels
# merge_request_id (required) - ID of MR merge_request.add_labels_by_names(params[:labels].split(","))
# Examples: end
# GET /projects/:id/merge_request/:merge_request_id/comments
#
get ":id/merge_request/:merge_request_id/comments" do
merge_request = user_project.merge_requests.find(params[:merge_request_id])
authorize! :read_merge_request, merge_request present merge_request, with: Entities::MergeRequest
else
handle_merge_request_errors! merge_request.errors
end
end
present paginate(merge_request.notes.fresh), with: Entities::MRNote # Merge MR
end #
# Parameters:
# id (required) - The ID of a project
# merge_request_id (required) - ID of MR
# merge_commit_message (optional) - Custom merge commit message
# should_remove_source_branch (optional) - When true, the source branch will be deleted if possible
# merge_when_build_succeeds (optional) - When true, this MR will be merged when the build succeeds
# Example:
# PUT /projects/:id/merge_requests/:merge_request_id/merge
#
put "#{path}/merge" do
merge_request = user_project.merge_requests.find(params[:merge_request_id])
# Merge request can not be merged
# because user dont have permissions to push into target branch
unauthorized! unless merge_request.can_be_merged_by?(current_user)
not_allowed! if !merge_request.open? || merge_request.work_in_progress?
merge_request.check_if_can_be_merged
render_api_error!('Branch cannot be merged', 406) unless merge_request.can_be_merged?
merge_params = {
commit_message: params[:merge_commit_message],
should_remove_source_branch: params[:should_remove_source_branch]
}
if parse_boolean(params[:merge_when_build_succeeds]) && merge_request.ci_commit && merge_request.ci_commit.active?
::MergeRequests::MergeWhenBuildSucceedsService.new(merge_request.target_project, current_user, merge_params).
execute(merge_request)
else
::MergeRequests::MergeService.new(merge_request.target_project, current_user, merge_params).
execute(merge_request)
end
# Post comment to merge request present merge_request, with: Entities::MergeRequest
# end
# Parameters:
# id (required) - The ID of a project
# merge_request_id (required) - ID of MR
# note (required) - Text of comment
# Examples:
# POST /projects/:id/merge_request/:merge_request_id/comments
#
post ":id/merge_request/:merge_request_id/comments" do
required_attributes! [:note]
merge_request = user_project.merge_requests.find(params[:merge_request_id]) # Cancel Merge if Merge When build succeeds is enabled
# Parameters:
# id (required) - The ID of a project
# merge_request_id (required) - ID of MR
#
post "#{path}/cancel_merge_when_build_succeeds" do
merge_request = user_project.merge_requests.find(params[:merge_request_id])
authorize! :create_note, merge_request unauthorized! unless merge_request.can_cancel_merge_when_build_succeeds?(current_user)
opts = { ::MergeRequest::MergeWhenBuildSucceedsService.new(merge_request.target_project, current_user).cancel(merge_request)
note: params[:note], end
noteable_type: 'MergeRequest',
noteable_id: merge_request.id
}
note = ::Notes::CreateService.new(user_project, current_user, opts).execute # Duplicate. DEPRECATED and WILL BE REMOVED in 9.0.
# Use GET "/projects/:id/merge_requests/:merge_request_id/notes" instead
#
# Get a merge request's comments
#
# Parameters:
# id (required) - The ID of a project
# merge_request_id (required) - ID of MR
# Examples:
# GET /projects/:id/merge_requests/:merge_request_id/comments
#
get "#{path}/comments" do
merge_request = user_project.merge_requests.find(params[:merge_request_id])
authorize! :read_merge_request, merge_request
present paginate(merge_request.notes.fresh), with: Entities::MRNote
end
if note.save # Duplicate. DEPRECATED and WILL BE REMOVED in 9.0.
present note, with: Entities::MRNote # Use POST "/projects/:id/merge_requests/:merge_request_id/notes" instead
else #
render_api_error!("Failed to save note #{note.errors.messages}", 400) # Post comment to merge request
#
# Parameters:
# id (required) - The ID of a project
# merge_request_id (required) - ID of MR
# note (required) - Text of comment
# Examples:
# POST /projects/:id/merge_requests/:merge_request_id/comments
#
post "#{path}/comments" do
required_attributes! [:note]
merge_request = user_project.merge_requests.find(params[:merge_request_id])
authorize! :create_note, merge_request
opts = {
note: params[:note],
noteable_type: 'MergeRequest',
noteable_id: merge_request.id
}
note = ::Notes::CreateService.new(user_project, current_user, opts).execute
if note.save
present note, with: Entities::MRNote
else
render_api_error!("Failed to save note #{note.errors.messages}", 400)
end
end end
end end
end end
......
...@@ -4,11 +4,14 @@ module Gitlab ...@@ -4,11 +4,14 @@ module Gitlab
key = :current_application_settings key = :current_application_settings
RequestStore.store[key] ||= begin RequestStore.store[key] ||= begin
settings = nil
if connect_to_db? if connect_to_db?
ApplicationSetting.current || ApplicationSetting.create_from_defaults settings = ApplicationSetting.current
else settings ||= ApplicationSetting.create_from_defaults unless ActiveRecord::Migrator.needs_migration?
fake_application_settings
end end
settings || fake_application_settings
end end
end end
...@@ -18,28 +21,32 @@ module Gitlab ...@@ -18,28 +21,32 @@ module Gitlab
default_branch_protection: Settings.gitlab['default_branch_protection'], default_branch_protection: Settings.gitlab['default_branch_protection'],
signup_enabled: Settings.gitlab['signup_enabled'], signup_enabled: Settings.gitlab['signup_enabled'],
signin_enabled: Settings.gitlab['signin_enabled'], signin_enabled: Settings.gitlab['signin_enabled'],
twitter_sharing_enabled: Settings.gitlab['twitter_sharing_enabled'],
gravatar_enabled: Settings.gravatar['enabled'], gravatar_enabled: Settings.gravatar['enabled'],
sign_in_text: Settings.extra['sign_in_text'], sign_in_text: Settings.extra['sign_in_text'],
restricted_visibility_levels: Settings.gitlab['restricted_visibility_levels'], restricted_visibility_levels: Settings.gitlab['restricted_visibility_levels'],
max_attachment_size: Settings.gitlab['max_attachment_size'], max_attachment_size: Settings.gitlab['max_attachment_size'],
session_expire_delay: Settings.gitlab['session_expire_delay'], session_expire_delay: Settings.gitlab['session_expire_delay'],
import_sources: Settings.gitlab['import_sources'], default_project_visibility: Settings.gitlab.default_projects_features['visibility_level'],
default_snippet_visibility: Settings.gitlab.default_projects_features['visibility_level'],
restricted_signup_domains: Settings.gitlab['restricted_signup_domains'],
import_sources: ['github','bitbucket','gitlab','gitorious','google_code','fogbugz','git'],
shared_runners_enabled: Settings.gitlab_ci['shared_runners_enabled'], shared_runners_enabled: Settings.gitlab_ci['shared_runners_enabled'],
max_artifacts_size: Settings.artifacts['max_size'], max_artifacts_size: Settings.artifacts['max_size'],
require_two_factor_authentication: false,
two_factor_grace_period: 48
) )
end end
private private
def connect_to_db? def connect_to_db?
use_db = if ENV['USE_DB'] == "false" # When the DBMS is not available, an exception (e.g. PG::ConnectionBad) is raised
false active_db_connection = ActiveRecord::Base.connection.active? rescue false
else
true ENV['USE_DB'] != 'false' &&
end active_db_connection &&
ActiveRecord::Base.connection.table_exists?('application_settings')
use_db && ActiveRecord::Base.connection.active? &&
ActiveRecord::Base.connection.table_exists?('application_settings')
rescue ActiveRecord::NoDatabaseError rescue ActiveRecord::NoDatabaseError
false false
......
...@@ -109,9 +109,9 @@ describe API::API, api: true do ...@@ -109,9 +109,9 @@ describe API::API, api: true do
end end
end end
describe "GET /projects/:id/merge_request/:merge_request_id" do describe "GET /projects/:id/merge_requests/:merge_request_id" do
it "should return merge_request" do it "should return merge_request" do
get api("/projects/#{project.id}/merge_request/#{merge_request.id}", user) get api("/projects/#{project.id}/merge_requests/#{merge_request.id}", user)
expect(response.status).to eq(200) expect(response.status).to eq(200)
expect(json_response['title']).to eq(merge_request.title) expect(json_response['title']).to eq(merge_request.title)
expect(json_response['iid']).to eq(merge_request.iid) expect(json_response['iid']).to eq(merge_request.iid)
...@@ -126,14 +126,14 @@ describe API::API, api: true do ...@@ -126,14 +126,14 @@ describe API::API, api: true do
end end
it "should return a 404 error if merge_request_id not found" do it "should return a 404 error if merge_request_id not found" do
get api("/projects/#{project.id}/merge_request/999", user) get api("/projects/#{project.id}/merge_requests/999", user)
expect(response.status).to eq(404) expect(response.status).to eq(404)
end end
end end
describe 'GET /projects/:id/merge_request/:merge_request_id/commits' do describe 'GET /projects/:id/merge_requests/:merge_request_id/commits' do
context 'valid merge request' do context 'valid merge request' do
before { get api("/projects/#{project.id}/merge_request/#{merge_request.id}/commits", user) } before { get api("/projects/#{project.id}/merge_requests/#{merge_request.id}/commits", user) }
let(:commit) { merge_request.commits.first } let(:commit) { merge_request.commits.first }
it { expect(response.status).to eq 200 } it { expect(response.status).to eq 200 }
...@@ -143,20 +143,20 @@ describe API::API, api: true do ...@@ -143,20 +143,20 @@ describe API::API, api: true do
end end
it 'returns a 404 when merge_request_id not found' do it 'returns a 404 when merge_request_id not found' do
get api("/projects/#{project.id}/merge_request/999/commits", user) get api("/projects/#{project.id}/merge_requests/999/commits", user)
expect(response.status).to eq(404) expect(response.status).to eq(404)
end end
end end
describe 'GET /projects/:id/merge_request/:merge_request_id/changes' do describe 'GET /projects/:id/merge_requests/:merge_request_id/changes' do
it 'should return the change information of the merge_request' do it 'should return the change information of the merge_request' do
get api("/projects/#{project.id}/merge_request/#{merge_request.id}/changes", user) get api("/projects/#{project.id}/merge_requests/#{merge_request.id}/changes", user)
expect(response.status).to eq 200 expect(response.status).to eq 200
expect(json_response['changes'].size).to eq(merge_request.diffs.size) expect(json_response['changes'].size).to eq(merge_request.diffs.size)
end end
it 'returns a 404 when merge_request_id not found' do it 'returns a 404 when merge_request_id not found' do
get api("/projects/#{project.id}/merge_request/999/changes", user) get api("/projects/#{project.id}/merge_requests/999/changes", user)
expect(response.status).to eq(404) expect(response.status).to eq(404)
end end
end end
...@@ -311,19 +311,19 @@ describe API::API, api: true do ...@@ -311,19 +311,19 @@ describe API::API, api: true do
end end
end end
describe "PUT /projects/:id/merge_request/:merge_request_id to close MR" do describe "PUT /projects/:id/merge_requests/:merge_request_id to close MR" do
it "should return merge_request" do it "should return merge_request" do
put api("/projects/#{project.id}/merge_request/#{merge_request.id}", user), state_event: "close" put api("/projects/#{project.id}/merge_requests/#{merge_request.id}", user), state_event: "close"
expect(response.status).to eq(200) expect(response.status).to eq(200)
expect(json_response['state']).to eq('closed') expect(json_response['state']).to eq('closed')
end end
end end
describe "PUT /projects/:id/merge_request/:merge_request_id/merge" do describe "PUT /projects/:id/merge_requests/:merge_request_id/merge" do
let(:ci_commit) { create(:ci_commit_without_jobs) } let(:ci_commit) { create(:ci_commit_without_jobs) }
it "should return merge_request in case of success" do it "should return merge_request in case of success" do
put api("/projects/#{project.id}/merge_request/#{merge_request.id}/merge", user) put api("/projects/#{project.id}/merge_requests/#{merge_request.id}/merge", user)
expect(response.status).to eq(200) expect(response.status).to eq(200)
end end
...@@ -332,7 +332,7 @@ describe API::API, api: true do ...@@ -332,7 +332,7 @@ describe API::API, api: true do
allow_any_instance_of(MergeRequest). allow_any_instance_of(MergeRequest).
to receive(:can_be_merged?).and_return(false) to receive(:can_be_merged?).and_return(false)
put api("/projects/#{project.id}/merge_request/#{merge_request.id}/merge", user) put api("/projects/#{project.id}/merge_requests/#{merge_request.id}/merge", user)
expect(response.status).to eq(406) expect(response.status).to eq(406)
expect(json_response['message']).to eq('Branch cannot be merged') expect(json_response['message']).to eq('Branch cannot be merged')
...@@ -340,14 +340,14 @@ describe API::API, api: true do ...@@ -340,14 +340,14 @@ describe API::API, api: true do
it "should return 405 if merge_request is not open" do it "should return 405 if merge_request is not open" do
merge_request.close merge_request.close
put api("/projects/#{project.id}/merge_request/#{merge_request.id}/merge", user) put api("/projects/#{project.id}/merge_requests/#{merge_request.id}/merge", user)
expect(response.status).to eq(405) expect(response.status).to eq(405)
expect(json_response['message']).to eq('405 Method Not Allowed') expect(json_response['message']).to eq('405 Method Not Allowed')
end end
it "should return 405 if merge_request is a work in progress" do it "should return 405 if merge_request is a work in progress" do
merge_request.update_attribute(:title, "WIP: #{merge_request.title}") merge_request.update_attribute(:title, "WIP: #{merge_request.title}")
put api("/projects/#{project.id}/merge_request/#{merge_request.id}/merge", user) put api("/projects/#{project.id}/merge_requests/#{merge_request.id}/merge", user)
expect(response.status).to eq(405) expect(response.status).to eq(405)
expect(json_response['message']).to eq('405 Method Not Allowed') expect(json_response['message']).to eq('405 Method Not Allowed')
end end
...@@ -355,7 +355,7 @@ describe API::API, api: true do ...@@ -355,7 +355,7 @@ describe API::API, api: true do
it "should return 401 if user has no permissions to merge" do it "should return 401 if user has no permissions to merge" do
user2 = create(:user) user2 = create(:user)
project.team << [user2, :reporter] project.team << [user2, :reporter]
put api("/projects/#{project.id}/merge_request/#{merge_request.id}/merge", user2) put api("/projects/#{project.id}/merge_requests/#{merge_request.id}/merge", user2)
expect(response.status).to eq(401) expect(response.status).to eq(401)
expect(json_response['message']).to eq('401 Unauthorized') expect(json_response['message']).to eq('401 Unauthorized')
end end
...@@ -364,7 +364,7 @@ describe API::API, api: true do ...@@ -364,7 +364,7 @@ describe API::API, api: true do
allow_any_instance_of(MergeRequest).to receive(:ci_commit).and_return(ci_commit) allow_any_instance_of(MergeRequest).to receive(:ci_commit).and_return(ci_commit)
allow(ci_commit).to receive(:active?).and_return(true) allow(ci_commit).to receive(:active?).and_return(true)
put api("/projects/#{project.id}/merge_request/#{merge_request.id}/merge", user), merge_when_build_succeeds: true put api("/projects/#{project.id}/merge_requests/#{merge_request.id}/merge", user), merge_when_build_succeeds: true
expect(response.status).to eq(200) expect(response.status).to eq(200)
expect(json_response['title']).to eq('Test') expect(json_response['title']).to eq('Test')
...@@ -372,33 +372,33 @@ describe API::API, api: true do ...@@ -372,33 +372,33 @@ describe API::API, api: true do
end end
end end
describe "PUT /projects/:id/merge_request/:merge_request_id" do describe "PUT /projects/:id/merge_requests/:merge_request_id" do
it "should return merge_request" do it "should return merge_request" do
put api("/projects/#{project.id}/merge_request/#{merge_request.id}", user), title: "New title" put api("/projects/#{project.id}/merge_requests/#{merge_request.id}", user), title: "New title"
expect(response.status).to eq(200) expect(response.status).to eq(200)
expect(json_response['title']).to eq('New title') expect(json_response['title']).to eq('New title')
end end
it "should return merge_request" do it "should return merge_request" do
put api("/projects/#{project.id}/merge_request/#{merge_request.id}", user), description: "New description" put api("/projects/#{project.id}/merge_requests/#{merge_request.id}", user), description: "New description"
expect(response.status).to eq(200) expect(response.status).to eq(200)
expect(json_response['description']).to eq('New description') expect(json_response['description']).to eq('New description')
end end
it "should return 400 when source_branch is specified" do it "should return 400 when source_branch is specified" do
put api("/projects/#{project.id}/merge_request/#{merge_request.id}", user), put api("/projects/#{project.id}/merge_requests/#{merge_request.id}", user),
source_branch: "master", target_branch: "master" source_branch: "master", target_branch: "master"
expect(response.status).to eq(400) expect(response.status).to eq(400)
end end
it "should return merge_request with renamed target_branch" do it "should return merge_request with renamed target_branch" do
put api("/projects/#{project.id}/merge_request/#{merge_request.id}", user), target_branch: "wiki" put api("/projects/#{project.id}/merge_requests/#{merge_request.id}", user), target_branch: "wiki"
expect(response.status).to eq(200) expect(response.status).to eq(200)
expect(json_response['target_branch']).to eq('wiki') expect(json_response['target_branch']).to eq('wiki')
end end
it 'should return 400 on invalid label names' do it 'should return 400 on invalid label names' do
put api("/projects/#{project.id}/merge_request/#{merge_request.id}", put api("/projects/#{project.id}/merge_requests/#{merge_request.id}",
user), user),
title: 'new issue', title: 'new issue',
labels: 'label, ?' labels: 'label, ?'
...@@ -407,11 +407,11 @@ describe API::API, api: true do ...@@ -407,11 +407,11 @@ describe API::API, api: true do
end end
end end
describe "POST /projects/:id/merge_request/:merge_request_id/comments" do describe "POST /projects/:id/merge_requests/:merge_request_id/comments" do
it "should return comment" do it "should return comment" do
original_count = merge_request.notes.size original_count = merge_request.notes.size
post api("/projects/#{project.id}/merge_request/#{merge_request.id}/comments", user), note: "My comment" post api("/projects/#{project.id}/merge_requests/#{merge_request.id}/comments", user), note: "My comment"
expect(response.status).to eq(201) expect(response.status).to eq(201)
expect(json_response['note']).to eq('My comment') expect(json_response['note']).to eq('My comment')
expect(json_response['author']['name']).to eq(user.name) expect(json_response['author']['name']).to eq(user.name)
...@@ -420,20 +420,20 @@ describe API::API, api: true do ...@@ -420,20 +420,20 @@ describe API::API, api: true do
end end
it "should return 400 if note is missing" do it "should return 400 if note is missing" do
post api("/projects/#{project.id}/merge_request/#{merge_request.id}/comments", user) post api("/projects/#{project.id}/merge_requests/#{merge_request.id}/comments", user)
expect(response.status).to eq(400) expect(response.status).to eq(400)
end end
it "should return 404 if note is attached to non existent merge request" do it "should return 404 if note is attached to non existent merge request" do
post api("/projects/#{project.id}/merge_request/404/comments", user), post api("/projects/#{project.id}/merge_requests/404/comments", user),
note: 'My comment' note: 'My comment'
expect(response.status).to eq(404) expect(response.status).to eq(404)
end end
end end
describe "GET :id/merge_request/:merge_request_id/comments" do describe "GET :id/merge_requests/:merge_request_id/comments" do
it "should return merge_request comments ordered by created_at" do it "should return merge_request comments ordered by created_at" do
get api("/projects/#{project.id}/merge_request/#{merge_request.id}/comments", user) get api("/projects/#{project.id}/merge_requests/#{merge_request.id}/comments", user)
expect(response.status).to eq(200) expect(response.status).to eq(200)
expect(json_response).to be_an Array expect(json_response).to be_an Array
expect(json_response.length).to eq(2) expect(json_response.length).to eq(2)
...@@ -443,7 +443,7 @@ describe API::API, api: true do ...@@ -443,7 +443,7 @@ describe API::API, api: true do
end end
it "should return a 404 error if merge_request_id not found" do it "should return a 404 error if merge_request_id not found" do
get api("/projects/#{project.id}/merge_request/999/comments", user) get api("/projects/#{project.id}/merge_requests/999/comments", user)
expect(response.status).to eq(404) expect(response.status).to eq(404)
end end
end end
......
...@@ -496,11 +496,11 @@ end ...@@ -496,11 +496,11 @@ end
describe Projects::ForksController, 'routing' do describe Projects::ForksController, 'routing' do
it 'to #new' do it 'to #new' do
expect(get('/gitlab/gitlabhq/fork/new')).to route_to('projects/forks#new', namespace_id: 'gitlab', project_id: 'gitlabhq') expect(get('/gitlab/gitlabhq/forks/new')).to route_to('projects/forks#new', namespace_id: 'gitlab', project_id: 'gitlabhq')
end end
it 'to #create' do it 'to #create' do
expect(post('/gitlab/gitlabhq/fork')).to route_to('projects/forks#create', namespace_id: 'gitlab', project_id: 'gitlabhq') expect(post('/gitlab/gitlabhq/forks')).to route_to('projects/forks#create', namespace_id: 'gitlab', project_id: 'gitlabhq')
end end
end end
......
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