rant 0.4.2 → 0.4.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data/NEWS +14 -0
  2. data/README +13 -7
  3. data/Rantfile +11 -0
  4. data/doc/md5.rdoc +49 -0
  5. data/doc/rantfile.rdoc +1 -1
  6. data/lib/rant/coregen.rb +193 -0
  7. data/lib/rant/import/archive/zip.rb +2 -0
  8. data/lib/rant/import/archive.rb +10 -2
  9. data/lib/rant/import/autoclean.rb +16 -7
  10. data/lib/rant/import/c/dependencies.rb +1 -1
  11. data/lib/rant/import/directedrule.rb +2 -2
  12. data/lib/rant/import/md5.rb +16 -0
  13. data/lib/rant/import/metadata.rb +162 -0
  14. data/lib/rant/import/nodes/default.rb +490 -0
  15. data/lib/rant/import/nodes/signed.rb +84 -0
  16. data/lib/rant/import/package/zip.rb +2 -0
  17. data/lib/rant/import/rubydoc.rb +5 -1
  18. data/lib/rant/import/rubypackage.rb +2 -1
  19. data/lib/rant/import/signature/md5.rb +38 -0
  20. data/lib/rant/import/signedfile.rb +235 -0
  21. data/lib/rant/import/subfile.rb +1 -1
  22. data/lib/rant/import.rb +5 -1
  23. data/lib/rant/node.rb +165 -0
  24. data/lib/rant/plugin/csharp.rb +2 -0
  25. data/lib/rant/rantlib.rb +64 -9
  26. data/lib/rant/rantsys.rb +39 -27
  27. data/lib/rant/rantvar.rb +32 -2
  28. data/misc/TODO +66 -0
  29. data/test/import/c/dependencies/test_on_the_fly.rb +52 -0
  30. data/test/import/metadata/Rantfile +16 -0
  31. data/test/import/metadata/sub/Rantfile +17 -0
  32. data/test/import/metadata/test_metadata.rb +126 -0
  33. data/test/import/nodes/signed/Rantfile +89 -0
  34. data/test/import/nodes/signed/sub1/Rantfile +6 -0
  35. data/test/import/nodes/signed/test_signed.rb +455 -0
  36. data/test/import/package/md5.rf +10 -0
  37. data/test/import/package/test_package.rb +127 -1
  38. data/test/import/signeddirectory/Rantfile +15 -0
  39. data/test/import/signeddirectory/test_signeddirectory.rb +84 -0
  40. data/test/import/signedfile/Rantfile +90 -0
  41. data/test/import/signedfile/sub1/Rantfile +4 -0
  42. data/test/import/signedfile/test_signedfile.rb +338 -0
  43. data/test/project1/Rantfile +0 -9
  44. data/test/project1/test_project.rb +2 -0
  45. data/test/project_rb1/test_project_rb1.rb +27 -10
  46. data/test/rant-import/test_rant-import.rb +46 -9
  47. data/test/subdirs/sub2/sub/rantfile +0 -5
  48. data/test/subdirs/test_subdirs.rb +0 -9
  49. data/test/test_examples.rb +131 -3
  50. data/test/test_filelist.rb +44 -0
  51. data/test/test_sys.rb +19 -1
  52. data/test/test_task.rb +2 -2
  53. data/test/tutil.rb +9 -3
  54. metadata +34 -4
  55. data/lib/rant/rantfile.rb +0 -897
  56. data/test/test_lighttask.rb +0 -68
data/lib/rant/rantsys.rb CHANGED
@@ -19,7 +19,8 @@ module Rant
19
19
  # Initialized to 0.
20
20
  attr_accessor :glob_flags
21
21
 
22
- attr_reader :ignore_rx
22
+ attr_accessor :ignore_rx
23
+ protected :ignore_rx=
23
24
 
24
25
  class << self
25
26
  def [](*patterns)
