sweet_cli/commands/
cmd_cargo.rs

1use anyhow::Result;
2use beet_utils::prelude::*;
3use clap::Parser;
4
5#[derive(Debug, Parser)]
6#[command(name = "test")]
7pub struct CargoTest {
8	#[command(flatten)]
9	cargo_runner: CargoCmdExtra,
10}
11impl CargoTest {
12	pub async fn run(mut self) -> Result<()> {
13		self.cargo_runner.build_cmd.cmd = "test".to_string();
14		self.cargo_runner.run().await?;
15		Ok(())
16	}
17}
18
19#[derive(Debug, Parser)]
20#[command(name = "run")]
21pub struct CargoRun {
22	#[command(flatten)]
23	cargo_runner: CargoCmdExtra,
24}
25impl CargoRun {
26	pub async fn run(mut self) -> Result<()> {
27		self.cargo_runner.build_cmd.cmd = "run".to_string();
28		self.cargo_runner.run().await?;
29		Ok(())
30	}
31}
32
33
34/// A cargo command with extra functionality like watch
35#[derive(Debug, Parser)]
36pub struct CargoCmdExtra {
37	/// the file passed in by cargo test.
38	///
39	/// It will look something like $CARGO_TARGET_DIR/wasm32-unknown-unknown/debug/deps/hello_test-c3298911e67ad05b.wasm
40	#[command(flatten)]
41	pub build_cmd: CargoBuildCmd,
42	#[arg(short, long)]
43	pub watch: bool,
44	#[arg(short, long)]
45	pub no_default_filters: bool,
46	#[command(flatten)]
47	pub filter: GlobFilter,
48}
49
50
51impl CargoCmdExtra {
52	pub async fn run(mut self) -> Result<()> {
53		self.append_args();
54		self.run_binary()?;
55		if self.watch {
56			self.watch().await?;
57		}
58		Ok(())
59	}
60
61	fn append_args(&mut self) {
62		if self.no_default_filters == false {
63			self.filter
64				.include("**/*.rs")
65				.exclude("{.git,target,html}/**")
66				.exclude("*/codegen/*");
67		}
68		let is_upstream = self
69			.build_cmd
70			.package
71			.as_ref()
72			// these crates are upstream of sweet test so do not support the watch command
73			.map(|p| ["beet_utils"].contains(&p.as_str()))
74			.unwrap_or(false);
75		if self.watch && self.build_cmd.lib && !is_upstream {
76			// watching
77			self.build_cmd.trailing_args.push("--watch".to_string());
78		}
79	}
80	// 	--include '**/*.rs' \
81	// --exclude '{.git,target,html}/**' \
82	// --exclude '*/codegen/*' \
83
84	async fn watch(self) -> Result<()> {
85		let mut rx = FsWatcher {
86			filter: self.filter.clone(),
87			..Default::default()
88		}
89		.watch()?;
90
91		while let Some(ev) = rx.recv().await? {
92			if !ev.has_mutate() {
93				continue;
94			}
95			self.run_binary()?;
96		}
97
98		Ok(())
99	}
100
101	/// run the binary:
102	/// ## Errors
103	/// Errors if not in watch mode and the command fails
104	fn run_binary(&self) -> Result<()> {
105		if self.watch {
106			terminal::clear()?;
107			println!("\n🤘 sweet as 🤘\n");
108		}
109		let result = self.build_cmd.spawn();
110		// we only propagate command errors if not in watch mode,
111		// otherwise assume its been logged to the terminal
112		if !self.watch {
113			result?;
114		}
115		Ok(())
116	}
117}