use crate::{Log, NodeInstance, utils};
use anyhow::Result;
use std::{
env,
path::Path,
process::{Command, Stdio},
};
const GEAR_BINARY: &str = "gear";
const DEFAULT_ARGS: [&str; 4] = ["--dev", "--tmp", "--no-hardware-benchmarks", "--rpc-port"];
pub struct Node {
command: Command,
port: Option<u16>,
logs: Option<usize>,
}
impl Node {
pub fn new() -> Result<Self> {
Self::from_path(which::which(GEAR_BINARY)?)
}
pub fn from_path(path: impl AsRef<Path>) -> Result<Self> {
Ok(Self {
command: Command::new(path.as_ref()),
port: None,
logs: None,
})
}
pub fn arg(&mut self, arg: &str) -> &mut Self {
self.command.arg(arg);
self
}
pub fn args(&mut self, args: &[&str]) -> &mut Self {
self.command.args(args);
self
}
pub fn rpc_port(&mut self, port: u16) -> &mut Self {
self.port = Some(port);
self
}
pub fn logs(&mut self, limit: usize) -> &mut Self {
self.logs = Some(limit);
self
}
pub fn spawn(&mut self) -> Result<NodeInstance> {
let port = self.port.unwrap_or(utils::pick()).to_string();
let mut args = DEFAULT_ARGS.to_vec();
args.push(&port);
let mut process = self
.command
.env(
"RUST_LOG",
env::var_os("GEAR_NODE_WRAPPER_LOG")
.or_else(|| env::var_os("RUST_LOG"))
.unwrap_or_default(),
)
.args(args)
.stderr(Stdio::piped())
.stdout(Stdio::piped())
.spawn()?;
let address = format!("{}:{port}", utils::LOCALHOST).parse()?;
let mut log = Log::new(self.logs);
log.spawn(&mut process)?;
Ok(NodeInstance {
address,
log,
process,
})
}
}