rant 0.4.6 → 0.4.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/INSTALL +44 -0
  2. data/NEWS +30 -0
  3. data/README +6 -46
  4. data/Rantfile +38 -7
  5. data/doc/c.rdoc +2 -0
  6. data/doc/command.rdoc +210 -0
  7. data/doc/examples/c_dependencies/Rantfile +1 -1
  8. data/doc/examples/directedrule/Rantfile +1 -1
  9. data/doc/homepage/index.html +12 -1
  10. data/doc/rant-import.rdoc +5 -0
  11. data/doc/rant_vs_rake.rdoc +107 -0
  12. data/doc/rantfile.rdoc +17 -17
  13. data/doc/rubyproject.rdoc +45 -45
  14. data/doc/subdirs.rdoc +1 -1
  15. data/lib/rant/coregen.rb +62 -22
  16. data/lib/rant/import/archive.rb +1 -0
  17. data/lib/rant/import/command.rb +206 -0
  18. data/lib/rant/import/nodes/default.rb +12 -6
  19. data/lib/rant/import/nodes/signed.rb +3 -3
  20. data/lib/rant/import/signedfile.rb +14 -15
  21. data/lib/rant/import/win32/rubycmdwrapper.rb +1 -0
  22. data/lib/rant/import.rb +52 -4
  23. data/lib/rant/metautils.rb +119 -0
  24. data/lib/rant/node.rb +11 -2
  25. data/lib/rant/rantenv.rb +5 -2
  26. data/lib/rant/rantlib.rb +30 -46
  27. data/lib/rant/rantsys.rb +81 -13
  28. data/lib/rant/rantvar.rb +1 -76
  29. data/lib/rant.rb +2 -2
  30. data/misc/TODO +21 -0
  31. data/test/deprecated/test_0_5_2.rb +28 -0
  32. data/test/deprecated/test_0_6_0.rb +24 -0
  33. data/test/dyn_dependencies.rf +25 -0
  34. data/test/import/command/Rantfile +102 -0
  35. data/test/import/command/test_command.rb +597 -0
  36. data/test/rant-import/test_rant-import.rb +23 -1
  37. data/test/rule.rf +2 -0
  38. data/test/test_dyn_dependencies.rb +45 -0
  39. data/test/test_env.rb +5 -4
  40. data/test/test_filelist.rb +60 -3
  41. data/test/test_rant_interface.rb +5 -0
  42. data/test/test_sys.rb +53 -2
  43. data/test/tutil.rb +14 -6
  44. metadata +17 -6
  45. data/test/deprecated/test_0_4_8.rb +0 -41
data/lib/rant/rantsys.rb CHANGED
@@ -138,15 +138,36 @@ module Rant
138
138
  end
139
139
  ##############################################################
140
140
 
141
- if Object.method_defined? :fcall # in Ruby 1.9 like __send__
141
+ if Object.method_defined?(:fcall) || Object.method_defined?(:funcall) # in Ruby 1.9 like __send__
142
+ @@__send_private__ = Object.method_defined?(:fcall) ? :fcall : :funcall
142
143
  def resolve
143
144
  @pending = false
144
- @actions.each{ |action| self.fcall(*action) }.clear
145
+ @actions.each{ |action| self.__send__(@@__send_private__, *action) }.clear
145
146
  ix = ignore_rx
146
147
  if ix
147
148
  @files.reject! { |f| f =~ ix && !@keep[f] }
148
149
  end
149
150
  end
