use crate::provider::prelude::*;
use crate::provider::CnfError;
use async_std::{fs, prelude::*};
use is_executable::is_executable;
#[derive(Debug, PartialEq)]
pub struct Cwd {
path: std::path::PathBuf,
}
impl Cwd {
pub fn new() -> Result<Self, CnfError> {
Ok(Cwd {
path: std::env::current_dir().context("cannot create 'cwd' provider")?,
})
}
pub fn with_path(path: std::path::PathBuf) -> Self {
Cwd { path }
}
}
impl fmt::Display for Cwd {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "cwd")
}
}
#[async_trait]
impl IsProvider for Cwd {
async fn search_internal(
&self,
command: &str,
_target_env: Arc<crate::environment::Environment>,
) -> ProviderResult<Vec<Candidate>> {
let mut results = vec![];
if let Ok(mut diriter) = fs::read_dir(&self.path).await {
while let Some(entry) = diriter.next().await {
if entry.is_err() {
continue;
}
let direntry = entry.unwrap();
let entrypath = &direntry.path();
log::debug!("Checking file {}", entrypath.display());
let metadata = match fs::metadata(entrypath).await {
Ok(val) => val,
Err(_) => continue,
};
if !metadata.file_type().is_file() {
log::debug!("Skipping {}: Not a file", entrypath.display());
continue;
}
let filename = direntry.file_name();
let filename = match filename.to_str().to_owned() {
Some(name) => name,
None => {
log::debug!("Skipping {}: Invalid unicode name", entrypath.display());
continue;
}
};
if filename.starts_with(command) {
let pwd = std::env::current_dir().unwrap();
let filename = pwd.join(filename).display().to_string().to_owned();
let mut candidate = Candidate {
package: filename.clone(),
origin: pwd.display().to_string(),
actions: Actions {
install: None,
execute: cmd!(filename.clone()),
},
..Candidate::default()
};
if !is_executable(entrypath) {
candidate.actions.install = Some(cmd!("chmod", "+x", &filename));
}
results.push(candidate);
}
}
if !results.is_empty() {
return Ok(results);
}
}
Err(ProviderError::NotFound(command.to_string()))
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::environment::current;
use crate::provider::search_in;
use crate::test::prelude::*;
use async_std::task;
#[test]
fn initialize() {
let _cwd = Cwd::new().unwrap();
}
#[test]
fn does_not_exist() {
let cwd = Cwd::new().unwrap();
let query = task::block_on(search_in(
Arc::new(cwd.into()),
"thisfiledoesnotexist",
Arc::new(current()),
));
assert::is_err!(query);
assert::err::not_found!(query);
}
}