rant 0.4.8 → 0.5.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 (49) hide show
  1. data/NEWS +31 -0
  2. data/README +3 -1
  3. data/Rantfile +53 -2
  4. data/doc/advanced.rdoc +86 -1
  5. data/doc/c.rdoc +8 -0
  6. data/doc/homepage/index.html +2 -0
  7. data/doc/rant.1 +4 -0
  8. data/doc/rant.rdoc +38 -0
  9. data/doc/rant_vs_rake.rdoc +13 -0
  10. data/doc/rantfile.rdoc +93 -63
  11. data/doc/sys.rdoc +568 -0
  12. data/lib/rant/coregen.rb +43 -16
  13. data/lib/rant/import/command.rb +7 -4
  14. data/lib/rant/import/filelist/more.rb +57 -0
  15. data/lib/rant/import/metadata.rb +5 -1
  16. data/lib/rant/import/nodes/default.rb +3 -24
  17. data/lib/rant/import/signedfile.rb +1 -8
  18. data/lib/rant/import/sys/more.rb +2 -1
  19. data/lib/rant/import/var/booleans.rb +65 -0
  20. data/lib/rant/import/var/lists.rb +34 -0
  21. data/lib/rant/import/var/numbers.rb +116 -0
  22. data/lib/rant/import/var/strings.rb +43 -0
  23. data/lib/rant/import.rb +19 -3
  24. data/lib/rant/node.rb +39 -6
  25. data/lib/rant/rantlib.rb +44 -8
  26. data/lib/rant/rantsys.rb +22 -54
  27. data/lib/rant/rantvar.rb +89 -256
  28. data/misc/TODO +18 -0
  29. data/misc/devel-notes +26 -1
  30. data/test/action.rant +24 -0
  31. data/test/deprecated/test_0_5_4.rb +53 -0
  32. data/test/deprecated/test_0_6_0.rb +1 -1
  33. data/test/dryrun/Rantfile +10 -0
  34. data/test/dryrun/foo.c +8 -0
  35. data/test/dryrun/test_dryrun.rb +31 -0
  36. data/test/import/c/dependencies/Rantfile +1 -1
  37. data/test/import/command/Rantfile +1 -1
  38. data/test/import/sys/test_tgz.rb +22 -0
  39. data/test/subdirs2/root.rant +11 -1
  40. data/test/subdirs2/sub1/sub.rant +3 -0
  41. data/test/subdirs2/test_subdirs2.rb +19 -0
  42. data/test/test_action.rb +75 -0
  43. data/test/test_filelist.rb +13 -10
  44. data/test/test_rant_interface.rb +2 -2
  45. data/test/test_rule.rb +121 -3
  46. data/test/test_sys_methods.rb +558 -0
  47. data/test/test_var.rb +10 -0
  48. data/test/tutil.rb +81 -8
  49. metadata +19 -2
