Skip to content

Commit

Permalink
Refactor bin/ocran.rb to use Ocran::Runner and implement Ocran.option=
Browse files Browse the repository at this point in the history
- Moved the implementation from bin/ocran.rb to Ocran::Runner to centralize execution logic.
- Implemented Ocran.option= to allow configuration of @option from within Ocran::Runner, enhancing modularity and configurability.
  • Loading branch information
shinokaro committed Aug 1, 2024
1 parent 4db75c4 commit 2c8d1dc
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 104 deletions.
107 changes: 3 additions & 104 deletions bin/ocran
Original file line number Diff line number Diff line change
@@ -1,112 +1,11 @@
#!/usr/bin/env ruby
# encoding: UTF-8
require "pathname"

module Ocran
def self.option = @option

load File.expand_path("../lib/ocran/command_output.rb", __dir__)
extend CommandOutput

def Ocran.fatal_error(s)
error s
exit 1
end

def self.script = @option&.script

def self.run_script? = @option&.run_script?

def Ocran.init
load File.expand_path("../lib/ocran/runtime_environment.rb", __dir__)
@pre_env = RuntimeEnvironment.save

load File.expand_path("../lib/ocran/option.rb", __dir__)
@option = Option.new.tap do |opt|
opt.parse(ARGV)
rescue RuntimeError => e
# Capture RuntimeError during parsing and display an appropriate
# error message to the user. This error usually occurs from invalid
# option arguments.
Ocran.fatal_error e.message
else
# Update ARGV with the parsed command line arguments to pass to
# the user's script. This ensures the script executes based on
# the user-specified arguments.
ARGV.replace(opt.argv)
end

@ignore_modules = ObjectSpace.each_object(Module).to_a
end

# Force loading autoloaded constants. Searches through all modules
# (and hence classes), and checks their constants for autoloaded
# ones, then attempts to load them.
def self.attempt_load_autoload(ignore_modules = [])
checked_modules = ignore_modules.inject({}) { |h, mod| h[mod] = true; h }
while ObjectSpace.each_object(Module).count { |mod|
next if checked_modules.include?(mod)
mod.constants.each do |const|
next unless mod.autoload?(const)
say "Attempting to trigger autoload of #{mod}::#{const}"
begin
mod.const_get(const)
rescue ScriptError, StandardError => e
# Some autoload constants may throw exceptions beyond the expected
# errors. This includes issues dependent on the system or execution
# environment, so it is preferable to ignore exceptions other than
# critical errors.
warning "#{mod}::#{const} loading failed: #{e.message}"
end
end
checked_modules[mod] = true
}.nonzero?
# Loops until all constants have been checked.
end
end

def self.build
# If the script was run and autoload is enabled, attempt to autoload libraries.
if @option.force_autoload?
attempt_load_autoload(@ignore_modules)
end

@post_env = RuntimeEnvironment.save
# NOTE: From this point, $LOADED_FEATURES has been captured, so it is now
# safe to call require_relative.

ENV.replace(@pre_env.env)

# It might be useful to reset the current directory to the point where the
# command was launched, especially when implementing the builder object.
Dir.chdir(@pre_env.pwd)

require_relative "../lib/ocran/direction"
direction = Direction.new(@post_env, @pre_env, @option)

if @option.use_inno_setup?
direction.build_inno_setup_installer
else
direction.build_stab_exe
end
rescue RuntimeError => e
Ocran.fatal_error e.message
end
singleton_class.attr_accessor :option
end # module Ocran

load File.expand_path("../lib/ocran/runner.rb", __dir__)
if File.basename(__FILE__) == File.basename($PROGRAM_NAME)
Ocran.init

at_exit do
if $!.nil? or $!.kind_of?(SystemExit)
Ocran.build
exit 0
end
end

if Ocran.run_script?
Ocran.say "Loading script to check dependencies"
$PROGRAM_NAME = Ocran.script.to_s
load Ocran.script
end
load Ocran::Runner.new.run
end
104 changes: 104 additions & 0 deletions lib/ocran/runner.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# frozen_string_literal: true

module Ocran
class Runner
load File.expand_path("command_output.rb", __dir__)
include CommandOutput

def fatal_error(statement)
error statement
exit false
end

def initialize
load File.expand_path("runtime_environment.rb", __dir__)
@pre_env = RuntimeEnvironment.save

load File.expand_path("option.rb", __dir__)
@option = Option.new.tap do |opt|
opt.parse(ARGV)
rescue RuntimeError => e
# Capture RuntimeError during parsing and display an appropriate
# error message to the user. This error usually occurs from invalid
# option arguments.
fatal_error e.message
else
# Update ARGV with the parsed command line arguments to pass to
# the user's script. This ensures the script executes based on
# the user-specified arguments.
ARGV.replace(opt.argv)
end

Ocran.option = @option

@ignore_modules = ObjectSpace.each_object(Module).to_a
end

def run
at_exit do
if $!.nil? or $!.kind_of?(SystemExit)
build
exit
end
end

exit unless @option.run_script?
say "Loading script to check dependencies"
$PROGRAM_NAME = @option.script.to_s
end

# Force loading autoloaded constants. Searches through all modules
# (and hence classes), and checks their constants for autoloaded
# ones, then attempts to load them.
def attempt_load_autoload(ignore_modules = [])
checked_modules = ignore_modules.inject({}) { |h, mod| h[mod] = true; h }
while ObjectSpace.each_object(Module).count { |mod|
next if checked_modules.include?(mod)
mod.constants.each do |const|
next unless mod.autoload?(const)
say "Attempting to trigger autoload of #{mod}::#{const}"
begin
mod.const_get(const)
rescue ScriptError, StandardError => e
# Some autoload constants may throw exceptions beyond the expected
# errors. This includes issues dependent on the system or execution
# environment, so it is preferable to ignore exceptions other than
# critical errors.
warning "#{mod}::#{const} loading failed: #{e.message}"
end
end
checked_modules[mod] = true
}.nonzero?
# Loops until all constants have been checked.
end
end

def build
# If the script was run and autoload is enabled, attempt to autoload libraries.
if @option.force_autoload?
attempt_load_autoload(@ignore_modules)
end

@post_env = RuntimeEnvironment.save
# NOTE: From this point, $LOADED_FEATURES has been captured, so it is now
# safe to call require_relative.

ENV.replace(@pre_env.env)

# It might be useful to reset the current directory to the point where the
# command was launched, especially when implementing the builder object.
Dir.chdir(@pre_env.pwd)

require_relative "direction"
direction = Direction.new(@post_env, @pre_env, @option)

if @option.use_inno_setup?
direction.build_inno_setup_installer
else
direction.build_stab_exe
end
rescue RuntimeError => e
fatal_error e.message
end
end
end

0 comments on commit 2c8d1dc

Please sign in to comment.