Commit 34457b30 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Implement rebase feature

Signed-off-by: default avatarDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
parent b8540106
...@@ -2,7 +2,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -2,7 +2,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
before_action :module_enabled before_action :module_enabled
before_action :merge_request, only: [ before_action :merge_request, only: [
:edit, :update, :show, :diffs, :commits, :merge, :merge_check, :edit, :update, :show, :diffs, :commits, :merge, :merge_check,
:ci_status, :toggle_subscription, :approve, :ff_merge :ci_status, :toggle_subscription, :approve, :ff_merge, :rebase
] ]
before_action :closes_issues, only: [:edit, :update, :show, :diffs, :commits] before_action :closes_issues, only: [:edit, :update, :show, :diffs, :commits]
before_action :validates_merge_request, only: [:show, :diffs, :commits] before_action :validates_merge_request, only: [:show, :diffs, :commits]
...@@ -231,6 +231,14 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -231,6 +231,14 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end end
end end
def rebase
return access_denied! unless @merge_request.can_be_merged_by?(current_user)
return render_404 unless @merge_request.approved?
MergeRequests::RebaseService.new(merge_request.target_project, current_user).
execute(merge_request)
end
protected protected
def selected_target_project def selected_target_project
......
module MergeRequests
# MergeService class
#
# Do git merge and in case of success
# mark merge request as merged and execute all hooks and notifications
# Executed when you do merge via GitLab UI
#
class RebaseService < MergeRequests::BaseService
include Gitlab::Popen
attr_reader :merge_request
def execute(merge_request)
@merge_request = merge_request
if rebase
success
else
error('Failed to rebase. Should be done manually')
end
end
def rebase
Gitlab::ShellEnv.set_env(current_user)
# Clone
output, status = popen(%W(git clone -b #{merge_request.source_branch} -- #{source_project.repository.path_to_repo} #{tree_path}))
raise 'Failed to clone repo' unless status.zero?
# Rebase
output, status = popen(%W(git pull --rebase #{target_project.repository.path_to_repo} #{merge_request.target_branch}), tree_path)
raise 'Failed to rebase' unless status.zero?
output, status = popen(%W(git push -f origin #{merge_request.source_branch}), tree_path)
raise 'Failed to push' unless status.zero?
true
ensure
Gitlab::ShellEnv.reset_env
end
def source_project
@source_project ||= merge_request.source_project
end
def target_project
@target_project ||= merge_request.target_project
end
def tree_path
@tree_path ||= Rails.root.join('tmp', 'rebase', source_project.id.to_s, SecureRandom.hex).to_s
end
end
end
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
Fast-forward merge without creating merge commit Fast-forward merge without creating merge commit
- else - else
= form_for [:rebase, @project.namespace.becomes(Namespace), @project, @merge_request], = form_for [:rebase, @project.namespace.becomes(Namespace), @project, @merge_request],
remote: true, method: :post, html: { class: 'accept-mr-form js-requires-input' } do |f| remote: false, method: :post, html: { class: 'accept-mr-form js-requires-input' } do |f|
= hidden_field_tag :authenticity_token, form_authenticity_token = hidden_field_tag :authenticity_token, form_authenticity_token
.accept-merge-holder.clearfix.js-toggle-container .accept-merge-holder.clearfix.js-toggle-container
- if @merge_request.target_project.merge_requests_rebase_enabled && can_rebase?(@merge_request.target_project, @merge_request.target_branch) - if @merge_request.target_project.merge_requests_rebase_enabled && can_rebase?(@merge_request.target_project, @merge_request.target_branch)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment