#!/usr/bin/env python # pkg # Copyright (C) 2021-present Michael Serajnik https://sr.ht/~mser/ # Copyright (C) 2021-present Chris Braun https://github.com/cryzed # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . import argparse import enum import os import pathlib import shutil import subprocess import sys import typing as T BASE_PATH = pathlib.Path(sys.argv[0]).parent.resolve() PACKAGES_PATH = BASE_PATH / "packages" REPOSITORY_PATH = BASE_PATH / "repository" PathType = T.Union[str, os.PathLike] class ExitCode(enum.IntEnum): SUCCESS = 0 FAILURE = 1 def get_argument_parser() -> argparse.ArgumentParser: parser = argparse.ArgumentParser( formatter_class=argparse.ArgumentDefaultsHelpFormatter ) return parser def get_path(path: PathType) -> pathlib.Path: return path if isinstance(path, pathlib.Path) else pathlib.Path(path) def get_all_packages() -> set[str]: return {path.name for path in PACKAGES_PATH.glob("*")} def get_updated_packages( git_repo_path: PathType = pathlib.Path().resolve(), ) -> set[str]: process = subprocess.run( ["git", "log", "-1", "--name-only", "--oneline"], cwd=git_repo_path, stdout=subprocess.PIPE, text=True, ) packages = set() for line in process.stdout.splitlines(): if not (line := line.strip()): continue path = pathlib.Path(line) if len(path.parts) >= 2 and path.parts[0] == "packages": package_name = path.parts[1] packages.add(package_name) return packages def get_vcs_packages() -> set[str]: return {path.name for path in PACKAGES_PATH.glob("*-git")} def build_package(package_name: str) -> None: package_dir = PACKAGES_PATH / package_name subprocess.run( ["makepkg", "-fsc", "--needed", "--noconfirm"], cwd=package_dir, stdout=sys.stdout, stderr=sys.stderr, check=True, ) def move_package(package_name: str) -> None: package_dir = PACKAGES_PATH / package_name for package in package_dir.glob("*.pkg.tar.zst"): # Don't use pathlib.Path.rename() here, because we might be moving across filesystem boundaries shutil.move(str(package), REPOSITORY_PATH) def run(arguments: argparse.Namespace) -> ExitCode: PACKAGES_PATH.mkdir(parents=True, exist_ok=True) REPOSITORY_PATH.mkdir(parents=True, exist_ok=True) force_rebuild_packages = os.getenv("FORCE_REBUILD_PACKAGES") packages = ( get_all_packages() if force_rebuild_packages is not None else get_updated_packages() ) rebuild_only_vcs_packages = os.getenv("REBUILD_ONLY_VCS_PACKAGES") if rebuild_only_vcs_packages: packages = get_vcs_packages() for package in packages: print(f"Building {package}…") build_package(package) move_package(package) return ExitCode.SUCCESS def main() -> None: parser = get_argument_parser() arguments = parser.parse_args() parser.exit(run(arguments)) if __name__ == "__main__": main()