mirror of
https://git.sr.ht/~rjarry/aerc
synced 2025-07-06 19:30:22 +02:00

Go 1.18 is already EOL. go-maildir v0.5.0 requires go 1.20 at least. Since go 1.20 is also EOL, bump the minimum required go version to the first still supported version which is 1.21. Go 1.20 deprecated Seed and Read in math/rand. Update the code accordingly. Changelog-deprecated: Support for go 1.20 and older. Signed-off-by: Bence Ferdinandy <bence@ferdinandy.com> Acked-by: Robin Jarry <robin@jarry.cc>
138 lines
3 KiB
Go
138 lines
3 KiB
Go
package pama
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"encoding/base64"
|
|
"fmt"
|
|
mathrand "math/rand"
|
|
"strings"
|
|
|
|
"git.sr.ht/~rjarry/aerc/lib/log"
|
|
"git.sr.ht/~rjarry/aerc/lib/pama/models"
|
|
)
|
|
|
|
func (m PatchManager) CurrentProject() (p models.Project, err error) {
|
|
store := m.store()
|
|
name, err := store.CurrentName()
|
|
if name == "" || err != nil {
|
|
log.Errorf("failed to get current name: %v", storeErr(err))
|
|
err = fmt.Errorf("no current project set. " +
|
|
"Run :patch init first")
|
|
return
|
|
}
|
|
names, err := store.Names()
|
|
if err != nil {
|
|
err = storeErr(err)
|
|
return
|
|
}
|
|
notFound := true
|
|
for _, s := range names {
|
|
if s == name {
|
|
notFound = !notFound
|
|
break
|
|
}
|
|
}
|
|
if notFound {
|
|
err = fmt.Errorf("project '%s' does not exist anymore. "+
|
|
"Run :patch init or :patch switch", name)
|
|
return
|
|
}
|
|
p, err = store.Current()
|
|
if err != nil {
|
|
err = storeErr(err)
|
|
}
|
|
return
|
|
}
|
|
|
|
func (m PatchManager) CurrentPatches() ([]string, error) {
|
|
c, err := m.CurrentProject()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return models.Commits(c.Commits).Tags(), nil
|
|
}
|
|
|
|
func (m PatchManager) Head(p models.Project) (string, error) {
|
|
rc, err := m.rc(p.RevctrlID, p.Root)
|
|
if err != nil {
|
|
return "", revErr(err)
|
|
}
|
|
return rc.Head()
|
|
}
|
|
|
|
func (m PatchManager) Clean(p models.Project) bool {
|
|
rc, err := m.rc(p.RevctrlID, p.Root)
|
|
if err != nil {
|
|
log.Errorf("could not get revctl: %v", revErr(err))
|
|
return false
|
|
}
|
|
return rc.Clean()
|
|
}
|
|
|
|
func (m PatchManager) ApplyCmd(p models.Project) (string, error) {
|
|
rc, err := m.rc(p.RevctrlID, p.Root)
|
|
if err != nil {
|
|
return "", revErr(err)
|
|
}
|
|
return rc.ApplyCmd(), nil
|
|
}
|
|
|
|
func generateTag(n int) (string, error) {
|
|
b := make([]byte, n)
|
|
_, err := rand.Read(b)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return base64.RawURLEncoding.EncodeToString(b), nil
|
|
}
|
|
|
|
func makeUnique(s string) string {
|
|
tag, err := generateTag(4)
|
|
if err != nil {
|
|
return fmt.Sprintf("%s_%d", s, mathrand.Uint32())
|
|
}
|
|
return fmt.Sprintf("%s_%s", s, tag)
|
|
}
|
|
|
|
// ApplyUpdate is called after the commits have been applied with the
|
|
// ApplyCmd(). It will determine the additional commits from the commitID (last
|
|
// HEAD position), assign the patch tag to those commits and store them in
|
|
// project p.
|
|
func (m PatchManager) ApplyUpdate(p models.Project, patch, commitID string,
|
|
kv map[string]string,
|
|
) (models.Project, error) {
|
|
rc, err := m.rc(p.RevctrlID, p.Root)
|
|
if err != nil {
|
|
return p, revErr(err)
|
|
}
|
|
|
|
commitIDs, err := rc.History(commitID)
|
|
if err != nil {
|
|
return p, revErr(err)
|
|
}
|
|
if len(commitIDs) == 0 {
|
|
return p, fmt.Errorf("no commits found for patch %s", patch)
|
|
}
|
|
|
|
if models.Commits(p.Commits).HasTag(patch) {
|
|
log.Warnf("Patch name '%s' already exists", patch)
|
|
patch = makeUnique(patch)
|
|
log.Warnf("Creating new name: '%s'", patch)
|
|
}
|
|
|
|
for _, c := range commitIDs {
|
|
nc := models.NewCommit(rc, c, patch)
|
|
for msgid, subj := range kv {
|
|
if nc.Subject == "" {
|
|
continue
|
|
}
|
|
if strings.Contains(subj, nc.Subject) {
|
|
nc.MessageId = msgid
|
|
}
|
|
}
|
|
p.Commits = append(p.Commits, nc)
|
|
}
|
|
|
|
err = m.store().StoreProject(p, true)
|
|
return p, storeErr(err)
|
|
}
|