class Epuber::Compiler::FileResolver

Constants

PATH_TYPES

Attributes

dest_finder[R]

@return [FileFinders::Imaginary]

destination_path[R]

@return [String] path where will be stored result files

files[R]

@return [Array<FileTypes::Abstract>] totally all files

manifest_files[R]

@return [Array<FileTypes::Abstract>] all files that has to be in manifest file (OPF)

package_files[R]

@return [Array<FileTypes::Abstract>] all files that will be copied to EPUB package

source_finder[R]

@return [FileFinders::Normal]

source_path[R]

@return [String] path where should look for source files

spine_files[R]

@return [Array<FileTypes::Abstract>] all files that will be in spine

Public Class Methods

new(source_path, destination_path) click to toggle source

@param [String] source_path @param [String] destination_path

# File lib/epuber/compiler/file_resolver.rb, line 68
def initialize(source_path, destination_path)
  @source_finder = FileFinders::Normal.new(source_path.unicode_normalize)
  @source_finder.ignored_patterns << ::File.join(Config::WORKING_PATH, '**')

  @dest_finder = FileFinders::Imaginary.new(destination_path.unicode_normalize)

  @source_path      = source_path.unicode_normalize
  @destination_path = destination_path.unicode_normalize

  @spine_files    = []
  @manifest_files = []
  @package_files  = []
  @files          = []

  @request_to_files = Hash.new { |hash, key| hash[key] = [] }
  @final_destination_path_to_file = {}
  @source_path_to_file = {}
  @abs_source_path_to_file = {}
end

Private Class Methods

file_class_for(extname) click to toggle source

@param [String] extname extension of file

@return [Class]

# File lib/epuber/compiler/file_resolver.rb, line 282
def self.file_class_for(extname)
  mapping = {
    '.styl'  => FileTypes::StylusFile,

    '.coffee' => FileTypes::CoffeeScriptFile,

    '.bade'  => FileTypes::BadeFile,
    '.xhtml' => FileTypes::XHTMLFile,
    '.html'  => FileTypes::XHTMLFile,

    '.jpg'   => FileTypes::ImageFile,
    '.jpeg'  => FileTypes::ImageFile,
    '.png'   => FileTypes::ImageFile,
  }

  mapping[extname] || FileTypes::StaticFile
end
path_comps_for(root_path = nil, path_type) click to toggle source

@param [String] root_path path to root of the package @param [Symbol] path_type path type of file

@return [Array<String>] path components

# File lib/epuber/compiler/file_resolver.rb, line 305
def self.path_comps_for(root_path = nil, path_type)
  case path_type
    when :spine, :manifest
      Array(root_path) + [Compiler::EPUB_CONTENT_FOLDER]
    when :package
      Array(root_path)
    else
      nil
  end
end
renamed_file_with_path(path) click to toggle source

@param [String] path path to some file

@return [String] path with changed extension

