Skip to content

Commit 972e85b

Browse files
committed
feat: Add serial ports config file
1 parent 8dea4e6 commit 972e85b

File tree

5 files changed

+151
-64
lines changed

5 files changed

+151
-64
lines changed

cargo-espflash/src/main.rs

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,12 @@ use std::{
77
use cargo_metadata::{Message, MetadataCommand};
88
use clap::{Args, CommandFactory, Parser, Subcommand};
99
use espflash::{
10-
cli::{self, config::Config, monitor::monitor, *},
10+
cli::{
11+
self,
12+
config::{Config, PortConfig},
13+
monitor::monitor,
14+
*,
15+
},
1116
flasher::FlashSize,
1217
logging::initialize_logger,
1318
targets::{Chip, XtalFrequency},
@@ -225,24 +230,27 @@ fn main() -> Result<()> {
225230
// Load any user configuration, if present.
226231
let config = Config::load()?;
227232

233+
// Load any user ports configuration, if present.
234+
let ports_config = PortConfig::load()?;
235+
228236
// Execute the correct action based on the provided subcommand and its
229237
// associated arguments.
230238
match args {
231-
Commands::BoardInfo(args) => board_info(&args, &config),
232-
Commands::ChecksumMd5(args) => checksum_md5(&args, &config),
239+
Commands::BoardInfo(args) => board_info(&args, &config, &ports_config),
240+
Commands::ChecksumMd5(args) => checksum_md5(&args, &config, &ports_config),
233241
Commands::Completions(args) => completions(&args, &mut Cli::command(), "cargo"),
234-
Commands::EraseFlash(args) => erase_flash(args, &config),
235-
Commands::EraseParts(args) => erase_parts(args, &config),
236-
Commands::EraseRegion(args) => erase_region(args, &config),
237-
Commands::Flash(args) => flash(args, &config),
238-
Commands::HoldInReset(args) => hold_in_reset(args, &config),
239-
Commands::ListPorts(args) => list_ports(&args, &config),
240-
Commands::Monitor(args) => serial_monitor(args, &config),
242+
Commands::EraseFlash(args) => erase_flash(args, &config, &ports_config),
243+
Commands::EraseParts(args) => erase_parts(args, &config, &ports_config),
244+
Commands::EraseRegion(args) => erase_region(args, &config, &ports_config),
245+
Commands::Flash(args) => flash(args, &config, &ports_config),
246+
Commands::HoldInReset(args) => hold_in_reset(args, &config, &ports_config),
247+
Commands::ListPorts(args) => list_ports(&args, &ports_config),
248+
Commands::Monitor(args) => serial_monitor(args, &config, &ports_config),
241249
Commands::PartitionTable(args) => partition_table(args),
242-
Commands::ReadFlash(args) => read_flash(args, &config),
243-
Commands::Reset(args) => reset(args, &config),
250+
Commands::ReadFlash(args) => read_flash(args, &config, &ports_config),
251+
Commands::Reset(args) => reset(args, &config, &ports_config),
244252
Commands::SaveImage(args) => save_image(args, &config),
245-
Commands::WriteBin(args) => write_bin(args, &config),
253+
Commands::WriteBin(args) => write_bin(args, &config, &ports_config),
246254
}
247255
}
248256

@@ -253,7 +261,7 @@ struct BuildContext {
253261
pub partition_table_path: Option<PathBuf>,
254262
}
255263

256-
pub fn erase_parts(args: ErasePartsArgs, config: &Config) -> Result<()> {
264+
pub fn erase_parts(args: ErasePartsArgs, config: &Config, ports_config: &PortConfig) -> Result<()> {
257265
if args.connect_args.no_stub {
258266
return Err(EspflashError::StubRequired).into_diagnostic();
259267
}
@@ -263,7 +271,7 @@ pub fn erase_parts(args: ErasePartsArgs, config: &Config) -> Result<()> {
263271
.as_deref()
264272
.or(config.partition_table.as_deref());
265273

266-
let mut flasher = connect(&args.connect_args, config, false, false)?;
274+
let mut flasher = connect(&args.connect_args, config, ports_config, false, false)?;
267275
let chip = flasher.chip();
268276
let partition_table = match partition_table {
269277
Some(path) => Some(parse_partition_table(path)?),
@@ -280,13 +288,14 @@ pub fn erase_parts(args: ErasePartsArgs, config: &Config) -> Result<()> {
280288
Ok(())
281289
}
282290

283-
fn flash(args: FlashArgs, config: &Config) -> Result<()> {
291+
fn flash(args: FlashArgs, config: &Config, ports_config: &PortConfig) -> Result<()> {
284292
let metadata = PackageMetadata::load(&args.build_args.package)?;
285293
let cargo_config = CargoConfig::load(&metadata.workspace_root, &metadata.package_root);
286294

287295
let mut flasher = connect(
288296
&args.connect_args,
289297
config,
298+
ports_config,
290299
args.flash_args.no_verify,
291300
args.flash_args.no_skip,
292301
)?;

espflash/src/bin/espflash.rs

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@ use std::{fs, path::PathBuf};
22

33
use clap::{Args, CommandFactory, Parser, Subcommand};
44
use espflash::{
5-
cli::{self, config::Config, monitor::monitor, *},
5+
cli::{
6+
self,
7+
config::{Config, PortConfig},
8+
monitor::monitor,
9+
*,
10+
},
611
flasher::FlashSize,
712
logging::initialize_logger,
813
targets::{Chip, XtalFrequency},
@@ -156,33 +161,36 @@ fn main() -> Result<()> {
156161
// Load any user configuration, if present.
157162
let config = Config::load()?;
158163

164+
// Load any user ports configuration, if present.
165+
let ports_config = PortConfig::load()?;
166+
159167
// Execute the correct action based on the provided subcommand and its
160168
// associated arguments.
161169
match args {
162-
Commands::BoardInfo(args) => board_info(&args, &config),
163-
Commands::ChecksumMd5(args) => checksum_md5(&args, &config),
170+
Commands::BoardInfo(args) => board_info(&args, &config, &ports_config),
171+
Commands::ChecksumMd5(args) => checksum_md5(&args, &config, &ports_config),
164172
Commands::Completions(args) => completions(&args, &mut Cli::command(), "espflash"),
165-
Commands::EraseFlash(args) => erase_flash(args, &config),
166-
Commands::EraseParts(args) => erase_parts(args, &config),
167-
Commands::EraseRegion(args) => erase_region(args, &config),
168-
Commands::Flash(args) => flash(args, &config),
169-
Commands::HoldInReset(args) => hold_in_reset(args, &config),
170-
Commands::ListPorts(args) => list_ports(&args, &config),
171-
Commands::Monitor(args) => serial_monitor(args, &config),
173+
Commands::EraseFlash(args) => erase_flash(args, &config, &ports_config),
174+
Commands::EraseParts(args) => erase_parts(args, &config, &ports_config),
175+
Commands::EraseRegion(args) => erase_region(args, &config, &ports_config),
176+
Commands::Flash(args) => flash(args, &config, &ports_config),
177+
Commands::HoldInReset(args) => hold_in_reset(args, &config, &ports_config),
178+
Commands::ListPorts(args) => list_ports(&args, &ports_config),
179+
Commands::Monitor(args) => serial_monitor(args, &config, &ports_config),
172180
Commands::PartitionTable(args) => partition_table(args),
173-
Commands::ReadFlash(args) => read_flash(args, &config),
174-
Commands::Reset(args) => reset(args, &config),
181+
Commands::ReadFlash(args) => read_flash(args, &config, &ports_config),
182+
Commands::Reset(args) => reset(args, &config, &ports_config),
175183
Commands::SaveImage(args) => save_image(args, &config),
176-
Commands::WriteBin(args) => write_bin(args, &config),
184+
Commands::WriteBin(args) => write_bin(args, &config, &ports_config),
177185
}
178186
}
179187

180-
pub fn erase_parts(args: ErasePartsArgs, config: &Config) -> Result<()> {
188+
pub fn erase_parts(args: ErasePartsArgs, config: &Config, ports_config: &PortConfig) -> Result<()> {
181189
if args.connect_args.no_stub {
182190
return Err(Error::StubRequired.into());
183191
}
184192

185-
let mut flasher = connect(&args.connect_args, config, false, false)?;
193+
let mut flasher = connect(&args.connect_args, config, ports_config, false, false)?;
186194
let chip = flasher.chip();
187195
let partition_table = match args.partition_table {
188196
Some(path) => Some(parse_partition_table(&path)?),
@@ -201,10 +209,11 @@ pub fn erase_parts(args: ErasePartsArgs, config: &Config) -> Result<()> {
201209
Ok(())
202210
}
203211

204-
fn flash(args: FlashArgs, config: &Config) -> Result<()> {
212+
fn flash(args: FlashArgs, config: &Config, ports_config: &PortConfig) -> Result<()> {
205213
let mut flasher = connect(
206214
&args.connect_args,
207215
config,
216+
ports_config,
208217
args.flash_args.no_verify,
209218
args.flash_args.no_skip,
210219
)?;

espflash/src/cli/config.rs

Lines changed: 66 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,18 +80,12 @@ pub struct Config {
8080
/// Bootloader path
8181
#[serde(default)]
8282
pub bootloader: Option<PathBuf>,
83-
/// Preferred serial port connection information
84-
#[serde(default)]
85-
pub connection: Connection,
8683
/// Partition table path
8784
#[serde(default)]
8885
pub partition_table: Option<PathBuf>,
8986
/// Partition table offset
9087
#[serde(default)]
9188
pub partition_table_offset: Option<u32>,
92-
/// Preferred USB devices
93-
#[serde(default)]
94-
pub usb_device: Vec<UsbDevice>,
9589
/// Flash settings
9690
#[serde(default)]
9791
pub flash: FlashSettings,
@@ -164,6 +158,72 @@ impl Config {
164158
}
165159
}
166160

161+
/// Deserialized contents of a serial port configuration file
162+
#[derive(Debug, Deserialize, Serialize, Default, Clone)]
163+
pub struct PortConfig {
164+
/// Preferred serial port connection information
165+
#[serde(default)]
166+
pub connection: Connection,
167+
/// Partition table path
168+
/// Preferred USB devices
169+
#[serde(default)]
170+
pub usb_device: Vec<UsbDevice>,
171+
/// Path of the file to save the configuration to
172+
#[serde(skip)]
173+
save_path: PathBuf,
174+
}
175+
176+
impl PortConfig {
177+
/// Gets the path to the configuration file.
178+
pub fn get_config_path() -> Result<PathBuf, Error> {
179+
let local_config = std::env::current_dir()?.join("espflash_ports.toml");
180+
if local_config.exists() {
181+
return Ok(local_config);
182+
}
183+
if let Some(parent_folder) = std::env::current_dir()?.parent() {
184+
let workspace_config = parent_folder.join("espflash_ports.toml");
185+
if workspace_config.exists() {
186+
return Ok(workspace_config);
187+
}
188+
}
189+
190+
let project_dirs = ProjectDirs::from("rs", "esp", "espflash").unwrap();
191+
let global_config = project_dirs.config_dir().join("espflash_ports.toml");
192+
Ok(global_config)
193+
}
194+
195+
/// Load configuration from the configuration file
196+
pub fn load() -> Result<Self> {
197+
let file = Self::get_config_path()?;
198+
199+
let mut config = if let Ok(data) = read_to_string(&file) {
200+
toml::from_str(&data).into_diagnostic()?
201+
} else {
202+
Self::default()
203+
};
204+
205+
config.save_path = file;
206+
debug!("Config: {:#?}", &config);
207+
Ok(config)
208+
}
209+
210+
/// Save configuration to the configuration file
211+
pub fn save_with<F: Fn(&mut Self)>(&self, modify_fn: F) -> Result<()> {
212+
let mut copy = self.clone();
213+
modify_fn(&mut copy);
214+
215+
let serialized = toml::to_string(&copy)
216+
.into_diagnostic()
217+
.wrap_err("Failed to serialize config")?;
218+
create_dir_all(self.save_path.parent().unwrap())
219+
.into_diagnostic()
220+
.wrap_err("Failed to create config directory")?;
221+
write(&self.save_path, serialized)
222+
.into_diagnostic()
223+
.wrap_err_with(|| format!("Failed to write config to {}", self.save_path.display()))
224+
}
225+
}
226+
167227
#[cfg(test)]
168228
mod tests {
169229
use serde::Deserialize;

0 commit comments

Comments
 (0)