Skip to main content

mars_agents/cli/
sync.rs

1//! `mars sync` — resolve + install (make reality match config).
2
3use crate::error::MarsError;
4use crate::sync::{ResolutionMode, SyncOptions, SyncRequest};
5
6use super::output;
7
8/// Arguments for `mars sync`.
9#[derive(Debug, clap::Args)]
10pub struct SyncArgs {
11    /// Overwrite local modifications for managed files.
12    #[arg(long)]
13    pub force: bool,
14
15    /// Dry run — show what would change.
16    #[arg(long)]
17    pub diff: bool,
18
19    /// Install exactly from lock file, error if stale.
20    #[arg(long)]
21    pub frozen: bool,
22
23    /// Skip the automatic models-cache refresh during sync.
24    #[arg(long)]
25    pub no_refresh_models: bool,
26
27    /// Suppress the post-sync upgrade hint line.
28    #[arg(long)]
29    pub no_upgrade_hint: bool,
30}
31
32/// Run `mars sync`.
33pub fn run(args: &SyncArgs, ctx: &super::MarsContext, json: bool) -> Result<i32, MarsError> {
34    let request = SyncRequest {
35        resolution: ResolutionMode::Normal,
36        mutation: None,
37        options: SyncOptions {
38            force: args.force,
39            dry_run: args.diff,
40            frozen: args.frozen,
41            no_refresh_models: args.no_refresh_models,
42        },
43    };
44
45    let report = crate::sync::execute(ctx, &request)?;
46
47    let no_upgrade_hint = args.no_upgrade_hint || no_upgrade_hint_from_env();
48    output::print_sync_report(&report, json, no_upgrade_hint);
49
50    if report.has_conflicts() { Ok(1) } else { Ok(0) }
51}
52
53fn no_upgrade_hint_from_env() -> bool {
54    match std::env::var("MARS_NO_UPGRADE_HINT") {
55        Ok(value) => value.trim() == "1",
56        Err(_) => false,
57    }
58}
59
60#[cfg(test)]
61mod tests {
62    use crate::cli::{Cli, Command};
63    use clap::Parser;
64
65    #[test]
66    fn parses_no_refresh_models() {
67        let cli = Cli::try_parse_from(["mars", "sync", "--no-refresh-models"]).unwrap();
68        let Command::Sync(args) = cli.command else {
69            panic!("expected sync command");
70        };
71        assert!(args.no_refresh_models);
72    }
73
74    #[test]
75    fn parses_no_upgrade_hint() {
76        let cli = Cli::try_parse_from(["mars", "sync", "--no-upgrade-hint"]).unwrap();
77        let Command::Sync(args) = cli.command else {
78            panic!("expected sync command");
79        };
80        assert!(args.no_upgrade_hint);
81    }
82}