/ src / bin / cmd / projects.rs
projects.rs
 1  use std::path::PathBuf;
 2  
 3  use clap::Parser;
 4  use serde::Serialize;
 5  
 6  use super::{AmbientError, Config, Leaf};
 7  use ambient_ci::{
 8      project::{ProjectError, Projects},
 9      runlog::RunLog,
10  };
11  
12  #[derive(Debug, Parser)]
13  pub struct ProjectsCmd {
14      #[clap(long)]
15      oneline: bool,
16  
17      /// Name of YAML file with projects.
18      #[clap(long)]
19      projects: Option<PathBuf>,
20  }
21  
22  impl Leaf for ProjectsCmd {
23      fn run(&self, config: &Config, _runlog: &mut RunLog) -> Result<(), AmbientError> {
24          let projects = if let Some(filename) = &self.projects {
25              filename.to_path_buf()
26          } else {
27              config.projects().into()
28          };
29  
30          let projects = Projects::from_file(&projects)
31              .map_err(|err| ProjectsCmdError::FromFile(projects, err))?;
32  
33          config.lint(&projects)?;
34  
35          let mut names: Vec<String> = projects.iter().map(|(name, _)| name.to_string()).collect();
36          names.sort();
37  
38          let list = ProjectsList { projects: names };
39  
40          let json = if self.oneline {
41              serde_json::to_string(&list).map_err(ProjectsCmdError::ToJson)?
42          } else {
43              serde_json::to_string_pretty(&list).map_err(ProjectsCmdError::ToJson)?
44          };
45  
46          println!("{json}");
47  
48          Ok(())
49      }
50  }
51  
52  #[derive(Serialize)]
53  struct ProjectsList {
54      projects: Vec<String>,
55  }
56  
57  #[derive(Debug, thiserror::Error)]
58  pub enum ProjectsCmdError {
59      #[error("failed to load project list from file {0}")]
60      FromFile(PathBuf, #[source] ProjectError),
61  
62      #[error("failed to serialize project list to JSON")]
63      ToJson(#[source] serde_json::Error),
64  }