rant 0.3.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 (64) hide show
  1. data/COPYING +504 -0
  2. data/README +203 -0
  3. data/Rantfile +104 -0
  4. data/TODO +19 -0
  5. data/bin/rant +12 -0
  6. data/bin/rant-import +12 -0
  7. data/devel-notes +50 -0
  8. data/doc/configure.rdoc +40 -0
  9. data/doc/csharp.rdoc +74 -0
  10. data/doc/rant-import.rdoc +32 -0
  11. data/doc/rant.rdoc +24 -0
  12. data/doc/rantfile.rdoc +227 -0
  13. data/doc/rubyproject.rdoc +210 -0
  14. data/lib/rant.rb +9 -0
  15. data/lib/rant/cs_compiler.rb +334 -0
  16. data/lib/rant/import.rb +291 -0
  17. data/lib/rant/import/rubydoc.rb +125 -0
  18. data/lib/rant/import/rubypackage.rb +417 -0
  19. data/lib/rant/import/rubytest.rb +97 -0
  20. data/lib/rant/plugin/README +50 -0
  21. data/lib/rant/plugin/configure.rb +345 -0
  22. data/lib/rant/plugin/csharp.rb +275 -0
  23. data/lib/rant/plugin_methods.rb +41 -0
  24. data/lib/rant/rantenv.rb +217 -0
  25. data/lib/rant/rantfile.rb +664 -0
  26. data/lib/rant/rantlib.rb +1118 -0
  27. data/lib/rant/rantsys.rb +258 -0
  28. data/lib/rant/rantvar.rb +82 -0
  29. data/rantmethods.rb +79 -0
  30. data/run_import +7 -0
  31. data/run_rant +7 -0
  32. data/setup.rb +1360 -0
  33. data/test/Rantfile +2 -0
  34. data/test/plugin/configure/Rantfile +47 -0
  35. data/test/plugin/configure/test_configure.rb +58 -0
  36. data/test/plugin/csharp/Hello.cs +10 -0
  37. data/test/plugin/csharp/Rantfile +30 -0
  38. data/test/plugin/csharp/src/A.cs +8 -0
  39. data/test/plugin/csharp/src/B.cs +8 -0
  40. data/test/plugin/csharp/test_csharp.rb +99 -0
  41. data/test/project1/Rantfile +127 -0
  42. data/test/project1/test_project.rb +203 -0
  43. data/test/project2/buildfile +14 -0
  44. data/test/project2/rantfile.rb +20 -0
  45. data/test/project2/sub1/Rantfile +12 -0
  46. data/test/project2/test_project.rb +87 -0
  47. data/test/project_rb1/README +14 -0
  48. data/test/project_rb1/bin/wgrep +5 -0
  49. data/test/project_rb1/lib/wgrep.rb +56 -0
  50. data/test/project_rb1/rantfile.rb +30 -0
  51. data/test/project_rb1/test/tc_wgrep.rb +21 -0
  52. data/test/project_rb1/test/text +3 -0
  53. data/test/project_rb1/test_project_rb1.rb +153 -0
  54. data/test/test_env.rb +47 -0
  55. data/test/test_filetask.rb +57 -0
  56. data/test/test_lighttask.rb +49 -0
  57. data/test/test_metatask.rb +29 -0
  58. data/test/test_rant_interface.rb +65 -0
  59. data/test/test_sys.rb +61 -0
  60. data/test/test_task.rb +115 -0
  61. data/test/toplevel.rf +11 -0
  62. data/test/ts_all.rb +4 -0
  63. data/test/tutil.rb +95 -0
  64. metadata +133 -0
