Class: Minitar::CLI::Command::Extract

Inherits:
Minitar::CLI::Command
  • Object
show all
Includes:
CatchMinitarErrors
Defined in:
lib/minitar/cli/command/extract.rb

Overview

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.

Constant Summary collapse

HELP =
<<-EOH
  minitar extract [OPTIONS] <tarfile|-> [<file>+]

Extracts files from an existing tarfile. If the tarfile is named .tar.gz
or .tgz, then it will be uncompressed automatically. If the tarfile is
"-", then it will be read from standard input (stdin) so that minitar
may be piped.

The files or directories that will be extracted from the tarfile are
specified after the name of the tarfile itself. Directories will be
processed recursively. Files must be specified in full. A file
"foo/bar/baz.txt" cannot simply be specified by specifying "baz.txt".
Any file not found will simply be skipped and an error will be reported.

extract Options:
  --uncompress, -z  Uncompresses the tarfile with gzip.
  --pipe            Emits the extracted files to STDOUT for piping.
  --output, -o      Extracts the files to the specified directory.

EOH

Instance Method Summary collapse

Methods included from CatchMinitarErrors

#call

Instance Method Details

#altnameObject



11
12
13
# File 'lib/minitar/cli/command/extract.rb', line 11

def altname
  "ex"
end

#helpObject



128
129
130
# File 'lib/minitar/cli/command/extract.rb', line 128

def help
  HELP
end

#nameObject



7
8
9
# File 'lib/minitar/cli/command/extract.rb', line 7

def name
  "extract"
end

#run(args, opts = {}) ⇒ Object



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# 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 /\.tar\.gz$|\.tgz$/ =~ opts[:name] || 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?
    Minitar.unpack(input, dest, files, &watcher)
    finisher.call
  else
    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