use crate::provider::prelude::*;
#[derive(Debug, Default, PartialEq)]
pub struct Path {}
impl fmt::Display for Path {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "$PATH")
}
}
impl Path {
pub fn new() -> Path {
Default::default()
}
}
#[async_trait]
impl IsProvider for Path {
async fn search_internal(
&self,
command: &str,
target_env: Arc<Environment>,
) -> ProviderResult<Vec<Candidate>> {
let result_success = |package: String| {
Ok(vec![Candidate {
package: package.clone(),
actions: Actions {
install: None,
execute: cmd!(package),
},
..Candidate::default()
}])
};
if &crate::environment::current() == target_env.as_ref() {
match which::which(command) {
Ok(path) => result_success(path.display().to_string()),
Err(_) => Err(ProviderError::NotFound(command.to_string())),
}
} else {
let stdout = target_env
.output_of(cmd!("command", "-v", command))
.await
.map_err(|e| {
if let ExecutionError::NonZero { .. } = e {
ProviderError::NotFound(command.to_string())
} else {
ProviderError::from(e)
}
})?;
result_success(stdout.trim_end().to_string())
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::test::prelude::*;
test::default_tests!(Path::new());
#[test]
fn search_nonexistent() {
let query = quick_test!(
Path::new(),
Err(ExecutionError::NonZero {
command: "command".to_string(),
output: std::process::Output {
stdout: "".into(),
stderr: "".into(),
status: ExitStatus::from_raw(1),
}
})
);
assert::is_err!(query);
assert::err::not_found!(query);
}
#[test]
fn search_existent() {
let query = quick_test!(Path::new(), Ok("/usr/bin/top".to_string()));
let result = query.results.unwrap();
assert_eq!(result.len(), 1);
assert_eq!(result[0].package, "/usr/bin/top".to_string());
assert_eq!(result[0].actions.execute, vec!["/usr/bin/top"].into());
}
}