pipe: use go-mbox for writing multiple messages

Use go-mbox for piping out multiple messages in the mbox format.

Signed-off-by: Koni Marti <koni.marti@gmail.com>
Acked-by: Robin Jarry <robin@jarry.cc>
This commit is contained in:
Koni Marti 2022-07-11 20:11:22 +02:00 committed by Robin Jarry
parent e572087e58
commit 5102d32cea
1 changed files with 13 additions and 38 deletions

View File

@ -11,6 +11,7 @@ import (
"git.sr.ht/~rjarry/aerc/commands" "git.sr.ht/~rjarry/aerc/commands"
"git.sr.ht/~rjarry/aerc/logging" "git.sr.ht/~rjarry/aerc/logging"
"git.sr.ht/~rjarry/aerc/widgets" "git.sr.ht/~rjarry/aerc/widgets"
mboxer "git.sr.ht/~rjarry/aerc/worker/mbox"
"git.sr.ht/~rjarry/aerc/worker/types" "git.sr.ht/~rjarry/aerc/worker/types"
"git.sr.ht/~sircmpwn/getopt" "git.sr.ht/~sircmpwn/getopt"
@ -174,7 +175,7 @@ func (Pipe) Execute(aerc *widgets.Aerc, args []string) error {
return infoi.Envelope.MessageId < infoj.Envelope.MessageId return infoi.Envelope.MessageId < infoj.Envelope.MessageId
}) })
reader := newMessagesReader(messages) reader := newMessagesReader(messages, len(messages) > 1)
if background { if background {
doExec(reader) doExec(reader)
} else { } else {
@ -204,43 +205,17 @@ func (Pipe) Execute(aerc *widgets.Aerc, args []string) error {
return nil return nil
} }
// The actual sender address does not matter, nor does the date. This is mostly indended func newMessagesReader(messages []*types.FullMessage, useMbox bool) io.Reader {
// for git am which requires separators to look like something valid. pr, pw := io.Pipe()
// https://github.com/git/git/blame/v2.35.1/builtin/mailsplit.c#L15-L44 go func() {
var mboxSeparator []byte = []byte("From ???@??? Tue Jun 23 16:32:49 1981\n") defer pw.Close()
for _, msg := range messages {
type messagesReader struct { if useMbox {
messages []*types.FullMessage mboxer.Write(pw, msg.Content.Reader, "", time.Now())
mbox bool } else {
separatorNeeded bool io.Copy(pw, msg.Content.Reader)
}
func newMessagesReader(messages []*types.FullMessage) io.Reader {
needMboxSeparator := len(messages) > 1
return &messagesReader{messages, needMboxSeparator, needMboxSeparator}
}
func (mr *messagesReader) Read(p []byte) (n int, err error) {
for len(mr.messages) > 0 {
if mr.separatorNeeded {
offset := copy(p, mboxSeparator)
n, err = mr.messages[0].Content.Reader.Read(p[offset:])
n += offset
mr.separatorNeeded = false
} else {
n, err = mr.messages[0].Content.Reader.Read(p)
}
if err == io.EOF {
mr.messages = mr.messages[1:]
mr.separatorNeeded = mr.mbox
}
if n > 0 || err != io.EOF {
if err == io.EOF && len(mr.messages) > 0 {
// Don't return EOF yet. More messages remain.
err = nil
} }
return n, err
} }
} }()
return 0, io.EOF return pr
} }