use std::path::PathBuf;
use defmt_decoder::DEFMT_VERSION;
use git_version::git_version;
use log::Level;
use probe_rs::Probe;
use structopt::{clap::AppSettings, StructOpt};
use crate::probe;
const EXIT_SUCCESS: i32 = 0;
#[derive(StructOpt)]
#[structopt(name = "probe-run", setting = AppSettings::TrailingVarArg)]
pub(crate) struct Opts {
#[structopt(long)]
list_chips: bool,
#[structopt(long)]
list_probes: bool,
#[structopt(long, required_unless_one(&["list-chips", "list-probes", "version"]), env = "PROBE_RUN_CHIP")]
chip: Option<String>,
#[structopt(long, env = "PROBE_RUN_PROBE")]
pub(crate) probe: Option<String>,
#[structopt(long)]
pub(crate) speed: Option<u32>,
#[structopt(name = "ELF", parse(from_os_str), required_unless_one(&["list-chips", "list-probes", "version"]))]
elf: Option<PathBuf>,
#[structopt(long, conflicts_with = "defmt")]
pub(crate) no_flash: bool,
#[structopt(long)]
pub(crate) connect_under_reset: bool,
#[structopt(short, long, parse(from_occurrences))]
verbose: u32,
#[structopt(short = "V", long)]
version: bool,
#[structopt(long, default_value = "auto")]
pub(crate) backtrace: String,
#[structopt(long, default_value = "50")]
pub(crate) backtrace_limit: u32,
#[structopt(long)]
pub(crate) shorten_paths: bool,
#[structopt(long)]
pub(crate) measure_stack: bool,
#[structopt(name = "REST")]
_rest: Vec<String>,
}
pub(crate) fn handle_arguments() -> anyhow::Result<i32> {
let opts: Opts = Opts::from_args();
let verbose = opts.verbose;
defmt_decoder::log::init_logger(verbose >= 1, move |metadata| {
if defmt_decoder::log::is_defmt_frame(metadata) {
true } else {
if verbose >= 2 {
true
} else if verbose >= 1 {
metadata.target().starts_with("probe_run")
} else {
metadata.target().starts_with("probe_run") && metadata.level() <= Level::Info
}
}
});
if opts.version {
print_version();
Ok(EXIT_SUCCESS)
} else if opts.list_probes {
probe::print(&Probe::list_all());
Ok(EXIT_SUCCESS)
} else if opts.list_chips {
print_chips();
Ok(EXIT_SUCCESS)
} else if let (Some(elf), Some(chip)) = (opts.elf.as_deref(), opts.chip.as_deref()) {
crate::run_target_program(elf, chip, &opts)
} else {
unreachable!("due to `StructOpt` constraints")
}
}
fn print_chips() {
let registry = probe_rs::config::families().expect("Could not retrieve chip family registry");
for chip_family in registry {
println!("{}\n Variants:", chip_family.name);
for variant in chip_family.variants.iter() {
println!(" {}", variant.name);
}
}
}
fn print_version() {
const VERSION: &str = env!("CARGO_PKG_VERSION");
const GIT_DESCRIBE: &str = git_version!(fallback = "--", args = ["--long"]);
let hash = extract_git_hash(GIT_DESCRIBE);
println!(
"{} {}\nsupported defmt version: {}",
VERSION, hash, DEFMT_VERSION
);
}
fn extract_git_hash(git_describe: &str) -> &str {
git_describe.split('-').nth(2).unwrap()
}
#[cfg(test)]
mod tests {
use rstest::rstest;
use super::*;
#[rstest]
#[case::normal("v0.2.3-12-g25c50d2", "g25c50d2")]
#[case::modified("v0.2.3-12-g25c50d2-modified", "g25c50d2")]
#[case::fallback("--", "")]
fn should_extract_hash_from_description(#[case] description: &str, #[case] expected: &str) {
let hash = extract_git_hash(description);
assert_eq!(hash, expected)
}
}