@@ -0,0 +1,97 @@
1
+
2
+ require 'rant/rantlib'
3
+
4
+ module Rant
5
+ class Generators::RubyTest
6
+
7
+ class << self
8
+
9
+ def rant_generate(app, ch, args, &block)
10
+ if !args || args.empty?
11
+ self.new(app, ch, &block)
12
+ elsif args.size == 1
13
+ name, pre, file, ln =
14
+ app.normalize_task_arg(args.first, ch)
15
+ self.new(app, ch, name, pre, &block)
16
+ else
17
+ app.abort(app.pos_text(file, ln),
18
+ "RubyTest takes only one additional argument, " +
19
+ "which should be like one given to the `task' command.")
20
+ end
21
+ end
22
+ end
23
+
24
+ attr_accessor :verbose
25
+ attr_accessor :libs
26
+ attr_accessor :options
27
+ attr_accessor :test_dirs
28
+ attr_accessor :pattern
29
+ attr_accessor :test_files
30
+ # Directory where to run unit tests.
31
+ attr_accessor :test_dir
32
+
33
+ def initialize(app, cinf, name = :test, prerequisites = [], &block)
34
+ @name = name
35
+ @pre = prerequisites
36
+ @block = block
37
+ @verbose = nil
38
+ cf = cinf[:file]
39
+ @libs = []
40
+ libdir = File.join(File.dirname(
41
+ File.expand_path(cf)), 'lib')
42
+ @libs << libdir if test(?d, libdir)
43
+ @options = []
44
+ @test_dirs = []
45
+ @pattern = nil
46
+ @test_files = nil
47
+ @test_dir = nil
48
+ yield self if block_given?
49
+ @pattern = "test*.rb" if @pattern.nil? && @test_files.nil?
50
+
51
+ @pre ||= []
52
+ # define the task
53
+ app.task({:__caller__ => cinf, @name => @pre}) { |t|
54
+ arg = ""
55
+ libpath = (@libs.nil? || @libs.empty?) ?
56
+ nil : @libs.join(File::PATH_SEPARATOR)
57
+ if libpath
58
+ arg << "-I " << Env.shell_path(libpath) << " "
59
+ end
60
+ arg << "-S testrb " << optlist
61
+ if @test_dir
62
+ app.context.sys.cd(@test_dir) {
63
+ arg << filelist.arglist
64
+ app.context.sys.ruby arg
65
+ }
66
+ else
67
+ if test(?d, "test")
68
+ @test_dirs << "test"
69
+ elsif test(?d, "tests")
70
+ @test_dirs << "tests"
71
+ end
72
+ arg << filelist.arglist
73
+ app.context.sys.ruby arg
74
+ end
75
+ }
76
+ end
77
+ def optlist
78
+ options = (@options.is_a? Array) ?
79
+ @options.arglist : @options
80
+ ENV["TESTOPTS"] || options || ""
81
+ end
82
+ def filelist
83
+ return Dir[ENV['TEST']] if ENV['TEST']
84
+ filelist = @test_files || []
85
+ if filelist.empty?
86
+ if @test_dirs && !@test_dirs.empty?
87
+ @test_dirs.each { |dir|
88
+ filelist.concat(Dir[File.join(dir, @pattern)])
89
+ }
90
+ else
91
+ filelist.concat(Dir[@pattern]) if @pattern
92
+ end
93
+ end
94
+ filelist
95
+ end
96
+ end # class Generators::RubyTest
97
+ end # module Rant
@@ -0,0 +1,50 @@
1
+
2
+ = Rant plugins
3
+
4
+ An Rant plugin provides additional functionality for the Rant program.
5
+ Every Ruby script (file ending in <tt>.rb</tt>) in the
6
+ <tt>rant/plugin</tt> directory is considered a plugin. Normally, it
7
+ contains one class in the Rant::Plugin module.
8
+
9
+ == Requirements for a plugin
10
+
11
+ One file ending in <tt>.rb</tt> in the <tt>rant/plugin</tt> directory.
12
+ One class, defined in this file, in the Rant::Plugin namespace
13
+ responding to the +new_plugin+ method. Note that the *class* has to
14
+ respond!
15
+
16
+ This is a list of all methods the plugin class/instance has to respond
17
+ to:
18
+
19
+ === Class methods:
20
+
21
+ [plugin_create]
22
+ Instantiates the plugin. Will be called every time a new
23
+ Rant::RantApp is created.
24
+
25
+ === Instance methods:
26
+
27
+ [rant_plugin_init]
28
+ Called on Rant startup. Usually directly after plugin
29
+ instantiation.
30
+ [rant_start]
31
+ Called before Rant runs the first task.
32
+ [rant_done]
33
+ Called when Rant has *successfully* processed all required
34
+ tasks.
35
+ [rant_plugin_stop]
36
+ Signals that the plugin should be stopped.
37
+ The plugin object should respond by disposing all reserved
38
+ resources, closing open files etc.
39
+ [rant_quit]
40
+ This is always called before the Rant application quits, even
41
+ if there was a failure. Usually immediately called after
42
+ +rant_plugin_stop+.
43
+
44
+ == Startup
45
+
46
+ Every time a Rant application is initialized, it calls the
47
+ +plugin_create+ method of every class (which has this method) in the
48
+ Plugin module. This method should return a new plugin instance.
49
+
50
+ == Shutdown
@@ -0,0 +1,345 @@
1
+
2
+ require 'rant/plugin_methods'
3
+ require 'yaml'
4
+
5
+ # Configure plugin for Rant
6
+
7
+ module Rant::Plugin
8
+
9
+ # === Startup of configure plugin
10
+ # ==== Config file exists
11
+ # The configuration file will be read and the data hash
12
+ # set up accordingly.
13
+ # ==== Config file doesn't exist
14
+ # The configuration process is run with +startup_modes+ which
15
+ # has to be one of CHECK_MODES. +startup_modes+ defaults to
16
+ # :default, which means if the configfile doesn't exist,
17
+ # all values will be set to their defaults on startup.
18
+ # === Access to configuration in Rantfile
19
+ # You can access all configuration values through the <tt>[]</tt>
20
+ # and <tt>[]=</tt> operators of the configure plugin.
21
+ #
22
+ # Example of configure in Rantfile:
23
+ #
24
+ # conf = plugin :Configure do |conf|
25
+ # conf.task # define a task named :configure
26
+ # conf.check "profile" do |c|
27
+ # c.default "full"
28
+ # c.guess { ENV["PROFILE"] }
29
+ # c.interact {
30
+ # conf.prompt "What build-profile should be used?"
31
+ # }
32
+ # end
33
+ # conf.check "optimize" do |c|
34
+ # c.default true
35
+ # c.guess { ENV["OPTIMIZE"] }
36
+ # c.interact {
37
+ # conf.ask_yes_no "Optimize build?"
38
+ # }
39
+ # end
40
+ # end
41
+ #
42
+ # # Set default target depending on profile:
43
+ # task :default => conf["profile"]
44
+ class Configure
45
+ include ::Rant::PluginMethods
46
+ include ::Rant::Console
47
+
48
+ class << self
49
+ def rant_plugin_new(app, cinf, *args, &block)
50
+ if args.size > 1
51
+ app.abort(app.pos_text(cinf[:file], cinf[:ln]),
52
+ "Configure plugin takes only one argument.")
53
+ end
54
+ self.new(app, args.first, &block)
55
+ end
56
+ end
57
+
58
+ CHECK_MODES = [
59
+ :default,
60
+ :env,
61
+ :guess,
62
+ :interact,
63
+ ]
64
+
65
+ # Name for this plugin instance. Defaults to "configure".
66
+ attr_reader :name
67
+
68
+ # Name of configuration file.
69
+ attr_accessor :file
70
+
71
+ # This flag is used to determine if data has changed and
72
+ # should be saved to file.
73
+ attr_accessor :modified
74
+
75
+ # An array with all checks to perform.
76
+ attr_reader :checklist
77
+
78
+ # Decide what the configure plugin does on startup if the
79
+ # configuration file doesn't exist. Initialized to
80
+ # <tt>[:guess]</tt>.
81
+ attr_accessor :init_modes
82
+
83
+ # Decide what the configure plugin does *after* reading the
84
+ # configuration file (or directly after running +init_modes+
85
+ # if the configuration file doesn't exist).
86
+ # Initialized to <tt>[:env]</tt>, probably the only usefull
87
+ # value.
88
+ attr_accessor :override_modes
89
+
90
+ # Don't write to file, config values will be lost when
91
+ # rant exits!
92
+ attr_accessor :no_write
93
+
94
+ # Don't read or write to configuration file nor run +guess+ or
95
+ # +interact+ blocks if *first* target given on commandline
96
+ # is in this list. This is usefull for targets that remove
97
+ # the configuration file.
98
+ # Defaults are "distclean", "clobber" and "clean".
99
+ attr_reader :no_action_list
100
+
101
+ def initialize(app, name = nil)
102
+ @name = name || rant_plugin_type
103
+ @app = app or raise ArgumentError, "no application given"
104
+ @file = "config"
105
+ @checklist = []
106
+ @init_modes = [:guess]
107
+ @override_modes = [:env]
108
+ @no_write = false
109
+ @modified = false
110
+ @no_action_list = ["distclean", "clobber", "clean"]
111
+ @no_action = false
112
+ @configured = false
113
+
114
+ yield self if block_given?
115
+
116
+ run_checklist([:default])
117
+ # we don't need to save our defaults
118
+ @modified = false
119
+ end
120
+
121
+ # Get the value for +key+ from +checklist+ or +nil+ if there
122
+ # isn't a check with the given +key+.
123
+ def [](key)
124
+ c = checklist.find { |c| c.key == key }
125
+ c ? c.value : nil
126
+ end
127
+
128
+ # Creates new check with default value if key doesn't exist.
129
+ def []=(key, val)
130
+ c = checklist.find { |c| c.key == key }
131
+ if c
132
+ if c.value != val
133
+ c.value = val
134
+ @modified = true
135
+ end
136
+ else
137
+ self.check(key) { |c|
138
+ c.default val
139
+ }
140
+ end
141
+ end
142
+
143
+ # Sets the specified check if a check with the given key
144
+ # exists.
145
+ # Returns the value if it was set, nil otherwise.
146
+ def set_if_exists(key, value)
147
+ c = checklist.find { |c| c.key == key }
148
+ if c
149
+ c.value = value
150
+ @modified = true
151
+ else
152
+ nil
153
+ end
154
+ end
155
+
156
+ # Builds a hash with all key-value pairs from checklist.
157
+ def data
158
+ hsh = {}
159
+ @checklist.each { |c|
160
+ hsh[c.key] = c.value
161
+ }
162
+ hsh
163
+ end
164
+
165
+ # This is true, if either a configure task was run, or the
166
+ # configuration file was read.
167
+ def configured?
168
+ @configured
169
+ end
170
+
171
+ # Define a task with +name+ that will run the configuration
172
+ # process in the given +check_modes+. If no task name is given
173
+ # or it is +nil+, the plugin name will be used as task name.
174
+ def task(name = nil, check_modes = [:guess, :interact])
175
+ name ||= @name
176
+ cinf = ::Rant::Lib.parse_caller_elem(caller[0])
177
+ file = cinf[:file]
178
+ ln = cinf[:ln] || 0
179
+ if !Array === check_modes || check_modes.empty?
180
+ @app.abort(@app.pos_text(file, ln),
181
+ "check_modes given to configure task has to be an array",
182
+ "containing at least one CHECK_MODE symbol")
183
+ end
184
+ check_modes.each { |cm|
185
+ unless CHECK_MODES.include? cm
186
+ @app.abort(@app.pos_text(file,ln),
187
+ "Unknown checkmode `#{cm.to_s}'.")
188
+ end
189
+ }
190
+ nt = @app.task(name) { |t|
191
+ run_checklist(check_modes)
192
+ save
193
+ @configured = true
194
+ }
195
+ nt
196
+ end
197
+
198
+ def check(key, val = nil, &block)
199
+ checklist << ConfigureCheck.new(key, val, &block)
200
+ end
201
+
202
+ # Run the configure process in the given modes.
203
+ def run_checklist(modes = [:guess, :interact])
204
+ @checklist.each { |c|
205
+ c.run_check(modes)
206
+ }
207
+ @modified = true
208
+ end
209
+
210
+ # Write configuration if modified.
211
+ def save
212
+ return if @no_write
213
+ write_yaml if @modified
214
+ true
215
+ end
216
+
217
+ # Immediately write configuration to +file+.
218
+ def write
219
+ write_yaml
220
+ @modified = false
221
+ end
222
+
223
+ ###### overriden plugin methods ##############################
224
+ def rant_plugin_type
225
+ "configure"
226
+ end
227
+
228
+ def rant_plugin_name
229
+ @name
230
+ end
231
+
232
+ def rant_plugin_init
233
+ @no_action = @no_action_list.include? @app.cmd_targets.first
234
+ @no_action || init_config
235
+ end
236
+
237
+ def rant_plugin_stop
238
+ @no_action || save
239
+ end
240
+ ##############################################################
241
+
242
+ private
243
+
244
+ # Returns true on success, nil on failure.
245
+ def init_config
246
+ if File.exist? @file
247
+ read_yaml
248
+ @configured = true
249
+ elsif !@init_modes == [:default]
250
+ run_checklist @init_modes
251
+ end
252
+ if @override_modes && !@override_modes.empty?
253
+ run_checklist @override_modes
254
+ end
255
+ end
256
+
257
+ def write_yaml
258
+ @app.msg 1, "Writing config to `#{@file}'."
259
+ File.open(@file, "w") { |f|
260
+ f << data.to_yaml
261
+ f << "\n"
262
+ }
263
+ true
264
+ rescue
265
+ @app.abort("When writing configuration: " + $!.message,
266
+ "Ensure writing to file (doesn't need to exist) `#{@file}'",
267
+ "is possible and try to reconfigure!")
268
+ end
269
+
270
+ def read_yaml
271
+ File.open(@file) { |f|
272
+ YAML.load_documents(f) { |doc|
273
+ if doc.is_a? Hash
274
+ doc.each_pair { |k, v|
275
+ self[k] = v
276
+ }
277
+ else
278
+ @app.abort("Invalid config file `#{@file}'.",
279
+ "Please remove this file or reconfigure.")
280
+ end
281
+ }
282
+ }
283
+ rescue
284
+ @app.abort("When attempting to read config: " + $!.message)
285
+ end
286
+
287
+ end # class Configure
288
+ class ConfigureCheck
289
+ include ::Rant::Console
290
+
291
+ public :msg, :prompt, :ask_yes_no
292
+
293
+ attr_reader :key
294
+ attr_accessor :value
295
+ attr_writer :default
296
+ attr_accessor :guess_block
297
+ attr_accessor :interact_block
298
+ attr_accessor :react_block
299
+ def initialize(key, val = nil)
300
+ @key = key or raise ArgumentError, "no key given"
301
+ @value = @default = val
302
+ @guess_block = nil
303
+ @interact_block = nil
304
+ @react_block = nil
305
+ yield self if block_given?
306
+ end
307
+ def default(val)
308
+ @default = val
309
+ @value = @default if @value.nil?
310
+ end
311
+ def guess(&block)
312
+ @guess_block = block
313
+ end
314
+ def interact(&block)
315
+ @interact_block = block
316
+ end
317
+ def react(&block)
318
+ @react_block = block
319
+ end
320
+
321
+ # Run checks as specified by +modes+. +modes+ has to be a list
322
+ # of symbols from the Configure::CHECK_MODES.
323
+ def run_check(modes = [:guess], env = ENV)
324
+ val = nil
325
+ modes.each { |mode|
326
+ case mode
327
+ when :default
328
+ val = @default
329
+ when :env
330
+ val = env[@key]
331
+ when :interact
332
+ val = @interact_block[self] if @interact_block
333
+ when :guess
334
+ val = @guess_block[self] if @guess_block
335
+ else
336
+ raise "unknown configure mode"
337
+ end
338
+ break unless val.nil?
339
+ }
340
+ val.nil? or @value = val
341
+ @react_block && @react_block[@value]
342
+ @value
343
+ end
344
+ end # class ConfigureCheck
345
+ end # module Rant::Plugin