From 6e4b690bd8bf24cfb161fdbecb56691552eac9ea Mon Sep 17 00:00:00 2001 From: Andrew Phillips Date: Tue, 12 Aug 2025 16:23:11 -0300 Subject: [PATCH] feat: use humansize crate and which crate for program lookup Co-authored-by: aider (openai/andrew/openrouter/qwen/qwen3-coder) --- Cargo.toml | 3 +- src/compression_engine/program.rs | 59 ++----------------------------- src/meta_plugin/program.rs | 59 ++----------------------------- src/modes/common.rs | 27 +------------- 4 files changed, 9 insertions(+), 139 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 838b35f..bd5388a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,7 +48,8 @@ axum = "0.7" tower = "0.4" tower-http = { version = "0.5", features = ["cors", "fs", "trace"] } hyper = { version = "1.0", features = ["full"] } -once_cell = "1.19.0" +once_cell = "1.19.0" once_cell = "1.19.0" +once_cell = "1.19.0"which = "6.0" [dev-dependencies] tempfile = "3.3.0" diff --git a/src/compression_engine/program.rs b/src/compression_engine/program.rs index d36db87..fcfd65b 100644 --- a/src/compression_engine/program.rs +++ b/src/compression_engine/program.rs @@ -1,15 +1,10 @@ use anyhow::{Context, Result, anyhow}; use log::*; -use std::env; -use std::fs; use std::fs::File; use std::io::{Read, Write}; -use std::os::unix::fs::PermissionsExt; use std::path::PathBuf; use std::process::{Child, Command, Stdio}; -use std::collections::HashMap; -use std::sync::Mutex; -use once_cell::sync::Lazy; +use which::which; use crate::compression_engine::CompressionEngine; @@ -69,11 +64,11 @@ impl CompressionEngineProgram { compress: Vec<&str>, decompress: Vec<&str>, ) -> CompressionEngineProgram { - let program_path = get_program_path(program); + let program_path = which(program); let supported = program_path.is_ok(); CompressionEngineProgram { - program: program_path.unwrap_or(program.to_string()), + program: program_path.map_or_else(|_| program.to_string(), |p| p.to_string_lossy().to_string()), compress: compress.iter().map(|s| s.to_string()).collect(), decompress: decompress.iter().map(|s| s.to_string()).collect(), supported, @@ -81,54 +76,6 @@ impl CompressionEngineProgram { } } -// Cache for program lookup results to avoid redundant filesystem operations -static PROGRAM_CACHE: Lazy>>> = - Lazy::new(|| Mutex::new(HashMap::new())); - -fn get_program_path(program: &str) -> Result { - // Check cache first - { - let cache = PROGRAM_CACHE.lock().unwrap(); - if let Some(result) = cache.get(program) { - return match result { - Some(path) => Ok(path.clone()), - None => Err(anyhow!("Unable to find binary {} in PATH", program)), - }; - } - } - - debug!("COMPRESSION: Looking for executable: {}", program); - let result = if let Ok(path) = env::var("PATH") { - let mut found_path = None; - for p in path.split(':') { - let p_str = format!("{}/{}", p, program); - if let Ok(stat) = fs::metadata(&p_str) { - let permissions = stat.permissions(); - if stat.is_file() && permissions.mode() & 0o111 != 0 { - found_path = Some(p_str); - break; - } - } - } - found_path - } else { - None - }; - - // Store result in cache - let mut cache = PROGRAM_CACHE.lock().unwrap(); - match &result { - Some(path) => { - cache.insert(program.to_string(), Some(path.clone())); - Ok(path.clone()) - } - None => { - cache.insert(program.to_string(), None); - Err(anyhow!("Unable to find binary {} in PATH", program)) - } - } -} - impl CompressionEngine for CompressionEngineProgram { fn is_supported(&self) -> bool { self.supported diff --git a/src/meta_plugin/program.rs b/src/meta_plugin/program.rs index be38488..3ff2424 100644 --- a/src/meta_plugin/program.rs +++ b/src/meta_plugin/program.rs @@ -1,15 +1,10 @@ use crate::plugins::ProgramWriter; use anyhow::{Context, Result, anyhow}; use log::*; -use std::env; -use std::fs; use std::io; use std::io::Write; -use std::os::unix::fs::PermissionsExt; use std::process::{Command, Stdio}; -use std::collections::HashMap; -use std::sync::Mutex; -use once_cell::sync::Lazy; +use which::which; use crate::meta_plugin::MetaPlugin; @@ -25,11 +20,11 @@ pub struct MetaPluginProgram { impl MetaPluginProgram { pub fn new(program: &str, args: Vec<&str>, meta_name: String, split_whitespace: bool) -> MetaPluginProgram { - let program_path = get_program_path(program); + let program_path = which(program); let supported = program_path.is_ok(); MetaPluginProgram { - program: program_path.unwrap_or(program.to_string()), + program: program_path.map_or_else(|_| program.to_string(), |p| p.to_string_lossy().to_string()), args: args.iter().map(|s| s.to_string()).collect(), supported, meta_name, @@ -134,51 +129,3 @@ impl MetaPlugin for MetaPluginProgram { } } - -// Cache for program lookup results to avoid redundant filesystem operations -static PROGRAM_CACHE: Lazy>>> = - Lazy::new(|| Mutex::new(HashMap::new())); - -fn get_program_path(program: &str) -> Result { - // Check cache first - { - let cache = PROGRAM_CACHE.lock().unwrap(); - if let Some(result) = cache.get(program) { - return match result { - Some(path) => Ok(path.clone()), - None => Err(anyhow!("Unable to find binary {} in PATH", program)), - }; - } - } - - debug!("META: Looking for executable: {}", program); - let result = if let Ok(path) = env::var("PATH") { - let mut found_path = None; - for p in path.split(':') { - let p_str = format!("{}/{}", p, program); - if let Ok(stat) = fs::metadata(&p_str) { - let permissions = stat.permissions(); - if stat.is_file() && permissions.mode() & 0o111 != 0 { - found_path = Some(p_str); - break; - } - } - } - found_path - } else { - None - }; - - // Store result in cache - let mut cache = PROGRAM_CACHE.lock().unwrap(); - match &result { - Some(path) => { - cache.insert(program.to_string(), Some(path.clone())); - Ok(path.clone()) - } - None => { - cache.insert(program.to_string(), None); - Err(anyhow!("Unable to find binary {} in PATH", program)) - } - } -} diff --git a/src/modes/common.rs b/src/modes/common.rs index 07a818f..e8beda8 100644 --- a/src/modes/common.rs +++ b/src/modes/common.rs @@ -29,34 +29,9 @@ pub fn get_meta_from_env() -> HashMap { meta_env } -pub fn format_size_human_readable(size: u64) -> String { - const UNITS: &[&str] = &["", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei"]; - const THRESHOLD: u64 = 1024; - - if size == 0 { - return "0".to_string(); - } - - let mut size_f = size as f64; - let mut unit_index = 0; - - while size_f >= THRESHOLD as f64 && unit_index < UNITS.len() - 1 { - size_f /= THRESHOLD as f64; - unit_index += 1; - } - - if unit_index == 0 { - format!("{}", size) - } else if size_f.fract() == 0.0 { - format!("{}{}", size_f as u64, UNITS[unit_index]) - } else { - format!("{:.1}{}", size_f, UNITS[unit_index]) - } -} - pub fn format_size(size: u64, human_readable: bool) -> String { match human_readable { - true => format_size_human_readable(size), + true => humansize::format_size(size, humansize::DECIMAL), false => size.to_string(), } }