diff options
author | Patrick Steinhardt <psteinhardt@gitlab.com> | 2023-08-18 11:37:23 +0300 |
---|---|---|
committer | Patrick Steinhardt <psteinhardt@gitlab.com> | 2023-08-18 11:45:05 +0300 |
commit | a7c90997007b25d4a7dedc340fe57bd787529541 (patch) | |
tree | 21524463d066a7ba29bd69c41368041b0da7d995 | |
parent | 3735c107042fc9eed44bda1dc600684ee16a1c92 (diff) |
operations: Implement UserRebaseToRef via plain Git
In 78cd66c96 (localrepo: Add a basic rebase support, 2023-07-31), we
have added basic rebase support that is implemented via plain Git
instead of libgit2. And while we have ported UserRebaseConfirmable to
use this new functionality, we didn't yet port UserRebaseToRef.
Port over UserRebaseToRef to use the new plain Git implementation.
Changelog: changed
-rw-r--r-- | internal/featureflag/ff_user_rebase_to_ref_pure_git.go | 10 | ||||
-rw-r--r-- | internal/gitaly/service/operations/rebase_to_ref.go | 47 | ||||
-rw-r--r-- | internal/gitaly/service/operations/rebase_to_ref_test.go | 32 |
3 files changed, 73 insertions, 16 deletions
diff --git a/internal/featureflag/ff_user_rebase_to_ref_pure_git.go b/internal/featureflag/ff_user_rebase_to_ref_pure_git.go new file mode 100644 index 000000000..e81a1f5e0 --- /dev/null +++ b/internal/featureflag/ff_user_rebase_to_ref_pure_git.go @@ -0,0 +1,10 @@ +package featureflag + +// UserRebaseToRefPureGit will enable the UserRebaseToRef RPC to +// use a pure git implemented rebase instead of git2go. +var UserRebaseToRefPureGit = NewFeatureFlag( + "user_rebase_to_ref_pure_git", + "v16.4.0", + "https://gitlab.com/gitlab-org/gitaly/-/issues/5524", + false, +) diff --git a/internal/gitaly/service/operations/rebase_to_ref.go b/internal/gitaly/service/operations/rebase_to_ref.go index 277d99fda..82b931890 100644 --- a/internal/gitaly/service/operations/rebase_to_ref.go +++ b/internal/gitaly/service/operations/rebase_to_ref.go @@ -6,7 +6,9 @@ import ( "fmt" "time" + "gitlab.com/gitlab-org/gitaly/v16/internal/featureflag" "gitlab.com/gitlab-org/gitaly/v16/internal/git" + "gitlab.com/gitlab-org/gitaly/v16/internal/git/localrepo" "gitlab.com/gitlab-org/gitaly/v16/internal/git2go" "gitlab.com/gitlab-org/gitaly/v16/internal/structerr" "gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb" @@ -84,21 +86,40 @@ func (s *Server) UserRebaseToRef(ctx context.Context, request *gitalypb.UserReba committer.When = request.Timestamp.AsTime() } - rebasedOID, err := s.git2goExecutor.Rebase(ctx, quarantineRepo, git2go.RebaseCommand{ - Repository: repoPath, - Committer: committer, - CommitID: sourceOID, - UpstreamCommitID: oid, - SkipEmptyCommits: true, - }) - if err != nil { - var conflictErr git2go.ConflictingFilesError - if errors.As(err, &conflictErr) { - return nil, structerr.NewFailedPrecondition("failed to rebase %s on %s while preparing %s due to conflict", - sourceOID, oid, string(request.TargetRef)) + var rebasedOID git.ObjectID + if featureflag.UserRebaseToRefPureGit.IsEnabled(ctx) { + rebasedOID, err = quarantineRepo.Rebase( + ctx, + oid.String(), + sourceOID.String(), + localrepo.RebaseWithCommitter(committer), + ) + if err != nil { + var conflictErr *localrepo.RebaseConflictError + if errors.As(err, &conflictErr) { + return nil, structerr.NewFailedPrecondition("failed to rebase %s on %s while preparing %s due to conflict", + sourceOID, oid, string(request.TargetRef)) + } + + return nil, structerr.NewInternal("rebasing commits: %w", err) } + } else { + rebasedOID, err = s.git2goExecutor.Rebase(ctx, quarantineRepo, git2go.RebaseCommand{ + Repository: repoPath, + Committer: committer, + CommitID: sourceOID, + UpstreamCommitID: oid, + SkipEmptyCommits: true, + }) + if err != nil { + var conflictErr git2go.ConflictingFilesError + if errors.As(err, &conflictErr) { + return nil, structerr.NewFailedPrecondition("failed to rebase %s on %s while preparing %s due to conflict", + sourceOID, oid, string(request.TargetRef)) + } - return nil, structerr.NewInternal("rebasing commits: %w", err) + return nil, structerr.NewInternal("rebasing commits: %w", err) + } } if err := quarantineDir.Migrate(); err != nil { diff --git a/internal/gitaly/service/operations/rebase_to_ref_test.go b/internal/gitaly/service/operations/rebase_to_ref_test.go index 49afe5f46..7f464d0c6 100644 --- a/internal/gitaly/service/operations/rebase_to_ref_test.go +++ b/internal/gitaly/service/operations/rebase_to_ref_test.go @@ -3,11 +3,13 @@ package operations import ( + "context" "errors" "fmt" "testing" "github.com/stretchr/testify/require" + "gitlab.com/gitlab-org/gitaly/v16/internal/featureflag" "gitlab.com/gitlab-org/gitaly/v16/internal/git" "gitlab.com/gitlab-org/gitaly/v16/internal/git/gittest" "gitlab.com/gitlab-org/gitaly/v16/internal/git/localrepo" @@ -20,8 +22,16 @@ import ( func TestUserRebaseToRef_successful(t *testing.T) { t.Parallel() + testhelper.NewFeatureSets( + featureflag.GPGSigning, + featureflag.UserRebaseToRefPureGit, + ).Run(t, testUserRebaseToRefSuccessful) +} + +func testUserRebaseToRefSuccessful(t *testing.T, ctx context.Context) { + t.Parallel() - ctx, cfg, client := setupOperationsServiceWithoutRepo(t, testhelper.Context(t)) + ctx, cfg, client := setupOperationsServiceWithoutRepo(t, ctx) repoProto, repoPath := gittest.CreateRepository(t, ctx, cfg) repo := localrepo.NewTestRepo(t, cfg, repoProto) @@ -76,8 +86,16 @@ func TestUserRebaseToRef_successful(t *testing.T) { func TestUserRebaseToRef_failure(t *testing.T) { t.Parallel() + testhelper.NewFeatureSets( + featureflag.GPGSigning, + featureflag.UserRebaseToRefPureGit, + ).Run(t, testUserRebaseToRefFailure) +} - ctx, cfg, client := setupOperationsServiceWithoutRepo(t, testhelper.Context(t)) +func testUserRebaseToRefFailure(t *testing.T, ctx context.Context) { + t.Parallel() + + ctx, cfg, client := setupOperationsServiceWithoutRepo(t, ctx) repo, repoPath := gittest.CreateRepository(t, ctx, cfg) mergeBaseOID := gittest.WriteCommit(t, cfg, repoPath, gittest.WithMessage("first commit")) @@ -194,8 +212,16 @@ func TestUserRebaseToRef_failure(t *testing.T) { func TestUserRebaseToRef_conflict(t *testing.T) { t.Parallel() + testhelper.NewFeatureSets( + featureflag.GPGSigning, + featureflag.UserRebaseToRefPureGit, + ).Run(t, testUserRebaseToRefConflict) +} + +func testUserRebaseToRefConflict(t *testing.T, ctx context.Context) { + t.Parallel() - ctx, cfg, client := setupOperationsServiceWithoutRepo(t, testhelper.Context(t)) + ctx, cfg, client := setupOperationsServiceWithoutRepo(t, ctx) repoProto, repoPath := gittest.CreateRepository(t, ctx, cfg) mergeBaseOID := gittest.WriteCommit(t, cfg, repoPath, gittest.WithMessage("first commit")) |