forked from bonzini/gst-visualgst
-
Notifications
You must be signed in to change notification settings - Fork 0
/
PackageBuilder.st
304 lines (271 loc) · 7.26 KB
/
PackageBuilder.st
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
#!/usr/bin/env gst
"
PackageBuilder.st
by Stefan Schmiedl
with ideas from Nico and Gwen
usage:
PackageBuilder new
name: 'Iliad-Core';
namespace: 'Iliad';
prereq: 'Sport';
prereq: 'Iconv';
...
testBuilder: (TestBuilder on: 'Tests' withExtension: '.st');
filein: 'Utilities/IliadObject.st';
filein: 'Utilities/Support.st';
...
buildXml
"
Object subclass: Indenter [
<comment: 'Decorate a WriteStream with indenting methods.'>
|stream indent indentString|
Indenter class >> on: aStream [
<category: 'instance creation'>
<comment: 'Answer a new indenter writing to aStream.'>
^ self new on: aStream
]
on: aStream [
<category: 'initialization'>
<comment: 'A new indenter starts with no indentation.'>
stream := aStream.
indent := ''.
indentString := ' '
]
indent [
<category: 'indenting'>
<comment: 'Write indent to stream. This assumes that stream is currently at the start of a new line.'>
stream nextPutAll: indent
]
indentMore [
<category: 'indenting'>
<comment: 'Increase indentation, see indentLess.'>
indent := indent , indentString
]
indentLess [
<category: 'indenting'>
<comment: 'Decrease indentation, see indentMore.'>
( indent size < indentString size )
ifTrue: [ indent := '' ]
ifFalse: [
indent := indent allButLast: indentString size
]
]
nextPutAll: aString [
<category: 'streaming'>
stream nextPutAll: aString
]
nextPut: aChar [
<category: 'streaming'>
stream nextPut: aChar
]
tag: aString [
<category: 'xml-printing'>
<comment: 'Write <aString> to stream.'>
stream nextPut: $<; nextPutAll: aString; nextPut: $>
]
indentNl: aBlock [
<category: 'printing'>
<comment: 'Basically printNl with indent. aBlock can use stream as parameter.'>
self indent.
aBlock cull: stream.
stream nl
]
wrap: aString do: aBlock [
<category: 'xml-printing'>
<comment: 'Write opening and closing tags on separate lines, use increased indentation in between.'>
self indentNl: [ self tag: aString ].
self indentMore.
aBlock value.
self indentLess.
self indentNl: [ self tag: '/',aString ].
]
wrap: aString around: contentString [
<category: 'xml-printing'>
<comment: 'Write opening and closing tags on the same line as the contentString.'>
self indentNl: [ :aStream |
self
tag: aString;
nextPutAll: contentString;
tag: '/',aString
]
]
wrap: aString aroundEachOf: aCollection [
<category: 'xml-printing'>
<comment: 'Wrap tag aString around each element of aCollection.'>
aCollection do: [ :item | self wrap: aString around: item ]
]
]
Object subclass: TestBuilder [
<comment: 'A testbuilder scrounges the filesystem for smalltalk files and test cases and writes the gathered data in a format suitable for use in package.xml.'>
| testroot pattern namespace |
testroot [
<category: 'accessing'>
^ testroot
]
testroot: aString [
<category: 'accessing'>
testroot := File name: aString
]
pattern [
<category: 'accessing'>
^ pattern
]
pattern: aString [
<category: 'accessing'>
pattern := aString
]
namespace [
<category: 'accessing'>
^ namespace
]
namespace: aString [
<category: 'accessing'>
namespace := aString
]
collectFiles [
<category: 'accessing'>
<comment: 'Answer a list of files below the testroot directory matching the specified filename pattern.'>
|files|
files := OrderedCollection new.
( self testroot ) allFilesMatching: self pattern do: [ :f |
files add: f
].
^ files
]
collectTestsIn: aCollection [
<category: 'accessing'>
<comment: 'Answer a list of class names highly suspect of being used in SUnit.'>
|tests|
tests := OrderedCollection new.
aCollection do: [ :file |
file contents onOccurrencesOfRegex: 'subclass: (.*Test)' do: [ :rr |
tests add: ( rr at: 1 )
]
].
^ tests
]
renderTests: aCollection on: aStream [
<category: 'accessing'>
<comment: 'Write test class names with package namespace.'>
aStream wrap: 'sunit' do: [
aCollection do: [ :tc |
aStream indentNl: [
aStream
nextPutAll: self namespace;
nextPut: $.;
nextPutAll: tc
]
]
]
]
renderXmlOn: aStream [
<category: 'accessing'>
<comment: 'Write the test subpackage specification to aStream.'>
aStream wrap: 'test' do: [ |files tests paths|
files := self collectFiles.
tests := self collectTestsIn: files.
paths := files collect: [ :f | self testroot parent pathTo: f ].
aStream wrap: 'filein' aroundEachOf: paths.
aStream wrap: 'file' aroundEachOf: paths.
self renderTests: tests on: aStream.
]
]
]
Object subclass: PackageBuilder [
|name namespace prereqs provides testBuilder start fileins ressources|
PackageBuilder class >> new [
^ self basicNew initialize
]
initialize [
prereqs := OrderedCollection new.
provides := OrderedCollection new.
fileins := OrderedCollection new.
ressources := OrderedCollection new
]
name [
<category: 'accessing'>
^ name
]
name: aString [
<category: 'accessing'>
name := aString
]
namespace [
<category: 'accessing'>
^ namespace
]
namespace: aString [
<category: 'accessing'>
namespace := aString
]
prereqs [
<category: 'accessing'>
^ prereqs
]
prereq: aString [
<category: 'accessing'>
prereqs add: aString
]
provides [
<category: 'accessing'>
^ provides
]
provides: aString [
<category: 'accessing'>
provides add: aString
]
start [
<category: 'accessing'>
^ start
]
start: aString [
<category: 'accessing'>
start := aString
]
fileins [
<category: 'accessing'>
^ fileins
]
filein: aString [
<category: 'accessing'>
fileins add: aString
]
ressource: aString [
<category: 'accessing'>
ressources add: aString
]
testsBelow: aDirname matching: aPattern [
<category: 'accessing'>
<comment: 'Make a testbuilder for the given specs.'>
testBuilder :=
TestBuilder new
testroot: aDirname;
pattern: aPattern;
namespace: self namespace.
]
renderXmlOn: aStream [
<category: 'xml-printing'>
<comment: 'Write a representation to aStream suitable for use in package.xml.'>
aStream wrap: 'package' do: [
aStream
wrap: 'name' around: self name;
wrap: 'namespace' around: self namespace.
self prereqs do: [ :p | aStream wrap: 'prereq' around: p ].
self provides do: [ :p | aStream wrap: 'provides' around: p ].
testBuilder ifNotNil: [ testBuilder renderXmlOn: aStream ].
aStream wrap: 'filein' aroundEachOf: fileins.
aStream wrap: 'file' aroundEachOf: fileins.
"aStream wrap: 'filein' aroundEachOf: ressources."
aStream wrap: 'file' aroundEachOf: ressources.
aStream wrap: 'start' around: start.
]
]
buildXml [
<category: 'xml-printing'>
<comment: 'This convenience method writes the xml package spec to stdout.'>
self renderXmlOn: ( Indenter on: FileStream stdout )
]
]
Eval [
Smalltalk arguments do: [ :filename | FileStream fileIn: filename ]
]