summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/api/api.rb1
-rw-r--r--lib/api/branches.rb16
-rw-r--r--lib/api/entities.rb21
-rw-r--r--lib/api/helpers.rb31
-rw-r--r--lib/api/internal.rb9
-rw-r--r--lib/api/issues.rb78
-rw-r--r--lib/api/labels.rb103
-rw-r--r--lib/api/merge_requests.rb25
-rw-r--r--lib/api/projects.rb30
-rw-r--r--lib/api/repositories.rb41
-rw-r--r--lib/api/users.rb4
-rw-r--r--lib/backup/repository.rb2
-rw-r--r--lib/gitlab/backend/shell.rb11
-rw-r--r--lib/gitlab/blacklist.rb26
-rw-r--r--lib/gitlab/compare_result.rb9
-rw-r--r--lib/gitlab/config_helper.rb9
-rw-r--r--lib/gitlab/contributors.rb9
-rw-r--r--lib/gitlab/diff_parser.rb2
-rw-r--r--lib/gitlab/git_access.rb39
-rw-r--r--lib/gitlab/git_ref_validator.rb11
-rw-r--r--lib/gitlab/issues_labels.rb38
-rw-r--r--lib/gitlab/ldap/access.rb15
-rw-r--r--lib/gitlab/ldap/adapter.rb13
-rw-r--r--lib/gitlab/ldap/person.rb2
-rw-r--r--lib/gitlab/ldap/user.rb21
-rw-r--r--lib/gitlab/markdown.rb7
-rw-r--r--lib/gitlab/markdown_helper.rb25
-rw-r--r--lib/gitlab/oauth/user.rb14
-rw-r--r--lib/gitlab/project_search_results.rb52
-rw-r--r--lib/gitlab/regex.rb25
-rw-r--r--lib/gitlab/satellite/action.rb2
-rw-r--r--lib/gitlab/satellite/compare_action.rb37
-rw-r--r--lib/gitlab/satellite/merge_action.rb18
-rw-r--r--lib/gitlab/satellite/satellite.rb3
-rw-r--r--lib/gitlab/search_results.rb69
-rw-r--r--lib/gitlab/sidekiq_middleware/arguments_logger.rb10
-rw-r--r--lib/gitlab/theme.rb10
-rw-r--r--lib/gitlab/upgrader.rb2
-rw-r--r--lib/gitlab/url_builder.rb25
-rw-r--r--lib/gitlab/user_access.rb9
-rw-r--r--lib/gitlab/visibility_level.rb24
-rw-r--r--lib/gt_one_coercion.rb5
-rw-r--r--lib/support/nginx/gitlab100
-rw-r--r--lib/support/nginx/gitlab-ssl104
-rw-r--r--lib/tasks/gitlab/check.rake54
-rw-r--r--lib/tasks/gitlab/cleanup.rake24
-rw-r--r--lib/tasks/gitlab/shell.rake5
-rw-r--r--lib/tasks/gitlab/sidekiq.rake47
-rw-r--r--lib/tasks/gitlab/test.rake2
-rw-r--r--lib/unfold_form.rb11
50 files changed, 963 insertions, 287 deletions
diff --git a/lib/api/api.rb b/lib/api/api.rb
index ce4cc8b34f7..2c7cd9038c3 100644
--- a/lib/api/api.rb
+++ b/lib/api/api.rb
@@ -46,5 +46,6 @@ module API
mount Commits
mount Namespaces
mount Branches
+ mount Labels
end
end
diff --git a/lib/api/branches.rb b/lib/api/branches.rb
index b32a4aa7bc2..4db5f61dd28 100644
--- a/lib/api/branches.rb
+++ b/lib/api/branches.rb
@@ -80,9 +80,17 @@ module API
# POST /projects/:id/repository/branches
post ":id/repository/branches" do
authorize_push_project
- @branch = CreateBranchService.new.execute(user_project, params[:branch_name], params[:ref], current_user)
-
- present @branch, with: Entities::RepoObject, project: user_project
+ result = CreateBranchService.new.execute(user_project,
+ params[:branch_name],
+ params[:ref],
+ current_user)
+ if result[:status] == :success
+ present result[:branch],
+ with: Entities::RepoObject,
+ project: user_project
+ else
+ render_api_error!(result[:message], 400)
+ end
end
# Delete branch
@@ -99,7 +107,7 @@ module API
if result[:state] == :success
true
else
- render_api_error!(result[:message], 405)
+ render_api_error!(result[:message], result[:return_code])
end
end
end
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index b190646a1e3..74fdef93543 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -102,6 +102,7 @@ module API
class RepoCommit < Grape::Entity
expose :id, :short_id, :title, :author_name, :author_email, :created_at
+ expose :safe_message, as: :message
end
class RepoCommitDetail < RepoCommit
@@ -126,7 +127,7 @@ module API
end
class Issue < ProjectEntity
- expose :label_list, as: :labels
+ expose :label_names, as: :labels
expose :milestone, using: Entities::Milestone
expose :assignee, :author, using: Entities::UserBasic
end
@@ -135,7 +136,9 @@ module API
expose :target_branch, :source_branch, :upvotes, :downvotes
expose :author, :assignee, using: Entities::UserBasic
expose :source_project_id, :target_project_id
- expose :label_list, as: :labels
+ expose :label_names, as: :labels
+ expose :description
+ expose :milestone, using: Entities::Milestone
end
class SSHKey < Grape::Entity
@@ -191,7 +194,7 @@ module API
end
class Label < Grape::Entity
- expose :name
+ expose :name, :color
end
class RepoDiff < Grape::Entity
@@ -201,13 +204,13 @@ module API
class Compare < Grape::Entity
expose :commit, using: Entities::RepoCommit do |compare, options|
- if compare.commit
- Commit.new compare.commit
- end
+ Commit.decorate(compare.commits).last
end
+
expose :commits, using: Entities::RepoCommit do |compare, options|
- Commit.decorate compare.commits
+ Commit.decorate(compare.commits)
end
+
expose :diffs, using: Entities::RepoDiff do |compare, options|
compare.diffs
end
@@ -218,5 +221,9 @@ module API
expose :same, as: :compare_same_ref
end
+
+ class Contributor < Grape::Entity
+ expose :name, :email, :commits, :additions, :deletions
+ end
end
end
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index b6a5806d646..6af0f6d1b25 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -5,6 +5,10 @@ module API
SUDO_HEADER ="HTTP_SUDO"
SUDO_PARAM = :sudo
+ def parse_boolean(value)
+ [ true, 1, '1', 't', 'T', 'true', 'TRUE', 'on', 'ON' ].include?(value)
+ end
+
def current_user
private_token = (params[PRIVATE_TOKEN_PARAM] || env[PRIVATE_TOKEN_HEADER]).to_s
@current_user ||= User.find_by(authentication_token: private_token)
@@ -98,10 +102,33 @@ module API
def attributes_for_keys(keys)
attrs = {}
+
keys.each do |key|
- attrs[key] = params[key] if params[key].present? or (params.has_key?(key) and params[key] == false)
+ if params[key].present? or (params.has_key?(key) and params[key] == false)
+ attrs[key] = params[key]
+ end
+ end
+
+ ActionController::Parameters.new(attrs).permit!
+ end
+
+ # Helper method for validating all labels against its names
+ def validate_label_params(params)
+ errors = {}
+
+ if params[:labels].present?
+ params[:labels].split(',').each do |label_name|
+ label = user_project.labels.create_with(
+ color: Label::DEFAULT_COLOR).find_or_initialize_by(
+ title: label_name.strip)
+
+ if label.invalid?
+ errors[label.title] = label.errors
+ end
+ end
end
- attrs
+
+ errors
end
# error helpers
diff --git a/lib/api/internal.rb b/lib/api/internal.rb
index 5850892df07..5f484f63418 100644
--- a/lib/api/internal.rb
+++ b/lib/api/internal.rb
@@ -12,7 +12,9 @@ module API
# ref - branch name
# forced_push - forced_push
#
- get "/allowed" do
+ post "/allowed" do
+ status 200
+
# Check for *.wiki repositories.
# Strip out the .wiki from the pathname before finding the
# project. This applies the correct project permissions to
@@ -34,10 +36,7 @@ module API
actor,
params[:action],
project,
- params[:ref],
- params[:oldrev],
- params[:newrev],
- params[:forced_push]
+ params[:changes]
)
end
diff --git a/lib/api/issues.rb b/lib/api/issues.rb
index f50be3a815d..5369149cdfc 100644
--- a/lib/api/issues.rb
+++ b/lib/api/issues.rb
@@ -3,13 +3,41 @@ module API
class Issues < Grape::API
before { authenticate! }
+ helpers do
+ def filter_issues_state(issues, state = nil)
+ case state
+ when 'opened' then issues.opened
+ when 'closed' then issues.closed
+ else issues
+ end
+ end
+
+ def filter_issues_labels(issues, labels)
+ issues.includes(:labels).where("labels.title" => labels.split(','))
+ end
+ end
+
resource :issues do
# Get currently authenticated user's issues
#
- # Example Request:
+ # Parameters:
+ # state (optional) - Return "opened" or "closed" issues
+ # labels (optional) - Comma-separated list of label names
+
+ # Example Requests:
# GET /issues
+ # GET /issues?state=opened
+ # GET /issues?state=closed
+ # GET /issues?labels=foo
+ # GET /issues?labels=foo,bar
+ # GET /issues?labels=foo,bar&state=opened
get do
- present paginate(current_user.issues), with: Entities::Issue
+ issues = current_user.issues
+ issues = filter_issues_state(issues, params[:state]) unless params[:state].nil?
+ issues = filter_issues_labels(issues, params[:labels]) unless params[:labels].nil?
+ issues = issues.order('issues.id DESC')
+
+ present paginate(issues), with: Entities::Issue
end
end
@@ -18,10 +46,24 @@ module API
#
# Parameters:
# id (required) - The ID of a project
- # Example Request:
+ # state (optional) - Return "opened" or "closed" issues
+ # labels (optional) - Comma-separated list of label names
+ #
+ # Example Requests:
+ # GET /projects/:id/issues
+ # GET /projects/:id/issues?state=opened
+ # GET /projects/:id/issues?state=closed
# GET /projects/:id/issues
+ # GET /projects/:id/issues?labels=foo
+ # GET /projects/:id/issues?labels=foo,bar
+ # GET /projects/:id/issues?labels=foo,bar&state=opened
get ":id/issues" do
- present paginate(user_project.issues), with: Entities::Issue
+ issues = user_project.issues
+ issues = filter_issues_state(issues, params[:state]) unless params[:state].nil?
+ issues = filter_issues_labels(issues, params[:labels]) unless params[:labels].nil?
+ issues = issues.order('issues.id DESC')
+
+ present paginate(issues), with: Entities::Issue
end
# Get a single project issue
@@ -50,10 +92,21 @@ module API
post ":id/issues" do
required_attributes! [:title]
attrs = attributes_for_keys [:title, :description, :assignee_id, :milestone_id]
- attrs[:label_list] = params[:labels] if params[:labels].present?
+
+ # Validate label names in advance
+ if (errors = validate_label_params(params)).any?
+ render_api_error!({ labels: errors }, 400)
+ end
+
issue = ::Issues::CreateService.new(user_project, current_user, attrs).execute
if issue.valid?
+ # Find or create labels and attach to issue. Labels are valid because
+ # we already checked its name, so there can't be an error here
+ if params[:labels].present?
+ issue.add_labels_by_names(params[:labels].split(','))
+ end
+
present issue, with: Entities::Issue
else
not_found!
@@ -76,13 +129,24 @@ module API
put ":id/issues/:issue_id" do
issue = user_project.issues.find(params[:issue_id])
authorize! :modify_issue, issue
-
attrs = attributes_for_keys [:title, :description, :assignee_id, :milestone_id, :state_event]
- attrs[:label_list] = params[:labels] if params[:labels].present?
+
+ # Validate label names in advance
+ if (errors = validate_label_params(params)).any?
+ render_api_error!({ labels: errors }, 400)
+ end
issue = ::Issues::UpdateService.new(user_project, current_user, attrs).execute(issue)
if issue.valid?
+ # Find or create labels and attach to issue. Labels are valid because
+ # we already checked its name, so there can't be an error here
+ unless params[:labels].nil?
+ issue.remove_labels
+ # Create and add labels to the new created issue
+ issue.add_labels_by_names(params[:labels].split(','))
+ end
+
present issue, with: Entities::Issue
else
not_found!
diff --git a/lib/api/labels.rb b/lib/api/labels.rb
new file mode 100644
index 00000000000..2fdf53ffec2
--- /dev/null
+++ b/lib/api/labels.rb
@@ -0,0 +1,103 @@
+module API
+ # Labels API
+ class Labels < Grape::API
+ before { authenticate! }
+
+ resource :projects do
+ # Get all labels of the project
+ #
+ # Parameters:
+ # id (required) - The ID of a project
+ # Example Request:
+ # GET /projects/:id/labels
+ get ':id/labels' do
+ present user_project.labels, with: Entities::Label
+ end
+
+ # Creates a new label
+ #
+ # Parameters:
+ # id (required) - The ID of a project
+ # name (required) - The name of the label to be deleted
+ # color (required) - Color of the label given in 6-digit hex
+ # notation with leading '#' sign (e.g. #FFAABB)
+ # Example Request:
+ # POST /projects/:id/labels
+ post ':id/labels' do
+ authorize! :admin_label, user_project
+ required_attributes! [:name, :color]
+
+ attrs = attributes_for_keys [:name, :color]
+ label = user_project.find_label(attrs[:name])
+
+ if label
+ return render_api_error!('Label already exists', 409)
+ end
+
+ label = user_project.labels.create(attrs)
+
+ if label.valid?
+ present label, with: Entities::Label
+ else
+ render_api_error!(label.errors.full_messages.join(', '), 400)
+ end
+ end
+
+ # Deletes an existing label
+ #
+ # Parameters:
+ # id (required) - The ID of a project
+ # name (required) - The name of the label to be deleted
+ #
+ # Example Request:
+ # DELETE /projects/:id/labels
+ delete ':id/labels' do
+ authorize! :admin_label, user_project
+ required_attributes! [:name]
+
+ label = user_project.find_label(params[:name])
+ if !label
+ return render_api_error!('Label not found', 404)
+ end
+
+ label.destroy
+ end
+
+ # Updates an existing label. At least one optional parameter is required.
+ #
+ # Parameters:
+ # id (required) - The ID of a project
+ # name (optional) - The name of the label to be deleted
+ # color (optional) - Color of the label given in 6-digit hex
+ # notation with leading '#' sign (e.g. #FFAABB)
+ # Example Request:
+ # PUT /projects/:id/labels
+ put ':id/labels' do
+ authorize! :admin_label, user_project
+ required_attributes! [:name]
+
+ label = user_project.find_label(params[:name])
+ if !label
+ return render_api_error!('Label not found', 404)
+ end
+
+ attrs = attributes_for_keys [:new_name, :color]
+
+ if attrs.empty?
+ return render_api_error!('Required parameters "name" or "color" ' \
+ 'missing',
+ 400)
+ end
+
+ # Rename new name to the actual label attribute name
+ attrs[:name] = attrs.delete(:new_name) if attrs.key?(:new_name)
+
+ if label.update(attrs)
+ present label, with: Entities::Label
+ else
+ render_api_error!(label.errors.full_messages.join(', '), 400)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb
index fc1f1254a9e..8726379bf3c 100644
--- a/lib/api/merge_requests.rb
+++ b/lib/api/merge_requests.rb
@@ -76,10 +76,20 @@ module API
authorize! :write_merge_request, user_project
required_attributes! [:source_branch, :target_branch, :title]
attrs = attributes_for_keys [:source_branch, :target_branch, :assignee_id, :title, :target_project_id, :description]
- attrs[:label_list] = params[:labels] if params[:labels].present?
+
+ # Validate label names in advance
+ if (errors = validate_label_params(params)).any?
+ render_api_error!({ labels: errors }, 400)
+ end
+
merge_request = ::MergeRequests::CreateService.new(user_project, current_user, attrs).execute
if merge_request.valid?
+ # Find or create labels and attach to issue
+ if params[:labels].present?
+ merge_request.add_labels_by_names(params[:labels].split(","))
+ end
+
present merge_request, with: Entities::MergeRequest
else
handle_merge_request_errors! merge_request.errors
@@ -103,12 +113,23 @@ module API
#
put ":id/merge_request/:merge_request_id" do
attrs = attributes_for_keys [:source_branch, :target_branch, :assignee_id, :title, :state_event, :description]
- attrs[:label_list] = params[:labels] if params[:labels].present?
merge_request = user_project.merge_requests.find(params[:merge_request_id])
authorize! :modify_merge_request, merge_request
+
+ # Validate label names in advance
+ if (errors = validate_label_params(params)).any?
+ render_api_error!({ labels: errors }, 400)
+ end
+
merge_request = ::MergeRequests::UpdateService.new(user_project, current_user, attrs).execute(merge_request)
if merge_request.valid?
+ # Find or create labels and attach to issue
+ unless params[:labels].nil?
+ merge_request.remove_labels
+ merge_request.add_labels_by_names(params[:labels].split(","))
+ end
+
present merge_request, with: Entities::MergeRequest
else
handle_merge_request_errors! merge_request.errors
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index 732c969d7ef..55f7975bbf7 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -7,7 +7,7 @@ module API
helpers do
def map_public_to_visibility_level(attrs)
publik = attrs.delete(:public)
- publik = [ true, 1, '1', 't', 'T', 'true', 'TRUE', 'on', 'ON' ].include?(publik)
+ publik = parse_boolean(publik)
attrs[:visibility_level] = Gitlab::VisibilityLevel::PUBLIC if !attrs[:visibility_level].present? && publik == true
attrs
end
@@ -15,10 +15,20 @@ module API
# Get a projects list for authenticated user
#
+ # Parameters:
+ # archived (optional) - if passed, limit by archived status
+ #
# Example Request:
# GET /projects
get do
- @projects = paginate current_user.authorized_projects
+ @projects = current_user.authorized_projects
+
+ # If the archived parameter is passed, limit results accordingly
+ if params[:archived].present?
+ @projects = @projects.where(archived: parse_boolean(params[:archived]))
+ end
+
+ @projects = paginate @projects
present @projects, with: Entities::Project
end
@@ -77,6 +87,7 @@ module API
# namespace_id (optional) - defaults to user namespace
# public (optional) - if true same as setting visibility_level = 20
# visibility_level (optional) - 0 by default
+ # import_url (optional)
# Example Request
# POST /projects
post do
@@ -117,6 +128,7 @@ module API
# snippets_enabled (optional)
# public (optional) - if true same as setting visibility_level = 20
# visibility_level (optional)
+ # import_url (optional)
# Example Request
# POST /projects/user/:user_id
post "user/:user_id" do
@@ -130,7 +142,8 @@ module API
:wiki_enabled,
:snippets_enabled,
:public,
- :visibility_level]
+ :visibility_level,
+ :import_url]
attrs = map_public_to_visibility_level(attrs)
@project = ::Projects::CreateService.new(user, attrs).execute
if @project.saved?
@@ -211,17 +224,6 @@ module API
@users = paginate @users
present @users, with: Entities::UserBasic
end
-
- # Get a project labels
- #
- # Parameters:
- # id (required) - The ID of a project
- # Example Request:
- # GET /projects/:id/labels
- get ':id/labels' do
- @labels = user_project.issues_labels
- present @labels, with: Entities::Label
- end
end
end
end
diff --git a/lib/api/repositories.rb b/lib/api/repositories.rb
index 03806d9343b..07c29aa7b4c 100644
--- a/lib/api/repositories.rb
+++ b/lib/api/repositories.rb
@@ -32,14 +32,23 @@ module API
# id (required) - The ID of a project
# tag_name (required) - The name of the tag
# ref (required) - Create tag from commit sha or branch
+ # message (optional) - Specifying a message creates an annotated tag.
# Example Request:
# POST /projects/:id/repository/tags
post ':id/repository/tags' do
authorize_push_project
- @tag = CreateTagService.new.execute(user_project, params[:tag_name],
- params[:ref], current_user)
-
- present @tag, with: Entities::RepoObject, project: user_project
+ message = params[:message] || nil
+ result = CreateTagService.new.execute(user_project, params[:tag_name],
+ params[:ref], message,
+ current_user)
+
+ if result[:status] == :success
+ present result[:tag],
+ with: Entities::RepoObject,
+ project: user_project
+ else
+ render_api_error!(result[:message], 400)
+ end
end
# Get a project repository tree
@@ -115,21 +124,13 @@ module API
# GET /projects/:id/repository/archive
get ":id/repository/archive", requirements: { format: Gitlab::Regex.archive_formats_regex } do
authorize! :download_code, user_project
- repo = user_project.repository
- ref = params[:sha]
- format = params[:format]
- storage_path = Gitlab.config.gitlab.repository_downloads_path
+ file_path = ArchiveRepositoryService.new.execute(user_project, params[:sha], params[:format])
- file_path = repo.archive_repo(ref, storage_path, format)
if file_path && File.exists?(file_path)
data = File.open(file_path, 'rb').read
-
header["Content-Disposition"] = "attachment; filename=\"#{File.basename(file_path)}\""
-
content_type MIME::Types.type_for(file_path).first.content_type
-
env['api.format'] = :binary
-
present data
else
not_found!
@@ -147,9 +148,21 @@ module API
get ':id/repository/compare' do
authorize! :download_code, user_project
required_attributes! [:from, :to]
- compare = Gitlab::Git::Compare.new(user_project.repository.raw_repository, params[:from], params[:to], MergeRequestDiff::COMMITS_SAFE_SIZE)
+ compare = Gitlab::Git::Compare.new(user_project.repository.raw_repository, params[:from], params[:to])
present compare, with: Entities::Compare
end
+
+ # Get repository contributors
+ #
+ # Parameters:
+ # id (required) - The ID of a project
+ # Example Request:
+ # GET /projects/:id/repository/contributors
+ get ':id/repository/contributors' do
+ authorize! :download_code, user_project
+
+ present user_project.repository.contributors, with: Entities::Contributor
+ end
end
end
end
diff --git a/lib/api/users.rb b/lib/api/users.rb
index 92dbe97f0a4..69553f16397 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -59,7 +59,7 @@ module API
authenticated_as_admin!
required_attributes! [:email, :password, :name, :username]
attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :extern_uid, :provider, :bio, :can_create_group, :admin]
- user = User.build_user(attrs, as: :admin)
+ user = User.build_user(attrs)
admin = attrs.delete(:admin)
user.admin = admin unless admin.nil?
if user.save
@@ -96,7 +96,7 @@ module API
admin = attrs.delete(:admin)
user.admin = admin unless admin.nil?
- if user.update_attributes(attrs, as: :admin)
+ if user.update_attributes(attrs)
present user, with: Entities::UserFull
else
not_found!
diff --git a/lib/backup/repository.rb b/lib/backup/repository.rb
index 6f7c4f7c909..ea05fa2c261 100644
--- a/lib/backup/repository.rb
+++ b/lib/backup/repository.rb
@@ -69,7 +69,7 @@ module Backup
end
print 'Put GitLab hooks in repositories dirs'.yellow
- if system("#{Gitlab.config.gitlab_shell.path}/support/rewrite-hooks.sh", Gitlab.config.gitlab_shell.repos_path)
+ if system("#{Gitlab.config.gitlab_shell.path}/bin/create-hooks")
puts " [DONE]".green
else
puts " [FAILED]".red
diff --git a/lib/gitlab/backend/shell.rb b/lib/gitlab/backend/shell.rb
index b93800e235f..907373ab991 100644
--- a/lib/gitlab/backend/shell.rb
+++ b/lib/gitlab/backend/shell.rb
@@ -27,7 +27,7 @@ module Gitlab
# import_repository("gitlab/gitlab-ci", "https://github.com/randx/six.git")
#
def import_repository(name, url)
- system "#{gitlab_shell_path}/bin/gitlab-projects", "import-project", "#{name}.git", url
+ system "#{gitlab_shell_path}/bin/gitlab-projects", "import-project", "#{name}.git", url, '240'
end
# Move repository
@@ -107,12 +107,17 @@ module Gitlab
# path - project path with namespace
# tag_name - new tag name
# ref - HEAD for new tag
+ # message - optional message for tag (annotated tag)
#
# Ex.
# add_tag("gitlab/gitlab-ci", "v4.0", "master")
+ # add_tag("gitlab/gitlab-ci", "v4.0", "master", "message")
#
- def add_tag(path, tag_name, ref)
- system "#{gitlab_shell_path}/bin/gitlab-projects", "create-tag", "#{path}.git", tag_name, ref
+ def add_tag(path, tag_name, ref, message = nil)
+ cmd = %W(#{gitlab_shell_path}/bin/gitlab-projects create-tag #{path}.git
+ #{tag_name} #{ref})
+ cmd << message unless message.nil? || message.empty?
+ system *cmd
end
# Remove repository tag
diff --git a/lib/gitlab/blacklist.rb b/lib/gitlab/blacklist.rb
index 6bc2c3b487c..65efb6e4407 100644
--- a/lib/gitlab/blacklist.rb
+++ b/lib/gitlab/blacklist.rb
@@ -3,7 +3,31 @@ module Gitlab
extend self
def path
- %w(admin dashboard files groups help profile projects search public assets u s teams merge_requests issues users snippets services repository hooks notes)
+ %w(
+ admin
+ dashboard
+ files
+ groups
+ help
+ profile
+ projects
+ search
+ public
+ assets
+ u
+ s
+ teams
+ merge_requests
+ issues
+ users
+ snippets
+ services
+ repository
+ hooks
+ notes
+ unsubscribes
+ all
+ )
end
end
end
diff --git a/lib/gitlab/compare_result.rb b/lib/gitlab/compare_result.rb
new file mode 100644
index 00000000000..d72391dade5
--- /dev/null
+++ b/lib/gitlab/compare_result.rb
@@ -0,0 +1,9 @@
+module Gitlab
+ class CompareResult
+ attr_reader :commits, :diffs
+
+ def initialize(compare)
+ @commits, @diffs = compare.commits, compare.diffs
+ end
+ end
+end
diff --git a/lib/gitlab/config_helper.rb b/lib/gitlab/config_helper.rb
new file mode 100644
index 00000000000..41880069e4c
--- /dev/null
+++ b/lib/gitlab/config_helper.rb
@@ -0,0 +1,9 @@
+module Gitlab::ConfigHelper
+ def gitlab_config_features
+ Gitlab.config.gitlab.default_projects_features
+ end
+
+ def gitlab_config
+ Gitlab.config.gitlab
+ end
+end
diff --git a/lib/gitlab/contributors.rb b/lib/gitlab/contributors.rb
new file mode 100644
index 00000000000..c41e92b620f
--- /dev/null
+++ b/lib/gitlab/contributors.rb
@@ -0,0 +1,9 @@
+module Gitlab
+ class Contributor
+ attr_accessor :email, :name, :commits, :additions, :deletions
+
+ def initialize
+ @commits, @additions, @deletions = 0, 0, 0
+ end
+ end
+end
diff --git a/lib/gitlab/diff_parser.rb b/lib/gitlab/diff_parser.rb
index 14bbb328637..b244295027e 100644
--- a/lib/gitlab/diff_parser.rb
+++ b/lib/gitlab/diff_parser.rb
@@ -30,7 +30,7 @@ module Gitlab
line_new = line.match(/\+[0-9]*/)[0].to_i.abs rescue 0
next if line_old == 1 && line_new == 1 #top of file
- yield(full_line, type, nil, nil, nil)
+ yield(full_line, type, nil, line_new, line_old)
next
else
type = identification_type(line)
diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb
index 38b3d82e2f4..e75a5a1d62e 100644
--- a/lib/gitlab/git_access.rb
+++ b/lib/gitlab/git_access.rb
@@ -5,7 +5,7 @@ module Gitlab
attr_reader :params, :project, :git_cmd, :user
- def allowed?(actor, cmd, project, ref = nil, oldrev = nil, newrev = nil, forced_push = false)
+ def allowed?(actor, cmd, project, changes = nil)
case cmd
when *DOWNLOAD_COMMANDS
if actor.is_a? User
@@ -19,12 +19,12 @@ module Gitlab
end
when *PUSH_COMMANDS
if actor.is_a? User
- push_allowed?(actor, project, ref, oldrev, newrev, forced_push)
+ push_allowed?(actor, project, changes)
elsif actor.is_a? DeployKey
# Deploy key not allowed to push
return false
elsif actor.is_a? Key
- push_allowed?(actor.user, project, ref, oldrev, newrev, forced_push)
+ push_allowed?(actor.user, project, changes)
else
raise 'Wrong actor'
end
@@ -41,13 +41,21 @@ module Gitlab
end
end
- def push_allowed?(user, project, ref, oldrev, newrev, forced_push)
- if user && user_allowed?(user)
+ def push_allowed?(user, project, changes)
+ return false unless user && user_allowed?(user)
+ return true if changes.blank?
+
+ changes = changes.lines if changes.kind_of?(String)
+
+ # Iterate over all changes to find if user allowed all of them to be applied
+ changes.each do |change|
+ oldrev, newrev, ref = changes.split('')
+
action = if project.protected_branch?(ref)
# we dont allow force push to protected branch
- if forced_push.to_s == 'true'
+ if forced_push?(oldrev, newrev)
:force_push_code_to_protected_branches
- # and we dont allow remove of protected branch
+ # and we dont allow remove of protected branch
elsif newrev =~ /0000000/
:remove_protected_branches
else
@@ -59,7 +67,22 @@ module Gitlab
else
:push_code
end
- user.can?(action, project)
+ unless user.can?(action, project)
+ # If user does not have access to make at least one change - cancel all push
+ return false
+ end
+ end
+
+ # If user has access to make all changes
+ true
+ end
+
+ def forced_push?(oldrev, newrev)
+ return false if project.empty_repo?
+
+ if oldrev !~ /00000000/ && newrev !~ /00000000/
+ missed_refs = IO.popen(%W(git --git-dir=#{project.repository.path_to_repo} rev-list #{oldrev} ^#{newrev})).read
+ missed_refs.split("\n").size > 0
else
false
end
diff --git a/lib/gitlab/git_ref_validator.rb b/lib/gitlab/git_ref_validator.rb
new file mode 100644
index 00000000000..13cb08948bb
--- /dev/null
+++ b/lib/gitlab/git_ref_validator.rb
@@ -0,0 +1,11 @@
+module Gitlab
+ module GitRefValidator
+ extend self
+ # Validates a given name against the git reference specification
+ #
+ # Returns true for a valid reference name, false otherwise
+ def validate(ref_name)
+ system *%W(git check-ref-format refs/#{ref_name})
+ end
+ end
+end
diff --git a/lib/gitlab/issues_labels.rb b/lib/gitlab/issues_labels.rb
index bc49d27b521..0d34976736f 100644
--- a/lib/gitlab/issues_labels.rb
+++ b/lib/gitlab/issues_labels.rb
@@ -1,27 +1,27 @@
module Gitlab
class IssuesLabels
class << self
- def important_labels
- %w(bug critical confirmed)
- end
-
- def warning_labels
- %w(documentation support)
- end
-
- def neutral_labels
- %w(discussion suggestion)
- end
-
- def positive_labels
- %w(feature enhancement)
- end
-
def generate(project)
- labels = important_labels + warning_labels + neutral_labels + positive_labels
+ red = '#d9534f'
+ yellow = '#f0ad4e'
+ blue = '#428bca'
+ green = '#5cb85c'
+
+ labels = [
+ { title: "bug", color: red },
+ { title: "critical", color: red },
+ { title: "confirmed", color: red },
+ { title: "documentation", color: yellow },
+ { title: "support", color: yellow },
+ { title: "discussion", color: blue },
+ { title: "suggestion", color: blue },
+ { title: "feature", color: green },
+ { title: "enhancement", color: green }
+ ]
- project.issues_default_label_list = labels
- project.save
+ labels.each do |label|
+ project.labels.create(label)
+ end
end
end
end
diff --git a/lib/gitlab/ldap/access.rb b/lib/gitlab/ldap/access.rb
index 4e48ff11871..c054b6f5865 100644
--- a/lib/gitlab/ldap/access.rb
+++ b/lib/gitlab/ldap/access.rb
@@ -9,13 +9,26 @@ module Gitlab
end
end
+ def self.allowed?(user)
+ self.open do |access|
+ if access.allowed?(user)
+ # GitLab EE LDAP code goes here
+ user.last_credential_check_at = Time.now
+ user.save
+ true
+ else
+ false
+ end
+ end
+ end
+
def initialize(adapter=nil)
@adapter = adapter
end
def allowed?(user)
if Gitlab::LDAP::Person.find_by_dn(user.extern_uid, adapter)
- !Gitlab::LDAP::Person.active_directory_disabled?(user.extern_uid, adapter)
+ !Gitlab::LDAP::Person.disabled_via_active_directory?(user.extern_uid, adapter)
else
false
end
diff --git a/lib/gitlab/ldap/adapter.rb b/lib/gitlab/ldap/adapter.rb
index e36616f0e66..68ac1b22909 100644
--- a/lib/gitlab/ldap/adapter.rb
+++ b/lib/gitlab/ldap/adapter.rb
@@ -14,7 +14,15 @@ module Gitlab
end
def self.adapter_options
- encryption = config['method'].to_s == 'ssl' ? :simple_tls : nil
+ encryption =
+ case config['method'].to_s
+ when 'ssl'
+ :simple_tls
+ when 'tls'
+ :start_tls
+ else
+ nil
+ end
options = {
host: config['host'],
@@ -78,7 +86,8 @@ module Gitlab
end
def dn_matches_filter?(dn, filter)
- ldap_search(base: dn, filter: filter, scope: Net::LDAP::SearchScope_BaseObject, attributes: %w{dn}).any?
+ ldap_search(base: dn, filter: filter,
+ scope: Net::LDAP::SearchScope_BaseObject, attributes: %w{dn}).any?
end
def ldap_search(*args)
diff --git a/lib/gitlab/ldap/person.rb b/lib/gitlab/ldap/person.rb
index 9ad6618bd46..87c3d711db4 100644
--- a/lib/gitlab/ldap/person.rb
+++ b/lib/gitlab/ldap/person.rb
@@ -16,7 +16,7 @@ module Gitlab
adapter.user('dn', dn)
end
- def self.active_directory_disabled?(dn, adapter=nil)
+ def self.disabled_via_active_directory?(dn, adapter=nil)
adapter ||= Gitlab::LDAP::Adapter.new
adapter.dn_matches_filter?(dn, AD_USER_DISABLED)
end
diff --git a/lib/gitlab/ldap/user.rb b/lib/gitlab/ldap/user.rb
index be3fcc4f035..e6aa3890992 100644
--- a/lib/gitlab/ldap/user.rb
+++ b/lib/gitlab/ldap/user.rb
@@ -26,7 +26,7 @@ module Gitlab
# * When user already has account and need to link their LDAP account.
# * LDAP uid changed for user with same email and we need to update their uid
#
- user = find_user(email)
+ user = model.find_by(email: email)
if user
user.update_attributes(extern_uid: uid, provider: provider)
@@ -43,21 +43,6 @@ module Gitlab
user
end
- def find_user(email)
- user = model.find_by(email: email)
-
- # If no user found and allow_username_or_email_login is true
- # we look for user by extracting part of their email
- if !user && email && ldap_conf['allow_username_or_email_login']
- uname = email.partition('@').first
- # Strip apostrophes since they are disallowed as part of username
- username = uname.gsub("'", "")
- user = model.find_by(username: username)
- end
-
- user
- end
-
def authenticate(login, password)
# Check user against LDAP backend if user is not authenticated
# Only check with valid login and password to prevent anonymous bind results
@@ -92,10 +77,6 @@ module Gitlab
model.where("provider = ? and lower(extern_uid) = ?", provider, uid.downcase).last
end
- def username
- auth.info.nickname.to_s.force_encoding("utf-8")
- end
-
def provider
'ldap'
end
diff --git a/lib/gitlab/markdown.rb b/lib/gitlab/markdown.rb
index 50e6b1efca6..6017a4c86c1 100644
--- a/lib/gitlab/markdown.rb
+++ b/lib/gitlab/markdown.rb
@@ -169,10 +169,13 @@ module Gitlab
end
def reference_user(identifier, project = @project)
- if user = User.find_by(username: identifier)
- options = html_options.merge(
+ options = html_options.merge(
class: "gfm gfm-team_member #{html_options[:class]}"
)
+
+ if identifier == "all"
+ link_to("@all", project_url(project), options)
+ elsif user = User.find_by(username: identifier)
link_to("@#{identifier}", user_url(identifier), options)
end
end
diff --git a/lib/gitlab/markdown_helper.rb b/lib/gitlab/markdown_helper.rb
new file mode 100644
index 00000000000..abed12fe570
--- /dev/null
+++ b/lib/gitlab/markdown_helper.rb
@@ -0,0 +1,25 @@
+module Gitlab
+ module MarkdownHelper
+ module_function
+
+ # Public: Determines if a given filename is compatible with GitHub::Markup.
+ #
+ # filename - Filename string to check
+ #
+ # Returns boolean
+ def markup?(filename)
+ filename.downcase.end_with?(*%w(.textile .rdoc .org .creole .wiki
+ .mediawiki .rst .adoc .asciidoc .asc))
+ end
+
+ # Public: Determines if a given filename is compatible with
+ # GitLab-flavored Markdown.
+ #
+ # filename - Filename string to check
+ #
+ # Returns boolean
+ def gitlab_markdown?(filename)
+ filename.downcase.end_with?(*%w(.mdown .md .markdown))
+ end
+ end
+end
diff --git a/lib/gitlab/oauth/user.rb b/lib/gitlab/oauth/user.rb
index c5be884a895..9670aad2c5d 100644
--- a/lib/gitlab/oauth/user.rb
+++ b/lib/gitlab/oauth/user.rb
@@ -27,7 +27,7 @@ module Gitlab
password_confirmation: password,
}
- user = model.build_user(opts, as: :admin)
+ user = model.build_user(opts)
user.skip_confirmation!
# Services like twitter and github does not return email via oauth
@@ -44,7 +44,13 @@ module Gitlab
user.username = email_username.gsub("'", "")
end
- user.save!
+ begin
+ user.save!
+ rescue ActiveRecord::RecordInvalid => e
+ log.info "(OAuth) Email #{e.record.errors[:email]}. Username #{e.record.errors[:username]}"
+ return nil, e.record.errors
+ end
+
log.info "(OAuth) Creating user #{email} from login with extern_uid => #{uid}"
if Gitlab.config.omniauth['block_auto_created_users'] && !ldap?
@@ -61,10 +67,11 @@ module Gitlab
end
def uid
- auth.info.uid || auth.uid
+ auth.uid.to_s
end
def email
+ return unless auth.info.respond_to?(:email)
auth.info.email.downcase unless auth.info.email.nil?
end
@@ -77,6 +84,7 @@ module Gitlab
end
def username
+ return unless auth.info.respond_to?(:nickname)
auth.info.nickname.to_s.force_encoding("utf-8")
end
diff --git a/lib/gitlab/project_search_results.rb b/lib/gitlab/project_search_results.rb
new file mode 100644
index 00000000000..90511662b20
--- /dev/null
+++ b/lib/gitlab/project_search_results.rb
@@ -0,0 +1,52 @@
+module Gitlab
+ class ProjectSearchResults < SearchResults
+ attr_reader :project, :repository_ref
+
+ def initialize(project_id, query, repository_ref = nil)
+ @project = Project.find(project_id)
+ @repository_ref = repository_ref
+ @query = Shellwords.shellescape(query) if query.present?
+ end
+
+ def objects(scope, page = nil)
+ case scope
+ when 'notes'
+ notes.page(page).per(per_page)
+ when 'blobs'
+ Kaminari.paginate_array(blobs).page(page).per(per_page)
+ else
+ super
+ end
+ end
+
+ def total_count
+ @total_count ||= issues_count + merge_requests_count + blobs_count + notes_count
+ end
+
+ def blobs_count
+ @blobs_count ||= blobs.count
+ end
+
+ def notes_count
+ @notes_count ||= notes.count
+ end
+
+ private
+
+ def blobs
+ if project.empty_repo?
+ []
+ else
+ project.repository.search_files(query, repository_ref)
+ end
+ end
+
+ def notes
+ Note.where(project_id: limit_project_ids).search(query).order('updated_at DESC')
+ end
+
+ def limit_project_ids
+ [project.id]
+ end
+ end
+end
diff --git a/lib/gitlab/regex.rb b/lib/gitlab/regex.rb
index e932b64f4f0..4b8038843b0 100644
--- a/lib/gitlab/regex.rb
+++ b/lib/gitlab/regex.rb
@@ -6,18 +6,35 @@ module Gitlab
default_regex
end
+ def username_regex_message
+ default_regex_message
+ end
+
def project_name_regex
/\A[a-zA-Z0-9_][a-zA-Z0-9_\-\. ]*\z/
end
+ def project_regex_message
+ "can contain only letters, digits, '_', '-' and '.' and space. " \
+ "It must start with letter, digit or '_'."
+ end
+
def name_regex
/\A[a-zA-Z0-9_\-\. ]*\z/
end
+ def name_regex_message
+ "can contain only letters, digits, '_', '-' and '.' and space."
+ end
+
def path_regex
default_regex
end
+ def path_regex_message
+ default_regex_message
+ end
+
def archive_formats_regex
#|zip|tar| tar.gz | tar.bz2 |
/(zip|tar|tar\.gz|tgz|gz|tar\.bz2|tbz|tbz2|tb2|bz2)/
@@ -48,8 +65,14 @@ module Gitlab
protected
+ def default_regex_message
+ "can contain only letters, digits, '_', '-' and '.'. " \
+ "It must start with letter, digit or '_', optionally preceeded by '.'. " \
+ "It must not end in '.git'."
+ end
+
def default_regex
- /\A[.?]?[a-zA-Z0-9_][a-zA-Z0-9_\-\.]*(?<!\.git)\z/
+ /\A[a-zA-Z0-9_.][a-zA-Z0-9_\-\.]*(?<!\.git)\z/
end
end
end
diff --git a/lib/gitlab/satellite/action.rb b/lib/gitlab/satellite/action.rb
index 5ea6f956765..be45cb5c98e 100644
--- a/lib/gitlab/satellite/action.rb
+++ b/lib/gitlab/satellite/action.rb
@@ -1,7 +1,7 @@
module Gitlab
module Satellite
class Action
- DEFAULT_OPTIONS = { git_timeout: 30.seconds }
+ DEFAULT_OPTIONS = { git_timeout: Gitlab.config.satellites.timeout.seconds }
attr_accessor :options, :project, :user
diff --git a/lib/gitlab/satellite/compare_action.rb b/lib/gitlab/satellite/compare_action.rb
index c923bb9c0f0..46c98a8f4ca 100644
--- a/lib/gitlab/satellite/compare_action.rb
+++ b/lib/gitlab/satellite/compare_action.rb
@@ -1,5 +1,7 @@
module Gitlab
module Satellite
+ class BranchesWithoutParent < StandardError; end
+
class CompareAction < Action
def initialize(user, target_project, target_branch, source_project, source_branch)
super user, target_project
@@ -8,34 +10,16 @@ module Gitlab
@source_project, @source_branch = source_project, source_branch
end
- # Only show what is new in the source branch compared to the target branch, not the other way around.
- # The line below with merge_base is equivalent to diff with three dots (git diff branch1...branch2)
- # From the git documentation: "git diff A...B" is equivalent to "git diff $(git-merge-base A B) B"
- def diffs
+ # Compare 2 repositories and return Gitlab::CompareResult object
+ def result
in_locked_and_timed_satellite do |target_repo|
prepare_satellite!(target_repo)
update_satellite_source_and_target!(target_repo)
- common_commit = target_repo.git.native(:merge_base, default_options, ["origin/#{@target_branch}", "source/#{@source_branch}"]).strip
- #this method doesn't take default options
- diffs = target_repo.diff(common_commit, "source/#{@source_branch}")
- diffs = diffs.map { |diff| Gitlab::Git::Diff.new(diff) }
- diffs
- end
- rescue Grit::Git::CommandFailed => ex
- handle_exception(ex)
- end
- # Retrieve an array of commits between the source and the target
- def commits
- in_locked_and_timed_satellite do |target_repo|
- prepare_satellite!(target_repo)
- update_satellite_source_and_target!(target_repo)
- commits = target_repo.commits_between("origin/#{@target_branch}", "source/#{@source_branch}")
- commits = commits.map { |commit| Gitlab::Git::Commit.new(commit, nil) }
- commits
+ Gitlab::CompareResult.new(compare(target_repo))
end
rescue Grit::Git::CommandFailed => ex
- handle_exception(ex)
+ raise BranchesWithoutParent
end
private
@@ -44,10 +28,17 @@ module Gitlab
def update_satellite_source_and_target!(target_repo)
target_repo.remote_add('source', @source_project.repository.path_to_repo)
target_repo.remote_fetch('source')
- target_repo.git.checkout(default_options({b: true}), @target_branch, "origin/#{@target_branch}")
rescue Grit::Git::CommandFailed => ex
handle_exception(ex)
end
+
+ def compare(repo)
+ @compare ||= Gitlab::Git::Compare.new(
+ Gitlab::Git::Repository.new(repo.path),
+ "origin/#{@target_branch}",
+ "source/#{@source_branch}"
+ )
+ end
end
end
end
diff --git a/lib/gitlab/satellite/merge_action.rb b/lib/gitlab/satellite/merge_action.rb
index 5f17aa60b8b..7c9b2294647 100644
--- a/lib/gitlab/satellite/merge_action.rb
+++ b/lib/gitlab/satellite/merge_action.rb
@@ -31,8 +31,9 @@ module Gitlab
# push merge back to bare repo
# will raise CommandFailed when push fails
merge_repo.git.push(default_options, :origin, merge_request.target_branch)
+
# remove source branch
- if merge_request.should_remove_source_branch && !project.root_ref?(merge_request.source_branch)
+ if merge_request.should_remove_source_branch && !project.root_ref?(merge_request.source_branch) && !merge_request.for_fork?
# will raise CommandFailed when push fails
merge_repo.git.push(default_options, :origin, ":#{merge_request.source_branch}")
end
@@ -44,27 +45,30 @@ module Gitlab
handle_exception(ex)
end
- # Get a raw diff of the source to the target
def diff_in_satellite
in_locked_and_timed_satellite do |merge_repo|
prepare_satellite!(merge_repo)
update_satellite_source_and_target!(merge_repo)
- diff = merge_repo.git.native(:diff, default_options, "origin/#{merge_request.target_branch}", "source/#{merge_request.source_branch}")
+
+ # Only show what is new in the source branch compared to the target branch, not the other way around.
+ # The line below with merge_base is equivalent to diff with three dots (git diff branch1...branch2)
+ # From the git documentation: "git diff A...B" is equivalent to "git diff $(git-merge-base A B) B"
+ common_commit = merge_repo.git.native(:merge_base, default_options, ["origin/#{merge_request.target_branch}", "source/#{merge_request.source_branch}"]).strip
+ merge_repo.git.native(:diff, default_options, common_commit, "source/#{merge_request.source_branch}")
end
rescue Grit::Git::CommandFailed => ex
handle_exception(ex)
end
- # Only show what is new in the source branch compared to the target branch, not the other way around.
- # The line below with merge_base is equivalent to diff with three dots (git diff branch1...branch2)
- # From the git documentation: "git diff A...B" is equivalent to "git diff $(git-merge-base A B) B"
def diffs_between_satellite
in_locked_and_timed_satellite do |merge_repo|
prepare_satellite!(merge_repo)
update_satellite_source_and_target!(merge_repo)
if merge_request.for_fork?
+ # Only show what is new in the source branch compared to the target branch, not the other way around.
+ # The line below with merge_base is equivalent to diff with three dots (git diff branch1...branch2)
+ # From the git documentation: "git diff A...B" is equivalent to "git diff $(git-merge-base A B) B"
common_commit = merge_repo.git.native(:merge_base, default_options, ["origin/#{merge_request.target_branch}", "source/#{merge_request.source_branch}"]).strip
- #this method doesn't take default options
diffs = merge_repo.diff(common_commit, "source/#{merge_request.source_branch}")
else
raise "Attempt to determine diffs between for a non forked merge request in satellite MergeRequest.id:[#{merge_request.id}]"
diff --git a/lib/gitlab/satellite/satellite.rb b/lib/gitlab/satellite/satellite.rb
index 05123ad9c41..f34d661c9fc 100644
--- a/lib/gitlab/satellite/satellite.rb
+++ b/lib/gitlab/satellite/satellite.rb
@@ -53,7 +53,7 @@ module Gitlab
File.open(lock_file, "w+") do |f|
begin
f.flock File::LOCK_EX
- Dir.chdir(path) { return yield }
+ yield
ensure
f.flock File::LOCK_UN
end
@@ -121,6 +121,7 @@ module Gitlab
#
# Note: this will only update remote branches (i.e. origin/*)
def update_from_source!
+ repo.git.remote(default_options, 'set-url', :origin, project.repository.path_to_repo)
repo.git.fetch(default_options, :origin)
end
diff --git a/lib/gitlab/search_results.rb b/lib/gitlab/search_results.rb
new file mode 100644
index 00000000000..75a3dfe37c3
--- /dev/null
+++ b/lib/gitlab/search_results.rb
@@ -0,0 +1,69 @@
+module Gitlab
+ class SearchResults
+ attr_reader :query
+
+ # Limit search results by passed project ids
+ # It allows us to search only for projects user has access to
+ attr_reader :limit_project_ids
+
+ def initialize(limit_project_ids, query)
+ @limit_project_ids = limit_project_ids || Project.all
+ @query = Shellwords.shellescape(query) if query.present?
+ end
+
+ def objects(scope, page = nil)
+ case scope
+ when 'projects'
+ projects.page(page).per(per_page)
+ when 'issues'
+ issues.page(page).per(per_page)
+ when 'merge_requests'
+ merge_requests.page(page).per(per_page)
+ else
+ Kaminari.paginate_array([]).page(page).per(per_page)
+ end
+ end
+
+ def total_count
+ @total_count ||= projects_count + issues_count + merge_requests_count
+ end
+
+ def projects_count
+ @projects_count ||= projects.count
+ end
+
+ def issues_count
+ @issues_count ||= issues.count
+ end
+
+ def merge_requests_count
+ @merge_requests_count ||= merge_requests.count
+ end
+
+ def empty?
+ total_count.zero?
+ end
+
+ private
+
+ def projects
+ Project.where(id: limit_project_ids).search(query)
+ end
+
+ def issues
+ Issue.where(project_id: limit_project_ids).full_search(query).order('updated_at DESC')
+ end
+
+ def merge_requests
+ MergeRequest.in_projects(limit_project_ids).full_search(query).order('updated_at DESC')
+ end
+
+ def default_scope
+ 'projects'
+ end
+
+ def per_page
+ 20
+ end
+ end
+end
diff --git a/lib/gitlab/sidekiq_middleware/arguments_logger.rb b/lib/gitlab/sidekiq_middleware/arguments_logger.rb
new file mode 100644
index 00000000000..7813091ec7b
--- /dev/null
+++ b/lib/gitlab/sidekiq_middleware/arguments_logger.rb
@@ -0,0 +1,10 @@
+module Gitlab
+ module SidekiqMiddleware
+ class ArgumentsLogger
+ def call(worker, job, queue)
+ Sidekiq.logger.info "arguments: #{job['args']}"
+ yield
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/theme.rb b/lib/gitlab/theme.rb
index 44237a062fc..b7c50cb734d 100644
--- a/lib/gitlab/theme.rb
+++ b/lib/gitlab/theme.rb
@@ -1,10 +1,10 @@
module Gitlab
class Theme
- BASIC = 1
- MARS = 2
- MODERN = 3
- GRAY = 4
- COLOR = 5
+ BASIC = 1 unless const_defined?(:BASIC)
+ MARS = 2 unless const_defined?(:MARS)
+ MODERN = 3 unless const_defined?(:MODERN)
+ GRAY = 4 unless const_defined?(:GRAY)
+ COLOR = 5 unless const_defined?(:COLOR)
def self.css_class_by_id(id)
themes = {
diff --git a/lib/gitlab/upgrader.rb b/lib/gitlab/upgrader.rb
index 0846359f9b1..74b049b5143 100644
--- a/lib/gitlab/upgrader.rb
+++ b/lib/gitlab/upgrader.rb
@@ -43,7 +43,7 @@ module Gitlab
end
def latest_version_raw
- remote_tags, _ = Gitlab::Popen.popen(%W(git ls-remote --tags origin))
+ remote_tags, _ = Gitlab::Popen.popen(%W(git ls-remote --tags https://gitlab.com/gitlab-org/gitlab-ce.git))
git_tags = remote_tags.split("\n").grep(/tags\/v#{current_version.major}/)
git_tags = git_tags.select { |version| version =~ /v\d\.\d\.\d\Z/ }
last_tag = git_tags.last.match(/v\d\.\d\.\d/).to_s
diff --git a/lib/gitlab/url_builder.rb b/lib/gitlab/url_builder.rb
new file mode 100644
index 00000000000..de7e0404086
--- /dev/null
+++ b/lib/gitlab/url_builder.rb
@@ -0,0 +1,25 @@
+module Gitlab
+ class UrlBuilder
+ include Rails.application.routes.url_helpers
+
+ def initialize(type)
+ @type = type
+ end
+
+ def build(id)
+ case @type
+ when :issue
+ issue_url(id)
+ end
+ end
+
+ private
+
+ def issue_url(id)
+ issue = Issue.find(id)
+ project_issue_url(id: issue.iid,
+ project_id: issue.project,
+ host: Settings.gitlab['url'])
+ end
+ end
+end
diff --git a/lib/gitlab/user_access.rb b/lib/gitlab/user_access.rb
index 16df21b49ba..4885baf9526 100644
--- a/lib/gitlab/user_access.rb
+++ b/lib/gitlab/user_access.rb
@@ -3,13 +3,8 @@ module Gitlab
def self.allowed?(user)
return false if user.blocked?
- if Gitlab.config.ldap.enabled
- if user.ldap_user?
- # Check if LDAP user exists and match LDAP user_filter
- Gitlab::LDAP::Access.open do |adapter|
- return false unless adapter.allowed?(user)
- end
- end
+ if user.requires_ldap_check?
+ return false unless Gitlab::LDAP::Access.allowed?(user)
end
true
diff --git a/lib/gitlab/visibility_level.rb b/lib/gitlab/visibility_level.rb
index eada9bcddf5..d0b6cde3c7e 100644
--- a/lib/gitlab/visibility_level.rb
+++ b/lib/gitlab/visibility_level.rb
@@ -5,9 +5,9 @@
#
module Gitlab
module VisibilityLevel
- PRIVATE = 0
- INTERNAL = 10
- PUBLIC = 20
+ PRIVATE = 0 unless const_defined?(:PRIVATE)
+ INTERNAL = 10 unless const_defined?(:INTERNAL)
+ PUBLIC = 20 unless const_defined?(:PUBLIC)
class << self
def values
@@ -21,9 +21,23 @@ module Gitlab
'Public' => PUBLIC
}
end
-
+
def allowed_for?(user, level)
- user.is_admin? || !Gitlab.config.gitlab.restricted_visibility_levels.include?(level)
+ user.is_admin? || allowed_level?(level)
+ end
+
+ # Level can be a string `"public"` or a value `20`, first check if valid,
+ # then check if the corresponding string appears in the config
+ def allowed_level?(level)
+ if options.has_key?(level.to_s)
+ non_restricted_level?(level)
+ elsif options.has_value?(level.to_i)
+ non_restricted_level?(options.key(level.to_i).downcase)
+ end
+ end
+
+ def non_restricted_level?(level)
+ ! Gitlab.config.gitlab.restricted_visibility_levels.include?(level)
end
end
diff --git a/lib/gt_one_coercion.rb b/lib/gt_one_coercion.rb
new file mode 100644
index 00000000000..ef2dc09767c
--- /dev/null
+++ b/lib/gt_one_coercion.rb
@@ -0,0 +1,5 @@
+class GtOneCoercion < Virtus::Attribute
+ def coerce(value)
+ [1, value.to_i].max
+ end
+end
diff --git a/lib/support/nginx/gitlab b/lib/support/nginx/gitlab
index 36306eeb3a6..16b06fe006e 100644
--- a/lib/support/nginx/gitlab
+++ b/lib/support/nginx/gitlab
@@ -1,69 +1,85 @@
-# GITLAB
-# Maintainer: @randx
-
-# CHUNKED TRANSFER
-# It is a known issue that Git-over-HTTP requires chunked transfer encoding [0] which is not
-# supported by Nginx < 1.3.9 [1]. As a result, pushing a large object with Git (i.e. a single large file)
-# can lead to a 411 error. In theory you can get around this by tweaking this configuration file and either
-# - installing an old version of Nginx with the chunkin module [2] compiled in, or
-# - using a newer version of Nginx.
-#
-# At the time of writing we do not know if either of these theoretical solutions works. As a workaround
-# users can use Git over SSH to push large files.
-#
-# [0] https://git.kernel.org/cgit/git/git.git/tree/Documentation/technical/http-protocol.txt#n99
-# [1] https://github.com/agentzh/chunkin-nginx-module#status
-# [2] https://github.com/agentzh/chunkin-nginx-module
+## GitLab
+## Maintainer: @randx
+##
+## Lines starting with two hashes (##) are comments with information.
+## Lines starting with one hash (#) are configuration parameters that can be uncommented.
+##
+##################################
+## CHUNKED TRANSFER ##
+##################################
+##
+## It is a known issue that Git-over-HTTP requires chunked transfer encoding [0]
+## which is not supported by Nginx < 1.3.9 [1]. As a result, pushing a large object
+## with Git (i.e. a single large file) can lead to a 411 error. In theory you can get
+## around this by tweaking this configuration file and either:
+## - installing an old version of Nginx with the chunkin module [2] compiled in, or
+## - using a newer version of Nginx.
+##
+## At the time of writing we do not know if either of these theoretical solutions works.
+## As a workaround users can use Git over SSH to push large files.
+##
+## [0] https://git.kernel.org/cgit/git/git.git/tree/Documentation/technical/http-protocol.txt#n99
+## [1] https://github.com/agentzh/chunkin-nginx-module#status
+## [2] https://github.com/agentzh/chunkin-nginx-module
+##
+###################################
+## configuration ##
+###################################
+##
upstream gitlab {
server unix:/home/git/gitlab/tmp/sockets/gitlab.socket;
}
+## Normal HTTP host
server {
- listen *:80 default_server; # e.g., listen 192.168.1.1:80; In most cases *:80 is a good idea
- server_name YOUR_SERVER_FQDN; # e.g., server_name source.example.com;
- server_tokens off; # don't show the version number, a security best practice
+ listen *:80 default_server;
+ server_name YOUR_SERVER_FQDN; ## Replace this with something like gitlab.example.com
+ server_tokens off; ## Don't show the nginx version number, a security best practice
root /home/git/gitlab/public;
-
- # Increase this if you want to upload large attachments
- # Or if you want to accept large git objects over http
+
+ ## Increase this if you want to upload large attachments
+ ## Or if you want to accept large git objects over http
client_max_body_size 20m;
- # individual nginx logs for this gitlab vhost
+ ## Individual nginx logs for this GitLab vhost
access_log /var/log/nginx/gitlab_access.log;
error_log /var/log/nginx/gitlab_error.log;
location / {
- # serve static files from defined root folder;.
- # @gitlab is a named location for the upstream fallback, see below
+ ## Serve static files from defined root folder.
+ ## @gitlab is a named location for the upstream fallback, see below.
try_files $uri $uri/index.html $uri.html @gitlab;
}
- # if a file, which is not found in the root folder is requested,
- # then the proxy pass the request to the upsteam (gitlab unicorn)
+ ## If a file, which is not found in the root folder is requested,
+ ## then the proxy passes the request to the upsteam (gitlab unicorn).
location @gitlab {
- # If you use https make sure you disable gzip compression
- # to be safe against BREACH attack
+ ## If you use HTTPS make sure you disable gzip compression
+ ## to be safe against BREACH attack.
# gzip off;
- proxy_read_timeout 300; # Some requests take more than 30 seconds.
- proxy_connect_timeout 300; # Some requests take more than 30 seconds.
- proxy_redirect 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 X-Forwarded-Proto $scheme;
- 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-Frame-Options SAMEORIGIN;
+ 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_set_header X-Frame-Options SAMEORIGIN;
proxy_pass http://gitlab;
}
- # Enable gzip compression as per rails guide: http://guides.rubyonrails.org/asset_pipeline.html#gzip-compression
- # WARNING: If you are using relative urls do remove the block below
- # See config/application.rb under "Relative url support" for the list of
- # other files that need to be changed for relative url support
- location ~ ^/(assets)/ {
+ ## Enable gzip compression as per rails guide:
+ ## http://guides.rubyonrails.org/asset_pipeline.html#gzip-compression
+ ## WARNING: If you are using relative urls remove the block below
+ ## See config/application.rb under "Relative url support" for the list of
+ ## other files that need to be changed for relative url support
+ location ~ ^/(assets)/ {
root /home/git/gitlab/public;
gzip_static on; # to serve pre-gzipped version
expires max;
diff --git a/lib/support/nginx/gitlab-ssl b/lib/support/nginx/gitlab-ssl
index 22e923b377c..0ba9d055c8c 100644
--- a/lib/support/nginx/gitlab-ssl
+++ b/lib/support/nginx/gitlab-ssl
@@ -3,33 +3,10 @@
##
## Modified from nginx http version
## Modified from http://blog.phusion.nl/2012/04/21/tutorial-setting-up-gitlab-on-debian-6/
+## Modified from https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html
##
-## Lines starting with two hashes (##) are comments containing information
-## for configuration. One hash (#) comments are actual configuration parameters
-## which you can comment/uncomment to your liking.
-##
-###################################
-## SSL configuration ##
-###################################
-##
-## Optimal configuration is taken from:
-## https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html
-## Make sure to read it and understand what each option does.
-##
-## [Optional] Generate a self-signed ssl certificate:
-## mkdir /etc/nginx/ssl/
-## cd /etc/nginx/ssl/
-## sudo openssl req -newkey rsa:2048 -x509 -nodes -days 3560 -out gitlab.crt -keyout gitlab.key
-## sudo chmod o-r gitlab.key
-##
-## Edit `gitlab-shell/config.yml`:
-## 1) Set "gitlab_url" param in `gitlab-shell/config.yml` to `https://git.example.com`
-## 2) Set "ca_file" to `/etc/nginx/ssl/gitlab.crt`
-## 3) Set "self_signed_cert" to `true`
-## Edit `gitlab/config/gitlab.yml`:
-## 1) Define port for http "port: 443"
-## 2) Enable https "https: true"
-## 3) Update ssl for gravatar "ssl_url: https://secure.gravatar.com/avatar/%{hash}?s=%{size}&d=mm"
+## Lines starting with two hashes (##) are comments with information.
+## Lines starting with one hash (#) are configuration parameters that can be uncommented.
##
##################################
## CHUNKED TRANSFER ##
@@ -42,39 +19,39 @@
## - installing an old version of Nginx with the chunkin module [2] compiled in, or
## - using a newer version of Nginx.
##
-## At the time of writing we do not know if either of these theoretical solutions works. As a workaround
-## users can use Git over SSH to push large files.
+## At the time of writing we do not know if either of these theoretical solutions works.
+## As a workaround users can use Git over SSH to push large files.
##
## [0] https://git.kernel.org/cgit/git/git.git/tree/Documentation/technical/http-protocol.txt#n99
## [1] https://github.com/agentzh/chunkin-nginx-module#status
## [2] https://github.com/agentzh/chunkin-nginx-module
-
+##
+##
+###################################
+## SSL configuration ##
+###################################
+##
+## See installation.md#using-https for additional HTTPS configuration details.
upstream gitlab {
-
- ## Uncomment if you have set up unicorn to listen on a unix socket (recommended).
server unix:/home/git/gitlab/tmp/sockets/gitlab.socket;
-
- ## Uncomment if unicorn is configured to listen on a tcp port.
- ## Check the port number in /home/git/gitlab/config/unicorn.rb
- # server 127.0.0.1:8080;
}
-## This is a normal HTTP host which redirects all traffic to the HTTPS host.
+## Normal HTTP host
server {
- listen *:80;
- ## Replace git.example.com with your FQDN.
- server_name git.example.com;
- server_tokens off;
- ## root doesn't have to be a valid path since we are redirecting
- root /nowhere;
- rewrite ^ https://$server_name$request_uri permanent;
+ listen *:80 default_server;
+ server_name YOUR_SERVER_FQDN; ## Replace this with something like gitlab.example.com
+ server_tokens off; ## Don't show the nginx version number, a security best practice
+
+ ## Redirects all traffic to the HTTPS host
+ root /nowhere; ## root doesn't have to be a valid path since we are redirecting
+ rewrite ^ https://$server_name$request_uri? permanent;
}
+## HTTPS host
server {
listen 443 ssl;
- ## Replace git.example.com with your FQDN.
- server_name git.example.com;
+ server_name YOUR_SERVER_FQDN; ## Replace this with something like gitlab.example.com
server_tokens off;
root /home/git/gitlab/public;
@@ -93,27 +70,29 @@ server {
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_session_cache builtin:1000 shared:SSL:10m;
- ## Enable OCSP stapling to reduce the overhead and latency of running SSL.
+ ssl_prefer_server_ciphers on;
+
+ add_header Strict-Transport-Security max-age=63072000;
+ add_header X-Frame-Options SAMEORIGIN;
+ add_header X-Content-Type-Options nosniff;
+
+ ## [Optional] If your certficate has OCSP, enable OCSP stapling to reduce the overhead and latency of running SSL.
## Replace with your ssl_trusted_certificate. For more info see:
## - https://medium.com/devops-programming/4445f4862461
## - https://www.ruby-forum.com/topic/4419319
- ssl_stapling on;
- ssl_stapling_verify on;
- ssl_trusted_certificate /etc/nginx/ssl/stapling.trusted.crt;
- resolver 208.67.222.222 208.67.222.220 valid=300s;
- resolver_timeout 10s;
-
- ssl_prefer_server_ciphers on;
- ## [Optional] Generate a stronger DHE parameter (recommended):
+ ## - https://www.digitalocean.com/community/tutorials/how-to-configure-ocsp-stapling-on-apache-and-nginx
+ # ssl_stapling on;
+ # ssl_stapling_verify on;
+ # ssl_trusted_certificate /etc/nginx/ssl/stapling.trusted.crt;
+ # resolver 208.67.222.222 208.67.222.220 valid=300s; # Can change to your DNS resolver if desired
+ # resolver_timeout 10s;
+
+ ## [Optional] Generate a stronger DHE parameter:
## cd /etc/ssl/certs
- ## openssl dhparam -out dhparam.pem 2048
+ ## sudo openssl dhparam -out dhparam.pem 4096
##
# ssl_dhparam /etc/ssl/certs/dhparam.pem;
- add_header Strict-Transport-Security max-age=63072000;
- add_header X-Frame-Options DENY;
- add_header X-Content-Type-Options nosniff;
-
## Individual nginx logs for this GitLab vhost
access_log /var/log/nginx/gitlab_access.log;
error_log /var/log/nginx/gitlab_error.log;
@@ -125,10 +104,9 @@ server {
}
## If a file, which is not found in the root folder is requested,
- ## then the proxy pass the request to the upsteam (gitlab unicorn).
+ ## then the proxy passes the request to the upsteam (gitlab unicorn).
location @gitlab {
-
- ## If you use https make sure you disable gzip compression
+ ## If you use HTTPS make sure you disable gzip compression
## to be safe against BREACH attack.
gzip off;
@@ -150,7 +128,7 @@ server {
## Enable gzip compression as per rails guide:
## http://guides.rubyonrails.org/asset_pipeline.html#gzip-compression
- ## WARNING: If you are using relative urls do remove the block below
+ ## WARNING: If you are using relative urls remove the block below
## See config/application.rb under "Relative url support" for the list of
## other files that need to be changed for relative url support
location ~ ^/(assets)/ {
diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake
index 34116568e99..9ea5c55abd6 100644
--- a/lib/tasks/gitlab/check.rake
+++ b/lib/tasks/gitlab/check.rake
@@ -27,6 +27,7 @@ namespace :gitlab do
check_projects_have_namespace
check_satellites_exist
check_redis_version
+ check_ruby_version
check_git_version
finished_checking "GitLab"
@@ -216,7 +217,7 @@ namespace :gitlab do
puts ""
Project.find_each(batch_size: 100) do |project|
- print "#{project.name_with_namespace.yellow} ... "
+ print sanitized_message(project)
if project.satellite.exists?
puts "yes".green
@@ -317,10 +318,11 @@ namespace :gitlab do
options = {
"user.name" => "GitLab",
- "user.email" => Gitlab.config.gitlab.email_from
+ "user.email" => Gitlab.config.gitlab.email_from,
+ "core.autocrlf" => "input"
}
correct_options = options.map do |name, value|
- run(%W(git config --global --get #{name})).try(:squish) == value
+ run(%W(#{Gitlab.config.git.bin_path} config --global --get #{name})).try(:squish) == value
end
if correct_options.all?
@@ -328,8 +330,9 @@ namespace :gitlab do
else
puts "no".red
try_fixing_it(
- sudo_gitlab("git config --global user.name \"#{options["user.name"]}\""),
- sudo_gitlab("git config --global user.email \"#{options["user.email"]}\"")
+ sudo_gitlab("\"#{Gitlab.config.git.bin_path}\" config --global user.name \"#{options["user.name"]}\""),
+ sudo_gitlab("\"#{Gitlab.config.git.bin_path}\" config --global user.email \"#{options["user.email"]}\""),
+ sudo_gitlab("\"#{Gitlab.config.git.bin_path}\" config --global core.autocrlf \"#{options["core.autocrlf"]}\"")
)
for_more_information(
see_installation_guide_section "GitLab"
@@ -525,7 +528,7 @@ namespace :gitlab do
puts ""
Project.find_each(batch_size: 100) do |project|
- print "#{project.name_with_namespace.yellow} ... "
+ print sanitized_message(project)
if project.empty_repo?
puts "repository is empty".magenta
@@ -538,7 +541,7 @@ namespace :gitlab do
"sudo -u #{gitlab_shell_ssh_user} ln -sf #{gitlab_shell_hook_file} #{project_hook_file}"
)
for_more_information(
- "#{gitlab_shell_path}/support/rewrite-hooks.sh"
+ "#{gitlab_shell_path}/bin/create-hooks"
)
fix_and_rerun
next
@@ -553,7 +556,7 @@ namespace :gitlab do
"sudo -u #{gitlab_shell_ssh_user} ln -sf #{gitlab_shell_hook_file} #{project_hook_file}"
)
for_more_information(
- "lib/support/rewrite-hooks.sh"
+ "#{gitlab_shell_path}/bin/create-hooks"
)
fix_and_rerun
end
@@ -588,7 +591,7 @@ namespace :gitlab do
puts ""
Project.find_each(batch_size: 100) do |project|
- print "#{project.name_with_namespace.yellow} ... "
+ print sanitized_message(project)
if project.namespace
puts "yes".green
@@ -816,6 +819,23 @@ namespace :gitlab do
end
end
+ def check_ruby_version
+ required_version = Gitlab::VersionInfo.new(2, 0, 0)
+ current_version = Gitlab::VersionInfo.parse(run(%W(ruby --version)))
+
+ print "Ruby version >= #{required_version} ? ... "
+
+ if current_version.valid? && required_version <= current_version
+ puts "yes (#{current_version})".green
+ else
+ puts "no".red
+ try_fixing_it(
+ "Update your ruby to a version >= #{required_version} from #{current_version}"
+ )
+ fix_and_rerun
+ end
+ end
+
def check_git_version
required_version = Gitlab::VersionInfo.new(1, 7, 10)
current_version = Gitlab::VersionInfo.parse(run(%W(#{Gitlab.config.git.bin_path} --version)))
@@ -837,4 +857,20 @@ namespace :gitlab do
def omnibus_gitlab?
Dir.pwd == '/opt/gitlab/embedded/service/gitlab-rails'
end
+
+ def sanitized_message(project)
+ if sanitize
+ "#{project.namespace_id.to_s.yellow}/#{project.id.to_s.yellow} ... "
+ else
+ "#{project.name_with_namespace.yellow} ... "
+ end
+ end
+
+ def sanitize
+ if ENV['SANITIZE'] == "true"
+ true
+ else
+ false
+ end
+ end
end
diff --git a/lib/tasks/gitlab/cleanup.rake b/lib/tasks/gitlab/cleanup.rake
index 4aaab11340f..63dcdc52370 100644
--- a/lib/tasks/gitlab/cleanup.rake
+++ b/lib/tasks/gitlab/cleanup.rake
@@ -84,5 +84,29 @@ namespace :gitlab do
puts "To cleanup this directories run this command with REMOVE=true".yellow
end
end
+
+ desc "GITLAB | Cleanup | Block users that have been removed in LDAP"
+ task block_removed_ldap_users: :environment do
+ warn_user_is_not_gitlab
+ block_flag = ENV['BLOCK']
+
+ User.ldap.each do |ldap_user|
+ print "#{ldap_user.name} (#{ldap_user.extern_uid}) ..."
+ if Gitlab::LDAP::Access.open { |access| access.allowed?(ldap_user) }
+ puts " [OK]".green
+ else
+ if block_flag
+ ldap_user.block!
+ puts " [BLOCKED]".red
+ else
+ puts " [NOT IN LDAP]".yellow
+ end
+ end
+ end
+
+ unless block_flag
+ puts "To block these users run this command with BLOCK=true".yellow
+ end
+ end
end
end
diff --git a/lib/tasks/gitlab/shell.rake b/lib/tasks/gitlab/shell.rake
index dfc90bb3339..ece3ad58385 100644
--- a/lib/tasks/gitlab/shell.rake
+++ b/lib/tasks/gitlab/shell.rake
@@ -4,10 +4,11 @@ namespace :gitlab do
task :install, [:tag, :repo] => :environment do |t, args|
warn_user_is_not_gitlab
- args.with_defaults(tag: "v1.9.3", repo: "https://gitlab.com/gitlab-org/gitlab-shell.git")
+ default_version = File.read(File.join(Rails.root, "GITLAB_SHELL_VERSION")).strip
+ args.with_defaults(tag: 'v' + default_version, repo: "https://gitlab.com/gitlab-org/gitlab-shell.git")
user = Settings.gitlab.user
- home_dir = Settings.gitlab.user_home
+ home_dir = Rails.env.test? ? Rails.root.join('tmp/tests') : Settings.gitlab.user_home
gitlab_url = Settings.gitlab.url
# gitlab-shell requires a / at the end of the url
gitlab_url += "/" unless gitlab_url.match(/\/$/)
diff --git a/lib/tasks/gitlab/sidekiq.rake b/lib/tasks/gitlab/sidekiq.rake
new file mode 100644
index 00000000000..7e2a6668e59
--- /dev/null
+++ b/lib/tasks/gitlab/sidekiq.rake
@@ -0,0 +1,47 @@
+namespace :gitlab do
+ namespace :sidekiq do
+ QUEUE = 'queue:post_receive'
+
+ desc 'Drop all Sidekiq PostReceive jobs for a given project'
+ task :drop_post_receive , [:project] => :environment do |t, args|
+ unless args.project.present?
+ abort "Please specify the project you want to drop PostReceive jobs for:\n rake gitlab:sidekiq:drop_post_receive[group/project]"
+ end
+ project_path = Project.find_with_namespace(args.project).repository.path_to_repo
+
+ Sidekiq.redis do |redis|
+ unless redis.exists(QUEUE)
+ abort "Queue #{QUEUE} is empty"
+ end
+
+ temp_queue = "#{QUEUE}_#{Time.now.to_i}"
+ redis.rename(QUEUE, temp_queue)
+
+ # At this point, then post_receive queue is empty. It may be receiving
+ # new jobs already. We will repopulate it with the old jobs, skipping the
+ # ones we want to drop.
+ dropped = 0
+ while (job = redis.lpop(temp_queue)) do
+ if repo_path(job) == project_path
+ dropped += 1
+ else
+ redis.rpush(QUEUE, job)
+ end
+ end
+ # The temp_queue will delete itself after we have popped all elements
+ # from it
+
+ puts "Dropped #{dropped} jobs containing #{project_path} from #{QUEUE}"
+ end
+ end
+
+ def repo_path(job)
+ job_args = JSON.parse(job)['args']
+ if job_args
+ job_args.first
+ else
+ nil
+ end
+ end
+ end
+end
diff --git a/lib/tasks/gitlab/test.rake b/lib/tasks/gitlab/test.rake
index 5b937ce0a28..c01b00bd1c0 100644
--- a/lib/tasks/gitlab/test.rake
+++ b/lib/tasks/gitlab/test.rake
@@ -11,4 +11,4 @@ namespace :gitlab do
system({'RAILS_ENV' => 'test', 'force' => 'yes'}, *cmd) or raise("#{cmd} failed!")
end
end
-end \ No newline at end of file
+end
diff --git a/lib/unfold_form.rb b/lib/unfold_form.rb
new file mode 100644
index 00000000000..46b12beeaaf
--- /dev/null
+++ b/lib/unfold_form.rb
@@ -0,0 +1,11 @@
+require_relative 'gt_one_coercion'
+
+class UnfoldForm
+ include Virtus.model
+
+ attribute :since, GtOneCoercion
+ attribute :to, GtOneCoercion
+ attribute :bottom, Boolean
+ attribute :unfold, Boolean, default: true
+ attribute :offset, Integer
+end