mirror of
https://github.com/thegeeklab/wp-git-clone.git
synced 2024-11-25 09:20:40 +00:00
183 lines
4.6 KiB
Go
183 lines
4.6 KiB
Go
package plugin
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
"time"
|
|
|
|
"github.com/rs/zerolog/log"
|
|
"github.com/thegeeklab/wp-plugin-go/v2/file"
|
|
"github.com/thegeeklab/wp-plugin-go/v2/types"
|
|
"github.com/thegeeklab/wp-plugin-go/v2/util"
|
|
)
|
|
|
|
const (
|
|
daemonBackoffMaxRetries = 3
|
|
daemonBackoffInitialInterval = 2 * time.Second
|
|
daemonBackoffMultiplier = 3.5
|
|
)
|
|
|
|
var (
|
|
ErrGitCloneDestintionNotValid = errors.New("destination not valid")
|
|
ErrTypeAssertionFailed = errors.New("type assertion failed")
|
|
)
|
|
|
|
//nolint:revive
|
|
func (p *Plugin) run(ctx context.Context) error {
|
|
if err := p.FlagsFromContext(); err != nil {
|
|
return fmt.Errorf("validation failed: %w", err)
|
|
}
|
|
|
|
if err := p.Validate(); err != nil {
|
|
return fmt.Errorf("validation failed: %w", err)
|
|
}
|
|
|
|
if err := p.Execute(); err != nil {
|
|
return fmt.Errorf("execution failed: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Validate handles the settings validation of the plugin.
|
|
func (p *Plugin) Validate() error {
|
|
var err error
|
|
|
|
// This default cannot be set in the cli flag, as the CI_* environment variables
|
|
// can be set empty, resulting in an empty default value.
|
|
if p.Settings.Repo.Branch == "" {
|
|
p.Settings.Repo.Branch = "main"
|
|
}
|
|
|
|
if p.Settings.Repo.WorkDir == "" {
|
|
p.Settings.Repo.WorkDir, err = os.Getwd()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get working directory: %w", err)
|
|
}
|
|
}
|
|
|
|
if p.Settings.Partial {
|
|
p.Settings.Repo.Depth = 1
|
|
p.Settings.Repo.Filter = "tree:0"
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Execute provides the implementation of the plugin.
|
|
func (p *Plugin) Execute() error {
|
|
var err error
|
|
|
|
homeDir := util.GetUserHomeDir()
|
|
batchCmd := make([]*types.Cmd, 0)
|
|
|
|
fmt.Println(p.Settings.Repo.WorkDir)
|
|
|
|
// Handle repo initialization.
|
|
if err := os.MkdirAll(p.Settings.Repo.WorkDir, os.ModePerm); err != nil {
|
|
return fmt.Errorf("failed to create working directory: %w", err)
|
|
}
|
|
|
|
p.Settings.Repo.IsEmpty, err = file.IsDirEmpty(p.Settings.Repo.WorkDir)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to check working directory: %w", err)
|
|
}
|
|
|
|
isDir, err := file.IsDir(filepath.Join(p.Settings.Repo.WorkDir, ".git"))
|
|
if err != nil {
|
|
return fmt.Errorf("failed to check working directory: %w", err)
|
|
}
|
|
|
|
if !isDir {
|
|
batchCmd = append(batchCmd, p.Settings.Repo.Init())
|
|
batchCmd = append(batchCmd, p.Settings.Repo.RemoteAdd())
|
|
|
|
if p.Settings.SSHKey != "" {
|
|
batchCmd = append(batchCmd, p.Settings.Repo.ConfigSSHCommand(p.Settings.SSHKey))
|
|
}
|
|
}
|
|
|
|
batchCmd = append(batchCmd, p.Settings.Repo.ConfigSSLVerify(p.Network.InsecureSkipVerify))
|
|
|
|
netrc := p.Settings.Netrc
|
|
if err := WriteNetrc(homeDir, netrc.Machine, netrc.Login, netrc.Password); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Handle clone
|
|
if p.Settings.Repo.CommitSha == "" {
|
|
// fetch and checkout by ref
|
|
log.Info().Msg("no commit information: using head checkout")
|
|
|
|
batchCmd = append(batchCmd, p.Settings.Repo.FetchSource(p.Settings.Repo.CommitRef))
|
|
batchCmd = append(batchCmd, p.Settings.Repo.CheckoutHead())
|
|
} else {
|
|
batchCmd = append(batchCmd, p.Settings.Repo.FetchSource(p.Settings.Repo.CommitSha))
|
|
batchCmd = append(batchCmd, p.Settings.Repo.CheckoutSha())
|
|
}
|
|
|
|
if p.Settings.Tags {
|
|
batchCmd = append(batchCmd, p.Settings.Repo.FetchTags())
|
|
}
|
|
|
|
for name, submoduleURL := range p.Settings.Repo.Submodules {
|
|
batchCmd = append(batchCmd, p.Settings.Repo.ConfigRemapSubmodule(name, submoduleURL))
|
|
}
|
|
|
|
if p.Settings.Recursive {
|
|
batchCmd = append(batchCmd, p.Settings.Repo.SubmoduleUpdate())
|
|
}
|
|
|
|
if p.Settings.Lfs {
|
|
batchCmd = append(batchCmd, p.Settings.Repo.FetchLFS())
|
|
batchCmd = append(batchCmd, p.Settings.Repo.CheckoutLFS())
|
|
}
|
|
|
|
for _, cmd := range batchCmd {
|
|
buf := new(bytes.Buffer)
|
|
|
|
// Don' set GIT_TERMINAL_PROMPT=0 as it prevents git from loading .netrc
|
|
defaultEnvVars := []string{
|
|
"GIT_LFS_SKIP_SMUDGE=1", // prevents git-lfs from retrieving any LFS files
|
|
}
|
|
|
|
if p.Settings.Home != "" {
|
|
if _, err := os.Stat(p.Settings.Home); !os.IsNotExist(err) {
|
|
defaultEnvVars = append(defaultEnvVars, fmt.Sprintf("HOME=%s", p.Settings.Home))
|
|
}
|
|
}
|
|
|
|
cmd.Env = append(os.Environ(), defaultEnvVars...)
|
|
cmd.Stdout = io.MultiWriter(os.Stdout, buf)
|
|
cmd.Stderr = io.MultiWriter(os.Stderr, buf)
|
|
cmd.Dir = p.Settings.Repo.WorkDir
|
|
|
|
err := cmd.Run()
|
|
|
|
switch {
|
|
case err != nil && shouldRetry(buf.String()):
|
|
return retryCmd(cmd)
|
|
case err != nil:
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (p *Plugin) FlagsFromContext() error {
|
|
submodules, ok := p.Context.Generic("submodule-override").(*types.MapFlag)
|
|
if !ok {
|
|
return fmt.Errorf("%w: failed to read submodule-override input", ErrTypeAssertionFailed)
|
|
}
|
|
|
|
p.Settings.Repo.Submodules = submodules.Get()
|
|
|
|
return nil
|
|
}
|