Skip to content

Commit 73bc596

Browse files
authored
Merge pull request #133 from jessebraham/feature/clap-refactor
Refactor the command-line argument handling
2 parents 8bd0dd4 + 194cc45 commit 73bc596

File tree

6 files changed

+285
-300
lines changed

6 files changed

+285
-300
lines changed

cargo-espflash/src/main.rs

Lines changed: 96 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,11 @@ use std::{
88
use cargo_metadata::Message;
99
use clap::{AppSettings, Parser};
1010
use espflash::{
11-
cli::{clap::*, connect, monitor::monitor},
12-
Chip, Config, FirmwareImage, ImageFormatId, PartitionTable,
11+
cli::{
12+
board_info, connect, flash_elf_image, monitor::monitor, save_elf_as_image, ConnectOpts,
13+
FlashOpts,
14+
},
15+
Chip, Config, ImageFormatId,
1316
};
1417
use miette::{IntoDiagnostic, Result, WrapErr};
1518

@@ -24,12 +27,11 @@ mod error;
2427
mod package_metadata;
2528

2629
#[derive(Parser)]
30+
#[clap(bin_name = "cargo", version)]
2731
#[clap(global_setting = AppSettings::PropagateVersion)]
28-
#[clap(bin_name = "cargo")]
29-
#[clap(version = env!("CARGO_PKG_VERSION"))]
3032
struct Opts {
3133
#[clap(subcommand)]
32-
sub_cmd: CargoSubCommand,
34+
subcommand: CargoSubCommand,
3335
}
3436

3537
#[derive(Parser)]
@@ -40,122 +42,137 @@ enum CargoSubCommand {
4042
#[derive(Parser)]
4143
struct EspFlashOpts {
4244
#[clap(flatten)]
43-
flash_args: FlashArgs,
45+
flash_opts: FlashOpts,
4446
#[clap(flatten)]
45-
build_args: BuildArgs,
47+
build_opts: BuildOpts,
4648
#[clap(flatten)]
47-
connect_args: ConnectArgs,
49+
connect_opts: ConnectOpts,
4850
#[clap(subcommand)]
49-
sub_cmd: Option<SubCommand>,
51+
subcommand: Option<SubCommand>,
5052
}
5153

5254
#[derive(Parser)]
5355
pub enum SubCommand {
56+
/// Display information about the connected board and exit without flashing
57+
BoardInfo(ConnectOpts),
58+
/// Save the image to disk instead of flashing to device
5459
SaveImage(SaveImageOpts),
55-
BoardInfo(BoardInfoOpts),
60+
}
61+
62+
#[derive(Parser)]
63+
pub struct BuildOpts {
64+
/// Build the application using the release profile
65+
#[clap(long)]
66+
pub release: bool,
67+
/// Example to build and flash
68+
#[clap(long)]
69+
pub example: Option<String>,
70+
/// Specify a (binary) package within a workspace to be built
71+
#[clap(long)]
72+
pub package: Option<String>,
73+
/// Comma delimited list of build features
74+
#[clap(long, use_delimiter = true)]
75+
pub features: Option<Vec<String>>,
76+
/// Image format to flash (bootloader/direct-boot)
77+
#[clap(long)]
78+
pub format: Option<String>,
79+
/// Target to build for
80+
#[clap(long)]
81+
pub target: Option<String>,
82+
/// Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details
83+
#[clap(short = 'Z')]
84+
pub unstable: Option<Vec<String>>,
85+
}
86+
87+
#[derive(Parser)]
88+
pub struct SaveImageOpts {
89+
#[clap(flatten)]
90+
pub build_args: BuildOpts,
91+
/// File name to save the generated image to
92+
pub file: PathBuf,
5693
}
5794

5895
fn main() -> Result<()> {
5996
miette::set_panic_hook();
6097

61-
let CargoSubCommand::Espflash(opts) = Opts::parse().sub_cmd;
98+
let CargoSubCommand::Espflash(opts) = Opts::parse().subcommand;
6299

63100
let config = Config::load()?;
64101
let metadata = CargoEspFlashMeta::load("Cargo.toml")?;
65102
let cargo_config = parse_cargo_config(".")?;
66103

67-
match opts.sub_cmd {
68-
Some(SubCommand::BoardInfo(matches)) => board_info(matches, config, metadata, cargo_config),
69-
Some(SubCommand::SaveImage(matches)) => save_image(matches, config, metadata, cargo_config),
70-
None => flash(opts, config, metadata, cargo_config),
104+
if let Some(subcommand) = opts.subcommand {
105+
use SubCommand::*;
106+
107+
match subcommand {
108+
BoardInfo(opts) => board_info(opts, config),
109+
SaveImage(opts) => save_image(opts, metadata, cargo_config),
110+
}
111+
} else {
112+
flash(opts, config, metadata, cargo_config)
71113
}
72114
}
73115

74116
fn flash(
75-
matches: EspFlashOpts,
117+
opts: EspFlashOpts,
76118
config: Config,
77119
metadata: CargoEspFlashMeta,
78120
cargo_config: CargoConfig,
79121
) -> Result<()> {
80-
// Connect the Flasher to the target device and print the board information
81-
// upon connection. If the '--board-info' flag has been provided, we have
82-
// nothing left to do so exit early.
83-
let mut flasher = connect(&matches.connect_args, &config)?;
84-
flasher.board_info()?;
122+
let mut flasher = connect(&opts.connect_opts, &config)?;
85123

86-
if matches.flash_args.board_info {
87-
return Ok(());
88-
}
89-
90-
let path = build(&matches.build_args, &cargo_config, Some(flasher.chip()))
124+
let artifact_path = build(&opts.build_opts, &cargo_config, Some(flasher.chip()))
91125
.wrap_err("Failed to build project")?;
92126

93-
// If the '--bootloader' option is provided, load the binary file at the
94-
// specified path.
95-
let bootloader = if let Some(path) = matches
96-
.flash_args
97-
.bootloader
98-
.as_deref()
99-
.or_else(|| metadata.bootloader.as_deref())
100-
{
101-
let path = fs::canonicalize(path).into_diagnostic()?;
102-
let data = fs::read(path).into_diagnostic()?;
103-
Some(data)
104-
} else {
105-
None
106-
};
107-
108-
// If the '--partition-table' option is provided, load the partition table from
109-
// the CSV at the specified path.
110-
let partition_table = if let Some(path) = matches
111-
.flash_args
112-
.partition_table
113-
.as_deref()
114-
.or_else(|| metadata.partition_table.as_deref())
115-
{
116-
let path = fs::canonicalize(path).into_diagnostic()?;
117-
let data = fs::read_to_string(path)
118-
.into_diagnostic()
119-
.wrap_err("Failed to open partition table")?;
120-
let table =
121-
PartitionTable::try_from_str(data).wrap_err("Failed to parse partition table")?;
122-
Some(table)
123-
} else {
124-
None
125-
};
126-
127-
let image_format = matches
128-
.build_args
129-
.format
130-
.as_deref()
131-
.map(ImageFormatId::from_str)
132-
.transpose()?
133-
.or(metadata.format);
127+
// Print the board information once the project has successfully built. We do
128+
// here rather than upon connection to show the Cargo output prior to the board
129+
// information, rather than breaking up cargo-espflash's output.
130+
flasher.board_info()?;
134131

135132
// Read the ELF data from the build path and load it to the target.
136-
let elf_data = fs::read(path).into_diagnostic()?;
137-
if matches.flash_args.ram {
133+
let elf_data = fs::read(artifact_path).into_diagnostic()?;
134+
135+
if opts.flash_opts.ram {
138136
flasher.load_elf_to_ram(&elf_data)?;
139137
} else {
140-
flasher.load_elf_to_flash_with_format(
138+
let bootloader = opts
139+
.flash_opts
140+
.bootloader
141+
.as_deref()
142+
.or(metadata.bootloader.as_deref());
143+
144+
let partition_table = opts
145+
.flash_opts
146+
.partition_table
147+
.as_deref()
148+
.or(metadata.partition_table.as_deref());
149+
150+
let image_format = opts
151+
.build_opts
152+
.format
153+
.as_deref()
154+
.map(ImageFormatId::from_str)
155+
.transpose()?
156+
.or(metadata.format);
157+
158+
flash_elf_image(
159+
&mut flasher,
141160
&elf_data,
142161
bootloader,
143162
partition_table,
144163
image_format,
145164
)?;
146165
}
147-
println!("\nFlashing has completed!");
148166

149-
if matches.flash_args.monitor {
167+
if opts.flash_opts.monitor {
150168
monitor(flasher.into_serial()).into_diagnostic()?;
151169
}
152170

153-
// We're all done!
154171
Ok(())
155172
}
156173

157174
fn build(
158-
build_options: &BuildArgs,
175+
build_options: &BuildOpts,
159176
cargo_config: &CargoConfig,
160177
chip: Option<Chip>,
161178
) -> Result<PathBuf> {
@@ -273,12 +290,11 @@ fn build(
273290
}
274291

275292
fn save_image(
276-
matches: SaveImageOpts,
277-
_config: Config,
293+
opts: SaveImageOpts,
278294
metadata: CargoEspFlashMeta,
279295
cargo_config: CargoConfig,
280296
) -> Result<()> {
281-
let target = matches
297+
let target = opts
282298
.build_args
283299
.target
284300
.as_deref()
@@ -288,45 +304,19 @@ fn save_image(
288304

289305
let chip = Chip::from_target(target).ok_or_else(|| Error::UnknownTarget(target.into()))?;
290306

291-
let path = build(&matches.build_args, &cargo_config, Some(chip))?;
307+
let path = build(&opts.build_args, &cargo_config, Some(chip))?;
292308
let elf_data = fs::read(path).into_diagnostic()?;
293309

294-
let image = FirmwareImage::from_data(&elf_data)?;
295-
296-
let image_format = matches
310+
let image_format = opts
297311
.build_args
298312
.format
299313
.as_deref()
300314
.map(ImageFormatId::from_str)
301315
.transpose()?
302316
.or(metadata.format);
303317

304-
let flash_image = chip.get_flash_image(&image, None, None, image_format, None)?;
305-
let parts: Vec<_> = flash_image.ota_segments().collect();
306-
307-
let out_path = matches.file;
318+
save_elf_as_image(chip, &elf_data, opts.file, image_format)?;
308319

309-
match parts.as_slice() {
310-
[single] => fs::write(out_path, &single.data).into_diagnostic()?,
311-
parts => {
312-
for part in parts {
313-
let part_path = format!("{:#x}_{}", part.addr, out_path);
314-
fs::write(part_path, &part.data).into_diagnostic()?
315-
}
316-
}
317-
}
318-
319-
Ok(())
320-
}
321-
322-
fn board_info(
323-
matches: BoardInfoOpts,
324-
config: Config,
325-
_metadata: CargoEspFlashMeta,
326-
_cargo_config: CargoConfig,
327-
) -> Result<()> {
328-
let mut flasher = connect(&matches.connect_args, &config)?;
329-
flasher.board_info()?;
330320
Ok(())
331321
}
332322

cargo-espflash/src/package_metadata.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
1-
use crate::error::{Error, TomlError};
1+
use std::{
2+
fs::read_to_string,
3+
path::{Path, PathBuf},
4+
};
5+
26
use cargo_toml::Manifest;
37
use espflash::ImageFormatId;
48
use miette::{IntoDiagnostic, Result, WrapErr};
59
use serde::Deserialize;
6-
use std::fs::read_to_string;
7-
use std::path::Path;
10+
11+
use crate::error::{Error, TomlError};
812

913
#[derive(Clone, Debug, Deserialize, Default)]
1014
pub struct CargoEspFlashMeta {
11-
pub partition_table: Option<String>,
12-
pub bootloader: Option<String>,
15+
pub partition_table: Option<PathBuf>,
16+
pub bootloader: Option<PathBuf>,
1317
pub format: Option<ImageFormatId>,
1418
}
1519

espflash/src/cli/clap.rs

Lines changed: 0 additions & 70 deletions
This file was deleted.

0 commit comments

Comments
 (0)