diff --git a/src/commands.rs b/src/commands.rs index 1ac1168..835676f 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -23,7 +23,7 @@ use crate::file_io::{FileError, FileReader, InputFile}; use crate::model::onkostar_editor::OnkostarEditor; use crate::profile::Profile; use clap::CommandFactory; -use clap_complete::generate; +use clap_complete::{generate, Shell}; use console::style; use dialoguer::Confirm; use quick_xml::se::Serializer; @@ -36,6 +36,60 @@ use std::io::Write; use std::ops::Add; use std::path::{Path, PathBuf}; +pub fn handle(command: SubCommand) -> Result<(), Box> { + match command { + SubCommand::Completion { shell } => handle_completion(shell), + SubCommand::List { + inputfile, + sorted, + filter, + } => handle_list(inputfile, sorted, filter)?, + SubCommand::Tree { + inputfile, + sorted, + filter, + } => handle_tree(inputfile, sorted, filter)?, + SubCommand::Modify { + inputfile, + profile, + outputfile, + compact, + sorted, + strip, + interactive, + fix, + } => handle_modify( + inputfile, + profile, + outputfile, + compact, + sorted, + strip, + interactive, + fix, + )?, + SubCommand::Diff { + inputfile_a, + inputfile_b, + strict, + } => handle_diff(&inputfile_a, &inputfile_b, strict)?, + SubCommand::Sha256Sum { inputfile } => handle_sha256sum(inputfile), + SubCommand::Check { + file, + list, + password, + } => handle_check(file, list, password), + #[cfg(feature = "unzip-osb")] + SubCommand::UnzipOsb { + file, + password, + dir, + } => handle_unzip_osb(&file, password, dir), + } + + Ok(()) +} + fn write_outputfile(filename: String, content: &String) -> Result<(), FileError> { OpenOptions::new() .read(false) @@ -49,278 +103,279 @@ fn write_outputfile(filename: String, content: &String) -> Result<(), FileError> Ok(()) } -pub fn handle(command: SubCommand) -> Result<(), Box> { - match command { - SubCommand::Completion { shell } => { - let command = &mut Cli::command(); - generate( - shell, - command, - command.get_name().to_string(), - &mut std::io::stdout(), - ); - } - SubCommand::List { - inputfile, - sorted, - filter, - } => match InputFile::read(inputfile, None)? { - osc @ InputFile::Osc { .. } => { - let mut content: OnkostarEditor = osc.try_into()?; - if sorted { - content.sorted(); - } - if let Some(name) = filter { - OnkostarEditor::print_list_filtered(&mut content, name.as_str()); - return Ok(()); - } - content.print_list(); +fn handle_completion(shell: Shell) { + let command = &mut Cli::command(); + generate( + shell, + command, + command.get_name().to_string(), + &mut std::io::stdout(), + ); +} + +fn handle_list( + inputfile: String, + sorted: bool, + filter: Option, +) -> Result<(), Box> { + match InputFile::read(inputfile, None)? { + osc @ InputFile::Osc { .. } => { + let mut content: OnkostarEditor = osc.try_into()?; + if sorted { + content.sorted(); } - InputFile::Osb { content, .. } => { - for file in content { - match file { - InputFile::Osc { .. } => { - println!( - "{}{}", - style("OSB-Paketinhalt: ").bold().yellow(), - style(file.filename()).bold() - ); + if let Some(name) = filter { + OnkostarEditor::print_list_filtered(&mut content, name.as_str()); + return Ok(()); + } + content.print_list(); + } + InputFile::Osb { content, .. } => { + for file in content { + match file { + InputFile::Osc { .. } => { + println!( + "{}{}", + style("OSB-Paketinhalt: ").bold().yellow(), + style(file.filename()).bold() + ); - let mut content: OnkostarEditor = match file.try_into() { - Ok(oe) => oe, - Err(err) => { - println!("{err}"); - continue; - } - }; + let mut content: OnkostarEditor = match file.try_into() { + Ok(oe) => oe, + Err(err) => { + println!("{err}"); + continue; + } + }; - if sorted { - content.sorted(); - } - if let Some(name) = filter { - OnkostarEditor::print_list_filtered(&mut content, name.as_str()); - return Ok(()); - } - content.print_list(); - println!(); + if sorted { + content.sorted(); } - _ => { - println!( - "{}{}{}", - style("OSB-Paketinhalt: ").bold().yellow(), - style(file.filename()).bold(), - style(" ignoriert").yellow() - ); + if let Some(name) = filter { + OnkostarEditor::print_list_filtered(&mut content, name.as_str()); + return Ok(()); } + content.print_list(); + println!(); + } + _ => { + println!( + "{}{}{}", + style("OSB-Paketinhalt: ").bold().yellow(), + style(file.filename()).bold(), + style(" ignoriert").yellow() + ); } } } - InputFile::Yaml { filename, .. } | InputFile::Other { filename, .. } => { - return Err(Box::new(FileError::Reading( - filename, - "Nur OSB- und OSC-Dateien werden unterstützt".to_string(), - ))) + } + InputFile::Yaml { filename, .. } | InputFile::Other { filename, .. } => { + return Err(Box::new(FileError::Reading( + filename, + "Nur OSB- und OSC-Dateien werden unterstützt".to_string(), + ))) + } + } + Ok(()) +} + +fn handle_tree( + inputfile: String, + sorted: bool, + filter: Option, +) -> Result<(), Box> { + match InputFile::read(inputfile, None)? { + osc @ InputFile::Osc { .. } => { + let mut content: OnkostarEditor = osc.try_into()?; + if sorted { + content.sorted(); } - }, - SubCommand::Tree { - inputfile, - sorted, - filter, - } => match InputFile::read(inputfile, None)? { - osc @ InputFile::Osc { .. } => { - let mut content: OnkostarEditor = osc.try_into()?; - if sorted { - content.sorted(); - } - if let Some(name) = filter { - OnkostarEditor::print_tree_filtered(&mut content, name.as_str()); - return Ok(()); - } - OnkostarEditor::print_tree(&content); + if let Some(name) = filter { + OnkostarEditor::print_tree_filtered(&mut content, name.as_str()); + return Ok(()); } - InputFile::Osb { filename, .. } => return Err(Box::new(FileError::Reading( + OnkostarEditor::print_tree(&content); + } + InputFile::Osb { filename, .. } => { + return Err(Box::new(FileError::Reading( filename, "Nur OSC-Dateien werden unterstützt. OSB-Dateien erzeugen eine zu lange Ausgabe." .to_string(), - ))), - InputFile::Yaml { filename, .. } | InputFile::Other { filename, .. } => { - return Err(Box::new(FileError::Reading( - filename, - "Nur OSC-Dateien werden unterstützt".to_string(), - ))) - } - }, - SubCommand::Modify { - inputfile, - profile, - outputfile, - compact, - sorted, - strip, - interactive, - fix, - } => { - let mut data: OnkostarEditor = InputFile::read(inputfile, None)?.try_into()?; - - if let Some(profile) = profile { - let profile = if profile.contains('.') { - FileReader::::read(&profile)? - } else { - Profile::embedded_profile(&profile)? - }; - - data.apply_profile(&profile); - } - - let mut compact = compact; - let mut sorted = sorted; - let mut strip = strip; - - if interactive { - compact = matches!( - Confirm::new() - .with_prompt("Kompakte Ausgabe, ohne Einrücken?") - .default(compact) - .interact(), - Ok(true) - ); - - sorted = matches!( - Confirm::new() - .with_prompt( - "Sortiere Kataloge und Formulare nach Name und Abhängigkeiten?" - ) - .default(sorted) - .interact(), - Ok(true) - ); - - strip = matches!( - Confirm::new() - .with_prompt( - "Entferne Einträge aus der Systembibliothek die nicht importiert werden?", - ) - .default(strip) - .interact(), - Ok(true) - ); - } - - if fix { - // No operation as of now - } - - if sorted { - data.sorted(); - } - - if strip { - data.strip_system_library_content(); - } - - let mut buf = String::new(); - - let mut serializer = Serializer::new(&mut buf); - if !compact { - serializer.indent(' ', 2); - } - - data.serialize(serializer).map_err(|_| { - FileError::Writing("Cannot serialize result".to_string(), String::new()) - })?; - - let output = &"\n" - .to_string() - .add( - buf - // Replace ' and " as used in original file - .replace("'", "'") - .replace(""", "\"") - .as_str(), - ); - - match outputfile { - Some(filename) => write_outputfile(filename, output)?, - None => { - println!("{output}"); - } - } + ))) } - SubCommand::Diff { - inputfile_a, - inputfile_b, - strict, - } => { - println!( - "Vergleiche Datei A ({}) mit Datei B ({})", - style(&inputfile_a).yellow(), - style(&inputfile_b).yellow() - ); - - let data_a = &mut FileReader::::read(&inputfile_a)?; - let data_b = &mut FileReader::::read(&inputfile_b)?; - - data_a.print_diff(data_b, strict); - } - SubCommand::Sha256Sum { inputfile } => match fs::read(inputfile.clone()) { - Ok(content) => { - let mut hasher = Sha256::new(); - hasher.update(content.as_slice()); - let hash = hasher.finalize(); - println!( - "{} {}", - base16ct::lower::encode_string(&hash), - PathBuf::from(inputfile.clone()) - .canonicalize() - .unwrap_or_default() - .to_str() - .unwrap_or_default() - ); - } - Err(err) => { - eprintln!("{}", FileError::Reading(inputfile, err.to_string())); - } - }, - SubCommand::Check { - file, - list, - password, - } => { - if list { - print(); - } else { - match check_file(Path::new(file.unwrap_or_default().as_str()), password) { - Ok(notices) => { - println!( - "Es wurden {} Probleme gefunden\n", - notices - .iter() - .filter(|notice| matches!( - notice, - CheckNotice::ErrorWithCode { .. } | CheckNotice::Error { .. } - )) - .count() - ); - for notice in notices { - println!("{notice}"); - } - } - Err(err) => { - println!("{err}"); - } - } - } - } - #[cfg(feature = "unzip-osb")] - SubCommand::UnzipOsb { - file, - password, - dir, - } => { - use crate::unzip_osb::unzip_osb; - unzip_osb(file.as_str(), dir.unwrap_or_default().as_str(), password) + InputFile::Yaml { filename, .. } | InputFile::Other { filename, .. } => { + return Err(Box::new(FileError::Reading( + filename, + "Nur OSC-Dateien werden unterstützt".to_string(), + ))) } } Ok(()) } + +fn handle_modify( + inputfile: String, + profile: Option, + outputfile: Option, + compact: bool, + sorted: bool, + strip: bool, + interactive: bool, + fix: bool, +) -> Result<(), Box> { + let mut data: OnkostarEditor = InputFile::read(inputfile, None)?.try_into()?; + + if let Some(profile) = profile { + let profile = if profile.contains('.') { + FileReader::::read(&profile)? + } else { + Profile::embedded_profile(&profile)? + }; + + data.apply_profile(&profile); + } + + let mut compact = compact; + let mut sorted = sorted; + let mut strip = strip; + + if interactive { + compact = matches!( + Confirm::new() + .with_prompt("Kompakte Ausgabe, ohne Einrücken?") + .default(compact) + .interact(), + Ok(true) + ); + + sorted = matches!( + Confirm::new() + .with_prompt("Sortiere Kataloge und Formulare nach Name und Abhängigkeiten?") + .default(sorted) + .interact(), + Ok(true) + ); + + strip = matches!( + Confirm::new() + .with_prompt( + "Entferne Einträge aus der Systembibliothek die nicht importiert werden?", + ) + .default(strip) + .interact(), + Ok(true) + ); + } + + if fix { + // No operation as of now + } + + if sorted { + data.sorted(); + } + + if strip { + data.strip_system_library_content(); + } + + let mut buf = String::new(); + + let mut serializer = Serializer::new(&mut buf); + if !compact { + serializer.indent(' ', 2); + } + + data.serialize(serializer) + .map_err(|_| FileError::Writing("Cannot serialize result".to_string(), String::new()))?; + + let output = &"\n" + .to_string() + .add( + buf + // Replace ' and " as used in original file + .replace("'", "'") + .replace(""", "\"") + .as_str(), + ); + + match outputfile { + Some(filename) => write_outputfile(filename, output)?, + None => { + println!("{output}"); + } + }; + + Ok(()) +} + +fn handle_diff(inputfile_a: &str, inputfile_b: &str, strict: bool) -> Result<(), Box> { + println!( + "Vergleiche Datei A ({}) mit Datei B ({})", + style(&inputfile_a).yellow(), + style(&inputfile_b).yellow() + ); + + let data_a = &mut FileReader::::read(inputfile_a)?; + let data_b = &mut FileReader::::read(inputfile_b)?; + + data_a.print_diff(data_b, strict); + + Ok(()) +} + +fn handle_sha256sum(inputfile: String) { + match fs::read(inputfile.clone()) { + Ok(content) => { + let mut hasher = Sha256::new(); + hasher.update(content.as_slice()); + let hash = hasher.finalize(); + println!( + "{} {}", + base16ct::lower::encode_string(&hash), + PathBuf::from(inputfile.clone()) + .canonicalize() + .unwrap_or_default() + .to_str() + .unwrap_or_default() + ); + } + Err(err) => { + eprintln!("{}", FileError::Reading(inputfile, err.to_string())); + } + } +} + +fn handle_check(file: Option, list: bool, password: Option) { + if list { + print(); + } else { + match check_file(Path::new(file.unwrap_or_default().as_str()), password) { + Ok(notices) => { + println!( + "Es wurden {} Probleme gefunden\n", + notices + .iter() + .filter(|notice| matches!( + notice, + CheckNotice::ErrorWithCode { .. } | CheckNotice::Error { .. } + )) + .count() + ); + for notice in notices { + println!("{notice}"); + } + } + Err(err) => { + println!("{err}"); + } + } + } +} + +#[cfg(feature = "unzip-osb")] +fn handle_unzip_osb(file: &str, password: Option, dir: Option) { + use crate::unzip_osb::unzip_osb; + unzip_osb(file, dir.unwrap_or_default().as_str(), password); +}