rook 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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)