pipe: reorder patches based on email subjects

The Message-Id header cannot be relied upon as users can tweak it before
sending. The subject seems a more reliable basis to reorder patches.

Change the logic of sorting. Previously, all messages were required to
look like patches to be sorted. Now if at least one message looks like
a patch, all messages will be sorted by Subject before piping them.
Since `git am` ignores non-patch messages, it should allow piping series
of emails including reviews and comments without getting confusing
errors.

I have tested that this works on multiple series that appeared out of
order in my INBOX with the following command (after marking the
messages):

  :pipe -m sed -n 's/^Subject: //p'

Signed-off-by: Robin Jarry <robin@jarry.cc>
Tested-by: Bence Ferdinandy <bence@ferdinandy.com>
This commit is contained in:
Robin Jarry 2022-10-23 16:01:21 +02:00
parent a820e12d0f
commit a381630604
2 changed files with 12 additions and 25 deletions

View file

@ -5,6 +5,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [Unreleased](https://git.sr.ht/~rjarry/aerc/log/master) ## [Unreleased](https://git.sr.ht/~rjarry/aerc/log/master)
### Fixed
- `:pipe -m git am -3` on patch series when `Message-Id` headers have not been
generated by `git send-email`.
## [0.13.0](https://git.sr.ht/~rjarry/aerc/refs/0.13.0) - 2022-10-20 ## [0.13.0](https://git.sr.ht/~rjarry/aerc/refs/0.13.0) - 2022-10-20
### Added ### Added

View file

@ -7,7 +7,6 @@ import (
"os/exec" "os/exec"
"regexp" "regexp"
"sort" "sort"
"strconv"
"time" "time"
"git.sr.ht/~rjarry/aerc/commands" "git.sr.ht/~rjarry/aerc/commands"
@ -169,11 +168,11 @@ func (Pipe) Execute(aerc *widgets.Aerc, args []string) error {
} }
} }
is_git_patches := true is_git_patches := false
for _, msg := range messages { for _, msg := range messages {
info := store.Messages[msg.Content.Uid] info := store.Messages[msg.Content.Uid]
if info == nil || !gitMessageIdRe.MatchString(info.Envelope.MessageId) { if info != nil && patchSeriesRe.MatchString(info.Envelope.Subject) {
is_git_patches = false is_git_patches = true
break break
} }
} }
@ -186,9 +185,7 @@ func (Pipe) Execute(aerc *widgets.Aerc, args []string) error {
if infoi == nil || infoj == nil { if infoi == nil || infoj == nil {
return false return false
} }
msgidi := padGitMessageId(infoi.Envelope.MessageId) return infoi.Envelope.Subject < infoj.Envelope.Subject
msgidj := padGitMessageId(infoj.Envelope.MessageId)
return msgidi < msgidj
}) })
} }
@ -241,21 +238,6 @@ func newMessagesReader(messages []*types.FullMessage, useMbox bool) io.Reader {
return pr return pr
} }
var gitMessageIdRe = regexp.MustCompile(`^(\d+\.\d+)-(\d+)-(.+)$`) var patchSeriesRe = regexp.MustCompile(
`^.*\[(RFC )?PATCH( [^\]]+)? \d+/\d+] .+$`,
// Git send-email Message-Id headers have the following format: )
//
// DATETIME.PID-NUM-COMMITTER
//
// Return a copy of the message id with NUM zero-padded to three characters.
func padGitMessageId(msgId string) string {
matches := gitMessageIdRe.FindStringSubmatch(msgId)
if matches == nil {
return msgId
}
number, err := strconv.Atoi(matches[2])
if err != nil {
return msgId
}
return fmt.Sprintf("%s-%03d-%s", matches[1], number, matches[3])
}