poise-archive 1.1.2 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cfaafe9923ce43911a655e20b02ab6dd00cb7048
4
- data.tar.gz: 80cc2672a626c92f4448b5936d5d10a51420c73c
3
+ metadata.gz: 5ba8a642607edf70f9c1cc3c985d6cd70eed6515
4
+ data.tar.gz: e1e3fa40223be0e015e1dae1e5640c5a839d5077
5
5
  SHA512:
6
- metadata.gz: 6f46fc0af69806f98c569071ffd083f377614eae6ef598be79691957b709506cda3e5f719523f27cc00b164c0b3d9cbf611e147ac76aaacf8fb633c07f1f9f3b
7
- data.tar.gz: b482be77a33a595e75f4a9d6ce56126cee7c7e452132c0a3e127bf8ed8834439abe2e00970878a6cb7ed31e702b303f384e68089aade9f6b286370ae78c07100
6
+ metadata.gz: 0d64cb5a421994253e7b5d124250df5c0d020a481e55e7ac4e699ecb6296327f43efe73fa1024bb95c940402435d79f9a1ba333f27d7dfb0b4ec95ac2c35607a
7
+ data.tar.gz: c54e8439eeb5b38a451636fa728fe59f3da6a9834aa8ed3609654b2e8e88292b785e24d1aafad84c9cae6367dce953f7aaa4496ca37334c577a622991f7491ca
@@ -1,5 +1,11 @@
1
1
  # Poise-Archive Changelog
2
2
 
3
+ ## v1.2.0
4
+
5
+ * Add back a tar-binary provider called `GnuTar`, used by default on Linux.
6
+ * Support for ZIP files via RubyZip.
7
+ * Full Windows support, including with the `user` and `group` properties.
8
+
3
9
  ## v1.1.2
4
10
 
5
11
  * Fix compat with older Ruby that doesn't include `Entry#symlink?`.
