maruto 0.0.3 → 0.0.4
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/.travis.yml +11 -0
- data/README.md +7 -3
- data/Rakefile +7 -1
- data/fixtures/magento_root/app/code/core/Mage/A/etc/config.xml +0 -0
- data/fixtures/magento_root/app/code/core/Mage/B/etc/config.xml +0 -0
- data/fixtures/magento_root/app/code/core/Mage/C/etc/config.xml +0 -0
- data/fixtures/magento_root/app/code/core/Mage/D/etc/config.xml +0 -0
- data/fixtures/magento_root/app/etc/modules/Mage_All.xml +401 -0
- data/fixtures/magento_root/app/etc/modules/Mage_Api.xml +38 -0
- data/lib/maruto.rb +6 -2
- data/lib/maruto/base.rb +3 -0
- data/lib/maruto/magento_instance.rb +29 -0
- data/lib/maruto/module_configuration.rb +82 -0
- data/lib/maruto/module_definition.rb +108 -0
- data/lib/maruto/runner.rb +7 -0
- data/lib/maruto/version.rb +1 -1
- data/maruto.gemspec +2 -0
- data/spec/module_definition_spec.rb +236 -0
- data/spec/module_events_spec.rb +171 -0
- data/spec/module_version_spec.rb +69 -0
- data/spec/spec_helper.rb +8 -0
- metadata +38 -3
data/.travis.yml
ADDED
data/README.md
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
[](https://travis-ci.org/jlgeering/maruto)
|
|
2
|
+
|
|
3
|
+
|
|
1
4
|
# Maruto
|
|
2
5
|
|
|
3
6
|
Magento Ruby Tools
|
|
@@ -24,6 +27,7 @@ Or install it yourself as:
|
|
|
24
27
|
|
|
25
28
|
1. Fork it
|
|
26
29
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
27
|
-
3.
|
|
28
|
-
4.
|
|
29
|
-
5.
|
|
30
|
+
3. Run the tests (`rake test`)
|
|
31
|
+
4. Commit your changes (`git commit -am 'Add some feature'`)
|
|
32
|
+
5. Push to the branch (`git push origin my-new-feature`)
|
|
33
|
+
6. Create new Pull Request
|
data/Rakefile
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
<?xml version="1.0"?>
|
|
2
|
+
<!--
|
|
3
|
+
/**
|
|
4
|
+
* Magento
|
|
5
|
+
*
|
|
6
|
+
* NOTICE OF LICENSE
|
|
7
|
+
*
|
|
8
|
+
* This source file is subject to the Academic Free License (AFL 3.0)
|
|
9
|
+
* that is bundled with this package in the file LICENSE_AFL.txt.
|
|
10
|
+
* It is also available through the world-wide-web at this URL:
|
|
11
|
+
* http://opensource.org/licenses/afl-3.0.php
|
|
12
|
+
* If you did not receive a copy of the license and are unable to
|
|
13
|
+
* obtain it through the world-wide-web, please send an email
|
|
14
|
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
|
15
|
+
*
|
|
16
|
+
* DISCLAIMER
|
|
17
|
+
*
|
|
18
|
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
|
19
|
+
* versions in the future. If you wish to customize Magento for your
|
|
20
|
+
* needs please refer to http://www.magentocommerce.com for more information.
|
|
21
|
+
*
|
|
22
|
+
* @category Mage
|
|
23
|
+
* @package Mage_Core
|
|
24
|
+
* @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com)
|
|
25
|
+
* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
|
|
26
|
+
*/
|
|
27
|
+
-->
|
|
28
|
+
<config>
|
|
29
|
+
<modules>
|
|
30
|
+
<Mage_Core>
|
|
31
|
+
<active>true</active>
|
|
32
|
+
<codePool>core</codePool>
|
|
33
|
+
</Mage_Core>
|
|
34
|
+
<Mage_Eav>
|
|
35
|
+
<active>true</active>
|
|
36
|
+
<codePool>core</codePool>
|
|
37
|
+
<depends>
|
|
38
|
+
<Mage_Core/>
|
|
39
|
+
</depends>
|
|
40
|
+
</Mage_Eav>
|
|
41
|
+
<Mage_Page>
|
|
42
|
+
<active>true</active>
|
|
43
|
+
<codePool>core</codePool>
|
|
44
|
+
<depends>
|
|
45
|
+
<Mage_Core/>
|
|
46
|
+
</depends>
|
|
47
|
+
</Mage_Page>
|
|
48
|
+
<Mage_Install>
|
|
49
|
+
<active>true</active>
|
|
50
|
+
<codePool>core</codePool>
|
|
51
|
+
<depends>
|
|
52
|
+
<Mage_Core/>
|
|
53
|
+
</depends>
|
|
54
|
+
</Mage_Install>
|
|
55
|
+
<Mage_Admin>
|
|
56
|
+
<active>true</active>
|
|
57
|
+
<codePool>core</codePool>
|
|
58
|
+
<depends>
|
|
59
|
+
<Mage_Core/>
|
|
60
|
+
</depends>
|
|
61
|
+
</Mage_Admin>
|
|
62
|
+
<Mage_Rule>
|
|
63
|
+
<active>true</active>
|
|
64
|
+
<codePool>core</codePool>
|
|
65
|
+
<depends>
|
|
66
|
+
<Mage_Core/>
|
|
67
|
+
</depends>
|
|
68
|
+
</Mage_Rule>
|
|
69
|
+
<Mage_Adminhtml>
|
|
70
|
+
<active>true</active>
|
|
71
|
+
<codePool>core</codePool>
|
|
72
|
+
<depends>
|
|
73
|
+
<Mage_Admin/>
|
|
74
|
+
</depends>
|
|
75
|
+
</Mage_Adminhtml>
|
|
76
|
+
<Mage_AdminNotification>
|
|
77
|
+
<active>true</active>
|
|
78
|
+
<codePool>core</codePool>
|
|
79
|
+
<depends>
|
|
80
|
+
<Mage_Core/>
|
|
81
|
+
<Mage_Adminhtml/>
|
|
82
|
+
</depends>
|
|
83
|
+
</Mage_AdminNotification>
|
|
84
|
+
<Mage_Cron>
|
|
85
|
+
<active>true</active>
|
|
86
|
+
<codePool>core</codePool>
|
|
87
|
+
<depends>
|
|
88
|
+
<Mage_Core/>
|
|
89
|
+
</depends>
|
|
90
|
+
</Mage_Cron>
|
|
91
|
+
<Mage_Directory>
|
|
92
|
+
<active>true</active>
|
|
93
|
+
<codePool>core</codePool>
|
|
94
|
+
<depends>
|
|
95
|
+
<Mage_Core/>
|
|
96
|
+
</depends>
|
|
97
|
+
</Mage_Directory>
|
|
98
|
+
<Mage_Customer>
|
|
99
|
+
<active>true</active>
|
|
100
|
+
<codePool>core</codePool>
|
|
101
|
+
<depends>
|
|
102
|
+
<Mage_Eav/>
|
|
103
|
+
<Mage_Dataflow/>
|
|
104
|
+
<Mage_Directory/>
|
|
105
|
+
</depends>
|
|
106
|
+
</Mage_Customer>
|
|
107
|
+
<Mage_Catalog>
|
|
108
|
+
<active>true</active>
|
|
109
|
+
<codePool>core</codePool>
|
|
110
|
+
<depends>
|
|
111
|
+
<Mage_Eav/>
|
|
112
|
+
<Mage_Dataflow/>
|
|
113
|
+
<Mage_Cms/>
|
|
114
|
+
<Mage_Index/>
|
|
115
|
+
</depends>
|
|
116
|
+
</Mage_Catalog>
|
|
117
|
+
<Mage_CatalogRule>
|
|
118
|
+
<active>true</active>
|
|
119
|
+
<codePool>core</codePool>
|
|
120
|
+
<depends>
|
|
121
|
+
<Mage_Rule/>
|
|
122
|
+
<Mage_Catalog/>
|
|
123
|
+
<Mage_Customer/>
|
|
124
|
+
</depends>
|
|
125
|
+
</Mage_CatalogRule>
|
|
126
|
+
<Mage_CatalogIndex>
|
|
127
|
+
<active>true</active>
|
|
128
|
+
<codePool>core</codePool>
|
|
129
|
+
<depends>
|
|
130
|
+
<Mage_Catalog/>
|
|
131
|
+
<Mage_Eav/>
|
|
132
|
+
<Mage_CatalogRule/>
|
|
133
|
+
</depends>
|
|
134
|
+
</Mage_CatalogIndex>
|
|
135
|
+
<Mage_CatalogSearch>
|
|
136
|
+
<active>true</active>
|
|
137
|
+
<codePool>core</codePool>
|
|
138
|
+
<depends>
|
|
139
|
+
<Mage_Catalog/>
|
|
140
|
+
</depends>
|
|
141
|
+
</Mage_CatalogSearch>
|
|
142
|
+
<Mage_Sales>
|
|
143
|
+
<active>true</active>
|
|
144
|
+
<codePool>core</codePool>
|
|
145
|
+
<depends>
|
|
146
|
+
<Mage_Rule/>
|
|
147
|
+
<Mage_Catalog/>
|
|
148
|
+
<Mage_Customer/>
|
|
149
|
+
<Mage_Payment/>
|
|
150
|
+
</depends>
|
|
151
|
+
</Mage_Sales>
|
|
152
|
+
<Mage_SalesRule>
|
|
153
|
+
<active>true</active>
|
|
154
|
+
<codePool>core</codePool>
|
|
155
|
+
<depends>
|
|
156
|
+
<Mage_Rule/>
|
|
157
|
+
<Mage_Catalog/>
|
|
158
|
+
<Mage_Sales/>
|
|
159
|
+
</depends>
|
|
160
|
+
</Mage_SalesRule>
|
|
161
|
+
<Mage_Checkout>
|
|
162
|
+
<active>true</active>
|
|
163
|
+
<codePool>core</codePool>
|
|
164
|
+
<depends>
|
|
165
|
+
<Mage_Sales/>
|
|
166
|
+
<Mage_CatalogInventory/>
|
|
167
|
+
</depends>
|
|
168
|
+
</Mage_Checkout>
|
|
169
|
+
<Mage_Shipping>
|
|
170
|
+
<active>true</active>
|
|
171
|
+
<codePool>core</codePool>
|
|
172
|
+
<depends>
|
|
173
|
+
<Mage_Core/>
|
|
174
|
+
<Mage_Catalog/>
|
|
175
|
+
</depends>
|
|
176
|
+
</Mage_Shipping>
|
|
177
|
+
<Mage_Payment>
|
|
178
|
+
<active>true</active>
|
|
179
|
+
<codePool>core</codePool>
|
|
180
|
+
<depends>
|
|
181
|
+
<Mage_Core/>
|
|
182
|
+
<Mage_Catalog/>
|
|
183
|
+
</depends>
|
|
184
|
+
</Mage_Payment>
|
|
185
|
+
<Mage_Usa>
|
|
186
|
+
<active>true</active>
|
|
187
|
+
<codePool>core</codePool>
|
|
188
|
+
<depends>
|
|
189
|
+
<Mage_Sales/>
|
|
190
|
+
<Mage_Shipping/>
|
|
191
|
+
</depends>
|
|
192
|
+
</Mage_Usa>
|
|
193
|
+
<Mage_Paygate>
|
|
194
|
+
<active>true</active>
|
|
195
|
+
<codePool>core</codePool>
|
|
196
|
+
<depends>
|
|
197
|
+
<Mage_Payment/>
|
|
198
|
+
</depends>
|
|
199
|
+
</Mage_Paygate>
|
|
200
|
+
<Mage_Paypal>
|
|
201
|
+
<active>true</active>
|
|
202
|
+
<codePool>core</codePool>
|
|
203
|
+
<depends>
|
|
204
|
+
<Mage_Paygate/>
|
|
205
|
+
<Mage_Checkout/>
|
|
206
|
+
<Mage_Sales/>
|
|
207
|
+
</depends>
|
|
208
|
+
</Mage_Paypal>
|
|
209
|
+
<Mage_PaypalUk>
|
|
210
|
+
<active>true</active>
|
|
211
|
+
<codePool>core</codePool>
|
|
212
|
+
<depends>
|
|
213
|
+
<Mage_Paygate/>
|
|
214
|
+
<Mage_Checkout/>
|
|
215
|
+
<Mage_Sales/>
|
|
216
|
+
<Mage_Paypal/>
|
|
217
|
+
</depends>
|
|
218
|
+
</Mage_PaypalUk>
|
|
219
|
+
<Mage_GoogleCheckout>
|
|
220
|
+
<active>true</active>
|
|
221
|
+
<codePool>core</codePool>
|
|
222
|
+
<depends>
|
|
223
|
+
<Mage_Sales/>
|
|
224
|
+
<Mage_Payment/>
|
|
225
|
+
<Mage_Usa/>
|
|
226
|
+
</depends>
|
|
227
|
+
</Mage_GoogleCheckout>
|
|
228
|
+
<Mage_Log>
|
|
229
|
+
<active>true</active>
|
|
230
|
+
<codePool>core</codePool>
|
|
231
|
+
<depends>
|
|
232
|
+
<Mage_Core/>
|
|
233
|
+
<Mage_Customer/>
|
|
234
|
+
</depends>
|
|
235
|
+
</Mage_Log>
|
|
236
|
+
<Mage_Backup>
|
|
237
|
+
<active>true</active>
|
|
238
|
+
<codePool>core</codePool>
|
|
239
|
+
<depends>
|
|
240
|
+
<Mage_Core/>
|
|
241
|
+
</depends>
|
|
242
|
+
</Mage_Backup>
|
|
243
|
+
<Mage_Poll>
|
|
244
|
+
<active>true</active>
|
|
245
|
+
<codePool>core</codePool>
|
|
246
|
+
<depends>
|
|
247
|
+
<Mage_Core/>
|
|
248
|
+
<Mage_Cms/>
|
|
249
|
+
</depends>
|
|
250
|
+
</Mage_Poll>
|
|
251
|
+
<Mage_Rating>
|
|
252
|
+
<active>true</active>
|
|
253
|
+
<codePool>core</codePool>
|
|
254
|
+
<depends>
|
|
255
|
+
<Mage_Core/>
|
|
256
|
+
<Mage_Review/>
|
|
257
|
+
</depends>
|
|
258
|
+
</Mage_Rating>
|
|
259
|
+
<Mage_Review>
|
|
260
|
+
<active>true</active>
|
|
261
|
+
<codePool>core</codePool>
|
|
262
|
+
<depends>
|
|
263
|
+
<Mage_Catalog/>
|
|
264
|
+
<Mage_Core/>
|
|
265
|
+
</depends>
|
|
266
|
+
</Mage_Review>
|
|
267
|
+
<Mage_Tag>
|
|
268
|
+
<active>true</active>
|
|
269
|
+
<codePool>core</codePool>
|
|
270
|
+
<depends>
|
|
271
|
+
<Mage_Catalog/>
|
|
272
|
+
</depends>
|
|
273
|
+
</Mage_Tag>
|
|
274
|
+
<Mage_Cms>
|
|
275
|
+
<active>true</active>
|
|
276
|
+
<codePool>core</codePool>
|
|
277
|
+
<depends>
|
|
278
|
+
<Mage_Core/>
|
|
279
|
+
</depends>
|
|
280
|
+
</Mage_Cms>
|
|
281
|
+
<Mage_Reports>
|
|
282
|
+
<active>true</active>
|
|
283
|
+
<codePool>core</codePool>
|
|
284
|
+
<depends>
|
|
285
|
+
<Mage_Customer/>
|
|
286
|
+
<Mage_Catalog/>
|
|
287
|
+
<Mage_Sales/>
|
|
288
|
+
<Mage_Cms/>
|
|
289
|
+
</depends>
|
|
290
|
+
</Mage_Reports>
|
|
291
|
+
<Mage_Newsletter>
|
|
292
|
+
<active>true</active>
|
|
293
|
+
<codePool>core</codePool>
|
|
294
|
+
<depends>
|
|
295
|
+
<Mage_Core/>
|
|
296
|
+
<Mage_Customer/>
|
|
297
|
+
<Mage_Eav/>
|
|
298
|
+
<Mage_Widget/>
|
|
299
|
+
</depends>
|
|
300
|
+
</Mage_Newsletter>
|
|
301
|
+
<Mage_Tax>
|
|
302
|
+
<active>true</active>
|
|
303
|
+
<codePool>core</codePool>
|
|
304
|
+
<depends>
|
|
305
|
+
<Mage_Catalog/>
|
|
306
|
+
<Mage_Customer/>
|
|
307
|
+
</depends>
|
|
308
|
+
</Mage_Tax>
|
|
309
|
+
<Mage_Wishlist>
|
|
310
|
+
<active>true</active>
|
|
311
|
+
<codePool>core</codePool>
|
|
312
|
+
<depends>
|
|
313
|
+
<Mage_Customer/>
|
|
314
|
+
<Mage_Catalog/>
|
|
315
|
+
</depends>
|
|
316
|
+
</Mage_Wishlist>
|
|
317
|
+
<Mage_GoogleAnalytics>
|
|
318
|
+
<active>true</active>
|
|
319
|
+
<codePool>core</codePool>
|
|
320
|
+
<depends>
|
|
321
|
+
<Mage_Core/>
|
|
322
|
+
</depends>
|
|
323
|
+
</Mage_GoogleAnalytics>
|
|
324
|
+
<Mage_CatalogInventory>
|
|
325
|
+
<active>true</active>
|
|
326
|
+
<codePool>core</codePool>
|
|
327
|
+
<depends>
|
|
328
|
+
<Mage_Catalog/>
|
|
329
|
+
</depends>
|
|
330
|
+
</Mage_CatalogInventory>
|
|
331
|
+
<Mage_GiftMessage>
|
|
332
|
+
<active>true</active>
|
|
333
|
+
<codePool>core</codePool>
|
|
334
|
+
<depends>
|
|
335
|
+
<Mage_Catalog/>
|
|
336
|
+
<Mage_Sales/>
|
|
337
|
+
</depends>
|
|
338
|
+
</Mage_GiftMessage>
|
|
339
|
+
<Mage_Sendfriend>
|
|
340
|
+
<active>true</active>
|
|
341
|
+
<codePool>core</codePool>
|
|
342
|
+
<depends>
|
|
343
|
+
<Mage_Catalog/>
|
|
344
|
+
</depends>
|
|
345
|
+
</Mage_Sendfriend>
|
|
346
|
+
<Mage_Media>
|
|
347
|
+
<active>true</active>
|
|
348
|
+
<codePool>core</codePool>
|
|
349
|
+
<depends>
|
|
350
|
+
<Mage_Core/>
|
|
351
|
+
</depends>
|
|
352
|
+
</Mage_Media>
|
|
353
|
+
<Mage_Sitemap>
|
|
354
|
+
<active>true</active>
|
|
355
|
+
<codePool>core</codePool>
|
|
356
|
+
<depends>
|
|
357
|
+
<Mage_Catalog/>
|
|
358
|
+
</depends>
|
|
359
|
+
</Mage_Sitemap>
|
|
360
|
+
<Mage_Contacts>
|
|
361
|
+
<active>true</active>
|
|
362
|
+
<codePool>core</codePool>
|
|
363
|
+
<depends>
|
|
364
|
+
<Mage_Core/>
|
|
365
|
+
</depends>
|
|
366
|
+
</Mage_Contacts>
|
|
367
|
+
<Mage_Dataflow>
|
|
368
|
+
<active>true</active>
|
|
369
|
+
<codePool>core</codePool>
|
|
370
|
+
<depends>
|
|
371
|
+
<Mage_Core/>
|
|
372
|
+
</depends>
|
|
373
|
+
</Mage_Dataflow>
|
|
374
|
+
<Mage_Rss>
|
|
375
|
+
<active>true</active>
|
|
376
|
+
<codePool>core</codePool>
|
|
377
|
+
<depends>
|
|
378
|
+
<Mage_Catalog/>
|
|
379
|
+
<Mage_CatalogInventory/>
|
|
380
|
+
<Mage_Sales/>
|
|
381
|
+
<Mage_SalesRule/>
|
|
382
|
+
<Mage_Wishlist/>
|
|
383
|
+
</depends>
|
|
384
|
+
</Mage_Rss>
|
|
385
|
+
<Mage_ProductAlert>
|
|
386
|
+
<active>true</active>
|
|
387
|
+
<codePool>core</codePool>
|
|
388
|
+
<depends>
|
|
389
|
+
<Mage_Catalog/>
|
|
390
|
+
<Mage_Customer/>
|
|
391
|
+
</depends>
|
|
392
|
+
</Mage_ProductAlert>
|
|
393
|
+
<Mage_Index>
|
|
394
|
+
<active>true</active>
|
|
395
|
+
<codePool>core</codePool>
|
|
396
|
+
<depends>
|
|
397
|
+
<Mage_Core/>
|
|
398
|
+
</depends>
|
|
399
|
+
</Mage_Index>
|
|
400
|
+
</modules>
|
|
401
|
+
</config>
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
<?xml version="1.0"?>
|
|
2
|
+
<!--
|
|
3
|
+
/**
|
|
4
|
+
* Magento
|
|
5
|
+
*
|
|
6
|
+
* NOTICE OF LICENSE
|
|
7
|
+
*
|
|
8
|
+
* This source file is subject to the Academic Free License (AFL 3.0)
|
|
9
|
+
* that is bundled with this package in the file LICENSE_AFL.txt.
|
|
10
|
+
* It is also available through the world-wide-web at this URL:
|
|
11
|
+
* http://opensource.org/licenses/afl-3.0.php
|
|
12
|
+
* If you did not receive a copy of the license and are unable to
|
|
13
|
+
* obtain it through the world-wide-web, please send an email
|
|
14
|
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
|
15
|
+
*
|
|
16
|
+
* DISCLAIMER
|
|
17
|
+
*
|
|
18
|
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
|
19
|
+
* versions in the future. If you wish to customize Magento for your
|
|
20
|
+
* needs please refer to http://www.magentocommerce.com for more information.
|
|
21
|
+
*
|
|
22
|
+
* @category Mage
|
|
23
|
+
* @package Mage_Api
|
|
24
|
+
* @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com)
|
|
25
|
+
* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
|
|
26
|
+
*/
|
|
27
|
+
-->
|
|
28
|
+
<config>
|
|
29
|
+
<modules>
|
|
30
|
+
<Mage_Api>
|
|
31
|
+
<active>true</active>
|
|
32
|
+
<codePool>core</codePool>
|
|
33
|
+
<depends>
|
|
34
|
+
<Mage_Core />
|
|
35
|
+
</depends>
|
|
36
|
+
</Mage_Api>
|
|
37
|
+
</modules>
|
|
38
|
+
</config>
|
data/lib/maruto.rb
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
require 'maruto/version'
|
|
2
2
|
require 'maruto/magento_config'
|
|
3
|
+
require 'maruto/magento_instance'
|
|
3
4
|
|
|
4
5
|
module Maruto
|
|
5
|
-
|
|
6
|
-
|
|
6
|
+
def self.warnings(magento_root)
|
|
7
|
+
magento = MagentoInstance.load(magento_root)
|
|
8
|
+
magento[:warnings]
|
|
9
|
+
end
|
|
10
|
+
end
|
data/lib/maruto/base.rb
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
|
|
2
|
+
require 'maruto/module_definition'
|
|
3
|
+
require 'maruto/module_configuration'
|
|
4
|
+
|
|
5
|
+
module Maruto::MagentoInstance
|
|
6
|
+
def self.load(magento_root)
|
|
7
|
+
Dir.chdir(magento_root) do
|
|
8
|
+
all_modules = Maruto::ModuleDefinition.parse_all_module_definitions()
|
|
9
|
+
sorted_modules, active_modules = Maruto::ModuleDefinition.analyse_module_definitions(all_modules)
|
|
10
|
+
|
|
11
|
+
sorted_modules.each do |m|
|
|
12
|
+
Maruto::ModuleConfiguration.load(m)
|
|
13
|
+
# ModuleConfiguration.analyse(m, active_modules)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
warnings = []
|
|
17
|
+
all_modules.each do |m|
|
|
18
|
+
warnings.concat m[:warnings].map{|w| "[module:#{m[:name]}] #{w}"} if m.include? :warnings
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
{
|
|
22
|
+
:active_modules => active_modules.map{|k,v| v},
|
|
23
|
+
:all_modules => all_modules,
|
|
24
|
+
:sorted_modules => sorted_modules,
|
|
25
|
+
:warnings => warnings,
|
|
26
|
+
}
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
require 'maruto/base'
|
|
2
|
+
require 'nokogiri'
|
|
3
|
+
|
|
4
|
+
module Maruto::ModuleConfiguration
|
|
5
|
+
|
|
6
|
+
def self.load(m)
|
|
7
|
+
f = File.open(m[:config_path])
|
|
8
|
+
doc = Nokogiri::XML(f) { |config| config.strict }
|
|
9
|
+
f.close
|
|
10
|
+
|
|
11
|
+
read_module_version(m, doc.root)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.read_module_version(m, xml_root)
|
|
15
|
+
xml_node = xml_root.at_xpath('/config/modules')
|
|
16
|
+
if xml_node.nil?
|
|
17
|
+
m[:warnings] ||= []
|
|
18
|
+
m[:warnings] << "config.xml is missing a <modules></modules> node (in '#{m[:config_path]}')"
|
|
19
|
+
return m
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
unless xml_node.at_xpath("./#{m[:name]}")
|
|
23
|
+
m[:warnings] ||= []
|
|
24
|
+
m[:warnings] << "config.xml is missing a <modules><#{m[:name]}></#{m[:name]}></modules> node (in '#{m[:config_path]}')"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
xml_node.xpath("./*").each do |n|
|
|
28
|
+
unless n.name.to_sym == m[:name]
|
|
29
|
+
m[:warnings] ||= []
|
|
30
|
+
m[:warnings] << "config.xml contains configuration for a different module (<modules><#{n.name}></#{n.name}></modules> in '#{m[:config_path]}')"
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
if xml_node.at_xpath("./#{m[:name]}/version")
|
|
35
|
+
m[:version] = xml_node.at_xpath("./#{m[:name]}/version").content
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
m
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def self.parse_scoped_events_observers(base_path, xml_node)
|
|
42
|
+
|
|
43
|
+
return [] if xml_node.nil?
|
|
44
|
+
|
|
45
|
+
events = []
|
|
46
|
+
|
|
47
|
+
xml_node.xpath('events/*').each do |e|
|
|
48
|
+
event = {
|
|
49
|
+
:name => e.name,
|
|
50
|
+
:path => base_path + '/events/' + e.name,
|
|
51
|
+
:observers => [],
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
e.xpath('observers/*').each do |o|
|
|
55
|
+
observer = {
|
|
56
|
+
:name => o.name,
|
|
57
|
+
:path => event[:path] + '/observers/' + o.name,
|
|
58
|
+
}
|
|
59
|
+
observer[:type] = o.at_xpath('type').content
|
|
60
|
+
observer[:class] = o.at_xpath('class').content
|
|
61
|
+
observer[:method] = o.at_xpath('method').content
|
|
62
|
+
|
|
63
|
+
event[:observers] << observer
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
events << event
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
events
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def self.parse_all_events_observers(base_path, xml_node)
|
|
73
|
+
# TODO handle multiple global / frontend / adminhtml nodes
|
|
74
|
+
h = {
|
|
75
|
+
:global => parse_scoped_events_observers(base_path + '/global', xml_node.at_xpath('global')),
|
|
76
|
+
:frontend => parse_scoped_events_observers(base_path + '/frontend', xml_node.at_xpath('frontend')),
|
|
77
|
+
:adminhtml => parse_scoped_events_observers(base_path + '/adminhtml', xml_node.at_xpath('adminhtml')),
|
|
78
|
+
}
|
|
79
|
+
h.delete_if {|k,v| v.size == 0}
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
end
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
require 'maruto/base'
|
|
2
|
+
require 'nokogiri'
|
|
3
|
+
require 'tsort'
|
|
4
|
+
|
|
5
|
+
module Maruto::ModuleDefinition
|
|
6
|
+
|
|
7
|
+
def self.parse_module_definition(xml_node)
|
|
8
|
+
module_definition = {
|
|
9
|
+
:name => xml_node.name.to_sym,
|
|
10
|
+
:active => !(/^(false|off)$/ =~ xml_node.at_xpath('active').content),
|
|
11
|
+
:code_pool => xml_node.at_xpath('codePool').content.to_sym,
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
deps = xml_node.xpath('depends/*').map { |e| e.name.to_sym }
|
|
15
|
+
module_definition[:dependencies] = deps if deps.size > 0
|
|
16
|
+
|
|
17
|
+
unless /^(true|false|off)$/ =~ xml_node.at_xpath('active').content then
|
|
18
|
+
module_definition[:warnings] = ["value for active element should be in ['true','false','off'] (element: #{xml_node.at_xpath('active')})"]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
unless /^(core|community|local)$/ =~ xml_node.at_xpath('codePool').content then
|
|
22
|
+
module_definition[:warnings] = ["value for codePool element should be in ['core','community','local'] (element: #{xml_node.at_xpath('codePool')})"]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
module_definition
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def self.parse_module_definition_file(path)
|
|
29
|
+
f = File.open(path)
|
|
30
|
+
doc = Nokogiri::XML(f) { |config| config.strict }
|
|
31
|
+
f.close
|
|
32
|
+
|
|
33
|
+
doc.xpath('//modules/*').map { |xml_node| self.parse_module_definition(xml_node).merge({:defined => path}) }
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def self.parse_all_module_definitions()
|
|
37
|
+
Dir.glob('app/etc/modules/*.xml').reduce([]) { |result, path| result + self.parse_module_definition_file(path) }
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
class ModuleSorter
|
|
41
|
+
include TSort
|
|
42
|
+
def initialize(h)
|
|
43
|
+
@h = h
|
|
44
|
+
end
|
|
45
|
+
def tsort_each_node(&block)
|
|
46
|
+
@h.each_key(&block)
|
|
47
|
+
end
|
|
48
|
+
def tsort_each_child(mod_name, &block)
|
|
49
|
+
@h[mod_name][:dependencies].each(&block) if @h[mod_name].include? :dependencies
|
|
50
|
+
end
|
|
51
|
+
def sorted
|
|
52
|
+
tsort.map { |mod_name| @h[mod_name] }
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def self.analyse_module_definitions(module_definitions)
|
|
57
|
+
h = Hash.new
|
|
58
|
+
module_definitions.each do |m|
|
|
59
|
+
if m[:active]
|
|
60
|
+
mod_name = m[:name]
|
|
61
|
+
if h.include? mod_name then
|
|
62
|
+
# disable first module
|
|
63
|
+
h[mod_name][:active] = false
|
|
64
|
+
m[:warnings] ||= []
|
|
65
|
+
m[:warnings] << "defined_in:#{m[:defined]} - duplicate module definition (in '#{h[mod_name][:defined]}' and '#{m[:defined]}')"
|
|
66
|
+
end
|
|
67
|
+
parts = mod_name.to_s.split('_')
|
|
68
|
+
h[mod_name] = m
|
|
69
|
+
if parts.size != 2
|
|
70
|
+
m[:warnings] ||= []
|
|
71
|
+
m[:warnings] << "defined_in:#{m[:defined]} - invalid module name" unless parts.size == 2
|
|
72
|
+
m[:active] = false
|
|
73
|
+
else
|
|
74
|
+
m[:config_path] = "app/code/#{m[:code_pool]}/#{parts[0]}/#{parts[1]}/etc/config.xml"
|
|
75
|
+
if !File.exists?(m[:config_path])
|
|
76
|
+
m[:warnings] ||= []
|
|
77
|
+
m[:warnings]<< "config.xml is missing (searching '#{m[:config_path]}' for #{m[:name]} defined in #{m[:defined]})"
|
|
78
|
+
m[:active] = false
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
# remove inactive modules
|
|
84
|
+
h.reject!{|n,m| !m[:active]}
|
|
85
|
+
# check dependencies
|
|
86
|
+
h.reject{|n,m| !m.include? :dependencies}.each do |mod_name, m|
|
|
87
|
+
# group by module name: hash of module_name => [module_name]
|
|
88
|
+
dependencies = m[:dependencies].group_by{ |e| e }
|
|
89
|
+
# find duplicates
|
|
90
|
+
duplicates = Hash[dependencies.select{ |k, v| v.size > 1 }].keys # in ruby 1.8.7 select returns an array of tuples
|
|
91
|
+
# unique values
|
|
92
|
+
m[:dependencies] = dependencies.keys
|
|
93
|
+
if duplicates.size > 0
|
|
94
|
+
m[:warnings] ||= []
|
|
95
|
+
m[:warnings] << "duplicate dependencies (#{duplicates.join(', ')}) in '#{m[:defined]}'"
|
|
96
|
+
end
|
|
97
|
+
m[:dependencies].each do |d|
|
|
98
|
+
unless h.include? d
|
|
99
|
+
m[:dependencies].delete d
|
|
100
|
+
m[:warnings] ||= []
|
|
101
|
+
m[:warnings] << "missing dependency: '#{d}' in '#{m[:defined]}'"
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
[ModuleSorter.new(h).sorted, h]
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
end
|
data/lib/maruto/runner.rb
CHANGED
|
@@ -43,6 +43,13 @@ class Maruto::Runner < Thor
|
|
|
43
43
|
magento_config = Maruto::MagentoConfig.new magento_root
|
|
44
44
|
magento_config.print_warnings
|
|
45
45
|
|
|
46
|
+
# next gen maruto:
|
|
47
|
+
|
|
48
|
+
warnings = Maruto::warnings magento_root
|
|
49
|
+
warnings.each do |w|
|
|
50
|
+
puts "#{w}"
|
|
51
|
+
end
|
|
52
|
+
|
|
46
53
|
end
|
|
47
54
|
|
|
48
55
|
desc "models", "list models sorted and grouped by their group_name"
|
data/lib/maruto/version.rb
CHANGED
data/maruto.gemspec
CHANGED
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
require 'maruto/module_definition'
|
|
4
|
+
|
|
5
|
+
describe Maruto::ModuleDefinition do
|
|
6
|
+
|
|
7
|
+
before do
|
|
8
|
+
@xml_nodes = {}
|
|
9
|
+
@xml_nodes[:Mage_Core] = Nokogiri::XML('''
|
|
10
|
+
<Mage_Core>
|
|
11
|
+
<active>true</active>
|
|
12
|
+
<codePool>core</codePool>
|
|
13
|
+
</Mage_Core>
|
|
14
|
+
''').root
|
|
15
|
+
@xml_nodes[:Mage_Customer] = Nokogiri::XML('''
|
|
16
|
+
<Mage_Customer>
|
|
17
|
+
<active>true</active>
|
|
18
|
+
<codePool>core</codePool>
|
|
19
|
+
<depends>
|
|
20
|
+
<Mage_Eav/>
|
|
21
|
+
<Mage_Dataflow/>
|
|
22
|
+
</depends>
|
|
23
|
+
</Mage_Customer>
|
|
24
|
+
''').root
|
|
25
|
+
@xml_nodes[:Mage_Dataflow] = Nokogiri::XML('''
|
|
26
|
+
<Mage_Dataflow>
|
|
27
|
+
<active>true</active>
|
|
28
|
+
<codePool>core</codePool>
|
|
29
|
+
<depends>
|
|
30
|
+
<Mage_Core/>
|
|
31
|
+
</depends>
|
|
32
|
+
</Mage_Dataflow>
|
|
33
|
+
''').root
|
|
34
|
+
@xml_nodes[:Mage_Eav] = Nokogiri::XML('''
|
|
35
|
+
<Mage_Eav>
|
|
36
|
+
<active>true</active>
|
|
37
|
+
<codePool>core</codePool>
|
|
38
|
+
<depends>
|
|
39
|
+
<Mage_Core/>
|
|
40
|
+
</depends>
|
|
41
|
+
</Mage_Eav>
|
|
42
|
+
''').root
|
|
43
|
+
|
|
44
|
+
magento_root = File.expand_path('../../fixtures/magento_root', __FILE__)
|
|
45
|
+
Dir.chdir(magento_root)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
describe "when parsing a module definition" do
|
|
49
|
+
|
|
50
|
+
it "will return a Hash" do
|
|
51
|
+
h = Maruto::ModuleDefinition.parse_module_definition(@xml_nodes[:Mage_Core])
|
|
52
|
+
h.must_be_kind_of Hash
|
|
53
|
+
h.must_include :name
|
|
54
|
+
h.must_include :code_pool
|
|
55
|
+
h.must_include :active
|
|
56
|
+
h.wont_include :dependencies
|
|
57
|
+
h.wont_include :warnings
|
|
58
|
+
h[:name].must_equal :Mage_Core
|
|
59
|
+
h[:code_pool].must_equal :core
|
|
60
|
+
h[:active].must_equal true
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it "will find dependencies" do
|
|
64
|
+
h = Maruto::ModuleDefinition.parse_module_definition(@xml_nodes[:Mage_Eav])
|
|
65
|
+
h.must_include :dependencies
|
|
66
|
+
h[:dependencies].size.must_equal 1
|
|
67
|
+
h[:dependencies].must_include :Mage_Core
|
|
68
|
+
|
|
69
|
+
h = Maruto::ModuleDefinition.parse_module_definition(@xml_nodes[:Mage_Customer])
|
|
70
|
+
h.must_include :dependencies
|
|
71
|
+
h[:dependencies].size.must_equal 2
|
|
72
|
+
h[:dependencies].must_include :Mage_Dataflow
|
|
73
|
+
h[:dependencies].must_include :Mage_Eav
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it "will treat any module that is <active>false</active> or <active>off</active> as inactive" do
|
|
77
|
+
Maruto::ModuleDefinition.parse_module_definition(Nokogiri::XML('''
|
|
78
|
+
<modname>
|
|
79
|
+
<active>false</active>
|
|
80
|
+
<codePool>core</codePool>
|
|
81
|
+
</modname>
|
|
82
|
+
''').root)[:active].must_equal false
|
|
83
|
+
Maruto::ModuleDefinition.parse_module_definition(Nokogiri::XML('''
|
|
84
|
+
<modname>
|
|
85
|
+
<active>off</active>
|
|
86
|
+
<codePool>core</codePool>
|
|
87
|
+
</modname>
|
|
88
|
+
''').root)[:active].must_equal false
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it "will warn when active is not in 'true', 'false' or 'off'" do
|
|
92
|
+
h = Maruto::ModuleDefinition.parse_module_definition(Nokogiri::XML('''
|
|
93
|
+
<modname>
|
|
94
|
+
<active>hello</active>
|
|
95
|
+
<codePool>core</codePool>
|
|
96
|
+
</modname>
|
|
97
|
+
''').root)
|
|
98
|
+
h.must_include :active
|
|
99
|
+
h.must_include :warnings
|
|
100
|
+
# any string that is not false or off => active
|
|
101
|
+
# TODO empty string => inactive (check in php)
|
|
102
|
+
h[:active].must_equal true
|
|
103
|
+
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
it "will warn when codePool is not in 'core', 'community' or 'local'" do
|
|
107
|
+
h = Maruto::ModuleDefinition.parse_module_definition(Nokogiri::XML('''
|
|
108
|
+
<modname>
|
|
109
|
+
<active>true</active>
|
|
110
|
+
<codePool>other</codePool>
|
|
111
|
+
</modname>
|
|
112
|
+
''').root)
|
|
113
|
+
h.must_include :warnings
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
describe "when parsing a module definition file" do
|
|
118
|
+
it "will return an Array of module definitions" do
|
|
119
|
+
a = Maruto::ModuleDefinition.parse_module_definition_file('app/etc/modules/Mage_Api.xml')
|
|
120
|
+
a.must_be_kind_of Array
|
|
121
|
+
a.size.must_equal 1
|
|
122
|
+
a[0].must_include :name
|
|
123
|
+
a[0][:name].must_equal :Mage_Api
|
|
124
|
+
end
|
|
125
|
+
it "will include the relative path to the file to the module definition" do
|
|
126
|
+
file = 'app/etc/modules/Mage_All.xml'
|
|
127
|
+
a = Maruto::ModuleDefinition.parse_module_definition_file(file)
|
|
128
|
+
a.size.must_be :>, 0
|
|
129
|
+
a.each do |m|
|
|
130
|
+
m.must_include :defined
|
|
131
|
+
m[:defined].must_equal file
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
it "will parse all module definition files in app/etc/modules" do
|
|
137
|
+
a = Maruto::ModuleDefinition.parse_all_module_definitions()
|
|
138
|
+
a.must_be_kind_of Array
|
|
139
|
+
a.size.must_be :>, 0
|
|
140
|
+
a.each do |m|
|
|
141
|
+
m.must_include :name
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
describe "when analysing module definitions" do
|
|
146
|
+
before do
|
|
147
|
+
@module_a = { :name => :Mage_A, :code_pool => :core, :defined => 'a'}
|
|
148
|
+
@module_b = { :name => :Mage_B, :code_pool => :core, :defined => 'b'}
|
|
149
|
+
@module_c = { :name => :Mage_C, :code_pool => :core, :defined => 'c'}
|
|
150
|
+
@module_d = { :name => :Mage_D, :code_pool => :core, :defined => 'd'}
|
|
151
|
+
end
|
|
152
|
+
it "will return an Array and a Hash" do
|
|
153
|
+
a,h = Maruto::ModuleDefinition.analyse_module_definitions([])
|
|
154
|
+
a.must_be_kind_of Array
|
|
155
|
+
h.must_be_kind_of Hash
|
|
156
|
+
end
|
|
157
|
+
it "will not include inactive modules (in Array or Hash)" do
|
|
158
|
+
parsed_module_definitions = [
|
|
159
|
+
@module_a.merge({ :active => false}),
|
|
160
|
+
]
|
|
161
|
+
a,h = Maruto::ModuleDefinition.analyse_module_definitions(parsed_module_definitions)
|
|
162
|
+
a.size.must_equal 0
|
|
163
|
+
h.size.must_equal 0
|
|
164
|
+
end
|
|
165
|
+
it "will remove missing dependencies and add a warning" do
|
|
166
|
+
parsed_module_definitions = [
|
|
167
|
+
@module_a.merge({ :active => true, :dependencies => [:Mage_B, :Mage_C], :warnings => ['first warning']}),
|
|
168
|
+
@module_b.merge({ :active => true }),
|
|
169
|
+
@module_c.merge({ :active => false }),
|
|
170
|
+
]
|
|
171
|
+
a,h = Maruto::ModuleDefinition.analyse_module_definitions(parsed_module_definitions)
|
|
172
|
+
h[:Mage_A][:dependencies].size.must_equal 1
|
|
173
|
+
h[:Mage_A][:warnings].size.must_equal 2
|
|
174
|
+
end
|
|
175
|
+
it "will remove duplicate dependencies and add a warning" do
|
|
176
|
+
parsed_module_definitions = [
|
|
177
|
+
@module_a.merge({ :active => true, :dependencies => [:Mage_B, :Mage_C, :Mage_B], :warnings => ['first warning']}),
|
|
178
|
+
@module_b.merge({ :active => true }),
|
|
179
|
+
@module_c.merge({ :active => true }),
|
|
180
|
+
]
|
|
181
|
+
a,h = Maruto::ModuleDefinition.analyse_module_definitions(parsed_module_definitions)
|
|
182
|
+
h[:Mage_A][:dependencies].size.must_equal 2
|
|
183
|
+
h[:Mage_A][:warnings].size.must_equal 2
|
|
184
|
+
end
|
|
185
|
+
it "will deactivate modules with an invalid name and add a warning" do
|
|
186
|
+
parsed_module_definitions = [
|
|
187
|
+
{ :name => :a, :active => true, :defined => 'a', :warnings => ['first warning'] },
|
|
188
|
+
]
|
|
189
|
+
a,h = Maruto::ModuleDefinition.analyse_module_definitions(parsed_module_definitions)
|
|
190
|
+
parsed_module_definitions[0][:active].must_equal false
|
|
191
|
+
parsed_module_definitions[0][:warnings].size.must_equal 2
|
|
192
|
+
parsed_module_definitions[0][:warnings][-1].must_include "invalid module name"
|
|
193
|
+
end
|
|
194
|
+
it "will add the path to the module's config.xml" do
|
|
195
|
+
parsed_module_definitions = [
|
|
196
|
+
@module_a.merge({ :active => true }),
|
|
197
|
+
]
|
|
198
|
+
a,h = Maruto::ModuleDefinition.analyse_module_definitions(parsed_module_definitions)
|
|
199
|
+
h[:Mage_A][:config_path].must_equal 'app/code/core/Mage/A/etc/config.xml'
|
|
200
|
+
h[:Mage_A].wont_include :warnings
|
|
201
|
+
end
|
|
202
|
+
it "will deactivate modules without a config.xml and add a warning" do
|
|
203
|
+
parsed_module_definitions = [
|
|
204
|
+
{ :name => :Hello_World, :code_pool => :core, :active => true, :defined => 'hello', :warnings => ['first warning'] },
|
|
205
|
+
]
|
|
206
|
+
a,h = Maruto::ModuleDefinition.analyse_module_definitions(parsed_module_definitions)
|
|
207
|
+
parsed_module_definitions[0][:active].must_equal false
|
|
208
|
+
parsed_module_definitions[0][:warnings].size.must_equal 2
|
|
209
|
+
end
|
|
210
|
+
it "will sort the Array according to module dependencies" do
|
|
211
|
+
parsed_module_definitions = [
|
|
212
|
+
@module_a.merge({ :active => true, :dependencies => [:Mage_D] }),
|
|
213
|
+
@module_b.merge({ :active => true }),
|
|
214
|
+
@module_c.merge({ :active => true, :dependencies => [:Mage_B, :Mage_A] }),
|
|
215
|
+
@module_d.merge({ :active => true, :dependencies => [:Mage_B] }),
|
|
216
|
+
]
|
|
217
|
+
a,h = Maruto::ModuleDefinition.analyse_module_definitions(parsed_module_definitions)
|
|
218
|
+
a.map{|m| m[:name]}.must_equal [:Mage_B, :Mage_D, :Mage_A, :Mage_C]
|
|
219
|
+
end
|
|
220
|
+
it "will deactivate the first one, add a warning on the second one and use the second one to the Hash when 2 active modules have the same name" do
|
|
221
|
+
parsed_module_definitions = [
|
|
222
|
+
@module_a.merge({ :active => true }),
|
|
223
|
+
@module_a.merge({ :active => true, :defined => 'b' }),
|
|
224
|
+
]
|
|
225
|
+
a,h = Maruto::ModuleDefinition.analyse_module_definitions(parsed_module_definitions)
|
|
226
|
+
a.size.must_equal 1
|
|
227
|
+
h.size.must_equal 1
|
|
228
|
+
parsed_module_definitions[0][:active].must_equal false
|
|
229
|
+
a[0][:active].must_equal true
|
|
230
|
+
a[0][:defined].must_equal 'b'
|
|
231
|
+
a[0].must_include :warnings
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
end
|
|
236
|
+
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
require 'maruto/module_configuration'
|
|
4
|
+
|
|
5
|
+
module Maruto
|
|
6
|
+
|
|
7
|
+
describe ModuleConfiguration do
|
|
8
|
+
|
|
9
|
+
describe "when parsing a module config.xml" do
|
|
10
|
+
describe "and reading events observers" do
|
|
11
|
+
before do
|
|
12
|
+
@xml_node = Nokogiri::XML('''
|
|
13
|
+
<events>
|
|
14
|
+
<first_event>
|
|
15
|
+
<observers>
|
|
16
|
+
<first_observer>
|
|
17
|
+
<type>model</type> <!-- model, object or singleton -->
|
|
18
|
+
<class>Mage_A_Model_Observer</class> <!-- observers class or class alias -->
|
|
19
|
+
<method>methodName</method> <!-- observer\'s method to be called -->
|
|
20
|
+
<args></args> <!-- additional arguments passed to observer -->
|
|
21
|
+
</first_observer>
|
|
22
|
+
</observers>
|
|
23
|
+
</first_event>
|
|
24
|
+
<second_event>
|
|
25
|
+
<observers>
|
|
26
|
+
<second_observer>
|
|
27
|
+
<type>object</type>
|
|
28
|
+
<class>Mage_B_Model_Observer</class>
|
|
29
|
+
<method>doSomething</method>
|
|
30
|
+
</second_observer>
|
|
31
|
+
<third_observer>
|
|
32
|
+
<type>singleton</type>
|
|
33
|
+
<class>Mage_C_Model_Observer</class>
|
|
34
|
+
<method>helloWorld</method>
|
|
35
|
+
</third_observer>
|
|
36
|
+
</observers>
|
|
37
|
+
</second_event>
|
|
38
|
+
</events>
|
|
39
|
+
''').root.at_xpath('/')
|
|
40
|
+
end
|
|
41
|
+
it "will return a array of events" do
|
|
42
|
+
e = ModuleConfiguration.parse_scoped_events_observers('', @xml_node)
|
|
43
|
+
e.must_be_kind_of Array
|
|
44
|
+
e.size.must_equal 2
|
|
45
|
+
end
|
|
46
|
+
it "will handle a missing <events> element or a nil node" do
|
|
47
|
+
node = Nokogiri::XML('''
|
|
48
|
+
<hello></hello>
|
|
49
|
+
''').root.at_xpath('/')
|
|
50
|
+
e = ModuleConfiguration.parse_scoped_events_observers('', node)
|
|
51
|
+
e.must_be_kind_of Array
|
|
52
|
+
e.size.must_equal 0
|
|
53
|
+
|
|
54
|
+
e = ModuleConfiguration.parse_scoped_events_observers('', nil)
|
|
55
|
+
e.must_be_kind_of Array
|
|
56
|
+
e.size.must_equal 0
|
|
57
|
+
end
|
|
58
|
+
it "will build the path to an event" do
|
|
59
|
+
e = ModuleConfiguration.parse_scoped_events_observers('root', @xml_node)
|
|
60
|
+
e[0][:path].must_equal 'root/events/first_event'
|
|
61
|
+
end
|
|
62
|
+
it "will read the name type class and method of an observer" do
|
|
63
|
+
e = ModuleConfiguration.parse_scoped_events_observers('', @xml_node)
|
|
64
|
+
e[0][:observers][0][:name].must_equal 'first_observer'
|
|
65
|
+
e[0][:observers][0][:type].must_equal 'model'
|
|
66
|
+
e[0][:observers][0][:class].must_equal 'Mage_A_Model_Observer'
|
|
67
|
+
e[0][:observers][0][:method].must_equal 'methodName'
|
|
68
|
+
end
|
|
69
|
+
it "will build the path to an event observer" do
|
|
70
|
+
e = ModuleConfiguration.parse_scoped_events_observers('root', @xml_node)
|
|
71
|
+
e[0][:observers][0][:path].must_equal 'root/events/first_event/observers/first_observer'
|
|
72
|
+
end
|
|
73
|
+
it "will group observers by events" do
|
|
74
|
+
e = ModuleConfiguration.parse_scoped_events_observers('', @xml_node)
|
|
75
|
+
e.size.must_equal 2
|
|
76
|
+
e[0].must_include :name
|
|
77
|
+
e[0].must_include :observers
|
|
78
|
+
e[0][:name].must_equal 'first_event'
|
|
79
|
+
e[0][:observers].size.must_equal 1
|
|
80
|
+
e[1][:name].must_equal 'second_event'
|
|
81
|
+
e[1][:observers].size.must_equal 2
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# TODO multiple global xml nodes?
|
|
85
|
+
|
|
86
|
+
# it "will warn when an event has no observers" do
|
|
87
|
+
# @xml_node_no_obs = Nokogiri::XML('''
|
|
88
|
+
# <events><first_event></first_event></events>
|
|
89
|
+
# ''').root.at_xpath('/events')
|
|
90
|
+
# e = ModuleConfiguration.parse_events_observers(@xml_node_no_obs)
|
|
91
|
+
# e.size.must_equal 1
|
|
92
|
+
# e[0].must_include :warnings
|
|
93
|
+
# e[0][:warnings].size.must_equal 1
|
|
94
|
+
# end
|
|
95
|
+
# it "will warn when an event has an empty observers node" do
|
|
96
|
+
# @xml_node_empty_obs = Nokogiri::XML('''
|
|
97
|
+
# <events><first_event><observers></observers></first_event></events>
|
|
98
|
+
# ''').root.at_xpath('/events')
|
|
99
|
+
# e = ModuleConfiguration.parse_events_observers(@xml_node_empty_obs)
|
|
100
|
+
# e.size.must_equal 1
|
|
101
|
+
# e[0][:warnings].size.must_equal 1
|
|
102
|
+
# end
|
|
103
|
+
# it "will warn if an observers type is invalid" do
|
|
104
|
+
# e = ModuleConfiguration.parse_events_observers(@xml_node)
|
|
105
|
+
# e[1][:warnings].size.must_equal 1
|
|
106
|
+
# e[1][:warnings][0].must_include '<type>something</type>'
|
|
107
|
+
# end
|
|
108
|
+
# it "will warn if an observers class is invalid" do
|
|
109
|
+
# # TODO
|
|
110
|
+
# end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
it "will group events by scope and build the correct path" do
|
|
114
|
+
node = Nokogiri::XML('''<config>
|
|
115
|
+
<global>
|
|
116
|
+
<events>
|
|
117
|
+
<e1><observers></observers></e1>
|
|
118
|
+
</events>
|
|
119
|
+
</global>
|
|
120
|
+
<frontend>
|
|
121
|
+
<events>
|
|
122
|
+
<e2><observers></observers></e2>
|
|
123
|
+
<e3></e3>
|
|
124
|
+
</events>
|
|
125
|
+
</frontend>
|
|
126
|
+
<adminhtml>
|
|
127
|
+
<events>
|
|
128
|
+
<e4></e4>
|
|
129
|
+
<e5></e5>
|
|
130
|
+
<e6></e6>
|
|
131
|
+
</events>
|
|
132
|
+
</adminhtml>
|
|
133
|
+
</config>''').root
|
|
134
|
+
|
|
135
|
+
e = ModuleConfiguration.parse_all_events_observers('root', node)
|
|
136
|
+
|
|
137
|
+
e.must_be_kind_of Hash
|
|
138
|
+
e.must_include :global
|
|
139
|
+
e.must_include :frontend
|
|
140
|
+
e.must_include :adminhtml
|
|
141
|
+
|
|
142
|
+
e[:global].size.must_equal 1
|
|
143
|
+
e[:global][0][:name].must_equal 'e1'
|
|
144
|
+
e[:global][0][:path].must_include 'root/global/events'
|
|
145
|
+
|
|
146
|
+
e[:frontend].size.must_equal 2
|
|
147
|
+
e[:frontend][0][:name].must_equal 'e2'
|
|
148
|
+
e[:frontend][0][:path].must_include 'root/frontend/events'
|
|
149
|
+
|
|
150
|
+
e[:adminhtml].size.must_equal 3
|
|
151
|
+
e[:adminhtml][0][:name].must_equal 'e4'
|
|
152
|
+
e[:adminhtml][0][:path].must_include 'root/adminhtml/events'
|
|
153
|
+
end
|
|
154
|
+
it "will skip scopes without events" do
|
|
155
|
+
node = Nokogiri::XML('''
|
|
156
|
+
<global>
|
|
157
|
+
<events>
|
|
158
|
+
</events>
|
|
159
|
+
</global>
|
|
160
|
+
<frontend>
|
|
161
|
+
</frontend>
|
|
162
|
+
''').root
|
|
163
|
+
e = ModuleConfiguration.parse_all_events_observers('', node)
|
|
164
|
+
e.must_be_kind_of Hash
|
|
165
|
+
e.wont_include :global
|
|
166
|
+
e.wont_include :frontend
|
|
167
|
+
e.wont_include :adminhtml
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
require 'maruto/module_configuration'
|
|
4
|
+
|
|
5
|
+
module Maruto
|
|
6
|
+
|
|
7
|
+
describe ModuleConfiguration do
|
|
8
|
+
|
|
9
|
+
before do
|
|
10
|
+
@module_a = { :name => :Mage_A, :active => true, :code_pool => :core, :defined => 'a', :config_path => 'app/code/core/Mage/A/etc/config.xml' }
|
|
11
|
+
@module_b = { :name => :Mage_B, :active => true, :code_pool => :core, :defined => 'b', :config_path => 'app/code/core/Mage/B/etc/config.xml' }
|
|
12
|
+
@module_c = { :name => :Mage_C, :active => true, :code_pool => :core, :defined => 'c', :config_path => 'app/code/core/Mage/C/etc/config.xml' }
|
|
13
|
+
@module_d = { :name => :Mage_D, :active => true, :code_pool => :core, :defined => 'd', :config_path => 'app/code/core/Mage/D/etc/config.xml' }
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
describe "when parsing a module config.xml" do
|
|
17
|
+
describe "and reading the module version" do
|
|
18
|
+
before do
|
|
19
|
+
@xml_config_root = Nokogiri::XML('''
|
|
20
|
+
<config><modules>
|
|
21
|
+
<Mage_A>
|
|
22
|
+
<version>0.0.1</version>
|
|
23
|
+
</Mage_A>
|
|
24
|
+
</modules></config>
|
|
25
|
+
''').root
|
|
26
|
+
end
|
|
27
|
+
it "will return the module definition hash" do
|
|
28
|
+
m = ModuleConfiguration.read_module_version(@module_a, @xml_config_root)
|
|
29
|
+
m.must_be_kind_of Hash
|
|
30
|
+
m.must_equal @module_a
|
|
31
|
+
end
|
|
32
|
+
it "will add the version to the hash" do
|
|
33
|
+
m = ModuleConfiguration.read_module_version(@module_a, @xml_config_root)
|
|
34
|
+
m.must_include :version
|
|
35
|
+
m[:version].must_equal '0.0.1'
|
|
36
|
+
end
|
|
37
|
+
it "will add a warning when then modules node is missing" do
|
|
38
|
+
w = @module_a.merge({ :warnings => ['first warning'] })
|
|
39
|
+
m = ModuleConfiguration.read_module_version(w, Nokogiri::XML('<config><a></a></config>').root)
|
|
40
|
+
m[:warnings].size.must_equal 2
|
|
41
|
+
m[:warnings][-1].must_include '<modules'
|
|
42
|
+
end
|
|
43
|
+
it "will add a warning when then node with the module's name is missing" do
|
|
44
|
+
w = @module_a.merge({ :warnings => ['first warning'] })
|
|
45
|
+
m = ModuleConfiguration.read_module_version(w, Nokogiri::XML('<config><modules></modules></config>').root)
|
|
46
|
+
m[:warnings].size.must_equal 2
|
|
47
|
+
m[:warnings][-1].must_include '<modules'
|
|
48
|
+
m[:warnings][-1].must_include '<Mage_A'
|
|
49
|
+
end
|
|
50
|
+
it "will add a warning when there is a node from a different module" do
|
|
51
|
+
xml_config_root = Nokogiri::XML('''
|
|
52
|
+
<config><modules>
|
|
53
|
+
<Mage_A>
|
|
54
|
+
<version>0.0.1</version>
|
|
55
|
+
</Mage_A>
|
|
56
|
+
<Mage_B>
|
|
57
|
+
<version>0.0.1</version>
|
|
58
|
+
</Mage_B>
|
|
59
|
+
</modules></config>
|
|
60
|
+
''').root
|
|
61
|
+
w = @module_a.merge({ :warnings => ['first warning'] })
|
|
62
|
+
m = ModuleConfiguration.read_module_version(w, xml_config_root)
|
|
63
|
+
m[:warnings].size.must_equal 2
|
|
64
|
+
m[:warnings][-1].must_include 'Mage_B'
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: maruto
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.4
|
|
5
5
|
prerelease:
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2013-
|
|
12
|
+
date: 2013-05-03 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: nokogiri
|
|
@@ -75,6 +75,22 @@ dependencies:
|
|
|
75
75
|
- - ! '>='
|
|
76
76
|
- !ruby/object:Gem::Version
|
|
77
77
|
version: '0'
|
|
78
|
+
- !ruby/object:Gem::Dependency
|
|
79
|
+
name: minitest
|
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
|
81
|
+
none: false
|
|
82
|
+
requirements:
|
|
83
|
+
- - ! '>='
|
|
84
|
+
- !ruby/object:Gem::Version
|
|
85
|
+
version: '0'
|
|
86
|
+
type: :development
|
|
87
|
+
prerelease: false
|
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
89
|
+
none: false
|
|
90
|
+
requirements:
|
|
91
|
+
- - ! '>='
|
|
92
|
+
- !ruby/object:Gem::Version
|
|
93
|
+
version: '0'
|
|
78
94
|
description: Magento Ruby Tools
|
|
79
95
|
email:
|
|
80
96
|
- jlgeering.13@gmail.com
|
|
@@ -85,16 +101,31 @@ extra_rdoc_files: []
|
|
|
85
101
|
files:
|
|
86
102
|
- .gitignore
|
|
87
103
|
- .ruby-version
|
|
104
|
+
- .travis.yml
|
|
88
105
|
- Gemfile
|
|
89
106
|
- LICENSE.txt
|
|
90
107
|
- README.md
|
|
91
108
|
- Rakefile
|
|
92
109
|
- bin/maruto
|
|
110
|
+
- fixtures/magento_root/app/code/core/Mage/A/etc/config.xml
|
|
111
|
+
- fixtures/magento_root/app/code/core/Mage/B/etc/config.xml
|
|
112
|
+
- fixtures/magento_root/app/code/core/Mage/C/etc/config.xml
|
|
113
|
+
- fixtures/magento_root/app/code/core/Mage/D/etc/config.xml
|
|
114
|
+
- fixtures/magento_root/app/etc/modules/Mage_All.xml
|
|
115
|
+
- fixtures/magento_root/app/etc/modules/Mage_Api.xml
|
|
93
116
|
- lib/maruto.rb
|
|
117
|
+
- lib/maruto/base.rb
|
|
94
118
|
- lib/maruto/magento_config.rb
|
|
119
|
+
- lib/maruto/magento_instance.rb
|
|
120
|
+
- lib/maruto/module_configuration.rb
|
|
121
|
+
- lib/maruto/module_definition.rb
|
|
95
122
|
- lib/maruto/runner.rb
|
|
96
123
|
- lib/maruto/version.rb
|
|
97
124
|
- maruto.gemspec
|
|
125
|
+
- spec/module_definition_spec.rb
|
|
126
|
+
- spec/module_events_spec.rb
|
|
127
|
+
- spec/module_version_spec.rb
|
|
128
|
+
- spec/spec_helper.rb
|
|
98
129
|
homepage: https://github.com/jlgeering/maruto
|
|
99
130
|
licenses:
|
|
100
131
|
- MIT
|
|
@@ -120,4 +151,8 @@ rubygems_version: 1.8.23
|
|
|
120
151
|
signing_key:
|
|
121
152
|
specification_version: 3
|
|
122
153
|
summary: config parser and analyser, ...
|
|
123
|
-
test_files:
|
|
154
|
+
test_files:
|
|
155
|
+
- spec/module_definition_spec.rb
|
|
156
|
+
- spec/module_events_spec.rb
|
|
157
|
+
- spec/module_version_spec.rb
|
|
158
|
+
- spec/spec_helper.rb
|