mailmanager 1.0.20 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2ee8afabb8d34fa2483f91bc718955eabb4a2596
4
+ data.tar.gz: 887655c56bb41103b68d1675d8acbc9ece21df5c
5
+ SHA512:
6
+ metadata.gz: b9e99831e907f9ae7f6ecc6e5f7670be7dc3ec4608ac420f9014b086af063d7d19f9d3b43b9c4063a10bd2339e17dfa841754b01214b9abc2fbcf42df9e45994
7
+ data.tar.gz: ec2036e04ed599144adcac319f0f74ea5e3e3540f6fcfeba767b1d2833e7d57ae408ea079619a5486c1dbd06a1b4fb6e8430e7e7d8a0cfc516e7bcfdeed72b7d
data/.gitignore CHANGED
@@ -5,3 +5,5 @@ doc/*
5
5
  results/*
6
6
  mailman
7
7
  coverage/*
8
+ Gemfile.lock
9
+ .ruby-version
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - "1.9.3"
4
+ - "2.1.2"
data/Changelog CHANGED
@@ -1,4 +1,10 @@
1
- Current version is 1.0.20
1
+ Current version is 1.1.0
2
+
3
+ changes since 1.0.20
4
+ - krissi added a find_member method and cleaned up some old cruft
5
+ - removed Cucumber; will re-do acceptance tests in a better way in the future
6
+ - added Travis CI build
7
+ - updated json gem dependency to 1.8.1 for Ruby 2.1.2 support
2
8
 
3
9
  changes since 1.0.19
4
10
  - none, just updated website & other README-type stuff
data/Gemfile CHANGED
@@ -1,3 +1,3 @@
1
- source :rubygems
1
+ source "https://rubygems.org/"
2
2
 
3
3
  gemspec
@@ -0,0 +1,109 @@
1
+ # MailManager
2
+
3
+ [![Build Status](https://travis-ci.org/cap10morgan/mailmanager.svg?branch=master)](https://travis-ci.org/cap10morgan/mailmanager)
4
+
5
+ MailManager is a Ruby wrapper for the GNU Mailman mailing list manager. It exposes
6
+ some administrative functions to Ruby. See the [API docs](http://rubydoc.info/github/cap10morgan/mailmanager/master/frames)
7
+ for details.
8
+ It is licensed under the New BSD License (see the LICENSE file for details).
9
+
10
+ MailManager has been tested with Mailman 2.1.14. It has NOT been tested with any
11
+ release of Mailman 3 (in alpha as of 1/19/2011). It requires Python 2.4 or higher.
12
+ Note that while Mailman itself requires Python, it can work with older versions. So
13
+ check your Python version before using this.
14
+
15
+ ## Installation
16
+
17
+ gem install mailmanager
18
+
19
+ ## Basic Usage
20
+
21
+ mm = MailManager.init('/mailman/root')
22
+ all_lists = mm.lists
23
+ foo_list = mm.get_list('foo')
24
+ new_list = mm.create_list(:name => 'newlist', :admin_email => 'me@here.com', :admin_password => 'secret')
25
+ new_list.add_member('bar@baz.com')
26
+ new_list.members -> ['bar@baz.com']
27
+
28
+ ## Hacking
29
+
30
+ Here are the basic steps for adding new features to this gem, if you're a programmer
31
+ type who likes to write code so you can code while you code... sorry.
32
+
33
+ MailManager's API currently consists of a handful of methods at the top-level
34
+ MailManager::Base class. This is where you'll find create_list and get_list. These
35
+ both return instances of MailManager::List, which is really where the action is.
36
+
37
+ MailManager::List contains the public Ruby API for interacting with Mailman's lists.
38
+ It exposes the methods and attributes of Mailman's MailList.py class, but makes
39
+ them a bit more Ruby-ish where appropriate. Not every method / attribute is
40
+ exposed, but this is where you come in, dear contributor.
41
+
42
+ The code that actually talks to Mailman is in lib/mailmanager/lib.rb.
43
+ It runs scripts in Mailman's bin directory. Anything that interacts with an
44
+ existing list uses Mailman's "withlist" script and the listproxy.py file in this
45
+ gem. If you read the docs on withlist that come with Mailman, it should be pretty
46
+ obvious what's going on there. But you don't need to understand all that to expose
47
+ new methods & attributes of MailList.py to MailManager.
48
+
49
+ Exposing new list properties works something like this:
50
+ * Look at Mailman's code in Mailman/MailList.py and see if the thing you want to
51
+ expose is a method or an attribute. You'll need to know a little Python, but not
52
+ much. Basically, a method is a callable thing and an attribute is a simple
53
+ property of the object. "AddMember" is a method, for example, while "description"
54
+ is an attribute.
55
+ * If it's a method, just write a simple method in lib/mailmanager/list.rb that
56
+ calls a method in lib.rb (just like the others do). Then go write the method
57
+ that you call in lib/mailmanager/lib.rb, using list_address or add_member as an
58
+ example (depending on whether you're writing a getter or a setter, respectively).
59
+ * All methods that interact with MailList.py instances (i.e. mailing lists) use the
60
+ withlist command, so just copy that stuff from an existing method.
61
+ * If you're exposing an attribute, then use the moderator methods as a guide.
62
+ For example, they do their own dupe checking since the MailList.py class will
63
+ let you set the attribute to whatever you want. Dangerous!
64
+ * If you're writing a setter, you have one more chore to make it work. You need the
65
+ listproxy.py code to lock the list and then save it after making your requested
66
+ change. It will do this for you if you do the following:
67
+ * For a method: Add the name of the MailList.py method to the needs_save dict and
68
+ have it return True. It should be obvious when you look at the others in there.
69
+ * For an attribute: Add the name of the attribute to the needs_save_with_arg dict.
70
+ This one is a bit different because the attr name is the same for gets and sets,
71
+ but we need to lock and save when it's a set, and we can guess that it's a set
72
+ when there is an argument passed, and a get when there is no argument. S-M-R-T
73
+ * For a chain of attrs/methods: Huh? Look at lib.rb#add_moderator for an
74
+ example. "moderator" is an array attribute of MailList.py, and we want to
75
+ append a new string to it. So our "command" to listproxy.py is
76
+ "moderator.append" with the new moderator string as the argument. listproxy is
77
+ smart enough to untangle that and get the moderator attribute and then call the
78
+ append method on it with your argument. But, in order to tell it to lock and
79
+ save the list for us, we must replace that dot in the name with an
80
+ underscore in the needs_save key. That's why we have "moderator_append=True"
81
+ in the needs_save dict in listproxy.py. So if you have a chain of attributes
82
+ and methods to get at the thing you're exposing, just replace the dots with
83
+ underscores in the needs_save dict key and you'll be all set.
84
+
85
+ That should get you started hacking on the gem. If you get stuck or are trying to
86
+ do anything more complex, please feel free to e-mail me: cap10morgan@gmail.com.
87
+
88
+ ## Testing
89
+
90
+ The RSpec suite should run out of the box with the `rake spec` command.
91
+ Feel free to open a GitHub issue if they do not.
92
+
93
+ ## Contributing
94
+
95
+ * Fork on GitHub
96
+ * Make a new branch
97
+ * Commit your feature addition or bug fix to that branch.
98
+ * Don't mess with Rakefile, version.rb, or Changelog. (If you want to have your own version, that's fine but bump version in its own commit so we can ignore it when we pull.)
99
+ * Add tests for it. This is important so we don't break it in a future version unintentionally.
100
+ * Push your changes to that branch (i.e. not master)
101
+ * Make a pull request
102
+ * Bask in your awesomeness
103
+
104
+ ## Author
105
+
106
+ * Wes Morgan (cap10morgan on GitHub) <cap10morgan@gmail.com>
107
+
108
+ Copyright 2011 Democratic National Committee,
109
+ All Rights Reserved.
data/Rakefile CHANGED
@@ -2,7 +2,7 @@ APP_ROOT = File.expand_path( File.dirname(__FILE__) )
2
2
  $LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
3
3
  require 'mailmanager/version'
4
4
  require 'rake'
5
- require 'rake/rdoctask'
5
+ require 'rdoc/task'
6
6
  require 'rspec/core/rake_task'
7
7
 
8
8
  # load all .rake files in the tasks dir
@@ -36,5 +36,7 @@ RSpec::Core::RakeTask.new(:spec) do |spec|
36
36
  spec.pattern = 'spec/**/*_spec.rb'
