diff --git a/cargo-espflash/Cargo.toml b/cargo-espflash/Cargo.toml index 0fb571a3..78ce97c7 100644 --- a/cargo-espflash/Cargo.toml +++ b/cargo-espflash/Cargo.toml @@ -26,6 +26,7 @@ categories = [ [dependencies] miette = "2" cargo_metadata = "0.14" +cargo_toml = "0.10" clap = "2.33" crossterm = "0.21" espflash = { version = "*", path = "../espflash" } @@ -33,4 +34,4 @@ guess_host_triple = "0.1" serde = { version = "1.0", features = ["derive"] } serial = "0.4" toml = "0.5" -thiserror = "1" \ No newline at end of file +thiserror = "1" diff --git a/cargo-espflash/README.md b/cargo-espflash/README.md index b883b108..b8d505de 100644 --- a/cargo-espflash/README.md +++ b/cargo-espflash/README.md @@ -43,6 +43,16 @@ or `%APPDATA%/esp/espflash/espflash.toml` on Windows. serial = "/dev/ttyUSB0" ``` +### Package metadata + +You can also specify the bootloader or partition table for a project in the package metadata in `Cargo.toml` + +```toml +[package.metadata.espflash] +partition_table = "partitions.csv" +bootloader = "bootloader.bin" +``` + ### Example ```bash diff --git a/cargo-espflash/src/error.rs b/cargo-espflash/src/error.rs index 53910e15..af6e7846 100644 --- a/cargo-espflash/src/error.rs +++ b/cargo-espflash/src/error.rs @@ -26,4 +26,10 @@ pub enum Error { help("Please specify which artifact to flash using --bin") )] MultipleArtifacts, + #[error("Specified partition table is not a csv file")] + #[diagnostic(code(cargo_espflash::partition_table_path))] + InvalidPartitionTablePath, + #[error("Specified bootloader table is not a bin file")] + #[diagnostic(code(cargo_espflash::bootloader_path))] + InvalidBootloaderPath, } diff --git a/cargo-espflash/src/main.rs b/cargo-espflash/src/main.rs index 3bb95afc..effa5972 100644 --- a/cargo-espflash/src/main.rs +++ b/cargo-espflash/src/main.rs @@ -1,8 +1,11 @@ +use cargo_config::has_build_std; use cargo_metadata::Message; use clap::{App, Arg, SubCommand}; use error::Error; use espflash::{Config, Flasher, PartitionTable}; use miette::{IntoDiagnostic, Result, WrapErr}; +use monitor::monitor; +use package_metadata::CargoEspFlashMeta; use serial::{BaudRate, SerialPort}; use std::{ fs, @@ -11,13 +14,11 @@ use std::{ string::ToString, }; -use cargo_config::has_build_std; -use monitor::monitor; - mod cargo_config; mod error; mod line_endings; mod monitor; +mod package_metadata; fn main() -> Result<()> { let mut app = App::new(env!("CARGO_PKG_NAME")) @@ -100,6 +101,7 @@ fn main() -> Result<()> { }; let config = Config::load(); + let metadata = CargoEspFlashMeta::load("Cargo.toml")?; // The serial port must be specified, either as a command-line argument or in // the cargo configuration file. In the case that both have been provided the @@ -158,7 +160,10 @@ fn main() -> Result<()> { // If the '--bootloader' option is provided, load the binary file at the // specified path. - let bootloader = if let Some(path) = matches.value_of("bootloader") { + let bootloader = if let Some(path) = matches + .value_of("bootloader") + .or_else(|| metadata.bootloader.as_deref()) + { let path = fs::canonicalize(path).into_diagnostic()?; let data = fs::read(path).into_diagnostic()?; Some(data) @@ -168,7 +173,10 @@ fn main() -> Result<()> { // If the '--partition-table' option is provided, load the partition table from // the CSV at the specified path. - let partition_table = if let Some(path) = matches.value_of("partition_table") { + let partition_table = if let Some(path) = matches + .value_of("partition_table") + .or_else(|| metadata.partition_table.as_deref()) + { let path = fs::canonicalize(path).into_diagnostic()?; let data = fs::read_to_string(path).into_diagnostic()?; let table = PartitionTable::try_from_str(data)?; diff --git a/cargo-espflash/src/package_metadata.rs b/cargo-espflash/src/package_metadata.rs new file mode 100644 index 00000000..830a8742 --- /dev/null +++ b/cargo-espflash/src/package_metadata.rs @@ -0,0 +1,43 @@ +use crate::error::Error; +use cargo_toml::Manifest; +use miette::{IntoDiagnostic, Result, WrapErr}; +use serde::Deserialize; +use std::path::Path; + +#[derive(Clone, Debug, Deserialize, Default)] +pub struct CargoEspFlashMeta { + pub partition_table: Option, + pub bootloader: Option, +} + +#[derive(Clone, Debug, Default, Deserialize)] +pub struct Meta { + pub espflash: Option, +} + +impl CargoEspFlashMeta { + pub fn load>(path: P) -> Result { + let manifest = Manifest::::from_path_with_metadata(path) + .into_diagnostic() + .wrap_err("Failed to parse Cargo.toml")?; + let meta = manifest + .package + .and_then(|pkg| pkg.metadata) + .unwrap_or_default() + .espflash + .unwrap_or_default(); + match meta.partition_table { + Some(table) if !table.ends_with(".csv") => { + return Err(Error::InvalidPartitionTablePath.into()) + } + _ => {} + } + match meta.bootloader { + Some(table) if !table.ends_with(".bin") => { + return Err(Error::InvalidBootloaderPath.into()) + } + _ => {} + } + Ok(meta) + } +}