1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
//! `wt` — thin binary entry point.
//!
//! Wires up error reporting and tracing, builds the runtime context over real
//! stdio and the process environment, then delegates to the library. This file
//! is intentionally minimal and is excluded from coverage measurement (see the
//! `coverage` task in `mise.toml`).
use std::io::IsTerminal;
use std::process::ExitCode;
fn main() -> ExitCode {
// Must precede any worktree operation: it arms the handlers that release
// the advisory repo lock on SIGINT/SIGTERM/SIGQUIT instead of stranding
// `wt-mutation.lock`. The TUI is unaffected — crossterm's raw mode clears
// `ISIG`, so Ctrl-C reaches it as a key event rather than a signal.
wt::install_signal_handlers();
if let Err(error) = color_eyre::install() {
eprintln!("wt: failed to install error reporter: {error}");
return ExitCode::FAILURE;
}
// Diagnostics go to stderr so stdout stays reserved for paths/JSON (§5).
// Verbosity is controlled by `RUST_LOG` (e.g. `RUST_LOG=wt=debug`); absent or
// unparseable, only warnings and errors are shown.
let filter = tracing_subscriber::EnvFilter::try_from_default_env()
.unwrap_or_else(|_| tracing_subscriber::EnvFilter::new("warn"));
tracing_subscriber::fmt()
.with_env_filter(filter)
.with_writer(std::io::stderr)
.init();
let out = wt::Stream::new(Box::new(std::io::stdout()), std::io::stdout().is_terminal());
let err = wt::Stream::new(Box::new(std::io::stderr()), std::io::stderr().is_terminal());
let cwd = std::env::current_dir().unwrap_or_default();
let git = std::sync::Arc::new(wt::git::RealGit);
let gh = std::sync::Arc::new(wt::gh::RealGh);
let agent = std::sync::Arc::new(wt::agent::RealAgent);
let input = Box::new(wt::cx::StdinInput);
let mut cx = wt::Cx::new(out, err, wt::Env::from_real(), cwd, git, gh, agent, input);
let args = std::env::args().skip(1).collect();
ExitCode::from(wt::run(args, &mut cx))
}