37
37
  end
38
38
 
39
- desc "Run tests for rubygems-test"
39
+ desc "Run tests for mailmanager"
40
40
  task :test => :spec
41
+
42
+ task :default => :spec
@@ -85,6 +85,14 @@ module MailManager
85
85
  @lib.list_names
86
86
  end
87
87
 
88
+ # Retrieves all lists for one or multiple list members selected by a regexp
89
+ # Returns something like { "member@example.com" => [ "first_list", "second_list" ] }
90
+ # Takes a String or a Regexp
91
+ #
92
+ def find_member(regex)
93
+ @lib.find_member(regex)
94
+ end
95
+
88
96
  # Create a new list. Returns an instance of MailManager::List. Params are:
89
97
  # * :name => 'new_list_name'
90
98
  # * :admin_email => 'admin@domain.com'
@@ -31,6 +31,13 @@ module MailManager
31
31
  lists.map { |list| list.name }
32
32
  end
33
33
 
34
+ def find_member(regex)
35
+ raise ArgumentError, "Expected a Python Regular Expression as String" if regex.is_a? Regexp
36
+ cmd = :find_member
37
+ out = command(cmd, {:regex => regex})
38
+ parse_output(cmd, out)
39
+ end
40
+
34
41
  def create_list(params)
35
42
  raise ArgumentError, "Missing :name param" if params[:name].nil?
36
43
  list_name = params[:name]
@@ -172,6 +179,9 @@ module MailManager
172
179
  when :rmlist
173
180
  raise ArgumentError, "Missing :name param" if params[:name].nil?
174
181
  mailman_cmd += "#{escape(params.delete(:name))} "
182
+ when :find_member
183
+ raise ArgumentError, "Missing :regex param" if params[:regex].nil?
184
+ mailman_cmd += "#{escape(params.delete(:regex))} "
175
185
  when :withlist
