1use clap::{Args, Subcommand, Parser};
2use std::path::PathBuf;
3use crate::mds::migrate;
4
5#[derive(Parser, Debug)]
6pub struct MigrateArgs {
7 #[command(subcommand)]
8 pub command: MigrateCommands,
9}
10
11#[derive(Subcommand, Debug)]
12pub enum MigrateCommands {
13 File(FileArgs),
15 Dir(DirArgs),
17}
18
19#[derive(Args, Debug)]
20pub struct FileArgs {
21 #[arg(short, long)]
23 pub input: PathBuf,
24 #[arg(short, long)]
26 pub output: Option<PathBuf>,
27 #[arg(long, default_value_t = false)]
29 pub verbose: bool,
30}
31
32#[derive(Args, Debug)]
33pub struct DirArgs {
34 #[arg(short, long)]
36 pub input_dir: PathBuf,
37 #[arg(short, long)]
39 pub output_dir: Option<PathBuf>,
40 #[arg(short, long)]
42 pub extension: Option<String>,
43 #[arg(long, default_value_t = false)]
45 pub verbose: bool,
46}
47
48pub async fn run(args: MigrateArgs) -> anyhow::Result<()> {
49 match args.command {
50 MigrateCommands::File(file_args) => {
51 let migrator = migrate::Migrator::new().verbose(file_args.verbose);
52 migrator.migrate_file(&file_args.input, file_args.output.as_ref()).map_err(|e| anyhow::anyhow!("Migration failed: {}", e))?;
53 Ok(())
54 }
55 MigrateCommands::Dir(dir_args) => {
56 let migrator = migrate::Migrator::new().verbose(dir_args.verbose);
57 let input_dir = &dir_args.input_dir;
58 let output_dir = dir_args.output_dir.as_ref();
59 let ext_filter = dir_args.extension.as_deref();
60 for entry in std::fs::read_dir(input_dir)? {
61 let entry = entry?;
62 let path = entry.path();
63 if path.is_file() {
64 if let Some(ext) = ext_filter {
65 if path.extension().and_then(|e| e.to_str()) != Some(ext) {
66 continue;
67 }
68 }
69 let output_path = output_dir.map(|od| od.join(path.file_name().unwrap()));
70 migrator.migrate_file(&path, output_path.as_ref())?;
71 }
72 }
73 Ok(())
74 }
75 }
76}