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}