From aaa3c63261fdb349674e384673c0a1f6e8f09942 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crazy=E5=87=A1?= <827799383@qq.com> Date: Mon, 8 May 2023 19:53:57 +0800 Subject: [PATCH] Add zstd support. --- Gemfile | 1 + cocoapods-downloader.gemspec | 2 ++ lib/cocoapods-downloader/remote_file.rb | 33 ++++++++++++++++-- .../fixtures/remote_file/lib_multiple.tar.zst | Bin 0 -> 163 bytes spec/remote_file_spec.rb | 13 +++++++ 5 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 spec/fixtures/remote_file/lib_multiple.tar.zst diff --git a/Gemfile b/Gemfile index 13ac913..7a16f0a 100644 --- a/Gemfile +++ b/Gemfile @@ -18,4 +18,5 @@ group :development do gem 'rubocop' gem 'codeclimate-test-reporter', :require => nil gem 'simplecov' + gem 'zstd-ruby', '~> 1.5' end diff --git a/cocoapods-downloader.gemspec b/cocoapods-downloader.gemspec index 25f2dce..153e076 100644 --- a/cocoapods-downloader.gemspec +++ b/cocoapods-downloader.gemspec @@ -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 diff --git a/lib/cocoapods-downloader/remote_file.rb b/lib/cocoapods-downloader/remote_file.rb index 3388342..6a82fcb 100644 --- a/lib/cocoapods-downloader/remote_file.rb +++ b/lib/cocoapods-downloader/remote_file.rb @@ -1,6 +1,8 @@ require 'fileutils' require 'uri' require 'zlib' +require 'zstd-ruby' +require 'pathname' module Pod module Downloader @@ -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 @@ -68,6 +70,8 @@ def type_with_url(url) :tbz when /\.(txz|tar\.xz)$/ :txz + when /\.(tzst|tar\.zst)$/ + :zst when /\.dmg$/ :dmg end @@ -75,7 +79,7 @@ def type_with_url(url) 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}" @@ -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 @@ -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 diff --git a/spec/fixtures/remote_file/lib_multiple.tar.zst b/spec/fixtures/remote_file/lib_multiple.tar.zst new file mode 100644 index 0000000000000000000000000000000000000000..af3e0ad9e737c56c2713d6eb84f176023fb49609 GIT binary patch literal 163 zcmV;U09^klwJ-euh}8rDG6xnBkbMA*o{&a)_vj8OFkD{+EeC{mb>0$sb1WUpxZZ&& zB$aYb$~%ikB_yPvQTzdfEn_g}{0FyXtO0Uh(lO+n5P}d% 'be62f423e2afde57ae7d79ba7bd3443df73e0021' } @@ -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