@@ -33,6 +34,7 @@ module Rant
33
34
  @actions = patterns.map { |pat| [:apply_include, pat] }
34
35
  @ignore_rx = nil
35
36
  @pending = true
37
+ @keep = {}
36
38
  yield self if block_given?
37
39
  end
38
40
 
@@ -41,6 +43,7 @@ module Rant
41
43
  c.files = @files.dup
42
44
  c.actions = @actions.dup
43
45
  c.ignore_rx = @ignore_rx.dup if @ignore_rx
46
+ c.instance_variable_set(:@keep, @keep.dup)
44
47
  c
45
48
  end
46
49
 
@@ -67,35 +70,32 @@ module Rant
67
70
  end
68
71
 
69
72
  def +(other)
70
- case other
71
- when Array
72
- c = dup
73
- c.files.concat(other)
74
- c
75
- when FileList
73
+ if FileList === other
76
74
  c = other.dup
77
75
  c.actions.concat(@actions)
78
76
  c.files.concat(@files)
79
77
  c.pending = !c.actions.empty?
80
78
  c
81
- else
79
+ elsif other.respond_to? :to_ary
80
+ c = dup
81
+ c.actions <<
82
+ [:apply_ary_method_1, :concat, other.to_ary.dup]
83
+ c.pending = true
84
+ c
85
+ else
82
86
  raise "argument has to be an Array or FileList"
83
- end
87
+ end
84
88
  end
85
89
 
86
- # Add file to filelist unless it matches an exclude pattern.
87
- # Take care: Don't rely on any order when inserting a file
88
- # with this method!
89
- def add(file)
90
- @files << file unless file =~ ignore_rx
91
- self
92
- end
93
-
94
- # Like #add but doesn't honor exclude patterns.
90
+ # Use this method to append +file+ to this list. +file+ will
91
+ # stay in this list even if it matches an exclude or ignore
92
+ # pattern.
93
+ #
95
94
  # Returns self.
96
95
  def <<(file)
97
- #STDERR.puts caller unless String === file
98
96
  @actions << [:apply_ary_method_1, :push, file]
97
+ @keep[file] = true
98
+ @pending = true
99
99
  self
100
100
  end
101
101
 
@@ -132,7 +132,7 @@ module Rant
132
132
  @actions.clear
133
133
  ix = ignore_rx
134
134
  if ix
135
- @files.reject! { |f| f =~ ix }
135
+ @files.reject! { |f| f =~ ix && !@keep[f] }
136
136
  end
137
137
  end
138
138
 
@@ -182,14 +182,14 @@ module Rant
182
182
 
183
183
  def apply_exclude(pattern)
184
184
  @files.reject! { |elem|
185
- File.fnmatch? pattern, elem, @glob_flags
185
+ File.fnmatch?(pattern, elem, @glob_flags) && !@keep[elem]
186
186
  }
187
187
  end
188
188
  private :apply_exclude
189
189
 
190
190
  def apply_exclude_rx(rx)
191
191
  @files.reject! { |elem|
192
- elem =~ rx
192
+ elem =~ rx && !@keep[elem]
193
193
  }
194
194
  end
195
195
  private :apply_exclude_rx
@@ -262,12 +262,13 @@ module Rant
262
262
  entry = nil
263
263
  unless name
264
264
  @files.reject! { |entry|
265
- test(?d, entry)
265
+ test(?d, entry) && !@keep[entry]
266
266
  }
267
267
  return
268
268
  end
269
269
  elems = nil
270
270
  @files.reject! { |entry|
271
+ next if @keep[entry]
271
272
  elems = Sys.split_path(entry)
272
273
  i = elems.index(name)
273
274
  if i
@@ -283,7 +284,9 @@ module Rant
283
284
  # Remove all files which have the given name.
284
285
  def no_file(name)
285
286
  @actions << [:apply_ary_method, :reject!,
286
- lambda { |entry| entry == name and test(?f, entry) }]
287
+ lambda { |entry|
288
+ entry == name && !@keep[entry] && test(?f, entry)
289
+ }]
287
290
  @pending = true
