Skip to content

Commit

Permalink
chore: Fix various other standard cleanups
Browse files Browse the repository at this point in the history
  • Loading branch information
halostatue committed Aug 7, 2024
1 parent df7e35b commit 6aa45af
Show file tree
Hide file tree
Showing 17 changed files with 499 additions and 539 deletions.
5 changes: 5 additions & 0 deletions .standard.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
---
parallel: true
ruby_version: 3.1

ignore:
- 'minitar.gemspec'

plugins:
- standard-minitest
- standard-thread_safety
2 changes: 2 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,6 @@ Hoe.spec "minitar" do
extra_dev_deps << ["rake", ">= 10.0", "< 14"]
extra_dev_deps << ["rdoc", ">= 0.0"]
extra_dev_deps << ["standard", "~> 1.0"]
extra_dev_deps << ["standard-minitest", "~> 1.0"]
extra_dev_deps << ["standard-thread_safety", "~> 1.0"]
end
320 changes: 146 additions & 174 deletions lib/minitar.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
# # Closes both tar and sgz.
# tar.close
# end
module Minitar
class Minitar
VERSION = "1.0.0".freeze # :nodoc:

# The base class for any minitar error.
Expand All @@ -60,211 +60,183 @@ module Minitar
SecureRelativePathError = Class.new(Error)
# The exception raised when a file contains an invalid Posix header.
InvalidTarStream = Class.new(Error)
end

class << self
# Tests if +path+ refers to a directory. Fixes an apparently
# corrupted <tt>stat()</tt> call on Windows.
def dir?(path)
File.directory?((path[-1] == "/") ? path : "#{path}/")
end
class << Minitar
# Tests if +path+ refers to a directory. Fixes an apparently
# corrupted <tt>stat()</tt> call on Windows.
def dir?(path)
File.directory?((path[-1] == "/") ? path : "#{path}/")
end

# A convenience method for wrapping Minitar::Input.open
# (mode +r+) and Minitar::Output.open (mode +w+). No other
# modes are currently supported.
def open(dest, mode = "r", &)
case mode
when "r"
Input.open(dest, &)
when "w"
Output.open(dest, &block)
else
raise "Unknown open mode for Minitar.open."
end
# A convenience method for wrapping Minitar::Input.open
# (mode +r+) and Minitar::Output.open (mode +w+). No other
# modes are currently supported.
def open(dest, mode = "r", &)
case mode
when "r"
Input.open(dest, &)
when "w"
Output.open(dest, &block)
else
raise "Unknown open mode for Minitar.open."
end
end

def const_missing(c) # :nodoc:
case c
when :BlockRequired
warn "This constant has been removed."
const_set(:BlockRequired, Class.new(StandardError))
else
super
end
def const_missing(c) # :nodoc:
case c
when :BlockRequired
warn "This constant has been removed."
const_set(:BlockRequired, Class.new(StandardError))
else
super
end
end

def windows? # :nodoc:
RbConfig::CONFIG["host_os"] =~ /^(mswin|mingw|cygwin)/
end
def windows? # :nodoc:
RbConfig::CONFIG["host_os"] =~ /^(mswin|mingw|cygwin)/
end

