remogatto-ffi-generator 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +4 -0
- data/History.txt +10 -0
- data/README.rdoc +89 -0
- data/Rakefile +36 -0
- data/bin/ffi-gen +7 -0
- data/examples/Rakefile +4 -0
- data/examples/interfaces/libc.i +26 -0
- data/examples/interfaces/wiiuse.i +672 -0
- data/lib/ffi-generator.rb +49 -0
- data/lib/generator/application.rb +69 -0
- data/lib/generator/generator.rb +304 -0
- data/lib/generator/generatortask.rb +45 -0
- data/spec/ffi-generator_spec.rb +7 -0
- data/spec/generator/generator_spec.rb +237 -0
- data/spec/generator/swig/constants.i +3 -0
- data/spec/generator/swig/enums.i +5 -0
- data/spec/generator/swig/functions.i +22 -0
- data/spec/generator/swig/structs.i +25 -0
- data/spec/generator/swig/testlib.i +47 -0
- data/spec/generator/swig/typedefs.i +5 -0
- data/spec/generator/swig/types.i +51 -0
- data/spec/generator/swig/unions.i +6 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +27 -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 +50 -0
- data/tasks/rubyforge.rake +55 -0
- data/tasks/setup.rb +300 -0
- data/tasks/spec.rake +54 -0
- data/tasks/svn.rake +47 -0
- data/tasks/test.rake +40 -0
- metadata +124 -0
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), %w[.. spec_helper])
|
|
2
|
+
|
|
3
|
+
include FFI
|
|
4
|
+
|
|
5
|
+
share_examples_for "All generation specs" do
|
|
6
|
+
after :all do
|
|
7
|
+
remove_xml
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
describe Generator::Parser do
|
|
12
|
+
it_should_behave_like 'All generation specs'
|
|
13
|
+
before :all do
|
|
14
|
+
@node = generate_xml_wrap_from('testlib')
|
|
15
|
+
end
|
|
16
|
+
it 'should generate ruby ffi wrap code' do
|
|
17
|
+
Generator::Parser.generate(@node).should == <<EOC
|
|
18
|
+
|
|
19
|
+
module TestLib
|
|
20
|
+
extend FFI::Library
|
|
21
|
+
CONST_1 = 0x10
|
|
22
|
+
CONST_2 = 0x20
|
|
23
|
+
ENUM_1 = 0
|
|
24
|
+
ENUM_2 = 1
|
|
25
|
+
ENUM_3 = 2
|
|
26
|
+
|
|
27
|
+
class UnionT < FFI::Union
|
|
28
|
+
layout(
|
|
29
|
+
:c, :char,
|
|
30
|
+
:f, :float
|
|
31
|
+
)
|
|
32
|
+
end
|
|
33
|
+
class TestStruct < FFI::Struct
|
|
34
|
+
layout(
|
|
35
|
+
:i, :int,
|
|
36
|
+
:c, :char,
|
|
37
|
+
:b, :uchar
|
|
38
|
+
)
|
|
39
|
+
end
|
|
40
|
+
class TestStruct3 < FFI::Struct
|
|
41
|
+
layout(
|
|
42
|
+
:c, :char
|
|
43
|
+
)
|
|
44
|
+
end
|
|
45
|
+
class TestStruct2 < FFI::Struct
|
|
46
|
+
layout(
|
|
47
|
+
:s, TestStruct,
|
|
48
|
+
:s_3, TestStruct3,
|
|
49
|
+
:e, :int,
|
|
50
|
+
:func, :pointer,
|
|
51
|
+
:u, UnionT
|
|
52
|
+
)
|
|
53
|
+
end
|
|
54
|
+
attach_function :get_int, [ :pointer ], :int
|
|
55
|
+
attach_function :get_char, [ :pointer ], :char
|
|
56
|
+
attach_function :func_with_enum, [ :int ], :int
|
|
57
|
+
attach_function :func_with_enum_2, [ :int ], :int
|
|
58
|
+
attach_function :func_with_typedef, [ ], :uchar
|
|
59
|
+
|
|
60
|
+
end
|
|
61
|
+
EOC
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
describe Generator::Constant do
|
|
66
|
+
it_should_behave_like 'All generation specs'
|
|
67
|
+
before :all do
|
|
68
|
+
@node = generate_xml_wrap_from('constants')
|
|
69
|
+
end
|
|
70
|
+
it 'should return a ruby constant assignment' do
|
|
71
|
+
Generator::Constant.new(@node / 'constant').to_s.should == "CONST_1 = 0x10"
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
describe Generator::Enum do
|
|
76
|
+
before :all do
|
|
77
|
+
@node = generate_xml_wrap_from('enums')
|
|
78
|
+
end
|
|
79
|
+
it 'should generate constants' do
|
|
80
|
+
Generator::Enum.new((@node / 'enum')[0]).to_s.should == <<EOE
|
|
81
|
+
ENUM_1 = 0
|
|
82
|
+
ENUM_2 = 1
|
|
83
|
+
ENUM_3 = 2
|
|
84
|
+
EOE
|
|
85
|
+
end
|
|
86
|
+
it 'should generate constants starting from the latest assignment' do
|
|
87
|
+
Generator::Enum.new((@node / 'enum')[1]).to_s.should == <<EOE
|
|
88
|
+
ENUM_21 = 2
|
|
89
|
+
ENUM_22 = 3
|
|
90
|
+
ENUM_23 = 4
|
|
91
|
+
EOE
|
|
92
|
+
Generator::Enum.new((@node / 'enum')[2]).to_s.should == <<EOE
|
|
93
|
+
ENUM_31 = 0
|
|
94
|
+
ENUM_32 = 5
|
|
95
|
+
ENUM_33 = 6
|
|
96
|
+
EOE
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
describe Generator::Type do
|
|
101
|
+
it_should_behave_like 'All generation specs'
|
|
102
|
+
before :all do
|
|
103
|
+
@node = generate_xml_wrap_from('types')
|
|
104
|
+
end
|
|
105
|
+
it 'should generate string type' do
|
|
106
|
+
Generator::Type.new((@node / 'cdecl')[0]).to_s.should == ':string'
|
|
107
|
+
end
|
|
108
|
+
it 'should generate pointer type' do
|
|
109
|
+
Generator::Type.new((@node / 'cdecl')[1]).to_s.should == ':pointer'
|
|
110
|
+
end
|
|
111
|
+
it 'should generate array type' do
|
|
112
|
+
Generator::Type.new((@node / 'cdecl')[2]).to_s.should == '[:int, 5]'
|
|
113
|
+
Generator::Type.new((@node / 'cdecl')[3]).to_s.should == '[:string, 5]'
|
|
114
|
+
end
|
|
115
|
+
it 'should generate struct type' do
|
|
116
|
+
Generator::Type.new((@node / 'cdecl')[5]).to_s.should == 'TestStruct'
|
|
117
|
+
end
|
|
118
|
+
it 'should generate struct array type' do
|
|
119
|
+
Generator::Type.new((@node / 'cdecl')[6]).to_s.should == '[TestStruct, 5]'
|
|
120
|
+
end
|
|
121
|
+
it 'should generate enum array type' do
|
|
122
|
+
Generator::Type.new((@node / 'cdecl')[7]).to_s.should == '[:int, 5]'
|
|
123
|
+
end
|
|
124
|
+
it 'should generate const type' do
|
|
125
|
+
Generator::Type.new((@node / 'cdecl')[8]).to_s.should == ':int'
|
|
126
|
+
Generator::Type.new((@node / 'cdecl')[9]).to_s.should == ':string'
|
|
127
|
+
end
|
|
128
|
+
Generator::TYPES.sort.each_with_index do |type, i|
|
|
129
|
+
it "should generate #{type[0]} type" do
|
|
130
|
+
Generator::Type.new((@node / 'cdecl')[i + 10]).to_s.should == type[1]
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
describe Generator::Function do
|
|
136
|
+
it_should_behave_like 'All generation specs'
|
|
137
|
+
before :all do
|
|
138
|
+
@node = generate_xml_wrap_from('functions')
|
|
139
|
+
end
|
|
140
|
+
it 'should return a properly generated attach_method' do
|
|
141
|
+
Generator::Function.new((@node / 'cdecl')[0]).to_s.should == "attach_function :func_1, [ :char, :int ], :int"
|
|
142
|
+
end
|
|
143
|
+
it 'should properly generate pointer arguments' do
|
|
144
|
+
Generator::Function.new((@node / 'cdecl')[1]).to_s.should == "attach_function :func_2, [ :pointer, :pointer ], :uint"
|
|
145
|
+
end
|
|
146
|
+
it 'should properly generate string arguments' do
|
|
147
|
+
Generator::Function.new((@node / 'cdecl')[2]).to_s.should == "attach_function :func_3, [ :string ], :void"
|
|
148
|
+
end
|
|
149
|
+
it 'should properly generate return type' do
|
|
150
|
+
Generator::Function.new((@node / 'cdecl')[3]).to_s.should == "attach_function :func_4, [ :int ], :string"
|
|
151
|
+
end
|
|
152
|
+
it 'should properly generate void return type' do
|
|
153
|
+
Generator::Function.new((@node / 'cdecl')[4]).to_s.should == "attach_function :func_5, [ ], :void"
|
|
154
|
+
end
|
|
155
|
+
it 'should properly generate pointer of pointer arguments' do
|
|
156
|
+
Generator::Function.new((@node / 'cdecl')[5]).to_s.should == "attach_function :func_6, [ :pointer ], :void"
|
|
157
|
+
end
|
|
158
|
+
it 'should properly generate enum arguments' do
|
|
159
|
+
Generator::Function.new((@node / 'cdecl')[6]).to_s.should == "attach_function :func_7, [ :int ], :void"
|
|
160
|
+
end
|
|
161
|
+
it 'should properly generate enum return type' do
|
|
162
|
+
Generator::Function.new((@node / 'cdecl')[7]).to_s.should == "attach_function :func_8, [ ], :int"
|
|
163
|
+
end
|
|
164
|
+
it 'should properly generate struct arguments' do
|
|
165
|
+
Generator::Function.new((@node / 'cdecl')[9]).to_s.should == "attach_function :func_9, [ TestStruct ], :void"
|
|
166
|
+
end
|
|
167
|
+
it 'should properly generate struct return type' do
|
|
168
|
+
Generator::Function.new((@node / 'cdecl')[10]).to_s.should == "attach_function :func_10, [ ], TestStruct"
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
describe Generator::Structure do
|
|
173
|
+
it_should_behave_like 'All generation specs'
|
|
174
|
+
before :all do
|
|
175
|
+
@node = generate_xml_wrap_from('structs')
|
|
176
|
+
end
|
|
177
|
+
it 'should properly generate the layout of a FFI::Struct class' do
|
|
178
|
+
Generator::Structure.new((@node / 'class')[0]).to_s.should == <<EOC
|
|
179
|
+
class TestStruct1 < FFI::Struct
|
|
180
|
+
layout(
|
|
181
|
+
:i, :int,
|
|
182
|
+
:c, :char,
|
|
183
|
+
:s, :string,
|
|
184
|
+
:a, [:char, 5]
|
|
185
|
+
)
|
|
186
|
+
end
|
|
187
|
+
EOC
|
|
188
|
+
|
|
189
|
+
end
|
|
190
|
+
it 'should properly generate the layout of a FFI::Struct containing pointer field' do
|
|
191
|
+
Generator::Structure.new((@node / 'class')[1]).to_s.should == <<EOC
|
|
192
|
+
class TestStruct2 < FFI::Struct
|
|
193
|
+
layout(
|
|
194
|
+
:ptr, :pointer
|
|
195
|
+
)
|
|
196
|
+
end
|
|
197
|
+
EOC
|
|
198
|
+
end
|
|
199
|
+
it 'should properly generate the layout of a FFI::Struct containing array field' do
|
|
200
|
+
Generator::Structure.new((@node / 'class')[2]).to_s.should == <<EOC
|
|
201
|
+
class TestStruct3 < FFI::Struct
|
|
202
|
+
layout(
|
|
203
|
+
:c, [:char, 5]
|
|
204
|
+
)
|
|
205
|
+
end
|
|
206
|
+
EOC
|
|
207
|
+
|
|
208
|
+
end
|
|
209
|
+
it 'should properly generate the layout of a FFI::Struct containing array field' do
|
|
210
|
+
Generator::Structure.new((@node / 'class')[3]).to_s.should == <<EOC
|
|
211
|
+
class TestStruct4 < FFI::Struct
|
|
212
|
+
layout(
|
|
213
|
+
:s, [TestStruct3, 5]
|
|
214
|
+
)
|
|
215
|
+
end
|
|
216
|
+
EOC
|
|
217
|
+
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
describe Generator::Union do
|
|
222
|
+
it_should_behave_like 'All generation specs'
|
|
223
|
+
before :all do
|
|
224
|
+
@node = generate_xml_wrap_from('unions')
|
|
225
|
+
end
|
|
226
|
+
it 'should properly generate the layout of a FFI::Union class' do
|
|
227
|
+
Generator::Union.new((@node / 'class')[0]).to_s.should == <<EOC
|
|
228
|
+
class UnionT < FFI::Union
|
|
229
|
+
layout(
|
|
230
|
+
:c, :char,
|
|
231
|
+
:f, :float
|
|
232
|
+
)
|
|
233
|
+
end
|
|
234
|
+
EOC
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
%module function_testlib
|
|
2
|
+
|
|
3
|
+
int func_1(char c, int i);
|
|
4
|
+
unsigned int func_2(int* p1, int* p2);
|
|
5
|
+
void func_3(char* str);
|
|
6
|
+
char *func_4(int i);
|
|
7
|
+
extern void func_5();
|
|
8
|
+
void func_6(void** ptr);
|
|
9
|
+
void func_7(enum e e1);
|
|
10
|
+
|
|
11
|
+
enum e { E_1, E_2 };
|
|
12
|
+
|
|
13
|
+
enum e func_8();
|
|
14
|
+
|
|
15
|
+
struct test_struct {
|
|
16
|
+
char c;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
void func_9(struct test_struct s);
|
|
20
|
+
struct test_struct func_10();
|
|
21
|
+
|
|
22
|
+
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
%module test_struct
|
|
2
|
+
|
|
3
|
+
struct test_struct_1 {
|
|
4
|
+
int i;
|
|
5
|
+
char c;
|
|
6
|
+
const char* s;
|
|
7
|
+
const char a[5];
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
struct test_struct_2 {
|
|
11
|
+
int* ptr;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
struct test_struct_3 {
|
|
15
|
+
char c[5];
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
struct test_struct_4 {
|
|
19
|
+
struct test_struct_3 s[5];
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
struct test_struct_5 {
|
|
23
|
+
struct test_struct_4 s;
|
|
24
|
+
};
|
|
25
|
+
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
%module testlib
|
|
2
|
+
|
|
3
|
+
%{
|
|
4
|
+
module TestLib
|
|
5
|
+
extend FFI::Library
|
|
6
|
+
%}
|
|
7
|
+
|
|
8
|
+
#define CONST_1 0x10
|
|
9
|
+
#define CONST_2 0x20
|
|
10
|
+
|
|
11
|
+
typedef unsigned char byte;
|
|
12
|
+
typedef void (*PFI)(char*, char*);
|
|
13
|
+
typedef enum e_1 {
|
|
14
|
+
ENUM_1, ENUM_2, ENUM_3
|
|
15
|
+
} enum_t;
|
|
16
|
+
|
|
17
|
+
union union_t {
|
|
18
|
+
char c;
|
|
19
|
+
float f;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
struct test_struct {
|
|
23
|
+
int i;
|
|
24
|
+
char c;
|
|
25
|
+
byte b;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
typedef struct {
|
|
29
|
+
char c;
|
|
30
|
+
} test_struct_3;
|
|
31
|
+
|
|
32
|
+
struct test_struct_2 {
|
|
33
|
+
struct test_struct s;
|
|
34
|
+
test_struct_3 s_3;
|
|
35
|
+
enum_t e;
|
|
36
|
+
PFI func;
|
|
37
|
+
union_t u;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
int get_int(struct test_struct* s);
|
|
41
|
+
char get_char(struct test_struct* s);
|
|
42
|
+
int func_with_enum(enum e_1 e);
|
|
43
|
+
int func_with_enum_2(enum_t e);
|
|
44
|
+
byte func_with_typedef();
|
|
45
|
+
%{
|
|
46
|
+
end
|
|
47
|
+
%}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
%module types_test
|
|
2
|
+
|
|
3
|
+
char *string;
|
|
4
|
+
void *ptr;
|
|
5
|
+
|
|
6
|
+
int array[5];
|
|
7
|
+
char* ptr_array[5];
|
|
8
|
+
|
|
9
|
+
struct test_struct {
|
|
10
|
+
char c;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
enum e { E_1, E_2, E_3 };
|
|
14
|
+
|
|
15
|
+
struct test_struct ts;
|
|
16
|
+
struct test_struct a[5];
|
|
17
|
+
enum e enum_array[5];
|
|
18
|
+
|
|
19
|
+
const int ci;
|
|
20
|
+
const char* cstring;
|
|
21
|
+
|
|
22
|
+
char c;
|
|
23
|
+
double d;
|
|
24
|
+
float f;
|
|
25
|
+
int i;
|
|
26
|
+
long l;
|
|
27
|
+
long int li;
|
|
28
|
+
long long ll;
|
|
29
|
+
long long int lli;
|
|
30
|
+
long unsigned int lui;
|
|
31
|
+
short s;
|
|
32
|
+
signed char sc;
|
|
33
|
+
signed int si;
|
|
34
|
+
signed long sl;
|
|
35
|
+
signed long int sli;
|
|
36
|
+
signed long long sll;
|
|
37
|
+
signed long long int slli;
|
|
38
|
+
signed short ss;
|
|
39
|
+
signed short int ssi;
|
|
40
|
+
unsigned char uc;
|
|
41
|
+
unsigned int ui;
|
|
42
|
+
unsigned long ul;
|
|
43
|
+
unsigned long int uli;
|
|
44
|
+
unsigned long long ull;
|
|
45
|
+
unsigned long long int ulli;
|
|
46
|
+
unsigned short us;
|
|
47
|
+
unsigned short int usi;
|
|
48
|
+
void v;
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'spec'
|
|
3
|
+
|
|
4
|
+
require File.expand_path(
|
|
5
|
+
File.join(File.dirname(__FILE__), %w[.. lib ffi-generator]))
|
|
6
|
+
|
|
7
|
+
Spec::Runner.configure do |config|
|
|
8
|
+
# == Mock Framework
|
|
9
|
+
#
|
|
10
|
+
# RSpec uses it's own mocking framework by default. If you prefer to
|
|
11
|
+
# use mocha, flexmock or RR, uncomment the appropriate line:
|
|
12
|
+
#
|
|
13
|
+
# config.mock_with :mocha
|
|
14
|
+
# config.mock_with :flexmock
|
|
15
|
+
# config.mock_with :rr
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def generate_xml_wrap_from(fn)
|
|
19
|
+
`swig -xml spec/generator/swig/#{fn + '.i'}`
|
|
20
|
+
Nokogiri::XML(File.open(File.join('spec/generator/swig/', "#{fn}_wrap.xml")))
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def remove_xml
|
|
24
|
+
FileUtils.rm(Dir.glob('spec/generator/swig/*.xml'))
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# EOF
|
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
|