1 /*
2 * Copyright (C) 2024 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 //! `aconfig-storage` is a debugging tool to parse storage files
18
19 use aconfig_storage_file::{
20 list_flags, list_flags_with_info, read_file_to_bytes, AconfigStorageError, FlagInfoList,
21 FlagTable, FlagValueList, PackageTable, StorageFileType,
22 };
23
24 use clap::{builder::ArgAction, Arg, Command};
25
cli() -> Command26 fn cli() -> Command {
27 Command::new("aconfig-storage")
28 .subcommand_required(true)
29 .subcommand(
30 Command::new("print")
31 .arg(Arg::new("file").long("file").required(true).action(ArgAction::Set))
32 .arg(
33 Arg::new("type")
34 .long("type")
35 .required(true)
36 .value_parser(|s: &str| StorageFileType::try_from(s)),
37 ),
38 )
39 .subcommand(
40 Command::new("list")
41 .arg(
42 Arg::new("package-map")
43 .long("package-map")
44 .required(true)
45 .action(ArgAction::Set),
46 )
47 .arg(Arg::new("flag-map").long("flag-map").required(true).action(ArgAction::Set))
48 .arg(Arg::new("flag-val").long("flag-val").required(true).action(ArgAction::Set))
49 .arg(
50 Arg::new("flag-info").long("flag-info").required(false).action(ArgAction::Set),
51 ),
52 )
53 }
54
print_storage_file( file_path: &str, file_type: &StorageFileType, ) -> Result<(), AconfigStorageError>55 fn print_storage_file(
56 file_path: &str,
57 file_type: &StorageFileType,
58 ) -> Result<(), AconfigStorageError> {
59 let bytes = read_file_to_bytes(file_path)?;
60 match file_type {
61 StorageFileType::PackageMap => {
62 let package_table = PackageTable::from_bytes(&bytes)?;
63 println!("{:?}", package_table);
64 }
65 StorageFileType::FlagMap => {
66 let flag_table = FlagTable::from_bytes(&bytes)?;
67 println!("{:?}", flag_table);
68 }
69 StorageFileType::FlagVal => {
70 let flag_value = FlagValueList::from_bytes(&bytes)?;
71 println!("{:?}", flag_value);
72 }
73 StorageFileType::FlagInfo => {
74 let flag_info = FlagInfoList::from_bytes(&bytes)?;
75 println!("{:?}", flag_info);
76 }
77 }
78 Ok(())
79 }
80
main() -> Result<(), AconfigStorageError>81 fn main() -> Result<(), AconfigStorageError> {
82 let matches = cli().get_matches();
83 match matches.subcommand() {
84 Some(("print", sub_matches)) => {
85 let file_path = sub_matches.get_one::<String>("file").unwrap();
86 let file_type = sub_matches.get_one::<StorageFileType>("type").unwrap();
87 print_storage_file(file_path, file_type)?
88 }
89 Some(("list", sub_matches)) => {
90 let package_map = sub_matches.get_one::<String>("package-map").unwrap();
91 let flag_map = sub_matches.get_one::<String>("flag-map").unwrap();
92 let flag_val = sub_matches.get_one::<String>("flag-val").unwrap();
93 let flag_info = sub_matches.get_one::<String>("flag-info");
94 match flag_info {
95 Some(info_file) => {
96 let flags = list_flags_with_info(package_map, flag_map, flag_val, info_file)?;
97 for flag in flags.iter() {
98 println!(
99 "{} {} {} {:?} IsReadWrite: {}, HasServerOverride: {}, HasLocalOverride: {}",
100 flag.package_name, flag.flag_name, flag.flag_value, flag.value_type,
101 flag.is_readwrite, flag.has_server_override, flag.has_local_override,
102 );
103 }
104 }
105 None => {
106 let flags = list_flags(package_map, flag_map, flag_val)?;
107 for flag in flags.iter() {
108 println!(
109 "{} {} {} {:?}",
110 flag.package_name, flag.flag_name, flag.flag_value, flag.value_type,
111 );
112 }
113 }
114 }
115 }
116 _ => unreachable!(),
117 }
118 Ok(())
119 }
120