sup

A curses threads-with-tags style email client

sup.git

git clone https://supmua.dev/git/sup/
commit ca10ef47501b52a37e28ad3a3ecf10b6a00dea35
parent 3abdab0acff1b6b9c4567e1f3f8e306ac28b0dbd
Author: Rich Lane <rlane@club.cc.cmu.edu>
Date:   Tue, 23 Mar 2010 23:26:56 -0700

skip seen mbox messages using the index

Diffstat:
M lib/sup/mbox.rb | 57 +++++++++++++++++++++------------------------------------
1 file changed, 21 insertions(+), 36 deletions(-)
diff --git a/lib/sup/mbox.rb b/lib/sup/mbox.rb
@@ -122,47 +122,32 @@ class MBox < Source
   end
 
   def each
-    offset = 0
+    offset = first_new_message
     end_offset = File.size @f
-    while offset < end_offset
-      returned_offset = nil
-      next_offset = offset
-
-      begin
-        @mutex.synchronize do
-          @f.seek offset
-
-          ## offset could be at one of two places here:
-
-          ## 1. before a \n and a mbox separator, if it was previously at
-          ##    EOF and a new message was added; or,
-          ## 2. at the beginning of an mbox separator (in all other
-          ##    cases).
-
-          l = @f.gets or break
-          if l =~ /^\s*$/ # case 1
-            returned_offset = @f.tell
-            @f.gets # now we're at a BREAK_RE, so skip past it
-          else # case 2
-            returned_offset = offset
-            ## we've already skipped past the BREAK_RE, so just go
-          end
-
-          while(line = @f.gets)
-            break if MBox::is_break_line? line
-            next_offset = @f.tell
-          end
-        end
-      rescue SystemCallError, IOError => e
-        raise FatalSourceError, "Error reading #{@f.path}: #{e.message}"
-      end
+    while offset and offset < end_offset
+      yield offset, (labels + [:unread])
+      offset = next_offset offset
+    end
+  end
 
-      offset = next_offset
-      yield returned_offset, (labels + [:unread])
+  def next_offset offset
+    @mutex.synchronize do
+      @f.seek offset
+      nil while line = @f.gets and not MBox::is_break_line? line
+      @f.tell
     end
   end
 
-  def next
+  ## TODO binary search
+  def first_new_message
+    offset = 0
+    end_offset = File.size @f
+    while offset < end_offset
+      offset = next_offset offset
+      new = Index.num_results_for(:location => [@id, offset]) == 0
+      return offset if new
+    end
+    return nil
   end
 
   def self.is_break_line? l