18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
# File 'lib/ruflet/cli/run_command.rb', line 18
def command_run(args)
options = { target: "mobile", requested_port: 8550 }
parser = OptionParser.new do |o|
o.on("--web") { options[:target] = "web" }
o.on("--desktop") { options[:target] = "desktop" }
o.on("--port PORT", Integer) { |v| options[:requested_port] = v }
end
parser.parse!(args)
script_token = args.shift || "main"
script_path = resolve_script(script_token)
unless script_path
warn "Script not found: #{script_token}"
warn "Expected: ./#{script_token}.rb, ./#{script_token}, or explicit file path."
return 1
end
selected_port = resolve_backend_port(options[:target], requested_port: options[:requested_port])
return 1 unless selected_port
env = {
"RUFLET_TARGET" => options[:target],
"RUFLET_SUPPRESS_SERVER_BANNER" => "1",
"RUFLET_PORT" => selected_port.to_s
}
assets_dir = File.join(File.dirname(script_path), "assets")
env["RUFLET_ASSETS_DIR"] = assets_dir if File.directory?(assets_dir)
print_run_banner(target: options[:target], requested_port: options[:requested_port], port: selected_port)
print_mobile_qr_hint(port: selected_port) if options[:target] == "mobile"
gemfile_path = find_nearest_gemfile(Dir.pwd)
cmd = build_runtime_command(script_path, gemfile_path: gemfile_path, env: env)
return 1 unless cmd
child_pid = Process.spawn(env, *cmd, pgroup: true)
launched_client_pids = launch_target_client(options[:target], selected_port)
forward_signal = lambda do |signal|
begin
Process.kill(signal, -child_pid)
rescue Errno::ESRCH
nil
end
end
previous_int = Signal.trap("INT") { forward_signal.call("INT") }
previous_term = Signal.trap("TERM") { forward_signal.call("TERM") }
_pid, status = Process.wait2(child_pid)
status.success? ? 0 : (status.exitstatus || 1)
ensure
Signal.trap("INT", previous_int) if defined?(previous_int) && previous_int
Signal.trap("TERM", previous_term) if defined?(previous_term) && previous_term
if defined?(child_pid) && child_pid
begin
Process.kill("TERM", -child_pid)
rescue Errno::ESRCH
nil
end
end
Array(defined?(launched_client_pids) ? launched_client_pids : nil).compact.each do |pid|
begin
Process.kill("TERM", -pid)
rescue Errno::ESRCH
begin
Process.kill("TERM", pid)
rescue Errno::ESRCH
nil
end
end
end
end
|