summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/api/api.rb3
-rw-r--r--lib/api/deploy_keys.rb14
-rw-r--r--lib/api/entities.rb74
-rw-r--r--lib/api/files.rb99
-rw-r--r--lib/api/groups.rb7
-rw-r--r--lib/api/helpers.rb26
-rw-r--r--lib/api/issues.rb39
-rw-r--r--lib/api/merge_requests.rb78
-rw-r--r--lib/api/milestones.rb34
-rw-r--r--lib/api/namespaces.rb23
-rw-r--r--lib/api/notes.rb40
-rw-r--r--lib/api/project_hooks.rb13
-rw-r--r--lib/api/project_snippets.rb4
-rw-r--r--lib/api/projects.rb55
-rw-r--r--lib/api/repositories.rb79
-rw-r--r--lib/api/services.rb44
-rw-r--r--lib/api/users.rb8
-rw-r--r--lib/backup/database.rb28
-rw-r--r--lib/backup/manager.rb10
-rw-r--r--lib/backup/repository.rb16
-rw-r--r--lib/backup/uploads.rb2
-rw-r--r--lib/extracts_path.rb2
-rw-r--r--lib/gitlab/auth.rb2
-rw-r--r--lib/gitlab/backend/grack_auth.rb68
-rw-r--r--lib/gitlab/backend/grack_helpers.rb2
-rw-r--r--lib/gitlab/backend/shell.rb39
-rw-r--r--lib/gitlab/blacklist.rb2
-rw-r--r--lib/gitlab/identifier.rb6
-rw-r--r--lib/gitlab/ldap/user.rb12
-rw-r--r--lib/gitlab/oauth/user.rb1
-rw-r--r--lib/gitlab/regex.rb30
-rw-r--r--lib/gitlab/satellite/files/delete_file_action.rb50
-rw-r--r--lib/gitlab/satellite/files/edit_file_action.rb (renamed from lib/gitlab/satellite/edit_file_action.rb)39
-rw-r--r--lib/gitlab/satellite/files/file_action.rb25
-rw-r--r--lib/gitlab/satellite/files/new_file_action.rb55
-rw-r--r--lib/gitlab/satellite/merge_action.rb46
-rw-r--r--lib/gitlab/satellite/satellite.rb2
-rw-r--r--lib/gitlab/theme.rb2
-rw-r--r--lib/gitlab/upgrader.rb96
-rw-r--r--lib/gitlab/visibility_level.rb42
-rw-r--r--lib/redcarpet/render/gitlab_html.rb24
-rwxr-xr-xlib/support/deploy/deploy.sh9
-rwxr-xr-xlib/support/init.d/gitlab144
-rwxr-xr-xlib/support/init.d/gitlab.default.example31
-rw-r--r--lib/support/logrotate/gitlab22
-rw-r--r--lib/support/nginx/gitlab26
-rw-r--r--lib/tasks/gitlab/bulk_add_permission.rake2
-rw-r--r--lib/tasks/gitlab/check.rake112
-rw-r--r--lib/tasks/gitlab/enable_namespaces.rake4
-rw-r--r--lib/tasks/gitlab/import.rake12
-rw-r--r--lib/tasks/gitlab/task_helpers.rake10
-rw-r--r--lib/tasks/sidekiq.rake15
52 files changed, 1191 insertions, 437 deletions
diff --git a/lib/api/api.rb b/lib/api/api.rb
index c4c9f166db1..283f7642f67 100644
--- a/lib/api/api.rb
+++ b/lib/api/api.rb
@@ -38,5 +38,8 @@ module API
mount ProjectSnippets
mount DeployKeys
mount ProjectHooks
+ mount Services
+ mount Files
+ mount Namespaces
end
end
diff --git a/lib/api/deploy_keys.rb b/lib/api/deploy_keys.rb
index 218b3d8eee2..7f5a125038c 100644
--- a/lib/api/deploy_keys.rb
+++ b/lib/api/deploy_keys.rb
@@ -5,16 +5,6 @@ module API
before { authorize_admin_project }
resource :projects do
- helpers do
- def handle_project_member_errors(errors)
- if errors[:project_access].any?
- error!(errors[:project_access], 422)
- end
- not_found!
- end
- end
-
-
# Get a specific project's keys
#
# Example Request:
@@ -48,14 +38,14 @@ module API
attrs[:key].strip!
# check if key already exist in project
- key = user_project.deploy_keys.find_by_key(attrs[:key])
+ key = user_project.deploy_keys.find_by(key: attrs[:key])
if key
present key, with: Entities::SSHKey
return
end
# Check for available deploy keys in other projects
- key = current_user.accessible_deploy_keys.find_by_key(attrs[:key])
+ key = current_user.accessible_deploy_keys.find_by(key: attrs[:key])
if key
user_project.deploy_keys << key
present key, with: Entities::SSHKey
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index b4771eecc7f..8f54d0d4d84 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -1,7 +1,7 @@
module API
module Entities
class User < Grape::Entity
- expose :id, :username, :email, :name, :bio, :skype, :linkedin, :twitter,
+ expose :id, :username, :email, :name, :bio, :skype, :linkedin, :twitter, :website_url,
:theme_id, :color_scheme_id, :state, :created_at, :extern_uid, :provider
expose :is_admin?, as: :is_admin
expose :can_create_group?, as: :can_create_group
@@ -24,6 +24,10 @@ module API
expose :id, :url, :created_at
end
+ class ProjectHook < Hook
+ expose :project_id, :push_events, :issues_events, :merge_requests_events
+ end
+
class ForkedFromProject < Grape::Entity
expose :id
expose :name, :name_with_namespace
@@ -31,30 +35,32 @@ module API
end
class Project < Grape::Entity
- expose :id, :description, :default_branch, :public, :ssh_url_to_repo, :http_url_to_repo, :web_url
+ expose :id, :description, :default_branch
+ expose :public?, as: :public
+ expose :visibility_level, :ssh_url_to_repo, :http_url_to_repo, :web_url
expose :owner, using: Entities::UserBasic
expose :name, :name_with_namespace
expose :path, :path_with_namespace
- expose :issues_enabled, :merge_requests_enabled, :wall_enabled, :wiki_enabled, :snippets_enabled, :created_at, :last_activity_at, :public
+ expose :issues_enabled, :merge_requests_enabled, :wall_enabled, :wiki_enabled, :snippets_enabled, :created_at, :last_activity_at
expose :namespace
expose :forked_from_project, using: Entities::ForkedFromProject, :if => lambda{ | project, options | project.forked? }
end
class ProjectMember < UserBasic
expose :project_access, as: :access_level do |user, options|
- options[:project].users_projects.find_by_user_id(user.id).project_access
+ options[:project].users_projects.find_by(user_id: user.id).project_access
end
end
class TeamMember < UserBasic
expose :permission, as: :access_level do |user, options|
- options[:user_team].user_team_user_relationships.find_by_user_id(user.id).permission
+ options[:user_team].user_team_user_relationships.find_by(user_id: user.id).permission
end
end
class TeamProject < Project
expose :greatest_access, as: :greatest_access_level do |project, options|
- options[:user_team].user_team_project_relationships.find_by_project_id(project.id).greatest_access
+ options[:user_team].user_team_project_relationships.find_by(project_id: project.id).greatest_access
end
end
@@ -68,12 +74,21 @@ module API
class GroupMember < UserBasic
expose :group_access, as: :access_level do |user, options|
- options[:group].users_groups.find_by_user_id(user.id).group_access
+ options[:group].users_groups.find_by(user_id: user.id).group_access
end
end
class RepoObject < Grape::Entity
- expose :name, :commit
+ expose :name
+
+ expose :commit do |repo_obj, options|
+ if repo_obj.respond_to?(:commit)
+ repo_obj.commit
+ elsif options[:project]
+ options[:project].repository.commit(repo_obj.target)
+ end
+ end
+
expose :protected do |repo, options|
if options[:project]
options[:project].protected_branch? repo.name
@@ -81,25 +96,40 @@ module API
end
end
+ class RepoTreeObject < Grape::Entity
+ expose :id, :name, :type
+
+ expose :mode do |obj, options|
+ filemode = obj.mode.to_s(8)
+ filemode = "0" + filemode if filemode.length < 6
+ filemode
+ end
+ end
+
class RepoCommit < Grape::Entity
expose :id, :short_id, :title, :author_name, :author_email, :created_at
end
+ class RepoCommitDetail < RepoCommit
+ expose :parent_ids, :committed_date, :authored_date
+ end
+
class ProjectSnippet < Grape::Entity
expose :id, :title, :file_name
expose :author, using: Entities::UserBasic
expose :expires_at, :updated_at, :created_at
end
- class Milestone < Grape::Entity
- expose :id
- expose (:project_id) {|milestone| milestone.project.id}
+ class ProjectEntity < Grape::Entity
+ expose :id, :iid
+ expose (:project_id) { |entity| entity.project.id }
+ end
+
+ class Milestone < ProjectEntity
expose :title, :description, :due_date, :state, :updated_at, :created_at
end
- class Issue < Grape::Entity
- expose :id
- expose (:project_id) {|issue| issue.project.id}
+ class Issue < ProjectEntity
expose :title, :description
expose :label_list, as: :labels
expose :milestone, using: Entities::Milestone
@@ -107,14 +137,14 @@ module API
expose :state, :updated_at, :created_at
end
- class SSHKey < Grape::Entity
- expose :id, :title, :key, :created_at
+ class MergeRequest < ProjectEntity
+ expose :target_branch, :source_branch, :title, :state, :upvotes, :downvotes
+ expose :author, :assignee, using: Entities::UserBasic
+ expose :source_project_id, :target_project_id
end
- class MergeRequest < Grape::Entity
- expose :id, :target_branch, :source_branch, :title, :state, :upvotes, :downvotes
- expose :target_project_id, as: :project_id
- expose :author, :assignee, using: Entities::UserBasic
+ class SSHKey < Grape::Entity
+ expose :id, :title, :key, :created_at
end
class Note < Grape::Entity
@@ -135,5 +165,9 @@ module API
expose :target_id, :target_type, :author_id
expose :data, :target_title
end
+
+ class Namespace < Grape::Entity
+ expose :id, :path, :kind
+ end
end
end
diff --git a/lib/api/files.rb b/lib/api/files.rb
new file mode 100644
index 00000000000..213604915a6
--- /dev/null
+++ b/lib/api/files.rb
@@ -0,0 +1,99 @@
+module API
+ # Projects API
+ class Files < Grape::API
+ before { authenticate! }
+ before { authorize! :push_code, user_project }
+
+ resource :projects do
+ # Create new file in repository
+ #
+ # Parameters:
+ # file_path (optional) - The path to new file. Ex. lib/class.rb
+ # branch_name (required) - The name of branch
+ # content (required) - File content
+ # commit_message (required) - Commit message
+ #
+ # Example Request:
+ # POST /projects/:id/repository/files
+ #
+ post ":id/repository/files" do
+ required_attributes! [:file_path, :branch_name, :content, :commit_message]
+ attrs = attributes_for_keys [:file_path, :branch_name, :content, :commit_message, :encoding]
+ branch_name = attrs.delete(:branch_name)
+ file_path = attrs.delete(:file_path)
+ result = ::Files::CreateService.new(user_project, current_user, attrs, branch_name, file_path).execute
+
+ if result[:status] == :success
+ status(201)
+
+ {
+ file_path: file_path,
+ branch_name: branch_name
+ }
+ else
+ render_api_error!(result[:error], 400)
+ end
+ end
+
+ # Update existing file in repository
+ #
+ # Parameters:
+ # file_path (optional) - The path to file. Ex. lib/class.rb
+ # branch_name (required) - The name of branch
+ # content (required) - File content
+ # commit_message (required) - Commit message
+ #
+ # Example Request:
+ # PUT /projects/:id/repository/files
+ #
+ put ":id/repository/files" do
+ required_attributes! [:file_path, :branch_name, :content, :commit_message]
+ attrs = attributes_for_keys [:file_path, :branch_name, :content, :commit_message, :encoding]
+ branch_name = attrs.delete(:branch_name)
+ file_path = attrs.delete(:file_path)
+ result = ::Files::UpdateService.new(user_project, current_user, attrs, branch_name, file_path).execute
+
+ if result[:status] == :success
+ status(200)
+
+ {
+ file_path: file_path,
+ branch_name: branch_name
+ }
+ else
+ render_api_error!(result[:error], 400)
+ end
+ end
+
+ # Delete existing file in repository
+ #
+ # Parameters:
+ # file_path (optional) - The path to file. Ex. lib/class.rb
+ # branch_name (required) - The name of branch
+ # content (required) - File content
+ # commit_message (required) - Commit message
+ #
+ # Example Request:
+ # DELETE /projects/:id/repository/files
+ #
+ delete ":id/repository/files" do
+ required_attributes! [:file_path, :branch_name, :commit_message]
+ attrs = attributes_for_keys [:file_path, :branch_name, :commit_message]
+ branch_name = attrs.delete(:branch_name)
+ file_path = attrs.delete(:file_path)
+ result = ::Files::DeleteService.new(user_project, current_user, attrs, branch_name, file_path).execute
+
+ if result[:status] == :success
+ status(200)
+
+ {
+ file_path: file_path,
+ branch_name: branch_name
+ }
+ else
+ render_api_error!(result[:error], 400)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/api/groups.rb b/lib/api/groups.rb
index 265417fd6bc..03f027706de 100644
--- a/lib/api/groups.rb
+++ b/lib/api/groups.rb
@@ -66,7 +66,6 @@ module API
present group, with: Entities::GroupDetail
end
-
# Remove group
#
# Parameters:
@@ -122,11 +121,11 @@ module API
render_api_error!("Wrong access level", 422)
end
group = find_group(params[:id])
- if group.users_groups.find_by_user_id(params[:user_id])
+ if group.users_groups.find_by(user_id: params[:user_id])
render_api_error!("Already exists", 409)
end
group.add_users([params[:user_id]], params[:access_level])
- member = group.users_groups.find_by_user_id(params[:user_id])
+ member = group.users_groups.find_by(user_id: params[:user_id])
present member.user, with: Entities::GroupMember, group: group
end
@@ -140,7 +139,7 @@ module API
# DELETE /groups/:id/members/:user_id
delete ":id/members/:user_id" do
group = find_group(params[:id])
- member = group.users_groups.find_by_user_id(params[:user_id])
+ member = group.users_groups.find_by(user_id: params[:user_id])
if member.nil?
render_api_error!("404 Not Found - user_id:#{params[:user_id]} not a member of group #{group.name}",404)
else
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index 2b0c672c7fa..f8c48e2f3b2 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -6,23 +6,23 @@ module API
SUDO_PARAM = :sudo
def current_user
- @current_user ||= User.find_by_authentication_token(params[PRIVATE_TOKEN_PARAM] || env[PRIVATE_TOKEN_HEADER])
+ private_token = (params[PRIVATE_TOKEN_PARAM] || env[PRIVATE_TOKEN_HEADER]).to_s
+ @current_user ||= User.find_by(authentication_token: private_token)
identifier = sudo_identifier()
+
# If the sudo is the current user do nothing
if (identifier && !(@current_user.id == identifier || @current_user.username == identifier))
render_api_error!('403 Forbidden: Must be admin to use sudo', 403) unless @current_user.is_admin?
- begin
- @current_user = User.by_username_or_id(identifier)
- rescue => ex
- not_found!("No user id or username for: #{identifier}")
- end
- not_found!("No user id or username for: #{identifier}") if current_user.nil?
+ @current_user = User.by_username_or_id(identifier)
+ not_found!("No user id or username for: #{identifier}") if @current_user.nil?
end
+
@current_user
end
def sudo_identifier()
identifier ||= params[SUDO_PARAM] ||= env[SUDO_HEADER]
+
# Regex for integers
if (!!(identifier =~ /^[0-9]+$/))
identifier.to_i
@@ -31,13 +31,23 @@ module API
end
end
+ def set_current_user_for_thread
+ Thread.current[:current_user] = current_user
+
+ begin
+ yield
+ ensure
+ Thread.current[:current_user] = nil
+ end
+ end
+
def user_project
@project ||= find_project(params[:id])
@project || not_found!
end
def find_project(id)
- project = Project.find_by_id(id) || Project.find_with_namespace(id)
+ project = Project.find_by(id: id) || Project.find_with_namespace(id)
if project && can?(current_user, :read_project, project)
project
diff --git a/lib/api/issues.rb b/lib/api/issues.rb
index a15203d1563..3d15c35b8cc 100644
--- a/lib/api/issues.rb
+++ b/lib/api/issues.rb
@@ -2,7 +2,6 @@ module API
# Issues API
class Issues < Grape::API
before { authenticate! }
- before { Thread.current[:current_user] = current_user }
resource :issues do
# Get currently authenticated user's issues
@@ -49,15 +48,17 @@ module API
# Example Request:
# POST /projects/:id/issues
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?
- @issue = user_project.issues.new attrs
- @issue.author = current_user
- if @issue.save
- present @issue, with: Entities::Issue
- else
- not_found!
+ set_current_user_for_thread do
+ required_attributes! [:title]
+ attrs = attributes_for_keys [:title, :description, :assignee_id, :milestone_id]
+ attrs[:label_list] = params[:labels] if params[:labels].present?
+ @issue = user_project.issues.new attrs
+ @issue.author = current_user
+ if @issue.save
+ present @issue, with: Entities::Issue
+ else
+ not_found!
+ end
end
end
@@ -75,16 +76,18 @@ module API
# Example Request:
# PUT /projects/:id/issues/:issue_id
put ":id/issues/:issue_id" do
- @issue = user_project.issues.find(params[:issue_id])
- authorize! :modify_issue, @issue
+ set_current_user_for_thread 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?
+ attrs = attributes_for_keys [:title, :description, :assignee_id, :milestone_id, :state_event]
+ attrs[:label_list] = params[:labels] if params[:labels].present?
- if @issue.update_attributes attrs
- present @issue, with: Entities::Issue
- else
- not_found!
+ if @issue.update_attributes attrs
+ present @issue, with: Entities::Issue
+ else
+ not_found!
+ end
end
end
diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb
index d690f1d07e7..0f62cac9a0c 100644
--- a/lib/api/merge_requests.rb
+++ b/lib/api/merge_requests.rb
@@ -2,7 +2,6 @@ module API
# MergeRequest API
class MergeRequests < Grape::API
before { authenticate! }
- before { Thread.current[:current_user] = current_user }
resource :projects do
helpers do
@@ -70,28 +69,29 @@ module API
# POST /projects/:id/merge_requests
#
post ":id/merge_requests" do
- 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]
- merge_request = user_project.merge_requests.new(attrs)
- merge_request.author = current_user
- merge_request.source_project = user_project
- target_project_id = attrs[:target_project_id]
- if not_fork?(target_project_id, user_project)
- merge_request.target_project = user_project
- else
- if target_matches_fork(target_project_id,user_project)
- merge_request.target_project = Project.find_by_id(attrs[:target_project_id])
+ set_current_user_for_thread do
+ 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]
+ merge_request = user_project.merge_requests.new(attrs)
+ merge_request.author = current_user
+ merge_request.source_project = user_project
+ target_project_id = attrs[:target_project_id]
+ if not_fork?(target_project_id, user_project)
+ merge_request.target_project = user_project
else
- render_api_error!('(Bad Request) Specified target project that is not the source project, or the source fork of the project.', 400)
+ if target_matches_fork(target_project_id,user_project)
+ merge_request.target_project = Project.find_by(id: attrs[:target_project_id])
+ else
+ render_api_error!('(Bad Request) Specified target project that is not the source project, or the source fork of the project.', 400)
+ end
end
- end
- if merge_request.save
- merge_request.reload_code
- present merge_request, with: Entities::MergeRequest
- else
- handle_merge_request_errors! merge_request.errors
+ if merge_request.save
+ present merge_request, with: Entities::MergeRequest
+ else
+ handle_merge_request_errors! merge_request.errors
+ end
end
end
@@ -109,17 +109,19 @@ module API
# PUT /projects/:id/merge_request/:merge_request_id
#
put ":id/merge_request/:merge_request_id" do
- attrs = attributes_for_keys [:source_branch, :target_branch, :assignee_id, :title, :state_event]
- merge_request = user_project.merge_requests.find(params[:merge_request_id])
+ set_current_user_for_thread do
+ attrs = attributes_for_keys [:source_branch, :target_branch, :assignee_id, :title, :state_event]
+ merge_request = user_project.merge_requests.find(params[:merge_request_id])
- authorize! :modify_merge_request, merge_request
+ authorize! :modify_merge_request, merge_request
- if merge_request.update_attributes attrs
- merge_request.reload_code
- merge_request.mark_as_unchecked
- present merge_request, with: Entities::MergeRequest
- else
- handle_merge_request_errors! merge_request.errors
+ if merge_request.update_attributes attrs
+ merge_request.reload_code
+ merge_request.mark_as_unchecked
+ present merge_request, with: Entities::MergeRequest
+ else
+ handle_merge_request_errors! merge_request.errors
+ end
end
end
@@ -133,16 +135,18 @@ module API
# POST /projects/:id/merge_request/:merge_request_id/comments
#
post ":id/merge_request/:merge_request_id/comments" do
- required_attributes! [:note]
+ set_current_user_for_thread do
+ required_attributes! [:note]
- merge_request = user_project.merge_requests.find(params[:merge_request_id])
- note = merge_request.notes.new(note: params[:note], project_id: user_project.id)
- note.author = current_user
+ merge_request = user_project.merge_requests.find(params[:merge_request_id])
+ note = merge_request.notes.new(note: params[:note], project_id: user_project.id)
+ note.author = current_user
- if note.save
- present note, with: Entities::MRNote
- else
- not_found!
+ if note.save
+ present note, with: Entities::MRNote
+ else
+ not_found!
+ end
end
end
diff --git a/lib/api/milestones.rb b/lib/api/milestones.rb
index aee12e7dc40..f7e63b23093 100644
--- a/lib/api/milestones.rb
+++ b/lib/api/milestones.rb
@@ -40,15 +40,17 @@ module API
# Example Request:
# POST /projects/:id/milestones
post ":id/milestones" do
- authorize! :admin_milestone, user_project
- required_attributes! [:title]
+ set_current_user_for_thread do
+ authorize! :admin_milestone, user_project
+ required_attributes! [:title]
- attrs = attributes_for_keys [:title, :description, :due_date]
- @milestone = user_project.milestones.new attrs
- if @milestone.save
- present @milestone, with: Entities::Milestone
- else
- not_found!
+ attrs = attributes_for_keys [:title, :description, :due_date]
+ @milestone = user_project.milestones.new attrs
+ if @milestone.save
+ present @milestone, with: Entities::Milestone
+ else
+ not_found!
+ end
end
end
@@ -64,14 +66,16 @@ module API
# Example Request:
# PUT /projects/:id/milestones/:milestone_id
put ":id/milestones/:milestone_id" do
- authorize! :admin_milestone, user_project
+ set_current_user_for_thread do
+ authorize! :admin_milestone, user_project
- @milestone = user_project.milestones.find(params[:milestone_id])
- attrs = attributes_for_keys [:title, :description, :due_date, :state_event]
- if @milestone.update_attributes attrs
- present @milestone, with: Entities::Milestone
- else
- not_found!
+ @milestone = user_project.milestones.find(params[:milestone_id])
+ attrs = attributes_for_keys [:title, :description, :due_date, :state_event]
+ if @milestone.update_attributes attrs
+ present @milestone, with: Entities::Milestone
+ else
+ not_found!
+ end
end
end
end
diff --git a/lib/api/namespaces.rb b/lib/api/namespaces.rb
new file mode 100644
index 00000000000..f9f2ed90ccc
--- /dev/null
+++ b/lib/api/namespaces.rb
@@ -0,0 +1,23 @@
+module API
+ # namespaces API
+ class Namespaces < Grape::API
+ before {
+ authenticate!
+ authenticated_as_admin!
+ }
+
+ resource :namespaces do
+ # Get a namespaces list
+ #
+ # Example Request:
+ # GET /namespaces
+ get do
+ @namespaces = Namespace.all
+ @namespaces = @namespaces.search(params[:search]) if params[:search].present?
+ @namespaces = paginate @namespaces
+
+ present @namespaces, with: Entities::Namespace
+ end
+ end
+ end
+end
diff --git a/lib/api/notes.rb b/lib/api/notes.rb
index cb2bc764476..f21907b1ffc 100644
--- a/lib/api/notes.rb
+++ b/lib/api/notes.rb
@@ -41,17 +41,19 @@ module API
# Example Request:
# POST /projects/:id/notes
post ":id/notes" do
- required_attributes! [:body]
+ set_current_user_for_thread do
+ required_attributes! [:body]
- @note = user_project.notes.new(note: params[:body])
- @note.author = current_user
+ @note = user_project.notes.new(note: params[:body])
+ @note.author = current_user
- if @note.save
- present @note, with: Entities::Note
- else
- # :note is exposed as :body, but :note is set on error
- bad_request!(:note) if @note.errors[:note].any?
- not_found!
+ if @note.save
+ present @note, with: Entities::Note
+ else
+ # :note is exposed as :body, but :note is set on error
+ bad_request!(:note) if @note.errors[:note].any?
+ not_found!
+ end
end
end
@@ -97,17 +99,19 @@ module API
# POST /projects/:id/issues/:noteable_id/notes
# POST /projects/:id/snippets/:noteable_id/notes
post ":id/#{noteables_str}/:#{noteable_id_str}/notes" do
- required_attributes! [:body]
+ set_current_user_for_thread do
+ required_attributes! [:body]
- @noteable = user_project.send(:"#{noteables_str}").find(params[:"#{noteable_id_str}"])
- @note = @noteable.notes.new(note: params[:body])
- @note.author = current_user
- @note.project = user_project
+ @noteable = user_project.send(:"#{noteables_str}").find(params[:"#{noteable_id_str}"])
+ @note = @noteable.notes.new(note: params[:body])
+ @note.author = current_user
+ @note.project = user_project
- if @note.save
- present @note, with: Entities::Note
- else
- not_found!
+ if @note.save
+ present @note, with: Entities::Note
+ else
+ not_found!
+ end
end
end
end
diff --git a/lib/api/project_hooks.rb b/lib/api/project_hooks.rb
index 738974955f3..c271dd8b61b 100644
--- a/lib/api/project_hooks.rb
+++ b/lib/api/project_hooks.rb
@@ -22,7 +22,7 @@ module API
# GET /projects/:id/hooks
get ":id/hooks" do
@hooks = paginate user_project.hooks
- present @hooks, with: Entities::Hook
+ present @hooks, with: Entities::ProjectHook
end
# Get a project hook
@@ -34,7 +34,7 @@ module API
# GET /projects/:id/hooks/:hook_id
get ":id/hooks/:hook_id" do
@hook = user_project.hooks.find(params[:hook_id])
- present @hook, with: Entities::Hook
+ present @hook, with: Entities::ProjectHook
end
@@ -47,10 +47,11 @@ module API
# POST /projects/:id/hooks
post ":id/hooks" do
required_attributes! [:url]
+ attrs = attributes_for_keys [:url, :push_events, :issues_events, :merge_requests_events]
+ @hook = user_project.hooks.new(attrs)
- @hook = user_project.hooks.new({"url" => params[:url]})
if @hook.save
- present @hook, with: Entities::Hook
+ present @hook, with: Entities::ProjectHook
else
if @hook.errors[:url].present?
error!("Invalid url given", 422)
@@ -70,10 +71,10 @@ module API
put ":id/hooks/:hook_id" do
@hook = user_project.hooks.find(params[:hook_id])
required_attributes! [:url]
+ attrs = attributes_for_keys [:url, :push_events, :issues_events, :merge_requests_events]
- attrs = attributes_for_keys [:url]
if @hook.update_attributes attrs
- present @hook, with: Entities::Hook
+ present @hook, with: Entities::ProjectHook
else
if @hook.errors[:url].present?
error!("Invalid url given", 422)
diff --git a/lib/api/project_snippets.rb b/lib/api/project_snippets.rb
index bee6544ea3d..8e09fff6843 100644
--- a/lib/api/project_snippets.rb
+++ b/lib/api/project_snippets.rb
@@ -41,7 +41,6 @@ module API
# id (required) - The ID of a project
# title (required) - The title of a snippet
# file_name (required) - The name of a snippet file
- # lifetime (optional) - The expiration date of a snippet
# code (required) - The content of a snippet
# Example Request:
# POST /projects/:id/snippets
@@ -50,7 +49,6 @@ module API
required_attributes! [:title, :file_name, :code]
attrs = attributes_for_keys [:title, :file_name]
- attrs[:expires_at] = params[:lifetime] if params[:lifetime].present?
attrs[:content] = params[:code] if params[:code].present?
@snippet = user_project.snippets.new attrs
@snippet.author = current_user
@@ -69,7 +67,6 @@ module API
# snippet_id (required) - The ID of a project snippet
# title (optional) - The title of a snippet
# file_name (optional) - The name of a snippet file
- # lifetime (optional) - The expiration date of a snippet
# code (optional) - The content of a snippet
# Example Request:
# PUT /projects/:id/snippets/:snippet_id
@@ -78,7 +75,6 @@ module API
authorize! :modify_project_snippet, @snippet
attrs = attributes_for_keys [:title, :file_name]
- attrs[:expires_at] = params[:lifetime] if params[:lifetime].present?
attrs[:content] = params[:code] if params[:code].present?
if @snippet.update_attributes attrs
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index cf357b23c40..888aa7e77d2 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -11,6 +11,13 @@ module API
end
not_found!
end
+
+ def map_public_to_visibility_level(attrs)
+ publik = attrs.delete(:public)
+ publik = [ true, 1, '1', 't', 'T', 'true', 'TRUE', 'on', 'ON' ].include?(publik)
+ attrs[:visibility_level] = Gitlab::VisibilityLevel::PUBLIC if !attrs[:visibility_level].present? && publik == true
+ attrs
+ end
end
# Get a projects list for authenticated user
@@ -31,6 +38,16 @@ module API
present @projects, with: Entities::Project
end
+ # Get all projects for admin user
+ #
+ # Example Request:
+ # GET /projects/all
+ get '/all' do
+ authenticated_as_admin!
+ @projects = paginate Project
+ present @projects, with: Entities::Project
+ end
+
# Get a single project
#
# Parameters:
@@ -60,14 +77,14 @@ module API
# Parameters:
# name (required) - name for new project
# description (optional) - short project description
- # default_branch (optional) - 'master' by default
# issues_enabled (optional)
# wall_enabled (optional)
# merge_requests_enabled (optional)
# wiki_enabled (optional)
# snippets_enabled (optional)
# namespace_id (optional) - defaults to user namespace
- # public (optional) - false by default
+ # public (optional) - if true same as setting visibility_level = 20
+ # visibility_level (optional) - 0 by default
# Example Request
# POST /projects
post do
@@ -75,15 +92,17 @@ module API
attrs = attributes_for_keys [:name,
:path,
:description,
- :default_branch,
:issues_enabled,
:wall_enabled,
:merge_requests_enabled,
:wiki_enabled,
:snippets_enabled,
:namespace_id,
- :public]
- @project = ::Projects::CreateContext.new(current_user, attrs).execute
+ :public,
+ :visibility_level,
+ :import_url]
+ attrs = map_public_to_visibility_level(attrs)
+ @project = ::Projects::CreateService.new(current_user, attrs).execute
if @project.saved?
present @project, with: Entities::Project
else
@@ -106,7 +125,8 @@ module API
# merge_requests_enabled (optional)
# wiki_enabled (optional)
# snippets_enabled (optional)
- # public (optional)
+ # public (optional) - if true same as setting visibility_level = 20
+ # visibility_level (optional)
# Example Request
# POST /projects/user/:user_id
post "user/:user_id" do
@@ -120,8 +140,10 @@ module API
:merge_requests_enabled,
:wiki_enabled,
:snippets_enabled,
- :public]
- @project = ::Projects::CreateContext.new(user, attrs).execute
+ :public,
+ :visibility_level]
+ attrs = map_public_to_visibility_level(attrs)
+ @project = ::Projects::CreateService.new(user, attrs).execute
if @project.saved?
present @project, with: Entities::Project
else
@@ -129,6 +151,16 @@ module API
end
end
+ # Remove project
+ #
+ # Parameters:
+ # id (required) - The ID of a project
+ # Example Request:
+ # DELETE /projects/:id
+ delete ":id" do
+ authorize! :remove_project, user_project
+ user_project.destroy
+ end
# Mark this project as forked from another
#
@@ -234,7 +266,7 @@ module API
authorize! :admin_project, user_project
required_attributes! [:access_level]
- team_member = user_project.users_projects.find_by_user_id(params[:user_id])
+ team_member = user_project.users_projects.find_by(user_id: params[:user_id])
not_found!("User can not be found") if team_member.nil?
if team_member.update_attributes(project_access: params[:access_level])
@@ -254,7 +286,7 @@ module API
# DELETE /projects/:id/members/:user_id
delete ":id/members/:user_id" do
authorize! :admin_project, user_project
- team_member = user_project.users_projects.find_by_user_id(params[:user_id])
+ team_member = user_project.users_projects.find_by(user_id: params[:user_id])
unless team_member.nil?
team_member.destroy
else
@@ -272,7 +304,8 @@ module API
# GET /projects/search/:query
get "/search/:query" do
ids = current_user.authorized_projects.map(&:id)
- projects = Project.where("(id in (?) OR public = true) AND (name LIKE (?))", ids, "%#{params[:query]}%")
+ visibility_levels = [ Gitlab::VisibilityLevel::INTERNAL, Gitlab::VisibilityLevel::PUBLIC ]
+ projects = Project.where("(id in (?) OR visibility_level in (?)) AND (name LIKE (?))", ids, visibility_levels, "%#{params[:query]}%")
present paginate(projects), with: Entities::Project
end
end
diff --git a/lib/api/repositories.rb b/lib/api/repositories.rb
index 1a911eae2bb..cad64760abb 100644
--- a/lib/api/repositories.rb
+++ b/lib/api/repositories.rb
@@ -1,3 +1,5 @@
+require 'mime/types'
+
module API
# Projects API
class Repositories < Grape::API
@@ -49,7 +51,7 @@ module API
@branch = user_project.repository.find_branch(params[:branch])
not_found! unless @branch
- protected_branch = user_project.protected_branches.find_by_name(@branch.name)
+ protected_branch = user_project.protected_branches.find_by(name: @branch.name)
user_project.protected_branches.create(name: @branch.name) unless protected_branch
present @branch, with: Entities::RepoObject, project: user_project
@@ -67,7 +69,7 @@ module API
@branch = user_project.repository.find_branch(params[:branch])
not_found! unless @branch
- protected_branch = user_project.protected_branches.find_by_name(@branch.name)
+ protected_branch = user_project.protected_branches.find_by(name: @branch.name)
protected_branch.destroy if protected_branch
present @branch, with: Entities::RepoObject, project: user_project
@@ -80,7 +82,7 @@ module API
# Example Request:
# GET /projects/:id/repository/tags
get ":id/repository/tags" do
- present user_project.repo.tags.sort_by(&:name).reverse, with: Entities::RepoObject
+ present user_project.repo.tags.sort_by(&:name).reverse, with: Entities::RepoObject, project: user_project
end
# Get a project repository commits
@@ -110,7 +112,7 @@ module API
sha = params[:sha]
commit = user_project.repository.commit(sha)
not_found! "Commit" unless commit
- present commit, with: Entities::RepoCommit
+ present commit, with: Entities::RepoCommitDetail
end
# Get the diff for a specific commit of a project
@@ -122,9 +124,9 @@ module API
# GET /projects/:id/repository/commits/:sha/diff
get ":id/repository/commits/:sha/diff" do
sha = params[:sha]
- result = CommitLoadContext.new(user_project, current_user, {id: sha}).execute
- not_found! "Commit" unless result[:commit]
- result[:commit].diffs
+ commit = user_project.repository.commit(sha)
+ not_found! "Commit" unless commit
+ commit.diffs
end
# Get a project repository tree
@@ -139,15 +141,9 @@ module API
path = params[:path] || nil
commit = user_project.repository.commit(ref)
- tree = Tree.new(user_project.repository, commit.id, path)
-
- trees = []
-
- %w(trees blobs submodules).each do |type|
- trees += tree.send(type).map { |t| { name: t.name, type: type.singularize, mode: t.mode, id: t.id } }
- end
+ tree = user_project.repository.tree(commit.id, path)
- trees
+ present tree.sorted_entries, with: Entities::RepoTreeObject
end
# Get a raw file contents
@@ -176,7 +172,58 @@ module API
content_type blob.mime_type
present blob.data
end
+
+ # Get a raw blob contents by blob sha
+ #
+ # Parameters:
+ # id (required) - The ID of a project
+ # sha (required) - The blob's sha
+ # Example Request:
+ # GET /projects/:id/repository/raw_blobs/:sha
+ get ":id/repository/raw_blobs/:sha" do
+ ref = params[:sha]
+
+ repo = user_project.repository
+
+ blob = Gitlab::Git::Blob.raw(repo, ref)
+
+ not_found! "Blob" unless blob
+
+ env['api.format'] = :txt
+
+ content_type blob.mime_type
+ present blob.data
+ end
+
+ # Get a an archive of the repository
+ #
+ # Parameters:
+ # id (required) - The ID of a project
+ # sha (optional) - the commit sha to download defaults to the tip of the default branch
+ # Example Request:
+ # 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 = Rails.root.join("tmp", "repositories")
+
+ 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!
+ end
+ end
end
end
end
-
diff --git a/lib/api/services.rb b/lib/api/services.rb
new file mode 100644
index 00000000000..bde502e32e1
--- /dev/null
+++ b/lib/api/services.rb
@@ -0,0 +1,44 @@
+module API
+ # Projects API
+ class Services < Grape::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
+ #
+ # 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/keys/:id
+ 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
+ end
+ end
+end
+
diff --git a/lib/api/users.rb b/lib/api/users.rb
index 54d3aeecb70..ae808b6272b 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -9,7 +9,7 @@ module API
# Example Request:
# GET /users
get do
- @users = User.scoped
+ @users = User.all
@users = @users.active if params[:active].present?
@users = @users.search(params[:search]) if params[:search].present?
@users = paginate @users
@@ -36,6 +36,7 @@ module API
# skype - Skype ID
# linkedin - Linkedin
# twitter - Twitter account
+ # website_url - Website url
# projects_limit - Number of projects user can create
# extern_uid - External authentication provider UID
# provider - External provider
@@ -67,6 +68,7 @@ module API
# skype - Skype ID
# linkedin - Linkedin
# twitter - Twitter account
+ # website_url - Website url
# projects_limit - Limit projects each user can create
# extern_uid - External authentication provider UID
# provider - External provider
@@ -78,7 +80,7 @@ module API
put ":id" do
authenticated_as_admin!
- attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :extern_uid, :provider, :bio, :can_create_group, :admin]
+ attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :website_url, :projects_limit, :username, :extern_uid, :provider, :bio, :can_create_group, :admin]
user = User.find(params[:id])
not_found!("User not found") unless user
@@ -117,7 +119,7 @@ module API
# DELETE /users/:id
delete ":id" do
authenticated_as_admin!
- user = User.find_by_id(params[:id])
+ user = User.find_by(id: params[:id])
if user
user.destroy
diff --git a/lib/backup/database.rb b/lib/backup/database.rb
index c4fb2e2e159..ebb4f289c52 100644
--- a/lib/backup/database.rb
+++ b/lib/backup/database.rb
@@ -11,23 +11,29 @@ module Backup
end
def dump
- case config["adapter"]
+ success = case config["adapter"]
when /^mysql/ then
- system("mysqldump #{mysql_args} #{config['database']} > #{db_file_name}")
+ print "Dumping MySQL database #{config['database']} ... "
+ system('mysqldump', *mysql_args, config['database'], out: db_file_name)
when "postgresql" then
+ print "Dumping PostgreSQL database #{config['database']} ... "
pg_env
- system("pg_dump #{config['database']} > #{db_file_name}")
+ system('pg_dump', config['database'], out: db_file_name)
end
+ report_success(success)
end
def restore
- case config["adapter"]
+ success = case config["adapter"]
when /^mysql/ then
- system("mysql #{mysql_args} #{config['database']} < #{db_file_name}")
+ print "Restoring MySQL database #{config['database']} ... "
+ system('mysql', *mysql_args, config['database'], in: db_file_name)
when "postgresql" then
+ print "Restoring PostgreSQL database #{config['database']} ... "
pg_env
- system("psql #{config['database']} -f #{db_file_name}")
+ system('psql', config['database'], '-f', db_file_name)
end
+ report_success(success)
end
protected
@@ -45,7 +51,7 @@ module Backup
'encoding' => '--default-character-set',
'password' => '--password'
}
- args.map { |opt, arg| "#{arg}='#{config[opt]}'" if config[opt] }.compact.join(' ')
+ args.map { |opt, arg| "#{arg}=#{config[opt]}" if config[opt] }.compact
end
def pg_env
@@ -54,5 +60,13 @@ module Backup
ENV['PGPORT'] = config["port"].to_s if config["port"]
ENV['PGPASSWORD'] = config["password"].to_s if config["password"]
end
+
+ def report_success(success)
+ if success
+ puts '[DONE]'.green
+ else
+ puts '[FAILED]'.red
+ end
+ end
end
end
diff --git a/lib/backup/manager.rb b/lib/backup/manager.rb
index 258a0fb2589..efaefa4ce44 100644
--- a/lib/backup/manager.rb
+++ b/lib/backup/manager.rb
@@ -1,5 +1,7 @@
module Backup
class Manager
+ BACKUP_CONTENTS = %w{repositories/ db/ uploads/ backup_information.yml}
+
def pack
# saving additional informations
s = {}
@@ -16,7 +18,7 @@ module Backup
# create archive
print "Creating backup archive: #{s[:backup_created_at].to_i}_gitlab_backup.tar ... "
- if Kernel.system("tar -cf #{s[:backup_created_at].to_i}_gitlab_backup.tar repositories/ db/ uploads/ backup_information.yml")
+ if Kernel.system('tar', '-cf', "#{s[:backup_created_at].to_i}_gitlab_backup.tar", *BACKUP_CONTENTS)
puts "done".green
else
puts "failed".red
@@ -25,7 +27,7 @@ module Backup
def cleanup
print "Deleting tmp directories ... "
- if Kernel.system("rm -rf repositories/ db/ uploads/ backup_information.yml")
+ if Kernel.system('rm', '-rf', *BACKUP_CONTENTS)
puts "done".green
else
puts "failed".red
@@ -44,7 +46,7 @@ module Backup
file_list.map! { |f| $1.to_i if f =~ /(\d+)_gitlab_backup.tar/ }
file_list.sort.each do |timestamp|
if Time.at(timestamp) < (Time.now - keep_time)
- if system("rm #{timestamp}_gitlab_backup.tar")
+ if Kernel.system(*%W(rm #{timestamp}_gitlab_backup.tar))
removed += 1
end
end
@@ -75,7 +77,7 @@ module Backup
end
print "Unpacking backup ... "
- unless Kernel.system("tar -xf #{tar_file}")
+ unless Kernel.system(*%W(tar -xf #{tar_file}))
puts "failed".red
exit 1
else
diff --git a/lib/backup/repository.rb b/lib/backup/repository.rb
index c5e3d049fd7..20fd5ba92a1 100644
--- a/lib/backup/repository.rb
+++ b/lib/backup/repository.rb
@@ -18,7 +18,7 @@ module Backup
# Create namespace dir if missing
FileUtils.mkdir_p(File.join(backup_repos_path, project.namespace.path)) if project.namespace
- if system("cd #{path_to_repo(project)} > /dev/null 2>&1 && git bundle create #{path_to_bundle(project)} --all > /dev/null 2>&1")
+ if system(*%W(git --git-dir=#{path_to_repo(project)} bundle create #{path_to_bundle(project)} --all), silent)
puts "[DONE]".green
else
puts "[FAILED]".red
@@ -28,7 +28,9 @@ module Backup
if File.exists?(path_to_repo(wiki))
print " * #{wiki.path_with_namespace} ... "
- if system("cd #{path_to_repo(wiki)} > /dev/null 2>&1 && git bundle create #{path_to_bundle(wiki)} --all > /dev/null 2>&1")
+ if wiki.empty?
+ puts " [SKIPPED]".cyan
+ elsif system(*%W(git --git-dir=#{path_to_repo(wiki)} bundle create #{path_to_bundle(wiki)} --all), silent)
puts " [DONE]".green
else
puts " [FAILED]".red
@@ -51,7 +53,7 @@ module Backup
project.namespace.ensure_dir_exist if project.namespace
- if system("git clone --bare #{path_to_bundle(project)} #{path_to_repo(project)} > /dev/null 2>&1")
+ if system(*%W(git clone --bare #{path_to_bundle(project)} #{path_to_repo(project)}), silent)
puts "[DONE]".green
else
puts "[FAILED]".red
@@ -61,7 +63,7 @@ module Backup
if File.exists?(path_to_bundle(wiki))
print " * #{wiki.path_with_namespace} ... "
- if system("git clone --bare #{path_to_bundle(wiki)} #{path_to_repo(wiki)} > /dev/null 2>&1")
+ if system(*%W(git clone --bare #{path_to_bundle(wiki)} #{path_to_repo(wiki)}), silent)
puts " [DONE]".green
else
puts " [FAILED]".red
@@ -71,7 +73,7 @@ module Backup
print 'Put GitLab hooks in repositories dirs'.yellow
gitlab_shell_user_home = File.expand_path("~#{Gitlab.config.gitlab_shell.ssh_user}")
- if system("#{gitlab_shell_user_home}/gitlab-shell/support/rewrite-hooks.sh #{Gitlab.config.gitlab_shell.repos_path}")
+ if system("#{gitlab_shell_user_home}/gitlab-shell/support/rewrite-hooks.sh", Gitlab.config.gitlab_shell.repos_path)
puts " [DONE]".green
else
puts " [FAILED]".red
@@ -101,5 +103,9 @@ module Backup
FileUtils.rm_rf(backup_repos_path)
FileUtils.mkdir_p(backup_repos_path)
end
+
+ def silent
+ {err: '/dev/null', out: '/dev/null'}
+ end
end
end
diff --git a/lib/backup/uploads.rb b/lib/backup/uploads.rb
index 462d3f1e274..e79da7e8fd2 100644
--- a/lib/backup/uploads.rb
+++ b/lib/backup/uploads.rb
@@ -19,7 +19,7 @@ module Backup
FileUtils.cp_r(backup_uploads_dir, app_uploads_dir)
end
-
+
def backup_existing_uploads_dir
if File.exists?(app_uploads_dir)
FileUtils.mv(app_uploads_dir, Rails.root.join('public', "uploads.#{Time.now.to_i}"))
diff --git a/lib/extracts_path.rb b/lib/extracts_path.rb
index 6e7872dcd03..e51cb30bdd9 100644
--- a/lib/extracts_path.rb
+++ b/lib/extracts_path.rb
@@ -117,7 +117,7 @@ module ExtractsPath
end
def tree
- @tree ||= Tree.new(@repo, @commit.id, @path)
+ @tree ||= @repo.tree(@commit.id, @path)
end
private
diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb
index 0f196297477..955abc1bedd 100644
--- a/lib/gitlab/auth.rb
+++ b/lib/gitlab/auth.rb
@@ -1,7 +1,7 @@
module Gitlab
class Auth
def find(login, password)
- user = User.find_by_email(login) || User.find_by_username(login)
+ user = User.find_by(email: login) || User.find_by(username: login)
if user.nil? || user.ldap_user?
# Second chance - try LDAP authentication
diff --git a/lib/gitlab/backend/grack_auth.rb b/lib/gitlab/backend/grack_auth.rb
index c522e0a413b..60c03ce1c04 100644
--- a/lib/gitlab/backend/grack_auth.rb
+++ b/lib/gitlab/backend/grack_auth.rb
@@ -38,6 +38,16 @@ module Grack
# Authentication with username and password
login, password = @auth.credentials
+ # Allow authentication for GitLab CI service
+ # if valid token passed
+ if login == "gitlab-ci-token" && project.gitlab_ci?
+ token = project.gitlab_ci_service.token
+
+ if token.present? && token == password && service_name == 'git-upload-pack'
+ return @app.call(env)
+ end
+ end
+
@user = authenticate_user(login, password)
if @user
@@ -48,7 +58,7 @@ module Grack
end
else
- return unauthorized unless project.public
+ return unauthorized unless project.public?
end
if authorized_git_request?
@@ -59,14 +69,7 @@ module Grack
end
def authorized_git_request?
- # Git upload and receive
- if @request.get?
- authorize_request(@request.params['service'])
- elsif @request.post?
- authorize_request(File.basename(@request.path))
- else
- false
- end
+ authorize_request(service_name)
end
def authenticate_user(login, password)
@@ -77,29 +80,46 @@ module Grack
def authorize_request(service)
case service
when 'git-upload-pack'
- project.public || can?(user, :download_code, project)
+ can?(user, :download_code, project)
when'git-receive-pack'
- action = if project.protected_branch?(ref)
- :push_code_to_protected_branches
- else
- :push_code
- end
+ refs.each do |ref|
+ action = if project.protected_branch?(ref)
+ :push_code_to_protected_branches
+ else
+ :push_code
+ end
+
+ return false unless can?(user, action, project)
+ end
- can?(user, action, project)
+ # Never let git-receive-pack trough unauthenticated; it's
+ # harmless but git < 1.8 doesn't like it
+ return false if user.nil?
+ true
else
false
end
end
+ def service_name
+ if @request.get?
+ @request.params['service']
+ elsif @request.post?
+ File.basename(@request.path)
+ else
+ nil
+ end
+ end
+
def project
@project ||= project_by_path(@request.path_info)
end
- def ref
- @ref ||= parse_ref
+ def refs
+ @refs ||= parse_refs
end
- def parse_ref
+ def parse_refs
input = if @env["HTTP_CONTENT_ENCODING"] =~ /gzip/
Zlib::GzipReader.new(@request.body).read
else
@@ -108,7 +128,15 @@ module Grack
# Need to reset seek point
@request.body.rewind
- /refs\/heads\/([\/\w\.-]+)/n.match(input.force_encoding('ascii-8bit')).to_a.last
+
+ # Parse refs
+ refs = input.force_encoding('ascii-8bit').scan(/refs\/heads\/([\/\w\.-]+)/n).flatten.compact
+
+ # Cleanup grabare from refs
+ # if push to multiple branches
+ refs.map do |ref|
+ ref.gsub(/00.*/, "")
+ end
end
end
end
diff --git a/lib/gitlab/backend/grack_helpers.rb b/lib/gitlab/backend/grack_helpers.rb
index 5ac9e9f325b..cb747fe0137 100644
--- a/lib/gitlab/backend/grack_helpers.rb
+++ b/lib/gitlab/backend/grack_helpers.rb
@@ -1,7 +1,7 @@
module Grack
module Helpers
def project_by_path(path)
- if m = /^\/([\w\.\/-]+)\.git/.match(path).to_a
+ if m = /^([\w\.\/-]+)\.git/.match(path).to_a
path_with_namespace = m.last
path_with_namespace.gsub!(/\.wiki$/, '')
diff --git a/lib/gitlab/backend/shell.rb b/lib/gitlab/backend/shell.rb
index c819ce56ac9..7121c8e40d2 100644
--- a/lib/gitlab/backend/shell.rb
+++ b/lib/gitlab/backend/shell.rb
@@ -10,7 +10,7 @@ module Gitlab
# add_repository("gitlab/gitlab-ci")
#
def add_repository(name)
- system "#{gitlab_shell_user_home}/gitlab-shell/bin/gitlab-projects", "add-project", "#{name}.git"
+ system "#{gitlab_shell_path}/bin/gitlab-projects", "add-project", "#{name}.git"
end
# Import repository
@@ -21,7 +21,7 @@ module Gitlab
# import_repository("gitlab/gitlab-ci", "https://github.com/randx/six.git")
#
def import_repository(name, url)
- system "#{gitlab_shell_user_home}/gitlab-shell/bin/gitlab-projects", "import-project", "#{name}.git", url
+ system "#{gitlab_shell_path}/bin/gitlab-projects", "import-project", "#{name}.git", url
end
# Move repository
@@ -33,7 +33,7 @@ module Gitlab
# mv_repository("gitlab/gitlab-ci", "randx/gitlab-ci-new.git")
#
def mv_repository(path, new_path)
- system "#{gitlab_shell_user_home}/gitlab-shell/bin/gitlab-projects", "mv-project", "#{path}.git", "#{new_path}.git"
+ system "#{gitlab_shell_path}/bin/gitlab-projects", "mv-project", "#{path}.git", "#{new_path}.git"
end
# Update HEAD for repository
@@ -45,7 +45,7 @@ module Gitlab
# update_repository_head("gitlab/gitlab-ci", "3-1-stable")
#
def update_repository_head(path, branch)
- system "#{gitlab_shell_user_home}/gitlab-shell/bin/gitlab-projects", "update-head", "#{path}.git", branch
+ system "#{gitlab_shell_path}/bin/gitlab-projects", "update-head", "#{path}.git", branch
end
# Fork repository to new namespace
@@ -57,7 +57,7 @@ module Gitlab
# fork_repository("gitlab/gitlab-ci", "randx")
#
def fork_repository(path, fork_namespace)
- system "#{gitlab_shell_user_home}/gitlab-shell/bin/gitlab-projects", "fork-project", "#{path}.git", fork_namespace
+ system "#{gitlab_shell_path}/bin/gitlab-projects", "fork-project", "#{path}.git", fork_namespace
end
# Remove repository from file system
@@ -68,7 +68,7 @@ module Gitlab
# remove_repository("gitlab/gitlab-ci")
#
def remove_repository(name)
- system "#{gitlab_shell_user_home}/gitlab-shell/bin/gitlab-projects", "rm-project", "#{name}.git"
+ system "#{gitlab_shell_path}/bin/gitlab-projects", "rm-project", "#{name}.git"
end
# Add repository branch from passed ref
@@ -81,7 +81,7 @@ module Gitlab
# add_branch("gitlab/gitlab-ci", "4-0-stable", "master")
#
def add_branch(path, branch_name, ref)
- system "#{gitlab_shell_user_home}/gitlab-shell/bin/gitlab-projects", "create-branch", "#{path}.git", branch_name, ref
+ system "#{gitlab_shell_path}/bin/gitlab-projects", "create-branch", "#{path}.git", branch_name, ref
end
# Remove repository branch
@@ -93,7 +93,7 @@ module Gitlab
# rm_branch("gitlab/gitlab-ci", "4-0-stable")
#
def rm_branch(path, branch_name)
- system "#{gitlab_shell_user_home}/gitlab-shell/bin/gitlab-projects", "rm-branch", "#{path}.git", branch_name
+ system "#{gitlab_shell_path}/bin/gitlab-projects", "rm-branch", "#{path}.git", branch_name
end
# Add repository tag from passed ref
@@ -106,7 +106,7 @@ module Gitlab
# add_tag("gitlab/gitlab-ci", "v4.0", "master")
#
def add_tag(path, tag_name, ref)
- system "#{gitlab_shell_user_home}/gitlab-shell/bin/gitlab-projects", "create-tag", "#{path}.git", tag_name, ref
+ system "#{gitlab_shell_path}/bin/gitlab-projects", "create-tag", "#{path}.git", tag_name, ref
end
# Remove repository tag
@@ -118,7 +118,7 @@ module Gitlab
# rm_tag("gitlab/gitlab-ci", "v4.0")
#
def rm_tag(path, tag_name)
- system "#{gitlab_shell_user_home}/gitlab-shell/bin/gitlab-projects", "rm-tag", "#{path}.git", tag_name
+ system "#{gitlab_shell_path}/bin/gitlab-projects", "rm-tag", "#{path}.git", tag_name
end
# Add new key to gitlab-shell
@@ -127,7 +127,7 @@ module Gitlab
# add_key("key-42", "sha-rsa ...")
#
def add_key(key_id, key_content)
- system "#{gitlab_shell_user_home}/gitlab-shell/bin/gitlab-keys", "add-key", key_id, key_content
+ system "#{gitlab_shell_path}/bin/gitlab-keys", "add-key", key_id, key_content
end
# Remove ssh key from gitlab shell
@@ -136,7 +136,7 @@ module Gitlab
# remove_key("key-342", "sha-rsa ...")
#
def remove_key(key_id, key_content)
- system "#{gitlab_shell_user_home}/gitlab-shell/bin/gitlab-keys", "rm-key", key_id, key_content
+ system "#{gitlab_shell_path}/bin/gitlab-keys", "rm-key", key_id, key_content
end
# Remove all ssh keys from gitlab shell
@@ -145,7 +145,7 @@ module Gitlab
# remove_all_keys
#
def remove_all_keys
- system "#{gitlab_shell_user_home}/gitlab-shell/bin/gitlab-keys", "clear"
+ system "#{gitlab_shell_path}/bin/gitlab-keys", "clear"
end
# Add empty directory for storing repositories
@@ -196,8 +196,21 @@ module Gitlab
Gitlab.config.gitlab_shell.ssh_path_prefix + "#{path}.git"
end
+ # Return GitLab shell version
+ def version
+ gitlab_shell_version_file = "#{gitlab_shell_path}/VERSION"
+
+ if File.readable?(gitlab_shell_version_file)
+ File.read(gitlab_shell_version_file)
+ end
+ end
+
protected
+ def gitlab_shell_path
+ Gitlab.config.gitlab_shell.path
+ end
+
def gitlab_shell_user_home
File.expand_path("~#{Gitlab.config.gitlab_shell.ssh_user}")
end
diff --git a/lib/gitlab/blacklist.rb b/lib/gitlab/blacklist.rb
index 2f9091e07df..6bc2c3b487c 100644
--- a/lib/gitlab/blacklist.rb
+++ b/lib/gitlab/blacklist.rb
@@ -3,7 +3,7 @@ module Gitlab
extend self
def path
- %w(admin dashboard 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)
end
end
end
diff --git a/lib/gitlab/identifier.rb b/lib/gitlab/identifier.rb
index a1ff248a77f..6e4de197eeb 100644
--- a/lib/gitlab/identifier.rb
+++ b/lib/gitlab/identifier.rb
@@ -6,17 +6,17 @@ module Gitlab
if identifier.blank?
# Local push from gitlab
email = project.repository.commit(newrev).author_email rescue nil
- User.find_by_email(email) if email
+ User.find_by(email: email) if email
elsif identifier =~ /\Auser-\d+\Z/
# git push over http
user_id = identifier.gsub("user-", "")
- User.find_by_id(user_id)
+ User.find_by(id: user_id)
elsif identifier =~ /\Akey-\d+\Z/
# git push over ssh
key_id = identifier.gsub("key-", "")
- Key.find_by_id(key_id).try(:user)
+ Key.find_by(id: key_id).try(:user)
end
end
end
diff --git a/lib/gitlab/ldap/user.rb b/lib/gitlab/ldap/user.rb
index 78fc5dab9cb..fd36dda7d22 100644
--- a/lib/gitlab/ldap/user.rb
+++ b/lib/gitlab/ldap/user.rb
@@ -23,8 +23,8 @@ module Gitlab
# Look for user with same emails
#
# Possible cases:
- # * When user already has account and need to link his LDAP account.
- # * LDAP uid changed for user with same email and we need to update his uid
+ # * 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)
@@ -44,13 +44,13 @@ module Gitlab
end
def find_user(email)
- user = model.find_by_email(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 his email
+ # we look for user by extracting part of their email
if !user && email && ldap_conf['allow_username_or_email_login']
uname = email.partition('@').first
- user = model.find_by_username(uname)
+ user = model.find_by(username: uname)
end
user
@@ -78,7 +78,7 @@ module Gitlab
# * when ldap account was deactivated by change of OU membership in 'dn'
def blocked?(dn)
ldap = OmniAuth::LDAP::Adaptor.new(ldap_conf)
- ldap.connection.search(base: dn, size: 1).blank?
+ ldap.connection.search(base: dn, scope: Net::LDAP::SearchScope_BaseObject, size: 1).blank?
end
private
diff --git a/lib/gitlab/oauth/user.rb b/lib/gitlab/oauth/user.rb
index 1b32b99f4ba..529753c4019 100644
--- a/lib/gitlab/oauth/user.rb
+++ b/lib/gitlab/oauth/user.rb
@@ -28,6 +28,7 @@ module Gitlab
}
user = model.build_user(opts, as: :admin)
+ user.skip_confirmation!
user.save!
log.info "(OAuth) Creating user #{email} from login with extern_uid => #{uid}"
diff --git a/lib/gitlab/regex.rb b/lib/gitlab/regex.rb
index b4be46d3b42..d18fc8bf2ce 100644
--- a/lib/gitlab/regex.rb
+++ b/lib/gitlab/regex.rb
@@ -18,10 +18,38 @@ module Gitlab
default_regex
end
+ def archive_formats_regex
+ #|zip|tar| tar.gz | tar.bz2 |
+ /(zip|tar|tar\.gz|tgz|gz|tar\.bz2|tbz|tbz2|tb2|bz2)/
+ end
+
+ def git_reference_regex
+ # Valid git ref regex, see:
+ # https://www.kernel.org/pub/software/scm/git/docs/git-check-ref-format.html
+
+ %r{
+ (?!
+ (?# doesn't begins with)
+ \/| (?# rule #6)
+ (?# doesn't contain)
+ .*(?:
+ [\/.]\.| (?# rule #1,3)
+ \/\/| (?# rule #6)
+ @\{| (?# rule #8)
+ \\ (?# rule #9)
+ )
+ )
+ [^\000-\040\177~^:?*\[]+ (?# rule #4-5)
+ (?# doesn't end with)
+ (?<!\.lock) (?# rule #1)
+ (?<![\/.]) (?# rule #6-7)
+ }x
+ end
+
protected
def default_regex
- /\A[a-zA-Z0-9][a-zA-Z0-9_\-\.]*\z/
+ /\A[.?]?[a-zA-Z0-9][a-zA-Z0-9_\-\.]*(?<!\.git)\z/
end
end
end
diff --git a/lib/gitlab/satellite/files/delete_file_action.rb b/lib/gitlab/satellite/files/delete_file_action.rb
new file mode 100644
index 00000000000..30462999aa3
--- /dev/null
+++ b/lib/gitlab/satellite/files/delete_file_action.rb
@@ -0,0 +1,50 @@
+require_relative 'file_action'
+
+module Gitlab
+ module Satellite
+ class DeleteFileAction < FileAction
+ # Deletes file and creates a new commit for it
+ #
+ # Returns false if committing the change fails
+ # Returns false if pushing from the satellite to bare repo failed or was rejected
+ # Returns true otherwise
+ def commit!(content, commit_message)
+ in_locked_and_timed_satellite do |repo|
+ prepare_satellite!(repo)
+
+ # create target branch in satellite at the corresponding commit from bare repo
+ repo.git.checkout({raise: true, timeout: true, b: true}, ref, "origin/#{ref}")
+
+ # update the file in the satellite's working dir
+ file_path_in_satellite = File.join(repo.working_dir, file_path)
+
+ # Prevent relative links
+ unless safe_path?(file_path_in_satellite)
+ Gitlab::GitLogger.error("FileAction: Relative path not allowed")
+ return false
+ end
+
+ File.delete(file_path_in_satellite)
+
+ # add removed file
+ repo.remove(file_path_in_satellite)
+
+ # commit the changes
+ # will raise CommandFailed when commit fails
+ repo.git.commit(raise: true, timeout: true, a: true, m: commit_message)
+
+
+ # push commit back to bare repo
+ # will raise CommandFailed when push fails
+ repo.git.push({raise: true, timeout: true}, :origin, ref)
+
+ # everything worked
+ true
+ end
+ rescue Grit::Git::CommandFailed => ex
+ Gitlab::GitLogger.error(ex.message)
+ false
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/satellite/edit_file_action.rb b/lib/gitlab/satellite/files/edit_file_action.rb
index d793d0ba8dc..cbdf70f7d12 100644
--- a/lib/gitlab/satellite/edit_file_action.rb
+++ b/lib/gitlab/satellite/files/edit_file_action.rb
@@ -1,40 +1,40 @@
+require_relative 'file_action'
+
module Gitlab
module Satellite
# GitLab server-side file update and commit
- class EditFileAction < Action
- attr_accessor :file_path, :ref
-
- def initialize(user, project, ref, file_path)
- super user, project, git_timeout: 10.seconds
- @file_path = file_path
- @ref = ref
- end
-
+ class EditFileAction < FileAction
# Updates the files content and creates a new commit for it
#
# Returns false if the ref has been updated while editing the file
# Returns false if committing the change fails
- # Returns false if pushing from the satellite to Gitolite failed or was rejected
+ # Returns false if pushing from the satellite to bare repo failed or was rejected
# Returns true otherwise
- def commit!(content, commit_message, last_commit)
- return false unless can_edit?(last_commit)
-
+ def commit!(content, commit_message, encoding)
in_locked_and_timed_satellite do |repo|
prepare_satellite!(repo)
- # create target branch in satellite at the corresponding commit from Gitolite
+ # create target branch in satellite at the corresponding commit from bare repo
repo.git.checkout({raise: true, timeout: true, b: true}, ref, "origin/#{ref}")
# update the file in the satellite's working dir
file_path_in_satellite = File.join(repo.working_dir, file_path)
- File.open(file_path_in_satellite, 'w') { |f| f.write(content) }
+
+ # Prevent relative links
+ unless safe_path?(file_path_in_satellite)
+ Gitlab::GitLogger.error("FileAction: Relative path not allowed")
+ return false
+ end
+
+ # Write file
+ write_file(file_path_in_satellite, content, encoding)
# commit the changes
# will raise CommandFailed when commit fails
repo.git.commit(raise: true, timeout: true, a: true, m: commit_message)
- # push commit back to Gitolite
+ # push commit back to bare repo
# will raise CommandFailed when push fails
repo.git.push({raise: true, timeout: true}, :origin, ref)
@@ -45,13 +45,6 @@ module Gitlab
Gitlab::GitLogger.error(ex.message)
false
end
-
- protected
-
- def can_edit?(last_commit)
- current_last_commit = Gitlab::Git::Commit.last_for_path(@project.repository, ref, file_path).sha
- last_commit == current_last_commit
- end
end
end
end
diff --git a/lib/gitlab/satellite/files/file_action.rb b/lib/gitlab/satellite/files/file_action.rb
new file mode 100644
index 00000000000..7701a6d5d60
--- /dev/null
+++ b/lib/gitlab/satellite/files/file_action.rb
@@ -0,0 +1,25 @@
+module Gitlab
+ module Satellite
+ class FileAction < Action
+ attr_accessor :file_path, :ref
+
+ def initialize(user, project, ref, file_path)
+ super user, project, git_timeout: 10.seconds
+ @file_path = file_path
+ @ref = ref
+ end
+
+ def safe_path?(path)
+ File.absolute_path(path) == path
+ end
+
+ def write_file(abs_file_path, content, file_encoding = 'text')
+ if file_encoding == 'base64'
+ File.open(abs_file_path, 'wb') { |f| f.write(Base64.decode64(content)) }
+ else
+ File.open(abs_file_path, 'w') { |f| f.write(content) }
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/satellite/files/new_file_action.rb b/lib/gitlab/satellite/files/new_file_action.rb
new file mode 100644
index 00000000000..15e9b7a6f77
--- /dev/null
+++ b/lib/gitlab/satellite/files/new_file_action.rb
@@ -0,0 +1,55 @@
+require_relative 'file_action'
+
+module Gitlab
+ module Satellite
+ class NewFileAction < FileAction
+ # Updates the files content and creates a new commit for it
+ #
+ # Returns false if the ref has been updated while editing the file
+ # Returns false if committing the change fails
+ # Returns false if pushing from the satellite to bare repo failed or was rejected
+ # Returns true otherwise
+ def commit!(content, commit_message, encoding)
+ in_locked_and_timed_satellite do |repo|
+ prepare_satellite!(repo)
+
+ # create target branch in satellite at the corresponding commit from bare repo
+ repo.git.checkout({raise: true, timeout: true, b: true}, ref, "origin/#{ref}")
+
+ file_path_in_satellite = File.join(repo.working_dir, file_path)
+ dir_name_in_satellite = File.dirname(file_path_in_satellite)
+
+ # Prevent relative links
+ unless safe_path?(file_path_in_satellite)
+ Gitlab::GitLogger.error("FileAction: Relative path not allowed")
+ return false
+ end
+
+ # Create dir if not exists
+ FileUtils.mkdir_p(dir_name_in_satellite)
+
+ # Write file
+ write_file(file_path_in_satellite, content, encoding)
+
+ # add new file
+ repo.add(file_path_in_satellite)
+
+ # commit the changes
+ # will raise CommandFailed when commit fails
+ repo.git.commit(raise: true, timeout: true, a: true, m: commit_message)
+
+
+ # push commit back to bare repo
+ # will raise CommandFailed when push fails
+ repo.git.push({raise: true, timeout: true}, :origin, ref)
+
+ # everything worked
+ true
+ end
+ rescue Grit::Git::CommandFailed => ex
+ Gitlab::GitLogger.error(ex.message)
+ false
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/satellite/merge_action.rb b/lib/gitlab/satellite/merge_action.rb
index d74d4194ff6..85615f282c4 100644
--- a/lib/gitlab/satellite/merge_action.rb
+++ b/lib/gitlab/satellite/merge_action.rb
@@ -24,11 +24,11 @@ module Gitlab
# Returns false if the merge produced conflicts
# Returns false if pushing from the satellite to the repository failed or was rejected
# Returns true otherwise
- def merge!
+ def merge!(merge_commit_message = nil)
in_locked_and_timed_satellite do |merge_repo|
prepare_satellite!(merge_repo)
- if merge_in_satellite!(merge_repo)
- # push merge back to Gitolite
+ if merge_in_satellite!(merge_repo, merge_commit_message)
+ # 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
@@ -49,14 +49,7 @@ module Gitlab
in_locked_and_timed_satellite do |merge_repo|
prepare_satellite!(merge_repo)
update_satellite_source_and_target!(merge_repo)
-
- if merge_request.for_fork?
- diff = merge_repo.git.native(:diff, default_options, "origin/#{merge_request.target_branch}", "source/#{merge_request.source_branch}")
- else
- diff = merge_repo.git.native(:diff, default_options, "#{merge_request.target_branch}", "#{merge_request.source_branch}")
- end
-
- return diff
+ diff = merge_repo.git.native(:diff, default_options, "origin/#{merge_request.target_branch}", "source/#{merge_request.source_branch}")
end
rescue Grit::Git::CommandFailed => ex
handle_exception(ex)
@@ -88,14 +81,7 @@ module Gitlab
in_locked_and_timed_satellite do |merge_repo|
prepare_satellite!(merge_repo)
update_satellite_source_and_target!(merge_repo)
-
- if (merge_request.for_fork?)
- patch = merge_repo.git.format_patch(default_options({stdout: true}), "origin/#{merge_request.target_branch}..source/#{merge_request.source_branch}")
- else
- patch = merge_repo.git.format_patch(default_options({stdout: true}), "#{merge_request.target_branch}..#{merge_request.source_branch}")
- end
-
- return patch
+ patch = merge_repo.git.format_patch(default_options({stdout: true}), "origin/#{merge_request.target_branch}..source/#{merge_request.source_branch}")
end
rescue Grit::Git::CommandFailed => ex
handle_exception(ex)
@@ -125,34 +111,26 @@ module Gitlab
#
# Returns false if the merge produced conflicts
# Returns true otherwise
- def merge_in_satellite!(repo)
+ def merge_in_satellite!(repo, message = nil)
update_satellite_source_and_target!(repo)
+ message ||= "Merge branch '#{merge_request.source_branch}' into '#{merge_request.target_branch}'"
+
# merge the source branch into the satellite
# will raise CommandFailed when merge fails
- if merge_request.for_fork?
- repo.git.pull(default_options({no_ff: true}), 'source', merge_request.source_branch)
- else
- repo.git.pull(default_options({no_ff: true}), 'origin', merge_request.source_branch)
- end
+ repo.git.merge(default_options({no_ff: true}), "-m #{message}", "source/#{merge_request.source_branch}")
rescue Grit::Git::CommandFailed => ex
handle_exception(ex)
end
# Assumes a satellite exists that is a fresh clone of the projects repo, prepares satellite for merges, diffs etc
def update_satellite_source_and_target!(repo)
- if merge_request.for_fork?
- repo.remote_add('source', merge_request.source_project.repository.path_to_repo)
- repo.remote_fetch('source')
- repo.git.checkout(default_options({b: true}), merge_request.target_branch, "origin/#{merge_request.target_branch}")
- else
- repo.git.checkout(default_options, "#{merge_request.source_branch}")
- repo.git.checkout(default_options({t: true}), "origin/#{merge_request.target_branch}")
- end
+ repo.remote_add('source', merge_request.source_project.repository.path_to_repo)
+ repo.remote_fetch('source')
+ repo.git.checkout(default_options({b: true}), merge_request.target_branch, "origin/#{merge_request.target_branch}")
rescue Grit::Git::CommandFailed => ex
handle_exception(ex)
end
-
end
end
end
diff --git a/lib/gitlab/satellite/satellite.rb b/lib/gitlab/satellite/satellite.rb
index 6cb7814fae5..353c3024aad 100644
--- a/lib/gitlab/satellite/satellite.rb
+++ b/lib/gitlab/satellite/satellite.rb
@@ -123,7 +123,7 @@ module Gitlab
remotes.each { |name| repo.git.remote(default_options,'rm', name)}
end
- # Updates the satellite from Gitolite
+ # Updates the satellite from bare repo
#
# Note: this will only update remote branches (i.e. origin/*)
def update_from_source!
diff --git a/lib/gitlab/theme.rb b/lib/gitlab/theme.rb
index 89604162304..44237a062fc 100644
--- a/lib/gitlab/theme.rb
+++ b/lib/gitlab/theme.rb
@@ -15,7 +15,7 @@ module Gitlab
COLOR => "ui_color"
}
- id ||= 1
+ id ||= Gitlab.config.gitlab.default_theme
return themes[id]
end
diff --git a/lib/gitlab/upgrader.rb b/lib/gitlab/upgrader.rb
new file mode 100644
index 00000000000..f46685e4bbe
--- /dev/null
+++ b/lib/gitlab/upgrader.rb
@@ -0,0 +1,96 @@
+require_relative "version_info"
+
+module Gitlab
+ class Upgrader
+ def execute
+ puts "GitLab #{current_version.major} upgrade tool"
+ puts "Your version is #{current_version}"
+ puts "Latest available version for GitLab #{current_version.major} is #{latest_version}"
+
+ if latest_version?
+ puts "You are using the latest GitLab version"
+ else
+ puts "Newer GitLab version is available"
+ answer = if ARGV.first == "-y"
+ "yes"
+ else
+ prompt("Do you want to upgrade (yes/no)? ", %w{yes no})
+ end
+
+ if answer == "yes"
+ upgrade
+ else
+ exit 0
+ end
+ end
+ end
+
+ def latest_version?
+ current_version >= latest_version
+ end
+
+ def current_version
+ @current_version ||= Gitlab::VersionInfo.parse(current_version_raw)
+ end
+
+ def latest_version
+ @latest_version ||= Gitlab::VersionInfo.parse(latest_version_raw)
+ end
+
+ def current_version_raw
+ File.read(File.join(gitlab_path, "VERSION")).strip
+ end
+
+ def latest_version_raw
+ git_tags = `git ls-remote --tags origin | grep tags\/v#{current_version.major}`
+ git_tags = git_tags.lines.to_a.select { |version| version =~ /v\d\.\d\.\d\Z/ }
+ last_tag = git_tags.last.match(/v\d\.\d\.\d/).to_s
+ end
+
+ def update_commands
+ {
+ "Stash changed files" => "git stash",
+ "Get latest code" => "git fetch",
+ "Switch to new version" => "git checkout v#{latest_version}",
+ "Install gems" => "bundle",
+ "Migrate DB" => "bundle exec rake db:migrate RAILS_ENV=production",
+ "Recompile assets" => "bundle exec rake assets:clean assets:precompile RAILS_ENV=production",
+ "Clear cache" => "bundle exec rake cache:clear RAILS_ENV=production"
+ }
+ end
+
+ def upgrade
+ update_commands.each do |title, cmd|
+ puts title
+ puts " -> #{cmd}"
+ if system(cmd)
+ puts " -> OK"
+ else
+ puts " -> FAILED"
+ puts "Failed to upgrade. Try to repeat task or proceed with upgrade manually "
+ exit 1
+ end
+ end
+
+ puts "Done"
+ end
+
+ def gitlab_path
+ File.expand_path(File.join(File.dirname(__FILE__), '../..'))
+ end
+
+ # Prompt the user to input something
+ #
+ # message - the message to display before input
+ # choices - array of strings of acceptable answers or nil for any answer
+ #
+ # Returns the user's answer
+ def prompt(message, choices = nil)
+ begin
+ print(message)
+ answer = STDIN.gets.chomp
+ end while !choices.include?(answer)
+ answer
+ end
+ end
+end
diff --git a/lib/gitlab/visibility_level.rb b/lib/gitlab/visibility_level.rb
new file mode 100644
index 00000000000..eada9bcddf5
--- /dev/null
+++ b/lib/gitlab/visibility_level.rb
@@ -0,0 +1,42 @@
+# Gitlab::VisibilityLevel module
+#
+# Define allowed public modes that can be used for
+# GitLab projects to determine project public mode
+#
+module Gitlab
+ module VisibilityLevel
+ PRIVATE = 0
+ INTERNAL = 10
+ PUBLIC = 20
+
+ class << self
+ def values
+ options.values
+ end
+
+ def options
+ {
+ 'Private' => PRIVATE,
+ 'Internal' => INTERNAL,
+ 'Public' => PUBLIC
+ }
+ end
+
+ def allowed_for?(user, level)
+ user.is_admin? || !Gitlab.config.gitlab.restricted_visibility_levels.include?(level)
+ end
+ end
+
+ def private?
+ visibility_level_field == PRIVATE
+ end
+
+ def internal?
+ visibility_level_field == INTERNAL
+ end
+
+ def public?
+ visibility_level_field == PUBLIC
+ end
+ end
+end
diff --git a/lib/redcarpet/render/gitlab_html.rb b/lib/redcarpet/render/gitlab_html.rb
index d9c2d3b626d..6da0c1d6f96 100644
--- a/lib/redcarpet/render/gitlab_html.rb
+++ b/lib/redcarpet/render/gitlab_html.rb
@@ -6,14 +6,12 @@ class Redcarpet::Render::GitlabHTML < Redcarpet::Render::HTML
def initialize(template, options = {})
@template = template
@project = @template.instance_variable_get("@project")
+ @ref = @template.instance_variable_get("@ref")
+ @request_path = @template.instance_variable_get("@path")
super options
end
def block_code(code, language)
- options = { options: {encoding: 'utf-8'} }
- lexer = Pygments::Lexer.find(language) # language can be an alias
- options.merge!(lexer: lexer.aliases[0].downcase) if lexer # downcase is required
-
# New lines are placed to fix an rendering issue
# with code wrapped inside <h1> tag for next case:
#
@@ -23,7 +21,11 @@ class Redcarpet::Render::GitlabHTML < Redcarpet::Render::HTML
#
<<-HTML
- <div class="#{h.user_color_scheme_class}">#{Pygments.highlight(code, options)}</div>
+<div class="highlighted-data #{h.user_color_scheme_class}">
+ <div class="highlight">
+ <pre><code class="#{language}">#{code}</code></pre>
+ </div>
+</div>
HTML
end
@@ -32,7 +34,19 @@ class Redcarpet::Render::GitlabHTML < Redcarpet::Render::HTML
h.link_to_gfm(content, link, title: title)
end
+ def preprocess(full_document)
+ if @project
+ h.create_relative_links(full_document, @project, @ref, @request_path, is_wiki?)
+ else
+ full_document
+ end
+ end
+
def postprocess(full_document)
h.gfm(full_document)
end
+
+ def is_wiki?
+ @template.instance_variable_get("@wiki")
+ end
end
diff --git a/lib/support/deploy/deploy.sh b/lib/support/deploy/deploy.sh
index 0d2f8418bcf..b96f73058b6 100755
--- a/lib/support/deploy/deploy.sh
+++ b/lib/support/deploy/deploy.sh
@@ -28,17 +28,18 @@ sudo -u git -H git pull origin master
echo 'Deploy: Bundle and migrate'
# change it to your needs
-sudo -u git -H bundle --without postgres
+sudo -u git -H bundle --without aws development test postgres --deployment
sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
+sudo -u git -H bundle exec rake assets:clean RAILS_ENV=production
+sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production
+sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
# return stashed changes (if necessary)
# sudo -u git -H git stash pop
-
echo 'Deploy: Starting GitLab server...'
sudo service gitlab start
-sleep 10
sudo -u git -H rm /home/git/gitlab/public/index.html
-echo 'Deploy: Done'
+echo 'Deploy: Done' \ No newline at end of file
diff --git a/lib/support/init.d/gitlab b/lib/support/init.d/gitlab
index 6aff7b5a8f9..c6e570784e0 100755
--- a/lib/support/init.d/gitlab
+++ b/lib/support/init.d/gitlab
@@ -3,7 +3,6 @@
# GITLAB
# Maintainer: @randx
# Authors: rovanion.luckey@gmail.com, @randx
-# App Version: 6.0
### BEGIN INIT INFO
# Provides: gitlab
@@ -15,36 +14,44 @@
# Description: GitLab git repository management
### END INIT INFO
+
+###
+# DO NOT EDIT THIS FILE!
+# This file will be overwritten on update.
+# Instead add/change your variables in /etc/default/gitlab
+# An example defaults file can be found in lib/support/init.d/gitlab.default.example
+###
+
+
### Environment variables
RAILS_ENV="production"
-# Script variable names should be lower-case not to conflict with internal
-# /bin/sh variables such as PATH, EDITOR or SHELL.
-app_root="/home/git/gitlab"
+# Script variable names should be lower-case not to conflict with
+# internal /bin/sh variables such as PATH, EDITOR or SHELL.
app_user="git"
-unicorn_conf="$app_root/config/unicorn.rb"
+app_root="/home/$app_user/gitlab"
pid_path="$app_root/tmp/pids"
socket_path="$app_root/tmp/sockets"
web_server_pid_path="$pid_path/unicorn.pid"
sidekiq_pid_path="$pid_path/sidekiq.pid"
-
-
-### Here ends user configuration ###
-
+# Read configuration variable file if it is present
+test -f /etc/default/gitlab && . /etc/default/gitlab
# Switch to the app_user if it is not he/she who is running the script.
if [ "$USER" != "$app_user" ]; then
sudo -u "$app_user" -H -i $0 "$@"; exit;
fi
-# Switch to the gitlab path, if it fails exit with an error.
+# Switch to the gitlab path, exit on failure.
if ! cd "$app_root" ; then
echo "Failed to cd into $app_root, exiting!"; exit 1
fi
+
### Init Script functions
+## Gets the pids from the files
check_pids(){
if ! mkdir -p "$pid_path"; then
echo "Could not create the path $pid_path needed to store the pids."
@@ -63,12 +70,29 @@ check_pids(){
fi
}
+## Called when we have started the two processes and are waiting for their pid files.
+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 -o ! -f $sidekiq_pid_path ]; do
+ sleep 0.1;
+ i=$((i+1))
+ if [ $((i%10)) = 0 ]; then
+ echo -n "."
+ elif [ $((i)) = 301 ]; then
+ echo "Waited 30s for the processes to write their pids, something probably went wrong."
+ exit 1;
+ fi
+ done
+ echo
+}
+
# We use the pids in so many parts of the script it makes sense to always check them.
# Only after start() is run should the pids change. Sidekiq sets it's own pid.
check_pids
-# Checks whether the different parts of the service are already running or not.
+## Checks whether the different parts of the service are already running or not.
check_status(){
check_pids
# If the web server is running kill -0 $wpid returns true, or rather 0.
@@ -85,9 +109,16 @@ check_status(){
else
sidekiq_status="-1"
fi
+ if [ $web_status = 0 -a $sidekiq_status = 0 ]; then
+ gitlab_status=0
+ else
+ # http://refspecs.linuxbase.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/iniscrptact.html
+ # code 3 means 'program is not running'
+ gitlab_status=3
+ fi
}
-# Check for stale pids and remove them if necessary
+## Check for stale pids and remove them if necessary.
check_stale_pids(){
check_status
# If there is a pid it is something else than 0, the service is running if
@@ -95,7 +126,7 @@ check_stale_pids(){
if [ "$wpid" != "0" -a "$web_status" != "0" ]; then
echo "Removing stale Unicorn web server pid. This is most likely caused by the web server crashing the last time it ran."
if ! rm "$web_server_pid_path"; then
- echo "Unable to remove stale pid, exiting"
+ echo "Unable to remove stale pid, exiting."
exit 1
fi
fi
@@ -108,7 +139,7 @@ check_stale_pids(){
fi
}
-# If no parts of the service is running, bail out.
+## If no parts of the service is running, bail out.
exit_if_not_running(){
check_stale_pids
if [ "$web_status" != "0" -a "$sidekiq_status" != "0" ]; then
@@ -117,86 +148,92 @@ exit_if_not_running(){
fi
}
-# Starts Unicorn and Sidekiq.
+## Starts Unicorn and Sidekiq if they're not running.
start() {
check_stale_pids
+ if [ "$web_status" != "0" -a "$sidekiq_status" != "0" ]; then
+ echo -n "Starting both the GitLab Unicorn and Sidekiq"
+ elif [ "$web_status" != "0" ]; then
+ echo -n "Starting GitLab Sidekiq"
+ elif [ "$sidekiq_status" != "0" ]; then
+ echo -n "Starting GitLab Unicorn"
+ fi
+
# Then check if the service is running. If it is: don't start again.
if [ "$web_status" = "0" ]; then
echo "The Unicorn web server already running with pid $wpid, not restarting."
else
- echo "Starting the GitLab Unicorn web server..."
# Remove old socket if it exists
rm -f "$socket_path"/gitlab.socket 2>/dev/null
- # Start the webserver
- bundle exec unicorn_rails -D -c "$unicorn_conf" -E "$RAILS_ENV"
+ # Start the web server
+ RAILS_ENV=$RAILS_ENV script/web start &
fi
# If sidekiq is already running, don't start it again.
if [ "$sidekiq_status" = "0" ]; then
echo "The Sidekiq job dispatcher is already running with pid $spid, not restarting"
else
- echo "Starting the GitLab Sidekiq event dispatcher..."
- RAILS_ENV=$RAILS_ENV bundle exec rake sidekiq:start
- # We are sleeping a bit here because sidekiq is slow at writing it's pid
- sleep 2
+ RAILS_ENV=$RAILS_ENV script/background_jobs start &
fi
+ # Wait for the pids to be planted
+ wait_for_pids
# Finally check the status to tell wether or not GitLab is running
- status
+ print_status
}
-# Asks the Unicorn and the Sidekiq if they would be so kind as to stop, if not kills them.
+## Asks the Unicorn and the Sidekiq if they would be so kind as to stop, if not kills them.
stop() {
exit_if_not_running
+
+ if [ "$web_status" = "0" -a "$sidekiq_status" = "0" ]; then
+ echo -n "Shutting down both Unicorn and Sidekiq"
+ elif [ "$web_status" = "0" ]; then
+ echo -n "Shutting down Sidekiq"
+ elif [ "$sidekiq_status" = "0" ]; then
+ echo -n "Shutting down Unicorn"
+ fi
+
# If the Unicorn web server is running, tell it to stop;
if [ "$web_status" = "0" ]; then
- kill -QUIT "$wpid"
- echo "Stopping the GitLab Unicorn web server..."
- stopping=true
- else
- echo "The Unicorn web was not running, doing nothing."
+ RAILS_ENV=$RAILS_ENV script/web stop
fi
# And do the same thing for the Sidekiq.
if [ "$sidekiq_status" = "0" ]; then
- printf "Stopping Sidekiq job dispatcher."
- RAILS_ENV=$RAILS_ENV bundle exec rake sidekiq:stop
- stopping=true
- else
- echo "The Sidekiq was not running, must have run out of breath."
+ RAILS_ENV=$RAILS_ENV script/background_jobs stop
fi
-
# If something needs to be stopped, lets wait for it to stop. Never use SIGKILL in a script.
- while [ "$stopping" = "true" ]; do
+ while [ "$web_status" = "0" -o "$sidekiq_status" = "0" ]; do
sleep 1
check_status
- if [ "$web_status" = "0" -o "$sidekiq_status" = "0" ]; then
- printf "."
- else
+ printf "."
+ if [ "$web_status" != "0" -a "$sidekiq_status" != "0" ]; then
printf "\n"
break
fi
done
+
sleep 1
# Cleaning up unused pids
rm "$web_server_pid_path" 2>/dev/null
# rm "$sidekiq_pid_path" # Sidekiq seems to be cleaning up it's own pid.
- status
+ print_status
}
-# Returns the status of GitLab and it's components
-status() {
+## Prints the status of GitLab and it's components.
+print_status() {
check_status
if [ "$web_status" != "0" -a "$sidekiq_status" != "0" ]; then
echo "GitLab is not running."
return
fi
if [ "$web_status" = "0" ]; then
- echo "The GitLab Unicorn webserver with pid $wpid is running."
+ echo "The GitLab Unicorn web server with pid $wpid is running."
else
- printf "The GitLab Unicorn webserver is \033[31mnot running\033[0m.\n"
+ printf "The GitLab Unicorn web server is \033[31mnot running\033[0m.\n"
fi
if [ "$sidekiq_status" = "0" ]; then
echo "The GitLab Sidekiq job dispatcher with pid $spid is running."
@@ -208,6 +245,7 @@ status() {
fi
}
+## Tells unicorn to reload it's config and Sidekiq to restart
reload(){
exit_if_not_running
if [ "$wpid" = "0" ];then
@@ -215,17 +253,16 @@ reload(){
exit 1
fi
printf "Reloading GitLab Unicorn configuration... "
- kill -USR2 "$wpid"
+ RAILS_ENV=$RAILS_ENV script/web reload
echo "Done."
echo "Restarting GitLab Sidekiq since it isn't capable of reloading its config..."
- RAILS_ENV=$RAILS_ENV bundle exec rake sidekiq:stop
- echo "Starting Sidekiq..."
- RAILS_ENV=$RAILS_ENV bundle exec rake sidekiq:start
- # Waiting 2 seconds for sidekiq to write it.
- sleep 2
- status
+ RAILS_ENV=$RAILS_ENV script/background_jobs restart
+
+ wait_for_pids
+ print_status
}
+## Restarts Sidekiq and Unicorn.
restart(){
check_status
if [ "$web_status" = "0" -o "$sidekiq_status" = "0" ]; then
@@ -235,7 +272,7 @@ restart(){
}
-## Finally the input handling.
+### Finally the input handling.
case "$1" in
start)
@@ -251,7 +288,8 @@ case "$1" in
reload
;;
status)
- status
+ print_status
+ exit $gitlab_status
;;
*)
echo "Usage: service gitlab {start|stop|restart|reload|status}"
diff --git a/lib/support/init.d/gitlab.default.example b/lib/support/init.d/gitlab.default.example
new file mode 100755
index 00000000000..9951bacedf5
--- /dev/null
+++ b/lib/support/init.d/gitlab.default.example
@@ -0,0 +1,31 @@
+# Copy this lib/support/init.d/gitlab.default.example file to
+# /etc/default/gitlab in order for it to apply to your system.
+
+# RAILS_ENV defines the type of installation that is running.
+# Normal values are "production", "test" and "development".
+RAILS_ENV="production"
+
+# app_user defines the user that GitLab is run as.
+# The default is "git".
+app_user="git"
+
+# app_root defines the folder in which gitlab and it's components are installed.
+# The default is "/home/$app_user/gitlab"
+app_root="/home/$app_user/gitlab"
+
+# pid_path defines a folder in which the gitlab and it's components place their pids.
+# This variable is also used below to define the relevant pids for the gitlab components.
+# The default is "$app_root/tmp/pids"
+pid_path="$app_root/tmp/pids"
+
+# socket_path defines the folder in which gitlab places the sockets
+#The default is "$app_root/tmp/sockets"
+socket_path="$app_root/tmp/sockets"
+
+# web_server_pid_path defines the path in which to create the pid file fo the web_server
+# The default is "$pid_path/unicorn.pid"
+web_server_pid_path="$pid_path/unicorn.pid"
+
+# sidekiq_pid_path defines the path in which to create the pid file for sidekiq
+# The default is "$pid_path/sidekiq.pid"
+sidekiq_pid_path="$pid_path/sidekiq.pid"
diff --git a/lib/support/logrotate/gitlab b/lib/support/logrotate/gitlab
new file mode 100644
index 00000000000..df9398d0795
--- /dev/null
+++ b/lib/support/logrotate/gitlab
@@ -0,0 +1,22 @@
+# GitLab logrotate settings
+# based on: http://stackoverflow.com/a/4883967
+
+/home/git/gitlab/log/*.log {
+ weekly
+ missingok
+ rotate 52
+ compress
+ delaycompress
+ notifempty
+ copytruncate
+}
+
+/home/git/gitlab-shell/gitlab-shell.log {
+ weekly
+ missingok
+ rotate 52
+ compress
+ delaycompress
+ notifempty
+ copytruncate
+}
diff --git a/lib/support/nginx/gitlab b/lib/support/nginx/gitlab
index 3e929c52990..882f0386046 100644
--- a/lib/support/nginx/gitlab
+++ b/lib/support/nginx/gitlab
@@ -1,6 +1,19 @@
# GITLAB
# Maintainer: @randx
-# App Version: 5.0
+
+# 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
upstream gitlab {
server unix:/home/git/gitlab/tmp/sockets/gitlab.socket;
@@ -11,6 +24,10 @@ server {
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
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
+ client_max_body_size 5m;
# individual nginx logs for this gitlab vhost
access_log /var/log/nginx/gitlab_access.log;
@@ -25,15 +42,18 @@ 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)
location @gitlab {
- proxy_read_timeout 300; # https://github.com/gitlabhq/gitlabhq/issues/694
- proxy_connect_timeout 300; # https://github.com/gitlabhq/gitlabhq/issues/694
+ 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;
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_pass http://gitlab;
}
+
+ error_page 502 /502.html;
}
diff --git a/lib/tasks/gitlab/bulk_add_permission.rake b/lib/tasks/gitlab/bulk_add_permission.rake
index c270232edba..612a9ba93a8 100644
--- a/lib/tasks/gitlab/bulk_add_permission.rake
+++ b/lib/tasks/gitlab/bulk_add_permission.rake
@@ -15,7 +15,7 @@ namespace :gitlab do
desc "GITLAB | Add a specific user to all projects (as a developer)"
task :user_to_projects, [:email] => :environment do |t, args|
- user = User.find_by_email args.email
+ user = User.find_by(email: args.email)
project_ids = Project.pluck(:id)
puts "Importing #{user.email} users into #{project_ids.size} projects"
UsersProject.add_users_into_projects(project_ids, Array.wrap(user.id), UsersProject::DEVELOPER)
diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake
index f52b98cb3ae..c91dedf74c7 100644
--- a/lib/tasks/gitlab/check.rake
+++ b/lib/tasks/gitlab/check.rake
@@ -3,6 +3,7 @@ namespace :gitlab do
task check: %w{gitlab:env:check
gitlab:gitlab_shell:check
gitlab:sidekiq:check
+ gitlab:ldap:check
gitlab:app:check}
@@ -278,8 +279,6 @@ namespace :gitlab do
start_checking "Environment"
check_gitlab_git_config
- check_python2_exists
- check_python2_version
finished_checking "Environment"
end
@@ -313,52 +312,6 @@ namespace :gitlab do
fix_and_rerun
end
end
-
- def check_python2_exists
- print "Has python2? ... "
-
- # Python prints its version to STDERR
- # so we can't just use run("python2 --version")
- if run_and_match("which python2", /python2$/)
- puts "yes".green
- else
- puts "no".red
- try_fixing_it(
- "Make sure you have Python 2.5+ installed",
- "Link it to python2"
- )
- for_more_information(
- see_installation_guide_section "Packages / Dependencies"
- )
- fix_and_rerun
- end
- end
-
- def check_python2_version
- print "python2 is supported version? ... "
-
- # Python prints its version to STDERR
- # so we can't just use run("python2 --version")
-
- unless run_and_match("which python2", /python2$/)
- puts "can't check because of previous errors".magenta
- return
- end
-
- if `python2 --version 2>&1` =~ /2\.[567]\.\d/
- puts "yes".green
- else
- puts "no".red
- try_fixing_it(
- "Make sure you have Python 2.5+ installed",
- "Link it to python2"
- )
- for_more_information(
- see_installation_guide_section "Packages / Dependencies"
- )
- fix_and_rerun
- end
- end
end
@@ -611,10 +564,7 @@ namespace :gitlab do
end
def gitlab_shell_version
- gitlab_shell_version_file = "#{gitlab_shell_user_home}/gitlab-shell/VERSION"
- if File.readable?(gitlab_shell_version_file)
- File.read(gitlab_shell_version_file)
- end
+ Gitlab::Shell.new.version
end
def has_gitlab_shell3?
@@ -643,12 +593,12 @@ namespace :gitlab do
def check_sidekiq_running
print "Running? ... "
- if sidekiq_process_match
+ if sidekiq_process_count > 0
puts "yes".green
else
puts "no".red
try_fixing_it(
- sudo_gitlab("bundle exec rake sidekiq:start RAILS_ENV=production")
+ sudo_gitlab("RAILS_ENV=production script/background_jobs start")
)
for_more_information(
see_installation_guide_section("Install Init Script"),
@@ -659,14 +609,14 @@ namespace :gitlab do
end
def only_one_sidekiq_running
- sidekiq_match = sidekiq_process_match
- return unless sidekiq_match
+ process_count = sidekiq_process_count
+ return if process_count.zero?
print 'Number of Sidekiq processes ... '
- if sidekiq_match.length == 1
+ if process_count == 1
puts '1'.green
else
- puts "#{sidekiq_match.length}".red
+ puts "#{process_count}".red
try_fixing_it(
'sudo service gitlab stop',
"sudo pkill -u #{gitlab_user} -f sidekiq",
@@ -677,11 +627,51 @@ namespace :gitlab do
end
end
- def sidekiq_process_match
- run_and_match("ps ux | grep -i sidekiq", /(sidekiq \d+\.\d+\.\d+.+$)/)
+ def sidekiq_process_count
+ `ps ux`.scan(/sidekiq \d+\.\d+\.\d+/).count
end
end
+ namespace :ldap do
+ task :check, [:limit] => :environment do |t, args|
+ # Only show up to 100 results because LDAP directories can be very big.
+ # This setting only affects the `rake gitlab:check` script.
+ args.with_defaults(limit: 100)
+ warn_user_is_not_gitlab
+ start_checking "LDAP"
+
+ if ldap_config.enabled
+ print_users(args.limit)
+ else
+ puts 'LDAP is disabled in config/gitlab.yml'
+ end
+
+ finished_checking "LDAP"
+ end
+
+ def print_users(limit)
+ puts "LDAP users with access to your GitLab server (only showing the first #{limit} results)"
+ ldap.search(attributes: attributes, filter: filter, size: limit, return_result: false) do |entry|
+ puts "DN: #{entry.dn}\t#{ldap_config.uid}: #{entry[ldap_config.uid]}"
+ end
+ end
+
+ def attributes
+ [ldap_config.uid]
+ end
+
+ def filter
+ Net::LDAP::Filter.present?(ldap_config.uid)
+ end
+
+ def ldap
+ @ldap ||= OmniAuth::LDAP::Adaptor.new(ldap_config).connection
+ end
+
+ def ldap_config
+ @ldap_config ||= Gitlab.config.ldap
+ end
+ end
# Helper methods
##########################
@@ -736,7 +726,7 @@ namespace :gitlab do
end
def check_gitlab_shell
- required_version = Gitlab::VersionInfo.new(1, 7, 1)
+ required_version = Gitlab::VersionInfo.new(1, 7, 9)
current_version = Gitlab::VersionInfo.parse(gitlab_shell_version)
print "GitLab Shell version >= #{required_version} ? ... "
diff --git a/lib/tasks/gitlab/enable_namespaces.rake b/lib/tasks/gitlab/enable_namespaces.rake
index 927748c0fd5..201f34ab546 100644
--- a/lib/tasks/gitlab/enable_namespaces.rake
+++ b/lib/tasks/gitlab/enable_namespaces.rake
@@ -43,13 +43,13 @@ namespace :gitlab do
username.gsub!("+", ".")
# return username if no matches
- return username unless User.find_by_username(username)
+ return username unless User.find_by(username: username)
# look for same username
(1..10).each do |i|
suffixed_username = "#{username}#{i}"
- return suffixed_username unless User.find_by_username(suffixed_username)
+ return suffixed_username unless User.find_by(username: suffixed_username)
end
end
diff --git a/lib/tasks/gitlab/import.rake b/lib/tasks/gitlab/import.rake
index 8fa89270854..cbfa736c84c 100644
--- a/lib/tasks/gitlab/import.rake
+++ b/lib/tasks/gitlab/import.rake
@@ -2,12 +2,12 @@ namespace :gitlab do
namespace :import do
# How to use:
#
- # 1. copy your bare repos under git repos_path
- # 2. run bundle exec rake gitlab:import:repos RAILS_ENV=production
+ # 1. copy the bare repos under the repos_path (commonly /home/git/repositories)
+ # 2. run: bundle exec rake gitlab:import:repos RAILS_ENV=production
#
# Notes:
- # * project owner will be a first admin
- # * existing projects will be skipped
+ # * The project owner will set to the first administator of the system
+ # * Existing projects will be skipped
#
desc "GITLAB | Import bare repositories from gitlab_shell -> repos_path into GitLab project instance"
task repos: :environment do
@@ -50,7 +50,7 @@ namespace :gitlab do
# find group namespace
if group_name
- group = Group.find_by_path(group_name)
+ group = Group.find_by(path: group_name)
# create group namespace
if !group
group = Group.new(:name => group_name)
@@ -66,7 +66,7 @@ namespace :gitlab do
project_params[:namespace_id] = group.id
end
- project = Projects::CreateContext.new(user, project_params).execute
+ project = Projects::CreateService.new(user, project_params).execute
if project.valid?
puts " * Created #{project.name} (#{repo_path})".green
diff --git a/lib/tasks/gitlab/task_helpers.rake b/lib/tasks/gitlab/task_helpers.rake
index ac2c4577c77..c46d5855faf 100644
--- a/lib/tasks/gitlab/task_helpers.rake
+++ b/lib/tasks/gitlab/task_helpers.rake
@@ -2,6 +2,16 @@ module Gitlab
class TaskAbortedByUserError < StandardError; end
end
+unless STDOUT.isatty
+ module Colored
+ extend self
+
+ def colorize(string, options={})
+ string
+ end
+ end
+end
+
namespace :gitlab do
# Ask if the user wants to continue
diff --git a/lib/tasks/sidekiq.rake b/lib/tasks/sidekiq.rake
index d0e9dfe46a1..e91678473a8 100644
--- a/lib/tasks/sidekiq.rake
+++ b/lib/tasks/sidekiq.rake
@@ -1,20 +1,21 @@
namespace :sidekiq do
desc "GITLAB | Stop sidekiq"
task :stop do
- system "bundle exec sidekiqctl stop #{pidfile}"
+ system "script/background_jobs stop"
end
desc "GITLAB | Start sidekiq"
task :start do
- system "nohup bundle exec sidekiq -q post_receive,mailer,system_hook,project_web_hook,gitlab_shell,common,default -e #{Rails.env} -P #{pidfile} >> #{Rails.root.join("log", "sidekiq.log")} 2>&1 &"
+ system "script/background_jobs start"
end
- desc "GITLAB | Start sidekiq with launchd on Mac OS X"
- task :launchd do
- system "bundle exec sidekiq -q post_receive,mailer,system_hook,project_web_hook,gitlab_shell,common,default -e #{Rails.env} -P #{pidfile} >> #{Rails.root.join("log", "sidekiq.log")} 2>&1"
+ desc 'GitLab | Restart sidekiq'
+ task :restart do
+ system "script/background_jobs restart"
end
- def pidfile
- Rails.root.join("tmp", "pids", "sidekiq.pid")
+ desc "GITLAB | Start sidekiq with launchd on Mac OS X"
+ task :launchd do
+ system "script/background_jobs start_no_deamonize"
end
end