From 823bc6062d1a0cb75a28a7dd1cd1fc3aaf92fcb9 Mon Sep 17 00:00:00 2001 From: Carlos Alexandro Becker Date: Wed, 14 Jun 2023 23:52:35 -0300 Subject: [PATCH] feat: make git client support creating multiple files in a single commit (#4107) extracted from #4081 a little bit of a better impl than there, actually... --- internal/client/client.go | 12 +++++++++++ internal/client/git.go | 41 ++++++++++++++++++++++--------------- internal/client/git_test.go | 29 +++++++++++++++----------- 3 files changed, 54 insertions(+), 28 deletions(-) diff --git a/internal/client/client.go b/internal/client/client.go index a58446083..f38f89aed 100644 --- a/internal/client/client.go +++ b/internal/client/client.go @@ -61,11 +61,23 @@ type ReleaserURLTemplater interface { ReleaseURLTemplate(ctx *context.Context) (string, error) } +// RepoFile is a file to be created. +type RepoFile struct { + Content []byte + Path string +} + // FileCreator can create the given file to some code repository. type FileCreator interface { CreateFile(ctx *context.Context, commitAuthor config.CommitAuthor, repo Repo, content []byte, path, message string) (err error) } +// FilesCreator can create the multiple files in some repository and in a single commit. +type FilesCreator interface { + FileCreator + CreateFiles(ctx *context.Context, commitAuthor config.CommitAuthor, repo Repo, message string, files []RepoFile) (err error) +} + // ReleaseNotesGenerator can generate release notes. type ReleaseNotesGenerator interface { GenerateReleaseNotes(ctx *context.Context, repo Repo, prev, current string) (string, error) diff --git a/internal/client/git.go b/internal/client/git.go index 84a3c9683..69dc72c4f 100644 --- a/internal/client/git.go +++ b/internal/client/git.go @@ -31,14 +31,14 @@ type gitClient struct { } // NewGitUploadClient -func NewGitUploadClient(branch string) FileCreator { +func NewGitUploadClient(branch string) FilesCreator { return &gitClient{ branch: branch, } } -// CreateFile implements FileCreator. -func (g *gitClient) CreateFile(ctx *context.Context, commitAuthor config.CommitAuthor, repo Repo, content []byte, path string, message string) error { +// CreateFiles implements FilesCreator. +func (g *gitClient) CreateFiles(ctx *context.Context, commitAuthor config.CommitAuthor, repo Repo, message string, files []RepoFile) (err error) { url, err := tmpl.New(ctx).Apply(repo.GitURL) if err != nil { return fmt.Errorf("git: failed to template git url: %w", err) @@ -95,20 +95,21 @@ func (g *gitClient) CreateFile(ctx *context.Context, commitAuthor config.CommitA return err } - location := filepath.Join(cwd, path) - log.WithField("path", location).Info("writing") - if err := os.MkdirAll(filepath.Dir(location), 0o755); err != nil { - return fmt.Errorf("failed to create parent dirs for %s: %w", path, err) + for _, file := range files { + location := filepath.Join(cwd, file.Path) + log.WithField("path", location).Info("writing") + if err := os.MkdirAll(filepath.Dir(location), 0o755); err != nil { + return fmt.Errorf("failed to create parent dirs for %s: %w", file.Path, err) + } + if err := os.WriteFile(location, file.Content, 0o644); err != nil { + return fmt.Errorf("failed to write %s: %w", file.Path, err) + } + log. + WithField("repository", url). + WithField("name", repo.Name). + WithField("file", file.Path). + Info("pushing") } - if err := os.WriteFile(location, content, 0o644); err != nil { - return fmt.Errorf("failed to write %s: %w", path, err) - } - - log. - WithField("repository", url). - WithField("name", repo.Name). - WithField("file", path). - Info("pushing") if err := runGitCmds(ctx, cwd, env, [][]string{ {"add", "-A", "."}, @@ -121,6 +122,14 @@ func (g *gitClient) CreateFile(ctx *context.Context, commitAuthor config.CommitA return nil } +// CreateFile implements FileCreator. +func (g *gitClient) CreateFile(ctx *context.Context, commitAuthor config.CommitAuthor, repo Repo, content []byte, path string, message string) error { + return g.CreateFiles(ctx, commitAuthor, repo, message, []RepoFile{{ + Path: path, + Content: content, + }}) +} + func keyPath(key string) (string, error) { if key == "" { return "", pipe.Skip("private_key is empty") diff --git a/internal/client/git_test.go b/internal/client/git_test.go index 3f9698be2..28c14bf99 100644 --- a/internal/client/git_test.go +++ b/internal/client/git_test.go @@ -29,23 +29,28 @@ func TestGitClient(t *testing.T) { PrivateKey: testlib.MakeNewSSHKey(t, keygen.Ed25519, ""), Name: "test1", } - require.NoError(t, cli.CreateFile( + require.NoError(t, cli.CreateFiles( ctx, author, repo, - []byte("fake content"), - "fake.txt", "hey test", + []RepoFile{ + { + Content: []byte("fake content"), + Path: "fake.txt", + }, + { + Content: []byte("fake2 content"), + Path: "fake2.txt", + }, + { + Content: []byte("fake content updated"), + Path: "fake.txt", + }, + }, )) - require.NoError(t, cli.CreateFile( - ctx, - author, - repo, - []byte("fake content 2"), - "fake.txt", - "hey test 2", - )) - require.Equal(t, "fake content 2", string(testlib.CatFileFromBareRepository(t, url, "fake.txt"))) + require.Equal(t, "fake content updated", string(testlib.CatFileFromBareRepository(t, url, "fake.txt"))) + require.Equal(t, "fake2 content", string(testlib.CatFileFromBareRepository(t, url, "fake2.txt"))) }) t.Run("no repo name", func(t *testing.T) { url := testlib.GitMakeBareRepository(t)