diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 0ef9e99123d..fbf2d8fa3ee 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -149,7 +149,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController return access_denied! unless @merge_request.can_be_merged_by?(current_user) if @merge_request.automergeable? - AutoMergeWorker.perform_async(@merge_request.id, current_user.id, params) + #AutoMergeWorker.perform_async(@merge_request.id, current_user.id, params) + @merge_request.automerge!(current_user, params[:commit_message]) @status = true else @status = false diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index aa2137e7469..e32b224eb77 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -206,11 +206,7 @@ class MergeRequest < ActiveRecord::Base def check_if_can_be_merged can_be_merged = - if for_fork? - raise 'Implement me' - else - project.repository.can_be_merged?(source_branch, target_branch) - end + project.repository.can_be_merged?(source_sha, target_branch) if can_be_merged mark_as_mergeable @@ -274,14 +270,14 @@ class MergeRequest < ActiveRecord::Base # # see "git diff" def to_diff(current_user) - raise 'Implement me' + target_project.repository.diff_text(target_branch, source_sha) end # Returns the commit as a series of email patches. # # see "git format-patch" def to_patch(current_user) - raise 'Implement me' + target_project.repository.format_patch(target_branch, source_sha) end def hook_attrs @@ -432,4 +428,13 @@ class MergeRequest < ActiveRecord::Base "Open" end end + + def target_sha + @target_sha ||= target_project. + repository.commit(target_branch).sha + end + + def source_sha + commits.first.sha + end end diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb index df1c2b78758..f3a1c91e75c 100644 --- a/app/models/merge_request_diff.rb +++ b/app/models/merge_request_diff.rb @@ -160,10 +160,12 @@ class MergeRequestDiff < ActiveRecord::Base private def compare_result + source_sha = merge_request.source_project.commit(source_branch).sha + @compare_result ||= CompareService.new.execute( merge_request.author, - merge_request.source_project, - merge_request.source_branch, + merge_request.target_project, + source_sha, merge_request.target_project, merge_request.target_branch, ) diff --git a/app/models/repository.rb b/app/models/repository.rb index 70d416159a7..1924e7ee072 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -422,15 +422,34 @@ class Repository } end - def can_be_merged?(source_branch, target_branch) + def can_be_merged?(source_sha, target_branch) our_commit = rugged.branches[target_branch].target - their_commit = rugged.branches[source_branch].target + their_commit = rugged.lookup(source_sha) if our_commit && their_commit !rugged.merge_commits(our_commit, their_commit).conflicts? end end + def merge(source_sha, target_branch, options = {}) + our_commit = rugged.branches[target_branch].target + their_commit = rugged.lookup(source_sha) + + raise "Invalid merge target" if our_commit.nil? + raise "Invalid merge source" if their_commit.nil? + + merge_index = rugged.merge_commits(our_commit, their_commit) + return false if merge_index.conflicts? + + actual_options = options.merge( + parents: [our_commit, their_commit], + tree: merge_index.write_tree(rugged), + update_ref: "refs/heads/#{target_branch}" + ) + + Rugged::Commit.create(rugged, actual_options) + end + def search_files(query, ref) offset = 2 args = %W(git grep -i -n --before-context #{offset} --after-context #{offset} #{query} #{ref || root_ref}) diff --git a/app/services/compare_service.rb b/app/services/compare_service.rb index 48ad7fab4e6..4c8b35edff8 100644 --- a/app/services/compare_service.rb +++ b/app/services/compare_service.rb @@ -1,3 +1,5 @@ +require 'securerandom' + # Compare 2 branches for one repo or between repositories # and return Gitlab::CompareResult object that responds to commits and diffs class CompareService @@ -12,7 +14,22 @@ class CompareService ) ) else - raise 'Implement me' + random_string = SecureRandom.hex + target_project.repository.fetch_ref( + source_project.repository.path_to_repo, + "refs/heads/#{source_branch}", + "refs/tmp/#{random_string}/head" + ) + + source_sha = source_project.commit(source_branch).sha + + Gitlab::CompareResult.new( + Gitlab::Git::Compare.new( + target_project.repository.raw_repository, + target_branch, + source_sha, + ) + ) end end end diff --git a/app/services/merge_requests/auto_merge_service.rb b/app/services/merge_requests/auto_merge_service.rb index 1c41148d41d..3db498acfcd 100644 --- a/app/services/merge_requests/auto_merge_service.rb +++ b/app/services/merge_requests/auto_merge_service.rb @@ -31,12 +31,8 @@ module MergeRequests end def merge! - if merge_request.for_fork? - raise 'Implement me' - else - if sha = commit - after_commit(sha, merge_request.target_branch) - end + if sha = commit + after_commit(sha, merge_request.target_branch) end end @@ -49,7 +45,7 @@ module MergeRequests committer: committer } - repository.merge(merge_request.source_branch, merge_request.target_branch, options) + repository.merge(merge_request.source_sha, merge_request.target_branch, options) end def after_commit(sha, branch) diff --git a/app/views/projects/merge_requests/_new_submit.html.haml b/app/views/projects/merge_requests/_new_submit.html.haml index 633a54f3620..76f44211dac 100644 --- a/app/views/projects/merge_requests/_new_submit.html.haml +++ b/app/views/projects/merge_requests/_new_submit.html.haml @@ -24,7 +24,7 @@ = icon('history') Commits %span.badge= @commits.size - %li.diffs-tab + %li.diffs-tab.active = link_to url_for(params), data: {target: '#diffs', action: 'diffs', toggle: 'tab'} do = icon('list-alt') Changes @@ -33,7 +33,7 @@ .tab-content #commits.commits.tab-pane = render "projects/commits/commits", project: @project - #diffs.diffs.tab-pane + #diffs.diffs.tab-pane.active - if @diffs.present? = render "projects/diffs/diffs", diffs: @diffs, project: @project - elsif @commits.size > MergeRequestDiff::COMMITS_SAFE_SIZE