commit b5e9d92ce85da9d3f6cf64b5e05f9e46180db999
parent d85ebd6d10c88292be1721d1a02b108080216d0a
Author: Rich Lane <rlane@club.cc.cmu.edu>
Date: Wed, 3 Mar 2010 23:23:42 -0800
Merge branch 'sup-cmd' into next
Conflicts:
lib/sup.rb
Diffstat:
| A |
bin/sup-cmd |
| |
110 |
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
| M |
lib/sup.rb |
| |
1 |
+
|
| A |
lib/sup/connection.rb |
| |
63 |
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
3 files changed, 174 insertions(+), 0 deletions(-)
diff --git a/bin/sup-cmd b/bin/sup-cmd
@@ -0,0 +1,110 @@
+#!/usr/bin/env ruby
+require 'rubygems'
+require 'trollop'
+require 'sup'
+require 'pp'
+require 'yaml'
+include Redwood
+
+SUB_COMMANDS = %w(query count label add)
+global_opts = Trollop::options do
+ #version = "sup-cmd (sup #{Redwood::VERSION})"
+ banner <<EOS
+Interact with a Sup index.
+
+Usage:
+ sup-cmd [global options] command [options]
+
+ Valid commands: #{SUB_COMMANDS * ', '}
+
+ Global options:
+EOS
+
+ opt :verbose
+
+ stop_on SUB_COMMANDS
+end
+
+cmd = ARGV.shift
+cmd_opts = case cmd
+when "query"
+ Trollop.options do
+ opt :offset, "Offset", :default => 0, :type => :int
+ opt :limit, "Limit", :type => :int
+ opt :raw, "Retrieve raw message text", :default => false
+ end
+when "count"
+ Trollop.options do
+ end
+when "label"
+ Trollop.options do
+ opt :add_labels, "Labels to add", :default => ""
+ opt :remove_labels, "Labels to remove", :default => ""
+ end
+when "add"
+ Trollop.options do
+ opt :labels, "Labels separated by commas", :default => ""
+ opt :mbox, "Treat input files as mboxes", :default => false
+ end
+else
+ Trollop::die "unrecognized command #{cmd.inspect}"
+end
+
+def get_query
+ text = ARGV.first or fail "query argument required"
+ Redwood::Index.parse_query text
+end
+
+Redwood.start
+Index.init
+Index.lock_interactively or exit
+begin
+ if(s = Redwood::SourceManager.source_for SentManager.source_uri)
+ SentManager.source = s
+ else
+ Redwood::SourceManager.add_source SentManager.default_source
+ end
+
+ Index.load
+ c = Redwood::Connection.new
+
+case cmd
+when "query"
+ c.query get_query, cmd_opts[:offset], cmd_opts[:limit], cmd_opts[:raw] do |result|
+ puts YAML.dump(result['summary'])
+ puts YAML.dump(result['raw']) if cmd_opts[:raw]
+ end
+when "count"
+ puts c.count(get_query)
+when "label"
+ c.label get_query, cmd_opts[:remove_labels].split(','), cmd_opts[:add_labels].split(',')
+when "add"
+ ARGF.binmode
+ labels = cmd_opts[:labels].split(',')
+ get_message = lambda do
+ return ARGF.gets(nil) unless cmd_opts[:mbox]
+ str = ""
+ l = ARGF.gets
+ str << l until ARGF.closed? || ARGF.eof? || MBox::is_break_line?(l = ARGF.gets)
+ str.empty? ? nil : str
+ end
+ i_s = i = 0
+ t = Time.now
+ while raw = get_message[]
+ i += 1
+ t_d = Time.now - t
+ if t_d >= 5
+ i_d = i - i_s
+ puts "indexed #{i} messages (#{i_d/t_d} m/s)" if global_opts[:verbose]
+ t = Time.now
+ i_s = i
+ end
+ c.add raw, labels
+ end
+else
+ fail "#{cmd} command unimplemented"
+end
+
+ensure
+ Index.unlock
+end
diff --git a/lib/sup.rb b/lib/sup.rb
@@ -348,6 +348,7 @@ require "sup/sent"
require "sup/search"
require "sup/modes/search-list-mode"
require "sup/idle"
+require "sup/connection"
$:.each do |base|
d = File.join base, "sup/share/modes/"
diff --git a/lib/sup/connection.rb b/lib/sup/connection.rb
@@ -0,0 +1,63 @@
+module Redwood
+
+## Hacky implementation of the sup-server API using existing Sup code
+class Connection
+ def result_from_message m, raw
+ mkperson = lambda { |p| { :email => p.email, :name => p.name } }
+ {
+ 'summary' => {
+ 'message_id' => m.id,
+ 'date' => m.date,
+ 'from' => mkperson[m.from],
+ 'to' => m.to.map(&mkperson),
+ 'cc' => m.cc.map(&mkperson),
+ 'bcc' => m.bcc.map(&mkperson),
+ 'subject' => m.subj,
+ 'refs' => m.refs,
+ 'replytos' => m.replytos,
+ 'labels' => m.labels.map(&:to_s),
+ },
+ 'raw' => raw ? m.raw_message : nil,
+ }
+ end
+
+ def query query, offset, limit, raw
+ c = 0
+ Index.each_message query do |m|
+ next if c < offset
+ break if c >= offset + limit if limit
+ yield result_from_message(m, raw)
+ c += 1
+ end
+ nil
+ end
+
+ def count query
+ Index.num_results_for query
+ end
+
+ def label query, remove_labels, add_labels
+ Index.each_message query do |m|
+ remove_labels.each { |l| m.remove_label l }
+ add_labels.each { |l| m.add_label l }
+ Index.update_message_state m
+ end
+ nil
+ end
+
+ def add raw, labels
+ SentManager.source.store_message Time.now, "test@example.com" do |io|
+ io.write raw
+ end
+ m2 = nil
+ PollManager.each_message_from(SentManager.source) do |m|
+ PollManager.add_new_message m
+ m2 = m
+ end
+ m2.labels = Set.new(labels.map(&:to_sym))
+ Index.update_message_state m2
+ nil
+ end
+end
+
+end