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