rant 0.3.8 → 0.4.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 (55) hide show
  1. data/NEWS +19 -0
  2. data/README +51 -24
  3. data/Rantfile +7 -8
  4. data/doc/advanced.rdoc +3 -1
  5. data/doc/package.rdoc +280 -0
  6. data/doc/rantfile.rdoc +9 -19
  7. data/doc/rubyproject.rdoc +24 -16
  8. data/lib/rant/archive/minitar.rb +983 -0
  9. data/lib/rant/archive/rubyzip/ioextras.rb +122 -0
  10. data/lib/rant/archive/rubyzip/stdrubyext.rb +114 -0
  11. data/lib/rant/archive/rubyzip/tempfile_bugfixed.rb +195 -0
  12. data/lib/rant/archive/rubyzip.rb +1575 -0
  13. data/lib/rant/import/archive/tgz.rb +49 -0
  14. data/lib/rant/import/archive/zip.rb +67 -0
  15. data/lib/rant/import/archive.rb +312 -0
  16. data/lib/rant/import/autoclean.rb +2 -2
  17. data/lib/rant/import/c/dependencies.rb +3 -3
  18. data/lib/rant/import/clean.rb +1 -1
  19. data/lib/rant/import/directedrule.rb +1 -1
  20. data/lib/rant/import/package/tgz.rb +35 -0
  21. data/lib/rant/import/package/zip.rb +36 -0
  22. data/lib/rant/import/rubydoc.rb +1 -1
  23. data/lib/rant/import/rubypackage.rb +19 -77
  24. data/lib/rant/import/rubytest.rb +1 -1
  25. data/lib/rant/import/subfile.rb +28 -14
  26. data/lib/rant/import/win32/rubycmdwrapper.rb +1 -1
  27. data/lib/rant/import.rb +36 -16
  28. data/lib/rant/plugin/csharp.rb +1 -1
  29. data/lib/rant/rantenv.rb +2 -13
  30. data/lib/rant/rantfile.rb +11 -11
  31. data/lib/rant/rantlib.rb +7 -3
  32. data/lib/rant/rantsys.rb +53 -2
  33. data/lib/rant/rantvar.rb +62 -1
  34. data/misc/TODO +41 -0
  35. data/{devel-notes → misc/devel-notes} +6 -0
  36. data/misc/mt.rb +3 -0
  37. data/misc/t.rb +18 -0
  38. data/test/import/c/dependencies/test_c_dependencies.rb +18 -0
  39. data/test/import/package/MANIFEST +4 -0
  40. data/test/import/package/Rantfile +49 -0
  41. data/test/import/package/deep/sub/sub/f1 +1 -0
  42. data/test/import/package/sub/f1 +1 -0
  43. data/test/import/package/sub2/f1 +1 -0
  44. data/test/import/package/test_package.rb +425 -0
  45. data/test/import/subfile/Rantfile +8 -0
  46. data/test/import/subfile/test_subfile.rb +12 -0
  47. data/test/project_rb1/rantfile.rb +3 -4
  48. data/test/project_rb1/test_project_rb1.rb +16 -40
  49. data/test/rant-import/test_rant-import.rb +3 -3
  50. data/test/test_filelist.rb +39 -2
  51. data/test/tutil.rb +89 -3
  52. metadata +35 -6
  53. data/TODO +0 -21
  54. data/lib/rant/import/package.rb +0 -258
  55. /data/{rantmethods.rb → misc/rantmethods.rb} +0 -0
