Restructure aconfig repo to be a cargo workspace with many crates
This is cherry pick of aosp/2924191 to avoid merge conflict in git main Previously, aconfig repo is the root directory of aconfig binary crate, but it also hosts printflags crate inside, and there is no cargo support for printflags binary crate. In addition, with more aconfig development, more crates are being added to this repo. Thus this repo should be configured as a Cargo workspace with multiple crates rather than a single crate. Note the top level Cargo.toml file specifies the crates this workspace carries: (1) aconfig_protos: the proto library crate that will be used by many other crates such as aconfig binary crate and printflags binary crate (2) aconfig: the aconfig binary crate (3) printflags: the printflags binary crate (1) aconfig_protos crate setup: Inside aconfig_protos dir we set up the aconfig_protos crate, the previously src/proto.rs is now aconfig_protos/src/lib.rs, the build.rs is carried over to this crate. (2) aconfig binary crate setup: Notice its Cargo.toml file claims package dependency on aconfig_protos crate. It no longer carries proto related module and build.rs file. (3) printflags binary crate setup: Similary, notice that in its Cargo.toml file, it claims package dependency on aconfig_protos crate. With this setup, we can Cargo build/test each crate individually when inside a specific crate dir. But we can also run Cargo build/test at repo root level, which will build/test all the crates in this workplace. This is the structuring cl. The next cl is to move storage modules into its own library crate. This storage file library crate will be used by both aconfig binary crate as well as flag read library crate (to be created as another new crate here). Bug: b/321984352 Test: top and individual crate dir level Cargo build/test, m each individual targets Ignore-AOSP-First: cherrypick to git main to resolve merge conflict Change-Id: I75833f4997f7ee554ff6c1557df9ac87f62b2732
This commit is contained in:
@@ -1,22 +1,7 @@
|
||||
[package]
|
||||
name = "aconfig"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
build = "build.rs"
|
||||
[workspace]
|
||||
|
||||
[features]
|
||||
default = ["cargo"]
|
||||
cargo = []
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.69"
|
||||
clap = { version = "4.1.8", features = ["derive"] }
|
||||
itertools = "0.10.5"
|
||||
paste = "1.0.11"
|
||||
protobuf = "3.2.0"
|
||||
serde = { version = "1.0.152", features = ["derive"] }
|
||||
serde_json = "1.0.93"
|
||||
tinytemplate = "1.2.1"
|
||||
|
||||
[build-dependencies]
|
||||
protobuf-codegen = "3.2.0"
|
||||
members = [
|
||||
"aconfig",
|
||||
"aconfig_protos",
|
||||
"printflags"
|
||||
]
|
||||
|
@@ -2,51 +2,6 @@ package {
|
||||
default_applicable_licenses: ["Android-Apache-2.0"],
|
||||
}
|
||||
|
||||
// proto libraries for consumers of `aconfig dump --format=protobuf` output
|
||||
|
||||
java_library {
|
||||
name: "libaconfig_java_proto_lite",
|
||||
host_supported: true,
|
||||
srcs: ["protos/aconfig.proto"],
|
||||
static_libs: ["libprotobuf-java-lite"],
|
||||
proto: {
|
||||
type: "lite",
|
||||
},
|
||||
sdk_version: "current",
|
||||
min_sdk_version: "34",
|
||||
apex_available: [
|
||||
"com.android.configinfrastructure",
|
||||
"//apex_available:platform",
|
||||
]
|
||||
}
|
||||
|
||||
java_library_host {
|
||||
name: "libaconfig_java_proto_full",
|
||||
srcs: ["protos/aconfig.proto"],
|
||||
static_libs: ["libprotobuf-java-full"],
|
||||
proto: {
|
||||
type: "full",
|
||||
},
|
||||
}
|
||||
|
||||
python_library_host {
|
||||
name: "libaconfig_python_proto",
|
||||
srcs: ["protos/aconfig.proto"],
|
||||
proto: {
|
||||
canonical_path_from_root: false,
|
||||
},
|
||||
}
|
||||
|
||||
// host binary: aconfig
|
||||
|
||||
rust_protobuf {
|
||||
name: "libaconfig_protos",
|
||||
protos: ["protos/aconfig.proto"],
|
||||
crate_name: "aconfig_protos",
|
||||
source_stem: "aconfig_protos",
|
||||
host_supported: true,
|
||||
}
|
||||
|
||||
rust_defaults {
|
||||
name: "aconfig.defaults",
|
||||
edition: "2021",
|
||||
@@ -63,9 +18,6 @@ rust_defaults {
|
||||
"libserde_json",
|
||||
"libtinytemplate",
|
||||
],
|
||||
proc_macros: [
|
||||
"libpaste",
|
||||
]
|
||||
}
|
||||
|
||||
rust_binary_host {
|
18
tools/aconfig/aconfig/Cargo.toml
Normal file
18
tools/aconfig/aconfig/Cargo.toml
Normal file
@@ -0,0 +1,18 @@
|
||||
[package]
|
||||
name = "aconfig"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[features]
|
||||
default = ["cargo"]
|
||||
cargo = []
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.69"
|
||||
clap = { version = "4.1.8", features = ["derive"] }
|
||||
itertools = "0.10.5"
|
||||
protobuf = "3.2.0"
|
||||
serde = { version = "1.0.152", features = ["derive"] }
|
||||
serde_json = "1.0.93"
|
||||
tinytemplate = "1.2.1"
|
||||
aconfig_protos = { path = "../aconfig_protos" }
|
@@ -19,10 +19,11 @@ use serde::Serialize;
|
||||
use std::path::PathBuf;
|
||||
use tinytemplate::TinyTemplate;
|
||||
|
||||
use aconfig_protos::{ProtoFlagPermission, ProtoFlagState, ProtoParsedFlag};
|
||||
|
||||
use crate::codegen;
|
||||
use crate::codegen::CodegenMode;
|
||||
use crate::commands::OutputFile;
|
||||
use crate::protos::{ProtoFlagPermission, ProtoFlagState, ProtoParsedFlag};
|
||||
|
||||
pub fn generate_cpp_code<I>(
|
||||
package: &str,
|
||||
@@ -136,7 +137,7 @@ fn create_class_element(package: &str, pf: &ProtoParsedFlag, rw_count: &mut i32)
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::protos::ProtoParsedFlags;
|
||||
use aconfig_protos::ProtoParsedFlags;
|
||||
use std::collections::HashMap;
|
||||
|
||||
const EXPORTED_PROD_HEADER_EXPECTED: &str = r#"
|
@@ -20,10 +20,11 @@ use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::path::PathBuf;
|
||||
use tinytemplate::TinyTemplate;
|
||||
|
||||
use aconfig_protos::{ProtoFlagPermission, ProtoFlagState, ProtoParsedFlag};
|
||||
|
||||
use crate::codegen;
|
||||
use crate::codegen::CodegenMode;
|
||||
use crate::commands::OutputFile;
|
||||
use crate::protos::{ProtoFlagPermission, ProtoFlagState, ProtoParsedFlag};
|
||||
|
||||
pub fn generate_java_code<I>(
|
||||
package: &str,
|
@@ -20,32 +20,7 @@ pub mod rust;
|
||||
|
||||
use anyhow::{ensure, Result};
|
||||
use clap::ValueEnum;
|
||||
|
||||
pub fn is_valid_name_ident(s: &str) -> bool {
|
||||
// Identifiers must match [a-z][a-z0-9_]*, except consecutive underscores are not allowed
|
||||
if s.contains("__") {
|
||||
return false;
|
||||
}
|
||||
let mut chars = s.chars();
|
||||
let Some(first) = chars.next() else {
|
||||
return false;
|
||||
};
|
||||
if !first.is_ascii_lowercase() {
|
||||
return false;
|
||||
}
|
||||
chars.all(|ch| ch.is_ascii_lowercase() || ch.is_ascii_digit() || ch == '_')
|
||||
}
|
||||
|
||||
pub fn is_valid_package_ident(s: &str) -> bool {
|
||||
if !s.contains('.') {
|
||||
return false;
|
||||
}
|
||||
s.split('.').all(is_valid_name_ident)
|
||||
}
|
||||
|
||||
pub fn is_valid_container_ident(s: &str) -> bool {
|
||||
s.split('.').all(is_valid_name_ident)
|
||||
}
|
||||
use aconfig_protos::{is_valid_name_ident, is_valid_package_ident};
|
||||
|
||||
pub fn create_device_config_ident(package: &str, flag_name: &str) -> Result<String> {
|
||||
ensure!(is_valid_package_ident(package), "bad package");
|
||||
@@ -75,6 +50,7 @@ impl std::fmt::Display for CodegenMode {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use aconfig_protos::is_valid_container_ident;
|
||||
|
||||
#[test]
|
||||
fn test_is_valid_name_ident() {
|
@@ -18,10 +18,11 @@ use anyhow::Result;
|
||||
use serde::Serialize;
|
||||
use tinytemplate::TinyTemplate;
|
||||
|
||||
use aconfig_protos::{ProtoFlagPermission, ProtoFlagState, ProtoParsedFlag};
|
||||
|
||||
use crate::codegen;
|
||||
use crate::codegen::CodegenMode;
|
||||
use crate::commands::OutputFile;
|
||||
use crate::protos::{ProtoFlagPermission, ProtoFlagState, ProtoParsedFlag};
|
||||
|
||||
pub fn generate_rust_code<I>(
|
||||
package: &str,
|
@@ -26,7 +26,7 @@ use crate::codegen::java::generate_java_code;
|
||||
use crate::codegen::rust::generate_rust_code;
|
||||
use crate::codegen::CodegenMode;
|
||||
use crate::dump::{DumpFormat, DumpPredicate};
|
||||
use crate::protos::{
|
||||
use aconfig_protos::{
|
||||
ParsedFlagExt, ProtoFlagMetadata, ProtoFlagPermission, ProtoFlagState, ProtoParsedFlag,
|
||||
ProtoParsedFlags, ProtoTracepoint,
|
||||
};
|
||||
@@ -44,7 +44,7 @@ impl Input {
|
||||
self.reader
|
||||
.read_to_end(&mut buffer)
|
||||
.with_context(|| format!("failed to read {}", self.source))?;
|
||||
crate::protos::parsed_flags::try_from_binary_proto(&buffer)
|
||||
aconfig_protos::parsed_flags::try_from_binary_proto(&buffer)
|
||||
.with_context(|| self.error_context())
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ pub fn parse_flags(
|
||||
.read_to_string(&mut contents)
|
||||
.with_context(|| format!("failed to read {}", input.source))?;
|
||||
|
||||
let flag_declarations = crate::protos::flag_declarations::try_from_text_proto(&contents)
|
||||
let flag_declarations = aconfig_protos::flag_declarations::try_from_text_proto(&contents)
|
||||
.with_context(|| input.error_context())?;
|
||||
ensure!(
|
||||
package == flag_declarations.package(),
|
||||
@@ -96,7 +96,7 @@ pub fn parse_flags(
|
||||
);
|
||||
}
|
||||
for mut flag_declaration in flag_declarations.flag.into_iter() {
|
||||
crate::protos::flag_declaration::verify_fields(&flag_declaration)
|
||||
aconfig_protos::flag_declaration::verify_fields(&flag_declaration)
|
||||
.with_context(|| input.error_context())?;
|
||||
|
||||
// create ParsedFlag using FlagDeclaration and default values
|
||||
@@ -130,7 +130,7 @@ pub fn parse_flags(
|
||||
parsed_flag.metadata = Some(metadata).into();
|
||||
|
||||
// verify ParsedFlag looks reasonable
|
||||
crate::protos::parsed_flag::verify_fields(&parsed_flag)?;
|
||||
aconfig_protos::parsed_flag::verify_fields(&parsed_flag)?;
|
||||
|
||||
// verify ParsedFlag can be added
|
||||
ensure!(
|
||||
@@ -151,10 +151,10 @@ pub fn parse_flags(
|
||||
.reader
|
||||
.read_to_string(&mut contents)
|
||||
.with_context(|| format!("failed to read {}", input.source))?;
|
||||
let flag_values = crate::protos::flag_values::try_from_text_proto(&contents)
|
||||
let flag_values = aconfig_protos::flag_values::try_from_text_proto(&contents)
|
||||
.with_context(|| input.error_context())?;
|
||||
for flag_value in flag_values.flag_value.into_iter() {
|
||||
crate::protos::flag_value::verify_fields(&flag_value)
|
||||
aconfig_protos::flag_value::verify_fields(&flag_value)
|
||||
.with_context(|| input.error_context())?;
|
||||
|
||||
let Some(parsed_flag) = parsed_flags
|
||||
@@ -184,8 +184,8 @@ pub fn parse_flags(
|
||||
}
|
||||
|
||||
// Create a sorted parsed_flags
|
||||
crate::protos::parsed_flags::sort_parsed_flags(&mut parsed_flags);
|
||||
crate::protos::parsed_flags::verify_fields(&parsed_flags)?;
|
||||
aconfig_protos::parsed_flags::sort_parsed_flags(&mut parsed_flags);
|
||||
aconfig_protos::parsed_flags::verify_fields(&parsed_flags)?;
|
||||
let mut output = Vec::new();
|
||||
parsed_flags.write_to_vec(&mut output)?;
|
||||
Ok(output)
|
||||
@@ -287,7 +287,7 @@ pub fn dump_parsed_flags(
|
||||
let individually_parsed_flags: Result<Vec<ProtoParsedFlags>> =
|
||||
input.iter_mut().map(|i| i.try_parse_flags()).collect();
|
||||
let parsed_flags: ProtoParsedFlags =
|
||||
crate::protos::parsed_flags::merge(individually_parsed_flags?, dedup)?;
|
||||
aconfig_protos::parsed_flags::merge(individually_parsed_flags?, dedup)?;
|
||||
let filters: Vec<Box<DumpPredicate>> = if filters.is_empty() {
|
||||
vec![Box::new(|_| true)]
|
||||
} else {
|
||||
@@ -386,16 +386,16 @@ where
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::protos::ProtoFlagPurpose;
|
||||
use aconfig_protos::ProtoFlagPurpose;
|
||||
|
||||
#[test]
|
||||
fn test_parse_flags() {
|
||||
let parsed_flags = crate::test::parse_test_flags(); // calls parse_flags
|
||||
crate::protos::parsed_flags::verify_fields(&parsed_flags).unwrap();
|
||||
aconfig_protos::parsed_flags::verify_fields(&parsed_flags).unwrap();
|
||||
|
||||
let enabled_ro =
|
||||
parsed_flags.parsed_flag.iter().find(|pf| pf.name() == "enabled_ro").unwrap();
|
||||
assert!(crate::protos::parsed_flag::verify_fields(enabled_ro).is_ok());
|
||||
assert!(aconfig_protos::parsed_flag::verify_fields(enabled_ro).is_ok());
|
||||
assert_eq!("com.android.aconfig.test", enabled_ro.package());
|
||||
assert_eq!("enabled_ro", enabled_ro.name());
|
||||
assert_eq!("This flag is ENABLED + READ_ONLY", enabled_ro.description());
|
||||
@@ -462,7 +462,7 @@ mod tests {
|
||||
)
|
||||
.unwrap();
|
||||
let parsed_flags =
|
||||
crate::protos::parsed_flags::try_from_binary_proto(&flags_bytes).unwrap();
|
||||
aconfig_protos::parsed_flags::try_from_binary_proto(&flags_bytes).unwrap();
|
||||
assert_eq!(1, parsed_flags.parsed_flag.len());
|
||||
let parsed_flag = parsed_flags.parsed_flag.first().unwrap();
|
||||
assert_eq!(ProtoFlagState::DISABLED, parsed_flag.state());
|
||||
@@ -602,7 +602,7 @@ mod tests {
|
||||
)
|
||||
.unwrap();
|
||||
let parsed_flags =
|
||||
crate::protos::parsed_flags::try_from_binary_proto(&flags_bytes).unwrap();
|
||||
aconfig_protos::parsed_flags::try_from_binary_proto(&flags_bytes).unwrap();
|
||||
assert_eq!(1, parsed_flags.parsed_flag.len());
|
||||
let parsed_flag = parsed_flags.parsed_flag.first().unwrap();
|
||||
assert_eq!(ProtoFlagPurpose::PURPOSE_FEATURE, parsed_flag.metadata.purpose());
|
@@ -14,10 +14,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use crate::protos::{
|
||||
use aconfig_protos::{
|
||||
ParsedFlagExt, ProtoFlagMetadata, ProtoFlagPermission, ProtoFlagState, ProtoTracepoint,
|
||||
};
|
||||
use crate::protos::{ProtoParsedFlag, ProtoParsedFlags};
|
||||
use aconfig_protos::{ProtoParsedFlag, ProtoParsedFlags};
|
||||
use anyhow::{anyhow, bail, Context, Result};
|
||||
use protobuf::Message;
|
||||
|
||||
@@ -197,7 +197,7 @@ fn create_filter_predicate_single(filter: &str) -> Result<Box<DumpPredicate>> {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::protos::ProtoParsedFlags;
|
||||
use aconfig_protos::ProtoParsedFlags;
|
||||
use crate::test::parse_test_flags;
|
||||
use protobuf::Message;
|
||||
|
@@ -27,7 +27,6 @@ use std::path::{Path, PathBuf};
|
||||
mod codegen;
|
||||
mod commands;
|
||||
mod dump;
|
||||
mod protos;
|
||||
mod storage;
|
||||
|
||||
use codegen::CodegenMode;
|
||||
@@ -57,8 +56,8 @@ fn cli() -> Command {
|
||||
.arg(
|
||||
Arg::new("default-permission")
|
||||
.long("default-permission")
|
||||
.value_parser(protos::flag_permission::parse_from_str)
|
||||
.default_value(protos::flag_permission::to_string(
|
||||
.value_parser(aconfig_protos::flag_permission::parse_from_str)
|
||||
.default_value(aconfig_protos::flag_permission::to_string(
|
||||
&commands::DEFAULT_FLAG_PERMISSION,
|
||||
)),
|
||||
)
|
||||
@@ -215,7 +214,7 @@ fn main() -> Result<()> {
|
||||
let declarations = open_zero_or_more_files(sub_matches, "declarations")?;
|
||||
let values = open_zero_or_more_files(sub_matches, "values")?;
|
||||
let default_permission =
|
||||
get_required_arg::<protos::ProtoFlagPermission>(sub_matches, "default-permission")?;
|
||||
get_required_arg::<aconfig_protos::ProtoFlagPermission>(sub_matches, "default-permission")?;
|
||||
let output = commands::parse_flags(
|
||||
package,
|
||||
container,
|
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
use crate::commands::assign_flag_ids;
|
||||
use crate::protos::ProtoFlagState;
|
||||
use aconfig_protos::ProtoFlagState;
|
||||
use crate::storage::{self, FlagPackage};
|
||||
use anyhow::{anyhow, Result};
|
||||
|
@@ -22,7 +22,7 @@ use anyhow::{anyhow, Result};
|
||||
use std::collections::{hash_map::DefaultHasher, HashMap, HashSet};
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
use crate::protos::{ProtoParsedFlag, ProtoParsedFlags};
|
||||
use aconfig_protos::{ProtoParsedFlag, ProtoParsedFlags};
|
||||
use crate::storage::{
|
||||
flag_table::FlagTable, flag_value::FlagValueList, package_table::PackageTable,
|
||||
};
|
||||
@@ -221,7 +221,7 @@ mod tests {
|
||||
crate::commands::DEFAULT_FLAG_PERMISSION,
|
||||
)
|
||||
.unwrap();
|
||||
crate::protos::parsed_flags::try_from_binary_proto(&bytes).unwrap()
|
||||
aconfig_protos::parsed_flags::try_from_binary_proto(&bytes).unwrap()
|
||||
})
|
||||
.collect()
|
||||
}
|
@@ -17,7 +17,7 @@
|
||||
#[cfg(test)]
|
||||
pub mod test_utils {
|
||||
use crate::commands::Input;
|
||||
use crate::protos::ProtoParsedFlags;
|
||||
use aconfig_protos::ProtoParsedFlags;
|
||||
use itertools;
|
||||
|
||||
pub const TEST_PACKAGE: &str = "com.android.aconfig.test";
|
||||
@@ -265,7 +265,7 @@ parsed_flag {
|
||||
crate::commands::DEFAULT_FLAG_PERMISSION,
|
||||
)
|
||||
.unwrap();
|
||||
crate::protos::parsed_flags::try_from_binary_proto(&bytes).unwrap()
|
||||
aconfig_protos::parsed_flags::try_from_binary_proto(&bytes).unwrap()
|
||||
}
|
||||
|
||||
pub fn parse_test_flags() -> ProtoParsedFlags {
|
||||
@@ -289,7 +289,7 @@ parsed_flag {
|
||||
crate::commands::DEFAULT_FLAG_PERMISSION,
|
||||
)
|
||||
.unwrap();
|
||||
crate::protos::parsed_flags::try_from_binary_proto(&bytes).unwrap()
|
||||
aconfig_protos::parsed_flags::try_from_binary_proto(&bytes).unwrap()
|
||||
}
|
||||
|
||||
pub fn first_significant_code_diff(a: &str, b: &str) -> Option<String> {
|
62
tools/aconfig/aconfig_protos/Android.bp
Normal file
62
tools/aconfig/aconfig_protos/Android.bp
Normal file
@@ -0,0 +1,62 @@
|
||||
package {
|
||||
default_applicable_licenses: ["Android-Apache-2.0"],
|
||||
}
|
||||
|
||||
// proto libraries for consumers of `aconfig dump --format=protobuf` output
|
||||
|
||||
java_library {
|
||||
name: "libaconfig_java_proto_lite",
|
||||
host_supported: true,
|
||||
srcs: ["protos/aconfig.proto"],
|
||||
static_libs: ["libprotobuf-java-lite"],
|
||||
proto: {
|
||||
type: "lite",
|
||||
},
|
||||
sdk_version: "current",
|
||||
min_sdk_version: "UpsideDownCake",
|
||||
apex_available: [
|
||||
"com.android.configinfrastructure",
|
||||
"//apex_available:platform",
|
||||
]
|
||||
}
|
||||
|
||||
java_library_host {
|
||||
name: "libaconfig_java_proto_full",
|
||||
srcs: ["protos/aconfig.proto"],
|
||||
static_libs: ["libprotobuf-java-full"],
|
||||
proto: {
|
||||
type: "full",
|
||||
},
|
||||
}
|
||||
|
||||
python_library_host {
|
||||
name: "libaconfig_python_proto",
|
||||
srcs: ["protos/aconfig.proto"],
|
||||
proto: {
|
||||
canonical_path_from_root: false,
|
||||
},
|
||||
}
|
||||
|
||||
rust_protobuf {
|
||||
name: "libaconfig_rust_proto",
|
||||
protos: ["protos/aconfig.proto"],
|
||||
crate_name: "aconfig_rust_proto",
|
||||
source_stem: "aconfig_rust_proto",
|
||||
host_supported: true,
|
||||
}
|
||||
|
||||
rust_library {
|
||||
name: "libaconfig_protos",
|
||||
srcs: ["src/lib.rs"],
|
||||
crate_name: "aconfig_protos",
|
||||
host_supported: true,
|
||||
lints: "none",
|
||||
rustlibs: [
|
||||
"libaconfig_rust_proto",
|
||||
"libanyhow",
|
||||
"libprotobuf",
|
||||
],
|
||||
proc_macros: [
|
||||
"libpaste",
|
||||
]
|
||||
}
|
17
tools/aconfig/aconfig_protos/Cargo.toml
Normal file
17
tools/aconfig/aconfig_protos/Cargo.toml
Normal file
@@ -0,0 +1,17 @@
|
||||
[package]
|
||||
name = "aconfig_protos"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
build = "build.rs"
|
||||
|
||||
[features]
|
||||
default = ["cargo"]
|
||||
cargo = []
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.69"
|
||||
paste = "1.0.11"
|
||||
protobuf = "3.2.0"
|
||||
|
||||
[build-dependencies]
|
||||
protobuf-codegen = "3.2.0"
|
@@ -29,17 +29,17 @@
|
||||
// ---- When building with the Android tool-chain ----
|
||||
#[cfg(not(feature = "cargo"))]
|
||||
mod auto_generated {
|
||||
pub use aconfig_protos::aconfig::flag_metadata::Flag_purpose as ProtoFlagPurpose;
|
||||
pub use aconfig_protos::aconfig::Flag_declaration as ProtoFlagDeclaration;
|
||||
pub use aconfig_protos::aconfig::Flag_declarations as ProtoFlagDeclarations;
|
||||
pub use aconfig_protos::aconfig::Flag_metadata as ProtoFlagMetadata;
|
||||
pub use aconfig_protos::aconfig::Flag_permission as ProtoFlagPermission;
|
||||
pub use aconfig_protos::aconfig::Flag_state as ProtoFlagState;
|
||||
pub use aconfig_protos::aconfig::Flag_value as ProtoFlagValue;
|
||||
pub use aconfig_protos::aconfig::Flag_values as ProtoFlagValues;
|
||||
pub use aconfig_protos::aconfig::Parsed_flag as ProtoParsedFlag;
|
||||
pub use aconfig_protos::aconfig::Parsed_flags as ProtoParsedFlags;
|
||||
pub use aconfig_protos::aconfig::Tracepoint as ProtoTracepoint;
|
||||
pub use aconfig_rust_proto::aconfig::flag_metadata::Flag_purpose as ProtoFlagPurpose;
|
||||
pub use aconfig_rust_proto::aconfig::Flag_declaration as ProtoFlagDeclaration;
|
||||
pub use aconfig_rust_proto::aconfig::Flag_declarations as ProtoFlagDeclarations;
|
||||
pub use aconfig_rust_proto::aconfig::Flag_metadata as ProtoFlagMetadata;
|
||||
pub use aconfig_rust_proto::aconfig::Flag_permission as ProtoFlagPermission;
|
||||
pub use aconfig_rust_proto::aconfig::Flag_state as ProtoFlagState;
|
||||
pub use aconfig_rust_proto::aconfig::Flag_value as ProtoFlagValue;
|
||||
pub use aconfig_rust_proto::aconfig::Flag_values as ProtoFlagValues;
|
||||
pub use aconfig_rust_proto::aconfig::Parsed_flag as ProtoParsedFlag;
|
||||
pub use aconfig_rust_proto::aconfig::Parsed_flags as ProtoParsedFlags;
|
||||
pub use aconfig_rust_proto::aconfig::Tracepoint as ProtoTracepoint;
|
||||
}
|
||||
|
||||
// ---- When building with cargo ----
|
||||
@@ -68,6 +68,32 @@ pub use auto_generated::*;
|
||||
use anyhow::Result;
|
||||
use paste::paste;
|
||||
|
||||
pub fn is_valid_name_ident(s: &str) -> bool {
|
||||
// Identifiers must match [a-z][a-z0-9_]*, except consecutive underscores are not allowed
|
||||
if s.contains("__") {
|
||||
return false;
|
||||
}
|
||||
let mut chars = s.chars();
|
||||
let Some(first) = chars.next() else {
|
||||
return false;
|
||||
};
|
||||
if !first.is_ascii_lowercase() {
|
||||
return false;
|
||||
}
|
||||
chars.all(|ch| ch.is_ascii_lowercase() || ch.is_ascii_digit() || ch == '_')
|
||||
}
|
||||
|
||||
pub fn is_valid_package_ident(s: &str) -> bool {
|
||||
if !s.contains('.') {
|
||||
return false;
|
||||
}
|
||||
s.split('.').all(is_valid_name_ident)
|
||||
}
|
||||
|
||||
pub fn is_valid_container_ident(s: &str) -> bool {
|
||||
s.split('.').all(is_valid_name_ident)
|
||||
}
|
||||
|
||||
fn try_from_text_proto<T>(s: &str) -> Result<T>
|
||||
where
|
||||
T: protobuf::MessageFull,
|
||||
@@ -87,14 +113,13 @@ macro_rules! ensure_required_fields {
|
||||
|
||||
pub mod flag_declaration {
|
||||
use super::*;
|
||||
use crate::codegen;
|
||||
use anyhow::ensure;
|
||||
|
||||
pub fn verify_fields(pdf: &ProtoFlagDeclaration) -> Result<()> {
|
||||
ensure_required_fields!("flag declaration", pdf, "name", "namespace", "description");
|
||||
|
||||
ensure!(codegen::is_valid_name_ident(pdf.name()), "bad flag declaration: bad name");
|
||||
ensure!(codegen::is_valid_name_ident(pdf.namespace()), "bad flag declaration: bad name");
|
||||
ensure!(is_valid_name_ident(pdf.name()), "bad flag declaration: bad name");
|
||||
ensure!(is_valid_name_ident(pdf.namespace()), "bad flag declaration: bad name");
|
||||
ensure!(!pdf.description().is_empty(), "bad flag declaration: empty description");
|
||||
ensure!(pdf.bug.len() == 1, "bad flag declaration: exactly one bug required");
|
||||
|
||||
@@ -104,7 +129,6 @@ pub mod flag_declaration {
|
||||
|
||||
pub mod flag_declarations {
|
||||
use super::*;
|
||||
use crate::codegen;
|
||||
use anyhow::ensure;
|
||||
|
||||
pub fn try_from_text_proto(s: &str) -> Result<ProtoFlagDeclarations> {
|
||||
@@ -118,11 +142,11 @@ pub mod flag_declarations {
|
||||
// TODO(b/312769710): Make the container field required.
|
||||
|
||||
ensure!(
|
||||
codegen::is_valid_package_ident(pdf.package()),
|
||||
is_valid_package_ident(pdf.package()),
|
||||
"bad flag declarations: bad package"
|
||||
);
|
||||
ensure!(
|
||||
!pdf.has_container() || codegen::is_valid_container_ident(pdf.container()),
|
||||
!pdf.has_container() || is_valid_container_ident(pdf.container()),
|
||||
"bad flag declarations: bad container"
|
||||
);
|
||||
for flag_declaration in pdf.flag.iter() {
|
||||
@@ -135,14 +159,13 @@ pub mod flag_declarations {
|
||||
|
||||
pub mod flag_value {
|
||||
use super::*;
|
||||
use crate::codegen;
|
||||
use anyhow::ensure;
|
||||
|
||||
pub fn verify_fields(fv: &ProtoFlagValue) -> Result<()> {
|
||||
ensure_required_fields!("flag value", fv, "package", "name", "state", "permission");
|
||||
|
||||
ensure!(codegen::is_valid_package_ident(fv.package()), "bad flag value: bad package");
|
||||
ensure!(codegen::is_valid_name_ident(fv.name()), "bad flag value: bad name");
|
||||
ensure!(is_valid_package_ident(fv.package()), "bad flag value: bad package");
|
||||
ensure!(is_valid_name_ident(fv.name()), "bad flag value: bad name");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -200,7 +223,6 @@ pub mod tracepoint {
|
||||
|
||||
pub mod parsed_flag {
|
||||
use super::*;
|
||||
use crate::codegen;
|
||||
use anyhow::ensure;
|
||||
|
||||
pub fn verify_fields(pf: &ProtoParsedFlag) -> Result<()> {
|
||||
@@ -215,13 +237,13 @@ pub mod parsed_flag {
|
||||
"permission"
|
||||
);
|
||||
|
||||
ensure!(codegen::is_valid_package_ident(pf.package()), "bad parsed flag: bad package");
|
||||
ensure!(is_valid_package_ident(pf.package()), "bad parsed flag: bad package");
|
||||
ensure!(
|
||||
!pf.has_container() || codegen::is_valid_container_ident(pf.container()),
|
||||
!pf.has_container() || is_valid_container_ident(pf.container()),
|
||||
"bad parsed flag: bad container"
|
||||
);
|
||||
ensure!(codegen::is_valid_name_ident(pf.name()), "bad parsed flag: bad name");
|
||||
ensure!(codegen::is_valid_name_ident(pf.namespace()), "bad parsed flag: bad namespace");
|
||||
ensure!(is_valid_name_ident(pf.name()), "bad parsed flag: bad name");
|
||||
ensure!(is_valid_name_ident(pf.namespace()), "bad parsed flag: bad namespace");
|
||||
ensure!(!pf.description().is_empty(), "bad parsed flag: empty description");
|
||||
ensure!(!pf.trace.is_empty(), "bad parsed flag: empty trace");
|
||||
for tp in pf.trace.iter() {
|
||||
@@ -261,7 +283,7 @@ pub mod parsed_flags {
|
||||
}
|
||||
|
||||
pub fn verify_fields(pf: &ProtoParsedFlags) -> Result<()> {
|
||||
use crate::protos::parsed_flag::path_to_declaration;
|
||||
use crate::parsed_flag::path_to_declaration;
|
||||
|
||||
let mut previous: Option<&ProtoParsedFlag> = None;
|
||||
for parsed_flag in pf.parsed_flag.iter() {
|
||||
@@ -848,7 +870,7 @@ parsed_flag {
|
||||
let parsed_flags = try_from_binary_proto_from_text_proto(text_proto).unwrap();
|
||||
let parsed_flag = &parsed_flags.parsed_flag[0];
|
||||
assert_eq!(
|
||||
crate::protos::parsed_flag::path_to_declaration(parsed_flag),
|
||||
crate::parsed_flag::path_to_declaration(parsed_flag),
|
||||
"flags.declarations"
|
||||
);
|
||||
}
|
15
tools/aconfig/printflags/Cargo.toml
Normal file
15
tools/aconfig/printflags/Cargo.toml
Normal file
@@ -0,0 +1,15 @@
|
||||
[package]
|
||||
name = "printflags"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[features]
|
||||
default = ["cargo"]
|
||||
cargo = []
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.69"
|
||||
paste = "1.0.11"
|
||||
protobuf = "3.2.0"
|
||||
regex = "1.10.3"
|
||||
aconfig_protos = { path = "../aconfig_protos" }
|
@@ -16,8 +16,8 @@
|
||||
|
||||
//! `printflags` is a device binary to print feature flags.
|
||||
|
||||
use aconfig_protos::aconfig::Flag_state as State;
|
||||
use aconfig_protos::aconfig::Parsed_flags as ProtoParsedFlags;
|
||||
use aconfig_protos::ProtoFlagState as State;
|
||||
use aconfig_protos::ProtoParsedFlags as ProtoParsedFlags;
|
||||
use anyhow::{bail, Context, Result};
|
||||
use regex::Regex;
|
||||
use std::collections::BTreeMap;
|
||||
|
Reference in New Issue
Block a user