# File lib/epuber/compiler/file_resolver.rb, line 246
def self.renamed_file_with_path(path)
  extname     = File.extname(path)
  new_extname = FileFinders::EXTENSIONS_RENAME[extname]

  if new_extname.nil?
    path
  else
    path.sub(/#{Regexp.escape(extname)}$/, new_extname)
  end
end

Public Instance Methods

add_file(file) click to toggle source

@param [Epuber::Compiler::FileTypes::AbstractFile] file

# File lib/epuber/compiler/file_resolver.rb, line 116
def add_file(file)
  type = file.path_type

  unless PATH_TYPES.include?(type)
    raise "Unknown file.path_type #{type.inspect}, expected are :spine, :manifest, :package or nil"
  end

  resolve_destination_path(file)

  existing_file = @final_destination_path_to_file[file.final_destination_path]

  # save mapping from file_request to file, file_request can be different, but result file could be the same ...
  unless file.try(:file_request).nil?
    @request_to_files[file.file_request] << (existing_file || file)
  end

  # return existing file if already exists, new file will be thrown away
  return existing_file unless existing_file.nil?

  if [:spine].include?(type)
    @spine_files << file
  end

  if [:spine, :manifest].include?(type)
    @manifest_files << file
  end

  if [:spine, :manifest, :package].include?(type)
    @package_files << file
  end

  @files << file


  dest_finder.add_file(file.destination_path)

  @final_destination_path_to_file[file.final_destination_path] = file

  if file.respond_to?(:source_path) && !file.source_path.nil?
    @source_path_to_file[file.source_path] = file
  end

  if file.respond_to?(:abs_source_path) && !file.abs_source_path.nil?
    @abs_source_path_to_file[file.abs_source_path] = file
  end
end
add_file_from_request(file_request, path_type = :manifest) click to toggle source

@param [Epuber::Book::FileRequest] file_request

# File lib/epuber/compiler/file_resolver.rb, line 90
def add_file_from_request(file_request, path_type = :manifest)
  if file_request.only_one
    file_path = @source_finder.find_file(file_request.source_pattern, groups: file_request.group)
    file_class = self.class.file_class_for(File.extname(file_path))

    file = file_class.new(file_path)
    file.file_request = file_request
    file.path_type = path_type

    add_file(file)
  else
    file_paths = @source_finder.find_all(file_request.source_pattern, groups: file_request.group)
    file_paths.map do |path|
      file_class = self.class.file_class_for(File.extname(path))

      file = file_class.new(path)
      file.file_request = file_request
      file.path_type = path_type

      add_file(file)
    end
  end
end
file_from_request(file_request) click to toggle source

Get instance of file from request instance

@param [Book::FileRequest] file_request

@return [FileTypes::AbstractFile, Array<FileTypes::AbstractFile>]

# File lib/epuber/compiler/file_resolver.rb, line 169
def file_from_request(file_request)
  files = @request_to_files[file_request]

  if files.empty? && file_request.only_one
    begin
      path  = @source_finder.find_file(file_request.source_pattern, groups: file_request.group)
      file  = file_with_source_path(path)

      unless file.nil?
        @request_to_files[file_request] = file
        files = [file]
      end
    rescue FileFinders::FileNotFoundError, FileFinders::MultipleFilesFoundError
      # noop
    end
  end

  if file_request.only_one
    files.first  # @request_to_files always returns array, see #initialize method
  else
    files
  end
end
file_with_destination_path(path, path_type = :manifest) click to toggle source

Method to get instance of file on specific path

@param [String] path path to file from destination folder @param [String] path_type path type of path (:spine, :manifest or :package)

@return [FileTypes::AbstractFile]

# File lib/epuber/compiler/file_resolver.rb, line 212
def file_with_destination_path(path, path_type = :manifest)
  final_path = File.join(*self.class.path_comps_for(destination_path, path_type), path.unicode_normalize)
  @final_destination_path_to_file[path] || @final_destination_path_to_file[final_path]
end
file_with_source_path(source_path) click to toggle source

Get instance of file from source path, but this is relative path from project root, if you want to find file with absolute source path see file_with_abs_source_path

@param [String] source_path

@return [FileTypes::AbstractFile]

# File lib/epuber/compiler/file_resolver.rb, line 200
def file_with_source_path(source_path)
  source_path = source_path.unicode_normalize
  @source_path_to_file[source_path] || @abs_source_path_to_file[source_path]
end
unneeded_files_in_destination() click to toggle source

Method to find all files that should be deleted, because they are not in files in receiver

@return [Array<String>] list of files that should be deleted in destination directory

# File lib/epuber/compiler/file_resolver.rb, line 221
def unneeded_files_in_destination
  requested_paths = files.map do |file|
    file.pkg_destination_path
  end

  existing_paths = FileFinders::Normal.new(destination_path).find_all('*')

  unnecessary_paths = existing_paths - requested_paths

  unnecessary_paths.select! do |path|
    !::File.directory?(File.join(destination_path, path))
  end

  unnecessary_paths
end

Private Instance Methods

resolve_destination_path(file) click to toggle source

@param file [Epuber::Compiler::AbstractFile]

@return [nil]

# File lib/epuber/compiler/file_resolver.rb, line 261
def resolve_destination_path(file)
  if file.final_destination_path.nil?
    dest_path = if file.respond_to?(:source_path) && !file.source_path.nil?
                  file.abs_source_path = File.expand_path(file.source_path, source_path)
                  self.class.renamed_file_with_path(file.source_path)
                elsif !file.destination_path.nil?
                  file.destination_path
                else
                  raise ResolveError, "What should I do with file that doesn't have source path or destination path? file: #{file.inspect}"
                end

    file.destination_path = dest_path
    file.pkg_destination_path = File.join(*self.class.path_comps_for(file.path_type), dest_path)
    file.final_destination_path = File.join(destination_path, file.pkg_destination_path)
  end
end