sup

A curses threads-with-tags style email client

sup.git

git clone https://supmua.dev/git/sup/
commit 336fd01936b3c3297e575c05add1e7a7991bef9d
parent 856c0ebb8845f0658e056c889390f2c7086b35e2
Author: Rich Lane <rlane@club.cc.cmu.edu>
Date:   Tue, 30 Mar 2010 23:25:29 -0700

turn each_message_from into poll_from

Diffstat:
M bin/sup-sync | 30 ++++++++++--------------------
M lib/sup/maildir.rb | 2 +-
M lib/sup/mbox.rb | 2 +-
M lib/sup/poll.rb | 50 ++++++++++++++++++--------------------------------
4 files changed, 30 insertions(+), 54 deletions(-)
diff --git a/bin/sup-sync b/bin/sup-sync
@@ -114,15 +114,13 @@ begin
     num_added = num_updated = num_scanned = num_restored = 0
     last_info_time = start_time = Time.now
 
-    Redwood::PollManager.each_message_from source do |action,m|
+    Redwood::PollManager.poll_from source do |action,m,old_m|
       if action == :delete
         puts "Deleting #{m.id}"
-        next
-      end
+      else
 
       num_scanned += 1
       seen[m.id] = true
-      old_m = index.build_message m.id
 
       ## tweak source labels according to commandline arguments if necessary
       m.labels.delete :inbox if opts[:archive]
@@ -130,11 +128,12 @@ begin
       m.labels += opts[:extra_labels].to_set_of_symbols(",")
 
       ## decide what to do based on message labels and the operation we're performing
-      dothis, new_labels = case
+      dothis = case
       when (op == :restore) && restored_state[m.id]
         if old_m && (old_m.labels != restored_state[m.id])
           num_restored += 1
-          [:update_message_state, restored_state[m.id]]
+          m.labels = restored_state[m.id]
+          :update_message_state
         elsif old_m.nil?
           num_restored += 1
           m.labels = restored_state[m.id]
@@ -144,40 +143,28 @@ begin
         end
       when op == :discard
         if old_m && (old_m.labels != m.labels)
-          [:update_message_state, m.labels]
+          :update_message_state
         else
           # labels are the same; don't do anything
         end
       else
-        ## duplicate behavior of poll mode: if index_state is non-nil, this is a newer
-        ## version of an older message, so merge in any new labels except :unread and
-        ## :inbox.
-        ##
-        ## TODO: refactor such that this isn't duplicated
         if old_m
-          m.labels = old_m.labels + (m.labels - [:unread, :inbox])
           :update_message
         else
           :add_message
         end
       end
 
-      m.locations = old_m.locations + m.locations if old_m
-
       ## now, actually do the operation
       case dothis
       when :add_message
         puts "Adding new message #{source}##{m.source_info} with labels #{m.labels}" if opts[:verbose]
-        index.add_message m unless opts[:dry_run]
         num_added += 1
       when :update_message
         puts "Updating message #{source}##{m.source_info}; labels #{old_m.labels} => #{m.labels}; offset #{old_m.source_info} => #{m.source_info}" if opts[:verbose]
-        index.update_message m unless opts[:dry_run]
         num_updated += 1
       when :update_message_state
-        puts "Changing flags for #{source}##{m.source_info} from #{m.labels} to #{new_labels}" if opts[:verbose]
-        m.labels = new_labels
-        index.update_message_state m unless opts[:dry_run]
+        puts "Changing flags for #{source}##{m.source_info} from #{old_m.labels} to #{m.labels}" if opts[:verbose]
         num_updated += 1
       end
 
@@ -188,6 +175,9 @@ begin
         remaining = (100.0 - pctdone) * (elapsed.to_f / pctdone)
         printf "## read %dm (~%.0f%%) @ %.1fm/s. %s elapsed, ~%s remaining\n", num_scanned, pctdone, num_scanned / elapsed, elapsed.to_time_s, remaining.to_time_s
       end
+
+      end
+      next if opts[:dry_run]
     end
 
     puts "Scanned #{num_scanned}, added #{num_added}, updated #{num_updated} messages from #{source}."
diff --git a/lib/sup/maildir.rb b/lib/sup/maildir.rb
@@ -103,7 +103,7 @@ class Maildir < Source
       added.each do |id|
         yield :add,
           :info => File.join(d,id),
-          :labels => @labels + maildir_labels(id),
+          :labels => @labels + maildir_labels(id) + [:inbox],
           :progress => 0.0
       end
 
