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
path: root/cmd
diff options
context:
space:
mode:
authorPatrick Steinhardt <psteinhardt@gitlab.com>2023-09-05 10:42:53 +0300
committerPatrick Steinhardt <psteinhardt@gitlab.com>2023-09-05 10:42:53 +0300
commit4325481ab92a44ae5de5f58e126fe1202512998a (patch)
tree7afd7ecb9bb3464b9f7e94b00f64cb4eceaa8695 /cmd
parent516b9e1684879959073a19cfe7e3a024ee2f95ec (diff)
gitaly-git2go: Remove the now-unused command
Remove the now-unused gitaly-git2o command as well as its supporting infrastructure.
Diffstat (limited to 'cmd')
-rw-r--r--cmd/gitaly-git2go/featureflags.go41
-rw-r--r--cmd/gitaly-git2go/git2goutil/commit.go47
-rw-r--r--cmd/gitaly-git2go/git2goutil/repo.go10
-rw-r--r--cmd/gitaly-git2go/git2goutil/sign.go22
-rw-r--r--cmd/gitaly-git2go/main.go165
-rw-r--r--cmd/gitaly-git2go/merge.go57
-rw-r--r--cmd/gitaly-git2go/rebase.go192
-rw-r--r--cmd/gitaly-git2go/rebase_test.go423
-rw-r--r--cmd/gitaly-git2go/testhelper_test.go44
-rw-r--r--cmd/gitaly-git2go/util.go32
10 files changed, 0 insertions, 1033 deletions
diff --git a/cmd/gitaly-git2go/featureflags.go b/cmd/gitaly-git2go/featureflags.go
deleted file mode 100644
index 055f18be9..000000000
--- a/cmd/gitaly-git2go/featureflags.go
+++ /dev/null
@@ -1,41 +0,0 @@
-//go:build static && system_libgit2 && gitaly_test
-
-package main
-
-import (
- "context"
- "encoding/gob"
- "flag"
-
- "gitlab.com/gitlab-org/gitaly/v16/internal/featureflag"
- "gitlab.com/gitlab-org/gitaly/v16/internal/git2go"
-)
-
-// This subcommand is only called in tests, so we don't want to register it like
-// the other subcommands but instead will do it in an init block. The gitaly_test build
-// flag will guarantee that this is not built and registered in the
-// gitaly-git2go binary
-func init() {
- subcommands["feature-flags"] = &featureFlagsSubcommand{}
-}
-
-type featureFlagsSubcommand struct{}
-
-func (featureFlagsSubcommand) Flags() *flag.FlagSet {
- return flag.NewFlagSet("feature-flags", flag.ExitOnError)
-}
-
-func (featureFlagsSubcommand) Run(ctx context.Context, decoder *gob.Decoder, encoder *gob.Encoder) error {
- var flags []git2go.FeatureFlag
- for flag, value := range featureflag.FromContext(ctx) {
- flags = append(flags, git2go.FeatureFlag{
- Name: flag.Name,
- MetadataKey: flag.MetadataKey(),
- Value: value,
- })
- }
-
- return encoder.Encode(git2go.FeatureFlags{
- Flags: flags,
- })
-}
diff --git a/cmd/gitaly-git2go/git2goutil/commit.go b/cmd/gitaly-git2go/git2goutil/commit.go
deleted file mode 100644
index 804715884..000000000
--- a/cmd/gitaly-git2go/git2goutil/commit.go
+++ /dev/null
@@ -1,47 +0,0 @@
-package git2goutil
-
-import (
- "fmt"
-
- git "github.com/libgit2/git2go/v34"
-)
-
-// CommitSubmitter is the helper struct to make signed Commits conveniently.
-type CommitSubmitter struct {
- Repo *git.Repository
- SigningKeyPath string
-}
-
-// NewCommitSubmitter creates a new CommitSubmitter.
-func NewCommitSubmitter(repo *git.Repository, signingKeyPath string) *CommitSubmitter {
- return &CommitSubmitter{
- Repo: repo,
- SigningKeyPath: signingKeyPath,
- }
-}
-
-// Commit commits a commit with or without signature depends on SigningKeyPath value.
-func (cs *CommitSubmitter) Commit(
- author, committer *git.Signature,
- messageEncoding git.MessageEncoding,
- message string,
- tree *git.Tree,
- parents ...*git.Commit,
-) (*git.Oid, error) {
- commitBytes, err := cs.Repo.CreateCommitBuffer(author, committer, messageEncoding, message, tree, parents...)
- if err != nil {
- return nil, err
- }
-
- signature, err := CreateCommitSignature(cs.SigningKeyPath, commitBytes)
- if err != nil {
- return nil, fmt.Errorf("create commit signature: %w", err)
- }
-
- commitID, err := cs.Repo.CreateCommitWithSignature(string(commitBytes), string(signature), "")
- if err != nil {
- return nil, err
- }
-
- return commitID, nil
-}
diff --git a/cmd/gitaly-git2go/git2goutil/repo.go b/cmd/gitaly-git2go/git2goutil/repo.go
deleted file mode 100644
index 1a1c4ede2..000000000
--- a/cmd/gitaly-git2go/git2goutil/repo.go
+++ /dev/null
@@ -1,10 +0,0 @@
-package git2goutil
-
-import (
- git "github.com/libgit2/git2go/v34"
-)
-
-// OpenRepository opens the repository located at path as a Git2Go repository.
-func OpenRepository(path string) (*git.Repository, error) {
- return git.OpenRepositoryExtended(path, git.RepositoryOpenFromEnv, "")
-}
diff --git a/cmd/gitaly-git2go/git2goutil/sign.go b/cmd/gitaly-git2go/git2goutil/sign.go
deleted file mode 100644
index efa8d1b1d..000000000
--- a/cmd/gitaly-git2go/git2goutil/sign.go
+++ /dev/null
@@ -1,22 +0,0 @@
-package git2goutil
-
-import (
- "fmt"
-
- "gitlab.com/gitlab-org/gitaly/v16/internal/signature"
-)
-
-// CreateCommitSignature reads the given signing key and produces PKCS#7 detached signature.
-// When the path to the signing key is not present, an empty signature is returned.
-func CreateCommitSignature(signingKeyPath string, contentToSign []byte) ([]byte, error) {
- if signingKeyPath == "" {
- return nil, nil
- }
-
- signingKeys, err := signature.ParseSigningKeys(signingKeyPath)
- if err != nil {
- return nil, fmt.Errorf("failed to parse signing key: %w", err)
- }
-
- return signingKeys.CreateSignature(contentToSign)
-}
diff --git a/cmd/gitaly-git2go/main.go b/cmd/gitaly-git2go/main.go
deleted file mode 100644
index 9c5c4009e..000000000
--- a/cmd/gitaly-git2go/main.go
+++ /dev/null
@@ -1,165 +0,0 @@
-//go:build static && system_libgit2
-
-package main
-
-import (
- "context"
- "encoding/gob"
- "flag"
- "fmt"
- "os"
- "strings"
-
- "github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/ctxlogrus"
- git "github.com/libgit2/git2go/v34"
- "github.com/sirupsen/logrus"
- "gitlab.com/gitlab-org/gitaly/v16/internal/featureflag"
- "gitlab.com/gitlab-org/gitaly/v16/internal/git2go"
- glog "gitlab.com/gitlab-org/gitaly/v16/internal/log"
- "gitlab.com/gitlab-org/labkit/correlation"
-)
-
-type subcmd interface {
- Flags() *flag.FlagSet
- Run(ctx context.Context, decoder *gob.Decoder, encoder *gob.Encoder) error
-}
-
-var subcommands = map[string]subcmd{
- "rebase": &rebaseSubcommand{},
-}
-
-func fatalf(logger logrus.FieldLogger, encoder *gob.Encoder, format string, args ...interface{}) {
- err := encoder.Encode(git2go.Result{
- Err: git2go.SerializableError(fmt.Errorf(format, args...)),
- })
- if err != nil {
- logger.WithError(err).Error("encode to gob failed")
- }
- // An exit code of 1 would indicate an error over stderr. Since our errors
- // are encoded over gob, we need to exit cleanly
- os.Exit(0)
-}
-
-func main() {
- decoder := gob.NewDecoder(os.Stdin)
- encoder := gob.NewEncoder(os.Stdout)
-
- var logFormat, logLevel, correlationID string
- var enabledFeatureFlags, disabledFeatureFlags featureFlagArg
-
- flags := flag.NewFlagSet(git2go.BinaryName, flag.PanicOnError)
- flags.StringVar(&logFormat, "log-format", "", "logging format")
- flags.StringVar(&logLevel, "log-level", "", "logging level")
- flags.StringVar(&correlationID, "correlation-id", "", "correlation ID used for request tracing")
- flags.Var(
- &enabledFeatureFlags,
- "enabled-feature-flags",
- "comma separated list of explicitly enabled feature flags",
- )
- flags.Var(
- &disabledFeatureFlags,
- "disabled-feature-flags",
- "comma separated list of explicitly disabled feature flags",
- )
- _ = flags.Parse(os.Args[1:])
-
- if correlationID == "" {
- correlationID = correlation.SafeRandomID()
- }
-
- ctx := correlation.ContextWithCorrelation(context.Background(), correlationID)
-
- logger, err := glog.Configure(os.Stderr, logFormat, logLevel)
- if err != nil {
- fmt.Printf("configuring logger failed: %v", err)
- os.Exit(1)
- }
-
- logger = logger.WithFields(logrus.Fields{
- "command.name": git2go.BinaryName,
- "correlation_id": correlationID,
- "enabled_feature_flags": enabledFeatureFlags,
- "disabled_feature_flags": disabledFeatureFlags,
- })
-
- if flags.NArg() < 1 {
- fatalf(logger, encoder, "missing subcommand")
- }
-
- subcmd, ok := subcommands[flags.Arg(0)]
- if !ok {
- fatalf(logger, encoder, "unknown subcommand: %q", flags.Arg(0))
- }
-
- subcmdFlags := subcmd.Flags()
- if err := subcmdFlags.Parse(flags.Args()[1:]); err != nil {
- fatalf(logger, encoder, "parsing flags of %q: %s", subcmdFlags.Name(), err)
- }
-
- if subcmdFlags.NArg() != 0 {
- fatalf(logger, encoder, "%s: trailing arguments", subcmdFlags.Name())
- }
-
- if err := git.EnableFsyncGitDir(true); err != nil {
- fatalf(logger, encoder, "enable fsync: %s", err)
- }
-
- for _, configLevel := range []git.ConfigLevel{
- git.ConfigLevelSystem,
- git.ConfigLevelXDG,
- git.ConfigLevelGlobal,
- } {
- if err := git.SetSearchPath(configLevel, "/dev/null"); err != nil {
- fatalf(logger, encoder, "setting search path: %s", err)
- }
- }
-
- subcmdLogger := logger.WithField("command.subcommand", subcmdFlags.Name())
- subcmdLogger.Infof("starting %s command", subcmdFlags.Name())
-
- ctx = ctxlogrus.ToContext(ctx, subcmdLogger)
- ctx = enabledFeatureFlags.ToContext(ctx, true)
- ctx = disabledFeatureFlags.ToContext(ctx, false)
-
- if err := subcmd.Run(ctx, decoder, encoder); err != nil {
- subcmdLogger.WithError(err).Errorf("%s command failed", subcmdFlags.Name())
- fatalf(logger, encoder, "%s: %s", subcmdFlags.Name(), err)
- }
-
- subcmdLogger.Infof("%s command finished", subcmdFlags.Name())
-}
-
-type featureFlagArg []featureflag.FeatureFlag
-
-func (v *featureFlagArg) String() string {
- metadataKeys := make([]string, 0, len(*v))
- for _, flag := range *v {
- metadataKeys = append(metadataKeys, flag.MetadataKey())
- }
- return strings.Join(metadataKeys, ",")
-}
-
-func (v *featureFlagArg) Set(s string) error {
- if s == "" {
- return nil
- }
-
- for _, metadataKey := range strings.Split(s, ",") {
- flag, err := featureflag.FromMetadataKey(metadataKey)
- if err != nil {
- return err
- }
-
- *v = append(*v, flag)
- }
-
- return nil
-}
-
-func (v featureFlagArg) ToContext(ctx context.Context, enabled bool) context.Context {
- for _, flag := range v {
- ctx = featureflag.IncomingCtxWithFeatureFlag(ctx, flag, enabled)
- }
-
- return ctx
-}
diff --git a/cmd/gitaly-git2go/merge.go b/cmd/gitaly-git2go/merge.go
deleted file mode 100644
index 92f0f53fb..000000000
--- a/cmd/gitaly-git2go/merge.go
+++ /dev/null
@@ -1,57 +0,0 @@
-//go:build static && system_libgit2
-
-package main
-
-import (
- "errors"
- "fmt"
-
- git "github.com/libgit2/git2go/v34"
-)
-
-func getConflictingFiles(index *git.Index) ([]string, error) {
- conflicts, err := getConflicts(index)
- if err != nil {
- return nil, fmt.Errorf("getting conflicts: %w", err)
- }
-
- conflictingFiles := make([]string, 0, len(conflicts))
- for _, conflict := range conflicts {
- switch {
- case conflict.Our != nil:
- conflictingFiles = append(conflictingFiles, conflict.Our.Path)
- case conflict.Ancestor != nil:
- conflictingFiles = append(conflictingFiles, conflict.Ancestor.Path)
- case conflict.Their != nil:
- conflictingFiles = append(conflictingFiles, conflict.Their.Path)
- default:
- return nil, errors.New("invalid conflict")
- }
- }
-
- return conflictingFiles, nil
-}
-
-func getConflicts(index *git.Index) ([]git.IndexConflict, error) {
- var conflicts []git.IndexConflict
-
- iterator, err := index.ConflictIterator()
- if err != nil {
- return nil, err
- }
- defer iterator.Free()
-
- for {
- conflict, err := iterator.Next()
- if err != nil {
- if git.IsErrorCode(err, git.ErrorCodeIterOver) {
- break
- }
- return nil, err
- }
-
- conflicts = append(conflicts, conflict)
- }
-
- return conflicts, nil
-}
diff --git a/cmd/gitaly-git2go/rebase.go b/cmd/gitaly-git2go/rebase.go
deleted file mode 100644
index cf221007f..000000000
--- a/cmd/gitaly-git2go/rebase.go
+++ /dev/null
@@ -1,192 +0,0 @@
-//go:build static && system_libgit2
-
-package main
-
-import (
- "context"
- "encoding/gob"
- "errors"
- "flag"
- "fmt"
-
- git "github.com/libgit2/git2go/v34"
- "gitlab.com/gitlab-org/gitaly/v16/cmd/gitaly-git2go/git2goutil"
- "gitlab.com/gitlab-org/gitaly/v16/internal/git2go"
-)
-
-type rebaseSubcommand struct{}
-
-func (cmd *rebaseSubcommand) Flags() *flag.FlagSet {
- return flag.NewFlagSet("rebase", flag.ExitOnError)
-}
-
-func (cmd *rebaseSubcommand) Run(ctx context.Context, decoder *gob.Decoder, encoder *gob.Encoder) error {
- var request git2go.RebaseCommand
- if err := decoder.Decode(&request); err != nil {
- return err
- }
-
- commitID, err := cmd.rebase(ctx, &request)
- return encoder.Encode(git2go.Result{
- CommitID: commitID,
- Err: git2go.SerializableError(err),
- })
-}
-
-func (cmd *rebaseSubcommand) verify(ctx context.Context, r *git2go.RebaseCommand) error {
- if r.Repository == "" {
- return errors.New("missing repository")
- }
- if r.Committer.Name == "" {
- return errors.New("missing committer name")
- }
- if r.Committer.Email == "" {
- return errors.New("missing committer email")
- }
- if r.BranchName == "" && r.CommitID == "" {
- return errors.New("missing branch name")
- }
- if r.BranchName != "" && r.CommitID != "" {
- return errors.New("both branch name and commit ID")
- }
- if r.UpstreamRevision == "" && r.UpstreamCommitID == "" {
- return errors.New("missing upstream revision")
- }
- if r.UpstreamRevision != "" && r.UpstreamCommitID != "" {
- return errors.New("both upstream revision and upstream commit ID")
- }
- return nil
-}
-
-func (cmd *rebaseSubcommand) rebase(ctx context.Context, request *git2go.RebaseCommand) (string, error) {
- if err := cmd.verify(ctx, request); err != nil {
- return "", err
- }
-
- repo, err := git2goutil.OpenRepository(request.Repository)
- if err != nil {
- return "", fmt.Errorf("open repository: %w", err)
- }
-
- opts, err := git.DefaultRebaseOptions()
- if err != nil {
- return "", fmt.Errorf("get rebase options: %w", err)
- }
- opts.InMemory = 1
- opts.CommitCreateCallback = git2goutil.NewCommitSubmitter(repo, request.SigningKey).Commit
-
- var commit *git.AnnotatedCommit
- if request.BranchName != "" {
- commit, err = repo.AnnotatedCommitFromRevspec(fmt.Sprintf("refs/heads/%s", request.BranchName))
- if err != nil {
- return "", fmt.Errorf("look up branch %q: %w", request.BranchName, err)
- }
- } else {
- commitOid, err := git.NewOid(request.CommitID.String())
- if err != nil {
- return "", fmt.Errorf("parse commit %q: %w", request.CommitID, err)
- }
-
- commit, err = repo.LookupAnnotatedCommit(commitOid)
- if err != nil {
- return "", fmt.Errorf("look up commit %q: %w", request.CommitID, err)
- }
- }
-
- upstreamCommitParam := request.UpstreamRevision
- if upstreamCommitParam == "" {
- upstreamCommitParam = request.UpstreamCommitID.String()
- }
-
- upstreamCommitOID, err := git.NewOid(upstreamCommitParam)
- if err != nil {
- return "", fmt.Errorf("parse upstream revision %q: %w", upstreamCommitParam, err)
- }
-
- upstreamCommit, err := repo.LookupAnnotatedCommit(upstreamCommitOID)
- if err != nil {
- return "", fmt.Errorf("look up upstream revision %q: %w", upstreamCommitParam, err)
- }
-
- mergeBase, err := repo.MergeBase(upstreamCommit.Id(), commit.Id())
- if err != nil {
- return "", fmt.Errorf("find merge base: %w", err)
- }
-
- if mergeBase.Equal(upstreamCommit.Id()) {
- // Branch is zero commits behind, so do not rebase
- return commit.Id().String(), nil
- }
-
- if mergeBase.Equal(commit.Id()) {
- // Branch is merged, so fast-forward to upstream
- return upstreamCommit.Id().String(), nil
- }
-
- mergeCommit, err := repo.LookupAnnotatedCommit(mergeBase)
- if err != nil {
- return "", fmt.Errorf("look up merge base: %w", err)
- }
-
- rebase, err := repo.InitRebase(commit, mergeCommit, upstreamCommit, &opts)
- if err != nil {
- return "", fmt.Errorf("initiate rebase: %w", err)
- }
-
- committer := git.Signature(request.Committer)
- var oid *git.Oid
- for {
- op, err := rebase.Next()
- if git.IsErrorCode(err, git.ErrorCodeIterOver) {
- break
- } else if err != nil {
- return "", fmt.Errorf("rebase iterate: %w", err)
- }
-
- commit, err := repo.LookupCommit(op.Id)
- if err != nil {
- return "", fmt.Errorf("lookup commit: %w", err)
- }
-
- if err := rebase.Commit(op.Id, nil, &committer, commit.Message()); err != nil {
- if git.IsErrorCode(err, git.ErrorCodeUnmerged) {
- index, err := rebase.InmemoryIndex()
- if err != nil {
- return "", fmt.Errorf("getting conflicting index: %w", err)
- }
-
- conflictingFiles, err := getConflictingFiles(index)
- if err != nil {
- return "", fmt.Errorf("getting conflicting files: %w", err)
- }
-
- return "", fmt.Errorf("commit %q: %w", op.Id.String(), git2go.ConflictingFilesError{
- ConflictingFiles: conflictingFiles,
- })
- }
-
- // If the commit has already been applied on the target branch then we can
- // skip it if we were told to.
- if request.SkipEmptyCommits && git.IsErrorCode(err, git.ErrorCodeApplied) {
- continue
- }
-
- return "", fmt.Errorf("commit %q: %w", op.Id.String(), err)
- }
-
- oid = op.Id.Copy()
- }
-
- // When the OID is unset here, then we didn't have to rebase any commits at all. We can
- // thus return the upstream commit directly: rebasing nothing onto the upstream commit is
- // the same as the upstream commit itself.
- if oid == nil {
- return upstreamCommit.Id().String(), nil
- }
-
- if err = rebase.Finish(); err != nil {
- return "", fmt.Errorf("finish rebase: %w", err)
- }
-
- return oid.String(), nil
-}
diff --git a/cmd/gitaly-git2go/rebase_test.go b/cmd/gitaly-git2go/rebase_test.go
deleted file mode 100644
index 6de901e32..000000000
--- a/cmd/gitaly-git2go/rebase_test.go
+++ /dev/null
@@ -1,423 +0,0 @@
-//go:build static && system_libgit2
-
-package main
-
-import (
- "fmt"
- "testing"
- "time"
-
- "github.com/stretchr/testify/require"
- "gitlab.com/gitlab-org/gitaly/v16/cmd/gitaly-git2go/git2goutil"
- "gitlab.com/gitlab-org/gitaly/v16/internal/git"
- "gitlab.com/gitlab-org/gitaly/v16/internal/git/gittest"
- "gitlab.com/gitlab-org/gitaly/v16/internal/git2go"
- "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper"
- "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper/testcfg"
-)
-
-var masterRevision = "1e292f8fedd741b75372e19097c76d327140c312"
-
-func TestRebase_validation(t *testing.T) {
- gittest.SkipWithSHA256(t)
-
- ctx := testhelper.Context(t)
- cfg := testcfg.Build(t)
-
- testcfg.BuildGitalyGit2Go(t, cfg)
-
- repo, repoPath := gittest.CreateRepository(t, ctx, cfg, gittest.CreateRepositoryConfig{
- SkipCreationViaService: true,
- })
-
- committer := git2go.NewSignature("Foo", "foo@example.com", time.Now())
- executor := buildExecutor(t, cfg)
-
- testcases := []struct {
- desc string
- request git2go.RebaseCommand
- expectedErr string
- }{
- {
- desc: "no arguments",
- expectedErr: "rebase: missing repository",
- },
- {
- desc: "missing repository",
- request: git2go.RebaseCommand{Committer: committer, BranchName: "feature", UpstreamRevision: masterRevision},
- expectedErr: "rebase: missing repository",
- },
- {
- desc: "missing committer name",
- request: git2go.RebaseCommand{Repository: repoPath, Committer: git2go.Signature{Email: "foo@example.com"}, BranchName: "feature", UpstreamRevision: masterRevision},
- expectedErr: "rebase: missing committer name",
- },
- {
- desc: "missing committer email",
- request: git2go.RebaseCommand{Repository: repoPath, Committer: git2go.Signature{Name: "Foo"}, BranchName: "feature", UpstreamRevision: masterRevision},
- expectedErr: "rebase: missing committer email",
- },
- {
- desc: "missing branch name",
- request: git2go.RebaseCommand{Repository: repoPath, Committer: committer, UpstreamRevision: masterRevision},
- expectedErr: "rebase: missing branch name",
- },
- {
- desc: "missing upstream branch",
- request: git2go.RebaseCommand{Repository: repoPath, Committer: committer, BranchName: "feature"},
- expectedErr: "rebase: missing upstream revision",
- },
- {
- desc: "both branch name and commit ID",
- request: git2go.RebaseCommand{Repository: repoPath, Committer: committer, BranchName: "feature", CommitID: "a"},
- expectedErr: "rebase: both branch name and commit ID",
- },
- {
- desc: "both upstream revision and upstream commit ID",
- request: git2go.RebaseCommand{Repository: repoPath, Committer: committer, BranchName: "feature", UpstreamRevision: "a", UpstreamCommitID: "a"},
- expectedErr: "rebase: both upstream revision and upstream commit ID",
- },
- }
- for _, tc := range testcases {
- t.Run(tc.desc, func(t *testing.T) {
- _, err := executor.Rebase(ctx, repo, tc.request)
- require.EqualError(t, err, tc.expectedErr)
- })
- }
-}
-
-func TestRebase_rebase(t *testing.T) {
- gittest.SkipWithSHA256(t)
-
- t.Parallel()
-
- ctx := testhelper.Context(t)
- cfg := testcfg.Build(t)
- testcfg.BuildGitalyGit2Go(t, cfg)
- executor := buildExecutor(t, cfg)
-
- committer := git2go.NewSignature(
- string(gittest.TestUser.Name),
- string(gittest.TestUser.Email),
- time.Date(2021, 3, 1, 13, 45, 50, 0, time.FixedZone("", +2*60*60)),
- )
-
- type setup struct {
- base, upstream, downstream git.ObjectID
- expecetedCommitsAhead int
- expectedObjectID git.ObjectID
- expectedErr string
- }
-
- testcases := []struct {
- desc string
- setup func(testing.TB, string) setup
- }{
- {
- desc: "Single commit rebase",
- setup: func(tb testing.TB, repoPath string) setup {
- base := gittest.WriteCommit(t, cfg, repoPath, gittest.WithTreeEntries(
- gittest.TreeEntry{Path: "path", Mode: "100644", Content: "a\nb\nc\nd\ne\nf\ng\n"},
- ))
- upstream := gittest.WriteCommit(t, cfg, repoPath, gittest.WithMessage("upstream"), gittest.WithParents(base), gittest.WithTreeEntries(
- gittest.TreeEntry{Path: "path", Mode: "100644", Content: "upstream\nb\nc\nd\ne\nf\ng\n"},
- ))
- downstream := gittest.WriteCommit(t, cfg, repoPath, gittest.WithMessage("downstream"), gittest.WithParents(base), gittest.WithTreeEntries(
- gittest.TreeEntry{Path: "path", Mode: "100644", Content: "a\nb\nc\nd\ne\nf\ndownstream\n"},
- ))
-
- return setup{
- base: base,
- upstream: upstream,
- downstream: downstream,
- expectedObjectID: "ef018adb419cd97453a0624c28271fafe622b83e",
- expecetedCommitsAhead: 1,
- }
- },
- },
- {
- desc: "Multiple commits",
- setup: func(tb testing.TB, repoPath string) setup {
- base := gittest.WriteCommit(t, cfg, repoPath, gittest.WithTreeEntries(
- gittest.TreeEntry{Path: "path", Mode: "100644", Content: "a\nb\nc\nd\ne\nf\ng\n"},
- ))
- upstream := gittest.WriteCommit(t, cfg, repoPath, gittest.WithMessage("upstream"), gittest.WithParents(base), gittest.WithTreeEntries(
- gittest.TreeEntry{Path: "path", Mode: "100644", Content: "upstream\nb\nc\nd\ne\nf\ng\n"},
- ))
- downstream1 := gittest.WriteCommit(t, cfg, repoPath, gittest.WithMessage("downstream-1"), gittest.WithParents(base), gittest.WithTreeEntries(
- gittest.TreeEntry{Path: "path", Mode: "100644", Content: "a\nb\nc\nd\ne\nf\ndownstream-1\n"},
- ))
- downstream2 := gittest.WriteCommit(t, cfg, repoPath, gittest.WithMessage("downstream-2"), gittest.WithParents(downstream1), gittest.WithTreeEntries(
- gittest.TreeEntry{Path: "path", Mode: "100644", Content: "a\nb\nc\nd\ne\nf\ndownstream-2\n"},
- ))
- downstream3 := gittest.WriteCommit(t, cfg, repoPath, gittest.WithMessage("downstream-3"), gittest.WithParents(downstream2), gittest.WithTreeEntries(
- gittest.TreeEntry{Path: "path", Mode: "100644", Content: "a\nb\nc\nd\ne\nf\ndownstream-3\n"},
- ))
-
- return setup{
- base: base,
- upstream: upstream,
- downstream: downstream3,
- expectedObjectID: "d3c737fdb3a0c4da3a371fc01de6df4cbb5bc3e4",
- expecetedCommitsAhead: 3,
- }
- },
- },
- {
- desc: "Branch zero commits behind",
- setup: func(tb testing.TB, repoPath string) setup {
- base := gittest.WriteCommit(t, cfg, repoPath, gittest.WithTreeEntries(
- gittest.TreeEntry{Path: "path", Mode: "100644", Content: "a\nb\nc\nd\ne\nf\ng\n"},
- ))
- downstream := gittest.WriteCommit(t, cfg, repoPath, gittest.WithMessage("downstream"), gittest.WithParents(base), gittest.WithTreeEntries(
- gittest.TreeEntry{Path: "path", Mode: "100644", Content: "a\nb\nc\nd\ne\nf\ndownstream\n"},
- ))
-
- return setup{
- base: base,
- upstream: base,
- downstream: downstream,
- expectedObjectID: downstream,
- expecetedCommitsAhead: 1,
- }
- },
- },
- {
- desc: "Merged branch",
- setup: func(tb testing.TB, repoPath string) setup {
- base := gittest.WriteCommit(t, cfg, repoPath, gittest.WithTreeEntries(
- gittest.TreeEntry{Path: "path", Mode: "100644", Content: "a\nb\nc\nd\ne\nf\ng\n"},
- ))
- downstream := gittest.WriteCommit(t, cfg, repoPath, gittest.WithParents(base), gittest.WithTreeEntries(
- gittest.TreeEntry{Path: "path", Mode: "100644", Content: "a\nb\nc\nd\ne\nf\ndownstream\n"},
- ))
- merge := gittest.WriteCommit(t, cfg, repoPath, gittest.WithParents(base, downstream), gittest.WithTreeEntries(
- gittest.TreeEntry{Path: "path", Mode: "100644", Content: "a\nb\nc\nd\ne\nf\ndownstream\n"},
- ))
-
- return setup{
- base: base, upstream: merge, downstream: downstream,
- expectedObjectID: merge,
- }
- },
- },
- {
- desc: "Partially merged branch",
- setup: func(tb testing.TB, repoPath string) setup {
- base := gittest.WriteCommit(t, cfg, repoPath, gittest.WithTreeEntries(
- gittest.TreeEntry{Path: "path", Mode: "100644", Content: "a\nb\nc\nd\ne\nf\ng\n"},
- ))
- downstream1 := gittest.WriteCommit(t, cfg, repoPath, gittest.WithParents(base), gittest.WithTreeEntries(
- gittest.TreeEntry{Path: "path", Mode: "100644", Content: "a\nb\nc\nd\ne\nf\ndownstream-1\n"},
- ))
- downstream2 := gittest.WriteCommit(t, cfg, repoPath, gittest.WithParents(downstream1), gittest.WithTreeEntries(
- gittest.TreeEntry{Path: "path", Mode: "100644", Content: "a\nb\nc\nd\ne\nf\ndownstream-2\n"},
- ))
- merge := gittest.WriteCommit(t, cfg, repoPath, gittest.WithParents(base, downstream1), gittest.WithTreeEntries(
- gittest.TreeEntry{Path: "path", Mode: "100644", Content: "a\nb\nc\nd\ne\nf\ndownstream-1\n"},
- ))
-
- return setup{
- base: base,
- upstream: merge,
- downstream: downstream2,
- expectedObjectID: "721e8bd36a394a7cc243b8c3960b44c5520c6246",
- expecetedCommitsAhead: 1,
- }
- },
- },
- {
- desc: "With upstream merged into",
- setup: func(tb testing.TB, repoPath string) setup {
- base := gittest.WriteCommit(t, cfg, repoPath, gittest.WithTreeEntries(
- gittest.TreeEntry{Path: "path", Mode: "100644", Content: "a\nb\nc\nd\ne\nf\ng\n"},
- ))
- upstream := gittest.WriteCommit(t, cfg, repoPath, gittest.WithMessage("upstream"), gittest.WithParents(base), gittest.WithTreeEntries(
- gittest.TreeEntry{Path: "path", Mode: "100644", Content: "upstream\nb\nc\nd\ne\nf\ng\n"},
- ))
- downstream := gittest.WriteCommit(t, cfg, repoPath, gittest.WithMessage("downstream"), gittest.WithParents(base), gittest.WithTreeEntries(
- gittest.TreeEntry{Path: "path", Mode: "100644", Content: "a\nb\nc\nd\ne\nf\ndownstream\n"},
- ))
- downstreamMerge := gittest.WriteCommit(t, cfg, repoPath, gittest.WithParents(downstream, upstream), gittest.WithTreeEntries(
- gittest.TreeEntry{Path: "path", Mode: "100644", Content: "upstream\nb\nc\nd\ne\nf\ndownstream\n"},
- ))
-
- return setup{
- base: base,
- upstream: upstream,
- downstream: downstreamMerge,
- expectedObjectID: "aa375bc059fa8830d9489d89af1278632722407d",
- expecetedCommitsAhead: 2,
- }
- },
- },
- {
- desc: "Rebase with conflict",
- setup: func(tb testing.TB, repoPath string) setup {
- base := gittest.WriteCommit(t, cfg, repoPath, gittest.WithTreeEntries(
- gittest.TreeEntry{Path: "path", Mode: "100644", Content: "base\n"},
- ))
- upstream := gittest.WriteCommit(t, cfg, repoPath, gittest.WithParents(base), gittest.WithTreeEntries(
- gittest.TreeEntry{Path: "path", Mode: "100644", Content: "upstream\n"},
- ))
- downstream := gittest.WriteCommit(t, cfg, repoPath, gittest.WithParents(base), gittest.WithTreeEntries(
- gittest.TreeEntry{Path: "path", Mode: "100644", Content: "downstream\n"},
- ))
-
- return setup{
- upstream: upstream,
- downstream: downstream,
- expectedErr: fmt.Sprintf("rebase: commit %q: there are conflicting files", downstream),
- }
- },
- },
- {
- desc: "Orphaned branch",
- setup: func(tb testing.TB, repoPath string) setup {
- upstream := gittest.WriteCommit(t, cfg, repoPath, gittest.WithTreeEntries(
- gittest.TreeEntry{Path: "path", Mode: "100644", Content: "upstream\n"},
- ))
- downstream := gittest.WriteCommit(t, cfg, repoPath, gittest.WithTreeEntries(
- gittest.TreeEntry{Path: "path", Mode: "100644", Content: "downstream\n"},
- ))
-
- return setup{
- upstream: upstream,
- downstream: downstream,
- expectedErr: "rebase: find merge base: no merge base found",
- }
- },
- },
- }
-
- for _, tc := range testcases {
- tc := tc
-
- t.Run(tc.desc, func(t *testing.T) {
- t.Parallel()
-
- repoProto, repoPath := gittest.CreateRepository(t, ctx, cfg, gittest.CreateRepositoryConfig{
- SkipCreationViaService: true,
- })
- setup := tc.setup(t, repoPath)
-
- gittest.WriteRef(t, cfg, repoPath, "refs/heads/upstream", setup.upstream)
- gittest.WriteRef(t, cfg, repoPath, "refs/heads/downstream", setup.downstream)
-
- repo, err := git2goutil.OpenRepository(repoPath)
- require.NoError(t, err)
-
- for desc, request := range map[string]git2go.RebaseCommand{
- "with branch and upstream": {
- Repository: repoPath,
- Committer: committer,
- BranchName: "downstream",
- UpstreamRevision: setup.upstream.String(),
- },
- "with branch and upstream commit ID": {
- Repository: repoPath,
- Committer: committer,
- BranchName: "downstream",
- UpstreamCommitID: setup.upstream,
- },
- "with commit ID and upstream": {
- Repository: repoPath,
- Committer: committer,
- CommitID: setup.downstream,
- UpstreamRevision: setup.upstream.String(),
- },
- "with commit ID and upstream commit ID": {
- Repository: repoPath,
- Committer: committer,
- CommitID: setup.downstream,
- UpstreamCommitID: setup.upstream,
- },
- } {
- t.Run(desc, func(t *testing.T) {
- response, err := executor.Rebase(ctx, repoProto, request)
- if setup.expectedErr != "" {
- require.EqualError(t, err, setup.expectedErr)
- } else {
- require.NoError(t, err)
- require.Equal(t, setup.expectedObjectID, response)
-
- commit, err := lookupCommit(repo, response.String())
- require.NoError(t, err)
-
- for i := setup.expecetedCommitsAhead; i > 0; i-- {
- commit = commit.Parent(0)
- }
- baseCommit, err := lookupCommit(repo, setup.base.String())
- require.NoError(t, err)
- require.Equal(t, baseCommit, commit)
- }
- })
- }
- })
- }
-}
-
-func TestRebase_skipEmptyCommit(t *testing.T) {
- gittest.SkipWithSHA256(t)
-
- ctx := testhelper.Context(t)
- cfg := testcfg.Build(t)
-
- testcfg.BuildGitalyGit2Go(t, cfg)
-
- repoProto, repoPath := gittest.CreateRepository(t, ctx, cfg, gittest.CreateRepositoryConfig{
- SkipCreationViaService: true,
- })
-
- // Set up history with two diverging lines of branches, where both sides have implemented
- // the same changes. During rebase, the diff will thus become empty.
- base := gittest.WriteCommit(t, cfg, repoPath,
- gittest.WithTreeEntries(gittest.TreeEntry{
- Path: "a", Content: "base", Mode: "100644",
- }),
- )
- theirs := gittest.WriteCommit(t, cfg, repoPath, gittest.WithMessage("theirs"),
- gittest.WithParents(base), gittest.WithTreeEntries(gittest.TreeEntry{
- Path: "a", Content: "changed", Mode: "100644",
- }),
- )
- ours := gittest.WriteCommit(t, cfg, repoPath, gittest.WithMessage("ours"),
- gittest.WithParents(base), gittest.WithTreeEntries(gittest.TreeEntry{
- Path: "a", Content: "changed", Mode: "100644",
- }),
- )
-
- for _, tc := range []struct {
- desc string
- skipEmptyCommits bool
- expectedErr string
- expectedResponse git.ObjectID
- }{
- {
- desc: "do not skip empty commit",
- skipEmptyCommits: false,
- expectedErr: fmt.Sprintf("rebase: commit %q: this patch has already been applied", ours),
- },
- {
- desc: "skip empty commit",
- skipEmptyCommits: true,
- expectedResponse: theirs,
- },
- } {
- t.Run(tc.desc, func(t *testing.T) {
- response, err := buildExecutor(t, cfg).Rebase(ctx, repoProto, git2go.RebaseCommand{
- Repository: repoPath,
- Committer: git2go.NewSignature("Foo", "foo@example.com", time.Now()),
- CommitID: ours,
- UpstreamCommitID: theirs,
- SkipEmptyCommits: tc.skipEmptyCommits,
- })
- if tc.expectedErr == "" {
- require.NoError(t, err)
- } else {
- require.EqualError(t, err, tc.expectedErr)
- }
- require.Equal(t, tc.expectedResponse, response)
- })
- }
-}
diff --git a/cmd/gitaly-git2go/testhelper_test.go b/cmd/gitaly-git2go/testhelper_test.go
deleted file mode 100644
index 0d72bec57..000000000
--- a/cmd/gitaly-git2go/testhelper_test.go
+++ /dev/null
@@ -1,44 +0,0 @@
-//go:build static && system_libgit2
-
-package main
-
-import (
- "fmt"
- "testing"
-
- git "github.com/libgit2/git2go/v34"
- "gitlab.com/gitlab-org/gitaly/v16/internal/git/gittest"
- "gitlab.com/gitlab-org/gitaly/v16/internal/git2go"
- "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/config"
- "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper"
-)
-
-// DefaultAuthor is the author used by BuildCommit
-var DefaultAuthor = git.Signature{
- Name: gittest.DefaultCommitterName,
- Email: gittest.DefaultCommitterMail,
- When: gittest.DefaultCommitTime,
-}
-
-func TestMain(m *testing.M) {
- testhelper.Run(m, testhelper.WithSetup(func() error {
- // We use Git2go to access repositories in our tests, so we must tell it to ignore
- // any configuration files that happen to exist. We do the same in `main()`, so
- // this is not only specific to tests.
- for _, configLevel := range []git.ConfigLevel{
- git.ConfigLevelSystem,
- git.ConfigLevelXDG,
- git.ConfigLevelGlobal,
- } {
- if err := git.SetSearchPath(configLevel, "/dev/null"); err != nil {
- return fmt.Errorf("setting Git2go search path: %w", err)
- }
- }
-
- return nil
- }))
-}
-
-func buildExecutor(tb testing.TB, cfg config.Cfg) *git2go.Executor {
- return git2go.NewExecutor(cfg, gittest.NewCommandFactory(tb, cfg), config.NewLocator(cfg), testhelper.SharedLogger(tb))
-}
diff --git a/cmd/gitaly-git2go/util.go b/cmd/gitaly-git2go/util.go
deleted file mode 100644
index c76b9370c..000000000
--- a/cmd/gitaly-git2go/util.go
+++ /dev/null
@@ -1,32 +0,0 @@
-//go:build static && system_libgit2
-
-package main
-
-import (
- "fmt"
-
- git "github.com/libgit2/git2go/v34"
- "gitlab.com/gitlab-org/gitaly/v16/internal/git2go"
-)
-
-func lookupCommit(repo *git.Repository, ref string) (*git.Commit, error) {
- object, err := repo.RevparseSingle(ref)
- switch {
- case git.IsErrorCode(err, git.ErrorCodeNotFound):
- return nil, git2go.CommitNotFoundError{Revision: ref}
- case err != nil:
- return nil, fmt.Errorf("lookup commit %q: %w", ref, err)
- }
-
- peeled, err := object.Peel(git.ObjectCommit)
- if err != nil {
- return nil, fmt.Errorf("lookup commit %q: peel: %w", ref, err)
- }
-
- commit, err := peeled.AsCommit()
- if err != nil {
- return nil, fmt.Errorf("lookup commit %q: as commit: %w", ref, err)
- }
-
- return commit, nil
-}