rant 0.3.8 → 0.4.0

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