rant 0.3.4 → 0.3.6
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/NEWS +13 -0
- data/README +1 -1
- data/Rantfile +24 -16
- data/doc/advanced.rdoc +188 -0
- data/doc/examples/directedrule/Rantfile +23 -0
- data/doc/examples/directedrule/src_a/a_1.c +0 -0
- data/doc/examples/directedrule/src_a/a_2.c +5 -0
- data/doc/examples/directedrule/src_b/b_1.c +0 -0
- data/doc/jamis.rb +590 -0
- data/doc/rantfile.rdoc +29 -9
- data/lib/rant/import.rb +19 -9
- data/lib/rant/import/autoclean.rb +65 -0
- data/lib/rant/import/clean.rb +45 -0
- data/lib/rant/import/directedrule.rb +122 -0
- data/lib/rant/import/package.rb +258 -0
- data/lib/rant/import/rubydoc.rb +5 -0
- data/lib/rant/import/rubypackage.rb +1 -1
- data/lib/rant/import/truth.rb +24 -0
- data/lib/rant/plugin/configure.rb +1 -0
- data/lib/rant/rantfile.rb +77 -26
- data/lib/rant/rantlib.rb +116 -21
- data/lib/rant/rantsys.rb +92 -4
- data/lib/rant/rantvar.rb +252 -11
- data/rantmethods.rb +2 -2
- data/test/Rantfile +35 -1
- data/test/import/directedrule/Rantfile +27 -0
- data/test/import/directedrule/test_directedrule.rb +31 -0
- data/test/import/truth/Rantfile +16 -0
- data/test/import/truth/test_truth.rb +23 -0
- data/test/rant-import/Rantfile +15 -0
- data/test/rant-import/test_rant-import.rb +65 -0
- data/test/test_clean.rb +134 -0
- data/test/test_examples.rb +47 -0
- data/test/test_filelist.rb +58 -0
- data/test/test_rac.rb +59 -0
- data/test/test_rantfile_api.rb +47 -0
- data/test/test_var.rb +176 -0
- data/test/tutil.rb +18 -2
- data/test/var.rf +23 -0
- metadata +29 -2
data/doc/rantfile.rdoc
CHANGED
@@ -26,13 +26,16 @@ methods with the Rant application:
|
|
26
26
|
"rubypackage"</tt> first.
|
27
27
|
+plugin+:: Instantiate a plugin. Example: <tt>plugin
|
28
28
|
:Configure</tt> instantiates the Configure plugin.
|
29
|
-
+sys+::
|
30
|
-
|
31
|
-
|
29
|
+
+sys+:: Run external commands or call portable file system
|
30
|
+
manipulation methods (copy files, unlink files,
|
31
|
+
install, ...).
|
32
32
|
+source+:: Takes a filename as argument and causes Rant to read
|
33
33
|
it in as Rantfile.
|
34
34
|
+subdirs+:: Takes a list of subdirectories in which Rant should
|
35
35
|
look for Rantfiles.
|
36
|
+
+var+:: Provides access to variables accessible in Rantfiles
|
37
|
+
and from the commandline.
|
38
|
+
+rac+:: The "Rant compiler" which is compiling the Rantfiles.
|
36
39
|
|
37
40
|
=== Defining a task
|
38
41
|
|
@@ -203,23 +206,31 @@ Note:: You are highly encouraged to not <tt>include Rant::Sys</tt>
|
|
203
206
|
read the ri docs to get an overview:
|
204
207
|
ri Dir::glob
|
205
208
|
|
209
|
+
From now on we'll call <tt>sys[...]</tt> the <it>glob
|
210
|
+
operator</it>.
|
211
|
+
|
206
212
|
You can give more patterns:
|
207
213
|
c_files = sys["**/*.h", "**/*.c"]
|
208
214
|
gives a list of all files ending in ".h" or ".c" in the current
|
209
215
|
directory and all subdirectories.
|
210
216
|
|
211
|
-
The object returned by
|
212
|
-
it is possible to pass it to methods expecting an array.
|
213
|
-
getting errors or experience strange behaviour convert
|
214
|
-
explicetely to an array:
|
217
|
+
The object returned by the glob operator _behaves_ like a list of
|
218
|
+
string, so it is possible to pass it to methods expecting an array.
|
219
|
+
If you're getting errors or experience strange behaviour convert
|
220
|
+
the list explicetely to an array:
|
215
221
|
sys.touch c_files.to_a
|
216
222
|
|
217
223
|
=== Generators
|
218
224
|
|
219
225
|
The *gen* function takes a generator which usually creates one or more
|
220
|
-
tasks for you.
|
226
|
+
tasks for you. The following list of generators is immediately
|
227
|
+
available:
|
221
228
|
+Directory+:: Create directories.
|
222
229
|
+Task+:: Define custom task.
|
230
|
+
+Rule+:: Define a rule (a rule produces tasks on the fly).
|
231
|
+
+Action+:: Run a block of code immediately.
|
232
|
+
The Action generator is discussed in
|
233
|
+
doc/advanced.rdoc[link:files/doc/advanced_rdoc.html].
|
223
234
|
|
224
235
|
=== The +Directory+ generator
|
225
236
|
|
@@ -294,11 +305,20 @@ last dot with the given string.
|
|
294
305
|
|
295
306
|
The +import+ function lets you import additional generators.
|
296
307
|
Currently the following are coming with Rant:
|
308
|
+
+Clean+:: Remove selected files.
|
309
|
+
+AutoClean+:: Remove all files generated by any file task (including
|
310
|
+
those generated by rules).
|
311
|
+
+DirectedRule+:: A Rule which takes sources from one or more
|
312
|
+
directories and puts generated files into a specified
|
313
|
+
directory.
|
297
314
|
+RubyTest+:: Run Test::Unit tests for your Ruby code.
|
298
315
|
+RubyDoc+:: Run RDoc.
|
299
316
|
+RubyPackage+:: Generate tar, zip and gem packages of your Ruby
|
300
317
|
application/library.
|
301
|
-
|
318
|
+
|
319
|
+
Read doc/advanced.rdoc[link:files/doc/advanced_rdoc.html] and
|
320
|
+
doc/rubyproject.rdoc[link:files/doc/rubyproject_rdoc.html] for
|
321
|
+
documentation.
|
302
322
|
|
303
323
|
=== The +subdirs+ command
|
304
324
|
|
data/lib/rant/import.rb
CHANGED
@@ -19,9 +19,6 @@ module Rant
|
|
19
19
|
class RantImport
|
20
20
|
include Rant::Console
|
21
21
|
|
22
|
-
# TODO: We currently only look for imports and plugins
|
23
|
-
# relative to this LIB_DIR. We should also look in all pathes
|
24
|
-
# in $LOAD_PATH after looking in LIB_DIR.
|
25
22
|
LIB_DIR = File.expand_path(File.dirname(__FILE__))
|
26
23
|
|
27
24
|
OPTIONS = [
|
@@ -244,8 +241,8 @@ EOF
|
|
244
241
|
rs = ""
|
245
242
|
@imports.each { |name|
|
246
243
|
next if @included_imports.include? name
|
247
|
-
path =
|
248
|
-
unless
|
244
|
+
path = get_lib_rant_path "import/#{name}.rb"
|
245
|
+
unless path
|
249
246
|
abort("No such import - #{name}")
|
250
247
|
end
|
251
248
|
msg "Including import `#{name}'", path
|
@@ -260,7 +257,7 @@ EOF
|
|
260
257
|
@plugins.each { |name|
|
261
258
|
lc_name = name.downcase
|
262
259
|
next if @included_plugins.include? lc_name
|
263
|
-
path =
|
260
|
+
path = get_lib_rant_path "plugin/#{lc_name}.rb"
|
264
261
|
unless File.exist? path
|
265
262
|
abort("No such plugin - #{name}")
|
266
263
|
end
|
@@ -275,8 +272,6 @@ EOF
|
|
275
272
|
# code by directly inserting the code.
|
276
273
|
def resolve_requires script
|
277
274
|
rs = ""
|
278
|
-
# TODO: skip multiline comments (=begin, =end) only of
|
279
|
-
# @skip_comments is true
|
280
275
|
in_ml_comment = false
|
281
276
|
script.each { |line|
|
282
277
|
if in_ml_comment
|
@@ -293,10 +288,15 @@ EOF
|
|
293
288
|
in_ml_comment = true
|
294
289
|
next if @skip_comments
|
295
290
|
end
|
291
|
+
name = nil
|
296
292
|
if line =~ /\s*(require|load)\s+('|")rant\/(\w+)(\.rb)?('|")/
|
297
293
|
name = $3
|
294
|
+
elsif line =~ /\s*(require|load)\s+('|")rant\/(import\/\w+)(\.rb)?('|")/
|
295
|
+
name = $3
|
296
|
+
end
|
297
|
+
if name
|
298
298
|
next if @core_imports.include? name
|
299
|
-
path =
|
299
|
+
path = get_lib_rant_path "#{name}.rb"
|
300
300
|
msg "Including `#{name}'", path
|
301
301
|
@core_imports << name
|
302
302
|
rs << resolve_requires(File.read(path))
|
@@ -308,5 +308,15 @@ EOF
|
|
308
308
|
rs
|
309
309
|
end
|
310
310
|
|
311
|
+
def get_lib_rant_path(fn)
|
312
|
+
path = File.join(LIB_DIR, fn)
|
313
|
+
return path if File.exist?(path)
|
314
|
+
$:.each { |lib_dir|
|
315
|
+
path = File.join(lib_dir, "rant", fn)
|
316
|
+
return path if File.exist?(path)
|
317
|
+
}
|
318
|
+
nil
|
319
|
+
end
|
320
|
+
|
311
321
|
end # class RantImport
|
312
322
|
end # module Rant
|
@@ -0,0 +1,65 @@
|
|
1
|
+
|
2
|
+
# autoclean.rb - "AutoClean" generator for Rant.
|
3
|
+
#
|
4
|
+
# Copyright (C) 2005 Stefan Lang <langstefan@gmx.at>
|
5
|
+
|
6
|
+
require 'rant/rantlib'
|
7
|
+
require 'rant/import/clean'
|
8
|
+
|
9
|
+
class Rant::Generators::AutoClean
|
10
|
+
def self.rant_generate(rac, ch, args, &block)
|
11
|
+
# validate args
|
12
|
+
if args.size > 1
|
13
|
+
rac.abort_at(ch,
|
14
|
+
"AutoClean doesn't take more than one argument.")
|
15
|
+
end
|
16
|
+
tname = args.first || "autoclean"
|
17
|
+
|
18
|
+
# we generate a normal clean task too, so that the user can
|
19
|
+
# add files to clean via a var
|
20
|
+
::Rant::Generators::Clean.rant_generate(rac, ch, [tname])
|
21
|
+
|
22
|
+
# create task
|
23
|
+
rac.task :__caller__ => ch, tname => [] do |t|
|
24
|
+
rac.tasks.each { |n, worker|
|
25
|
+
worker.each_target { |entry|
|
26
|
+
if test ?e, entry
|
27
|
+
if test ?f, entry
|
28
|
+
rac.cx.sys.rm_f entry
|
29
|
+
else
|
30
|
+
rac.cx.sys.rm_rf entry
|
31
|
+
end
|
32
|
+
end
|
33
|
+
}
|
34
|
+
}
|
35
|
+
target_rx = nil
|
36
|
+
rac.resolve_hooks.each { |hook|
|
37
|
+
if hook.respond_to? :each_target
|
38
|
+
hook.each_target { |entry|
|
39
|
+
if test ?f, entry
|
40
|
+
rac.cx.sys.rm_f entry
|
41
|
+
else
|
42
|
+
rac.cx.sys.rm_rf entry
|
43
|
+
end
|
44
|
+
}
|
45
|
+
elsif hook.respond_to? :target_rx
|
46
|
+
next(rx) unless (t_rx = hook.target_rx)
|
47
|
+
target_rx = target_rx.nil? ? t_rx :
|
48
|
+
Regexp.union(target_rx, t_rx)
|
49
|
+
end
|
50
|
+
}
|
51
|
+
if target_rx
|
52
|
+
rac.msg 1, "searching for rule products"
|
53
|
+
rac.cx.sys["**/*"].each { |entry|
|
54
|
+
if entry =~ target_rx
|
55
|
+
if test ?f, entry
|
56
|
+
rac.cx.sys.rm_f entry
|
57
|
+
else
|
58
|
+
rac.cx.sys.rm_rf entry
|
59
|
+
end
|
60
|
+
end
|
61
|
+
}
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
|
2
|
+
# clean.rb - "Clean" generator for Rant.
|
3
|
+
#
|
4
|
+
# Copyright (C) 2005 Stefan Lang <langstefan@gmx.at>
|
5
|
+
|
6
|
+
require 'rant/rantlib'
|
7
|
+
|
8
|
+
class Rant::Generators::Clean
|
9
|
+
def self.rant_generate(rac, ch, args, &block)
|
10
|
+
# validate args
|
11
|
+
if args.size > 1
|
12
|
+
rac.abort_at(ch, "Clean doesn't take more than one argument.")
|
13
|
+
end
|
14
|
+
tname = args.first || "clean"
|
15
|
+
|
16
|
+
# set var with task name to a MultiFileList
|
17
|
+
case rac.var[tname]
|
18
|
+
when nil
|
19
|
+
rac.var[tname] = Rant::MultiFileList.new(rac)
|
20
|
+
when Rant::RacFileList
|
21
|
+
ml = Rant::MultiFileList.new(rac)
|
22
|
+
rac.var[tname] = ml.add(rac.var[tname])
|
23
|
+
when Rant::MultiFileList
|
24
|
+
# ok, nothing to do
|
25
|
+
else
|
26
|
+
# TODO: refine error message
|
27
|
+
rac.abort_at(ch,
|
28
|
+
"var `#{tname}' already exists.",
|
29
|
+
"Clean uses var with the same name as the task name.")
|
30
|
+
end
|
31
|
+
|
32
|
+
# create task
|
33
|
+
rac.task :__caller__ => ch, tname => [] do |t|
|
34
|
+
rac.var[tname].each_entry { |entry|
|
35
|
+
if test ?e, entry
|
36
|
+
if test ?f, entry
|
37
|
+
rac.cx.sys.rm_f entry
|
38
|
+
else
|
39
|
+
rac.cx.sys.rm_rf entry
|
40
|
+
end
|
41
|
+
end
|
42
|
+
}
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end # class Rant::Generators::Clean
|
@@ -0,0 +1,122 @@
|
|
1
|
+
|
2
|
+
# directedrule.rb - "DirectedRule" generator for Rant.
|
3
|
+
#
|
4
|
+
# Copyright (C) 2005 Stefan Lang <langstefan@gmx.at>
|
5
|
+
|
6
|
+
require 'rant/rantlib'
|
7
|
+
|
8
|
+
class Rant::Generators::DirectedRule
|
9
|
+
def self.rant_generate(rac, ch, args, &block)
|
10
|
+
unless args.size == 1
|
11
|
+
rac.abort_at(ch, "DirectedRule takes one arguments.")
|
12
|
+
end
|
13
|
+
h = args.first
|
14
|
+
if h.respond_to? :to_hash
|
15
|
+
h = h.to_hash
|
16
|
+
else
|
17
|
+
rac.abort_at(ch, "Argument has to be a hash.")
|
18
|
+
end
|
19
|
+
ts_h, dir_h = nil, nil
|
20
|
+
h.each { |k, v| v.respond_to?(:to_ary) ?
|
21
|
+
dir_h = { k => v } :
|
22
|
+
ts_h = { k => v }
|
23
|
+
}
|
24
|
+
unless dir_h
|
25
|
+
rac.abort_at(ch,
|
26
|
+
"Source directory argument has to be a list.")
|
27
|
+
end
|
28
|
+
target, source = nil, nil
|
29
|
+
ts_h.each { |target, source| }
|
30
|
+
target_dir, source_dirs = nil, nil
|
31
|
+
dir_h.each { |target_dir, source_dirs| }
|
32
|
+
if target_dir.respond_to? :to_str
|
33
|
+
target_dir = target_dir.to_str
|
34
|
+
else
|
35
|
+
rac.abort_at(ch, "String required as target directory.")
|
36
|
+
end
|
37
|
+
if source_dirs.respond_to? :to_ary
|
38
|
+
source_dirs = source_dirs.to_ary
|
39
|
+
elsif source_dirs.respond_to? :to_str
|
40
|
+
source_dirs = [source_dirs.to_str]
|
41
|
+
else
|
42
|
+
rac.abort_at(ch,
|
43
|
+
"List of strings or string required for source directories.")
|
44
|
+
end
|
45
|
+
target = ".#{target}" if Symbol === target
|
46
|
+
source = ".#{source}" if Symbol === source
|
47
|
+
if target.respond_to? :to_str
|
48
|
+
target = target.to_str
|
49
|
+
else
|
50
|
+
rac.abort_at(ch, "target has to be a string")
|
51
|
+
end
|
52
|
+
if source.respond_to? :to_str
|
53
|
+
source = source.to_str
|
54
|
+
else
|
55
|
+
rac.abort_at(ch, "source has to be a string or symbol")
|
56
|
+
end
|
57
|
+
blk = self.new(rac, ch, target_dir, source_dirs,
|
58
|
+
target, source, &block)
|
59
|
+
blk.define_hook
|
60
|
+
blk
|
61
|
+
end
|
62
|
+
def initialize(rac, ch, target_dir, source_dirs,
|
63
|
+
target, source, &block)
|
64
|
+
@rac = rac
|
65
|
+
@ch = ch
|
66
|
+
@source_dirs = source_dirs
|
67
|
+
@target_dir = target_dir
|
68
|
+
# target should be a string (file extension)
|
69
|
+
@target = target.sub(/^\./, '')
|
70
|
+
@target_rx = /#{Regexp.escape(target)}$/o
|
71
|
+
# source should be a string (file extension)
|
72
|
+
@source = source.sub(/^\./, '')
|
73
|
+
@esc_target_dir = Regexp.escape(target_dir)
|
74
|
+
@block = block
|
75
|
+
end
|
76
|
+
def call(name)
|
77
|
+
self[name]
|
78
|
+
end
|
79
|
+
def [](name)
|
80
|
+
#puts "rule for #{name} ?"
|
81
|
+
if name =~ /^#@esc_target_dir\//o && name =~ @target_rx
|
82
|
+
#puts " matches"
|
83
|
+
fn = File.basename(name)
|
84
|
+
src_fn = fn.sub_ext(@source)
|
85
|
+
#puts " source filename #{src_fn}"
|
86
|
+
src = nil
|
87
|
+
@source_dirs.each { |d|
|
88
|
+
path = File.join(d, src_fn)
|
89
|
+
#puts " #{path} exist?"
|
90
|
+
(src = path) && break if test(?e, path)
|
91
|
+
}
|
92
|
+
if src
|
93
|
+
[@rac.file(:__caller__ => @ch, name => src, &@block)]
|
94
|
+
else
|
95
|
+
nil
|
96
|
+
end
|
97
|
+
else
|
98
|
+
nil
|
99
|
+
end
|
100
|
+
end
|
101
|
+
def define_hook
|
102
|
+
@rac.resolve_hooks << self
|
103
|
+
end
|
104
|
+
def each_target &block
|
105
|
+
@rac.cx.sys["#@target_dir/*"].each { |entry|
|
106
|
+
yield entry if entry =~ @target_rx
|
107
|
+
}
|
108
|
+
end
|
109
|
+
def candidates
|
110
|
+
sources.map { |src|
|
111
|
+
File.join(@target_dir, File.basename(src).sub_ext(@target))
|
112
|
+
}
|
113
|
+
end
|
114
|
+
def sources
|
115
|
+
# TODO: returning a file list would be more efficient
|
116
|
+
cl = []
|
117
|
+
@source_dirs.each { |dir|
|
118
|
+
cl.concat(@rac.cx.sys["#{dir}/*.#@source"])
|
119
|
+
}
|
120
|
+
cl
|
121
|
+
end
|
122
|
+
end # class Rant::Generators::DirectedRule
|
@@ -0,0 +1,258 @@
|
|
1
|
+
|
2
|
+
require 'rant/rantlib'
|
3
|
+
|
4
|
+
class Rant::Generators::Package
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def rant_generate(app, ch, args, &block)
|
8
|
+
if !args || args.empty?
|
9
|
+
self.new(:app => app, :__caller__ => ch, &block)
|
10
|
+
elsif args.size == 1
|
11
|
+
pkg_name = case args.first
|
12
|
+
when String: args.first
|
13
|
+
when Symbol: args.first.to_s
|
14
|
+
else
|
15
|
+
app.abort("Package takes only one additional " +
|
16
|
+
"argument, which should be a string or symbol.")
|
17
|
+
end
|
18
|
+
self.new(:app => app, :__caller__ => ch,
|
19
|
+
:name => pkg_name, &block)
|
20
|
+
else
|
21
|
+
app.abort(app.pos_text(file, ln),
|
22
|
+
"Package takes only one additional argument, " +
|
23
|
+
"which should be a string or symbol.")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# A hash containing all package information.
|
29
|
+
attr_reader :data
|
30
|
+
# Directory where packages go to. Defaults to "pkg".
|
31
|
+
attr_accessor :pkg_dir
|
32
|
+
|
33
|
+
def initialize(opts = {})
|
34
|
+
@rac = opts[:app] || Rant.rantapp
|
35
|
+
@pkg_dir = "pkg"
|
36
|
+
@pkg_dir_task = nil
|
37
|
+
@dist_dir_task = nil
|
38
|
+
@tar_task = nil
|
39
|
+
@zip_task = nil
|
40
|
+
@package_task = nil
|
41
|
+
name = opts[:name]
|
42
|
+
@ch = opts[:__caller__] || Rant::Lib.parse_caller_elem(caller[0])
|
43
|
+
unless name
|
44
|
+
# TODO: pos_text
|
45
|
+
@rac.warn_msg(@rac.pos_text(@ch[:file], @ch[:ln]),
|
46
|
+
"No package name given, using directory name.")
|
47
|
+
# use directory name as project name
|
48
|
+
name = File.split(Dir.pwd)[1]
|
49
|
+
# reset name if it contains a slash or a backslash
|
50
|
+
name = nil if name =~ /\/|\\/
|
51
|
+
end
|
52
|
+
@data = { "name" => name }
|
53
|
+
|
54
|
+
yield self if block_given?
|
55
|
+
end
|
56
|
+
|
57
|
+
def name
|
58
|
+
@data["name"]
|
59
|
+
end
|
60
|
+
|
61
|
+
def version
|
62
|
+
@data["version"]
|
63
|
+
end
|
64
|
+
|
65
|
+
def version=(str)
|
66
|
+
unless String === str
|
67
|
+
@rac.abort_at(@ch, "version has to be a String")
|
68
|
+
end
|
69
|
+
@data["version"] = str
|
70
|
+
end
|
71
|
+
|
72
|
+
def files
|
73
|
+
@data["files"]
|
74
|
+
end
|
75
|
+
|
76
|
+
def files=(list)
|
77
|
+
unless Array === list || ::Rant::FileList === List
|
78
|
+
if list.respond_to? :to_ary
|
79
|
+
list = list.to_ary
|
80
|
+
else
|
81
|
+
@rac.abort_at(@ch,
|
82
|
+
"files must be an Array or FileList")
|
83
|
+
end
|
84
|
+
end
|
85
|
+
@data["files"] = list
|
86
|
+
end
|
87
|
+
|
88
|
+
def validate_attrs(pkg_type = :general)
|
89
|
+
%w(name files).each { |a|
|
90
|
+
pkg_requires_attr a
|
91
|
+
}
|
92
|
+
end
|
93
|
+
private :validate_attrs
|
94
|
+
|
95
|
+
def pkg_requires_attr(attr_name)
|
96
|
+
unless @data[attr_name]
|
97
|
+
@rac.abort("Packaged defined: " +
|
98
|
+
@rac.pos_text(@ch[:file], @ch[:ln]),
|
99
|
+
"`#{attr_name}' attribute required")
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def pkg_dir_task
|
104
|
+
return if @pkg_dir_task
|
105
|
+
if @dist_dir_task
|
106
|
+
# not ideal but should work: If only the gem task will
|
107
|
+
# be run, dist dir creation wouldn't be necessary
|
108
|
+
return @pkg_dir_task = @dist_dir_task
|
109
|
+
end
|
110
|
+
@pkg_dir_task = @rac.gen(
|
111
|
+
::Rant::Generators::Directory, @pkg_dir)
|
112
|
+
end
|
113
|
+
|
114
|
+
def dist_dir_task
|
115
|
+
return if @dist_dir_task
|
116
|
+
pkg_name = pkg_dist_dir
|
117
|
+
dist_dir = pkg_dist_dir
|
118
|
+
@dist_dir_task = @rac.gen(Rant::Generators::Directory,
|
119
|
+
dist_dir => files) { |t|
|
120
|
+
# ensure to create new and empty destination directory
|
121
|
+
if Dir.entries(dist_dir).size > 2 # "." and ".."
|
122
|
+
@rac.sys.rm_rf(dist_dir)
|
123
|
+
@rac.sys.mkdir(dist_dir)
|
124
|
+
end
|
125
|
+
# evaluate directory structure first
|
126
|
+
dirs = []
|
127
|
+
fl = []
|
128
|
+
files.each { |e|
|
129
|
+
if test(?d, e)
|
130
|
+
dirs << e unless dirs.include? e
|
131
|
+
else # assuming e is a file
|
132
|
+
fl << e
|
133
|
+
dir = File.dirname(e)
|
134
|
+
dirs << dir unless dir == "." || dirs.include?(dir)
|
135
|
+
end
|
136
|
+
}
|
137
|
+
# create directory structure
|
138
|
+
dirs.each { |dir|
|
139
|
+
dest = File.join(dist_dir, dir)
|
140
|
+
@rac.sys.mkpath(dest) unless test(?d, dest)
|
141
|
+
}
|
142
|
+
# link or copy files
|
143
|
+
fl.each { |f|
|
144
|
+
dest = File.join(dist_dir, f)
|
145
|
+
@rac.sys.safe_ln(f, dest)
|
146
|
+
}
|
147
|
+
}
|
148
|
+
end
|
149
|
+
|
150
|
+
def tar_task(tname = :tar)
|
151
|
+
validate_attrs
|
152
|
+
# Create tar task first to ensure that a pending description
|
153
|
+
# is used for the tar task and not for the dist dir task.
|
154
|
+
pkg_name = tar_pkg_path
|
155
|
+
pkg_files = files
|
156
|
+
if tname
|
157
|
+
# shortcut task
|
158
|
+
@rac.task({:__caller__ => @ch, tname => pkg_name})
|
159
|
+
end
|
160
|
+
# actual tar-creating task
|
161
|
+
@tar_task = @rac.file(:__caller__ => @ch,
|
162
|
+
pkg_name => [pkg_dist_dir] + pkg_files) { |t|
|
163
|
+
@rac.sys.cd(@pkg_dir) {
|
164
|
+
@rac.sys %W(tar zcf #{tar_pkg_name} #{pkg_base_name})
|
165
|
+
}
|
166
|
+
}
|
167
|
+
dist_dir_task
|
168
|
+
end
|
169
|
+
|
170
|
+
def zip_task(tname = :zip)
|
171
|
+
validate_attrs
|
172
|
+
# Create zip task first to ensure that a pending description
|
173
|
+
# is used for the zip task and not for the dist dir task.
|
174
|
+
pkg_name = zip_pkg_path
|
175
|
+
pkg_files = files
|
176
|
+
if tname
|
177
|
+
# shortcut task
|
178
|
+
@rac.task({:__caller__ => @ch, tname => pkg_name})
|
179
|
+
end
|
180
|
+
# actual zip-creating task
|
181
|
+
@zip_task = @rac.file(:__caller__ => @ch,
|
182
|
+
pkg_name => [pkg_dist_dir] + pkg_files) { |t|
|
183
|
+
@rac.sys.cd(@pkg_dir) {
|
184
|
+
# zip options:
|
185
|
+
# y: store symlinks instead of referenced files
|
186
|
+
# r: recurse into directories
|
187
|
+
# q: quiet operation
|
188
|
+
@rac.sys %W(zip -yqr #{zip_pkg_name} #{pkg_base_name})
|
189
|
+
}
|
190
|
+
}
|
191
|
+
dist_dir_task
|
192
|
+
end
|
193
|
+
|
194
|
+
# Create a task which runs gem/zip/tar tasks.
|
195
|
+
def package_task(tname = :package)
|
196
|
+
def_tasks = [@tar_task, @zip_task].compact
|
197
|
+
if def_tasks.empty?
|
198
|
+
# take description for overall package task
|
199
|
+
pdesc = @rac.pop_desc
|
200
|
+
unless def_available_tasks
|
201
|
+
@rac.desc pdesc
|
202
|
+
@rac.warn_msg("No tools for packaging available (tar, zip):",
|
203
|
+
"Can't generate task `#{tname}'.")
|
204
|
+
return
|
205
|
+
end
|
206
|
+
@rac.desc pdesc
|
207
|
+
end
|
208
|
+
pre = []
|
209
|
+
pre << tar_pkg_path if @tar_task
|
210
|
+
pre << zip_pkg_path if @zip_task
|
211
|
+
pre << gem_pkg_path if @gem_task
|
212
|
+
@rac.task(:__caller__ => @ch, tname => pre)
|
213
|
+
end
|
214
|
+
|
215
|
+
# Returns true if at least one task was defined.
|
216
|
+
def def_available_tasks
|
217
|
+
defined = false
|
218
|
+
if Rant::Env.have_tar?
|
219
|
+
# we don't create shortcut tasks, hence nil as argument
|
220
|
+
self.tar_task(nil)
|
221
|
+
defined = true
|
222
|
+
end
|
223
|
+
if Rant::Env.have_zip?
|
224
|
+
self.zip_task(nil)
|
225
|
+
defined = true
|
226
|
+
end
|
227
|
+
defined
|
228
|
+
end
|
229
|
+
|
230
|
+
def pkg_base_name
|
231
|
+
unless name
|
232
|
+
@rac.abort(@rac.pos_text(@ch[:file], @ch[:ln]),
|
233
|
+
"`name' required for packaging")
|
234
|
+
end
|
235
|
+
version ? "#{name}-#{version}" : name
|
236
|
+
end
|
237
|
+
|
238
|
+
def tar_pkg_name
|
239
|
+
pkg_base_name + ".tar.gz"
|
240
|
+
end
|
241
|
+
|
242
|
+
def tar_pkg_path
|
243
|
+
pkg_dist_dir + ".tar.gz"
|
244
|
+
end
|
245
|
+
|
246
|
+
def zip_pkg_name
|
247
|
+
pkg_base_name + ".zip"
|
248
|
+
end
|
249
|
+
|
250
|
+
def zip_pkg_path
|
251
|
+
pkg_dist_dir + ".zip"
|
252
|
+
end
|
253
|
+
|
254
|
+
def pkg_dist_dir
|
255
|
+
@pkg_dir ? File.join(@pkg_dir, pkg_base_name) : pkg_base_name
|
256
|
+
end
|
257
|
+
|
258
|
+
end # class Rant::Generators::Package
|