Class: Buildr::ArchiveTask

Inherits:
Rake::FileTask show all
Defined in:
lib/buildr/packaging/archive.rb

Overview

Base class for ZipTask, TarTask and other archives.

Direct Known Subclasses

PackageGemTask, TarTask, ZipTask

Defined Under Namespace

Classes: Merge, Path, ZipExpander

Instance Method Summary collapse

Methods inherited from Rake::FileTask

#exist?

Constructor Details

#initialize(*args) ⇒ ArchiveTask

:nodoc:



274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
# File 'lib/buildr/packaging/archive.rb', line 274

def initialize(*args) #:nodoc:
  super
  clean

  # Make sure we're the last enhancements, so other enhancements can add content.
  enhance do
    @file_map = {}
    enhance do
      send 'create' if respond_to?(:create)
      # We're here because the archive file does not exist, or one of the files is newer than the archive contents;
      # we need to make sure the archive doesn't exist (e.g. opening an existing Zip will add instead of create).
      # We also want to protect against partial updates.
      rm name rescue nil
      mkpath File.dirname(name)
      begin
        @paths.each do |name, object|
          @file_map[name] = nil unless name.empty?
          object.add_files(@file_map)
        end
        create_from @file_map
      rescue
        rm name rescue nil
        raise
      end
    end
  end
end

Instance Method Details

#cleanObject

:call-seq:

clean => self

Removes all previously added content from this archive. Use this method if you want to remove default content from a package. For example, package(:jar) by default includes compiled classes and resources, using this method, you can create an empty jar and afterwards add the desired content to it.

package(:jar).clean.include path_to('desired/content')


312
313
314
315
316
# File 'lib/buildr/packaging/archive.rb', line 312

def clean
  @paths = { '' => Path.new(self, '') }
  @prepares = []
  self
end

#contain?(*files) ⇒ Boolean

:call-seq:

contain(file*) => boolean

Returns true if this ZIP file contains all the specified files. You can use absolute file names and glob patterns (using *, **, etc).

Returns:

  • (Boolean)


470
471
472
# File 'lib/buildr/packaging/archive.rb', line 470

def contain?(*files)
  path("").contain?(*files)
end

#empty?Boolean

:call-seq:

empty? => boolean

Returns true if this ZIP file is empty (has no other entries inside).

Returns:

  • (Boolean)


461
462
463
# File 'lib/buildr/packaging/archive.rb', line 461

def empty?
  path("").empty
end

#exclude(*files) ⇒ Object

:call-seq:

exclude(*files) => self

Excludes files and returns self. Can be used in combination with include to prevent some files from being included.



362
363
364
365
# File 'lib/buildr/packaging/archive.rb', line 362

def exclude(*files)
  @paths[''].exclude *files
  self
end

#include(*files) ⇒ Object Also known as: add, <<

:call-seq:

include(*files) => self
include(*files, :path=>path) => self
include(file, :as=>name) => self
include(:from=>path) => self
include(*files, :merge=>true) => self

Include files in this archive, or when called on a path, within that path. Returns self.

The first form accepts a list of files, directories and glob patterns and adds them to the archive. For example, to include the file foo, directory bar (including all files in there) and all files under baz:

zip(..).include('foo', 'bar', 'baz/*')

The second form is similar but adds files/directories under the specified path. For example, to add foo as bar/foo:

zip(..).include('foo', :path=>'bar')

The :path option is the same as using the path method:

zip(..).path('bar').include('foo')

All other options can be used in combination with the :path option.

The third form adds a file or directory under a different name. For example, to add the file foo under the name bar:

zip(..).include('foo', :as=>'bar')

The fourth form adds the contents of a directory using the directory as a prerequisite:

zip(..).include(:from=>'foo')

Unlike include('foo') it includes the contents of the directory, not the directory itself. Unlike include('foo/*'), it uses the directory timestamp for dependency management.

