1use crate::formats::parse_custom_format;
2use crate::transformers::custom_format_to_resource;
3use indicatif::{ProgressBar, ProgressStyle};
4use langcodec::Codec;
5
6#[derive(Debug, Clone, PartialEq, clap::ValueEnum)]
8pub enum ConflictStrategy {
9 First,
11 Last,
13 Skip,
15}
16
17pub fn run_merge_command(
19 inputs: Vec<String>,
20 output: String,
21 strategy: ConflictStrategy,
22 lang: Option<String>,
23) {
24 if inputs.is_empty() {
25 eprintln!("Error: At least one input file is required.");
26 std::process::exit(1);
27 }
28
29 let progress_bar = ProgressBar::new_spinner();
31 progress_bar.set_style(
32 ProgressStyle::default_spinner()
33 .template("{spinner:.green} {wide_msg}")
34 .unwrap(),
35 );
36
37 let mut codec = Codec::new();
39 for (i, input) in inputs.iter().enumerate() {
40 progress_bar.set_message(format!(
41 "Reading file {}/{}: {}",
42 i + 1,
43 inputs.len(),
44 input
45 ));
46
47 if let Ok(()) = codec.read_file_by_extension(input, lang.clone()) {
49 continue;
50 }
51
52 if input.ends_with(".json") || input.ends_with(".yaml") || input.ends_with(".yml") {
54 if let Ok(()) = try_custom_format_merge(input, lang.clone(), &mut codec) {
55 continue;
56 }
57 }
58
59 progress_bar.finish_with_message("❌ Error reading input file");
61 eprintln!("Error reading {}: unsupported format", input);
62 std::process::exit(1);
63 }
64
65 progress_bar.set_message("Merging resources...");
69 let conflict_strategy = match strategy {
70 ConflictStrategy::First => langcodec::types::ConflictStrategy::First,
71 ConflictStrategy::Last => langcodec::types::ConflictStrategy::Last,
72 ConflictStrategy::Skip => langcodec::types::ConflictStrategy::Skip,
73 };
74
75 let merged_resource = match Codec::merge_resources(&codec.resources, conflict_strategy) {
76 Ok(resource) => resource,
77 Err(e) => {
78 progress_bar.finish_with_message("❌ Error merging resources");
79 eprintln!("Error: {}", e);
80 std::process::exit(1);
81 }
82 };
83
84 progress_bar.set_message("Writing merged output...");
86 if let Err(e) = Codec::write_resource_to_file(&merged_resource, &output) {
87 progress_bar.finish_with_message("❌ Error writing output file");
88 eprintln!("Error writing to {}: {}", output, e);
89 std::process::exit(1);
90 }
91
92 progress_bar.finish_with_message(format!(
93 "✅ Successfully merged {} files into {}",
94 inputs.len(),
95 output
96 ));
97}
98
99fn try_custom_format_merge(
101 input: &str,
102 _lang: Option<String>,
103 codec: &mut Codec,
104) -> Result<(), String> {
105 crate::validation::validate_custom_format_file(input)?;
107
108 let file_content = std::fs::read_to_string(input)
110 .map_err(|e| format!("Error reading file {}: {}", input, e))?;
111
112 crate::formats::validate_custom_format_content(input, &file_content)?;
114
115 let resources =
117 custom_format_to_resource(input.to_string(), parse_custom_format("json-language-map")?)?;
118
119 for resource in resources {
121 codec.add_resource(resource);
122 }
123
124 Ok(())
125}