]> git.cworth.org Git - sup/blob - lib/sup/mbox/ssh-loader.rb
yet more error handling updates
[sup] / lib / sup / mbox / ssh-loader.rb
1 require 'net/ssh'
2
3 module Redwood
4 module MBox
5
6 class SSHLoader < Source
7   attr_accessor :username, :password
8
9   def initialize uri, username=nil, password=nil, start_offset=nil, usual=true, archived=false, id=nil
10     raise ArgumentError, "not an mbox+ssh uri: #{uri.inspect}" unless uri =~ %r!^mbox\+ssh://!
11
12     super uri, start_offset, usual, archived, id
13
14     @parsed_uri = URI(uri)
15     @username = username
16     @password = password
17     @uri = uri
18     @cur_offset = start_offset
19
20     opts = {}
21     opts[:username] = @username if @username
22     opts[:password] = @password if @password
23     
24     @f = SSHFile.new host, filename, opts
25     @loader = Loader.new @f, start_offset, usual, archived, id
26     
27     ## heuristic: use the filename as a label, unless the file
28     ## has a path that probably represents an inbox.
29     @labels = [:unread]
30     @labels << File.basename(filename).intern unless File.dirname(filename) =~ /\b(var|usr|spool)\b/
31   end
32
33   def connect; safely { @f.connect }; end
34   def host; @parsed_uri.host; end
35   def filename; @parsed_uri.path[1..-1] end
36
37   def next
38     safely do
39       offset, labels = @loader.next
40       self.cur_offset = @loader.cur_offset # superclass keeps @cur_offset which is used by yaml
41       [offset, (labels + @labels).uniq] # add our labels
42     end
43   end
44
45   def end_offset
46     safely { @f.size }
47   end
48
49   def cur_offset= o; @cur_offset = @loader.cur_offset = o; @dirty = true; end
50   def id; @loader.id; end
51   def id= o; @id = @loader.id = o; end
52   # def cur_offset; @loader.cur_offset; end # think we'll be ok without this
53   def to_s; @parsed_uri.to_s; end
54
55   def safely
56     begin
57       yield
58     rescue Net::SSH::Exception, SocketError, SSHFileError, SystemCallError, IOError => e
59       m = "error communicating with SSH server #{host} (#{e.class.name}): #{e.message}"
60       raise FatalSourceError, m
61     end
62   end
63
64   [:start_offset, :load_header, :load_message, :raw_header, :raw_full_message].each do |meth|
65     define_method(meth) { |*a| safely { @loader.send meth, *a } }
66   end
67 end
68
69 Redwood::register_yaml(SSHLoader, %w(uri username password cur_offset usual archived id))
70
71 end
72 end