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:



272
273
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
# File 'lib/buildr/packaging/archive.rb', line 272

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, :verbose=>false rescue nil
      mkpath File.dirname(name), :verbose=>false
      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, :verbose=>false 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')


310
311
312
313
314
# File 'lib/buildr/packaging/archive.rb', line 310

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)


467
468
469
# File 'lib/buildr/packaging/archive.rb', line 467

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)


458
459
460
# File 'lib/buildr/packaging/archive.rb', line 458

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.



359
360
361
362
# File 'lib/buildr/packaging/archive.rb', line 359

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.



348
349
350
351
# File 'lib/buildr/packaging/archive.rb', line 348

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

#invoke_prerequisites(args, chain) ⇒ Object

:nodoc:



430
431
432
433
434
435
# File 'lib/buildr/packaging/archive.rb', line 430

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


373
374
375
# File 'lib/buildr/packaging/archive.rb', line 373

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

#needed?Boolean

:nodoc:

Returns:

  • (Boolean)


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

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


388
389
390
391
392
393
394
395
396
397
398
399
400
401
# File 'lib/buildr/packaging/archive.rb', line 388

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.



407
408
409
# File 'lib/buildr/packaging/archive.rb', line 407

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


419
420
421
422
423
424
425
426
427
428
# File 'lib/buildr/packaging/archive.rb', line 419

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