diff --git a/src/envs/error_handler.rs b/src/envs/error_handler.rs index 2d383ec..e677e25 100644 --- a/src/envs/error_handler.rs +++ b/src/envs/error_handler.rs @@ -4,11 +4,15 @@ use crate::util::message; pub const WRN_GENERAL: i32 = 0x00; pub const ERR_GENERAL: i32 = 0x01; -pub const ERR_FILE_NOT_FOUND: i32 = 0x02; -pub const ERR_MODULE_NOT_IMPLEMENTED: i32 = 0x03; -pub const ERR_ARGPARSE: i32 = 0x04; -pub const ERR_BINARY_NOT_FOUND: i32 = 0x05; -pub const ERR_OUTPUT_EXISTS: i32 = 0x06; +pub const ERR_FILE_NOT_FOUND: i32 = 0x10; +pub const ERR_FILE_INVALID: i32 = 0x11; +pub const ERR_BINARY_NOT_FOUND: i32 = 0x20; +pub const ERR_BINARY_NOT_EXECUTABLE: i32 = 0x21; +pub const ERR_BINARY_INVALID: i32 = 0x22; +pub const ERR_MODULE_NOT_IMPLEMENTED: i32 = 0x30; +pub const ERR_ARGPARSE: i32 = 0x40; +pub const ERR_OUTPUT_EXISTS: i32 = 0x50; + fn build_message(code: i32, passed_object: Option) -> String { let object = passed_object.unwrap_or_else(|| "".to_string()); @@ -16,10 +20,14 @@ fn build_message(code: i32, passed_object: Option) -> String { WRN_GENERAL => format!("Warning: {}", object), ERR_GENERAL => format!("Error: {}", object), ERR_FILE_NOT_FOUND => format!("File not found: {}", object), + ERR_FILE_INVALID => format!("Invalid file given: {}", object), + ERR_BINARY_NOT_FOUND => format!("Binary not found: {}", object), + ERR_BINARY_NOT_EXECUTABLE => format!("Binary not executable: {}", object), + ERR_BINARY_INVALID => format!("Invalid binary given: {}", object), ERR_MODULE_NOT_IMPLEMENTED => format!("Module not implemented: {}", object), ERR_ARGPARSE => format!("Argument parsing error: {}", object), - ERR_BINARY_NOT_FOUND => format!("Binary not found: {}", object), ERR_OUTPUT_EXISTS => format!("Output file already exists: {}; use -o to overwrite", object), + _ => "Unknown error".to_string(), } } diff --git a/src/envs/variables.rs b/src/envs/variables.rs index 4f04f6c..45809cc 100644 --- a/src/envs/variables.rs +++ b/src/envs/variables.rs @@ -131,6 +131,7 @@ impl BinaryPaths { let mut split = line.split('='); let name = split.next().unwrap_or(""); let path = split.next().unwrap_or(""); + if path.len() == 0 { continue; } if let Some(&i) = self.map.get(name) { self.bin[i].path = path.to_string(); self.bin[i].set = true; diff --git a/src/modules/config.rs b/src/modules/config.rs index 6f06a8c..4467cf9 100644 --- a/src/modules/config.rs +++ b/src/modules/config.rs @@ -1,11 +1,14 @@ +use std::os::unix::fs::MetadataExt; +use std::io::Write; use crate::envs::error_handler as err; use crate::envs::variables as var; +use crate::envs::variables::BinaryPaths; use crate::util::command as cmd; use crate::util::message as msg; use crate::util::arg_parser::Args; use color_print::cstr; -fn task_check(bin: &crate::envs::variables::BinaryPaths) -> Result<(), Box> { +fn task_check(bin: &BinaryPaths) -> Result<(), Box> { msg::println_message(&format!("{}", cstr!(r#"System:"#)), 3); msg::println_message(&format!("Unicore version: {}", var::VERSION), 3); msg::println_message(&format!("OS: {}", std::env::consts::OS), 3); @@ -48,7 +51,7 @@ fn binary_run_test(path: &str, sw: &str) -> bool { let mut test_command = std::process::Command::new(path); let test_command = match sw { "mmseqs" | "foldseek" | "foldmason" => test_command.arg("version"), - "mafft" | "iqtree" => test_command.arg("--version"), + "mafft" | "mafft-linsi" | "iqtree" => test_command.arg("--version"), "fasttree" => &mut test_command, "raxml" => test_command.arg("-v"), _ => return false, @@ -56,32 +59,35 @@ fn binary_run_test(path: &str, sw: &str) -> bool { cmd::run_code(test_command) == 0 } -fn binary_status(bin: &crate::envs::variables::BinaryPaths, sw: &str) -> u8 { - if let Some(&ref bin) = &bin.get(sw) { - if !std::path::Path::new(&bin.path).exists() { return 1; } // Binary path does not exist - } else { return 2; } // Binary path is not set +fn set_binary(bin: &BinaryPaths, path: &str, sw: &str) -> Result<(), Box> { + if !std::fs::File::open(path).is_ok() { err::error(err::ERR_BINARY_NOT_FOUND, Some(format!("{}", path))); } + if std::fs::metadata(path)?.is_dir() { err::error(err::ERR_FILE_INVALID, Some(format!("{}", path))); } + if std::fs::metadata(path)?.mode() & 0o111 == 0 { err::error(err::ERR_BINARY_NOT_EXECUTABLE, Some(format!("{}", path))); } + if !binary_run_test(path, sw) { err::error(err::ERR_BINARY_INVALID, Some(format!("{}", path))); } - 0 + let path = std::fs::canonicalize(path)?.to_str().unwrap().to_string(); + msg::println_message(&format!("Setting dependency {} to {}...", sw, path), 3); + let mut cfg = std::fs::File::create(var::locate_path_cfg())?; + for &prog in var::VALID_BINARY.iter() { + if prog == sw { cfg.write_all(format!("{}={}\n", prog, path).as_bytes())?; } + else if bin.get(prog).is_none() || !bin.get(prog).unwrap().set { cfg.write_all(format!("#{}=\n", prog).as_bytes())?; } + else { cfg.write_all(format!("{}={}\n", prog, bin.get(prog).unwrap().path).as_bytes())?; } + } + msg::println_message(&"Done. Please run \"unicore config -c\" to check".to_string(), 3); + + Ok(()) } -const TASK_SET_MMSEQS: u8 = 0x02; -const TASK_SET_FOLDSEEK: u8 = 0x03; -const TASK_SET_FOLDMASON: u8 = 0x04; -const TASK_SET_MAFFT: u8 = 0x05; -const TASK_SET_MAFFT_LINSI: u8 = 0x06; -const TASK_SET_IQTREE: u8 = 0x07; -const TASK_SET_FASTTREE: u8 = 0x08; -const TASK_SET_RAXML: u8 = 0x09; -pub fn run(args: &Args, bin: &crate::envs::variables::BinaryPaths) -> Result<(), Box> { +pub fn run(args: &Args, bin: &BinaryPaths) -> Result<(), Box> { if args.config_check.is_some() && args.config_check.unwrap() { task_check(bin)?; } - else if args.config_set_mmseqs.is_some() { TASK_SET_MMSEQS; } - else if args.config_set_foldseek.is_some() { TASK_SET_FOLDSEEK; } - else if args.config_set_foldmason.is_some() { TASK_SET_FOLDMASON; } - else if args.config_set_mafft.is_some() { TASK_SET_MAFFT; } - else if args.config_set_mafft_linsi.is_some() { TASK_SET_MAFFT_LINSI; } - else if args.config_set_iqtree.is_some() { TASK_SET_IQTREE; } - else if args.config_set_fasttree.is_some() { TASK_SET_FASTTREE; } - else if args.config_set_raxml.is_some() { TASK_SET_RAXML; } + else if args.config_set_mmseqs.is_some() { set_binary(bin, args.config_set_mmseqs.clone().unwrap().as_str(), "mmseqs")?; } + else if args.config_set_foldseek.is_some() { set_binary(bin, args.config_set_foldseek.clone().unwrap().as_str(), "foldseek")?; } + else if args.config_set_foldmason.is_some() { set_binary(bin, args.config_set_foldmason.clone().unwrap().as_str(), "foldmason")?; } + else if args.config_set_mafft.is_some() { set_binary(bin, args.config_set_mafft.clone().unwrap().as_str(), "mafft")?; } + else if args.config_set_mafft_linsi.is_some() { set_binary(bin, args.config_set_mafft_linsi.clone().unwrap().as_str(), "mafft-linsi")?; } + else if args.config_set_iqtree.is_some() { set_binary(bin, args.config_set_iqtree.clone().unwrap().as_str(), "iqtree")?; } + else if args.config_set_fasttree.is_some() { set_binary(bin, args.config_set_fasttree.clone().unwrap().as_str(), "fasttree")?; } + else if args.config_set_raxml.is_some() { set_binary(bin, args.config_set_raxml.clone().unwrap().as_str(), "raxml")?; } else { err::error(err::ERR_ARGPARSE, Some("No task specified".to_string())) }; Ok(()) } \ No newline at end of file