summaryrefslogtreecommitdiff
path: root/src/main.rs
blob: bb2a716a35b7105122728f03b19d75f01fe65f18 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
mod db;
mod files;
mod flac;
use anyhow::Result;
use clap::{Arg, ArgAction, Command, ValueHint, command, value_parser};
use clap_complete::{Generator, Shell, generate};
use std::path::PathBuf;

fn build_cli() -> Command {
    command!()
        .arg(
            Arg::new("path")
                .help("Path for indexing/reencoding")
                .action(ArgAction::Set)
                .value_hint(ValueHint::DirPath)
                .value_parser(value_parser!(PathBuf)),
        )
        .arg(
            Arg::new("doit")
                .long("doit")
                .help("Actually reencode files")
                .action(ArgAction::SetTrue),
        )
        .arg(
            Arg::new("clean")
                .short('c')
                .long("clean")
                .help("Clean and dedupe database")
                .action(ArgAction::SetTrue),
        )
        .arg(
            Arg::new("threads")
                .short('t')
                .long("threads")
                .help("Set number of reencoding threads")
                .action(ArgAction::Set)
                .value_hint(ValueHint::Other)
                .value_parser(value_parser!(usize))
                .default_value("4"),
        )
        .arg(
            Arg::new("db")
                .short('d')
                .long("db")
                .help("Path to databse file")
                .action(ArgAction::Set)
                .value_hint(ValueHint::FilePath)
                .value_parser(value_parser!(PathBuf)),
        )
        .arg(
            Arg::new("shell")
                .short('g')
                .long("generate")
                .help("Generate shell completions")
                .action(ArgAction::Set)
                .value_parser(value_parser!(Shell)),
        )
}

fn print_completions<G: Generator>(generator: G, cmd: &mut Command) {
    generate(
        generator,
        cmd,
        cmd.get_name().to_string(),
        &mut std::io::stdout(),
    );
}

fn main() -> Result<()> {
    let args = build_cli().get_matches();

    if let Some(generator) = args.get_one::<Shell>("shell").copied() {
        let mut cmd = build_cli();
        eprintln!("Generating completion file for {generator}...");
        print_completions(generator, &mut cmd);
        return Ok(());
    }

    let runtime = tokio::runtime::Builder::new_multi_thread()
        .max_blocking_threads(*args.get_one::<usize>("threads").unwrap())
        .enable_all()
        .build()?;
    runtime.block_on(async move {
        let conn = if let Some(path) = args.get_one::<PathBuf>("db") {
            db::Database::new(path).await?
        } else {
            db::open_default_db().await?
        };
        let path = args.get_one::<PathBuf>("path");

        if path.is_none() && !args.get_flag("clean") && !args.get_flag("doit") {
            let count = conn.get_toencode_number().await?;
            println!("Files to reencode:\t{count}");
        } else if let Some(realpath) = path {
            if !args.get_flag("doit") {
                files::index_files_recursively(realpath, &conn).await?;
            }
        }

        if args.get_flag("clean") {
            conn.clean_files().await?;
        }

        if args.get_flag("doit") {
            files::reencode_files(&conn).await?;
        }
        Ok::<(), anyhow::Error>(())
    })?;

    Ok(())
}