class Epuber::Command::Build

Public Class Methods

new(argv) click to toggle source

@param [CLAide::ARGV] argv

Calls superclass method Epuber::Command::new
# File lib/epuber/command/build.rb, line 36
def initialize(argv)
  @targets_names = argv.arguments!
  @should_check = argv.flag?('check', false)
  @should_write = argv.flag?('write', false)
  @release_version = argv.flag?('release', false)
  @use_cache = argv.flag?('cache', true)

  UI.logger.debug_steps_times = argv.flag?('debug-steps-times', false)

  super(argv)
end
options() click to toggle source
Calls superclass method
# File lib/epuber/command/build.rb, line 19
def self.options
  [
    ['--check',    'Performs additional validation on sources + checks result epub with epubcheck.'],
    ['--write',    'Performs additional transformations which writes to source files.'],
    ['--release',  'Create release version of the book, no caching, everything creates from scratch.'],
    ['--no-cache', 'Turns off incremental build, can resolve some bugs but build takes much longer.'],
    ['--debug-steps-times', 'Shows times of each step'],
  ].concat(super)
end
subcommands() click to toggle source

To resolve problem with ‘compile` treating as subcommand

# File lib/epuber/command/build.rb, line 30
def self.subcommands
  []
end

Public Instance Methods

run() click to toggle source
Calls superclass method Epuber::Command::run
# File lib/epuber/command/build.rb, line 56
def run
  super

  UI.info "building book `#{Config.instance.pretty_path_from_project(book.file_path)}`"

  if @release_version
    # Remove all previous versions of compiled files
    cleanup_build_folders

    # Build all targets to always clean directory
    targets.each do |target|
      Epuber::Config.instance.release_build = true

      compiler = Epuber::Compiler.new(book, target)
      build_path = Epuber::Config.instance.release_build_path(target)
      compiler.compile(build_path, check: true, write: @should_write,
                                   release: true, verbose: verbose?,
                                   use_cache: false)

      archive_name = compiler.epub_name

      FileUtils.remove_file(archive_name) if ::File.exist?(archive_name)

      archive_path = compiler.archive(archive_name)
      run_epubcheck(archive_path, build_path)
      convert_epub_to_mobi(archive_path, "#{::File.basename(archive_path, '.epub')}.mobi") if target.create_mobi

      Epuber::Config.instance.release_build = false
    end

    # Build all targets to always clean directory
  else
    targets.each do |target|
      compiler = Epuber::Compiler.new(book, target)
      build_path = Epuber::Config.instance.build_path(target)
      compiler.compile(build_path, check: @should_check, write: @should_write, verbose: verbose?,
                                   use_cache: @use_cache)
      archive_path = compiler.archive(configuration_suffix: 'debug')

      run_epubcheck(archive_path, build_path) if @should_check

      convert_epub_to_mobi(archive_path, "#{::File.basename(archive_path, '.epub')}.mobi") if target.create_mobi
    end
  end

  # Exit with error if there are any errors
  if (@release_version || @should_check) && Epuber::UI.logger.error?
    exit(1)
  else
    UI.info('🎉 Build finished successfully.'.ansi.green)
    write_lockfile
  end
end
validate!() click to toggle source
Calls superclass method
# File lib/epuber/command/build.rb, line 48
def validate!
  super
  verify_one_bookspec_exists!
  verify_all_targets_exists!

  pre_build_checks
end

Private Instance Methods

cleanup_build_folders() click to toggle source
# File lib/epuber/command/build.rb, line 198
def cleanup_build_folders
  targets.each do |target|
    build_path = Epuber::Config.instance.release_build_path(target)

    FileUtils.remove_dir(build_path, true) if ::File.directory?(build_path)
  end
end
convert_epub_to_mobi(epub_path, mobi_path) click to toggle source
# File lib/epuber/command/build.rb, line 194
def convert_epub_to_mobi(epub_path, mobi_path)
  system(find_calibre_convert_file, epub_path, mobi_path)
end
find_calibre_app() click to toggle source
# File lib/epuber/command/build.rb, line 170
def find_calibre_app
  locations = `mdfind "kMDItemCFBundleIdentifier == net.kovidgoyal.calibre"`.split("\n")
  UI.error!("Can't find location of calibre.app to convert EPUB to MOBI.") if locations.empty?

  selected = locations.first
  UI.warning("Found multiple calibre.app, using at location #{selected}") if locations.count > 1

  selected
end
find_calibre_convert_file() click to toggle source
# File lib/epuber/command/build.rb, line 180
def find_calibre_convert_file
  if OS.osx?
    ::File.join(find_calibre_app, 'Contents/MacOS/ebook-convert')
  elsif OS.linux?
    script_path = '/usr/bin/ebook-convert'
    unless ::File.executable?(script_path)
      UI.error!("Can't find ebook-convert in folder /usr/bin to convert EPUB to MOBI.")
    end
    script_path
  else
    UI.error!('Unsupported OS to convert EPUB to MOBI.')
  end
end
run_epubcheck(archive_path, build_dir) click to toggle source
# File lib/epuber/command/build.rb, line 138
def run_epubcheck(archive_path, build_dir)
  UI.info("Running Epubcheck for #{archive_path}")

  report = Epubcheck.check(archive_path)
  report.problems.each do |problem|
    relative_path = problem.location.path.sub("#{archive_path}/", '')
    file_path = ::File.join(build_dir, relative_path)

    nice_path = Config.instance.pretty_path_from_project(file_path)
    content = ::File.read(file_path)

    log_level = case problem.level
                when :fatal, :error then :error
                when :warning then :warning
                else :info
                end
    message = "#{problem.level}(#{problem.code}): #{problem.message}"

    p = Compiler::Problem.new(problem.level, message, content, line: problem.location.lineno,
                                                               column: problem.location.column,
                                                               length: 1,
                                                               file_path: nice_path)
    UI.send(log_level, p, backtrace: nil)
  end

  if report.error?
    UI.error('Epubcheck found some errors in epub file.')
  else
    UI.info('Epubcheck finished successfully.')
  end
end
targets() click to toggle source

@return [Array<Epuber::Book::Target>]

# File lib/epuber/command/build.rb, line 114
def targets
  @targets ||= begin
    targets = @targets_names

    # when the list of targets is nil pick all available targets
    if targets.empty?
      book.buildable_targets
    else
      targets.map { |target_name| book.target_named(target_name) }
    end
  end
end
validate_dir(path) click to toggle source
# File lib/epuber/command/build.rb, line 132
def validate_dir(path)
  return unless ::File.directory?(path)

  path
end
verify_all_targets_exists!() click to toggle source
# File lib/epuber/command/build.rb, line 127
def verify_all_targets_exists!
  index = targets.index(&:nil?)
  help! "Not found target `#{@targets_names[index]}' in bookspec `#{book.file_path}'" unless index.nil?
end