mod commands;
mod elevate;
mod keys;
mod manifest;
mod registry;
mod selfcmd;
mod tui;
mod wg;
use anyhow::Result;
use clap::{Parser, Subcommand};
use commands::dir::DirArgs;
use commands::mesh::MeshArgs;
use std::io::IsTerminal;
use std::path::PathBuf;
const AFTER: &str = concat!(
"Run bare `ewg` for the interface manager TUI. `dir` registers \
where your .conf files live so `list`/`up`/`down`/`status`/TUI \
span them all. `mesh` edits a manifest; `mesh gen` turns it into \
each node's config as \"all peers minus itself\". `qr` renders any \
config (a .conf or a mesh node) as a scannable QR for a phone.",
"\n\n",
env!("CARGO_PKG_REPOSITORY"),
"\ncontributors: ",
env!("CARGO_PKG_AUTHORS"),
);
const LONG_VERSION: &str = concat!(
env!("CARGO_PKG_VERSION"),
"\n",
env!("CARGO_PKG_LICENSE"),
" ",
env!("CARGO_PKG_REPOSITORY"),
"\ncontributors: ",
env!("CARGO_PKG_AUTHORS"),
);
#[derive(Parser)]
#[command(
name = "ewg",
version,
long_version = LONG_VERSION,
about,
after_help = AFTER
)]
struct Cli {
#[arg(long, global = true, env = "EWG_DIR")]
dir: Option<PathBuf>,
#[command(subcommand)]
cmd: Option<Cmd>,
}
#[derive(Subcommand)]
#[allow(clippy::large_enum_variant)] enum Cmd {
Tui,
#[command(name = "self", subcommand)]
Selfie(selfcmd::Cmd),
#[command(visible_alias = "ls")]
List,
Status,
#[command(verbatim_doc_comment)]
Up { name: String },
#[command(verbatim_doc_comment)]
Down { name: String },
Dir(DirArgs),
Mesh(MeshArgs),
Key,
Psk,
#[command(verbatim_doc_comment)]
Pubkey { private: String },
#[command(verbatim_doc_comment)]
Qr {
target: String,
#[arg(short = 'm', long, default_value = "mesh.toml")]
manifest: PathBuf,
#[arg(short, long)]
out: Option<PathBuf>,
},
#[command(verbatim_doc_comment)]
Check {
#[arg(required = true)]
paths: Vec<PathBuf>,
},
}
fn main() -> Result<()> {
if !std::io::stdout().is_terminal() {
colored::control::set_override(false);
}
let cli = Cli::parse();
match cli.cmd {
Some(Cmd::Selfie(cmd)) => selfcmd::run(cmd),
None | Some(Cmd::Tui) => {
let dirs = registry::resolve_dirs(cli.dir)?;
elevate::elevate_for(&dirs)?;
tui::run(&dirs)
}
Some(Cmd::List) => {
let dirs = registry::resolve_dirs(cli.dir)?;
elevate::elevate_for(&dirs)?;
commands::list::run(&dirs)
}
Some(Cmd::Status) => {
let dirs = registry::resolve_dirs(cli.dir)?;
elevate::elevate_for(&dirs)?;
commands::status::run(&dirs)
}
Some(Cmd::Up { name }) => {
let dirs = registry::resolve_dirs(cli.dir)?;
elevate::elevate_for(&dirs)?;
wg::up(&wg::find(&dirs, &name)?)
}
Some(Cmd::Down { name }) => {
let dirs = registry::resolve_dirs(cli.dir)?;
elevate::elevate_for(&dirs)?;
wg::down(&wg::find(&dirs, &name)?)
}
Some(Cmd::Dir(action)) => commands::dir::run(action),
Some(Cmd::Mesh(action)) => commands::mesh::run(action),
Some(Cmd::Key) => commands::key::run(),
Some(Cmd::Psk) => commands::psk::run(),
Some(Cmd::Pubkey { private }) => commands::pubkey::run(&private),
Some(Cmd::Qr {
target,
manifest,
out,
}) => commands::qr::run(&target, &manifest, out.as_deref()),
Some(Cmd::Check { paths }) => commands::check::run(&paths),
}
}