1
0
mirror of https://git.yoctoproject.org/meta-arm synced 2026-04-20 11:29:54 +00:00
Files
meta-arm/scripts/machine-summary.py
Ross Burton cb29175ab4 scripts/machine-summary: harvest more patch data
Instead of just putting whether there are patches or not into the
context, store the list of patches, the layer they came from, and the
upstream status.

Signed-off-by: Ross Burton <ross.burton@arm.com>
Signed-off-by: Jon Mason <jon.mason@arm.com>
2022-01-19 17:09:58 -05:00

145 lines
4.6 KiB
Python
Executable File

#! /usr/bin/env python3
import argparse
import datetime
import os
import re
import sys
import jinja2
def get_template(name):
template_dir = os.path.dirname(os.path.abspath(__file__))
env = jinja2.Environment(
loader=jinja2.FileSystemLoader(template_dir),
autoescape=jinja2.select_autoescape(),
trim_blocks=True,
lstrip_blocks=True
)
def is_old(version, upstream):
if "+git" in version:
# strip +git and see if this is a post-release snapshot
version = version.replace("+git", "")
return version != upstream
env.tests["old"] = is_old
return env.get_template(f"machine-summary-{name}.jinja")
def trim_pv(pv):
"""
Strip anything after +git from the PV
"""
return "".join(pv.partition("+git")[:2])
def layer_path(layername, d):
"""
Return the path to the specified layer, or None if the layer isn't present.
"""
import re
bbpath = d.getVar("BBPATH").split(":")
pattern = d.getVar('BBFILE_PATTERN_' + layername)
for path in reversed(sorted(bbpath)):
if re.match(pattern, path + "/"):
return path
return None
def extract_patch_info(src_uri, d):
"""
Parse the specified patch entry from a SRC_URI and return (base name, layer name, status) tuple
"""
import bb.fetch, bb.utils
info = {}
localpath = bb.fetch.decodeurl(src_uri)[2]
info["name"] = os.path.basename(localpath)
info["layer"] = bb.utils.get_file_layer(localpath, d)
status = "Unknown"
with open(localpath, errors="ignore") as f:
m = re.search(r"^[\t ]*Upstream[-_ ]Status:?[\t ]*(\w*)", f.read(), re.IGNORECASE | re.MULTILINE)
if m:
# TODO: validate
status = m.group(1)
info["status"] = status
return info
def harvest_data(machines, recipes):
import bb.tinfoil
with bb.tinfoil.Tinfoil() as tinfoil:
tinfoil.prepare(config_only=True)
corepath = layer_path("core", tinfoil.config_data)
sys.path.append(os.path.join(corepath, "lib"))
import oe.recipeutils
import oe.patch
# Queue of recipes that we're still looking for upstream releases for
to_check = list(recipes)
# Upstream releases
upstreams = {}
# Machines to recipes to versions
versions = {}
for machine in machines:
print(f"Gathering data for {machine}...")
os.environ["MACHINE"] = machine
with bb.tinfoil.Tinfoil() as tinfoil:
versions[machine] = {}
tinfoil.prepare(quiet=2)
for recipe in recipes:
try:
d = tinfoil.parse_recipe(recipe)
except bb.providers.NoProvider:
continue
if recipe in to_check:
try:
info = oe.recipeutils.get_recipe_upstream_version(d)
upstreams[recipe] = info["version"]
to_check.remove(recipe)
except (bb.providers.NoProvider, KeyError):
pass
details = versions[machine][recipe] = {}
details["recipe"] = d.getVar("PN")
details["version"] = trim_pv(d.getVar("PV"))
details["patches"] = [extract_patch_info(p, d) for p in oe.patch.src_patches(d)]
details["patched"] = bool(details["patches"])
# Now backfill the upstream versions
for machine in versions:
for recipe in versions[machine]:
versions[machine][recipe]["upstream"] = upstreams[recipe]
return upstreams, versions
# TODO can this be inferred from the list of recipes in the layer
recipes = ("virtual/kernel",
"scp-firmware",
"trusted-firmware-a",
"trusted-firmware-m",
"edk2-firmware",
"u-boot",
"optee-os",
"armcompiler-native",
"gcc-aarch64-none-elf-native",
"gcc-arm-none-eabi-native")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="machine-summary")
parser.add_argument("machines", nargs="+", help="machine names", metavar="MACHINE")
parser.add_argument("-t", "--template", required=True)
parser.add_argument("-o", "--output", required=True, type=argparse.FileType('w', encoding='UTF-8'))
args = parser.parse_args()
template = get_template(args.template)
context = {}
# TODO: include git describe for meta-arm
context["timestamp"] = str(datetime.datetime.now().strftime("%c"))
context["recipes"] = sorted(recipes)
context["releases"], context["data"] = harvest_data(args.machines, recipes)
args.output.write(template.render(context))