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:
authorPatrick Steinhardt <psteinhardt@gitlab.com>2023-08-18 11:37:23 +0300
committerPatrick Steinhardt <psteinhardt@gitlab.com>2023-08-18 11:45:05 +0300
commita7c90997007b25d4a7dedc340fe57bd787529541 (patch)
tree21524463d066a7ba29bd69c41368041b0da7d995
parent3735c107042fc9eed44bda1dc600684ee16a1c92 (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.go10
-rw-r--r--internal/gitaly/service/operations/rebase_to_ref.go47
-rw-r--r--internal/gitaly/service/operations/rebase_to_ref_test.go32
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"))