class WinRM::FS::Core::TmpZip

A temporary Zip file for a given directory.

@author Fletcher Nichol <fnichol@nichol.ca>

Attributes

dir[R]

@return [Pathname] the directory used to create the Zip file @api private

logger[R]

@return [#debug] the logger @api private

zip_io[R]

@return [IO] the Zip file IO @api private

Public Class Methods

new(dir, logger = nil) click to toggle source

Contructs a new Zip file for the given directory.

There are 2 ways to interpret the directory path:

  • If the directory has no path separator terminator, then the directory basename will be used as the base directory in the resulting zip file.

  • If the directory has a path separator terminator (such as `/` or `\`), then the entries under the directory will be added to the resulting zip file.

The following emaples assume a directory tree structure of:

src
|-- alpha.txt
|-- beta.txt
\-- sub
    \-- charlie.txt

@example Including the base directory in the zip file

TmpZip.new("/path/to/src")
# produces a zip file with entries:
# - src/alpha.txt
# - src/beta.txt
# - src/sub/charlie.txt

@example Excluding the base directory in the zip file

TmpZip.new("/path/to/src/")
# produces a zip file with entries:
# - alpha.txt
# - beta.txt
# - sub/charlie.txt

@param dir [String,Pathname,#to_s] path to the directory @param logger [#debug,#debug?] an optional logger/ui object that

responds to `#debug` and `#debug?` (default `nil`)
# File lib/winrm-fs/core/tmp_zip.rb, line 70
def initialize(dir, logger = nil)
  @logger = logger || Logging.logger[self]
  @dir = clean_dirname(dir)
  @zip_io = Tempfile.open(['tmpzip-', '.zip'], binmode: true)
  write_zip
  @zip_io.close
end

Public Instance Methods

path() click to toggle source

@return [Pathname] path to zip file

# File lib/winrm-fs/core/tmp_zip.rb, line 79
def path
  Pathname.new(zip_io.path) if zip_io.path
end

Private Instance Methods

clean_dirname(dir) click to toggle source

@return [Pathname] the pathname object representing dirname that doesn't have any of those ~ in it @api private

# File lib/winrm-fs/core/tmp_zip.rb, line 105
def clean_dirname(dir)
  paths = Pathname.glob(dir)
  raise "Expected Pathname.glob(dir) to return only dir, got #{paths}" if paths.length != 1

  paths.first
end
entries() click to toggle source

@return [Array<Pathname] all recursive files under the base

directory, excluding directories

@api private

# File lib/winrm-fs/core/tmp_zip.rb, line 115
def entries
  Pathname.glob(dir.join('**/.*')).push(*Pathname.glob(dir.join('**/*'))).delete_if(&:directory?).sort
end
log_subject() click to toggle source

(see Logging.log_subject) @api private

# File lib/winrm-fs/core/tmp_zip.rb, line 121
def log_subject
  @log_subject ||= [self.class.to_s.split('::').last, path].join('::')
end
produce_zip_entries(zos) click to toggle source

Adds all file entries to the Zip output stream.

@param zos [Zip::OutputStream] zip output stream @api private

# File lib/winrm-fs/core/tmp_zip.rb, line 129
def produce_zip_entries(zos)
  entries.each do |entry|
    entry_path = entry.relative_path_from(dir)
    logger.debug "+++ Adding #{entry_path}"
    zos.put_next_entry(
      zip_entry(entry_path),
      nil, nil, ::Zip::Entry::DEFLATED, Zlib::BEST_COMPRESSION
    )
    entry.open('rb') { |src| IO.copy_stream(src, zos) }
  end
  logger.debug '=== All files added.'
end
write_zip() click to toggle source

Writes out a temporary Zip file.

@api private

# File lib/winrm-fs/core/tmp_zip.rb, line 145
def write_zip
  logger.debug 'Populating files'
  Zip::OutputStream.write_buffer(NoDupIO.new(zip_io)) do |zos|
    produce_zip_entries(zos)
  end
end
zip_entry(entry_path) click to toggle source
# File lib/winrm-fs/core/tmp_zip.rb, line 152
def zip_entry(entry_path)
  Zip::Entry.new(
    zip_io.path,
    entry_path.to_s,
    nil, nil, nil, nil, nil, nil,
    ::Zip::DOSTime.new(2000)
  )
end