1use crate::error::MarsError;
4use crate::sync::{ResolutionMode, SyncOptions, SyncRequest};
5
6use super::output;
7
8#[derive(Debug, clap::Args)]
10pub struct SyncArgs {
11 #[arg(long)]
13 pub force: bool,
14
15 #[arg(long)]
17 pub diff: bool,
18
19 #[arg(long)]
21 pub frozen: bool,
22
23 #[arg(long, conflicts_with = "no_refresh_models")]
25 pub refresh_models: bool,
26
27 #[arg(long, conflicts_with = "refresh_models")]
29 pub no_refresh_models: bool,
30
31 #[arg(long)]
33 pub no_upgrade_hint: bool,
34
35 #[arg(long)]
37 pub verbose: bool,
38}
39
40pub fn run(args: &SyncArgs, ctx: &super::MarsContext, json: bool) -> Result<i32, MarsError> {
42 let no_upgrade_hint = args.no_upgrade_hint || no_upgrade_hint_from_env();
43 let request = SyncRequest {
44 resolution: ResolutionMode::Normal,
45 mutation: None,
46 options: SyncOptions {
47 force: args.force,
48 dry_run: args.diff,
49 frozen: args.frozen,
50 refresh_models: args.refresh_models,
51 no_refresh_models: args.no_refresh_models,
52 check_upgrades: !no_upgrade_hint,
53 },
54 recovery: Default::default(),
55 lossiness_mode: if args.verbose {
56 crate::diagnostic::LossinessMode::Verbose
57 } else {
58 crate::diagnostic::LossinessMode::Surface
59 },
60 };
61
62 let report = crate::sync::execute(ctx, &request)?;
63
64 output::print_sync_report(&report, json, no_upgrade_hint);
65
66 Ok(0)
67}
68
69fn no_upgrade_hint_from_env() -> bool {
70 match std::env::var("MARS_NO_UPGRADE_HINT") {
71 Ok(value) => value.trim() == "1",
72 Err(_) => false,
73 }
74}
75
76#[cfg(test)]
77mod tests {
78 use crate::cli::{Cli, Command};
79 use clap::Parser;
80
81 #[test]
82 fn parses_no_refresh_models() {
83 let cli = Cli::try_parse_from(["mars", "sync", "--no-refresh-models"]).unwrap();
84 let Command::Sync(args) = cli.command else {
85 panic!("expected sync command");
86 };
87 assert!(args.no_refresh_models);
88 }
89
90 #[test]
91 fn parses_refresh_models() {
92 let cli = Cli::try_parse_from(["mars", "sync", "--refresh-models"]).unwrap();
93 let Command::Sync(args) = cli.command else {
94 panic!("expected sync command");
95 };
96 assert!(args.refresh_models);
97 }
98
99 #[test]
100 fn refresh_and_no_refresh_conflict() {
101 assert!(
102 Cli::try_parse_from(["mars", "sync", "--refresh-models", "--no-refresh-models"])
103 .is_err()
104 );
105 }
106
107 #[test]
108 fn parses_no_upgrade_hint() {
109 let cli = Cli::try_parse_from(["mars", "sync", "--no-upgrade-hint"]).unwrap();
110 let Command::Sync(args) = cli.command else {
111 panic!("expected sync command");
112 };
113 assert!(args.no_upgrade_hint);
114 }
115
116 #[test]
117 fn parses_verbose() {
118 let cli = Cli::try_parse_from(["mars", "sync", "--verbose"]).unwrap();
119 let Command::Sync(args) = cli.command else {
120 panic!("expected sync command");
121 };
122 assert!(args.verbose);
123 }
124}