lib/fontist/import/recursive_extraction.rb in fontist-1.8.7 vs lib/fontist/import/recursive_extraction.rb in fontist-1.8.8
- old
+ new
@@ -1,23 +1,20 @@
-require "find"
-require_relative "extractors"
require_relative "files/font_detector"
module Fontist
module Import
class RecursiveExtraction
- FONTS_PATTERN = "**/*.{ttf,otf,ttc}".freeze
- ARCHIVE_EXTENSIONS = %w[zip msi exe cab].freeze
LICENSE_PATTERN = /(ofl\.txt|ufl\.txt|licenses?\.txt|copying)$/i.freeze
def initialize(archive, subarchive: nil, subdir: nil)
@archive = archive
- @subarchive = subarchive
@subdir = subdir
- @operations = []
+ @operations = {}
@font_files = []
@collection_files = []
+
+ save_operation_subdir
end
def extension
fetch_extension(@archive)
end
@@ -37,15 +34,22 @@
@license_text
end
def operations
ensure_extracted
- @operations.size == 1 ? @operations.first : @operations
+ @operations
end
private
+ def save_operation_subdir
+ return unless @subdir
+
+ @operations[:options] ||= {}
+ @operations[:options][:fonts_sub_dir] = @subdir
+ end
+
def fetch_extension(file)
File.extname(filename(file)).sub(/^\./, "")
end
def filename(file)
@@ -55,149 +59,51 @@
File.basename(file)
end
end
def ensure_extracted
- extracted_path
- end
+ return if @extracted
- def extracted_path
- @extracted_path ||= extract_recursively(@archive)
+ extract_data(@archive)
+ @extracted = true
end
- def extract_recursively(archive)
- path = operate_on_archive(archive)
- match_files(path)
- if matched?
- save_operation_subdir
- return path
+ def extract_data(archive)
+ Excavate::Archive.new(path(archive)).files(recursive_packages: true) do |path|
+ match_license(path)
+ match_font(path) if font_directory?(path)
end
-
- next_archive = find_archive(path)
- extract_recursively(next_archive)
end
- def operate_on_archive(archive)
- extractor = choose_extractor(archive)
- Fontist.ui.say("Extracting #{archive} with #{extractor.class.name}")
-
- save_operation(extractor)
- extractor.extract
+ def path(file)
+ file.respond_to?(:path) ? file.path : file
end
- # rubocop:disable Metrics/MethodLength
- def choose_extractor(archive)
- case fetch_extension(archive).downcase
- when "msi"
- Extractors::OleExtractor.new(archive)
- when "cab"
- Extractors::CabExtractor.new(archive)
- when "exe"
- extractor = Extractors::SevenZipExtractor.new(archive)
- extractor.try ? extractor : Extractors::CabExtractor.new(archive)
- when "zip"
- Extractors::ZipExtractor.new(archive)
- when "rpm"
- Extractors::RpmExtractor.new(archive)
- when "gz"
- Extractors::GzipExtractor.new(archive)
- when "cpio"
- Extractors::CpioExtractor.new(archive)
- when "tar"
- Extractors::TarExtractor.new(archive)
- else
- raise Errors::UnknownArchiveError, "Could not unarchive `#{filename(archive)}`."
- end
- end
- # rubocop:enable Metrics/MethodLength
-
- def save_operation(extractor)
- @operations << { format: extractor.format }
- end
-
- def match_files(dir_path)
- Find.find(dir_path) do |entry_path| # rubocop:disable Style/CollectionMethods
- match_license(entry_path)
- match_font(entry_path) if font_directory?(entry_path, dir_path)
- end
- end
-
def match_license(path)
@license_text ||= File.read(path) if license?(path)
end
def license?(file)
file.match?(LICENSE_PATTERN)
end
- def font_directory?(path, base_path)
- return true unless @subdir
-
- # https://bugs.ruby-lang.org/issues/10011
- base_path = Pathname.new(base_path)
-
- relative_path = Pathname.new(path).relative_path_from(base_path).to_s
- dirname = File.dirname(relative_path)
- normalized_pattern = @subdir.chomp("/")
- File.fnmatch?(normalized_pattern, dirname)
- end
-
def match_font(path)
case Files::FontDetector.detect(path)
when :font
@font_files << Otf::FontFile.new(path)
when :collection
@collection_files << Files::CollectionFile.new(path)
end
end
- def matched?
- [@font_files, @collection_files].any? do |files|
- files.size.positive?
- end
- end
+ def font_directory?(path)
+ return true unless subdirectory_pattern
- def save_operation_subdir
- return unless @subdir
-
- @operations.last[:options] ||= {}
- @operations.last[:options][:fonts_sub_dir] = @subdir
+ File.fnmatch?(subdirectory_pattern, File.dirname(path))
end
- def find_archive(path)
- children = Dir.entries(path) - [".", ".."] # ruby 2.4 compat
- paths = children.map { |file| File.join(path, file) }
- by_subarchive(paths) || by_size(paths)
- end
-
- def by_subarchive(paths)
- return unless @subarchive
-
- path_found = paths.detect do |path|
- @subarchive == File.basename(path)
- end
-
- return unless path_found
-
- save_operation_subarchive(path_found)
-
- path_found
- end
-
- def save_operation_subarchive(path)
- @operations.last[:options] ||= {}
- @operations.last[:options][:subarchive] = File.basename(path)
- end
-
- def by_size(paths)
- paths.max_by do |path|
- [file_type(path), File.size(path)]
- end
- end
-
- def file_type(file_path)
- extension = File.extname(file_path).delete(".")
- ARCHIVE_EXTENSIONS.include?(extension) ? 1 : 0
+ def subdirectory_pattern
+ @subdirectory_pattern ||= "*" + @subdir.chomp("/") if @subdir
end
end
end
end