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
/// A simple file-based deduplication tool using CoW semantics (reflink)
#[derive(clap::Parser, Debug)]
#[command(author, version, about)]
pub struct CliConfig {
    #[command(subcommand)]
    pub command: Subcommands,
}

#[derive(clap::Subcommand, Debug)]
pub enum Subcommands {
    /// List duplicated files
    #[command(alias = "g")]
    Group(GroupArgs),
    /// Do file deduplication
    #[command(alias = "d")]
    Dedupe(DedupeArgs),
}

#[derive(clap::Args, Debug, Clone)]
pub struct GroupArgs {
    /// Print the whole hash of each file. Otherwise it will print the only first 20 bytes.
    #[arg(long, default_value = "false")]
    pub full_hash: bool,
    /// Output format
    #[arg(short = 'f', long, default_value = "default")]
    pub output_format: OutputFormat,
    #[command(flatten)]
    pub common: CommonArgs,
}

#[derive(clap::Args, Debug)]
pub struct DedupeArgs {
    /// Don't do anything; just print the size of duplicated files
    #[arg(short, long)]
    pub dry_run: bool,
    #[arg(long, default_value = "yes")]
    pub use_cp_cmd: YesNoChoice,
    #[command(flatten)]
    pub common: CommonArgs,
}

#[derive(clap::Args, Debug, Clone)]
pub struct CommonArgs {
    /// Minimum size filter
    #[arg(short, long, default_value = "1B")]
    pub min_size: String,
    /// Paths
    #[arg(required = true)]
    pub path: Vec<String>,
    /// Hashing algorithm to be used
    #[arg(long, default_value = "b3-512")]
    pub hash_fn: HashFn,
    /// JSON or binary input file
    #[arg(short, long)]
    pub input_file: Option<String>,
}

#[derive(clap::ValueEnum, Debug, Clone, Copy)]
pub enum HashFn {
    B3_128,
    B3_160,
    B3_256,
    B3_512,
    B3_1024,
    B3_2048,
    Sha256,
    Sha512,
    Sha3_256,
    Sha3_512,
}

#[derive(clap::ValueEnum, Debug, Clone, Copy)]
pub enum OutputFormat {
    Default,
    Json,
    Binary,
}

#[derive(clap::ValueEnum, Debug, Clone, Copy, PartialEq, Eq)]
pub enum YesNoChoice {
    Yes,
    No,
}

impl YesNoChoice {
    #[inline]
    pub fn yes(&self) -> bool {
        *self == Self::Yes
    }

    #[inline]
    pub fn no(&self) -> bool {
        !self.yes()
    }
}