You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
aerc/commands/patch/find.go

141 lines
2.5 KiB
Go

package patch
import (
"errors"
"fmt"
"net/textproto"
"strings"
"git.sr.ht/~rjarry/aerc/app"
"git.sr.ht/~rjarry/aerc/commands"
"git.sr.ht/~rjarry/aerc/commands/account"
"git.sr.ht/~rjarry/aerc/lib/pama"
"git.sr.ht/~rjarry/aerc/lib/pama/models"
"git.sr.ht/~rjarry/go-opt/v2"
)
type Find struct {
Filter bool `opt:"-f" desc:"Filter message list instead of search."`
Commit []string `opt:"..." required:"true" complete:"Complete" desc:"Search for <commit-ish>."`
}
func init() {
register(Find{})
}
func (Find) Description() string {
return "Search for applied patches."
}
func (Find) Context() commands.CommandContext {
return commands.GLOBAL
}
func (Find) Aliases() []string {
return []string{"find"}
}
func (*Find) Complete(arg string) []string {
m := pama.New()
p, err := m.CurrentProject()
if err != nil {
return nil
}
options := make([]string, len(p.Commits))
for i, c := range p.Commits {
options[i] = fmt.Sprintf("%-6.6s %s", c.ID, c.Subject)
}
return commands.FilterList(options, arg, nil)
}
func (s Find) Execute(_ []string) error {
m := pama.New()
p, err := m.CurrentProject()
if err != nil {
return err
}
if len(s.Commit) == 0 {
return errors.New("missing commit hash")
}
lexed := opt.LexArgs(strings.TrimSpace(s.Commit[0]))
hash, err := lexed.ArgSafe(0)
if err != nil {
return err
}
if len(hash) < 4 {
return errors.New("Commit hash is too short.")
}
var c models.Commit
for _, commit := range p.Commits {
if strings.Contains(commit.ID, hash) {
c = commit
break
}
}
if c.ID == "" {
var err error
c, err = m.Find(hash, p)
if err != nil {
return err
}
}
// If Message-Id is provided, find it in store
if c.MessageId != "" {
if selectMessageId(c.MessageId) {
return nil
}
}
// Fallback to a search based on the subject line
args := []string{"search"}
if s.Filter {
args[0] = "filter"
}
headers := make(textproto.MIMEHeader)
args = append(args, fmt.Sprintf("-H Subject:%s", c.Subject))
headers.Add("Subject", c.Subject)
cmd := account.SearchFilter{
Headers: headers,
}
return cmd.Execute(args)
}
func selectMessageId(msgid string) bool {
acct := app.SelectedAccount()
if acct == nil {
return false
}
store := acct.Store()
if store == nil {
return false
}
for uid, msg := range store.Messages {
if msg == nil {
continue
}
if msg.RFC822Headers == nil {
continue
}
id, err := msg.RFC822Headers.MessageID()
if err != nil {
continue
}
if id == msgid {
store.Select(uid)
return true
}
}
return false
}