<commit_before>require 'forwardable'
require 'pathname'
require 'pathname/common_prefix'
require 'fileutils'
require 'tmpdir'
require 'time'
require 'uuid'
require 'archive/zip'
require 'epub/book'
require 'epub/parser'
require "epub/maker/version"
require 'epub/maker/ocf'
require 'epub/maker/publication'
require 'epub/maker/content_document'

module EPUB
  module Constants
    MIME_TYPE = 'application/epub+zip'
  end

  class Maker
    include ($VERBOSE ? ::FileUtils::Verbose : ::FileUtils)

    class << self
      def make(path, &block)
        new.make(path, &block)
      end

      def make_from_package_document(package_document_path, root_dir=nil)
        maker = new
        maker.package_document_path = package_document_path
        maker.root_dir = root_dir
        FileUtils.cp File.expand_path('../../../templates/template.epub', __FILE__), maker.output_path.to_s
        Zip::Archive.open maker.output_path.to_s do |archive|
          archive.add_buffer 'META-INF/container.xml', maker.container.to_xml
          archive.add_file maker.rootfile_path.to_s, maker.package_document_path.to_s
          maker.package.manifest.items.each do |item|
            path_on_container = maker.base_dir + item.href.to_s
            path_on_file_system = maker.root_dir + path_on_container
            archive.add_file path_on_container.to_s, path_on_file_system.to_s
          end
        end
      end

      def make_from_directory(dir)
        dir = Pathname(dir)

        container_dir = dir + EPUB::Parser::OCF::DIRECTORY
        container_file = container_dir + 'container.xml'
        ocf_parser = Parser::OCF.new(nil)
        container = ocf_parser.parse_container(container_file.read)

        opf_file = dir + container.rootfile.full_path
        publication_parser = Parser::Publication.new(opf_file.read, opf_file.to_s)
        package = publication_parser.parse

        files = package.manifest.items.select {|item| item.href.relative?}
        target_file = dir.sub_ext('.epub')
        template_file = Pathname(File.expand_path('../../../templates/template.epub', __FILE__))
        FileUtils.copy_file template_file, target_file.to_s

        Zip::Archive.open target_file.to_s do |zip|
          rootfile = Pathname(container.rootfile.full_path)
          rootdir = dir + rootfile.dirname
          zip.add_file File.join('META-INF', 'container.xml'), container_file.to_s
          zip.add_file rootfile.to_s, opf_file.to_s
          files.each do |file|
            puts "add_file #{file.href} #{rootdir+file.href}"
            zip.add_file file.href.to_s, (rootdir+file.href.to_s).to_s
          end
        end
      end
    end

    attr_reader :package_document_path
    attr_writer :container, :package, :root_dir, :base_dir, :output_path

    # @param path [Pathname|#to_path|String]
    # @todo Add option whether mv blocks or not when file locked already
    # @todo Timeout when file shared-locked long time
    def make(path)
      path = Pathname(path) unless path.kind_of? Pathname
      book = EPUB::Book.new
      Dir.mktmpdir 'epub-maker' do |dir|
        dir = Pathname(dir)
        temp_path = dir + path.basename
        mimetype = dir + 'mimetype'
        mimetype.write EPUB::MIME_TYPE
        Archive::Zip.open temp_path.to_path, :w do |archive|
          file = Archive::Zip::Entry.from_file(mimetype.to_path, compression_codec: Archive::Zip::Codec::Store)
          archive.add_entry file
        end

        Zip::Archive.open temp_path.to_path do |archive|
          yield book if block_given?
          book.save archive
        end

        File.open path, 'wb' do |file|
          raise "Other process is locking #{path}" unless file.flock File::LOCK_SH|File::LOCK_NB
          move temp_path.to_path, path.to_path
        end
      end
      book

      # validate
      # build_xml
      # archive
    end

    def package_document_path=(path)
      @package_document_path = path.kind_of?(Pathname) ? path : Pathname.new(path)
    end

    def container
      @container ||= begin
        c = OCF::Container.new
        c.rootfiles << rootfile
        c
      end
    end

    def package
      @package ||= EPUB::Parser::Publication.new(package_document_path.read, package_document_path.to_path).parse
    end<commit_msg>Use Pathname#open instead of File.open<commit_after>require 'forwardable'
