Switched to maildir
authorDmitriy Morozov <morozov@cs.duke.edu>
Wed, 16 Apr 2008 17:21:40 -0400
changeset 21 5b3579dc7abf
parent 20 1630cf85c7f7
child 22 88f126b2dd08
Switched to maildir
artemis.py
convert-mbox-maildir.py
--- a/artemis.py	Fri Jan 11 09:01:17 2008 -0500
+++ b/artemis.py	Wed Apr 16 17:21:40 2008 -0400
@@ -43,18 +43,19 @@
     properties += _get_properties(opts['property'])
 
     for issue in issues:
-        mbox = mailbox.mbox(issue)
+        mbox = mailbox.Maildir(issue, factory=mailbox.MaildirMessage)
+        root = _find_root_key(mbox)
         property_match = True
         for property,value in properties:
-            property_match = property_match and (mbox[0][property] == value)
-        if not show_all and (not properties or not property_match) and (properties or mbox[0]['State'].upper() == state['fixed'].upper()): continue
+            property_match = property_match and (mbox[root][property] == value)
+        if not show_all and (not properties or not property_match) and (properties or mbox[root]['State'].upper() == state['fixed'].upper()): continue
 
 
-        if match_date and not date_match(util.parsedate(mbox[0]['date'])[0]): continue
+        if match_date and not date_match(util.parsedate(mbox[root]['date'])[0]): continue
         ui.write("%s (%3d) [%s]: %s\n" % (issue[len(issues_path)+1:], # +1 for trailing /
                                           len(mbox)-1,                # number of replies (-1 for self)
-                                          mbox[0]['State'],
-                                          mbox[0]['Subject']))
+                                          mbox[root]['State'],
+                                          mbox[root]['Subject']))
 
 
 def iadd(ui, repo, id = None, comment = 0):
@@ -89,8 +90,8 @@
         return
 
     # Create the message
-    msg = mailbox.mboxMessage(issue)
-    msg.set_from('artemis', True)
+    msg = mailbox.MaildirMessage(issue)
+    #msg.set_from('artemis', True)
 
     # Pick random filename
     if not id:
@@ -101,21 +102,24 @@
     # else: issue_fn already set
 
     # Add message to the mailbox
-    mbox = mailbox.mbox(issue_fn)
-    if id and comment not in mbox:
+    mbox = mailbox.Maildir(issue_fn)
+    keys = _order_keys_date(mbox)
+    mbox.lock()
+    if id and comment >= len(mbox):
         ui.warn('No such comment number in mailbox, commenting on the issue itself\n')
+
     if not id:
         msg.add_header('Message-Id', "<%s-0-artemis@%s>" % (issue_id, socket.gethostname()))
     else:
+        root = keys[0]
         msg.add_header('Message-Id', "<%s-%s-artemis@%s>" % (issue_id, _random_id(), socket.gethostname()))
-        msg.add_header('References', mbox[(comment < len(mbox) and comment) or 0]['Message-Id'])
-        msg.add_header('In-Reply-To', mbox[(comment < len(mbox) and comment) or 0]['Message-Id'])
-    mbox.add(msg)
+        msg.add_header('References', mbox[(comment < len(mbox) and keys[comment]) or root]['Message-Id'])
+        msg.add_header('In-Reply-To', mbox[(comment < len(mbox) and keys[comment]) or root]['Message-Id'])
+    repo.add([issue_fn[(len(repo.root)+1):] + '/new/'  + mbox.add(msg)])   # +1 for the trailing /
     mbox.close()
 
     # If adding issue, add the new mailbox to the repository
     if not id:
-        repo.add([issue_fn[(len(repo.root)+1):]])            # +1 for the trailing /
         ui.status('Added new issue %s\n' % issue_id)
 
 
@@ -125,13 +129,16 @@
     comment = int(comment)
     issue, id = _find_issue(ui, repo, id)
     if not issue: return
-    mbox = mailbox.mbox(issue)
+    mbox = mailbox.Maildir(issue, factory=mailbox.MaildirMessage)
 
     if opts['all']:
         ui.write('='*70 + '\n')
-        for i in xrange(len(mbox)):
-            _write_message(ui, mbox[i], i)
+        i = 0
+        keys = _order_keys_date(mbox) 
+        for k in keys:
+            _write_message(ui, mbox[k], i)
             ui.write('-'*70 + '\n')
