1use std::{fs, path::Path};
3
4use crate::e_target::{CargoTarget, TargetKind, TargetOrigin};
5use anyhow::{Context, Result};
6
7pub fn discover_targets(current_dir: &Path) -> Result<Vec<CargoTarget>> {
10 let mut targets = Vec::new();
11 let parent = current_dir.parent().expect("expected cwd to have a parent");
12 let manifest_path = current_dir.join("Cargo.toml");
14 if manifest_path.exists() {
15 targets.push(CargoTarget {
16 name: "default".to_string(),
17 display_name: "Default Manifest".to_string(),
18 manifest_path: manifest_path.to_string_lossy().to_string(),
19 kind: TargetKind::Manifest,
20 extended: false,
21 origin: None,
22 });
23 }
24
25 let examples_dir = current_dir.join("examples");
27 if examples_dir.exists() && examples_dir.is_dir() {
28 for entry in fs::read_dir(&examples_dir)
29 .with_context(|| format!("Reading directory {:?}", examples_dir))?
30 {
31 let entry = entry?;
32 let path = entry.path();
33 if path.is_file() {
34 if let Some(ext) = path.extension() {
36 if ext == "rs" {
37 if let Some(stem) = path.file_stem() {
38 targets.push(CargoTarget {
39 name: stem.to_string_lossy().to_string(),
40 display_name: stem.to_string_lossy().to_string(),
41 manifest_path: current_dir
42 .join("Cargo.toml")
43 .to_string_lossy()
44 .to_string(),
45 kind: TargetKind::Example,
46 extended: false,
47 origin: Some(TargetOrigin::SingleFile(path)),
48 });
49 }
50 }
51 }
52 } else if path.is_dir() {
53 let sub_manifest = path.join("Cargo.toml");
55 if sub_manifest.exists() {
56 if let Some(name) = path.file_name() {
57 targets.push(CargoTarget {
58 name: name.to_string_lossy().to_string(),
59 display_name: format!(
60 "parent{} {}",
61 parent.display(),
62 name.to_string_lossy()
63 ),
64 manifest_path: sub_manifest.to_string_lossy().to_string(),
65 kind: TargetKind::Example,
66 extended: true,
67 origin: Some(TargetOrigin::SubProject(sub_manifest)),
68 });
69 }
70 }
71 }
72 }
73 }
74
75 Ok(targets)
78}
79
80#[cfg(test)]
81mod tests {
82 use super::*;
83 use std::fs;
84 use tempfile::tempdir;
85
86 #[test]
87 fn test_discover_targets_no_manifest() {
88 let temp = tempdir().unwrap();
89 let targets = discover_targets(temp.path()).unwrap();
91 assert!(targets.is_empty());
92 }
93
94 #[test]
95 fn test_discover_targets_with_manifest_and_example() {
96 let temp = tempdir().unwrap();
97 let manifest_path = temp.path().join("Cargo.toml");
99 fs::write(&manifest_path, "[package]\nname = \"dummy\"\n").unwrap();
100
101 let examples_dir = temp.path().join("examples");
103 fs::create_dir(&examples_dir).unwrap();
104 let example_file = examples_dir.join("example1.rs");
105 fs::write(&example_file, "fn main() {}").unwrap();
106
107 let targets = discover_targets(temp.path()).unwrap();
108 assert!(targets.len() >= 2);
110
111 let example_target = targets
112 .iter()
113 .find(|t| t.kind == TargetKind::Example && t.name == "example1");
114 assert!(example_target.is_some());
115 }
116}