class Minitar::CLI::Command::Extract

Tarball extraction command. This will be replaced in a future version by one of the better-executed CLI application frameworks like GLI, after Ruby 1.8 and 1.9 support have been dropped.

Constants

HELP

Public Instance Methods

altname() click to toggle source
# File lib/minitar/cli/command/extract.rb, line 11
def altname
  'ex'
end
help() click to toggle source
# File lib/minitar/cli/command/extract.rb, line 128
def help
  HELP
end
name() click to toggle source
# File lib/minitar/cli/command/extract.rb, line 7
def name
  'extract'
end
run(args, opts = {}) click to toggle source
# File lib/minitar/cli/command/extract.rb, line 38
def run(args, opts = {})
  argv    = []
  output  = nil
  dest    = '.'
  files   = []

  while (arg = args.shift)
    case arg
    when '--uncompress', '-z'
      opts[:uncompress] = true
    when '--pipe'
      output = ioe[:output]
      ioe[:output] = ioe[:error]
    when '--output', '-o'
      dest = args.shift
    else
      argv << arg
    end
  end

  if argv.empty?
    ioe[:output] << "Not enough arguments.\n\n"
    commander.command('help').call(%w(extract))
    return 255
  end

  input = argv.shift
  if '-' == input
    opts[:name] = 'STDIN'
    input = ioe[:input]
  else
    opts[:name] = input
    input = File.open(input, 'rb')
  end

  if opts[:name] =~ /\.tar\.gz$|\.tgz$/ or opts[:uncompress]
    require 'zlib'
    input = Zlib::GzipReader.new(input)
  end

  files << argv.to_a
  files.flatten!

  watcher, finisher =
    if opts[:verbose]
      verbose
    elsif opts[:progress]
      progress
    else
      silent
    end

  if output.nil?
    Archive::Tar::Minitar.unpack(input, dest, files, &watcher)
    finisher.call
  else
    Archive::Tar::Minitar::Input.each_entry(input) do |entry|
      next unless files.empty? || files.include?(entry.full_name)

      stats = {
        :mode     => entry.mode,
        :mtime    => entry.mtime,
        :size     => entry.size,
        :gid      => entry.gid,
        :uid      => entry.uid,
        :current  => 0,
        :currinc  => 0,
        :entry    => entry
      }

      if entry.directory?
        watcher.call(:dir, dest, stats)
      else
        watcher.call(:file_start, destfile, stats)
        loop do
          data = entry.read(4096)
          break unless data
          stats[:currinc] = output.write(data)
          stats[:current] += stats[:currinc]

          watcher.call(:file_progress, name, stats)
        end
        watcher.call(:file_done, name, stats)
      end
    end
  end

  0
end

Private Instance Methods

progress() click to toggle source
# File lib/minitar/cli/command/extract.rb, line 143
def progress
  require 'powerbar'
  progress = PowerBar.new(:msg => opts[:name], :total => 1)
  [
    lambda { |action, name, stats|
      progress_info = {}

      case action
      when :file_start, :dir
        progress_info[:msg] = File.basename(name)
        if action == :dir
          progress_info[:total] = progress.total + 1
          progress_info[:done] = progress.done + 1
        else
          progress_info[:total] = progress.total + stats[:entry].size
        end
      when :file_progress
        progress_info[:done] = progress.done + stats[:currinc]
      end

      progress.show(progress_info)
    },
    lambda {
      progress.show(:msg => opts[:name])
      progress.close(true)
    }
  ]
end
silent() click to toggle source
# File lib/minitar/cli/command/extract.rb, line 172
def silent
  [ lambda { |_, _, _| }, lambda {} ]
end
verbose() click to toggle source
# File lib/minitar/cli/command/extract.rb, line 134
def verbose
  [
    lambda { |action, name, _stats|
      ioe[:output] << "#{name}\n" if action == :dir or action == :file_done
    },
    lambda { ioe[:output] << "\n" }
  ]
end