Files
feather-case/lib/feather_case_wizard/toolchain.rb
T

50 lines
1.5 KiB
Ruby

# frozen_string_literal: true
module FeatherCaseWizard
class ToolError < StandardError; end
class Toolchain
attr_reader :openscad, :blender
def initialize(env: ENV)
@env = env
@openscad = discover("OPENSCAD", "openscad")
@blender = discover("BLENDER", "blender")
end
def check!
missing = []
missing << "OpenSCAD (`sudo apt-get install openscad` or set OPENSCAD)" unless openscad
missing << "Blender (`sudo apt-get install blender` or set BLENDER)" unless blender
return self if missing.empty?
raise ToolError, "Missing required tools:\n - #{missing.join("\n - ")}"
end
def run!(*command, chdir: nil, env: {})
options = chdir ? {chdir: chdir} : {}
stdout, stderr, status = Open3.capture3(env, *command, **options)
return [stdout, stderr] if status.success?
detail = [stdout, stderr].reject(&:empty?).join("\n").strip
result = status.exitstatus || "signal #{status.termsig}"
raise ToolError, "Command failed (#{result}): #{command.first}\n#{detail}"
rescue Errno::ENOENT => e
raise ToolError, "Cannot run #{command.first}: #{e.message}"
end
private
def discover(env_name, command)
override = @env[env_name]
return File.expand_path(override) if override && File.executable?(override)
@env.fetch("PATH", "").split(File::PATH_SEPARATOR).each do |directory|
candidate = File.join(directory, command)
return candidate if File.file?(candidate) && File.executable?(candidate)
end
nil
end
end
end