50 lines
1.5 KiB
Ruby
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
|