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.
Files changed (87) hide show
  1. data/README.txt +124 -37
  2. data/bin/rook +8 -902
  3. data/doc-api/classes/BZ2.html +111 -0
  4. data/doc-api/classes/BZ2/Reader.html +234 -0
  5. data/doc-api/classes/Digest.html +107 -0
  6. data/doc-api/classes/Digest/Base.html +254 -0
  7. data/doc-api/classes/Enumerable.html +430 -0
  8. data/doc-api/classes/File.html +208 -0
  9. data/doc-api/classes/FileUtils.html +758 -0
  10. data/doc-api/classes/Kernel.html +317 -0
  11. data/doc-api/classes/Rook.html +148 -0
  12. data/doc-api/classes/Rook/Assertion.html +164 -0
  13. data/doc-api/classes/Rook/AssertionError.html +111 -0
  14. data/doc-api/classes/Rook/CommandOptionError.html +113 -0
  15. data/doc-api/classes/Rook/Commands.html +1158 -0
  16. data/doc-api/classes/Rook/Cookbook.html +357 -0
  17. data/doc-api/classes/Rook/CookbookError.html +161 -0
  18. data/doc-api/classes/Rook/CookbookValidator.html +215 -0
  19. data/doc-api/classes/Rook/Kitchen.html +875 -0
  20. data/doc-api/classes/Rook/KitchenHelper.html +386 -0
  21. data/doc-api/classes/Rook/Main.html +325 -0
  22. data/doc-api/classes/Rook/Parameters.html +443 -0
  23. data/doc-api/classes/Rook/Recipe.html +546 -0
  24. data/doc-api/classes/Rook/RookError.html +111 -0
  25. data/doc-api/classes/Rook/Util.html +408 -0
  26. data/doc-api/classes/Rook/Util/UndefinedPropertyError.html +160 -0
  27. data/doc-api/created.rid +1 -0
  28. data/doc-api/files/__/README_txt.html +313 -0
  29. data/doc-api/files/rook/commands_rb.html +115 -0
  30. data/doc-api/files/rook/cookbook_rb.html +115 -0
  31. data/doc-api/files/rook/helper/bz2_rb.html +114 -0
  32. data/doc-api/files/rook/helper/digest_rb.html +114 -0
  33. data/doc-api/files/rook/helper/enumerable_rb.html +107 -0
  34. data/doc-api/files/rook/helper/file_rb.html +107 -0
  35. data/doc-api/files/rook/helper/fileutils_rb.html +124 -0
  36. data/doc-api/files/rook/helper/kernel_rb.html +107 -0
  37. data/doc-api/files/rook/kitchen_rb.html +117 -0
  38. data/doc-api/files/rook/main_rb.html +117 -0
  39. data/doc-api/files/rook/recipe_rb.html +114 -0
  40. data/doc-api/files/rook/util_rb.html +115 -0
  41. data/doc-api/files/rook_rb.html +122 -0
  42. data/doc-api/fr_class_index.html +50 -0
  43. data/doc-api/fr_file_index.html +40 -0
  44. data/doc-api/fr_method_index.html +181 -0
  45. data/doc-api/index.html +24 -0
  46. data/doc-api/rdoc-style.css +208 -0
  47. data/examples/hello_c/Rookbook.rb +37 -0
  48. data/examples/hello_c/Rookbook.yaml +45 -0
  49. data/examples/hello_c/hello.c +6 -3
  50. data/examples/project/README.txt +8 -0
  51. data/examples/project/Rookbook.props +1 -0
  52. data/examples/project/Rookbook.rb +120 -0
  53. data/examples/project/Rookbook.yaml +117 -0
  54. data/examples/project/bin/example +12 -0
  55. data/examples/project/example.gemspec +29 -0
  56. data/examples/project/lib/example.rb +36 -0
  57. data/examples/{archive → project}/lib/example/bar.rb +0 -0
  58. data/examples/{archive → project}/lib/example/baz.rb +0 -0
  59. data/examples/{archive → project}/lib/example/foo.rb +0 -0
  60. data/examples/project/setup.rb +1331 -0
  61. data/examples/project/test/test.rb +27 -0
  62. data/lib/rook.rb +50 -0
  63. data/lib/rook/commands.rb +426 -0
  64. data/lib/rook/cookbook.rb +237 -0
  65. data/lib/rook/helper/bz2.rb +39 -0
  66. data/lib/rook/helper/digest.rb +76 -0
  67. data/lib/rook/helper/enumerable.rb +121 -0
  68. data/lib/rook/helper/file.rb +50 -0
  69. data/lib/rook/helper/fileutils.rb +340 -0
  70. data/lib/rook/helper/kernel.rb +108 -0
  71. data/lib/rook/kitchen.rb +668 -0
  72. data/lib/rook/main.rb +280 -0
  73. data/lib/rook/recipe.rb +259 -0
  74. data/lib/rook/rookbook.schema.yaml +156 -0
  75. data/lib/rook/util.rb +172 -0
  76. data/rook.gemspec +56 -0
  77. metadata +139 -45
  78. data/examples/archive/COPYING +0 -340
  79. data/examples/archive/README.txt +0 -1
  80. data/examples/archive/Rookbook +0 -56
  81. data/examples/archive/bin/example +0 -0
  82. data/examples/archive/doc/index.html +0 -0
  83. data/examples/archive/doc/index.txt +0 -0
  84. data/examples/archive/lib/example.rb +0 -0
  85. data/examples/archive/test/test1.rb +0 -0
  86. data/examples/archive/test/test2.rb +0 -0
  87. data/examples/hello_c/Rookbook +0 -24
