package git import ( "errors" "fmt" "path/filepath" "strings" "time" "github.com/ProtonMail/go-crypto/openpgp" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing/object" ) type CommitOption func(*Commit) func WithAuthor(name, email string) CommitOption { return func(c *Commit) { c.Author = &object.Signature{ Name: name, Email: email, When: time.Now(), } } } func WithCommitter(name, email string) CommitOption { return func(c *Commit) { c.Committer = &object.Signature{ Name: name, Email: email, When: time.Now(), } } } func WithFileContent(content []byte, filename, folder string) CommitOption { return func(c *Commit) { c.Content = content c.Filename = filepath.Join(folder, fmt.Sprintf("%s.json", filename)) } } func WithSigner(signKey SignKey) CommitOption { return func(c *Commit) { c.signKey = signKey.entity } } type Commit struct { Author *object.Signature Committer *object.Signature Content []byte Filename string KeyFile string project *Project signKey *openpgp.Entity } func (p *Project) NewCommit(options ...CommitOption) *Commit { commit := &Commit{project: p} for _, option := range options { option(commit) } return commit } func (c *Commit) Create(msg string) error { if err := c.addContent(); err != nil { return err } if _, err := c.project.worktree.Add(c.Filename); err != nil { return err } commitOpts := git.CommitOptions{Author: c.Author} if c.Committer != nil { commitOpts.Committer = c.Committer } if c.signKey != nil { commitOpts.SignKey = c.signKey } _, err := c.project.worktree.Commit(msg, &commitOpts) if err != nil { return err } return nil } func (c *Commit) Exists(uid string, id uint) bool { commitIter, err := c.project.repository.Log(&git.LogOptions{}) if err != nil { return false } err = commitIter.ForEach(func(commit *object.Commit) error { if strings.Contains(commit.Message, fmt.Sprintf("Update %s", uid)) && strings.Contains(commit.Message, fmt.Sprintf("version %d", id)) { return errors.New("version already committed") } return nil }) return err != nil } func (c *Commit) addContent() error { file, err := c.project.worktree.Filesystem.Create(c.Filename) if err != nil { return err } defer file.Close() _, err = file.Write(c.Content) return err }