aboutsummaryrefslogtreecommitdiffstats
path: root/commands/msg/pipe.go
diff options
context:
space:
mode:
authorRobin Jarry <robin@jarry.cc>2022-07-28 23:10:30 +0200
committerRobin Jarry <robin@jarry.cc>2022-08-01 09:38:15 +0200
commitc816103a24757bd0e91f7d96b60073a3063bc85a (patch)
treee9e70a0bd2b96925cc60732fd4ef6c9f5349409e /commands/msg/pipe.go
parentd05cad1707c8702b52c244678d6d6a4e86ed5a87 (diff)
downloadaerc-c816103a24757bd0e91f7d96b60073a3063bc85a.tar.gz
pipe: fix ordering by message id for long patch series
Git send-email Message-Id headers have the following format: DATETIME.PID-NUM-COMMITTER Unfortunately, when there are more than 9 patches, the patch number (NUM) is not zero-padded which makes ascii sorting invalid, e.g.: 1 10 11 12 2 3 4 5 6 7 8 9 Instead of: 1 2 3 4 5 6 7 8 9 10 11 12 We need the patches to be ordered correctly to pipe them to git am. Make sure to pad the patch number with zero characters to allow series of up to 999 patches. Only re-order messages before piping them if all the Message-Id headers look like git-send-email headers. Link: https://github.com/git/git/blob/v2.36.0/git-send-email.perl#L1197 Signed-off-by: Robin Jarry <robin@jarry.cc> Tested-by: Koni Marti <koni.marti@gmail.com>
Diffstat (limited to 'commands/msg/pipe.go')
-rw-r--r--commands/msg/pipe.go49
1 files changed, 40 insertions, 9 deletions
diff --git a/commands/msg/pipe.go b/commands/msg/pipe.go
index 35ee05bc..71e402d2 100644
--- a/commands/msg/pipe.go
+++ b/commands/msg/pipe.go
@@ -5,7 +5,9 @@ import (
"fmt"
"io"
"os/exec"
+ "regexp"
"sort"
+ "strconv"
"time"
"git.sr.ht/~rjarry/aerc/commands"
@@ -164,16 +166,28 @@ func (Pipe) Execute(aerc *widgets.Aerc, args []string) error {
}
}
- // Sort all messages by increasing Message-Id header.
- // This will ensure that patch series are applied in order.
- sort.Slice(messages, func(i, j int) bool {
- infoi := store.Messages[messages[i].Content.Uid]
- infoj := store.Messages[messages[j].Content.Uid]
- if infoi == nil || infoj == nil {
- return false
+ is_git_patches := true
+ for _, msg := range messages {
+ info := store.Messages[msg.Content.Uid]
+ if info == nil || !gitMessageIdRe.MatchString(info.Envelope.MessageId) {
+ is_git_patches = false
+ break
}
- return infoi.Envelope.MessageId < infoj.Envelope.MessageId
- })
+ }
+ if is_git_patches {
+ // Sort all messages by increasing Message-Id header.
+ // This will ensure that patch series are applied in order.
+ sort.Slice(messages, func(i, j int) bool {
+ infoi := store.Messages[messages[i].Content.Uid]
+ infoj := store.Messages[messages[j].Content.Uid]
+ if infoi == nil || infoj == nil {
+ return false
+ }
+ msgidi := padGitMessageId(infoi.Envelope.MessageId)
+ msgidj := padGitMessageId(infoj.Envelope.MessageId)
+ return msgidi < msgidj
+ })
+ }
reader := newMessagesReader(messages, len(messages) > 1)
if background {
@@ -219,3 +233,20 @@ func newMessagesReader(messages []*types.FullMessage, useMbox bool) io.Reader {
}()
return pr
}
+
+var gitMessageIdRe = regexp.MustCompile(`^(\d+\.\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])
+}