288
291
  self
289
292
  end
@@ -302,7 +305,7 @@ module Rant
302
305
  @files.reject! { |entry|
303
306
  elems = Sys.split_path(entry)
304
307
  elems.any? { |elem|
305
- elem =~ /#{suffix}$/
308
+ elem =~ /#{suffix}$/ && !@keep[entry]
306
309
  }
307
310
  }
308
311
  end
@@ -321,7 +324,7 @@ module Rant
321
324
  @files.reject! { |entry|
322
325
  elems = Sys.split_path(entry)
323
326
  elems.any? { |elem|
324
- elem =~ /^#{prefix}/
327
+ elem =~ /^#{prefix}/ && !@keep[entry]
325
328
  }
326
329
  }
327
330
  end
@@ -356,6 +359,8 @@ module Rant
356
359
  self
357
360
  end
358
361
 
362
+ # Same as #map! but evaluation is delayed until the next read
363
+ # access (e.g. by calling #each). Always returns self.
359
364
  def lazy_map!(&block)
360
365
  @actions << [:apply_ary_method, :map!, block]
361
366
  @pending = true
@@ -510,6 +515,13 @@ module Rant
510
515
  def fu_output_message(msg) #:nodoc:
511
516
  ::Rant.rac.cmd_msg msg if ::Rant.rac
512
517
  end
518
+ private :fu_output_message
519
+
520
+ def fu_each_src_dest(src, *rest)
521
+ src = src.to_ary if src.respond_to? :to_ary
522
+ super(src, *rest)
523
+ end
524
+ private :fu_each_src_dest
513
525
 
514
526
  # Run an external command. When given one argument, this is
515
527
  # subject to shell interpretation. Otherwise the first
@@ -553,7 +565,7 @@ module Rant
553
565
  else
554
566
  begin
555
567
  ln(*args)
556
- rescue Errno::EOPNOTSUPP
568
+ rescue Exception #Errno::EOPNOTSUPP
557
569
  Sys.symlink_supported = false
558
570
  cp(*args)
559
571
  end
data/lib/rant/rantvar.rb CHANGED
@@ -16,7 +16,7 @@
16
16
  # If you're looking for general info about Rant, read the
17
17
  # README[link:files/README.html].
18
18
  module Rant
19
- VERSION = '0.4.2'
19
+ VERSION = '0.4.4'
20
20
 
21
21
  # Those are the filenames for rantfiles.
22
22
  # Case matters!
@@ -52,7 +52,7 @@ module Rant
52
52
  end
53
53
 
54
54
  module MetaUtils
55
- # Creates two accessor methods:
55
+ # Creates three accessor methods:
56
56
  # obj.attr_name:: Return value of instance variable
57
57
  # @attr_name
58
58
  # obj.attr_name = val:: Set value instance variable
@@ -72,6 +72,24 @@ module Rant
72
72
  EOD
73
73
  nil
74
74
  end
75
+ # Creates three accessor methods:
76
+ # obj.attr_name?:: Return value, true or false
77
+ # obj.attr_name:: Set attribute to true
78
+ # obj.no_attr_name:: Set attribute to false
79
+ def rant_flag attr_name
80
+ attr_name = valid_attr_name attr_name
81
+ module_eval <<-EOD
82
+ def #{attr_name}?
83
+ @#{attr_name}
84
+ end
85
+ def #{attr_name}
86
+ @#{attr_name} = true
87
+ end
88
+ def no_#{attr_name}
89
+ @#{attr_name} = false
90
+ end
91
+ EOD
92
+ end
75
93
  # Creates accessor methods like #rant_attr for the attribute
76
94
  # attr_name. Additionally, values are converted with to_str
77
95
  # before assignment to instance variables happens.
