diff --git a/Library/.rubocop.yml b/Library/.rubocop.yml index 3a453e8c50..83165428c6 100644 --- a/Library/.rubocop.yml +++ b/Library/.rubocop.yml @@ -279,6 +279,7 @@ Sorbet/FalseSigil: - 'Homebrew/test/**/Casks/**/*.rb' Sorbet/StrictSigil: + Enabled: true Include: - '**/*.rbi' diff --git a/Library/Homebrew/extend/os/mac/unpack_strategy/zip.rb b/Library/Homebrew/extend/os/mac/unpack_strategy/zip.rb index d90cdb21f5..b804e49f35 100644 --- a/Library/Homebrew/extend/os/mac/unpack_strategy/zip.rb +++ b/Library/Homebrew/extend/os/mac/unpack_strategy/zip.rb @@ -1,9 +1,19 @@ -# typed: false +# typed: strict # frozen_string_literal: true +require "system_command" + module UnpackStrategy class Zip module MacOSZipExtension + extend T::Sig + + include UnpackStrategy + include SystemCommand::Mixin + + using Magic + + sig { override.params(unpack_dir: Pathname, basename: Pathname, verbose: T::Boolean).returns(T.untyped) } def extract_to_dir(unpack_dir, basename:, verbose:) if merge_xattrs && contains_extended_attributes?(path) # We use ditto directly, because dot_clean has issues if the __MACOSX @@ -16,7 +26,7 @@ module UnpackStrategy end result = begin - super + T.let(super, SystemCommand::Result) rescue ErrorDuringExecution => e raise unless e.stderr.include?("End-of-central-directory signature not found.") @@ -47,6 +57,13 @@ module UnpackStrategy end end end + + private + + sig { params(path: Pathname).returns(T::Boolean) } + def contains_extended_attributes?(path) + path.zipinfo.grep(/(^__MACOSX|\._)/).any? + end end private_constant :MacOSZipExtension diff --git a/Library/Homebrew/extend/os/mac/unpack_strategy/zip.rbi b/Library/Homebrew/extend/os/mac/unpack_strategy/zip.rbi new file mode 100644 index 0000000000..ee40416382 --- /dev/null +++ b/Library/Homebrew/extend/os/mac/unpack_strategy/zip.rbi @@ -0,0 +1,9 @@ +# typed: strict + +module UnpackStrategy + class Zip + module MacOSZipExtension + include Kernel + end + end +end diff --git a/Library/Homebrew/sorbet/config b/Library/Homebrew/sorbet/config index 02fbf5ab02..024ba458ec 100644 --- a/Library/Homebrew/sorbet/config +++ b/Library/Homebrew/sorbet/config @@ -6,3 +6,6 @@ --ignore /test/.gem + +--dsl-plugins +sorbet/triggers.yml diff --git a/Library/Homebrew/sorbet/plugins/unpack_strategy_magic.rb b/Library/Homebrew/sorbet/plugins/unpack_strategy_magic.rb new file mode 100644 index 0000000000..d5c83fa8b5 --- /dev/null +++ b/Library/Homebrew/sorbet/plugins/unpack_strategy_magic.rb @@ -0,0 +1,21 @@ +# typed: strict +# frozen_string_literal: true + +source = ARGV[5] + +/\busing +Magic\b/.match(source) do |_| + puts <<-RUBY + # typed: strict + + class ::Pathname + sig { returns(String) } + def magic_number; end + + sig { returns(String) } + def file_type; end + + sig { returns(T::Array[String]) } + def zipinfo; end + end + RUBY +end diff --git a/Library/Homebrew/sorbet/triggers.yml b/Library/Homebrew/sorbet/triggers.yml new file mode 100644 index 0000000000..52bc3b2aea --- /dev/null +++ b/Library/Homebrew/sorbet/triggers.yml @@ -0,0 +1,5 @@ +ruby_extra_args: + - --disable-gems + +triggers: + using: sorbet/plugins/unpack_strategy_magic.rb diff --git a/Library/Homebrew/unpack_strategy.rb b/Library/Homebrew/unpack_strategy.rb index 774d296156..c187be8286 100644 --- a/Library/Homebrew/unpack_strategy.rb +++ b/Library/Homebrew/unpack_strategy.rb @@ -7,12 +7,16 @@ require "system_command" # # @api private module UnpackStrategy + extend T::Sig + extend T::Helpers + include SystemCommand::Mixin # Helper module for identifying the file type. module Magic # Length of the longest regex (currently Tar). MAX_MAGIC_NUMBER_LENGTH = 262 + private_constant :MAX_MAGIC_NUMBER_LENGTH refine Pathname do def magic_number @@ -125,11 +129,16 @@ module UnpackStrategy @merge_xattrs = merge_xattrs end - def extract(to: nil, basename: nil, verbose: false) + abstract! + sig { abstract.params(unpack_dir: Pathname, basename: Pathname, verbose: T::Boolean).returns(T.untyped) } + def extract_to_dir(unpack_dir, basename:, verbose:); end + private :extract_to_dir + + def extract(to: nil, basename: nil, verbose: nil) basename ||= path.basename unpack_dir = Pathname(to || Dir.pwd).expand_path unpack_dir.mkpath - extract_to_dir(unpack_dir, basename: basename, verbose: verbose) + extract_to_dir(unpack_dir, basename: Pathname(basename), verbose: verbose || false) end def extract_nestedly(to: nil, basename: nil, verbose: false, prioritise_extension: false) diff --git a/Library/Homebrew/unpack_strategy.rbi b/Library/Homebrew/unpack_strategy.rbi new file mode 100644 index 0000000000..d7550c56b2 --- /dev/null +++ b/Library/Homebrew/unpack_strategy.rbi @@ -0,0 +1,5 @@ +# typed: strict + +module UnpackStrategy + include Kernel +end diff --git a/Library/Homebrew/unpack_strategy/zip.rb b/Library/Homebrew/unpack_strategy/zip.rb index 09db337f84..ac5238d5ca 100644 --- a/Library/Homebrew/unpack_strategy/zip.rb +++ b/Library/Homebrew/unpack_strategy/zip.rb @@ -1,27 +1,31 @@ -# typed: true +# typed: strict # frozen_string_literal: true module UnpackStrategy # Strategy for unpacking ZIP archives. class Zip + extend T::Sig + include UnpackStrategy using Magic + sig { returns(T::Array[String]) } def self.extensions [".zip"] end + sig { params(path: Pathname).returns(T::Boolean) } def self.can_extract?(path) path.magic_number.match?(/\APK(\003\004|\005\006)/n) end private - def contains_extended_attributes?(path) - path.zipinfo.grep(/(^__MACOSX|\._)/).any? + sig do + override.params(unpack_dir: Pathname, basename: Pathname, verbose: T::Boolean) + .returns(SystemCommand::Result) end - def extract_to_dir(unpack_dir, basename:, verbose:) quiet_flags = verbose ? [] : ["-qq"] result = system_command! "unzip",