diff --git a/git/commit.go b/git/commit.go index 3c5783a..31e008e 100644 --- a/git/commit.go +++ b/git/commit.go @@ -21,18 +21,18 @@ func (r *Repository) Add() *types.Cmd { return cmd } -// TestCleanTree returns non-zero if diff between index and local repository. +// IsCleanTree returns non-zero if diff between index and local repository. func (r *Repository) IsCleanTree() *types.Cmd { - cmd := &types.Cmd{ - Cmd: execabs.Command( - gitBin, - "diff-index", - "--quiet", - "HEAD", - "--ignore-submodules", - ), + args := []string{ + "diff-index", + "--quiet", + "HEAD", + "--ignore-submodules", } + cmd := &types.Cmd{ + Cmd: execabs.Command(gitBin, args...), + } cmd.Dir = r.WorkDir cmd.Stdout = io.Discard cmd.Stderr = io.Discard @@ -43,10 +43,6 @@ func (r *Repository) IsCleanTree() *types.Cmd { // Commit creates a new commit with the specified commit message. func (r *Repository) Commit() *types.Cmd { - if err := r.IsCleanTree().Run(); err == nil && !r.EmptyCommit { - return nil - } - args := []string{ "commit", "-m", diff --git a/git/status.go b/git/status.go deleted file mode 100644 index e558eb8..0000000 --- a/git/status.go +++ /dev/null @@ -1,43 +0,0 @@ -package git - -import ( - "github.com/rs/zerolog/log" - "github.com/thegeeklab/wp-plugin-go/v2/types" - "golang.org/x/sys/execabs" -) - -// Status returns a command that runs `git status --porcelain` for the given repository. -func (r *Repository) Status() *types.Cmd { - cmd := &types.Cmd{ - Cmd: execabs.Command( - gitBin, - "status", - "--porcelain", - ), - } - cmd.Dir = r.WorkDir - - return cmd -} - -// IsDirty checks if the given repository has any uncommitted changes. -// It runs `git status --porcelain` and returns true if the output is non-empty, -// indicating that there are uncommitted changes in the repository. -// If there is an error running the git command, it returns false. -func (r *Repository) IsDirty() bool { - cmd := r.Status() - cmd.Dir = r.WorkDir - - out, err := cmd.CombinedOutput() - if err != nil { - return false - } - - if len(out) > 0 { - log.Debug().Msg(string(out)) - - return true - } - - return false -} diff --git a/git/status_test.go b/git/status_test.go deleted file mode 100644 index aa539e3..0000000 --- a/git/status_test.go +++ /dev/null @@ -1,86 +0,0 @@ -package git - -import ( - "os" - "path/filepath" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestStatus(t *testing.T) { - tests := []struct { - name string - repo Repository - want []string - }{ - { - name: "with work dir", - repo: Repository{ - WorkDir: "/path/to/repo", - }, - want: []string{gitBin, "status", "--porcelain"}, - }, - { - name: "without work dir", - repo: Repository{}, - want: []string{gitBin, "status", "--porcelain"}, - }, - { - name: "with custom stderr", - repo: Repository{ - WorkDir: "/path/to/repo", - }, - want: []string{gitBin, "status", "--porcelain"}, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - cmd := tt.repo.Status() - assert.Equal(t, tt.want, cmd.Cmd.Args) - assert.Equal(t, tt.repo.WorkDir, cmd.Cmd.Dir) - }) - } -} - -func TestIsDirty(t *testing.T) { - tests := []struct { - name string - repo Repository - want bool - }{ - { - name: "dirty repo", - repo: Repository{ - WorkDir: t.TempDir(), - Branch: "main", - }, - want: true, - }, - { - name: "clean repo", - repo: Repository{ - WorkDir: t.TempDir(), - Branch: "main", - }, - want: false, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if err := tt.repo.Init().Run(); err != nil { - assert.NoError(t, err) - } - - if tt.want { - _, err := os.Create(filepath.Join(tt.repo.WorkDir, "dummy")) - assert.NoError(t, err) - } - - isDirty := tt.repo.IsDirty() - assert.Equal(t, tt.want, isDirty) - }) - } -} diff --git a/plugin/impl.go b/plugin/impl.go index 5b8b65d..9b6e5b0 100644 --- a/plugin/impl.go +++ b/plugin/impl.go @@ -101,6 +101,8 @@ func (p *Plugin) Validate() error { } // Execute provides the implementation of the plugin. +// +//nolint:gocognit func (p *Plugin) Execute() error { var err error @@ -161,45 +163,49 @@ func (p *Plugin) Execute() error { batchCmd = append(batchCmd, p.Settings.Repo.ConfigUserEmail()) batchCmd = append(batchCmd, p.Settings.Repo.ConfigSSLVerify(p.Network.InsecureSkipVerify)) + if err := ExecBatch(batchCmd); err != nil { + return err + } + for _, actionStr := range p.Settings.Action.Value() { action := GitAction(actionStr) switch action { case GitActionClone: log.Debug().Msg("Compose action cmd: clone") - cmds, err := p.handleClone() - if err != nil { + if err := p.handleClone(); err != nil { return err } - - batchCmd = append(batchCmd, cmds...) case GitActionCommit: log.Debug().Msg("Compose action cmd: commit") - batchCmd = append(batchCmd, p.handleCommit()...) + if err := p.handleCommit(); err != nil { + return err + } case GitActionPush: log.Debug().Msg("Compose action cmd: push") - batchCmd = append(batchCmd, p.handlePush()...) + if err := p.handlePush(); err != nil { + return err + } case GitActionPages: log.Debug().Msg("Compose action cmd: pages") - cmds, err := p.handlePages() - if err != nil { + if err := p.handleClone(); err != nil { return err } - batchCmd = append(batchCmd, cmds...) - } - } + if err := p.handlePages(); err != nil { + return err + } - for _, cmd := range batchCmd { - if cmd == nil { - continue - } + if err := p.handleCommit(); err != nil { + return err + } - if err := cmd.Run(); err != nil { - return err + if err := p.handlePush(); err != nil { + return err + } } } @@ -208,65 +214,57 @@ func (p *Plugin) Execute() error { // handleClone clones the remote repository into the configured working directory. // If the working directory is not empty, it returns an error. -func (p *Plugin) handleClone() ([]*types.Cmd, error) { - var cmds []*types.Cmd +func (p *Plugin) handleClone() error { + var batchCmd []*types.Cmd if !p.Settings.Repo.IsEmpty { - return cmds, fmt.Errorf("%w: %s exists and not empty", ErrGitCloneDestintionNotValid, p.Settings.Repo.WorkDir) + return fmt.Errorf("%w: %s exists and not empty", ErrGitCloneDestintionNotValid, p.Settings.Repo.WorkDir) } if p.Settings.Repo.RemoteURL != "" { - cmds = append(cmds, p.Settings.Repo.RemoteAdd()) + batchCmd = append(batchCmd, p.Settings.Repo.RemoteAdd()) } - cmds = append(cmds, p.Settings.Repo.FetchSource()) - cmds = append(cmds, p.Settings.Repo.CheckoutHead()) + batchCmd = append(batchCmd, p.Settings.Repo.FetchSource()) + batchCmd = append(batchCmd, p.Settings.Repo.CheckoutHead()) - return cmds, nil + return ExecBatch(batchCmd) } // HandleCommit commits changes locally. -func (p *Plugin) handleCommit() []*types.Cmd { - var cmds []*types.Cmd +func (p *Plugin) handleCommit() error { + if err := p.Settings.Repo.Add().Run(); err != nil { + return err + } - cmds = append(cmds, p.Settings.Repo.Add()) - cmds = append(cmds, p.Settings.Repo.Commit()) + if err := p.Settings.Repo.IsCleanTree().Run(); err == nil { + if !p.Settings.Repo.EmptyCommit { + log.Debug().Msg("Commit skipped: no changes") - return cmds + return nil + } + } + + return p.Settings.Repo.Commit().Run() } // HandlePush pushs changes to remote. -func (p *Plugin) handlePush() []*types.Cmd { - return []*types.Cmd{p.Settings.Repo.RemotePush()} +func (p *Plugin) handlePush() error { + return p.Settings.Repo.RemotePush().Run() } // HandlePages syncs, commits and pushes the changes from the pages directory to the pages branch. -func (p *Plugin) handlePages() ([]*types.Cmd, error) { - var cmds []*types.Cmd - +func (p *Plugin) handlePages() error { log.Debug(). Str("src", p.Settings.Pages.Directory). Str("dest", p.Settings.Repo.WorkDir). Msg("handlePages") - ccmd, err := p.handleClone() - if err != nil { - return cmds, err - } - - cmds = append(cmds, ccmd...) - cmds = append(cmds, - SyncDirectories( - p.Settings.Pages.Exclude.Value(), - p.Settings.Pages.Delete, - p.Settings.Pages.Directory, - p.Settings.Repo.WorkDir, - (zerolog.GlobalLevel() == zerolog.DebugLevel), - ), - ) - - cmds = append(cmds, p.handleCommit()...) - cmds = append(cmds, p.handlePush()...) - - return cmds, nil + return SyncDirectories( + p.Settings.Pages.Exclude.Value(), + p.Settings.Pages.Delete, + p.Settings.Pages.Directory, + p.Settings.Repo.WorkDir, + (zerolog.GlobalLevel() == zerolog.DebugLevel), + ).Run() } diff --git a/plugin/util.go b/plugin/util.go index 10e8ab5..9fe48c9 100644 --- a/plugin/util.go +++ b/plugin/util.go @@ -4,6 +4,8 @@ import ( "fmt" "os" "path/filepath" + + "github.com/thegeeklab/wp-plugin-go/v2/types" ) const ( @@ -26,3 +28,18 @@ func WriteNetrc(path, machine, login, password string) error { return nil } + +// ExecBatch executes a batch of commands. If any command in the batch fails, the function will return the error. +func ExecBatch(batchCmd []*types.Cmd) error { + for _, cmd := range batchCmd { + if cmd == nil { + continue + } + + if err := cmd.Run(); err != nil { + return err + } + } + + return nil +}