From 34457b307bb4d60a8abe8be3e63b44f986b802bd Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 2 Sep 2015 16:04:51 +0200 Subject: [PATCH] Implement rebase feature Signed-off-by: Dmitriy Zaporozhets --- .../projects/merge_requests_controller.rb | 10 +++- app/services/merge_requests/rebase_service.rb | 54 +++++++++++++++++++ .../widget/open/_ff_accept.html.haml | 2 +- 3 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 app/services/merge_requests/rebase_service.rb diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 83b401cee2..a17d07d95d 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -2,7 +2,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController before_action :module_enabled before_action :merge_request, only: [ :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 :validates_merge_request, only: [:show, :diffs, :commits] @@ -231,6 +231,14 @@ class Projects::MergeRequestsController < Projects::ApplicationController 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 def selected_target_project diff --git a/app/services/merge_requests/rebase_service.rb b/app/services/merge_requests/rebase_service.rb new file mode 100644 index 0000000000..619c5d2c83 --- /dev/null +++ b/app/services/merge_requests/rebase_service.rb @@ -0,0 +1,54 @@ +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 diff --git a/app/views/projects/merge_requests/widget/open/_ff_accept.html.haml b/app/views/projects/merge_requests/widget/open/_ff_accept.html.haml index 70b9853024..97a4651d6c 100644 --- a/app/views/projects/merge_requests/widget/open/_ff_accept.html.haml +++ b/app/views/projects/merge_requests/widget/open/_ff_accept.html.haml @@ -10,7 +10,7 @@ Fast-forward merge without creating merge commit - else = 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 .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)