# A convenience method to pack the file provided. +entry+ may either be a
# filename (in which case various values for the file (see below) will be
# obtained from <tt>File#stat(entry)</tt> or a Hash with the fields:
#
# <tt>:name</tt>:: The filename to be packed into the archive. Required.
# <tt>:mode</tt>:: The mode to be applied.
# <tt>:uid</tt>:: The user owner of the file. (Ignored on Windows.)
# <tt>:gid</tt>:: The group owner of the file. (Ignored on Windows.)
# <tt>:mtime</tt>:: The modification Time of the file.
#
# During packing, if a block is provided, #pack_file yields an +action+ Symol, the
# full name of the file being packed, and a Hash of statistical information, just as
# with Minitar::Input#extract_entry.
#
# The +action+ will be one of:
# <tt>:dir</tt>:: The +entry+ is a directory.
# <tt>:file_start</tt>:: The +entry+ is a file; the extract of the
# file is just beginning.
# <tt>:file_progress</tt>:: Yielded every 4096 bytes during the extract
# of the +entry+.
# <tt>:file_done</tt>:: Yielded when the +entry+ is completed.
#
# The +stats+ hash contains the following keys:
# <tt>:current</tt>:: The current total number of bytes read in the
# +entry+.
# <tt>:currinc</tt>:: The current number of bytes read in this read
# cycle.
# <tt>:name</tt>:: The filename to be packed into the tarchive.
# *REQUIRED*.
# <tt>:mode</tt>:: The mode to be applied.
# <tt>:uid</tt>:: The user owner of the file. (+nil+ on Windows.)
# <tt>:gid</tt>:: The group owner of the file. (+nil+ on Windows.)
# <tt>:mtime</tt>:: The modification Time of the file.
def pack_file(entry, outputter) # :yields action, name, stats:
if outputter.is_a?(Minitar::Output)
outputter = outputter.tar
end
# A convenience method to pack the file provided. +entry+ may either be a
# filename (in which case various values for the file (see below) will be
# obtained from <tt>File#stat(entry)</tt> or a Hash with the fields:
#
# <tt>:name</tt>:: The filename to be packed into the archive. Required.
# <tt>:mode</tt>:: The mode to be applied.
# <tt>:uid</tt>:: The user owner of the file. (Ignored on Windows.)
# <tt>:gid</tt>:: The group owner of the file. (Ignored on Windows.)
# <tt>:mtime</tt>:: The modification Time of the file.
#
# During packing, if a block is provided, #pack_file yields an +action+ Symol, the
# full name of the file being packed, and a Hash of statistical information, just as
# with Minitar::Input#extract_entry.
#
# The +action+ will be one of:
# <tt>:dir</tt>:: The +entry+ is a directory.
# <tt>:file_start</tt>:: The +entry+ is a file; the extract of the
# file is just beginning.
# <tt>:file_progress</tt>:: Yielded every 4096 bytes during the extract
# of the +entry+.
# <tt>:file_done</tt>:: Yielded when the +entry+ is completed.
#
# The +stats+ hash contains the following keys:
# <tt>:current</tt>:: The current total number of bytes read in the
# +entry+.
# <tt>:currinc</tt>:: The current number of bytes read in this read
# cycle.
# <tt>:name</tt>:: The filename to be packed into the tarchive.
# *REQUIRED*.
# <tt>:mode</tt>:: The mode to be applied.
# <tt>:uid</tt>:: The user owner of the file. (+nil+ on Windows.)
# <tt>:gid</tt>:: The group owner of the file. (+nil+ on Windows.)
# <tt>:mtime</tt>:: The modification Time of the file.
def pack_file(entry, outputter) # :yields action, name, stats:
if outputter.is_a?(Minitar::Output)
outputter = outputter.tar
end

stats = {}
stats = {}

if entry.is_a?(Hash)
name = entry[:name]
entry.each { |kk, vv| stats[kk] = vv unless vv.nil? }
else
name = entry
end
if entry.is_a?(Hash)
name = entry[:name]
entry.each { |kk, vv| stats[kk] = vv unless vv.nil? }
else
name = entry
end

name = name.sub(%r{\./}, "")
stat = File.stat(name)
stats[:mode] ||= stat.mode
stats[:mtime] ||= stat.mtime
stats[:size] = stat.size
name = name.sub(%r{\./}, "")
stat = File.stat(name)
stats[:mode] ||= stat.mode
stats[:mtime] ||= stat.mtime
stats[:size] = stat.size

if windows?
stats[:uid] = nil
stats[:gid] = nil
else
stats[:uid] ||= stat.uid
stats[:gid] ||= stat.gid
end
if windows?
stats[:uid] = nil
stats[:gid] = nil
else
stats[:uid] ||= stat.uid
stats[:gid] ||= stat.gid
end

if File.file?(name)
outputter.add_file_simple(name, stats) do |os|
stats[:current] = 0
yield :file_start, name, stats if block_given?
File.open(name, "rb") do |ff|
until ff.eof?
stats[:currinc] = os.write(ff.read(4096))
stats[:current] += stats[:currinc]
yield :file_progress, name, stats if block_given?
end
if File.file?(name)
outputter.add_file_simple(name, stats) do |os|
stats[:current] = 0
yield :file_start, name, stats if block_given?
File.open(name, "rb") do |ff|
until ff.eof?
stats[:currinc] = os.write(ff.read(4096))
stats[:current] += stats[:currinc]
yield :file_progress, name, stats if block_given?
end
yield :file_done, name, stats if block_given?
end
elsif dir?(name)
yield :dir, name, stats if block_given?
outputter.mkdir(name, stats)
else
raise "Don't yet know how to pack this type of file."
yield :file_done, name, stats if block_given?
end
elsif dir?(name)
yield :dir, name, stats if block_given?
outputter.mkdir(name, stats)
else
raise "Don't yet know how to pack this type of file."
end
end

