sup

A curses threads-with-tags style email client

sup.git

git clone https://supmua.dev/git/sup/
commit ec590ef28f7c98b8ba146dfb3a73b9e8fef01fa3
parent 4e5d3ece2fb6f63988a05792ed7047158bcc894a
Author: Gaute Hope <eg@gaute.vetsj.com>
Date:   Wed, 16 Oct 2013 13:18:22 +0200

Merge #162: Move sup-sync-back to sup-sync-back-mbox

Diffstat:
M History.txt | 2 ++
D bin/sup-sync-back | 181 -------------------------------------------------------------------------------
A bin/sup-sync-back-mbox | 181 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
M contrib/completion/_sup.zsh | 4 ++--
M lib/sup/mbox.rb | 2 +-
M lib/sup/source.rb | 2 +-
M sup.gemspec | 2 +-
7 files changed, 188 insertions(+), 186 deletions(-)
diff --git a/History.txt b/History.txt
@@ -34,6 +34,8 @@
 * Various encoding fixes and minor bug fixes
 * Tempfiles for attachments are persistent through the sup process to
   ensure that spawned processes have access to them.
+* sup-sync-back has been renamed to sup-sync-back-mbox to conform with
+  the other sync-back scripts.
 
 == 0.14.1 / 2013-08-31
 
diff --git a/bin/sup-sync-back b/bin/sup-sync-back
@@ -1,181 +0,0 @@
-#!/usr/bin/env ruby
-
-$:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
-
-require 'rubygems'
-require 'uri'
-require 'tempfile'
-require 'trollop'
-require "sup"
-
-fail "not working yet"
-
-## save a message 'm' to an open file pointer 'fp'
-def save m, fp
-  m.source.each_raw_message_line(m.source_info) { |l| fp.print l }
-end
-def die msg
-  $stderr.puts "Error: #{msg}"
-  exit(-1)
-end
-def has_any_from_source_with_label? index, source, label
-  query = { :source_id => source.id, :label => label, :limit => 1, :load_spam => true, :load_deleted => true, :load_killed => true }
-  index.num_results_for(query) != 0
-end
-
-opts = Trollop::options do
-  version "sup-sync-back (sup #{Redwood::VERSION})"
-  banner <<EOS
-Drop or move messages from Sup sources that are marked as deleted or
-spam in the Sup index.
-
-Currently only works with mbox sources.
-
-Usage:
-  sup-sync-back [options] <source>*
-
-where <source>* is zero or more source URIs. If no sources are given,
-sync back all usual sources.
-
-You almost certainly want to run sup-sync --changed after this command.
-Running this does not change the index.
-
-Options include:
-EOS
-  opt :drop_deleted, "Drop deleted messages.", :default => false, :short => "d"
-  opt :move_deleted, "Move deleted messages to a local mbox file.", :type => String, :short => :none
-  opt :drop_spam, "Drop spam messages.", :default => false, :short => "s"
-  opt :move_spam, "Move spam messages to a local mbox file.", :type => String, :short => :none
-
-  opt :with_dotlockfile, "Specific dotlockfile location (mbox files only).", :default => "/usr/bin/dotlockfile", :short => :none
-  opt :dont_use_dotlockfile, "Don't use dotlockfile to lock mbox files. Dangerous if other processes modify them concurrently.", :default => false, :short => :none
-
-  opt :verbose, "Print message ids as they're processed."
-  opt :dry_run, "Don't actually modify the index. Probably only useful with --verbose.", :short => "-n"
-  opt :version, "Show version information", :short => :none
-
-  conflicts :drop_deleted, :move_deleted
-  conflicts :drop_spam, :move_spam
-end
-
-unless opts[:drop_deleted] || opts[:move_deleted] || opts[:drop_spam] || opts[:move_spam]
-  puts <<EOS
-Nothing to do. Please specify at least one of --drop-deleted, --move-deleted,
---drop-spam, or --move-spam.
-EOS
-
-  exit
-end
-
-Redwood::start
-index = Redwood::Index.init
-index.lock_interactively or exit
-
-deleted_fp, spam_fp = nil
-unless opts[:dry_run]
-  deleted_fp = File.open(opts[:move_deleted], "a") if opts[:move_deleted]
-  spam_fp = File.open(opts[:move_spam], "a") if opts[:move_spam]
-end
-
-dotlockfile = opts[:with_dotlockfile] || "/usr/bin/dotlockfile"
-
-begin
-  index.load
-
-  sources = ARGV.map do |uri|
-    s = Redwood::SourceManager.source_for(uri) or die "unknown source: #{uri}. Did you add it with sup-add first?"
-    s.is_a?(Redwood::MBox) or die "#{uri} is not an mbox source."
-    s
-  end
-
-  if sources.empty?
-    sources = Redwood::SourceManager.usual_sources.select { |s| s.is_a? Redwood::MBox }
-  end
-
-  unless sources.all? { |s| s.file_path.nil? } || File.executable?(dotlockfile) || opts[:dont_use_dotlockfile]
-    die <<EOS
-can't execute dotlockfile binary: #{dotlockfile}. Specify --with-dotlockfile
-if it's in a nonstandard location, or, if you want to live dangerously, try
---dont-use-dotlockfile
-EOS
-  end
-
-  modified_sources = []
-  sources.each do |source|
-    $stderr.puts "Scanning #{source}..."
-
-    unless ((opts[:drop_deleted] || opts[:move_deleted]) && has_any_from_source_with_label?(index, source, :deleted)) || ((opts[:drop_spam] || opts[:move_spam]) && has_any_from_source_with_label?(index, source, :spam))
-      $stderr.puts "Nothing to do from this source; skipping"
-      next
-    end
-
-    source.reset!
-    num_dropped = num_moved = num_scanned = 0
-
-    out_fp = Tempfile.new "sup-sync-back-#{source.id}"
-    Redwood::PollManager.each_message_from source do |m|
-      num_scanned += 1
-
-      if(m_old = index.build_message(m.id))
-        labels = m_old.labels
-
-        if labels.member? :deleted
-          if opts[:drop_deleted]
-            puts "Dropping deleted message #{source}##{m.source_info}" if opts[:verbose]
-            num_dropped += 1
-          elsif opts[:move_deleted] && labels.member?(:deleted)
-            puts "Moving deleted message #{source}##{m.source_info}" if opts[:verbose]
-            save m, deleted_fp unless opts[:dry_run]
-            num_moved += 1
-          end
-
-        elsif labels.member? :spam
-          if opts[:drop_spam]
-            puts "Dropping spam message #{source}##{m.source_info}" if opts[:verbose]
-            num_dropped += 1
-          elsif opts[:move_spam] && labels.member?(:spam)
-            puts "Moving spam message #{source}##{m.source_info}" if opts[:verbose]
-            save m, spam_fp unless opts[:dry_run]
-            num_moved += 1
-          end
-        else
-          save m, out_fp unless opts[:dry_run]
-        end
-      else
-        save m, out_fp unless opts[:dry_run]
-      end
-    end
-    $stderr.puts "Scanned #{num_scanned}, dropped #{num_dropped}, moved #{num_moved} messages from #{source}."
-    modified_sources << source if num_dropped > 0 || num_moved > 0
-    out_fp.close unless opts[:dry_run]
-
-    unless opts[:dry_run] || (num_dropped == 0 && num_moved == 0)
-      deleted_fp.flush if deleted_fp
-      spam_fp.flush if spam_fp
-      unless opts[:dont_use_dotlockfile]
-        puts "Locking #{source.file_path}..."
-        system "#{opts[:dotlockfile]} -l #{source.file_path}"
-        puts "Writing #{source.file_path}..."
-        FileUtils.cp out_fp.path, source.file_path
-        puts "Unlocking #{source.file_path}..."
-        system "#{opts[:dotlockfile]} -u #{source.file_path}"
-      end
-    end
-  end
-
-  unless opts[:dry_run]
-    deleted_fp.close if deleted_fp
-    spam_fp.close if spam_fp
-  end
-
-  $stderr.puts "Done."
-  unless modified_sources.empty?
-    $stderr.puts "You should now run: sup-sync --changed #{modified_sources.join(' ')}"
-  end
-rescue Exception => e
-  File.open("sup-exception-log.txt", "w") { |f| f.puts e.backtrace }
-  raise
-ensure
-  Redwood::finish
-  index.unlock
-end
diff --git a/bin/sup-sync-back-mbox b/bin/sup-sync-back-mbox
@@ -0,0 +1,181 @@
+#!/usr/bin/env ruby
+
+$:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
+
+require 'rubygems'
+require 'uri'
+require 'tempfile'
+require 'trollop'
+require "sup"
+
+fail "not working yet"
+
+## save a message 'm' to an open file pointer 'fp'
+def save m, fp
+  m.source.each_raw_message_line(m.source_info) { |l| fp.print l }
+end
+def die msg
+  $stderr.puts "Error: #{msg}"
+  exit(-1)
+end
+def has_any_from_source_with_label? index, source, label
+  query = { :source_id => source.id, :label => label, :limit => 1, :load_spam => true, :load_deleted => true, :load_killed => true }
+  index.num_results_for(query) != 0
+end
+
+opts = Trollop::options do
+  version "sup-sync-back-mbox (sup #{Redwood::VERSION})"
+  banner <<EOS
+Drop or move messages from Sup sources that are marked as deleted or
+spam in the Sup index.
+
+Currently only works with mbox sources.
+
+Usage:
+  sup-sync-back-mbox [options] <source>*
+
+where <source>* is zero or more source URIs. If no sources are given,
+sync back all usual sources.
+
+You almost certainly want to run sup-sync --changed after this command.
+Running this does not change the index.
+
+Options include:
+EOS
+  opt :drop_deleted, "Drop deleted messages.", :default => false, :short => "d"
+  opt :move_deleted, "Move deleted messages to a local mbox file.", :type => String, :short => :none
+  opt :drop_spam, "Drop spam messages.", :default => false, :short => "s"
+  opt :move_spam, "Move spam messages to a local mbox file.", :type => String, :short => :none
+
+  opt :with_dotlockfile, "Specific dotlockfile location (mbox files only).", :default => "/usr/bin/dotlockfile", :short => :none
+  opt :dont_use_dotlockfile, "Don't use dotlockfile to lock mbox files. Dangerous if other processes modify them concurrently.", :default => false, :short => :none
+
+  opt :verbose, "Print message ids as they're processed."
+  opt :dry_run, "Don't actually modify the index. Probably only useful with --verbose.", :short => "-n"
+  opt :version, "Show version information", :short => :none
+
+  conflicts :drop_deleted, :move_deleted
+  conflicts :drop_spam, :move_spam
+end
+
+unless opts[:drop_deleted] || opts[:move_deleted] || opts[:drop_spam] || opts[:move_spam]
+  puts <<EOS
+Nothing to do. Please specify at least one of --drop-deleted, --move-deleted,
+--drop-spam, or --move-spam.
+EOS
+
+  exit
+end
+
+Redwood::start
+index = Redwood::Index.init
+index.lock_interactively or exit
+
+deleted_fp, spam_fp = nil
+unless opts[:dry_run]
+  deleted_fp = File.open(opts[:move_deleted], "a") if opts[:move_deleted]
+  spam_fp = File.open(opts[:move_spam], "a") if opts[:move_spam]
+end
+
+dotlockfile = opts[:with_dotlockfile] || "/usr/bin/dotlockfile"
+
+begin
+  index.load
+
+  sources = ARGV.map do |uri|
+    s = Redwood::SourceManager.source_for(uri) or die "unknown source: #{uri}. Did you add it with sup-add first?"
+    s.is_a?(Redwood::MBox) or die "#{uri} is not an mbox source."
+    s
+  end
+
+  if sources.empty?
+    sources = Redwood::SourceManager.usual_sources.select { |s| s.is_a? Redwood::MBox }
+  end
+
+  unless sources.all? { |s| s.file_path.nil? } || File.executable?(dotlockfile) || opts[:dont_use_dotlockfile]
+    die <<EOS
+can't execute dotlockfile binary: #{dotlockfile}. Specify --with-dotlockfile
+if it's in a nonstandard location, or, if you want to live dangerously, try
+--dont-use-dotlockfile
+EOS
+  end
+
+  modified_sources = []
+  sources.each do |source|
+    $stderr.puts "Scanning #{source}..."
+
+    unless ((opts[:drop_deleted] || opts[:move_deleted]) && has_any_from_source_with_label?(index, source, :deleted)) || ((opts[:drop_spam] || opts[:move_spam]) && has_any_from_source_with_label?(index, source, :spam))
+      $stderr.puts "Nothing to do from this source; skipping"
+      next
+    end
+
+    source.reset!
+    num_dropped = num_moved = num_scanned = 0
+
+    out_fp = Tempfile.new "sup-sync-back-mbox-#{source.id}"
+    Redwood::PollManager.each_message_from source do |m|
+      num_scanned += 1
+
+      if(m_old = index.build_message(m.id))
+        labels = m_old.labels
+
+        if labels.member? :deleted
+          if opts[:drop_deleted]
+            puts "Dropping deleted message #{source}##{m.source_info}" if opts[:verbose]
+            num_dropped += 1
+          elsif opts[:move_deleted] && labels.member?(:deleted)
+            puts "Moving deleted message #{source}##{m.source_info}" if opts[:verbose]
+            save m, deleted_fp unless opts[:dry_run]
+            num_moved += 1
+          end
+
+        elsif labels.member? :spam
+          if opts[:drop_spam]
+            puts "Dropping spam message #{source}##{m.source_info}" if opts[:verbose]
+            num_dropped += 1
+          elsif opts[:move_spam] && labels.member?(:spam)
+            puts "Moving spam message #{source}##{m.source_info}" if opts[:verbose]
+            save m, spam_fp unless opts[:dry_run]
+            num_moved += 1
+          end
+        else
+          save m, out_fp unless opts[:dry_run]
+        end
+      else
+        save m, out_fp unless opts[:dry_run]
+      end
+    end
+    $stderr.puts "Scanned #{num_scanned}, dropped #{num_dropped}, moved #{num_moved} messages from #{source}."
+    modified_sources << source if num_dropped > 0 || num_moved > 0
+    out_fp.close unless opts[:dry_run]
+
+    unless opts[:dry_run] || (num_dropped == 0 && num_moved == 0)
+      deleted_fp.flush if deleted_fp
+      spam_fp.flush if spam_fp
+      unless opts[:dont_use_dotlockfile]
+        puts "Locking #{source.file_path}..."
+        system "#{opts[:dotlockfile]} -l #{source.file_path}"
+        puts "Writing #{source.file_path}..."
+        FileUtils.cp out_fp.path, source.file_path
+        puts "Unlocking #{source.file_path}..."
+        system "#{opts[:dotlockfile]} -u #{source.file_path}"
+      end
+    end
+  end
+
+  unless opts[:dry_run]
+    deleted_fp.close if deleted_fp
+    spam_fp.close if spam_fp
+  end
+
+  $stderr.puts "Done."
+  unless modified_sources.empty?
+    $stderr.puts "You should now run: sup-sync --changed #{modified_sources.join(' ')}"
+  end
+rescue Exception => e
+  File.open("sup-exception-log.txt", "w") { |f| f.puts e.backtrace }
+  raise
+ensure
+  Redwood::finish
+  index.unlock
+end
diff --git a/contrib/completion/_sup.zsh b/contrib/completion/_sup.zsh
@@ -1,8 +1,8 @@
-#compdef sup sup-add sup-config sup-dump sup-sync sup-sync-back sup-tweak-labels sup-recover-sources
+#compdef sup sup-add sup-config sup-dump sup-sync sup-sync-back-mbox sup-tweak-labels sup-recover-sources
 # vim: set et sw=2 sts=2 ts=2 ft=zsh :
 
 # TODO: sources completion: maildir://some/dir, mbox://some/file, ...
-#       for sup-add, sup-sync, sup-sync-back, sup-tweak-labels
+#       for sup-add, sup-sync, sup-sync-back-mbox, sup-tweak-labels
 
 (( ${+functions[_sup_cmd]} )) ||
 _sup_cmd()
diff --git a/lib/sup/mbox.rb b/lib/sup/mbox.rb
@@ -120,7 +120,7 @@ class MBox < Source
   ## into memory with raw_message.
   ##
   ## i hoped never to have to move shit around on disk but
-  ## sup-sync-back has to do it.
+  ## sup-sync-back-mbox has to do it.
   def each_raw_message_line offset
     @mutex.synchronize do
       ensure_open
diff --git a/lib/sup/source.rb b/lib/sup/source.rb
@@ -68,7 +68,7 @@ class Source
     @poll_lock = Monitor.new
   end
 
-  ## overwrite me if you have a disk incarnation (currently used only for sup-sync-back)
+  ## overwrite me if you have a disk incarnation (currently used only for sup-sync-back-mbox)
   def file_path; nil end
 
   def to_s; @uri.to_s; end
diff --git a/sup.gemspec b/sup.gemspec
@@ -5,7 +5,7 @@ require 'sup/version'
 
 # Files
 SUP_EXECUTABLES = %w(sup sup-add sup-config sup-dump sup-import-dump
-  sup-recover-sources sup-sync sup-sync-back sup-tweak-labels
+  sup-recover-sources sup-sync sup-sync-back-mbox sup-tweak-labels
   sup-psych-ify-config-files)
 SUP_EXTRA_FILES = %w(CONTRIBUTORS README.md LICENSE History.txt ReleaseNotes)
 SUP_FILES =