1use crate::core::config::LockFile;
2use crate::error::{Error, Result};
3use crate::storage::XdgPaths;
4use std::path::Path;
5
6#[derive(Debug, clap::Args)]
7pub struct CheckCommand;
8
9impl CheckCommand {
10 pub fn run(&self) -> Result<()> {
11 let mai_lock = Path::new("mai.lock");
12 if !mai_lock.exists() {
13 return Err(Error::project_error(
14 "mai.lock not found. Run 'mai sync' first.",
15 ));
16 }
17
18 let lock_file = LockFile::load(mai_lock)?;
19 let paths = XdgPaths::new();
20 let report = lock_file.verify_integrity(paths.data_dir());
21
22 println!("Lock file integrity check:");
23 println!(" {}", report.summary());
24
25 if !report.is_valid() {
26 if !report.missing.is_empty() {
27 println!("\nMissing packs:");
28 for dep in &report.missing {
29 println!(
30 " - {}/{}@{}",
31 dep.tool.as_deref().unwrap_or("*"),
32 dep.name,
33 dep.version
34 );
35 }
36 }
37
38 if !report.hash_mismatch.is_empty() {
39 println!("\nHash mismatches (content modified):");
40 for dep in &report.hash_mismatch {
41 println!(
42 " - {}/{}@{}",
43 dep.tool.as_deref().unwrap_or("*"),
44 dep.name,
45 dep.version
46 );
47 }
48 }
49
50 if !report.unreadable.is_empty() {
51 println!("\nUnreadable packs:");
52 for dep in &report.unreadable {
53 println!(
54 " - {}/{}@{}",
55 dep.tool.as_deref().unwrap_or("*"),
56 dep.name,
57 dep.version
58 );
59 }
60 }
61
62 return Err(Error::project_error("Lock file integrity check failed"));
63 }
64
65 println!(
66 "\n✓ All {} packs verified successfully",
67 report.verified.len()
68 );
69 Ok(())
70 }
71}