diff options
author | Lin Jen-Shin <godfat@godfat.org> | 2016-12-10 00:40:23 +0800 |
---|---|---|
committer | Lin Jen-Shin <godfat@godfat.org> | 2016-12-10 00:40:23 +0800 |
commit | bb9d30590d4ca5b25d5020234916ce961acf15b6 (patch) | |
tree | 22eb73a17b42b86fbe2cc24f1429a4a8af2f76f1 | |
parent | 5a115671b9d7c22daf8160d7284786d0f8b216cb (diff) | |
download | gitlab-ce-bb9d30590d4ca5b25d5020234916ce961acf15b6.tar.gz |
Pass source_commit so that we save a few lookups
-rw-r--r-- | app/models/repository.rb | 51 | ||||
-rw-r--r-- | app/services/git_operation_service.rb | 25 | ||||
-rw-r--r-- | spec/models/repository_spec.rb | 28 |
3 files changed, 54 insertions, 50 deletions
diff --git a/app/models/repository.rb b/app/models/repository.rb index 389d52f8c0f..4034a49ae63 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -849,15 +849,12 @@ class Repository GitOperationService.new(user, self).with_branch( branch_name, source_branch_name: source_branch_name, - source_project: source_project) do + source_project: source_project) do |source_commit| index = rugged.index - branch_commit = source_project.repository.find_branch( - source_branch_name || branch_name) - parents = if branch_commit - last_commit = branch_commit.dereferenced_target - index.read_tree(last_commit.raw_commit.tree) - [last_commit.sha] + parents = if source_commit + index.read_tree(source_commit.raw_commit.tree) + [source_commit.sha] else [] end @@ -904,17 +901,17 @@ class Repository end def merge(user, merge_request, options = {}) - our_commit = rugged.branches[merge_request.target_branch].target - their_commit = rugged.lookup(merge_request.diff_head_sha) + GitOperationService.new(user, self).with_branch( + 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" if our_commit.nil? - raise "Invalid merge source" if their_commit.nil? + raise 'Invalid merge target' unless our_commit + raise 'Invalid merge source' unless their_commit - merge_index = rugged.merge_commits(our_commit, their_commit) - return false if merge_index.conflicts? + merge_index = rugged.merge_commits(our_commit, their_commit) + break if merge_index.conflicts? - GitOperationService.new(user, self).with_branch( - merge_request.target_branch) do actual_options = options.merge( parents: [our_commit, their_commit], tree: merge_index.write_tree(rugged), @@ -924,6 +921,8 @@ class Repository merge_request.update(in_progress_merge_commit_sha: commit_id) commit_id end + rescue Repository::CommitError # when merge_index.conflicts? + false end def revert( @@ -936,10 +935,8 @@ class Repository GitOperationService.new(user, self).with_branch( 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) Rugged::Commit.create(rugged, @@ -947,7 +944,7 @@ class Repository author: committer, committer: committer, tree: revert_tree_id, - parents: [rugged.lookup(source_sha)]) + parents: [source_commit.sha]) end end @@ -961,10 +958,8 @@ class Repository GitOperationService.new(user, self).with_branch( 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) Rugged::Commit.create(rugged, @@ -976,7 +971,7 @@ class Repository }, committer: committer, tree: cherry_pick_tree_id, - parents: [rugged.lookup(source_sha)]) + parents: [source_commit.sha]) end end @@ -1145,16 +1140,6 @@ class Repository 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 def git_action(index, action) diff --git a/app/services/git_operation_service.rb b/app/services/git_operation_service.rb index a7d267cd6b4..62a9eda3eba 100644 --- a/app/services/git_operation_service.rb +++ b/app/services/git_operation_service.rb @@ -37,13 +37,16 @@ GitOperationService = Struct.new(:user, :repository) do check_with_branch_arguments!( 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 - yield(ref) + yield(source_commit) else repository.with_tmp_ref( source_project.repository, source_branch_name) do - yield(ref) + yield(source_commit) end end end @@ -54,31 +57,29 @@ GitOperationService = Struct.new(:user, :repository) do def update_branch_with_hooks(branch_name) update_autocrlf_option - ref = Gitlab::Git::BRANCH_REF_PREFIX + branch_name - oldrev = Gitlab::Git::BLANK_SHA was_empty = repository.empty? # Make commit - newrev = yield(ref) + newrev = yield unless newrev raise Repository::CommitError.new('Failed to create commit') end branch = repository.find_branch(branch_name) - oldrev = if repository.rugged.lookup(newrev).parent_ids.empty? || - branch.nil? - Gitlab::Git::BLANK_SHA + oldrev = if branch + # This could verify we're not losing commits + repository.rugged.merge_base(newrev, branch.target) else - repository.rugged.merge_base( - newrev, branch.dereferenced_target.sha) + Gitlab::Git::BLANK_SHA end + ref = Gitlab::Git::BRANCH_REF_PREFIX + branch_name with_hooks_and_update_ref(ref, oldrev, newrev) do # If repo was empty expire cache repository.after_create if was_empty repository.after_create_branch if was_empty || - oldrev == Gitlab::Git::BLANK_SHA + Gitlab::Git.blank_ref?(oldrev) end newrev diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index 9cc13a9a25b..a61d7f0c76d 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -257,6 +257,24 @@ describe Repository, models: true do expect(newdir.path).to eq('newdir') 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 it "uses the given email/name to set the commit's author" do expect do @@ -758,9 +776,9 @@ describe Repository, models: true do end context 'when the update adds more than one commit' do - it 'runs without errors' do - old_rev = '33f3729a45c02fc67d00adb1b8bca394b0e761d9' + let(:old_rev) { '33f3729a45c02fc67d00adb1b8bca394b0e761d9' } + it 'runs without errors' do # old_rev is an ancestor of new_rev expect(repository.rugged.merge_base(old_rev, new_rev)).to eq(old_rev) @@ -779,10 +797,10 @@ describe Repository, models: true do end context 'when the update would remove commits from the target branch' do - it 'raises an exception' do - branch = 'master' - old_rev = repository.find_branch(branch).dereferenced_target.sha + let(:branch) { 'master' } + let(:old_rev) { repository.find_branch(branch).dereferenced_target.sha } + it 'raises an exception' do # The 'master' branch is NOT an ancestor of new_rev. expect(repository.rugged.merge_base(old_rev, new_rev)).not_to eq(old_rev) |