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 ADDED
@@ -0,0 +1,2 @@
1
+ pkg/*
2
+ benchmarks/scratch.rb
data/Rakefile CHANGED
@@ -22,3 +22,8 @@ begin
22
22
  rescue LoadError
23
23
  puts "Jeweler not available. Install it with: sudo gem install jeweler"
24
24
  end
25
+
26
+ desc "Run benchmarks"
27
+ task :bench do
28
+ load File.join(File.dirname(__FILE__), "benchmarks", "runner")
29
+ end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.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
- $: << File.join(File.dirname(__FILE__), '..', 'lib')
4
- require 'maildir'
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 IO object out as a new message. See Maildir::Message.create for
47
- # more.
48
- def add_message(io)
49
- Maildir::Message.create(self, io)
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
- results.map!{|message_path| message_path.sub!(self.path, '')}
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
 
@@ -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 io. The message is
9
- # first written to the tmp dir, then moved to new. This is a shortcut for:
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(io)
12
- def create(maildir, io)
12
+ # message.write(string_or_io)
13
+ def create(maildir, string_or_io)
13
14
  message = self.new(maildir)
14
- message.write(io)
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
- # Message.new(maildir)
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
- # Instantiate an existing message:
25
- # Message.new(maildir, key)
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
- raise ArgumentError, "State must be in #{Maildir::SUBDIRS.inspect}" unless Maildir::SUBDIRS.include? dir
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 io to disk. Can only be called on messages instantiated without a
42
- # key (which haven't been written to disk). If the io object has a 'read'
43
- # method, calls io.read. Otherwise, calls io.to_s.
44
- def write(io)
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
- file.puts io.respond_to?(:read) ? io.read : io.to_s
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
- def old_path
100
- File.join(@maildir.path, old_key)
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 in key
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.1.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: 2009-12-05 00:00:00 -05:00
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