rook 0.0.2 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.txt +124 -37
- data/bin/rook +8 -902
- data/doc-api/classes/BZ2.html +111 -0
- data/doc-api/classes/BZ2/Reader.html +234 -0
- data/doc-api/classes/Digest.html +107 -0
- data/doc-api/classes/Digest/Base.html +254 -0
- data/doc-api/classes/Enumerable.html +430 -0
- data/doc-api/classes/File.html +208 -0
- data/doc-api/classes/FileUtils.html +758 -0
- data/doc-api/classes/Kernel.html +317 -0
- data/doc-api/classes/Rook.html +148 -0
- data/doc-api/classes/Rook/Assertion.html +164 -0
- data/doc-api/classes/Rook/AssertionError.html +111 -0
- data/doc-api/classes/Rook/CommandOptionError.html +113 -0
- data/doc-api/classes/Rook/Commands.html +1158 -0
- data/doc-api/classes/Rook/Cookbook.html +357 -0
- data/doc-api/classes/Rook/CookbookError.html +161 -0
- data/doc-api/classes/Rook/CookbookValidator.html +215 -0
- data/doc-api/classes/Rook/Kitchen.html +875 -0
- data/doc-api/classes/Rook/KitchenHelper.html +386 -0
- data/doc-api/classes/Rook/Main.html +325 -0
- data/doc-api/classes/Rook/Parameters.html +443 -0
- data/doc-api/classes/Rook/Recipe.html +546 -0
- data/doc-api/classes/Rook/RookError.html +111 -0
- data/doc-api/classes/Rook/Util.html +408 -0
- data/doc-api/classes/Rook/Util/UndefinedPropertyError.html +160 -0
- data/doc-api/created.rid +1 -0
- data/doc-api/files/__/README_txt.html +313 -0
- data/doc-api/files/rook/commands_rb.html +115 -0
- data/doc-api/files/rook/cookbook_rb.html +115 -0
- data/doc-api/files/rook/helper/bz2_rb.html +114 -0
- data/doc-api/files/rook/helper/digest_rb.html +114 -0
- data/doc-api/files/rook/helper/enumerable_rb.html +107 -0
- data/doc-api/files/rook/helper/file_rb.html +107 -0
- data/doc-api/files/rook/helper/fileutils_rb.html +124 -0
- data/doc-api/files/rook/helper/kernel_rb.html +107 -0
- data/doc-api/files/rook/kitchen_rb.html +117 -0
- data/doc-api/files/rook/main_rb.html +117 -0
- data/doc-api/files/rook/recipe_rb.html +114 -0
- data/doc-api/files/rook/util_rb.html +115 -0
- data/doc-api/files/rook_rb.html +122 -0
- data/doc-api/fr_class_index.html +50 -0
- data/doc-api/fr_file_index.html +40 -0
- data/doc-api/fr_method_index.html +181 -0
- data/doc-api/index.html +24 -0
- data/doc-api/rdoc-style.css +208 -0
- data/examples/hello_c/Rookbook.rb +37 -0
- data/examples/hello_c/Rookbook.yaml +45 -0
- data/examples/hello_c/hello.c +6 -3
- data/examples/project/README.txt +8 -0
- data/examples/project/Rookbook.props +1 -0
- data/examples/project/Rookbook.rb +120 -0
- data/examples/project/Rookbook.yaml +117 -0
- data/examples/project/bin/example +12 -0
- data/examples/project/example.gemspec +29 -0
- data/examples/project/lib/example.rb +36 -0
- data/examples/{archive → project}/lib/example/bar.rb +0 -0
- data/examples/{archive → project}/lib/example/baz.rb +0 -0
- data/examples/{archive → project}/lib/example/foo.rb +0 -0
- data/examples/project/setup.rb +1331 -0
- data/examples/project/test/test.rb +27 -0
- data/lib/rook.rb +50 -0
- data/lib/rook/commands.rb +426 -0
- data/lib/rook/cookbook.rb +237 -0
- data/lib/rook/helper/bz2.rb +39 -0
- data/lib/rook/helper/digest.rb +76 -0
- data/lib/rook/helper/enumerable.rb +121 -0
- data/lib/rook/helper/file.rb +50 -0
- data/lib/rook/helper/fileutils.rb +340 -0
- data/lib/rook/helper/kernel.rb +108 -0
- data/lib/rook/kitchen.rb +668 -0
- data/lib/rook/main.rb +280 -0
- data/lib/rook/recipe.rb +259 -0
- data/lib/rook/rookbook.schema.yaml +156 -0
- data/lib/rook/util.rb +172 -0
- data/rook.gemspec +56 -0
- metadata +139 -45
- data/examples/archive/COPYING +0 -340
- data/examples/archive/README.txt +0 -1
- data/examples/archive/Rookbook +0 -56
- data/examples/archive/bin/example +0 -0
- data/examples/archive/doc/index.html +0 -0
- data/examples/archive/doc/index.txt +0 -0
- data/examples/archive/lib/example.rb +0 -0
- data/examples/archive/test/test1.rb +0 -0
- data/examples/archive/test/test2.rb +0 -0
- data/examples/hello_c/Rookbook +0 -24
data/lib/rook/kitchen.rb
ADDED
@@ -0,0 +1,668 @@
|
|
1
|
+
##
|
2
|
+
## $Rev: 32 $
|
3
|
+
## $Release: 0.1.0 $
|
4
|
+
## copyright(c) 2006 kuwata-lab.com all rights reserved.
|
5
|
+
##
|
6
|
+
|
7
|
+
|
8
|
+
require 'abstract'
|
9
|
+
require 'rook/util'
|
10
|
+
require 'rook/cookbook'
|
11
|
+
require 'rook/recipe'
|
12
|
+
|
13
|
+
|
14
|
+
|
15
|
+
module Rook
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
##
|
20
|
+
## add functions for DSL (ruby-style cookbook)
|
21
|
+
##
|
22
|
+
module KitchenHelper
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
|
27
|
+
##
|
28
|
+
## define a property in Rookbook.rb
|
29
|
+
##
|
30
|
+
## ex. (in Rookbook.rb)
|
31
|
+
## property 'release', '1.0.0', :desc=>'release number'
|
32
|
+
## property 'project', 'myapp'
|
33
|
+
##
|
34
|
+
## the above is equivarent to the following (in Rookbook.yaml):
|
35
|
+
## properties:
|
36
|
+
## - release : 1.0.0
|
37
|
+
## :desc : 'release number'
|
38
|
+
## - project : myapp
|
39
|
+
##
|
40
|
+
## this method define a global variable which name is the same as property name.
|
41
|
+
## for example, global variables $release and $project are defined in above ex.
|
42
|
+
##
|
43
|
+
## property value can be overwrited by command-line option.
|
44
|
+
##
|
45
|
+
## ex. (in command-line)
|
46
|
+
## $ rook --release=1.2.3 --project='myapp2'
|
47
|
+
##
|
48
|
+
def property(name, value, options={}) # :doc:
|
49
|
+
hash = { 'name'=>name.to_s, 'value'=>value }
|
50
|
+
options.each { |name, value| hash[name.to_s] = value }
|
51
|
+
add_property(hash)
|
52
|
+
end
|
53
|
+
|
54
|
+
#--
|
55
|
+
#abstract_method 'hash', :add_property, :add_variable
|
56
|
+
#++
|
57
|
+
|
58
|
+
def add_property(hash)
|
59
|
+
not_implemented
|
60
|
+
end
|
61
|
+
|
62
|
+
def add_variable(hash)
|
63
|
+
not_implemented
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
##
|
68
|
+
## define a variable in Rookbook.rb
|
69
|
+
##
|
70
|
+
## ex. (in Rookbook.rb)
|
71
|
+
## variable :srcdir, 'src'
|
72
|
+
## variable :files, Dir.glob('src/*.rb')
|
73
|
+
## variable :rook_product, :all
|
74
|
+
##
|
75
|
+
## the above code is equivalent to the following in Rookbook.yaml:
|
76
|
+
## variables:
|
77
|
+
## - srcdir : src
|
78
|
+
## - files* : Dir.glob('src/*.rb')
|
79
|
+
## - rook_product : :all
|
80
|
+
##
|
81
|
+
def variable(name, value, options={}) # :doc:
|
82
|
+
hash = { 'name'=>name.to_s, 'value'=>value }
|
83
|
+
options.each { |name, value| hash[name.to_s] = value }
|
84
|
+
add_variable(hash)
|
85
|
+
end
|
86
|
+
|
87
|
+
|
88
|
+
##
|
89
|
+
## specify material (= non-products) in Rookbook.rb
|
90
|
+
##
|
91
|
+
## ex. (in Rookbook.rb)
|
92
|
+
## material 'index.html'
|
93
|
+
## material 'readme.html'
|
94
|
+
##
|
95
|
+
## the above is equivarent to the following in Rookbook.yaml:
|
96
|
+
## materials:
|
97
|
+
## - index.html
|
98
|
+
## - readme.html
|
99
|
+
##
|
100
|
+
def material(material_name) # :doc:
|
101
|
+
add_material(material_name)
|
102
|
+
end
|
103
|
+
|
104
|
+
#--
|
105
|
+
#abstract_method 'material_name', :add_material
|
106
|
+
#++
|
107
|
+
|
108
|
+
|
109
|
+
def add_material(material_name)
|
110
|
+
not_implemented
|
111
|
+
end
|
112
|
+
|
113
|
+
|
114
|
+
|
115
|
+
##
|
116
|
+
## specify description of recipe in Rookbook.rb
|
117
|
+
##
|
118
|
+
## ex. (in Rookbook.rb)
|
119
|
+
## desc 'create *.o from *.c'
|
120
|
+
## recipe '*.o', '$(1).c' do
|
121
|
+
## sys "gcc -c #{@ingreds[0]}"
|
122
|
+
## end
|
123
|
+
##
|
124
|
+
## the above is equivarent to the following in Rookbook.yaml:
|
125
|
+
## recipes:
|
126
|
+
## - product: *.o
|
127
|
+
## desc: create *.o from *.c
|
128
|
+
## ingreds: [ $(1).c ]
|
129
|
+
## method: |
|
130
|
+
## sys "gcc -c #{@ingreds[0]}"
|
131
|
+
##
|
132
|
+
def desc(text) # :doc:
|
133
|
+
@_desc = text
|
134
|
+
end
|
135
|
+
|
136
|
+
|
137
|
+
|
138
|
+
##
|
139
|
+
## define a recipe in Rookbook.rb
|
140
|
+
##
|
141
|
+
## ex. (in Rookbook.rb)
|
142
|
+
## recipe '*.o' , '$(1).c', :options=>['$(1).h'], :desc=>'compile *.c' do
|
143
|
+
## sys "gcc -c #{@ingreds[0]}"
|
144
|
+
## end
|
145
|
+
##
|
146
|
+
## the above is equivarent to the following in Rookbook.yaml:
|
147
|
+
## recipes:
|
148
|
+
## - product: *.o
|
149
|
+
## ingreds: [ $(1).c ]
|
150
|
+
## options: [ $(1).h ]
|
151
|
+
## desc: compile *.c
|
152
|
+
## method: |
|
153
|
+
## sys "gcc -c #{@ingreds[0]}"
|
154
|
+
##
|
155
|
+
## return value is a recipe created.
|
156
|
+
##
|
157
|
+
def recipe(product, *args, &block) # :doc:
|
158
|
+
hash = {}
|
159
|
+
if args[-1].is_a?(Hash)
|
160
|
+
args.pop.each do |key, val|
|
161
|
+
case key.to_s
|
162
|
+
when 'option', 'coprod', 'byprod'
|
163
|
+
hash[key.to_s + 's'] = [val]
|
164
|
+
else
|
165
|
+
hash[key.to_s] = val
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
hash['product'] = product
|
170
|
+
hash['ingreds'] = args.flatten
|
171
|
+
hash['block'] = block
|
172
|
+
if @_desc != nil
|
173
|
+
hash['desc'] = @_desc
|
174
|
+
@_desc = nil
|
175
|
+
end
|
176
|
+
r = Recipe.new(hash)
|
177
|
+
add_recipe(r)
|
178
|
+
return r
|
179
|
+
end
|
180
|
+
|
181
|
+
|
182
|
+
#--
|
183
|
+
#abstract_method 'product, *args, &block', :add_recipe
|
184
|
+
#++
|
185
|
+
|
186
|
+
def add_recipe(product, *args, &block)
|
187
|
+
not_implemented
|
188
|
+
end
|
189
|
+
|
190
|
+
|
191
|
+
end
|
192
|
+
|
193
|
+
|
194
|
+
class Parameters
|
195
|
+
|
196
|
+
def initialize
|
197
|
+
@_property_table = {}
|
198
|
+
@_variable_table = {}
|
199
|
+
end
|
200
|
+
|
201
|
+
def has_property?(name)
|
202
|
+
return @_property_table.key?(name.to_s)
|
203
|
+
end
|
204
|
+
|
205
|
+
def has_variable?(name)
|
206
|
+
return @_variable_table.key?(name.to_s)
|
207
|
+
end
|
208
|
+
|
209
|
+
def set_property(name, value)
|
210
|
+
name = name.to_s
|
211
|
+
return if has_property?(name) # cannot override
|
212
|
+
@_property_table[name] = value
|
213
|
+
instance_variable_set("@#{name}", value)
|
214
|
+
end
|
215
|
+
|
216
|
+
def set_variable(name, value)
|
217
|
+
@_variable_table[name.to_s] = value
|
218
|
+
end
|
219
|
+
|
220
|
+
def get_property(name)
|
221
|
+
return @_property_table[name.to_s]
|
222
|
+
end
|
223
|
+
|
224
|
+
def get_variable(name)
|
225
|
+
return @_variable_table[name.to_s]
|
226
|
+
end
|
227
|
+
|
228
|
+
def get_value(name)
|
229
|
+
name = name.to_s
|
230
|
+
return get_property(name) if has_property?(name) # allow overwrite variable by property
|
231
|
+
return get_variable(name) if has_variable?(name)
|
232
|
+
#if has_property?(name) || has_variable?(name)
|
233
|
+
# return _get(name)
|
234
|
+
#end
|
235
|
+
msg = "'$(#{name})': no such property nor variable."
|
236
|
+
#raise UndefinedPropertyError.new(msg, name)
|
237
|
+
raise RookError.new(msg)
|
238
|
+
end
|
239
|
+
|
240
|
+
def evaluate_value(value)
|
241
|
+
case value
|
242
|
+
when String
|
243
|
+
if value =~ /\A\$\(([a-zA-Z_]\w*)\)\z/
|
244
|
+
val = get_value($1)
|
245
|
+
else
|
246
|
+
val = value.gsub(/\$\(([a-zA-Z_]\w*)\)/) { get_value($1) }
|
247
|
+
end
|
248
|
+
when Array
|
249
|
+
list = value.collect { |val| evaluate_value(val) }
|
250
|
+
val = list
|
251
|
+
when Hash
|
252
|
+
hash = {}
|
253
|
+
value.each { |key, val| hash[key] = evaluate_value(val) }
|
254
|
+
val = hash
|
255
|
+
else
|
256
|
+
val = value
|
257
|
+
end
|
258
|
+
return val
|
259
|
+
end
|
260
|
+
|
261
|
+
def evaluate_expr(expr, filename='(expr)', linenum=1)
|
262
|
+
code = @_variable_table.keys.collect { |name| "#{name}=@_variable_table['#{name}'];" }
|
263
|
+
code << expr
|
264
|
+
return self.instance_eval(code.join, filename, linenum)
|
265
|
+
end
|
266
|
+
|
267
|
+
def property_names
|
268
|
+
return @_property_table.keys
|
269
|
+
end
|
270
|
+
|
271
|
+
def variable_names
|
272
|
+
return @_variable_table.keys
|
273
|
+
end
|
274
|
+
|
275
|
+
end
|
276
|
+
|
277
|
+
|
278
|
+
|
279
|
+
|
280
|
+
##
|
281
|
+
## kitchen class
|
282
|
+
##
|
283
|
+
## ex.
|
284
|
+
## cookbooks, errors = Cookbook.load_yamlfile('Rookbook.yaml')
|
285
|
+
## kitchen = Kitchen.new
|
286
|
+
## cookbooks.each { |book| kitchen.load_book(book) }
|
287
|
+
## kitchen.start_cooking('product_name')
|
288
|
+
##
|
289
|
+
class Kitchen
|
290
|
+
include Assertion
|
291
|
+
include KitchenHelper
|
292
|
+
|
293
|
+
|
294
|
+
def initialize(properties={}, options={})
|
295
|
+
@parameters = Parameters.new
|
296
|
+
@properties = []
|
297
|
+
@variables = []
|
298
|
+
properties.each do |name, value|
|
299
|
+
add_property({'name'=>name.to_s, 'value'=>value})
|
300
|
+
end
|
301
|
+
@recipes = []
|
302
|
+
@recipe_table = {}
|
303
|
+
@materials = []
|
304
|
+
@precookings = []
|
305
|
+
@forced = options[:forced]
|
306
|
+
#@verbose = options[:verbose]
|
307
|
+
#@noexec = options[:noexec]
|
308
|
+
end
|
309
|
+
attr_reader :properties, :variables
|
310
|
+
attr_reader :materials, :precookings, :recipes
|
311
|
+
#attr_reader :forced, :quiet, :noexec
|
312
|
+
|
313
|
+
|
314
|
+
def has_property?(name)
|
315
|
+
return @parameters.has_property?(name)
|
316
|
+
end
|
317
|
+
|
318
|
+
def has_variable?(name)
|
319
|
+
return @parameters.has_variable?(name)
|
320
|
+
end
|
321
|
+
|
322
|
+
def get_property(name)
|
323
|
+
return @parameters.get_property(name)
|
324
|
+
end
|
325
|
+
|
326
|
+
def get_variable(name)
|
327
|
+
return @parameters.get_variable(name)
|
328
|
+
end
|
329
|
+
|
330
|
+
def load_books(cookbooks)
|
331
|
+
cookboos.each do |cookbook| load_book(cookbook) end
|
332
|
+
end
|
333
|
+
|
334
|
+
|
335
|
+
def load_book(cookbook)
|
336
|
+
b = cookbook
|
337
|
+
# precooking
|
338
|
+
b.precookings.each do |hash|
|
339
|
+
add_precooking(hash['code'], b.bookname, hash['linenum'])
|
340
|
+
end if b.precooking
|
341
|
+
# properties
|
342
|
+
b.properties.each do |hash|
|
343
|
+
hash['bookname'] = b.bookname
|
344
|
+
add_property(hash, b.bookname)
|
345
|
+
end if b.properties
|
346
|
+
# variables
|
347
|
+
b.variables.each do |hash|
|
348
|
+
hash['bookname'] = b.bookname
|
349
|
+
add_variable(hash, b.bookname)
|
350
|
+
end if b.variables
|
351
|
+
# materials
|
352
|
+
b.materials.each do |nonprod|
|
353
|
+
add_nonproduct(nonprod)
|
354
|
+
end if b.materials
|
355
|
+
# recipes
|
356
|
+
b.recipes.each do |hash|
|
357
|
+
hash = @parameters.evaluate_value(hash)
|
358
|
+
hash['bookname'] = b.bookname
|
359
|
+
recipe = Recipe.new(hash)
|
360
|
+
add_recipe(recipe)
|
361
|
+
end if b.recipes
|
362
|
+
end
|
363
|
+
|
364
|
+
|
365
|
+
def load_script(filename)
|
366
|
+
self.instance_eval File.read(filename), filename, 1
|
367
|
+
end
|
368
|
+
|
369
|
+
def load_script!(script, filename)
|
370
|
+
self.instance_eval script, filename, 1
|
371
|
+
end
|
372
|
+
|
373
|
+
|
374
|
+
def add_precooking(code_str, bookname='', linenum=1)
|
375
|
+
@precookings << [code_str, bookname, linenum]
|
376
|
+
Util.evaluate(code_str, bookname, linenum) # or instance_eval?
|
377
|
+
end
|
378
|
+
|
379
|
+
|
380
|
+
def add_property(hash, bookname='')
|
381
|
+
hash['access'] ||= 'public'
|
382
|
+
name = hash['name']
|
383
|
+
if @parameters.has_property?(name)
|
384
|
+
value = @parameters.get_property(name)
|
385
|
+
else
|
386
|
+
if hash.key?('value')
|
387
|
+
value = @parameters.evaluate_value(hash['value'])
|
388
|
+
elsif hash.key?('expr') || hash.key?('value*')
|
389
|
+
expr = hash.key?('expr') ? hash['expr'] : hash['value*']
|
390
|
+
expr = @parameters.evaluate_value(expr)
|
391
|
+
value = @valuemap.evaluate_expr(expr, bookname, hash['linenum'])
|
392
|
+
else
|
393
|
+
raise RookError.new("property '#{name}': no value.")
|
394
|
+
end
|
395
|
+
@parameters.set_property(name, value)
|
396
|
+
hash['value'] = value
|
397
|
+
@properties << hash
|
398
|
+
end
|
399
|
+
#eval "$#{name} = value"
|
400
|
+
end
|
401
|
+
|
402
|
+
|
403
|
+
def add_variable(hash, bookname='')
|
404
|
+
name = hash['name']
|
405
|
+
if @parameters.has_variable?(name)
|
406
|
+
@variables.delete_if { |h| h['name'] == name }
|
407
|
+
end
|
408
|
+
if hash.key?('value')
|
409
|
+
value = @parameters.evaluate_value(hash['value'])
|
410
|
+
elsif hash.key?('expr') || hash.key?('value*')
|
411
|
+
expr = hash.key?('expr') ? hash['expr'] : hash['value*']
|
412
|
+
linenum = hash['linenum'] || 1
|
413
|
+
expr = @parameters.evaluate_value(expr)
|
414
|
+
value = @parameters.evaluate_expr(expr, bookname, linenum)
|
415
|
+
else
|
416
|
+
raise RookError.new("variable '#{name}': no value.")
|
417
|
+
end
|
418
|
+
@parameters.set_variable(name, value)
|
419
|
+
hash['value'] = value
|
420
|
+
@variables << hash
|
421
|
+
end
|
422
|
+
|
423
|
+
|
424
|
+
def add_material(material_str)
|
425
|
+
mat_str = @parameters.evaluate_value(material_str)
|
426
|
+
@materials << mat_str
|
427
|
+
end
|
428
|
+
|
429
|
+
|
430
|
+
def add_recipe_hash(hash)
|
431
|
+
%w[ingreds byprods coprods options].each do |key|
|
432
|
+
if hash.key?("#{key}*")
|
433
|
+
val = hash.delete("#{key}*")
|
434
|
+
assert val.is_a?(String), "val.class=#{val.class}"
|
435
|
+
val = @parameters.evaluate_expr(val)
|
436
|
+
val = [ val ] unless val.is_a?(Array)
|
437
|
+
hash[key] = val
|
438
|
+
elsif hash.key?(key)
|
439
|
+
val = @parameters.evaluate_expr(val)
|
440
|
+
hash[key] = val
|
441
|
+
end
|
442
|
+
end
|
443
|
+
r = Recipe.new(hash['product'])
|
444
|
+
add_recipe(r)
|
445
|
+
end
|
446
|
+
|
447
|
+
def add_recipe(recipe)
|
448
|
+
@recipes.delete_if { |r| r.product == recipe.product } if @recipe_table[recipe.product]
|
449
|
+
@recipe_table[recipe.product] = recipe
|
450
|
+
@recipes << recipe
|
451
|
+
end
|
452
|
+
|
453
|
+
|
454
|
+
def find_generic_recipe(product)
|
455
|
+
return @recipes.find { |r| r.kind == 'generic' && r.match?(product) }
|
456
|
+
end
|
457
|
+
|
458
|
+
|
459
|
+
def find_specific_recipe(product)
|
460
|
+
return @recipes.find { |r| r.kind == 'specific' && r.match?(product) }
|
461
|
+
end
|
462
|
+
|
463
|
+
|
464
|
+
def find_recipe(product)
|
465
|
+
return find_specific_recipe(product) || find_generic_recipe(product)
|
466
|
+
end
|
467
|
+
|
468
|
+
|
469
|
+
def start_cooking(product)
|
470
|
+
cooking = Cooking.new(product)
|
471
|
+
begin
|
472
|
+
cook(product, cooking, 0)
|
473
|
+
rescue Exception => ex
|
474
|
+
log(ex.message, 0, nil, '*** ')
|
475
|
+
raise ex
|
476
|
+
end
|
477
|
+
end
|
478
|
+
|
479
|
+
|
480
|
+
##
|
481
|
+
## cook product
|
482
|
+
##
|
483
|
+
## return true when product recipe is invoked, else return false.
|
484
|
+
##
|
485
|
+
def cook(product, cooking, level=0, verbose=nil, parent_fingerprint=false)
|
486
|
+
## check
|
487
|
+
if @materials.include?(product)
|
488
|
+
log("skip '#{Util.to_str(product)}': material.", level, verbose)
|
489
|
+
return false
|
490
|
+
end
|
491
|
+
if cooking.cooked?(product)
|
492
|
+
log("skip '#{Util.to_str(product)}': already cooked.", level, verbose)
|
493
|
+
return false
|
494
|
+
end
|
495
|
+
if cooking.now_cooking?(product)
|
496
|
+
raise RookError.new("'#{Util.to_str(product)}': recipe is recursively looped.")
|
497
|
+
end
|
498
|
+
|
499
|
+
## find recipe
|
500
|
+
recipe = find_recipe(product)
|
501
|
+
unless recipe
|
502
|
+
if product.is_a?(String) && test(?e, product)
|
503
|
+
log("skip '#{Util.to_str(product)}': raw ingredient.", level, verbose)
|
504
|
+
return false
|
505
|
+
else
|
506
|
+
raise RookError.new("'#{Util.to_str(product)}': recipe not found.")
|
507
|
+
end
|
508
|
+
end
|
509
|
+
recipe = recipe.to_specific(product)
|
510
|
+
|
511
|
+
## start cooking
|
512
|
+
cooking.start(recipe)
|
513
|
+
log("begin '#{Util.to_str(product)}'", level, recipe.verbose?)
|
514
|
+
flag_exec = @forced
|
515
|
+
|
516
|
+
## ingredients
|
517
|
+
ingreds = recipe.ingreds ? recipe.ingreds.dup : []
|
518
|
+
ingreds.concat(recipe.options.find_all { |f| test(?e, f) }) if recipe.options
|
519
|
+
# ingreds.each do |ingred|
|
520
|
+
# flag = cook(ingred, cooking, level+1, recipe.verbose?, recipe.fingerprint)
|
521
|
+
# flag_exec = true if flag
|
522
|
+
# end
|
523
|
+
|
524
|
+
## execute when
|
525
|
+
## * command-line option -F specified
|
526
|
+
## * executed at least one recipe of ingredients
|
527
|
+
## * recipe attribute 'forced' is true
|
528
|
+
## * recipe is symbolic and has howoto part
|
529
|
+
## * there isn't product
|
530
|
+
## * recipe has no ingredient
|
531
|
+
## * there is any ingredient which is newer than product
|
532
|
+
unless flag_exec
|
533
|
+
flag_exec ||= recipe.forced?
|
534
|
+
flag_exec ||= recipe.symbolic? && (recipe.method || recipe.block)
|
535
|
+
flag_exec ||= !recipe.symbolic? && !test(?e, product)
|
536
|
+
flag_exec ||= ingreds.empty? && (recipe.method || recipe.block)
|
537
|
+
end
|
538
|
+
unless flag_exec || ingreds.empty?
|
539
|
+
prod_mtime = File.mtime(product)
|
540
|
+
flag_exec = ingreds.any? { |f| f.is_a?(String) && test(?e, f) && prod_mtime < File.mtime(f) }
|
541
|
+
#unless flag_exec
|
542
|
+
# log("skip '#{Util.to_str(product)}': newer than all ingredients.", level, recipe.verbose?)
|
543
|
+
#end
|
544
|
+
end
|
545
|
+
|
546
|
+
## invoke ingredients' recipe
|
547
|
+
#ingreds = recipe.ingreds ? recipe.ingreds.dup : []
|
548
|
+
#ingreds.concat(recipe.options.find_all { |f| test(?e, f) }) if recipe.options
|
549
|
+
ingreds.each do |ingred|
|
550
|
+
flag = cook(ingred, cooking, level+1, recipe.verbose?, recipe.fingerprint)
|
551
|
+
flag_exec = true if flag
|
552
|
+
end
|
553
|
+
|
554
|
+
unless flag_exec || ingreds.empty?
|
555
|
+
log("skip '#{Util.to_str(product)}': newer than all ingredients.", level, recipe.verbose?)
|
556
|
+
end
|
557
|
+
|
558
|
+
## execute method part
|
559
|
+
fingerprint_value = nil
|
560
|
+
if flag_exec
|
561
|
+
flag_fp = parent_fingerprint == 'ingreds' || recipe.fingerprint == 'product'
|
562
|
+
if flag_fp && test(?f, product)
|
563
|
+
fingerprint_value = Util.fingerprint(product)
|
564
|
+
end
|
565
|
+
report(product, level, recipe.verbose?)
|
566
|
+
begin
|
567
|
+
recipe.invoke(@parameters)
|
568
|
+
rescue => ex
|
569
|
+
prods = [ recipe.product ]
|
570
|
+
prods += recipe.coprods if recipe.coprods
|
571
|
+
prods.each do |file|
|
572
|
+
next unless file.is_a?(String) && test(?f, file)
|
573
|
+
log("removing '#{file}' because of #{ex.class.name} - #{ex.message}", level, true)
|
574
|
+
File.unlink(file)
|
575
|
+
end
|
576
|
+
raise ex
|
577
|
+
end
|
578
|
+
end
|
579
|
+
|
580
|
+
## validate whether product is generated
|
581
|
+
unless recipe.symbolic? || test(?e, product)
|
582
|
+
raise RookError.new("product '#{Util.to_str(product)}': not generated")
|
583
|
+
end
|
584
|
+
|
585
|
+
## fingerprint check
|
586
|
+
if fingerprint_value
|
587
|
+
fp1 = fingerprint_value
|
588
|
+
fp2 = Util.fingerprint(product)
|
589
|
+
op = fp1 == fp2 ? '==' : '!='
|
590
|
+
log("fingerprint of #{product}: #{fp1} #{op} #{fp2}", level, recipe.verbose?)
|
591
|
+
flag_exec = false if fp1 == fp2
|
592
|
+
end
|
593
|
+
|
594
|
+
## finish cooking
|
595
|
+
log("end '#{Util.to_str(product)}'", level, recipe.verbose?)
|
596
|
+
cooking.finish(recipe)
|
597
|
+
return flag_exec
|
598
|
+
|
599
|
+
end
|
600
|
+
|
601
|
+
|
602
|
+
private
|
603
|
+
|
604
|
+
|
605
|
+
def log(mesg, level, verbose=nil, prompt='# ')
|
606
|
+
#flag = verbose.nil? ? @verbose == true : verbose
|
607
|
+
flag = verbose.nil? ? $rook_verbose == true : verbose
|
608
|
+
_puts(prompt + (' ' * level) + mesg) if flag
|
609
|
+
end
|
610
|
+
|
611
|
+
|
612
|
+
def report(product, level, verbose=nil)
|
613
|
+
#flag = verbose.nil? ? @verbose != false : verbose
|
614
|
+
flag = verbose.nil? ? $rook_verbose != false : verbose
|
615
|
+
str = Util.to_str(product)
|
616
|
+
_puts("### #{'*' * (level+1)} #{str}") if verbose || $rook_verbose != false
|
617
|
+
end
|
618
|
+
|
619
|
+
|
620
|
+
def _puts(str)
|
621
|
+
puts str
|
622
|
+
end
|
623
|
+
|
624
|
+
|
625
|
+
end
|
626
|
+
|
627
|
+
|
628
|
+
|
629
|
+
class Cooking #:nodoc:
|
630
|
+
|
631
|
+
|
632
|
+
def initialize(goal_product)
|
633
|
+
@goal_product = goal_product
|
634
|
+
@cooked = {}
|
635
|
+
@now_cooking = {}
|
636
|
+
end
|
637
|
+
attr_reader :goal_product, :cooked
|
638
|
+
|
639
|
+
|
640
|
+
def cooked?(product)
|
641
|
+
return @cooked.key?(product)
|
642
|
+
end
|
643
|
+
|
644
|
+
|
645
|
+
def now_cooking?(product)
|
646
|
+
return @now_cooking.key?(product)
|
647
|
+
end
|
648
|
+
|
649
|
+
|
650
|
+
def start(recipe)
|
651
|
+
recipe.all_products.each do |prod|
|
652
|
+
@now_cooking[prod] = recipe
|
653
|
+
end
|
654
|
+
end
|
655
|
+
|
656
|
+
|
657
|
+
def finish(recipe)
|
658
|
+
recipe.all_products.each do |prod|
|
659
|
+
@cooked[prod] = @now_cooking.delete(prod)
|
660
|
+
end
|
661
|
+
end
|
662
|
+
|
663
|
+
|
664
|
+
end
|
665
|
+
|
666
|
+
|
667
|
+
|
668
|
+
end
|