diff options
author | Patrick Steinhardt <psteinhardt@gitlab.com> | 2023-08-22 14:20:56 +0300 |
---|---|---|
committer | Patrick Steinhardt <psteinhardt@gitlab.com> | 2023-08-22 14:36:24 +0300 |
commit | 54eab509e0178083c7b31a3977e807c4a0400f33 (patch) | |
tree | 4796b0191dc1a7f4ec381110f4ed3541005e4049 | |
parent | 1c4e452083e7a88ba199a53b724ccae2e71c60ce (diff) |
cmd/gitaly-git2go: Remove now-unused cherry-pick implementation
We have removed the feature flag that was guarding the Git based
implementation of UserCherryPick, which makes the Git2go-based
cherry-pick implementation unused. Remove it.
-rw-r--r-- | cmd/gitaly-git2go/cherry_pick.go | 127 | ||||
-rw-r--r-- | cmd/gitaly-git2go/cherry_pick_test.go | 290 | ||||
-rw-r--r-- | cmd/gitaly-git2go/main.go | 3 | ||||
-rw-r--r-- | internal/git2go/cherry_pick.go | 38 |
4 files changed, 1 insertions, 457 deletions
diff --git a/cmd/gitaly-git2go/cherry_pick.go b/cmd/gitaly-git2go/cherry_pick.go deleted file mode 100644 index 0de2ada5f..000000000 --- a/cmd/gitaly-git2go/cherry_pick.go +++ /dev/null @@ -1,127 +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 cherryPickSubcommand struct{} - -func (cmd *cherryPickSubcommand) Flags() *flag.FlagSet { - return flag.NewFlagSet("cherry-pick", flag.ExitOnError) -} - -func (cmd *cherryPickSubcommand) Run(ctx context.Context, decoder *gob.Decoder, encoder *gob.Encoder) error { - var request git2go.CherryPickCommand - if err := decoder.Decode(&request); err != nil { - return err - } - - commitID, err := cmd.cherryPick(ctx, &request) - return encoder.Encode(git2go.Result{ - CommitID: commitID, - Err: git2go.SerializableError(err), - }) -} - -func (cmd *cherryPickSubcommand) verify(ctx context.Context, r *git2go.CherryPickCommand) error { - if r.Repository == "" { - return errors.New("missing repository") - } - if r.CommitterName == "" { - return errors.New("missing committer name") - } - if r.CommitterMail == "" { - return errors.New("missing committer mail") - } - if r.CommitterDate.IsZero() { - return errors.New("missing committer date") - } - if r.Message == "" { - return errors.New("missing message") - } - if r.Ours == "" { - return errors.New("missing ours") - } - if r.Commit == "" { - return errors.New("missing commit") - } - - return nil -} - -func (cmd *cherryPickSubcommand) cherryPick(ctx context.Context, r *git2go.CherryPickCommand) (string, error) { - if err := cmd.verify(ctx, r); err != nil { - return "", err - } - - repo, err := git2goutil.OpenRepository(r.Repository) - if err != nil { - return "", fmt.Errorf("could not open repository: %w", err) - } - defer repo.Free() - - ours, err := lookupCommit(repo, r.Ours) - if err != nil { - return "", fmt.Errorf("ours commit lookup: %w", err) - } - - pick, err := lookupCommit(repo, r.Commit) - if err != nil { - return "", fmt.Errorf("commit lookup: %w", err) - } - - opts, err := git.DefaultCherrypickOptions() - if err != nil { - return "", fmt.Errorf("could not get default cherry-pick options: %w", err) - } - opts.Mainline = r.Mainline - - index, err := repo.CherrypickCommit(pick, ours, opts) - if err != nil { - return "", fmt.Errorf("could not cherry-pick commit: %w", err) - } - - if index.HasConflicts() { - conflictingFiles, err := getConflictingFiles(index) - if err != nil { - return "", fmt.Errorf("getting conflicting files: %w", err) - } - - return "", git2go.ConflictingFilesError{ - ConflictingFiles: conflictingFiles, - } - } - - treeOID, err := index.WriteTreeTo(repo) - if err != nil { - return "", fmt.Errorf("could not write tree: %w", err) - } - tree, err := repo.LookupTree(treeOID) - if err != nil { - return "", fmt.Errorf("lookup tree: %w", err) - } - - if treeOID.Equal(ours.TreeId()) { - return "", git2go.EmptyError{} - } - - committer := git.Signature(git2go.NewSignature(r.CommitterName, r.CommitterMail, r.CommitterDate)) - - commitID, err := git2goutil.NewCommitSubmitter(repo, r.SigningKey). - Commit(pick.Author(), &committer, git.MessageEncodingUTF8, r.Message, tree, ours) - if err != nil { - return "", fmt.Errorf("create not create cherry-pick commit: %w", err) - } - - return commitID.String(), nil -} diff --git a/cmd/gitaly-git2go/cherry_pick_test.go b/cmd/gitaly-git2go/cherry_pick_test.go deleted file mode 100644 index d9bfc2e39..000000000 --- a/cmd/gitaly-git2go/cherry_pick_test.go +++ /dev/null @@ -1,290 +0,0 @@ -//go:build static && system_libgit2 && !gitaly_test_sha256 - -package main - -import ( - "testing" - "time" - - git "github.com/libgit2/git2go/v34" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "gitlab.com/gitlab-org/gitaly/v16/cmd/gitaly-git2go/git2goutil" - "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" -) - -func TestCherryPick_validation(t *testing.T) { - ctx := testhelper.Context(t) - cfg := testcfg.Build(t) - - repo, repoPath := gittest.CreateRepository(t, ctx, cfg, gittest.CreateRepositoryConfig{ - SkipCreationViaService: true, - Seed: gittest.SeedGitLabTest, - }) - testcfg.BuildGitalyGit2Go(t, cfg) - executor := buildExecutor(t, cfg) - - testcases := []struct { - desc string - request git2go.CherryPickCommand - expectedErr string - }{ - { - desc: "no arguments", - expectedErr: "cherry-pick: missing repository", - }, - { - desc: "missing repository", - request: git2go.CherryPickCommand{CommitterName: "Foo", CommitterMail: "foo@example.com", CommitterDate: time.Now(), Message: "Foo", Ours: "HEAD", Commit: "HEAD"}, - expectedErr: "cherry-pick: missing repository", - }, - { - desc: "missing committer name", - request: git2go.CherryPickCommand{Repository: repoPath, CommitterMail: "foo@example.com", CommitterDate: time.Now(), Message: "Foo", Ours: "HEAD", Commit: "HEAD"}, - expectedErr: "cherry-pick: missing committer name", - }, - { - desc: "missing committer mail", - request: git2go.CherryPickCommand{Repository: repoPath, CommitterName: "Foo", CommitterDate: time.Now(), Message: "Foo", Ours: "HEAD", Commit: "HEAD"}, - expectedErr: "cherry-pick: missing committer mail", - }, - { - desc: "missing committer date", - request: git2go.CherryPickCommand{Repository: repoPath, CommitterName: "Foo", CommitterMail: "foo@example.com", Message: "Foo", Ours: "HEAD", Commit: "HEAD"}, - expectedErr: "cherry-pick: missing committer date", - }, - { - desc: "missing message", - request: git2go.CherryPickCommand{Repository: repoPath, CommitterName: "Foo", CommitterMail: "foo@example.com", CommitterDate: time.Now(), Ours: "HEAD", Commit: "HEAD"}, - expectedErr: "cherry-pick: missing message", - }, - { - desc: "missing ours", - request: git2go.CherryPickCommand{Repository: repoPath, CommitterName: "Foo", CommitterMail: "foo@example.com", CommitterDate: time.Now(), Message: "Foo", Commit: "HEAD"}, - expectedErr: "cherry-pick: missing ours", - }, - { - desc: "missing commit", - request: git2go.CherryPickCommand{Repository: repoPath, CommitterName: "Foo", CommitterMail: "foo@example.com", CommitterDate: time.Now(), Message: "Foo", Ours: "HEAD"}, - expectedErr: "cherry-pick: missing commit", - }, - } - for _, tc := range testcases { - t.Run(tc.desc, func(t *testing.T) { - _, err := executor.CherryPick(ctx, repo, tc.request) - require.EqualError(t, err, tc.expectedErr) - }) - } -} - -func TestCherryPick(t *testing.T) { - testcases := []struct { - desc string - base []gittest.TreeEntry - ours []gittest.TreeEntry - commit []gittest.TreeEntry - expected map[string]string - expectedCommitID string - expectedErrAs interface{} - expectedErrMsg string - }{ - { - desc: "trivial cherry-pick succeeds", - base: []gittest.TreeEntry{ - {Path: "file", Content: "foo", Mode: "100644"}, - }, - ours: []gittest.TreeEntry{ - {Path: "file", Content: "foo", Mode: "100644"}, - }, - commit: []gittest.TreeEntry{ - {Path: "file", Content: "foobar", Mode: "100644"}, - }, - expected: map[string]string{ - "file": "foobar", - }, - expectedCommitID: "a54ea83118c363c34cc605a6e61fd7abc4795cc4", - }, - { - desc: "conflicting cherry-pick fails", - base: []gittest.TreeEntry{ - {Path: "file", Content: "foo", Mode: "100644"}, - }, - ours: []gittest.TreeEntry{ - {Path: "file", Content: "fooqux", Mode: "100644"}, - }, - commit: []gittest.TreeEntry{ - {Path: "file", Content: "foobar", Mode: "100644"}, - }, - expectedErrAs: &git2go.ConflictingFilesError{}, - expectedErrMsg: "cherry-pick: there are conflicting files", - }, - { - desc: "empty cherry-pick fails", - base: []gittest.TreeEntry{ - {Path: "file", Content: "foo", Mode: "100644"}, - }, - ours: []gittest.TreeEntry{ - {Path: "file", Content: "fooqux", Mode: "100644"}, - }, - commit: []gittest.TreeEntry{ - {Path: "file", Content: "fooqux", Mode: "100644"}, - }, - expectedErrAs: &git2go.EmptyError{}, - expectedErrMsg: "cherry-pick: could not apply because the result was empty", - }, - { - desc: "fails on nonexistent ours commit", - expectedErrAs: &git2go.CommitNotFoundError{}, - expectedErrMsg: "cherry-pick: ours commit lookup: commit not found: \"nonexistent\"", - }, - { - desc: "fails on nonexistent cherry-pick commit", - ours: []gittest.TreeEntry{ - {Path: "file", Content: "fooqux", Mode: "100644"}, - }, - expectedErrAs: &git2go.CommitNotFoundError{}, - expectedErrMsg: "cherry-pick: commit lookup: commit not found: \"nonexistent\"", - }, - } - for _, tc := range testcases { - ctx := testhelper.Context(t) - cfg := testcfg.Build(t) - - repo, repoPath := gittest.CreateRepository(t, ctx, cfg, gittest.CreateRepositoryConfig{ - SkipCreationViaService: true, - Seed: gittest.SeedGitLabTest, - }) - testcfg.BuildGitalyGit2Go(t, cfg) - executor := buildExecutor(t, cfg) - - base := gittest.WriteCommit(t, cfg, repoPath, gittest.WithTreeEntries(tc.base...)) - - ours, commit := "nonexistent", "nonexistent" - if len(tc.ours) > 0 { - ours = gittest.WriteCommit(t, cfg, repoPath, gittest.WithParents(base), gittest.WithTreeEntries(tc.ours...)).String() - } - if len(tc.commit) > 0 { - commit = gittest.WriteCommit(t, cfg, repoPath, gittest.WithParents(base), gittest.WithTreeEntries(tc.commit...)).String() - } - - t.Run(tc.desc, func(t *testing.T) { - committer := git.Signature{ - Name: "Baz", - Email: "baz@example.com", - When: time.Date(2021, 1, 17, 14, 45, 51, 0, time.FixedZone("", +2*60*60)), - } - - response, err := executor.CherryPick(ctx, repo, git2go.CherryPickCommand{ - Repository: repoPath, - CommitterName: committer.Name, - CommitterMail: committer.Email, - CommitterDate: committer.When, - Message: "Foo", - Ours: ours, - Commit: commit, - }) - - if tc.expectedErrMsg != "" { - require.EqualError(t, err, tc.expectedErrMsg) - - if tc.expectedErrAs != nil { - require.ErrorAs(t, err, tc.expectedErrAs) - } - return - } - - require.NoError(t, err) - assert.Equal(t, tc.expectedCommitID, response.String()) - - repo, err := git2goutil.OpenRepository(repoPath) - require.NoError(t, err) - defer repo.Free() - - commitOid, err := git.NewOid(response.String()) - require.NoError(t, err) - - commit, err := repo.LookupCommit(commitOid) - require.NoError(t, err) - - // The computed author does not include the timezone string "UTC+1". - expectedAuthor := DefaultAuthor - expectedAuthor.When = expectedAuthor.When.In(time.FixedZone("", 1*60*60)) - require.Equal(t, &expectedAuthor, commit.Author()) - require.Equal(t, &committer, commit.Committer()) - - tree, err := commit.Tree() - require.NoError(t, err) - require.Len(t, tc.expected, int(tree.EntryCount())) - - for name, contents := range tc.expected { - entry := tree.EntryByName(name) - require.NotNil(t, entry) - - blob, err := repo.LookupBlob(entry.Id) - require.NoError(t, err) - require.Equal(t, []byte(contents), blob.Contents()) - } - }) - } -} - -func TestCherryPickStructuredErrors(t *testing.T) { - ctx := testhelper.Context(t) - cfg := testcfg.Build(t) - - repo, repoPath := gittest.CreateRepository(t, ctx, cfg, gittest.CreateRepositoryConfig{ - SkipCreationViaService: true, - Seed: gittest.SeedGitLabTest, - }) - - testcfg.BuildGitalyGit2Go(t, cfg) - executor := buildExecutor(t, cfg) - - base := gittest.WriteCommit( - t, - cfg, - repoPath, - gittest.WithTreeEntries(gittest.TreeEntry{ - Path: "file", Content: "foo", Mode: "100644", - })) - - ours := gittest.WriteCommit( - t, - cfg, - repoPath, - gittest.WithParents(base), - gittest.WithTreeEntries( - gittest.TreeEntry{Path: "file", Content: "fooqux", Mode: "100644"}, - )).String() - - commit := gittest.WriteCommit( - t, - cfg, - repoPath, - gittest.WithParents(base), - gittest.WithTreeEntries( - gittest.TreeEntry{Path: "file", Content: "foobar", Mode: "100644"}, - )).String() - - committer := git.Signature{ - Name: "Baz", - Email: "baz@example.com", - When: time.Date(2021, 1, 17, 14, 45, 51, 0, time.FixedZone("", +2*60*60)), - } - - _, err := executor.CherryPick(ctx, repo, git2go.CherryPickCommand{ - Repository: repoPath, - CommitterName: committer.Name, - CommitterMail: committer.Email, - CommitterDate: committer.When, - Message: "Foo", - Ours: ours, - Commit: commit, - }) - - require.EqualError(t, err, "cherry-pick: there are conflicting files") - require.ErrorAs(t, err, &git2go.ConflictingFilesError{}) -} diff --git a/cmd/gitaly-git2go/main.go b/cmd/gitaly-git2go/main.go index 73e79c99d..9c5c4009e 100644 --- a/cmd/gitaly-git2go/main.go +++ b/cmd/gitaly-git2go/main.go @@ -25,8 +25,7 @@ type subcmd interface { } var subcommands = map[string]subcmd{ - "cherry-pick": &cherryPickSubcommand{}, - "rebase": &rebaseSubcommand{}, + "rebase": &rebaseSubcommand{}, } func fatalf(logger logrus.FieldLogger, encoder *gob.Encoder, format string, args ...interface{}) { diff --git a/internal/git2go/cherry_pick.go b/internal/git2go/cherry_pick.go deleted file mode 100644 index 435d85cbf..000000000 --- a/internal/git2go/cherry_pick.go +++ /dev/null @@ -1,38 +0,0 @@ -package git2go - -import ( - "context" - "time" - - "gitlab.com/gitlab-org/gitaly/v16/internal/git" - "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" -) - -// CherryPickCommand contains parameters to perform a cherry-pick. -type CherryPickCommand struct { - // Repository is the path where to execute the cherry-pick. - Repository string - // CommitterName is the committer name for the resulting commit. - CommitterName string - // CommitterMail is the committer mail for the resulting commit. - CommitterMail string - // CommitterDate is the committer date of revert commit. - CommitterDate time.Time - // Message is the message to be used for the resulting commit. - Message string - // Ours is the commit that the revert is applied to. - Ours string - // Commit is the commit that is to be picked. - Commit string - // Mainline is the parent to be considered the mainline - Mainline uint - // SigningKey is a path to the key to sign commit using OpenPGP - SigningKey string -} - -// CherryPick performs a cherry-pick via gitaly-git2go. -func (b *Executor) CherryPick(ctx context.Context, repo storage.Repository, m CherryPickCommand) (git.ObjectID, error) { - m.SigningKey = b.signingKey - - return b.runWithGob(ctx, repo, "cherry-pick", m) -} |