rant 0.4.6 → 0.4.8

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 (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
@@ -21,6 +21,8 @@ module Rant
21
21
  }
22
22
  end
23
23
 
24
+ attr_accessor :receiver
25
+
24
26
  def initialize(rac, name, prerequisites, &block)
25
27
  super()
26
28
  @rac = rac
@@ -30,7 +32,7 @@ module Rant
30
32
  @block = block
31
33
  @run = false
32
34
  @success = nil
33
- @needed_blk = nil
35
+ @receiver = nil
34
36
  end
35
37
  def prerequisites
36
38
  @pre
@@ -41,7 +43,7 @@ module Rant
41
43
  @pre.first.to_s
42
44
  end
43
45
  def has_actions?
44
- !!@block
46
+ @block or @receiver && @receiver.has_pre_action?
45
47
  end
46
48
  def file_target?
47
49
  true
@@ -75,9 +77,6 @@ module Rant
75
77
  def needed?
76
78
  invoke(:needed? => true)
77
79
  end
78
- def needed(&blk)
79
- @needed_blk = blk
80
- end
81
80
  def invoke(opt = INVOKE_OPT)
82
81
  return circular_dep if @run
83
82
  @run = true
@@ -86,19 +85,17 @@ module Rant
86
85
  goto_task_home
87
86
  @cur_checksums = []
88
87
  @sigs = @rac.var._get("__signature__")
88
+ @md = @rac.var._get("__metadata__")
89
89
  key = "prerequisites_sig_#{@sigs.name}"
90
90
  target_key = "target_sig_#{@sigs.name}"
91
91
  up = signed_process_prerequisites(opt)
92
92
  up ||= opt[:force]
93
- if @needed_blk
94
- up = true if @needed_blk.call(self)
95
- end
93
+ up = true if @receiver && @receiver.update?(self)
96
94
  @cur_checksums.sort!
97
95
  check_str = @cur_checksums.join
98
96
  @cur_checksums = nil
99
- metadata = @rac.var._get("__metadata__")
100
- old_check_str = metadata.path_fetch(key, @name)
101
- old_target_str = metadata.path_fetch(target_key, @name)
97
+ old_check_str = @md.path_fetch(key, @name)
98
+ old_target_str = @md.path_fetch(target_key, @name)
102
99
  # check explicitely for plain file, thus allow the
103
100
  # target of a SignedFile to be a directory ;)
104
101
  if test(?f, @name)
@@ -119,18 +116,19 @@ module Rant
119
116
  @sigs.signature_for_file(@name) : ""
120
117
  target_changed = target_str != old_target_str
121
118
  if target_changed
122
- metadata.path_set(target_key, target_str, @name)
119
+ @md.path_set(target_key, target_str, @name)
123
120
  end
124
121
  if check_str_changed
125
- metadata.path_set(key, check_str, @name)
122
+ @md.path_set(key, check_str, @name)
126
123
  end
124
+ @success = true
127
125
  return target_changed
128
126
  rescue TaskFail => e
129
127
  raise
130
128
  rescue Exception => e
131
129
  self.fail(nil, e)
132
130
  ensure
133
- @sigs = nil
131
+ @md = @sigs = nil
134
132
  @run = false
135
133
  end
136
134
  end
@@ -196,7 +194,8 @@ module Rant
196
194
  self.fail "can't handle prerequisite `#{dep_str}'"
197
195
  end
198
196
  goto_task_home
199
- up
197
+ # changed in 0.4.7
198
+ false #up
200
199
  end
201
200
  def handle_file(path)
202
201
  @cur_checksums << @sigs.signature_for_file(path)
@@ -26,6 +26,7 @@ module Rant::Generators
26
26
  i_bin = File.join(::Rant::Env::RUBY_BINDIR,
27
27
  File.basename(bin))
28
28
  rac.cmd_msg "Writing #{t.name}: #{i_bin}"
29
+ # TODO: Better use Env::RUBY_EXE?
29
30
  f.puts "@#{rac.cx.sys.sp ::Rant::Env::RUBY} #{rac.cx.sys.sp i_bin} %*"
30
31
  }
31
32
  end
