Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Berks package corrupt archive fixed using relative path #6

Merged
merged 3 commits into from Jun 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
17 changes: 17 additions & 0 deletions features/commands/package.feature
Expand Up @@ -15,3 +15,20 @@ Feature: berks package
"""
Cookbook(s) packaged to
"""
And the archive "my-cookbooks.tar.gz" should contain:
"""
cookbooks
cookbooks/fake
cookbooks/fake/attributes
cookbooks/fake/attributes/default.rb
cookbooks/fake/files
cookbooks/fake/files/default
cookbooks/fake/files/default/file.h
cookbooks/fake/metadata.json
cookbooks/fake/metadata.rb
cookbooks/fake/recipes
cookbooks/fake/recipes/default.rb
cookbooks/fake/templates
cookbooks/fake/templates/default
cookbooks/fake/templates/default/template.erb
"""
7 changes: 7 additions & 0 deletions features/step_definitions/utility_steps.rb
Expand Up @@ -2,6 +2,13 @@
skip
end

Then("the archive {string} should contain:") do |path, expected_contents|
actual_contents = Zlib::GzipReader.open(expand_path(path)) do |gz|
Archive::Tar::Minitar::Input.each_entry(gz).map(&:full_name).join("\n")
end
expect(actual_contents).to eql(expected_contents)
end

Then /the output from \`(.+)\` should be the same as \`(.+)\`/ do |actual, expected|
run(actual)
actual_output = last_command_started.stdout
Expand Down
40 changes: 38 additions & 2 deletions lib/berkshelf/packager.rb
@@ -1,4 +1,5 @@
require "archive/tar/minitar"
require "find" unless defined?(Find)
require "zlib" unless defined?(Zlib)

module Berkshelf
Expand Down Expand Up @@ -40,8 +41,18 @@ def initialize(out_file)
# @return [String]
# path to the generated archive
def run(source)
tgz = Zlib::GzipWriter.new(File.open(out_file, "wb"))
Archive::Tar::Minitar.pack(Dir.glob("#{source}/*"), tgz)
begin
dest = Zlib::GzipWriter.open(out_file)
tar = RelativeTarWriter.new(dest, source)
Find.find(source) do |entry|
next if source == entry

Archive::Tar::Minitar.pack_file(entry, tar)
end
ensure
tar.close
dest.close
end

out_file
rescue SystemCallError => ex
Expand All @@ -67,5 +78,30 @@ def validate!

# @return [String]
attr_reader :filename

# A private decorator for Archive::Tar::Minitar::Writer that
# turns absolute paths into relative ones.
class RelativeTarWriter < SimpleDelegator # :nodoc:
def initialize(io, base_path)
@base_path = Pathname.new(base_path)
super(Archive::Tar::Minitar::Writer.new(io))
end

%w{add_file add_file_simple mkdir}.each do |method|
class_eval <<~RUBY
def #{method}(name, *opts, &block)
super(relative_path(name), *opts, &block)
end
RUBY
end

private

attr_reader :base_path

def relative_path(path)
Pathname.new(path).relative_path_from(base_path).to_s
end
end
end
end