1use crate::{
7 e_collect::collect_all_targets, e_processmanager::ProcessManager, e_target::CargoTarget, Cli,
8};
9#[cfg(feature = "uses_plugins")]
11use crate::plugins::plugin_api::load_plugins;
12use anyhow::{anyhow, Result};
13#[cfg(feature = "uses_plugins")]
14use once_cell::sync::OnceCell;
15use std::{collections::HashSet, path::PathBuf, sync::Arc};
16
17pub struct ExtContext {
19 pub cli: Cli,
21 pub manager: Arc<ProcessManager>,
23 pub cwd: PathBuf,
25 #[cfg(feature = "uses_plugins")]
27 plugins: OnceCell<Vec<Box<dyn crate::plugins::plugin_api::Plugin>>>,
28}
29
30impl ExtContext {
31 pub fn new(cli: Cli, manager: Arc<ProcessManager>) -> Result<Self> {
35 let cwd = std::env::current_dir()?;
36 Ok(ExtContext {
37 cli,
38 manager,
39 cwd,
40 #[cfg(feature = "uses_plugins")]
41 plugins: OnceCell::new(),
42 })
43 }
44
45 pub fn collect_targets(&self) -> Result<Vec<CargoTarget>> {
48 let threads = std::thread::available_parallelism()
50 .map(|n| n.get())
51 .unwrap_or(4);
52 let mut all = collect_all_targets(
53 self.cli.manifest_path.clone(),
54 self.cli.workspace,
55 threads,
56 self.cli.json_all_targets,
57 false,
58 )
59 .map_err(|e| anyhow!("collect_all_targets failed: {}", e))?;
60 #[cfg(feature = "uses_plugins")]
62 {
63 use crate::e_target::TargetKind;
64 use crate::e_target::TargetOrigin;
65 let plugins = self
66 .plugins
67 .get_or_try_init(|| load_plugins(&self.cli, self.manager.clone()))?;
68 for plugin in plugins.iter() {
69 if plugin.matches(&self.cwd) {
70 let plugin_path = plugin
71 .source()
72 .map(PathBuf::from)
73 .unwrap_or_else(|| self.cwd.clone());
74 for pt in plugin.collect_targets(&self.cwd)? {
75 let ct = if let Some(ct) = pt.cargo_target {
76 ct
77 } else {
78 let reported = pt
79 .metadata
80 .as_ref()
81 .map(PathBuf::from)
82 .unwrap_or_else(|| self.cwd.clone());
83 CargoTarget {
84 name: pt.name.clone(),
85 display_name: pt.name.clone(),
86 manifest_path: self.cwd.clone(),
87 kind: TargetKind::Plugin,
88 extended: false,
89 toml_specified: false,
90 origin: Some(TargetOrigin::Plugin {
91 plugin_path: plugin_path.clone(),
92 reported,
93 }),
94 }
95 };
96 all.push(ct);
97 }
98 }
99 }
100 }
101 let mut seen = HashSet::new();
103 all.retain(|t| seen.insert((t.name.clone(), t.kind, t.extended)));
104 Ok(all)
105 }
106 pub fn run_target(&self, target: &CargoTarget) -> Result<Option<std::process::ExitStatus>> {
109 #[cfg(feature = "uses_plugins")]
111 {
112 #[allow(unused_imports)]
113 use crate::e_target::{TargetKind, TargetOrigin};
114 if target.kind == TargetKind::Plugin {
115 let plugins = self
117 .plugins
118 .get_or_try_init(|| load_plugins(&self.cli, self.manager.clone()))?;
119 for plugin in plugins.iter() {
120 if let Some(crate::e_target::TargetOrigin::Plugin { plugin_path, .. }) =
121 &target.origin
122 {
123 if plugin.source().map(PathBuf::from) == Some(plugin_path.clone()) {
124 let _plugin_target =
126 crate::plugins::plugin_api::Target::from(target.clone());
127 plugin.run_with_manager(self.manager.clone(), &self.cli, target)?;
129 return Ok(None);
130 }
131 }
132 }
133 return Ok(None);
134 }
135 }
136 crate::e_runner::run_example(self.manager.clone(), &self.cli, target)
138 }
139}