Skip to content

Commit

Permalink
Merge branch 'add-source-subcommand'
Browse files Browse the repository at this point in the history
Add a new subcommand to grep for and print the Android.bp definition of
a module.

* add-source-subcommand:
  Add `source` subcommand
  Add method to grep for module definition in Android.bp file
  deps: regex (1.10)
  Import Android.bp for unit tests

Signed-off-by: Mårten Kongstad <[email protected]>
  • Loading branch information
amhk committed Jun 20, 2024
2 parents 8fc0448 + 91f3e35 commit ff7c817
Show file tree
Hide file tree
Showing 6 changed files with 498 additions and 11 deletions.
31 changes: 22 additions & 9 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ edition = "2021"
anyhow = "1.0"
clap = "2.33"
memmap = "0.7"
regex = "1.10"
serde_json = "1.0"

[dependencies.serde]
Expand Down
32 changes: 32 additions & 0 deletions src/blueprint.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
use anyhow::Result;
use regex::Regex;

#[allow(dead_code)]
pub fn find_module_source<'h>(haystack: &'h str, name: &str) -> Result<Option<&'h str>> {
let regex_module = Regex::new(r"(?ms)[ \t]*[_a-zA-Z0-9]+\s*\{.*?^\}")?;
let regex_name = Regex::new(&format!(r#"(?m)^\s*name:\s*"{}""#, name))?;
for cap in regex_module.captures_iter(haystack) {
let match_ = cap.get(0).unwrap();
if regex_name.is_match(match_.as_str()) {
return Ok(Some(&haystack[match_.range()]));
}
}

Ok(None)
}

#[cfg(test)]
mod tests {
use super::*;

const BLUEPRINT: &str = include_str!("../tests/data/Android.bp");

#[test]
fn test_find_module_source() {
assert!(find_module_source("", "").unwrap().is_none());
assert!(find_module_source(BLUEPRINT, "none").unwrap().is_none());
let source = find_module_source(BLUEPRINT, "idmap2").unwrap().unwrap();
assert!(source.starts_with("cc_binary {\n name: \"idmap2\",\n"));
assert!(source.ends_with("},\n\n}"));
}
}
57 changes: 55 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,28 @@
use clap::{App, AppSettings, Arg};
use memmap::MmapOptions;
use std::env;
use std::fs::File;
use std::fs::{self, File};
use std::path::PathBuf;

use anyhow::{anyhow, bail, Result};
use anyhow::{anyhow, bail, ensure, Context, Result};

mod blueprint;
mod modinfo;

use modinfo::ModuleInfo;

#[derive(Debug)]
struct Arguments {
module_info_path: PathBuf,
android_top_path: PathBuf,
command: Command,
}

#[derive(Debug)]
enum Command {
List,
Show(String, Option<String>),
Source(String),
}

const MODULE_FIELDS: [&str; 9] = [
Expand All @@ -46,6 +49,14 @@ fn parse_args() -> Result<Arguments> {
.value_name("FILE")
.takes_value(true),
)
.arg(
Arg::with_name("android-top")
.help("Path to top of Android tree")
.long_help("Path to the top of the Android tree; defaults to `$ANDROID_BUILD_TOP`.")
.long("android-top")
.value_name("DIR")
.takes_value(true),
)
.subcommand(App::new("list").about("Prints the names of all modules"))
.subcommand(
App::new("show")
Expand All @@ -57,6 +68,13 @@ fn parse_args() -> Result<Arguments> {
.help("Name of field to show")
.possible_values(&MODULE_FIELDS)),
)
.subcommand(
App::new("source")
.about("Prints the Android.bp definition of module")
.arg(Arg::with_name("NAME")
.help("Name of module to show")
.required(true))
)
.get_matches();

let module_info_path = if matches.is_present("module-info") {
Expand All @@ -69,6 +87,14 @@ fn parse_args() -> Result<Arguments> {
path
};

let android_top_path = if matches.is_present("android-top") {
matches.value_of("android-top").unwrap().into()
} else {
env::var("ANDROID_BUILD_TOP")
.map_err(|_| anyhow!("ANDROID_BUILD_TOP not set"))?
.into()
};

let command = match &matches.subcommand() {
("list", _) => Command::List,
("show", Some(args)) => Command::Show(
Expand All @@ -77,11 +103,17 @@ fn parse_args() -> Result<Arguments> {
.to_string(),
args.value_of("FIELD").map(|s| s.to_string()),
),
("source", Some(args)) => Command::Source(
args.value_of("NAME")
.expect("value guaranteed by clap")
.to_string(),
),
(_, _) => unreachable!(),
};

Ok(Arguments {
module_info_path,
android_top_path,
command,
})
}
Expand Down Expand Up @@ -130,6 +162,27 @@ fn main() -> Result<()> {
println!("{:#?}", module);
}
}
Command::Source(name) => {
let module = modinfo
.find(&name)
.ok_or_else(|| anyhow!("{}: module not found", name))??;
ensure!(
module.path.len() == 1,
"{}: module does not have exactly one path: {:?}",
name,
module.path
);
let blueprint_path = format!(
"{}/{}/Android.bp",
args.android_top_path.display(),
module.path[0]
);
let blueprint_contents = fs::read_to_string(&blueprint_path)
.with_context(|| format!("could not read file {}", blueprint_path))?;
let module_source = blueprint::find_module_source(&blueprint_contents, &name)?
.ok_or_else(|| anyhow!("{}: module source not found", name))?;
println!("{}", module_source);
}
}

Ok(())
Expand Down
13 changes: 13 additions & 0 deletions tests/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ mod integration {
Command::cargo_bin("amodinfo")?
.arg("--module-info")
.arg("tests/data/module-info.json")
.arg("--android-top")
.arg("/dev/null")
.arg("list")
.assert()
.success()
Expand All @@ -42,6 +44,8 @@ mod integration {
Command::cargo_bin("amodinfo")?
.arg("--module-info")
.arg("tests/data/module-info.json")
.arg("--android-top")
.arg("/dev/null")
.arg("show")
.assert()
.failure();
Expand All @@ -50,6 +54,8 @@ mod integration {
Command::cargo_bin("amodinfo")?
.arg("--module-info")
.arg("tests/data/module-info.json")
.arg("--android-top")
.arg("/dev/null")
.arg("show")
.arg("does-not-exist")
.assert()
Expand All @@ -59,6 +65,8 @@ mod integration {
Command::cargo_bin("amodinfo")?
.arg("--module-info")
.arg("tests/data/module-info.json")
.arg("--android-top")
.arg("/dev/null")
.arg("show")
.arg("idmap2")
.assert()
Expand All @@ -74,6 +82,8 @@ mod integration {
Command::cargo_bin("amodinfo")?
.arg("--module-info")
.arg("tests/data/module-info.json")
.arg("--android-top")
.arg("/dev/null")
.arg("show")
.arg("idmap2")
.arg("path")
Expand All @@ -86,6 +96,8 @@ mod integration {
Command::cargo_bin("amodinfo")?
.arg("--module-info")
.arg("tests/data/module-info.json")
.arg("--android-top")
.arg("/dev/null")
.arg("show")
.arg("idmap2")
.arg("foo")
Expand All @@ -99,6 +111,7 @@ mod integration {
fn implicit_module_info_path() -> Result<(), Box<dyn Error>> {
Command::cargo_bin("amodinfo")?
.env("ANDROID_PRODUCT_OUT", "tests/data")
.env("ANDROID_BUILD_TOP", "/dev/null")
.arg("show")
.arg("idmap2")
.assert()
Expand Down
Loading

0 comments on commit ff7c817

Please sign in to comment.