rant 0.3.4 → 0.3.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|