7 class Error < StandardError; end
11 bool_reader :usual, :archived, :read, :dirty
12 attr_accessor :id, :labels
14 ## end_offset is the last offsets within the file which we've read.
15 ## everything after that is considered new messages that haven't
17 def initialize filename, end_offset=nil, usual=true, archived=false, id=nil
18 @filename = filename.gsub(%r(^mbox://), "")
19 @end_offset = end_offset || 0
25 @f = File.open @filename
28 archived ? nil : :inbox,
30 if File.dirname(filename) =~ /\b(var|usr|spool)\b/
33 [File.basename(filename).intern]
38 @end_offset = [offset, File.size(@f) - 1].min;
41 def reset!; seek_to! 0; end
42 def == o; o.is_a?(Loader) && o.filename == filename; end
43 def to_s; "mbox://#{@filename}"; end
46 @filename == s || self.to_s == s
49 def load_header offset
50 raise ArgumentError, "nil offset" unless offset
53 @f.seek offset if offset
55 raise Error, "offset mismatch in mbox file offset #{offset.inspect}: #{l.inspect}. Run 'sup-import --rebuild #{to_s}' to correct this." unless l =~ BREAK_RE
56 header = MBox::read_header @f
61 def load_message offset
65 RMail::Mailbox::MBoxReader.new(@f).each_message do |input|
66 return RMail::Parser.read(input)
75 until @f.eof? || (l = @f.gets) =~ /^$/
82 def raw_full_message offset
86 @f.gets # skip mbox header
87 until @f.eof? || (l = @f.gets) =~ BREAK_RE
98 next_end_offset = @end_offset
100 ## @end_offset could be at one of two places here: before a \n and
101 ## a mbox separator, if it was previously at EOF and a new message
102 ## was added; or, at the beginning of an mbox separator (in all
104 @mutex.synchronize do
106 l = @f.gets or return nil
108 start_offset = @f.tell
111 start_offset = @end_offset
114 while(line = @f.gets)
115 break if line =~ BREAK_RE
116 next_end_offset = @f.tell
120 @end_offset = next_end_offset
125 until @end_offset >= File.size(@f)
127 yield(n, labels) if n
131 def done?; @end_offset >= File.size(@f); end
132 def total; File.size @f; end
135 Redwood::register_yaml(Loader, %w(filename end_offset usual archived id))