Skip to main content

light_fw_cli_core/
cargo.rs

1//! Обёртка над подкомандами `cargo`.
2//!
3//! Здесь формируются векторы аргументов (чтобы их можно было проверять в
4//! тестах без запуска процесса) и выполняются вызовы `cargo add` / `cargo
5//! remove` / `cargo check` через [`CommandRunner`].
6
7use std::path::Path;
8
9use crate::error::{Error, Result};
10use crate::process::CommandRunner;
11
12/// Аргументы `cargo add`.
13///
14/// Для workspace-члена передаётся `path` (тогда используется `--path`), иначе
15/// `name@version` при наличии версии.
16pub fn add_args(
17    name: &str,
18    version: Option<&str>,
19    path: Option<&Path>,
20    optional: bool,
21    features: &[String],
22) -> Vec<String> {
23    let mut args = vec!["add".to_string()];
24    if let Some(p) = path {
25        args.push(name.to_string());
26        args.push("--path".to_string());
27        args.push(p.display().to_string());
28    } else if let Some(v) = version {
29        args.push(format!("{name}@{v}"));
30    } else {
31        args.push(name.to_string());
32    }
33    if optional {
34        args.push("--optional".to_string());
35    }
36    if !features.is_empty() {
37        args.push("--features".to_string());
38        args.push(features.join(","));
39    }
40    args
41}
42
43/// Аргументы `cargo remove`.
44pub fn remove_args(name: &str) -> Vec<String> {
45    vec!["remove".to_string(), name.to_string()]
46}
47
48/// Аргументы `cargo check`.
49pub fn check_args() -> Vec<String> {
50    vec!["check".to_string(), "--quiet".to_string()]
51}
52
53/// Запускает `cargo add` и проверяет код возврата.
54pub fn run_add(
55    runner: &dyn CommandRunner,
56    cwd: &Path,
57    name: &str,
58    version: Option<&str>,
59    path: Option<&Path>,
60    optional: bool,
61    features: &[String],
62) -> Result<()> {
63    run_cargo(
64        runner,
65        cwd,
66        &add_args(name, version, path, optional, features),
67    )
68}
69
70/// Запускает `cargo remove` и проверяет код возврата.
71pub fn run_remove(runner: &dyn CommandRunner, cwd: &Path, name: &str) -> Result<()> {
72    run_cargo(runner, cwd, &remove_args(name))
73}
74
75/// Запускает `cargo check` в каталоге проекта.
76pub fn run_check(runner: &dyn CommandRunner, cwd: &Path, no_verify: bool) -> Result<()> {
77    if no_verify {
78        return Ok(());
79    }
80    run_cargo(runner, cwd, &check_args())
81}
82
83fn run_cargo(runner: &dyn CommandRunner, cwd: &Path, args: &[String]) -> Result<()> {
84    let output = runner.run("cargo", args, Some(cwd))?;
85    if !output.success() {
86        return Err(Error::CommandFailed {
87            program: format!("cargo {}", args.first().map(String::as_str).unwrap_or("")),
88            code: output.status,
89            stderr: output.stderr.trim().to_string(),
90        });
91    }
92    Ok(())
93}
94
95#[cfg(test)]
96mod tests {
97    use super::*;
98    use std::path::PathBuf;
99
100    #[test]
101    fn add_args_with_version() {
102        assert_eq!(
103            add_args("light-fw-element-form", Some("0.1.2"), None, true, &[]),
104            vec!["add", "light-fw-element-form@0.1.2", "--optional"]
105        );
106    }
107
108    #[test]
109    fn add_args_with_path() {
110        let path = PathBuf::from("crates/light-element-form");
111        assert_eq!(
112            add_args(
113                "light-fw-element-form",
114                None,
115                Some(path.as_path()),
116                true,
117                &[]
118            ),
119            vec![
120                "add",
121                "light-fw-element-form",
122                "--path",
123                "crates/light-element-form",
124                "--optional"
125            ]
126        );
127    }
128
129    #[test]
130    fn add_args_without_version() {
131        assert_eq!(
132            add_args("light-widget-datepicker", None, None, false, &[]),
133            vec!["add", "light-widget-datepicker"]
134        );
135    }
136
137    #[test]
138    fn add_args_with_features() {
139        let features = vec!["derive".to_string(), "serde".to_string()];
140        assert_eq!(
141            add_args("serde", Some("1.0"), None, false, &features),
142            vec!["add", "serde@1.0", "--features", "derive,serde"]
143        );
144    }
145
146    #[test]
147    fn remove_args_shape() {
148        assert_eq!(
149            remove_args("light-fw-element-form"),
150            vec!["remove", "light-fw-element-form"]
151        );
152    }
153}