2022-02-25 00:17:02 +01:00
|
|
|
package mapper
|
2022-02-24 22:38:17 +01:00
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"os"
|
2022-03-01 19:52:02 +01:00
|
|
|
"os/exec"
|
2022-02-28 23:41:21 +01:00
|
|
|
"time"
|
2022-02-24 22:38:17 +01:00
|
|
|
|
|
|
|
"github.com/go-git/go-git/v5"
|
2022-02-28 23:41:21 +01:00
|
|
|
"github.com/go-git/go-git/v5/plumbing/object"
|
2022-02-26 01:28:36 +01:00
|
|
|
"github.com/go-git/go-git/v5/plumbing/transport"
|
2022-02-24 22:38:17 +01:00
|
|
|
"github.com/go-git/go-git/v5/plumbing/transport/http"
|
2022-02-26 01:28:36 +01:00
|
|
|
"github.com/go-git/go-git/v5/plumbing/transport/ssh"
|
2022-02-24 22:38:17 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
2022-02-26 01:28:36 +01:00
|
|
|
ErrDirIsFile = errors.New("path is a file")
|
|
|
|
ErrInvalidEnv = errors.New("found invalid environment variable in path")
|
2022-02-24 22:38:17 +01:00
|
|
|
)
|
|
|
|
|
2022-02-28 23:41:21 +01:00
|
|
|
type RepositoryActions interface {
|
|
|
|
PushChanges(msg string) error
|
|
|
|
openRepository() error
|
|
|
|
}
|
|
|
|
|
|
|
|
type Repository struct {
|
|
|
|
auth transport.AuthMethod
|
|
|
|
repository *git.Repository
|
|
|
|
repoPath string
|
|
|
|
author author
|
|
|
|
url string
|
|
|
|
}
|
|
|
|
|
|
|
|
type author struct {
|
|
|
|
name string
|
|
|
|
email string
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewRepository(config Git, repoPath string) (RepositoryActions, error) {
|
|
|
|
var auth transport.AuthMethod
|
2022-03-01 12:31:35 +01:00
|
|
|
if config.URL == "" {
|
|
|
|
return nil, errors.New("a repository URI is needed (either using GIT protocol or HTTPS)")
|
|
|
|
}
|
|
|
|
repoPath, err := absolutePath(repoPath)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2022-02-28 23:41:21 +01:00
|
|
|
|
|
|
|
if config.SSH.Passphrase != "" && config.SSH.PrivateKey != "" {
|
|
|
|
privateKey, err := absolutePath(config.SSH.PrivateKey)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, err := os.Stat(privateKey); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
auth, err = ssh.NewPublicKeysFromFile("git", privateKey, config.SSH.Passphrase)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
auth = &http.BasicAuth{
|
|
|
|
Username: config.BasicAuth.Username,
|
|
|
|
Password: config.BasicAuth.Password,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
repo := &Repository{
|
|
|
|
auth: auth,
|
|
|
|
repository: nil,
|
|
|
|
repoPath: repoPath,
|
2022-03-01 12:31:35 +01:00
|
|
|
url: config.URL,
|
2022-02-28 23:41:21 +01:00
|
|
|
author: author{
|
|
|
|
name: config.Name,
|
|
|
|
email: config.Email,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := repo.openRepository(); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return repo, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *Repository) openRepository() error {
|
|
|
|
s, err := os.Stat(r.repoPath)
|
2022-02-24 22:38:17 +01:00
|
|
|
if err != nil {
|
|
|
|
if os.IsNotExist(err) {
|
2022-02-28 23:41:21 +01:00
|
|
|
repo, err := git.PlainClone(r.repoPath, false, &git.CloneOptions{
|
|
|
|
URL: r.url,
|
2022-02-24 22:38:17 +01:00
|
|
|
Progress: os.Stdout,
|
2022-02-28 23:41:21 +01:00
|
|
|
Auth: r.auth,
|
2022-02-24 22:38:17 +01:00
|
|
|
})
|
|
|
|
if err != nil {
|
2022-02-28 23:41:21 +01:00
|
|
|
return err
|
2022-02-24 22:38:17 +01:00
|
|
|
}
|
|
|
|
|
2022-02-28 23:41:21 +01:00
|
|
|
r.repository = repo
|
|
|
|
return nil
|
2022-02-24 22:38:17 +01:00
|
|
|
}
|
|
|
|
|
2022-02-28 23:41:21 +01:00
|
|
|
return err
|
2022-02-24 22:38:17 +01:00
|
|
|
}
|
|
|
|
|
2022-02-26 01:28:36 +01:00
|
|
|
if !s.IsDir() {
|
2022-02-28 23:41:21 +01:00
|
|
|
return ErrDirIsFile
|
2022-02-24 22:38:17 +01:00
|
|
|
}
|
|
|
|
|
2022-02-28 23:41:21 +01:00
|
|
|
repo, err := git.PlainOpen(r.repoPath)
|
2022-02-24 22:38:17 +01:00
|
|
|
if err != nil {
|
2022-02-28 23:41:21 +01:00
|
|
|
return err
|
2022-02-24 22:38:17 +01:00
|
|
|
}
|
|
|
|
|
2022-02-28 23:41:21 +01:00
|
|
|
r.repository = repo
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *Repository) PushChanges(msg string) error {
|
|
|
|
w, err := r.repository.Worktree()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2022-03-01 19:52:02 +01:00
|
|
|
// TODO: debug why deleted files/folders aren't added to index
|
|
|
|
// if err := w.AddWithOptions(&git.AddOptions{
|
|
|
|
// All: true,
|
|
|
|
// }); err != nil {
|
|
|
|
// return err
|
|
|
|
// }
|
|
|
|
|
|
|
|
cmd := exec.Command("git", "add", ".")
|
|
|
|
cmd.Dir = r.repoPath
|
|
|
|
if err := cmd.Run(); err != nil {
|
|
|
|
return errors.New("failed to add files to git index: " + err.Error())
|
2022-02-28 23:41:21 +01:00
|
|
|
}
|
|
|
|
|
2022-03-01 19:52:02 +01:00
|
|
|
if _, err := w.Commit(msg, &git.CommitOptions{
|
2022-02-28 23:41:21 +01:00
|
|
|
Author: &object.Signature{
|
|
|
|
Name: r.author.name,
|
|
|
|
Email: r.author.email,
|
|
|
|
When: time.Now(),
|
|
|
|
},
|
2022-03-01 19:52:02 +01:00
|
|
|
}); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2022-02-28 23:41:21 +01:00
|
|
|
|
|
|
|
return r.repository.Push(&git.PushOptions{})
|
2022-02-24 22:38:17 +01:00
|
|
|
}
|