1use std::{
2 fs,
3 path::{Path, PathBuf},
4 process::{Command, Output, Stdio},
5};
6
7use anyhow::Result;
8use tracing::{info, instrument, warn};
9
10use crate::project::subcommand::OutputFormat;
11
12#[instrument(err)]
13pub fn wrap_command(command: &mut Command) -> Result<Output> {
14 let output = command
15 .stdout(Stdio::piped())
16 .stderr(Stdio::piped())
17 .spawn()?
18 .wait_with_output()?;
19
20 if output.status.success() && !output.stdout.is_empty() {
22 info!("{}", String::from_utf8_lossy(&output.stdout).trim());
23 } else if !output.stderr.is_empty() {
24 warn!("{}", String::from_utf8_lossy(&output.stderr).trim());
25 }
26
27 Ok(output)
28}
29
30#[instrument(err)]
31pub fn get_directories(path: &Path) -> Result<Vec<PathBuf>> {
32 Ok(fs::read_dir(path)?
33 .filter_map(|dir| match dir {
34 Ok(dir) => match dir.file_type() {
35 Ok(ft) => {
36 if ft.is_dir() {
37 Some(dir.path())
38 } else {
39 None
40 }
41 }
42 Err(err) => {
43 eprintln!("An error occurred, skipping entry: {err}");
44 None
45 }
46 },
47 Err(err) => {
48 eprintln!("An error occurred, skipping entry: {err}");
49 None
50 }
51 })
52 .collect())
53}
54
55pub fn formatted_print<T>(output: &OutputFormat, value: T) -> Result<()>
56where
57 T: std::fmt::Debug + serde::Serialize,
58{
59 match output {
60 OutputFormat::Debug => {
61 println!("{:#?}", value);
62 }
63 OutputFormat::Json => {
64 println!("{}", serde_json::to_string_pretty(&value)?)
65 }
66 OutputFormat::Yaml => println!("{}", serde_yaml::to_string(&value)?),
67 OutputFormat::JsonR => {
68 println!("{}", serde_json::to_string(&value)?)
69 }
70 }
71 Ok(())
72}