# A convenience method to pack files specified by +src+ into +dest+. If
# +src+ is an Array, then each file detailed therein will be packed into
# the resulting Minitar::Output stream; if +recurse_dirs+ is
# true, then directories will be recursed.
#
# If +src+ is not an Array, it will be treated as the result of Find.find;
# all files matching will be packed.
def pack(src, dest, recurse_dirs = true, &block)
require "find"
Output.open(dest) do |outp|
if src.is_a?(Array)
src.each do |entry|
if dir?(entry) && recurse_dirs
Find.find(entry) do |ee|
pack_file(ee, outp, &block)
end
else
pack_file(entry, outp, &block)
# A convenience method to pack files specified by +src+ into +dest+. If
# +src+ is an Array, then each file detailed therein will be packed into
# the resulting Minitar::Output stream; if +recurse_dirs+ is
# true, then directories will be recursed.
#
# If +src+ is not an Array, it will be treated as the result of Find.find;
# all files matching will be packed.
def pack(src, dest, recurse_dirs = true, &block)
require "find"
Minitar::Output.open(dest) do |outp|
if src.is_a?(Array)
src.each do |entry|
if dir?(entry) && recurse_dirs
Find.find(entry) do |ee|
pack_file(ee, outp, &block)
end
end
else
Find.find(src) do |entry|
else
pack_file(entry, outp, &block)
end
end
end
end

# A convenience method to unpack files from +src+ into the directory
# specified by +dest+. Only those files named explicitly in +files+
# will be extracted.
def unpack(src, dest, files = [], options = {}, &block)
Input.open(src) do |inp|
if File.exist?(dest) && !dir?(dest)
raise "Can't unpack to a non-directory."
end

FileUtils.mkdir_p(dest) unless File.exist?(dest)

inp.each do |entry|
if files.empty? || files.include?(entry.full_name)
inp.extract_entry(dest, entry, options, &block)
end
else
Find.find(src) do |entry|
pack_file(entry, outp, &block)
end
end
end
end

# Check whether +io+ can seek without errors.
def seekable?(io, methods = nil)
# The IO class throws an exception at runtime if we try to change
# position on a non-regular file.
if io.respond_to?(:stat)
io.stat.file?
else
# Duck-type the rest of this.
methods ||= [:pos, :pos=, :seek, :rewind]
methods = [methods] unless methods.is_a?(Array)
methods.all? { |m| io.respond_to?(m) }
# A convenience method to unpack files from +src+ into the directory
# specified by +dest+. Only those files named explicitly in +files+
# will be extracted.
def unpack(src, dest, files = [], options = {}, &block)
Minitar::Input.open(src) do |inp|
if File.exist?(dest) && !dir?(dest)
raise "Can't unpack to a non-directory."
end
end

private

def included(mod)
return if modules.include?(mod)
warn "Including #{self} has been deprecated (Minitar will become a class)."
modules << mod
end
FileUtils.mkdir_p(dest) unless File.exist?(dest)

def modules
require "set"
@modules ||= Set.new
inp.each do |entry|
if files.empty? || files.include?(entry.full_name)
inp.extract_entry(dest, entry, options, &block)
end
end
end
end

# This exists to make bytesize implementations work across Ruby versions.
module ByteSize # :nodoc:
private

if "".respond_to?(:bytesize)
def bytesize(item)
item.bytesize
end
# Check whether +io+ can seek without errors.
def seekable?(io, methods = nil)
# The IO class throws an exception at runtime if we try to change
# position on a non-regular file.
if io.respond_to?(:stat)
io.stat.file?
else
def bytesize(item)
item.size
end
# Duck-type the rest of this.
methods ||= [:pos, :pos=, :seek, :rewind]
methods = [methods] unless methods.is_a?(Array)
methods.all? { |m| io.respond_to?(m) }
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/minitar/input.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
require "minitar/reader"

module Minitar
class Minitar
# Wraps a Minitar::Reader with convenience methods and wrapped
# stream management; Input only works with data streams that can be rewound.
class Input
Expand Down
2 changes: 1 addition & 1 deletion lib/minitar/output.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
require "minitar/writer"

module Minitar
class Minitar
# Wraps a Minitar::Writer with convenience methods and wrapped
# stream management. If the stream provided to Output does not support random
# access, only Writer#add_file_simple and Writer#mkdir are guaranteed to
Expand Down
Loading

0 comments on commit 6aa45af

Please sign in to comment.