bones 2.5.1 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +2 -0
- data/README.rdoc +54 -306
- data/Rakefile +28 -37
- data/bin/bones +10 -3
- data/{spec/data/data → default}/.bnsignore +3 -1
- data/{data → default}/History.txt.bns +0 -0
- data/{data → default}/README.txt.bns +0 -0
- data/default/Rakefile.bns +21 -0
- data/{data → default}/bin/NAME.bns +0 -0
- data/{data → default}/lib/NAME.rb.bns +0 -0
- data/{data → default}/spec/NAME_spec.rb.bns +0 -0
- data/{data → default}/spec/spec_helper.rb.bns +0 -0
- data/{data → default}/test/test_NAME.rb +0 -0
- data/lib/bones.rb +73 -31
- data/lib/bones/annotation_extractor.rb +16 -26
- data/lib/bones/app.rb +87 -58
- data/lib/bones/app/command.rb +143 -64
- data/lib/bones/app/create.rb +93 -0
- data/lib/bones/app/file_manager.rb +7 -8
- data/lib/bones/app/freeze.rb +59 -0
- data/lib/bones/app/info.rb +39 -0
- data/lib/bones/app/unfreeze.rb +44 -0
- data/lib/bones/colors.rb +54 -0
- data/lib/bones/gem_package_task.rb +71 -0
- data/lib/bones/helpers.rb +93 -0
- data/lib/bones/plugins/ann.rb +166 -0
- data/lib/bones/plugins/bones_plugin.rb +193 -0
- data/lib/bones/plugins/gem.rb +274 -0
- data/lib/bones/plugins/notes.rb +45 -0
- data/lib/bones/plugins/rdoc.rb +93 -0
- data/lib/bones/plugins/test.rb +57 -0
- data/lib/bones/smtp_tls.rb +1 -0
- data/spec/bones/app/file_manager_spec.rb +6 -6
- data/spec/bones/app_spec.rb +14 -18
- data/spec/bones_spec.rb +9 -4
- data/{data → spec/data/default}/.bnsignore +0 -0
- data/spec/data/{data → default}/History +0 -0
- data/spec/data/{data → default}/NAME/NAME.rb.bns +0 -0
- data/spec/data/{data → default}/README.txt.bns +0 -0
- data/{data → spec/data/default}/Rakefile.bns +0 -0
- data/spec/data/{data → default}/lib/NAME.rb.bns +0 -0
- metadata +94 -68
- data/lib/bones/app/create_command.rb +0 -86
- data/lib/bones/app/freeze_command.rb +0 -73
- data/lib/bones/app/info_command.rb +0 -58
- data/lib/bones/app/unfreeze_command.rb +0 -53
- data/lib/bones/app/update_command.rb +0 -47
- data/lib/bones/debug.rb +0 -72
- data/lib/bones/tasks/ann.rake +0 -80
- data/lib/bones/tasks/bones.rake +0 -20
- data/lib/bones/tasks/gem.rake +0 -201
- data/lib/bones/tasks/git.rake +0 -40
- data/lib/bones/tasks/notes.rake +0 -27
- data/lib/bones/tasks/post_load.rake +0 -34
- data/lib/bones/tasks/rdoc.rake +0 -51
- data/lib/bones/tasks/rubyforge.rake +0 -55
- data/lib/bones/tasks/setup.rb +0 -292
- data/lib/bones/tasks/spec.rake +0 -54
- data/lib/bones/tasks/svn.rake +0 -47
- data/lib/bones/tasks/test.rake +0 -40
- data/lib/bones/tasks/zentest.rake +0 -36
- data/spec/data/data/Rakefile.bns +0 -30
- data/tasks/ann.rake +0 -80
- data/tasks/bones.rake +0 -20
- data/tasks/gem.rake +0 -201
- data/tasks/git.rake +0 -40
- data/tasks/notes.rake +0 -27
- data/tasks/post_load.rake +0 -34
- data/tasks/rdoc.rake +0 -51
- data/tasks/rubyforge.rake +0 -55
- data/tasks/setup.rb +0 -292
- data/tasks/spec.rake +0 -54
- data/tasks/svn.rake +0 -47
- data/tasks/test.rake +0 -40
- data/tasks/zentest.rake +0 -36
@@ -1,86 +0,0 @@
|
|
1
|
-
|
2
|
-
module Bones
|
3
|
-
class App
|
4
|
-
|
5
|
-
class CreateCommand < Command
|
6
|
-
|
7
|
-
def run( args )
|
8
|
-
parse args
|
9
|
-
|
10
|
-
fm = FileManager.new(
|
11
|
-
:source => repository || skeleton_dir,
|
12
|
-
:destination => output_dir,
|
13
|
-
:stdout => @out,
|
14
|
-
:stderr => @err,
|
15
|
-
:verbose => verbose?
|
16
|
-
)
|
17
|
-
raise "Output directory already exists #{output_dir.inspect}" if test(?e, fm.destination)
|
18
|
-
|
19
|
-
begin
|
20
|
-
fm.copy
|
21
|
-
copy_tasks(File.join(output_dir, 'tasks')) if with_tasks?
|
22
|
-
fm.finalize name
|
23
|
-
|
24
|
-
pwd = File.expand_path(FileUtils.pwd)
|
25
|
-
msg = "Created '#{name}'"
|
26
|
-
msg << " in directory '#{output_dir}'" if name != output_dir
|
27
|
-
@out.puts msg
|
28
|
-
|
29
|
-
if test(?f, File.join(output_dir, 'Rakefile'))
|
30
|
-
begin
|
31
|
-
FileUtils.cd output_dir
|
32
|
-
@out.puts "Now you need to fix these files"
|
33
|
-
system "#{::Bones::RUBY} -S rake notes"
|
34
|
-
ensure
|
35
|
-
FileUtils.cd pwd
|
36
|
-
end
|
37
|
-
end
|
38
|
-
rescue Exception => err
|
39
|
-
FileUtils.rm_rf output_dir
|
40
|
-
msg = "Could not create '#{name}'"
|
41
|
-
msg << " in directory '#{output_dir}'" if name != output_dir
|
42
|
-
raise msg
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def parse( args )
|
47
|
-
std_opts = standard_options
|
48
|
-
|
49
|
-
opts = OptionParser.new
|
50
|
-
opts.banner = 'Usage: bones create [options] <project_name>'
|
51
|
-
|
52
|
-
opts.separator ''
|
53
|
-
opts.separator " Create a new project from a Mr Bones project skeleton. The skeleton can"
|
54
|
-
opts.separator " be the default project skeleton from the Mr Bones gem or one of the named"
|
55
|
-
opts.separator " skeletons found in the '~/.mrbones/' folder. A git or svn repository can"
|
56
|
-
opts.separator " be used as the skeleton if the '--repository' flag is given."
|
57
|
-
|
58
|
-
opts.separator ''
|
59
|
-
opts.on(*std_opts[:directory])
|
60
|
-
opts.on(*std_opts[:skeleton])
|
61
|
-
opts.on(*std_opts[:repository])
|
62
|
-
opts.on(*std_opts[:with_tasks])
|
63
|
-
|
64
|
-
opts.separator ''
|
65
|
-
opts.separator ' Common Options:'
|
66
|
-
opts.on_tail( '-h', '--help', 'show this message' ) {
|
67
|
-
@out.puts opts
|
68
|
-
exit
|
69
|
-
}
|
70
|
-
|
71
|
-
# parse the command line arguments
|
72
|
-
opts.parse! args
|
73
|
-
options[:name] = args.empty? ? nil : args.join('_')
|
74
|
-
|
75
|
-
if name.nil?
|
76
|
-
@out.puts opts
|
77
|
-
exit 1
|
78
|
-
end
|
79
|
-
options[:output_dir] = name if output_dir.nil?
|
80
|
-
end
|
81
|
-
|
82
|
-
end # class CreateCommand
|
83
|
-
end # class App
|
84
|
-
end # module Bones
|
85
|
-
|
86
|
-
# EOF
|
@@ -1,73 +0,0 @@
|
|
1
|
-
|
2
|
-
module Bones
|
3
|
-
class App
|
4
|
-
|
5
|
-
class FreezeCommand < Command
|
6
|
-
|
7
|
-
def run( args )
|
8
|
-
parse args
|
9
|
-
|
10
|
-
fm = FileManager.new(
|
11
|
-
:source => repository || ::Bones.path('data'),
|
12
|
-
:destination => output_dir,
|
13
|
-
:stdout => @out,
|
14
|
-
:stderr => @err,
|
15
|
-
:verbose => verbose?
|
16
|
-
)
|
17
|
-
|
18
|
-
fm.archive_destination
|
19
|
-
return freeze_to_repository if repository
|
20
|
-
|
21
|
-
fm.copy
|
22
|
-
copy_tasks(File.join(output_dir, 'tasks')) if with_tasks?
|
23
|
-
|
24
|
-
@out.puts "Project skeleton #{name.inspect} " <<
|
25
|
-
"has been frozen to Mr Bones #{::Bones::VERSION}"
|
26
|
-
end
|
27
|
-
|
28
|
-
def parse( args )
|
29
|
-
std_opts = standard_options
|
30
|
-
|
31
|
-
opts = OptionParser.new
|
32
|
-
opts.banner = 'Usage: bones freeze [options] [skeleton_name]'
|
33
|
-
|
34
|
-
opts.separator ''
|
35
|
-
opts.separator ' Freeze the project skeleton to the current Mr Bones project skeleton.'
|
36
|
-
opts.separator ' If a name is not given, then the default name "data" will be used.'
|
37
|
-
opts.separator ' Optionally a git or svn repository can be frozen as the project'
|
38
|
-
opts.separator ' skeleton.'
|
39
|
-
|
40
|
-
opts.separator ''
|
41
|
-
opts.on(*std_opts[:repository])
|
42
|
-
opts.on(*std_opts[:with_tasks])
|
43
|
-
|
44
|
-
opts.separator ''
|
45
|
-
opts.separator ' Common Options:'
|
46
|
-
opts.on_tail( '-h', '--help', 'show this message' ) {
|
47
|
-
@out.puts opts
|
48
|
-
exit
|
49
|
-
}
|
50
|
-
|
51
|
-
# parse the command line arguments
|
52
|
-
opts.parse! args
|
53
|
-
options[:name] = args.empty? ? 'data' : args.join('_')
|
54
|
-
options[:output_dir] = File.join(mrbones_dir, name)
|
55
|
-
end
|
56
|
-
|
57
|
-
# Freeze the project skeleton to the git or svn repository that the user
|
58
|
-
# passed in on the command line. This essentially creates an alias to the
|
59
|
-
# reposiory using the name passed in on the command line.
|
60
|
-
#
|
61
|
-
def freeze_to_repository
|
62
|
-
FileUtils.mkdir_p(File.dirname(output_dir))
|
63
|
-
File.open(output_dir, 'w') {|fd| fd.puts repository}
|
64
|
-
@out.puts "Project skeleton #{name.inspect} " <<
|
65
|
-
"has been frozen to #{repository.inspect}"
|
66
|
-
end
|
67
|
-
|
68
|
-
|
69
|
-
end # class FreezeCommand
|
70
|
-
end # class App
|
71
|
-
end # module Bones
|
72
|
-
|
73
|
-
# EOF
|
@@ -1,58 +0,0 @@
|
|
1
|
-
|
2
|
-
module Bones
|
3
|
-
class App
|
4
|
-
|
5
|
-
class InfoCommand < Command
|
6
|
-
|
7
|
-
def run( args )
|
8
|
-
parse args
|
9
|
-
|
10
|
-
skeleton_dir = File.join(mrbones_dir, 'data')
|
11
|
-
skeleton_dir = ::Bones.path('data') unless test(?d, skeleton_dir)
|
12
|
-
|
13
|
-
msg = "\n"
|
14
|
-
msg << "The default project skeleton will be copied from:\n"
|
15
|
-
msg << " " << skeleton_dir << "\n\n"
|
16
|
-
|
17
|
-
fmt = " %-12s => %s\n"
|
18
|
-
msg << "Available projects skeletons are:\n"
|
19
|
-
Dir.glob(File.join(mrbones_dir, '*')).sort.each do |fn|
|
20
|
-
next if fn =~ %r/\.archive$/
|
21
|
-
next if File.basename(fn) == 'data'
|
22
|
-
|
23
|
-
if test(?f, fn)
|
24
|
-
msg << fmt % [File.basename(fn), File.read(fn).strip]
|
25
|
-
else
|
26
|
-
msg << " " << File.basename(fn) << "\n"
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
@out.puts msg
|
31
|
-
@out.puts
|
32
|
-
end
|
33
|
-
|
34
|
-
def parse( args )
|
35
|
-
std_opts = standard_options
|
36
|
-
|
37
|
-
opts = OptionParser.new
|
38
|
-
opts.banner = 'Usage: bones info'
|
39
|
-
|
40
|
-
opts.separator ''
|
41
|
-
opts.separator ' Shows information about available skeletons'
|
42
|
-
|
43
|
-
opts.separator ''
|
44
|
-
opts.separator ' Common Options:'
|
45
|
-
opts.on_tail( '-h', '--help', 'show this message' ) {
|
46
|
-
@out.puts opts
|
47
|
-
exit
|
48
|
-
}
|
49
|
-
|
50
|
-
# parse the command line arguments
|
51
|
-
opts.parse! args
|
52
|
-
end
|
53
|
-
|
54
|
-
end # class InfoCommand
|
55
|
-
end # class App
|
56
|
-
end # module Bones
|
57
|
-
|
58
|
-
# EOF
|
@@ -1,53 +0,0 @@
|
|
1
|
-
|
2
|
-
module Bones
|
3
|
-
class App
|
4
|
-
|
5
|
-
class UnfreezeCommand < Command
|
6
|
-
|
7
|
-
def run( args )
|
8
|
-
parse args
|
9
|
-
|
10
|
-
fm = FileManager.new(
|
11
|
-
:source => repository || ::Bones.path('data'),
|
12
|
-
:destination => output_dir,
|
13
|
-
:stdout => @out,
|
14
|
-
:stderr => @err,
|
15
|
-
:verbose => verbose?
|
16
|
-
)
|
17
|
-
|
18
|
-
if fm.archive_destination
|
19
|
-
@out.puts "Project skeleton #{name.inspect} has been unfrozen"
|
20
|
-
else
|
21
|
-
@out.puts "Project skeleton #{name.inspect} is not frozen " <<
|
22
|
-
"(no action taken)"
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
def parse( args )
|
27
|
-
std_opts = standard_options
|
28
|
-
|
29
|
-
opts = OptionParser.new
|
30
|
-
opts.banner = 'Usage: bones unfreeze [skeleton_name]'
|
31
|
-
|
32
|
-
opts.separator ''
|
33
|
-
opts.separator " Removes the named skeleton from the '~/.mrbones/' folder. If a name is"
|
34
|
-
opts.separator " not given then the default skeleton is removed."
|
35
|
-
|
36
|
-
opts.separator ''
|
37
|
-
opts.separator ' Common Options:'
|
38
|
-
opts.on_tail( '-h', '--help', 'show this message' ) {
|
39
|
-
@out.puts opts
|
40
|
-
exit
|
41
|
-
}
|
42
|
-
|
43
|
-
# parse the command line arguments
|
44
|
-
opts.parse! args
|
45
|
-
options[:name] = args.empty? ? 'data' : args.join('_')
|
46
|
-
options[:output_dir] = File.join(mrbones_dir, name)
|
47
|
-
end
|
48
|
-
|
49
|
-
end # class UnfreezeCommand
|
50
|
-
end # class App
|
51
|
-
end # module Bones
|
52
|
-
|
53
|
-
# EOF
|
@@ -1,47 +0,0 @@
|
|
1
|
-
|
2
|
-
module Bones
|
3
|
-
class App
|
4
|
-
|
5
|
-
class UpdateCommand < Command
|
6
|
-
|
7
|
-
def run( args )
|
8
|
-
parse args
|
9
|
-
|
10
|
-
raise "'#{output_dir}' does not exist" unless test(?e, output_dir)
|
11
|
-
copy_tasks(File.join(output_dir, 'tasks'))
|
12
|
-
|
13
|
-
msg = "Updated tasks in directory '#{output_dir}'"
|
14
|
-
@out.puts msg
|
15
|
-
end
|
16
|
-
|
17
|
-
def parse( args )
|
18
|
-
std_opts = standard_options
|
19
|
-
|
20
|
-
opts = OptionParser.new
|
21
|
-
opts.banner = 'Usage: bones update <directory>'
|
22
|
-
|
23
|
-
opts.separator ''
|
24
|
-
opts.separator ' Copy the Mr Bones rake tasks into the project directory'
|
25
|
-
|
26
|
-
opts.separator ''
|
27
|
-
opts.separator ' Common Options:'
|
28
|
-
opts.on_tail( '-h', '--help', 'show this message' ) {
|
29
|
-
@out.puts opts
|
30
|
-
exit
|
31
|
-
}
|
32
|
-
|
33
|
-
# parse the command line arguments
|
34
|
-
opts.parse! args
|
35
|
-
options[:output_dir] = args.empty? ? nil : args.join('_')
|
36
|
-
|
37
|
-
if output_dir.nil?
|
38
|
-
@out.puts opts
|
39
|
-
exit 1
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
end # class CreateCommand
|
44
|
-
end # class App
|
45
|
-
end # module Bones
|
46
|
-
|
47
|
-
# EOF
|
data/lib/bones/debug.rb
DELETED
@@ -1,72 +0,0 @@
|
|
1
|
-
|
2
|
-
require 'pp'
|
3
|
-
require 'stringio'
|
4
|
-
|
5
|
-
module Bones
|
6
|
-
|
7
|
-
# Helper module that will pretty print OpenStruct objects. It is used mainly
|
8
|
-
# for debugging the Mr Bones project open struct.
|
9
|
-
#
|
10
|
-
module Debug
|
11
|
-
|
12
|
-
# :stopdoc:
|
13
|
-
KEY_LENGTH = 20
|
14
|
-
VAR_LENGTH = 78 - 6 - KEY_LENGTH
|
15
|
-
SEP = "\n" + ' '*(KEY_LENGTH+6)
|
16
|
-
FMT = " %-#{KEY_LENGTH}s => %s"
|
17
|
-
# :startdoc:
|
18
|
-
|
19
|
-
# Print all the keys for the given _ostruct_ to stdout. If a _prefix_ is
|
20
|
-
# given, then the open struct keys will be prefixed with this string.
|
21
|
-
#
|
22
|
-
def self.show( ostruct, prefix = '' )
|
23
|
-
sio = StringIO.new
|
24
|
-
|
25
|
-
h = ostruct.instance_variable_get(:@table)
|
26
|
-
h.keys.map {|k| k.to_s}.sort.each do |k|
|
27
|
-
sio.seek 0
|
28
|
-
sio.truncate 0
|
29
|
-
next if k =~ %r/^_/o
|
30
|
-
|
31
|
-
val = h[k.to_sym]
|
32
|
-
if val.instance_of?(OpenStruct)
|
33
|
-
self.show(val, prefix + k + '.')
|
34
|
-
else
|
35
|
-
PP.pp(val, sio, VAR_LENGTH)
|
36
|
-
sio.seek 0
|
37
|
-
val = sio.read
|
38
|
-
val = val.split("\n").join(SEP)
|
39
|
-
|
40
|
-
key = prefix + k
|
41
|
-
key[(KEY_LENGTH-3)..-1] = '...' if key.length > KEY_LENGTH
|
42
|
-
puts(FMT % [key, val])
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
# Print a single attribute from the given _ostruct_ to stdout. The
|
48
|
-
# attributed is identified by the given _key_.
|
49
|
-
#
|
50
|
-
def self.show_attr( ostruct, key )
|
51
|
-
sio = StringIO.new
|
52
|
-
|
53
|
-
key = key.dup if key.frozen?
|
54
|
-
val = key.split('.').inject(ostruct) {|os,k| os.send(k)}
|
55
|
-
|
56
|
-
if val.instance_of?(OpenStruct)
|
57
|
-
self.show(val, key + '.')
|
58
|
-
else
|
59
|
-
PP.pp(val, sio, VAR_LENGTH)
|
60
|
-
sio.seek 0
|
61
|
-
val = sio.read
|
62
|
-
val = val.split("\n").join(SEP)
|
63
|
-
|
64
|
-
key[(KEY_LENGTH-3)..-1] = '...' if key.length > KEY_LENGTH
|
65
|
-
puts(FMT % [key, val])
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
end # module Debug
|
70
|
-
end # module Bones
|
71
|
-
|
72
|
-
# EOF
|
data/lib/bones/tasks/ann.rake
DELETED
@@ -1,80 +0,0 @@
|
|
1
|
-
|
2
|
-
begin
|
3
|
-
require 'bones/smtp_tls'
|
4
|
-
rescue LoadError
|
5
|
-
require 'net/smtp'
|
6
|
-
end
|
7
|
-
require 'time'
|
8
|
-
|
9
|
-
namespace :ann do
|
10
|
-
|
11
|
-
# A prerequisites task that all other tasks depend upon
|
12
|
-
task :prereqs
|
13
|
-
|
14
|
-
file PROJ.ann.file do
|
15
|
-
ann = PROJ.ann
|
16
|
-
puts "Generating #{ann.file}"
|
17
|
-
File.open(ann.file,'w') do |fd|
|
18
|
-
fd.puts("#{PROJ.name} version #{PROJ.version}")
|
19
|
-
fd.puts(" by #{Array(PROJ.authors).first}") if PROJ.authors
|
20
|
-
fd.puts(" #{PROJ.url}") if PROJ.url.valid?
|
21
|
-
fd.puts(" (the \"#{PROJ.release_name}\" release)") if PROJ.release_name
|
22
|
-
fd.puts
|
23
|
-
fd.puts("== DESCRIPTION")
|
24
|
-
fd.puts
|
25
|
-
fd.puts(PROJ.description)
|
26
|
-
fd.puts
|
27
|
-
fd.puts(PROJ.changes.sub(%r/^.*$/, '== CHANGES'))
|
28
|
-
fd.puts
|
29
|
-
ann.paragraphs.each do |p|
|
30
|
-
fd.puts "== #{p.upcase}"
|
31
|
-
fd.puts
|
32
|
-
fd.puts paragraphs_of(PROJ.readme_file, p).join("\n\n")
|
33
|
-
fd.puts
|
34
|
-
end
|
35
|
-
fd.puts ann.text if ann.text
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
desc "Create an announcement file"
|
40
|
-
task :announcement => ['ann:prereqs', PROJ.ann.file]
|
41
|
-
|
42
|
-
desc "Send an email announcement"
|
43
|
-
task :email => ['ann:prereqs', PROJ.ann.file] do
|
44
|
-
ann = PROJ.ann
|
45
|
-
from = ann.email[:from] || Array(PROJ.authors).first || PROJ.email
|
46
|
-
to = Array(ann.email[:to])
|
47
|
-
|
48
|
-
### build a mail header for RFC 822
|
49
|
-
rfc822msg = "From: #{from}\n"
|
50
|
-
rfc822msg << "To: #{to.join(',')}\n"
|
51
|
-
rfc822msg << "Subject: [ANN] #{PROJ.name} #{PROJ.version}"
|
52
|
-
rfc822msg << " (#{PROJ.release_name})" if PROJ.release_name
|
53
|
-
rfc822msg << "\n"
|
54
|
-
rfc822msg << "Date: #{Time.new.rfc822}\n"
|
55
|
-
rfc822msg << "Message-Id: "
|
56
|
-
rfc822msg << "<#{"%.8f" % Time.now.to_f}@#{ann.email[:domain]}>\n\n"
|
57
|
-
rfc822msg << File.read(ann.file)
|
58
|
-
|
59
|
-
params = [:server, :port, :domain, :acct, :passwd, :authtype].map do |key|
|
60
|
-
ann.email[key]
|
61
|
-
end
|
62
|
-
|
63
|
-
params[3] = PROJ.email if params[3].nil?
|
64
|
-
|
65
|
-
if params[4].nil?
|
66
|
-
STDOUT.write "Please enter your e-mail password (#{params[3]}): "
|
67
|
-
params[4] = STDIN.gets.chomp
|
68
|
-
end
|
69
|
-
|
70
|
-
### send email
|
71
|
-
Net::SMTP.start(*params) {|smtp| smtp.sendmail(rfc822msg, from, to)}
|
72
|
-
end
|
73
|
-
end # namespace :ann
|
74
|
-
|
75
|
-
desc 'Alias to ann:announcement'
|
76
|
-
task :ann => 'ann:announcement'
|
77
|
-
|
78
|
-
CLOBBER << PROJ.ann.file
|
79
|
-
|
80
|
-
# EOF
|