Module: Omnizip::Convenience
- Included in:
- Omnizip
- Defined in:
- lib/omnizip/convenience.rb
Overview
Convenience methods for common archive operations.
All public methods accept an optional format: keyword (default
:zip) that selects the underlying archive handler via
Omnizip::ArchiveHandler. New formats gain access to the convenience
API by registering a handler; no edits to this file are needed.
Constant Summary collapse
- DEFAULT_FORMAT =
:zip- ARCHIVE_FORMAT_EXTENSIONS =
Extension -> single-file compressor map. Each lambda takes (input_path, output_path, options). These formats are streams, not archives, so they bypass ArchiveHandler. Extensions naming archive formats with a registered handler; routed when the caller did not pass an explicit
format:. { ".zip" => :zip, ".tar" => :tar, ".7z" => :seven_zip, }.freeze
- READ_ONLY_FORMAT_EXTENSIONS =
Extensions naming real formats this gem can READ but not write through the convenience API. Writing them a ZIP under a foreign name was silent corruption; failing truthfully is the only honest behavior.
[".rar", ".iso", ".cpio"].freeze
- SINGLE_FILE_COMPRESSORS =
{ ".gz" => lambda do |input, output, | Omnizip::Formats::Gzip.compress(input, output, ) end, ".bz2" => lambda do |input, output, | Omnizip::Formats::Bzip2File.compress(input, output, ) end, ".xz" => lambda do |input, output, | Omnizip::Formats::Xz.create(::File.binread(input), output, ) end, ".lzma" => lambda do |input, output, | ::File.open(input, "rb") do |input_io| ::File.open(output, "wb") do |output_io| Omnizip::Formats::LzmaAlone.compress_stream(input_io, output_io, ) end end end, ".lz" => lambda do |input, output, | ::File.open(input, "rb") do |input_io| ::File.open(output, "wb") do |output_io| Omnizip::Formats::Lzip.compress_stream(input_io, output_io, ) end end end, }.freeze
Instance Method Summary collapse
-
#add_to_archive(archive_path, entry_name, source_path, format: DEFAULT_FORMAT) ⇒ String
Add a file to an existing archive.
-
#compress_directory(input_dir, output_path, format: DEFAULT_FORMAT, recursive: true, **options) ⇒ String
Compress a directory into an archive.
-
#compress_file(input_path, output_path, format: DEFAULT_FORMAT, **options) ⇒ String
Compress a single file into an archive.
-
#create_rar(archive_path, **options, &block) ⇒ Object
Create a RAR archive (requires RAR license — see NotLicensedError).
-
#extract_archive(archive_path, output_dir, format: DEFAULT_FORMAT, overwrite: false, **options) ⇒ Array<String>
Extract an archive to a directory.
-
#list_archive(archive_path, format: DEFAULT_FORMAT, details: false, **options) ⇒ Array<String>, Array<Hash>
List contents of an archive.
-
#read_from_archive(archive_path, entry_name, format: DEFAULT_FORMAT) ⇒ String
Read a single entry from an archive.
-
#remove_from_archive(archive_path, entry_name, format: DEFAULT_FORMAT) ⇒ String
Remove an entry from an existing archive.
-
#resolve_archive_format(path, format) ⇒ Object
Archive format for a path: an explicit
formatwins unless it is the default; otherwise the extension routes. -
#single_file_handler(output_path) ⇒ Object
The single-file compressor matching the output extension, or nil.
Instance Method Details
#add_to_archive(archive_path, entry_name, source_path, format: DEFAULT_FORMAT) ⇒ String
Add a file to an existing archive.
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/omnizip/convenience.rb', line 127 def add_to_archive(archive_path, entry_name, source_path, format: DEFAULT_FORMAT) require_archive!(archive_path) unless ::File.exist?(source_path) raise Errno::ENOENT, "Source file not found: #{source_path}" end handler = Omnizip::ArchiveHandler.for(resolve_archive_format(archive_path, format)) # allowed: handler is a registered duck; missing add_entry raises below if handler.respond_to?(:add_entry) handler.add_entry(archive_path, entry_name, source_path) else raise Omnizip::UnsupportedFormatError, "Format #{format.inspect} does not support adding entries" end archive_path end |
#compress_directory(input_dir, output_path, format: DEFAULT_FORMAT, recursive: true, **options) ⇒ String
Compress a directory into an archive.
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/omnizip/convenience.rb', line 58 def compress_directory(input_dir, output_path, format: DEFAULT_FORMAT, recursive: true, **) unless ::File.exist?(input_dir) raise Errno::ENOENT, "Input directory not found: #{input_dir}" end unless ::File.directory?(input_dir) raise ArgumentError, "Input is not a directory: #{input_dir}" end if [:profile] first_file = find_first_file(input_dir) apply_profile(first_file, ) end Omnizip::ArchiveHandler.for(resolve_archive_format(output_path, format)).create(output_path) do |archive| add_directory_contents(archive, input_dir, "", recursive: recursive) end output_path end |
#compress_file(input_path, output_path, format: DEFAULT_FORMAT, **options) ⇒ String
Compress a single file into an archive.
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/omnizip/convenience.rb', line 20 def compress_file(input_path, output_path, format: DEFAULT_FORMAT, **) unless ::File.exist?(input_path) raise Errno::ENOENT, "Input file not found: #{input_path}" end if ::File.directory?(input_path) raise ArgumentError, "Input is a directory: #{input_path}" end = apply_profile(input_path, ) if [:profile] if [:chunked] return Omnizip::Chunked.compress_file(input_path, output_path, **) end # Single-file compression formats route by output extension # (unless an archive format was requested explicitly): writing # output.lzma through the archive path silently produced a ZIP # under a foreign extension. if format == DEFAULT_FORMAT && (handler = single_file_handler(output_path)) handler.call(input_path, output_path, ) return output_path end Omnizip::ArchiveHandler.for(resolve_archive_format(output_path, format)).create(output_path) do |archive| archive.add(::File.basename(input_path), input_path) end output_path end |
#create_rar(archive_path, **options, &block) ⇒ Object
Create a RAR archive (requires RAR license — see NotLicensedError). rubocop:disable-next Naming/BlockForwarding, Style/ArgumentsForwarding -- Ruby 3.0 compatibility
167 168 169 170 |
# File 'lib/omnizip/convenience.rb', line 167 def create_rar(archive_path, **, &block) [:version] ||= 5 Omnizip::Formats::Rar.create(archive_path, , &block) end |
#extract_archive(archive_path, output_dir, format: DEFAULT_FORMAT, overwrite: false, **options) ⇒ Array<String>
Extract an archive to a directory.
87 88 89 90 91 92 93 |
# File 'lib/omnizip/convenience.rb', line 87 def extract_archive(archive_path, output_dir, format: DEFAULT_FORMAT, overwrite: false, **) require_archive!(archive_path) Omnizip::ArchiveHandler.for(resolve_archive_format(archive_path, format)) .extract_to(archive_path, output_dir, overwrite: overwrite, **) end |
#list_archive(archive_path, format: DEFAULT_FORMAT, details: false, **options) ⇒ Array<String>, Array<Hash>
List contents of an archive.
102 103 104 105 106 107 |
# File 'lib/omnizip/convenience.rb', line 102 def list_archive(archive_path, format: DEFAULT_FORMAT, details: false, **) require_archive!(archive_path) Omnizip::ArchiveHandler.for(resolve_archive_format(archive_path, format)) .list(archive_path, details: details, **) end |
#read_from_archive(archive_path, entry_name, format: DEFAULT_FORMAT) ⇒ String
Read a single entry from an archive.
115 116 117 118 |
# File 'lib/omnizip/convenience.rb', line 115 def read_from_archive(archive_path, entry_name, format: DEFAULT_FORMAT) require_archive!(archive_path) Omnizip::ArchiveHandler.for(resolve_archive_format(archive_path, format)).read_entry(archive_path, entry_name) end |
#remove_from_archive(archive_path, entry_name, format: DEFAULT_FORMAT) ⇒ String
Remove an entry from an existing archive.
152 153 154 155 156 157 158 159 160 161 162 163 |
# File 'lib/omnizip/convenience.rb', line 152 def remove_from_archive(archive_path, entry_name, format: DEFAULT_FORMAT) require_archive!(archive_path) handler = Omnizip::ArchiveHandler.for(resolve_archive_format(archive_path, format)) # allowed: handler is a registered duck; missing remove_entry raises below unless handler.respond_to?(:remove_entry) raise Omnizip::UnsupportedFormatError, "Format #{format.inspect} does not support removing entries" end handler.remove_entry(archive_path, entry_name) archive_path end |
#resolve_archive_format(path, format) ⇒ Object
Archive format for a path: an explicit format wins unless it
is the default; otherwise the extension routes. Known-but-
unwritable extensions raise instead of receiving a mislabeled
ZIP.
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 |
# File 'lib/omnizip/convenience.rb', line 227 def resolve_archive_format(path, format) return format unless format == DEFAULT_FORMAT ext = ::File.extname(path).downcase routed = ARCHIVE_FORMAT_EXTENSIONS[ext] return routed if routed if READ_ONLY_FORMAT_EXTENSIONS.include?(ext) raise Omnizip::UnsupportedFormatError, "#{ext} archives cannot be written by the convenience " \ "API (read-only support); use the format-specific reader" end DEFAULT_FORMAT end |
#single_file_handler(output_path) ⇒ Object
The single-file compressor matching the output extension, or nil.
218 219 220 221 |
# File 'lib/omnizip/convenience.rb', line 218 def single_file_handler(output_path) ext = ::File.extname(output_path).downcase SINGLE_FILE_COMPRESSORS[ext] end |