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
@@ -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