data/lib/rant/import.rb CHANGED
@@ -24,8 +24,10 @@ module Rant
24
24
  OPTIONS = [
25
25
  [ "--help", "-h", GetoptLong::NO_ARGUMENT,
26
26
  "Print this help and exit." ],
27
- [ "--version", "-v", GetoptLong::NO_ARGUMENT,
27
+ [ "--version", "-V", GetoptLong::NO_ARGUMENT,
28
28
  "Print version of rant-import and exit." ],
29
+ [ "-v", GetoptLong::NO_ARGUMENT,
30
+ "Deprecated. Use -V or --version instead." ],
29
31
  [ "--quiet", "-q", GetoptLong::NO_ARGUMENT,
30
32
  "Operate quiet." ],
31
33
  [ "--plugins", "-p", GetoptLong::REQUIRED_ARGUMENT,
@@ -38,6 +40,8 @@ module Rant
38
40
  "Include comments from Rant sources." ],
39
41
  [ "--reduce-whitespace", "-r",GetoptLong::NO_ARGUMENT,
40
42
  "Remove as much whitespace from Rant sources as possible." ],
43
+ [ "--zip", "-z", GetoptLong::NO_ARGUMENT,
44
+ "Compress created script." ],
41
45
  [ "--auto", "-a", GetoptLong::NO_ARGUMENT,
42
46
  "Automatically try to determine imports and plugins.\n" +
43
47
  "Warning: loads Rantfile!" ],
@@ -87,6 +91,7 @@ module Rant
87
91
  @auto = false
88
92
  @arg_rantfiles = []
89
93
  @quiet = false
94
+ @zip = false
90
95
  end
91
96
 
92
97
  def run
@@ -132,6 +137,7 @@ Rant::CODE_IMPORTS.concat %w(#{@included_imports.join(' ')}
132
137
  alias require_backup_by_rant require
133
138
  def require libf
134
139
  if libf == "rant"
140
+ # TODO: needs rework! look at lib/rant.rb
135
141
  self.class.instance_eval { include Rant }
136
142
  else
137
143
  begin
@@ -146,8 +152,48 @@ exit Rant.run
146
152
  EOF
147
153
  msg "Postprocessing..."
148
154
  script = filter_reopen_module(script)
149
- File.open @mono_fn, "w" do |mf|
150
- mf.write script
155
+ if @zip
156
+ msg "zipping and writing to #@zip_fn"
157
+ require 'zlib'
158
+ Zlib::GzipWriter.open @zip_fn do |gz|
159
+ gz.write script
160
+ end
161
+ open @mono_fn, "w" do |mf|
162
+ mf.write <<EOF
163
+ #!/usr/bin/env ruby
164
+
165
+ # #@mono_fn - Monolithic rant script, autogenerated by rant-import #{Rant::VERSION}.
166
+ #
167
+ # Copyright (C) 2005 Stefan Lang <langstefan@gmx.at>
168
+ #
169
+ # This program is free software.
170
+ # You can distribute/modify this program under the terms of
171
+ # the GNU LGPL, Lesser General Public License version 2.1.
172
+
173
+ # This script just loads and runs #@zip_fn.
174
+
175
+ require 'zlib'
176
+
177
+ dir = File.expand_path(File.dirname(__FILE__))
178
+ path = "\#{dir}/\#{File.basename(__FILE__)}.gz"
179
+ script = nil
180
+ begin
181
+ Zlib::GzipReader.open(path) { |gz| script = gz.read }
182
+ rescue Errno::ENOENT
183
+ $stderr.print <<EOH
184
+ The file `\#{path}' should contain the zip-compressed monolithic
185
+ Rant script but doesn't exist!
186
+ EOH
187
+ exit 1
188
+ end
189
+
190
+ eval(script)
191
+ EOF
192
+ end
193
+ else
194
+ open @mono_fn, "w" do |mf|
195
+ mf.write script
196
+ end
151
197
  end
152
198
  msg "Done.",
153
199
  "Included imports: " + @included_imports.join(', '),
@@ -172,7 +218,7 @@ EOF
172
218
  cmd_opts.quiet = true
173
219
  cmd_opts.each { |opt, value|
174
220
  case opt
175
- when "--version"
221
+ when "--version", "-v":
176
222
  puts "rant-import #{Rant::VERSION}"
177
223
  done
178
224
  when "--help": help
@@ -180,6 +226,7 @@ EOF
180
226
  when "--force": @force = true
181
227
  when "--with-comments": @skip_comments = false
182
228
  when "--reduce-whitespace": @reduce_whitespace = true
229
+ when "--zip": @zip = true
183
230
  when "--imports"
184
231
  @imports.concat(value.split(/\s*,\s*/))
185
232
  when "--plugins"
@@ -197,6 +244,7 @@ EOF
197
244
  "Type `rant-import --help' for usage.")
198
245
  end
199
246
  @mono_fn = rem_args.first if rem_args.first
247
+ @zip_fn = "#@mono_fn.gz"
200
248
  rescue GetoptLong::Error => e
201
249
  abort(e.message)
202
250
  ensure
@@ -0,0 +1,119 @@
1
+
2
+ # metautils.rb - Meta programming utils for Rant internals.
3
+ #
4
+ # Copyright (C) 2005 Stefan Lang <langstefan@gmx.at>
5
+
6
+ module Rant
7
+ module MetaUtils
8
+ # Creates three accessor methods:
9
+ # obj.attr_name:: Return value of instance variable
10
+ # @attr_name
11
+ # obj.attr_name = val:: Set value instance variable
12
+ # @attr_name to val
13
+ # obj.attr_name val:: same as above
14
+ def rant_attr attr_name
15
+ attr_name = valid_attr_name attr_name
16
+ attr_writer attr_name
17
+ module_eval <<-EOD
18
+ def #{attr_name} val=Rant.__rant_no_value__
19
+ if val.equal? Rant.__rant_no_value__
20
+ @#{attr_name}
21
+ else
22
+ @#{attr_name} = val
23
+ end
24
+ end
25
+ EOD
26
+ nil
27
+ end
28
+ # Creates three accessor methods:
29
+ # obj.attr_name?:: Return value, true or false
30
+ # obj.attr_name:: Set attribute to true
31
+ # obj.no_attr_name:: Set attribute to false
32
+ def rant_flag attr_name
33
+ attr_name = valid_attr_name attr_name
34
+ module_eval <<-EOD
35
+ def #{attr_name}?
36
+ @#{attr_name}
37
+ end
38
+ def #{attr_name}
39
+ @#{attr_name} = true
40
+ end
41
+ def no_#{attr_name}
42
+ @#{attr_name} = false
43
+ end
44
+ EOD
45
+ end
46
+ # Creates accessor methods like #rant_attr for the attribute
47
+ # attr_name. Additionally, values are converted with to_str
48
+ # before assignment to instance variables happens.
49
+ def string_attr attr_name
50
+ attr_name = valid_attr_name attr_name
51
+ module_eval <<-EOD
52
+ def #{attr_name}=(val)
53
+ if val.respond_to? :to_str
54
+ @#{attr_name} = val.to_str
55
+ else
56
+ raise ArgumentError,
57
+ "string (#to_str) value required", caller
58
+ end
59
+ end
60
+ def #{attr_name} val=Rant.__rant_no_value__
61
+ if val.equal? Rant.__rant_no_value__
62
+ @#{attr_name}
63
+ else
64
+ self.__send__(:#{attr_name}=, val)
65
+ end
66
+ end
67
+ EOD
68
+ nil
69
+ end
70
+ def redirect_accessor(receiver, *attributes)
71
+ redirect_reader(receiver, *attributes)
72
+ redirect_writer(receiver, *attributes)
73
+ end
74
+ # Create attribute reader methods that redirect to the entity
75
+ # given as first argument (e.g. an instance variable name).
76
+ def redirect_reader(receiver, *attributes)
77
+ attributes.each { |attr_name|
78
+ attr_name = valid_attr_name attr_name
79
+ module_eval <<-EOD
80
+ def #{attr_name}; #{receiver}.#{attr_name}; end
81
+ EOD
82
+ }
83
+ nil
84
+ end
85
+ # Create attribute writer methods that redirect to the entity
86
+ # given as first argument (e.g. an instance variable name).
87
+ def redirect_writer(receiver, *attributes)
88
+ attributes.each { |attr_name|
89
+ attr_name = valid_attr_name attr_name
90
+ module_eval <<-EOD
91
+ def #{attr_name}=(val); #{receiver}.#{attr_name}=
92
+ val; end
93
+ EOD
94
+ }
95
+ nil
96
+ end
97
+ def redirect_message(receiver, *messages)
98
+ messages.each { |message|
99
+ module_eval <<-EOD
100
+ def #{message}(*args, &blk)
101
+ # the first ; on the next line is needed
102
+ # because of rant-import
103
+ ;#{receiver}.#{message}(*args, &blk)
104
+ end
105
+ EOD
106
+ }
107
+ nil
108
+ end
109
+ # attr_name is converted to a string with #to_s and has to
110
+ # match /^\w+$/. Returns attr_name.to_s.
111
+ def valid_attr_name attr_name
112
+ attr_name = attr_name.to_s
113
+ attr_name =~ /^\w+\??$/ or
114
+ raise ArgumentError,
115
+ "argument has to match /^\w+\??$/", caller
116
+ attr_name
117
+ end
118
+ end # module MetaUtils
119
+ end # module Rant
data/lib/rant/node.rb CHANGED
@@ -96,6 +96,10 @@ module Rant
96
96
  sd.empty? ? name : File.join(sd, name)
97
97
  end
98
98
 
99
+ def ch
100
+ {:file => rantfile.to_str, :ln => line_number}
101
+ end
102
+
99
103
  # Change current working directory to the directory this task
100
104
  # was defined in.
101
105
  #
@@ -155,12 +159,17 @@ module Rant
155
159
  def each_target
156
160
  end
157
161
 
162
+ def has_actions?
163
+ defined? @block and @block
164
+ end
165
+
158
166
  private
159
167
  def run
160
- return unless @block
168
+ return unless has_actions?
161
169
  goto_task_home
162
170
  @rac.running_task(self)
163
- @block.arity == 0 ? @block.call : @block[self]
171
+ @receiver.pre_run(self) if defined? @receiver and @receiver
172
+ @block.arity == 0 ? @block.call : @block[self] if @block
164
173
  end
165
174
 
166
175
  def circular_dep
data/lib/rant/rantenv.rb CHANGED
@@ -13,12 +13,15 @@ module Rant::Env
13
13
  OS = ::Config::CONFIG['target']
14
14
  RUBY = ::Config::CONFIG['ruby_install_name']
15
15
  RUBY_BINDIR = ::Config::CONFIG['bindir']
16
+ RUBY_EXE = File.join(RUBY_BINDIR, RUBY + ::Config::CONFIG["EXEEXT"])
16
17
 
17
18
  @@zip_bin = false
18
19
  @@tar_bin = false
19
20
 
20
- def on_windows?
21
- OS =~ /mswin/i
21
+ if OS =~ /mswin/i
22
+ def on_windows?; true; end
23
+ else
24
+ def on_windows?; false; end
22
25
  end
23
26
 
24
27
  def have_zip?
data/lib/rant/rantlib.rb CHANGED
@@ -77,10 +77,18 @@ class Array
77
77
  # Concatenates all elements like #join(' ') but also puts quotes
78
78
  # around strings that contain a space.
79
79
  def arglist
80
- self.shell_pathes.join(' ')
80
+ warn caller[0]
81
+ warn "[WARNING] Use `sys.sp(ary)' in Rantfiles instead of deprecated Array#arglist."
82
+ Rant::Sys.sp(self)
81
83
  end
82
84
 
83
85
  def shell_pathes
86
+ warn caller[0]
87
+ warn "[WARNING] Array#shell_pathes is highly deprecated " +
88
+ "and will not come with future (0.5.0 and later) Rant releases."
89
+ warn "Use `ary.map { |path| sys.sp path }' in Rantfiles."
90
+ map { |path| Rant::Sys.sp(path) }
91
+ =begin
84
92
  entry = nil
85
93
  if ::Rant::Env.on_windows?
86
94
  self.collect { |entry|
@@ -101,6 +109,7 @@ class Array
101
109
  end
102
110
  }
103
111
  end
112
+ =end
104
113
  end
105
114
  end
106
115
 
@@ -209,7 +218,7 @@ module RantContext
209
218
  # +rac+ stands for "rant compiler"
210
219
  def rac
211
220
  ch = Rant::Lib.parse_caller_elem caller[0]
212
- rant.warn_msg(@__rant__.pos_text(ch[:file], ch[:ln]),
221
+ rant.warn_msg(rant.pos_text(ch[:file], ch[:ln]),
213
222
  "Method `rac' is deprecated. Use `rant' instead.")
214
223
  rant
215
224
  end
@@ -240,6 +249,7 @@ end
240
249
 
241
250
  module Rant
242
251
 
252
+ @__rant__ = nil
243
253
  class << self
244
254
 
245
255
  # Run a new rant application in the current working directory.
@@ -271,14 +281,13 @@ module Rant
271
281
  if rant && !rant.run?
272
282
  rant.run(args.flatten)
273
283
  else
274
- Rant::MAIN_OBJECT.instance_variable_set(
275
- :@__rant__, Rant::RantApp.new)
284
+ @__rant__ = Rant::RantApp.new
276
285
  rant.run(args)
277
286
  end
278
287
  end
279
288
 
280
289
  def rant
281
- Rant::MAIN_OBJECT.instance_variable_get(:@__rant__)
290
+ @__rant__
282
291
  end
283
292
  end
284
293
 
@@ -385,13 +394,8 @@ class Rant::RantApp
385
394
 
386
395
  attr_accessor :node_factory
387
396
 
388
- def initialize(*args)
389
- unless args.empty?
390
- STDERR.puts caller[0]
391
- STDERR.puts "Warning: Giving arguments Rant::RantApp.new " +
392
- "is deprecated. Give them to the #run method."
393
- end
394
- @args = args.flatten
397
+ def initialize
398
+ @args = []
395
399
  # Rantfiles will be loaded in the context of this object.
396
400
  @context = RantAppContext.new(self)
397
401
  @sys = ::Rant::SysObject.new(self)
@@ -471,20 +475,6 @@ class Rant::RantApp
471
475
  vmsg 1, "in #{abs_path}"
472
476
  end
473
477
  end
474
- =begin
475
- # Execute block in subdirectory context to subdir, relative to
476
- # project root directory. Important: Does NOT change the process
477
- # working directory. Not thread safe.
478
- #
479
- # For Rant internal use only!
480
- def define_in_project_dir(dir)
481
- old_subdir = @current_subdir
482
- @current_subdir = dir
483
- yield
484
- ensure
485
- @current_subdir = old_subdir
486
- end
487
- =end
488
478
  ##################################################################
489
479
 
490
480
  def run?
@@ -507,7 +497,7 @@ class Rant::RantApp
507
497
  orig_pwd = @rootdir = Dir.pwd
508
498
  # Process commandline.
509
499
  process_args
510
- Dir.chdir(@rootdir)
500
+ Dir.chdir(@rootdir) rescue abort $!.message
511
501
  # read rantfiles, might change @rootdir and Dir.pwd
512
502
  load_rantfiles
513
503
 
@@ -541,7 +531,7 @@ class Rant::RantApp
541
531
  return 1
542
532
  ensure
543
533
  # TODO: exception handling!
544
- Dir.chdir @rootdir
534
+ Dir.chdir @rootdir if test ?d, @rootdir
545
535
  hooks = var._get("__at_return__")
546
536
  hooks.each { |hook| hook.call } if hooks
547
537
  @plugins.each { |plugin| plugin.rant_plugin_stop }
@@ -579,7 +569,7 @@ class Rant::RantApp
579
569
  generator = args.shift
580
570
  unless generator.respond_to? :rant_gen
581
571
  abort_at(ch,
582
- "gen: First argument to has to be a task-generator.")
572
+ "gen: First argument has to be a task-generator.")
583
573
  end
584
574
  # ask generator to produce a task for this application
585
575
  generator.rant_gen(self, ch, args, &block)
@@ -804,7 +794,7 @@ class Rant::RantApp
804
794
  tlist.each { |t|
805
795
  print(prefix + t.to_s.ljust(name_length) + infix)
806
796
  dt = t.description.sub(/\s+$/, "")
807
- puts dt.sub(/\n/, "\n" + ' ' * cmd_length + infix + " ")
797
+ puts dt.gsub(/\n/, "\n" + ' ' * cmd_length + infix + " ")
808
798
  }
809
799
  true
810
800
  end
@@ -972,13 +962,15 @@ class Rant::RantApp
972
962
  old_subdir = @current_subdir
973
963
  old_pwd = Dir.pwd
974
964
  resolve(target).each { |t|
975
- matching_tasks += 1
976
- begin
977
- t.invoke(opt)
978
- rescue Rant::TaskFail => e
979
- err_task_fail(e)
980
- abort
981
- end
965
+ unless opt[:type] == :file && !t.file_target?
966
+ matching_tasks += 1
967
+ begin
968
+ t.invoke(opt)
969
+ rescue Rant::TaskFail => e
970
+ err_task_fail(e)
971
+ abort
972
+ end
973
+ end
982
974
  }
983
975
  @current_subdir = old_subdir
984
976
  Dir.chdir old_pwd
@@ -1057,7 +1049,7 @@ class Rant::RantApp
1057
1049
  rf, is_new = rantfile_for_path(fn)
1058
1050
  load_file rf if is_new
1059
1051
  else
1060
- abort "No such file -- #{rf}"
1052
+ abort "No such file -- #{fn}"
1061
1053
  end
1062
1054
  }
1063
1055
  return
@@ -1138,14 +1130,6 @@ class Rant::RantApp
1138
1130
  path = dir ? File.join(dir, rfn) : rfn
1139
1131
  return path if test ?f, path
1140
1132
  }
1141
- ::Rant::DEPRECATED_RANTFILES.each { |rfn|
1142
- path = dir ? File.join(dir, rfn) : rfn
1143
- if test ?f, path
1144
- warn_msg "filename deprecated -- #{path}",
1145
- "please rename it to `Rantfile' or `root.rant'!"
1146
- return path
1147
- end
1148
- }
1149
1133
  nil
1150
1134
  end
1151
1135