176
186
  raise ArgumentError, "Missing :name param" if params[:name].nil?
177
187
  proxy_path = File.dirname(__FILE__)
@@ -235,6 +245,21 @@ module MailManager
235
245
  end
236
246
  end
237
247
  return_obj = lists
248
+ when :find_member
249
+ matches = {}
250
+ puts "Output from Mailman:\n#{output}" if MailManager.debug
251
+ last_member = nil
252
+ output.split("\n").each do |line|
253
+ if line =~ /^(.+) found in:/
254
+ puts "Found member #{$1}" if MailManager.debug
255
+ last_member = $1
256
+ matches[last_member] = []
257
+ elsif line =~ /^\s*(.+?)$/
258
+ puts "Found list #{$1} for member #{last_member}" if MailManager.debug
259
+ matches[last_member] << $1
260
+ end
261
+ end
262
+ return_obj = matches
238
263
  end
239
264
  return_obj
240
265
  end
@@ -1,3 +1,3 @@
1
1
  module MailManager
2
- VERSION = '1.0.20'
2
+ VERSION = '1.1.1'
3
3
  end
@@ -7,6 +7,7 @@ require 'mailmanager/version'
7
7
  spec = Gem::Specification.new do |s|
8
8
  s.name = 'mailmanager'
9
9
  s.version = MailManager::VERSION
10
+ s.licenses = "BSD-3-Clause"
10
11
  s.date = Time.now.utc.strftime("%Y-%m-%d")
11
12
  s.summary = "GNU Mailman wrapper for Ruby"