@@ -0,0 +1,49 @@
1
+
2
+ # tgz.rb - Archive::Tgz generator for Rant.
3
+ #
4
+ # Copyright (C) 2005 Stefan Lang <langstefan@gmx.at>
5
+
6
+ require 'rant/import/archive'
7
+ #require 'rant/archive/minitar' #rant-import:uncomment
8
+
9
+ module Rant::Generators::Archive
10
+ # Use this class as a generator to create gzip compressed tar
11
+ # archives.
12
+ class Tgz < Base
13
+ def initialize(*args)
14
+ super
15
+ @extension = ".tgz"
16
+ end
17
+ # Ensure to set #rac first.
18
+ # Creates a file task wich invokes tar to create a tgz
19
+ # archive. Returns the created task.
20
+ def define_task
21
+ if ::Rant::Env.have_tar?
22
+ define_tar_task
23
+ else
24
+ define_minitar_task
25
+ end
26
+ end
27
+ private
28
+ def define_tar_task
29
+ define_cmd_task { |path, t|
30
+ @rac.cx.sys "tar -h --no-recursion --files-from #{path} -czf #{t.name}"
31
+ }
32
+ end
33
+ def define_minitar_task
34
+ define_cmd_task do |path, t|
35
+ minitar_tgz t.name, @res_files
36
+ end
37
+ end
38
+ def minitar_tgz fn, files, opts = {:recurse => false}
39
+ require 'zlib'
40
+ require 'rant/archive/minitar'
41
+ @rac.cmd_msg "minitar #{fn}"
42
+ files = files.to_ary if files.respond_to? :to_ary
43
+ tgz = Zlib::GzipWriter.new(File.open(fn, 'wb'))
44
+ # pack closes tgz
45
+ Rant::Archive::Minitar.pack(files, tgz, opts[:recurse])
46
+ nil
47
+ end
48
+ end # class Tgz
49
+ end # module Rant::Generators::Archive
@@ -0,0 +1,67 @@
1
+
2
+ # zip.rb - Archive::Zip generator for Rant.
3
+ #
4
+ # Copyright (C) 2005 Stefan Lang <langstefan@gmx.at>
5
+
6
+ require 'rant/import/archive'
7
+ #require 'rant/archive/rubyzip' #rant-import:uncomment
8
+
9
+ module Rant::Generators::Archive
10
+ # Use this class as a generator to create zip archives.
11
+ class Zip < Base
12
+ def initialize(*args)
13
+ super
14
+ @extension = ".zip"
15
+ end
16
+ # Ensure to set #rac first.
17
+ # Creates a file task wich invokes zip to create a zip
18
+ # archive. Returns the created task.
19
+ def define_task
20
+ if ::Rant::Env.have_zip?
21
+ define_zip_task
22
+ else
23
+ define_rubyzip_task
24
+ end
25
+ end
26
+ def define_zip_task
27
+ define_cmd_task { |path, t|
28
+ # Add -y option to store symlinks instead of
29
+ # referenced files.
30
+ cmd = "zip -@q #{t.name}"
31
+ @rac.cmd_msg cmd
32
+ IO.popen cmd, "w" do |z|
33
+ z.print IO.read(path)
34
+ end
35
+ raise Rant::CommandError.new(cmd, $?) unless $?.success?
36
+ }
37
+ end
38
+ def define_rubyzip_task
39
+ define_cmd_task do |path, t|
40
+ rubyzip t.name, @res_files
41
+ end
42
+ end
43
+ def rubyzip fn, files, opts = {:recurse => false}
44
+ require 'rant/archive/rubyzip'
45
+ @rac.cmd_msg "rubyzip #{fn}"
46
+ Rant::Archive::Rubyzip::ZipFile.open fn,
47
+ Rant::Archive::Rubyzip::ZipFile::CREATE do |z|
48
+ if opts[:recurse]
49
+ require 'find'
50
+ files.each { |f|
51
+ if test ?d, f
52
+ Find.find(f) { |f2| z.add f2, f2 }
53
+ else
54
+ z.add f, f
55
+ end
56
+ }
57
+ else
58
+ files.each { |f|
59
+ z.add f, f
60
+ }
61
+ end
62
+ end
63
+ nil
64
+ end
65
+
66
+ end # class Zip
67
+ end # module Rant::Generators::Archive
@@ -0,0 +1,312 @@
1
+
2
+ # archive.rb - Archiving support for Rant.
3
+ #
4
+ # Copyright (C) 2005 Stefan Lang <langstefan@gmx.at>
5
+ #
6
+ # This file currently doesn't contain a generator. Thus an <tt>import
7
+ # "archive"</tt> doesn't make sense. Do an <tt>import
8
+ # "archive/tgz"</tt> or <tt>import "archive/zip"</tt> instead.
9
+
10
+ require 'rant/rantlib'
11
+ require 'rant/import/subfile'
12
+
13
+ module Rant::Generators::Archive
14
+ # A subclass has to provide a +define_task+ method to act as a
15
+ # generator.
16
+ class Base
17
+ extend Rant::MetaUtils
18
+
19
+ def self.rant_gen(rac, ch, args, &block)
20
+ pkg_name = args.shift
21
+ unless pkg_name
22
+ rac.abort_at(ch,
23
+ "#{self} takes at least one argument (package name)")
24
+ end
25
+ opts = nil
26
+ flags = []
27
+ arg = args.shift
28
+ case arg
29
+ when String
30
+ basedir = pkg_name
31
+ pkg_name = arg
32
+ when Symbol
33
+ flags << arg
34
+ else
35
+ opts = arg
36
+ end
37
+ flags << arg while Symbol === (arg = args.shift)
38
+ opts ||= (arg || {})
39
+ unless args.empty?
40
+ rac.abort_at(ch, "#{self}: too many arguments")
41
+ end
42
+
43
+ pkg = self.new(pkg_name)
44
+ pkg.basedir = basedir if basedir
45
+ pkg.rac = rac
46
+ pkg.ch = ch
47
+ flags.each { |f|
48
+ case f
49
+ when :manifest
50
+ pkg.manifest = "MANIFEST"
51
+ when :verbose
52
+ # TODO
53
+ when :quiet
54
+ # TODO
55
+ else
56
+ rac.warn_msg(
57
+ "#{self}: ignoring unknown flag #{flag}")
58
+ end
59
+ }
60
+ if opts.respond_to? :to_hash
61
+ opts = opts.to_hash
62
+ else
63
+ rac.abort_at(ch,
64
+ "#{self}: option argument has to be a hash.")
65
+ end
66
+ opts.each { |k, v|
67
+ case k
68
+ when :version
69
+ pkg.version = v
70
+ when :extension
71
+ pkg.extension = v
72
+ when :files
73
+ pkg.files = v
74
+ when :manifest
75
+ pkg.manifest = v
76
+ when :files_only
77
+ pkg.files_only = v
78
+ else
79
+ rac.warn_msg(
80
+ "#{self}: ignoring unknown option #{k}")
81
+ end
82
+ }
83
+ desc = pkg.rac.pop_desc
84
+ pkg.define_manifest_task if opts[:files] && opts[:manifest]
85
+ pkg.rac.cx.desc desc
86
+ pkg.define_task
87
+ pkg
88
+ end
89
+
90
+ string_attr :name
91
+ string_attr :version
92
+ string_attr :basedir
93
+ string_attr :extension
94
+ rant_attr :files
95
+ string_attr :manifest
96
+ attr_reader :archive_path
97
+ # If this is true, directories won't be included for packaging
98
+ # (only files). Defaults to true.
99
+ rant_attr :files_only
100
+ # Caller information, e.g.: {:file => "Rantfile", :ln => 10}
101
+ attr_accessor :ch
102
+
103
+ def initialize(name, files = nil)
104
+ self.name = name or raise "package name required"
105
+ @files = files
106
+ @version, @extension, @archive_path = nil
107
+ @rac = nil
108
+ @pkg_task = nil
109
+ @ch = nil
110
+ @files_only = false
111
+ @manifest_task = nil
112
+ @basedir = nil
113
+ @res_files = nil
114
+ @manifest = nil
115
+ @dist_dir_task = nil
116
+ end
117
+
118
+ def rac
119
+ @rac
120
+ end
121
+ def rac=(val)
122
+ @rac = val
123
+ @pkg_task = nil
124
+ end
125
+
126
+ # Path to archive file.
127
+ def path
128
+ if basedir
129
+ File.join(basedir, get_archive_path)
130
+ else
131
+ get_archive_path
132
+ end
133
+ end
134
+
135
+ # Path to archive without basedir.
136
+ def get_archive_path
137
+ return @archive_path if @archive_path
138
+ path = name.dup
139
+ path << "-#@version" if @version
140
+ path << @extension if @extension
141
+ @archive_path = path
142
+ end
143
+
144
+ # This method sets @res_files to the return value, a list of
145
+ # files to include in the archive.
146
+ def get_files
147
+ return @res_files if @res_files
148
+ fl = @files ? @files.dup : []
149
+ if @manifest
150
+ fl = read_manifest unless @files
151
+ fl = Rant::RacFileList.filelist(@rac, fl)
152
+ fl << @manifest
153
+ elsif @files_only
154
+ fl = Rant::RacFileList.filelist(@rac, fl)
155
+ fl.no_dirs
156
+ else
157
+ fl = Rant::RacFileList.filelist(@rac, fl)
158
+ end
159
+ @res_files = fl.lazy_uniq!.lazy_sort!
160
+ end
161
+
162
+ # Creates an (eventually) temporary manifest file and yields
163
+ # with the path of this file as argument.
164
+ def with_manifest
165
+ fl = get_files
166
+ if @manifest
167
+ rac.make @manifest
168
+ yield @manifest
169
+ else
170
+ require 'tempfile'
171
+ tf = Tempfile.new "rant"
172
+ begin
173
+ fl.each { |path| tf.puts path }
174
+ tf.close
175
+ yield(tf.path)
176
+ ensure
177
+ tf.unlink
178
+ end
179
+ end
180
+ nil
181
+ end
182
+
183
+ def define_manifest_task
184
+ return @manifest_task if @manifest_task
185
+ @manifest_task =
186
+ @rac.gen ::Rant::Task, @manifest do |t|
187
+ def t.each_target
188
+ goto_task_home
189
+ yield name
190
+ end
191
+ t.needed {
192
+ # fl refers to @res_files
193
+ fl = get_files
194
+ if test ?f, @manifest
195
+ read_manifest != @res_files.to_ary
196
+ else
197
+ true
198
+ end
199
+ }
200
+ t.act {
201
+ write_manifest get_files
202
+ }
203
+ end
204
+ end
205
+
206
+ private
207
+ def read_manifest
208
+ fl = []
209
+ open @manifest do |f|
210
+ f.each { |line|
211
+ line.chomp!
212
+ fl << line unless line.strip.empty?
213
+ }
214
+ end
215
+ fl
216
+ end
217
+ def write_manifest fl
218
+ @rac.cmd_msg "writing #@manifest" if @rac
219
+ open @manifest, "w" do |f|
220
+ fl.each { |path| f.puts path }
221
+ end
222
+ end
223
+ def define_cmd_task
224
+ return @pkg_task if @pkg_task
225
+ targ = {get_archive_path => get_files}
226
+ @pkg_task =
227
+ ::Rant::Generators::SubFile.rant_gen(
228
+ @rac, @ch, [basedir, targ].compact) do |t|
229
+ with_manifest { |path| yield(path, t) }
230
+ end
231
+ end
232
+ # Define a task to package one dir. For usage in subclasses.
233
+ # This method sets the following instance variables:
234
+ # [@dist_dirname] The name of the directory which shall be
235
+ # the root of all entries in the archive.
236
+ # [@dist_root] The directory in which the @dist_dirname
237
+ # directory will be created with contents for
238
+ # archiving.
239
+ # [@dist_path] @dist_root/@dist_dirname (or just
240
+ # @dist_dirname if @dist_root is ".")
241
+ #
242
+ # The block supplied to this method will be the action
243
+ # to create the archive file (e.g. by invoking the tar
244
+ # command).
245
+ def define_task_for_dir(&block)
246
+ return @pkg_task if @pkg_task
247
+
248
+ get_files # set @res_files
249
+ @dist_dirname = File.split(name).last
250
+ @dist_dirname << "-#@version" if @version
251
+ @dist_root, = File.split path
252
+ @dist_path = (@dist_root == "." ?
253
+ @dist_dirname : File.join(@dist_root, @dist_dirname))
254
+
255
+ targ = {get_archive_path => [@dist_path]}
256
+ #STDERR.puts "basedir: #{basedir}, fn: #@archive_path"
257
+ @pkg_task = ::Rant::Generators::SubFile.rant_gen(
258
+ @rac, @ch, [basedir, targ].compact, &block)
259
+
260
+ define_dist_dir_task
261
+
262
+ @pkg_task
263
+ end
264
+
265
+ # This method sets the instance variable @dist_dir_task.
266
+ # Assumes that @res_files is set.
267
+ #
268
+ # Returns a task which creates the directory @dist_path and
269
+ # links/copies @res_files to @dist_path.
270
+ def define_dist_dir_task
271
+ return if @dist_dir_task
272
+ cx = @rac.cx
273
+ if @basedir
274
+ @basedir.sub!(/\/$/, '') if @basedir.length > 1
275
+ c_dir = @dist_path.sub(/^#@basedir\//, '')
276
+ targ = {c_dir => @res_files}
277
+ else
278
+ targ = {@dist_path => @res_files}
279
+ end
280
+ @dist_dir_task = Rant::Generators::Directory.rant_gen(
281
+ @rac, @ch, [@basedir, targ].compact) { |t|
282
+ # ensure to create new and empty destination directory
283
+ if Dir.entries(@dist_path).size > 2 # "." and ".."
284
+ cx.sys.rm_rf(@dist_path)
285
+ cx.sys.mkdir(@dist_path)
286
+ end
287
+ # evaluate directory structure first
288
+ dirs = []
289
+ fl = []
290
+ @res_files.each { |e|
291
+ if test(?d, e)
292
+ dirs << e unless dirs.include? e
293
+ else # assuming e is a file
294
+ fl << e
295
+ dir = File.dirname(e)
296
+ dirs << dir unless dir == "." || dirs.include?(dir)
297
+ end
298
+ }
299
+ # create directory structure
300
+ dirs.each { |dir|
301
+ dest = File.join(@dist_path, dir)
302
+ cx.sys.mkpath(dest) unless test(?d, dest)
303
+ }
304
+ # link or copy files
305
+ fl.each { |f|
306
+ dest = File.join(@dist_path, f)
307
+ cx.sys.safe_ln(f, dest)
308
+ }
309
+ }
310
+ end
311
+ end # class Base
312
+ end # module Rant::Generators::Archive
@@ -7,7 +7,7 @@ require 'rant/rantlib'
7
7
  require 'rant/import/clean'
8
8
 
9
9
  class Rant::Generators::AutoClean
10
- def self.rant_generate(rac, ch, args, &block)
10
+ def self.rant_gen(rac, ch, args, &block)
11
11
  # validate args
12
12
  if args.size > 1
13
13
  rac.abort_at(ch,
@@ -17,7 +17,7 @@ class Rant::Generators::AutoClean
17
17
 
18
18
  # we generate a normal clean task too, so that the user can
19
19
  # add files to clean via a var
20
- ::Rant::Generators::Clean.rant_generate(rac, ch, [tname])
20
+ ::Rant::Generators::Clean.rant_gen(rac, ch, [tname])
21
21
 
22
22
  # create task
23
23
  rac.task :__caller__ => ch, tname => [] do |t|
@@ -8,7 +8,7 @@ require 'rant/c/include'
8
8
 
9
9
  module Rant::Generators::C end
10
10
  class Rant::Generators::C::Dependencies
11
- def self.rant_generate(rac, ch, args, &block)
11
+ def self.rant_gen(rac, ch, args, &block)
12
12
  c_files, out_fn, include_pathes, opts = nil
13
13
  # args validation
14
14
  if block
@@ -121,7 +121,7 @@ class Rant::Generators::C::Dependencies
121
121
  nil
122
122
  end
123
123
  def self.file_deps(target, deps)
124
- s = "gen SourceNode, #{target.to_str.inspect} => "
125
- s << "[#{ deps.map{ |fn| fn.to_str.inspect }.join(', ')}]"
124
+ s = "gen SourceNode, #{target.to_str.dump} => "
125
+ s << "[#{ deps.map{ |fn| fn.to_str.dump }.join(', ')}]"
126
126
  end
127
127
  end # class Rant::Generators::C::Dependencies
@@ -6,7 +6,7 @@
6
6
  require 'rant/rantlib'
7
7
 
8
8
  class Rant::Generators::Clean
9
- def self.rant_generate(rac, ch, args, &block)
9
+ def self.rant_gen(rac, ch, args, &block)
10
10
  # validate args
11
11
  if args.size > 1
12
12
  rac.abort_at(ch, "Clean doesn't take more than one argument.")
@@ -6,7 +6,7 @@
6
6
  require 'rant/rantlib'
7
7
 
8
8
  class Rant::Generators::DirectedRule
9
- def self.rant_generate(rac, ch, args, &block)
9
+ def self.rant_gen(rac, ch, args, &block)
10
10
  unless args.size == 1
11
11
  rac.abort_at(ch, "DirectedRule takes one arguments.")
12
12
  end
@@ -0,0 +1,35 @@
1
+
2
+ # tgz.rb - Package::Tgz generator for Rant.
3
+ #
4
+ # Copyright (C) 2005 Stefan Lang <langstefan@gmx.at>
5
+
6
+ require 'rant/import/archive/tgz'
7
+
8
+ # The classes in this module act as generators which create archives.
9
+ # The difference to the Archive::* generators is, that the Package
10
+ # generators move all archive entries into a toplevel directory.
11
+ module Rant::Generators::Package
12
+ class Tgz < Rant::Generators::Archive::Tgz
13
+ def define_tar_task
14
+ define_task_for_dir do |t|
15
+ fn = @dist_dirname + (@extension ? @extension : "")
16
+ old_pwd = Dir.pwd
17
+ Dir.chdir @dist_root
18
+ @rac.cx.sys %W(tar zcf #{fn} #@dist_dirname)
19
+ Dir.chdir old_pwd
20
+ end
21
+ end
22
+ def define_minitar_task
23
+ define_task_for_dir do
24
+ fn = @dist_dirname + (@extension ? @extension : "")
25
+ old_pwd = Dir.pwd
26
+ begin
27
+ Dir.chdir @dist_root
28
+ minitar_tgz fn, @dist_dirname, :recurse => true
29
+ ensure
30
+ Dir.chdir old_pwd
31
+ end
32
+ end
33
+ end
34
+ end # class Tgz
35
+ end # module Rant::Generators::Package
@@ -0,0 +1,36 @@
1
+
2
+ # zip.rb - Package::Zip generator for Rant.
3
+ #
4
+ # Copyright (C) 2005 Stefan Lang <langstefan@gmx.at>
5
+
6
+ require 'rant/import/archive/zip'
7
+
8
+ module Rant::Generators::Package
9
+ class Zip < Rant::Generators::Archive::Zip
10
+ def define_zip_task
11
+ define_task_for_dir do
12
+ fn = @dist_dirname + (@extension ? @extension : "")
13
+ old_pwd = Dir.pwd
14
+ Dir.chdir @dist_root
15
+ # zip options:
16
+ # y: store symlinks instead of referenced files
17
+ # r: recurse into directories
18
+ # q: quiet operation
19
+ @rac.cx.sys %W(zip -yqr #{fn} #@dist_dirname)
20
+ Dir.chdir old_pwd
21
+ end
22
+ end
23
+ def define_rubyzip_task
24
+ define_task_for_dir do
25
+ fn = @dist_dirname + (@extension ? @extension : "")
26
+ old_pwd = Dir.pwd
27
+ begin
28
+ Dir.chdir @dist_root
29
+ rubyzip fn, @dist_dirname, :recurse => true
30
+ ensure
31
+ Dir.chdir old_pwd
32
+ end
33
+ end
34
+ end
35
+ end # class Zip
36
+ end # module Rant::Generators::Package
@@ -6,7 +6,7 @@ module Rant
6
6
 
7
7
  class << self
8
8
 
9
- def rant_generate(app, ch, args, &block)
9
+ def rant_gen(app, ch, args, &block)
10
10
  if !args || args.empty?
11
11
  self.new(app, ch, &block)
12
12
  elsif args.size == 1