data/README.md CHANGED
@@ -7,9 +7,9 @@
7
7
  [![Gemnasium](https://img.shields.io/gemnasium/poise/poise-archive.svg)](https://gemnasium.com/poise/poise-archive)
8
8
  [![License](https://img.shields.io/badge/license-Apache_2-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0)
9
9
 
10
- A [Chef](https://www.chef.io/) cookbook to unpack file archives like TAR and ZIP files.
10
+ A [Chef](https://www.chef.io/) cookbook to unpack file archives.
11
11
 
12
- **NOTE:** ZIP files are not supported yet, stay tuned.
12
+ It supports `.tar`, `.tar.gz`, `.tar.bz2`, and `.zip` archive files.
13
13
 
14
14
  ## Quick Start
15
15
 
@@ -27,6 +27,12 @@ remote_file "#{Chef::Config[:file_cache_path]}/myapp.tgz" do
27
27
  end
28
28
  ```
29
29
 
30
+ ## Platforms
31
+
32
+ This cookbook supports all platforms (including Windows) but non-Linux platforms
33
+ may see very slow tar file unpacking when using the pure-Ruby fallback
34
+ implementation.
35
+
30
36
  ## Resources
31
37
 
32
38
  ### `poise_archive`
@@ -16,6 +16,7 @@
16
16
 
17
17
  require 'chef/platform/provider_priority_map'
18
18
 
19
+ require 'poise_archive/archive_providers/gnu_tar'
19
20
  require 'poise_archive/archive_providers/tar'
20
21
  require 'poise_archive/archive_providers/zip'
21
22
 
@@ -27,6 +28,7 @@ module PoiseArchive
27
28
  module ArchiveProviders
28
29
  # Set up priority maps
29
30
  Chef::Platform::ProviderPriorityMap.instance.priority(:poise_archive, [
31
+ PoiseArchive::ArchiveProviders::GnuTar,
30
32
  PoiseArchive::ArchiveProviders::Tar,
31
33
  PoiseArchive::ArchiveProviders::Zip,
32
34
  ])
@@ -55,11 +55,13 @@ module PoiseArchive
55
55
  #
56
56
  # @return [void]
57
57
  def action_unpack
58
- notifying_block do
59
- create_directory
58
+ converge_by("unpack archive #{new_resource.path} to #{new_resource.absolute_destination}") do
59
+ notifying_block do
60
+ create_directory
61
+ end
62
+ empty_directory
63
+ unpack_archive
60
64
  end
61
- empty_directory
62
- unpack_archive
63
65
  end
64
66
 
65
67
  private
@@ -0,0 +1,82 @@
1
+ #
2
+ # Copyright 2016, Noah Kantrowitz
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ require 'fileutils'
18
+ require 'tmpdir'
19
+
20
+ require 'poise_archive/archive_providers/base'
21
+
22
+
23
+ module PoiseArchive
24
+ module ArchiveProviders
25
+ # The `gnu_tar` provider class for `poise_archive` to install from TAR
26
+ # archives using GNU's tar executable.
27
+ #
28
+ # @see PoiseArchive::Resources::PoiseArchive::Resource
29
+ # @provides poise_archive
30
+ class GnuTar < Base
31
+ provides_extension(/\.t(ar|gz|bz|xz)/)
32
+
33
+ # Only use this if we are on Linux. Everyone else gets the slow Ruby code.
34
+ #
35
+ # @api private
36
+ def self.provides?(node, _resource)
37
+ super && node['os'] == 'linux'
38
+ end
39
+
40
+ private
41
+
42
+ def unpack_archive
43
+ notifying_block do
44
+ install_prereqs
45
+ end
46
+ unpack_tar
47
+ end
48
+
49
+ # Install any needed prereqs.
50
+ #
51
+ # @return [void]
52
+ def install_prereqs
53
+ utils = ['tar']
54
+ utils << 'bzip2' if new_resource.path =~ /\.t?bz/
55
+ utils << 'xz-utils' if new_resource.path =~ /\.t?xz/
56
+ # This is a resource.
57
+ package utils
58
+ end
59
+
60
+ # Unpack the archive and process `strip_components`.
61
+ #
62
+ # @return [void]
63
+ def unpack_tar
64
+ # Build the tar command.
65
+ cmd = %w{tar}
66
+ cmd << "--strip-components=#{new_resource.strip_components}" if new_resource.strip_components && new_resource.strip_components > 0
67
+ cmd << if new_resource.path =~ /\.t?gz/
68
+ '-xzvf'
69
+ elsif new_resource.path =~ /\.t?bz/
70
+ '-xjvf'
71
+ elsif new_resource.path =~ /\.t?xz/
72
+ '-xJvf'
73
+ else
74
+ '-xvf'
75
+ end
76
+ cmd << new_resource.path
77
+ poise_shell_out!(cmd, cwd: new_resource.absolute_destination, group: new_resource.group, user: new_resource.user)
78
+ end
79
+
80
+ end
81
+ end
82
+ end
@@ -14,7 +14,6 @@
14
14
  # limitations under the License.
15
15
  #
16
16
 
17
- require 'fileutils'
18
17
  require 'rubygems/package'
19
18
  require 'zlib'
20
19
 
@@ -41,12 +40,14 @@ module PoiseArchive
41
40
 
42
41
  def unpack_archive
43
42
  unpack_tar
43
+ chown_entries if new_resource.user || new_resource.group
44
44
  end
45
45
 
46
46
  # Unpack the archive.
47
47
  #
48
48
  # @return [void]
49
49
  def unpack_tar
50
+ @tar_entry_paths = []
50
51
  tar_each_with_longlink do |entry|
51
52
  entry_name = entry.full_name.split(/\//).drop(new_resource.strip_components).join('/')
52
53
  # If strip_components wiped out the name, don't process this entry.
@@ -54,18 +55,20 @@ module PoiseArchive
54
55
  dest = ::File.join(new_resource.destination, entry_name)
55
56
  if entry.directory?
56
57
  Dir.mkdir(dest, entry.header.mode)
58
+ @tar_entry_paths << [:directory, dest]
57
59
  elsif entry.file?
58
60
  ::File.open(dest, 'wb', entry.header.mode) do |dest_f|
59
61
  while buf = entry.read(4096)
60
62
  dest_f.write(buf)
61
63
  end
62
64
  end
65
+ @tar_entry_paths << [:file, dest]
63
66
  elsif entry.header.typeflag == '2' # symlink? is new in Ruby 2.0, apparently.
64
67
  ::File.symlink(entry.header.linkname, dest)
68
+ @tar_entry_paths << [:link, dest]
65
69
  else
66
70
  raise RuntimeError.new("Unknown tar entry type #{entry.header.typeflag.inspect} in #{new_resource.path}")
67
71
  end
68
- FileUtils.chown(new_resource.user, new_resource.group, dest)
69
72
  end
70
73
  end
71
74
 
@@ -138,6 +141,18 @@ module PoiseArchive
138
141
  end
139
142
  end
140
143
 
144
+ def chown_entries
145
+ paths = @tar_entry_paths
146
+ notifying_block do
147
+ paths.each do |type, path|
148
+ send(type, path) do
149
+ group new_resource.group
150
+ owner new_resource.user
151
+ end
152
+ end
153
+ end
154
+ end
155
+
141
156
  end
142
157
  end
143
158
  end
@@ -25,6 +25,54 @@ module PoiseArchive
25
25
  # @provides poise_archive
26
26
  class Zip < Base
27
27
  provides_extension(/\.zip$/)
28
+
29
+ private
30
+
31
+ def unpack_archive
32
+ check_rubyzip
33
+ unpack_zip
34
+ chown_entries if new_resource.user || new_resource.group
35
+ end
36
+
37
+ def check_rubyzip
38
+ require 'zip'
39
+ rescue LoadError
40
+ notifying_block do
41
+ install_rubyzip
42
+ end
43
+ require 'zip'
44
+ end
45
+
46
+ def install_rubyzip
47
+ chef_gem 'rubyzip'
48
+ end
49
+
50
+ def unpack_zip
51
+ @zip_entry_paths = []
52
+ ::Zip::File.open(new_resource.path) do |zip_file|
53
+ zip_file.each do |entry|
54
+ entry_name = entry.name.split(/\//).drop(new_resource.strip_components).join('/')
55
+ # If strip_components wiped out the name, don't process this entry.
56
+ next if entry_name.empty?
57
+ entry_path = ::File.join(new_resource.destination, entry_name)
58
+ entry.extract(entry_path)
59
+ @zip_entry_paths << [entry.directory? ? :directory : entry.file? ? :file : :link, entry_path]
60
+ end
61
+ end
62
+ end
63
+
64
+ def chown_entries
65
+ paths = @zip_entry_paths
66
+ notifying_block do
67
+ paths.each do |type, path|
68
+ send(type, path) do
69
+ group new_resource.group
70
+ owner new_resource.user
71
+ end
72
+ end
73
+ end
74
+ end
75
+
28
76
  end
29
77
  end
30
78
  end
@@ -57,19 +57,26 @@ module PoiseArchive
57
57
  # like GNU tar's --strip-components.
58
58
  # @return [Integer]
59
59
  attribute(:strip_components, kind_of: Integer, default: 1)
60
- # @!attribute group
60
+ # @!attribute user
61
61
  # User to run the unpack as.
62
62
  # @return [String, Integer, nil, false]
63
63
  attribute(:user, kind_of: [String, Integer, NilClass, FalseClass])
64
64
 
65
+ # Alias for the forgetful.
66
+ # @api private
67
+ alias_method :owner, :user
68
+
65
69
  def absolute_path
66
70
  ::File.expand_path(path, Chef::Config[:file_cache_path])
67
71
  end
68
72
 
73
+ # Filename components to ignore.
74
+ # @api private
75
+ BASENAME_IGNORE = /(\.(t?(ar|gz|bz2?|xz)|zip))+$/
76
+
69
77
  def absolute_destination
70
78
  destination || begin
71
- basename = ::File.basename(path)
72
- ::File.join(::File.dirname(absolute_path), basename.split(/\./).find {|part| !part.empty? } || basename)
79
+ ::File.join(::File.dirname(absolute_path), ::File.basename(path).gsub(BASENAME_IGNORE, ''))
73
80
  end
74
81
  end
75
82
  end
@@ -16,5 +16,5 @@
16
16
 
17
17
 
18
18
  module PoiseArchive
19
- VERSION = '1.1.2'
19
+ VERSION = '1.2.0'
20
20
  end
@@ -19,49 +19,70 @@ directory '/test' do
19
19
  mode '777'
20
20
  end
21
21
 
22
+ # Test user/group.
23
+ group 'gpoise' do
24
+ system true
25
+ end
26
+
27
+ user 'poise' do
28
+ group 'gpoise'
29
+ system true
30
+ end
31
+
22
32
  # Tests for each fixture file.
23
- %w{tar tar.gz tar.bz2}.each do |ext|
24
- cookbook_file "/test/myapp-1.0.0.#{ext}" do
25
- source "myapp-1.0.0.#{ext}"
33
+ [
34
+ {ext: 'tar', provider: nil},
35
+ {ext: 'tar.gz', provider: nil},
36
+ {ext: 'tar.bz2', provider: nil},
37
+ {ext: 'zip', provider: nil},
38
+ {ext: 'tar', provider: PoiseArchive::ArchiveProviders::Tar},
39
+ {ext: 'tar.gz', provider: PoiseArchive::ArchiveProviders::Tar},
40
+ {ext: 'tar.bz2', provider: PoiseArchive::ArchiveProviders::Tar},
41
+ {ext: 'tar', provider: PoiseArchive::ArchiveProviders::GnuTar, only_if: proc { node['os'] == 'linux' }},
42
+ {ext: 'tar.gz', provider: PoiseArchive::ArchiveProviders::GnuTar, only_if: proc { node['os'] == 'linux' }},
43
+ {ext: 'tar.bz2', provider: PoiseArchive::ArchiveProviders::GnuTar, only_if: proc { node['os'] == 'linux' }},
44
+ {ext: 'zip', provider: PoiseArchive::ArchiveProviders::Zip},
45
+ ].each do |test|
46
+ next if test[:only_if] && !test[:only_if].call
47
+ test_base = "/test/#{test[:provider].to_s.split('::').last || 'default'}"
48
+ directory test_base do
49
+ mode '777'
50
+ end
51
+
52
+ cookbook_file "#{test_base}/myapp-1.0.0.#{test[:ext]}" do
53
+ source "myapp-1.0.0.#{test[:ext]}"
26
54
  end
27
55
 
28
- poise_archive "/test/myapp-1.0.0.#{ext}" do
29
- destination "/test/#{ext}"
56
+ poise_archive "#{test_base}/myapp-1.0.0.#{test[:ext]}" do
57
+ destination "#{test_base}/#{test[:ext]}"
58
+ provider test[:provider] if test[:provider]
30
59
  end
31
60
 
32
- poise_archive "/test/myapp-1.0.0.#{ext}_0" do
33
- path "/test/myapp-1.0.0.#{ext}"
34
- destination "/test/#{ext}_0"
61
+ poise_archive "#{test_base}/myapp-1.0.0.#{test[:ext]}_0" do
62
+ path "#{test_base}/myapp-1.0.0.#{test[:ext]}"
63
+ destination "#{test_base}/#{test[:ext]}_0"
64
+ provider test[:provider] if test[:provider]
35
65
  strip_components 0
36
66
  end
37
67
 
38
- poise_archive "/test/myapp-1.0.0.#{ext}_2" do
39
- path "/test/myapp-1.0.0.#{ext}"
40
- destination "/test/#{ext}_2"
68
+ poise_archive "#{test_base}/myapp-1.0.0.#{test[:ext]}_2" do
69
+ path "#{test_base}/myapp-1.0.0.#{test[:ext]}"
70
+ destination "#{test_base}/#{test[:ext]}_2"
71
+ provider test[:provider] if test[:provider]
41
72
  strip_components 2
42
73
  end
43
- end
44
74
 
45
- # Some general tests for core features.
46
- # Test user-specific unpacking.
47
- group 'poise' do
48
- system true
49
- end
50
-
51
- user 'poise' do
52
- group 'poise'
53
- system true
54
- end
55
-
56
- directory '/test/user' do
57
- group 'poise'
58
- mode '700'
59
- owner 'poise'
75
+ poise_archive "#{test_base}/myapp-1.0.0.#{test[:ext]}_user" do
76
+ path "#{test_base}/myapp-1.0.0.#{test[:ext]}"
77
+ destination "#{test_base}/#{test[:ext]}_user"
78
+ provider test[:provider] if test[:provider]
79
+ user 'poise'
80
+ end
60
81
  end
61
82
 
62
- poise_archive '/test/myapp-1.0.0.tar' do
63
- destination '/test/user'
64
- user 'poise'
83
+ # Some general tests for core features.
84
+ cookbook_file '/test/myapp-1.0.0.tar' do
85
+ source 'myapp-1.0.0.tar'
65
86
  end
66
87
 
67
88
  # Test keep_existing true.
@@ -14,8 +14,17 @@
14
14
  # limitations under the License.
15
15
  #
16
16
 
17
+ require 'rbconfig'
18
+
17
19
  require 'serverspec'
18
- set :backend, :exec
20
+
21
+ if RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/
22
+ set :backend, :cmd
23
+ set :os, :family => 'windows'
24
+ else
25
+ set :backend, :exec
26
+ end
27
+
19
28
 
20
29
  RSpec.shared_examples 'a poise_archive test' do |ext|
21
30
  base = "/test/#{ext}"
@@ -35,28 +44,69 @@ RSpec.shared_examples 'a poise_archive test' do |ext|
35
44
  describe file("#{base}_2/main.c") do
36
45
  it { is_expected.to be_a_file }
37
46
  end
47
+ describe file("#{base}_user") do
48
+ it { is_expected.to be_owned_by 'poise' }
49
+ it { is_expected.to be_mode '755' } unless os[:family] == 'windows'
50
+ end
51
+ describe file("#{base}_user/README") do
52
+ it { is_expected.to be_owned_by 'poise' }
53
+ it { is_expected.to be_mode '644' } unless os[:family] == 'windows'
54
+ end
38
55
  end
39
56
 
40
- describe 'tar' do
41
- it_should_behave_like 'a poise_archive test', 'tar'
42
- end
57
+ describe 'default provider' do
58
+ describe 'tar' do
59
+ it_should_behave_like 'a poise_archive test', 'default/tar'
60
+ end
61
+
62
+ describe 'tar.gz' do
63
+ it_should_behave_like 'a poise_archive test', 'default/tar.gz'
64
+ end
43
65
 
44
- describe 'tar.gz' do
45
- it_should_behave_like 'a poise_archive test', 'tar.gz'
66
+ describe 'tar.bz2' do
67
+ it_should_behave_like 'a poise_archive test', 'default/tar.bz2'
68
+ end
69
+
70
+ describe 'zip' do
71
+ it_should_behave_like 'a poise_archive test', 'default/zip'
72
+ end
46
73
  end
47
74
 
48
- describe 'tar.bz2' do
49
- it_should_behave_like 'a poise_archive test', 'tar.bz2'
75
+ describe 'Tar provider' do
76
+ describe 'tar' do
77
+ it_should_behave_like 'a poise_archive test', 'Tar/tar'
78
+ end
79
+
80
+ describe 'tar.gz' do
81
+ it_should_behave_like 'a poise_archive test', 'Tar/tar.gz'
82
+ end
83
+
84
+ describe 'tar.bz2' do
85
+ it_should_behave_like 'a poise_archive test', 'Tar/tar.bz2'
86
+ end
50
87
  end
51
88
 
52
- describe 'core features' do
53
- describe file('/test/user') do
54
- it { is_expected.to be_owned_by 'poise' }
55
- it { is_expected.to be_mode '700' }
89
+ describe 'GnuTar provider', if: File.exist?('/test/GnuTar') do
90
+ describe 'tar' do
91
+ it_should_behave_like 'a poise_archive test', 'GnuTar/tar'
56
92
  end
57
- describe file('/test/user/README') do
58
- it { is_expected.to be_owned_by 'poise' }
93
+
94
+ describe 'tar.gz' do
95
+ it_should_behave_like 'a poise_archive test', 'GnuTar/tar.gz'
59
96
  end
97
+
98
+ describe 'tar.bz2' do
99
+ it_should_behave_like 'a poise_archive test', 'GnuTar/tar.bz2'
100
+ end
101
+ end
102
+
103
+ describe 'Zip provider' do
104
+ describe 'zip' do
105
+ it_should_behave_like 'a poise_archive test', 'Zip/zip'
106
+ end
107
+ end
108
+
109
+ describe 'core features' do
60
110
  describe file('/test/keep/EXISTING') do
61
111
  it { is_expected.to be_a_file }
62
112
  end
@@ -0,0 +1,166 @@
1
+ #
2
+ # Copyright 2016, Noah Kantrowitz
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ require 'spec_helper'
18
+
19
+ FIXTURES_PATH = File.expand_path('../../../cookbook/files', __FILE__)
20
+
21
+ describe PoiseArchive::ArchiveProviders::GnuTar do
22
+ step_into(:poise_archive)
23
+ let(:archive_provider) { chef_run.poise_archive('myapp').provider_for_action(:unpack) }
24
+ before do
25
+ chefspec_options.update(platform: 'ubuntu', version: '14.04')
26
+ # Stub out some stuff from the base class.
27
+ expect(Dir).to receive(:mkdir).and_call_original
28
+ allow(Dir).to receive(:entries).and_call_original
29
+ allow(Dir).to receive(:entries).with('/test/myapp').and_return(%w{. ..})
30
+ end
31
+
32
+ context 'with a .tar path' do
33
+ recipe do
34
+ poise_archive 'myapp' do
35
+ path "/test/myapp-1.0.0.tar"
36
+ destination '/test/myapp'
37
+ end
38
+ end
39
+
40
+ it do
41
+ expect_any_instance_of(described_class).to receive(:poise_shell_out!).with(%w{tar --strip-components=1 -xvf /test/myapp-1.0.0.tar}, cwd: '/test/myapp', group: nil, user: nil)
42
+ run_chef
43
+ expect(archive_provider).to be_a described_class
44
+ end
45
+ end # /context with a .tar path
46
+
47
+ context 'with a .tar.gz path' do
48
+ recipe do
49
+ poise_archive 'myapp' do
50
+ path "/test/myapp-1.0.0.tar.gz"
51
+ destination '/test/myapp'
52
+ end
53
+ end
54
+
55
+ it do
56
+ expect_any_instance_of(described_class).to receive(:poise_shell_out!).with(%w{tar --strip-components=1 -xzvf /test/myapp-1.0.0.tar.gz}, cwd: '/test/myapp', group: nil, user: nil)
57
+ run_chef
58
+ expect(archive_provider).to be_a described_class
59
+ end
60
+ end # /context with a .tar.gz path
61
+
62
+ context 'with a .tar.bz2 path' do
63
+ recipe do
64
+ poise_archive 'myapp' do
65
+ path "/test/myapp-1.0.0.tar.bz2"
66
+ destination '/test/myapp'
67
+ end
68
+ end
69
+
70
+ it do
71
+ expect_any_instance_of(described_class).to receive(:poise_shell_out!).with(%w{tar --strip-components=1 -xjvf /test/myapp-1.0.0.tar.bz2}, cwd: '/test/myapp', group: nil, user: nil)
72
+ run_chef
73
+ expect(archive_provider).to be_a described_class
74
+ end
75
+ end # /context with a .tar.bz2 path
76
+
77
+ context 'with a .tgz path' do
78
+ recipe do
79
+ poise_archive 'myapp' do
80
+ path "/test/myapp-1.0.0.tgz"
81
+ destination '/test/myapp'
82
+ end
83
+ end
84
+
85
+ it do
86
+ expect_any_instance_of(described_class).to receive(:poise_shell_out!).with(%w{tar --strip-components=1 -xzvf /test/myapp-1.0.0.tgz}, cwd: '/test/myapp', group: nil, user: nil)
87
+ run_chef
88
+ expect(archive_provider).to be_a described_class
89
+ end
90
+ end # /context with a .tgz path
91
+
92
+ context 'with a .tbz2 path' do
93
+ recipe do
94
+ poise_archive 'myapp' do
95
+ path "/test/myapp-1.0.0.tbz2"
96
+ destination '/test/myapp'
97
+ end
98
+ end
99
+
100
+ it do
101
+ expect_any_instance_of(described_class).to receive(:poise_shell_out!).with(%w{tar --strip-components=1 -xjvf /test/myapp-1.0.0.tbz2}, cwd: '/test/myapp', group: nil, user: nil)
102
+ run_chef
103
+ expect(archive_provider).to be_a described_class
104
+ end
105
+ end # /context with a .tbz2 path
106
+
107
+ context 'with strip_components 0' do
108
+ recipe do
109
+ poise_archive 'myapp' do
110
+ path "/test/myapp-1.0.0.tar"
111
+ destination '/test/myapp'
112
+ strip_components 0
113
+ end
114
+ end
115
+
116
+ it do
117
+ expect_any_instance_of(described_class).to receive(:poise_shell_out!).with(%w{tar -xvf /test/myapp-1.0.0.tar}, cwd: '/test/myapp', group: nil, user: nil)
118
+ run_chef
119
+ end
120
+ end # /context with strip_components 0
121
+
122
+ context 'with strip_components 2' do
123
+ recipe do
124
+ poise_archive 'myapp' do
125
+ path "/test/myapp-1.0.0.tar"
126
+ destination '/test/myapp'
127
+ strip_components 2
128
+ end
129
+ end
130
+
131
+ it do
132
+ expect_any_instance_of(described_class).to receive(:poise_shell_out!).with(%w{tar --strip-components=2 -xvf /test/myapp-1.0.0.tar}, cwd: '/test/myapp', group: nil, user: nil)
133
+ run_chef
134
+ end
135
+ end # /context with strip_components 2
136
+
137
+ context 'with a user' do
138
+ recipe do
139
+ poise_archive 'myapp' do
140
+ path "/test/myapp-1.0.0.tar"
141
+ destination '/test/myapp'
142
+ user 'myuser'
143
+ end
144
+ end
145
+
146
+ it do
147
+ expect_any_instance_of(described_class).to receive(:poise_shell_out!).with(%w{tar --strip-components=1 -xvf /test/myapp-1.0.0.tar}, cwd: '/test/myapp', group: nil, user: 'myuser')
148
+ run_chef
149
+ end
150
+ end # /context with a user
151
+
152
+ context 'with a group' do
153
+ recipe do
154
+ poise_archive 'myapp' do
155
+ path "/test/myapp-1.0.0.tar"
156
+ destination '/test/myapp'
157
+ group 'mygroup'
158
+ end
159
+ end
160
+
161
+ it do
162
+ expect_any_instance_of(described_class).to receive(:poise_shell_out!).with(%w{tar --strip-components=1 -xvf /test/myapp-1.0.0.tar}, cwd: '/test/myapp', group: 'mygroup', user: nil)
163
+ run_chef
164
+ end
165
+ end # /context with a group
166
+ end
@@ -20,70 +20,66 @@ FIXTURES_PATH = File.expand_path('../../../cookbook/files', __FILE__)
20
20
 
21
21
  describe PoiseArchive::ArchiveProviders::Tar do
22
22
  step_into(:poise_archive)
23
+ let(:archive_provider) { chef_run.poise_archive('myapp').provider_for_action(:unpack) }
24
+ before do
25
+ expect(Dir).to receive(:mkdir).and_call_original
26
+ allow(Dir).to receive(:entries).and_call_original
27
+ allow(Dir).to receive(:entries).with('/test/myapp').and_return(%w{. ..})
28
+ allow(File).to receive(:open).and_call_original
29
+ allow(File).to receive(:open).with('/test/myapp-1.0.0.tar', 'rb') { File.open(File.join(FIXTURES_PATH, 'myapp-1.0.0.tar')) }
30
+ allow(File).to receive(:open).with('/test/myapp-1.0.0.tar.gz', 'rb') { File.open(File.join(FIXTURES_PATH, 'myapp-1.0.0.tar.gz')) }
31
+ allow(File).to receive(:open).with('/test/myapp-1.0.0.tgz', 'rb') { File.open(File.join(FIXTURES_PATH, 'myapp-1.0.0.tar.gz')) }
32
+ allow(File).to receive(:open).with('/test/myapp-1.0.0.tar.bz2', 'rb') { File.open(File.join(FIXTURES_PATH, 'myapp-1.0.0.tar.bz2')) }
33
+ allow(File).to receive(:open).with('/test/myapp-1.0.0.tbz2', 'rb') { File.open(File.join(FIXTURES_PATH, 'myapp-1.0.0.tar.bz2')) }
34
+ end
23
35
 
24
- describe '#action_unpack' do
25
- let(:archive_provider) { chef_run.poise_archive('myapp').provider_for_action(:unpack) }
26
- before do
27
- # allow(described_class).to receive(:mktmpdir).and_yield('/test')
28
- expect(Dir).to receive(:mkdir).and_call_original
29
- allow(Dir).to receive(:entries).and_call_original
30
- allow(Dir).to receive(:entries).with('/test/myapp').and_return(%w{. ..})
31
- # expect_any_instance_of(described_class).to receive(:poise_shell_out!).with(tar_cmd, cwd: '/test', group: nil, user: nil)
32
- # expect_any_instance_of(described_class).to receive(:entries_at_depth).with('/test', 1).and_return(%w{/test/myapp/bin /test/myapp/src})
33
- # expect(File).to receive(:rename).with('/test/myapp/bin', '/root/myapp/bin')
34
- # expect(File).to receive(:rename).with('/test/myapp/src', '/root/myapp/src')
35
- allow(File).to receive(:open).and_call_original
36
- allow(File).to receive(:open).with('/test/myapp-1.0.0.tar', 'rb') { File.open(File.join(FIXTURES_PATH, 'myapp-1.0.0.tar')) }
37
- allow(File).to receive(:open).with('/test/myapp-1.0.0.tar.gz', 'rb') { File.open(File.join(FIXTURES_PATH, 'myapp-1.0.0.tar.gz')) }
38
- allow(File).to receive(:open).with('/test/myapp-1.0.0.tgz', 'rb') { File.open(File.join(FIXTURES_PATH, 'myapp-1.0.0.tar.gz')) }
39
- allow(File).to receive(:open).with('/test/myapp-1.0.0.tar.bz2', 'rb') { File.open(File.join(FIXTURES_PATH, 'myapp-1.0.0.tar.bz2')) }
40
- allow(File).to receive(:open).with('/test/myapp-1.0.0.tbz2', 'rb') { File.open(File.join(FIXTURES_PATH, 'myapp-1.0.0.tar.bz2')) }
41
- end
42
-
43
- RSpec.shared_examples 'a poise_archive test' do |ext|
44
- recipe do
45
- poise_archive 'myapp' do
46
- path "/test/myapp-1.0.0.#{ext}"
47
- destination '/test/myapp'
48
- end
36
+ RSpec.shared_examples 'a poise_archive tar test' do |ext|
37
+ recipe do
38
+ poise_archive 'myapp' do
39
+ path "/test/myapp-1.0.0.#{ext}"
40
+ destination '/test/myapp'
41
+ user 'myuser'
49
42
  end
43
+ end
50
44
 
51
- def expect_file(path, content, mode)
52
- fake_file = double("file for #{path}")
53
- expect(fake_file).to receive(:write).with(content)
54
- allow(File).to receive(:open).with(path, 'wb', mode).and_yield(fake_file)
55
- expect(FileUtils).to receive(:chown).with(nil, nil, path)
56
- end
45
+ def expect_file(path, content, mode)
46
+ fake_file = double("file for #{path}")
47
+ expect(fake_file).to receive(:write).with(content)
48
+ allow(File).to receive(:open).with(path, 'wb', mode).and_yield(fake_file)
49
+ end
57
50
 
58
- it do
59
- expect_file('/test/myapp/LICENSE', "This is in the public domain.\n", 0644)
60
- expect_file('/test/myapp/README', "This is a project!\n\n", 0644)
61
- expect(Dir).to receive(:mkdir).with('/test/myapp/src', 0755)
62
- expect(FileUtils).to receive(:chown).with(nil, nil, '/test/myapp/src')
63
- expect_file('/test/myapp/src/main.c', "int main(int argc, char **argv)\n{\n return 0;\n}\n\n", 0644)
64
- run_chef
65
- expect(archive_provider).to be_a described_class
66
- end
51
+ it do
52
+ expect_file('/test/myapp/LICENSE', "This is in the public domain.\n", 0644)
53
+ expect_file('/test/myapp/README', "This is a project!\n\n", 0644)
54
+ expect(Dir).to receive(:mkdir).with('/test/myapp/src', 0755)
55
+ expect_file('/test/myapp/src/main.c', "int main(int argc, char **argv)\n{\n return 0;\n}\n\n", 0644)
56
+ run_chef
57
+ expect(archive_provider).to be_a described_class
58
+ expect(chef_run).to create_directory('/test/myapp').with(user: 'myuser', group: nil)
59
+ expect(chef_run).to create_directory('/test/myapp/src').with(user: 'myuser', group: nil)
60
+ expect(chef_run).to create_file('/test/myapp/LICENSE').with(user: 'myuser', group: nil)
61
+ expect(chef_run).to create_file('/test/myapp/README').with(user: 'myuser', group: nil)
62
+ expect(chef_run).to create_file('/test/myapp/src/main.c').with(user: 'myuser', group: nil)
67
63
  end
64
+ end
68
65
 
69
- context 'with a .tar path' do
70
- it_should_behave_like 'a poise_archive test', 'tar'
71
- end # /context with a .tar path
66
+ context 'with a .tar path' do
67
+ it_should_behave_like 'a poise_archive tar test', 'tar'
68
+ end # /context with a .tar path
72
69
 
73
- context 'with a .tar.gz path' do
74
- it_should_behave_like 'a poise_archive test', 'tar.gz'
75
- end # /context with a .tar.gz path
70
+ context 'with a .tar.gz path' do
71
+ it_should_behave_like 'a poise_archive tar test', 'tar.gz'
72
+ end # /context with a .tar.gz path
76
73
 
77
- context 'with a .tar.bz2 path' do
78
- it_should_behave_like 'a poise_archive test', 'tar.bz2'
79
- end # /context with a .tar.bz2 path
74
+ context 'with a .tar.bz2 path' do
75
+ it_should_behave_like 'a poise_archive tar test', 'tar.bz2'
76
+ end # /context with a .tar.bz2 path
80
77
 
81
- context 'with a .tgz path' do
82
- it_should_behave_like 'a poise_archive test', 'tgz'
83
- end # /context with a .tgz path
78
+ context 'with a .tgz path' do
79
+ it_should_behave_like 'a poise_archive tar test', 'tgz'
80
+ end # /context with a .tgz path
84
81
 
85
- context 'with a .tbz2 path' do
86
- it_should_behave_like 'a poise_archive test', 'tbz2'
87
- end # /context with a .tbz2 path
88
- end # /describe #action_unpack
82
+ context 'with a .tbz2 path' do
83
+ it_should_behave_like 'a poise_archive tar test', 'tbz2'
84
+ end # /context with a .tbz2 path
89
85
  end
@@ -69,19 +69,83 @@ describe PoiseArchive::Resources::PoiseArchive do
69
69
  end # /context an explicit destination
70
70
  end # /context a relative path
71
71
 
72
- context 'with a two-extension path' do
72
+ context 'with .tar.gz' do
73
73
  recipe do
74
74
  poise_archive '/tmp/myapp.tar.gz'
75
75
  end
76
76
 
77
77
  it { is_expected.to unpack_poise_archive('/tmp/myapp.tar.gz').with(absolute_path: '/tmp/myapp.tar.gz', absolute_destination: '/tmp/myapp') }
78
- end # /context with a two-extension path
78
+ end # /context with .tar.gz
79
+
80
+ context 'with .tgz' do
81
+ recipe do
82
+ poise_archive '/tmp/myapp.tgz'
83
+ end
84
+
85
+ it { is_expected.to unpack_poise_archive('/tmp/myapp.tgz').with(absolute_path: '/tmp/myapp.tgz', absolute_destination: '/tmp/myapp') }
86
+ end # /context with .tgz
87
+
88
+ context 'with .tar.bz2' do
89
+ recipe do
90
+ poise_archive '/tmp/myapp.tar.bz2'
91
+ end
92
+
93
+ it { is_expected.to unpack_poise_archive('/tmp/myapp.tar.bz2').with(absolute_path: '/tmp/myapp.tar.bz2', absolute_destination: '/tmp/myapp') }
94
+ end # /context with .tar.bz2
95
+
96
+ context 'with .tbz2' do
97
+ recipe do
98
+ poise_archive '/tmp/myapp.tbz2'
99
+ end
100
+
101
+ it { is_expected.to unpack_poise_archive('/tmp/myapp.tbz2').with(absolute_path: '/tmp/myapp.tbz2', absolute_destination: '/tmp/myapp') }
102
+ end # /context with .tbz2
103
+
104
+ context 'with .tar.xz' do
105
+ recipe do
106
+ poise_archive '/tmp/myapp.tar.xz'
107
+ end
108
+
109
+ it { is_expected.to unpack_poise_archive('/tmp/myapp.tar.xz').with(absolute_path: '/tmp/myapp.tar.xz', absolute_destination: '/tmp/myapp') }
110
+ end # /context with .tar.xz
111
+
112
+ context 'with .txz' do
113
+ recipe do
114
+ poise_archive '/tmp/myapp.txz'
115
+ end
116
+
117
+ it { is_expected.to unpack_poise_archive('/tmp/myapp.txz').with(absolute_path: '/tmp/myapp.txz', absolute_destination: '/tmp/myapp') }
118
+ end # /context with .txz
119
+
120
+ context 'with .zip' do
121
+ recipe do
122
+ poise_archive '/tmp/myapp.zip'
123
+ end
124
+
125
+ it { is_expected.to unpack_poise_archive('/tmp/myapp.zip').with(absolute_path: '/tmp/myapp.zip', absolute_destination: '/tmp/myapp') }
126
+ end # /context with .zip
79
127
 
80
128
  context 'with a hidden file' do
81
129
  recipe do
82
130
  poise_archive '/tmp/.myapp.tar'
83
131
  end
84
132
 
85
- it { is_expected.to unpack_poise_archive('/tmp/.myapp.tar').with(absolute_path: '/tmp/.myapp.tar', absolute_destination: '/tmp/myapp') }
133
+ it { is_expected.to unpack_poise_archive('/tmp/.myapp.tar').with(absolute_path: '/tmp/.myapp.tar', absolute_destination: '/tmp/.myapp') }
86
134
  end # /context with a hidden file
135
+
136
+ context 'with a version number' do
137
+ recipe do
138
+ poise_archive '/tmp/myapp-1.0.0.tar'
139
+ end
140
+
141
+ it { is_expected.to unpack_poise_archive('/tmp/myapp-1.0.0.tar').with(absolute_path: '/tmp/myapp-1.0.0.tar', absolute_destination: '/tmp/myapp-1.0.0') }
142
+ end # /context with a version number
143
+
144
+ context 'with a version number and .tar.gz' do
145
+ recipe do
146
+ poise_archive '/tmp/myapp-1.0.0.tar.gz'
147
+ end
148
+
149
+ it { is_expected.to unpack_poise_archive('/tmp/myapp-1.0.0.tar.gz').with(absolute_path: '/tmp/myapp-1.0.0.tar.gz', absolute_destination: '/tmp/myapp-1.0.0') }
150
+ end # /context with a version number and .tar.gz
87
151
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: poise-archive
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.2
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Noah Kantrowitz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-04-03 00:00:00.000000000 Z
11
+ date: 2016-04-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: halite
@@ -71,6 +71,7 @@ files:
71
71
  - lib/poise_archive.rb
72
72
  - lib/poise_archive/archive_providers.rb
73
73
  - lib/poise_archive/archive_providers/base.rb
74
+ - lib/poise_archive/archive_providers/gnu_tar.rb
74
75
  - lib/poise_archive/archive_providers/tar.rb
75
76
  - lib/poise_archive/archive_providers/zip.rb
76
77
  - lib/poise_archive/bzip2.rb
@@ -102,6 +103,7 @@ files:
102
103
  - test/gemfiles/chef-12.gemfile
103
104
  - test/gemfiles/master.gemfile
104
105
  - test/integration/default/serverspec/default_spec.rb
106
+ - test/spec/archive_providers/gnu_tar_spec.rb
105
107
  - test/spec/archive_providers/tar_spec.rb
106
108
  - test/spec/archive_providers/zip_spec.rb
107
109
  - test/spec/resources/poise_archive_spec.rb
@@ -148,6 +150,7 @@ test_files:
148
150
  - test/gemfiles/chef-12.gemfile
149
151
  - test/gemfiles/master.gemfile
150
152
  - test/integration/default/serverspec/default_spec.rb
153
+ - test/spec/archive_providers/gnu_tar_spec.rb
151
154
  - test/spec/archive_providers/tar_spec.rb
152
155
  - test/spec/archive_providers/zip_spec.rb
153
156
  - test/spec/resources/poise_archive_spec.rb