use super::report_output::print_report; 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(¶ms)?; 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(¶ms)?; 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(¶ms)?; print_report(options.output_format, &report) } CliCommand::UnityFsPatchField => { let params = unityfs_field_params_from_options(options)?; let report = apply_unityfs_field_patch_file(¶ms)?; 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 { 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 { 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 { 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 { 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(value: Option, name: &str) -> anyhow::Result { 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() || options.patch_manifest.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() || options.patch_manifest.is_some() { return Err(anyhow::anyhow!( "{command} 不接受 UnityFS 写入参数;请改用 unityfs-patch-* 命令" )); } Ok(()) } use super::*;