sup

A curses threads-with-tags style email client

sup.git

git clone https://supmua.dev/git/sup/

bin/sup-import-dump (2984B) - raw

      1 #!/usr/bin/env ruby
      2 
      3 $:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
      4 
      5 require 'uri'
      6 require 'optimist'
      7 require "sup"
      8 
      9 PROGRESS_UPDATE_INTERVAL = 15 # seconds
     10 
     11 class AbortExecution < SystemExit
     12 end
     13 
     14 opts = Optimist::options do
     15   version "sup-import-dump (sup #{Redwood::VERSION})"
     16   banner <<EOS
     17 Imports message state previously exported by sup-dump into the index.
     18 sup-import-dump operates on the index only, so the messages must have already
     19 been added using sup-sync. If you need to recreate the index, see sup-sync
     20 --restore <filename> instead.
     21 
     22 Messages not mentioned in the dump file will not be modified.
     23 
     24 Usage:
     25   sup-import-dump [options] <dump file>
     26 
     27 Options:
     28 EOS
     29   opt :verbose, "Print message ids as they're processed."
     30   opt :ignore_missing, "Silently skip over messages that are not in the index."
     31   opt :warn_missing, "Warn about messages that are not in the index, but continue."
     32   opt :abort_missing, "Abort on encountering messages that are not in the index. (default)"
     33   opt :atomic, "Use transaction to apply all changes atomically."
     34   opt :dry_run, "Don't actually modify the index. Probably only useful with --verbose.", :short => "-n"
     35   opt :version, "Show version information", :short => :none
     36 
     37   conflicts :ignore_missing, :warn_missing, :abort_missing
     38 end
     39 Optimist::die "No dump file given" if ARGV.empty?
     40 Optimist::die "Extra arguments given" if ARGV.length > 1
     41 dump_name = ARGV.shift
     42 missing_action = [:ignore_missing, :warn_missing, :abort_missing].find { |x| opts[x] } || :abort_missing
     43 
     44 Redwood::start
     45 index = Redwood::Index.init
     46 
     47 index.lock_interactively or exit
     48 begin
     49   num_read = 0
     50   num_changed = 0
     51   index.load
     52   index.begin_transaction if opts[:atomic]
     53 
     54   IO.foreach dump_name do |l|
     55     l =~ /^(\S+) \((.*?)\)$/ or raise "Can't read dump line: #{l.inspect}"
     56     mid, labels = $1, $2
     57     num_read += 1
     58 
     59     unless index.contains_id? mid
     60       if missing_action == :abort_missing
     61         $stderr.puts "Message #{mid} not found in index, aborting."
     62         raise AbortExecution, 10
     63       elsif missing_action == :warn_missing
     64         $stderr.puts "Message #{mid} not found in index, skipping."
     65       end
     66 
     67       next
     68     end
     69 
     70     m = index.build_message mid
     71     new_labels = labels.to_set_of_symbols
     72 
     73     if m.labels == new_labels
     74       puts "#{mid} unchanged" if opts[:verbose]
     75       next
     76     end
     77 
     78     puts "Changing flags for #{mid} from '#{m.labels.to_a * ' '}' to '#{new_labels.to_a * ' '}'" if opts[:verbose]
     79     num_changed += 1
     80 
     81     next if opts[:dry_run]
     82 
     83     m.labels = new_labels
     84     index.update_message_state [m, false]
     85   end
     86 
     87   index.commit_transaction if opts[:atomic]
     88   puts "Updated #{num_changed} of #{num_read} messages."
     89 rescue AbortExecution
     90   index.cancel_transaction if opts[:atomic]
     91   raise
     92 rescue Exception => e
     93   index.cancel_transaction if opts[:atomic]
     94   File.open("sup-exception-log.txt", "w") { |f| f.puts e.backtrace }
     95   raise
     96 ensure
     97   index.save_index unless opts[:atomic]
     98   Redwood::finish
     99   index.unlock
    100 end