@@ -314,6 +332,18 @@ module Rant
314
332
  !self[vid].nil?
315
333
  end
316
334
 
335
+ def _set(vid, val) #:nodoc:
336
+ @store[vid] = val
337
+ end
338
+
339
+ def _get(vid) #:nodoc:
340
+ @store[vid]
341
+ end
342
+
343
+ def _init(vid, val) #:nodoc:
344
+ @store[vid] ||= val
345
+ end
346
+
317
347
  end # class Space
318
348
 
319
349
  module Constraint
data/misc/TODO CHANGED
@@ -1,6 +1,72 @@
1
1
 
2
2
  = TODO
3
3
 
4
+ == Improve SourceNode types
5
+
6
+ Currently a SourceNode can only have other SourceNodes or files as
7
+ prerequisites. But if e.g., a header file should be autogenerated,
8
+ this isn't sufficient anymore.
9
+
10
+ ---
11
+ Update
12
+
13
+ Done (0.4.3) for SignedSourceNodes.
14
+
15
+ == Deprecate plugin API
16
+
17
+ ... and provide alternatives for the Configure and CSharp plugins.
18
+
19
+ == FileList
20
+
21
+ FileList objects need a method which adds a file which won't be
22
+ removed by any pattern (also not affected by var[:ignore]).
23
+
24
+ ---
25
+ Done (0.4.3).
26
+
27
+ Use FileList#<< to append a single entry which won't be removed by
28
+ exclude/ignore patterns.
29
+
30
+ == Semantics of directories as prerequisites of file creating nodes.
31
+
32
+ Currently there are two so called "file creating" nodes: FileTask and
33
+ SignedFile. The following treatments of a directory as prerequisite
34
+ are possible:
35
+
36
+ 1. Current behaviour:
37
+ FileTask:: If a directory node exists, invoke it and compare if
38
+ the modification time of the directory is newer than
39
+ the target file.
40
+ SignedFile:: If a directory node exists, invoke it. If the
41
+ invocation return true, rebuild target file. If no
42
+ directory node exists, create a signature of the
43
+ directory by reading its entries and check this
44
+ signature against the signature of the last time the
45
+ target file was built.
46
+
47
+ 2. Just check if a directory node exists and invoke it. Trigger target
48
+ rebuild if +invoke+ returns true. If no node exists do nothing
49
+ special, the directory doesn't trigger a target file rebuild.
50
+
51
+ I'm currently in favour of #2.
52
+
53
+ ---
54
+ *Update*
55
+
56
+ Current behaviour:
57
+ FileTask:: If a directory node exists, invoke it and compare if
58
+ the modification time of the directory is newer than
59
+ the target file. If no node exists, just compare the
60
+ modification time.
61
+ SignedFile:: If a directory node exists, invoke it and trigger a
62
+ rebuild if +invoke+ returns true. Anyway create a
63
+ signature of the path, which results in a rebuild if
64
+ the directory path changes once. This could be
65
+ considered an inconsistency since path/name changes of
66
+ other prerequisites don't trigger a rebuild.
67
+
68
+ == Don't use testrb as testrunner for RubyTest.
69
+
4
70
  == Solve archiving dependency problem
5
71
  Because of timed depdencies, the archiving tasks don't recognize if
6
72
  the only change is that a file was removed. The only exception is a
@@ -41,4 +41,56 @@ class TestImportCDependenciesOnTheFly < Test::Unit::TestCase
41
41
  assert_rant("-frf.t")
42
42
  assert(File.mtime("bar.t") > old_mtime)
43
43
  end
