aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--commands/patch/find.go132
-rw-r--r--doc/aerc-patch.7.scd10
-rw-r--r--lib/pama/find.go19
3 files changed, 161 insertions, 0 deletions
diff --git a/commands/patch/find.go b/commands/patch/find.go
new file mode 100644
index 00000000..9579e1f8
--- /dev/null
+++ b/commands/patch/find.go
@@ -0,0 +1,132 @@
+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"
+)
+
+type Find struct {
+ Filter bool `opt:"-f"`
+ Commit []string `opt:"..." required:"true" complete:"Complete"`
+}
+
+func init() {
+ register(Find{})
+}
+
+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
+}
diff --git a/doc/aerc-patch.7.scd b/doc/aerc-patch.7.scd
index 932bf8b1..7b5579a6 100644
--- a/doc/aerc-patch.7.scd
+++ b/doc/aerc-patch.7.scd
@@ -77,6 +77,16 @@ The following *:patch* sub-commands are supported:
If the _<commit-ish>_ is omitted, *aerc* will use the base commit of
the current project for the rebase.
+*:patch find* [*-f*] _<commit-hash>_
+ Searches the messages in the current folder of the current account for
+ the message associated with this _commit hash_ based on the subject line.
+
+ If a Message-ID is linked to a commit (i.e. when *:patch apply* was
+ used) then *find* will first perform a search for the Message-ID.
+
+ *-f*: Filter the message list instead of just showing the search
+ results. Only effective when search for Message-ID was not successful.
+
*:patch cd*
Changes the working directory to the root directory of the current
project.
diff --git a/lib/pama/find.go b/lib/pama/find.go
new file mode 100644
index 00000000..72203ee6
--- /dev/null
+++ b/lib/pama/find.go
@@ -0,0 +1,19 @@
+package pama
+
+import (
+ "fmt"
+
+ "git.sr.ht/~rjarry/aerc/lib/pama/models"
+)
+
+func (m PatchManager) Find(hash string, p models.Project) (models.Commit, error) {
+ var c models.Commit
+ rc, err := m.rc(p.RevctrlID, p.Root)
+ if err != nil {
+ return c, revErr(err)
+ }
+ if !rc.Exists(hash) {
+ return c, fmt.Errorf("no commit found for hash %s", hash)
+ }
+ return models.NewCommit(rc, hash, ""), nil
+}