blob: 6307c47d6871c5401affc6ccf499d40e74ea36bd [file] [log] [blame]
# Copyright 2023 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.
#### CATEGORY=Build
### List which packages are built.
import argparse
import collections
import json
import os
import pathlib
import re
import sys
from typing import Callable, Dict, List
# Print all the packages in sorted order, one per line.
def print_packages(packages_by_source: Dict[str, List[str]]) -> None:
packages = set()
for ps in packages_by_source.values():
packages.update(ps)
for p in sorted(packages):
print(p)
# Print all the packages in sorted order, along with which package set(s) they
# are included in, one package per line.
def print_packages_verbose(packages_by_source: Dict[str, List[str]]) -> None:
packages = collections.defaultdict(list)
for source, ps in packages_by_source.items():
for p in ps:
packages[p].append(source)
for p in sorted(packages.keys()):
print(p, " [", " ".join(sorted(packages[p])), "]", sep="")
# Extracts the list of package names that are accepted by filter_ from a
# decoded package list manifest.
def extract_packages_from_listing(
listing, filter_: Callable[[str], bool]
) -> [str]:
return list(
filter(
filter_,
(path.split("/")[-1] for path in listing["content"]["manifests"]),
)
)
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(
description="""
list-packages lists the packages that the build is aware of. These are
packages that can be rebuilt and/or pushed to a device.
If no package sets are specified, all package sets will be checked.
Note: list-packages DOES NOT list all packages that *could* be built, only
those that are included in the current build configuration.
""",
epilog="""
See https://fuchsia.dev/fuchsia-src/development/build/boards_and_products
for more information about using these package sets.
""",
)
parser.add_argument(
"--base", action="store_true", help="list packages in base"
)
parser.add_argument(
"--cache", action="store_true", help="list packages in cache"
)
parser.add_argument(
"--universe", action="store_true", help="list packages in universe"
)
parser.add_argument(
"--verbose",
action="store_true",
help="print package set for each listed package",
)
parser.add_argument(
"pattern",
nargs="?",
help="list only packages that full match this regular expression",
)
return parser.parse_args()
def main() -> None:
args = parse_args()
if args.pattern:
regex = re.compile(args.pattern)
filter_ = lambda s: bool(regex.fullmatch(s))
else:
filter_ = lambda s: True
packages_by_source = {}
fuchsia_build_dir = os.environ.get("FUCHSIA_BUILD_DIR")
if fuchsia_build_dir is None:
raise RuntimError(
'Environment variable "FUCHSIA_BUILD_DIR" is not set.'
)
def add_listing(listing, filename):
with open(f"{fuchsia_build_dir}/{filename}") as f:
packages_by_source[listing] = extract_packages_from_listing(
json.load(f), filter_
)
none_specified = not any([args.base, args.cache, args.universe])
if args.base or none_specified:
add_listing("base", "base_packages.list")
if args.cache or none_specified:
add_listing("cache", "cache_packages.list")
if args.universe or none_specified:
add_listing("universe", "universe_packages.list")
if args.verbose:
print_packages_verbose(packages_by_source)
else:
print_packages(packages_by_source)
if __name__ == "__main__":
sys.exit(main())