Commit d77f333f authored by Marin Jankovski's avatar Marin Jankovski

Merge branch 'master' of gitlab.com:gitlab-org/gitlab-ce

Conflicts:
	lib/gitlab/markdown.rb
parents 96d093e5 c14c03a8
...@@ -49,6 +49,9 @@ v 7.10.0 (unreleased) ...@@ -49,6 +49,9 @@ v 7.10.0 (unreleased)
- Improve file icons rendering on tree (Sullivan Sénéchal) - Improve file icons rendering on tree (Sullivan Sénéchal)
- API: Add pagination to project events - API: Add pagination to project events
- Get issue links in notification mail to work again. - Get issue links in notification mail to work again.
- Don't show commit comment button when user is not signed in.
- Fix admin user projects lists.
- Don't leak private group existence by redirecting from namespace controller to group controller.
v 7.9.0 v 7.9.0
- Send EmailsOnPush email when branch or tag is created or deleted. - Send EmailsOnPush email when branch or tag is created or deleted.
......
...@@ -100,6 +100,8 @@ class Dispatcher ...@@ -100,6 +100,8 @@ class Dispatcher
when 'users:show' when 'users:show'
new User() new User()
new Activities() new Activities()
when 'admin:users:show'
new ProjectsList()
switch path.first() switch path.first()
when 'admin' when 'admin'
......
...@@ -9,12 +9,8 @@ class @Issue ...@@ -9,12 +9,8 @@ class @Issue
if $("a.btn-close").length if $("a.btn-close").length
$("li.task-list-item input:checkbox").prop("disabled", false) $("li.task-list-item input:checkbox").prop("disabled", false)
$(".task-list-item input:checkbox").on( $('.task-list-item input:checkbox').off('change')
"click" $('.task-list-item input:checkbox').change('issue', updateTaskState)
null
"issue"
updateTaskState
)
$('.issue-details').waitForImages -> $('.issue-details').waitForImages ->
$('.issuable-affix').affix offset: $('.issuable-affix').affix offset:
......
...@@ -81,12 +81,8 @@ class @MergeRequest ...@@ -81,12 +81,8 @@ class @MergeRequest
this.$('.remove_source_branch_in_progress').hide() this.$('.remove_source_branch_in_progress').hide()
this.$('.remove_source_branch_widget.failed').show() this.$('.remove_source_branch_widget.failed').show()
$(".task-list-item input:checkbox").on( $('.task-list-item input:checkbox').off('change')
"click" $('.task-list-item input:checkbox').change('merge_request', updateTaskState)
null
"merge_request"
updateTaskState
)
activateTab: (action) -> activateTab: (action) ->
this.$('.merge-request-tabs li').removeClass 'active' this.$('.merge-request-tabs li').removeClass 'active'
......
...@@ -246,7 +246,7 @@ li.note { ...@@ -246,7 +246,7 @@ li.note {
.milestone { .milestone {
&.milestone-closed { &.milestone-closed {
background: #eee; background: #f9f9f9;
} }
.progress { .progress {
margin-bottom: 0; margin-bottom: 0;
......
...@@ -4,14 +4,22 @@ class NamespacesController < ApplicationController ...@@ -4,14 +4,22 @@ class NamespacesController < ApplicationController
def show def show
namespace = Namespace.find_by(path: params[:id]) namespace = Namespace.find_by(path: params[:id])
unless namespace if namespace
return render_404 if namespace.is_a?(Group)
group = namespace
else
user = namespace.owner
end
end end
if namespace.type == "Group" if user
redirect_to group_path(namespace) redirect_to user_path(user)
elsif group && can?(current_user, :read_group, group)
redirect_to group_path(group)
elsif current_user.nil?
authenticate_user!
else else
redirect_to user_path(namespace.owner) render_404
end end
end end
end end
...@@ -29,6 +29,10 @@ module GitlabRoutingHelper ...@@ -29,6 +29,10 @@ module GitlabRoutingHelper
namespace_project_merge_request_path(entity.project.namespace, entity.project, entity, *args) namespace_project_merge_request_path(entity.project.namespace, entity.project, entity, *args)
end end
def milestone_path(entity, *args)
namespace_project_milestone_path(entity.project.namespace, entity.project, entity, *args)
end
def project_url(project, *args) def project_url(project, *args)
namespace_project_url(project.namespace, project, *args) namespace_project_url(project.namespace, project, *args)
end end
......
...@@ -52,7 +52,7 @@ module Mentionable ...@@ -52,7 +52,7 @@ module Mentionable
if identifier == "all" if identifier == "all"
users.push(*project.team.members.flatten) users.push(*project.team.members.flatten)
elsif namespace = Namespace.find_by(path: identifier) elsif namespace = Namespace.find_by(path: identifier)
if namespace.type == "Group" if namespace.is_a?(Group)
users.push(*namespace.users) users.push(*namespace.users)
else else
users << namespace.owner users << namespace.owner
......
%li{class: "milestone milestone-#{milestone.closed? ? 'closed' : 'open'}", id: dom_id(milestone.milestones.first) }
%h4
= link_to_gfm truncate(milestone.title, length: 100), dashboard_milestone_path(milestone.safe_title, title: milestone.title)
.row
.col-sm-6
= link_to dashboard_milestone_path(milestone.safe_title, title: milestone.title) do
= pluralize milestone.issue_count, 'Issue'
&nbsp;
= link_to dashboard_milestone_path(milestone.safe_title, title: milestone.title) do
= pluralize milestone.merge_requests_count, 'Merge Request'
&nbsp;
%span.light #{milestone.percent_complete}% complete
.col-sm-6
= milestone_progress_bar(milestone)
%div
- milestone.milestones.each do |milestone|
= link_to milestone_path(milestone) do
%span.label.label-gray
= milestone.project.name_with_namespace
...@@ -16,23 +16,5 @@ ...@@ -16,23 +16,5 @@
.nothing-here-block No milestones to show .nothing-here-block No milestones to show
- else - else
- @dashboard_milestones.each do |milestone| - @dashboard_milestones.each do |milestone|
%li{class: "milestone milestone-#{milestone.closed? ? 'closed' : 'open'}", id: dom_id(milestone.milestones.first) } = render 'milestone', milestone: milestone
%h4
= link_to_gfm truncate(milestone.title, length: 100), dashboard_milestone_path(milestone.safe_title, title: milestone.title)
%div
%div
= link_to dashboard_milestone_path(milestone.safe_title, title: milestone.title) do
= pluralize milestone.issue_count, 'Issue'
&nbsp;
= link_to dashboard_milestone_path(milestone.safe_title, title: milestone.title) do
= pluralize milestone.merge_requests_count, 'Merge Request'
&nbsp;
%span.light #{milestone.percent_complete}% complete
= milestone_progress_bar(milestone)
%div
%br
- milestone.milestones.each do |milestone|
= link_to namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone) do
%span.label.label-default
= milestone.project.name_with_namespace
= paginate @dashboard_milestones, theme: "gitlab" = paginate @dashboard_milestones, theme: "gitlab"
%li{class: "milestone milestone-#{milestone.closed? ? 'closed' : 'open'}", id: dom_id(milestone.milestones.first) }
.pull-right
- if can?(current_user, :manage_group, @group)
- if milestone.closed?
= link_to 'Reopen Milestone', group_milestone_path(@group, milestone.safe_title, title: milestone.title, milestone: {state_event: :activate }), method: :put, class: "btn btn-sm btn-grouped btn-reopen"
- else
= link_to 'Close Milestone', group_milestone_path(@group, milestone.safe_title, title: milestone.title, milestone: {state_event: :close }), method: :put, class: "btn btn-sm btn-close"
%h4
= link_to_gfm truncate(milestone.title, length: 100), group_milestone_path(@group, milestone.safe_title, title: milestone.title)
.row
.col-sm-6
= link_to group_milestone_path(@group, milestone.safe_title, title: milestone.title) do
= pluralize milestone.issue_count, 'Issue'
&nbsp;
= link_to group_milestone_path(@group, milestone.safe_title, title: milestone.title) do
= pluralize milestone.merge_requests_count, 'Merge Request'
&nbsp;
%span.light #{milestone.percent_complete}% complete
.col-sm-6
= milestone_progress_bar(milestone)
%div
- milestone.milestones.each do |milestone|
= link_to milestone_path(milestone) do
%span.label.label-gray
= milestone.project.name
...@@ -18,29 +18,5 @@ ...@@ -18,29 +18,5 @@
.nothing-here-block No milestones to show .nothing-here-block No milestones to show
- else - else
- @group_milestones.each do |milestone| - @group_milestones.each do |milestone|
%li{class: "milestone milestone-#{milestone.closed? ? 'closed' : 'open'}", id: dom_id(milestone.milestones.first) } = render 'milestone', milestone: milestone
.pull-right
- if can?(current_user, :manage_group, @group)
- if milestone.closed?
= link_to 'Reopen Milestone', group_milestone_path(@group, milestone.safe_title, title: milestone.title, milestone: {state_event: :activate }), method: :put, class: "btn btn-sm btn-grouped btn-reopen"
- else
= link_to 'Close Milestone', group_milestone_path(@group, milestone.safe_title, title: milestone.title, milestone: {state_event: :close }), method: :put, class: "btn btn-sm btn-close"
%h4
= link_to_gfm truncate(milestone.title, length: 100), group_milestone_path(@group, milestone.safe_title, title: milestone.title)
%div
%div
= link_to group_milestone_path(@group, milestone.safe_title, title: milestone.title) do
= pluralize milestone.issue_count, 'Issue'
&nbsp;
= link_to group_milestone_path(@group, milestone.safe_title, title: milestone.title) do
= pluralize milestone.merge_requests_count, 'Merge Request'
&nbsp;
%span.light #{milestone.percent_complete}% complete
= milestone_progress_bar(milestone)
%div
%br
- milestone.milestones.each do |milestone|
= link_to namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone) do
%span.label.label-default
= milestone.project.name
= paginate @group_milestones, theme: "gitlab" = paginate @group_milestones, theme: "gitlab"
...@@ -11,16 +11,14 @@ ...@@ -11,16 +11,14 @@
%span.cred (Expired) %span.cred (Expired)
%small %small
= milestone.expires_at = milestone.expires_at
- if milestone.is_empty? .row
%span.muted Empty .col-sm-6
- else = link_to namespace_project_issues_path(milestone.project.namespace, milestone.project, milestone_id: milestone.id) do
%div = pluralize milestone.issues.count, 'Issue'
%div &nbsp;
= link_to namespace_project_issues_path(milestone.project.namespace, milestone.project, milestone_id: milestone.id) do = link_to namespace_project_merge_requests_path(milestone.project.namespace, milestone.project, milestone_id: milestone.id) do
= pluralize milestone.issues.count, 'Issue' = pluralize milestone.merge_requests.count, 'Merge Request'
&nbsp; &nbsp;
= link_to namespace_project_merge_requests_path(milestone.project.namespace, milestone.project, milestone_id: milestone.id) do %span.light #{milestone.percent_complete}% complete
= pluralize milestone.merge_requests.count, 'Merge Request' .col-sm-6
&nbsp;
%span.light #{milestone.percent_complete}% complete
= milestone_progress_bar(milestone) = milestone_progress_bar(milestone)
...@@ -15,5 +15,5 @@ ...@@ -15,5 +15,5 @@
if(current_url == log_url) { if(current_url == log_url) {
// Load 10 more commit log for each file in tree // Load 10 more commit log for each file in tree
// if we still on the same page // if we still on the same page
ajaxGet('#{logs_file_namespace_project_ref_path(@project.namespace, @project, @ref, @path || '/', offset: (@offset + @limit))}'); ajaxGet('#{logs_file_namespace_project_ref_path(@project.namespace, @project, @ref, @path || '', offset: (@offset + @limit))}');
} }
- if @contributed_projects.present? - if local_assigns.has_key?(:contributed_projects) && contributed_projects.present?
.panel.panel-default.contributed-projects .panel.panel-default.contributed-projects
.panel-heading Projects contributed to .panel-heading Projects contributed to
= render 'shared/projects_list', = render 'shared/projects_list',
projects: @contributed_projects.sort_by(&:star_count).reverse, projects: contributed_projects.sort_by(&:star_count).reverse,
projects_limit: 5, stars: true, avatar: false projects_limit: 5, stars: true, avatar: false
- if @projects.present? - if local_assigns.has_key?(:projects) && projects.present?
.panel.panel-default .panel.panel-default
.panel-heading Personal projects .panel-heading Personal projects
= render 'shared/projects_list', = render 'shared/projects_list',
projects: @projects.sort_by(&:star_count).reverse, projects: projects.sort_by(&:star_count).reverse,
projects_limit: 10, stars: true, avatar: false projects_limit: 10, stars: true, avatar: false
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
= spinner = spinner
%aside.col-md-4 %aside.col-md-4
= render 'profile', user: @user = render 'profile', user: @user
= render 'projects' = render 'projects', projects: @projects, contributed_projects: @contributed_projects
:coffeescript :coffeescript
$(".user-calendar").load("#{user_calendar_path}") $(".user-calendar").load("#{user_calendar_path}")
...@@ -66,8 +66,8 @@ production: &base ...@@ -66,8 +66,8 @@ production: &base
# If a commit message matches this regular expression, all issues referenced from the matched text will be closed. # If a commit message matches this regular expression, all issues referenced from the matched text will be closed.
# This happens when the commit is pushed or merged into the default branch of a project. # This happens when the commit is pushed or merged into the default branch of a project.
# When not specified the default issue_closing_pattern as specified below will be used. # When not specified the default issue_closing_pattern as specified below will be used.
# Tip: you can test your closing pattern at http://rubular.com # Tip: you can test your closing pattern at http://rubular.com.
# issue_closing_pattern: '((?:[Cc]los(?:e[sd]|ing)|[Ff]ix(?:e[sd]|ing)?) +(?:(?:issues? +)?#\d+(?:(?:, *| +and +)?))+)' # issue_closing_pattern: '((?:[Cc]los(?:e[sd]?|ing)|[Ff]ix(?:e[sd]|ing)?) +(?:(?:issues? +)?#\d+(?:(?:, *| +and +)?))+)'
## Default project features settings ## Default project features settings
default_projects_features: default_projects_features:
......
# Issue closing pattern # Issue closing pattern
By default you can close issues from commit messages by saying 'Closes #12' or 'Fixed #101'. If a commit message matches the regular expression below, all issues referenced from
the matched text will be closed. This happens when the commit is pushed or merged
into the default branch of a project.
If you want to customize the message please do so in [gitlab.yml](https://gitlab.com/gitlab-org/gitlab-ce/blob/73b92f85bcd6c213b845cc997843a969cf0906cf/config/gitlab.yml.example#L73) When not specified, the default issue_closing_pattern as shown below will be used:
```bash
((?:[Cc]los(?:e[sd]?|ing)|[Ff]ix(?:e[sd]|ing)?) +(?:(?:issues? +)?#\d+(?:(?:, *| +and +)?))+)
```
For example:
```
git commit -m "Awesome commit message (Fix #20, Fixes #21 and Closes #22). This commit is also related to #17 and fixes #18, #19 and #23."
```
will close `#20`, `#21`, `#22`, `#18`, `#19` and `#23`, but `#17` won't be closed
as it does not match the pattern. It also works with multiline commit messages.
Tip: you can test this closing pattern at [http://rubular.com][1]. Use this site
to test your own patterns.
## Change the pattern
For Omnibus installs you can change the default pattern in `/etc/gitlab/gitlab.rb`:
```
issue_closing_pattern: '((?:[Cc]los(?:e[sd]|ing)|[Ff]ix(?:e[sd]|ing)?) +(?:(?:issues? +)?#\d+(?:(?:, *| +and +)?))+)'
```
For manual installs you can customize the pattern in [gitlab.yml][0].
[0]: https://gitlab.com/gitlab-org/gitlab-ce/blob/40c3675372320febf5264061c9bcd63db2dfd13c/config/gitlab.yml.example#L65
[1]: http://rubular.com/r/Xmbexed1OJ
require 'mime/types' require 'mime/types'
require 'uri'
module API module API
# Projects API # Projects API
...@@ -101,10 +100,11 @@ module API ...@@ -101,10 +100,11 @@ module API
# branch (required) - The name of the branch # branch (required) - The name of the branch
# Example Request: # Example Request:
# DELETE /projects/:id/repository/branches/:branch # DELETE /projects/:id/repository/branches/:branch
delete ":id/repository/branches/:branch" do delete ":id/repository/branches/:branch",
requirements: { branch: /.*/ } do
authorize_push_project authorize_push_project
result = DeleteBranchService.new(user_project, current_user). result = DeleteBranchService.new(user_project, current_user).
execute(URI.unescape(params[:branch])) execute(params[:branch])
if result[:status] == :success if result[:status] == :success
{ {
......
...@@ -121,7 +121,7 @@ module Gitlab ...@@ -121,7 +121,7 @@ module Gitlab
markdown_pipeline = HTML::Pipeline::Gitlab.new(filters).pipeline markdown_pipeline = HTML::Pipeline::Gitlab.new(filters).pipeline
result = markdown_pipeline.call(text, markdown_context) result = markdown_pipeline.call(text, markdown_context)
save_options = 0 save_options = 0
if options[:xhtml] if options[:xhtml]
save_options |= Nokogiri::XML::Node::SaveOptions::AS_XHTML save_options |= Nokogiri::XML::Node::SaveOptions::AS_XHTML
...@@ -244,18 +244,18 @@ module Gitlab ...@@ -244,18 +244,18 @@ module Gitlab
if identifier == "all" if identifier == "all"
link_to( link_to(
"@all", "@all",
namespace_project_url(project.namespace, project, only_path: options[:reference_only_path]), namespace_project_url(project.namespace, project, only_path: options[:reference_only_path]),
link_options link_options
) )
elsif namespace = Namespace.find_by(path: identifier) elsif namespace = Namespace.find_by(path: identifier)
url = url =
if namespace.type == "Group" if namespace.is_a?(Group)
group_url(identifier, only_path: options[:reference_only_path]) group_url(identifier, only_path: options[:reference_only_path])
else else
user_url(identifier, only_path: options[:reference_only_path]) user_url(identifier, only_path: options[:reference_only_path])
end end
link_to("@#{identifier}", url, link_options) link_to("@#{identifier}", url, link_options)
end end
end end
...@@ -300,7 +300,7 @@ module Gitlab ...@@ -300,7 +300,7 @@ module Gitlab
class: "gfm gfm-merge_request #{html_options[:class]}" class: "gfm gfm-merge_request #{html_options[:class]}"
) )
url = namespace_project_merge_request_url(project.namespace, project, url = namespace_project_merge_request_url(project.namespace, project,
merge_request, merge_request,
only_path: options[:reference_only_path]) only_path: options[:reference_only_path])
link_to("#{prefix_text}!#{identifier}", url, link_options) link_to("#{prefix_text}!#{identifier}", url, link_options)
end end
...@@ -314,7 +314,7 @@ module Gitlab ...@@ -314,7 +314,7 @@ module Gitlab
) )
link_to( link_to(
"$#{identifier}", "$#{identifier}",
namespace_project_snippet_url(project.namespace, project, snippet, namespace_project_snippet_url(project.namespace, project, snippet,
only_path: options[:reference_only_path]), only_path: options[:reference_only_path]),
link_options link_options
) )
...@@ -330,7 +330,7 @@ module Gitlab ...@@ -330,7 +330,7 @@ module Gitlab
prefix_text = "#{prefix_text}@" if prefix_text prefix_text = "#{prefix_text}@" if prefix_text
link_to( link_to(
"#{prefix_text}#{identifier}", "#{prefix_text}#{identifier}",
namespace_project_commit_url( project.namespace, project, commit, namespace_project_commit_url( project.namespace, project, commit,
only_path: options[:reference_only_path]), only_path: options[:reference_only_path]),
link_options link_options
) )
...@@ -343,8 +343,8 @@ module Gitlab ...@@ -343,8 +343,8 @@ module Gitlab
inclusive = identifier !~ /\.{3}/ inclusive = identifier !~ /\.{3}/
from_id << "^" if inclusive from_id << "^" if inclusive
if project.valid_repo? && if project.valid_repo? &&
from = project.repository.commit(from_id) && from = project.repository.commit(from_id) &&
to = project.repository.commit(to_id) to = project.repository.commit(to_id)
link_options = html_options.merge( link_options = html_options.merge(
...@@ -355,8 +355,8 @@ module Gitlab ...@@ -355,8 +355,8 @@ module Gitlab
link_to( link_to(
"#{prefix_text}#{identifier}", "#{prefix_text}#{identifier}",
namespace_project_compare_url(project.namespace, project, namespace_project_compare_url(project.namespace, project,
from: from_id, to: to_id, from: from_id, to: to_id,
only_path: options[:reference_only_path]), only_path: options[:reference_only_path]),
link_options link_options
) )
......
require 'spec_helper'
describe NamespacesController do
let!(:user) { create(:user, avatar: fixture_file_upload(Rails.root + "spec/fixtures/dk.png", "image/png")) }
describe "GET show" do
context "when the namespace belongs to a user" do
let!(:other_user) { create(:user) }
it "redirects to the user's page" do
get :show, id: other_user.username
expect(response).to redirect_to(user_path(other_user))
end
end
context "when the namespace belongs to a group" do
let!(:group) { create(:group) }
let!(:project) { create(:project, namespace: group) }
context "when the group has public projects" do
before do
project.update_attribute(:visibility_level, Project::PUBLIC)
end
context "when not signed in" do
it "redirects to the group's page" do
get :show, id: group.path
expect(response).to redirect_to(group_path(group))
end
end
context "when signed in" do
before do
sign_in(user)
end
it "redirects to the group's page" do
get :show, id: group.path
expect(response).to redirect_to(group_path(group))
end
end
end
context "when the project doesn't have public projects" do
context "when not signed in" do
it "redirects to the sign in page" do
get :show, id: group.path
expect(response).to redirect_to(new_user_session_path)
end
end
context "when signed in" do
before do
sign_in(user)
end
context "when the user has access to the project" do
before do
project.team << [user, :master]
end
context "when the user is blocked" do
before do
user.block
project.team << [user, :master]
end
it "redirects to the sign in page" do
get :show, id: group.path
expect(response).to redirect_to(new_user_session_path)
end
end
context "when the user isn't blocked" do
it "redirects to the group's page" do
get :show, id: group.path
expect(response).to redirect_to(group_path(group))
end
end
end
context "when the user doesn't have access to the project" do
it "responds with status 404" do
get :show, id: group.path
expect(response.status).to eq(404)
end
end
end
end
end
context "when the namespace doesn't exist" do
context "when signed in" do
before do
sign_in(user)
end
it "responds with status 404" do
get :show, id: "doesntexist"
expect(response.status).to eq(404)
end
end
context "when not signed in" do
it "redirects to the sign in page" do
get :show, id: "doesntexist"
expect(response).to redirect_to(new_user_session_path)
end
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