aconfig: add create storage command

Add a new aconfig command called create-storage which takes a number
of aconfig cache files that belong to a specific container and produces
storage files.

Add a new module called storage (src/storage/mod.rs) as the entry point
of storage files generation. FlagPackage struct is defined as an
intermediate data structure that will be used to drive all storage files creation.

Add a unit test to lock down FlagPackage creation behaviors.

Bug: b/312243587
Test: atest aconfig.test

Change-Id: Ia7e9f68237ea903f295ac7891c923f6a39f3422d
diff --git a/tools/aconfig/src/main.rs b/tools/aconfig/src/main.rs
index 6872809..63a50c8 100644
--- a/tools/aconfig/src/main.rs
+++ b/tools/aconfig/src/main.rs
@@ -27,6 +27,7 @@
 mod codegen;
 mod commands;
 mod protos;
+mod storage;
 
 #[cfg(test)]
 mod test;
@@ -108,6 +109,17 @@
                 .arg(Arg::new("dedup").long("dedup").num_args(0).action(ArgAction::SetTrue))
                 .arg(Arg::new("out").long("out").default_value("-")),
         )
+        .subcommand(
+            Command::new("create-storage")
+                .arg(
+                    Arg::new("container")
+                        .long("container")
+                        .required(true)
+                        .help("The target container for the generated storage file."),
+                )
+                .arg(Arg::new("cache").long("cache").required(true))
+                .arg(Arg::new("out").long("out").required(true)),
+        )
 }
 
 fn get_required_arg<'a, T>(matches: &'a ArgMatches, arg_name: &str) -> Result<&'a T>
@@ -242,6 +254,16 @@
             let path = get_required_arg::<String>(sub_matches, "out")?;
             write_output_to_file_or_stdout(path, &output)?;
         }
+        Some(("create-storage", sub_matches)) => {
+            let cache = open_zero_or_more_files(sub_matches, "cache")?;
+            let container = get_required_arg::<String>(sub_matches, "container")?;
+            let dir = PathBuf::from(get_required_arg::<String>(sub_matches, "out")?);
+            let generated_files = commands::create_storage(cache, container)
+                .context("failed to create storage files")?;
+            generated_files
+                .iter()
+                .try_for_each(|file| write_output_file_realtive_to_dir(&dir, file))?;
+        }
         _ => unreachable!(),
     }
     Ok(())