data/doc/sys.rdoc ADDED
@@ -0,0 +1,568 @@
1
+
2
+ == sys methods
3
+
4
+ The +sys+ object, which is accessible from anywhere in an Rantfile,
5
+ provides many methods for common file system operations like deleting,
6
+ copying, moving, comparing and writing files.
7
+
8
+ Unless explicitely mentioned otherwise, the following statements apply
9
+ to all below documented methods:
10
+
11
+ 1. Portable across all supported platforms.
12
+ 2. Ignore the return value!
13
+ 3. The messages printed to standard output may change.
14
+ 4. Error conditions are reported through exceptions of class
15
+ +SystemCallError+ or subclasses of +SystemCallError+.
16
+
17
+ The following methods print messages to standard output:
18
+
19
+ * <b>cd(dir)</b>
20
+
21
+ Change the current directory to +dir+. +dir+ may be an absolute path
22
+ or a path relative to the current directory.
23
+ If a block is given, the current directory will be changed to +dir+,
24
+ then the block is executed and it is ensured, that after block
25
+ execution the old working directory is resumed (even if an exception
26
+ is thrown during block execution).
27
+
28
+ Examples:
29
+
30
+ # relative path
31
+ sys.pwd # => "/home/user"
32
+ sys.cd "tmp" # prints "cd tmp"
33
+ sys.pwd # => "/home/user/tmp"
34
+ sys.cd ".." # prints "cd .."
35
+ sys.pwd # => "/home/user"
36
+
37
+ # absolute path
38
+ sys.cd "/etc" # prints "cd /etc"
39
+ sys.pwd # => "/etc"
40
+
41
+ # relative path, with block
42
+ sys.pwd # => "/home/user"
43
+ sys.cd "tmp" do
44
+ sys.pwd # => "/home/user/tmp"
45
+ # perform some operations, may
46
+ # also call sys.cd
47
+ sys.cd "/etc"
48
+ end
49
+ sys.pwd # => "/home/user"
50
+
51
+ * <b>rm(file)</b>
52
+
53
+ Remove +file+. +file+ may be an absolute or relative path (string).
54
+ If +file+ is an array of strings or a filelist, remove all entries
55
+ of +file+.
56
+
57
+ Examples:
58
+
59
+ # remove the file "util.o" in the current directory
60
+ sys.rm "util.o" # prints "rm util.o"
61
+
62
+ # remove all files ending in ".o" in the "lib" directory
63
+ sys.rm sys["lib/*.o"]
64
+
65
+ Raises a +SystemCallError+ if +file+ doesn't exist or is a
66
+ directory.
67
+
68
+ * <b>rm_f(file)</b>
69
+
70
+ Same as <tt>rm(file)</tt>, but doesn't throw an exception if +file+
71
+ doesn't exist.
72
+
73
+ Example:
74
+
75
+ # remove "main.o" if it exists
76
+ sys.rm_f "main.o" # prints "rm -f main.o"
77
+
78
+ * <b>rmdir(dir)</b>
79
+
80
+ Remove the empty directory +dir+. +dir+ may be a list of strings, a
81
+ filelist or a string. Raises a +SystemCallError+ if +dir+ is not
82
+ empty or doesn't exist.
83
+
84
+ Examples:
85
+
86
+ # remove empty directory "/home/user/tmp"
87
+ sys.rmdir "/home/user/tmp"
88
+
89
+ # remove empty directory, relative path
90
+ sys.rmdir "tmp"
91
+
92
+ # remove empty directories "tmp" and "/usr/local/tmp"
93
+ sys.rmdir ["tmp", "/usr/local/tmp"]
94
+
95
+ # remove all (empty) directories in the current directory ending
96
+ # in ".t"
97
+ sys.rmdir sys["*.t"]
98
+
99
+ * <b>rm_r(entry)</b>
100
+
101
+ If +entry+ is a (relative or absolute) path to a file, simply
102
+ removes the file. If +entry+ is a directory, remove the directory
103
+ and all its contents (including subdirectories).
104
+
105
+ If +entry+ is an array of pathes or a filelist, remove all entries
106
+ listed in +entry+ (directories are removed, including their
107
+ contents, too).
108
+
109
+ Examples:
110
+
111
+ # remove the "tmp" directory and all its contents
112
+ sys.rm_r "tmp" # prints "rm -r tmp"
113
+
114
+ Raises a +SystemCallError+ if +entry+ doesn't exist.
115
+
116
+ * <b>rm_rf(entry)</b>
117
+
118
+ Does the same as <tt>rm_r(entry)</tt>, but doesn't raise an
119
+ exception if +entry+ doens't exist.
120
+
121
+ Example:
122
+
123
+ # remove the "tmp" directory and all its contents if it exists
124
+ sys.rm_rf "tmp" # prints "rm -rf tmp"
125
+
126
+ * <b>mkdir(dir)</b>
127
+
128
+ If +dir+ is a string, create the new directory +dir+. +dir+ may be a
129
+ relative or absolute path.
130
+
131
+ Examples:
132
+
133
+ # relative path
134
+ sys.mkdir "foo"
135
+
136
+ # absolute path
137
+ sys.mkdir "/home/user/foo"
138
+
139
+ If +dir+ is a list of strings, or a filelist, create all directories
140
+ listed in +dir+.
141
+
142
+ Example:
143
+
144
+ # with array, creates directory "foo" and directory "bar"
145
+ sys.mkdir ["foo", "bar"]
146
+
147
+ Raises a +SystemCallError+ if a file/directory with this name
148
+ already exists.
149
+
150
+ * <b>mkdir_p(dir)</b>
151
+
152
+ Creates the directory +dir+ and all its parent directories, if
153
+ necessary. Does nothing if +dir+ already exists.
154
+
155
+ If +dir+ is an array/filelist, creates all directories listed in
156
+ +dir+.
157
+
158
+ Examples:
159
+
160
+ # creates "/usr" if a directory of this name doesn't exist
161
+ # creates "/usr/local" if a directory of this name doesn't exist
162
+ # creates "/usr/local/bin" if a directory of this name doesn't exist
163
+ sys.mkdir_p "/usr/local/bin" # prints "mkdir -p /usr/local/bin"
164
+
165
+ # creates the three given pathes
166
+ sys.mkdir_p ["foo/include", "foo/src/util", "foo/src/ui"]
167
+
168
+ * <b>cp(src, dest)</b>
169
+
170
+ If +src+ is a (relative or absolute) path to a file, copy the file
171
+ +src+ to +dest+.
172
+
173
+ Example:
174
+
175
+ # copy "main.c" to "build/main.c"
176
+ sys.cp "main.c", "build/main.c" # prints "cp main.c build/main.c"
177
+
178
+ If +dest+ is a directory, copy +src+ to <tt>dest/src</tt>.
179
+ If +src+ is an array of strings or a filelist, copy all files listed
180
+ in +src+ to the directory +dest+.
181
+
182
+ Examples:
183
+
184
+ # copy "main.c" to the "build" directory
185
+ sys.cp "main.c", "build"
186
+
187
+ # copy all files ending in ".c" from the current directory to the
188
+ # "build" directory
189
+ sys.cp sys["*.c"], "build"
190
+
191
+ Raises a +SystemCallError+ if +src+ is a directory or doesn't exist.
192
+
193
+ * <b>cp_r(src, dest)</b>
194
+
195
+ Does the same as <tt>cp(src, dest)</tt>, but also accepts a
196
+ directory/directories as +src+. Directories are recursively copied
197
+ to +dest+.
198
+
199
+ Example:
200
+
201
+ # Recursively copy all files/directories in the "src" directory
202
+ # to the (existing) "/backup" directory.
203
+ sys.cp_r sys["src/*"], "/backup" # prints "cp -r <list of src/* files> /backup"
204
+
205
+ * <b>mv(src, dest)</b>
206
+
207
+ If +src+ is a path (string), move the file +src+ to +dest+.
208
+
209
+ Example:
210
+
211
+ # move "build/foo.exe" to "dist/foo.exe"
212
+ sys.mv "build/foo.exe", "dist/foo.exe" # prints "mv build/foo.exe dist/foo.exe"
213
+
214
+ If +dest+ is a directory, move +src+ do <tt>dest/src</tt>. If +src+
215
+ is an array of pathes or a filelist, move all entries of +src+ to
216
+ the directory +dest+.
217
+
218
+ Example:
219
+
220
+ # move all files ending in ".exe" from the "build" directory to
221
+ # the "dist" directory
222
+ sys.mv sys["build/*.exe"], "dist"
223
+
224
+ +src+ may also be a (empty or non-empty) directory. Of course a
225
+ mixed array/filelist of "normal" files and directories is also
226
+ allowed.
227
+
228
+ Raises a +SystemCallError+ if +src+ is an array/filelist and +dest+
229
+ is not a directory.
230
+
231
+ * <b>touch(file)</b>
232
+
233
+ +file+ may be a single path to a file, an array of pathes or a
234
+ filelist. Updates the modification time and the access time of all
235
+ files. If a file doesn't exist, creates an empty one with this name.
236
+
237
+ Examples:
238
+
239
+ # "main.c" is a file, update its modification time
240
+ sys.touch "main.c"
241
+
242
+ # "ts1" and "ts2" don't exist, create two empty files
243
+ sys.touch ["ts1", "ts2"]
244
+
245
+ * <b>safe_ln(src, dest)</b>
246
+
247
+ This creates a hard link +dest+ which points to the same file as
248
+ +src+, on platforms that support hard links. Simply copies +src+ to
249
+ +dest+ on other platforms.
250
+
251
+ Example:
252
+
253
+ # link or copy "main.c" to "package/main.c"
254
+ sys.safe_ln "main.c", "package/main.c"
255
+ # prints "ln main.c package/main.c" if a hard link is created
256
+ # prints "cp main.c package/main.c" if is main.c is copied
257
+
258
+ * <b>ln(src, dest)</b>
259
+
260
+ Creates a hard link +dest+ which points to the same file as +src+. If
261
+ +dest+ is a directory, creates the hard link <tt>dest/src</tt>.
262
+
263
+ Example:
264
+
265
+ # link "main.c" to "package/main.c"
266
+ sys.ln "main.c", "package" # prints "ln main.c package"
267
+
268
+ Raises a +SystemCallError+ if +dest+ is a file or doesn't exist.
269
+
270
+ Note:: Not all file systems and operating systems support hard
271
+ links.
272
+ On operating systems without support for hard links,
273
+ a +NotImplementedError+ exception is risen.
274
+ If the operating system supports hard links, but the file
275
+ system not, a +SystemCallError+ is risen.
276
+
277
+ * <b>ln_f(src, dest)</b>
278
+
279
+ Same as <tt>ln(src, dest)</tt>, but overwrites +dest+ if +dest+
280
+ is a file.
281
+
282
+ Example:
283
+
284
+ # link "main.c" to "package/main.c", overwriting any existing
285
+ # "package/main.c" file
286
+ sys.ln_f "main.c", "package"
287
+
288
+ # ... equivalent to
289
+ sys.ln_f "main.c", "package/main.c"
290
+
291
+ * <b>ln_s(src, dest)</b>
292
+
293
+ Creates a symbolic link +dest+ which points to +src+. If +dest+ is a
294
+ directory, creates the symbolic link <tt>dest/src</tt>.
295
+
296
+ Examples:
297
+
298
+ # Create the symbolic link "NEWS" to the existing file "ChangeLog"
299
+ sys.ln_s "ChangeLog", "NEWS" # prints "ln -s ChangeLog NEWS"
300
+
301
+ Raises a +SystemCallError+ if +dest+ is the name of an existing
302
+ file or +src+ doesn't exist.
303
+
304
+ Note:: Not all file systems and operating systems support
305
+ symbolic links.
306
+ On operating systems without support for symbolic links, a
307
+ +NotImplementedError+ exception is risen. If the
308
+ operating system supports symbolic links, but the file
309
+ system not, a +SystemCallError+ is risen.
310
+
311
+ * <b>ln_sf(src, dest)</b>
312
+
313
+ Same as <tt>ln_s(src, dest)</tt>, but overwrites +dest+ if +dest+
314
+ exists.
315
+
316
+ Example:
317
+
318
+ # Create the symbolic link "NEWS" to the existing file
319
+ # "ChangeLog", overwrite any existing "NEWS" file.
320
+ sys.ln_s "ChangeLog", "NEWS" # prints "ln -sf ChangeLog NEWS"
321
+
322
+ * <b>install(src, dest, options = {})</b>
323
+
324
+ Copy file +src+ to +dest+ if +dest+ doesn't exist or differs from
325
+ +src+. Install +src+ to <tt>dest/src</tt> if +dest+ is a directory.
326
+ If +src+ is an array/filelist, installs each entry in +src+ under
327
+ the +dest+ directory.
328
+
329
+ Options is a hash which may contain the following keys:
330
+
331
+ <tt>:mode</tt>:: If given, after copying the mode of the target
332
+ file(s) is changed to the integer given as
333
+ value.
334
+
335
+ <tt>:preserve</tt>:: Takes either +true+ or +false+. If given and
336
+ +true+, the target file(s) will have the same
337
+ access and modification times as the source
338
+ file(s).
339
+
340
+ Examples:
341
+
342
+ # copy the file "./ruby" to "/usr/local/bin/ruby19" and change the
343
+ # mode of the target file to 0755.
344
+ sys.install "ruby", "/usr/local/bin/ruby19", :mode => 0755
345
+
346
+ # install all files in the "lib" directory in "/usr/lib/foo" and
347
+ # change the access and modification times of the target files to
348
+ # match those of their source files.
349
+ sys.install sys["lib/*"], "/usr/lib/foo", :preserve => true
350
+
351
+ * <b>chmod(mode, file)</b>
352
+
353
+ +file+ may be a single file name or an array/filelist. Changes the
354
+ file permissions of all given files to the bit pattern represented
355
+ by the integer +mode+.
356
+
357
+ Examples:
358
+
359
+ # make file "/usr/local/bin/ruby" executable
360
+ sys.chmod 0755, "/usr/local/bin/ruby" # prints "chmod 0755 /usr/local/bin/ruby"
361
+
362
+ # make all files in the "bin" directory executable
363
+ sys.chmod 0755, sys["bin/*"]
364
+
365
+ Note:: Not all file systems/operating systems support the same
366
+ permission bits. This method will only set the supported
367
+ ones.
368
+
369
+ * <b>ruby(arg1, arg2, ...)</b>
370
+
371
+ Starts a new ruby interpreter with the given arguments.
372
+
373
+ Example:
374
+
375
+ sys.ruby "setup.rb", "--prefix=/usr" # prints "<absolute path to ruby> setup.rb --prefix=/usr"
376
+
377
+ IMPORTANT:: It does NOT start a subshell.
378
+
379
+ Bad Example:
380
+
381
+ # This probably does not do what was intended. Ruby will search
382
+ # for the script file with the name "setup.rb --prefix=/usr"!
383
+ sys.ruby "setup.rb --prefix=/usr"
384
+
385
+ Note:: Rant determines the absolute path to the ruby interpreter
386
+ which is running the current Rant instance. It uses this
387
+ path to start a new ruby interpreter. As a result, this
388
+ method will also work when "ruby" is not on the PATH.
389
+
390
+ * <b>write_to_file(fn, text)</b>
391
+
392
+ Requires <tt>import "sys/more"</tt>
393
+
394
+ Write the string +text+ to the file with name +fn+. If the file
395
+ already exists, it is overwritten, otherwise a new file is created.
396
+
397
+ Example:
398
+
399
+ import "sys/more"
400
+
401
+ sys.write_to_file "version", "1.2.0\n" # => prints "writing 6 bytes to file `version'"
402
+
403
+ * <b>unpack_tgz(fn, options = {})</b>
404
+
405
+ Requires <tt>import "sys/tgz"</tt>
406
+
407
+ Unpack the gzipped tar archive file with the file name +fn+ in the
408
+ current directory. If +options+ contains the key <tt>:in</tt>, its
409
+ value will be used as name of the output directory.
410
+
411
+ Example:
412
+
413
+ import "sys/tgz"
414
+
415
+ # Creates the "pkg" directory if it doesn't exist and unpacks all
416
+ # contents of "rant-0.4.6.tgz" in the "pkg" directory.
417
+ sys.unpack_tgz "rant-0.4.6.tgz", :in => "pkg"
418
+
419
+ Existing files will be overwritten.
420
+
421
+ * <b>unpack_zip(fn, options = {})</b>
422
+
423
+ Requires <tt>import "sys/zip"</tt>
424
+
425
+ Unpack the zip archive file with the file name +fn+ in the current
426
+ directory. If +options+ contains the key <tt>:in</tt>, its value
427
+ will be used as name of the output directory.
428
+
429
+ Example:
430
+
431
+ import "sys/zip"
432
+
433
+ # Creates the "pkg" directory if it doesn't exist and unpacks all
434
+ # contents of "rant-0.4.6.zip" in the "pkg" directory.
435
+ sys.unpack_zip "rant-0.4.6.zip", :in => "pkg"
436
+
437
+ Existing files will be overwritten.
438
+
439
+ The following methods are "silent", i.e. they don't print messages to
440
+ standard output:
441
+
442
+ * <b>pwd</b>
443
+
444
+ Returns the current working directory as string.
445
+
446
+ Example:
447
+
448
+ sys.pwd # => "/home/user"
449
+
450
+ * <b>compare_file(a, b)</b>
451
+
452
+ Returns true if the files +a+ and +b+ have the same contents, false
453
+ otherwise.
454
+
455
+ Example:
456
+
457
+ unless sys.compare_file("lib/main.c", "/backup/main.c")
458
+ puts "lib/main.c differs from /backup/main.c"
459
+ end
460
+
461
+ Raises a +SystemCallError+ if +a+ or +b+ is not a file.
462
+
463
+ * <b>uptodate?(new, old_list)</b>
464
+
465
+ Returns true if the file with name +new+ is newer (checked by file
466
+ modification time) than all files listed in the +old_list+
467
+ array/filelist. A non-existent file (including +new+) is considered
468
+ older than any other file.
469
+
470
+ Example:
471
+
472
+ unless sys.uptodate?("foo.exe", sys["src/*.c", "include/*.h"])
473
+ puts "(re)build of foo.exe required"
474
+ end
475
+
476
+ * <b>expand_path(path)</b>
477
+
478
+ Resolves any "." or ".." elements in +path+ and expands +path+ to an
479
+ absolute path. Replaces a leading <tt>@</tt> character with an
480
+ absolute path to the project's root directory. Returns the resulting
481
+ path string.
482
+
483
+ Examples, assuming current directory is "/home/user/project/sub"
484
+ and project root directory is "/home/user/project":
485
+
486
+ sys.expand_path("README") # => "/home/user/project/sub/README"
487
+ sys.expand_path("./README") # => "/home/user/project/sub/README"
488
+ sys.expand_path("@README") # => "/home/user/project/README"
489
+ sys.expand_path("../../README") # => "/home/user/README"
490
+ sys.expand_path("/@README") # => "/@README"
491
+ sys.expand_path("subsub/./../") # => "/home/user/project/sub"
492
+
493
+ * <b>split_all(path)</b>
494
+
495
+ Splits +path+ into all its elements and returns and array.
496
+
497
+ Examples:
498
+
499
+ sys.split_all("abc") # => ["abc"]
500
+ sys.split_all("foo/bar") # => ["foo", "bar"]
501
+ sys.split_all("foo/bar/baz") # => ["foo", "bar", "baz"]
502
+
503
+ * <b>escape(arg)</b>
504
+
505
+ Escapes all spaces in +arg+ for the shell which is used on the
506
+ current platform. Returns the escaped string.
507
+
508
+ Example:
509
+
510
+ sys.escape("foo bar")
511
+ # gives on Windows: '"foo bar"'
512
+ # other systems: 'foo\ bar'
513
+
514
+ If +arg+ is an array (or filelist) all elements are escaped and the
515
+ resulting strings joined together, seperated by spaces.
516
+
517
+ Example:
518
+
519
+ sys.escape(["foo bar", "arg 2"])
520
+ # gives on Windows: '"foo bar" "arg 2"'
521
+ # other systems: 'foo\ bar arg\ 2'
522
+
523
+ Note:: Might escape more special shell characters in the future.
524
+
525
+ * <b>sp(path)</b>
526
+
527
+ Does the same as <tt>escape(path)</tt>, but also replaces all
528
+ slashes with backslashes on windows.
529
+
530
+ Example:
531
+
532
+ libdir = "/home/user/program files/d"
533
+ sources = ["foo bar.d", "util.d"]
534
+ sys "dmd #{sys.sp sources} -offoo -I#{sys.sp libdir}"
535
+ # executes the command
536
+ # on windows: 'dmd "foo bar.d" util.d -offoo -I"/home/user/program files/d"'
537
+ # other systems: 'dmd foo\ bar.d util.d -offoo -I/home/user/program\ files/d'
538
+
539
+ * <b>glob(pattern1, pattern2, ...)</b>
540
+
541
+ <b>[pattern1, pattern2, ...]</b>
542
+
543
+ Returns a filelist including the given patterns. For a discussion of
544
+ filelists, read <em>Selecting files with filelists</em> in
545
+ doc/advanced.rdoc[link:files/doc/advanced_rdoc.html].
546
+
547
+ Examples:
548
+
549
+ # the following two are equivalent
550
+ sys.glob("*.c", "*.h")
551
+ sys["*.c", "*.h"]
552
+
553
+ Filelists created with this method, ignore entries starting with a
554
+ dot.
555
+
556
+ * <b>glob_all(pattern1, pattern2, ...)</b>
557
+
558
+ Like <tt>glob(pattern1, pattern2, ...)</tt>, but the created filelist
559
+ doesn't ignore entries starting with a dot.
560
+
561
+ == See also
562
+
563
+ Rantfile basics::
564
+ doc/rantfile.rdoc[link:files/doc/rantfile_rdoc.html]
565
+ Advanced Rantfiles::
566
+ doc/advanced.rdoc[link:files/doc/advanced_rdoc.html]
567
+ Rant Overview::
568
+ README[link:files/README.html]
data/lib/rant/coregen.rb CHANGED
@@ -105,6 +105,7 @@ module Rant
105
105
  unless args.size == 1