+            i += 1
         return
 
     _show_mbox(ui, mbox, comment)
@@ -146,8 +153,9 @@
     properties = _get_properties(opts['property'])
 
     # Read the issue
-    mbox = mailbox.mbox(issue)
-    msg = mbox[0]
+    mbox = mailbox.Maildir(issue, factory=mailbox.MaildirMessage)
+    root = _find_root_key(mbox)
+    msg = mbox[root]
 
     # Fix the properties
     properties_text = ''
@@ -157,7 +165,8 @@
         else:
             msg.add_header(property, value)
         properties_text += '%s=%s\n' % (property, value)
-    mbox[0] = msg
+    mbox.lock()
+    mbox[root] = msg
 
     # Write down a comment about updated properties
     if properties and not opts['no_property_comment']:
@@ -170,9 +179,9 @@
         msg.add_header('Message-Id', "<%s-%s-artemis@%s>" % (id, _random_id(), socket.gethostname()))
         msg.add_header('References', mbox[0]['Message-Id'])
         msg.add_header('In-Reply-To', mbox[0]['Message-Id'])
-        msg.set_from('artemis', True)
-        mbox.add(msg)
-    mbox.flush()
+        #msg.set_from('artemis', True)
+        repo.add([issue_fn[(len(repo.root)+1):] + '/new/'  + mbox.add(msg)])   # +1 for the trailing /
+    mbox.close()
 
     # Show updated message
     _show_mbox(ui, mbox, 0)
@@ -212,11 +221,13 @@
     if comment >= len(mbox):
         comment = 0
         ui.warn('Comment out of range, showing the issue itself\n')
-    msg = mbox[comment]
+    keys = _order_keys_date(mbox)
+    root = keys[0]
+    msg = mbox[keys[comment]]
     ui.write('='*70 + '\n')
     if comment:
-        ui.write('Subject: %s\n' % mbox[0]['Subject'])
-        ui.write('State: %s\n' % mbox[0]['State'])
+        ui.write('Subject: %s\n' % mbox[root]['Subject'])
+        ui.write('State: %s\n' % mbox[root]['State'])
         ui.write('-'*70 + '\n')
     _write_message(ui, msg, comment)
     ui.write('-'*70 + '\n')
@@ -224,10 +235,12 @@
     # Read the mailbox into the messages and children dictionaries
     messages = {}
     children = {}
-    for i in xrange(len(mbox)):
-        m = mbox[i]
+    i = 0
+    for k in keys:
+        m = mbox[k]
         messages[m['Message-Id']] = (i,m)
         children.setdefault(m['In-Reply-To'], []).append(m['Message-Id'])
+        i += 1
     children[None] = []                # Safeguard against infinte loop on empty Message-Id
 
     # Iterate over children
@@ -242,6 +255,17 @@
         ui.write('  '*offset + ('%d: ' % index) + msg['Subject'] + '\n')
     ui.write('-'*70 + '\n')
 
+def _find_root_key(maildir):
+    for k,m in maildir.iteritems():
+        if 'in-reply-to' not in m:
+            return k
+
+def _order_keys_date(mbox):
+    keys = mbox.keys()
+    root = _find_root_key(mbox)
+    keys.sort(lambda k1,k2: -(k1 == root) or cmp(util.parsedate(mbox[k1]['date']), util.parsedate(mbox[k2]['date'])))
+    return keys
+
 def _pretty_list(lst):
     s = ''
     for i in lst:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/convert-mbox-maildir.py	Wed Apr 16 17:21:40 2008 -0400
@@ -0,0 +1,18 @@
+import mailbox, glob, os.path, os
+import artemis
+from mercurial import ui, hg
+
+repo = hg.repository(ui.ui())
+
+issue_filenames = glob.glob(os.path.join(artemis.issues_dir, '*'))
+for fn in issue_filenames:
+    mb = mailbox.mbox(fn)
+    messages = [m for m in mb]
+    mb.close()
+    os.unlink(fn)
+    repo.remove([fn])
+    md = mailbox.Maildir(fn)
+    md.lock()
+    keys = [md.add(m) for m in messages]
+    md.close()
+    for k in keys: repo.add([fn + '/new/' + k])