Multiple changes.
- Remove the runtime dependency on rake-compiler. - Use #rb_str_new instead of #rb_str_new2, the hash character array isn't null terminated. - Add various safeguards for object instantiations. - Remove the 'threaded' options for messages, folding them into 'archived'. If archiving is enabled, so is threading. - Return nil for lookups from the list object instead of raising exceptions. - Open subject indexes with the proper encodings (thanks Michael Granger!) - Allow touching and unlinking files to operate on multiple paths at once, within a single safety() wrap.
This commit is contained in:
parent
c99bdfe747
commit
3871084daa
17 changed files with 257 additions and 110 deletions
|
|
@ -2,3 +2,4 @@ Session.vim
|
|||
pkg/*
|
||||
docs/*
|
||||
tmp/*
|
||||
lib/ezmlm/hash.so
|
||||
|
|
|
|||
|
|
@ -37,10 +37,6 @@ be a generic interface for parsing and browsing list content.
|
|||
|
||||
$ gem install ezmlm
|
||||
|
||||
## Usage
|
||||
|
||||
....
|
||||
|
||||
|
||||
## TODO
|
||||
|
||||
|
|
|
|||
2
Rakefile
2
Rakefile
|
|
@ -59,7 +59,7 @@ environment.)
|
|||
s.required_ruby_version = '>= 2.1'
|
||||
|
||||
s.add_dependency 'mail', "~> 2.6"
|
||||
s.add_dependency 'rake-compiler', "~> 1.0"
|
||||
s.add_development_dependency 'rake-compiler', "~> 1.0"
|
||||
end
|
||||
|
||||
Gem::PackageTask.new( spec ) do |pkg|
|
||||
|
|
|
|||
126
USAGE.md
Normal file
126
USAGE.md
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
|
||||
Usage
|
||||
=======
|
||||
|
||||
Here's a quick rundown of how to use this library. For specifics, see
|
||||
the generated RDoc.
|
||||
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
|
||||
*Print the list address for all lists in a directory*:
|
||||
|
||||
Ezmlm.each_list( '/lists' ) do |list|
|
||||
puts list.address
|
||||
end
|
||||
|
||||
|
||||
*Check if I'm subscribed to a list, and if so, unsubscribe*:
|
||||
|
||||
(You don't really have to check first, subscribe and unsubscribe are
|
||||
idempotent.)
|
||||
|
||||
list = Ezmlm::List.new( '/lists/waffle-lovers' )
|
||||
|
||||
if list.include?( 'mahlon@martini.nu' )
|
||||
list.unsubscribe( 'mahlon@martini.nu' )
|
||||
end
|
||||
|
||||
puts "The list now has %d subscribers!" % [ list.subscribers.size ]
|
||||
|
||||
|
||||
*Iterate over the subscriber list*:
|
||||
|
||||
list.subscribers.each do |subscriber|
|
||||
# ...
|
||||
end
|
||||
|
||||
|
||||
*Make the list moderated, and add a moderator*:
|
||||
|
||||
list.moderated = true
|
||||
list.add_moderator( 'mahlon@martini.nu' )
|
||||
list.moderated? #=> true
|
||||
|
||||
All other list behavior tunables operate in a similar fashion, see RDoc
|
||||
for details.
|
||||
|
||||
|
||||
*Archiving!*
|
||||
|
||||
All of the archival pieces take advantage of Ezmlm-IDX extensions.
|
||||
If you want to use these features, you'll want to enable archiving
|
||||
and indexing for your lists, using the -a and -i flags to ezmlm-make.
|
||||
(Enabling archiving with this library also enables indexing and thread
|
||||
indexes, I assume that since you're using ezmlm-idx, you want these
|
||||
enhancements!)
|
||||
|
||||
list.archived? #=> false
|
||||
list.archived = true
|
||||
list.archived? #=> true
|
||||
|
||||
If your list(s) already had archiving enabled (the default to
|
||||
ezmlm-make) but not indexing, you can manually run ezmlm-archive to
|
||||
rebuild the necessary files - afterwards, they are kept up to date
|
||||
automatically.
|
||||
|
||||
|
||||
*How many messages are in the archive?*:
|
||||
|
||||
list.message_count #=> 123
|
||||
|
||||
|
||||
*Fetch message number 100 from the archive*:
|
||||
|
||||
message = list.message( 100 ) or abort "No such message."
|
||||
|
||||
puts message.subject
|
||||
puts message.body.to_s # Print just the body of the message.
|
||||
puts message.to_s # Print the entire, unparsed message.
|
||||
|
||||
thread = message.thread # Returns an Ezmlm::List::Thread object
|
||||
author = message.author # Returns an Ezmlm::List::Author object
|
||||
|
||||
As a general rule, methods called on the Ezmlm::List object return nil
|
||||
if they are unable to perform the requested task. Instantiating the
|
||||
underlying objects directly raise with a specific error. The following
|
||||
are equivalent, but behave differently:
|
||||
|
||||
message = list.message( 10000 ) # nonexistent message, returns nil
|
||||
message = Ezmlm::List::Message.new( list, 10000 ) # Raises a RuntimeError
|
||||
|
||||
Message objects act as "Mail" objects from the excellent library from
|
||||
Mikel Lindsaar (https://github.com/mikel/mail). See its documentation
|
||||
for specifics.
|
||||
|
||||
|
||||
*Iterate over messages in a specific thread*:
|
||||
|
||||
Messages know what thread they belong to. Once you have a thread object
|
||||
from a message, it is an enumerable. Iterate or sort on it using
|
||||
standard Ruby methods.
|
||||
|
||||
thread.each do |message|
|
||||
# ...
|
||||
end
|
||||
|
||||
Threads are also aware of who participated in the conversation, via the
|
||||
'authors' and 'each_author' methods.
|
||||
|
||||
|
||||
*Iterate over messages from a specific author:*
|
||||
|
||||
Messages know who authored them. Once you have an author object from a
|
||||
message, it is an enumerable. Iterate or sort on it using standard Ruby
|
||||
methods.
|
||||
|
||||
author.each do |message|
|
||||
# ...
|
||||
end
|
||||
|
||||
An Author object is also aware of all threads the author participated
|
||||
in, via the 'threads' and 'each_thread' methods.
|
||||
|
||||
|
||||
|
|
@ -148,12 +148,12 @@ address( VALUE klass, VALUE email ) {
|
|||
|
||||
Check_Type( email, T_STRING );
|
||||
|
||||
email = rb_str_plus( rb_str_new2("<"), email);
|
||||
email = rb_str_plus( rb_str_new2("<"), email );
|
||||
input = StringValueCStr( email );
|
||||
|
||||
makehash( input, strlen(input), hash );
|
||||
|
||||
return rb_str_new2( hash );
|
||||
return rb_str_new( hash, 20 );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
11
lib/ezmlm.rb
11
lib/ezmlm.rb
|
|
@ -1,8 +1,15 @@
|
|||
#!/usr/bin/ruby
|
||||
# vim: set nosta noet ts=4 sw=4:
|
||||
#
|
||||
|
||||
|
||||
# A Ruby interface to the ezmlm-idx mailing list system.
|
||||
#
|
||||
# Ezmlm.find_directories( '/lists' ) #=> [ Ezmlm::List, Ezmlm::List ]
|
||||
#
|
||||
# Ezmlm.each_list( '/lists' ) do |list|
|
||||
# puts "\"%s\" <%s>" % [ list.name, list.address ]
|
||||
# end
|
||||
#
|
||||
#
|
||||
# == Version
|
||||
#
|
||||
# $Id$
|
||||
|
|
|
|||
|
|
@ -1,8 +1,12 @@
|
|||
#!/usr/bin/ruby
|
||||
# vim: set nosta noet ts=4 sw=4:
|
||||
#
|
||||
|
||||
|
||||
# A Ruby interface to a single Ezmlm-idx mailing list directory.
|
||||
#
|
||||
# list = Ezmlm::List.new( '/path/to/listdir' )
|
||||
#
|
||||
#
|
||||
# == Version
|
||||
#
|
||||
# $Id$
|
||||
|
|
@ -28,6 +32,9 @@ class Ezmlm::List
|
|||
###
|
||||
def initialize( listdir )
|
||||
listdir = Pathname.new( listdir ) unless listdir.is_a?( Pathname )
|
||||
unless listdir.directory? && ( listdir + 'mailinglist' ).exist?
|
||||
raise ArgumentError, "%p doesn't appear to be an ezmlm-idx list." % [ listdir.to_s ]
|
||||
end
|
||||
@listdir = listdir
|
||||
end
|
||||
|
||||
|
|
@ -219,27 +226,6 @@ class Ezmlm::List
|
|||
end
|
||||
|
||||
|
||||
### Returns +true+ if message threading is enabled.
|
||||
###
|
||||
def threaded?
|
||||
return ( self.listdir + 'threaded' ).exist?
|
||||
end
|
||||
|
||||
### Disable or enable message threading.
|
||||
###
|
||||
### This automatically builds message indexes and thread
|
||||
### information on an incoming message.
|
||||
###
|
||||
def threaded=( enable=true )
|
||||
if enable
|
||||
self.touch( 'threaded' )
|
||||
else
|
||||
self.unlink( 'threaded' )
|
||||
end
|
||||
end
|
||||
alias_method :threaded, :threaded=
|
||||
|
||||
|
||||
### Returns +true+ if the list is configured to respond
|
||||
### to remote management requests.
|
||||
###
|
||||
|
|
@ -380,21 +366,23 @@ class Ezmlm::List
|
|||
### Returns +true+ if message archival is enabled.
|
||||
###
|
||||
def archived?
|
||||
return ( self.listdir + 'archived' ).exist? || ( self.listdir + 'indexed' ).exist?
|
||||
test = %w[ archived indexed threaded ].each_with_object( [] ) do |f, acc|
|
||||
acc << self.listdir + f
|
||||
end
|
||||
|
||||
return test.all?( &:exist? )
|
||||
end
|
||||
|
||||
### Disable or enable message archiving (and indexing.)
|
||||
### Disable or enable message archiving (and indexing/threading.)
|
||||
###
|
||||
def archive=( enable=true )
|
||||
def archived=( enable=true )
|
||||
if enable
|
||||
self.touch( 'archived' )
|
||||
self.touch( 'indexed' )
|
||||
self.touch( 'archived', 'indexed', 'threaded' )
|
||||
else
|
||||
self.unlink( 'archived' )
|
||||
self.unlink( 'indexed' )
|
||||
self.unlink( 'archived', 'indexed', 'threaded' )
|
||||
end
|
||||
end
|
||||
alias_method :archive, :archive=
|
||||
alias_method :archived, :archived=
|
||||
|
||||
### Returns +true+ if the message archive is accessible only to
|
||||
### moderators.
|
||||
|
|
@ -653,9 +641,8 @@ class Ezmlm::List
|
|||
### Returns an individual message if archiving was enabled.
|
||||
###
|
||||
def message( message_id )
|
||||
raise "Archiving is not enabled." unless self.archived?
|
||||
raise "Message archive is empty." if self.message_count.zero?
|
||||
return Ezmlm::List::Message.new( self, message_id )
|
||||
return Ezmlm::List::Message.new( self, message_id ) rescue nil
|
||||
end
|
||||
|
||||
### Lazy load each message ID as a Ezmlm::List::Message,
|
||||
|
|
@ -671,8 +658,7 @@ class Ezmlm::List
|
|||
### Return a Thread object for the given +thread_id+.
|
||||
###
|
||||
def thread( thread_id )
|
||||
raise "Archiving is not enabled." unless self.archived?
|
||||
return Ezmlm::List::Thread.new( self, thread_id )
|
||||
return Ezmlm::List::Thread.new( self, thread_id ) rescue nil
|
||||
end
|
||||
|
||||
|
||||
|
|
@ -680,9 +666,8 @@ class Ezmlm::List
|
|||
### could also be an email address.
|
||||
###
|
||||
def author( author_id )
|
||||
raise "Archiving is not enabled." unless self.archived?
|
||||
author_id = Ezmlm::Hash.address(author_id) if author_id.index( '@' )
|
||||
return Ezmlm::List::Author.new( self, author_id )
|
||||
return Ezmlm::List::Author.new( self, author_id ) rescue nil
|
||||
end
|
||||
|
||||
|
||||
|
|
@ -700,22 +685,25 @@ class Ezmlm::List
|
|||
index = archivedir + dir.to_s + 'index'
|
||||
next unless index.exist?
|
||||
|
||||
index.each_line.lazy.slice_before( /^\d+:/ ).each do |message|
|
||||
match = message[0].match( /^(?<message_id>\d+): (?<thread_id>\w+)/ )
|
||||
next unless match
|
||||
thread_id = match[ :thread_id ]
|
||||
index.open( 'r', encoding: Encoding::ISO8859_1 ) do |fh|
|
||||
fh.each_line.lazy.slice_before( /^\d+:/ ).each do |message|
|
||||
|
||||
match = message[1].match( /^(?<date>[^;]+);(?<author_id>\w+) / )
|
||||
next unless match
|
||||
author_id = match[ :author_id ]
|
||||
date = match[ :date ]
|
||||
match = message[0].match( /^(?<message_id>\d+): (?<thread_id>\w+)/ )
|
||||
next unless match
|
||||
thread_id = match[ :thread_id ]
|
||||
|
||||
metadata = {
|
||||
date: Time.parse( date ),
|
||||
thread: thread_id,
|
||||
author: author_id
|
||||
}
|
||||
acc << metadata
|
||||
match = message[1].match( /^(?<date>[^;]+);(?<author_id>\w+) / )
|
||||
next unless match
|
||||
author_id = match[ :author_id ]
|
||||
date = match[ :date ]
|
||||
|
||||
metadata = {
|
||||
date: Time.parse( date ),
|
||||
thread: thread_id,
|
||||
author: author_id
|
||||
}
|
||||
acc << metadata
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -757,18 +745,25 @@ class Ezmlm::List
|
|||
|
||||
### Simply create an empty file, safely.
|
||||
###
|
||||
def touch( file )
|
||||
self.write( file ) {}
|
||||
def touch( *file )
|
||||
self.with_safety do
|
||||
Array( file ).flatten.each do |f|
|
||||
f = self.listdir + f unless f.is_a?( Pathname )
|
||||
f.open( 'w' ) {}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
### Delete +file+ safely.
|
||||
###
|
||||
def unlink( file )
|
||||
file = self.listdir + file unless file.is_a?( Pathname )
|
||||
return unless file.exist?
|
||||
def unlink( *file )
|
||||
self.with_safety do
|
||||
file.unlink
|
||||
Array( file ).flatten.each do |f|
|
||||
f = self.listdir + f unless f.is_a?( Pathname )
|
||||
next unless f.exist?
|
||||
f.unlink
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#!/usr/bin/ruby
|
||||
# vim: set nosta noet ts=4 sw=4:
|
||||
#
|
||||
|
||||
|
||||
# A collection of messages authored from a unique user.
|
||||
#
|
||||
# Note that Ezmlm uses the "real name" part of an address
|
||||
|
|
@ -27,12 +28,12 @@ class Ezmlm::List::Author
|
|||
include Enumerable
|
||||
|
||||
### Instantiate a new list of messages given
|
||||
### a +list+ and a +author_id+.
|
||||
### a +list+ and an +author_id+.
|
||||
###
|
||||
def initialize( list, author_id )
|
||||
raise ArgumentError, "Unknown list object." unless list.respond_to?( :listdir )
|
||||
raise ArgumentError, "Malformed Author ID." unless author_id =~ /^\w{20}$/
|
||||
raise "Thread indexing is not enabled." unless list.threaded?
|
||||
raise "Archiving is not enabled." unless list.archived?
|
||||
|
||||
@list = list
|
||||
@id = author_id
|
||||
|
|
@ -67,6 +68,7 @@ class Ezmlm::List::Author
|
|||
yield Ezmlm::List::Message.new( self.list, id )
|
||||
end
|
||||
end
|
||||
alias_method :each_message, :each
|
||||
|
||||
|
||||
### Lazy load each thread ID as a Ezmlm::List::Thread, yielding it to the block.
|
||||
|
|
@ -92,13 +94,15 @@ class Ezmlm::List::Author
|
|||
path = self.author_path
|
||||
raise "Unknown author: %p" % [ self.id ] unless path.exist?
|
||||
|
||||
path.each_line.with_index do |line, i|
|
||||
if i.zero?
|
||||
@name = line.match( /^\w+ (.+)/ )[1]
|
||||
else
|
||||
match = line.match( /^(\d+):\d+:(\w+) / ) or next
|
||||
self.messages << match[1].to_i
|
||||
self.threads << match[2]
|
||||
path.open( 'r', encoding: Encoding::ISO8859_1 ) do |fh|
|
||||
fh.each_line.with_index do |line, i|
|
||||
if i.zero?
|
||||
@name = line.match( /^\w+ (.+)/ )[1]
|
||||
else
|
||||
match = line.match( /^(\d+):\d+:(\w+) / ) or next
|
||||
self.messages << match[1].to_i
|
||||
self.threads << match[2]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#!/usr/bin/ruby
|
||||
# vim: set nosta noet ts=4 sw=4:
|
||||
#
|
||||
|
||||
|
||||
# An individual list message.
|
||||
#
|
||||
# message = Ezmlm::List::Message.new( list, 24 )
|
||||
|
|
@ -31,6 +32,7 @@ class Ezmlm::List::Message
|
|||
def initialize( list, message_number=0 )
|
||||
raise ArgumentError, "Unknown list object." unless list.respond_to?( :listdir )
|
||||
raise ArgumentError, "Invalid message number (impossible)" if message_number < 1
|
||||
raise "Archiving is not enabled." unless list.archived?
|
||||
raise ArgumentError, "Invalid message number (out of list bounds)" if message_number > list.message_count
|
||||
|
||||
@list = list
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#!/usr/bin/ruby
|
||||
# vim: set nosta noet ts=4 sw=4:
|
||||
#
|
||||
|
||||
|
||||
# A collection of messages for a specific archive thread.
|
||||
#
|
||||
# thread = Ezmlm::List::Thread.new( list, 'acgcbmbmeapgpfckcdol' )
|
||||
|
|
@ -29,7 +30,7 @@ class Ezmlm::List::Thread
|
|||
def initialize( list, thread_id )
|
||||
raise ArgumentError, "Unknown list object." unless list.respond_to?( :listdir )
|
||||
raise ArgumentError, "Malformed Thread ID." unless thread_id =~ /^\w{20}$/
|
||||
raise "Thread indexing is not enabled." unless list.threaded?
|
||||
raise "Archiving is not enabled." unless list.archived?
|
||||
|
||||
@list = list
|
||||
@id = thread_id
|
||||
|
|
@ -65,6 +66,18 @@ class Ezmlm::List::Thread
|
|||
yield Ezmlm::List::Message.new( self.list, id )
|
||||
end
|
||||
end
|
||||
alias_method :each_message, :each
|
||||
|
||||
|
||||
### Lazy load each author ID as a Ezmlm::List::Author, yielding it
|
||||
### to the block.
|
||||
###
|
||||
def each_author
|
||||
self.load_thread # refresh for any thread updates since object was created
|
||||
self.authors.each do |id|
|
||||
yield Ezmlm::List::Author.new( self.list, id )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
#########
|
||||
|
|
@ -79,13 +92,15 @@ class Ezmlm::List::Thread
|
|||
path = self.thread_path
|
||||
raise "Unknown thread: %p" % [ self.id ] unless path.exist?
|
||||
|
||||
path.each_line.with_index do |line, i|
|
||||
if i.zero?
|
||||
@subject = line.match( /^\w+ (.+)/ )[1]
|
||||
else
|
||||
match = line.match( /^(\d+):\d+:(\w+) / ) or next
|
||||
self.messages << match[1].to_i
|
||||
self.authors << match[2]
|
||||
path.open( 'r', encoding: Encoding::ISO8859_1 ) do |fh|
|
||||
fh.each_line.with_index do |line, i|
|
||||
if i.zero?
|
||||
@subject = line.match( /^\w+ (.+)/ )[1]
|
||||
else
|
||||
match = line.match( /^(\d+):\d+:(\w+) / ) or next
|
||||
self.messages << match[1].to_i
|
||||
self.authors << match[2]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
7 May 2017 21:55:05 -0000;gclofnmfhpbehngoppdg Amalia Purdy
|
||||
11: bhfejoliggjidmkbclnn Parsing panel for a hard drive?????
|
||||
7 May 2017 21:55:05 -0000;decddajmifhkgodaginh Sally Pagac
|
||||
12: fbhfcpngckkjbhlfjooh Trying to override SCSI on the microchip.
|
||||
12: fbhfcpngckkjbhlfjooh Trying to override SCSIs on the microchip.
|
||||
7 May 2017 21:55:05 -0000;kdlcjeacpilheebkcbaf Wayne Friesen
|
||||
13: mipieokohgoiigideadf Generating circuit for a application?????
|
||||
7 May 2017 21:55:05 -0000;ojjhjlapnejjlbcplabi Jena Smitham
|
||||
|
|
|
|||
1
spec/data/testlist/mailinglist
Normal file
1
spec/data/testlist/mailinglist
Normal file
|
|
@ -0,0 +1 @@
|
|||
contact testlist-help@lists.laika.com; run by ezmlm
|
||||
|
|
@ -28,11 +28,11 @@ describe Ezmlm::List::Author do
|
|||
}.to raise_error( ArgumentError, /unknown list/i )
|
||||
end
|
||||
|
||||
it 'raises error if thread indexing is disabled' do
|
||||
expect( list ).to receive( :threaded? ).and_return( false )
|
||||
it 'raises error if thread archiving is disabled' do
|
||||
expect( list ).to receive( :archived? ).and_return( false )
|
||||
expect {
|
||||
described_class.new( list, author_id )
|
||||
}.to raise_error( RuntimeError, /indexing is not enabled/i )
|
||||
}.to raise_error( RuntimeError, /archiving is not enabled/i )
|
||||
end
|
||||
|
||||
it 'raises error if passed a malformed author ID' do
|
||||
|
|
@ -43,7 +43,7 @@ describe Ezmlm::List::Author do
|
|||
|
||||
it 'raises error when unable to read index file' do
|
||||
allow( list ).to receive( :listdir ).and_return( Pathname('/nope') )
|
||||
expect( list ).to receive( :threaded? ).and_return( true )
|
||||
expect( list ).to receive( :archived? ).and_return( true )
|
||||
expect {
|
||||
described_class.new( list, author_id )
|
||||
}.to raise_error( RuntimeError, /unknown author/i )
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ describe Ezmlm::List::Message do
|
|||
it 'raises error when unable to read message' do
|
||||
allow( list ).to receive( :listdir ).and_return( Pathname('/nope') )
|
||||
expect( list ).to receive( :message_count ).and_return( 1 )
|
||||
expect( list ).to receive( :archived? ).and_return( true )
|
||||
expect {
|
||||
described_class.new( list, 1 )
|
||||
}.to raise_error( RuntimeError, /unable to determine message path/i )
|
||||
|
|
|
|||
|
|
@ -29,10 +29,10 @@ describe Ezmlm::List::Thread do
|
|||
end
|
||||
|
||||
it 'raises error if thread indexing is disabled' do
|
||||
expect( list ).to receive( :threaded? ).and_return( false )
|
||||
expect( list ).to receive( :archived? ).and_return( false )
|
||||
expect {
|
||||
described_class.new( list, thread_id )
|
||||
}.to raise_error( RuntimeError, /indexing is not enabled/i )
|
||||
}.to raise_error( RuntimeError, /archiving is not enabled/i )
|
||||
end
|
||||
|
||||
it 'raises error if passed a malformed thread ID' do
|
||||
|
|
@ -43,7 +43,7 @@ describe Ezmlm::List::Thread do
|
|||
|
||||
it 'raises error when unable to read thread file' do
|
||||
allow( list ).to receive( :listdir ).and_return( Pathname('/nope') )
|
||||
expect( list ).to receive( :threaded? ).and_return( true )
|
||||
expect( list ).to receive( :archived? ).and_return( true )
|
||||
expect {
|
||||
described_class.new( list, thread_id )
|
||||
}.to raise_error( RuntimeError, /unknown thread/i )
|
||||
|
|
|
|||
|
|
@ -113,16 +113,6 @@ describe Ezmlm::List do
|
|||
end
|
||||
|
||||
|
||||
it 'returns the current threading state' do
|
||||
expect( list.threaded? ).to be_truthy
|
||||
end
|
||||
|
||||
it 'can set the threading state' do
|
||||
list.threaded = false
|
||||
expect( list.threaded? ).to be_falsey
|
||||
end
|
||||
|
||||
|
||||
it 'returns the current public/private state' do
|
||||
expect( list.public? ).to be_truthy
|
||||
expect( list.private? ).to be_falsey
|
||||
|
|
@ -200,9 +190,9 @@ describe Ezmlm::List do
|
|||
|
||||
it 'can set archival status' do
|
||||
expect( list.archived? ).to be_truthy
|
||||
list.archive = false
|
||||
list.archived = false
|
||||
expect( list.archived? ).to be_falsey
|
||||
list.archive = true
|
||||
list.archived = true
|
||||
expect( list.archived? ).to be_truthy
|
||||
end
|
||||
|
||||
|
|
@ -336,6 +326,10 @@ describe Ezmlm::List do
|
|||
expect( list.thread('cadgeokhhaieijmndokb') ).to be_a( Ezmlm::List::Thread )
|
||||
end
|
||||
|
||||
it 'returns nil when fetching an invalid thread' do
|
||||
expect( list.thread('whatever') ).to be_nil
|
||||
end
|
||||
|
||||
|
||||
it 'fetches author objects upon request' do
|
||||
expect( list.author('ojjhjlapnejjlbcplabi') ).to be_a( Ezmlm::List::Author )
|
||||
|
|
@ -346,13 +340,19 @@ describe Ezmlm::List do
|
|||
expect( list.author('yvette@example.net').name ).to eq( author.name )
|
||||
end
|
||||
|
||||
it 'returns nil when fetching an invalid author' do
|
||||
expect( list.author('whatever') ).to be_nil
|
||||
end
|
||||
|
||||
|
||||
context 'fetching messages' do
|
||||
it 'raises an error if archiving is disabled' do
|
||||
it 'returns nil if archiving is disabled' do
|
||||
expect( list ).to receive( :archived? ).and_return( false )
|
||||
expect {
|
||||
list.message( 1 )
|
||||
}.to raise_error( RuntimeError, /archiving is not enabled/i )
|
||||
expect( list.message(1) ).to be_nil
|
||||
end
|
||||
|
||||
it 'returns nil when fetching an invalid message id' do
|
||||
expect( list.message(2389234) ).to be_nil
|
||||
end
|
||||
|
||||
it 'raises an error if the message archive is empty' do
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
require 'simplecov' if ENV['COVERAGE']
|
||||
require 'rspec'
|
||||
require 'loggability/spechelpers'
|
||||
require 'fileutils'
|
||||
|
||||
require_relative '../lib/ezmlm'
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue