Introduce Repository#with_tmp_ref which we need

commits from the other repository. We'll cleanup
the tmp ref after we're done with our business.
This commit is contained in:
Lin Jen-Shin 2016-12-08 17:57:52 +08:00
parent 23032467d4
commit 8384d0d8d5
8 changed files with 54 additions and 29 deletions

View file

@ -37,7 +37,8 @@ class Projects::CompareController < Projects::ApplicationController
end end
def define_diff_vars def define_diff_vars
@compare = CompareService.new.execute(@project, @head_ref, @project, @start_ref) @compare = CompareService.new(@project, @head_ref).
execute(@project, @start_ref)
if @compare if @compare
@commits = @compare.commits @commits = @compare.commits

View file

@ -169,7 +169,8 @@ class MergeRequestDiff < ActiveRecord::Base
# When compare merge request versions we want diff A..B instead of A...B # When compare merge request versions we want diff A..B instead of A...B
# so we handle cases when user does squash and rebase of the commits between versions. # so we handle cases when user does squash and rebase of the commits between versions.
# For this reason we set straight to true by default. # For this reason we set straight to true by default.
CompareService.new.execute(project, head_commit_sha, project, sha, straight: straight) CompareService.new(project, head_commit_sha).
execute(project, sha, straight: straight)
end end
def commits_count def commits_count

View file

@ -1099,6 +1099,21 @@ class Repository
Gitlab::Popen.popen(args, path_to_repo).first.lines.map(&:strip) Gitlab::Popen.popen(args, path_to_repo).first.lines.map(&:strip)
end end
def with_tmp_ref(source_repository, source_branch_name)
random_string = SecureRandom.hex
fetch_ref(
source_repository.path_to_repo,
"#{Gitlab::Git::BRANCH_REF_PREFIX}#{source_branch_name}",
"refs/tmp/#{random_string}/head"
)
yield
ensure
FileUtils.rm_rf("#{path_to_repo}/refs/tmp/#{random_string}")
end
def fetch_ref(source_path, source_ref, target_ref) def fetch_ref(source_path, source_ref, target_ref)
args = %W(#{Gitlab.config.git.bin_path} fetch --no-tags -f #{source_path} #{source_ref}:#{target_ref}) args = %W(#{Gitlab.config.git.bin_path} fetch --no-tags -f #{source_path} #{source_ref}:#{target_ref})
Gitlab::Popen.popen(args, path_to_repo) Gitlab::Popen.popen(args, path_to_repo)

View file

@ -3,23 +3,29 @@ require 'securerandom'
# Compare 2 branches for one repo or between repositories # Compare 2 branches for one repo or between repositories
# and return Gitlab::Git::Compare object that responds to commits and diffs # and return Gitlab::Git::Compare object that responds to commits and diffs
class CompareService class CompareService
def execute(source_project, source_branch, target_project, target_branch, straight: false) attr_reader :source_project, :source_sha
source_commit = source_project.commit(source_branch)
return unless source_commit
source_sha = source_commit.sha def initialize(new_source_project, source_branch)
@source_project = new_source_project
@source_sha = new_source_project.commit(source_branch).try(:sha)
end
def execute(target_project, target_branch, straight: false)
return unless source_sha
# If compare with other project we need to fetch ref first # If compare with other project we need to fetch ref first
unless target_project == source_project if target_project == source_project
random_string = SecureRandom.hex compare(target_project, target_branch, straight)
else
target_project.repository.fetch_ref( target_project.repository.with_tmp_ref(source_project, source_branch) do
source_project.repository.path_to_repo, compare(target_project, target_branch, straight)
"refs/heads/#{source_branch}", end
"refs/tmp/#{random_string}/head"
)
end end
end
private
def compare(target_project, target_branch, straight)
raw_compare = Gitlab::Git::Compare.new( raw_compare = Gitlab::Git::Compare.new(
target_project.repository.raw_repository, target_project.repository.raw_repository,
target_branch, target_branch,

View file

@ -38,15 +38,14 @@ GitOperationService = Struct.new(:user, :repository) do
branch_name, source_branch_name, source_project) branch_name, source_branch_name, source_project)
update_branch_with_hooks(branch_name) do |ref| update_branch_with_hooks(branch_name) do |ref|
if repository.project != source_project if repository.project == source_project
repository.fetch_ref( yield(ref)
source_project.repository.path_to_repo, else
"#{Gitlab::Git::BRANCH_REF_PREFIX}#{source_branch_name}", repository.with_tmp_ref(
"#{Gitlab::Git::BRANCH_REF_PREFIX}#{branch_name}" source_project.repository, source_branch_name) do
) yield(ref)
end
end end
yield(ref)
end end
end end

View file

@ -16,9 +16,10 @@ module MergeRequests
messages = validate_branches(merge_request) messages = validate_branches(merge_request)
return build_failed(merge_request, messages) unless messages.empty? return build_failed(merge_request, messages) unless messages.empty?
compare = CompareService.new.execute( compare = CompareService.new(
merge_request.source_project, merge_request.source_project,
merge_request.source_branch, merge_request.source_branch
).execute(
merge_request.target_project, merge_request.target_project,
merge_request.target_branch, merge_request.target_branch,
) )

View file

@ -33,13 +33,15 @@ class EmailsOnPushWorker
reverse_compare = false reverse_compare = false
if action == :push if action == :push
compare = CompareService.new.execute(project, after_sha, project, before_sha) compare = CompareService.new(project, after_sha).
execute(project, before_sha)
diff_refs = compare.diff_refs diff_refs = compare.diff_refs
return false if compare.same return false if compare.same
if compare.commits.empty? if compare.commits.empty?
compare = CompareService.new.execute(project, before_sha, project, after_sha) compare = CompareService.new(project, before_sha).
execute(project, after_sha)
diff_refs = compare.diff_refs diff_refs = compare.diff_refs
reverse_compare = true reverse_compare = true

View file

@ -3,17 +3,17 @@ require 'spec_helper'
describe CompareService, services: true do describe CompareService, services: true do
let(:project) { create(:project) } let(:project) { create(:project) }
let(:user) { create(:user) } let(:user) { create(:user) }
let(:service) { described_class.new } let(:service) { described_class.new(project, 'feature') }
describe '#execute' do describe '#execute' do
context 'compare with base, like feature...fix' do context 'compare with base, like feature...fix' do
subject { service.execute(project, 'feature', project, 'fix', straight: false) } subject { service.execute(project, 'fix', straight: false) }
it { expect(subject.diffs.size).to eq(1) } it { expect(subject.diffs.size).to eq(1) }
end end
context 'straight compare, like feature..fix' do context 'straight compare, like feature..fix' do
subject { service.execute(project, 'feature', project, 'fix', straight: true) } subject { service.execute(project, 'fix', straight: true) }
it { expect(subject.diffs.size).to eq(3) } it { expect(subject.diffs.size).to eq(3) }
end end