Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 30cd7290 authored by Mårten Kongstad's avatar Mårten Kongstad Committed by Automerger Merge Worker
Browse files

Merge changes from topic "record-finalized-flags-part-2" into main am: 0c971299

parents 690c0a27 0c971299
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -9,7 +9,10 @@ rust_defaults {
    lints: "android",
    srcs: ["src/main.rs"],
    rustlibs: [
        "libaconfig_protos",
        "libanyhow",
        "libclap",
        "libregex",
    ],
}

+3 −0
Original line number Diff line number Diff line
@@ -9,4 +9,7 @@ version = "0.1.0"
edition = "2021"

[dependencies]
aconfig_protos = { path = "../aconfig/aconfig_protos" }
anyhow = { path = "../../../../external/rust/android-crates-io/crates/anyhow" }
clap = { path = "../../../../external/rust/android-crates-io/crates/clap", features = ["derive"] }
regex = { path = "../../../../external/rust/android-crates-io/crates/regex" }
+49 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

use anyhow::Result;
use regex::Regex;
use std::{collections::HashSet, io::Read};

use crate::FlagId;

/// Grep for all flags used with @FlaggedApi annotations in an API signature file (*current.txt
/// file).
pub(crate) fn extract_flagged_api_flags<R: Read>(mut reader: R) -> Result<HashSet<FlagId>> {
    let mut haystack = String::new();
    reader.read_to_string(&mut haystack)?;
    let regex = Regex::new(r#"(?ms)@FlaggedApi\("(.*?)"\)"#).unwrap();
    let iter = regex.captures_iter(&haystack).map(|cap| cap[1].to_owned());
    Ok(HashSet::from_iter(iter))
}

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

    #[test]
    fn test() {
        let api_signature_file = include_bytes!("../tests/api-signature-file.txt");
        let flags = extract_flagged_api_flags(&api_signature_file[..]).unwrap();
        assert_eq!(
            flags,
            HashSet::from_iter(vec![
                "record_finalized_flags.test.foo".to_string(),
                "this.flag.is.not.used".to_string(),
            ])
        );
    }
}
+47 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

use anyhow::Result;
use std::{collections::HashSet, io::Read};

use crate::FlagId;

/// Read a list of flag names. The input is expected to be plain text, with each line containing
/// the name of a single flag.
pub(crate) fn read_finalized_flags<R: Read>(mut reader: R) -> Result<HashSet<FlagId>> {
    let mut contents = String::new();
    reader.read_to_string(&mut contents)?;
    let iter = contents.lines().map(|s| s.to_owned());
    Ok(HashSet::from_iter(iter))
}

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

    #[test]
    fn test() {
        let input = include_bytes!("../tests/finalized-flags.txt");
        let flags = read_finalized_flags(&input[..]).unwrap();
        assert_eq!(
            flags,
            HashSet::from_iter(vec![
                "record_finalized_flags.test.bar".to_string(),
                "record_finalized_flags.test.baz".to_string(),
            ])
        );
    }
}
+53 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

use aconfig_protos::{ParsedFlagExt, ProtoFlagPermission, ProtoFlagState};
use anyhow::{anyhow, Result};
use std::{collections::HashSet, io::Read};

use crate::FlagId;

/// Parse a ProtoParsedFlags binary protobuf blob and return the fully qualified names of flags
/// that are slated for API finalization (i.e. are both ENABLED and READ_ONLY).
pub(crate) fn get_relevant_flags_from_binary_proto<R: Read>(
    mut reader: R,
) -> Result<HashSet<FlagId>> {
    let mut buffer = Vec::new();
    reader.read_to_end(&mut buffer)?;
    let parsed_flags = aconfig_protos::parsed_flags::try_from_binary_proto(&buffer)
        .map_err(|_| anyhow!("failed to parse binary proto"))?;
    let iter = parsed_flags
        .parsed_flag
        .into_iter()
        .filter(|flag| {
            flag.state() == ProtoFlagState::ENABLED
                && flag.permission() == ProtoFlagPermission::READ_ONLY
        })
        .map(|flag| flag.fully_qualified_name());
    Ok(HashSet::from_iter(iter))
}

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

    #[test]
    fn test_disabled_or_read_write_flags_are_ignored() {
        let bytes = include_bytes!("../tests/flags.protobuf");
        let flags = get_relevant_flags_from_binary_proto(&bytes[..]).unwrap();
        assert_eq!(flags, HashSet::from_iter(vec!["record_finalized_flags.test.foo".to_string()]));
    }
}
Loading