sup

A curses threads-with-tags style email client

sup.git

git clone https://supmua.dev/git/sup/
commit 1bf2c1c01aa885f49ef2e9886f8c1af9c5aaf309
parent 1b2dbdf073cc042075ffd377564a71e7089e825d
Author: Edward Z. Yang <ezyang@mit.edu>
Date:   Mon, 27 Aug 2012 13:31:12 -0400

Better backwards synchronization for killed messages.

Signed-off-by: Edward Z. Yang 

Diffstat:
M bin/sup-sync-back-maildir | 4 ++++
M lib/sup/index.rb | 26 ++++++++++++++++++++++++++
M lib/sup/maildir.rb | 2 +-
M lib/sup/poll.rb | 5 +++++
4 files changed, 36 insertions(+), 1 deletion(-)
diff --git a/bin/sup-sync-back-maildir b/bin/sup-sync-back-maildir
@@ -88,6 +88,10 @@ begin
             m.merge_labels_from_locations [:replied, :forwarded]
           end
 
+          if Redwood::Index.message_joining_killed? m
+            m.labels += [:killed]
+          end
+
           index.save_message m
         end
       end
diff --git a/lib/sup/index.rb b/lib/sup/index.rb
@@ -161,6 +161,32 @@ EOS
     matchset.matches_estimated
   end
 
+  ## check if a message is part of a killed thread
+  ## (warning: duplicates code below)
+  ## NOTE: We can be more efficient if we assume every
+  ## killed message that hasn't been initially added
+  ## to the indexi s this way
+  def message_joining_killed? m
+    return false unless doc = find_doc(m.id)
+    queue = doc.value(THREAD_VALUENO).split(',')
+    seen_threads = Set.new
+    seen_messages = Set.new [m.id]
+    while not queue.empty?
+      thread_id = queue.pop
+      next if seen_threads.member? thread_id
+      return true if thread_killed?(thread_id)
+      seen_threads << thread_id
+      docs = term_docids(mkterm(:thread, thread_id)).map { |x| @xapian.document x }
+      docs.each do |doc|
+        msgid = doc.value MSGID_VALUENO
+        next if seen_messages.member? msgid
+        seen_messages << msgid
+        queue.concat doc.value(THREAD_VALUENO).split(',')
+      end
+    end
+    false
+  end
+
   ## yield all messages in the thread containing 'm' by repeatedly
   ## querying the index. yields pairs of message ids and
   ## message-building lambdas, so that building an unwanted message
diff --git a/lib/sup/maildir.rb b/lib/sup/maildir.rb
@@ -214,7 +214,7 @@ private
       if labels.member? :forwarded then new_flags.add?( "P" ) else new_flags.delete?( "P" ) end 
       if labels.member? :replied then new_flags.add?( "R" ) else new_flags.delete?( "R" ) end 
       if not labels.member? :unread then new_flags.add?( "S" ) else new_flags.delete?( "S" ) end 
-      if labels.member? :deleted then new_flags.add?( "T" ) else new_flags.delete?( "T" ) end 
+      if labels.member? :deleted or labels.member? :killed then new_flags.add?( "T" ) else new_flags.delete?( "T" ) end
 
       ## Flags must be stored in ASCII order according to Maildir
       ## documentation
diff --git a/lib/sup/poll.rb b/lib/sup/poll.rb
@@ -188,6 +188,11 @@ EOS
           yield :add, m, old_m, args[:progress] if block_given?
           Index.sync_message m, true
 
+          if Index.message_joining_killed? m
+            m.labels += [:killed]
+            Index.sync_message m, true
+          end
+
           ## We need to add or unhide the message when it either did not exist
           ## before at all or when it was updated. We do *not* add/unhide when
           ## the same message was found at a different location