class Nucleus::ArchiveExtractor

Public Class Methods

new(exclude_git = true) click to toggle source
# File lib/nucleus/core/common/files/archive_extractor.rb, line 3
def initialize(exclude_git = true)
  @exclude_git = exclude_git
end

Public Instance Methods

extract(file, destination_path, compression_format) click to toggle source

Extract the file to the destination path. The compression format indicates which method must be used to extract the archive. @param [IO] file in-memory archive file to extract @param [String] destination_path where the archive is going to be extracted to @param [String] compression_format represented by well-known file extensions, e.g. zip or tar.gz @raise [StandardError] if the compression_format is not supported and can’t be extracted @return [Integer] number of extracted files

# File lib/nucleus/core/common/files/archive_extractor.rb, line 14
def extract(file, destination_path, compression_format)
  compression_method = compression_format_method_name(compression_format)
  raise StandardError, 'Unsupported compression format' unless respond_to?(compression_method, true)

  # be sure that directory exists
  FileUtils.mkdir_p(destination_path, verbose: false)

  begin
    send(compression_method, file, destination_path)
  rescue Zip::Error, Zlib::GzipFile::Error
    raise API::Errors::ApplicationArchiveError, "Failed to extract #{compression_format} archive"
  end
end
supports?(compression_format) click to toggle source

Checks if the compression format is supported and an archive of this type could be extracted. @param [String] compression_format represented by well-known file extensions, e.g. zip or tar.gz @return [Boolean] true if format is supported, false if not

# File lib/nucleus/core/common/files/archive_extractor.rb, line 31
def supports?(compression_format)
  compression_method = compression_format_method_name(compression_format)
  respond_to?(compression_method, true)
end

Private Instance Methods

compression_format_method_name(compression_format) click to toggle source
# File lib/nucleus/core/common/files/archive_extractor.rb, line 38
def compression_format_method_name(compression_format)
  "un_#{compression_format.downcase.tr('.', '_').underscore}".to_sym
end
tar_git_entry?(full_name) click to toggle source
# File lib/nucleus/core/common/files/archive_extractor.rb, line 97
def tar_git_entry?(full_name)
  @exclude_git && full_name.start_with?('._.git', '.git')
end
un_tar_gz(file, destination_path) click to toggle source
# File lib/nucleus/core/common/files/archive_extractor.rb, line 64
def un_tar_gz(file, destination_path)
  extracted = 0
  # unzip the archive into the repo, closes resource automatically
  # Thanks to Draco Ater: http://stackoverflow.com/a/19139114/1009436
  Gem::Package::TarReader.new(Zlib::GzipReader.open(file)) do |tar|
    dest = nil
    tar.each do |entry|
      # Process Longlinks and skip to next entry
      if entry.full_name == '././@LongLink'
        dest = File.join(destination_path, entry.read.strip)
        next
      end

      # Process default entry types (dir, file, symlink)
      full_name = entry.full_name.sub(%r{(\.\/)?}, '')
      dest ||= File.join(destination_path, full_name)
      next if tar_git_entry? full_name
      if entry.directory?
        write_tar_dir_entry(entry, dest)
      elsif entry.file?
        write_tar_file_entry(entry, dest)
        # increase count
        extracted += 1
      elsif entry.header.typeflag == '2'
        # handle symlinks
        File.symlink(entry.header.linkname, dest)
      end
      dest = nil
    end
  end
end
Also aliased as: un_tgz
un_tgz(file, destination_path)
Alias for: un_tar_gz
un_zip(file, destination_path) click to toggle source
# File lib/nucleus/core/common/files/archive_extractor.rb, line 42
def un_zip(file, destination_path)
  extracted = 0
  Zip::File.open(file) do |zip_file|
    # Handle entries one by one
    zip_file.each do |entry|
      next if @exclude_git && entry.name.start_with?('.git')
      dest = File.join(destination_path, entry.name)
      if entry.name_is_directory?
        FileUtils.mkdir_p(dest) unless File.exist?(dest)
      else
        # make sure parent directory exists
        FileUtils.mkdir_p(File.expand_path('..', dest))

        entry.extract(dest) unless File.exist?(dest)
        # increase count
        extracted += 1
      end
    end
  end
  extracted
end
write_tar_dir_entry(entry, dest) click to toggle source
# File lib/nucleus/core/common/files/archive_extractor.rb, line 107
def write_tar_dir_entry(entry, dest)
  File.delete(dest) if File.file?(dest)
  FileUtils.mkdir_p(dest, mode: entry.header.mode, verbose: false)
end
write_tar_file_entry(entry, dest) click to toggle source
# File lib/nucleus/core/common/files/archive_extractor.rb, line 101
def write_tar_file_entry(entry, dest)
  FileUtils.rm_rf(dest) if File.directory?(dest)
  File.open(dest, 'wb') { |f| f.print entry.read }
  FileUtils.chmod(entry.header.mode, dest, verbose: false)
end