From 1bbafc9865162773ee0a601c087a9f0a516bc5c3 Mon Sep 17 00:00:00 2001 From: Daniel DW Kim Date: Mon, 10 Feb 2025 18:03:13 +0900 Subject: [PATCH] config check route --- src/envs/variables.rs | 7 ++-- src/modules/config.rs | 82 ++++++++++++++++++++++++++++++++++++++++++ src/util/arg_parser.rs | 11 ++---- src/util/command.rs | 20 +++++++++++ 4 files changed, 109 insertions(+), 11 deletions(-) diff --git a/src/envs/variables.rs b/src/envs/variables.rs index 577a668..4f04f6c 100644 --- a/src/envs/variables.rs +++ b/src/envs/variables.rs @@ -85,18 +85,20 @@ pub fn locate_encoder_py() -> String { } // binary paths -const VALID_BINARY: [&str; 7] = [ - "mmseqs", "foldseek", "mafft", "mafft-linsi", "foldmason", "iqtree", "fasttree", +pub const VALID_BINARY: [&str; 8] = [ + "mmseqs", "foldseek", "mafft", "mafft-linsi", "foldmason", "iqtree", "fasttree", "raxml" ]; pub struct Binary { name: String, pub path: String, + pub set: bool, } impl Binary { fn new(name: &str, path: &str) -> Self { Binary { name: name.to_string(), path: path.to_string(), + set: false, } } fn test(&self, args: Vec<&str>) -> bool { @@ -131,6 +133,7 @@ impl BinaryPaths { let path = split.next().unwrap_or(""); if let Some(&i) = self.map.get(name) { self.bin[i].path = path.to_string(); + self.bin[i].set = true; } } Ok(()) diff --git a/src/modules/config.rs b/src/modules/config.rs index 7815fe3..6f06a8c 100644 --- a/src/modules/config.rs +++ b/src/modules/config.rs @@ -1,5 +1,87 @@ +use crate::envs::error_handler as err; +use crate::envs::variables as var; +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> { + 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); + msg::println_message(&format!("Threads: {}", var::threads()), 3); + println!(); + msg::println_message(&format!("{}", cstr!(r#"Dependencies:"#)), 3); + msg::println_message(&format!("MMseqs2: {} .. {}", + if let Some(&ref bin) = &bin.get("mmseqs") { if bin.set { bin.path.clone() } else { "Unset".to_string() } } else { "Undefined".to_string() }, + if let Some(&ref bin) = &bin.get("mmseqs") { if bin.set { if binary_run_test(&bin.path, "mmseqs") { cstr!(r#"ok"#) } else { cstr!(r#"no"#) } } else { cstr!(r#"n/a"#) } } else { cstr!(r#"n/a"#) }, + ), 3); + msg::println_message(&format!("Foldseek: {} .. {}", + if let Some(&ref bin) = &bin.get("foldseek") { if bin.set { bin.path.clone() } else { "Unset".to_string() } } else { "Undefined".to_string() }, + if let Some(&ref bin) = &bin.get("foldseek") { if bin.set { if binary_run_test(&bin.path, "foldseek") { cstr!(r#"ok"#) } else { cstr!(r#"no"#) } } else { cstr!(r#"n/a"#) } } else { cstr!(r#"n/a"#) }, + ), 3); + msg::println_message(&format!("FoldMason: {} .. {}", + if let Some(&ref bin) = &bin.get("foldmason") { if bin.set { bin.path.clone() } else { "Unset".to_string() } } else { "Undefined".to_string() }, + if let Some(&ref bin) = &bin.get("foldmason") { if bin.set { if binary_run_test(&bin.path, "foldmason") { cstr!(r#"ok"#) } else { cstr!(r#"no"#) } } else { cstr!(r#"n/a"#) } } else { cstr!(r#"n/a"#) }, + ), 3); + msg::println_message(&format!("MAFFT: {} .. {}", + if let Some(&ref bin) = &bin.get("mafft") { if bin.set { bin.path.clone() } else { "Unset".to_string() } } else { "Undefined".to_string() }, + if let Some(&ref bin) = &bin.get("mafft") { if bin.set { if binary_run_test(&bin.path, "mafft") { cstr!(r#"ok"#) } else { cstr!(r#"no"#) } } else { cstr!(r#"n/a"#) } } else { cstr!(r#"n/a"#) }, + ), 3); + msg::println_message(&format!("IQ-TREE: {} .. {}", + if let Some(&ref bin) = &bin.get("iqtree") { if bin.set { bin.path.clone() } else { "Unset".to_string() } } else { "Undefined".to_string() }, + if let Some(&ref bin) = &bin.get("iqtree") { if bin.set { if binary_run_test(&bin.path, "iqtree") { cstr!(r#"ok"#) } else { cstr!(r#"no"#) } } else { cstr!(r#"n/a"#) } } else { cstr!(r#"n/a"#) }, + ), 3); + msg::println_message(&format!("FastTree: {} .. {}", + if let Some(&ref bin) = &bin.get("fasttree") { if bin.set { bin.path.clone() } else { "Unset".to_string() } } else { "Undefined".to_string() }, + if let Some(&ref bin) = &bin.get("fasttree") { if bin.set { if binary_run_test(&bin.path, "fasttree") { cstr!(r#"ok"#) } else { cstr!(r#"no"#) } } else { cstr!(r#"n/a"#) } } else { cstr!(r#"n/a"#) }, + ), 3); + msg::println_message(&format!("RAxML: {} .. {}", + if let Some(&ref bin) = &bin.get("raxml") { if bin.set { bin.path.clone() } else { "Unset".to_string() } } else { "Undefined".to_string() }, + if let Some(&ref bin) = &bin.get("raxml") { if bin.set { if binary_run_test(&bin.path, "raxml") { cstr!(r#"ok"#) } else { cstr!(r#"no"#) } } else { cstr!(r#"n/a"#) } } else { cstr!(r#"n/a"#) }, + ), 3); + Ok(()) +} + +fn binary_run_test(path: &str, sw: &str) -> bool { + if !var::VALID_BINARY.contains(&sw) { return false; } + 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"), + "fasttree" => &mut test_command, + "raxml" => test_command.arg("-v"), + _ => return false, + }; + 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 + + 0 +} +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> { + 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 { err::error(err::ERR_ARGPARSE, Some("No task specified".to_string())) }; Ok(()) } \ No newline at end of file diff --git a/src/util/arg_parser.rs b/src/util/arg_parser.rs index c9b71f0..512d9a9 100644 --- a/src/util/arg_parser.rs +++ b/src/util/arg_parser.rs @@ -365,10 +365,7 @@ pub enum Commands { /// Runtime environment configuration #[clap(arg_required_else_help = true, allow_hyphen_values = true)] Config { - /// Show current environment - #[arg(short='s', long)] - show: bool, - /// Check dependencies + /// Check current environment configuration #[arg(short='c', long)] check: bool, /// Set mmseqs binary path @@ -457,7 +454,6 @@ pub struct Args { pub genetree_aligner: Option, pub genetree_aligner_options: Option>, - pub config_show: Option, pub config_check: Option, pub config_set_mmseqs: Option, pub config_set_foldseek: Option, @@ -690,9 +686,6 @@ impl Args { Some(GeneTree { threshold, .. }) => Some(*threshold), _ => None, }; - let config_show = match &args.command { - Some(Config { show, .. }) => Some(*show), _ => None, - }; let config_check = match &args.command { Some(Config { check, .. }) => Some(*check), _ => None, }; @@ -729,7 +722,7 @@ impl Args { cluster_input, cluster_output, cluster_tmp, cluster_keep_cluster_db, cluster_cluster_options, tree_db, tree_input, tree_output, tree_aligner, tree_tree_builder, tree_aligner_options, tree_tree_options, tree_threshold, genetree_input, genetree_names, genetree_tree_builder, genetree_tree_options, genetree_realign, genetree_aligner, genetree_aligner_options, genetree_threshold, - config_show, config_check, config_set_mmseqs, config_set_foldseek, config_set_foldmason, config_set_mafft, config_set_mafft_linsi, config_set_iqtree, config_set_fasttree, config_set_raxml, + config_check, config_set_mmseqs, config_set_foldseek, config_set_foldmason, config_set_mafft, config_set_mafft_linsi, config_set_iqtree, config_set_fasttree, config_set_raxml, } } } \ No newline at end of file diff --git a/src/util/command.rs b/src/util/command.rs index c54a00a..169436a 100644 --- a/src/util/command.rs +++ b/src/util/command.rs @@ -23,6 +23,26 @@ pub fn run(cmd: &mut std::process::Command) { } } +pub fn run_code(cmd: &mut std::process::Command) -> i32 { + let cmd = cmd.stdout(std::process::Stdio::null()).stderr(std::process::Stdio::null()); + let cmdstr = format!("{:?}", cmd).replace("\"", ""); + msg::println_message(&format!("Running command: {}", cmdstr), 4); + if let Ok(mut child) = cmd.spawn() { + let wait = child.wait(); + if let Ok(status) = wait { + if let Some(code) = status.code() { + code + } else { + 1 + } + } else { + 1 + } + } else { + 1 + } +} + pub fn _run_at(cmd: &mut std::process::Command, path: &std::path::Path) { let cmdstr = format!("{:?}", cmd); if let Ok(mut child) = cmd.current_dir(path).spawn() {