106
106
  rac.abort_at(ch, "Rule takes only one argument.")
107
107
  end
108
+ rac.abort_at(ch, "Rule: block required.") unless block
108
109
  arg = args.first
109
110
  target = nil
110
111
  src_arg = nil
@@ -178,16 +179,9 @@ module Rant
178
179
  have_src = true
179
180
  src = @src_proc[target]
180
181
  if src.respond_to? :to_ary
181
- src.each { |f|
182
- if @rant.resolve(f).empty? && !test(?e, f)
183
- have_src = false
184
- break
185
- end
186
- }
182
+ have_src = src.to_ary.all? { |s| have_src?(s) }
187
183
  else
188
- if @rant.resolve(src).empty? && !test(?e, src)
189
- have_src = false
190
- end
184
+ have_src = have_src?(src)
191
185
  end
192
186
  if have_src
193
187
  create_nodes(rel_project_dir, target, src)
@@ -196,6 +190,10 @@ module Rant
196
190
  end
197
191
  alias [] call
198
192
  private
193
+ def have_src?(name)
194
+ !@rant.rec_save_resolve(name, self).empty? or
195
+ test(?e, name)
196
+ end
199
197
  def create_nodes(rel_project_dir, target, deps)
200
198
  case nodes = @block[target, deps]
