rant 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING +504 -0
- data/README +203 -0
- data/Rantfile +104 -0
- data/TODO +19 -0
- data/bin/rant +12 -0
- data/bin/rant-import +12 -0
- data/devel-notes +50 -0
- data/doc/configure.rdoc +40 -0
- data/doc/csharp.rdoc +74 -0
- data/doc/rant-import.rdoc +32 -0
- data/doc/rant.rdoc +24 -0
- data/doc/rantfile.rdoc +227 -0
- data/doc/rubyproject.rdoc +210 -0
- data/lib/rant.rb +9 -0
- data/lib/rant/cs_compiler.rb +334 -0
- data/lib/rant/import.rb +291 -0
- data/lib/rant/import/rubydoc.rb +125 -0
- data/lib/rant/import/rubypackage.rb +417 -0
- data/lib/rant/import/rubytest.rb +97 -0
- data/lib/rant/plugin/README +50 -0
- data/lib/rant/plugin/configure.rb +345 -0
- data/lib/rant/plugin/csharp.rb +275 -0
- data/lib/rant/plugin_methods.rb +41 -0
- data/lib/rant/rantenv.rb +217 -0
- data/lib/rant/rantfile.rb +664 -0
- data/lib/rant/rantlib.rb +1118 -0
- data/lib/rant/rantsys.rb +258 -0
- data/lib/rant/rantvar.rb +82 -0
- data/rantmethods.rb +79 -0
- data/run_import +7 -0
- data/run_rant +7 -0
- data/setup.rb +1360 -0
- data/test/Rantfile +2 -0
- data/test/plugin/configure/Rantfile +47 -0
- data/test/plugin/configure/test_configure.rb +58 -0
- data/test/plugin/csharp/Hello.cs +10 -0
- data/test/plugin/csharp/Rantfile +30 -0
- data/test/plugin/csharp/src/A.cs +8 -0
- data/test/plugin/csharp/src/B.cs +8 -0
- data/test/plugin/csharp/test_csharp.rb +99 -0
- data/test/project1/Rantfile +127 -0
- data/test/project1/test_project.rb +203 -0
- data/test/project2/buildfile +14 -0
- data/test/project2/rantfile.rb +20 -0
- data/test/project2/sub1/Rantfile +12 -0
- data/test/project2/test_project.rb +87 -0
- data/test/project_rb1/README +14 -0
- data/test/project_rb1/bin/wgrep +5 -0
- data/test/project_rb1/lib/wgrep.rb +56 -0
- data/test/project_rb1/rantfile.rb +30 -0
- data/test/project_rb1/test/tc_wgrep.rb +21 -0
- data/test/project_rb1/test/text +3 -0
- data/test/project_rb1/test_project_rb1.rb +153 -0
- data/test/test_env.rb +47 -0
- data/test/test_filetask.rb +57 -0
- data/test/test_lighttask.rb +49 -0
- data/test/test_metatask.rb +29 -0
- data/test/test_rant_interface.rb +65 -0
- data/test/test_sys.rb +61 -0
- data/test/test_task.rb +115 -0
- data/test/toplevel.rf +11 -0
- data/test/ts_all.rb +4 -0
- data/test/tutil.rb +95 -0
- 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
|