diff --git a/lib/sup/mbox.rb b/lib/sup/mbox.rb
@@ -127,7 +127,7 @@ class MBox < Source
     while offset and offset < end_offset
       yield :add,
         :info => offset,
-        :labels => (labels + [:unread]),
+        :labels => (labels + [:inbox, :unread]),
         :progress => 0.0
       offset = next_offset offset
     end
diff --git a/lib/sup/poll.rb b/lib/sup/poll.rb
@@ -112,29 +112,18 @@ EOS
 
         num = 0
         numi = 0
-        each_message_from source do |action,m|
+        poll_from source do |action,m,old_m|
           if action == :delete
             yield "Deleting #{m.id}"
-            next
-          end
-
-          old_m = Index.build_message m.id
+          else
           if old_m
             if not old_m.locations.member? [source, m.source_info]
-              ## here we merge labels between new and old versions, but we don't let the new
-              ## message add :unread or :inbox labels. (they can exist in the old version,
-              ## just not be added.)
-              new_labels = old_m.labels + (m.labels - [:unread, :inbox])
-              yield "Message at #{m.source_info} is an updated of an old message. Updating labels from #{m.labels.to_a * ','} => #{new_labels.to_a * ','}"
-              m.labels = new_labels
-              m.locations = old_m.locations + m.locations
-              Index.update_message m
+              yield "Message at #{m.source_info} is an updated of an old message. Updating labels from #{old_m.labels.to_a * ','} => #{m.labels.to_a * ','}"
             else
               yield "Skipping already-imported message at #{m.source_info}"
             end
           else
             yield "Found new message at #{m.source_info} with labels #{m.labels.to_a * ','}"
-            add_new_message m
             loaded_labels.merge m.labels
             num += 1
             from_and_subj << [m.from && m.from.longname, m.subj]
@@ -143,7 +132,7 @@ EOS
               numi += 1
             end
           end
-          m
+          end
         end
         yield "Found #{num} messages, #{numi} to inbox." unless num == 0
         total_num += num
@@ -158,11 +147,10 @@ EOS
     [total_num, total_numi, from_and_subj, from_and_subj_inbox, loaded_labels]
   end
 
-  ## like Source#each, but yields successive Message objects, which have their
-  ## labels and offsets set correctly.
-  ##
-  ## this is the primary mechanism for iterating over messages from a source.
-  def each_message_from source, opts={}
+  ## like Source#poll, but yields successive Message objects, which have their
+  ## labels and locations set correctly. The Messages are saved to or removed
+  ## from the index after being yielded.
+  def poll_from source, opts={}
     begin
       return if source.has_errors?
 
@@ -175,15 +163,23 @@ EOS
         case sym
         when :add
           m = Message.build_from_source source, args[:info]
+          old_m = Index.build_message m.id
           m.labels += args[:labels]
           m.labels.delete :unread if source.read?
           m.labels.delete :unread if m.source_marked_read? # preserve read status if possible
           m.labels.each { |l| LabelManager << l }
+          m.labels = old_m.labels + (m.labels - [:unread, :inbox]) if old_m
+          m.locations = old_m.locations + m.locations if old_m
           HookManager.run "before-add-message", :message => m
-          yield :add, m
+          yield :add, m, old_m if block_given?
+          Index.sync_message m, true
+          UpdateManager.relay self, :added, m
         when :delete
           Index.each_message :location => [source.id, args[:info]] do |m|
-            yield :delete, m
+            m.locations.delete [source,args[:info]]
+            yield :delete, m, [source,args[:info]] if block_given?
+            Index.sync_message m, false
+            UpdateManager.relay self, :deleted, m
           end
         end
       end
@@ -202,16 +198,6 @@ EOS
     end
   end
 
-  ## TODO: see if we can do this within PollMode rather than by calling this
-  ## method.
-  ##
-  ## a wrapper around Index.add_message that calls the proper hooks,
-  ## does the gui callback stuff, etc.
-  def add_new_message m
-    Index.add_message m
-    UpdateManager.relay self, :added, m
-  end
-
   def handle_idle_update sender, idle_since; @should_clear_running_totals = false; end
   def handle_unidle_update sender, idle_since; @should_clear_running_totals = true; clear_running_totals; end
   def clear_running_totals; @running_totals = {:num => 0, :numi => 0, :loaded_labels => Set.new}; end