Commit 1af8b1e4 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch 'master' of dev.gitlab.org:gitlab/gitlabhq into ce-to-ee

Conflicts:
	app/views/help/index.html.haml
	lib/gitlab/git_access.rb
	public/500.html
	public/502.html
parents 21b10d61 be969bb4
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 7.11.0 (unreleased) v 7.11.0 (unreleased)
- Fix broken view when viewing history of a file that includes a path that used to be another file (Stan Hu)
- Don't show duplicate deploy keys - Don't show duplicate deploy keys
- Fix commit time being displayed in the wrong timezone in some cases (Hannes Rosenögger) - Fix commit time being displayed in the wrong timezone in some cases (Hannes Rosenögger)
- Make the first branch pushed to an empty repository the default HEAD (Stan Hu) - Make the first branch pushed to an empty repository the default HEAD (Stan Hu)
...@@ -42,6 +43,9 @@ v 7.11.0 (unreleased) ...@@ -42,6 +43,9 @@ v 7.11.0 (unreleased)
- Task lists are now usable in comments, and will show up in Markdown previews. - Task lists are now usable in comments, and will show up in Markdown previews.
- Fix bug where avatar filenames were not actually deleted from the database during removal (Stan Hu) - Fix bug where avatar filenames were not actually deleted from the database during removal (Stan Hu)
- Fix bug where Slack service channel was not saved in admin template settings. (Stan Hu) - Fix bug where Slack service channel was not saved in admin template settings. (Stan Hu)
- Protect OmniAuth request phase against CSRF.
-
-
- Move snippets UI to fluid layout - Move snippets UI to fluid layout
- Improve UI for sidebar. Increase separation between navigation and content - Improve UI for sidebar. Increase separation between navigation and content
- Improve new project command options (Ben Bodenmiller) - Improve new project command options (Ben Bodenmiller)
...@@ -56,6 +60,12 @@ v 7.11.0 (unreleased) ...@@ -56,6 +60,12 @@ v 7.11.0 (unreleased)
- Add "Create Merge Request" buttons to commits and branches pages and push event. - Add "Create Merge Request" buttons to commits and branches pages and push event.
- Show user roles by comments. - Show user roles by comments.
- Fix automatic blocking of auto-created users from Active Directory. - Fix automatic blocking of auto-created users from Active Directory.
- Call merge request web hook for each new commits (Arthur Gautier)
- Use SIGKILL by default in Sidekiq::MemoryKiller
- Fix mentioning of private groups.
- Add style for <kbd> element in markdown
- Spin spinner icon next to "Checking for CI status..." on MR page.
- Fix reference links in dashboard activity and ATOM feeds.
v 7.10.2 v 7.10.2
- Fix CI links on MR page - Fix CI links on MR page
......
...@@ -23,7 +23,7 @@ gem "pg", group: :postgres ...@@ -23,7 +23,7 @@ gem "pg", group: :postgres
# Auth # Auth
gem "devise", '3.2.4' gem "devise", '3.2.4'
gem "devise-async", '0.9.0' gem "devise-async", '0.9.0'
gem 'omniauth', "~> 1.1.3" gem 'omniauth', "~> 1.2.2"
gem 'omniauth-google-oauth2' gem 'omniauth-google-oauth2'
gem 'omniauth-twitter' gem 'omniauth-twitter'
gem 'omniauth-github' gem 'omniauth-github'
...@@ -44,7 +44,7 @@ gem "browser" ...@@ -44,7 +44,7 @@ gem "browser"
# Extracting information from a git repository # Extracting information from a git repository
# Provide access to Gitlab::Git library # Provide access to Gitlab::Git library
gem "gitlab_git", '~> 7.1.11' gem "gitlab_git", '~> 7.1.12'
# Ruby/Rack Git Smart-HTTP Server Handler # Ruby/Rack Git Smart-HTTP Server Handler
gem 'gitlab-grack', '~> 2.0.2', require: 'grack' gem 'gitlab-grack', '~> 2.0.2', require: 'grack'
......
...@@ -226,7 +226,7 @@ GEM ...@@ -226,7 +226,7 @@ GEM
mime-types (~> 1.19) mime-types (~> 1.19)
gitlab_emoji (0.1.0) gitlab_emoji (0.1.0)
gemojione (~> 2.0) gemojione (~> 2.0)
gitlab_git (7.1.11) gitlab_git (7.1.12)
activesupport (~> 4.0) activesupport (~> 4.0)
charlock_holmes (~> 0.6) charlock_holmes (~> 0.6)
gitlab-linguist (~> 3.0) gitlab-linguist (~> 3.0)
...@@ -363,9 +363,9 @@ GEM ...@@ -363,9 +363,9 @@ GEM
rack (~> 1.2) rack (~> 1.2)
octokit (3.7.0) octokit (3.7.0)
sawyer (~> 0.6.0, >= 0.5.3) sawyer (~> 0.6.0, >= 0.5.3)
omniauth (1.1.4) omniauth (1.2.2)
hashie (>= 1.2, < 3) hashie (>= 1.2, < 4)
rack rack (~> 1.0)
omniauth-bitbucket (0.0.2) omniauth-bitbucket (0.0.2)
multi_json (~> 1.7) multi_json (~> 1.7)
omniauth (~> 1.1) omniauth (~> 1.1)
...@@ -725,7 +725,7 @@ DEPENDENCIES ...@@ -725,7 +725,7 @@ DEPENDENCIES
gitlab-license (~> 0.0.2) gitlab-license (~> 0.0.2)
gitlab-linguist (~> 3.0.1) gitlab-linguist (~> 3.0.1)
gitlab_emoji (~> 0.1) gitlab_emoji (~> 0.1)
gitlab_git (~> 7.1.11) gitlab_git (~> 7.1.12)
gitlab_meta (= 7.0) gitlab_meta (= 7.0)
gitlab_omniauth-ldap (= 1.2.1) gitlab_omniauth-ldap (= 1.2.1)
gollum-lib (~> 4.0.2) gollum-lib (~> 4.0.2)
...@@ -754,7 +754,7 @@ DEPENDENCIES ...@@ -754,7 +754,7 @@ DEPENDENCIES
newrelic_rpm newrelic_rpm
nprogress-rails nprogress-rails
octokit (= 3.7.0) octokit (= 3.7.0)
omniauth (~> 1.1.3) omniauth (~> 1.2.2)
omniauth-bitbucket omniauth-bitbucket
omniauth-github omniauth-github
omniauth-gitlab omniauth-gitlab
......
...@@ -73,6 +73,22 @@ ...@@ -73,6 +73,22 @@
padding: 0; padding: 0;
} }
kbd {
display: inline-block;
padding: 3px 5px;
font-size: 11px;
line-height: 10px;
color: #555;
vertical-align: middle;
background-color: #FCFCFC;
border-width: 1px;
border-style: solid;
border-color: #CCC #CCC #BBB;
border-image: none;
border-radius: 3px;
box-shadow: 0px -1px 0px #BBB inset;
}
h1 { h1 {
margin-top: 45px; margin-top: 45px;
font-size: 2.5em; font-size: 2.5em;
......
...@@ -33,7 +33,16 @@ ul.notes { ...@@ -33,7 +33,16 @@ ul.notes {
&:before { &:before {
content: "\00b7"; content: "\00b7";
} }
font-size: 13px; font-size: 13px;
a {
@extend .cgray;
&:hover {
text-decoration: underline;
}
}
} }
.author { .author {
color: #333; color: #333;
...@@ -47,7 +56,7 @@ ul.notes { ...@@ -47,7 +56,7 @@ ul.notes {
.note-role { .note-role {
float: right; float: right;
margin-top: 2px; margin-top: 1px;
border: 1px solid #bbb; border: 1px solid #bbb;
background-color: transparent; background-color: transparent;
color: #999; color: #999;
...@@ -142,31 +151,23 @@ ul.notes { ...@@ -142,31 +151,23 @@ ul.notes {
.discussion, .discussion,
.note { .note {
&.note:hover {
.note-actions { display: block; }
.note-actions + .note-role { display: none; }
}
.discussion-header:hover {
.discussion-actions { display: block; }
}
.discussion-actions, .discussion-actions,
.note-actions { .note-actions {
display: none;
float: right; float: right;
margin-left: 10px;
i.fa {
font-size: 16px;
line-height: 16px;
vertical-align: middle;
}
a { a {
margin-left: 5px; margin-left: 5px;
@extend .cgray; color: #999;
i.fa {
font-size: 16px;
line-height: 16px;
}
&:hover { &:hover {
@extend .cgray;
&.danger { @extend .cred; } &.danger { @extend .cred; }
} }
} }
......
...@@ -218,6 +218,10 @@ ul.nav.nav-projects-tabs { ...@@ -218,6 +218,10 @@ ul.nav.nav-projects-tabs {
color: #555; color: #555;
} }
.actions {
margin-top: 10px;
}
.nav-pills a { .nav-pills a {
padding: 10px; padding: 10px;
} }
......
...@@ -43,6 +43,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController ...@@ -43,6 +43,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
:default_project_visibility, :default_project_visibility,
:default_snippet_visibility, :default_snippet_visibility,
:restricted_signup_domains_raw, :restricted_signup_domains_raw,
:version_check_enabled,
restricted_visibility_levels: [], restricted_visibility_levels: [],
) )
end end
......
...@@ -73,8 +73,15 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController ...@@ -73,8 +73,15 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
redirect_to omniauth_error_path(oauth['provider'], error: error_message) and return redirect_to omniauth_error_path(oauth['provider'], error: error_message) and return
end end
end end
rescue Gitlab::OAuth::ForbiddenAction => e rescue Gitlab::OAuth::SignupDisabledError => e
flash[:notice] = e.message message = "Signing in using your #{oauth['provider']} account without a pre-existing GitLab account is not allowed."
if current_application_settings.signup_enabled?
message << " Create a GitLab account first, and then connect it to your #{oauth['provider']} account."
end
flash[:notice] = message
redirect_to new_user_session_path redirect_to new_user_session_path
end end
......
class SessionsController < Devise::SessionsController class SessionsController < Devise::SessionsController
prepend_before_action :authenticate_with_two_factor, only: [:create] include AuthenticatesWithTwoFactor
# This action comes from DeviseController, but because we call `sign_in` prepend_before_action :authenticate_with_two_factor, only: [:create]
# manually inside `authenticate_with_two_factor`, not skipping this action
# would cause a "You are already signed in." error message to be shown upon
# successful login.
skip_before_action :require_no_authentication, only: [:create]
def new def new
redirect_path = redirect_path =
...@@ -74,9 +70,7 @@ class SessionsController < Devise::SessionsController ...@@ -74,9 +70,7 @@ class SessionsController < Devise::SessionsController
end end
else else
if user && user.valid_password?(user_params[:password]) if user && user.valid_password?(user_params[:password])
# Save the user's ID to session so we can ask for a one-time password prompt_for_two_factor(user)
session[:otp_user_id] = user.id
render :two_factor and return
end end
end end
end end
......
...@@ -330,12 +330,20 @@ module ApplicationHelper ...@@ -330,12 +330,20 @@ module ApplicationHelper
count = count =
if project.nil? if project.nil?
"" nil
elsif current_controller?(:issues) elsif current_controller?(:issues)
" (#{project.issues.send(entity).count})" project.issues.send(entity).count
elsif current_controller?(:merge_requests) elsif current_controller?(:merge_requests)
" (#{project.merge_requests.send(entity).count})" project.merge_requests.send(entity).count
end end
"#{entity_title}#{count}"
html = content_tag :span, entity_title
if count.present?
html += " "
html += content_tag :span, number_with_delimiter(count), class: 'badge'
end
html.html_safe
end end
end end
...@@ -168,8 +168,8 @@ module EventsHelper ...@@ -168,8 +168,8 @@ module EventsHelper
end end
end end
def event_note(text) def event_note(text, options = {})
text = first_line_in_markdown(text, 150) text = first_line_in_markdown(text, 150, options)
sanitize(text, tags: %w(a img b pre code p span)) sanitize(text, tags: %w(a img b pre code p span))
end end
...@@ -189,7 +189,7 @@ module EventsHelper ...@@ -189,7 +189,7 @@ module EventsHelper
xml.id "tag:#{request.host},#{event.created_at.strftime("%Y-%m-%d")}:#{event.id}" xml.id "tag:#{request.host},#{event.created_at.strftime("%Y-%m-%d")}:#{event.id}"
xml.link href: event_link xml.link href: event_link
xml.title truncate(event_title, length: 80) xml.title truncate(event_title, length: 80)
xml.updated event.created_at.strftime("%Y-%m-%dT%H:%M:%SZ") xml.updated event.created_at.strftime("%Y-%m-%dT%H:%M:%S%Z")
xml.media :thumbnail, width: "40", height: "40", url: avatar_icon(event.author_email) xml.media :thumbnail, width: "40", height: "40", url: avatar_icon(event.author_email)
xml.author do |author| xml.author do |author|
xml.name event.author_name xml.name event.author_name
......
...@@ -19,7 +19,7 @@ module GitlabMarkdownHelper ...@@ -19,7 +19,7 @@ module GitlabMarkdownHelper
escape_once(body) escape_once(body)
end end
gfm_body = gfm(escaped_body, @project, html_options) gfm_body = gfm(escaped_body, {}, html_options)
gfm_body.gsub!(%r{<a.*?>.*?</a>}m) do |match| gfm_body.gsub!(%r{<a.*?>.*?</a>}m) do |match|
"</a>#{match}#{link_to("", url, html_options)[0..-5]}" # "</a>".length +1 "</a>#{match}#{link_to("", url, html_options)[0..-5]}" # "</a>".length +1
...@@ -32,11 +32,13 @@ module GitlabMarkdownHelper ...@@ -32,11 +32,13 @@ module GitlabMarkdownHelper
unless @markdown && options == @options unless @markdown && options == @options
@options = options @options = options
# see https://github.com/vmg/redcarpet#darling-i-packed-you-a-couple-renderers-for-lunch options.merge!(
rend = Redcarpet::Render::GitlabHTML.new(self, user_color_scheme_class, {
# Handled further down the line by Gitlab::Markdown::SanitizationFilter # Handled further down the line by Gitlab::Markdown::SanitizationFilter
escape_html: false escape_html: false
}.merge(options)) )
# see https://github.com/vmg/redcarpet#darling-i-packed-you-a-couple-renderers-for-lunch
rend = Redcarpet::Render::GitlabHTML.new(self, user_color_scheme_class, options)
# see https://github.com/vmg/redcarpet#and-its-like-really-simple-to-use # see https://github.com/vmg/redcarpet#and-its-like-really-simple-to-use
@markdown = Redcarpet::Markdown.new(rend, @markdown = Redcarpet::Markdown.new(rend,
...@@ -58,8 +60,8 @@ module GitlabMarkdownHelper ...@@ -58,8 +60,8 @@ module GitlabMarkdownHelper
# as Markdown. HTML tags in the parsed output are not counted toward the # as Markdown. HTML tags in the parsed output are not counted toward the
# +max_chars+ limit. If the length limit falls within a tag's contents, then # +max_chars+ limit. If the length limit falls within a tag's contents, then
# the tag contents are truncated without removing the closing tag. # the tag contents are truncated without removing the closing tag.
def first_line_in_markdown(text, max_chars = nil) def first_line_in_markdown(text, max_chars = nil, options = {})
md = markdown(text).strip md = markdown(text, options).strip
truncate_visible(md, max_chars || md.length) if md.present? truncate_visible(md, max_chars || md.length) if md.present?
end end
...@@ -72,146 +74,6 @@ module GitlabMarkdownHelper ...@@ -72,146 +74,6 @@ module GitlabMarkdownHelper
end end
end end
# TODO (rspeicher): This should be its own filter
def create_relative_links(text)
paths = extract_paths(text)
paths.uniq.each do |file_path|
# If project does not have repository
# its nothing to rebuild
#
# TODO: pass project variable to markdown helper instead of using
# instance variable. Right now it generates invalid path for pages out
# of project scope. Example: search results where can be rendered markdown
# from different projects
if @repository && @repository.exists? && !@repository.empty?
new_path = rebuild_path(file_path)
# Finds quoted path so we don't replace other mentions of the string
# eg. "doc/api" will be replaced and "/home/doc/api/text" won't
text.gsub!("\"#{file_path}\"", "\"/#{new_path}\"")
end
end
text
end
def extract_paths(text)
links = substitute_links(text)
image_links = substitute_image_links(text)
links + image_links
end
def substitute_links(text)
links = text.scan(/<a href=\"([^"]*)\">/)
relative_links = links.flatten.reject{ |link| link_to_ignore? link }
relative_links
end
def substitute_image_links(text)
links = text.scan(/<img src=\"([^"]*)\"/)
relative_links = links.flatten.reject{ |link| link_to_ignore? link }
relative_links
end
def link_to_ignore?(link)
if link =~ /\A\#\w+/
# ignore anchors like <a href="#my-header">
true
else
ignored_protocols.map{ |protocol| link.include?(protocol) }.any?
end
end
def ignored_protocols
["http://","https://", "ftp://", "mailto:", "smb://"]
end
def rebuild_path(file_path)
file_path = file_path.dup
file_path.gsub!(/(#.*)/, "")
id = $1 || ""
file_path = relative_file_path(file_path)
file_path = sanitize_slashes(file_path)
[
Gitlab.config.gitlab.relative_url_root,
@project.path_with_namespace,
path_with_ref(file_path),
file_path
].compact.join("/").gsub(/\A\/*|\/*\z/, '') + id
end
def sanitize_slashes(path)
path[0] = "" if path.start_with?("/")
path.chop if path.end_with?("/")
path
end
def relative_file_path(path)
requested_path = @path
nested_path = build_nested_path(path, requested_path)
return nested_path if file_exists?(nested_path)
path
end
# Covering a special case, when the link is referencing file in the same directory eg:
# If we are at doc/api/README.md and the README.md contains relative links like [Users](users.md)
# this takes the request path(doc/api/README.md), and replaces the README.md with users.md so the path looks like doc/api/users.md
# If we are at doc/api and the README.md shown in below the tree view
# this takes the request path(doc/api) and adds users.md so the path looks like doc/api/users.md
def build_nested_path(path, request_path)
return request_path if path == ""
return path unless request_path
if local_path(request_path) == "tree"
base = request_path.split("/").push(path)
base.join("/")
else
base = request_path.split("/")
base.pop
base.push(path).join("/")
end
end
# Checks if the path exists in the repo
# eg. checks if doc/README.md exists, if not then link to blob
def path_with_ref(path)
if file_exists?(path)
"#{local_path(path)}/#{correct_ref}"
else
"blob/#{correct_ref}"
end
end
def file_exists?(path)
return false if path.nil?
@repository.blob_at(current_sha, path).present? || @repository.tree(current_sha, path).entries.any?
end
# Check if the path is pointing to a directory(tree) or a file(blob)
# eg. doc/api is directory and doc/README.md is file
def local_path(path)
return "tree" if @repository.tree(current_sha, path).entries.any?
return "raw" if @repository.blob_at(current_sha, path).image?
"blob"
end
def current_sha
if @commit
@commit.id
elsif @repository && !@repository.empty?
if @ref
@repository.commit(@ref).try(:sha)
else
@repository.head_commit.sha
end
end
end
# We will assume that if no ref exists we can point to master
def correct_ref
@ref ? @ref : "master"
end
private private
# Return +text+, truncated to +max_chars+ characters, excluding any HTML # Return +text+, truncated to +max_chars+ characters, excluding any HTML
......
module VersionCheckHelper
def version_status_badge
if Rails.env.production?
image_tag VersionCheck.new.url
end
end
end
...@@ -42,10 +42,10 @@ module Mentionable ...@@ -42,10 +42,10 @@ module Mentionable
SystemNoteService.cross_reference_exists?(target, local_reference) SystemNoteService.cross_reference_exists?(target, local_reference)
end end
def mentioned_users(current_user = nil, p = project) def mentioned_users(current_user = nil)
return [] if mentionable_text.blank? return [] if mentionable_text.blank?
ext = Gitlab::ReferenceExtractor.new(p, current_user) ext = Gitlab::ReferenceExtractor.new(self.project, current_user)
ext.analyze(mentionable_text) ext.analyze(mentionable_text)
ext.users.uniq ext.users.uniq
end end
......
...@@ -40,7 +40,7 @@ module Participable ...@@ -40,7 +40,7 @@ module Participable
meth = method(attr) meth = method(attr)
value = value =
if meth.arity == 1 if meth.arity == 1 || meth.arity == -1
meth.call(current_user) meth.call(current_user)
else else
meth.call meth.call
......
...@@ -10,6 +10,7 @@ module MergeRequests ...@@ -10,6 +10,7 @@ module MergeRequests
close_merge_requests close_merge_requests
reload_merge_requests reload_merge_requests
execute_mr_web_hooks
comment_mr_with_commits comment_mr_with_commits
true true
...@@ -88,6 +89,20 @@ module MergeRequests ...@@ -88,6 +89,20 @@ module MergeRequests
end end
end end
# Call merge request webhook with update branches
def execute_mr_web_hooks
merge_requests = @project.origin_merge_requests.opened
.where(source_branch: @branch_name)
.to_a
merge_requests += @fork_merge_requests.where(source_branch: @branch_name)
.to_a
merge_requests = filter_merge_requests(merge_requests)
merge_requests.each do |merge_request|
execute_hooks(merge_request, 'update')
end
end
def filter_merge_requests(merge_requests) def filter_merge_requests(merge_requests)
merge_requests.uniq.select(&:source_project) merge_requests.uniq.select(&:source_project)
end end
......
...@@ -32,6 +32,12 @@ ...@@ -32,6 +32,12 @@
= f.check_box :twitter_sharing_enabled, :'aria-describedby' => 'twitter_help_block' = f.check_box :twitter_sharing_enabled, :'aria-describedby' => 'twitter_help_block'
%strong Twitter enabled %strong Twitter enabled
%span.help-block#twitter_help_block Show users a button to share their newly created public or internal projects on twitter %span.help-block#twitter_help_block Show users a button to share their newly created public or internal projects on twitter
.form-group
.col-sm-offset-2.col-sm-10
.checkbox
= f.label :version_check_enabled do
= f.check_box :version_check_enabled
Version check enabled
%fieldset %fieldset
%legend Misc %legend Misc
.form-group .form-group
......
...@@ -56,7 +56,12 @@ ...@@ -56,7 +56,12 @@
%span.light.pull-right %span.light.pull-right
= boolean_to_icon Gitlab.config.omniauth.enabled = boolean_to_icon Gitlab.config.omniauth.enabled
.col-md-4 .col-md-4
%h4 Components %h4
Components
- if current_application_settings.version_check_enabled
.pull-right
= version_status_badge
%hr %hr
%p %p
GitLab GitLab
......
...@@ -5,6 +5,6 @@ ...@@ -5,6 +5,6 @@
- providers.each do |provider| - providers.each do |provider|
%span.light %span.light
- if default_providers.include?(provider) - if default_providers.include?(provider)
= link_to oauth_image_tag(provider), omniauth_authorize_path(resource_name, provider), class: 'oauth-image-link' = link_to oauth_image_tag(provider), omniauth_authorize_path(resource_name, provider), method: :post, class: 'oauth-image-link'
- else - else
= link_to provider.to_s.titleize, omniauth_authorize_path(resource_name, provider), class: "btn", "data-no-turbolink" => "true" = link_to provider.to_s.titleize, omniauth_authorize_path(resource_name, provider), method: :post, class: "btn", "data-no-turbolink" => "true"
...@@ -2,4 +2,4 @@ ...@@ -2,4 +2,4 @@
.commit-row-title .commit-row-title
= link_to truncate_sha(commit[:id]), namespace_project_commit_path(project.namespace, project, commit[:id]), class: "commit_short_id", alt: '' = link_to truncate_sha(commit[:id]), namespace_project_commit_path(project.namespace, project, commit[:id]), class: "commit_short_id", alt: ''
&nbsp; &nbsp;
= gfm event_commit_title(commit[:message]), project = gfm event_commit_title(commit[:message]), project: project
%div{xmlns: "http://www.w3.org/1999/xhtml"} %div{xmlns: "http://www.w3.org/1999/xhtml"}
- if issue.description.present? - if issue.description.present?
= markdown(issue.description, xhtml: true) = markdown(issue.description, xhtml: true, reference_only_path: false, project: issue.project)
%div{xmlns: "http://www.w3.org/1999/xhtml"} %div{xmlns: "http://www.w3.org/1999/xhtml"}
- if merge_request.description.present? - if merge_request.description.present?
= markdown(merge_request.description, xhtml: true) = markdown(merge_request.description, xhtml: true, reference_only_path: false, project: merge_request.project)
%div{xmlns: "http://www.w3.org/1999/xhtml"} %div{xmlns: "http://www.w3.org/1999/xhtml"}
= markdown(note.note, xhtml: true) = markdown(note.note, xhtml: true, reference_only_path: false, project: note.project)
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
%i %i
at at
= commit[:timestamp].to_time.to_s(:short) = commit[:timestamp].to_time.to_s(:short)
%blockquote= markdown(escape_once(commit[:message]), xhtml: true) %blockquote= markdown(escape_once(commit[:message]), xhtml: true, reference_only_path: false, project: note.project)
- if event.commits_count > 15 - if event.commits_count > 15
%p %p
%i %i
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
.event-note .event-note
.md .md
%i.fa.fa-comment-o.event-note-icon %i.fa.fa-comment-o.event-note-icon
= event_note(event.target.note) = event_note(event.target.note, project: event.project)
- note = event.target - note = event.target
- if note.attachment.url - if note.attachment.url
- if note.attachment.image? - if note.attachment.image?
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
%span.light Enterprise Edition %span.light Enterprise Edition
%span= Gitlab::VERSION %span= Gitlab::VERSION
%small= Gitlab::REVISION %small= Gitlab::REVISION
- if current_application_settings.version_check_enabled
= version_status_badge
%br %br
Read more about GitLab at #{link_to promo_host, promo_url, target: '_blank'}. Read more about GitLab at #{link_to promo_host, promo_url, target: '_blank'}.
- if help_text.present? - if help_text.present?
......
...@@ -61,7 +61,7 @@ ...@@ -61,7 +61,7 @@
- enabled_social_providers.each do |provider| - enabled_social_providers.each do |provider|
.btn-group .btn-group
= link_to oauth_image_tag(provider), omniauth_authorize_path(User, provider), = link_to oauth_image_tag(provider), omniauth_authorize_path(User, provider),
class: "btn btn-lg #{'active' if oauth_active?(provider)}" method: :post, class: "btn btn-lg #{'active' if oauth_active?(provider)}"
- if oauth_active?(provider) - if oauth_active?(provider)
= link_to unlink_profile_account_path(provider: provider), method: :delete, class: 'btn btn-lg' do = link_to unlink_profile_account_path(provider: provider), method: :delete, class: 'btn btn-lg' do
= icon('close') = icon('close')
......
...@@ -10,17 +10,14 @@ ...@@ -10,17 +10,14 @@
- if @repository.changelog - if @repository.changelog
%li.hidden-xs %li.hidden-xs
= link_to changelog_url(@project) do = link_to changelog_url(@project) do
= icon("list-alt fw")
Changelog Changelog
- if @repository.license - if @repository.license
%li %li
= link_to license_url(@project) do = link_to license_url(@project) do
= icon("check-circle-o fw")
License License
- if @repository.contribution_guide - if @repository.contribution_guide
%li %li
= link_to contribution_guide_url(@project) do = link_to contribution_guide_url(@project) do
= icon("info-circle fw")
Contribution guide Contribution guide
.actions .actions
...@@ -73,15 +70,12 @@ ...@@ -73,15 +70,12 @@
%ul.nav.nav-pills %ul.nav.nav-pills
%li %li
= link_to namespace_project_commits_path(@project.namespace, @project, @ref || @repository.root_ref) do = link_to namespace_project_commits_path(@project.namespace, @project, @ref || @repository.root_ref) do
= icon("history fw")
= pluralize(number_with_delimiter(@repository.commit_count), 'commit') = pluralize(number_with_delimiter(@repository.commit_count), 'commit')
%li %li
= link_to namespace_project_branches_path(@project.namespace, @project) do = link_to namespace_project_branches_path(@project.namespace, @project) do
= icon("code-fork fw")
= pluralize(number_with_delimiter(@repository.branch_names.count), 'branch') = pluralize(number_with_delimiter(@repository.branch_names.count), 'branch')
%li %li
= link_to namespace_project_tags_path(@project.namespace, @project) do = link_to namespace_project_tags_path(@project.namespace, @project) do
= icon("tags fw")
= pluralize(number_with_delimiter(@repository.tag_names.count), 'tag') = pluralize(number_with_delimiter(@repository.tag_names.count), 'tag')
.actions .actions
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
= link_to namespace_project_commits_path(@project.namespace, @project, @ref || @repository.root_ref) do = link_to namespace_project_commits_path(@project.namespace, @project, @ref || @repository.root_ref) do
= icon("history") = icon("history")
Commits Commits
%span.badge= number_with_precision(@repository.commit_count, precision: 0, delimiter: ',') %span.badge= number_with_delimiter(@repository.commit_count)
= nav_link(controller: :compare) do = nav_link(controller: :compare) do
= link_to namespace_project_compare_index_path(@project.namespace, @project, from: @repository.root_ref, to: @ref || @repository.root_ref) do = link_to namespace_project_compare_index_path(@project.namespace, @project, from: @repository.root_ref, to: @ref || @repository.root_ref) do
= icon("exchange") = icon("exchange")
......
- if @commits.any? - if @commits.any?
.ci_widget.ci-success{style: "display:none"} .ci_widget.ci-success{style: "display:none"}
%i.fa.fa-check = icon("check")
%span CI build passed %span CI build passed
for #{@merge_request.last_commit_short_sha}. for #{@merge_request.last_commit_short_sha}.
= link_to "View build page", ci_build_details_path(@merge_request), :"data-no-turbolink" => "data-no-turbolink" = link_to "View build page", ci_build_details_path(@merge_request), :"data-no-turbolink" => "data-no-turbolink"
.ci_widget.ci-failed{style: "display:none"} .ci_widget.ci-failed{style: "display:none"}
%i.fa.fa-times = icon("times")
%span CI build failed %span CI build failed
for #{@merge_request.last_commit_short_sha}. for #{@merge_request.last_commit_short_sha}.
= link_to "View build page", ci_build_details_path(@merge_request), :"data-no-turbolink" => "data-no-turbolink" = link_to "View build page", ci_build_details_path(@merge_request), :"data-no-turbolink" => "data-no-turbolink"
- [:running, :pending].each do |status| - [:running, :pending].each do |status|
.ci_widget{class: "ci-#{status}", style: "display:none"} .ci_widget{class: "ci-#{status}", style: "display:none"}
%i.fa.fa-clock-o = icon("clock-o")
%span CI build #{status} %span CI build #{status}
for #{@merge_request.last_commit_short_sha}. for #{@merge_request.last_commit_short_sha}.
= link_to "View build page", ci_build_details_path(@merge_request), :"data-no-turbolink" => "data-no-turbolink" = link_to "View build page", ci_build_details_path(@merge_request), :"data-no-turbolink" => "data-no-turbolink"
.ci_widget .ci_widget
%i.fa.fa-spinner = icon("spinner spin")
Checking for CI status for #{@merge_request.last_commit_short_sha} Checking for CI status for #{@merge_request.last_commit_short_sha}
.ci_widget.ci-canceled{style: "display:none"} .ci_widget.ci-canceled{style: "display:none"}
%i.fa.fa-times = icon("times")
%span CI build canceled %span CI build canceled
for #{@merge_request.last_commit_short_sha}. for #{@merge_request.last_commit_short_sha}.
= link_to "View build page", ci_build_details_path(@merge_request), :"data-no-turbolink" => "data-no-turbolink" = link_to "View build page", ci_build_details_path(@merge_request), :"data-no-turbolink" => "data-no-turbolink"
.ci_widget.ci-error{style: "display:none"} .ci_widget.ci-error{style: "display:none"}
%i.fa.fa-times = icon("times")
%span Cannot connect to the CI server. Please check your settings and try again. %span Cannot connect to the CI server. Please check your settings and try again.
...@@ -8,19 +8,13 @@ ...@@ -8,19 +8,13 @@
= image_tag avatar_icon(note.author_email), class: 'avatar s40', alt: '' = image_tag avatar_icon(note.author_email), class: 'avatar s40', alt: ''
.timeline-content .timeline-content
.note-header .note-header
.note-actions - if note_editable?(note)
= link_to "##{dom_id(note)}", name: dom_id(note), title: "Link here" do .note-actions
= icon('link fw')
Link here
- if note_editable?(note)
= link_to '#', title: 'Edit comment', class: 'js-note-edit' do = link_to '#', title: 'Edit comment', class: 'js-note-edit' do
= icon('pencil-square-o fw') = icon('pencil-square-o')
Edit
= link_to namespace_project_note_path(note.project.namespace, note.project, note), title: 'Remove comment', method: :delete, data: { confirm: 'Are you sure you want to remove this comment?' }, remote: true, class: 'danger js-note-delete' do = link_to namespace_project_note_path(note.project.namespace, note.project, note), title: 'Remove comment', method: :delete, data: { confirm: 'Are you sure you want to remove this comment?' }, remote: true, class: 'js-note-delete danger' do
= icon('trash-o fw', class: 'cred') = icon('trash-o')
Remove
- unless note.system - unless note.system
- member = note.project.team.find_member(note.author.id) - member = note.project.team.find_member(note.author.id)
...@@ -33,10 +27,13 @@ ...@@ -33,10 +27,13 @@
= image_tag avatar_icon(note.author_email), class: 'avatar s16', alt: '' = image_tag avatar_icon(note.author_email), class: 'avatar s16', alt: ''
= link_to_member(note.project, note.author, avatar: false) = link_to_member(note.project, note.author, avatar: false)
%span.author-username %span.author-username
= '@' + note.author.username = '@' + note.author.username
%span.note-last-update %span.note-last-update
= note_timestamp(note) = link_to "##{dom_id(note)}", name: dom_id(note), title: "Link here" do
= note_timestamp(note)
- if note.superceded?(@notes) - if note.superceded?(@notes)
- if note.upvote? - if note.upvote?
......
...@@ -14,7 +14,9 @@ ...@@ -14,7 +14,9 @@
- last_note = discussion_notes.last - last_note = discussion_notes.last
last updated by last updated by
= link_to_member(@project, last_note.author, avatar: false) = link_to_member(@project, last_note.author, avatar: false)
%span.discussion-last-update %span.discussion-last-update
#{time_ago_with_tooltip(last_note.updated_at, 'bottom', 'discussion_updated_ago')} #{time_ago_with_tooltip(last_note.updated_at, 'bottom', 'discussion_updated_ago')}
.discussion-body.js-toggle-content .discussion-body.js-toggle-content
= render "projects/notes/discussions/diff", discussion_notes: discussion_notes, note: note = render "projects/notes/discussions/diff", discussion_notes: discussion_notes, note: note
...@@ -13,3 +13,8 @@ if Gitlab::LDAP::Config.enabled? ...@@ -13,3 +13,8 @@ if Gitlab::LDAP::Config.enabled?
end end
end end
end end
OmniAuth.config.allowed_request_methods = [:post]
OmniAuth.config.before_request_phase do |env|
OmniAuth::RequestForgeryProtection.new(env).call
end
...@@ -31,7 +31,7 @@ en: ...@@ -31,7 +31,7 @@ en:
messages: messages:
# Common error messages # Common error messages
invalid_request: 'The request is missing a required parameter, includes an unsupported parameter value, or is otherwise malformed.' invalid_request: 'The request is missing a required parameter, includes an unsupported parameter value, or is otherwise malformed.'
invalid_redirect_uri: 'The redirect uri included is not valid.' invalid_redirect_uri: 'The redirect URI included is not valid.'
unauthorized_client: 'The client is not authorized to perform this request using this method.' unauthorized_client: 'The client is not authorized to perform this request using this method.'
access_denied: 'The resource owner or authorization server denied the request.' access_denied: 'The resource owner or authorization server denied the request.'
invalid_scope: 'The requested scope is invalid, unknown, or malformed.' invalid_scope: 'The requested scope is invalid, unknown, or malformed.'
...@@ -63,11 +63,11 @@ en: ...@@ -63,11 +63,11 @@ en:
flash: flash:
applications: applications:
create: create:
notice: 'Application created.' notice: 'The application was created successfully.'
destroy: destroy:
notice: 'Application deleted.' notice: 'The application was deleted successfully.'
update: update:
notice: 'Application updated.' notice: 'The application was updated successfully.'
authorized_applications: authorized_applications:
destroy: destroy:
notice: 'Application revoked.' notice: 'The application was revoked access.'
class AddVersionCheckToApplicationSettings < ActiveRecord::Migration
def change
add_column :application_settings, :version_check_enabled, :boolean, default: true
end
end
...@@ -40,6 +40,7 @@ ActiveRecord::Schema.define(version: 20150509180749) do ...@@ -40,6 +40,7 @@ ActiveRecord::Schema.define(version: 20150509180749) do
t.boolean "twitter_sharing_enabled", default: true t.boolean "twitter_sharing_enabled", default: true
t.text "help_text" t.text "help_text"
t.text "restricted_visibility_levels" t.text "restricted_visibility_levels"
t.boolean "version_check_enabled", default: true
t.integer "max_attachment_size", default: 10, null: false t.integer "max_attachment_size", default: 10, null: false
t.integer "default_project_visibility" t.integer "default_project_visibility"
t.integer "default_snippet_visibility" t.integer "default_snippet_visibility"
......
...@@ -32,6 +32,7 @@ Parameters: ...@@ -32,6 +32,7 @@ Parameters:
- `order_by` (optional) - Return requests ordered by `id`, `name`, `path`, `created_at`, `updated_at` or `last_activity_at` fields. Default is `created_at` - `order_by` (optional) - Return requests ordered by `id`, `name`, `path`, `created_at`, `updated_at` or `last_activity_at` fields. Default is `created_at`
- `sort` (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc` - `sort` (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc`
- `search` (optional) - Return list of authorized projects according to a search criteria - `search` (optional) - Return list of authorized projects according to a search criteria
- `ci_enabled_first` - Return projects ordered by ci_enabled flag. Projects with enabled GitLab CI go first
```json ```json
[ [
...@@ -134,6 +135,7 @@ Parameters: ...@@ -134,6 +135,7 @@ Parameters:
- `order_by` (optional) - Return requests ordered by `id`, `name`, `path`, `created_at`, `updated_at` or `last_activity_at` fields. Default is `created_at` - `order_by` (optional) - Return requests ordered by `id`, `name`, `path`, `created_at`, `updated_at` or `last_activity_at` fields. Default is `created_at`
- `sort` (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc` - `sort` (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc`
- `search` (optional) - Return list of authorized projects according to a search criteria - `search` (optional) - Return list of authorized projects according to a search criteria
- `ci_enabled_first` - Return projects ordered by ci_enabled flag. Projects with enabled GitLab CI go first
### List ALL projects ### List ALL projects
...@@ -149,6 +151,7 @@ Parameters: ...@@ -149,6 +151,7 @@ Parameters:
- `order_by` (optional) - Return requests ordered by `id`, `name`, `path`, `created_at`, `updated_at` or `last_activity_at` fields. Default is `created_at` - `order_by` (optional) - Return requests ordered by `id`, `name`, `path`, `created_at`, `updated_at` or `last_activity_at` fields. Default is `created_at`
- `sort` (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc` - `sort` (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc`
- `search` (optional) - Return list of authorized projects according to a search criteria - `search` (optional) - Return list of authorized projects according to a search criteria
- `ci_enabled_first` - Return projects ordered by ci_enabled flag. Projects with enabled GitLab CI go first
### Get single project ### Get single project
......
# GitLab Upgrader # GitLab Upgrader
*Make sure you view this [upgrade guide from the `master` branch](../../../master/doc/update/upgrader.md) for the most up to date instructions.*
*DEPRECATED* We recommend to [switch to the Omnibus package and repository server](https://about.gitlab.com/update/) instead of using this script.
Although deprecated, if someone wants to make this script into a gem or otherwise improve it merge requests are welcome.
*Make sure you view this [upgrade guide from the 'master' branch](../../../master/doc/update/upgrader.md) for the most up to date instructions.*
GitLab Upgrader - a ruby script that allows you easily upgrade GitLab to latest minor version. GitLab Upgrader - a ruby script that allows you easily upgrade GitLab to latest minor version.
...@@ -24,13 +29,15 @@ If you have local changes to your GitLab repository the script will stash them a ...@@ -24,13 +29,15 @@ If you have local changes to your GitLab repository the script will stash them a
## 2. Run GitLab upgrade tool ## 2. Run GitLab upgrade tool
Note: GitLab 7.9 adds `nodejs` as a dependency. GitLab 7.6 adds `libkrb5-dev` as a dependency (installed by default on Ubuntu and OSX). GitLab 7.2 adds `pkg-config` and `cmake` as dependency. Please check the dependencies in the [installation guide.](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/installation.md#1-packages-dependencies) Please replace X.X.X with the [latest GitLab release](https://packages.gitlab.com/gitlab/gitlab-ce).
GitLab 7.9 adds `nodejs` as a dependency. GitLab 7.6 adds `libkrb5-dev` as a dependency (installed by default on Ubuntu and OSX). GitLab 7.2 adds `pkg-config` and `cmake` as dependency. Please check the dependencies in the [installation guide.](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/installation.md#1-packages-dependencies)
cd /home/git/gitlab cd /home/git/gitlab
sudo -u git -H ruby -Ilib -e 'require "gitlab/upgrader"' -e 'class Gitlab::Upgrader' -e 'def latest_version_raw' -e '"v7.10.1"' -e 'end' -e 'end' -e 'Gitlab::Upgrader.new.execute' sudo -u git -H ruby -Ilib -e 'require "gitlab/upgrader"' -e 'class Gitlab::Upgrader' -e 'def latest_version_raw' -e '"vX.X.X"' -e 'end' -e 'end' -e 'Gitlab::Upgrader.new.execute'
# to perform a non-interactive install (no user input required) you can add -y # to perform a non-interactive install (no user input required) you can add -y
# sudo -u git -H ruby -Ilib -e 'require "gitlab/upgrader"' -e 'class Gitlab::Upgrader' -e 'def latest_version_raw' -e '"v7.10.1"' -e 'end' -e 'end' -e 'Gitlab::Upgrader.new.execute' -- -y # sudo -u git -H ruby -Ilib -e 'require "gitlab/upgrader"' -e 'class Gitlab::Upgrader' -e 'def latest_version_raw' -e '"vX.X.X"' -e 'end' -e 'end' -e 'Gitlab::Upgrader.new.execute' -- -y
## 3. Start application ## 3. Start application
...@@ -59,13 +66,15 @@ sudo -u git -H git checkout v`cat /home/git/gitlab/GITLAB_SHELL_VERSION` ...@@ -59,13 +66,15 @@ sudo -u git -H git checkout v`cat /home/git/gitlab/GITLAB_SHELL_VERSION`
You've read through the entire guide and probably already did all the steps one by one. You've read through the entire guide and probably already did all the steps one by one.
Here is a one line command with step 1 to 5 for the next time you upgrade: Below is a one line command with step 1 to 5 for the next time you upgrade.
Please replace X.X.X with the [latest GitLab release](https://packages.gitlab.com/gitlab/gitlab-ce).
```bash ```bash
cd /home/git/gitlab; \ cd /home/git/gitlab; \
sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production; \ sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production; \
sudo service gitlab stop; \ sudo service gitlab stop; \
sudo -u git -H ruby -Ilib -e 'require "gitlab/upgrader"' -e 'class Gitlab::Upgrader' -e 'def latest_version_raw' -e '"v7.10.1"' -e 'end' -e 'end' -e 'Gitlab::Upgrader.new.execute' -- -y; \ sudo -u git -H ruby -Ilib -e 'require "gitlab/upgrader"' -e 'class Gitlab::Upgrader' -e 'def latest_version_raw' -e '"vX.X.X"' -e 'end' -e 'end' -e 'Gitlab::Upgrader.new.execute' -- -y; \
cd /home/git/gitlab-shell; \ cd /home/git/gitlab-shell; \
sudo -u git -H git fetch; \ sudo -u git -H git fetch; \
sudo -u git -H git checkout v`cat /home/git/gitlab/GITLAB_SHELL_VERSION`; \ sudo -u git -H git checkout v`cat /home/git/gitlab/GITLAB_SHELL_VERSION`; \
......
...@@ -145,7 +145,7 @@ X-Gitlab-Event: Issue Hook ...@@ -145,7 +145,7 @@ X-Gitlab-Event: Issue Hook
## Merge request events ## Merge request events
Triggered when a new merge request is created or an existing merge request was updated/merged/closed. Triggered when a new merge request is created, an existing merge request was updated/merged/closed or a commit is added in the source branch.
**Request header**: **Request header**:
......
...@@ -5,15 +5,14 @@ RUN apt-get update -q \ ...@@ -5,15 +5,14 @@ RUN apt-get update -q \
&& DEBIAN_FRONTEND=noninteractive apt-get install -qy --no-install-recommends \ && DEBIAN_FRONTEND=noninteractive apt-get install -qy --no-install-recommends \
ca-certificates \ ca-certificates \
openssh-server \ openssh-server \
wget wget \
apt-transport-https
# Download & Install GitLab # Download & Install GitLab
# If the Omnibus package version below is outdated please contribute a merge request to update it.
# If you run GitLab Enterprise Edition point it to a location where you have downloaded it. # If you run GitLab Enterprise Edition point it to a location where you have downloaded it.
RUN TMP_FILE=$(mktemp); \ RUN echo "deb https://packages.gitlab.com/gitlab/gitlab-ce/ubuntu/ `lsb_release -cs` main" > /etc/apt/sources.list.d/gitlab_gitlab-ce.list
wget -q -O $TMP_FILE https://downloads-packages.s3.amazonaws.com/ubuntu-14.04/gitlab-ce_7.10.1~omnibus.2-1_amd64.deb \ RUN wget -q -O - https://packages.gitlab.com/gpg.key | apt-key add -
&& dpkg -i $TMP_FILE \ RUN apt-get update && apt-get install -yq --no-install-recommends gitlab-ce
&& rm -f $TMP_FILE
# Manage SSHD through runit # Manage SSHD through runit
RUN mkdir -p /opt/gitlab/sv/sshd/supervise \ RUN mkdir -p /opt/gitlab/sv/sshd/supervise \
......
...@@ -2,20 +2,18 @@ FROM ubuntu:14.04 ...@@ -2,20 +2,18 @@ FROM ubuntu:14.04
MAINTAINER Sytse Sijbrandij MAINTAINER Sytse Sijbrandij
# Install required packages # Install required packages
RUN apt-get update RUN apt-get update -q \
ENV DEBIAN_FRONTEND noninteractive && DEBIAN_FRONTEND=noninteractive apt-get install -yq --no-install-recommends \
RUN apt-get install -yq --no-install-recommends \
ca-certificates \ ca-certificates \
openssh-server \ openssh-server \
wget wget \
apt-transport-https
# Download & Install GitLab # Download & Install GitLab
# If the Omnibus package version below is outdated please contribute a merge request to update it.
# If you run GitLab Enterprise Edition point it to a location where you have downloaded it. # If you run GitLab Enterprise Edition point it to a location where you have downloaded it.
RUN TMP_FILE=$(mktemp); \ RUN echo "deb https://packages.gitlab.com/gitlab/gitlab-ce/ubuntu/ `lsb_release -cs` main" > /etc/apt/sources.list.d/gitlab_gitlab-ce.list
wget -q -O $TMP_FILE https://downloads-packages.s3.amazonaws.com/ubuntu-14.04/gitlab-ce_7.10.1~omnibus.2-1_amd64.deb \ RUN wget -q -O - https://packages.gitlab.com/gpg.key | apt-key add -
&& dpkg -i $TMP_FILE \ RUN apt-get update && apt-get install -yq --no-install-recommends gitlab-ce
&& rm -f $TMP_FILE
# Manage SSHD through runit # Manage SSHD through runit
RUN mkdir -p /opt/gitlab/sv/sshd/supervise \ RUN mkdir -p /opt/gitlab/sv/sshd/supervise \
......
...@@ -24,10 +24,6 @@ module API ...@@ -24,10 +24,6 @@ module API
User.find_by(id: params[:user_id]) User.find_by(id: params[:user_id])
end end
unless actor
return Gitlab::GitAccessStatus.new(false, 'No such user or key')
end
project_path = params[:project] project_path = params[:project]
# Check for *.wiki repositories. # Check for *.wiki repositories.
...@@ -39,22 +35,14 @@ module API ...@@ -39,22 +35,14 @@ module API
project = Project.find_with_namespace(project_path) project = Project.find_with_namespace(project_path)
if project access =
access = if wiki
if wiki Gitlab::GitAccessWiki.new(actor, project)
Gitlab::GitAccessWiki.new(actor, project) else
else Gitlab::GitAccess.new(actor, project)
Gitlab::GitAccess.new(actor, project) end
end
status = access.check(params[:action], params[:changes])
end
if project && access.can_read_project? access.check(params[:action], params[:changes])
status
else
Gitlab::GitAccessStatus.new(false, 'No such project')
end
end end
# #
......
...@@ -22,7 +22,12 @@ module API ...@@ -22,7 +22,12 @@ module API
projects = projects.search(params[:search]) projects = projects.search(params[:search])
end end
projects.reorder(project_order_by => project_sort) if params[:ci_enabled_first].present?
projects.includes(:gitlab_ci_service).
reorder("services.active DESC, projects.#{project_order_by} #{project_sort}")
else
projects.reorder(project_order_by => project_sort)
end
end end
def project_order_by def project_order_by
......
...@@ -51,9 +51,9 @@ module Gitlab ...@@ -51,9 +51,9 @@ module Gitlab
def protection_options def protection_options
{ {
"Not protected, developers and masters can (force) push and delete the branch" => PROTECTION_NONE, "Not protected: Both developers and masters can push new commits, force push, or delete the branch." => PROTECTION_NONE,
"Partially protected, developers can also push but prevent all force pushes and deletion" => PROTECTION_DEV_CAN_PUSH, "Partially protected: Developers can push new commits, but cannot force push or delete the branch. Masters can do all of those." => PROTECTION_DEV_CAN_PUSH,
"Fully protected, only masters can push and prevent all force pushes and deletion" => PROTECTION_FULL, "Fully protected: Developers cannot push new commits, force push, or delete the branch. Only masters can do any of those." => PROTECTION_FULL,
} }
end end
......
...@@ -32,8 +32,7 @@ module Gitlab ...@@ -32,8 +32,7 @@ module Gitlab
def can_push_to_branch?(ref) def can_push_to_branch?(ref)
return false unless user return false unless user
if project.protected_branch?(ref) && if project.protected_branch?(ref) && !project.developers_can_push_to_protected_branch?(ref)
!(project.developers_can_push_to_protected_branch?(ref) && project.team.developer?(user))
user.can?(:push_code_to_protected_branches, project) user.can?(:push_code_to_protected_branches, project)
else else
user.can?(:push_code, project) user.can?(:push_code, project)
...@@ -51,6 +50,18 @@ module Gitlab ...@@ -51,6 +50,18 @@ module Gitlab
end end
def check(cmd, changes = nil) def check(cmd, changes = nil)
unless actor
return build_status_object(false, "No user or key was provided.")
end
if user && !user_allowed?
return build_status_object(false, "Your account has been blocked.")
end
unless project && can_read_project?
return build_status_object(false, 'The project you were looking for could not be found.')
end
case cmd case cmd
when *DOWNLOAD_COMMANDS when *DOWNLOAD_COMMANDS
download_access_check download_access_check
...@@ -61,7 +72,7 @@ module Gitlab ...@@ -61,7 +72,7 @@ module Gitlab
git_annex_access_check(actor.user, project, changes) git_annex_access_check(actor.user, project, changes)
end end
else else
build_status_object(false, "Wrong command") build_status_object(false, "The command you're trying to execute is not allowed.")
end end
end end
...@@ -69,7 +80,7 @@ module Gitlab ...@@ -69,7 +80,7 @@ module Gitlab
if user if user
user_download_access_check user_download_access_check
elsif deploy_key elsif deploy_key
deploy_key_download_access_check build_status_object(true)
else else
raise 'Wrong actor' raise 'Wrong actor'
end end
...@@ -79,41 +90,29 @@ module Gitlab ...@@ -79,41 +90,29 @@ module Gitlab
if user if user
user_push_access_check(changes) user_push_access_check(changes)
elsif deploy_key elsif deploy_key
build_status_object(false, "Deploy key not allowed to push") build_status_object(false, "Deploy keys are not allowed to push code.")
else else
raise 'Wrong actor' raise 'Wrong actor'
end end
end end
def user_download_access_check def user_download_access_check
if user && user_allowed? && user.can?(:download_code, project) unless user.can?(:download_code, project)
build_status_object(true) return build_status_object(false, "You are not allowed to download code from this project.")
else
build_status_object(false, "You don't have access")
end end
end
def deploy_key_download_access_check build_status_object(true)
if can_read_project?
build_status_object(true)
else
build_status_object(false, "Deploy key not allowed to access this project")
end
end end
def user_push_access_check(changes) def user_push_access_check(changes)
unless user && user_allowed?
return build_status_object(false, "You don't have access")
end
if changes.blank? if changes.blank?
return build_status_object(true) return build_status_object(true)
end end
unless project.repository.exists? unless project.repository.exists?
return build_status_object(false, "Repository does not exist") return build_status_object(false, "A repository for this project does not exist yet.")
end end
if ::License.block_changes? if ::License.block_changes?
message = ::LicenseHelper.license_message(signed_in: true, is_admin: (user && user.is_admin?)) message = ::LicenseHelper.license_message(signed_in: true, is_admin: (user && user.is_admin?))
return build_status_object(false, message) return build_status_object(false, message)
...@@ -146,11 +145,21 @@ module Gitlab ...@@ -146,11 +145,21 @@ module Gitlab
:push_code :push_code
end end
# Stop execution if user has no access to this project
unless user.can?(action, project) unless user.can?(action, project)
return build_status_object(false, "You don't have permission") status =
case action
when :force_push_code_to_protected_branches
build_status_object(false, "You are not allowed to force push code to a protected branch on this project.")
when :remove_protected_branches
build_status_object(false, "You are not allowed to deleted protected branches from this project.")
when :push_code_to_protected_branches
build_status_object(false, "You are not allowed to push code to protected branches on this project.")
when :admin_project
build_status_object(false, "You are not allowed to change existing tags on this project.")
else # :push_code
build_status_object(false, "You are not allowed to push code to this project.")
end
return status
end end
# Return build_status_object(true) if all git hook checks passed successfully # Return build_status_object(true) if all git hook checks passed successfully
......
...@@ -4,7 +4,7 @@ module Gitlab ...@@ -4,7 +4,7 @@ module Gitlab
if user.can?(:write_wiki, project) if user.can?(:write_wiki, project)
build_status_object(true) build_status_object(true)
else else
build_status_object(false, "You don't have access") build_status_object(false, "You are not allowed to write to this project's wiki.")
end end
end end
end end
......
...@@ -15,6 +15,7 @@ module Gitlab ...@@ -15,6 +15,7 @@ module Gitlab
autoload :IssueReferenceFilter, 'gitlab/markdown/issue_reference_filter' autoload :IssueReferenceFilter, 'gitlab/markdown/issue_reference_filter'
autoload :LabelReferenceFilter, 'gitlab/markdown/label_reference_filter' autoload :LabelReferenceFilter, 'gitlab/markdown/label_reference_filter'
autoload :MergeRequestReferenceFilter, 'gitlab/markdown/merge_request_reference_filter' autoload :MergeRequestReferenceFilter, 'gitlab/markdown/merge_request_reference_filter'
autoload :RelativeLinkFilter, 'gitlab/markdown/relative_link_filter'
autoload :SanitizationFilter, 'gitlab/markdown/sanitization_filter' autoload :SanitizationFilter, 'gitlab/markdown/sanitization_filter'
autoload :SnippetReferenceFilter, 'gitlab/markdown/snippet_reference_filter' autoload :SnippetReferenceFilter, 'gitlab/markdown/snippet_reference_filter'
autoload :TableOfContentsFilter, 'gitlab/markdown/table_of_contents_filter' autoload :TableOfContentsFilter, 'gitlab/markdown/table_of_contents_filter'
...@@ -23,10 +24,10 @@ module Gitlab ...@@ -23,10 +24,10 @@ module Gitlab
# Public: Parse the provided text with GitLab-Flavored Markdown # Public: Parse the provided text with GitLab-Flavored Markdown
# #
# text - the source text # text - the source text
# project - the project # options - options
# html_options - extra options for the reference links as given to link_to # html_options - extra options for the reference links as given to link_to
def gfm(text, project = @project, html_options = {}) def gfm(text, options = {}, html_options = {})
gfm_with_options(text, {}, project, html_options) gfm_with_options(text, options, html_options)
end end
# Public: Parse the provided text with GitLab-Flavored Markdown # Public: Parse the provided text with GitLab-Flavored Markdown
...@@ -37,7 +38,7 @@ module Gitlab ...@@ -37,7 +38,7 @@ module Gitlab
# :reference_only_path - Use relative path for reference links # :reference_only_path - Use relative path for reference links
# project - the project # project - the project
# html_options - extra options for the reference links as given to link_to # html_options - extra options for the reference links as given to link_to
def gfm_with_options(text, options = {}, project = @project, html_options = {}) def gfm_with_options(text, options = {}, html_options = {})
return text if text.nil? return text if text.nil?
# Duplicate the string so we don't alter the original, then call to_str # Duplicate the string so we don't alter the original, then call to_str
...@@ -47,7 +48,9 @@ module Gitlab ...@@ -47,7 +48,9 @@ module Gitlab
options.reverse_merge!( options.reverse_merge!(
xhtml: false, xhtml: false,
reference_only_path: true reference_only_path: true,
project: @project,
current_user: current_user
) )
pipeline = HTML::Pipeline.new(filters) pipeline = HTML::Pipeline.new(filters)
...@@ -61,10 +64,15 @@ module Gitlab ...@@ -61,10 +64,15 @@ module Gitlab
no_header_anchors: options[:no_header_anchors], no_header_anchors: options[:no_header_anchors],
# ReferenceFilter # ReferenceFilter
current_user: current_user, current_user: options[:current_user],
only_path: options[:reference_only_path], only_path: options[:reference_only_path],
project: project, project: options[:project],
reference_class: html_options[:class] reference_class: html_options[:class],
# RelativeLinkFilter
ref: @ref,
requested_path: @path,
project_wiki: @project_wiki
} }
result = pipeline.call(text, context) result = pipeline.call(text, context)
...@@ -91,6 +99,7 @@ module Gitlab ...@@ -91,6 +99,7 @@ module Gitlab
[ [
Gitlab::Markdown::SanitizationFilter, Gitlab::Markdown::SanitizationFilter,
Gitlab::Markdown::RelativeLinkFilter,
Gitlab::Markdown::EmojiFilter, Gitlab::Markdown::EmojiFilter,
Gitlab::Markdown::TableOfContentsFilter, Gitlab::Markdown::TableOfContentsFilter,
Gitlab::Markdown::AutolinkFilter, Gitlab::Markdown::AutolinkFilter,
......
require 'html/pipeline/filter'
require 'uri'
module Gitlab
module Markdown
# HTML filter that "fixes" relative links to files in a repository.
#
# Context options:
# :commit
# :project
# :project_wiki
# :ref
# :requested_path
class RelativeLinkFilter < HTML::Pipeline::Filter
def call
return doc unless linkable_files?
doc.search('a').each do |el|
process_link_attr el.attribute('href')
end
doc.search('img').each do |el|
process_link_attr el.attribute('src')
end
doc
end
protected
def linkable_files?
context[:project_wiki].nil? && repository.try(:exists?) && !repository.empty?
end
def process_link_attr(html_attr)
return if html_attr.blank?
uri = URI(html_attr.value)
if uri.relative? && uri.path.present?
html_attr.value = rebuild_relative_uri(uri).to_s
end
rescue URI::Error
# noop
end
def rebuild_relative_uri(uri)
file_path = relative_file_path(uri.path)
uri.path = [
relative_url_root,
context[:project].path_with_namespace,
path_type(file_path),
ref || 'master', # assume that if no ref exists we can point to master
file_path
].compact.join('/').squeeze('/').chomp('/')
uri
end
def relative_file_path(path)
nested_path = build_nested_path(path, context[:requested_path])
file_exists?(nested_path) ? nested_path : path
end
# Covering a special case, when the link is referencing file in the same
# directory.
# If we are at doc/api/README.md and the README.md contains relative
# links like [Users](users.md), this takes the request
# path(doc/api/README.md) and replaces the README.md with users.md so the
# path looks like doc/api/users.md.
# If we are at doc/api and the README.md shown in below the tree view
# this takes the request path(doc/api) and adds users.md so the path
# looks like doc/api/users.md
def build_nested_path(path, request_path)
return request_path if path.empty?
return path unless request_path
parts = request_path.split('/')
parts.pop if path_type(request_path) != 'tree'
parts.push(path).join('/')
end
def file_exists?(path)
return false if path.nil?
repository.blob_at(current_sha, path).present? ||
repository.tree(current_sha, path).entries.any?
end
# Get the type of the given path
#
# path - String path to check
#
# Examples:
#
# path_type('doc/README.md') # => 'blob'
# path_type('doc/logo.png') # => 'raw'
# path_type('doc/api') # => 'tree'
#
# Returns a String
def path_type(path)
if repository.tree(current_sha, path).entries.any?
'tree'
elsif repository.blob_at(current_sha, path).try(:image?)
'raw'
else
'blob'
end
end
def current_sha
context[:commit].try(:id) ||
ref ? repository.commit(ref).try(:sha) : repository.head_commit.sha
end
def relative_url_root
Gitlab.config.gitlab.relative_url_root.presence || '/'
end
def ref
context[:ref]
end
def repository
context[:project].try(:repository)
end
end
end
end
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
# #
module Gitlab module Gitlab
module OAuth module OAuth
class ForbiddenAction < StandardError; end class SignupDisabledError < StandardError; end
class User class User
attr_accessor :auth_hash, :gl_user attr_accessor :auth_hash, :gl_user
...@@ -99,7 +99,7 @@ module Gitlab ...@@ -99,7 +99,7 @@ module Gitlab
end end
def unauthorized_to_create def unauthorized_to_create
raise ForbiddenAction.new("Unauthorized to create user, signup disabled for #{auth_hash.provider}") raise SignupDisabledError
end end
end end
end end
......
...@@ -7,7 +7,7 @@ module Gitlab ...@@ -7,7 +7,7 @@ module Gitlab
GRACE_TIME = (ENV['SIDEKIQ_MEMORY_KILLER_GRACE_TIME'] || 15 * 60).to_s.to_i GRACE_TIME = (ENV['SIDEKIQ_MEMORY_KILLER_GRACE_TIME'] || 15 * 60).to_s.to_i
# Wait 30 seconds for running jobs to finish during graceful shutdown # Wait 30 seconds for running jobs to finish during graceful shutdown
SHUTDOWN_WAIT = (ENV['SIDEKIQ_MEMORY_KILLER_SHUTDOWN_WAIT'] || 30).to_s.to_i SHUTDOWN_WAIT = (ENV['SIDEKIQ_MEMORY_KILLER_SHUTDOWN_WAIT'] || 30).to_s.to_i
SHUTDOWN_SIGNAL = (ENV['SIDEKIQ_MEMORY_KILLER_SHUTDOWN_SIGNAL'] || 'SIGTERM').to_s SHUTDOWN_SIGNAL = (ENV['SIDEKIQ_MEMORY_KILLER_SHUTDOWN_SIGNAL'] || 'SIGKILL').to_s
# Create a mutex used to ensure there will be only one thread waiting to # Create a mutex used to ensure there will be only one thread waiting to
# shut Sidekiq down # shut Sidekiq down
......
# Protects OmniAuth request phase against CSRF.
module OmniAuth
# Based on ActionController::RequestForgeryProtection.
class RequestForgeryProtection
def initialize(env)
@env = env
end
def request
@request ||= ActionDispatch::Request.new(@env)
end
def session
request.session
end
def reset_session
request.reset_session
end
def params
request.params
end
def call
verify_authenticity_token
end
def verify_authenticity_token
if !verified_request?
Rails.logger.warn "Can't verify CSRF token authenticity" if Rails.logger
handle_unverified_request
end
end
private
def protect_against_forgery?
ApplicationController.allow_forgery_protection
end
def request_forgery_protection_token
ApplicationController.request_forgery_protection_token
end
def forgery_protection_strategy
ApplicationController.forgery_protection_strategy
end
def verified_request?
!protect_against_forgery? || request.get? || request.head? ||
form_authenticity_token == params[request_forgery_protection_token] ||
form_authenticity_token == request.headers['X-CSRF-Token']
end
def handle_unverified_request
forgery_protection_strategy.new(self).handle_unverified_request
end
# Sets the token value for the current session.
def form_authenticity_token
session[:_csrf_token] ||= SecureRandom.base64(32)
end
end
end
...@@ -7,9 +7,12 @@ class Redcarpet::Render::GitlabHTML < Redcarpet::Render::HTML ...@@ -7,9 +7,12 @@ class Redcarpet::Render::GitlabHTML < Redcarpet::Render::HTML
def initialize(template, color_scheme, options = {}) def initialize(template, color_scheme, options = {})
@template = template @template = template
@color_scheme = color_scheme @color_scheme = color_scheme
@project = @template.instance_variable_get("@project")
@options = options.dup @options = options.dup
@options.reverse_merge!(
project: @template.instance_variable_get("@project")
)
super(options) super(options)
end end
...@@ -36,10 +39,6 @@ class Redcarpet::Render::GitlabHTML < Redcarpet::Render::HTML ...@@ -36,10 +39,6 @@ class Redcarpet::Render::GitlabHTML < Redcarpet::Render::HTML
end end
def postprocess(full_document) def postprocess(full_document)
unless @template.instance_variable_get("@project_wiki") || @project.nil?
full_document = h.create_relative_links(full_document)
end
h.gfm_with_options(full_document, @options) h.gfm_with_options(full_document, @options)
end end
end end
require "base64"
# This class is used to build image URL to
# check if it is a new version for update
class VersionCheck
def data
{ version: Gitlab::VERSION }
end
def url
encoded_data = Base64.urlsafe_encode64(data.to_json)
"#{host}?gitlab_info=#{encoded_data}"
end
def host
'https://version.gitlab.com/check.png'
end
end
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>The page you were looking for doesn't exist (404)</title> <title>The page you're looking for could not be found (404)</title>
<link href="/static.css" media="screen" rel="stylesheet" type="text/css" /> <link href="/static.css" media="screen" rel="stylesheet" type="text/css" />
</head> </head>
<body> <body>
<h1>404</h1> <h1>404</h1>
<h3>The page you were looking for doesn't exist.</h3> <h3>The page you're looking for could not be found.</h3>
<hr/> <hr/>
<p>You may have mistyped the address or the page may have moved.</p> <p>Make sure the address is correct and that the page hasn't moved.</p>
<p>Please contact your GitLab administrator if you think this is a mistake.</p>
</body> </body>
</html> </html>
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>The change you wanted was rejected (422)</title> <title>The change you requested was rejected (422)</title>
<link href="/static.css" media="screen" rel="stylesheet" type="text/css" /> <link href="/static.css" media="screen" rel="stylesheet" type="text/css" />
</head> </head>
<body> <body>
<!-- This file lives in public/422.html --> <!-- This file lives in public/422.html -->
<h1>422</h1> <h1>422</h1>
<div> <h3>The change you requested was rejected.</h3>
<h2>The change you wanted was rejected.</h2> <hr />
<p>Maybe you tried to change something you didn't have access to.</p> <p>Make sure you have access to the thing you tried to change.</p>
</div> <p>Please contact your GitLab administrator if you think this is a mistake.</p>
</body> </body>
</html> </html>
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>We're sorry, but something went wrong (500)</title> <title>Something went wrong (500)</title>
<link href="/static.css" media="screen" rel="stylesheet" type="text/css" /> <link href="/static.css" media="screen" rel="stylesheet" type="text/css" />
</head> </head>
<body> <body>
<h1>500</h1> <h1>500</h1>
<h3>We're sorry, but something went wrong.</h3> <h3>Whoops, something went wrong on our end.</h3>
<hr/> <hr/>
<p>Try refreshing the page, or going back and attempting the action again.</p>
<p><a href="/help" >Please contact your GitLab administrator</a> if this problem persists.</p> <p><a href="/help" >Please contact your GitLab administrator</a> if this problem persists.</p>
</body> </body>
</html> </html>
...@@ -6,8 +6,9 @@ ...@@ -6,8 +6,9 @@
</head> </head>
<body> <body>
<h1>502</h1> <h1>502</h1>
<h3>GitLab is not responding.</h3> <h3>Whoops, GitLab is taking too much time to respond.</h3>
<hr/> <hr/>
<p>Try refreshing the page, or going back and attempting the action again.</p>
<p><a href="/help" >Please contact your GitLab administrator</a> if this problem persists.</p> <p><a href="/help" >Please contact your GitLab administrator</a> if this problem persists.</p>
</body> </body>
</html> </html>
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>Deploy in progress. Please try again in a few minutes</title> <title>Deploy in progress</title>
<link href="/static.css" media="screen" rel="stylesheet" type="text/css" /> <link href="/static.css" media="screen" rel="stylesheet" type="text/css" />
</head> </head>
<body> <body>
<h1><center><img src="/gitlab_logo.png"/></center>Deploy in progress</h1> <h1>
<h3>Please try again in a few minutes or contact your administrator.</h3> <img src="/gitlab_logo.png" /><br />
Deploy in progress
</h1>
<h3>Please try again in a few minutes.</h3>
<hr/>
<p>Please contact your GitLab administrator if this problem persists.</p>
</body> </body>
</html> </html>
...@@ -2,18 +2,24 @@ body { ...@@ -2,18 +2,24 @@ body {
color: #666; color: #666;
text-align: center; text-align: center;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
margin:0; margin: 0;
width: 800px; width: 800px;
margin: auto; margin: auto;
font-size: 14px; font-size: 14px;
} }
h1 { h1 {
font-size: 56px; font-size: 56px;
line-height: 100px; line-height: 100px;
font-weight: normal; font-weight: normal;
color: #456; color: #456;
} }
h2 { font-size: 24px; color: #666; line-height: 1.5em; }
h2 {
font-size: 24px;
color: #666;
line-height: 1.5em;
}
h3 { h3 {
color: #456; color: #456;
......
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnp2mUaLBoHFX127ysonX
OihiGpI4098eFfH1iAxpKHIof0vs0jFF05IUScNXJZ1U3w8G1U/unY/wGGa3NzAb
ZfDd22eOF6X2Gfiey6U4w9dFf0/UT5x1bphlpX357yh4O9oWWuNaWD062DTbOOsJ
U6UW2U/sZAu/QScys0Nw+gJ58t93hb4jFq+nO5IAQc6g4S8ek5YvIXOshFEpF2in
ZLbSYowx92+9GzfjvdQ7fk0Q2ssg0zfScVa6FY8n019osz0SC3wcSd/qicdfecpu
7oycpd9YDqk4lufE1qVMOsgE8OO4KXMrByz2f+T0p/bH9zdBa5HYylf1T7i60hIL
kQIDAQAB
-----END PUBLIC KEY-----
...@@ -21,7 +21,7 @@ describe GitlabMarkdownHelper do ...@@ -21,7 +21,7 @@ describe GitlabMarkdownHelper do
describe "#gfm" do describe "#gfm" do
it "should forward HTML options to links" do it "should forward HTML options to links" do
expect(gfm("Fixed in #{commit.id}", @project, class: 'foo')). expect(gfm("Fixed in #{commit.id}", { project: @project }, class: 'foo')).
to have_selector('a.gfm.foo') to have_selector('a.gfm.foo')
end end
...@@ -96,79 +96,6 @@ describe GitlabMarkdownHelper do ...@@ -96,79 +96,6 @@ describe GitlabMarkdownHelper do
end end
end end
describe "#markdown" do
# TODO (rspeicher): These belong in a relative link filter spec
context 'relative links' do
context 'with a valid repository' do
before do
@repository = project.repository
@ref = 'markdown'
end
it "should handle relative urls for a file in master" do
actual = "[GitLab API doc](doc/api/README.md)\n"
expected = "<p><a href=\"/#{project.path_with_namespace}/blob/#{@ref}/doc/api/README.md\">GitLab API doc</a></p>\n"
expect(markdown(actual)).to match(expected)
end
it "should handle relative urls for a file in master with an anchor" do
actual = "[GitLab API doc](doc/api/README.md#section)\n"
expected = "<p><a href=\"/#{project.path_with_namespace}/blob/#{@ref}/doc/api/README.md#section\">GitLab API doc</a></p>\n"
expect(markdown(actual)).to match(expected)
end
it "should not handle relative urls for the current file with an anchor" do
actual = "[GitLab API doc](#section)\n"
expected = "<p><a href=\"#section\">GitLab API doc</a></p>\n"
expect(markdown(actual)).to match(expected)
end
it "should handle relative urls for a directory in master" do
actual = "[GitLab API doc](doc/api)\n"
expected = "<p><a href=\"/#{project.path_with_namespace}/tree/#{@ref}/doc/api\">GitLab API doc</a></p>\n"
expect(markdown(actual)).to match(expected)
end
it "should handle absolute urls" do
actual = "[GitLab](https://www.gitlab.com)\n"
expected = "<p><a href=\"https://www.gitlab.com\">GitLab</a></p>\n"
expect(markdown(actual)).to match(expected)
end
it "should handle relative urls in reference links for a file in master" do
actual = "[GitLab API doc][GitLab readme]\n [GitLab readme]: doc/api/README.md\n"
expected = "<p><a href=\"/#{project.path_with_namespace}/blob/#{@ref}/doc/api/README.md\">GitLab API doc</a></p>\n"
expect(markdown(actual)).to match(expected)
end
it "should handle relative urls in reference links for a directory in master" do
actual = "[GitLab API doc directory][GitLab readmes]\n [GitLab readmes]: doc/api/\n"
expected = "<p><a href=\"/#{project.path_with_namespace}/tree/#{@ref}/doc/api\">GitLab API doc directory</a></p>\n"
expect(markdown(actual)).to match(expected)
end
it "should not handle malformed relative urls in reference links for a file in master" do
actual = "[GitLab readme]: doc/api/README.md\n"
expected = ""
expect(markdown(actual)).to match(expected)
end
end
context 'with an empty repository' do
before do
@project = create(:empty_project)
@repository = @project.repository
end
it "should not touch relative urls" do
actual = "[GitLab API doc][GitLab readme]\n [GitLab readme]: doc/api/README.md\n"
expected = "<p><a href=\"doc/api/README.md\">GitLab API doc</a></p>\n"
expect(markdown(actual)).to match(expected)
end
end
end
end
describe '#render_wiki_content' do describe '#render_wiki_content' do
before do before do
@wiki = double('WikiPage') @wiki = double('WikiPage')
......
...@@ -115,18 +115,10 @@ describe Gitlab::GitAccess do ...@@ -115,18 +115,10 @@ describe Gitlab::GitAccess do
let(:actor) { key } let(:actor) { key }
context 'pull code' do context 'pull code' do
context 'allowed' do before { key.projects << project }
before { key.projects << project } subject { access.download_access_check }
subject { access.download_access_check }
it { expect(subject.allowed?).to be_truthy }
end
context 'denied' do
subject { access.download_access_check }
it { expect(subject.allowed?).to be_falsey } it { expect(subject.allowed?).to be_truthy }
end
end end
end end
end end
......
require 'spec_helper'
module Gitlab::Markdown
describe RelativeLinkFilter do
def filter(doc)
described_class.call(doc, {
commit: project.commit,
project: project,
project_wiki: project_wiki,
ref: ref,
requested_path: requested_path
})
end
def image(path)
%(<img src="#{path}" />)
end
def link(path)
%(<a href="#{path}">#{path}</a>)
end
let(:project) { create(:project) }
let(:project_path) { project.path_with_namespace }
let(:ref) { 'markdown' }
let(:project_wiki) { nil }
let(:requested_path) { '/' }
shared_examples :preserve_unchanged do
it 'does not modify any relative URL in anchor' do
doc = filter(link('README.md'))
expect(doc.at_css('a')['href']).to eq 'README.md'
end
it 'does not modify any relative URL in image' do
doc = filter(image('files/images/logo-black.png'))
expect(doc.at_css('img')['src']).to eq 'files/images/logo-black.png'
end
end
shared_examples :relative_to_requested do
it 'rebuilds URL relative to the requested path' do
doc = filter(link('users.md'))
expect(doc.at_css('a')['href']).
to eq "/#{project_path}/blob/#{ref}/doc/api/users.md"
end
end
context 'with a project_wiki' do
let(:project_wiki) { double('ProjectWiki') }
include_examples :preserve_unchanged
end
context 'without a repository' do
let(:project) { create(:empty_project) }
include_examples :preserve_unchanged
end
context 'with an empty repository' do
let(:project) { create(:project_empty_repo) }
include_examples :preserve_unchanged
end
it 'does not raise an exception on invalid URIs' do
act = link("://foo")
expect { filter(act) }.not_to raise_error
end
context 'with a valid repository' do
it 'rebuilds relative URL for a file in the repo' do
doc = filter(link('doc/api/README.md'))
expect(doc.at_css('a')['href']).
to eq "/#{project_path}/blob/#{ref}/doc/api/README.md"
end
it 'rebuilds relative URL for a file in the repo with an anchor' do
doc = filter(link('README.md#section'))
expect(doc.at_css('a')['href']).
to eq "/#{project_path}/blob/#{ref}/README.md#section"
end
it 'rebuilds relative URL for a directory in the repo' do
doc = filter(link('doc/api/'))
expect(doc.at_css('a')['href']).
to eq "/#{project_path}/tree/#{ref}/doc/api"
end
it 'rebuilds relative URL for an image in the repo' do
doc = filter(link('files/images/logo-black.png'))
expect(doc.at_css('a')['href']).
to eq "/#{project_path}/raw/#{ref}/files/images/logo-black.png"
end
it 'does not modify relative URL with an anchor only' do
doc = filter(link('#section-1'))
expect(doc.at_css('a')['href']).to eq '#section-1'
end
it 'does not modify absolute URL' do
doc = filter(link('http://example.com'))
expect(doc.at_css('a')['href']).to eq 'http://example.com'
end
context 'when requested path is a file in the repo' do
let(:requested_path) { 'doc/api/README.md' }
include_examples :relative_to_requested
end
context 'when requested path is a directory in the repo' do
let(:requested_path) { 'doc/api' }
include_examples :relative_to_requested
end
end
end
end
...@@ -86,6 +86,15 @@ describe API::API, api: true do ...@@ -86,6 +86,15 @@ describe API::API, api: true do
expect(json_response).to be_an Array expect(json_response).to be_an Array
expect(json_response.first['id']).to eq(project3.id) expect(json_response.first['id']).to eq(project3.id)
end end
it 'returns projects in the correct order when ci_enabled_first parameter is passed' do
[project, project2, project3].each{ |project| project.build_missing_services }
project2.gitlab_ci_service.update(active: true, token: "token", project_url: "url")
get api('/projects', user), { ci_enabled_first: 'true'}
expect(response.status).to eq(200)
expect(json_response).to be_an Array
expect(json_response.first['id']).to eq(project2.id)
end
end end
end end
end end
......
...@@ -30,11 +30,18 @@ describe MergeRequests::RefreshService do ...@@ -30,11 +30,18 @@ describe MergeRequests::RefreshService do
end end
context 'push to origin repo source branch' do context 'push to origin repo source branch' do
let(:refresh_service) { service.new(@project, @user) }
before do before do
service.new(@project, @user).execute(@oldrev, @newrev, 'refs/heads/master') allow(refresh_service).to receive(:execute_hooks)
refresh_service.execute(@oldrev, @newrev, 'refs/heads/master')
reload_mrs reload_mrs
end end
it 'should execute hooks with update action' do
expect(refresh_service).to have_received(:execute_hooks).
with(@merge_request, 'update')
end
it { expect(@merge_request.notes).not_to be_empty } it { expect(@merge_request.notes).not_to be_empty }
it { expect(@merge_request).to be_open } it { expect(@merge_request).to be_open }
it { expect(@fork_merge_request).to be_open } it { expect(@fork_merge_request).to be_open }
...@@ -54,11 +61,18 @@ describe MergeRequests::RefreshService do ...@@ -54,11 +61,18 @@ describe MergeRequests::RefreshService do
end end
context 'push to fork repo source branch' do context 'push to fork repo source branch' do
let(:refresh_service) { service.new(@fork_project, @user) }
before do before do
service.new(@fork_project, @user).execute(@oldrev, @newrev, 'refs/heads/master') allow(refresh_service).to receive(:execute_hooks)
refresh_service.execute(@oldrev, @newrev, 'refs/heads/master')
reload_mrs reload_mrs
end end
it 'should execute hooks with update action' do
expect(refresh_service).to have_received(:execute_hooks).
with(@fork_merge_request, 'update')
end
it { expect(@merge_request.notes).to be_empty } it { expect(@merge_request.notes).to be_empty }
it { expect(@merge_request).to be_open } it { expect(@merge_request).to be_open }
it { expect(@fork_merge_request.notes.last.note).to include('Added 4 commits') } it { expect(@fork_merge_request.notes.last.note).to include('Added 4 commits') }
......
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