#![deny(missing_docs)]
use std::{path::{Path, PathBuf}, time::SystemTime};
use cargo_toml::{Error, Manifest};
pub const DIR_DEBUG: &str = "debug";
pub const DIR_RELEASE: &str = "release";
pub const DIR_TARGET: &str = "target";
pub const FILE_MANIFEST: &str = "Cargo.toml";
fn find_recursive(
path_dir: &Path,
path_sub: &Path,
results: &mut Vec<PathBuf>,
recurse: usize,
) -> std::io::Result<()> {
for sub in path_dir.read_dir()? {
if let Ok(entry) = sub {
let path: PathBuf = entry.path();
if path.is_dir() {
let mut path_file: PathBuf = path.clone();
path_file.push(path_sub);
if path_file.is_file() {
results.push(path_file);
}
if 0 < recurse {
find_recursive(&path, path_sub, results, recurse - 1)?;
}
}
}
}
Ok(())
}
pub enum Mode {
Debug,
Release,
Latest,
}
impl Mode {
pub fn make_path(
&self,
path_dir_target: impl Into<PathBuf>,
path_exe: impl AsRef<Path>,
) -> Option<PathBuf> {
let mut path: PathBuf = path_dir_target.into();
let path_exe: &Path = path_exe.as_ref();
match self {
Mode::Debug => {
path.push(DIR_DEBUG);
path.push(path_exe);
Some(path)
}
Mode::Release => {
path.push(DIR_RELEASE);
path.push(path_exe);
Some(path)
}
Mode::Latest => {
let mut paths = Vec::new();
if let Err(e) = find_recursive(&path, path_exe, &mut paths, 2) {
eprintln!(
"WARNING: An error occurred while searching in `{}`. \
Results may not be complete.\
\n Error: {}",
path.display(),
e
);
}
paths.sort_by_key(|path| {
path.metadata()
.and_then(|meta| meta.modified())
.unwrap_or(SystemTime::UNIX_EPOCH)
});
paths.pop()
}
}
}
}
pub fn path_project(dir_or_manifest: &Path) -> &Path {
if dir_or_manifest.is_file() {
match dir_or_manifest.parent() {
Some(parent) => parent,
None => ".".as_ref(),
}
} else {
dir_or_manifest
}
}
pub fn names_bin(path_manifest: impl AsRef<Path>) -> Result<Vec<String>, Error> {
let manifest = Manifest::from_path(path_manifest)?;
Ok(manifest.bin.into_iter().filter_map(|p| p.name).collect())
}