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

Add zstd support. #144

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ group :development do
gem 'rubocop'
gem 'codeclimate-test-reporter', :require => nil
gem 'simplecov'
gem 'zstd-ruby', '~> 1.5'
end
2 changes: 2 additions & 0 deletions cocoapods-downloader.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,6 @@ Gem::Specification.new do |s|

s.required_ruby_version = '>= 2.6'
s.specification_version = 3 if s.respond_to? :specification_version

s.add_runtime_dependency 'zstd-ruby', '~> 1.5'
end
33 changes: 31 additions & 2 deletions lib/cocoapods-downloader/remote_file.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
require 'fileutils'
require 'uri'
require 'zlib'
require 'zstd-ruby'
require 'pathname'

module Pod
module Downloader
Expand Down Expand Up @@ -49,7 +51,7 @@ def headers
def should_flatten?
if options.key?(:flatten)
options[:flatten]
elsif [:tgz, :tar, :tbz, :txz].include?(type)
elsif [:tgz, :tar, :tbz, :txz, :zst].include?(type)
true # those archives flatten by default
else
false # all others (actually only .zip) default not to flatten
Expand All @@ -68,14 +70,16 @@ def type_with_url(url)
:tbz
when /\.(txz|tar\.xz)$/
:txz
when /\.(tzst|tar\.zst)$/
:zst
when /\.dmg$/
:dmg
end
end

def filename_with_type(type = :zip)
case type
when :zip, :tgz, :tar, :tbz, :txz, :dmg
when :zip, :tgz, :tar, :tbz, :txz, :zst, :dmg
"file.#{type}"
else
raise UnsupportedFileTypeError, "Unsupported file type: #{type}"
Expand All @@ -95,6 +99,8 @@ def extract_with_type(full_filename, type = :zip)
unzip! unpack_from, '-d', unpack_to
when :tar, :tgz, :tbz, :txz
tar! 'xf', unpack_from, '-C', unpack_to
when :zst
extract_tar_zstd(unpack_from, unpack_to)
when :dmg
extract_dmg(unpack_from, unpack_to)
else
Expand Down Expand Up @@ -132,6 +138,29 @@ def extract_dmg(unpack_from, unpack_to)
hdiutil! 'detach', mount_point
end

def extract_tar_zstd(unpack_from, unpack_to)
tmp_tar_file = unpack_from.sub_ext(".tmp.tar")

begin
stream = Zstd::StreamingDecompress.new

File.open(unpack_from, 'rb') do |io|
buffer_size = 1024 * 1024
File.open(tmp_tar_file, 'wb') do |output|
until io.eof?
output.write(stream.decompress(io.read(buffer_size)))
end
end
end

tar! 'xf', tmp_tar_file, '-C', unpack_to
rescue StandardError => e
raise "Failed to decompress file: #{e}"
ensure
FileUtils.rm(tmp_tar_file) if File.exist?(tmp_tar_file)
end
end

def compare_hash(filename, hasher, hash)
incremental_hash = hasher.new

Expand Down
Binary file added spec/fixtures/remote_file/lib_multiple.tar.zst
Binary file not shown.
13 changes: 13 additions & 0 deletions spec/remote_file_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,14 @@ def download_file(full_filename)
downloader.head_supported?.should.be.false
end

it 'does not move unpacked contents to parent dir when archive contains multiple children' do
downloader = MockRemoteFile.new(tmp_folder, "#{@fixtures_url}/lib_multiple.tar.zst", {})
downloader.download
tmp_folder('lib_1/file.txt').should.exist
tmp_folder('lib_2/file.txt').should.exist
tmp_folder('lib_multiple.tar.zst').should.not.exist
end

describe 'concerning archive validation' do
it 'verifies that the downloaded file matches a sha1 hash' do
options = { :sha1 => 'be62f423e2afde57ae7d79ba7bd3443df73e0021' }
Expand Down Expand Up @@ -166,6 +174,11 @@ def download_file(full_filename)
downloader.send(:type).should == :txz
end

it 'detects zst files' do
downloader = MockRemoteFile.new(tmp_folder, 'file:///path/to/file.tar.zst', {})
downloader.send(:type).should == :zst
end

it 'detects dmg files' do
downloader = MockRemoteFile.new(tmp_folder, 'file:///path/to/file.dmg', {})
downloader.send(:type).should == :dmg
Expand Down