sqrbl 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +4 -0
- data/LICENSE.txt +621 -0
- data/README.txt +85 -0
- data/Rakefile +32 -0
- data/TODO.txt +11 -0
- data/bin/sqrbl +8 -0
- data/lib/core_exts/object.rb +44 -0
- data/lib/core_exts/symbol.rb +16 -0
- data/lib/sqrbl/base_migration_writer.rb +52 -0
- data/lib/sqrbl/call_stack.rb +21 -0
- data/lib/sqrbl/group.rb +42 -0
- data/lib/sqrbl/individual_migration_writer.rb +48 -0
- data/lib/sqrbl/migration.rb +62 -0
- data/lib/sqrbl/mixins/expects_block_with_new.rb +27 -0
- data/lib/sqrbl/mixins/has_todos.rb +65 -0
- data/lib/sqrbl/mixins/method_missing_delegation.rb +83 -0
- data/lib/sqrbl/step.rb +192 -0
- data/lib/sqrbl/step_pair.rb +56 -0
- data/lib/sqrbl/unified_migration_writer.rb +34 -0
- data/lib/sqrbl.rb +83 -0
- data/spec/README.txt +4 -0
- data/spec/functional/base_migration_writer_spec.rb +12 -0
- data/spec/functional/individual_migration_writer_spec.rb +172 -0
- data/spec/functional/unified_migration_writer_spec.rb +97 -0
- data/spec/spec_helper.rb +31 -0
- data/spec/unit/group_spec.rb +85 -0
- data/spec/unit/migration_spec.rb +68 -0
- data/spec/unit/sqrbl_spec.rb +28 -0
- data/spec/unit/step_pair_spec.rb +110 -0
- data/spec/unit/step_spec.rb +154 -0
- data/tasks/ann.rake +80 -0
- data/tasks/bones.rake +20 -0
- data/tasks/gem.rake +201 -0
- data/tasks/git.rake +40 -0
- data/tasks/notes.rake +27 -0
- data/tasks/post_load.rake +34 -0
- data/tasks/rdoc.rake +51 -0
- data/tasks/rubyforge.rake +55 -0
- data/tasks/setup.rb +292 -0
- data/tasks/spec.rake +54 -0
- data/tasks/svn.rake +47 -0
- data/tasks/test.rake +40 -0
- data/tasks/zentest.rake +36 -0
- metadata +115 -0
@@ -0,0 +1,85 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), %w[.. spec_helper])
|
2
|
+
|
3
|
+
include Sqrbl
|
4
|
+
|
5
|
+
describe Group do
|
6
|
+
before(:each) do
|
7
|
+
@mig = mock('Migration')
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should evaluate the block in its own context" do
|
11
|
+
group = Group.new(@mig, "foo", :skip_block_evaluation => true) do
|
12
|
+
hello_world()
|
13
|
+
end
|
14
|
+
group.should_receive(:hello_world)
|
15
|
+
group.send(:evaluate_block!)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should delegate method_missing calls back to the migration object" do
|
19
|
+
@mig.should_receive(:goodbye_world)
|
20
|
+
group = Group.new(@mig, "foo") do
|
21
|
+
goodbye_world()
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
it "methods defined in the group block should become available as methods on the Group instance" do
|
26
|
+
group = Group.new(@mig, "foo") do
|
27
|
+
def hello_world
|
28
|
+
"Hello, world!"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
group.should respond_to(:hello_world)
|
32
|
+
group.hello_world.should == "Hello, world!"
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "when #todo is called" do
|
36
|
+
it "should create a Todo object that saves the message" do
|
37
|
+
group = Group.new(@mig, 'foo') { todo 'bar' }
|
38
|
+
group.todos.map(&:message).should == ['bar']
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should create a Todo object that saves the location of the #todo call" do
|
42
|
+
group = Group.new(@mig, 'foo') { todo 'bar' }; line_num = __LINE__
|
43
|
+
group.todos.first.location.should == [__FILE__, line_num].join(':')
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "when #step is called" do
|
48
|
+
it "should create a StepPair object and pass it the group, the description, and the block arg" do
|
49
|
+
test_self = self
|
50
|
+
group = Group.new(@mig, "foo") do
|
51
|
+
StepPair.should_receive(:new).with(self, 'do something').and_yield # Look weird? See ./README.txt
|
52
|
+
step('do something') {}
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe :valid? do
|
58
|
+
it "should return false if steps is empty" do
|
59
|
+
group = Group.new(@mig, "foo") {}
|
60
|
+
group.should_not be_valid
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should return false if steps is not empty, but any step is invalid" do
|
64
|
+
group = Group.new(@mig, "foo") { step("foo") {} }
|
65
|
+
group.steps.map(&:valid?).should include(false)
|
66
|
+
group.should_not be_valid
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should return true if steps is not empty, and all steps are themselves valid" do
|
70
|
+
group = Group.new(@mig, "foo") do
|
71
|
+
step("foo") do
|
72
|
+
up {}
|
73
|
+
down {}
|
74
|
+
end
|
75
|
+
end
|
76
|
+
group.should be_valid
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should have a unix_name property that consists of the regular name with characters sanitized" do
|
81
|
+
group = Group.new(@mig, "This be a test, matey! ARRR!!") {}
|
82
|
+
group.unix_name.should == 'this_be_a_test_matey_arrr'
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), %w[.. spec_helper])
|
2
|
+
|
3
|
+
include Sqrbl
|
4
|
+
|
5
|
+
describe Migration do
|
6
|
+
describe "A new migration" do
|
7
|
+
it "should know the file that created it" do
|
8
|
+
mig = Migration.new
|
9
|
+
mig.creating_file.should == File.expand_path(__FILE__)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "A migration built with Migration.build" do
|
14
|
+
it "should still know the file that created it" do
|
15
|
+
mig = Migration.build {}
|
16
|
+
mig.creating_file.should == File.expand_path(__FILE__)
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "when the block calls #group once" do
|
20
|
+
it "should have one group with the proper description" do
|
21
|
+
mig = Migration.build do
|
22
|
+
group "first group" do
|
23
|
+
'hello world'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
mig.groups.all? { |group| group.should be_kind_of(Group) }
|
27
|
+
mig.groups.map(&:description).should == ['first group']
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "when the block calls #group twice" do
|
32
|
+
it "should have two group with the proper descriptions" do
|
33
|
+
mig = Migration.build do
|
34
|
+
group "first group" do
|
35
|
+
'hello world'
|
36
|
+
end
|
37
|
+
group "second group" do
|
38
|
+
'goodbye world'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
mig.groups.all? { |group| group.should be_kind_of(Group) }
|
42
|
+
mig.groups.map(&:description).should == ['first group', 'second group']
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should pass itself as a dependency to any group it builds" do
|
47
|
+
mig = Migration.build do
|
48
|
+
group("first group" ) { '' }
|
49
|
+
group("second group" ) { '' }
|
50
|
+
group("group the third") { '' }
|
51
|
+
end
|
52
|
+
|
53
|
+
mig.groups.all? { |group| group.migration.should == mig }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "when #todo is called" do
|
58
|
+
it "should create a Todo object that saves the message" do
|
59
|
+
mig = Migration.build { todo 'foo' }
|
60
|
+
mig.todos.map(&:message).should == ['foo']
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should create a Todo object that saves the location of the #todo call" do
|
64
|
+
mig = Migration.build { todo 'foo' }; line_num = __LINE__
|
65
|
+
mig.todos.first.location.should == [__FILE__, line_num].join(':')
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), %w[.. spec_helper])
|
2
|
+
|
3
|
+
include Sqrbl
|
4
|
+
|
5
|
+
describe Sqrbl do
|
6
|
+
it ".build_migration should return an instance of Sqrbl::Migration" do
|
7
|
+
migration = Sqrbl.build_migration { 'hello, world!' }
|
8
|
+
migration.should be_kind_of(Sqrbl::Migration)
|
9
|
+
end
|
10
|
+
|
11
|
+
it ".migration should take the return value from Sqrbl::Migration.build and pass it to write_migration" do
|
12
|
+
mig = mock('Migration')
|
13
|
+
Migration.should_receive(:build).and_yield.and_return(mig)
|
14
|
+
Sqrbl.should_receive(:write_migration!).with(mig)
|
15
|
+
Sqrbl.migration { 'Hello, world!' }
|
16
|
+
end
|
17
|
+
|
18
|
+
describe :write_migration! do
|
19
|
+
it "should take a migration object and pass it off to any and all writers that exist" do
|
20
|
+
mig = mock('Migration')
|
21
|
+
BaseMigrationWriter.subclasses.each do |writer_class|
|
22
|
+
writer_class.should_receive(:write_migration!).with(mig)
|
23
|
+
end
|
24
|
+
Sqrbl.write_migration!(mig)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), %w[.. spec_helper])
|
2
|
+
|
3
|
+
include Sqrbl
|
4
|
+
|
5
|
+
describe StepPair do
|
6
|
+
before(:each) do
|
7
|
+
@group = mock('Group')
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should evaluate the block in its own context" do
|
11
|
+
step_pair = StepPair.new(@group, "foo", :skip_block_evaluation => true) do
|
12
|
+
hello_world()
|
13
|
+
end
|
14
|
+
step_pair.should_receive(:hello_world)
|
15
|
+
step_pair.send(:evaluate_block!)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should delegate method_missing calls back to the group object" do
|
19
|
+
@group.should_receive(:goodbye_world)
|
20
|
+
step_pair = StepPair.new(@group, "foo") do
|
21
|
+
goodbye_world()
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
it "methods defined in the step_pair block should become available as methods on the StepPair instance" do
|
26
|
+
step_pair = StepPair.new(@group, "foo") do
|
27
|
+
def hello_world
|
28
|
+
"Hello, world!"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
step_pair.should respond_to(:hello_world)
|
32
|
+
step_pair.hello_world.should == "Hello, world!"
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "when #up is called" do
|
36
|
+
it "should create a Step object and pass it the StepPair and the block arg" do
|
37
|
+
step_pair = StepPair.new(@group, "foo") do
|
38
|
+
Step.should_receive(:new).with(self).and_yield # Look weird? See ./README.txt
|
39
|
+
up {}
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should put the Step object in its up_step attribute" do
|
44
|
+
step_pair = StepPair.new(@group, "foo") do
|
45
|
+
up {}
|
46
|
+
end
|
47
|
+
step_pair.up_step.should be_kind_of(Step)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "when #down is called" do
|
52
|
+
it "should create a Step object and pass it the StepPair and the block arg" do
|
53
|
+
step_pair = StepPair.new(@group, "foo") do
|
54
|
+
Step.should_receive(:new).with(self).and_yield # Look weird? See ./README.txt
|
55
|
+
down {}
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should put the Step object in its down_step attribute" do
|
60
|
+
step_pair = StepPair.new(@group, "foo") do
|
61
|
+
down {}
|
62
|
+
end
|
63
|
+
step_pair.down_step.should be_kind_of(Step)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe :valid? do
|
68
|
+
it "should return false if up_step is nil" do
|
69
|
+
step_pair = StepPair.new(@group, "foo") do
|
70
|
+
end
|
71
|
+
step_pair.should_not be_valid
|
72
|
+
end
|
73
|
+
it "should return false if up_step is nil and down_step is not nil" do
|
74
|
+
step_pair = StepPair.new(@group, "foo") do
|
75
|
+
down {}
|
76
|
+
end
|
77
|
+
step_pair.should_not be_valid
|
78
|
+
end
|
79
|
+
it "should return false if up_step is not nil and down_step is nil" do
|
80
|
+
step_pair = StepPair.new(@group, "foo") do
|
81
|
+
up {}
|
82
|
+
end
|
83
|
+
step_pair.should_not be_valid
|
84
|
+
end
|
85
|
+
it "should return true if neither up_step and down_step is nil" do
|
86
|
+
step_pair = StepPair.new(@group, "foo") do
|
87
|
+
up {}
|
88
|
+
down {}
|
89
|
+
end
|
90
|
+
step_pair.should be_valid
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe "when #todo is called" do
|
95
|
+
it "should create a Todo object that saves the message" do
|
96
|
+
pair = StepPair.new(@group, 'foo') { todo 'bar' }
|
97
|
+
pair.todos.map(&:message).should == ['bar']
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should create a Todo object that saves the location of the #todo call" do
|
101
|
+
pair = StepPair.new(@group, 'foo') { todo 'bar' }; line_num = __LINE__
|
102
|
+
pair.todos.first.location.should == [__FILE__, line_num].join(':')
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
it "should have a unix_name property that consists of the regular name with characters sanitized" do
|
107
|
+
pair = StepPair.new(@group, "This be a test, matey! ARRR!!") {}
|
108
|
+
pair.unix_name.should == 'this_be_a_test_matey_arrr'
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,154 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), %w[.. spec_helper])
|
2
|
+
|
3
|
+
include Sqrbl
|
4
|
+
|
5
|
+
describe Step do
|
6
|
+
before(:each) do
|
7
|
+
@pair = mock('StepPair')
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should evaluate the block in its own context" do
|
11
|
+
step = Step.new(@pair, :skip_block_evaluation => true) do
|
12
|
+
hello_world()
|
13
|
+
end
|
14
|
+
step.should_receive(:hello_world)
|
15
|
+
step.send(:evaluate_block!)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should delegate method_missing calls back to the step_pair object" do
|
19
|
+
@pair.should_receive(:goodbye_world)
|
20
|
+
step = Step.new(@pair) do
|
21
|
+
goodbye_world()
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
it "methods defined in the step's block should become available as methods on the Step instance" do
|
26
|
+
step = Step.new(@pair) do
|
27
|
+
def hello_world
|
28
|
+
"Hello, world!"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
step.should respond_to(:hello_world)
|
32
|
+
step.hello_world.should == "Hello, world!"
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "when #todo is called" do
|
36
|
+
it "should create a Todo object that saves the message" do
|
37
|
+
step = Step.new(@pair) { todo 'foo' }
|
38
|
+
step.todos.map(&:message).should == ['foo']
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should create a Todo object that saves the location of the #todo call" do
|
42
|
+
step = Step.new(@pair) { todo 'foo' }; line_num = __LINE__
|
43
|
+
step.todos.first.location.should == [__FILE__, line_num].join(':')
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should prepend its argument with '--> todo ([file], line [line #]):' and put it in #output" do
|
47
|
+
line_num = 0
|
48
|
+
step = Step.new(@pair) do
|
49
|
+
todo 'Fix a terrible issue'; line_num = __LINE__
|
50
|
+
end
|
51
|
+
|
52
|
+
step.output.should =~ /^--> todo \(.*\)\:/i
|
53
|
+
step.output.should include(__FILE__)
|
54
|
+
step.output.should =~ Regexp.new("line #{line_num}")
|
55
|
+
step.output.should include('Fix a terrible issue')
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "when #comment is called" do
|
60
|
+
it "should prepend its argument with '-- ' and put it in #output" do
|
61
|
+
message = "Here's something you should probably be aware of."
|
62
|
+
step = Step.new(@pair) { comment(message) }
|
63
|
+
step.output.should =~ Regexp.new('^-- ' + message)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "when #block_comment is called" do
|
68
|
+
it "should surround its argument with /* and */ on newlines and put the whole thing in #output" do
|
69
|
+
message = "Here's something you should probably be aware of."
|
70
|
+
step = Step.new(@pair) { block_comment { message } }
|
71
|
+
step.output.should =~ /^\/\*/
|
72
|
+
step.output.should =~ Regexp.new('^ ' + message)
|
73
|
+
step.output.should =~ /^\*\//
|
74
|
+
end
|
75
|
+
|
76
|
+
describe "and given a string with extra spaces (as, e.g., a heredoc)" do
|
77
|
+
it "should unindent the argument before putting it in #output" do
|
78
|
+
step = Step.new(@pair) do
|
79
|
+
block_comment do
|
80
|
+
<<-EOF
|
81
|
+
Foo.
|
82
|
+
Bar.
|
83
|
+
Baz.
|
84
|
+
EOF
|
85
|
+
end
|
86
|
+
end
|
87
|
+
step.output.should =~ /^ Foo./
|
88
|
+
step.output.should =~ /^ Bar./
|
89
|
+
step.output.should =~ /^ Baz./
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe "when #warning is called" do
|
95
|
+
it "should create a Todo object with type=:warning that saves the message" do
|
96
|
+
step = Step.new(@pair) { warning 'Danger, Will Robinson!' }
|
97
|
+
step.todos.map(&:type).should == [:warning]
|
98
|
+
step.todos.map(&:message).should == ['Danger, Will Robinson!']
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should write a giant ASCII warning to #output" do
|
102
|
+
line_num = 0
|
103
|
+
step = Step.new(@pair) do
|
104
|
+
warning 'Danger, Will Robinson!'; line_num = __LINE__
|
105
|
+
end
|
106
|
+
step.output.should include(Step::GiantWarningSeparator)
|
107
|
+
step.output.should include(Step::GiantWarningText)
|
108
|
+
step.output.should include('Danger, Will Robinson!')
|
109
|
+
step.output.should =~ Regexp.new("line #{line_num}")
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
describe "when #action is called with a string and a block" do
|
114
|
+
before(:each) do
|
115
|
+
@step = Step.new(@pair) do
|
116
|
+
action "Do something" do
|
117
|
+
<<-EOF
|
118
|
+
Hello world!
|
119
|
+
EOF
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
it "should treat the string as a comment" do
|
125
|
+
@step.output.should =~ /^-- Do something/
|
126
|
+
end
|
127
|
+
|
128
|
+
it "should unindent the return value from the block and put it in #output" do
|
129
|
+
@step.output.should =~ /^Hello world!/
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
describe "#insert_into" do
|
134
|
+
it "should produce an INSERT INTO fragment" do
|
135
|
+
@step = Step.new(@pair) {}
|
136
|
+
insert_fragment = @step.insert_into 'new_widgets', {
|
137
|
+
:name => 'widget_name',
|
138
|
+
:part_num => 'CONCAT("X_", part_number)',
|
139
|
+
:note => '"Imported from old_widgets"',
|
140
|
+
}
|
141
|
+
# puts '<pre>%s</pre>' % insert_fragment
|
142
|
+
|
143
|
+
insert_fragment.should include('new_widgets')
|
144
|
+
|
145
|
+
insert_fragment.should =~ /^\s*name/
|
146
|
+
insert_fragment.should =~ /^\s*part_num/
|
147
|
+
insert_fragment.should =~ /^\s*note/
|
148
|
+
|
149
|
+
insert_fragment.should include('widget_name AS name')
|
150
|
+
insert_fragment.should include('CONCAT("X_", part_number) AS part_num')
|
151
|
+
insert_fragment.should include('"Imported from old_widgets" AS note')
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
data/tasks/ann.rake
ADDED
@@ -0,0 +1,80 @@
|
|
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
|
data/tasks/bones.rake
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
|
2
|
+
if HAVE_BONES
|
3
|
+
|
4
|
+
namespace :bones do
|
5
|
+
|
6
|
+
desc 'Show the PROJ open struct'
|
7
|
+
task :debug do |t|
|
8
|
+
atr = if t.application.top_level_tasks.length == 2
|
9
|
+
t.application.top_level_tasks.pop
|
10
|
+
end
|
11
|
+
|
12
|
+
if atr then Bones::Debug.show_attr(PROJ, atr)
|
13
|
+
else Bones::Debug.show PROJ end
|
14
|
+
end
|
15
|
+
|
16
|
+
end # namespace :bones
|
17
|
+
|
18
|
+
end # HAVE_BONES
|
19
|
+
|
20
|
+
# EOF
|