blkar_lib/
cli_update.rs

1use crate::cli_utils::*;
2use crate::json_printer::BracketType;
3use crate::multihash;
4use crate::sbx_block::Metadata;
5use crate::sbx_block::MetadataID;
6use crate::update_core;
7use crate::update_core::Param;
8use clap::*;
9
10pub fn sub_command<'a, 'b>() -> App<'a, 'b> {
11    SubCommand::with_name("update")
12        .about("Update SBX container metadata")
13        .arg(in_file_arg().help("SBX container to update"))
14        .arg(pr_verbosity_level_arg())
15        .arg(burst_arg().help(
16            "Burst error resistance level used by the container.
17Use this if the level used by the container is above 1000,
18as blkar will only guess up to 1000. Or use this when blkar
19fails to guess correctly.",
20        ))
21        .arg(
22            verbose_arg()
23                .help("Show reference block info, and changes made in each metadata block"),
24        )
25        .arg(
26            Arg::with_name("skip_warning")
27                .short("y")
28                .long("skip-warning")
29                .help("Skip warning about in-place updates"),
30        )
31        .arg(dry_run_arg().help("Only do updates in memory. The container will not be modified."))
32        .arg(json_arg().help(
33            "Output information in JSON format. Note that blkar does not
34guarantee the JSON data to be well-formed if blkar is interrupted.
35This also implies --skip-warning, and changes progress report text
36(if any) to be in JSON.",
37        ))
38        .arg(
39            Arg::with_name("fnm")
40                .value_name("NAME")
41                .takes_value(true)
42                .long("fnm")
43                .help("New file name"),
44        )
45        .arg(
46            Arg::with_name("snm")
47                .value_name("NAME")
48                .takes_value(true)
49                .long("snm")
50                .help("New SBX container name"),
51        )
52        .arg(
53            Arg::with_name("no_fnm")
54                .long("no-fnm")
55                .help("Remove file name")
56                .conflicts_with("fnm"),
57        )
58        .arg(
59            Arg::with_name("no_snm")
60                .long("no-snm")
61                .help("Remove SBX container name")
62                .conflicts_with("snm"),
63        )
64        .arg(
65            Arg::with_name("hash_type")
66                .long("hash")
67                .value_name("HASH-TYPE")
68                .help(
69                    "Rehash the stored data with HASH-TYPE hash function. If HSH
70field already exists, then it is replaced with the new hash
71result. Otherwise a HSH field is added for the new hash result.
72HASH-TYPE may be one of (case-insensitive) :
73sha1
74sha256
75sha512
76blake2b-256
77blake2b-512
78blake2s-128
79blake2s-256",
80                ),
81        )
82        .arg(
83            Arg::with_name("no_hsh")
84                .long("no-hsh")
85                .help("Remove SBX container stored data hash")
86                .conflicts_with("hash_type"),
87        )
88}
89
90pub fn update<'a>(matches: &ArgMatches<'a>) -> i32 {
91    let json_printer = get_json_printer!(matches);
92
93    json_printer.print_open_bracket(None, BracketType::Curly);
94
95    let in_file = get_in_file!(matches, json_printer);
96
97    let pr_verbosity_level = get_pr_verbosity_level!(matches, json_printer);
98
99    let burst = get_burst_opt!(matches, json_printer);
100
101    let hash_type = match matches.value_of("hash_type") {
102        None => None,
103        Some(x) => match multihash::string_to_hash_type(x) {
104            Ok(x) => Some(x),
105            Err(_) => exit_with_msg!(usr json_printer => "Invalid hash type"),
106        },
107    };
108
109    let metas_to_update = {
110        let mut res = smallvec![];
111
112        if let Some(x) = matches.value_of("fnm") {
113            res.push(Metadata::FNM(x.to_string()))
114        }
115        if let Some(x) = matches.value_of("snm") {
116            res.push(Metadata::SNM(x.to_string()))
117        }
118        if let Some(_) = matches.value_of("hash_type") {
119            let hash_type = hash_type.unwrap();
120            let dummy_hash = multihash::hash::Ctx::new(hash_type)
121                .unwrap()
122                .finish_into_bytes();
123            res.push(Metadata::HSH((hash_type, dummy_hash)))
124        }
125
126        res
127    };
128
129    let metas_to_remove = {
130        let mut res = smallvec![];
131
132        if matches.is_present("no_fnm") {
133            res.push(MetadataID::FNM)
134        }
135        if matches.is_present("no_snm") {
136            res.push(MetadataID::SNM)
137        }
138        if matches.is_present("no_hsh") {
139            res.push(MetadataID::HSH)
140        }
141
142        res
143    };
144
145    if matches.is_present("dry_run") && !json_printer.json_enabled() {
146        print_block!(
147            "Note : This is a dry run only, the container is not modified.";
148            "";
149        );
150    }
151
152    if !matches.is_present("skip_warning")
153        && !matches.is_present("dry_run")
154        && !json_printer.json_enabled()
155    {
156        print_block!(
157            "Warning :";
158            "";
159            "    Update mode modifies the SBX container in-place.";
160            "";
161            "    This may cause irreversible damage to the container and prohibit normal";
162            "    functioning, depending on your workflow.";
163            "";
164            "    It is advisable to do a dry run first via supplying the --dry-run flag";
165            "    and examine the changes before actually updating the container.";
166            "";
167        );
168
169        ask_if_wish_to_continue!();
170    }
171
172    let mut param = Param::new(
173        in_file,
174        matches.is_present("dry_run"),
175        metas_to_update,
176        metas_to_remove,
177        &json_printer,
178        hash_type,
179        matches.is_present("verbose"),
180        pr_verbosity_level,
181        burst,
182    );
183    match update_core::update_file(&mut param) {
184        Ok(Some(s)) => exit_with_msg!(ok json_printer => "{}", s),
185        Ok(None) => exit_with_msg!(ok json_printer => ""),
186        Err(e) => exit_with_msg!(op json_printer => "{}", e),
187    }
188}