diff options
author | Koni Marti <koni.marti@gmail.com> | 2023-11-24 16:03:11 +0100 |
---|---|---|
committer | Robin Jarry <robin@jarry.cc> | 2023-12-30 15:42:09 +0100 |
commit | 6f8f3d718c8b0303d16d9bfae2770a031678df59 (patch) | |
tree | 8211c92e944f3f6a53750cbcd930682f664e0f9b | |
parent | f8c9e7fff564667700c3dbc239d55db8fcd032a6 (diff) | |
download | aerc-6f8f3d718c8b0303d16d9bfae2770a031678df59.tar.gz |
patch/find: add find sub-cmd
Implement the :patch find command. Search and filter for a given commit
by subject line in the current accout and current folder.
Signed-off-by: Koni Marti <koni.marti@gmail.com>
Acked-by: Robin Jarry <robin@jarry.cc>
-rw-r--r-- | commands/patch/find.go | 132 | ||||
-rw-r--r-- | doc/aerc-patch.7.scd | 10 | ||||
-rw-r--r-- | lib/pama/find.go | 19 |
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 +} |