1#![deny(missing_docs)]
3
4use std::{path::{Path, PathBuf}, time::SystemTime};
5use cargo_toml::{Error, Manifest};
6
7
8pub const DIR_DEBUG: &str = "debug";
10pub const DIR_RELEASE: &str = "release";
12pub const DIR_TARGET: &str = "target";
14pub const FILE_MANIFEST: &str = "Cargo.toml";
16
17
18fn find_recursive(
19 path_dir: &Path,
20 path_sub: &Path,
21 results: &mut Vec<PathBuf>,
22 recurse: usize,
23) -> std::io::Result<()> {
24 for sub in path_dir.read_dir()? {
25 if let Ok(entry) = sub {
26 let path: PathBuf = entry.path();
27
28 if path.is_dir() {
29 let mut path_file: PathBuf = path.clone();
30 path_file.push(path_sub);
31
32 if path_file.is_file() {
33 results.push(path_file);
34 }
35
36 if 0 < recurse {
37 find_recursive(&path, path_sub, results, recurse - 1)?;
38 }
39 }
40 }
41 }
42
43 Ok(())
44}
45
46
47pub enum Mode {
50 Debug,
52 Release,
54 Latest,
57}
58
59impl Mode {
60 pub fn make_path(
66 &self,
67 path_dir_target: impl Into<PathBuf>,
68 path_exe: impl AsRef<Path>,
69 ) -> Option<PathBuf> {
70 let mut path: PathBuf = path_dir_target.into();
71 let path_exe: &Path = path_exe.as_ref();
72
73 match self {
74 Mode::Debug => {
75 path.push(DIR_DEBUG);
76 path.push(path_exe);
77 Some(path)
78 }
79 Mode::Release => {
80 path.push(DIR_RELEASE);
81 path.push(path_exe);
82 Some(path)
83 }
84 Mode::Latest => {
85 let mut paths = Vec::new();
86
87 if let Err(e) = find_recursive(&path, path_exe, &mut paths, 2) {
88 eprintln!(
89 "WARNING: An error occurred while searching in `{}`. \
90 Results may not be complete.\
91 \n Error: {}",
92 path.display(),
93 e
94 );
95 }
96
97 paths.sort_by_key(|path| {
98 path.metadata()
99 .and_then(|meta| meta.modified())
100 .unwrap_or(SystemTime::UNIX_EPOCH)
101 });
102
103 paths.pop()
104 }
105 }
106 }
107}
108
109
110pub fn path_project(dir_or_manifest: &Path) -> &Path {
113 if dir_or_manifest.is_file() {
114 match dir_or_manifest.parent() {
115 Some(parent) => parent,
116 None => ".".as_ref(),
117 }
118 } else {
119 dir_or_manifest
120 }
121}
122
123
124pub fn names_bin(path_manifest: impl AsRef<Path>) -> Result<Vec<String>, Error> {
129 let manifest = Manifest::from_path(path_manifest)?;
130 Ok(manifest.bin.into_iter().filter_map(|p| p.name).collect())
131}