maildir 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +2 -0
- data/Rakefile +5 -0
- data/VERSION +1 -1
- data/benchmarks/runner +28 -2
- data/lib/maildir.rb +10 -5
- data/lib/maildir/message.rb +44 -20
- data/maildir.gemspec +61 -0
- data/test/test_maildir.rb +11 -0
- data/test/test_message.rb +9 -0
- metadata +4 -2
data/.gitignore
ADDED
data/Rakefile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/benchmarks/runner
CHANGED
@@ -1,4 +1,30 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
$:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
3
|
+
require 'maildir'
|
4
|
+
require 'benchmark'
|
2
5
|
|
3
|
-
|
4
|
-
|
6
|
+
maildir_path = ENV['MAILDIR'] || "./tmp"
|
7
|
+
maildir = Maildir.new(maildir_path)
|
8
|
+
|
9
|
+
n = 300
|
10
|
+
message = "Write #{n} messages:"
|
11
|
+
tms = Benchmark.bmbm(message.size) do |x|
|
12
|
+
x.report(message) { n.times { maildir.add_message("") } }
|
13
|
+
end
|
14
|
+
|
15
|
+
puts "#{n/tms.first.real} messages per second"
|
16
|
+
|
17
|
+
|
18
|
+
message = "List new:"
|
19
|
+
tms = Benchmark.bm(message.size) do |x|
|
20
|
+
x.report(message) { n.times { maildir.list_keys(:new)} }
|
21
|
+
end
|
22
|
+
|
23
|
+
# require 'ruby-prof'
|
24
|
+
# result = RubyProf.profile do
|
25
|
+
# n.times { maildir.list_keys(:new) }
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# # Print a graph profile to text
|
29
|
+
# printer = RubyProf::GraphPrinter.new(result)
|
30
|
+
# printer.print(STDOUT, 0)
|
data/lib/maildir.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'fileutils'
|
1
2
|
class Maildir
|
2
3
|
|
3
4
|
SUBDIRS = [:tmp, :new, :cur].freeze
|
@@ -43,10 +44,10 @@ class Maildir
|
|
43
44
|
get_dir_listing(new_or_cur)
|
44
45
|
end
|
45
46
|
|
46
|
-
# Writes
|
47
|
-
# more.
|
48
|
-
def add_message(
|
49
|
-
Maildir::Message.create(self,
|
47
|
+
# Writes string_or_io object out as a new message. See
|
48
|
+
# Maildir::Message.create for more.
|
49
|
+
def add_message(string_or_io)
|
50
|
+
Maildir::Message.create(self, string_or_io)
|
50
51
|
end
|
51
52
|
|
52
53
|
def get_message(key)
|
@@ -57,8 +58,12 @@ class Maildir
|
|
57
58
|
def get_dir_listing(new_or_cur)
|
58
59
|
search_path = File.join(self.path, new_or_cur.to_s, '*')
|
59
60
|
results = Dir.glob(search_path)
|
61
|
+
|
60
62
|
# Remove the maildir's path from the beginning of the message path
|
61
|
-
|
63
|
+
@dir_listing_regexp ||= /^#{Regexp.quote(self.path)}/
|
64
|
+
results.each do |message_path|
|
65
|
+
message_path.sub!(@dir_listing_regexp, "")
|
66
|
+
end
|
62
67
|
end
|
63
68
|
end
|
64
69
|
|
data/lib/maildir/message.rb
CHANGED
@@ -5,24 +5,27 @@ class Maildir::Message
|
|
5
5
|
INFO = "2,"
|
6
6
|
|
7
7
|
class << self
|
8
|
-
# Create a new message in maildir with the contents of
|
9
|
-
# first written to the tmp dir, then moved to new. This is
|
8
|
+
# Create a new message in maildir with the contents of string_or_io.
|
9
|
+
# The message is first written to the tmp dir, then moved to new. This is
|
10
|
+
# a shortcut for:
|
10
11
|
# message = Maildir::Message.new(maildir)
|
11
|
-
# message.write(
|
12
|
-
def create(maildir,
|
12
|
+
# message.write(string_or_io)
|
13
|
+
def create(maildir, string_or_io)
|
13
14
|
message = self.new(maildir)
|
14
|
-
message.write(
|
15
|
+
message.write(string_or_io)
|
15
16
|
message
|
16
17
|
end
|
17
18
|
end
|
18
19
|
|
19
20
|
attr_reader :dir, :unique_name, :info, :old_key
|
20
21
|
|
21
|
-
# Create a new, unwritten message
|
22
|
-
#
|
22
|
+
# Create a new, unwritten message or instantiate an existing message.
|
23
|
+
# If key is nil, create a new message:
|
24
|
+
# Message.new(maildir) # => a new, unwritten message
|
23
25
|
#
|
24
|
-
#
|
25
|
-
#
|
26
|
+
# If +key+ is not nil, instantiate a message object for the message at
|
27
|
+
# +key+.
|
28
|
+
# Message.new(maildir, key) # => an existing message
|
26
29
|
def initialize(maildir, key=nil)
|
27
30
|
@maildir = maildir
|
28
31
|
if key.nil?
|
@@ -31,33 +34,44 @@ class Maildir::Message
|
|
31
34
|
parse_key(key)
|
32
35
|
end
|
33
36
|
|
34
|
-
|
37
|
+
unless Maildir::SUBDIRS.include? dir
|
38
|
+
raise ArgumentError, "State must be in #{Maildir::SUBDIRS.inspect}"
|
39
|
+
end
|
35
40
|
|
36
41
|
if :tmp == dir
|
37
42
|
@unique_name = Maildir::UniqueName.create
|
38
43
|
end
|
39
44
|
end
|
40
45
|
|
41
|
-
# Writes
|
42
|
-
# key (which haven't been written to disk). If the
|
43
|
-
#
|
44
|
-
|
46
|
+
# Writes string_or_io to disk. Can only be called on messages
|
47
|
+
# instantiated without a key (which haven't been written to disk). If the
|
48
|
+
# +string_or_io+ object has a 'read' method, calls string_or_io.read.
|
49
|
+
# Otherwise, calls string_or_io.to_s.
|
50
|
+
#
|
51
|
+
# Returns the message's key
|
52
|
+
def write(string_or_io)
|
45
53
|
raise "Can only write to messages in tmp" unless :tmp == @dir
|
46
54
|
# Write out contents to tmp
|
47
55
|
File.open(path, 'w') do |file|
|
48
|
-
|
56
|
+
if string_or_io.respond_to?(:read)
|
57
|
+
file.puts string_or_io.read
|
58
|
+
else
|
59
|
+
file.puts string_or_io.to_s
|
60
|
+
end
|
49
61
|
end
|
50
62
|
|
51
63
|
# Rename to new
|
52
64
|
rename(:new)
|
53
|
-
|
54
65
|
end
|
55
66
|
|
56
|
-
# Move a message from new to cur, add info
|
67
|
+
# Move a message from new to cur, add info.
|
68
|
+
# Returns the message's key
|
57
69
|
def process
|
58
70
|
rename(:cur, INFO)
|
59
71
|
end
|
60
72
|
|
73
|
+
# Set info on a message.
|
74
|
+
# Returns the message's key
|
61
75
|
def info=(info)
|
62
76
|
raise "Can only set info on cur messages" unless :cur == @dir
|
63
77
|
rename(:cur, info)
|
@@ -68,6 +82,8 @@ class Maildir::Message
|
|
68
82
|
@info.sub(INFO,'').split('')
|
69
83
|
end
|
70
84
|
|
85
|
+
# Sets the flags on a message.
|
86
|
+
# Returns the message's key
|
71
87
|
def flags=(*flags)
|
72
88
|
self.info = INFO + sort_flags(flags.flatten.join(''))
|
73
89
|
end
|
@@ -96,22 +112,29 @@ class Maildir::Message
|
|
96
112
|
File.join(@maildir.path, key)
|
97
113
|
end
|
98
114
|
|
99
|
-
|
100
|
-
|
115
|
+
# Deletes the message path and freezes the message object
|
116
|
+
def destroy
|
117
|
+
File.delete(path)
|
118
|
+
freeze
|
101
119
|
end
|
102
120
|
|
103
121
|
protected
|
104
|
-
# Sets dir, unique_name, and info based
|
122
|
+
# Sets dir, unique_name, and info based on the key
|
105
123
|
def parse_key(key)
|
106
124
|
@dir, filename = key.split(File::SEPARATOR)
|
107
125
|
@dir = @dir.to_sym
|
108
126
|
@unique_name, @info = filename.split(COLON)
|
109
127
|
end
|
110
128
|
|
129
|
+
# Ensure the flags are uppercase and sorted
|
111
130
|
def sort_flags(flags)
|
112
131
|
flags.split('').map{|f| f.upcase}.sort!.uniq.join('')
|
113
132
|
end
|
114
133
|
|
134
|
+
def old_path
|
135
|
+
File.join(@maildir.path, old_key)
|
136
|
+
end
|
137
|
+
|
115
138
|
def rename(new_dir, new_info=nil)
|
116
139
|
# Safe the old key so we can revert to the old state
|
117
140
|
@old_key = key
|
@@ -122,6 +145,7 @@ class Maildir::Message
|
|
122
145
|
|
123
146
|
begin
|
124
147
|
File.rename(old_path, path) unless old_path == path
|
148
|
+
return key
|
125
149
|
rescue Errno::ENOENT
|
126
150
|
# Restore ourselves to the old state
|
127
151
|
parse_key(@old_key)
|
data/maildir.gemspec
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{maildir}
|
8
|
+
s.version = "0.2.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Aaron Suggs"]
|
12
|
+
s.date = %q{2010-01-05}
|
13
|
+
s.description = %q{A ruby library for reading and writing arbitrary messages in DJB's maildir format}
|
14
|
+
s.email = %q{aaron@ktheory.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".gitignore",
|
21
|
+
"LICENSE",
|
22
|
+
"NOTES.txt",
|
23
|
+
"README.rdoc",
|
24
|
+
"Rakefile",
|
25
|
+
"VERSION",
|
26
|
+
"benchmarks/runner",
|
27
|
+
"lib/maildir.rb",
|
28
|
+
"lib/maildir/message.rb",
|
29
|
+
"lib/maildir/unique_name.rb",
|
30
|
+
"maildir.gemspec",
|
31
|
+
"test/test_helper.rb",
|
32
|
+
"test/test_maildir.rb",
|
33
|
+
"test/test_message.rb",
|
34
|
+
"test/test_unique_name.rb"
|
35
|
+
]
|
36
|
+
s.homepage = %q{http://github.com/ktheory/maildir}
|
37
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
38
|
+
s.require_paths = ["lib"]
|
39
|
+
s.rubygems_version = %q{1.3.5}
|
40
|
+
s.summary = %q{Read & write messages in the maildir format}
|
41
|
+
s.test_files = [
|
42
|
+
"test/test_helper.rb",
|
43
|
+
"test/test_maildir.rb",
|
44
|
+
"test/test_message.rb",
|
45
|
+
"test/test_unique_name.rb"
|
46
|
+
]
|
47
|
+
|
48
|
+
if s.respond_to? :specification_version then
|
49
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
50
|
+
s.specification_version = 3
|
51
|
+
|
52
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
53
|
+
s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
|
54
|
+
else
|
55
|
+
s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
|
56
|
+
end
|
57
|
+
else
|
58
|
+
s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
data/test/test_maildir.rb
CHANGED
@@ -33,6 +33,17 @@ class TestMaildir < Test::Unit::TestCase
|
|
33
33
|
assert_equal temp_maildir.path, new_maildir.path
|
34
34
|
assert_equal temp_maildir, new_maildir
|
35
35
|
end
|
36
|
+
|
37
|
+
context "with a message" do
|
38
|
+
setup do
|
39
|
+
@key = temp_maildir.add_message("").key
|
40
|
+
end
|
41
|
+
|
42
|
+
should "list the message in it's keys" do
|
43
|
+
keys = temp_maildir.list_keys(:new)
|
44
|
+
assert_equal keys, [@key]
|
45
|
+
end
|
46
|
+
end
|
36
47
|
end
|
37
48
|
|
38
49
|
end
|
data/test/test_message.rb
CHANGED
@@ -147,6 +147,15 @@ class TestMessage < Test::Unit::TestCase
|
|
147
147
|
assert_match /#{path_suffix}$/, @message.path
|
148
148
|
end
|
149
149
|
end
|
150
|
+
context "when destroyed" do
|
151
|
+
setup { @message.destroy }
|
152
|
+
should "be frozen" do
|
153
|
+
assert @message.frozen?, "Message is not frozen"
|
154
|
+
end
|
155
|
+
should "have a nonexistant path" do
|
156
|
+
assert !File.exists?(@message.path), "Message path exists"
|
157
|
+
end
|
158
|
+
end
|
150
159
|
end
|
151
160
|
end
|
152
161
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: maildir
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aaron Suggs
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date:
|
12
|
+
date: 2010-01-05 00:00:00 -05:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -32,6 +32,7 @@ extra_rdoc_files:
|
|
32
32
|
- LICENSE
|
33
33
|
- README.rdoc
|
34
34
|
files:
|
35
|
+
- .gitignore
|
35
36
|
- LICENSE
|
36
37
|
- NOTES.txt
|
37
38
|
- README.rdoc
|
@@ -41,6 +42,7 @@ files:
|
|
41
42
|
- lib/maildir.rb
|
42
43
|
- lib/maildir/message.rb
|
43
44
|
- lib/maildir/unique_name.rb
|
45
|
+
- maildir.gemspec
|
44
46
|
- test/test_helper.rb
|
45
47
|
- test/test_maildir.rb
|
46
48
|
- test/test_message.rb
|