Added "be-handle-mail --notify-since REVISION".
authorW. Trevor King <wking@drexel.edu>
Mon, 27 Jul 2009 13:01:04 +0000 (09:01 -0400)
committerW. Trevor King <wking@drexel.edu>
Mon, 27 Jul 2009 13:01:04 +0000 (09:01 -0400)
interfaces/email/interactive/be-handle-mail

index 5516c80e736e548802abbb07bd3dfba50c162636..90f5c28eaff618e5ef35c61d5bae64adea88f061 100755 (executable)
@@ -289,13 +289,14 @@ class Diff (libbe.diff.Diff):
         return comment.string()
 
 class Message (object):
-    def __init__(self, email_text):
-        self.text = email_text
-        p=email.Parser.Parser()
-        self.msg=p.parsestr(self.text)
-        if LOGFILE != None:
-            LOGFILE.write(u"handling %s\n" % self.author_addr())
-            LOGFILE.write(u"\n%s\n\n" % self.text)
+    def __init__(self, email_text=None, disable_parsing=False):
+        if disable_parsing == False:
+            self.text = email_text
+            p=email.Parser.Parser()
+            self.msg=p.parsestr(self.text)
+            if LOGFILE != None:
+                LOGFILE.write(u"handling %s\n" % self.author_addr())
+                LOGFILE.write(u"\n%s\n\n" % self.text)
     def author_tuple(self):
         """
         Extract and normalize the sender's email address.  Returns a
@@ -530,13 +531,14 @@ class Message (object):
             for message in self._response_messages:
                 response_body.attach(message)
         return send_pgp_mime.attach_root(self.response_header, response_body)
-    def subscriber_emails(self):
-        if AUTOCOMMIT != True: # no way to tell what's changed
-            raise NotificationFailed("Autocommit dissabled")
-        assert len(self._response_messages) > 0
-        if self.commit_command.ret != 0:
-            # commit failed.  Error already logged.
-            raise NotificationFailed("Commit failed")
+    def subscriber_emails(self, previous_revision=None):
+        if previous_revision == None:
+            if AUTOCOMMIT != True: # no way to tell what's changed
+                raise NotificationFailed("Autocommit dissabled")
+            assert len(self._response_messages) > 0
+            if self.commit_command.ret != 0:
+                # commit failed.  Error already logged.
+                raise NotificationFailed("Commit failed")
 
         # read only bugdir.
         bd = libbe.bugdir.BugDir(from_disk=True,
@@ -548,7 +550,7 @@ class Message (object):
         if len(subscribers) == 0:
             return [] 
 
-        before_bd, after_bd = self._get_before_and_after_bugdirs(bd)
+        before_bd, after_bd = self._get_before_and_after_bugdirs(bd, previous_revision)
         diff = Diff(before_bd, after_bd)
         diff_tree = diff.report_tree(diff_tree=DiffTree)
         bug_index = {}
@@ -558,7 +560,7 @@ class Message (object):
             bug_index[child.name] = ("modified", child)
         for child in diff_tree.child_by_path("/bugs/rem"):
             bug_index[child.name] = ("removed", child)
-        header = self._subscriber_header(bd)
+        header = self._subscriber_header(bd, previous_revision)
 
         emails = []
         for subscriber,subscriptions in subscribers.items():
@@ -586,13 +588,16 @@ class Message (object):
                     root.attach(part)
             emails.append(send_pgp_mime.attach_root(header, root))
             if LOGFILE != None:
-                LOGFILE.write("Notfying %s of changes\n" % subscriber)
+                LOGFILE.write("Preparing to notify %s of changes\n" % subscriber)
         return emails
-    def _get_before_and_after_bugdirs(self, bd):
-        commit_msg = self.commit_command.stdout
-        assert commit_msg.startswith("Committed "), commit_msg
-        after_revision = commit_msg[len("Committed "):]
-        before_revision = bd.rcs.revision_id(-2)
+    def _get_before_and_after_bugdirs(self, bd, previous_revision=None):
+        if previous_revision == None:
+            commit_msg = self.commit_command.stdout
+            assert commit_msg.startswith("Committed "), commit_msg
+            after_revision = commit_msg[len("Committed "):]
+            before_revision = bd.rcs.revision_id(-2)
+        else:
+            before_revision = previous_revision
         if before_revision == None:
             # this commit was the initial commit
             before_bd = libbe.bugdir.BugDir(from_disk=False,
@@ -602,10 +607,14 @@ class Message (object):
         #after_bd = bd.duplicate_bugdir(after_revision)
         after_bd = bd # assume no changes since commit a few cycles ago
         return (before_bd, after_bd)
-    def _subscriber_header(self, bd):
+    def _subscriber_header(self, bd, previous_revision=None):
         root_dir = os.path.basename(bd.root)
-        subject = "Changes to %s on %s by %s" \
-            % (root_dir, THIS_SERVER, self.author_addr())
+        if previous_revision == None:
+            subject = "Changes to %s on %s by %s" \
+                % (root_dir, THIS_SERVER, self.author_addr())
+        else:
+            subject = "Changes to %s on %s since revision %s" \
+                % (root_dir, THIS_SERVER, previous_revision)
         header = [u"From: %s" % THIS_ADDRESS,
                   u"To: %s" % u"DUMMY-AUTHOR",
                   u"Date: %s" % libbe.utility.time_to_str(time.time()),
@@ -685,6 +694,8 @@ def main():
     parser.add_option('-s', '--disable-subscribers', dest='subscribers',
                       default=True, action='store_false',
                       help='Disable subscriber notification emails.')
+    parser.add_option('--notify-since', dest='notify_since', metavar='REVISION',
+                      help='Notify subscribers of all changes since REVISION.  When this option is set, no input email parsing is done.')
     parser.add_option('--test', dest='test', action='store_true',
                       help='Run internal unit-tests and exit.')
 
@@ -700,6 +711,28 @@ def main():
     AUTOCOMMIT = options.autocommit
     generate_global_tags(options.tag_base)
 
+    if options.notify_since != None:
+        if options.subscribers == True:
+            libbe.encoding.set_IO_stream_encodings(ENCODING) # _after_ reading message
+            open_logfile(options.logfile)
+            if LOGFILE != None:
+                LOGFILE.write(u"Checking for subscribers to notify since revision %s\n"
+                              % options.notify_since)
+            try:
+                m = Message(disable_parsing=True)
+                emails = m.subscriber_emails(options.notify_since)
+            except NotificationFailed, e:
+                if LOGFILE != None:
+                    LOGFILE.write(unicode(e) + u"\n")
+            else:
+                for msg in emails:
+                    if options.output == True:
+                        print send_pgp_mime.flatten(msg, to_unicode=True)
+                    else:
+                        send_pgp_mime.mail(msg, send_pgp_mime.sendmail)
+            close_logfile()
+        sys.exit(0)
+
     msg_text = sys.stdin.read()
     libbe.encoding.set_IO_stream_encodings(ENCODING) # _after_ reading message
     open_logfile(options.logfile)
@@ -730,11 +763,13 @@ def main():
                                                               to_unicode=True))
         send_pgp_mime.mail(response, send_pgp_mime.sendmail)
     if options.subscribers == True:
-        LOGFILE.write(u"Checking for subscribers\n")
+        if LOGFILE != None:
+            LOGFILE.write(u"Checking for subscribers\n")
         try:
             emails = m.subscriber_emails()
         except NotificationFailed, e:
-            LOGFILE.write(unicode(e) + u"\n")
+            if LOGFILE != None:
+                LOGFILE.write(unicode(e) + u"\n")
         else:
             for msg in emails:
                 if options.output == True: