bin/sup-sync-back in sup-0.1 vs bin/sup-sync-back in sup-0.2
- old
+ new
@@ -6,100 +6,123 @@
require 'trollop'
require "sup"
## save a message 'm' to an open file pointer 'fp'
def save m, fp
- m.source.each_raw_full_message_line(m.source_info) { |l| fp.print l }
+ m.source.each_raw_message_line(m.source_info) { |l| fp.print l }
end
+def die msg
+ $stderr.puts "Error: #{msg}"
+ exit(-1)
+end
opts = Trollop::options do
version "sup-sync-back (sup #{Redwood::VERSION})"
banner <<EOS
-Partially synchronizes a message source with the Sup index by deleting
-or moving any messages from the source that are marked as deleted or
+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 probably want to run sup-sync --changed after this command.
+You almost certainly want to run sup-sync --changed after this command.
+Running this does not change the index.
Options include:
EOS
- opt :delete_deleted, "Delete deleted messages.", :default => false, :short => "d"
+ 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 :delete_spam, "Delete spam messages.", :default => false, :short => "s"
+ 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 :delete_deleted, :move_deleted
- conflicts :delete_spam, :move_spam
+ 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 "Nothing to do."
+ exit
+end
+
Redwood::start
index = Redwood::Index.new
index.lock_or_die
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 = index.source_for(uri) or Trollop::die "Unknown source: #{uri}. Did you add it with sup-add first?"
- s.is_a?(Redwood::MBox::Loader) or Trollop::die "#{uri} is not an mbox source."
+ s = index.source_for(uri) or die "unknown source: #{uri}. Did you add it with sup-add first?"
+ s.is_a?(Redwood::MBox::Loader) or die "#{uri} is not an mbox source."
s
end
if sources.empty?
sources = index.usual_sources.select { |s| s.is_a? Redwood::MBox::Loader }
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[:delete_deleted] || opts[:move_deleted]) && index.has_any_from_source_with_label?(source, :deleted)) || ((opts[:delete_spam] || opts[:move_spam]) && index.has_any_from_source_with_label?(source, :spam))
+ unless ((opts[:drop_deleted] || opts[:move_deleted]) && index.has_any_from_source_with_label?(source, :deleted)) || ((opts[:drop_spam] || opts[:move_spam]) && index.has_any_from_source_with_label?(source, :spam))
$stderr.puts "Nothing to do from this source; skipping"
next
end
source.reset!
- num_deleted = num_moved = num_scanned = 0
+ num_dropped = num_moved = num_scanned = 0
out_fp = Tempfile.new "sup-sync-back-#{source.id}"
Redwood::PollManager.add_messages_from source do |m, offset, entry|
num_scanned += 1
if entry
labels = entry[:label].split.map { |x| x.intern }.to_boolean_h
if labels.member? :deleted
- if opts[:delete_deleted]
+ if opts[:drop_deleted]
puts "Dropping deleted message #{source}##{offset}" if opts[:verbose]
- num_deleted += 1
+ num_dropped += 1
elsif opts[:move_deleted] && labels.member?(:deleted)
puts "Moving deleted message #{source}##{offset}" if opts[:verbose]
save m, deleted_fp unless opts[:dry_run]
num_moved += 1
end
elsif labels.member? :spam
- if opts[:delete_spam]
- puts "Deleting spam message #{source}##{offset}" if opts[:verbose]
- num_deleted += 1
+ if opts[:drop_spam]
+ puts "Dropping spam message #{source}##{offset}" if opts[:verbose]
+ num_dropped += 1
elsif opts[:move_spam] && labels.member?(:spam)
puts "Moving spam message #{source}##{offset}" if opts[:verbose]
save m, spam_fp unless opts[:dry_run]
num_moved += 1
end
@@ -110,19 +133,25 @@
save m, out_fp unless opts[:dry_run]
end
nil # don't actually add anything!
end
- $stderr.puts "Scanned #{num_scanned}, deleted #{num_deleted}, moved #{num_moved} messages from #{source}."
- modified_sources << source if num_deleted > 0 || num_moved > 0
+ $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_deleted == 0 && num_moved == 0)
+ unless opts[:dry_run] || (num_dropped == 0 && num_moved == 0)
deleted_fp.flush if deleted_fp
spam_fp.flush if spam_fp
- $stderr.puts "Moving #{out_fp.path} to #{source.file_path}"
- FileUtils.mv out_fp.path, source.file_path
+ 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
@@ -135,9 +164,8 @@
end
rescue Exception => e
File.open("sup-exception-log.txt", "w") { |f| f.puts e.backtrace }
raise
ensure
- index.save
Redwood::finish
index.unlock
end