summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorValery Sizov <valery@gitlab.com>2017-09-13 17:11:10 +0300
committerEric Eastwood <contact@ericeastwood.com>2017-09-19 23:48:40 -0500
commit7af585f1667935165701ec290e6ce37a436ad4c6 (patch)
tree8905263cdf5e28c740176cb9dff827d33c38f5aa
parentdede5f01889e31ae7dd1e3b45f6b3852e7c0e18a (diff)
downloadgitlab-ce-7af585f1667935165701ec290e6ce37a436ad4c6.tar.gz
Fast forward merge: basic implemenation[ci skip]
-rw-r--r--app/controllers/projects_controller.rb1
-rw-r--r--app/models/project.rb17
-rw-r--r--app/models/repository.rb19
-rw-r--r--app/serializers/merge_request_entity.rb5
-rw-r--r--app/services/merge_requests/ff_merge_service.rb24
-rw-r--r--app/services/merge_requests/merge_service.rb5
-rw-r--r--app/views/projects/_merge_request_merge_settings.html.haml22
-rw-r--r--spec/lib/gitlab/import_export/safe_model_attributes.yml1
8 files changed, 94 insertions, 0 deletions
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index b13034d3333..a738ca9f361 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -344,6 +344,7 @@ class ProjectsController < Projects::ApplicationController
:tag_list,
:visibility_level,
:template_name,
+ :merge_method,
project_feature_attributes: %i[
builds_access_level
diff --git a/app/models/project.rb b/app/models/project.rb
index f7221e4f3b2..cd1fa734e78 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -1557,6 +1557,23 @@ class Project < ActiveRecord::Base
persisted? && path_changed?
end
+ def merge_method
+ if self.merge_requests_ff_only_enabled
+ :ff
+ else
+ :merge
+ end
+ end
+
+ def merge_method=(method)
+ self.merge_requests_ff_only_enabled = method.to_s == "ff"
+ end
+
+ def ff_merge_must_be_possible?
+ self.merge_requests_ff_only_enabled
+ end
+ # alias_method :merge_requests_ff_only_enabled?, :merge_requests_ff_only_enabled
+
private
def storage
diff --git a/app/models/repository.rb b/app/models/repository.rb
index f11cf1b065d..2df6c9c80da 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -854,6 +854,25 @@ class Repository
end
end
+ def ff_merge(user, source, target_branch, merge_request: nil)
+ our_commit = rugged.branches[target_branch].target
+ their_commit =
+ if source.is_a?(Gitlab::Git::Commit)
+ source.raw_commit
+ else
+ rugged.lookup(source)
+ end
+
+ raise 'Invalid merge target' if our_commit.nil?
+ raise 'Invalid merge source' if their_commit.nil?
+
+ with_branch(user, target_branch) do |start_commit|
+ merge_request&.update(in_progress_merge_commit_sha: their_commit.oid)
+
+ their_commit.oid
+ end
+ end
+
def revert(
user, commit, branch_name, message,
start_branch_name: nil, start_project: project)
diff --git a/app/serializers/merge_request_entity.rb b/app/serializers/merge_request_entity.rb
index 07650ce6f20..1f5ce2ef58c 100644
--- a/app/serializers/merge_request_entity.rb
+++ b/app/serializers/merge_request_entity.rb
@@ -13,6 +13,11 @@ class MergeRequestEntity < IssuableEntity
expose :target_branch
expose :target_project_id
+ expose :ff_only_enabled do |merge_request|
+ merge_request.project.merge_requests_ff_only_enabled
+ end
+
+
# Events
expose :merge_event, using: EventEntity
expose :closed_event, using: EventEntity
diff --git a/app/services/merge_requests/ff_merge_service.rb b/app/services/merge_requests/ff_merge_service.rb
new file mode 100644
index 00000000000..ba6853b835a
--- /dev/null
+++ b/app/services/merge_requests/ff_merge_service.rb
@@ -0,0 +1,24 @@
+module MergeRequests
+ # MergeService class
+ #
+ # Do git fast-forward merge and in case of success
+ # mark merge request as merged and execute all hooks and notifications
+ # Executed when you do fast-forward merge via GitLab UI
+ #
+ class FfMergeService < MergeRequests::MergeService
+ private
+
+ def commit
+ repository.ff_merge(current_user,
+ source,
+ merge_request.target_branch,
+ merge_request: merge_request)
+ rescue Gitlab::Git::HooksService::PreReceiveError => e
+ raise MergeError, e.message
+ rescue StandardError => e
+ raise MergeError, "Something went wrong during merge: #{e.message}"
+ ensure
+ merge_request.update(in_progress_merge_commit_sha: nil)
+ end
+ end
+end
diff --git a/app/services/merge_requests/merge_service.rb b/app/services/merge_requests/merge_service.rb
index 07cbd8f92a9..0d75c68feb2 100644
--- a/app/services/merge_requests/merge_service.rb
+++ b/app/services/merge_requests/merge_service.rb
@@ -11,6 +11,11 @@ module MergeRequests
attr_reader :merge_request, :source
def execute(merge_request)
+ if project.merge_requests_ff_only_enabled && !self.is_a?(FfMergeService)
+ FfMergeService.new(project, current_user, params).execute(merge_request)
+ return
+ end
+
@merge_request = merge_request
unless @merge_request.mergeable?
diff --git a/app/views/projects/_merge_request_merge_settings.html.haml b/app/views/projects/_merge_request_merge_settings.html.haml
index 1dd8778f800..0016526f788 100644
--- a/app/views/projects/_merge_request_merge_settings.html.haml
+++ b/app/views/projects/_merge_request_merge_settings.html.haml
@@ -1,6 +1,28 @@
- form = local_assigns.fetch(:form)
.form-group
+ = label_tag :merge_method_merge, class: 'label-light' do
+ Merge method
+ .radio
+ = label_tag :project_merge_method_merge do
+ = form.radio_button :merge_method, :merge, class: "js-merge-method-radio"
+ %strong Merge commit
+ %br
+ %span.descr
+ A merge commit is created for every merge, and merging is allowed as long as there are no conflicts.
+
+ .radio
+ = label_tag :project_merge_method_ff do
+ = form.radio_button :merge_method, :ff, class: "js-merge-method-radio"
+ %strong Fast-forward merge
+ %br
+ %span.descr
+ No merge commits are created and all merges are fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded.
+ %br
+ %span.descr
+ When fast-forward merge is not possible, the user must first rebase locally.
+
+.form-group
.checkbox.builds-feature{ class: ("hidden" if @project && @project.project_feature.send(:builds_access_level) == 0) }
= form.label :only_allow_merge_if_pipeline_succeeds do
= form.check_box :only_allow_merge_if_pipeline_succeeds
diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml
index 899d17d97c2..64b8e7f7e18 100644
--- a/spec/lib/gitlab/import_export/safe_model_attributes.yml
+++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml
@@ -412,6 +412,7 @@ Project:
- last_repository_updated_at
- ci_config_path
- delete_error
+- merge_requests_ff_only_enabled
Author:
- name
ProjectFeature: