Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitaly.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Cai <jcai@gitlab.com>2020-04-27 19:15:16 +0300
committerJohn Cai <jcai@gitlab.com>2020-04-27 19:15:16 +0300
commit738599c95a53b970efaf694fdf921163fded42b5 (patch)
treebdd5548d30f11a8f37fc1225c16d4ce24e652ffe
parentca7faa446b4db4713ad128698d4130aa4de8a26e (diff)
parenta16627f7b2bad16f72d58ad36ddb8686505360c0 (diff)
Merge branch 'sh-fix-rebase' into 'master'
Fix rebase when diff contains only deleted files Closes gitlab#209817 See merge request gitlab-org/gitaly!2109
-rw-r--r--changelogs/unreleased/sh-fix-rebase.yml5
-rw-r--r--internal/service/operations/rebase_test.go64
-rw-r--r--ruby/lib/gitlab/git/repository.rb20
3 files changed, 88 insertions, 1 deletions
diff --git a/changelogs/unreleased/sh-fix-rebase.yml b/changelogs/unreleased/sh-fix-rebase.yml
new file mode 100644
index 000000000..54a81afc2
--- /dev/null
+++ b/changelogs/unreleased/sh-fix-rebase.yml
@@ -0,0 +1,5 @@
+---
+title: Fix rebase when diff contains only deleted files
+merge_request: 2109
+author:
+type: fixed
diff --git a/internal/service/operations/rebase_test.go b/internal/service/operations/rebase_test.go
index da254dced..222c723fd 100644
--- a/internal/service/operations/rebase_test.go
+++ b/internal/service/operations/rebase_test.go
@@ -404,6 +404,70 @@ func getBranchSha(t *testing.T, repoPath string, branchName string) string {
return strings.TrimSpace(branchSha)
}
+func TestRebaseRequestWithDeletedFile(t *testing.T) {
+ ctxOuter, cancel := testhelper.Context()
+ defer cancel()
+
+ server, serverSocketPath := runFullServerWithHooks(t)
+ defer server.Stop()
+
+ client, conn := operations.NewOperationClient(t, serverSocketPath)
+ defer conn.Close()
+
+ testRepo, testRepoPath, cleanupFn := testhelper.NewTestRepoWithWorktree(t)
+ defer cleanupFn()
+
+ testRepoCopy, _, cleanup := testhelper.NewTestRepo(t)
+ defer cleanup()
+
+ cleanupSrv := operations.SetupAndStartGitlabServer(t, rebaseUser.GlId, testRepo.GlRepository)
+ defer cleanupSrv()
+
+ md := testhelper.GitalyServersMetadata(t, serverSocketPath)
+ ctx := metadata.NewOutgoingContext(ctxOuter, md)
+
+ branch := "rebase-delete-test"
+
+ testhelper.MustRunCommand(t, nil, "git", "-C", testRepoPath, "config", "user.name", string(rebaseUser.Name))
+ testhelper.MustRunCommand(t, nil, "git", "-C", testRepoPath, "config", "user.email", string(rebaseUser.Email))
+ testhelper.MustRunCommand(t, nil, "git", "-C", testRepoPath, "checkout", "-b", branch, "master~1")
+ testhelper.MustRunCommand(t, nil, "git", "-C", testRepoPath, "rm", "README")
+ testhelper.MustRunCommand(t, nil, "git", "-C", testRepoPath, "commit", "-a", "-m", "delete file")
+
+ branchSha := getBranchSha(t, testRepoPath, branch)
+
+ rebaseStream, err := client.UserRebaseConfirmable(ctx)
+ require.NoError(t, err)
+
+ headerRequest := buildHeaderRequest(testRepo, rebaseUser, "1", branch, branchSha, testRepoCopy, "master")
+ require.NoError(t, rebaseStream.Send(headerRequest), "send header")
+
+ firstResponse, err := rebaseStream.Recv()
+ require.NoError(t, err, "receive first response")
+
+ _, err = gitlog.GetCommit(ctx, testRepo, firstResponse.GetRebaseSha())
+ require.NoError(t, err, "look up git commit before rebase is applied")
+
+ applyRequest := buildApplyRequest(true)
+ require.NoError(t, rebaseStream.Send(applyRequest), "apply rebase")
+
+ secondResponse, err := rebaseStream.Recv()
+ require.NoError(t, err, "receive second response")
+
+ err = testhelper.ReceiveEOFWithTimeout(func() error {
+ _, err = rebaseStream.Recv()
+ return err
+ })
+ require.NoError(t, err, "consume EOF")
+
+ newBranchSha := getBranchSha(t, testRepoPath, branch)
+
+ require.NotEqual(t, newBranchSha, branchSha)
+ require.Equal(t, newBranchSha, firstResponse.GetRebaseSha())
+
+ require.True(t, secondResponse.GetRebaseApplied(), "the second rebase is applied")
+}
+
// This error is used as a sentinel value
var errRecvTimeout = errors.New("timeout waiting for response")
diff --git a/ruby/lib/gitlab/git/repository.rb b/ruby/lib/gitlab/git/repository.rb
index 80b4c24ef..942880482 100644
--- a/ruby/lib/gitlab/git/repository.rb
+++ b/ruby/lib/gitlab/git/repository.rb
@@ -736,6 +736,14 @@ module Gitlab
private
+ def sparse_checkout_empty?(output)
+ output.include?("error: Sparse checkout leaves no entry on working directory")
+ end
+
+ def disable_sparse_checkout
+ run_git!(%w[config core.sparseCheckout false], include_stderr: true)
+ end
+
def create_merge_commit(user, our_commit, their_commit, message)
raise 'Invalid merge target' unless our_commit
raise 'Invalid merge source' unless their_commit
@@ -884,7 +892,17 @@ module Gitlab
configure_sparse_checkout(worktree_git_path, sparse_checkout_files)
# After sparse checkout configuration, checkout `branch` in worktree
- run_git!(%W[checkout --detach #{branch}], chdir: worktree.path, env: env, include_stderr: true)
+ output, cmd_status = run_git(%W[checkout --detach #{branch}], chdir: worktree.path, env: env, include_stderr: true)
+
+ # If sparse checkout fails, fall back to a regular checkout.
+ if cmd_status.nonzero?
+ if sparse_checkout_empty?(output)
+ disable_sparse_checkout
+ run_git!(%W[checkout --detach #{branch}], chdir: worktree.path, env: env, include_stderr: true)
+ else
+ raise GitError, output
+ end
+ end
else
# Create worktree and checkout `branch` in it
run_git!(base_args + [worktree.path, branch], env: env, include_stderr: true)