data/README.txt CHANGED
@@ -1,73 +1,160 @@
1
- .=title: README
2
- .?release: $Release: 0.0.2$
3
- .?lastupdated: $Date: 2005-04-30 11:16:15 +0900 (Sat, 30 Apr 2005) $
1
+ = README
4
2
 
3
+ release:: $Release: 0.1.0 $
4
+ copyright:: copyright(c) 2006 kuwata-lab.com all rights reserved.
5
5
 
6
- .$ About
6
+
7
+
8
+ == Introduction
7
9
 
8
10
  Rook is a tool for SCM such as Make, Rake, Ant, and so on.
9
- Rook is inspired by Cook which is made by Peter Miller.
11
+ Rook has inspired by Cook which is made by Peter Miller.
10
12
  http://www.canb.auug.org.au/~millerp/cook/cook.html
11
13
 
14
+ Features:
15
+ * Liken software build process to cooking.
16
+ * Two-style approach support: YAML-style and Ruby-style.
17
+ * Natural notation for production rule and optional ingredients.
18
+ * 'tar.gz', 'tar.bz2', and '.zip' support
19
+ (requires 'minitar', 'bz2', and 'rubyzip' libraries.)
20
+ * Able to invoke build command forcedly
21
+
12
22
  Attention! Rook is under alpha version and specification
13
23
  may change frequently.
14
24
 
15
25
 
16
- .$ Installation
17
26
 
18
- Just copy bin/rook file into a proper directory such as
19
- /usr/local/bin or /usr/bin.
27
+ == Installation
20
28
 
29
+ If you have installed RubyGems, just stype 'gem install -r rook'.
30
+ $ sudo gem install -r rook
21
31
 
22
- .$ Usage
32
+ Otherwise download ruby_X.X.X.tar.bz2 and install with setup.rb.
33
+ $ tar xjf rook_X.X.X.tar.bz2
34
+ $ cd rook_X.X.X/
35
+ $ sudo setup.rb
23
36
 
24
- Install Rook and type `rook --help'.
37
+ (Must) If you have installed rook without RubyGems, the following
38
+ libraries must be installed.
39
+ * abstract.rb (>= 1.0.0) (http://www.rubyforge.org/projects/abstract)
40
+ * kwalify (>= 0.6.0) (http://www.rubyforge.org/projects/kwalify)
25
41
 
42
+ (Optional) If you want to handle *.tar.gz, *.tar.bz2, or *.zip
43
+ files, you must install the following libraries.
44
+ * minitar - http://raa.ruby-lang.org/project/minitar/
45
+ * bz2 - http://raa.ruby-lang.org/project/bz2/
46
+ * rubyzip - http://raa.ruby-lang.org/project/rubyzip/
26
47
 
27
- .$ Terms
48
+ (Optional) Helper script 'ruby_X.X.X/contrib/inline_require.rb'
49
+ merges 'bin/rook' and rook libraries into a file.
50
+ $ cd rook_X.X.X/
51
+ $ unset RUBYLIB
52
+ $ ruby contrib/inline_require.rb -I lib bin/rook > contrib/rook
28
53
 
29
- .[ Product ]
30
- Product is an output of cooking.
31
54
 
32
- .[ Ingredient ]
33
- Ingredient is materials needed for cooking.
34
55
 
35
- .[ Recipe ]
36
- Recipe is a method how to cook product.
56
+ == Examples
37
57
 
38
- .[ Generic recipe ]
39
- Generic recipe is a recipe whose product is
40
- specified as regular expression.
58
+ The following is an example of Rookbook.yaml to cook *.c files.
59
+ (Rookbook is the equivarent to Makefile in Make or Rakefile in Rake.)
41
60
 
42
- .[ Specific recipe ]
43
- Specific recipe is a recipe whose product is
44
- specified as filename.
61
+ properties:
62
+ - project: hello
63
+ - c_flags: '-g -Wall -O2'
45
64
 
46
- .[ Symbolic recipe ]
47
- Symbolic recipe is a recipe whose product is
48
- specified as Symbol.
65
+ variables:
66
+ - command: $(project)
67
+ - objfiles*: Dir.glob('*.c').collect{|f| f.sub(/\.c$/, '.o')}
49
68
 
69
+ recipes:
70
+ - product: $(command)
71
+ ingreds: [ $(objfiles) ]
72
+ desc: create '$(command)' command
73
+ method: |
74
+ sys "gcc #{@c_flags} -o #{@product} #{@ingreds.join(' ')}"
50
75
 
51
- .$ Example
76
+ - product: *.o
77
+ ingreds: [ $(1).c ]
78
+ options: [ $(1).h ]
79
+ method: |
80
+ sys "gcc #{@c_flags} -c #{@ingred}"
52
81
 
53
- See `examples/' directory.
82
+ - product: :clean
83
+ method: |
84
+ rm_f Dir.glob("*.o")
54
85
 
55
86
 
56
- .$ To Do
87
+ Rook supports two style of Rookbook: YAML-style and Ruby-style.
88
+ The following ('Rookbook.rb') is the Ruby-style example of Rookbook
89
+ which is equivarent to the above YAML-style example.
57
90
 
