mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-09-09 22:33:37 +00:00
Cache ripgrep availability check in all execution environments
The rg availability probe (rg --version / which rg) was running on every grep() call. Cache the result in a OnceLock/OnceCell per environment so the probe runs at most once. Also add grep -rn fallback to Daytona env, matching the pattern already used by local and Docker envs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
915cdd2a1f
commit
f211ec86d9
3 changed files with 55 additions and 28 deletions
|
|
@ -60,6 +60,7 @@ pub struct DockerExecutionEnvironment {
|
|||
container_id: tokio::sync::OnceCell<String>,
|
||||
cached_platform: std::sync::OnceLock<String>,
|
||||
cached_os_version: std::sync::OnceLock<String>,
|
||||
rg_available: tokio::sync::OnceCell<bool>,
|
||||
event_callback: Option<ExecEnvEventCallback>,
|
||||
}
|
||||
|
||||
|
|
@ -77,6 +78,7 @@ impl DockerExecutionEnvironment {
|
|||
container_id: tokio::sync::OnceCell::new(),
|
||||
cached_platform: std::sync::OnceLock::new(),
|
||||
cached_os_version: std::sync::OnceLock::new(),
|
||||
rg_available: tokio::sync::OnceCell::const_new(),
|
||||
event_callback: None,
|
||||
})
|
||||
}
|
||||
|
|
@ -581,16 +583,15 @@ impl ExecutionEnvironment for DockerExecutionEnvironment {
|
|||
) -> Result<Vec<String>, String> {
|
||||
let container_path = self.resolve_container_path(path);
|
||||
|
||||
// Detect ripgrep availability
|
||||
let (_, _, rg_check) = self
|
||||
.docker_exec(
|
||||
// Detect ripgrep availability (cached)
|
||||
let use_rg = *self.rg_available.get_or_init(|| async {
|
||||
let result = self.docker_exec(
|
||||
vec!["which".to_string(), "rg".to_string()],
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let use_rg = rg_check == 0;
|
||||
).await;
|
||||
matches!(result, Ok((_, _, 0)))
|
||||
}).await;
|
||||
|
||||
let command = if use_rg {
|
||||
let mut args = vec!["rg".to_string(), "-n".to_string()];
|
||||
|
|
|
|||
|
|
@ -9,12 +9,13 @@ use tokio_util::sync::CancellationToken;
|
|||
pub struct LocalExecutionEnvironment {
|
||||
working_directory: PathBuf,
|
||||
event_callback: Option<ExecEnvEventCallback>,
|
||||
rg_available: std::sync::OnceLock<bool>,
|
||||
}
|
||||
|
||||
impl LocalExecutionEnvironment {
|
||||
#[must_use]
|
||||
pub fn new(working_directory: PathBuf) -> Self {
|
||||
Self { working_directory, event_callback: None }
|
||||
Self { working_directory, event_callback: None, rg_available: std::sync::OnceLock::new() }
|
||||
}
|
||||
|
||||
pub fn set_event_callback(&mut self, cb: ExecEnvEventCallback) {
|
||||
|
|
@ -230,13 +231,15 @@ impl ExecutionEnvironment for LocalExecutionEnvironment {
|
|||
let full_path = self.resolve_path(path);
|
||||
|
||||
// Try rg (ripgrep) first, fall back to grep
|
||||
let use_rg = std::process::Command::new("rg")
|
||||
.arg("--version")
|
||||
.stdout(std::process::Stdio::null())
|
||||
.stderr(std::process::Stdio::null())
|
||||
.status()
|
||||
.map(|s| s.success())
|
||||
.unwrap_or(false);
|
||||
let use_rg = *self.rg_available.get_or_init(|| {
|
||||
std::process::Command::new("rg")
|
||||
.arg("--version")
|
||||
.stdout(std::process::Stdio::null())
|
||||
.stderr(std::process::Stdio::null())
|
||||
.status()
|
||||
.map(|s| s.success())
|
||||
.unwrap_or(false)
|
||||
});
|
||||
|
||||
let output = if use_rg {
|
||||
let mut args = vec!["-n".to_string()];
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ pub struct DaytonaExecutionEnvironment {
|
|||
config: DaytonaConfig,
|
||||
client: daytona_sdk::Client,
|
||||
sandbox: tokio::sync::OnceCell<daytona_sdk::Sandbox>,
|
||||
rg_available: tokio::sync::OnceCell<bool>,
|
||||
event_callback: Option<ExecEnvEventCallback>,
|
||||
}
|
||||
|
||||
|
|
@ -52,6 +53,7 @@ impl DaytonaExecutionEnvironment {
|
|||
config,
|
||||
client,
|
||||
sandbox: tokio::sync::OnceCell::new(),
|
||||
rg_available: tokio::sync::OnceCell::const_new(),
|
||||
event_callback: None,
|
||||
}
|
||||
}
|
||||
|
|
@ -584,23 +586,44 @@ impl ExecutionEnvironment for DaytonaExecutionEnvironment {
|
|||
) -> Result<Vec<String>, String> {
|
||||
let resolved = self.resolve_path(path);
|
||||
|
||||
// Build rg command (same approach as Docker env)
|
||||
let mut cmd = "rg --line-number --no-heading".to_string();
|
||||
if options.case_insensitive {
|
||||
cmd.push_str(" -i");
|
||||
}
|
||||
if let Some(ref glob_filter) = options.glob_filter {
|
||||
cmd.push_str(&format!(" --glob '{glob_filter}'"));
|
||||
}
|
||||
if let Some(max) = options.max_results {
|
||||
cmd.push_str(&format!(" --max-count {max}"));
|
||||
}
|
||||
cmd.push_str(&format!(" -- '{}' '{}'", pattern.replace('\'', "'\\''"), resolved));
|
||||
// Detect ripgrep availability (cached)
|
||||
let use_rg = *self.rg_available.get_or_init(|| async {
|
||||
let result = self.exec_command("rg --version", 10_000, None, None, None).await;
|
||||
matches!(result, Ok(r) if r.exit_code == 0)
|
||||
}).await;
|
||||
|
||||
let cmd = if use_rg {
|
||||
let mut cmd = "rg --line-number --no-heading".to_string();
|
||||
if options.case_insensitive {
|
||||
cmd.push_str(" -i");
|
||||
}
|
||||
if let Some(ref glob_filter) = options.glob_filter {
|
||||
cmd.push_str(&format!(" --glob '{glob_filter}'"));
|
||||
}
|
||||
if let Some(max) = options.max_results {
|
||||
cmd.push_str(&format!(" --max-count {max}"));
|
||||
}
|
||||
cmd.push_str(&format!(" -- '{}' '{}'", pattern.replace('\'', "'\\''"), resolved));
|
||||
cmd
|
||||
} else {
|
||||
let mut cmd = "grep -rn".to_string();
|
||||
if options.case_insensitive {
|
||||
cmd.push_str(" -i");
|
||||
}
|
||||
if let Some(ref glob_filter) = options.glob_filter {
|
||||
cmd.push_str(&format!(" --include '{glob_filter}'"));
|
||||
}
|
||||
if let Some(max) = options.max_results {
|
||||
cmd.push_str(&format!(" -m {max}"));
|
||||
}
|
||||
cmd.push_str(&format!(" -- '{}' '{}'", pattern.replace('\'', "'\\''"), resolved));
|
||||
cmd
|
||||
};
|
||||
|
||||
let result = self.exec_command(&cmd, 30_000, None, None, None).await?;
|
||||
|
||||
if result.exit_code == 1 {
|
||||
// rg exits 1 for no matches
|
||||
// Both rg and grep exit 1 for no matches
|
||||
return Ok(Vec::new());
|
||||
}
|
||||
if result.exit_code != 0 {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue