use std::path::PathBuf;
use defmt_decoder::DEFMT_VERSION;
use git_version::git_version;
use log::Level;
use probe_rs::{config::registry, 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)]
pub(crate) force_backtrace: bool,
#[structopt(long, default_value = "50")]
pub(crate) max_backtrace_len: u32,
#[structopt(long)]
pub(crate) shorten_paths: 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 = registry::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 super::*;
#[test]
fn should_extract_hash_from_description() {
let hash = extract_git_hash("v0.2.3-12-g25c50d2");
assert_eq!(hash, "g25c50d2")
}
#[test]
fn should_extract_hash_from_modified_description() {
let hash = extract_git_hash("v0.2.3-12-g25c50d2-modified");
assert_eq!(hash, "g25c50d2")
}
#[test]
fn should_extract_empty_from_fallback() {
let hash = extract_git_hash("--");
assert_eq!(hash, "")
}
}