151
+ elsif RUBY_VERSION < "1.8.2"
152
+ def resolve
153
+ @pending = false
154
+ @actions.each{ |action| self.__send__(*action) }.clear
155
+ ix = ignore_rx
156
+ @files.reject! { |f|
157
+ unless @keep[f]
158
+ next(true) if ix && f =~ ix
159
+ if @glob_flags & File::FNM_DOTMATCH != File::FNM_DOTMATCH
160
+ if ESC_ALT_SEPARATOR
161
+ f =~ /(^|(#{ESC_SEPARATOR}|#{ESC_ALT_SEPARATOR})+)\..*
162
+ ((#{ESC_SEPARATOR}|#{ESC_ALT_SEPARATOR})+|$)/x
163
+ else
164
+ f =~ /(^|#{ESC_SEPARATOR}+)\..*
165
+ (#{ESC_SEPARATOR}+|$)/x
166
+ end
167
+ end
168
+ end
169
+ }
170
+ end
150
171
  else
151
172
  def resolve
152
173
  @pending = false
@@ -359,9 +380,9 @@ end
359
380
  # will result on windows:
360
381
  # rdoc foo\bar "with space"
361
382
  # on other systems:
362
- # rdoc foo/bar 'with space'
383
+ # rdoc foo/bar with\ space
363
384
  def arglist
364
- to_ary.arglist
385
+ Rant::Sys.sp to_ary
365
386
  end
366
387
  alias to_s arglist
367
388
 
@@ -422,10 +443,15 @@ end
422
443
  @basedir = Dir.pwd
423
444
  super(*patterns)
424
445
  @ignore_hash = nil
446
+ @add_ignore_args = []
425
447
  update_ignore_rx
426
448
  end
427
449
 
428
- private :ignore
450
+ alias filelist_ignore ignore
451
+ def ignore(*patterns)
452
+ @add_ignore_args.concat patterns
453
+ self
454
+ end
429
455
 
430
456
  def ignore_rx
431
457
  update_ignore_rx
@@ -450,10 +476,11 @@ end
450
476
  private
451
477
  def update_ignore_rx
452
478
  ri = @rac.var[:ignore]
479
+ ri = ri ? (ri + @add_ignore_args) : @add_ignore_args
453
480
  rh = ri.hash
454
481
  unless rh == @ignore_hash
455
482
  @ignore_rx = nil
456
- ignore(*ri) if ri
483
+ filelist_ignore(*ri)
457
484
  @ignore_hash = rh
458
485
  end
459
486
  end
@@ -571,18 +598,51 @@ end
571
598
  # The empty string argument ensures that +system+
572
599
  # doesn't start a subshell but invokes ruby directly.
573
600
  # The empty string argument is ignored by ruby.
574
- sh(Env::RUBY, '', &block)
601
+ sh(Env::RUBY_EXE, '', &block)
575
602
  else
576
- sh(args.unshift(Env::RUBY), &block)
603
+ sh(args.unshift(Env::RUBY_EXE), &block)
577
604
  end
578
605
  end
579
606
 
580
607
  # Returns a string that can be used as a valid path argument
581
608
  # on the shell respecting portability issues.
582
- def sp path
583
- Env.shell_path path
609
+ def sp(arg)
610
+ if arg.respond_to? :to_ary
611
+ arg.to_ary.map{ |e| sp e }.join(' ')
612
+ else
613
+ _escaped_path arg
614
+ end
584
615
  end
585
616
 
617
+ # Escape special shell characters (currently only spaces).
618
+ # Flattens arrays and returns always a single string.
619
+ def escape(arg)
620
+ if arg.respond_to? :to_ary
621
+ arg.to_ary.map{ |e| escape e }.join(' ')
622
+ else
623
+ _escaped arg
624
+ end
625
+ end
626
+
627
+ if Env.on_windows?
628
+ def _escaped_path(path)
629
+ _escaped(path.to_s.tr("/", "\\"))
630
+ end
631
+ def _escaped(arg)
632
+ sarg = arg.to_s
633
+ return sarg unless sarg.include?(" ")
634
+ sarg << "\\" if sarg[-1].chr == "\\"
635
+ "\"#{sarg}\""
636
+ end
637
+ else
638
+ def _escaped_path(path)
639
+ path.to_s.gsub(/(?=\s)/, "\\")
640
+ end
641
+ alias _escaped _escaped_path
642
+ end
643
+ private :_escaped_path
644
+ private :_escaped
645
+
586
646
  # If supported, make a hardlink, otherwise
587
647
  # fall back to copying.
588
648
  def safe_ln(*args)
@@ -612,7 +672,7 @@ end
612
672
 
613
673
  extend self
614
674
 
615
- if RUBY_VERSION >= "1.9.0"
675
+ if RUBY_VERSION >= "1.8.4" # needed by 1.9.0, too
616
676
  class << self
617
677
  public(*::FileUtils::METHODS)
618
678
  end
@@ -634,12 +694,20 @@ end
634
694
  raise ArgumentError, "controller required"
635
695
  end
636
696
 
637
- def glob(*args, &block)
638
- fl = RacFileList.new(@rac, *args)
697
+ def glob(*patterns, &block)
698
+ fl = RacFileList.new(@rac, *patterns)
639
699
  fl.instance_eval(&block) if block
640
700
  fl
641
701
  end
642
702
 
703
+ def glob_all(*patterns, &block)
704
+ fl = RacFileList.new(@rac, *patterns)
705
+ fl.ignore(".", "..")
706
+ fl.glob_flags |= File::FNM_DOTMATCH
707
+ fl.instance_eval(&block) if block
708
+ fl
709
+ end
710
+
643
711
  def [](*patterns)
644
712
  RacFileList.new(@rac, *patterns)
645
713
  end
data/lib/rant/rantvar.rb CHANGED
@@ -16,14 +16,13 @@
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.6'
19
+ VERSION = '0.4.8'
20
20
 
21
21
  # Those are the filenames for rantfiles.
22
22
  # Case matters!
23
23
  ROOT_RANTFILE = "root.rant"
24
24
  SUB_RANTFILE = "sub.rant"
25
25
  RANTFILES = [ "Rantfile", "rantfile", ROOT_RANTFILE ]
26
- DEPRECATED_RANTFILES = [ "Rantfile.rb", "rantfile.rb" ]
27
26
 
28
27
  # Names of plugins and imports for which code was loaded.
29
28
  # Files that where loaded with the `import' commant are directly
@@ -49,80 +48,6 @@ module Rant
49
48
  @__rant_no_value__
50
49
  end
51
50
 
52
- module MetaUtils
53
- # Creates three accessor methods:
54
- # obj.attr_name:: Return value of instance variable
55
- # @attr_name
56
- # obj.attr_name = val:: Set value instance variable
57
- # @attr_name to val
58
- # obj.attr_name val:: same as above
59
- def rant_attr attr_name
60
- attr_name = valid_attr_name attr_name
61
- attr_writer attr_name
62
- module_eval <<-EOD
63
- def #{attr_name} val=Rant.__rant_no_value__
64
- if val.equal? Rant.__rant_no_value__
65
- @#{attr_name}
66
- else
67
- @#{attr_name} = val
68
- end
69
- end
70
- EOD
71
- nil
72
- end
73
- # Creates three accessor methods:
74
- # obj.attr_name?:: Return value, true or false
75
- # obj.attr_name:: Set attribute to true
76
- # obj.no_attr_name:: Set attribute to false
77
- def rant_flag attr_name
78
- attr_name = valid_attr_name attr_name
79
- module_eval <<-EOD
80
- def #{attr_name}?
81
- @#{attr_name}
82
- end
83
- def #{attr_name}
84
- @#{attr_name} = true
85
- end
86
- def no_#{attr_name}
87
- @#{attr_name} = false
88
- end
89
- EOD
90
- end
91
- # Creates accessor methods like #rant_attr for the attribute
92
- # attr_name. Additionally, values are converted with to_str
93
- # before assignment to instance variables happens.
94
- def string_attr attr_name
95
- attr_name = valid_attr_name attr_name
96
- module_eval <<-EOD
97
- def #{attr_name}=(val)
98
- if val.respond_to? :to_str
99
- @#{attr_name} = val.to_str
100
- else
101
- raise ArgumentError,
102
- "string (#to_str) value required", caller
103
- end
104
- end
105
- def #{attr_name} val=Rant.__rant_no_value__
106
- if val.equal? Rant.__rant_no_value__
107
- @#{attr_name}
108
- else
109
- self.__send__(:#{attr_name}=, val)
110
- end
111
- end
112
- EOD
113
- nil
114
- end
115
- # attr_name is converted to a string with #to_s and has to
116
- # match /^\w+$/. Returns attr_name.to_s.
117
- def valid_attr_name attr_name
118
- attr_name = attr_name.to_s
119
- attr_name =~ /^\w+$/ or
120
- raise ArgumentError,
121
- "argument has to match /^\w+$/", caller
122
- attr_name
123
- end
124
- end # module MetaUtils
125
-
126
51
  module RantVar
127
52
 
128
53
  class Error < Rant::Error
data/lib/rant.rb CHANGED
@@ -60,9 +60,9 @@ module Rant
60
60
  end
61
61
 
62
62
  def rant
63
- @__rant__
63
+ Rant.rant
64
64
  end
65
65
 
66
- @__rant__ = Rant::RantApp.new
66
+ Rant.instance_variable_set(:@__rant__, Rant::RantApp.new)
67
67
 
68
68
  include RantContext
data/misc/TODO CHANGED
@@ -1,6 +1,25 @@
1
1
 
2
2
  = TODO
3
3
 
4
+ == Don't use +invoke+ result of dependency to check if update is
5
+ necessary
6
+
7
+ It doesn't make sense since:
8
+ 1. The node (prerequisite) could have already been invoked by another
9
+ node as prerequisite. For the first node, the prerequisite would
10
+ return true, all following false.
11
+ 2. The node (prerequisite) *can* *not* know if the invoking node is
12
+ up to date compared to itself.
13
+
14
+ == Check +enhance+ for SourceNodes
15
+
16
+ Rant fails (infinite recursion) for enhance on SourceNodes.
17
+ Update: Infinite recursion occurs only when a <tt>require "rant"</tt>
18
+ was done. Else an appropriate message is printed. Can be
19
+ considered OK.
20
+
21
+ == Implement Rant::FileList#==
22
+
4
23
  == Update documentation with regards to resolve hooks.
5
24
 
6
25
  The argument list for resolve hooks has changed in version 0.4.5.
@@ -18,6 +37,8 @@ could get a common source of annoyance/bugs.
18
37
 
19
38
  Favorite candidate is currently <tt>@</tt>.
20
39
 
40
+ Done (0.4.5), using <tt>@</tt>.
41
+
21
42
  == Improve SourceNode types
22
43
 
23
44
  Currently a SourceNode can only have other SourceNodes or files as
@@ -30,4 +30,32 @@ class TestDeprecated_0_5_2 < Test::Unit::TestCase
30
30
  assert_match(/\bdeprecated\b/, err)
31
31
  end
32
32
  end
33
+ def test_ary_arglist
34
+ in_local_temp_dir do
35
+ write_to_file "Rantfile", <<-EOF
36
+ task :default do
37
+ sys(sys.sp(Env::RUBY_EXE) + " -e \\"puts ARGV\\" " +
38
+ ["a b", "c/d"].arglist + " > a.out")
39
+ end
40
+ EOF
41
+ out, err = assert_rant
42
+ content = Rant::Env.on_windows? ? "a b\nc\\d\n" : "a b\nc/d\n"
43
+ assert_file_content "a.out", content
44
+ assert_match(/\bWARNING\b/, err)
45
+ assert_match(/\barglist\b/, err)
46
+ assert_match(/\bsp\b/, err)
47
+ assert_match(/\bdeprecated\b/, err)
48
+ end
49
+ end
50
+ def test_ary_shell_pathes
51
+ out, err = capture_std do
52
+ sp = ["a b", "a/b"].shell_pathes
53
+ assert sp.respond_to?(:to_ary)
54
+ assert_equal 2, sp.size
55
+ end
56
+ assert_match(/\bWARNING\b/, err)
57
+ assert_match(/\bshell_pathes\b/, err)
58
+ assert_match(/\bsp\b/, err)
59
+ assert_match(/\bdeprecated\b/, err)
60
+ end
33
61
  end
@@ -0,0 +1,24 @@
1
+
2
+ require 'test/unit'
3
+ require 'tutil'
4
+ require 'rant/import'
5
+
6
+ $test_deprecated_dir ||= File.expand_path(File.dirname(__FILE__))
7
+
8
+ class TestDeprecated_0_6_0 < Test::Unit::TestCase
9
+ include Rant::TestUtil
10
+ def setup
11
+ Dir.chdir $test_deprecated_dir
12
+ end
13
+ def test_rant_import_option_v
14
+ out, err = capture_std do
15
+ assert_equal(0, Rant::RantImport.new("-v").run)
16
+ end
17
+ if Rant::VERSION > "0.4.8"
18
+ assert_match(/-v\bdeprecated\b.*-V.*--version\b/, err)
19
+ else
20
+ assert err.empty?
21
+ end
22
+ assert_match(/rant-import\s#{Regexp.escape Rant::VERSION}/, out)
23
+ end
24
+ end
@@ -0,0 +1,25 @@
1
+
2
+ import "sys/more", "autoclean"
3
+
4
+ @print = lambda { |t| puts t.name }
5
+ @write = lambda { |t|
6
+ sys.write_to_file(t.name, (var[t.name[0,1]]||t.name))
7
+ }
8
+
9
+ task :A => :B, &@print
10
+ task :B do |t|
11
+ enhance :A => [:C, :D]
12
+ @print[t]
13
+ end
14
+ task :C, &@print
15
+ task :D, &@print
16
+
17
+ file "a.t" => "b.t", &@write
18
+ file "b.t" do |t|
19
+ enhance "a.t" => ["c.t", "d.t"]
20
+ @write[t]
21
+ end
22
+ file "c.t", &@write
23
+ file "d.t", &@write
24
+
25
+ gen AutoClean
@@ -0,0 +1,102 @@
1
+
2
+ import "command", "autoclean"
3
+
4
+ @ruby = Env::RUBY_EXE
5
+ @sh_echo = "#{sys.sp Env::RUBY_EXE} -e \"puts ARGV.join(' ')\""
6
+ @sh_puts = "#{sys.sp Env::RUBY_EXE} -e \"puts ARGV\""
7
+ @sh_cat = "#{sys.sp Env::RUBY_EXE} -e \"print ARGF.read\""
8
+
9
+ desc "Build a.t"
10
+ gen Command, "a.t" => ["b.t", "c.t"] do |t|
11
+ "#@sh_echo #{sys.sp t.prerequisites} > #{t.name}"
12
+ end
13
+ gen Command, "f_a.t" do |t|
14
+ sys "#@sh_echo #{sys.escape "I will fail."} > #{t.name}"
15
+ end
16
+
17
+ var :btxt => "b"
18
+ var :be, :Bool
19
+
20
+ gen Command, "b.t", "$[sh_echo] $(btxt) > $(>)"
21
+
22
+ if var[:be]
23
+ enhance "b.t" => "d.t" do |t|
24
+ import "sys/more"
25
+ sys.write_to_file(t.name,
26
+ File.read(t.name) + File.read(t.source))
27
+ end
28
+ end
29
+
30
+ gen Command, "c.t", sys["d???.t"], "$[sh_echo] $(<) > $(>)"
31
+
32
+ gen Command, "with space/a.t",
33
+ ["b.t", "with space/b.t"],
34
+ "$[sh_puts] $(<) > $(>)"
35
+
36
+ var :fargs => "/I$(p_ath1)"
37
+ var :p_ath1 => "a bc"
38
+ gen Command, "f.t", "$[sh_echo] $[fargs] > $[>]"
39
+
40
+ var :eargs => "/I$(epath)"
41
+ var :epath => "a b/c/"
42
+ gen Command, "e.t", "$[sh_echo] $[eargs] > ${>}"
43
+
44
+ var :gargs => "/I${gpath}"
45
+ var :gpath => "a b/c/"
46
+ gen Command, "g.t", "$[sh_echo] $[gargs] > $(>)"
47
+
48
+ var :h1 => 1
49
+ var :h2 => 2
50
+ gen Command, "h.t", <<end
51
+ $[sh_echo] ${h1} > $(>)1
52
+ $[sh_echo] ${h2} > $(>)2
53
+ $[sh_cat] $(>)1 $(>)2 > $(>)
54
+ end
55
+
56
+ var :rargs => "$(prerequisites) $(source) > $(name)"
57
+ var :rcmd => "$[sh_echo] " + var[:rargs]
58
+ gen Rule, :out => [:in1, :in2] do |name, sources|
59
+ gen Command, name, sources, var[:rcmd]
60
+ end
61
+
62
+ gen Directory, "a.in1"
63
+
64
+ var :rc_dep => "puts 'a'"
65
+ gen Command, "dep1.t", "$(ruby) -e \"$[rc_dep]\" > $(>)"
66
+
67
+ gen Command, "t1.t", "dep1.t", "$[sh_echo] making t1 > $(>)"
68
+ gen Command, "t2.t", "dep1.t", "$[sh_echo] making t2 > $(>)"
69
+
70
+ gen Command, "sub1.t/a", "#@sh_echo ${>} > $(>)"
71
+ gen Command, "sub2.t/a", "$[sh_echo] ${>} > $(>)"
72
+ gen Directory, "sub2.t"
73
+
74
+ task :sub3 do
75
+ puts "task sub3"
76
+ end
77
+ gen Command, "sub3/a", "$[sh_echo] ${>} > $(>)"
78
+
79
+ gen Command, "x.t", '[#$[sh_puts] ${a}#] ${b} > $(>)'
80
+
81
+ gen Command, "delay.t", "$[sh_echo] ${foo} > $(>)"
82
+
83
+ gen Command, "p1.t", '$[sh_puts] ${p1} > $(>)'
84
+ gen Command, "p2.t", '$[sh_puts] ${p2} > $(>)'
85
+ gen Command, "p3.t", '$[sh_puts] ${p2} > $(>)'
86
+
87
+ var :foo => "foo value"
88
+ task :change_foo do
89
+ var[:foo] = "changed"
90
+ end
91
+
92
+ var[:p1] = lambda { |n| "#{n.full_name} $[foo]" }
93
+ var[:p2] = lambda { var[:foo] << "." }
94
+
95
+ if var[:inc_foo]
96
+ var[:p2].call
97
+ end
98
+
99
+ @h = {:a => "b"}
100
+ gen Command, "hash.t", "$[sh_puts] ${h} > $(>)"
101
+
102
+ gen AutoClean