poise-archive 1.1.2 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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