12
13
  s.description = %{Ruby wrapper library for GNU Mailman's admin functions}
@@ -14,20 +15,12 @@ spec = Gem::Specification.new do |s|
14
15
  s.test_files = `git ls-files spec`.split("\n")
15
16
  s.require_paths = ['lib']
16
17
  s.has_rdoc = true
17
- s.extra_rdoc_files = [
18
- "README.rdoc"
19
- ]
20
18
  s.rdoc_options = ["--charset=UTF-8"]
21
19
  s.authors = ["Wes Morgan"]
22
20
  s.email = "cap10morgan@gmail.com"
23
21
  s.homepage = "http://github.com/cap10morgan/mailmanager"
24
- s.add_runtime_dependency('json', '~>1.4.6')
25
- s.add_runtime_dependency('open4', '~>1.0.1')
26
- s.add_development_dependency('rspec', '~>2.4.0')
27
- s.add_development_dependency('ZenTest', '~>4.4.2')
28
- s.add_development_dependency('ruby-debug19')
29
- s.add_development_dependency('ci_reporter')
30
- s.add_development_dependency('cucumber')
31
- s.add_development_dependency('simplecov')
32
- s.add_development_dependency('simplecov-rcov', '~>0.1.4')
22
+ s.add_runtime_dependency('json', '~> 1.8')
23
+ s.add_runtime_dependency('open4', '~> 1.0')
24
+ s.add_development_dependency('rake', '~> 10.3')
25
+ s.add_development_dependency('rspec', '~> 2.4')
33
26
  end
@@ -1,11 +1,11 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe MailManager::Lib do
4
- let(:mailmanager) { mock(MailManager) }
4
+ let(:mailmanager) { double(MailManager) }
5
5
  let(:subject) { MailManager::Lib.new }
6
6
  let(:fake_root) { '/foo/bar' }
7
7
  let(:python) { '/usr/bin/env python' }
8
- let(:process) { mock(Process::Status) }
8
+ let(:process) { double(Process::Status) }
9
9
  let(:list_result) { <<EOF
10
10
  3 matching mailing lists found:
11
11
  Foo - [no description available]
@@ -25,7 +25,7 @@ EOF
25
25
  it "should return all existing lists" do
26
26
  subject.stub(:run_command).with("#{python} #{fake_root}/bin/list_lists 2>&1", nil).
27
27
  and_return([list_result, process])
28
- subject.lists.should have(3).lists
28
+ expect(subject.lists.size).to eq(3)
29
29
  end
30
30
  end
31
31
 
@@ -68,11 +68,11 @@ EOF
68
68
  }
69
69
  let(:new_list_return) {
70
70
  prefix =<<EOF
71
- To finish creating your mailing list, you must edit your /etc/aliases (or
72
- equivalent) file by adding the following lines, and possibly running the
73
- `newaliases' program:
74
-
75
- ## bar mailing list
71
+ To finish creating your mailing list, you must edit your /etc/aliases (or
72
+ equivalent) file by adding the following lines, and possibly running the
73
+ `newaliases' program:
74
+
75
+ ## bar mailing list
76
76
  EOF
77
77
  prefix+new_aliases.join("\n")
78
78
  }
@@ -138,7 +138,7 @@ EOF
138
138
  end
139
139
 
140
140
  context "with populated list" do
141
- let(:list) { list = mock(MailManager::List)
141
+ let(:list) { list = double(MailManager::List)
142
142
  list.stub(:name).and_return('foo')
143
143
  list }
144
144
 
@@ -256,6 +256,36 @@ EOF
256
256
  end
257
257
  end
258
258
 
259
+ describe "#find_member" do
260
+ context "with string as argument" do
261
+ it "should ask Mailman for the matching lists" do
262
+ subject.should_receive(:run_command).
263
+ with(/python.*find_member.*foo/, nil).and_return([<<-EOF, process])
264
+ foo@example.com found in:
265
+ list1
266
+ list2
267
+ foobar
268
+ foo@example.net found in:
269
+ list3
270
+ EOF
271
+
272
+ result = subject.find_member('foo@bar.com')
273
+ result.should be_a(Hash)
274
+ result.keys.first.should eq('foo@example.com')
275
+ result.values.first.should eq(['list1', 'list2', 'foobar'])
276
+ result.values.last.should eq(['list3'])
277
+ end
278
+ end
279
+
280
+ context "with Regexp as argument" do
281
+ it "raises an ArgumentError" do
282
+ lambda {
283
+ subject.find_member(/^member/)
284
+ }.should raise_error(ArgumentError, /Python/)
285
+ end
286
+ end
287
+ end
288
+
259
289
  describe "#web_page_url" do
260
290
  it "should ask Mailman for the list's web address" do
261
291
  test_attr_getter(:web_page_url, "http://bar.com/mailman/listinfo/foo")
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe MailManager::List do
4
- let(:lib) { mock(MailManager::Lib) }
4
+ let(:lib) { double(MailManager::Lib) }
5
5
  let(:subject) { MailManager::List.new('foo') }
6
6
 
7
7
  before :each do
metadata CHANGED
@@ -1,139 +1,86 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mailmanager
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.20
5
- prerelease:
4
+ version: 1.1.1
6
5
  platform: ruby
7
6
  authors:
8
7
  - Wes Morgan
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2011-12-06 00:00:00.000000000Z
11
+ date: 2014-08-25 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: json
16
- requirement: &70116502937460 !ruby/object:Gem::Requirement
17
- none: false
15
+ requirement: !ruby/object:Gem::Requirement
18
16
  requirements:
19
- - - ~>
17
+ - - "~>"
20
18
  - !ruby/object:Gem::Version
21
- version: 1.4.6
19
+ version: '1.8'
22
20
  type: :runtime
23
21
  prerelease: false
24
- version_requirements: *70116502937460
25
- - !ruby/object:Gem::Dependency
26
- name: open4
27
- requirement: &70116502936960 !ruby/object:Gem::Requirement
28
- none: false
29
- requirements:
30
- - - ~>
31
- - !ruby/object:Gem::Version
32
- version: 1.0.1
33
- type: :runtime
34
- prerelease: false
35
- version_requirements: *70116502936960
36
- - !ruby/object:Gem::Dependency
37
- name: rspec
38
- requirement: &70116502936500 !ruby/object:Gem::Requirement
39
- none: false
22
+ version_requirements: !ruby/object:Gem::Requirement
40
23
  requirements:
41
- - - ~>
24
+ - - "~>"
42
25
  - !ruby/object:Gem::Version
43
- version: 2.4.0
44
- type: :development
45
- prerelease: false
46
- version_requirements: *70116502936500
26
+ version: '1.8'
47
27
  - !ruby/object:Gem::Dependency
48
- name: ZenTest
49
- requirement: &70116502936040 !ruby/object:Gem::Requirement
50
- none: false
28
+ name: open4
29
+ requirement: !ruby/object:Gem::Requirement
51
30
  requirements:
52
- - - ~>
31
+ - - "~>"
53
32
  - !ruby/object:Gem::Version
54
- version: 4.4.2
55
- type: :development
33
+ version: '1.0'
34
+ type: :runtime
56
35
  prerelease: false
57
- version_requirements: *70116502936040
58
- - !ruby/object:Gem::Dependency
59
- name: ruby-debug19
60
- requirement: &70116502935660 !ruby/object:Gem::Requirement
61
- none: false
36
+ version_requirements: !ruby/object:Gem::Requirement
62
37
  requirements:
63
- - - ! '>='
38
+ - - "~>"
64
39
  - !ruby/object:Gem::Version
65
- version: '0'
66
- type: :development
67
- prerelease: false
68
- version_requirements: *70116502935660
40
+ version: '1.0'
69
41
  - !ruby/object:Gem::Dependency
70
- name: ci_reporter
71
- requirement: &70116502935200 !ruby/object:Gem::Requirement
72
- none: false
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
73
44
  requirements:
74
- - - ! '>='
45
+ - - "~>"
75
46
  - !ruby/object:Gem::Version
76
- version: '0'
47
+ version: '10.3'
77
48
  type: :development
78
49
  prerelease: false
79
- version_requirements: *70116502935200
80
- - !ruby/object:Gem::Dependency
81
- name: cucumber
82
- requirement: &70116502934780 !ruby/object:Gem::Requirement
83
- none: false
50
+ version_requirements: !ruby/object:Gem::Requirement
84
51
  requirements:
85
- - - ! '>='
52
+ - - "~>"
86
53
  - !ruby/object:Gem::Version
87
- version: '0'
88
- type: :development
89
- prerelease: false
90
- version_requirements: *70116502934780
54
+ version: '10.3'
91
55
  - !ruby/object:Gem::Dependency
92
- name: simplecov
93
- requirement: &70116502934360 !ruby/object:Gem::Requirement
94
- none: false
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
95
58
  requirements:
96
- - - ! '>='
59
+ - - "~>"
97
60
  - !ruby/object:Gem::Version
98
- version: '0'
61
+ version: '2.4'
99
62
  type: :development
100
63
  prerelease: false
101
- version_requirements: *70116502934360
102
- - !ruby/object:Gem::Dependency
103
- name: simplecov-rcov
104
- requirement: &70116502933860 !ruby/object:Gem::Requirement
105
- none: false
64
+ version_requirements: !ruby/object:Gem::Requirement
106
65
  requirements:
107
- - - ~>
66
+ - - "~>"
108
67
  - !ruby/object:Gem::Version
109
- version: 0.1.4
110
- type: :development
111
- prerelease: false
112
- version_requirements: *70116502933860
68
+ version: '2.4'
113
69
  description: Ruby wrapper library for GNU Mailman's admin functions
114
70
  email: cap10morgan@gmail.com
115
71
  executables: []
116
72
  extensions: []
117
- extra_rdoc_files:
118
- - README.rdoc
73
+ extra_rdoc_files: []
119
74
  files:
120
- - .gitignore
121
- - .rspec
122
- - .rvmrc
75
+ - ".gitignore"
76
+ - ".rspec"
77
+ - ".travis.yml"
123
78
  - Changelog
124
79
  - Gemfile
125
- - Gemfile.lock
126
80
  - LICENSE
127
- - README.rdoc
81
+ - README.md
128
82
  - Rakefile
129
83
  - config/cucumber.yml
130
- - features/create_list.feature
131
- - features/delete_list.feature
132
- - features/list_metadata.feature
133
- - features/moderators.feature
134
- - features/step_definitions/global_steps.rb
135
- - features/step_definitions/list_steps.rb
136
- - features/support/env.rb
137
84
  - lib/mailmanager.rb
138
85
  - lib/mailmanager/lib.rb
139
86
  - lib/mailmanager/list.rb
@@ -147,29 +94,29 @@ files:
147
94
  - spec/spec_helper.rb
148
95
  - tasks/hudson.rake
149
96
  homepage: http://github.com/cap10morgan/mailmanager
150
- licenses: []
97
+ licenses:
98
+ - BSD-3-Clause
99
+ metadata: {}
151
100
  post_install_message:
152
101
  rdoc_options:
153
- - --charset=UTF-8
102
+ - "--charset=UTF-8"
154
103
  require_paths:
155
104
  - lib
156
105
  required_ruby_version: !ruby/object:Gem::Requirement
157
- none: false
158
106
  requirements:
159
- - - ! '>='
107
+ - - ">="
160
108
  - !ruby/object:Gem::Version
161
109
  version: '0'
162
110
  required_rubygems_version: !ruby/object:Gem::Requirement
163
- none: false
164
111
  requirements:
165
- - - ! '>='
112
+ - - ">="
166
113
  - !ruby/object:Gem::Version
167
114
  version: '0'
168
115
  requirements: []
169
116
  rubyforge_project:
170
- rubygems_version: 1.8.6
117
+ rubygems_version: 2.2.2
171
118
  signing_key:
172
- specification_version: 3
119
+ specification_version: 4
173
120
  summary: GNU Mailman wrapper for Ruby
174
121
  test_files:
175
122
  - spec/lib/mailmanager/lib_spec.rb
data/.rvmrc DELETED
@@ -1,31 +0,0 @@
1
- #!/usr/bin/env bash
2
-
3
- ruby_string="ruby-1.9.2"
4
- gemset_name="mailmanager"
5
-
6
- if rvm list strings | grep -q "${ruby_string}" ; then
7
-
8
- # Load or create the specified environment
9
- if [[ -d "${rvm_path:-$HOME/.rvm}/environments" \
10
- && -s "${rvm_path:-$HOME/.rvm}/environments/${ruby_string}@${gemset_name}" ]] ; then
11
- \. "${rvm_path:-$HOME/.rvm}/environments/${ruby_string}@${gemset_name}"
12
- else
13
- rvm --create "${ruby_string}@${gemset_name}"
14
- fi
15
-
16
- # Ensure that Bundler is installed; install it if not
17
- if ! command -v bundle ; then
18
- echo "Installing bundler... "
19
- gem install bundler
20
- fi
21
-
22
- # Run bundler but reduce excess noise
23
- echo "Checking your bundle... "
24
- bundle | grep -v 'Using' | grep -v 'complete' | sed '/^$/d'
25
-
26
- else
27
-
28
- # Notify user to install the requested interpreter before proceeding
29
- echo "${ruby_string} was not found, please run 'rvm install ${ruby_string}' and then cd back into this directory."
30
-
31
- fi
@@ -1,66 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- mailmanager (1.0.19)
5
- json (~> 1.4.6)
6
- open4 (~> 1.0.1)
7
-
8
- GEM
9
- remote: http://rubygems.org/
10
- specs:
11
- ZenTest (4.4.2)
12
- archive-tar-minitar (0.5.2)
13
- builder (3.0.0)
14
- ci_reporter (1.6.4)
15
- builder (>= 2.1.2)
16
- columnize (0.3.2)
17
- cucumber (0.10.0)
18
- builder (>= 2.1.2)
19
- diff-lcs (~> 1.1.2)
20
- gherkin (~> 2.3.2)
21
- json (~> 1.4.6)
22
- term-ansicolor (~> 1.0.5)
23
- diff-lcs (1.1.2)
24
- gherkin (2.3.3)
25
- json (~> 1.4.6)
26
- json (1.4.6)
27
- linecache19 (0.5.11)
28
- ruby_core_source (>= 0.1.4)
29
- open4 (1.0.1)
30
- rspec (2.4.0)
31
- rspec-core (~> 2.4.0)
32
- rspec-expectations (~> 2.4.0)
33
- rspec-mocks (~> 2.4.0)
34
- rspec-core (2.4.0)
35
- rspec-expectations (2.4.0)
36
- diff-lcs (~> 1.1.2)
37
- rspec-mocks (2.4.0)
38
- ruby-debug-base19 (0.11.24)
39
- columnize (>= 0.3.1)
40
- linecache19 (>= 0.5.11)
41
- ruby_core_source (>= 0.1.4)
42
- ruby-debug19 (0.11.6)
43
- columnize (>= 0.3.1)
44
- linecache19 (>= 0.5.11)
45
- ruby-debug-base19 (>= 0.11.19)
46
- ruby_core_source (0.1.4)
47
- archive-tar-minitar (>= 0.5.2)
48
- simplecov (0.3.9)
49
- simplecov-html (>= 0.3.7)
50
- simplecov-html (0.3.9)
51
- simplecov-rcov (0.1.4)
52
- simplecov
53
- term-ansicolor (1.0.5)
54
-
55
- PLATFORMS
56
- ruby
57
-
58
- DEPENDENCIES
59
- ZenTest (~> 4.4.2)
60
- ci_reporter
61
- cucumber
62
- mailmanager!
63
- rspec (~> 2.4.0)
64
- ruby-debug19
65
- simplecov
66
- simplecov-rcov (~> 0.1.4)
@@ -1,123 +0,0 @@
1
- = MailManager
2
-
3
- Website[http://github.com/cap10morgan/mailmanager]
4
-
5
- MailManager is a Ruby wrapper for the GNU Mailman mailing list manager. It exposes
6
- some administrative functions to Ruby. See the API docs[http://rubydoc.info/github/cap10morgan/mailmanager/master/frames]
7
- for details.
8
- It is licensed under the New BSD License (see the LICENSE file for details).
9
-
10
- MailManager has been tested with Mailman 2.1.14. It has NOT been tested with any
11
- release of Mailman 3 (in alpha as of 1/19/2011). It requires Python 2.4 or higher.
12
- Note that while Mailman itself requires Python, it can work with older versions. So
13
- check your Python version before using this.
14
-
15
- == Installation
16
-
17
- gem install mailmanager
18
-
19
- == Basic Usage
20
-
21
- mm = MailManager.init('/mailman/root')
22
- all_lists = mm.lists
23
- foo_list = mm.get_list('foo')
24
- new_list = mm.create_list(:name => 'newlist', :admin_email => 'me@here.com', :admin_password => 'secret')
25
- new_list.add_member('bar@baz.com')
26
- new_list.members -> ['bar@baz.com']
27
-
28
- == Hacking
29
-
30
- Here are the basic steps for adding new features to this gem, if you're a programmer
31
- type who likes to write code so you can code while you code... sorry.
32
-
33
- MailManager's API currently consists of a handful of methods at the top-level
34
- MailManager::Base class. This is where you'll find create_list and get_list. These
35
- both return instances of MailManager::List, which is really where the action is.
36
-
37
- MailManager::List contains the public Ruby API for interacting with Mailman's lists.
38
- It exposes the methods and attributes of Mailman's MailList.py class, but makes
39
- them a bit more Ruby-ish where appropriate. Not every method / attribute is
40
- exposed, but this is where you come in, dear contributor.
41
-
42
- The code that actually talks to Mailman is in lib/mailmanager/lib.rb.
43
- It runs scripts in Mailman's bin directory. Anything that interacts with an
44
- existing list uses Mailman's "withlist" script and the listproxy.py file in this
45
- gem. If you read the docs on withlist that come with Mailman, it should be pretty
46
- obvious what's going on there. But you don't need to understand all that to expose
47
- new methods & attributes of MailList.py to MailManager.
48
-
49
- Exposing new list properties works something like this:
50
- - Look at Mailman's code in Mailman/MailList.py and see if the thing you want to
51
- expose is a method or an attribute. You'll need to know a little Python, but not
52
- much. Basically, a method is a callable thing and an attribute is a simple
53
- property of the object. "AddMember" is a method, for example, while "description"
54
- is an attribute.
55
- - If it's a method, just write a simple method in lib/mailmanager/list.rb that
56
- calls a method in lib.rb (just like the others do). Then go write the method
57
- that you call in lib/mailmanager/lib.rb, using list_address or add_member as an
58
- example (depending on whether you're writing a getter or a setter, respectively).
59
- - All methods that interact with MailList.py instances (i.e. mailing lists) use the
60
- withlist command, so just copy that stuff from an existing method.
61
- - If you're exposing an attribute, then use the moderator methods as a guide.
62
- For example, they do their own dupe checking since the MailList.py class will
63
- let you set the attribute to whatever you want. Dangerous!
64
- - If you're writing a setter, you have one more chore to make it work. You need the
65
- listproxy.py code to lock the list and then save it after making your requested
66
- change. It will do this for you if you do the following:
67
- - For a method: Add the name of the MailList.py method to the needs_save dict and
68
- have it return True. It should be obvious when you look at the others in there.
69
- - For an attribute: Add the name of the attribute to the needs_save_with_arg dict.
70
- This one is a bit different because the attr name is the same for gets and sets,
71
- but we need to lock and save when it's a set, and we can guess that it's a set
72
- when there is an argument passed, and a get when there is no argument. S-M-R-T
73
- - For a chain of attrs/methods: Huh? Look at lib.rb#add_moderator for an
74
- example. "moderator" is an array attribute of MailList.py, and we want to
75
- append a new string to it. So our "command" to listproxy.py is
76
- "moderator.append" with the new moderator string as the argument. listproxy is
77
- smart enough to untangle that and get the moderator attribute and then call the
78
- append method on it with your argument. But, in order to tell it to lock and
79
- save the list for us, we must replace that dot in the name with an
80
- underscore in the needs_save key. That's why we have "moderator_append=True"
81
- in the needs_save dict in listproxy.py. So if you have a chain of attributes
82
- and methods to get at the thing you're exposing, just replace the dots with
83
- underscores in the needs_save dict key and you'll be all set.
84
-
85
- That should get you started hacking on the gem. If you get stuck or are trying to
86
- do anything more complex, please feel free to e-mail me: cap10morgan@gmail.com.
87
-
88
- == Testing
89
-
90
- The RSpec suite should run out of the box with the 'rake spec' command.
91
- Feel free to open a GitHub issue if they do not.
92
-
93
- You'll need a local working installation of GNU Mailman 2.1.14 (or a later version
94
- of 2.1.x, probably) to run the Cucumber integration tests. Make a symlink to the
95
- root directory of your Mailman install in the mailmanager directory. It should be
96
- named "mailman". So if you are in the top-level mailmanager directory and your
97
- Mailman installation is in /usr/local/mailman, you would run this command:
98
- ln -s /usr/local/mailman mailman
99
-
100
- Once that's done, you should be able to just run 'cucumber' in the top-level
101
- mailmanager directory.
102
-
103
- <b>MAKE SURE THIS IS NOT A MAILMAN INSTALLATION YOU CARE ABOUT!</b> The Cucumber test
104
- suite will start by deleting all mailing lists so it can have a clean slate to
105
- test with.
106
-
107
- == Contributing
108
-
109
- - Fork on GitHub
110
- - Make a new branch
111
- - Commit your feature addition or bug fix to that branch.
112
- - Don't mess with Rakefile, version.rb, or Changelog. (If you want to have your own version, that's fine but bump version in its own commit so we can ignore it when we pull.)
113
- - Add tests for it. This is important so we don't break it in a future version unintentionally.
114
- - Push your changes to that branch (i.e. not master)
115
- - Make a pull request
116
- - Bask in your awesomeness
117
-
118
- == Author
119
-
120
- - Wes Morgan (cap10morgan on GitHub) <cap10morgan@gmail.com>
121
-
122
- Copyright 2011 Democratic National Committee,
123
- All Rights Reserved.
@@ -1,18 +0,0 @@
1
- Feature: Creating a new list
2
- As a developer using MailManager
3
- In order to create new mailing lists
4
- I want MailManager to offer this feature
5
-
6
- Background:
7
- Given MailManager is initialized on "./mailman"
8
-
9
- Scenario: Creating a new list
10
- Given no lists exist
11
- When I create a new list "foo"
12
- Then I should have a list named "foo"
13
-
14
- Scenario: Creating a list with the same name as an existing list
15
- Given no lists exist
16
- When I create a new list "foo"
17
- Then it should raise MailManager::ListNameConflictError when I create a new list "foo"
18
- And I should have 1 list
@@ -1,16 +0,0 @@
1
- Feature: Deleting a list
2
- As a developer using MailManager
3
- In order to delete lists
4
- I want MailManager to offer this feature
5
-
6
- Background:
7
- Given MailManager is initialized on "./mailman"
8
-
9
- Scenario: Deleting a list
10
- Given I have a list named "foo"
11
- When I delete list "foo"
12
- Then I should have 0 lists
13
-
14
- Scenario: Deleting a list that doesn't exist
15
- Given no lists exist
16
- Then it should raise MailManager::ListNotFoundError when I delete list "foo"
@@ -1,37 +0,0 @@
1
- Feature: List metadata
2
-
3
- Background:
4
- Given MailManager is initialized on "./mailman"
5
-
6
- Scenario: Getting the info URL
7
- Given I have a list named "foo"
8
- When I ask for its info_url
9
- Then I should get a URL
10
-
11
- Scenario: Getting the list address
12
- Given I have a list named "foo"
13
- When I ask for its address
14
- Then I should get an email address
15
-
16
- Scenario: Getting the request email
17
- Given I have a list named "foo"
18
- When I ask for its request_email
19
- Then I should get an email address
20
-
21
- Scenario: Setting & getting the list description
22
- Given I have a list named "foo"
23
- And I set its description to "foo list of fun"
24
- When I ask for its description
25
- Then I should get "foo list of fun"
26
-
27
- Scenario: Setting & getting the subject prefix
28
- Given I have a list named "foo"
29
- And I set its subject_prefix to "[Foo List] "
30
- When I ask for its subject_prefix
31
- Then I should get "[Foo List] "
32
-
33
- Scenario: Getting & setting the host name
34
- Given I have a list named "foo"
35
- And I set its host_name to "groups.foo.org"
36
- When I ask for its host_name
37
- Then I should get "groups.foo.org"
@@ -1,22 +0,0 @@
1
- Feature: List moderators administration
2
-
3
- Background:
4
- Given MailManager is initialized on "./mailman"
5
- Given I have a list named "foo"
6
-
7
- Scenario: Adding a moderator
8
- When I add a moderator "me@bar.com"
9
- Then I should have 1 moderator
10
-
11
- Scenario: Adding a moderator that already exists
12
- Given I add a moderator "me@bar.com"
13
- Then it should raise MailManager::ModeratorAlreadyExistsError when I add a moderator "me@bar.com"
14
-
15
- Scenario: Deleting a moderator
16
- Given I add a moderator "me@bar.com"
17
- When I delete a moderator "me@bar.com"
18
- Then I should have 0 moderators
19
-
20
- Scenario: Deleting a moderator that doesn't exist
21
- Given I add a moderator "other@bar.com"
22
- Then it should raise MailManager::ModeratorNotFoundError when I delete a moderator "me@bar.com"
@@ -1,24 +0,0 @@
1
- Given /^MailManager is initialized on "([^\"]+)"$/ do |mailman_root|
2
- @mailmanager = MailManager.init(mailman_root)
3
- end
4
-
5
- Given /^no lists exist$/ do
6
- @mailmanager.list_names.each do |list_name|
7
- @mailmanager.delete_list(list_name)
8
- end
9
- end
10
-
11
- Then /^it should raise (.+?) when (.+)$/ do |exception,when_step|
12
- lambda {
13
- When when_step
14
- }.should raise_error(eval(exception))
15
- end
16
-
17
- Then /^I should have (\d+) lists?$/ do |num|
18
- @mailmanager.should have(num.to_i).lists
19
- end
20
-
21
- Then /^I should have a list named "([^"]*)"$/ do |list_name|
22
- @mailmanager.list_names.should include(list_name)
23
- end
24
-
@@ -1,47 +0,0 @@
1
- Given /^I have a list named "([^"]*)"$/ do |list_name|
2
- Given %{no lists exist}
3
- When %{I create a new list "#{list_name}"}
4
- end
5
-
6
- When /^I create a new list "([^"]*)"$/ do |list_name|
7
- @list = @mailmanager.create_list(:name => list_name, :admin_email => 'cuke@foo.org', :admin_password => 'greenisgood')
8
- end
9
-
10
- When /^I delete list "([^"]*)"$/ do |list_name|
11
- list = @mailmanager.get_list(list_name)
12
- list.delete
13
- end
14
-
15
- When /^I ask for its (.+)$/ do |attr|
16
- @attr = @list.send(attr)
17
- end
18
-
19
- Then /^I should get a URL$/ do
20
- @attr.should =~ %r{^http://.*/}
21
- end
22
-
23
- Then /^I should get an email address$/ do
24
- # super basic email regex
25
- @attr.should =~ %r{^[^@]+@[^\.]+\..+}
26
- end
27
-
28
- When /^I add a moderator "([^"]*)"$/ do |mod|
29
- @list.add_moderator(mod)
30
- end
31
-
32
- Then /^I should have (\d+) moderators?$/ do |num|
33
- @list.should have(num.to_i).moderators
34
- end
35
-
36
- When /^I delete a moderator "([^"]*)"$/ do |mod|
37
- @list.delete_moderator(mod)
38
- end
39
-
40
- Given /^I set its (.+?) to "([^"]*)"$/ do |attr,val|
41
- @list.send("#{attr}=",val)
42
- end
43
-
44
- Then /^I should get "([^"]*)"$/ do |val|
45
- @attr.should == val
46
- end
47
-
@@ -1,7 +0,0 @@
1
- $LOAD_PATH.unshift File.expand_path('../../lib', File.dirname(__FILE__))
2
- if ENV['COVERAGE_REPORT']
3
- $LOAD_PATH.unshift File.expand_path('../../spec', File.dirname(__FILE__))
4
- require "mailmanager_simplecov"
5
- SimpleCov.start 'mailmanager'
6
- end
7
- require "mailmanager"