Files
BlueArchiveToolkit/infrastructure/src/bin/bat/patch_commands.rs
T
2026-08-03 00:43:11 +08:00

200 lines
8.3 KiB
Rust

pub(super) fn run_write_patch_command(options: &CliOptions) -> anyhow::Result<()> {
match options.command {
CliCommand::PatchApply => {
let params = patch_apply_params_from_options(options)?;
let report = apply_patch_file(&params)?;
print_report(options.output_format, &report)
}
CliCommand::UnityFsPatchTextAsset => {
let params = unityfs_text_asset_params_from_options(options)?;
let report = apply_unityfs_text_asset_patch_file(&params)?;
print_report(options.output_format, &report)
}
CliCommand::UnityFsPatchStringField => {
let params = unityfs_string_field_params_from_options(options)?;
let report = apply_unityfs_string_field_patch_file(&params)?;
print_report(options.output_format, &report)
}
CliCommand::UnityFsPatchField => {
let params = unityfs_field_params_from_options(options)?;
let report = apply_unityfs_field_patch_file(&params)?;
print_report(options.output_format, &report)
}
_ => Err(anyhow::anyhow!("不是写入 patch 命令")),
}
}
pub(super) fn is_write_patch_command(command: CliCommand) -> bool {
matches!(
command,
CliCommand::PatchApply
| CliCommand::UnityFsPatchTextAsset
| CliCommand::UnityFsPatchStringField
| CliCommand::UnityFsPatchField
)
}
pub(super) fn validate_write_patch_options(options: &CliOptions) -> anyhow::Result<()> {
match options.command {
CliCommand::PatchApply => {
let _ = patch_apply_params_from_options(options)?;
reject_unityfs_write_options(options, "patch-apply")?;
}
CliCommand::UnityFsPatchTextAsset => {
let _ = unityfs_text_asset_params_from_options(options)?;
reject_patch_apply_options(options, "unityfs-patch-text-asset")?;
if options.unityfs_field_path.is_some()
|| options.unityfs_replacement_text.is_some()
|| options.unityfs_expected_value.is_some()
{
return Err(anyhow::anyhow!(
"unityfs-patch-text-asset 不接受 --field-path、--string-field-path、--replacement-text 或 --expected-value"
));
}
}
CliCommand::UnityFsPatchStringField => {
let _ = unityfs_string_field_params_from_options(options)?;
reject_patch_apply_options(options, "unityfs-patch-string-field")?;
if options.unityfs_expected_name.is_some() {
return Err(anyhow::anyhow!(
"unityfs-patch-string-field 不接受 --expected-name"
));
}
}
CliCommand::UnityFsPatchField => {
let _ = unityfs_field_params_from_options(options)?;
reject_patch_apply_options(options, "unityfs-patch-field")?;
if options.unityfs_expected_name.is_some()
|| options.unityfs_replacement_text.is_some()
|| options.unityfs_expected_value.is_some()
{
return Err(anyhow::anyhow!(
"unityfs-patch-field 不接受 --expected-name、--replacement-text 或 --expected-value;请使用 --replacement-json / --expected-json"
));
}
}
_ => {}
}
Ok(())
}
fn patch_apply_params_from_options(options: &CliOptions) -> anyhow::Result<PatchApplyParams> {
Ok(PatchApplyParams {
kind: require_cli_option(options.patch_kind, "--patch-kind")?,
source_path: require_cli_option(options.patch_source_path.clone(), "--source-file")?,
patch_path: require_cli_option(options.patch_patch_path.clone(), "--patch-file")?,
target_path: require_cli_option(options.patch_target_path.clone(), "--target-file")?,
})
}
fn unityfs_text_asset_params_from_options(
options: &CliOptions,
) -> anyhow::Result<UnityFsTextAssetPatchParams> {
Ok(UnityFsTextAssetPatchParams {
bundle_path: require_cli_option(options.unityfs_bundle_path.clone(), "--bundle-file")?,
serialized_file_path: require_cli_option(
options.unityfs_serialized_file_path.clone(),
"--serialized-file",
)?,
path_id: require_cli_option(options.unityfs_path_id, "--object-path-id")?,
replacement_path: require_cli_option(
options.unityfs_replacement_path.clone(),
"--replacement-file",
)?,
target_path: require_cli_option(options.patch_target_path.clone(), "--target-file")?,
expected_name: options.unityfs_expected_name.clone(),
})
}
fn unityfs_string_field_params_from_options(
options: &CliOptions,
) -> anyhow::Result<UnityFsStringFieldPatchParams> {
let has_replacement_text = options.unityfs_replacement_text.is_some();
let has_replacement_path = options.unityfs_replacement_path.is_some();
if has_replacement_text == has_replacement_path {
return Err(anyhow::anyhow!(
"unityfs-patch-string-field 必须且只能指定 --replacement-text 或 --replacement-file 其中一个"
));
}
Ok(UnityFsStringFieldPatchParams {
bundle_path: require_cli_option(options.unityfs_bundle_path.clone(), "--bundle-file")?,
serialized_file_path: require_cli_option(
options.unityfs_serialized_file_path.clone(),
"--serialized-file",
)?,
path_id: require_cli_option(options.unityfs_path_id, "--object-path-id")?,
field_path: require_cli_option(
options.unityfs_field_path.clone(),
"--field-path/--string-field-path",
)?,
replacement_text: options.unityfs_replacement_text.clone(),
replacement_path: options.unityfs_replacement_path.clone(),
target_path: require_cli_option(options.patch_target_path.clone(), "--target-file")?,
expected_value: options.unityfs_expected_value.clone(),
})
}
fn unityfs_field_params_from_options(
options: &CliOptions,
) -> anyhow::Result<UnityFsFieldPatchParams> {
if options.unityfs_replacement_path.is_some() {
return Err(anyhow::anyhow!(
"unityfs-patch-field 不接受 --replacement-file;请使用 --replacement-json"
));
}
Ok(UnityFsFieldPatchParams {
bundle_path: require_cli_option(options.unityfs_bundle_path.clone(), "--bundle-file")?,
serialized_file_path: require_cli_option(
options.unityfs_serialized_file_path.clone(),
"--serialized-file",
)?,
path_id: require_cli_option(options.unityfs_path_id, "--object-path-id")?,
field_path: require_cli_option(
options.unityfs_field_path.clone(),
"--field-path/--string-field-path",
)?,
replacement: require_cli_option(
options.unityfs_replacement_value.clone(),
"--replacement-json",
)?,
target_path: require_cli_option(options.patch_target_path.clone(), "--target-file")?,
expected_value: options.unityfs_expected_semantic_value.clone(),
})
}
fn require_cli_option<T>(value: Option<T>, name: &str) -> anyhow::Result<T> {
value.ok_or_else(|| anyhow::anyhow!("缺少必要参数 {name}"))
}
fn reject_patch_apply_options(options: &CliOptions, command: &str) -> anyhow::Result<()> {
if options.patch_kind.is_some()
|| options.patch_source_path.is_some()
|| options.patch_patch_path.is_some()
{
return Err(anyhow::anyhow!(
"{command} 不接受 --patch-kind、--source-file 或 --patch-file"
));
}
Ok(())
}
fn reject_unityfs_write_options(options: &CliOptions, command: &str) -> anyhow::Result<()> {
if options.unityfs_bundle_path.is_some()
|| options.unityfs_serialized_file_path.is_some()
|| options.unityfs_path_id.is_some()
|| options.unityfs_field_path.is_some()
|| options.unityfs_replacement_path.is_some()
|| options.unityfs_replacement_text.is_some()
|| options.unityfs_expected_name.is_some()
|| options.unityfs_expected_value.is_some()
|| options.unityfs_replacement_value.is_some()
|| options.unityfs_expected_semantic_value.is_some()
{
return Err(anyhow::anyhow!(
"{command} 不接受 UnityFS 写入参数;请改用 unityfs-patch-* 命令"
));
}
Ok(())
}
use super::*;