dtmt: Add option to compile file when injecting
This commit is contained in:
parent
ea7886b08f
commit
126d3c743d
1 changed files with 64 additions and 50 deletions
|
@ -3,19 +3,28 @@ use std::path::PathBuf;
|
||||||
use clap::{value_parser, Arg, ArgMatches, Command};
|
use clap::{value_parser, Arg, ArgMatches, Command};
|
||||||
use color_eyre::eyre::{self, Context, Result};
|
use color_eyre::eyre::{self, Context, Result};
|
||||||
use color_eyre::Help;
|
use color_eyre::Help;
|
||||||
|
use sdk::murmur::IdString64;
|
||||||
use sdk::Bundle;
|
use sdk::Bundle;
|
||||||
use tokio::fs::{self, File};
|
use tokio::fs::{self, File};
|
||||||
use tokio::io::AsyncReadExt;
|
use tokio::io::AsyncReadExt;
|
||||||
|
|
||||||
pub(crate) fn command_definition() -> Command {
|
pub(crate) fn command_definition() -> Command {
|
||||||
Command::new("inject")
|
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(
|
||||||
Arg::new("replace")
|
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')
|
.short('r')
|
||||||
.long("replace"),
|
.long("replace"),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new("compile")
|
||||||
|
.help("Compile the file with the given data format before injecting.")
|
||||||
|
.long("compile")
|
||||||
|
.short('c')
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new("output")
|
Arg::new("output")
|
||||||
.help(
|
.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")?
|
Bundle::from_binary(&ctx, name, binary).wrap_err("Failed to open bundle file")?
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(name) = matches.get_one::<String>("replace") {
|
let name = match matches.get_one::<String>("replace") {
|
||||||
let mut file = File::open(&file_path)
|
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
|
.await
|
||||||
.wrap_err_with(|| format!("Failed to open '{}'", file_path.display()))?;
|
.wrap_err("Failed to read input file")?;
|
||||||
|
variant.set_data(data);
|
||||||
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::<PathBuf>("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(())
|
|
||||||
} else {
|
} 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::<PathBuf>("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(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue