Class: Buildr::Unzip

Inherits:
Object show all
Defined in:
lib/buildr/packaging/ziptask.rb

Overview

An object for unzipping/untarring a file into a target directory. You can tell it to include or exclude only specific files and directories, and also to map files from particular paths inside the zip file into the target directory. Once ready, call #extract.

Usually it is more convenient to create a file task for extracting the zip file (see #unzip) and pass this object as a prerequisite to other tasks.

See Buildr#unzip.

Defined Under Namespace

Classes: FromPath

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(args) ⇒ Unzip

Initialize with hash argument of the form target=>zip_file.



158
159
160
161
162
# File 'lib/buildr/packaging/ziptask.rb', line 158

def initialize(args)
  @target, arg_names, zip_file = Buildr.application.resolve_args([args])
  @zip_file = zip_file.first
  @paths = {}
end

Instance Attribute Details

#targetObject

The target directory to extract to.



155
156
157
# File 'lib/buildr/packaging/ziptask.rb', line 155

def target
  @target
end

#zip_fileObject

The zip file to extract.



153
154
155
# File 'lib/buildr/packaging/ziptask.rb', line 153

def zip_file
  @zip_file
end

Instance Method Details

#exclude(*files) ⇒ Object

:call-seq:

exclude(*files) => self

Exclude all files that match the patterns and return self.

Use exclude to unzip all files except those that match the pattern. You can use #exclude in combination with #include.



265
266
267
268
269
270
271
272
# File 'lib/buildr/packaging/ziptask.rb', line 265

def exclude(*files)
  if Hash === files.last
    from_path(files.pop[:path]).exclude *files
  else
    from_path(nil).exclude *files
  end
  self
end

#extractObject

:call-seq:

extract

Extract the zip/tgz file into the target directory.

You can call this method directly. However, if you are using the #unzip method, it creates a file task for the target directory: use that task instead as a prerequisite. For example:

build unzip(dir=>zip_file)

Or:

unzip(dir=>zip_file).target.invoke


175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
# File 'lib/buildr/packaging/ziptask.rb', line 175

def extract
  # If no paths specified, then no include/exclude patterns
  # specified. Nothing will happen unless we include all files.
  if @paths.empty?
    @paths[nil] = FromPath.new(self, nil)
  end

  # Otherwise, empty unzip creates target as a file when touching.
  mkpath target.to_s
  if zip_file.to_s.match /\.t?gz$/
    #un-tar.gz
    Zlib::GzipReader.open(zip_file.to_s) { |tar|
      Archive::Tar::Minitar::Input.open(tar) do |inp|
        inp.each do |tar_entry|
          @paths.each do |path, patterns|
            patterns.map([tar_entry]).each do |dest, entry|
              next if entry.directory?
              dest = File.expand_path(dest, target.to_s)
              trace "Extracting #{dest}"
              mkpath File.dirname(dest) rescue nil
              File.open(dest, 'wb', entry.mode) {|f| f.write entry.read}
              File.chmod(entry.mode, dest)
            end
          end
        end
      end
    }
  else
    Zip::File.open(zip_file.to_s) do |zip|
      entries = zip.collect
      @paths.each do |path, patterns|
        patterns.map(entries).each do |dest, entry|
          next if entry.directory?
          dest = File.expand_path(dest, target.to_s)
          trace "Extracting #{dest}"
          mkpath File.dirname(dest) rescue nil
          entry.restore_permissions = true
          entry.extract(dest) { true }
        end
      end
    end
  end
  # Let other tasks know we updated the target directory.
  touch target.to_s
end

#from_path(name) ⇒ Object Also known as: path

:call-seq:

from_path(name) => Path

Allows you to unzip from a path. Returns an object you can use to specify which files to include/exclude relative to that path. Expands the file relative to that path.

For example:

unzip(Dir.pwd=>'test.jar').from_path('etc').include('LICENSE')

will unzip etc/LICENSE into ./LICENSE.

This is different from:

unzip(Dir.pwd=>'test.jar').include('etc/LICENSE')

which unzips etc/LICENSE into ./etc/LICENSE.



288
289
290
# File 'lib/buildr/packaging/ziptask.rb', line 288

def from_path(name)
  @paths[name] ||= FromPath.new(self, name)
end

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

:call-seq:

include(*files) => self
include(*files, :path=>name) => self

Include all files that match the patterns and returns self.

Use include if you only want to unzip some of the files, by specifying them instead of using exclusion. You can use #include in combination with #exclude.



248
249
250
251
252
253
254
255
# File 'lib/buildr/packaging/ziptask.rb', line 248

def include(*files)
  if Hash === files.last
    from_path(files.pop[:path]).include *files
  else
    from_path(nil).include *files
  end
  self
end

#included?(entry_name) ⇒ Boolean

reads the includes/excludes and apply them to the entry_name

Returns:

  • (Boolean)


222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
# File 'lib/buildr/packaging/ziptask.rb', line 222

def included?(entry_name)
  @paths.each do |path, patterns|
    return true if path.nil?
    if entry_name =~ /^#{path}/
      short = entry_name.sub(path, '')
      if patterns.include.any? { |pattern| File.fnmatch(pattern, entry_name) } &&
        !patterns.exclude.any? { |pattern| File.fnmatch(pattern, entry_name) }
        # trace "tar_entry.full_name " + entry_name + " is included"
        return true
      end
    end
  end
  # trace "tar_entry.full_name " + entry_name + " is excluded"
  return false
end

#rootObject

:call-seq:

root => Unzip

Returns the root path, essentially the Unzip object itself. In case you are wondering down paths and want to go back.



298
299
300
# File 'lib/buildr/packaging/ziptask.rb', line 298

def root
  self
end

#to_sObject

Returns the path to the target directory.



303
304
305
# File 'lib/buildr/packaging/ziptask.rb', line 303

def to_s
  target.to_s
end