File: archive.rb

package info (click to toggle)
puppet-module-voxpupuli-archive 7.1.0-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 744 kB
  • sloc: ruby: 2,483; sh: 10; makefile: 4
file content (171 lines) | stat: -rw-r--r-- 6,168 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# frozen_string_literal: true

require 'digest'
require 'puppet/util/execution'
require 'shellwords'

module PuppetX
  module Bodeco
    class Archive
      def initialize(file)
        @file = file
        @file_path =  if Facter.value(:osfamily) == 'windows'
                        "\"#{file}\""
                      else
                        Shellwords.shellescape file
                      end
      end

      def checksum(type)
        return nil if type == :none

        digest = Digest.const_get(type.to_s.upcase)
        digest.file(@file).hexdigest
      rescue LoadError
        raise $ERROR_INFO, "invalid checksum type #{type}. #{$ERROR_INFO}", $ERROR_INFO.backtrace
      end

      def root_dir
        if Facter.value(:osfamily) == 'windows'
          'C:\\'
        else
          '/'
        end
      end

      def extract(path = root_dir, opts = {})
        opts = {
          custom_command: nil,
          options: '',
          uid: nil,
          gid: nil
        }.merge(opts)

        custom_command = opts.fetch(:custom_command, nil)
        options = opts.fetch(:options)
        Dir.chdir(path) do
          cmd = if custom_command && custom_command =~ %r{%s}
                  custom_command % @file_path
                elsif custom_command
                  "#{custom_command} #{options} #{@file_path}"
                else
                  command(options)
                end

          Puppet.debug("Archive extracting #{@file} in #{path}: #{cmd}")
          File.chmod(0o644, @file) if opts[:uid] || opts[:gid]
          Puppet::Util::Execution.execute(cmd, uid: opts[:uid], gid: opts[:gid], failonfail: true, squelch: false, combine: true)
        end
      end

      private

      def win_7zip
        if ENV['path'].include?('7-Zip') || system('where 7z.exe')
          '7z.exe'
        elsif File.directory?('C:\\Program Files\\7-Zip')
          'C:\\Program Files\\7-Zip\\7z.exe'
        elsif File.directory?('C:\\Program Files (x86)\\7-zip')
          'C:\\Program Files (x86)\\7-Zip\\7z.exe'
        elsif @file_path =~ %r{.zip"$}
          # Fallback to powershell for zipfiles - this works with windows
          # 2012+ if your powershell/.net is too old the script will fail
          # on execution and ask user to install 7zip.
          # We have to manually extract each entry in the zip file
          # to ensure we extract fresh copy because `ExtractToDirectory`
          # method does not support overwriting
          ps = <<-END
          try {
              Add-Type -AssemblyName System.IO.Compression.FileSystem -erroraction "silentlycontinue"
              $zipFile = [System.IO.Compression.ZipFile]::openread(#{@file_path})
              foreach ($zipFileEntry in $zipFile.Entries) {
                  $pwd = (Get-Item -Path "." -Verbose).FullName
                  $outputFile = [io.path]::combine($pwd, $zipFileEntry.FullName)
                  $dir = ([io.fileinfo]$outputFile).DirectoryName

                  if (-not(Test-Path -type Container -path $dir)) {
                      mkdir $dir
                  }
                  if ($zipFileEntry.Name -ne "") {
                      write-host "[extract] $zipFileEntry.Name"
                      [System.IO.Compression.ZipFileExtensions]::ExtractToFile($zipFileEntry, $outputFile, $true)
                  }
              }
          } catch [System.invalidOperationException] {
              write-error "Your OS does not support System.IO.Compression.FileSystem - please install 7zip"
          }
          END

          "powershell -command #{ps.gsub(%r{"}, '\\"').gsub(%r{\n}, '; ')}"
        else
          raise StandardError, '7z.exe not available'
        end
      end

      def command(options)
        if Facter.value(:osfamily) == 'windows'
          opt = parse_flags('x -aoa', options, '7z')
          cmd = win_7zip
          cmd =~ %r{7z.exe} ? "#{cmd} #{opt} #{@file_path}" : cmd
        else
          case @file
          when %r{\.tar$}
            opt = parse_flags('xf', options, 'tar')
            "tar #{opt} #{@file_path}"
          when %r{(\.tgz|\.tar\.gz)$}
            case Facter.value(:osfamily)
            when 'Solaris', 'AIX'
              gunzip_opt = parse_flags('-dc', options, 'gunzip')
              tar_opt = parse_flags('xf', options, 'tar')
              "gunzip #{gunzip_opt} #{@file_path} | tar #{tar_opt} -"
            else
              opt = parse_flags('xzf', options, 'tar')
              "tar #{opt} #{@file_path}"
            end
          when %r{(\.tbz|\.tar\.bz2)$}
            case Facter.value(:osfamily)
            when 'Solaris', 'AIX'
              bunzip_opt = parse_flags('-dc', options, 'bunzip')
              tar_opt = parse_flags('xf', options, 'tar')
              "bunzip2 #{bunzip_opt} #{@file_path} | tar #{tar_opt} -"
            else
              opt = parse_flags('xjf', options, 'tar')
              "tar #{opt} #{@file_path}"
            end
          when %r{(\.txz|\.tar\.xz)$}
            unxz_opt = parse_flags('-dc', options, 'unxz')
            tar_opt = parse_flags('xf', options, 'tar')
            "unxz #{unxz_opt} #{@file_path} | tar #{tar_opt} -"
          when %r{\.gz$}
            opt = parse_flags('-d', options, 'gunzip')
            "gunzip #{opt} #{@file_path}"
          when %r{(\.zip|\.war|\.jar)$}
            opt = parse_flags('-o', options, 'zip')
            "unzip #{opt} #{@file_path}"
          when %r{(\.bz2)$}
            opt = parse_flags('-d', options, 'bunzip2')
            "bunzip2 #{opt} #{@file_path}"
          when %r{(\.tar\.Z)$}
            tar_opt = parse_flags('xf', options, 'tar')
            "uncompress -c #{@file_path} | tar #{tar_opt} -"
          else
            raise NotImplementedError, "Unknown filetype: #{@file}"
          end
        end
      end

      def parse_flags(default, options, command = nil)
        case options
        when :undef
          default
        when ::String
          options
        when ::Hash
          options[command]
        else
          raise ArgumentError, "Invalid options for command #{command}: #{options.inspect}"
        end
      end
    end
  end
end