Pass source_commit so that we save a few lookups

This commit is contained in:
Lin Jen-Shin 2016-12-10 00:40:23 +08:00
parent 5a115671b9
commit bb9d30590d
3 changed files with 56 additions and 52 deletions

View file

@ -849,15 +849,12 @@ class Repository
GitOperationService.new(user, self).with_branch( GitOperationService.new(user, self).with_branch(
branch_name, branch_name,
source_branch_name: source_branch_name, source_branch_name: source_branch_name,
source_project: source_project) do source_project: source_project) do |source_commit|
index = rugged.index index = rugged.index
branch_commit = source_project.repository.find_branch(
source_branch_name || branch_name)
parents = if branch_commit parents = if source_commit
last_commit = branch_commit.dereferenced_target index.read_tree(source_commit.raw_commit.tree)
index.read_tree(last_commit.raw_commit.tree) [source_commit.sha]
[last_commit.sha]
else else
[] []
end end
@ -904,17 +901,17 @@ class Repository
end end
def merge(user, merge_request, options = {}) def merge(user, merge_request, options = {})
our_commit = rugged.branches[merge_request.target_branch].target
their_commit = rugged.lookup(merge_request.diff_head_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?
GitOperationService.new(user, self).with_branch( GitOperationService.new(user, self).with_branch(
merge_request.target_branch) do merge_request.target_branch) do |source_commit|
our_commit = source_commit.raw_commit
their_commit = rugged.lookup(merge_request.diff_head_sha)
raise 'Invalid merge target' unless our_commit
raise 'Invalid merge source' unless their_commit
merge_index = rugged.merge_commits(our_commit, their_commit)
break if merge_index.conflicts?
actual_options = options.merge( actual_options = options.merge(
parents: [our_commit, their_commit], parents: [our_commit, their_commit],
tree: merge_index.write_tree(rugged), tree: merge_index.write_tree(rugged),
@ -924,6 +921,8 @@ class Repository
merge_request.update(in_progress_merge_commit_sha: commit_id) merge_request.update(in_progress_merge_commit_sha: commit_id)
commit_id commit_id
end end
rescue Repository::CommitError # when merge_index.conflicts?
false
end end
def revert( def revert(
@ -936,10 +935,8 @@ class Repository
GitOperationService.new(user, self).with_branch( GitOperationService.new(user, self).with_branch(
branch_name, branch_name,
source_branch_name: source_branch_name, source_branch_name: source_branch_name,
source_project: source_project) do source_project: source_project) do |source_commit|
source_sha = source_project.repository.find_source_sha(
source_branch_name || branch_name)
committer = user_to_committer(user) committer = user_to_committer(user)
Rugged::Commit.create(rugged, Rugged::Commit.create(rugged,
@ -947,7 +944,7 @@ class Repository
author: committer, author: committer,
committer: committer, committer: committer,
tree: revert_tree_id, tree: revert_tree_id,
parents: [rugged.lookup(source_sha)]) parents: [source_commit.sha])
end end
end end
@ -961,10 +958,8 @@ class Repository
GitOperationService.new(user, self).with_branch( GitOperationService.new(user, self).with_branch(
branch_name, branch_name,
source_branch_name: source_branch_name, source_branch_name: source_branch_name,
source_project: source_project) do source_project: source_project) do |source_commit|
source_sha = source_project.repository.find_source_sha(
source_branch_name || branch_name)
committer = user_to_committer(user) committer = user_to_committer(user)
Rugged::Commit.create(rugged, Rugged::Commit.create(rugged,
@ -976,7 +971,7 @@ class Repository
}, },
committer: committer, committer: committer,
tree: cherry_pick_tree_id, tree: cherry_pick_tree_id,
parents: [rugged.lookup(source_sha)]) parents: [source_commit.sha])
end end
end end
@ -1145,16 +1140,6 @@ class Repository
end end
end end
protected
def find_source_sha(branch_name)
if branch_exists?(branch_name)
find_branch(branch_name).dereferenced_target.sha
else
Gitlab::Git::BLANK_SHA
end
end
private private
def git_action(index, action) def git_action(index, action)

View file

@ -37,13 +37,16 @@ GitOperationService = Struct.new(:user, :repository) do
check_with_branch_arguments!( check_with_branch_arguments!(
branch_name, source_branch_name, source_project) branch_name, source_branch_name, source_project)
update_branch_with_hooks(branch_name) do |ref| source_commit = source_project.repository.find_branch(
source_branch_name || branch_name).try(:dereferenced_target)
update_branch_with_hooks(branch_name) do
if repository.project == source_project if repository.project == source_project
yield(ref) yield(source_commit)
else else
repository.with_tmp_ref( repository.with_tmp_ref(
source_project.repository, source_branch_name) do source_project.repository, source_branch_name) do
yield(ref) yield(source_commit)
end end
end end
end end
@ -54,31 +57,29 @@ GitOperationService = Struct.new(:user, :repository) do
def update_branch_with_hooks(branch_name) def update_branch_with_hooks(branch_name)
update_autocrlf_option update_autocrlf_option
ref = Gitlab::Git::BRANCH_REF_PREFIX + branch_name
oldrev = Gitlab::Git::BLANK_SHA
was_empty = repository.empty? was_empty = repository.empty?
# Make commit # Make commit
newrev = yield(ref) newrev = yield
unless newrev unless newrev
raise Repository::CommitError.new('Failed to create commit') raise Repository::CommitError.new('Failed to create commit')
end end
branch = repository.find_branch(branch_name) branch = repository.find_branch(branch_name)
oldrev = if repository.rugged.lookup(newrev).parent_ids.empty? || oldrev = if branch
branch.nil? # This could verify we're not losing commits
Gitlab::Git::BLANK_SHA repository.rugged.merge_base(newrev, branch.target)
else else
repository.rugged.merge_base( Gitlab::Git::BLANK_SHA
newrev, branch.dereferenced_target.sha)
end end
ref = Gitlab::Git::BRANCH_REF_PREFIX + branch_name
with_hooks_and_update_ref(ref, oldrev, newrev) do with_hooks_and_update_ref(ref, oldrev, newrev) do
# If repo was empty expire cache # If repo was empty expire cache
repository.after_create if was_empty repository.after_create if was_empty
repository.after_create_branch if was_empty || repository.after_create_branch if was_empty ||
oldrev == Gitlab::Git::BLANK_SHA Gitlab::Git.blank_ref?(oldrev)
end end
newrev newrev

View file

@ -257,6 +257,24 @@ describe Repository, models: true do
expect(newdir.path).to eq('newdir') expect(newdir.path).to eq('newdir')
end end
context "when committing to another project" do
let(:forked_project) { create(:project) }
it "creates a fork and commit to the forked project" do
expect do
repository.commit_dir(user, 'newdir',
message: 'Create newdir', branch_name: 'patch',
source_branch_name: 'master', source_project: forked_project)
end.to change { repository.commits('master').count }.by(0)
expect(repository.branch_exists?('patch')).to be_truthy
expect(forked_project.repository.branch_exists?('patch')).to be_falsy
newdir = repository.tree('patch', 'newdir')
expect(newdir.path).to eq('newdir')
end
end
context "when an author is specified" do context "when an author is specified" do
it "uses the given email/name to set the commit's author" do it "uses the given email/name to set the commit's author" do
expect do expect do
@ -758,9 +776,9 @@ describe Repository, models: true do
end end
context 'when the update adds more than one commit' do context 'when the update adds more than one commit' do
it 'runs without errors' do let(:old_rev) { '33f3729a45c02fc67d00adb1b8bca394b0e761d9' }
old_rev = '33f3729a45c02fc67d00adb1b8bca394b0e761d9'
it 'runs without errors' do
# old_rev is an ancestor of new_rev # old_rev is an ancestor of new_rev
expect(repository.rugged.merge_base(old_rev, new_rev)).to eq(old_rev) expect(repository.rugged.merge_base(old_rev, new_rev)).to eq(old_rev)
@ -779,10 +797,10 @@ describe Repository, models: true do
end end
context 'when the update would remove commits from the target branch' do context 'when the update would remove commits from the target branch' do
it 'raises an exception' do let(:branch) { 'master' }
branch = 'master' let(:old_rev) { repository.find_branch(branch).dereferenced_target.sha }
old_rev = repository.find_branch(branch).dereferenced_target.sha
it 'raises an exception' do
# The 'master' branch is NOT an ancestor of new_rev. # The 'master' branch is NOT an ancestor of new_rev.
expect(repository.rugged.merge_base(old_rev, new_rev)).not_to eq(old_rev) expect(repository.rugged.merge_base(old_rev, new_rev)).not_to eq(old_rev)