agentstatedeveloper_cli/commands/
sync.rs1use std::path::{Path, PathBuf};
11
12use anyhow::Result;
13use clap::Args;
14use serde_json::json;
15
16use agentstatedeveloper_core::{Engine, ledger_counts, prune_sidecar, sync_to_dir};
17
18use crate::config::Config;
19
20#[derive(Debug, Args)]
21pub struct SyncArgs {
22 #[arg(long)]
26 pub dir: Option<PathBuf>,
27
28 #[arg(long, default_value_t = false)]
31 pub prune: bool,
32}
33
34pub fn run(cfg: &Config, args: SyncArgs) -> Result<()> {
35 let engine = Engine::open_sqlite(&cfg.db_path)?;
36 let dir = resolve_dir(args.dir, &cfg.db_path)?;
37
38 let mut summary = sync_to_dir(&engine.repo, &engine.ref_name, &dir)?;
39
40 if args.prune {
41 summary.pruned = prune_sidecar(&engine.repo, &engine.ref_name, &dir)?;
42 }
43
44 let ledger = ledger_counts(
48 &engine.repo,
49 &engine.ref_name,
50 engine.fts.as_ref(),
51 Some(&dir),
52 )?;
53 let ledger_warning = ledger.warning();
54 if let Some(w) = &ledger_warning {
55 eprintln!("asd sync: warning: {w}");
56 }
57
58 let out = json!({
59 "db": cfg.db_path.display().to_string(),
60 "dir": dir.join(".asd/v1").display().to_string(),
61 "effects_written": summary.effects_written,
62 "ledger_entries_written": summary.ledger_entries_written,
63 "symbols_written": summary.symbols_written,
64 "schema_version": summary.schema_version,
65 "pruned": summary.pruned,
66 "moved_entries_removed": summary.moved_entries_removed,
67 "ledger": ledger,
68 "ledger_warning": ledger_warning,
69 "note": "current-state only; ASG commit history is not carried in the sidecar",
70 });
71 println!("{}", serde_json::to_string_pretty(&out)?);
72 Ok(())
73}
74
75fn resolve_dir(explicit: Option<PathBuf>, db_path: &Path) -> Result<PathBuf> {
80 if let Some(p) = explicit {
81 return Ok(p);
82 }
83 let cwd = std::env::current_dir()?;
84 Ok(match db_path.parent() {
85 Some(p) if !p.as_os_str().is_empty() => cwd.join(p),
86 _ => cwd,
87 })
88}