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, ZipEntryData, ZipExpander

Instance Method Summary collapse

Methods inherited from Rake::FileTask

#exist?

Constructor Details

#initialize(*args) ⇒ ArchiveTask

:nodoc:



358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
# File 'lib/buildr/packaging/archive.rb', line 358

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

  # Make sure we're the last enhancements, so other enhancements can add content.
  enhance do
    @file_map = Hash.new {|h,k| h[k]=[]}
    @transform_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, @transform_map)
        end
        create_from @file_map, @transform_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')


397
398
399
400
401
402
# File 'lib/buildr/packaging/archive.rb', line 397

def clean
  @paths = {}
  @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)


565
566
567
# File 'lib/buildr/packaging/archive.rb', line 565

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)


556
557
558
# File 'lib/buildr/packaging/archive.rb', line 556

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.



448
449
450
451
# File 'lib/buildr/packaging/archive.rb', line 448

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.



436
437
438
439
440
# File 'lib/buildr/packaging/archive.rb', line 436

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:



519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
# File 'lib/buildr/packaging/archive.rb', line 519

def invoke_prerequisites(args, chain) #:nodoc:
  @prepares.each { |prepare| prepare.call(self) }
  @prepares.clear

  file_map = Hash.new {|h,k| h[k]=[]}
  transform_map = {}
  @paths.each do |name, path|
    path.add_files(file_map, transform_map)
  end

  # filter out Procs (dynamic content), nils and others
  @prerequisites |= file_map.values.select { |src| src.is_a?(String) || src.is_a?(Rake::Task) }

  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/*')


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

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

#needed?Boolean

:nodoc:

Returns:

  • (Boolean)


535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
# File 'lib/buildr/packaging/archive.rb', line 535

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


477
478
479
480
481
482
483
484
485
486
487
488
489
490
# File 'lib/buildr/packaging/archive.rb', line 477

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.



496
497
498
# File 'lib/buildr/packaging/archive.rb', line 496

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')


508
509
510
511
512
513
514
515
516
517
# File 'lib/buildr/packaging/archive.rb', line 508

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