mb2q: Support notmuch tag based export
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
diff --git a/mb2q b/mb2q
index ede83fa..3167109 100755
--- a/mb2q
+++ b/mb2q
@@ -3,13 +3,17 @@
# Copyright Thomas Gleixner <tglx@linutronix.de>
from email.utils import make_msgid, formatdate
+from email import message_from_binary_file
+from email.policy import EmailPolicy
from argparse import ArgumentParser
+from importlib import import_module
import subprocess
import mailbox
import email.policy
import email
import yaml
import time
+import copy
import sys
import os
import re
@@ -450,7 +454,7 @@
self.others = []
# Initial scan to gather information
- for k, msg in mbox.iteritems():
+ for k, msg in mbox.items():
if self.should_drop(msg):
continue
@@ -607,11 +611,65 @@
mbox.add(mailbox.mboxMessage(msg))
mbox.close()
+class nm_mbox(object):
+ def __init__(self, tag):
+ try:
+ notmuch = import_module('notmuch')
+ except ImportError:
+ sys.stderr.write('Notmuch module not found. Support disabled\n')
+ sys.exit(1)
+
+ self.db = notmuch.Database(mode=notmuch.Database.MODE.READ_WRITE)
+ self.msgs = []
+
+ try:
+ prefix, realtag = tag.split(':')
+ self.realtag = realtag.strip()
+ if not len(self.realtag):
+ raise Exception
+ except:
+ sys.stderr.write('Invalid notmuch tag: %s\n' %tag)
+ sys.exit(1)
+
+ policy = EmailPolicy(utf8=True)
+ try:
+ self.db.begin_atomic()
+ q = notmuch.Query(self.db, tag)
+ for nmmsg in q.search_messages():
+ mid = nmmsg.get_message_id()
+ try:
+ fpath = nmmsg.get_filename()
+ with open(fpath, 'rb') as f:
+ msg = message_from_binary_file(f, policy=policy)
+ except:
+ sys.stderr.write('Failed to read %s (%s)\n' %(fpath, mid))
+ raise
+
+ self.msgs.append((mid, msg))
+ nmmsg.remove_tag(realtag)
+
+ except notmuch.NotmuchError as ex:
+ self.db.end_atomic()
+ sys.stderr.write('%s\nCheck your tag expression\n' %repr(ex))
+ sys.exit(1)
+
+ except Exception as ex:
+ self.db.end_atomic()
+ sys.stderr.write('%s\n' %repr(ex))
+ sys.exit(1)
+
+ self.db.end_atomic()
+
+ def items(self):
+ return copy.copy(self.msgs)
+
if __name__ == '__main__':
parser = ArgumentParser(description='Mailbox 2 quilt converter')
parser.add_argument('inbox', metavar='inbox',
- help='Input mbox file or maildir directory')
+ help='''
+ Input mbox file or maildir directory or notmuch tag.
+ notmuch tag format is tag:$TAGNAME''')
parser.add_argument('-c', '--config', dest='config', default='~/.mb2q.yaml',
help='Config file. Default: ~/.mb2q.yaml')
parser.add_argument('-d', '--droplinks', dest='droplinks',
@@ -677,12 +735,16 @@
q = quilter(args)
- if os.path.isfile(args.inbox):
- patchsuffix = args.inbox
+ patchsuffix = args.inbox
+ if args.inbox.startswith('tag:'):
+ mbox = nm_mbox(args.inbox)
+ patchsuffix = 'notmuch_%s' %args.inbox.replace(':', '_')
+ elif os.path.isfile(args.inbox):
+ mbox = mailbox.mbox(args.inbox, create=False)
elif os.path.isdir(args.inbox):
mbox = mailbox.Maildir(args.inbox, create=False)
else:
- sys.stderr.write('Invalid input source %s\n' %args.inbox)
+ sys.stderr.write('Unknown input source %s\n' %args.inbox)
sys.exit(1)
try:
@@ -695,7 +757,7 @@
sys.exit(1)
if not len(q.patches):
- sys.stderr.write("No patches found in mbox\n")
+ sys.stderr.write("No patches found in input\n")
sys.exit(1)
if args.mboxout:
@@ -705,7 +767,7 @@
if args.patchesdir:
pdir = os.path.expanduser(args.patchesdir)
else:
- pdir = 'patches-%s' % os.path.basename(args.inbox)
+ pdir = 'patches-%s' % os.path.basename(patchsuffix)
if not os.path.isdir(pdir):
os.makedirs(pdir)
q.write_series(pdir)