summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDouwe Maan <douwe@gitlab.com>2015-09-09 12:01:38 +0100
committerDouwe Maan <douwe@gitlab.com>2015-09-09 12:01:38 +0100
commit2c8d5aeaf332e25c030b7287919958bc7809e831 (patch)
treea6e308f25ba67279e713d0ed907d1e72f7f758b0 /lib
parent58c487e28b3f10c8a871dc82f7d79a45c7876f15 (diff)
parente0da2c352325c1cb2ede88a73434ed7afc037481 (diff)
downloadgitlab-ce-2c8d5aeaf332e25c030b7287919958bc7809e831.tar.gz
Merge branch 'master' into reply-by-email-docs
Diffstat (limited to 'lib')
-rw-r--r--lib/api/api.rb1
-rw-r--r--lib/api/entities.rb4
-rw-r--r--lib/api/helpers.rb26
-rw-r--r--lib/api/keys.rb20
-rw-r--r--lib/api/services.rb86
-rw-r--r--lib/gitlab/backend/grack_auth.rb49
-rw-r--r--lib/gitlab/bitbucket_import/client.rb23
-rw-r--r--lib/gitlab/bitbucket_import/importer.rb34
-rw-r--r--lib/gitlab/color_schemes.rb67
-rw-r--r--lib/gitlab/current_settings.rb14
-rw-r--r--lib/gitlab/github_import/importer.rb3
-rw-r--r--lib/gitlab/gitlab_import/importer.rb3
-rw-r--r--lib/gitlab/import_formatter.rb4
-rw-r--r--lib/gitlab/ldap/user.rb11
-rw-r--r--lib/gitlab/markdown.rb65
-rw-r--r--lib/gitlab/markdown/autolink_filter.rb1
-rw-r--r--lib/gitlab/markdown/commit_range_reference_filter.rb2
-rw-r--r--lib/gitlab/markdown/commit_reference_filter.rb2
-rw-r--r--lib/gitlab/markdown/cross_project_reference.rb2
-rw-r--r--lib/gitlab/markdown/emoji_filter.rb3
-rw-r--r--lib/gitlab/markdown/external_issue_reference_filter.rb2
-rw-r--r--lib/gitlab/markdown/external_link_filter.rb1
-rw-r--r--lib/gitlab/markdown/issue_reference_filter.rb2
-rw-r--r--lib/gitlab/markdown/label_reference_filter.rb2
-rw-r--r--lib/gitlab/markdown/merge_request_reference_filter.rb2
-rw-r--r--lib/gitlab/markdown/reference_filter.rb4
-rw-r--r--lib/gitlab/markdown/relative_link_filter.rb1
-rw-r--r--lib/gitlab/markdown/sanitization_filter.rb1
-rw-r--r--lib/gitlab/markdown/snippet_reference_filter.rb2
-rw-r--r--lib/gitlab/markdown/syntax_highlight_filter.rb39
-rw-r--r--lib/gitlab/markdown/table_of_contents_filter.rb1
-rw-r--r--lib/gitlab/markdown/task_list_filter.rb1
-rw-r--r--lib/gitlab/markdown/user_reference_filter.rb2
-rw-r--r--lib/gitlab/reference_extractor.rb10
-rw-r--r--lib/gitlab/themes.rb18
-rw-r--r--lib/gitlab/url_builder.rb8
-rw-r--r--lib/redcarpet/render/gitlab_html.rb46
-rwxr-xr-xlib/support/init.d/gitlab76
-rwxr-xr-xlib/support/init.d/gitlab.default.example10
-rw-r--r--lib/support/nginx/gitlab44
-rw-r--r--lib/support/nginx/gitlab-ssl44
-rw-r--r--lib/tasks/gitlab/check.rake13
-rw-r--r--lib/tasks/services.rake89
43 files changed, 607 insertions, 231 deletions
diff --git a/lib/api/api.rb b/lib/api/api.rb
index eebd44ea5b6..c09488d3547 100644
--- a/lib/api/api.rb
+++ b/lib/api/api.rb
@@ -50,5 +50,6 @@ module API
mount Branches
mount Labels
mount Settings
+ mount Keys
end
end
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index 1f9dd6bc152..8dddcd7ccc3 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -199,6 +199,10 @@ module API
expose :id, :title, :key, :created_at
end
+ class SSHKeyWithUser < SSHKey
+ expose :user, using: Entities::UserFull
+ end
+
class Note < Grape::Entity
expose :id
expose :note, as: :body
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index 1ebf9a1f022..76c9cc2e3a4 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -55,6 +55,32 @@ module API
end
end
+ def project_service
+ @project_service ||= begin
+ underscored_service = params[:service_slug].underscore
+
+ if Service.available_services_names.include?(underscored_service)
+ user_project.build_missing_services
+
+ service_method = "#{underscored_service}_service"
+
+ send_service(service_method)
+ end
+ end
+
+ @project_service || not_found!("Service")
+ end
+
+ def send_service(service_method)
+ user_project.send(service_method)
+ end
+
+ def service_attributes
+ @service_attributes ||= project_service.fields.inject([]) do |arr, hash|
+ arr << hash[:name].to_sym
+ end
+ end
+
def find_group(id)
begin
group = Group.find(id)
diff --git a/lib/api/keys.rb b/lib/api/keys.rb
new file mode 100644
index 00000000000..2b723b79504
--- /dev/null
+++ b/lib/api/keys.rb
@@ -0,0 +1,20 @@
+module API
+ # Keys API
+ class Keys < Grape::API
+ before { authenticate! }
+
+ resource :keys do
+ # Get single ssh key by id. Only available to admin users.
+ #
+ # Example Request:
+ # GET /keys/:id
+ get ":id" do
+ authenticated_as_admin!
+
+ key = Key.find(params[:id])
+
+ present key, with: Entities::SSHKeyWithUser
+ end
+ end
+ end
+end
diff --git a/lib/api/services.rb b/lib/api/services.rb
index 3ad59cf3adf..73645cedea4 100644
--- a/lib/api/services.rb
+++ b/lib/api/services.rb
@@ -4,73 +4,49 @@ module API
before { authenticate! }
before { authorize_admin_project }
+
resource :projects do
- # Set GitLab CI service for project
- #
- # Parameters:
- # token (required) - CI project token
- # project_url (required) - CI project url
+ # Set <service_slug> service for project
#
# Example Request:
+ #
# PUT /projects/:id/services/gitlab-ci
- put ":id/services/gitlab-ci" do
- required_attributes! [:token, :project_url]
- attrs = attributes_for_keys [:token, :project_url]
- user_project.build_missing_services
-
- if user_project.gitlab_ci_service.update_attributes(attrs.merge(active: true))
- true
- else
- not_found!
- end
- end
-
- # Delete GitLab CI service settings
#
- # Example Request:
- # DELETE /projects/:id/services/gitlab-ci
- delete ":id/services/gitlab-ci" do
- if user_project.gitlab_ci_service
- user_project.gitlab_ci_service.update_attributes(
- active: false,
- token: nil,
- project_url: nil
- )
- end
- end
+ put ':id/services/:service_slug' do
+ if project_service
+ validators = project_service.class.validators.select do |s|
+ s.class == ActiveRecord::Validations::PresenceValidator &&
+ s.attributes != [:project_id]
+ end
- # Set Hipchat service for project
- #
- # Parameters:
- # token (required) - Hipchat token
- # room (required) - Hipchat room name
- #
- # Example Request:
- # PUT /projects/:id/services/hipchat
- put ':id/services/hipchat' do
- required_attributes! [:token, :room]
- attrs = attributes_for_keys [:token, :room]
- user_project.build_missing_services
+ required_attributes! validators.map(&:attributes).flatten.uniq
+ attrs = attributes_for_keys service_attributes
- if user_project.hipchat_service.update_attributes(
- attrs.merge(active: true))
- true
- else
- not_found!
+ if project_service.update_attributes(attrs.merge(active: true))
+ true
+ else
+ not_found!
+ end
end
end
- # Delete Hipchat service settings
+ # Delete <service_slug> service for project
#
# Example Request:
- # DELETE /projects/:id/services/hipchat
- delete ':id/services/hipchat' do
- if user_project.hipchat_service
- user_project.hipchat_service.update_attributes(
- active: false,
- token: nil,
- room: nil
- )
+ #
+ # DELETE /project/:id/services/gitlab-ci
+ #
+ delete ':id/services/:service_slug' do
+ if project_service
+ attrs = service_attributes.inject({}) do |hash, key|
+ hash.merge!(key => nil)
+ end
+
+ if project_service.update_attributes(attrs.merge(active: false))
+ true
+ else
+ not_found!
+ end
end
end
end
diff --git a/lib/gitlab/backend/grack_auth.rb b/lib/gitlab/backend/grack_auth.rb
index 12292f614e9..0353b3b7ed3 100644
--- a/lib/gitlab/backend/grack_auth.rb
+++ b/lib/gitlab/backend/grack_auth.rb
@@ -1,6 +1,14 @@
require_relative 'shell_env'
module Grack
+ class AuthSpawner
+ def self.call(env)
+ # Avoid issues with instance variables in Grack::Auth persisting across
+ # requests by creating a new instance for each request.
+ Auth.new({}).call(env)
+ end
+ end
+
class Auth < Rack::Auth::Basic
attr_accessor :user, :project, :env
@@ -10,7 +18,7 @@ module Grack
@request = Rack::Request.new(env)
@auth = Request.new(env)
- @gitlab_ci = false
+ @ci = false
# Need this patch due to the rails mount
# Need this if under RELATIVE_URL_ROOT
@@ -26,13 +34,9 @@ module Grack
auth!
if project && authorized_request?
- if ENV['GITLAB_GRACK_AUTH_ONLY'] == '1'
- # Tell gitlab-git-http-server the request is OK, and what the GL_ID is
- render_grack_auth_ok
- else
- @app.call(env)
- end
- elsif @user.nil? && !@gitlab_ci
+ # Tell gitlab-git-http-server the request is OK, and what the GL_ID is
+ render_grack_auth_ok
+ elsif @user.nil? && !@ci
unauthorized
else
render_not_found
@@ -51,8 +55,8 @@ module Grack
# Allow authentication for GitLab CI service
# if valid token passed
- if gitlab_ci_request?(login, password)
- @gitlab_ci = true
+ if ci_request?(login, password)
+ @ci = true
return
end
@@ -64,12 +68,17 @@ module Grack
end
end
- def gitlab_ci_request?(login, password)
- if login == "gitlab-ci-token" && project && project.gitlab_ci?
- token = project.gitlab_ci_service.token
+ def ci_request?(login, password)
+ matched_login = /(?<s>^[a-zA-Z]*-ci)-token$/.match(login)
+
+ if project && matched_login.present? && git_cmd == 'git-upload-pack'
+ underscored_service = matched_login['s'].underscore
- if token.present? && token == password && git_cmd == 'git-upload-pack'
- return true
+ if Service.available_services_names.include?(underscored_service)
+ service_method = "#{underscored_service}_service"
+ service = project.send(service_method)
+
+ return service && service.activated? && service.valid_token?(password)
end
end
@@ -128,11 +137,13 @@ module Grack
end
def authorized_request?
- return true if @gitlab_ci
+ return true if @ci
case git_cmd
when *Gitlab::GitAccess::DOWNLOAD_COMMANDS
- if user
+ if !Gitlab.config.gitlab_shell.upload_pack
+ false
+ elsif user
Gitlab::GitAccess.new(user, project).download_access_check.allowed?
elsif project.public?
# Allow clone/fetch for public projects
@@ -141,7 +152,9 @@ module Grack
false
end
when *Gitlab::GitAccess::PUSH_COMMANDS
- if user
+ if !Gitlab.config.gitlab_shell.receive_pack
+ false
+ elsif user
# Skip user authorization on upload request.
# It will be done by the pre-receive hook in the repository.
true
diff --git a/lib/gitlab/bitbucket_import/client.rb b/lib/gitlab/bitbucket_import/client.rb
index aec44b8c87b..d88a6eaac6b 100644
--- a/lib/gitlab/bitbucket_import/client.rb
+++ b/lib/gitlab/bitbucket_import/client.rb
@@ -52,11 +52,26 @@ module Gitlab
end
def issues(project_identifier)
- JSON.parse(get("/api/1.0/repositories/#{project_identifier}/issues").body)
+ all_issues = []
+ offset = 0
+ per_page = 50 # Maximum number allowed by Bitbucket
+ index = 0
+
+ begin
+ issues = JSON.parse(get(issue_api_endpoint(project_identifier, per_page, offset)).body)
+ # Find out how many total issues are present
+ total = issues["count"] if index == 0
+ all_issues.concat(issues["issues"])
+ offset += issues["issues"].count
+ index += 1
+ end while all_issues.count < total
+
+ all_issues
end
def issue_comments(project_identifier, issue_id)
- JSON.parse(get("/api/1.0/repositories/#{project_identifier}/issues/#{issue_id}/comments").body)
+ comments = JSON.parse(get("/api/1.0/repositories/#{project_identifier}/issues/#{issue_id}/comments").body)
+ comments.sort_by { |comment| comment["utc_created_on"] }
end
def project(project_identifier)
@@ -100,6 +115,10 @@ module Gitlab
response
end
+ def issue_api_endpoint(project_identifier, per_page, offset)
+ "/api/1.0/repositories/#{project_identifier}/issues?sort=utc_created_on&limit=#{per_page}&start=#{offset}"
+ end
+
def config
Gitlab.config.omniauth.providers.find { |provider| provider.name == "bitbucket"}
end
diff --git a/lib/gitlab/bitbucket_import/importer.rb b/lib/gitlab/bitbucket_import/importer.rb
index d8a7d29f1bf..2355b3c6ddc 100644
--- a/lib/gitlab/bitbucket_import/importer.rb
+++ b/lib/gitlab/bitbucket_import/importer.rb
@@ -20,8 +20,18 @@ module Gitlab
#Issues && Comments
issues = client.issues(project_identifier)
- issues["issues"].each do |issue|
- body = @formatter.author_line(issue["reported_by"]["username"], issue["content"])
+ issues.each do |issue|
+ body = ''
+ reporter = nil
+ author = 'Anonymous'
+
+ if issue["reported_by"] && issue["reported_by"]["username"]
+ reporter = issue["reported_by"]["username"]
+ author = reporter
+ end
+
+ body = @formatter.author_line(author)
+ body += issue["content"]
comments = client.issue_comments(project_identifier, issue["local_id"])
@@ -30,14 +40,20 @@ module Gitlab
end
comments.each do |comment|
- body += @formatter.comment(comment["author_info"]["username"], comment["utc_created_on"], comment["content"])
+ author = 'Anonymous'
+
+ if comment["author_info"] && comment["author_info"]["username"]
+ author = comment["author_info"]["username"]
+ end
+
+ body += @formatter.comment(author, comment["utc_created_on"], comment["content"])
end
project.issues.create!(
description: body,
title: issue["title"],
state: %w(resolved invalid duplicate wontfix).include?(issue["status"]) ? 'closed' : 'opened',
- author_id: gl_user_id(project, issue["reported_by"]["username"])
+ author_id: gl_user_id(project, reporter)
)
end
@@ -47,9 +63,13 @@ module Gitlab
private
def gl_user_id(project, bitbucket_id)
- user = User.joins(:identities).find_by("identities.extern_uid = ? AND identities.provider = 'bitbucket'", bitbucket_id.to_s)
- (user && user.id) || project.creator_id
- end
+ if bitbucket_id
+ user = User.joins(:identities).find_by("identities.extern_uid = ? AND identities.provider = 'bitbucket'", bitbucket_id.to_s)
+ (user && user.id) || project.creator_id
+ else
+ project.creator_id
+ end
+ end
end
end
end
diff --git a/lib/gitlab/color_schemes.rb b/lib/gitlab/color_schemes.rb
new file mode 100644
index 00000000000..9c4664df903
--- /dev/null
+++ b/lib/gitlab/color_schemes.rb
@@ -0,0 +1,67 @@
+module Gitlab
+ # Module containing GitLab's syntax color scheme definitions and helper
+ # methods for accessing them.
+ module ColorSchemes
+ # Struct class representing a single Scheme
+ Scheme = Struct.new(:id, :name, :css_class)
+
+ SCHEMES = [
+ Scheme.new(1, 'White', 'white'),
+ Scheme.new(2, 'Dark', 'dark'),
+ Scheme.new(3, 'Solarized Light', 'solarized-light'),
+ Scheme.new(4, 'Solarized Dark', 'solarized-dark'),
+ Scheme.new(5, 'Monokai', 'monokai')
+ ].freeze
+
+ # Convenience method to get a space-separated String of all the color scheme
+ # classes that might be applied to a code block.
+ #
+ # Returns a String
+ def self.body_classes
+ SCHEMES.collect(&:css_class).uniq.join(' ')
+ end
+
+ # Get a Scheme by its ID
+ #
+ # If the ID is invalid, returns the default Scheme.
+ #
+ # id - Integer ID
+ #
+ # Returns a Scheme
+ def self.by_id(id)
+ SCHEMES.detect { |s| s.id == id } || default
+ end
+
+ # Returns the number of defined Schemes
+ def self.count
+ SCHEMES.size
+ end
+
+ # Get the default Scheme
+ #
+ # Returns a Scheme
+ def self.default
+ by_id(1)
+ end
+
+ # Iterate through each Scheme
+ #
+ # Yields the Scheme object
+ def self.each(&block)
+ SCHEMES.each(&block)
+ end
+
+ # Get the Scheme for the specified user, or the default
+ #
+ # user - User record
+ #
+ # Returns a Scheme
+ def self.for_user(user)
+ if user
+ by_id(user.color_scheme_id)
+ else
+ default
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/current_settings.rb b/lib/gitlab/current_settings.rb
index 1a2a50a14d0..0ea1b6a2f6f 100644
--- a/lib/gitlab/current_settings.rb
+++ b/lib/gitlab/current_settings.rb
@@ -4,7 +4,7 @@ module Gitlab
key = :current_application_settings
RequestStore.store[key] ||= begin
- if ActiveRecord::Base.connected? && ActiveRecord::Base.connection.table_exists?('application_settings')
+ if connect_to_db?
ApplicationSetting.current || ApplicationSetting.create_from_defaults
else
fake_application_settings
@@ -26,5 +26,17 @@ module Gitlab
import_sources: Settings.gitlab['import_sources']
)
end
+
+ private
+
+ def connect_to_db?
+ use_db = if ENV['USE_DB'] == "false"
+ false
+ else
+ true
+ end
+
+ use_db && ActiveRecord::Base.connection.active? && ActiveRecord::Base.connection.table_exists?('application_settings')
+ end
end
end
diff --git a/lib/gitlab/github_import/importer.rb b/lib/gitlab/github_import/importer.rb
index 8c106a61735..bd7340a80f1 100644
--- a/lib/gitlab/github_import/importer.rb
+++ b/lib/gitlab/github_import/importer.rb
@@ -18,7 +18,8 @@ module Gitlab
direction: :asc).each do |issue|
if issue.pull_request.nil?
- body = @formatter.author_line(issue.user.login, issue.body)
+ body = @formatter.author_line(issue.user.login)
+ body += issue.body
if issue.comments > 0
body += @formatter.comments_header
diff --git a/lib/gitlab/gitlab_import/importer.rb b/lib/gitlab/gitlab_import/importer.rb
index 50594d2b24f..e24b94d6159 100644
--- a/lib/gitlab/gitlab_import/importer.rb
+++ b/lib/gitlab/gitlab_import/importer.rb
@@ -18,7 +18,8 @@ module Gitlab
issues = client.issues(project_identifier)
issues.each do |issue|
- body = @formatter.author_line(issue["author"]["name"], issue["description"])
+ body = @formatter.author_line(issue["author"]["name"])
+ body += issue["description"]
comments = client.issue_comments(project_identifier, issue["id"])
diff --git a/lib/gitlab/import_formatter.rb b/lib/gitlab/import_formatter.rb
index 72e041a90b1..3e54456e936 100644
--- a/lib/gitlab/import_formatter.rb
+++ b/lib/gitlab/import_formatter.rb
@@ -8,8 +8,8 @@ module Gitlab
"\n\n\n**Imported comments:**\n"
end
- def author_line(author, body)
- "*Created by: #{author}*\n\n#{body}"
+ def author_line(author)
+ "*Created by: #{author}*\n\n"
end
end
end
diff --git a/lib/gitlab/ldap/user.rb b/lib/gitlab/ldap/user.rb
index f7f3ba9ad7d..04a22237478 100644
--- a/lib/gitlab/ldap/user.rb
+++ b/lib/gitlab/ldap/user.rb
@@ -44,9 +44,14 @@ module Gitlab
gl_user.skip_reconfirmation!
gl_user.email = auth_hash.email
- # Build new identity only if we dont have have same one
- gl_user.identities.find_or_initialize_by(provider: auth_hash.provider,
- extern_uid: auth_hash.uid)
+ # find_or_initialize_by doesn't update `gl_user.identities`, and isn't autosaved.
+ identity = gl_user.identities.find { |identity| identity.provider == auth_hash.provider }
+ identity ||= gl_user.identities.build(provider: auth_hash.provider)
+
+ # For a new user set extern_uid to the LDAP DN
+ # For an existing user with matching email but changed DN, update the DN.
+ # For an existing user with no change in DN, this line changes nothing.
+ identity.extern_uid = auth_hash.uid
gl_user
end
diff --git a/lib/gitlab/markdown.rb b/lib/gitlab/markdown.rb
index 9f6e19a09fd..097caf67a65 100644
--- a/lib/gitlab/markdown.rb
+++ b/lib/gitlab/markdown.rb
@@ -5,6 +5,32 @@ module Gitlab
#
# See the files in `lib/gitlab/markdown/` for specific processing information.
module Markdown
+ # Convert a Markdown String into an HTML-safe String of HTML
+ #
+ # markdown - Markdown String
+ # context - Hash of context options passed to our HTML Pipeline
+ #
+ # Returns an HTML-safe String
+ def self.render(markdown, context = {})
+ html = renderer.render(markdown)
+ html = gfm(html, context)
+
+ html.html_safe
+ end
+
+ # Convert a Markdown String into HTML without going through the HTML
+ # Pipeline.
+ #
+ # Note that because the pipeline is skipped, SanitizationFilter is as well.
+ # Do not output the result of this method to the user.
+ #
+ # markdown - Markdown String
+ #
+ # Returns a String
+ def self.render_without_gfm(markdown)
+ renderer.render(markdown)
+ end
+
# Provide autoload paths for filters to prevent a circular dependency error
autoload :AutolinkFilter, 'gitlab/markdown/autolink_filter'
autoload :CommitRangeReferenceFilter, 'gitlab/markdown/commit_range_reference_filter'
@@ -18,6 +44,7 @@ module Gitlab
autoload :RelativeLinkFilter, 'gitlab/markdown/relative_link_filter'
autoload :SanitizationFilter, 'gitlab/markdown/sanitization_filter'
autoload :SnippetReferenceFilter, 'gitlab/markdown/snippet_reference_filter'
+ autoload :SyntaxHighlightFilter, 'gitlab/markdown/syntax_highlight_filter'
autoload :TableOfContentsFilter, 'gitlab/markdown/table_of_contents_filter'
autoload :TaskListFilter, 'gitlab/markdown/task_list_filter'
autoload :UserReferenceFilter, 'gitlab/markdown/user_reference_filter'
@@ -28,8 +55,7 @@ module Gitlab
# options - A Hash of options used to customize output (default: {}):
# :xhtml - output XHTML instead of HTML
# :reference_only_path - Use relative path for reference links
- # html_options - extra options for the reference links as given to link_to
- def gfm(text, options = {}, html_options = {})
+ def self.gfm(text, options = {})
return text if text.nil?
# Duplicate the string so we don't alter the original, then call to_str
@@ -40,8 +66,8 @@ module Gitlab
options.reverse_merge!(
xhtml: false,
reference_only_path: true,
- project: @project,
- current_user: current_user
+ project: options[:project],
+ current_user: options[:current_user]
)
@pipeline ||= HTML::Pipeline.new(filters)
@@ -61,12 +87,11 @@ module Gitlab
current_user: options[:current_user],
only_path: options[:reference_only_path],
project: options[:project],
- reference_class: html_options[:class],
# RelativeLinkFilter
- ref: @ref,
- requested_path: @path,
- project_wiki: @project_wiki
+ ref: options[:ref],
+ requested_path: options[:path],
+ project_wiki: options[:project_wiki]
}
result = @pipeline.call(text, context)
@@ -83,14 +108,36 @@ module Gitlab
private
+ def self.renderer
+ @markdown ||= begin
+ renderer = Redcarpet::Render::HTML.new
+ Redcarpet::Markdown.new(renderer, redcarpet_options)
+ end
+ end
+
+ def self.redcarpet_options
+ # https://github.com/vmg/redcarpet#and-its-like-really-simple-to-use
+ @redcarpet_options ||= {
+ fenced_code_blocks: true,
+ footnotes: true,
+ lax_spacing: true,
+ no_intra_emphasis: true,
+ space_after_headers: true,
+ strikethrough: true,
+ superscript: true,
+ tables: true
+ }.freeze
+ end
+
# Filters used in our pipeline
#
# SanitizationFilter should come first so that all generated reference HTML
# goes through untouched.
#
# See https://github.com/jch/html-pipeline#filters for more filters.
- def filters
+ def self.filters
[
+ Gitlab::Markdown::SyntaxHighlightFilter,
Gitlab::Markdown::SanitizationFilter,
Gitlab::Markdown::RelativeLinkFilter,
diff --git a/lib/gitlab/markdown/autolink_filter.rb b/lib/gitlab/markdown/autolink_filter.rb
index 541f1d88ffc..c37c3bc55bf 100644
--- a/lib/gitlab/markdown/autolink_filter.rb
+++ b/lib/gitlab/markdown/autolink_filter.rb
@@ -1,3 +1,4 @@
+require 'gitlab/markdown'
require 'html/pipeline/filter'
require 'uri'
diff --git a/lib/gitlab/markdown/commit_range_reference_filter.rb b/lib/gitlab/markdown/commit_range_reference_filter.rb
index a9f1ee9c161..8613150894b 100644
--- a/lib/gitlab/markdown/commit_range_reference_filter.rb
+++ b/lib/gitlab/markdown/commit_range_reference_filter.rb
@@ -1,3 +1,5 @@
+require 'gitlab/markdown'
+
module Gitlab
module Markdown
# HTML filter that replaces commit range references with links.
diff --git a/lib/gitlab/markdown/commit_reference_filter.rb b/lib/gitlab/markdown/commit_reference_filter.rb
index eacdf8a6d37..5696b4fa585 100644
--- a/lib/gitlab/markdown/commit_reference_filter.rb
+++ b/lib/gitlab/markdown/commit_reference_filter.rb
@@ -1,3 +1,5 @@
+require 'gitlab/markdown'
+
module Gitlab
module Markdown
# HTML filter that replaces commit references with links.
diff --git a/lib/gitlab/markdown/cross_project_reference.rb b/lib/gitlab/markdown/cross_project_reference.rb
index 66c256c5104..855748fdccc 100644
--- a/lib/gitlab/markdown/cross_project_reference.rb
+++ b/lib/gitlab/markdown/cross_project_reference.rb
@@ -1,3 +1,5 @@
+require 'gitlab/markdown'
+
module Gitlab
module Markdown
# Common methods for ReferenceFilters that support an optional cross-project
diff --git a/lib/gitlab/markdown/emoji_filter.rb b/lib/gitlab/markdown/emoji_filter.rb
index 6794ab9c897..da10e4d3760 100644
--- a/lib/gitlab/markdown/emoji_filter.rb
+++ b/lib/gitlab/markdown/emoji_filter.rb
@@ -1,6 +1,7 @@
+require 'action_controller'
+require 'gitlab/markdown'
require 'gitlab_emoji'
require 'html/pipeline/filter'
-require 'action_controller'
module Gitlab
module Markdown
diff --git a/lib/gitlab/markdown/external_issue_reference_filter.rb b/lib/gitlab/markdown/external_issue_reference_filter.rb
index afd28dd8cf3..f7c43e1ca89 100644
--- a/lib/gitlab/markdown/external_issue_reference_filter.rb
+++ b/lib/gitlab/markdown/external_issue_reference_filter.rb
@@ -1,3 +1,5 @@
+require 'gitlab/markdown'
+
module Gitlab
module Markdown
# HTML filter that replaces external issue tracker references with links.
diff --git a/lib/gitlab/markdown/external_link_filter.rb b/lib/gitlab/markdown/external_link_filter.rb
index c539e0fb823..29e51b6ade6 100644
--- a/lib/gitlab/markdown/external_link_filter.rb
+++ b/lib/gitlab/markdown/external_link_filter.rb
@@ -1,3 +1,4 @@
+require 'gitlab/markdown'
require 'html/pipeline/filter'
module Gitlab
diff --git a/lib/gitlab/markdown/issue_reference_filter.rb b/lib/gitlab/markdown/issue_reference_filter.rb
index ab6f6bc1cf7..01320f80796 100644
--- a/lib/gitlab/markdown/issue_reference_filter.rb
+++ b/lib/gitlab/markdown/issue_reference_filter.rb
@@ -1,3 +1,5 @@
+require 'gitlab/markdown'
+
module Gitlab
module Markdown
# HTML filter that replaces issue references with links. References to
diff --git a/lib/gitlab/markdown/label_reference_filter.rb b/lib/gitlab/markdown/label_reference_filter.rb
index 2186f36f854..3d7445a27f1 100644
--- a/lib/gitlab/markdown/label_reference_filter.rb
+++ b/lib/gitlab/markdown/label_reference_filter.rb
@@ -1,3 +1,5 @@
+require 'gitlab/markdown'
+
module Gitlab
module Markdown
# HTML filter that replaces label references with links.
diff --git a/lib/gitlab/markdown/merge_request_reference_filter.rb b/lib/gitlab/markdown/merge_request_reference_filter.rb
index 884f60f9d53..48248f5219d 100644
--- a/lib/gitlab/markdown/merge_request_reference_filter.rb
+++ b/lib/gitlab/markdown/merge_request_reference_filter.rb
@@ -1,3 +1,5 @@
+require 'gitlab/markdown'
+
module Gitlab
module Markdown
# HTML filter that replaces merge request references with links. References
diff --git a/lib/gitlab/markdown/reference_filter.rb b/lib/gitlab/markdown/reference_filter.rb
index 47ee1d99da3..9b293c957d6 100644
--- a/lib/gitlab/markdown/reference_filter.rb
+++ b/lib/gitlab/markdown/reference_filter.rb
@@ -1,4 +1,5 @@
require 'active_support/core_ext/string/output_safety'
+require 'gitlab/markdown'
require 'html/pipeline/filter'
module Gitlab
@@ -9,7 +10,6 @@ module Gitlab
#
# Context options:
# :project (required) - Current project, ignored if reference is cross-project.
- # :reference_class - Custom CSS class added to reference links.
# :only_path - Generate path-only links.
#
# Results:
@@ -70,7 +70,7 @@ module Gitlab
end
def reference_class(type)
- "gfm gfm-#{type} #{context[:reference_class]}".strip
+ "gfm gfm-#{type}"
end
# Iterate through the document's text nodes, yielding the current node's
diff --git a/lib/gitlab/markdown/relative_link_filter.rb b/lib/gitlab/markdown/relative_link_filter.rb
index 30f50b82996..8c5cf51bfe1 100644
--- a/lib/gitlab/markdown/relative_link_filter.rb
+++ b/lib/gitlab/markdown/relative_link_filter.rb
@@ -1,3 +1,4 @@
+require 'gitlab/markdown'
require 'html/pipeline/filter'
require 'uri'
diff --git a/lib/gitlab/markdown/sanitization_filter.rb b/lib/gitlab/markdown/sanitization_filter.rb
index 74b3a8d274f..68ed57f6257 100644
--- a/lib/gitlab/markdown/sanitization_filter.rb
+++ b/lib/gitlab/markdown/sanitization_filter.rb
@@ -1,3 +1,4 @@
+require 'gitlab/markdown'
require 'html/pipeline/filter'
require 'html/pipeline/sanitization_filter'
diff --git a/lib/gitlab/markdown/snippet_reference_filter.rb b/lib/gitlab/markdown/snippet_reference_filter.rb
index 92979a356dc..9e1aab936cb 100644
--- a/lib/gitlab/markdown/snippet_reference_filter.rb
+++ b/lib/gitlab/markdown/snippet_reference_filter.rb
@@ -1,3 +1,5 @@
+require 'gitlab/markdown'
+
module Gitlab
module Markdown
# HTML filter that replaces snippet references with links. References to
diff --git a/lib/gitlab/markdown/syntax_highlight_filter.rb b/lib/gitlab/markdown/syntax_highlight_filter.rb
new file mode 100644
index 00000000000..86f4385753a
--- /dev/null
+++ b/lib/gitlab/markdown/syntax_highlight_filter.rb
@@ -0,0 +1,39 @@
+require 'gitlab/markdown'
+require 'html/pipeline/filter'
+require 'rouge/plugins/redcarpet'
+
+module Gitlab
+ module Markdown
+ # HTML Filter to highlight fenced code blocks
+ #
+ class SyntaxHighlightFilter < HTML::Pipeline::Filter
+ include Rouge::Plugins::Redcarpet
+
+ def call
+ doc.search('pre > code').each do |node|
+ highlight_node(node)
+ end
+
+ doc
+ end
+
+ def highlight_node(node)
+ language = node.attr('class')
+ code = node.text
+
+ highlighted = block_code(code, language)
+
+ # Replace the parent `pre` element with the entire highlighted block
+ node.parent.replace(highlighted)
+ end
+
+ private
+
+ # Override Rouge::Plugins::Redcarpet#rouge_formatter
+ def rouge_formatter(lexer)
+ Rouge::Formatters::HTMLGitlab.new(
+ cssclass: "code highlight js-syntax-highlight #{lexer.tag}")
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/markdown/table_of_contents_filter.rb b/lib/gitlab/markdown/table_of_contents_filter.rb
index 38887c9778c..bbb3bf7fc8b 100644
--- a/lib/gitlab/markdown/table_of_contents_filter.rb
+++ b/lib/gitlab/markdown/table_of_contents_filter.rb
@@ -1,3 +1,4 @@
+require 'gitlab/markdown'
require 'html/pipeline/filter'
module Gitlab
diff --git a/lib/gitlab/markdown/task_list_filter.rb b/lib/gitlab/markdown/task_list_filter.rb
index c6eb2e2bf6d..2f133ae8500 100644
--- a/lib/gitlab/markdown/task_list_filter.rb
+++ b/lib/gitlab/markdown/task_list_filter.rb
@@ -1,3 +1,4 @@
+require 'gitlab/markdown'
require 'task_list/filter'
module Gitlab
diff --git a/lib/gitlab/markdown/user_reference_filter.rb b/lib/gitlab/markdown/user_reference_filter.rb
index a4aec7a05d1..1871e52df0e 100644
--- a/lib/gitlab/markdown/user_reference_filter.rb
+++ b/lib/gitlab/markdown/user_reference_filter.rb
@@ -1,3 +1,5 @@
+require 'gitlab/markdown'
+
module Gitlab
module Markdown
# HTML filter that replaces user or group references with links.
diff --git a/lib/gitlab/reference_extractor.rb b/lib/gitlab/reference_extractor.rb
index e836b05ff25..0961bd80421 100644
--- a/lib/gitlab/reference_extractor.rb
+++ b/lib/gitlab/reference_extractor.rb
@@ -1,3 +1,5 @@
+require 'gitlab/markdown'
+
module Gitlab
# Extract possible GFM references from an arbitrary String for further processing.
class ReferenceExtractor
@@ -10,7 +12,7 @@ module Gitlab
def analyze(text)
references.clear
- @text = markdown.render(text.dup)
+ @text = Gitlab::Markdown.render_without_gfm(text)
end
%i(user label issue merge_request snippet commit commit_range).each do |type|
@@ -21,10 +23,6 @@ module Gitlab
private
- def markdown
- @markdown ||= Redcarpet::Markdown.new(Redcarpet::Render::HTML, GitlabMarkdownHelper::MARKDOWN_OPTIONS)
- end
-
def references
@references ||= Hash.new do |references, type|
type = type.to_sym
@@ -42,7 +40,7 @@ module Gitlab
# Returns the results Array for the requested filter type
def pipeline_result(filter_type)
klass = filter_type.to_s.camelize + 'ReferenceFilter'
- filter = "Gitlab::Markdown::#{klass}".constantize
+ filter = Gitlab::Markdown.const_get(klass)
context = {
project: project,
diff --git a/lib/gitlab/themes.rb b/lib/gitlab/themes.rb
index 5209df92795..83f91de810c 100644
--- a/lib/gitlab/themes.rb
+++ b/lib/gitlab/themes.rb
@@ -37,6 +37,11 @@ module Gitlab
THEMES.detect { |t| t.id == id } || default
end
+ # Returns the number of defined Themes
+ def self.count
+ THEMES.size
+ end
+
# Get the default Theme
#
# Returns a Theme
@@ -51,6 +56,19 @@ module Gitlab
THEMES.each(&block)
end
+ # Get the Theme for the specified user, or the default
+ #
+ # user - User record
+ #
+ # Returns a Theme
+ def self.for_user(user)
+ if user
+ by_id(user.theme_id)
+ else
+ default
+ end
+ end
+
private
def self.default_id
diff --git a/lib/gitlab/url_builder.rb b/lib/gitlab/url_builder.rb
index 11b0d44f340..779819bc2bf 100644
--- a/lib/gitlab/url_builder.rb
+++ b/lib/gitlab/url_builder.rb
@@ -23,12 +23,12 @@ module Gitlab
def build_issue_url(id)
issue = Issue.find(id)
- issue_url(issue, host: Gitlab.config.gitlab['url'])
+ issue_url(issue)
end
def build_merge_request_url(id)
merge_request = MergeRequest.find(id)
- merge_request_url(merge_request, host: Gitlab.config.gitlab['url'])
+ merge_request_url(merge_request)
end
def build_note_url(id)
@@ -37,22 +37,18 @@ module Gitlab
namespace_project_commit_url(namespace_id: note.project.namespace,
id: note.commit_id,
project_id: note.project,
- host: Gitlab.config.gitlab['url'],
anchor: "note_#{note.id}")
elsif note.for_issue?
issue = Issue.find(note.noteable_id)
issue_url(issue,
- host: Gitlab.config.gitlab['url'],
anchor: "note_#{note.id}")
elsif note.for_merge_request?
merge_request = MergeRequest.find(note.noteable_id)
merge_request_url(merge_request,
- host: Gitlab.config.gitlab['url'],
anchor: "note_#{note.id}")
elsif note.for_project_snippet?
snippet = Snippet.find(note.noteable_id)
project_snippet_url(snippet,
- host: Gitlab.config.gitlab['url'],
anchor: "note_#{note.id}")
end
end
diff --git a/lib/redcarpet/render/gitlab_html.rb b/lib/redcarpet/render/gitlab_html.rb
deleted file mode 100644
index f57b56cbdf0..00000000000
--- a/lib/redcarpet/render/gitlab_html.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-require 'active_support/core_ext/string/output_safety'
-
-class Redcarpet::Render::GitlabHTML < Redcarpet::Render::HTML
- attr_reader :template
- alias_method :h, :template
-
- def initialize(template, color_scheme, options = {})
- @template = template
- @color_scheme = color_scheme
- @options = options.dup
-
- @options.reverse_merge!(
- # Handled further down the line by Gitlab::Markdown::SanitizationFilter
- escape_html: false,
- project: @template.instance_variable_get("@project")
- )
-
- super(options)
- end
-
- def normal_text(text)
- ERB::Util.html_escape_once(text)
- end
-
- # Stolen from Rouge::Plugins::Redcarpet as this module is not required
- # from Rouge's gem root.
- def block_code(code, language)
- lexer = Rouge::Lexer.find_fancy(language, code) || Rouge::Lexers::PlainText
-
- # XXX HACK: Redcarpet strips hard tabs out of code blocks,
- # so we assume you're not using leading spaces that aren't tabs,
- # and just replace them here.
- if lexer.tag == 'make'
- code.gsub!(/^ /, "\t")
- end
-
- formatter = Rouge::Formatters::HTMLGitlab.new(
- cssclass: "code highlight #{@color_scheme} #{lexer.tag}"
- )
- formatter.format(lexer.lex(code))
- end
-
- def postprocess(full_document)
- h.gfm(full_document, @options)
- end
-end
diff --git a/lib/support/init.d/gitlab b/lib/support/init.d/gitlab
index 41a2f254db6..a80e7e77430 100755
--- a/lib/support/init.d/gitlab
+++ b/lib/support/init.d/gitlab
@@ -37,6 +37,10 @@ web_server_pid_path="$pid_path/unicorn.pid"
sidekiq_pid_path="$pid_path/sidekiq.pid"
mail_room_enabled=false
mail_room_pid_path="$pid_path/mail_room.pid"
+gitlab_git_http_server_pid_path="$pid_path/gitlab-git-http-server.pid"
+gitlab_git_http_server_options="-listenUmask 0 -listenNetwork unix -listenAddr $socket_path/gitlab-git-http-server.socket -authBackend http://127.0.0.1:8080"
+gitlab_git_http_server_repo_root='/home/git/repositories'
+gitlab_git_http_server_log="$app_root/log/gitlab-git-http-server.log"
shell_path="/bin/bash"
# Read configuration variable file if it is present
@@ -72,6 +76,11 @@ check_pids(){
else
spid=0
fi
+ if [ -f "$gitlab_git_http_server_pid_path" ]; then
+ hpid=$(cat "$gitlab_git_http_server_pid_path")
+ else
+ hpid=0
+ fi
if [ "$mail_room_enabled" = true ]; then
if [ -f "$mail_room_pid_path" ]; then
mpid=$(cat "$mail_room_pid_path")
@@ -85,7 +94,7 @@ check_pids(){
wait_for_pids(){
# We are sleeping a bit here mostly because sidekiq is slow at writing it's pid
i=0;
- while [ ! -f $web_server_pid_path ] || [ ! -f $sidekiq_pid_path ] || { [ "$mail_room_enabled" = true ] && [ ! -f $mail_room_pid_path ]; }; do
+ while [ ! -f $web_server_pid_path ] || [ ! -f $sidekiq_pid_path ] || [ ! -f $gitlab_git_http_server_pid_path ] || { [ "$mail_room_enabled" = true ] && [ ! -f $mail_room_pid_path ]; }; do
sleep 0.1;
i=$((i+1))
if [ $((i%10)) = 0 ]; then
@@ -120,6 +129,12 @@ check_status(){
else
sidekiq_status="-1"
fi
+ if [ $hpid -ne 0 ]; then
+ kill -0 "$hpid" 2>/dev/null
+ gitlab_git_http_server_status="$?"
+ else
+ gitlab_git_http_server_status="-1"
+ fi
if [ "$mail_room_enabled" = true ]; then
if [ $mpid -ne 0 ]; then
kill -0 "$mpid" 2>/dev/null
@@ -128,7 +143,7 @@ check_status(){
mail_room_status="-1"
fi
fi
- if [ $web_status = 0 ] && [ $sidekiq_status = 0 ] && { [ "$mail_room_enabled" != true ] || [ $mail_room_status = 0 ]; }; then
+ if [ $web_status = 0 ] && [ $sidekiq_status = 0 ] && [ $gitlab_git_http_server_status = 0 ] && { [ "$mail_room_enabled" != true ] || [ $mail_room_status = 0 ]; }; then
gitlab_status=0
else
# http://refspecs.linuxbase.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/iniscrptact.html
@@ -156,6 +171,13 @@ check_stale_pids(){
exit 1
fi
fi
+ if [ "$hpid" != "0" ] && [ "$gitlab_git_http_server_status" != "0" ]; then
+ echo "Removing stale gitlab-git-http-server pid. This is most likely caused by gitlab-git-http-server crashing the last time it ran."
+ if ! rm "$gitlab_git_http_server_pid_path"; then
+ echo "Unable to remove stale pid, exiting"
+ exit 1
+ fi
+ fi
if [ "$mail_room_enabled" = true ] && [ "$mpid" != "0" ] && [ "$mail_room_status" != "0" ]; then
echo "Removing stale MailRoom job dispatcher pid. This is most likely caused by MailRoom crashing the last time it ran."
if ! rm "$mail_room_pid_path"; then
@@ -168,7 +190,7 @@ check_stale_pids(){
## If no parts of the service is running, bail out.
exit_if_not_running(){
check_stale_pids
- if [ "$web_status" != "0" ] && [ "$sidekiq_status" != "0" ] && { [ "$mail_room_enabled" != true ] || [ "$mail_room_status" != "0" ]; }; then
+ if [ "$web_status" != "0" ] && [ "$sidekiq_status" != "0" ] && [ "$gitlab_git_http_server_status" != "0" ] && { [ "$mail_room_enabled" != true ] || [ "$mail_room_status" != "0" ]; }; then
echo "GitLab is not running."
exit
fi
@@ -184,6 +206,9 @@ start_gitlab() {
if [ "$sidekiq_status" != "0" ]; then
echo "Starting GitLab Sidekiq"
fi
+ if [ "$gitlab_git_http_server_status" != "0" ]; then
+ echo "Starting gitlab-git-http-server"
+ fi
if [ "$mail_room_enabled" = true ] && [ "$mail_room_status" != "0" ]; then
echo "Starting GitLab MailRoom"
fi
@@ -205,6 +230,17 @@ start_gitlab() {
RAILS_ENV=$RAILS_ENV bin/background_jobs start &
fi
+ if [ "$gitlab_git_http_server_status" = "0" ]; then
+ echo "The gitlab-git-http-server is already running with pid $spid, not restarting"
+ else
+ # No need to remove a socket, gitlab-git-http-server does this itself
+ $app_root/bin/daemon_with_pidfile $gitlab_git_http_server_pid_path \
+ $app_root/../gitlab-git-http-server/gitlab-git-http-server \
+ $gitlab_git_http_server_options \
+ $gitlab_git_http_server_repo_root \
+ >> $gitlab_git_http_server_log 2>&1 &
+ fi
+
if [ "$mail_room_enabled" = true ]; then
# If MailRoom is already running, don't start it again.
if [ "$mail_room_status" = "0" ]; then
@@ -226,33 +262,27 @@ stop_gitlab() {
if [ "$web_status" = "0" ]; then
echo "Shutting down GitLab Unicorn"
+ RAILS_ENV=$RAILS_ENV bin/web stop
fi
if [ "$sidekiq_status" = "0" ]; then
echo "Shutting down GitLab Sidekiq"
- fi
- if [ "$mail_room_enabled" = true ] && [ "$mail_room_status" = "0" ]; then
- echo "Shutting down GitLab MailRoom"
- fi
-
- # If the Unicorn web server is running, tell it to stop;
- if [ "$web_status" = "0" ]; then
- RAILS_ENV=$RAILS_ENV bin/web stop
- fi
- # And do the same thing for the Sidekiq.
- if [ "$sidekiq_status" = "0" ]; then
RAILS_ENV=$RAILS_ENV bin/background_jobs stop
fi
- # And do the same thing for the MailRoom.
+ if [ "$gitlab_git_http_server_status" = "0" ]; then
+ echo "Shutting down gitlab-git-http-server"
+ kill -- $(cat $gitlab_git_http_server_pid_path)
+ fi
if [ "$mail_room_enabled" = true ] && [ "$mail_room_status" = "0" ]; then
+ echo "Shutting down GitLab MailRoom"
RAILS_ENV=$RAILS_ENV bin/mail_room stop
fi
# If something needs to be stopped, lets wait for it to stop. Never use SIGKILL in a script.
- while [ "$web_status" = "0" ] || [ "$sidekiq_status" = "0" ] || { [ "$mail_room_enabled" = true ] && [ "$mail_room_status" = "0" ]; }; do
+ while [ "$web_status" = "0" ] || [ "$sidekiq_status" = "0" ] || [ "$gitlab_git_http_server_status" = "0" ] || { [ "$mail_room_enabled" = true ] && [ "$mail_room_status" = "0" ]; }; do
sleep 1
check_status
printf "."
- if [ "$web_status" != "0" ] && [ "$sidekiq_status" != "0" ] && { [ "$mail_room_enabled" != true ] || [ "$mail_room_status" != "0" ]; }; then
+ if [ "$web_status" != "0" ] && [ "$sidekiq_status" != "0" ] && [ "$gitlab_git_http_server_status" != "0" ] && { [ "$mail_room_enabled" != true ] || [ "$mail_room_status" != "0" ]; }; then
printf "\n"
break
fi
@@ -262,6 +292,7 @@ stop_gitlab() {
# Cleaning up unused pids
rm "$web_server_pid_path" 2>/dev/null
# rm "$sidekiq_pid_path" 2>/dev/null # Sidekiq seems to be cleaning up it's own pid.
+ rm -f "$gitlab_git_http_server_pid_path"
if [ "$mail_room_enabled" = true ]; then
rm "$mail_room_pid_path" 2>/dev/null
fi
@@ -272,7 +303,7 @@ stop_gitlab() {
## Prints the status of GitLab and it's components.
print_status() {
check_status
- if [ "$web_status" != "0" ] && [ "$sidekiq_status" != "0" ] && { [ "$mail_room_enabled" != true ] || [ "$mail_room_status" != "0" ]; }; then
+ if [ "$web_status" != "0" ] && [ "$sidekiq_status" != "0" ] && [ "$gitlab_git_http_server_status" != "0" ] && { [ "$mail_room_enabled" != true ] || [ "$mail_room_status" != "0" ]; }; then
echo "GitLab is not running."
return
fi
@@ -286,9 +317,14 @@ print_status() {
else
printf "The GitLab Sidekiq job dispatcher is \033[31mnot running\033[0m.\n"
fi
+ if [ "$gitlab_git_http_server_status" = "0" ]; then
+ echo "The gitlab-git-http-server with pid $hpid is running."
+ else
+ printf "The gitlab-git-http-server is \033[31mnot running\033[0m.\n"
+ fi
if [ "$mail_room_enabled" = true ]; then
if [ "$mail_room_status" = "0" ]; then
- echo "The GitLab MailRoom email processor with pid $spid is running."
+ echo "The GitLab MailRoom email processor with pid $mpid is running."
else
printf "The GitLab MailRoom email processor is \033[31mnot running\033[0m.\n"
fi
@@ -324,7 +360,7 @@ reload_gitlab(){
## Restarts Sidekiq and Unicorn.
restart_gitlab(){
check_status
- if [ "$web_status" = "0" ] || [ "$sidekiq_status" = "0" ] || { [ "$mail_room_enabled" = true ] && [ "$mail_room_status" = "0" ]; }; then
+ if [ "$web_status" = "0" ] || [ "$sidekiq_status" = "0" ] || [ "$gitlab_git_http_server" = "0" ] || { [ "$mail_room_enabled" = true ] && [ "$mail_room_status" = "0" ]; }; then
stop_gitlab
fi
start_gitlab
diff --git a/lib/support/init.d/gitlab.default.example b/lib/support/init.d/gitlab.default.example
index fd70cb7cc74..aab5acaa72c 100755
--- a/lib/support/init.d/gitlab.default.example
+++ b/lib/support/init.d/gitlab.default.example
@@ -30,6 +30,16 @@ web_server_pid_path="$pid_path/unicorn.pid"
# The default is "$pid_path/sidekiq.pid"
sidekiq_pid_path="$pid_path/sidekiq.pid"
+gitlab_git_http_server_pid_path="$pid_path/gitlab-git-http-server.pid"
+# The -listenXxx settings determine where gitlab-git-http-server
+# listens for connections from NGINX. To listen on localhost:8181, write
+# '-listenNetwork tcp -listenAddr localhost:8181'.
+# The -authBackend setting tells gitlab-git-http-server where it can reach
+# Unicorn.
+gitlab_git_http_server_options="-listenUmask 0 -listenNetwork unix -listenAddr $socket_path/gitlab-git-http-server.socket -authBackend http://127.0.0.1:8080"
+gitlab_git_http_server_repo_root="/home/git/repositories"
+gitlab_git_http_server_log="$app_root/log/gitlab-git-http-server.log"
+
# mail_room_enabled specifies whether mail_room, which is used to process incoming email, is enabled.
# This is required for the Reply by email feature.
# The default is "false"
diff --git a/lib/support/nginx/gitlab b/lib/support/nginx/gitlab
index efa0898900f..17f89c8beb6 100644
--- a/lib/support/nginx/gitlab
+++ b/lib/support/nginx/gitlab
@@ -38,10 +38,9 @@ upstream gitlab {
server unix:/home/git/gitlab/tmp/sockets/gitlab.socket fail_timeout=0;
}
-## Experimental: gitlab-git-http-server
-# upstream gitlab-git-http-server {
-# server localhost:8181;
-# }
+upstream gitlab-git-http-server {
+ server unix:/home/git/gitlab/tmp/sockets/gitlab-git-http-server.socket fail_timeout=0;
+}
## Normal HTTP host
server {
@@ -114,25 +113,24 @@ server {
proxy_pass http://gitlab;
}
- ## Experimental: send Git HTTP traffic to gitlab-git-http-server instead of Unicorn
- # location ~ [-\/\w\.]+\.git\/ {
- # ## If you use HTTPS make sure you disable gzip compression
- # ## to be safe against BREACH attack.
- # # gzip off;
-
- # ## https://github.com/gitlabhq/gitlabhq/issues/694
- # ## Some requests take more than 30 seconds.
- # proxy_read_timeout 300;
- # proxy_connect_timeout 300;
- # proxy_redirect off;
-
- # proxy_set_header Host $http_host;
- # proxy_set_header X-Real-IP $remote_addr;
- # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- # proxy_set_header X-Forwarded-Proto $scheme;
-
- # proxy_pass http://gitlab-git-http-server;
- # }
+ location ~ [-\/\w\.]+\.git\/ {
+ ## If you use HTTPS make sure you disable gzip compression
+ ## to be safe against BREACH attack.
+ # gzip off;
+
+ ## https://github.com/gitlabhq/gitlabhq/issues/694
+ ## Some requests take more than 30 seconds.
+ proxy_read_timeout 300;
+ proxy_connect_timeout 300;
+ proxy_redirect off;
+
+ proxy_set_header Host $http_host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+
+ proxy_pass http://gitlab-git-http-server;
+ }
## Enable gzip compression as per rails guide:
## http://guides.rubyonrails.org/asset_pipeline.html#gzip-compression
diff --git a/lib/support/nginx/gitlab-ssl b/lib/support/nginx/gitlab-ssl
index 314525518f1..5ba39fc41a4 100644
--- a/lib/support/nginx/gitlab-ssl
+++ b/lib/support/nginx/gitlab-ssl
@@ -42,10 +42,9 @@ upstream gitlab {
server unix:/home/git/gitlab/tmp/sockets/gitlab.socket fail_timeout=0;
}
-## Experimental: gitlab-git-http-server
-# upstream gitlab-git-http-server {
-# server localhost:8181;
-# }
+upstream gitlab-git-http-server {
+ server unix:/home/git/gitlab/tmp/sockets/gitlab-git-http-server.socket fail_timeout=0;
+}
## Redirects all HTTP traffic to the HTTPS host
server {
@@ -161,25 +160,24 @@ server {
proxy_pass http://gitlab;
}
- ## Experimental: send Git HTTP traffic to gitlab-git-http-server instead of Unicorn
- # location ~ [-\/\w\.]+\.git\/ {
- # ## If you use HTTPS make sure you disable gzip compression
- # ## to be safe against BREACH attack.
- # gzip off;
-
- # ## https://github.com/gitlabhq/gitlabhq/issues/694
- # ## Some requests take more than 30 seconds.
- # proxy_read_timeout 300;
- # proxy_connect_timeout 300;
- # proxy_redirect off;
-
- # proxy_set_header Host $http_host;
- # proxy_set_header X-Real-IP $remote_addr;
- # proxy_set_header X-Forwarded-Ssl on;
- # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- # proxy_set_header X-Forwarded-Proto $scheme;
- # proxy_pass http://gitlab-git-http-server;
- # }
+ location ~ [-\/\w\.]+\.git\/ {
+ ## If you use HTTPS make sure you disable gzip compression
+ ## to be safe against BREACH attack.
+ gzip off;
+
+ ## https://github.com/gitlabhq/gitlabhq/issues/694
+ ## Some requests take more than 30 seconds.
+ proxy_read_timeout 300;
+ proxy_connect_timeout 300;
+ proxy_redirect off;
+
+ proxy_set_header Host $http_host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-Ssl on;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ proxy_pass http://gitlab-git-http-server;
+ }
## Enable gzip compression as per rails guide:
## http://guides.rubyonrails.org/asset_pipeline.html#gzip-compression
diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake
index 9815582d02d..bcd25ccbaf3 100644
--- a/lib/tasks/gitlab/check.rake
+++ b/lib/tasks/gitlab/check.rake
@@ -278,7 +278,7 @@ namespace :gitlab do
fix_and_rerun
end
end
-
+
def check_uploads
print "Uploads directory setup correctly? ... "
@@ -331,15 +331,18 @@ namespace :gitlab do
end
def check_redis_version
- print "Redis version >= 2.0.0? ... "
+ min_redis_version = "2.4.0"
+ print "Redis version >= #{min_redis_version}? ... "
redis_version = run(%W(redis-cli --version))
- if redis_version.try(:match, /redis-cli 2.\d.\d/) || redis_version.try(:match, /redis-cli 3.\d.\d/)
+ redis_version = redis_version.try(:match, /redis-cli (.*)/)
+ if redis_version &&
+ (Gem::Version.new(redis_version[1]) > Gem::Version.new(min_redis_version))
puts "yes".green
else
puts "no".red
try_fixing_it(
- "Update your redis server to a version >= 2.0.0"
+ "Update your redis server to a version >= #{min_redis_version}"
)
for_more_information(
"gitlab-public-wiki/wiki/Trouble-Shooting-Guide in section sidekiq"
@@ -488,7 +491,7 @@ namespace :gitlab do
else
puts "wrong or missing hooks".red
try_fixing_it(
- sudo_gitlab("#{gitlab_shell_path}/bin/create-hooks"),
+ sudo_gitlab("#{File.join(gitlab_shell_path, 'bin/create-hooks')}"),
'Check the hooks_path in config/gitlab.yml',
'Check your gitlab-shell installation'
)
diff --git a/lib/tasks/services.rake b/lib/tasks/services.rake
new file mode 100644
index 00000000000..3f276a5e12e
--- /dev/null
+++ b/lib/tasks/services.rake
@@ -0,0 +1,89 @@
+services_template = <<-ERB
+# Services
+
+<% services.each do |service| %>
+## <%= service[:title] %>
+
+
+<% unless service[:description].blank? %>
+<%= service[:description] %>
+<% end %>
+
+
+### Create/Edit <%= service[:title] %> service
+
+Set <%= service[:title] %> service for a project.
+<% unless service[:help].blank? %>
+
+> <%= service[:help].gsub("\n", ' ') %>
+
+<% end %>
+
+```
+PUT /projects/:id/services/<%= service[:dashed_name] %>
+
+```
+
+Parameters:
+
+<% service[:params].each do |param| %>
+- `<%= param[:name] %>` <%= param[:required] ? "(**required**)" : "(optional)" %><%= [" -", param[:description]].join(" ").gsub("\n", '') unless param[:description].blank? %>
+
+<% end %>
+
+### Delete <%= service[:title] %> service
+
+Delete <%= service[:title] %> service for a project.
+
+```
+DELETE /projects/:id/services/<%= service[:dashed_name] %>
+
+```
+
+<% end %>
+ERB
+
+namespace :services do
+ task doc: :environment do
+ services = Service.available_services_names.map do |s|
+ service_start = Time.now
+ klass = "#{s}_service".classify.constantize
+
+ service = klass.new
+
+ service_hash = {}
+
+ service_hash[:title] = service.title
+ service_hash[:dashed_name] = s.dasherize
+ service_hash[:description] = service.description
+ service_hash[:help] = service.help
+ service_hash[:params] = service.fields.map do |p|
+ param_hash = {}
+
+ param_hash[:name] = p[:name]
+ param_hash[:description] = p[:placeholder] || p[:title]
+ param_hash[:required] = klass.validators_on(p[:name].to_sym).any? do |v|
+ v.class == ActiveRecord::Validations::PresenceValidator
+ end
+
+ param_hash
+ end.sort_by { |p| p[:required] ? 0 : 1 }
+
+ puts "Collected data for: #{service.title}, #{Time.now-service_start}"
+ service_hash
+ end
+
+ doc_start = Time.now
+ doc_path = File.join(Rails.root, 'doc', 'api', 'services.md')
+
+ result = ERB.new(services_template, 0 , '>')
+ .result(OpenStruct.new(services: services).instance_eval { binding })
+
+ File.open(doc_path, 'w') do |f|
+ f.write result
+ end
+
+ puts "write a new service.md to: #{doc_path.to_s}, #{Time.now-doc_start}"
+
+ end
+end