maildir 0.2.0 → 0.3.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/LICENSE +1 -1
- data/README.rdoc +100 -2
- data/Rakefile +3 -1
- data/VERSION +1 -1
- data/benchmarks/runner +1 -1
- data/lib/maildir/message.rb +40 -17
- data/lib/maildir/serializer/base.rb +20 -0
- data/lib/maildir/serializer/json.rb +13 -0
- data/lib/maildir/serializer/mail.rb +13 -0
- data/lib/maildir/serializer/marshal.rb +12 -0
- data/lib/maildir/serializer/yaml.rb +13 -0
- data/lib/maildir.rb +43 -18
- data/maildir.gemspec +18 -6
- data/test/test_maildir.rb +10 -8
- data/test/test_message.rb +22 -14
- data/test/test_serializers.rb +43 -0
- metadata +30 -4
- data/NOTES.txt +0 -17
data/LICENSE
CHANGED
data/README.rdoc
CHANGED
@@ -2,8 +2,106 @@
|
|
2
2
|
|
3
3
|
A ruby library for reading and writing messages in the maildir format.
|
4
4
|
|
5
|
-
|
5
|
+
== What's so great about the maildir format
|
6
|
+
|
7
|
+
See http://cr.yp.to/proto/maildir.html and http://en.wikipedia.org/wiki/Maildir
|
8
|
+
|
9
|
+
As Daniel J. Berstein puts it: "Two words: no locks." The maildir format allows multiple processes to read and write arbitrary messages without file locks.
|
10
|
+
|
11
|
+
New messages are initially written to a "tmp" directory with an automatically-generated unique filename. After the message is written, it's moved to the "new" directory where other processes may read it.
|
12
|
+
|
13
|
+
While the maildir format was created for email, it works well for arbitrary data. This library can read & write email messages or arbitrary data. See Pluggable serializers for more.
|
14
|
+
|
15
|
+
== Install
|
16
|
+
|
17
|
+
sudo gem install maildir
|
18
|
+
|
19
|
+
== Usage
|
20
|
+
|
21
|
+
Create a maildir in /home/aaron/mail
|
22
|
+
|
23
|
+
maildir = Maildir.new("/home/aaron/mail") # creates tmp, new, and cur dirs
|
24
|
+
# call Maildir.new("/home/aaron/mail", false) to skip directory creation.
|
25
|
+
|
26
|
+
Add a new message. This creates a new file with the contents "Hello World!"; returns the path fragment to the file. Messages are written to the tmp dir then moved to new.
|
27
|
+
|
28
|
+
message = maildir.add("Hello World!")
|
29
|
+
|
30
|
+
List new messages
|
31
|
+
|
32
|
+
maildir.list(:new) # => [message]
|
33
|
+
|
34
|
+
Move the message from "new" to "cur" to indicate that some process has retrieved the message.
|
35
|
+
|
36
|
+
message.process
|
37
|
+
|
38
|
+
Indeed, the message is in cur, not new.
|
39
|
+
|
40
|
+
maildir.list(:new) # => []
|
41
|
+
maildir.list(:cur) # => [message]
|
42
|
+
|
43
|
+
Add some flags to the message to indicate state. See "What can I put in info" at http://cr.yp.to/proto/maildir.html for flag conventions.
|
44
|
+
|
45
|
+
message.add_flag("S") # Mark the message as "seen"
|
46
|
+
message.add_flag("F") # Mark the message as "flagged"
|
47
|
+
message.remove_flag("F") # unflag the message
|
48
|
+
message.add_flag("T") # Mark the message as "trashed"
|
49
|
+
|
50
|
+
Get a key to uniquely identify the message
|
51
|
+
|
52
|
+
key = message.key
|
53
|
+
|
54
|
+
Load the contents of the message
|
55
|
+
|
56
|
+
data = message.data
|
57
|
+
|
58
|
+
Find the message based using the key
|
59
|
+
|
60
|
+
message_copy = maildir.get(key)
|
61
|
+
message == message_copy # => true
|
62
|
+
|
63
|
+
Delete the message from disk
|
64
|
+
|
65
|
+
message.destroy # => returns the frozen message
|
66
|
+
maildir.list(:cur) # => []
|
67
|
+
|
68
|
+
== Pluggable serializers
|
69
|
+
|
70
|
+
By default, message data are written and read from disk as a string. It's often desirable to process the string into a useful object. Maildir supports configurable serializers to convert message data into a useful object.
|
71
|
+
|
72
|
+
The following serializers are included:
|
73
|
+
|
74
|
+
* Maildir::Serializer::Base (the default)
|
75
|
+
* Maildir::Serializer::Mail
|
76
|
+
* Maildir::Serializer::Marshal
|
77
|
+
* Maildir::Serializer::JSON
|
78
|
+
* Maildir::Serializer::YAML
|
79
|
+
|
80
|
+
Maildir::Serializer::Base simply reads and writes strings to disk.
|
81
|
+
|
82
|
+
Maildir::Message.serializer # => Maildir::Serializer::Base.new (by default)
|
83
|
+
message = maildir.add("Hello World!") # writes "Hello World!" to disk
|
84
|
+
message.data # => "Hello World!"
|
85
|
+
|
86
|
+
The Mail serializer takes a ruby Mail object (http://github.com/mikel/mail) and writes RFC2822 email messages.
|
87
|
+
|
88
|
+
Maildir::Message.serializer = Maildir::Serializer::Mail.new
|
89
|
+
mail = Mail.new(...)
|
90
|
+
message = maildir.add(mail) # writes and RFC2822 message to disk
|
91
|
+
message.data == mail # => true; data is parsed as a Mail object
|
92
|
+
|
93
|
+
The Marshal, JSON, and YAML serializers work similarly. E.g.
|
94
|
+
|
95
|
+
Maildir::Message.serializer = Maildir::Serializer::JSON.new
|
96
|
+
my_data = {"foo" => nil, "my_array" => [1,2,3]}
|
97
|
+
message = maildir.add(my_data) # writes {"foo":null,"my_array":[1,2,3]}
|
98
|
+
message.data == my_data # => true
|
99
|
+
|
100
|
+
It's trivial to create a custom serializer. Implement the following two methods:
|
101
|
+
|
102
|
+
load(path)
|
103
|
+
dump(data, path)
|
6
104
|
|
7
105
|
== Copyright
|
8
106
|
|
9
|
-
Copyright (c)
|
107
|
+
Copyright (c) 2010 Aaron Suggs. See LICENSE for details.
|
data/Rakefile
CHANGED
@@ -16,7 +16,9 @@ begin
|
|
16
16
|
gemspec.email = "aaron@ktheory.com"
|
17
17
|
gemspec.homepage = "http://github.com/ktheory/maildir"
|
18
18
|
gemspec.authors = ["Aaron Suggs"]
|
19
|
-
gemspec.add_development_dependency "
|
19
|
+
gemspec.add_development_dependency "shoulda", ">= 0"
|
20
|
+
gemspec.add_development_dependency "mail", ">= 0"
|
21
|
+
gemspec.add_development_dependency "json", ">= 0"
|
20
22
|
end
|
21
23
|
Jeweler::GemcutterTasks.new
|
22
24
|
rescue LoadError
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.0
|
data/benchmarks/runner
CHANGED
@@ -9,7 +9,7 @@ maildir = Maildir.new(maildir_path)
|
|
9
9
|
n = 300
|
10
10
|
message = "Write #{n} messages:"
|
11
11
|
tms = Benchmark.bmbm(message.size) do |x|
|
12
|
-
x.report(message) { n.times { maildir.
|
12
|
+
x.report(message) { n.times { maildir.add("") } }
|
13
13
|
end
|
14
14
|
|
15
15
|
puts "#{n/tms.first.real} messages per second"
|
data/lib/maildir/message.rb
CHANGED
@@ -4,19 +4,28 @@ class Maildir::Message
|
|
4
4
|
# The default info, to which flags are appended
|
5
5
|
INFO = "2,"
|
6
6
|
|
7
|
+
include Comparable
|
8
|
+
|
7
9
|
class << self
|
8
|
-
# Create a new message in maildir with
|
10
|
+
# Create a new message in maildir with data.
|
9
11
|
# The message is first written to the tmp dir, then moved to new. This is
|
10
12
|
# a shortcut for:
|
11
13
|
# message = Maildir::Message.new(maildir)
|
12
|
-
# message.write(
|
13
|
-
def create(maildir,
|
14
|
+
# message.write(data)
|
15
|
+
def create(maildir, data)
|
14
16
|
message = self.new(maildir)
|
15
|
-
message.write(
|
17
|
+
message.write(data)
|
16
18
|
message
|
17
19
|
end
|
20
|
+
|
21
|
+
# The serializer processes data before it is written to disk and after
|
22
|
+
# reading from disk.
|
23
|
+
attr_accessor :serializer
|
18
24
|
end
|
19
25
|
|
26
|
+
# Default serializer
|
27
|
+
@serializer = Maildir::Serializer::Base.new
|
28
|
+
|
20
29
|
attr_reader :dir, :unique_name, :info, :old_key
|
21
30
|
|
22
31
|
# Create a new, unwritten message or instantiate an existing message.
|
@@ -43,24 +52,32 @@ class Maildir::Message
|
|
43
52
|
end
|
44
53
|
end
|
45
54
|
|
46
|
-
#
|
47
|
-
#
|
48
|
-
#
|
49
|
-
|
55
|
+
# Compares messages by their paths.
|
56
|
+
# If message is a different class, return nil.
|
57
|
+
# Otherwise, return 1, 0, or -1.
|
58
|
+
def <=>(message)
|
59
|
+
# Return nil if comparing different classes
|
60
|
+
return nil unless self.class === message
|
61
|
+
|
62
|
+
self.path <=> message.path
|
63
|
+
end
|
64
|
+
|
65
|
+
# Returns the class' serializer
|
66
|
+
def serializer
|
67
|
+
self.class.serializer
|
68
|
+
end
|
69
|
+
|
70
|
+
# Writes data to disk. Can only be called on messages instantiated without
|
71
|
+
# a key (which haven't been written to disk). After successfully writing
|
72
|
+
# to disk, rename the message to the new dir
|
50
73
|
#
|
51
74
|
# Returns the message's key
|
52
|
-
def write(
|
75
|
+
def write(data)
|
53
76
|
raise "Can only write to messages in tmp" unless :tmp == @dir
|
77
|
+
|
54
78
|
# Write out contents to tmp
|
55
|
-
|
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
|
61
|
-
end
|
79
|
+
serializer.dump(data, path)
|
62
80
|
|
63
|
-
# Rename to new
|
64
81
|
rename(:new)
|
65
82
|
end
|
66
83
|
|
@@ -112,6 +129,11 @@ class Maildir::Message
|
|
112
129
|
File.join(@maildir.path, key)
|
113
130
|
end
|
114
131
|
|
132
|
+
# Returns the message's data from disk
|
133
|
+
def data
|
134
|
+
serializer.load(path)
|
135
|
+
end
|
136
|
+
|
115
137
|
# Deletes the message path and freezes the message object
|
116
138
|
def destroy
|
117
139
|
File.delete(path)
|
@@ -119,6 +141,7 @@ class Maildir::Message
|
|
119
141
|
end
|
120
142
|
|
121
143
|
protected
|
144
|
+
|
122
145
|
# Sets dir, unique_name, and info based on the key
|
123
146
|
def parse_key(key)
|
124
147
|
@dir, filename = key.split(File::SEPARATOR)
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Maildir::Serializer
|
2
|
+
# The Maildir::Serializer::Base class reads & writes data to disk as a
|
3
|
+
# string. Other serializers (e.g. Maildir::Serializer::Mail) can extend this
|
4
|
+
# class to do some pre- and post-processing of the string.
|
5
|
+
#
|
6
|
+
# The Serializer API has two methods:
|
7
|
+
# load(path) # => returns data
|
8
|
+
# dump(data, path) # => returns number of bytes written
|
9
|
+
class Base
|
10
|
+
# Reads the file at path. Returns the contents of path.
|
11
|
+
def load(path)
|
12
|
+
File.read(path)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Writes data to path. Returns number of bytes written.
|
16
|
+
def dump(data, path)
|
17
|
+
File.open(path, "w") {|file| file.write(data)}
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'json'
|
2
|
+
# Serialize messages as JSON
|
3
|
+
class Maildir::Serializer::JSON < Maildir::Serializer::Base
|
4
|
+
# Read data from path and parse it as JSON.
|
5
|
+
def load(path)
|
6
|
+
::JSON.load(super(path))
|
7
|
+
end
|
8
|
+
|
9
|
+
# Dump data as JSON and writes it to path.
|
10
|
+
def dump(data, path)
|
11
|
+
super(data.to_json, path)
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'mail'
|
2
|
+
# Serialize messages as a ruby Mail object
|
3
|
+
class Maildir::Serializer::Mail < Maildir::Serializer::Base
|
4
|
+
# Build a new Mail object from the data at path.
|
5
|
+
def load(path)
|
6
|
+
::Mail.new(super(path))
|
7
|
+
end
|
8
|
+
|
9
|
+
# Write data to path as a Mail message.
|
10
|
+
def dump(data, path)
|
11
|
+
super(data.to_s, path)
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# Serialize messages as Marshalled ruby objects
|
2
|
+
class Maildir::Serializer::Marshal < Maildir::Serializer::Base
|
3
|
+
# Read data from path and unmarshal it.
|
4
|
+
def load(path)
|
5
|
+
::Marshal.load(super(path))
|
6
|
+
end
|
7
|
+
|
8
|
+
# Marshal data and write it to path.
|
9
|
+
def dump(data, path)
|
10
|
+
super(::Marshal.dump(data), path)
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
# Serialize messages as YAML
|
3
|
+
class Maildir::Serializer::YAML < Maildir::Serializer::Base
|
4
|
+
# Read data from path and parse it as YAML.
|
5
|
+
def load(path)
|
6
|
+
::YAML.load(super(path))
|
7
|
+
end
|
8
|
+
|
9
|
+
# Dump data as YAML and writes it to path.
|
10
|
+
def dump(data, path)
|
11
|
+
super(data.to_yaml, path)
|
12
|
+
end
|
13
|
+
end
|
data/lib/maildir.rb
CHANGED
@@ -1,19 +1,28 @@
|
|
1
|
-
require 'fileutils'
|
1
|
+
require 'fileutils' # For create_directories
|
2
2
|
class Maildir
|
3
3
|
|
4
4
|
SUBDIRS = [:tmp, :new, :cur].freeze
|
5
5
|
READABLE_DIRS = SUBDIRS.reject{|s| :tmp == s}.freeze
|
6
6
|
|
7
|
+
include Comparable
|
8
|
+
|
7
9
|
attr_reader :path
|
10
|
+
|
11
|
+
# Create a new maildir at +path+. If +create+ is true, will ensure that the
|
12
|
+
# required subdirectories exist.
|
8
13
|
def initialize(path, create = true)
|
9
14
|
@path = File.join(path, '/') # Ensure path has a trailing slash
|
10
|
-
|
15
|
+
create_directories if create
|
11
16
|
end
|
12
17
|
|
13
|
-
#
|
14
|
-
|
15
|
-
|
16
|
-
|
18
|
+
# Compare maildirs by their paths.
|
19
|
+
# If maildir is a different class, return nil.
|
20
|
+
# Otherwise, return 1, 0, or -1.
|
21
|
+
def <=>(maildir)
|
22
|
+
# Return nil if comparing different classes
|
23
|
+
return nil unless self.class === maildir
|
24
|
+
|
25
|
+
self.path <=> maildir.path
|
17
26
|
end
|
18
27
|
|
19
28
|
# define methods tmp_path, new_path, & cur_path
|
@@ -26,31 +35,47 @@ class Maildir
|
|
26
35
|
# Ensure subdirectories exist. This can safely be called multiple times, but
|
27
36
|
# must hit the disk. Avoid calling this if you're certain the directories
|
28
37
|
# exist.
|
29
|
-
def
|
38
|
+
def create_directories
|
30
39
|
SUBDIRS.each do |subdir|
|
31
40
|
FileUtils.mkdir_p(self.send("#{subdir}_path"))
|
32
41
|
end
|
33
42
|
end
|
34
43
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
44
|
+
# Returns an arry of messages from :new or :cur directory, sorted by key.
|
45
|
+
# If options[:limit] is specified, returns only so many keys.
|
46
|
+
#
|
47
|
+
# E.g.
|
48
|
+
# maildir.list(:new) # => all new messages
|
49
|
+
# maildir.list(:cur, :limit => 10) # => 10 oldest messages in cur
|
50
|
+
def list(new_or_cur, options = {})
|
40
51
|
new_or_cur = new_or_cur.to_sym
|
41
52
|
unless [:new, :cur].include? new_or_cur
|
42
53
|
raise ArgumentError, "first arg must be new or cur"
|
43
54
|
end
|
44
|
-
|
55
|
+
|
56
|
+
keys = get_dir_listing(new_or_cur)
|
57
|
+
|
58
|
+
# Map keys to message objects
|
59
|
+
messages = keys.map{|key| get(key)}
|
60
|
+
|
61
|
+
# Sort the messages (effectively chronological order)
|
62
|
+
# TODO: make sorting configurable
|
63
|
+
messages.sort!
|
64
|
+
|
65
|
+
# Apply the limit
|
66
|
+
if limit = options[:limit]
|
67
|
+
messages = messages[0,limit]
|
68
|
+
end
|
69
|
+
messages
|
45
70
|
end
|
46
71
|
|
47
|
-
# Writes
|
72
|
+
# Writes data object out as a new message. Returns a Maildir::Message. See
|
48
73
|
# Maildir::Message.create for more.
|
49
|
-
def
|
50
|
-
Maildir::Message.create(self,
|
74
|
+
def add(data)
|
75
|
+
Maildir::Message.create(self, data)
|
51
76
|
end
|
52
77
|
|
53
|
-
def
|
78
|
+
def get(key)
|
54
79
|
Maildir::Message.new(self, key)
|
55
80
|
end
|
56
81
|
|
@@ -66,6 +91,6 @@ class Maildir
|
|
66
91
|
end
|
67
92
|
end
|
68
93
|
end
|
69
|
-
|
70
94
|
require 'maildir/unique_name'
|
95
|
+
require 'maildir/serializer/base'
|
71
96
|
require 'maildir/message'
|
data/maildir.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{maildir}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.3.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Aaron Suggs"]
|
12
|
-
s.date = %q{2010-01-
|
12
|
+
s.date = %q{2010-01-08}
|
13
13
|
s.description = %q{A ruby library for reading and writing arbitrary messages in DJB's maildir format}
|
14
14
|
s.email = %q{aaron@ktheory.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -19,18 +19,23 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.files = [
|
20
20
|
".gitignore",
|
21
21
|
"LICENSE",
|
22
|
-
"NOTES.txt",
|
23
22
|
"README.rdoc",
|
24
23
|
"Rakefile",
|
25
24
|
"VERSION",
|
26
25
|
"benchmarks/runner",
|
27
26
|
"lib/maildir.rb",
|
28
27
|
"lib/maildir/message.rb",
|
28
|
+
"lib/maildir/serializer/base.rb",
|
29
|
+
"lib/maildir/serializer/json.rb",
|
30
|
+
"lib/maildir/serializer/mail.rb",
|
31
|
+
"lib/maildir/serializer/marshal.rb",
|
32
|
+
"lib/maildir/serializer/yaml.rb",
|
29
33
|
"lib/maildir/unique_name.rb",
|
30
34
|
"maildir.gemspec",
|
31
35
|
"test/test_helper.rb",
|
32
36
|
"test/test_maildir.rb",
|
33
37
|
"test/test_message.rb",
|
38
|
+
"test/test_serializers.rb",
|
34
39
|
"test/test_unique_name.rb"
|
35
40
|
]
|
36
41
|
s.homepage = %q{http://github.com/ktheory/maildir}
|
@@ -42,6 +47,7 @@ Gem::Specification.new do |s|
|
|
42
47
|
"test/test_helper.rb",
|
43
48
|
"test/test_maildir.rb",
|
44
49
|
"test/test_message.rb",
|
50
|
+
"test/test_serializers.rb",
|
45
51
|
"test/test_unique_name.rb"
|
46
52
|
]
|
47
53
|
|
@@ -50,12 +56,18 @@ Gem::Specification.new do |s|
|
|
50
56
|
s.specification_version = 3
|
51
57
|
|
52
58
|
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
53
|
-
s.add_development_dependency(%q<
|
59
|
+
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
60
|
+
s.add_development_dependency(%q<mail>, [">= 0"])
|
61
|
+
s.add_development_dependency(%q<json>, [">= 0"])
|
54
62
|
else
|
55
|
-
s.add_dependency(%q<
|
63
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
64
|
+
s.add_dependency(%q<mail>, [">= 0"])
|
65
|
+
s.add_dependency(%q<json>, [">= 0"])
|
56
66
|
end
|
57
67
|
else
|
58
|
-
s.add_dependency(%q<
|
68
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
69
|
+
s.add_dependency(%q<mail>, [">= 0"])
|
70
|
+
s.add_dependency(%q<json>, [">= 0"])
|
59
71
|
end
|
60
72
|
end
|
61
73
|
|
data/test/test_maildir.rb
CHANGED
@@ -2,11 +2,6 @@ require 'test_helper'
|
|
2
2
|
class TestMaildir < Test::Unit::TestCase
|
3
3
|
|
4
4
|
context "A maildir" do
|
5
|
-
|
6
|
-
should "be initialized" do
|
7
|
-
assert temp_maildir
|
8
|
-
end
|
9
|
-
|
10
5
|
should "have a path" do
|
11
6
|
assert_not_empty temp_maildir.path
|
12
7
|
end
|
@@ -36,14 +31,21 @@ class TestMaildir < Test::Unit::TestCase
|
|
36
31
|
|
37
32
|
context "with a message" do
|
38
33
|
setup do
|
39
|
-
@
|
34
|
+
@message = temp_maildir.add("")
|
40
35
|
end
|
41
36
|
|
42
37
|
should "list the message in it's keys" do
|
43
|
-
|
44
|
-
assert_equal
|
38
|
+
messages = temp_maildir.list(:new)
|
39
|
+
assert_equal messages, [@message]
|
45
40
|
end
|
46
41
|
end
|
47
42
|
end
|
48
43
|
|
44
|
+
context "Maildirs with the same path" do
|
45
|
+
should "be identical" do
|
46
|
+
another_maildir = Maildir.new(temp_maildir.path, false)
|
47
|
+
assert_equal temp_maildir, another_maildir
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
49
51
|
end
|
data/test/test_message.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
class TestMessage < Test::Unit::TestCase
|
3
3
|
|
4
|
-
|
5
4
|
context "An new, unwritten message" do
|
6
5
|
setup do
|
7
6
|
@message = Maildir::Message.new(temp_maildir)
|
@@ -66,18 +65,7 @@ class TestMessage < Test::Unit::TestCase
|
|
66
65
|
end
|
67
66
|
|
68
67
|
should "have the correct data" do
|
69
|
-
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
context "when written with an IO object" do
|
74
|
-
setup do
|
75
|
-
@data = "foo\n"
|
76
|
-
@message.write(StringIO.open(@data))
|
77
|
-
end
|
78
|
-
|
79
|
-
should "have the correct data" do
|
80
|
-
assert @data == File.open(@message.path).read
|
68
|
+
assert_equal @data, @message.data
|
81
69
|
end
|
82
70
|
end
|
83
71
|
end
|
@@ -89,7 +77,7 @@ class TestMessage < Test::Unit::TestCase
|
|
89
77
|
end
|
90
78
|
|
91
79
|
should "have the correct data" do
|
92
|
-
|
80
|
+
assert_equal @data, @message.data
|
93
81
|
end
|
94
82
|
|
95
83
|
context "when processed" do
|
@@ -158,4 +146,24 @@ class TestMessage < Test::Unit::TestCase
|
|
158
146
|
end
|
159
147
|
end
|
160
148
|
end
|
149
|
+
|
150
|
+
context "Messages" do
|
151
|
+
setup do
|
152
|
+
@message1 = temp_maildir.add("")
|
153
|
+
end
|
154
|
+
|
155
|
+
should "differ" do
|
156
|
+
@message2 = Maildir::Message.new(temp_maildir)
|
157
|
+
assert_equal -1, @message1 <=> @message2
|
158
|
+
assert_equal 1, @message2 <=> @message1
|
159
|
+
assert_not_equal @message1, @message2
|
160
|
+
|
161
|
+
end
|
162
|
+
|
163
|
+
should "be identical" do
|
164
|
+
another_message1 = temp_maildir.get(@message1.key)
|
165
|
+
assert_equal @message1, another_message1
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
161
169
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
# Require all the serializers
|
4
|
+
path = File.join(File.dirname(__FILE__), "..","lib","maildir","serializer","*")
|
5
|
+
Dir.glob(path).each do |file|
|
6
|
+
require file
|
7
|
+
end
|
8
|
+
|
9
|
+
class TestSerializers < Test::Unit::TestCase
|
10
|
+
|
11
|
+
serializers = [
|
12
|
+
[Maildir::Serializer::Mail, lambda {|data| Mail.new(data).to_s}],
|
13
|
+
[Maildir::Serializer::Marshal, lambda {|data| Marshal.dump(data)}],
|
14
|
+
[Maildir::Serializer::JSON, lambda {|data| JSON.dump(data)}],
|
15
|
+
[Maildir::Serializer::YAML, lambda {|data| YAML.dump(data)}]
|
16
|
+
]
|
17
|
+
|
18
|
+
serializers.each do |klass, dumper|
|
19
|
+
context "A message serialized with #{klass}" do
|
20
|
+
setup do
|
21
|
+
@data = case klass.new
|
22
|
+
when Maildir::Serializer::Mail
|
23
|
+
Mail.new
|
24
|
+
else
|
25
|
+
# Test a few common data structures
|
26
|
+
[1, nil, {"foo" => true}]
|
27
|
+
end
|
28
|
+
|
29
|
+
# Set the message serializer
|
30
|
+
Maildir::Message.serializer = klass.new
|
31
|
+
@message = temp_maildir.add(@data)
|
32
|
+
end
|
33
|
+
|
34
|
+
should "have the correct data" do
|
35
|
+
assert_equal @data, @message.data
|
36
|
+
end
|
37
|
+
|
38
|
+
should "have serialized data on disk" do
|
39
|
+
assert_equal dumper.call(@data), File.read(@message.path)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
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.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aaron Suggs
|
@@ -9,11 +9,31 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-01-
|
12
|
+
date: 2010-01-08 00:00:00 -05:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
|
-
name:
|
16
|
+
name: shoulda
|
17
|
+
type: :development
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: mail
|
27
|
+
type: :development
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: "0"
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: json
|
17
37
|
type: :development
|
18
38
|
version_requirement:
|
19
39
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -34,18 +54,23 @@ extra_rdoc_files:
|
|
34
54
|
files:
|
35
55
|
- .gitignore
|
36
56
|
- LICENSE
|
37
|
-
- NOTES.txt
|
38
57
|
- README.rdoc
|
39
58
|
- Rakefile
|
40
59
|
- VERSION
|
41
60
|
- benchmarks/runner
|
42
61
|
- lib/maildir.rb
|
43
62
|
- lib/maildir/message.rb
|
63
|
+
- lib/maildir/serializer/base.rb
|
64
|
+
- lib/maildir/serializer/json.rb
|
65
|
+
- lib/maildir/serializer/mail.rb
|
66
|
+
- lib/maildir/serializer/marshal.rb
|
67
|
+
- lib/maildir/serializer/yaml.rb
|
44
68
|
- lib/maildir/unique_name.rb
|
45
69
|
- maildir.gemspec
|
46
70
|
- test/test_helper.rb
|
47
71
|
- test/test_maildir.rb
|
48
72
|
- test/test_message.rb
|
73
|
+
- test/test_serializers.rb
|
49
74
|
- test/test_unique_name.rb
|
50
75
|
has_rdoc: true
|
51
76
|
homepage: http://github.com/ktheory/maildir
|
@@ -79,4 +104,5 @@ test_files:
|
|
79
104
|
- test/test_helper.rb
|
80
105
|
- test/test_maildir.rb
|
81
106
|
- test/test_message.rb
|
107
|
+
- test/test_serializers.rb
|
82
108
|
- test/test_unique_name.rb
|
data/NOTES.txt
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
md = Maildir.new(path)
|
2
|
-
|
3
|
-
md.add(data) => message
|
4
|
-
|
5
|
-
md.list_new => array of messages
|
6
|
-
|
7
|
-
md.list_cur => array of messages
|
8
|
-
|
9
|
-
message.process(flags) => moves message from new to cur and adds flags
|
10
|
-
|
11
|
-
message.flags
|
12
|
-
message.flags=
|
13
|
-
message.add_flag
|
14
|
-
message.remove_flag
|
15
|
-
|
16
|
-
message.info
|
17
|
-
message.info=
|