| #!/usr/bin/env python3 | 
 |  | 
 | import argparse | 
 | import datetime | 
 | import os | 
 | import shutil | 
 | import subprocess | 
 | import sys | 
 | import tempfile | 
 | from jinja2 import Environment, FileSystemLoader | 
 |  | 
 |  | 
 | def version_str() -> str: | 
 |     try: | 
 |         return subprocess.check_output(["git", "describe"]).strip().decode("utf-8") | 
 |     except subprocess.CalledProcessError: | 
 |         return "0" | 
 |  | 
 |  | 
 | def prep_tree(package) -> tuple: | 
 |     tmpdir = tempfile.mkdtemp() | 
 |     builddir = os.path.join(tmpdir, package) | 
 |     fwdir = os.path.join(builddir, "updates") | 
 |     targetdir = "dist" | 
 |  | 
 |     os.makedirs(targetdir, exist_ok=True) | 
 |     os.makedirs(builddir, exist_ok=False) | 
 |     os.makedirs(fwdir, exist_ok=False) | 
 |  | 
 |     subprocess.check_output(["./copy-firmware.sh", fwdir]) | 
 |     shutil.copy("WHENCE", os.path.join(builddir, "WHENCE")) | 
 |  | 
 |     return (tmpdir, builddir, fwdir, targetdir) | 
 |  | 
 |  | 
 | def build_deb_package(package, builddir) -> None: | 
 |     env = Environment(loader=FileSystemLoader(os.path.join("contrib", "templates"))) | 
 |  | 
 |     d = { | 
 |         "package": package, | 
 |         "date": datetime.datetime.now() | 
 |         .astimezone() | 
 |         .strftime("%a, %d %b %Y %H:%M:%S %z"), | 
 |         "version": version_str(), | 
 |     } | 
 |  | 
 |     templates = { | 
 |         "debian.control": "control", | 
 |         "debian.changelog": "changelog", | 
 |         "debian.copyright": "copyright", | 
 |     } | 
 |  | 
 |     os.makedirs(os.path.join(builddir, "debian")) | 
 |     for f in templates: | 
 |         template = env.get_template(f) | 
 |         with open(os.path.join(builddir, "debian", templates[f]), "w") as w: | 
 |             w.write(template.render(d)) | 
 |  | 
 |     with open(os.path.join(builddir, "debian", "install"), "w") as w: | 
 |         w.write("updates lib/firmware\n") | 
 |  | 
 |     with open(os.path.join(builddir, "debian", "docs"), "w") as w: | 
 |         w.write("WHENCE\n") | 
 |  | 
 |     with open(os.path.join(builddir, "debian", "rules"), "w") as w: | 
 |         w.write("#!/usr/bin/make -f\n") | 
 |         w.write("%:\n") | 
 |         w.write("\tdh $@\n") | 
 |     os.chmod(os.path.join(builddir, "debian", "rules"), 0o755) | 
 |  | 
 |     os.mkdir(os.path.join(builddir, "debian", "source")) | 
 |     with open(os.path.join(builddir, "debian", "source", "format"), "w") as w: | 
 |         w.write("3.0 (native)\n") | 
 |  | 
 |     # build the package | 
 |     os.environ["DEB_BUILD_OPTIONS"] = "nostrip" | 
 |     subprocess.check_output(["dpkg-buildpackage", "-us", "-uc", "-b"], cwd=builddir) | 
 |  | 
 |     # result is in tmpdir (not builddir!) | 
 |     return os.path.join( | 
 |         "..", | 
 |         "{package}_{version}_all.deb".format(package=package, version=version_str()), | 
 |     ) | 
 |  | 
 |  | 
 | def build_rpm_package(package, builddir) -> None: | 
 |  | 
 |     v = version_str().replace("-", "_") | 
 |     env = Environment(loader=FileSystemLoader(os.path.join("contrib", "templates"))) | 
 |  | 
 |     d = { | 
 |         "package": package, | 
 |         "version": v, | 
 |         "cwd": builddir, | 
 |     } | 
 |  | 
 |     template = env.get_template("rpm.spec") | 
 |     with open(os.path.join(builddir, "package.spec"), "wt") as w: | 
 |         w.write(template.render(d)) | 
 |     cmd = ["rpmbuild", "-bb", "--build-in-place", "package.spec"] | 
 |     subprocess.check_call(cmd, cwd=builddir, stderr=subprocess.STDOUT) | 
 |  | 
 |     # result is in ~/rpmbuild/RPMS/noarch/ | 
 |     for root, dirs, files in os.walk( | 
 |         os.path.join(os.getenv("HOME"), "rpmbuild", "RPMS", "noarch") | 
 |     ): | 
 |         for f in files: | 
 |             if f.startswith(package) and f.endswith(".rpm") and v in f: | 
 |                 return os.path.join(root, f) | 
 |     raise FileNotFoundError("RPM package not found") | 
 |  | 
 |  | 
 | def parse_args(): | 
 |     parser = argparse.ArgumentParser("Build upstream packages using Jinja2 templates") | 
 |     parser.add_argument("--deb", help="Build DEB package", action="store_true") | 
 |     parser.add_argument("--rpm", help="Build RPM package", action="store_true") | 
 |     parser.add_argument("--debug", help="Enable debug output", action="store_true") | 
 |     args = parser.parse_args() | 
 |  | 
 |     if not (args.rpm or args.deb) or (args.rpm and args.deb): | 
 |         parser.print_help() | 
 |         sys.exit(1) | 
 |  | 
 |     return args | 
 |  | 
 |  | 
 | if __name__ == "__main__": | 
 |     args = parse_args() | 
 |  | 
 |     package = "linux-firmware-upstream" | 
 |     tmpdir, builddir, fwdir, targetdir = prep_tree(package) | 
 |  | 
 |     try: | 
 |         if args.deb: | 
 |             result = build_deb_package(package, builddir) | 
 |         elif args.rpm: | 
 |             result = build_rpm_package(package, builddir) | 
 |         shutil.copy(os.path.join(builddir, result), targetdir) | 
 |         print( | 
 |             "Built package: {}".format( | 
 |                 os.path.join(targetdir, os.path.basename(result)) | 
 |             ) | 
 |         ) | 
 |     finally: | 
 |         if not args.debug: | 
 |             shutil.rmtree(tmpdir) |