cli: Implement `rad node start` with support for deamonizing
Signed-off-by: xphoniex <dj.2dixx@gmail.com>
This commit is contained in:
parent
362f26a0c8
commit
ac12a4deee
|
|
@ -22,12 +22,14 @@ pub const HELP: Help = Help {
|
|||
Usage
|
||||
|
||||
rad node status [<option>...]
|
||||
rad node start [<option>...]
|
||||
rad node start [--daemon|-d] [<option>...] [-- <node-option>...]
|
||||
rad node stop [<option>...]
|
||||
rad node connect <nid> <addr> [<option>...]
|
||||
rad node routing [<option>...]
|
||||
rad node tracking [--repos|--nodes] [<option>...]
|
||||
|
||||
For `<node-option>` see `radicle-node --help`.
|
||||
|
||||
Options
|
||||
|
||||
--help Print help
|
||||
|
|
@ -41,12 +43,20 @@ pub struct Options {
|
|||
}
|
||||
|
||||
pub enum Operation {
|
||||
Connect { nid: NodeId, addr: Address },
|
||||
Connect {
|
||||
nid: NodeId,
|
||||
addr: Address,
|
||||
},
|
||||
Routing,
|
||||
Start,
|
||||
Start {
|
||||
daemon: bool,
|
||||
options: Vec<OsString>,
|
||||
},
|
||||
Status,
|
||||
Stop,
|
||||
Tracking { mode: TrackingMode },
|
||||
Tracking {
|
||||
mode: TrackingMode,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
|
|
@ -71,6 +81,8 @@ impl Args for Options {
|
|||
fn from_args(args: Vec<OsString>) -> anyhow::Result<(Self, Vec<OsString>)> {
|
||||
use lexopt::prelude::*;
|
||||
|
||||
let mut daemon = false;
|
||||
let mut options = vec![];
|
||||
let mut parser = lexopt::Parser::from_args(args);
|
||||
let mut op: Option<OperationName> = None;
|
||||
let mut tracking_mode = TrackingMode::default();
|
||||
|
|
@ -111,6 +123,12 @@ impl Args for Options {
|
|||
Long("nodes") if matches!(op, Some(OperationName::Tracking)) => {
|
||||
tracking_mode = TrackingMode::Nodes
|
||||
}
|
||||
Long("daemon") | Short('d') if matches!(op, Some(OperationName::Start)) => {
|
||||
daemon = true;
|
||||
}
|
||||
Value(val) if matches!(op, Some(OperationName::Start)) => {
|
||||
options.push(val);
|
||||
}
|
||||
_ => return Err(anyhow!(arg.unexpected())),
|
||||
}
|
||||
}
|
||||
|
|
@ -121,7 +139,7 @@ impl Args for Options {
|
|||
addr: addr.ok_or_else(|| anyhow!("an address must be provided"))?,
|
||||
},
|
||||
OperationName::Routing => Operation::Routing,
|
||||
OperationName::Start => Operation::Start,
|
||||
OperationName::Start => Operation::Start { daemon, options },
|
||||
OperationName::Status => Operation::Status,
|
||||
OperationName::Stop => Operation::Stop,
|
||||
OperationName::Tracking => Operation::Tracking {
|
||||
|
|
@ -145,7 +163,7 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
|
|||
radicle::node::routing::Table::reader(profile.home.node().join(ROUTING_DB_FILE))?;
|
||||
routing::run(&store)?;
|
||||
}
|
||||
Operation::Start => control::start()?,
|
||||
Operation::Start { daemon, options } => control::start(daemon, options)?,
|
||||
Operation::Status => {
|
||||
let node = Node::new(profile.socket());
|
||||
control::status(&node);
|
||||
|
|
|
|||
|
|
@ -1,10 +1,34 @@
|
|||
use std::ffi::OsString;
|
||||
use std::fs::OpenOptions;
|
||||
use std::process;
|
||||
|
||||
use radicle::node::{Address, Handle as _, NodeId};
|
||||
use radicle::Node;
|
||||
|
||||
use crate::terminal as term;
|
||||
|
||||
pub fn start() -> anyhow::Result<()> {
|
||||
todo!()
|
||||
pub fn start(daemon: bool, options: Vec<OsString>) -> anyhow::Result<()> {
|
||||
if daemon {
|
||||
let home = radicle::profile::home()?;
|
||||
let log = OpenOptions::new()
|
||||
.append(true)
|
||||
.create(true)
|
||||
.open(home.node().join("node.log"))?;
|
||||
process::Command::new("radicle-node")
|
||||
.args(options)
|
||||
.stdin(process::Stdio::null())
|
||||
.stdout(process::Stdio::from(log))
|
||||
.stderr(process::Stdio::null())
|
||||
.spawn()?;
|
||||
} else {
|
||||
let mut child = process::Command::new("radicle-node")
|
||||
.args(options)
|
||||
.spawn()?;
|
||||
|
||||
child.wait()?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn stop(node: Node) -> anyhow::Result<()> {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
//! Logging module.
|
||||
use std::io;
|
||||
use std::io::{self, Write};
|
||||
|
||||
use chrono::prelude::*;
|
||||
use colored::*;
|
||||
|
|
@ -18,35 +18,28 @@ impl Log for Logger {
|
|||
if self.enabled(record.metadata()) {
|
||||
let target = record.target();
|
||||
|
||||
if record.level() == Level::Error {
|
||||
write(record, target, io::stderr());
|
||||
} else {
|
||||
write(record, target, io::stdout());
|
||||
}
|
||||
let message = format!(
|
||||
"{:<5} {:<8} {}",
|
||||
record.level(),
|
||||
target.cyan(),
|
||||
record.args()
|
||||
);
|
||||
|
||||
fn write(record: &log::Record, target: &str, mut stream: impl io::Write) {
|
||||
let message = format!(
|
||||
"{:<5} {:<8} {}",
|
||||
record.level(),
|
||||
target.cyan(),
|
||||
record.args()
|
||||
);
|
||||
let message = format!(
|
||||
"{} {}",
|
||||
Local::now().to_rfc3339_opts(SecondsFormat::Millis, true),
|
||||
message,
|
||||
);
|
||||
|
||||
let message = format!(
|
||||
"{} {}",
|
||||
Local::now().to_rfc3339_opts(SecondsFormat::Millis, true),
|
||||
message,
|
||||
);
|
||||
let message = match record.level() {
|
||||
Level::Error => message.red(),
|
||||
Level::Warn => message.yellow(),
|
||||
Level::Info => message.normal(),
|
||||
Level::Debug => message.dimmed(),
|
||||
Level::Trace => message.white().dimmed(),
|
||||
};
|
||||
|
||||
let message = match record.level() {
|
||||
Level::Error => message.red(),
|
||||
Level::Warn => message.yellow(),
|
||||
Level::Info => message.normal(),
|
||||
Level::Debug => message.dimmed(),
|
||||
Level::Trace => message.white().dimmed(),
|
||||
};
|
||||
writeln!(stream, "{message}").expect("write shouldn't fail");
|
||||
}
|
||||
writeln!(io::stdout(), "{message}").expect("write shouldn't fail");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue