feat: use humansize crate and which crate for program lookup
Co-authored-by: aider (openai/andrew/openrouter/qwen/qwen3-coder) <aider@aider.chat>
This commit is contained in:
@@ -48,7 +48,8 @@ axum = "0.7"
|
|||||||
tower = "0.4"
|
tower = "0.4"
|
||||||
tower-http = { version = "0.5", features = ["cors", "fs", "trace"] }
|
tower-http = { version = "0.5", features = ["cors", "fs", "trace"] }
|
||||||
hyper = { version = "1.0", features = ["full"] }
|
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]
|
[dev-dependencies]
|
||||||
tempfile = "3.3.0"
|
tempfile = "3.3.0"
|
||||||
|
|||||||
@@ -1,15 +1,10 @@
|
|||||||
use anyhow::{Context, Result, anyhow};
|
use anyhow::{Context, Result, anyhow};
|
||||||
use log::*;
|
use log::*;
|
||||||
use std::env;
|
|
||||||
use std::fs;
|
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
use std::os::unix::fs::PermissionsExt;
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::process::{Child, Command, Stdio};
|
use std::process::{Child, Command, Stdio};
|
||||||
use std::collections::HashMap;
|
use which::which;
|
||||||
use std::sync::Mutex;
|
|
||||||
use once_cell::sync::Lazy;
|
|
||||||
|
|
||||||
use crate::compression_engine::CompressionEngine;
|
use crate::compression_engine::CompressionEngine;
|
||||||
|
|
||||||
@@ -69,11 +64,11 @@ impl CompressionEngineProgram {
|
|||||||
compress: Vec<&str>,
|
compress: Vec<&str>,
|
||||||
decompress: Vec<&str>,
|
decompress: Vec<&str>,
|
||||||
) -> CompressionEngineProgram {
|
) -> CompressionEngineProgram {
|
||||||
let program_path = get_program_path(program);
|
let program_path = which(program);
|
||||||
let supported = program_path.is_ok();
|
let supported = program_path.is_ok();
|
||||||
|
|
||||||
CompressionEngineProgram {
|
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(),
|
compress: compress.iter().map(|s| s.to_string()).collect(),
|
||||||
decompress: decompress.iter().map(|s| s.to_string()).collect(),
|
decompress: decompress.iter().map(|s| s.to_string()).collect(),
|
||||||
supported,
|
supported,
|
||||||
@@ -81,54 +76,6 @@ impl CompressionEngineProgram {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cache for program lookup results to avoid redundant filesystem operations
|
|
||||||
static PROGRAM_CACHE: Lazy<Mutex<HashMap<String, Option<String>>>> =
|
|
||||||
Lazy::new(|| Mutex::new(HashMap::new()));
|
|
||||||
|
|
||||||
fn get_program_path(program: &str) -> Result<String> {
|
|
||||||
// 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 {
|
impl CompressionEngine for CompressionEngineProgram {
|
||||||
fn is_supported(&self) -> bool {
|
fn is_supported(&self) -> bool {
|
||||||
self.supported
|
self.supported
|
||||||
|
|||||||
@@ -1,15 +1,10 @@
|
|||||||
use crate::plugins::ProgramWriter;
|
use crate::plugins::ProgramWriter;
|
||||||
use anyhow::{Context, Result, anyhow};
|
use anyhow::{Context, Result, anyhow};
|
||||||
use log::*;
|
use log::*;
|
||||||
use std::env;
|
|
||||||
use std::fs;
|
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::os::unix::fs::PermissionsExt;
|
|
||||||
use std::process::{Command, Stdio};
|
use std::process::{Command, Stdio};
|
||||||
use std::collections::HashMap;
|
use which::which;
|
||||||
use std::sync::Mutex;
|
|
||||||
use once_cell::sync::Lazy;
|
|
||||||
|
|
||||||
use crate::meta_plugin::MetaPlugin;
|
use crate::meta_plugin::MetaPlugin;
|
||||||
|
|
||||||
@@ -25,11 +20,11 @@ pub struct MetaPluginProgram {
|
|||||||
|
|
||||||
impl MetaPluginProgram {
|
impl MetaPluginProgram {
|
||||||
pub fn new(program: &str, args: Vec<&str>, meta_name: String, split_whitespace: bool) -> 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();
|
let supported = program_path.is_ok();
|
||||||
|
|
||||||
MetaPluginProgram {
|
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(),
|
args: args.iter().map(|s| s.to_string()).collect(),
|
||||||
supported,
|
supported,
|
||||||
meta_name,
|
meta_name,
|
||||||
@@ -134,51 +129,3 @@ impl MetaPlugin for MetaPluginProgram {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cache for program lookup results to avoid redundant filesystem operations
|
|
||||||
static PROGRAM_CACHE: Lazy<Mutex<HashMap<String, Option<String>>>> =
|
|
||||||
Lazy::new(|| Mutex::new(HashMap::new()));
|
|
||||||
|
|
||||||
fn get_program_path(program: &str) -> Result<String> {
|
|
||||||
// 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))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -29,34 +29,9 @@ pub fn get_meta_from_env() -> HashMap<String, String> {
|
|||||||
meta_env
|
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 {
|
pub fn format_size(size: u64, human_readable: bool) -> String {
|
||||||
match human_readable {
|
match human_readable {
|
||||||
true => format_size_human_readable(size),
|
true => humansize::format_size(size, humansize::DECIMAL),
|
||||||
false => size.to_string(),
|
false => size.to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user