44
+ def write(fn, content)
45
+ open fn, "w" do |f|
46
+ f.write content
47
+ end
48
+ end
49
+ def test_md5
50
+ write "include/a.tt", <<-EOF
51
+ void abc(void);
52
+ EOF
53
+ write "a.tt", <<-EOF
54
+ #include "a.tt"
55
+ EOF
56
+ write "rf.t", <<-EOF
57
+ import "md5", "c/dependencies", "autoclean"
58
+ gen C::Dependencies,
59
+ :search => ["include"],
60
+ :sources => ["a.tt", "include/a.tt"]
61
+ gen Action do source "c_dependencies" end
62
+ gen AutoClean
63
+ file "a.out" => "a.tt" do |t|
64
+ sys.cp t.source, t.name
65
+ end
66
+ EOF
67
+ out, err = assert_rant("-frf.t", "a.out")
68
+ assert(err.empty?)
69
+ assert(!out.empty?)
70
+ assert(test(?f, "c_dependencies"))
71
+ assert(test(?f, "a.out"))
72
+ assert_equal(File.read("a.tt"), File.read("a.out"))
73
+ out, err = assert_rant("-frf.t", "a.out")
74
+ assert(err.empty?)
75
+ assert(out.empty?)
76
+ write "include/a.tt", <<-EOF
77
+ int abc(void);
78
+ EOF
79
+ out, err = assert_rant("-frf.t", "a.out")
80
+ assert(err.empty?)
81
+ assert(!out.empty?)
82
+ assert(test(?f, "c_dependencies"))
83
+ assert(test(?f, "a.out"))
84
+ assert_equal(File.read("a.tt"), File.read("a.out"))
85
+ out, err = assert_rant("-frf.t", "a.out")
86
+ assert(err.empty?)
87
+ assert(out.empty?)
88
+ assert_rant("-frf.t", "autoclean")
89
+ assert(!test(?e, ".rant.meta"))
90
+ assert(!test(?e, "a.out"))
91
+ assert(test(?f, "include/a.tt"))
92
+ assert(test(?f, "a.tt"))
93
+ ensure
94
+ FileUtils.rm_f %w(include/a.tt a.tt rf.t a.out .rant.meta)
95
+ end
44
96
  end