The fifth form includes the contents of another archive by expanding it into this archive. For example:

zip(..).include('foo.zip', :merge=>true).include('bar.zip')

You can also use the method #merge.



350
351
352
353
354
# File 'lib/buildr/packaging/archive.rb', line 350

def include(*files)
  fail "AchiveTask.include() called with nil values" if files.include? nil
  @paths[''].include *files if files.compact.size > 0
  self
end

#invoke_prerequisites(args, chain) ⇒ Object

:nodoc:



433
434
435
436
437
438
# File 'lib/buildr/packaging/archive.rb', line 433

def invoke_prerequisites(args, chain) #:nodoc:
  @prepares.each { |prepare| prepare.call(self) }
  @prepares.clear
  @prerequisites |= @paths.collect { |name, path| path.sources }.flatten
  super
end

#merge(*files) ⇒ Object

:call-seq:

merge(*files) => Merge
merge(*files, :path=>name) => Merge

Merges another archive into this one by including the individual files from the merged archive.

Returns an object that supports two methods: include and exclude. You can use these methods to merge only specific files. For example:

zip(..).merge('src.zip').include('module1/*')


376
377
378
# File 'lib/buildr/packaging/archive.rb', line 376

def merge(*files)
  @paths[''].merge *files
end

#needed?Boolean

:nodoc:

Returns:

  • (Boolean)


440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
# File 'lib/buildr/packaging/archive.rb', line 440

def needed? #:nodoc:
  return true unless File.exist?(name)
  # You can do something like:
  #   include('foo', :path=>'foo').exclude('foo/bar', path=>'foo').
  #     include('foo/bar', :path=>'foo/bar')
  # This will play havoc if we handled all the prerequisites together
  # under the task, so instead we handle them individually for each path.
  #
  # We need to check that any file we include is not newer than the
  # contents of the Zip. The file itself but also the directory it's
  # coming from, since some tasks touch the directory, e.g. when the
  # content of target/classes is included into a WAR.
  most_recent = @paths.collect { |name, path| path.sources }.flatten.
    select { |file| File.exist?(file) }.collect { |file| File.stat(file).mtime }.max
  File.stat(name).mtime < (most_recent || Rake::EARLY) || super
end

#path(name) ⇒ Object

:call-seq:

path(name) => Path

Returns a path object. Use the path object to include files under a path, for example, to include the file ‘foo’ as ‘bar/foo’:

zip(..).path('bar').include('foo')

Returns a Path object. The Path object implements all the same methods, like include, exclude, merge and so forth. It also implements path and root, so that:

path('foo').path('bar') == path('foo/bar')
path('foo').root == root


391
392
393
394
395
396
397
398
399
400
401
402
403
404
# File 'lib/buildr/packaging/archive.rb', line 391

def path(name)
  return @paths[''] if name.nil?
  normalized = name.split('/').inject([]) do |path, part|
    case part
    when '.', nil, ''
      path
    when '..'
      path[0...-1]
    else
      path << part
    end
  end.join('/')
  @paths[normalized] ||= Path.new(self, normalized)
end

#rootObject

:call-seq:

root => ArchiveTask

Call this on an archive to return itself, and on a path to return the archive.



410
411
412
# File 'lib/buildr/packaging/archive.rb', line 410

def root
  self
end

#with(options) ⇒ Object

:call-seq:

with(options) => self

Passes options to the task and returns self. Some tasks support additional options, for example, the WarTask supports options like :manifest, :libs and :classes.

For example:

package(:jar).with(:manifest=>'MANIFEST_MF')


422
423
424
425
426
427
428
429
430
431
# File 'lib/buildr/packaging/archive.rb', line 422

def with(options)
  options.each do |key, value|
    begin
      send "#{key}=", value
    rescue NoMethodError
      raise ArgumentError, "#{self.class.name} does not support the option #{key}"
    end
  end
  self
end