Add minimal CLI debug utilities
This commit is contained in:
parent
32a36f8627
commit
23f5f607cc
7 changed files with 273 additions and 2 deletions
113
backend/Cargo.lock
generated
113
backend/Cargo.lock
generated
|
@ -92,6 +92,54 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.6.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e2e1ebcb11de5c03c67de28a7df593d32191b44939c482e97702baaaa6ab6a5"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-parse",
|
||||
"anstyle-query",
|
||||
"anstyle-wincon",
|
||||
"colorchoice",
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2faccea4cc4ab4a667ce676a30e8ec13922a692c99bb8f5b11f1502c72e04220"
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-parse"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c"
|
||||
dependencies = [
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-query"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648"
|
||||
dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-wincon"
|
||||
version = "3.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-recursion"
|
||||
version = "1.0.5"
|
||||
|
@ -280,6 +328,46 @@ dependencies = [
|
|||
"libloading",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.4.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.4.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
"clap_lex",
|
||||
"strsim",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
|
||||
|
||||
[[package]]
|
||||
name = "cmake"
|
||||
version = "0.1.50"
|
||||
|
@ -289,6 +377,12 @@ dependencies = [
|
|||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
|
||||
|
||||
[[package]]
|
||||
name = "community_settings_core"
|
||||
version = "0.1.0"
|
||||
|
@ -624,6 +718,12 @@ dependencies = [
|
|||
"http",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.3.3"
|
||||
|
@ -1072,6 +1172,7 @@ name = "powertools"
|
|||
version = "1.5.0-ng1"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"clap",
|
||||
"community_settings_core",
|
||||
"libc",
|
||||
"libryzenadj",
|
||||
|
@ -1364,6 +1465,12 @@ version = "0.9.8"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "2.4.1"
|
||||
|
@ -1691,6 +1798,12 @@ version = "0.7.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
|
|
|
@ -37,6 +37,8 @@ libryzenadj = { version = "0.13" }
|
|||
# ureq's tls feature does not like musl targets
|
||||
ureq = { version = "2", features = ["json", "gzip", "brotli", "charset"], default-features = false, optional = true }
|
||||
|
||||
clap = { version = "4.4", features = [ "derive" ] }
|
||||
|
||||
[features]
|
||||
default = ["online", "decky"]
|
||||
decky = ["usdpl-back/decky"]
|
||||
|
|
42
backend/src/cli/args.rs
Normal file
42
backend/src/cli/args.rs
Normal file
|
@ -0,0 +1,42 @@
|
|||
use clap::{Parser, Subcommand};
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(author, version, about, long_about = None)]
|
||||
pub struct Args {
|
||||
/// TCP port for front-end client connection
|
||||
#[arg(long)]
|
||||
pub port: Option<u16>,
|
||||
|
||||
/// Override log file location
|
||||
#[arg(long)]
|
||||
pub log: Option<std::path::PathBuf>,
|
||||
|
||||
/// Force verbose logging
|
||||
#[arg(short, long)]
|
||||
pub verbose: bool,
|
||||
|
||||
/// Specail operation to perform
|
||||
#[command(subcommand)]
|
||||
pub op: Option<Operation>,
|
||||
}
|
||||
|
||||
impl Args {
|
||||
pub fn load() -> Self {
|
||||
Self::parse()
|
||||
}
|
||||
|
||||
pub fn is_default(&self) -> bool {
|
||||
self.port.is_none()
|
||||
&& self.log.is_none()
|
||||
&& !self.verbose
|
||||
&& self.op.is_none()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Subcommand, Debug)]
|
||||
pub enum Operation {
|
||||
/// Dump useful system information for adding new device support
|
||||
DumpSys,
|
||||
/// Remove all files created by PowerTools, not including $HOME/homebrew/plugins/PowerTools/
|
||||
Clean,
|
||||
}
|
21
backend/src/cli/clean.rs
Normal file
21
backend/src/cli/clean.rs
Normal file
|
@ -0,0 +1,21 @@
|
|||
pub fn clean_up() -> Result<(), ()> {
|
||||
let dirs = vec![
|
||||
crate::utility::settings_dir_old(),
|
||||
crate::utility::settings_dir(),
|
||||
];
|
||||
|
||||
if let Err(e) = clean_up_io(dirs.iter()) {
|
||||
log::error!("Error removing directories: {}", e);
|
||||
Err(())
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn clean_up_io(directories: impl Iterator<Item=impl AsRef<std::path::Path>>) -> std::io::Result<()> {
|
||||
let results = directories.map(|dir| std::fs::remove_dir_all(dir));
|
||||
for res in results {
|
||||
res?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
66
backend/src/cli/dump_sys.rs
Normal file
66
backend/src/cli/dump_sys.rs
Normal file
|
@ -0,0 +1,66 @@
|
|||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
use std::thread::{self, JoinHandle};
|
||||
use std::sync::mpsc::{channel, Sender};
|
||||
use std::io::Write;
|
||||
|
||||
pub fn dump_sys_info() -> Result<(), ()> {
|
||||
let (tx, rx) = channel();
|
||||
let mut join_handles = Vec::new();
|
||||
let useful_files = vec![
|
||||
PathBuf::from("/proc/ioports"),
|
||||
PathBuf::from("/proc/cpuinfo"),
|
||||
PathBuf::from("/etc/os-release"),
|
||||
];
|
||||
for file in useful_files {
|
||||
join_handles.push(read_file(file, tx.clone()));
|
||||
}
|
||||
|
||||
let useful_commands = vec![
|
||||
"dmidecode",
|
||||
];
|
||||
for cmd in useful_commands.into_iter() {
|
||||
join_handles.push(execute_command(cmd, tx.clone()));
|
||||
}
|
||||
|
||||
for join_handle in join_handles.into_iter() {
|
||||
if let Err(e) = join_handle.join() {
|
||||
log::error!("Thread failed to complete: {:?}", e);
|
||||
}
|
||||
}
|
||||
|
||||
let mut dump_file = std::fs::File::create("powertools_sys_dump.txt").expect("Failed to create dump file");
|
||||
for response in rx.into_iter() {
|
||||
dump_file.write(
|
||||
&format!("{} v{} ###### {} ######\n{}\n",
|
||||
crate::consts::PACKAGE_NAME,
|
||||
crate::consts::PACKAGE_VERSION,
|
||||
response.0,
|
||||
response.1.unwrap_or("[None]".to_owned())
|
||||
).into_bytes()
|
||||
).expect("Failed to write to dump file");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn read_file(file: impl AsRef<Path> + Send + 'static, tx: Sender<(String, Option<String>)>) -> JoinHandle<()> {
|
||||
thread::spawn(move || {
|
||||
let file = file.as_ref();
|
||||
tx.send(
|
||||
(file.display().to_string(),
|
||||
std::fs::read_to_string(file).ok())
|
||||
).expect("Failed to send file contents");
|
||||
})
|
||||
}
|
||||
|
||||
fn execute_command(command: &'static str, tx: Sender<(String, Option<String>)>) -> JoinHandle<()> {
|
||||
thread::spawn(move || {
|
||||
tx.send(
|
||||
(command.to_owned(), Command::new(command)
|
||||
.output()
|
||||
.map(|out| String::from_utf8_lossy(&out.stdout).into_owned())
|
||||
.ok()
|
||||
)).expect("Failed to send command output");
|
||||
}
|
||||
)
|
||||
}
|
12
backend/src/cli/mod.rs
Normal file
12
backend/src/cli/mod.rs
Normal file
|
@ -0,0 +1,12 @@
|
|||
mod args;
|
||||
mod clean;
|
||||
mod dump_sys;
|
||||
|
||||
pub use args::{Args, Operation};
|
||||
|
||||
pub fn do_op(op: &Operation) -> Result<(), ()> {
|
||||
match op {
|
||||
Operation::DumpSys => dump_sys::dump_sys_info(),
|
||||
Operation::Clean => clean::clean_up(),
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
mod api;
|
||||
mod cli;
|
||||
mod persist;
|
||||
mod settings;
|
||||
mod state;
|
||||
|
@ -19,13 +20,18 @@ use usdpl_back::core::serdes::Primitive;
|
|||
use usdpl_back::Instance;
|
||||
|
||||
fn main() -> Result<(), ()> {
|
||||
let args = cli::Args::load();
|
||||
#[cfg(debug_assertions)]
|
||||
let log_filepath = usdpl_back::api::dirs::home()
|
||||
.unwrap_or_else(|| "/tmp/".into())
|
||||
.join(PACKAGE_NAME.to_owned() + ".log");
|
||||
#[cfg(not(debug_assertions))]
|
||||
let log_filepath = std::path::Path::new("/tmp").join(format!("{}.log", PACKAGE_NAME));
|
||||
let log_filepath = args.log.clone().unwrap_or(log_filepath);
|
||||
println!("Logging to: {:?}", log_filepath);
|
||||
if !args.is_default() {
|
||||
println!("CLI arguments, as parsed: {:?}", &args);
|
||||
}
|
||||
#[cfg(debug_assertions)]
|
||||
let old_log_filepath = usdpl_back::api::dirs::home()
|
||||
.unwrap_or_else(|| "/tmp/".into())
|
||||
|
@ -44,7 +50,7 @@ fn main() -> Result<(), ()> {
|
|||
},
|
||||
#[cfg(not(debug_assertions))]
|
||||
{
|
||||
LevelFilter::Info
|
||||
if args.verbose { LevelFilter::Debug } else { LevelFilter::Info }
|
||||
},
|
||||
Default::default(),
|
||||
std::fs::File::create(&log_filepath).expect("Failed to create log file"),
|
||||
|
@ -52,6 +58,15 @@ fn main() -> Result<(), ()> {
|
|||
)
|
||||
.unwrap();
|
||||
log::debug!("Logging to: {:?}.", log_filepath);
|
||||
log::info!("CLI arguments, as parsed: {:?}", &args);
|
||||
|
||||
// sepcial operation start-up
|
||||
if let Some(op) = &args.op {
|
||||
return cli::do_op(op);
|
||||
// do not continue with regular startup
|
||||
}
|
||||
|
||||
// regular start-up
|
||||
log::info!("Starting back-end ({} v{})", PACKAGE_NAME, PACKAGE_VERSION);
|
||||
println!("Starting back-end ({} v{})", PACKAGE_NAME, PACKAGE_VERSION);
|
||||
log::info!(
|
||||
|
@ -125,7 +140,7 @@ fn main() -> Result<(), ()> {
|
|||
|
||||
let (message_getter, message_dismisser) = api::message::MessageHandler::new().to_callables();
|
||||
|
||||
let instance = Instance::new(PORT)
|
||||
let instance = Instance::new(args.port.unwrap_or(PORT))
|
||||
.register("V_INFO", |_: Vec<Primitive>| {
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue