]> git.cworth.org Git - sup/blob - lib/sup/source.rb
many changes (while on the airplane).
[sup] / lib / sup / source.rb
1 module Redwood
2
3 class SourceError < StandardError; end
4
5 class Source
6   ## dirty? described whether cur_offset has changed, which means the
7   ## source needs to be re-saved to disk.
8   ##
9   ## broken? means no message can be loaded, e.g. IMAP server is
10   ## down, mbox file is corrupt and needs to be rescanned.
11
12   ## When writing a new source, you should implement:
13   ##
14   ## start_offset
15   ## end_offset
16   ## load_header(offset)
17   ## load_message(offset)
18   ## raw_header(offset)
19   ## raw_full_message(offset)
20   ## next (or each, if you prefer)
21
22   ## you can throw SourceErrors from any of those, but we don't catch
23   ## anything else, so make sure you catch all non-fatal errors and
24   ## reraise them as source errors.
25
26   bool_reader :usual, :archived, :dirty
27   attr_reader :uri, :cur_offset, :broken_msg
28   attr_accessor :id
29
30   def initialize uri, initial_offset=nil, usual=true, archived=false, id=nil
31     @uri = uri
32     @cur_offset = initial_offset
33     @usual = usual
34     @archived = archived
35     @id = id
36     @dirty = false
37     @broken_msg = nil
38   end
39
40   def broken?; !@broken_msg.nil?; end
41   def to_s; @uri; end
42   def seek_to! o; self.cur_offset = o; end
43   def reset!
44     return if broken?
45     begin
46       seek_to! start_offset
47     rescue SourceError
48     end
49   end
50   def == o; o.to_s == to_s; end
51   def done?;
52     return true if broken? 
53     begin
54       (self.cur_offset ||= start_offset) >= end_offset
55     rescue SourceError => e
56       true
57     end
58   end
59   def is_source_for? s; to_s == s; end
60
61   def each
62     return if broken?
63     begin
64       self.cur_offset ||= start_offset
65       until done? || broken? # just like life!
66         n, labels = self.next
67         raise "no message" unless n
68         yield n, labels
69       end
70     rescue SourceError => e
71       self.broken_msg = e.message
72     end
73   end
74
75 protected
76   
77   def cur_offset= o
78     @cur_offset = o
79     @dirty = true
80   end
81
82   def broken_msg= m
83     @broken_msg = m
84 #    Redwood::log "#{to_s}: #{m}"
85   end
86 end
87
88 Redwood::register_yaml(Source, %w(uri cur_offset usual archived id))
89
90 end