require 'pathname'
require 'pathname/common_prefix'
require 'fileutils'
require 'tmpdir'
require 'time'
require 'uuid'
require 'archive/zip'
require 'epub/book'
require 'epub/parser'
require "epub/maker/version"
require 'epub/maker/ocf'
require 'epub/maker/publication'
require 'epub/maker/content_document'

module EPUB
  module Constants
    MIME_TYPE = 'application/epub+zip'
  end

  class Maker
    include ($VERBOSE ? ::FileUtils::Verbose : ::FileUtils)

    class << self
      def make(path, &block)
        new.make(path, &block)
      end

      def make_from_package_document(package_document_path, root_dir=nil)
        maker = new
        maker.package_document_path = package_document_path
        maker.root_dir = root_dir
        FileUtils.cp File.expand_path('../../../templates/template.epub', __FILE__), maker.output_path.to_s
        Zip::Archive.open maker.output_path.to_s do |archive|
          archive.add_buffer 'META-INF/container.xml', maker.container.to_xml
          archive.add_file maker.rootfile_path.to_s, maker.package_document_path.to_s
          maker.package.manifest.items.each do |item|
            path_on_container = maker.base_dir + item.href.to_s
            path_on_file_system = maker.root_dir + path_on_container
            archive.add_file path_on_container.to_s, path_on_file_system.to_s
          end
        end
      end

      def make_from_directory(dir)
        dir = Pathname(dir)

        container_dir = dir + EPUB::Parser::OCF::DIRECTORY
        container_file = container_dir + 'container.xml'
        ocf_parser = Parser::OCF.new(nil)
        container = ocf_parser.parse_container(container_file.read)

        opf_file = dir + container.rootfile.full_path
        publication_parser = Parser::Publication.new(opf_file.read, opf_file.to_s)
        package = publication_parser.parse

        files = package.manifest.items.select {|item| item.href.relative?}
        target_file = dir.sub_ext('.epub')
        template_file = Pathname(File.expand_path('../../../templates/template.epub', __FILE__))
        FileUtils.copy_file template_file, target_file.to_s

        Zip::Archive.open target_file.to_s do |zip|
          rootfile = Pathname(container.rootfile.full_path)
          rootdir = dir + rootfile.dirname
          zip.add_file File.join('META-INF', 'container.xml'), container_file.to_s
          zip.add_file rootfile.to_s, opf_file.to_s
          files.each do |file|
            puts "add_file #{file.href} #{rootdir+file.href}"
            zip.add_file file.href.to_s, (rootdir+file.href.to_s).to_s
          end
        end
      end
    end

    attr_reader :package_document_path
    attr_writer :container, :package, :root_dir, :base_dir, :output_path

    # @param path [Pathname|#to_path|String]
    # @todo Add option whether mv blocks or not when file locked already
    # @todo Timeout when file shared-locked long time
    def make(path)
      path = Pathname(path) unless path.kind_of? Pathname
      book = EPUB::Book.new
      Dir.mktmpdir 'epub-maker' do |dir|
        dir = Pathname(dir)
        temp_path = dir + path.basename
        mimetype = dir + 'mimetype'
        mimetype.write EPUB::MIME_TYPE
        Archive::Zip.open temp_path.to_path, :w do |archive|
          file = Archive::Zip::Entry.from_file(mimetype.to_path, compression_codec: Archive::Zip::Codec::Store)
          archive.add_entry file
        end

        Zip::Archive.open temp_path.to_path do |archive|
          yield book if block_given?
          book.save archive
        end

        path.open 'wb' do |file|
          raise "Other process is locking #{path}" unless file.flock File::LOCK_SH|File::LOCK_NB
          move temp_path.to_path, path.to_path
        end
      end
      book

      # validate
      # build_xml
      # archive
    end

    def package_document_path=(path)
      @package_document_path = path.kind_of?(Pathname) ? path : Pathname.new(path)
    end

    def container
      @container ||= begin
        c = OCF::Container.new
        c.rootfiles << rootfile
        c
      end
    end

    def package
      @package ||= EPUB::Parser::Publication.new(package_document_path.read, package_document_path.to_path).parse
    end
{'fraction_non_alphanumeric': 0.10017492711370263, 'fraction_numerical': 0.0, 'mean_word_length': 2.7206073752711495, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 10}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '760522', 'n_tokens_mistral': 2768, 'n_tokens_neox': 2711, 'n_words': 552}