diff --git a/native/src/base/derive/argh/mod.rs b/native/src/base/derive/argh/mod.rs index 115740f28..68a9640fe 100644 --- a/native/src/base/derive/argh/mod.rs +++ b/native/src/base/derive/argh/mod.rs @@ -279,7 +279,7 @@ fn impl_from_args_struct( .collect(); ensure_unique_names(errors, &fields); - ensure_only_last_positional_is_optional(errors, &fields); + ensure_only_trailing_positionals_are_optional(errors, &fields); let impl_span = Span::call_site(); @@ -441,17 +441,22 @@ fn get_help_triggers(type_attrs: &TypeAttrs) -> Vec { }) } -/// Ensures that only the last positional arg is non-required. -fn ensure_only_last_positional_is_optional(errors: &Errors, fields: &[StructField<'_>]) { +/// Ensures that only trailing positional args are non-required. +fn ensure_only_trailing_positionals_are_optional(errors: &Errors, fields: &[StructField<'_>]) { let mut first_non_required_span = None; for field in fields { if field.kind == FieldKind::Positional { - if let Some(first) = first_non_required_span { + if let Some(first) = first_non_required_span + && field.optionality.is_required() + { errors.err_span( first, - "Only the last positional argument may be `Option`, `Vec`, or defaulted.", + "Only trailing positional arguments may be `Option`, `Vec`, or defaulted.", + ); + errors.err( + &field.field, + "Later non-optional positional argument declared here.", ); - errors.err(&field.field, "Later positional argument declared here."); return; } if !field.optionality.is_required() { diff --git a/native/src/boot/cli.rs b/native/src/boot/cli.rs index 271dba925..81acfc5c5 100644 --- a/native/src/boot/cli.rs +++ b/native/src/boot/cli.rs @@ -58,8 +58,8 @@ struct Repack { no_compress: bool, #[argh(positional)] img: Utf8CString, - #[argh(positional, default = r#"Utf8CString::from("new-boot.img")"#)] - out: Utf8CString, + #[argh(positional)] + out: Option, } #[derive(FromArgs)] @@ -77,33 +77,24 @@ struct Sign { #[argh(positional)] img: Utf8CString, #[argh(positional)] - args: Vec, + name: Option, + #[argh(positional)] + cert: Option, + #[argh(positional)] + key: Option, } +#[derive(FromArgs)] +#[argh(subcommand, name = "extract")] struct Extract { + #[argh(positional)] payload: Utf8CString, + #[argh(positional)] partition: Option, + #[argh(positional)] outfile: Option, } -impl FromArgs for Extract { - fn from_args(_command_name: &[&str], args: &[&str]) -> Result { - let mut parse = PositionalArgParser(args.iter()); - Ok(Extract { - payload: parse.required("payload.bin")?, - partition: parse.optional(), - outfile: parse.last_optional()?, - }) - } -} - -impl SubCommand for Extract { - const COMMAND: &'static CommandInfo = &CommandInfo { - name: "extract", - description: "", - }; -} - #[derive(FromArgs)] #[argh(subcommand, name = "hexpatch")] struct HexPatch { @@ -186,28 +177,15 @@ impl SubCommand for Compress { }; } +#[derive(FromArgs)] +#[argh(subcommand, name = "decompress")] struct Decompress { + #[argh(positional)] file: Utf8CString, + #[argh(positional)] out: Option, } -impl FromArgs for Decompress { - fn from_args(_command_name: &[&str], args: &[&str]) -> Result { - let mut iter = PositionalArgParser(args.iter()); - Ok(Decompress { - file: iter.required("infile")?, - out: iter.last_optional()?, - }) - } -} - -impl SubCommand for Decompress { - const COMMAND: &'static CommandInfo = &CommandInfo { - name: "decompress", - description: "", - }; -} - fn print_usage(cmd: &str) { eprintln!( r#"MagiskBoot - Boot Image Modification Tool @@ -386,21 +364,24 @@ fn boot_main(cmds: CmdArgs) -> LoggedResult { img, out, }) => { - repack(&img, &out, no_compress); + repack( + &img, + out.as_deref().unwrap_or(cstr!("new-boot.img")), + no_compress, + ); } Action::Verify(Verify { img, cert }) => { if !verify_cmd(&img, cert.as_deref()) { return log_err!(); } } - Action::Sign(Sign { img, args }) => { - let mut iter = args.iter(); - sign_cmd( - &img, - iter.next().map(AsRef::as_ref), - iter.next().map(AsRef::as_ref), - iter.next().map(AsRef::as_ref), - )?; + Action::Sign(Sign { + img, + name, + cert, + key, + }) => { + sign_cmd(&img, name.as_deref(), cert.as_deref(), key.as_deref())?; } Action::Extract(Extract { payload,