58
- .* [_] Documentation
59
- .* [_] Fingerprint support
60
- .* [_] Dependency Tree
61
- .* [_] Plugin architecture
91
+ property :project, 'hello'
92
+ property :c_flags, '-g -Wall -O2'
62
93
 
94
+ command = @project
95
+ objfiles = Dir.glob('*.c').collect{|f| f.sub(/\.c$/, '.o')}
63
96
 
64
- .$ License
97
+ desc "create '#{command}' command"
98
+ recipe command, objfiles do |r|
99
+ sys "gcc #{@c_flags} -o #{@product} #{@ingreds.join(' ')}"
100
+ end
65
101
 
66
- GPL ver2
102
+ recipe "*.o", '$(1).c', :options=>['$(1).h'] do |r|
103
+ sys "gcc #{@c_flags} -c #{@ingred}"
104
+ end
105
+
106
+ recipe :clean do |r|
107
+ rm_f Dir.glob("*.o")
108
+ end
109
+
110
+
111
+ See 'examples/' directory for more examples.
112
+
113
+
114
+ == Documents
115
+
116
+ Sorry, there is no documentation.
117
+
118
+
119
+ == Terms
120
+
121
+ [ Product ]
122
+ Output of cooking.
67
123
 
124
+ [ Ingredient ]
125
+ Materials needed for cooking.
68
126
 
69
- .$ Copyright
127
+ [ Byproduct ]
128
+ Garbages produced in cooking.
70
129
 
71
- Copyright(c) makoto kuwata all rights reserved
130
+ [ Recipe ]
131
+ Method how to cook product.
132
+
133
+ [ Generic recipe ]
134
+ Recipe which product is specified by pattern.
135
+ This is equivarent to 'rule' in Rake.
136
+
137
+ [ Specific recipe ]
138
+ Recipe which product is specified by name.
139
+ This is equivarent to 'file' in Rake.
140
+
141
+ [ Symbolic recipe ]
142
+ Recipe which product is specified by Symbol.
143
+ This is equivarent to 'task' in Rake.
144
+
145
+
146
+
147
+ == To Do
148
+
149
+ * [_] Documentation
150
+ * [_] Fingerprint support
151
+ * [_] Dependency Tree
152
+ * [_] Plugin architecture
153
+
154
+
155
+
156
+ == License
157
+
158
+ GPL ver2
72
159
 
73
160
 
data/bin/rook CHANGED
@@ -1,906 +1,12 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- ###
4
- ### rook - a SCM(Software Cooking Method) tool, like `make', `cook', or `rake'
5
- ###
6
- ### copryright(c) 2005 makoto kuwata all rights reserverd
7
- ###
8
- ### $Id: rook 14 2005-04-30 02:16:15Z kwatch $
9
- ### $Release: 0.0.2$
10
- ###
3
+ ##
4
+ ## $Rev: 18 $
5
+ ## $Release: 0.1.0 $
6
+ ## copyright(c) 2006 kuwata-lab.com all rights reserved.
7
+ ##
11
8
 
12
- require 'fileutils'
9
+ require 'rook'
10
+ require 'rook/main'
13
11
 
14
- ## force FileUtils to print message to $stdout
15
- FileUtils.instance_eval "@fileutils_output = $stdout"
16
-
17
- module Rook
18
-
19
- VERSION = ('$Rev: 14 $' =~ /(\d+)/) && $1
20
- LAST_UPDATE = ('$Date: 2005-04-30 11:16:15 +0900 (Sat, 30 Apr 2005) $' =~ /([-\d]+)/) && $1
21
- RELEASE = ('$Release: 0.0.2$' =~ /([\.\d]+)/) && $1
22
-
23
- $rook_defaults = {
24
- :bookname => 'Rookbook', # or 'Cookbook.rb'
25
- :target => :default, # or :start
26
- :descriptions => {
27
- :all => 'create all products',
28
- :clean => 'remove by-products',
29
- :clear => 'remove all products and by-products',
30
- :deploy => 'deploy products',
31
- :config => 'configure',
32
- :setup => 'setup',
33
- :install => 'install products',
34
- #:start => 'start cooking',
35
- :default => 'default recipe to start'
36
- },
37
- }
38
- $rook_prompt = "rook$ "
39
- $rook_current_recipe = nil
40
- $rook_properties = {}
41
- $rook_context = {}
42
- $rook_recipe_desc = nil
43
-
44
-
45
- class RookError < StandardError
46
- end
47
-
48
- class RecipeNotFoundError < RookError
49
- end
50
-
51
- class CommandOptionError < RookError
52
- end
53
-
54
- class GenericRecipeExecutionError < RookError
55
- end
56
-
57
- class RecipeExecutionError < RookError
58
- end
59
-
60
- class RecipeError < RookError
61
- end
62
-
63
- class IngredientNotFoundError < RookError
64
- end
65
-
66
- class CookbookNotFoundError < RookError
67
- end
68
-
69
- class AssersionError
70
- end
71
-
72
-
73
- ##
74
- ##
75
- ##
76
- class Cookbook
77
- def initialize(bookname)
78
- @bookname = bookname
79
- @specific_recipes = []
80
- @generic_recipes = []
81
- @symbolic_recipes = []
82
- #
83
- #unless test(?f, @bookname)
84
- # raise CookbookNotFoundError.new("`#{@bookname}': cookbook not found.")
85
- #end
86
- #load(@bookname) ## load cookbook
87
- end
88
- attr_reader :bookname
89
- attr_reader :specific_recipes, :generic_recipes, :symbolic_recipes
90
-
91
- def add_specific_recipe(recipe)
92
- @specific_recipes.unshift(recipe)
93
- recipe.cookbook = self
94
- end
95
-
96
- def add_generic_recipe(recipe)
97
- @generic_recipes.unshift(recipe)
98
- recipe.cookbook = self
99
- end
100
-
101
- def add_symbolic_recipe(recipe)
102
- @symbolic_recipes.unshift(recipe)
103
- recipe.cookbook = self
104
- end
105
-
106
- def add_recipe(recipe)
107
- recipe.add_to_cookbook(self)
108
- end
109
-
110
- def lookup(product, index=0)
111
- if product.is_a?(String) && product[0] == ?:
112
- product = product[1, product.length-1].intern
113
- end
114
- recipe = nil
115
- if index == 0
116
- case product
117
- when Symbol
118
- recipe = @symbolic_recipes.find { |r| r.product === product }
119
- when String
120
- recipe = @specific_recipes.find { |r| r.product === product }
121
- if !recipe
122
- recipe = @generic_recipes.find { |r| r.product === product }
123
- recipe = recipe.specify(product) if recipe
124
- end
125
- end
126
- else
127
- case product
128
- when Symbol
129
- recipes = @symbolic_recipes.find_all { |r| r.product === product }
130
- recipe = recipes[index]
131
- when String
132
- recipes = @specific_recipes.find_all { |r| r.product === product }
133
- recipes2 = @generic_recipes.find_all { |r| r.product === product }
134
- recipes.concat(recipes2)
135
- recipe = recipe[index]
136
- recipe = specify(product) if recipe
137
- end
138
- end
139
- return recipe
140
- end
141
-
142
- def create_context()
143
- context = {
144
- :cookbook => self,
145
- :dress_level => 0,
146
- }
147
- return context
148
- end
149
-
150
- def _execute()
151
- ## prework
152
- rook_context_bkup = $rook_context
153
- $rook_context = create_context()
154
- unless test(?f, @bookname)
155
- raise CookbookNotFoundError.new("`#{@bookname}': cookbook not found.")
156
- end
157
- load(@bookname) ## load cookbook
158
- ## main body
159
- yield()
160
- ## postwork
161
- $rook_context = rook_context_bkup
162
- end
163
- private :_execute
164
-
165
- def start(targets)
166
- _execute() do
167
- if targets == nil || targets.empty?
168
- target = $rook_defaults[:target]
169
- recipe = lookup(target)
170
- raise AssertionError.new("recipe.class=#{recipe.class.name}") if recipe.kind_of?(GenericRecipe)
171
- if recipe
172
- recipe.execute()
173
- else
174
- #raise RecipeNotFoundError.new("#{target}: recipe not found.")
175
- puts "*** target is not specified."
176
- listup()
177
- end
178
- else
179
- targets.each do |target|
180
- target = target[1,target.length-1].intern if target.is_a?(String) && target[0] == ?:
181
- recipe = lookup(target)
182
- raise RecipeNotFoundError.new("#{target}: recipe not found.") unless recipe
183
- raise AssertionError.new("recipe.class=#{recipe.class.name}") if recipe.kind_of?(GenericRecipe)
184
- recipe.execute()
185
- end
186
- end
187
- end
188
- end
189
-
190
- def listup()
191
- _listup(@symbolic_recipes, false)
192
- _listup(@specific_recipes, false)
193
- _listup(@generic_recipes, false)
194
- end
195
-
196
- def listup_all()
197
- _listup(@symbolic_recipes, true)
198
- _listup(@specific_recipes, true)
199
- _listup(@generic_recipes, true)
200
- end
201
-
202
- def _listup(recipe_list, flag_all=true)
203
- _execute() do
204
- list = []; hash = {}
205
- recipe_list.each do |recipe|
206
- next if hash.key?(recipe.product)
207
- next unless flag_all || recipe.desc
208
- hash[recipe.product] = true
209
- list << recipe
210
- end
211
- list.reverse.each do |recipe|
212
- product = recipe.product
213
- display_name = recipe.display_name
214
- #display_name = product.is_a?(String) ? product : product.inspect
215
- description = recipe.desc || '(no description)'
216
- puts(" %-20s - %s" % [ display_name, description ])
217
- end
218
- end
219
- end
220
-
221
- end
222
-
223
-
224
- ##
225
- ##
226
- ##
227
- class Recipe
228
-
229
- def add_to_cookbook
230
- raise AssertionError.new("Recipe#add_to_cookbook() not implemented.")
231
- end
232
-
233
- def initialize(product, *ingredients, &steps)
234
- @product = product
235
- @ingredients = []
236
- ingredients.each do |ingred|
237
- add_ingredient(ingred)
238
- end if ingredients
239
- @steps = steps
240
- @matched = nil
241
- @cookbook = nil
242
- @desc = nil
243
- end
244
-
245
- def self.create(product, *ingredients, &steps)
246
- self.new(product, *ingredients, &steps)
247
- end
248
-
249
- attr_accessor :product, :ingredients, :steps, :matched, :cookbook, :desc
250
-
251
- alias :prod :product
252
- alias :ingreds :ingredients
253
- def ingredient
254
- return @ingredients[0]
255
- end
256
- alias :ingred :ingredient
257
-
258
- attr_writer :display_name
259
- def display_name
260
- return @display_name || @product
261
- end
262
-
263
- def add_ingredient(ingred)
264
- case ingred
265
- when String, Symbol, Proc, Hash
266
- @ingredients << ingred
267
- when Array
268
- ingred.each do |ingred2|
269
- add_ingredient(ingred2)
270
- end
271
- when Regexp
272
- raise ReicpeError.new("#{ingred.to_s}: regexp is not avairable as ingredient.")
273
- else
274
- raise RecipeError.new("`#{ingred.to_s}'(class #{ingred.class.name}): ingredient is invalid object.")
275
- end
276
- end
277
-
278
- def execute(depth=0)
279
- bkup = $rook_current_recipe
280
- $rook_current_recipe = self
281
- puts "### #{self.product.to_s}" unless $rook_properties[:QUIET]
282
- @steps.call(self) if @steps
283
- $rook_current_recipe = bkup
284
- return true
285
- end
286
-
287
- def specify(product)
288
- raise AssertionError.new("Root#specify() is called.")
289
- end
290
-
291
- end
292
-
293
-
294
- ##
295
- ##
296
- ##
297
- class SpecificRecipe < Recipe
298
-
299
- def add_to_cookbook(cookbook)
300
- cookbook.add_specific_recipe(self)
301
- end
302
-
303
- def initialize(product, *ingredients, &steps)
304
- super(product, *ingredients, &steps)
305
- end
306
-
307
- def self.create(product, *ingredients, &steps)
308
- recipe = self.new(product, *ingredients, &steps)
309
- if ingredients.find { |ingred| ingred.is_a?(Hash) }
310
- raise RecipeError.new("`#{product}': specific recipe can't take a hash as an ingredient.")
311
- end
312
- return recipe
313
- end
314
-
315
- def specify(product)
316
- return self
317
- end
318
-
319
- def execute(depth=0)
320
- flag_execute = false
321
- if @ingredients.empty?
322
- flag_execute = true
323
- else
324
- if test(?e, @product)
325
- prod_mtime = File.mtime(@product)
326
- else
327
- prod_mtime = nil
328
- flag_execute = true
329
- end
330
- @ingredients.each do |ingred|
331
- ingred_recipe = cookbook().lookup(ingred)
332
- if ingred_recipe
333
- flag = ingred_recipe.execute(depth+1)
334
- flag_execute = true if flag
335
- end
336
- if !flag_execute && _ingred_newer?(ingred, prod_mtime)
337
- flag_execute = true
338
- end
339
- end
340
- unless $rook_properties[:noact]
341
- @ingredients.each do |ingred|
342
- if ingred.is_a?(String) && !test(?e, ingred)
343
- raise IngredientNotFoundError.new("`#{ingred}': ingredient not found (required by `#{@product}').")
344
- end
345
- end
346
- end
347
- end
348
- if flag_execute || $rook_properties[:FORCE] || (depth == 0 && $rook_properties[:force])
349
- begin
350
- super(depth)
351
- rescue RecipeExecutionError => ex
352
- File.delete(@product) if test(?f, @product)
353
- raise ex
354
- end
355
- end
356
- return flag_execute
357
- end
358
-
359
- def _ingred_newer?(ingred, prod_mtime)
360
- return ingred.is_a?(String) && test(?e, ingred) && prod_mtime && prod_mtime < File.mtime(ingred)
361
- end
362
-
363
- end
364
-
365
-
366
- ##
367
- ##
368
- ##
369
- class GenericRecipe < Recipe
370
- def add_to_cookbook(cookbook)
371
- cookbook.add_generic_recipe(self)
372
- end
373
-
374
- def initialize(product_pattern, *ingredients, &steps)
375
- super(product_pattern, *ingredients, &steps)
376
- end
377
-
378
- def self.create(product_pattern, *ingredients, &steps)
379
- recipe = self.new(product_pattern, *ingredients, &steps)
380
- return recipe
381
- end
382
-
383
- def display_name
384
- return @display_name || @product.inspect
385
- end
386
-
387
- ## generates specific recipe
388
- def specify(product)
389
- ingred_list = []
390
- pattern = @product
391
- pattern =~ product
392
- m = [ $&, $1, $2, $3, $4, $5 ]
393
- @ingredients.each do |ingred|
394
- case ingred
395
- when String
396
- ingred2 = expand_matched(ingred, m)
397
- ingred_list << ingred2
398
- when Symbol
399
- ingred_list << ingred
400
- when Proc
401
- result = ingred.call(product)
402
- ingred_list << result if result
403
- when Hash
404
- ingred.each do |key, val|
405
- case key
406
- when :if_exists
407
- ingred2 = expand_matched(val, m)
408
- ingred_list << ingred2 if test(?e, ingred2)
409
- else
410
- raise RecipeError.new("`:#{key.id2name}': invalid keyword.")
411
- end
412
- end
413
- else
414
- raise RecipeError.new("#{product.to_s}(class #{product.class.name}): invalid product.")
415
- end
416
- end if @ingredients
417
- recipe = SpecificRecipe.new(product, *ingred_list, &@steps)
418
- recipe.matched = m
419
- recipe.cookbook = self.cookbook()
420
- return recipe
421
- end
422
-
423
- def execute(depth=0)
424
- raise GenericRecipeExecutionError.new("cannot execute generic recipe.")
425
- end
426
-
427
- end
428
-
429
-
430
- ##
431
- ##
432
- ##
433
- class SymbolicRecipe < Recipe
434
-
435
- def add_to_cookbook(cookbook)
436
- cookbook.add_symbolic_recipe(self)
437
- end
438
-
439
- def initialize(product_pattern, *ingredients, &steps)
440
- super(product_pattern, *ingredients, &steps)
441
- end
442
-
443
- def self.create(product, *ingredients, &steps)
444
- recipe = self.new(product, *ingredients, &steps)
445
- if ingredients.find { |ingred| ingred.is_a?(Hash) }
446
- raise RecipeError.new("`#{product}': symbolic recipe can't take a hash as an ingredient.")
447
- end
448
- return recipe
449
- end
450
-
451
- def display_name
452
- return @display_name || @product.inspect
453
- end
454
-
455
- def execute(depth=0)
456
- @ingredients.each do |ingred|
457
- recipe = cookbook().lookup(ingred)
458
- if recipe
459
- flag = recipe.execute(depth+1)
460
- flag_execute = true if flag
461
- end
462
- end
463
- super(depth)
464
- return true
465
- #flag_execute = false
466
- #if @ingredients.empty?
467
- # flag_execute = true
468
- #else
469
- # @ingredients.each do |ingred|
470
- # recipe = cookbook().lookup(ingred)
471
- # if recipe
472
- # flag = recipe.execute(depth+1)
473
- # flag_execute = true if flag
474
- # end
475
- # end
476
- #end
477
- #if flag_execute
478
- # super(depth)
479
- #end
480
- #return flag_execute
481
- end
482
-
483
- def specify(product)
484
- raise AssertionError.new("SymbolicRecipe#specify is called.")
485
- end
486
- end
487
- end
488
-
489
-
490
- module RookCommand
491
-
492
- ##
493
- ##
494
- ##
495
- def desc(description=nil)
496
- $rook_recipe_desc = description
497
- end
498
-
499
- def recipe(product, *ingredients, &steps)
500
- cookbook = $rook_context[:cookbook]
501
- case product
502
- when String
503
- recipe = Rook::SpecificRecipe.create(product, *ingredients, &steps)
504
- cookbook.add_specific_recipe(recipe)
505
- when Regexp
506
- recipe = Rook::GenericRecipe.create(product, *ingredients, &steps)
507
- cookbook.add_generic_recipe(recipe)
508
- when Symbol
509
- recipe = Rook::SymbolicRecipe.create(product, *ingredients, &steps)
510
- cookbook.add_symbolic_recipe(recipe)
511
- end
512
- ## set description
513
- if $rook_recipe_desc == nil
514
- recipe.desc = $rook_defaults[:descriptions][product]
515
- elsif $rook_recipe_desc == false
516
- recipe.desc = nil
517
- else
518
- recipe.desc = $rook_recipe_desc
519
- end
520
- $rook_recipe_desc = nil
521
- return recipe
522
- end
523
-
524
- def grecipe(product, *ingredients, &steps)
525
- ## convert wildcard ('*', '?', and '{}') into Regexp
526
- s = product.to_s
527
- s = Regexp::quote(s)
528
- s.gsub!(/(\\\?+)/) { |m| '(' + ('.' * m.length) + ')' }
529
- s.gsub!(/(\\\*)/, '(.*?)')
530
- s.gsub!(/(\\\{(.*?)\\\})/) { '(' + $2.gsub(/\\\|/, '|') + ')' }
531
- s.gsub!(/%/, '(.*?)')
532
- regexp = Regexp::compile("^#{s}$")
533
- r = recipe(regexp, *ingredients, &steps)
534
- r.display_name = product
535
- return r
536
- end
537
-
538
- def rook(*targets)
539
- bookname = $rook_context[:cookbook].bookname
540
- cookbook = Rook::Cookbook.new(bookname)
541
- targets = expand_matched(targets, m()) if m()
542
- cookbook.start(targets)
543
- end
544
-
545
- def dress(product=nil)
546
- product = $rook_current_recipe.product if !product
547
- $rook_context[:dress_level] += 1
548
- recipe = $root_context[:cookbook].lookup(product, $rook_context[:dress_level])
549
- recipe.execute()
550
- $rook_context[:dress_level] -= 1
551
- end
552
-
553
- def set_prompt(prompt)
554
- $rook_prompt = prompt
555
- end
556
-
557
- def get_prompt()
558
- $rook_prompt
559
- end
560
-
561
-
562
- def expand_matched(obj, m=nil)
563
- m = $rook_current_recipe.matched unless m
564
- return obj unless m
565
- case obj
566
- when String
567
- if m
568
- obj = obj.dup
569
- obj.gsub!(/\{0\}/, m[0]) if m[0]
570
- obj.gsub!(/\{1\}/, m[1]) if m[1]
571
- obj.gsub!(/\{2\}/, m[2]) if m[2]
572
- obj.gsub!(/\{3\}/, m[3]) if m[3]
573
- obj.gsub!(/\{4\}/, m[4]) if m[4]
574
- obj.gsub!(/\{5\}/, m[5]) if m[5]
575
- end
576
- when Array
577
- obj = obj.collect { |item| expand_matched(item, m) }
578
- end
579
- return obj
580
- end
581
- private :expand_matched
582
-
583
- def m()
584
- return $rook_current_recipe.matched
585
- end
586
-
587
- def _cmd(cmd_str, prompt, ignore_error)
588
- cmd_str = expand_matched(cmd_str, m()) if m()
589
- print get_prompt(), cmd_str, "\n" unless $rook_properties[:quiet]
590
- unless $rook_properties[:noact]
591
- result = system(cmd_str)
592
- else
593
- result = true
594
- end
595
- unless result || ignore_error
596
- raise Rook::RecipeExecutionError.new("command failed: `#{cmd_str}'")
597
- end
598
- return result
599
- end
600
- private :_cmd
601
-
602
- def cmd(cmd_str, prompt=$rook_prompt)
603
- _cmd(cmd_str, prompt, false)
604
- end
605
- alias :sh :cmd
606
- alias :cmd :cmd
607
- #alias :do :cmd
608
-
609
- def cmd!(cmd_str, prompt=$rook_prompt)
610
- cmd(cmd_str, prompt, true)
611
- end
612
- alias sh! cmd!
613
- #alias do! cmd!
614
-
615
- def echo(*args)
616
- args = expand_matched(args, m()) if m()
617
- unless $rook_properties[:noact]
618
- echo_n(*args)
619
- puts
620
- end
621
- end
622
-
623
- def echo_n(*args)
624
- unless $rook_properties[:noact]
625
- print args.flatten.join(" ")
626
- end
627
- end
628
-
629
-
630
- def chdir(dir, &block)
631
- dir = expand_matched(dir, m()) if m()
632
- opts = {}
633
- opts[:noop] = true if $rook_properties[:noact]
634
- opts[:verbose] = true if ! $rook_properties[:quiet]
635
- print get_prompt() if opts[:verbose]
636
- FileUtils.chdir(dir, opts, &block)
637
- end
638
- alias :cd :chdir
639
-
640
- def _command1(command, args)
641
- args = args.flatten
642
- args = expand_matched(args, m()) if m()
643
- opts = {}
644
- opts[:noop] = true if $rook_properties[:noact]
645
- opts[:verbose] = true if ! $rook_properties[:quiet]
646
- print get_prompt() if opts[:verbose]
647
- FileUtils.__send__(command, args, opts)
648
- end
649
- private :_command1
650
-
651
- def mkdir(*dirs)
652
- _command1(:mkdir, dirs)
653
- end
654
-
655
- def mkdir_p(*dirs)
656
- _command1(:mkdir_p, dirs)
657
- end
658
-
659
- def rmdir(*dirs)
660
- _command1(:rmdir, dirs)
661
- end
662
-
663
- def remove(*files)
664
- _command1(:rm, files)
665
- end
666
- alias :rm :remove
667
-
668
- def remove_r(*files)
669
- _command1(:rm_r, files)
670
- end
671
- alias :rm_r :remove_r
672
-
673
- def remove_rf(*files)
674
- _command1(:rm_rf, files)
675
- end
676
- alias :rm_rf :remove_rf
677
-
678
-
679
- def _command1_ifexists(command, files)
680
- list = files.flatten.find_all { |f| test(?e, f) }
681
- _command1(command, list) unless list.empty?
682
- end
683
-
684
- def delete(*files)
685
- _command1_ifexists(:rm, files)
686
- end
687
- alias :del :delete
688
-
689
- def delete_r(*files)
690
- _command1_ifexists(:rm_r, files)
691
- end
692
- alias :del_r :delete_r
693
-
694
- def delete_rf(*files)
695
- _command1_ifexists(:rm_rf, files)
696
- end
697
- alias :del_rf :delete_rf
698
-
699
-
700
- def _command2(command, args)
701
- args = args.flatten
702
- args = expand_matched(args, m()) if m()
703
- src = dest = nil
704
- if args.length == 1
705
- src = args[0]
706
- elsif args.length > 1
707
- dest = args.pop
708
- src = args
709
- end
710
- opts = {}
711
- opts[:noop] = true if $rook_properties[:noact]
712
- opts[:verbose] = true if !$rook_properties[:quiet]
713
- print get_prompt() if opts[:verbose]
714
- FileUtils.__send__(command, src, dest, opts)
715
- end
716
- private :_command2
717
-
718
- def copy(*args)
719
- _command2(:cp, args)
720
- end
721
- alias :cp :copy
722
-
723
- def copy_r(*args)
724
- _command2(:cp_r, args)
725
- end
726
- alias :cp_r :copy_r
727
-
728
- def move(*args)
729
- _command2(:mv, args)
730
- end
731
- alias :mv :move
732
-
733
- def store(*args, &filter)
734
- args = args.flatten
735
- args = expand_matched(args, m()) if m()
736
- store_to = args.pop
737
- src_files = []
738
- args.each do |file|
739
- src_files.concat Dir.glob(file)
740
- end
741
- src_files.delete_if { |f| !filter.call(f) } if filter
742
- if ! $rook_properties[:quiet]
743
- print get_prompt()
744
- print "store #{args.join(' ')} #{store_to}"
745
- puts
746
- end
747
- if ! $rook_properties[:noact]
748
- src_files.each do |f|
749
- srcdir = File::dirname(f)
750
- destdir = "#{store_to}/#{srcdir}"
751
- FileUtils.mkdir_p(destdir) unless test(?d, destdir)
752
- FileUtils.cp_r(f, destdir) unless test(?d, f)
753
- end
754
- end
755
- end
756
-
757
- end
758
-
759
-
760
- module Rook
761
- ##
762
- ##
763
- ##
764
- class Main
765
- def initialize(argv = ARGV)
766
- @argv = argv
767
- end
768
-
769
- def execute
770
- options, properties = parse_argv(@argv)
771
- if properties[:help]
772
- properties.delete(:help)
773
- options[?h] = true
774
- end
775
- if properties[:version]
776
- properties.delete(:version)
777
- options[?v] = true
778
- end
779
- if options[?h] || options[?v]
780
- command = File::basename($0)
781
- puts "#{command} - a SCM (Software Cooking Method) tool" if options[?h]
782
- puts version() if options[?v]
783
- puts usage() if options[?h]
784
- return
785
- end
786
- properties[:noact] = true if options[?n]
787
- properties[:quiet] = true if options[?q]
788
- properties[:quiet] = properties[:QUIET] = true if options[?Q]
789
- properties[:force] = true if options[?f]
790
- properties[:force] = properties[:FORCE] = true if options[?F]
791
- $rook_properties = properties
792
- $rook_prompt = options[?p] if options[?p]
793
- #
794
- bookname = options[?b] || $rook_defaults[:bookname]
795
- cookbook = Cookbook.new(bookname)
796
- if options[?l] || options[?T]
797
- cookbook.listup()
798
- elsif options[?L]
799
- cookbook.listup_all()
800
- else
801
- targets = @argv
802
- cookbook.start(targets)
803
- #elsif !@argv.empty?
804
- # targets = @argv
805
- # cookbook.start(targets)
806
- #elsif cookbook.lookup($rook_defaults[:target]) == nil
807
- # puts "*** target is not specified."
808
- # cookbook.listup()
809
- #else
810
- # target = $rook_defaults[:target]
811
- # cookbook.start([target])
812
- end
813
- end
814
-
815
- def usage()
816
- command = File::basename($0)
817
- s = ""
818
- s << "usage: #{command} [options] target-product\n"
819
- s << " -h : help\n"
820
- s << " -v : version\n"
821
- s << " -b cookbook : cookbook (default `#{$rook_defaults[:bookname]}')\n"
822
- s << " -p prompt : set prompt\n"
823
- s << " -n : no execute\n"
824
- s << " -q : quiet\n"
825
- s << " -Q : more quiet\n"
826
- s << " -l : list described recipes\n"
827
- s << " -L : list all recipes\n"
828
- s << " -f : force\n"
829
- s << " -F : force strongly\n"
830
- end
831
-
832
- def version()
833
- return "Release: #{Rook::RELEASE} (Revision: #{Rook::VERSION})"
834
- end
835
-
836
- def parse_argv(argv)
837
- options = []
838
- properties = {}
839
- while argv[0] && argv[0][0] == ?-
840
- optstr = argv.shift.dup
841
- optstr.gsub!(/\A-/, '')
842
- if optstr[0] == ?-
843
- optstr.gsub!(/\A-/, '')
844
- if optstr =~ /\A([-\w]+)(=(.*))?\z/
845
- prop_name = $1.gsub(/-/, '_')
846
- prop_value = $3
847
- properties[prop_name.intern] = prop_value == nil ? true : parse_value(prop_value)
848
- end
849
- else
850
- while optstr && !optstr.empty?
851
- optchar = optstr[0]
852
- optstr.gsub!(/\A./, '')
853
- case optchar
854
- when ?h, ?v, ?n, ?q, ?Q, ?f, ?F, ?l, ?L
855
- options[optchar] = true
856
- when ?b, ?p
857
- arg = optstr.empty? ? ARGV.shift : opstr
858
- optstr = nil
859
- unless arg
860
- case optchar
861
- when ?f ; msg = "-#{optchar.chr}: cookbook required."
862
- when ?p ; msg = "-#{optchar.chr}: prompt required."
863
- end
864
- raise CommandOptionError.new(msg)
865
- end
866
- options[optchar] = arg
867
- else
868
- raise CommandOptionError.new("-#{optchar.chr}: invalid option.")
869
- end
870
- end
871
- end
872
- end
873
- return options, properties
874
- end
875
-
876
- def parse_value(value)
877
- case value
878
- when 'true', 'yes' ; return true
879
- when 'false', 'no' ; return false
880
- when 'nil', 'null' ; return nil
881
- when /\A\d+\z/ ; return value.to_i # eval(value)
882
- when /\A\d+\.\d+\z/ ; return value.to_f # eval(value)
883
- when /\A\/(.*)\/\z/ ; return Regexp.compile($1) # eval(value)
884
- when /\A:(.*)\z/ ; return $1.intern # eval(value)
885
- when /\A'.*'\z/ ; return eval(value)
886
- when /\A".*"\z/ ; return eval(value) # unsafe?
887
- else ; return value
888
- end
889
- end
890
- end
891
-
892
- end
893
-
894
-
895
- #if __FILE__ == $0
896
- include RookCommand
897
- begin
898
- main = Rook::Main.new(ARGV)
899
- main.execute
900
- rescue Rook::RookError => ex
901
- $stderr.puts "[ERROR] #{ex.message}"
902
- #if ex.class == CommandOptionError
903
- # $stderr.puts main.usage()
904
- #end
905
- end
906
- #end
12
+ Rook::Main.main(ARGV)