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.
@@ -0,0 +1,11 @@
1
+ language: ruby
2
+ rvm:
3
+ - "1.8.7"
4
+ - "1.9.2"
5
+ - "1.9.3"
6
+ - "2.0.0"
7
+ - jruby-18mode # JRuby in 1.8 mode
8
+ - jruby-19mode # JRuby in 1.9 mode
9
+ - rbx-18mode
10
+ - rbx-19mode
11
+ script: bundle exec rake test
data/README.md CHANGED
@@ -1,3 +1,6 @@
1
+ [![Build Status](https://travis-ci.org/jlgeering/maruto.png)](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. Commit your changes (`git commit -am 'Add some feature'`)
28
- 4. Push to the branch (`git push origin my-new-feature`)
29
- 5. Create new Pull Request
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
@@ -1 +1,7 @@
1
- require "bundler/gem_tasks"
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.libs << "spec"
6
+ t.pattern = "spec/*_spec.rb"
7
+ end
@@ -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>
@@ -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
- # Your code goes here...
6
- end
6
+ def self.warnings(magento_root)
7
+ magento = MagentoInstance.load(magento_root)
8
+ magento[:warnings]
9
+ end
10
+ end
@@ -0,0 +1,3 @@
1
+ module Maruto
2
+ # Your code goes here...
3
+ end
@@ -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
@@ -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"
@@ -1,3 +1,3 @@
1
1
  module Maruto
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
@@ -23,4 +23,6 @@ Gem::Specification.new do |spec|
23
23
 
24
24
  spec.add_development_dependency "bundler", "~> 1.3"
25
25
  spec.add_development_dependency "rake"
26
+ spec.add_development_dependency "minitest"
27
+ # spec.add_development_dependency "minitest-reporters"
26
28
  end
@@ -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
@@ -0,0 +1,8 @@
1
+ require 'minitest/autorun'
2
+
3
+ # https://github.com/CapnKernul/minitest-reporters
4
+ # incompatible with ruby 1.8.7
5
+ # require 'minitest/reporters'
6
+ # MiniTest::Reporters.use!
7
+ # MiniTest::Reporters.use! MiniTest::Reporters::SpecReporter.new
8
+
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.3
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-04-01 00:00:00.000000000 Z
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