201
199
  when Array: nodes
@@ -210,6 +208,11 @@ module Rant
210
208
  end
211
209
  class FileHook < Hook
212
210
  private
211
+ def have_src?(name)
212
+ test(?e, name) or
213
+ @rant.rec_save_resolve(name, self
214
+ ).any? { |t| t.file_target? }
215
+ end
213
216
  def create_nodes(rel_project_dir, target, deps)
214
217
  t = @rant.file(:__caller__ => @ch,
215
218
  target => deps, &@block)
@@ -220,14 +223,38 @@ module Rant
220
223
  end # class Rule
221
224
  class Action
222
225
  def self.rant_gen(rac, ch, args, &block)
223
- unless args.empty?
224
- rac.warn_msg(rac.pos_text(ch[:file], ch[:ln]),
225
- "Action doesn't take arguments.")
226
- end
227
- unless (rac[:tasks] || rac[:stop_after_load])
228
- yield
229
- end
226
+ case args.size
227
+ when 0:
228
+ unless (rac[:tasks] || rac[:stop_after_load])
229
+ yield
230
+ end
231
+ when 1:
232
+ rx = args.first
233
+ unless rx.kind_of? Regexp
234
+ rac.abort_at(ch, "Action: argument has " +
235
+ "to be a regular expression.")
236
+ end
237
+ rac.resolve_hooks << self.new(rac, block, rx)
238
+ nil
239
+ else
240
+ rac.abort_at(ch, "Action: too many arguments.")
241
+ end
230
242
  end
