Incorporate OperationService.UserSquash Gitaly RPC
This commit is contained in:
parent
a00aed74af
commit
e60bf2f256
5 changed files with 114 additions and 28 deletions
|
@ -1 +1 @@
|
|||
0.77.0
|
||||
0.78.0
|
||||
|
|
|
@ -1222,33 +1222,13 @@ module Gitlab
|
|||
end
|
||||
|
||||
def squash(user, squash_id, branch:, start_sha:, end_sha:, author:, message:)
|
||||
squash_path = worktree_path(SQUASH_WORKTREE_PREFIX, squash_id)
|
||||
env = git_env_for_user(user).merge(
|
||||
'GIT_AUTHOR_NAME' => author.name,
|
||||
'GIT_AUTHOR_EMAIL' => author.email
|
||||
)
|
||||
diff_range = "#{start_sha}...#{end_sha}"
|
||||
diff_files = run_git!(
|
||||
%W(diff --name-only --diff-filter=a --binary #{diff_range})
|
||||
).chomp
|
||||
|
||||
with_worktree(squash_path, branch, sparse_checkout_files: diff_files, env: env) do
|
||||
# Apply diff of the `diff_range` to the worktree
|
||||
diff = run_git!(%W(diff --binary #{diff_range}))
|
||||
run_git!(%w(apply --index), chdir: squash_path, env: env) do |stdin|
|
||||
stdin.write(diff)
|
||||
gitaly_migrate(:squash) do |is_enabled|
|
||||
if is_enabled
|
||||
gitaly_operation_client.user_squash(user, squash_id, branch,
|
||||
start_sha, end_sha, author, message)
|
||||
else
|
||||
git_squash(user, squash_id, branch, start_sha, end_sha, author, message)
|
||||
end
|
||||
|
||||
# Commit the `diff_range` diff
|
||||
run_git!(%W(commit --no-verify --message #{message}), chdir: squash_path, env: env)
|
||||
|
||||
# Return the squash sha. May print a warning for ambiguous refs, but
|
||||
# we can ignore that with `--quiet` and just take the SHA, if present.
|
||||
# HEAD here always refers to the current HEAD commit, even if there is
|
||||
# another ref called HEAD.
|
||||
run_git!(
|
||||
%w(rev-parse --quiet --verify HEAD), chdir: squash_path, env: env
|
||||
).chomp
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -2164,6 +2144,37 @@ module Gitlab
|
|||
end
|
||||
end
|
||||
|
||||
def git_squash(user, squash_id, branch, start_sha, end_sha, author, message)
|
||||
squash_path = worktree_path(SQUASH_WORKTREE_PREFIX, squash_id)
|
||||
env = git_env_for_user(user).merge(
|
||||
'GIT_AUTHOR_NAME' => author.name,
|
||||
'GIT_AUTHOR_EMAIL' => author.email
|
||||
)
|
||||
diff_range = "#{start_sha}...#{end_sha}"
|
||||
diff_files = run_git!(
|
||||
%W(diff --name-only --diff-filter=a --binary #{diff_range})
|
||||
).chomp
|
||||
|
||||
with_worktree(squash_path, branch, sparse_checkout_files: diff_files, env: env) do
|
||||
# Apply diff of the `diff_range` to the worktree
|
||||
diff = run_git!(%W(diff --binary #{diff_range}))
|
||||
run_git!(%w(apply --index), chdir: squash_path, env: env) do |stdin|
|
||||
stdin.write(diff)
|
||||
end
|
||||
|
||||
# Commit the `diff_range` diff
|
||||
run_git!(%W(commit --no-verify --message #{message}), chdir: squash_path, env: env)
|
||||
|
||||
# Return the squash sha. May print a warning for ambiguous refs, but
|
||||
# we can ignore that with `--quiet` and just take the SHA, if present.
|
||||
# HEAD here always refers to the current HEAD commit, even if there is
|
||||
# another ref called HEAD.
|
||||
run_git!(
|
||||
%w(rev-parse --quiet --verify HEAD), chdir: squash_path, env: env
|
||||
).chomp
|
||||
end
|
||||
end
|
||||
|
||||
def local_fetch_ref(source_path, source_ref:, target_ref:)
|
||||
args = %W(fetch --no-tags -f #{source_path} #{source_ref}:#{target_ref})
|
||||
run_git(args)
|
||||
|
|
|
@ -183,6 +183,32 @@ module Gitlab
|
|||
end
|
||||
end
|
||||
|
||||
def user_squash(user, squash_id, branch, start_sha, end_sha, author, message)
|
||||
request = Gitaly::UserSquashRequest.new(
|
||||
repository: @gitaly_repo,
|
||||
user: Gitlab::Git::User.from_gitlab(user).to_gitaly,
|
||||
squash_id: squash_id.to_s,
|
||||
branch: encode_binary(branch),
|
||||
start_sha: start_sha,
|
||||
end_sha: end_sha,
|
||||
author: Gitlab::Git::User.from_gitlab(author).to_gitaly,
|
||||
commit_message: encode_binary(message)
|
||||
)
|
||||
|
||||
response = GitalyClient.call(
|
||||
@repository.storage,
|
||||
:operation_service,
|
||||
:user_squash,
|
||||
request
|
||||
)
|
||||
|
||||
if response.git_error.presence
|
||||
raise Gitlab::Git::Repository::GitError, response.git_error
|
||||
end
|
||||
|
||||
response.squash_sha
|
||||
end
|
||||
|
||||
def user_commit_files(
|
||||
user, branch_name, commit_message, actions, author_email, author_name,
|
||||
start_branch_name, start_repository)
|
||||
|
|
|
@ -2183,7 +2183,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
|
|||
repository.squash(user, squash_id, opts)
|
||||
end
|
||||
|
||||
context 'sparse checkout' do
|
||||
context 'sparse checkout', :skip_gitaly_mock do
|
||||
let(:expected_files) { %w(files files/js files/js/application.js) }
|
||||
|
||||
before do
|
||||
|
|
|
@ -123,4 +123,53 @@ describe Gitlab::GitalyClient::OperationService do
|
|||
expect(subject.branch_created).to be(false)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#user_squash' do
|
||||
let(:branch_name) { 'my-branch' }
|
||||
let(:squash_id) { '1' }
|
||||
let(:start_sha) { 'b83d6e391c22777fca1ed3012fce84f633d7fed0' }
|
||||
let(:end_sha) { '54cec5282aa9f21856362fe321c800c236a61615' }
|
||||
let(:commit_message) { 'Squash message' }
|
||||
let(:request) do
|
||||
Gitaly::UserSquashRequest.new(
|
||||
repository: repository.gitaly_repository,
|
||||
user: gitaly_user,
|
||||
squash_id: squash_id.to_s,
|
||||
branch: branch_name,
|
||||
start_sha: start_sha,
|
||||
end_sha: end_sha,
|
||||
author: gitaly_user,
|
||||
commit_message: commit_message
|
||||
)
|
||||
end
|
||||
let(:squash_sha) { 'f00' }
|
||||
let(:response) { Gitaly::UserSquashResponse.new(squash_sha: squash_sha) }
|
||||
|
||||
subject do
|
||||
client.user_squash(user, squash_id, branch_name, start_sha, end_sha, user, commit_message)
|
||||
end
|
||||
|
||||
it 'sends a user_squash message and returns the squash sha' do
|
||||
expect_any_instance_of(Gitaly::OperationService::Stub)
|
||||
.to receive(:user_squash).with(request, kind_of(Hash))
|
||||
.and_return(response)
|
||||
|
||||
expect(subject).to eq(squash_sha)
|
||||
end
|
||||
|
||||
context "when git_error is present" do
|
||||
let(:response) do
|
||||
Gitaly::UserSquashResponse.new(git_error: "something failed")
|
||||
end
|
||||
|
||||
it "throws a PreReceive exception" do
|
||||
expect_any_instance_of(Gitaly::OperationService::Stub)
|
||||
.to receive(:user_squash).with(request, kind_of(Hash))
|
||||
.and_return(response)
|
||||
|
||||
expect { subject }.to raise_error(
|
||||
Gitlab::Git::Repository::GitError, "something failed")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue