diff --git a/crates/dtmt/src/cmd/bundle/inject.rs b/crates/dtmt/src/cmd/bundle/inject.rs index 2b86691..4e5cbac 100644 --- a/crates/dtmt/src/cmd/bundle/inject.rs +++ b/crates/dtmt/src/cmd/bundle/inject.rs @@ -3,19 +3,28 @@ use std::path::PathBuf; use clap::{value_parser, Arg, ArgMatches, Command}; use color_eyre::eyre::{self, Context, Result}; use color_eyre::Help; +use sdk::murmur::IdString64; use sdk::Bundle; use tokio::fs::{self, File}; use tokio::io::AsyncReadExt; pub(crate) fn command_definition() -> Command { Command::new("inject") - .about("Inject a file into a bundle.") + .about("Inject a file into a bundle.\n\ + Raw binary data can be used to directly replace the file's variant data blob without affecting the metadata.\n\ + Alternatively, a compiler format may be specified, and a complete bundle file is created.") .arg( Arg::new("replace") - .help("The name of a file in the bundle whos content should be replaced.") + .help("The name of a file in the bundle whose content should be replaced.") .short('r') .long("replace"), ) + .arg( + Arg::new("compile") + .help("Compile the file with the given data format before injecting.") + .long("compile") + .short('c') + ) .arg( Arg::new("output") .help( @@ -58,55 +67,60 @@ pub(crate) async fn run(ctx: sdk::Context, matches: &ArgMatches) -> Result<()> { Bundle::from_binary(&ctx, name, binary).wrap_err("Failed to open bundle file")? }; - if let Some(name) = matches.get_one::("replace") { - let mut file = File::open(&file_path) + let name = match matches.get_one::("replace") { + Some(name) => match u64::from_str_radix(name, 16) { + Ok(id) => IdString64::from(id), + Err(_) => IdString64::String(name.clone()), + }, + None => eyre::bail!("Currently, only the '--replace' operation is supported."), + }; + + let mut file = File::open(&file_path) + .await + .wrap_err_with(|| format!("Failed to open '{}'", file_path.display()))?; + + if let Some(variant) = bundle + .files_mut() + .filter(|file| file.matches_name(name.clone())) + // TODO: Handle file variants + .find_map(|file| file.variants_mut().next()) + { + let mut data = Vec::new(); + file.read_to_end(&mut data) .await - .wrap_err_with(|| format!("Failed to open '{}'", file_path.display()))?; - - if let Some(variant) = bundle - .files_mut() - .filter(|file| file.matches_name(name.clone())) - // TODO: Handle file variants - .find_map(|file| file.variants_mut().next()) - { - let mut data = Vec::new(); - file.read_to_end(&mut data) - .await - .wrap_err("Failed to read input file")?; - variant.set_data(data); - } else { - let err = eyre::eyre!("No file '{}' in this bundle.", name) - .with_suggestion(|| { - format!( - "Run '{} bundle list {}' to list the files in this bundle.", - clap::crate_name!(), - bundle_path.display() - ) - }) - .with_suggestion(|| { - format!( - "Use '{} bundle inject --add {} {} {}' to add it as a new file", - clap::crate_name!(), - name, - bundle_path.display(), - file_path.display() - ) - }); - - return Err(err); - } - - let out_path = matches.get_one::("output").unwrap_or(bundle_path); - let data = bundle - .to_binary() - .wrap_err("Failed to write changed bundle to output")?; - - fs::write(out_path, &data) - .await - .wrap_err("Failed to write data to output file")?; - - Ok(()) + .wrap_err("Failed to read input file")?; + variant.set_data(data); } else { - eyre::bail!("Currently, only the '--replace' operation is supported."); + let err = + eyre::eyre!("No file '{}' in this bundle.", name.display()).with_suggestion(|| { + format!( + "Run '{} bundle list {}' to list the files in this bundle.", + clap::crate_name!(), + bundle_path.display() + ) + // Not yet supported. + // }) + // .with_suggestion(|| { + // format!( + // "Use '{} bundle inject --add {} {} {}' to add it as a new file", + // clap::crate_name!(), + // name.display(), + // bundle_path.display(), + // file_path.display() + // ) + }); + + return Err(err); } + + let out_path = matches.get_one::("output").unwrap_or(bundle_path); + let data = bundle + .to_binary() + .wrap_err("Failed to write changed bundle to output")?; + + fs::write(out_path, &data) + .await + .wrap_err("Failed to write data to output file")?; + + Ok(()) }