Redwood::start
Index.load
- if(s = Index.source_for DraftManager.source_name)
+ if(s = Redwood::SourceManager.source_for DraftManager.source_name)
DraftManager.source = s
else
Redwood::log "no draft source, auto-adding..."
- Index.add_source DraftManager.new_source
+ Redwood::SourceManager.add_source DraftManager.new_source
end
- if(s = Index.source_for SentManager.source_uri)
+ if(s = Redwood::SourceManager.source_for SentManager.source_uri)
SentManager.source = s
else
- Index.add_source SentManager.default_source
+ Redwood::SourceManager.add_source SentManager.default_source
end
HookManager.run "startup"
bm.draw_screen
- Index.usual_sources.each do |s|
+ Redwood::SourceManager.usual_sources.each do |s|
next unless s.respond_to? :connect
reporting_thread("call #connect on #{s}") do
begin
index.lock_or_die
begin
- index.load_sources
+ Redwood::SourceManager.load_sources
ARGV.each do |uri|
labels = $opts[:labels] ? $opts[:labels].split(/\s*,\s*/).uniq : []
- if !$opts[:force_new] && index.source_for(uri)
+ if !$opts[:force_new] && Redwood::SourceManager.source_for(uri)
say "Already know about #{uri}; skipping."
next
end
when "mbox+ssh"
say "For SSH connections, if you will use public key authentication, you may leave the username and password blank."
say ""
- username, password = get_login_info uri, index.sources
+ username, password = get_login_info uri, Redwood::SourceManager.sources
Redwood::MBox::SSHLoader.new uri, username, password, nil, !$opts[:unusual], $opts[:archive], nil, labels
when "imap", "imaps"
- username, password = get_login_info uri, index.sources
+ username, password = get_login_info uri, Redwood::SourceManager.sources
Redwood::IMAP.new uri, username, password, nil, !$opts[:unusual], $opts[:archive], nil, labels
when "maildir"
Redwood::Maildir.new uri, nil, !$opts[:unusual], $opts[:archive], nil, labels
Trollop::die "Unknown source type #{parsed_uri.scheme.inspect}"
end
say "Adding #{source}..."
- index.add_source source
+ Redwood::SourceManager.add_source source
end
ensure
index.save
$terminal.wrap_at = :auto
Redwood::start
index = Redwood::Index.new
-index.load_sources
+Redwood::SourceManager.load_sources
say <<EOS
Howdy neighbor! This here's sup-config, ready to help you jack in to
done = false
until done
say "\nNow, we'll tell Sup where to find all your email."
- index.load_sources
+ Redwood::SourceManager.load_sources
say "Current sources:"
- if index.sources.empty?
+ if Redwood::SourceManager.sources.empty?
say " No sources!"
else
- index.sources.each { |s| puts "* #{s}" }
+ Redwood::SourceManager.sources.each { |s| puts "* #{s}" }
end
say "\n"
say "\nSup needs to know where to store your sent messages."
say "Only sources capable of storing mail will be listed.\n\n"
-index.load_sources
-if index.sources.empty?
+Redwood::SourceManager.load_sources
+if Redwood::SourceManager.sources.empty?
say "\nUsing the default sup://sent, since you haven't configured other sources yet."
$config[:sent_source] = 'sup://sent'
else
choose do |menu|
menu.prompt = "Store my sent mail in? "
- valid_sents = index.sources.each do |s|
+ valid_sents = Redwood::SourceManager.sources.each do |s|
have_sup_sent = true if s.to_s.eql?('sup://sent')
menu.choice(s.to_s) { $config[:sent_source] = s.to_s } if s.respond_to? :store_message
end.parse(ARGV)
require "sup"
+Redwood::start
puts "loading index..."
index = Redwood::Index.new
index.load
puts "loaded index of #{index.size} messages"
ARGV.each do |fn|
- next if index.source_for fn
+ next if Redwood::SourceManager.source_for fn
## TODO: merge this code with the same snippet in import
source =
source.each do |offset, labels|
m = Redwood::Message.new :source => source, :source_info => offset
m.load_from_source!
- source_id = index.source_for_id m.id
+ source_id = Redwood::SourceManager.source_for_id m.id
next unless source_id
source_ids[source_id] += 1
count += 1
id = source_ids.keys.first.to_i
puts "assigned #{source} to #{source_ids.keys.first}"
source.id = id
- index.add_source source
+ Redwood::SourceManager.add_source source
else
puts ">> unable to determine #{source}: #{source_ids.inspect}"
end
index.load
sources = ARGV.map do |uri|
- index.source_for uri or Trollop::die "Unknown source: #{uri}. Did you add it with sup-add first?"
+ Redwood::SourceManager.source_for uri or Trollop::die "Unknown source: #{uri}. Did you add it with sup-add first?"
end
- sources = index.usual_sources if sources.empty?
- sources = index.sources if opts[:all_sources]
+ sources = Redwood::SourceManager.usual_sources if sources.empty?
+ sources = Redwood::SourceManager.sources if opts[:all_sources]
unless target == :new
if opts[:start_at]
index.load
sources = ARGV.map do |uri|
- s = index.source_for(uri) or die "unknown source: #{uri}. Did you add it with sup-add first?"
+ s = Redwood::SourceManager.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 }
+ sources = Redwood::SourceManager.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]
source_ids =
if opts[:all_sources]
- index.sources
+ Redwood::SourceManager.sources
else
ARGV.map do |uri|
- index.source_for uri or Trollop::die "Unknown source: #{uri}. Did you add it with sup-add first?"
+ Redwood::SourceManager.source_for uri or Trollop::die "Unknown source: #{uri}. Did you add it with sup-add first?"
end
end.map { |s| s.id }
Trollop::die "nothing to do: no sources" if source_ids.empty?
Redwood::SuicideManager.new Redwood::SUICIDE_FN
Redwood::CryptoManager.new
Redwood::UndoManager.new
+ Redwood::SourceManager.new
end
def finish
def report_broken_sources opts={}
return unless BufferManager.instantiated?
- broken_sources = Index.sources.select { |s| s.error.is_a? FatalSourceError }
+ broken_sources = SourceManager.sources.select { |s| s.error.is_a? FatalSourceError }
unless broken_sources.empty?
BufferManager.spawn_unless_exists("Broken source notification for #{broken_sources.join(',')}", opts) do
TextMode.new(<<EOM)
end
end
- desynced_sources = Index.sources.select { |s| s.error.is_a? OutOfSyncSourceError }
+ desynced_sources = SourceManager.sources.select { |s| s.error.is_a? OutOfSyncSourceError }
unless desynced_sources.empty?
BufferManager.spawn_unless_exists("Out-of-sync source notification for #{broken_sources.join(',')}", opts) do
TextMode.new(<<EOM)
def initialize dir=BASE_DIR
@index_mutex = Monitor.new
-
@dir = dir
- @sources = {}
- @sources_dirty = false
- @source_mutex = Monitor.new
wsa = Ferret::Analysis::WhiteSpaceAnalyzer.new false
sa = Ferret::Analysis::StandardAnalyzer.new [], true
end
def load
- load_sources
+ SourceManager.load_sources
load_index
end
def save
Redwood::log "saving index and sources..."
FileUtils.mkdir_p @dir unless File.exists? @dir
- save_sources
+ SourceManager.save_sources
save_index
end
- def add_source source
- @source_mutex.synchronize do
- raise "duplicate source!" if @sources.include? source
- @sources_dirty = true
- max = @sources.max_of { |id, s| s.is_a?(DraftLoader) || s.is_a?(SentLoader) ? 0 : id }
- source.id ||= (max || 0) + 1
- ##source.id += 1 while @sources.member? source.id
- @sources[source.id] = source
- end
- end
-
- def sources
- ## favour the inbox by listing non-archived sources first
- @source_mutex.synchronize { @sources.values }.sort_by { |s| s.id }.partition { |s| !s.archived? }.flatten
- end
-
- def source_for uri; sources.find { |s| s.is_source_for? uri }; end
- def usual_sources; sources.find_all { |s| s.usual? }; end
-
def load_index dir=File.join(@dir, "ferret")
if File.exists? dir
Redwood::log "loading index..."
@index_mutex.synchronize do
doc = @index[docid] or return
- source = @source_mutex.synchronize { @sources[doc[:source_id].to_i] }
+ source = SourceManager[doc[:source_id].to_i]
raise "invalid source #{doc[:source_id]}" unless source
#puts "building message #{doc[:message_id]} (#{source}##{doc[:source_info]})"
contacts.keys.compact
end
- def load_sources fn=Redwood::SOURCE_FN
- source_array = (Redwood::load_yaml_obj(fn) || []).map { |o| Recoverable.new o }
- @source_mutex.synchronize do
- @sources = Hash[*(source_array).map { |s| [s.id, s] }.flatten]
- @sources_dirty = false
- end
- end
-
def each_docid query={}
ferret_query = build_ferret_query query
results = @index_mutex.synchronize { @index.search ferret_query, :limit => (query[:limit] || :all) }
q.add_query Ferret::Search::TermQuery.new("source_id", query[:source_id]), :must if query[:source_id]
q
end
-
- def save_sources fn=Redwood::SOURCE_FN
- @source_mutex.synchronize do
- if @sources_dirty || @sources.any? { |id, s| s.dirty? }
- bakfn = fn + ".bak"
- if File.exists? fn
- File.chmod 0600, fn
- FileUtils.mv fn, bakfn, :force => true unless File.exists?(bakfn) && File.size(fn) == 0
- end
- Redwood::save_yaml_obj sources.sort_by { |s| s.id.to_i }, fn, true
- File.chmod 0600, fn
- end
- @sources_dirty = false
- end
- end
end
end
from_and_subj_inbox = []
@mutex.synchronize do
- Index.usual_sources.each do |source|
+ SourceManager.usual_sources.each do |source|
# yield "source #{source} is done? #{source.done?} (cur_offset #{source.cur_offset} >= #{source.end_offset})"
begin
yield "Loading from #{source}... " unless source.done? || (source.respond_to?(:has_errors?) && source.has_errors?)
end
end
+class SourceManager
+ include Singleton
+
+ def initialize
+ @sources = {}
+ @sources_dirty = false
+ @source_mutex = Monitor.new
+ self.class.i_am_the_instance self
+ end
+
+ def [](id)
+ @source_mutex.synchronize { @sources[id] }
+ end
+
+ def add_source source
+ @source_mutex.synchronize do
+ raise "duplicate source!" if @sources.include? source
+ @sources_dirty = true
+ max = @sources.max_of { |id, s| s.is_a?(DraftLoader) || s.is_a?(SentLoader) ? 0 : id }
+ source.id ||= (max || 0) + 1
+ ##source.id += 1 while @sources.member? source.id
+ @sources[source.id] = source
+ end
+ end
+
+ def sources
+ ## favour the inbox by listing non-archived sources first
+ @source_mutex.synchronize { @sources.values }.sort_by { |s| s.id }.partition { |s| !s.archived? }.flatten
+ end
+
+ def source_for uri; sources.find { |s| s.is_source_for? uri }; end
+ def usual_sources; sources.find_all { |s| s.usual? }; end
+
+ def load_sources fn=Redwood::SOURCE_FN
+ source_array = (Redwood::load_yaml_obj(fn) || []).map { |o| Recoverable.new o }
+ @source_mutex.synchronize do
+ @sources = Hash[*(source_array).map { |s| [s.id, s] }.flatten]
+ @sources_dirty = false
+ end
+ end
+
+ def save_sources fn=Redwood::SOURCE_FN
+ @source_mutex.synchronize do
+ if @sources_dirty || @sources.any? { |id, s| s.dirty? }
+ bakfn = fn + ".bak"
+ if File.exists? fn
+ File.chmod 0600, fn
+ FileUtils.mv fn, bakfn, :force => true unless File.exists?(bakfn) && File.size(fn) == 0
+ end
+ Redwood::save_yaml_obj sources.sort_by { |s| s.id.to_i }, fn, true
+ File.chmod 0600, fn
+ end
+ @sources_dirty = false
+ end
+ end
+end
+
end