Class: Redwood::MBox
Defined Under Namespace
Classes: Loader
Constant Summary
collapse
- BREAK_RE =
/^From \S+ (.+)$/
Instance Attribute Summary collapse
Attributes inherited from Source
#id, #uri
Class Method Summary
collapse
Instance Method Summary
collapse
#after_unmarshal!, #before_marshal
Methods inherited from Source
#==, parse_raw_email_header, #read?, #to_s, #usual, #valid?
Constructor Details
#initialize(uri_or_fp, usual = true, archived = false, id = nil, labels = nil) ⇒ MBox
uri_or_fp is horrific. need to refactor.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
# File 'lib/sup/mbox.rb', line 15
def initialize uri_or_fp, usual=true, archived=false, id=nil, labels=nil
@mutex = Mutex.new
@labels = Set.new((labels || []) - LabelManager::RESERVED_LABELS)
case uri_or_fp
when String
@expanded_uri = Source.expand_filesystem_uri(uri_or_fp)
uri = URI(@expanded_uri)
raise ArgumentError, "not an mbox uri" unless uri.scheme == "mbox"
raise ArgumentError, "mbox URI ('#{uri}') cannot have a host: #{uri.host}" if uri.host
raise ArgumentError, "mbox URI must have a path component" unless uri.path
@f = nil
@path = uri.path
else
@f = uri_or_fp
@path = uri_or_fp.path
@expanded_uri = "mbox://#{@path}"
end
super uri_or_fp, usual, archived, id
end
|
Instance Attribute Details
Returns the value of attribute labels.
12
13
14
|
# File 'lib/sup/mbox.rb', line 12
def labels
@labels
end
|
Class Method Details
.is_break_line?(l) ⇒ Boolean
172
173
174
175
176
177
178
179
180
181
182
183
|
# File 'lib/sup/mbox.rb', line 172
def self.is_break_line? l
l =~ BREAK_RE or return false
time = $1
begin
Time.parse time, 0
true
rescue NoMethodError, ArgumentError
warn "found invalid date in potential mbox split line, not splitting: #{l.inspect}"
false
end
end
|
.suggest_labels_for(path) ⇒ Object
40
41
42
43
44
45
46
47
48
|
# File 'lib/sup/mbox.rb', line 40
def self.suggest_labels_for path
if File.dirname(path) =~ /\b(var|usr|spool)\b/
[]
else
[File.basename(path).downcase.intern]
end
end
|
Instance Method Details
#default_labels ⇒ Object
134
135
136
|
# File 'lib/sup/mbox.rb', line 134
def default_labels
[:inbox, :unread]
end
|
#each_raw_message_line(offset) ⇒ Object
apparently it’s a million times faster to call this directly if we’re just moving messages around on disk, than reading things into memory with raw_message.
i hoped never to have to move shit around on disk but sup-sync-back has to do it.
124
125
126
127
128
129
130
131
132
|
# File 'lib/sup/mbox.rb', line 124
def each_raw_message_line offset
@mutex.synchronize do
ensure_open
@f.seek offset
until @f.eof? || MBox::is_break_line?(l = @f.gets)
yield l
end
end
end
|
#file_path ⇒ Object
37
|
# File 'lib/sup/mbox.rb', line 37
def file_path; @path end
|
#first_new_message ⇒ Object
offset of first new message or nil
168
169
170
|
# File 'lib/sup/mbox.rb', line 168
def first_new_message
next_offset(last_indexed_message || 0)
end
|
55
56
57
58
59
60
61
|
# File 'lib/sup/mbox.rb', line 55
def go_idle
@mutex.synchronize do
return if @f.nil? or @path.nil?
@f.close
@f = nil
end
end
|
#is_source_for?(uri) ⇒ Boolean
38
|
# File 'lib/sup/mbox.rb', line 38
def is_source_for? uri; super || (uri == @expanded_uri) end
|
#last_indexed_message ⇒ Object
TODO optimize this by iterating over allterms list backwards or storing source_info negated
163
164
165
|
# File 'lib/sup/mbox.rb', line 163
def last_indexed_message
benchmark(:mbox_read_index) { Enumerator.new(Index.instance, :each_source_info, self.id).map(&:to_i).max }
end
|
63
64
65
66
67
68
69
70
71
|
# File 'lib/sup/mbox.rb', line 63
def offset
= nil
@mutex.synchronize do
ensure_open
@f.seek offset
= @f
end
end
|
#load_message(offset) ⇒ Object
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
# File 'lib/sup/mbox.rb', line 73
def load_message offset
@mutex.synchronize do
ensure_open
@f.seek offset
begin
string = ""
until @f.eof? || MBox::is_break_line?(l = @f.gets)
string << l
end
RMail::Parser.read string
rescue RMail::Parser::Error => e
raise FatalSourceError, "error parsing mbox file: #{e.message}"
end
end
end
|
#next_offset(offset) ⇒ Object
151
152
153
154
155
156
157
158
159
|
# File 'lib/sup/mbox.rb', line 151
def next_offset offset
@mutex.synchronize do
ensure_open
@f.seek offset
nil while line = @f.gets and not MBox::is_break_line? line
offset = @f.tell
offset != File.size(@f) ? offset : nil
end
end
|
138
139
140
141
142
143
144
145
146
147
148
149
|
# File 'lib/sup/mbox.rb', line 138
def poll
first_offset = first_new_message
offset = first_offset
end_offset = File.size @f
while offset and offset < end_offset
yield :add,
:info => offset,
:labels => (labels + default_labels),
:progress => (offset - first_offset).to_f/end_offset
offset = next_offset offset
end
end
|
91
92
93
94
95
96
97
98
99
100
101
|
# File 'lib/sup/mbox.rb', line 91
def offset
ret = ""
@mutex.synchronize do
ensure_open
@f.seek offset
until @f.eof? || (l = @f.gets) =~ /^\r*$/
ret << l
end
end
ret
end
|
#raw_message(offset) ⇒ Object
103
104
105
106
107
|
# File 'lib/sup/mbox.rb', line 103
def raw_message offset
ret = ""
each_raw_message_line(offset) { |l| ret << l }
ret
end
|
#store_message(date, from_email, &block) ⇒ Object
109
110
111
112
113
114
115
116
|
# File 'lib/sup/mbox.rb', line 109
def store_message date, from_email, &block
need_blank = File.exists?(@path) && !File.zero?(@path)
File.open(@path, "ab") do |f|
f.puts if need_blank
f.puts "From #{from_email} #{date.asctime}"
yield f
end
end
|