243
+ def initialize(rant, block, rx)
244
+ @rant = rant
245
+ @subdir = @rant.current_subdir
246
+ @block = block
247
+ @rx = rx
248
+ end
249
+ def call(target, rel_project_dir)
250
+ if target =~ @rx
251
+ @rant.resolve_hooks.delete(self)
252
+ @rant.goto_project_dir @subdir
253
+ @block.call
254
+ @rant.resolve(target, rel_project_dir)
255
+ end
256
+ end
257
+ alias [] call
231
258
  end
232
259
  end # module Generators
233
260
  end # module Rant
@@ -113,8 +113,8 @@ module Rant
113
113
  def val_for_interp_var(var)
114
114
  case var
115
115
  when "name": self.name
116
- when "prerequisites": self.prerequisites
117
- when "source": self.source
116
+ when "prerequisites": prerequisites.map { |n| rac.resolve_root_ref(n) }
117
+ when "source": rac.resolve_root_ref(source)
118
118
  else
119
119
  cx = rac.cx
120
120
  val = cx.var._get(var) || (
@@ -143,8 +143,8 @@ module Rant
143
143
  def val_for_interp_sym(sym)
144
144
  case sym
145
145
  when ">": name
146
- when "<": prerequisites
147
- when "-": source
146
+ when "<": prerequisites.map { |n| rac.resolve_root_ref(n) }
147
+ when "-": rac.resolve_root_ref(source)
148
148
  end
149
149
  end
150
150
  end
@@ -173,6 +173,9 @@ module Rant
173
173
  end
174
174
  @command_changed = @cmd_key = @new_sig = @md = nil
175
175
  end
176
+ def pre_action_descs
177
+ [@command ? "SHELL\n#@command" : "SHELL"]
178
+ end
176
179
  private
177
180
  def res_command(node)
178
181
  return if @command