@@ -0,0 +1,16 @@
1
+
2
+ import "metadata"
3
+
4
+ task :dummy
5
+
6
+ p var[:__metadata__].fetch("cmd", "a")
7
+ var[:__metadata__].set("cmd", "touch a", "a")
8
+
9
+ if var[:subdir]
10
+ subdirs "sub"
11
+ rac.goto "sub"
12
+ p var[:__metadata__].fetch("cmd", "b", "sub")
13
+ rac.goto "#"
14
+ else
15
+ p var[:__metadata__].fetch("cmd", "a")
16
+ end
@@ -0,0 +1,17 @@
1
+
2
+ gen Task, "b" do |t|
3
+ t.needed {
4
+ #puts Dir.pwd
5
+ #puts rac.current_subdir
6
+ rv = var[:__metadata__].fetch("cmd", "b") != "create b"
7
+ #p var[:__metadata__].fetch("cmd", "b")
8
+ #p var[:__metadata__].instance_variable_get(:@read_dirs)
9
+ #p var[:__metadata__].instance_variable_get(:@store)
10
+ rv
11
+ }
12
+ t.act {
13
+ sys.touch t.name
14
+ var[:__metadata__].set("cmd", "create b", "b")
15
+ #p var[:__metadata__].instance_variable_get(:@store)
16
+ }
17
+ end
@@ -0,0 +1,126 @@
1
+
2
+ require 'test/unit'
3
+ require 'tutil'
4
+
5
+ $testImportMetaDataDir ||= File.expand_path(File.dirname(__FILE__))
6
+
7
+ class TestMetaData < Test::Unit::TestCase
8
+ def setup
9
+ # Ensure we run in test directory.
10
+ Dir.chdir($testImportMetaDataDir)
11
+ end
12
+ def teardown
13
+ Dir.chdir($testImportMetaDataDir)
14
+ FileUtils.rm_rf(Dir["*.t"] + %w(.rant.meta sub/.rant.meta sub/b))
15
+ end
16
+ def test_fetch_set_fetch
17
+ out, err = assert_rant
18
+ assert(err.empty?)
19
+ assert_equal("nil\n\"touch a\"\n", out)
20
+ out, err = assert_rant
21
+ assert(err.empty?)
22
+ assert_equal("\"touch a\"\n\"touch a\"\n", out)
23
+ end
24
+ def test_subdir
25
+ out, err = assert_rant("subdir=true", "sub/b")
26
+ assert(err.empty?)
27
+ assert_equal("nil\nnil\ntouch b\n", out)
28
+ assert(test(?f, ".rant.meta"))
29
+ assert(test(?f, "sub/.rant.meta"))
30
+ out, err = assert_rant("subdir=true", "sub/b")
31
+ assert(err.empty?)
32
+ assert_equal("\"touch a\"\n\"create b\"\n", out)
33
+ end
34
+ def test_rant_import
35
+ run_import("-q", "--auto", "make.t")
36
+ assert_exit
37
+ FileUtils.rm ".rant.meta"
38
+ out = run_ruby("make.t", "subdir=true", "sub/b")
39
+ assert_exit
40
+ assert_equal("nil\nnil\ntouch b\n", out)
41
+ assert(test(?f, ".rant.meta"))
42
+ assert(test(?f, "sub/.rant.meta"))
43
+ out = run_ruby("make.t", "subdir=true", "sub/b")
44
+ assert_exit
45
+ assert_equal("\"touch a\"\n\"create b\"\n", out)
46
+ end
47
+ def test_more_commands_and_lines
48
+ FileUtils.mkdir "more.t"
49
+ Dir.chdir "more.t"
50
+ open "Rantfile", "w" do |f|
51
+ f << <<-EOF
52
+ import "metadata"
53
+ task :dummy
54
+ puts var[:__metadata__].fetch("x", "a")
55
+ puts var[:__metadata__].fetch("y", "a")
56
+ puts var[:__metadata__].fetch("x", "b")
57
+ #STDERR.puts(var[:__metadata__].instance_variable_get(:@store).inspect)
58
+ var[:__metadata__].set("x", "1\n2\n\n", "a")
59
+ var[:__metadata__].set("y", "3\n4", "a")
60
+ var[:__metadata__].set("x", "5", "b")
61
+ #STDERR.puts(var[:__metadata__].instance_variable_get(:@store).inspect)
62
+ EOF
63
+ end
64
+ out, err = assert_rant
65
+ assert(err.empty?)
66
+ assert_equal("nil\nnil\nnil\n", out)
67
+ assert(test(?f, ".rant.meta"))
68
+ out, err = assert_rant
69
+ assert(err.empty?)
70
+ assert_equal("1\n2\n3\n4\n5\n", out)
71
+ out, err = assert_rant
72
+ assert(err.empty?)
73
+ assert_equal("1\n2\n3\n4\n5\n", out)
74
+ end
75
+ def test_write_current_version
76
+ top_data = <<EOF
77
+ Rant
78
+ a
79
+ 1
80
+ cmd
81
+ 1
82
+ touch a
83
+ EOF
84
+ sub_data = <<EOF
85
+ Rant
86
+ b
87
+ 1
88
+ cmd
89
+ 1
90
+ create b
91
+ EOF
92
+ assert_rant("subdir=true", "sub/b")
93
+ assert_equal(top_data, File.read(".rant.meta"))
94
+ assert_equal(sub_data, File.read("sub/.rant.meta"))
95
+ end
96
+ def test_read_meta_data_format_version_0_4_4
97
+ assert(!test(?e, ".rant.meta"))
98
+ assert(!test(?e, "sub/.rant.meta"))
99
+ open ".rant.meta", "w" do |f|
100
+ f << <<EOF
101
+ Rant
102
+ a
103
+ 1
104
+ cmd
105
+ 1
106
+ touch a
107
+ EOF
108
+ end
109
+ open "sub/.rant.meta", "w" do |f|
110
+ f << <<EOF
111
+ Rant
112
+ b
113
+ 1
114
+ cmd
115
+ 1
116
+ create b
117
+ EOF
118
+ end
119
+ out, err = assert_rant
120
+ assert(err.empty?)
121
+ assert_equal("\"touch a\"\n\"touch a\"\n", out)
122
+ out, err = assert_rant("subdir=true", "sub/b")
123
+ assert(err.empty?)
124
+ assert_equal("\"touch a\"\n\"create b\"\n", out)
125
+ end
126
+ end
@@ -0,0 +1,89 @@
1
+
2
+ import "md5", "autoclean"
3
+
4
+ var :content => "1\n"
5
+
6
+ task :a => "f1.t"
7
+
8
+ file "f1.t" do |t|
9
+ write_content(t.name)
10
+ end
11
+
12
+ gen Directory, "d1.t"
13
+
14
+ gen Directory, "base.t", "s/s" => ["a.t", "f1.t"] do |t|
15
+ fn = t.name + "/t"
16
+ puts "copying to #{fn}"
17
+ open fn, "w" do |f|
18
+ f.write(File.read(t.source))
19
+ f.write(File.read("f1.t"))
20
+ end; sys.cd "sub1"
21
+ end
22
+
23
+ if var["subfile"]
24
+ import "subfile"
25
+ gen SubFile, "d2.t/f" => "f1.t" do |t|
26
+ sys.cp t.source, t.name
27
+ end
28
+ end
29
+
30
+ file "f2.t" => ["base.t/s/s"] do |t|
31
+ sys.cp "#{t.source}/t", t.name
32
+ end
33
+
34
+ gen SourceNode, "c1.t"
35
+
36
+ gen SourceNode, "c2.t" => ["c1.t", "c3.t"]
37
+
38
+ file "f3.t" => "c1.t" do |t|
39
+ var[:content] = File.read(t.source)
40
+ write_content(t.name)
41
+ end
42
+
43
+ file "f4.t" => ["f3.t", "c2.t"] do |t|
44
+ var[:content] = t.deps.inject("") { |c, fn| c + File.read(fn) }
45
+ write_content(t.name)
46
+ end
47
+
48
+ gen SourceNode, "c4.t" => "c2.t"
49
+
50
+ file "f5.t" => "c2.t" do |t|
51
+ sys.cp t.source, t.name
52
+ end
53
+
54
+ gen SourceNode, "c5.t" => ["sub1/c1.t", "c6.t"]
55
+
56
+ file "f6.t" => "c5.t" do |t|
57
+ write_content(t.name)
58
+ end
59
+
60
+ gen Rule, ".r.t" => ".t" do |t|
61
+ sys.cp t.source, t.name
62
+ end
63
+
64
+ gen Rule, ".r.t" => ".tt" do |t|
65
+ sys.cp t.source, t.name
66
+ end
67
+
68
+ gen SourceNode, "c7.t" => ["f1.t", "c8.t"]
69
+
70
+ file "f7.t" => "c7.t" do |t|
71
+ sys.cp t.source, t.name
72
+ sys.cd "sub1"
73
+ end
74
+
75
+ desc "copy f1.t from sub1 to f8.t"
76
+ file "f8.t" => "sub1/f1.t" do |t|
77
+ sys.cp t.source, t.name
78
+ end
79
+
80
+ subdirs "sub1"
81
+
82
+ def write_content(fn)
83
+ puts "writing #{fn}"
84
+ open fn, "w" do |f|
85
+ f.write var[:content]
86
+ end
87
+ end
88
+
89
+ gen AutoClean
@@ -0,0 +1,6 @@
1
+
2
+ gen SourceNode, "c1.t" => "c2.t"
3
+
4
+ file "f1.t" do |t|
5
+ write_content(t.name)
6
+ end