cargo_lambda_system/
lib.rs1use std::{collections::HashMap, path::PathBuf};
2
3use cargo_lambda_metadata::{
4 cargo::CargoMetadata,
5 config::{
6 Config, ConfigOptions, general_config_figment, get_config_from_all_packages,
7 load_config_without_cli_flags,
8 },
9};
10use clap::Args;
11use miette::{IntoDiagnostic, Result};
12
13use cargo_lambda_build::{InstallOption, Zig, install_options, install_zig, print_install_options};
14use cargo_lambda_interactive::is_stdin_tty;
15use serde::{Deserialize, Serialize};
16use strum_macros::{Display, EnumString};
17use tracing::trace;
18
19#[derive(Clone, Debug, Default, Deserialize, Display, EnumString, Serialize)]
20#[strum(ascii_case_insensitive)]
21#[serde(rename_all = "lowercase")]
22pub enum OutputFormat {
23 #[default]
24 Text,
25 Json,
26}
27
28#[derive(Args, Clone, Debug)]
29#[command(
30 visible_alias = "config",
31 after_help = "Full command documentation: https://www.cargo-lambda.info/commands/system.html"
32)]
33pub struct System {
34 #[arg(long, visible_alias = "install-zig", alias = "install")]
36 setup: bool,
37
38 #[arg(short, long)]
40 manifest_path: Option<PathBuf>,
41
42 #[arg(short, long)]
44 output_format: Option<OutputFormat>,
45
46 #[arg(short, long)]
48 package: Option<String>,
49}
50
51impl System {
52 pub fn manifest_path(&self) -> PathBuf {
53 self.manifest_path
54 .clone()
55 .unwrap_or_else(|| "Cargo.toml".into())
56 }
57
58 pub fn package(&self) -> Option<String> {
59 self.package.clone()
60 }
61}
62
63#[derive(Debug, Default, Serialize)]
64struct ZigInfo {
65 #[serde(skip_serializing_if = "Option::is_none")]
66 path: Option<PathBuf>,
67 #[serde(skip_serializing_if = "Option::is_none")]
68 install_options: Option<Vec<InstallOption>>,
69}
70
71#[derive(Debug, Serialize)]
72struct Info {
73 zig: ZigInfo,
74 config: ConfigInfo,
75}
76
77#[derive(Debug, Serialize)]
78enum ConfigInfo {
79 #[serde(rename = "package")]
80 Package(Config),
81 #[serde(rename = "global")]
82 Global {
83 workspace: Config,
84 packages: HashMap<String, Config>,
85 },
86}
87
88#[tracing::instrument(target = "cargo_lambda")]
89pub async fn run(config: &System, metadata: &CargoMetadata, options: &ConfigOptions) -> Result<()> {
90 trace!("running config command");
91
92 if config.setup {
93 let options = install_options();
94 if is_stdin_tty() {
95 install_zig(options).await?;
96 } else {
97 print_install_options(&options);
98 }
99
100 return Ok(());
101 }
102
103 let config_info = if options.name.is_some() || metadata.packages.len() == 1 {
104 let config = load_config_without_cli_flags(metadata, options)?;
105 ConfigInfo::Package(config)
106 } else {
107 let (_, _, workspace) = general_config_figment(metadata, options)?;
108
109 let packages = get_config_from_all_packages(metadata)?;
110
111 ConfigInfo::Global {
112 workspace: workspace.extract().into_diagnostic()?,
113 packages,
114 }
115 };
116
117 let zig_info = if let Ok((path, _)) = Zig::find_zig() {
118 ZigInfo {
119 path: Some(path),
120 install_options: None,
121 }
122 } else {
123 let options = install_options();
124 ZigInfo {
125 path: None,
126 install_options: Some(options),
127 }
128 };
129
130 let info = Info {
131 zig: zig_info,
132 config: config_info,
133 };
134
135 match config.output_format {
136 Some(OutputFormat::Json) => {
137 println!("{}", serde_json::to_string(&info).into_diagnostic()?);
138 }
139 _ => {
140 let data = serde_yml::to_string(&info).unwrap();
141 bat::PrettyPrinter::new()
142 .language("yaml")
143 .input_from_bytes(data.as_bytes())
144 .colored_output(false)
145 .print()
146 .into_diagnostic()?;
147 }
148 }
149
150 Ok(())
151}