blob: 0d0a6453ea9712c0b15e9a2422810a23d61f9abe [file] [log] [blame] [edit]
# Copyright 2024 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Generate a filtered version of the Fuchsia Build API module files. See https://fxbug.dev/359845634"""
import json
import typing as T
class BuildApiFilter(object):
"""Convenience class used to filter build API module files."""
def __init__(
self, ninja_artifacts: T.Sequence[str], ninja_sources: T.Sequence[str]
):
"""Initialization. |ninja_artifacts| is a list of Ninja file paths."""
self._ninja_artifacts = set(ninja_artifacts)
self._ninja_sources = set(ninja_sources)
self._ninja_all = self._ninja_artifacts | self._ninja_sources
def _filter_json_scopes(
self, input_json: T.Any, key_name: str
) -> T.List[str]:
assert isinstance(input_json, list)
return [s for s in input_json if s[key_name] in self._ninja_all]
def _filter_json_path_list(
self, input_paths: T.Sequence[str]
) -> T.Sequence[str]:
return [p for p in input_paths if p in self._ninja_all]
def _filter_json_scopes_with_multiple_keys(
self, input_json: T.Any, key_names: T.Sequence[str]
) -> T.List[str]:
assert isinstance(input_json, list)
return [
s
for s in input_json
if any(
s[key_name] in self._ninja_all
for key_name in key_names
if key_name in s
)
]
def filter_api_json(self, api_module: str, json_content: T.Any) -> T.Any:
"""Filter the content of a given build API module.
Args:
api_module: Name of build API module, without the .json suffix.
json_content: File content, as a JSON value.
Returns:
New version of the input content, where all items that are not
related to the set of ninja inputs passed to the constructor are
removed.
"""
if api_module in (
"assembly_input_archives",
"images",
"package-repositories",
"platform_artifacts",
"sdk_archives",
"tool_paths",
):
return self._filter_json_scopes(json_content, "path")
if api_module == "product_bundles":
# Do not filter on "path" which is a directory that does not appear
# directly as a Ninja output. Use "json" field which points to the
# product bundle's JSON manifest file instead.See https://fxbug.dev/365039385.
return self._filter_json_scopes(json_content, "json")
if api_module == "assembly_manifests":
return self._filter_json_scopes(
json_content, "assembly_manifest_path"
)
if api_module == "build_events_log":
return self._filter_json_scopes(json_content, "build_events_log")
if api_module == "binaries":
return self._filter_json_scopes(json_content, "debug")
if api_module == "debug_symbols":
return self._filter_json_scopes_with_multiple_keys(
json_content, ("debug", "manifest")
)
if api_module == "boards":
return self._filter_json_scopes(json_content, "outdir")
if api_module == "clippy_target_mapping":
return self._filter_json_scopes(json_content, "output")
if api_module == "generated_sources":
return self._filter_json_path_list(json_content)
if api_module == "golden_files":
return self._filter_json_scopes(json_content, "stamp")
return json_content
def filter_api_file(self, api_module: str, content: str) -> str:
"""Filter the content of a given build API module.
Args:
api_module: Name of build API module, without the .json suffix.
content: File content, as a string.
Returns:
New version of the input content, pretty-printed, where all items that
are not related to the set of ninja inputs passed to the constructor
are removed.
"""
json_content = self.filter_api_json(api_module, json.loads(content))
return json.dumps(
json_content, sort_keys=True, indent=2, separators=(",", ": ")
)