1use crate::provider::prelude::*;
10
11#[derive(Debug, Default, PartialEq)]
12pub struct Path {}
13
14impl fmt::Display for Path {
15 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
16 write!(f, "$PATH")
17 }
18}
19
20impl Path {
21 pub fn new() -> Path {
22 Default::default()
23 }
24}
25
26#[async_trait]
27impl IsProvider for Path {
28 async fn search_internal(
29 &self,
30 command: &str,
31 target_env: Arc<Environment>,
32 ) -> ProviderResult<Vec<Candidate>> {
33 let result_success = |package: String| {
34 Ok(vec![Candidate {
35 package: package.clone(),
36 actions: Actions {
37 install: None,
38 execute: cmd!(package),
39 },
40 ..Candidate::default()
41 }])
42 };
43
44 if &crate::environment::current() == target_env.as_ref() {
45 match which::which(command) {
46 Ok(path) => result_success(path.display().to_string()),
47 Err(_) => Err(ProviderError::NotFound(command.to_string())),
48 }
49 } else {
50 let stdout = target_env
51 .output_of(cmd!("command", "-v", command))
52 .await
53 .map_err(|e| {
54 if let ExecutionError::NonZero { .. } = e {
55 ProviderError::NotFound(command.to_string())
56 } else {
57 ProviderError::from(e)
58 }
59 })?;
60
61 result_success(stdout.trim_end().to_string())
62 }
63 }
64}
65
66#[cfg(test)]
67mod tests {
68 use super::*;
69 use crate::test::prelude::*;
70
71 test::default_tests!(Path::new());
72
73 #[test]
74 fn search_nonexistent() {
75 let query = quick_test!(
76 Path::new(),
77 Err(ExecutionError::NonZero {
78 command: "command".to_string(),
79 output: std::process::Output {
80 stdout: "".into(),
81 stderr: "".into(),
82 status: ExitStatus::from_raw(1),
83 }
84 })
85 );
86
87 assert::is_err!(query);
88 assert::err::not_found!(query);
89 }
90
91 #[test]
92 fn search_existent() {
93 let query = quick_test!(Path::new(), Ok("/usr/bin/top".to_string()));
94
95 let result = query.results.unwrap();
96
97 assert_eq!(result.len(), 1);
98 assert_eq!(result[0].package, "/usr/bin/top".to_string());
99 assert_eq!(result[0].actions.execute, vec!["/usr/bin/top"].into());
100 }
101}