]> git.cworth.org Git - sup/blobdiff - bin/sup-sync
Sent label handling change
[sup] / bin / sup-sync
old mode 100644 (file)
new mode 100755 (executable)
index ab72ea0..9c342d2
@@ -5,8 +5,13 @@ require 'rubygems'
 require 'trollop'
 require "sup"
 
+PROGRESS_UPDATE_INTERVAL = 15 # seconds
+
 class Float
   def to_s; sprintf '%.2f', self; end
+   def to_time_s
+     infinite? ? "unknown" : super
+   end
 end
 
 class Numeric
@@ -97,7 +102,7 @@ restored_state =
     IO.foreach opts[:restore] do |l|
       l =~ /^(\S+) \((.*?)\)$/ or raise "Can't read dump line: #{l.inspect}"
       mid, labels = $1, $2
-      dump[mid] = labels.split(" ").map { |x| x.intern }
+      dump[mid] = labels.symbolistize
     end
     $stderr.puts "Read #{dump.size} entries from dump file."
     dump
@@ -119,7 +124,9 @@ begin
 
   unless target == :new
     if opts[:start_at]
-      sources.each { |s| s.seek_to! opts[:start_at] }
+      Trollop::die :start_at, "can only be used on one source" unless sources.size == 1
+      sources.first.seek_to! opts[:start_at]
+      sources.first.correct_offset! if sources.first.respond_to?(:correct_offset!)
     else
       sources.each { |s| s.reset! }
     end
@@ -130,37 +137,41 @@ begin
     num_added = num_updated = num_scanned = num_restored = 0
     last_info_time = start_time = Time.now
 
-    Redwood::PollManager.add_messages_from source do |m, offset, entry|
+    Redwood::PollManager.add_messages_from source, :force_overwrite => true do |m, offset, entry|
       num_scanned += 1
       seen[m.id] = true
 
+      if Time.now - last_info_time > PROGRESS_UPDATE_INTERVAL
+        last_info_time = Time.now
+        elapsed = last_info_time - start_time
+        start = opts[:start_at] || source.start_offset
+        pctdone = 100.0 * (source.cur_offset - start).to_f / (source.end_offset - start).to_f
+        remaining = (100.0 - pctdone) * (elapsed.to_f / pctdone)
+        $stderr.printf "## read %dm (about %.0f%%) @ %.1fm/s. %s elapsed, about %s remaining\n", num_scanned, pctdone, num_scanned / elapsed, elapsed.to_time_s, remaining.to_time_s
+      end
+
       ## skip if we're operating only on changed messages, the message
       ## is in the index, and it's unchanged from what the source is
       ## reporting.
       next if target == :changed && entry && entry[:source_id].to_i == source.id && entry[:source_info].to_i == offset
 
       ## get the state currently in the index
-      index_state =
-        if entry
-          entry[:label].split(/\s+/).map { |x| x.intern }
-        else
-          nil
-        end
+      index_state = entry[:label].symbolistize if entry
 
       ## skip if we're operating on restored messages, and this one
       ## ain't.
-      next if target == :restored && (!restored_state[m.id] || restored_state[m.id].sort_by { |s| s.to_s } == index_state.sort_by { |s| s.to_s })
+      next if target == :restored && (!restored_state[m.id] || (index_state && restored_state[m.id].sort_by { |s| s.to_s } == index_state.sort_by { |s| s.to_s }))
 
       ## m.labels is the default source labels. tweak these according
       ## to default source state modification flags.
       m.labels -= [:inbox] if opts[:archive]
       m.labels -= [:unread] if opts[:read]
-      m.labels += opts[:extra_labels].split(/\s*,\s*/).map { |x| x.intern } if opts[:extra_labels]
+      m.labels += opts[:extra_labels].strip.split(/\s*,\s*/).map { |x| x.intern } if opts[:extra_labels]
 
       ## assign message labels based on the operation we're performing
       case op
       when :asis
-        m.labels = index_state if index_state
+        m.labels = ((m.labels - [:unread, :inbox]) + index_state).uniq if index_state
       when :restore
         ## if the entry exists on disk
         if restored_state[m.id]
@@ -173,16 +184,16 @@ begin
         ## nothin! use default source labels
       end
 
-      if Time.now - last_info_time > 60
+      if Time.now - last_info_time > PROGRESS_UPDATE_INTERVAL
         last_info_time = Time.now
         elapsed = last_info_time - start_time
         pctdone = source.respond_to?(:pct_done) ? source.pct_done : 100.0 * (source.cur_offset.to_f - source.start_offset).to_f / (source.end_offset - source.start_offset).to_f
         remaining = (100.0 - pctdone) * (elapsed.to_f / pctdone)
-        $stderr.puts "## #{num_scanned} (#{pctdone}%) read; #{elapsed.to_time_s} elapsed; #{remaining.to_time_s} remaining"
+        $stderr.printf "## read %dm (about %.0f%%) @ %.1fm/s. %s elapsed, about %s remaining\n", num_scanned, pctdone, num_scanned / elapsed, elapsed.to_time_s, remaining.to_time_s
       end
 
       if index_state.nil?
-        puts "Adding message #{source}##{offset} with state {#{m.labels * ', '}}" if opts[:verbose]
+        puts "Adding message #{source}##{offset} from #{m.from} with state {#{m.labels * ', '}}" if opts[:verbose]
         num_added += 1
       else
         puts "Updating message #{source}##{offset}, source #{entry[:source_id]} => #{source.id}, offset #{entry[:source_info]} => #{offset}, state {#{index_state * ', '}} => {#{m.labels * ', '}}" if opts[:verbose]
@@ -202,9 +213,7 @@ begin
   ## API.
   ##
   ## TODO: move this to Index, i suppose.
-
-
-  if target == :all || target == :changed
+  if (target == :all || target == :changed) && !opts[:start_at]
     $stderr.puts "Deleting missing messages from the index..."
     num_del, num_scanned = 0, 0
     sources.each do |source|
@@ -224,6 +233,8 @@ begin
     $stderr.puts "Deleted #{num_del} / #{num_scanned} messages"
   end
 
+  index.save
+
   if opts[:optimize]
     $stderr.puts "Optimizing index..."
     optt = time { index.index.optimize unless opts[:dry_run] }
@@ -235,7 +246,6 @@ rescue Exception => e
   File.open("sup-exception-log.txt", "w") { |f| f.puts e.backtrace }
   raise
 ensure
-  index.save
   Redwood::finish
   index.unlock
 end