#!/usr/bin/env python3 import hashlib import json import os import re import subprocess import yaml def _load_stdout(args): p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) p.wait() result = p.stdout.read() if p.returncode != 0: raise RuntimeError("Process crashed with " + repr(p.returncode) + ". Args: " + repr(args)) return result _moduleFiles = {} class ModuleLoader(): path = str content = dict __hash_find = re.compile(".*WB_HASH\\=\\'(?P[a-zA-Z0-9]*)\\'.*") def __module(self, modules): for iID in range(len(modules)): i = modules[iID] if isinstance(i, str): i = self.relative(i) if i in _moduleFiles: tmp = _moduleFiles[i] else: tmp = ModuleLoader(i) modules[iID] = tmp.content else: if "modules" in i: self.__module(i["modules"]) def __init__(self, source): if not isinstance(source, str): raise ValueError("source have to be string. It was a " + repr(source) + ".") self.path = os.path.abspath(source) _moduleFiles[self.path] = self self.content = yaml.load(open(self.path, "r").read(), Loader=yaml.SafeLoader) if "modules" in self.content: self.__module(self.content["modules"]) def hash(self, function): tmp = json.dumps(self.content, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, indent=None, separators=("", ""), default=None, sort_keys=True) tmp = tmp.encode("utf-8") return function(tmp) def gen_base_version(self, arch): version = self.content["runtime-version"] sdk = _load_stdout(["flatpak", "info", "-c", "--arch=" + arch, "--user", self.content["sdk"], version]) platform = _load_stdout(["flatpak", "info", "-c", "--arch=" + arch, "--user", self.content["runtime"], version]) sdk = sdk.splitlines()[0] platform = platform.splitlines()[0] return sdk, platform def get_depends(self, arch): version_src = "/" + arch + "/" + self.content["runtime-version"] version_target = "/" + arch + "/" + self.content["branch"] result = [self.content["sdk"] + version_src, self.content["runtime"] + version_src, self.content["id"] + version_target, self.content["id-platform"] + version_target] return result def get_old_hash(self, arch): vers = self.content["branch"] try: hash_sdk = _load_stdout(["flatpak", "info", "--arch=" + arch, "--user", self.content["id"], vers]) hash_platform = _load_stdout(["flatpak", "info", "--arch=" + arch, "--user", self.content["id-platform"], vers]) if b"WB_HASH=" in hash_sdk: hash_sdk = hash_sdk[hash_sdk.find(b"WB_HASH="):] hash_sdk = self.__hash_find.match(hash_sdk.decode()) if hash_sdk is None: hash_sdk = "--None--" else: hash_sdk = hash_sdk.groupdict()["hash"] if b"WB_HASH=" in hash_platform: hash_platform = hash_platform[hash_platform.find(b"WB_HASH="):] hash_platform = self.__hash_find.match(hash_platform.decode()) if hash_platform is None: hash_platform = "--None--" else: hash_platform = hash_platform.groupdict()["hash"] return hash_sdk, hash_platform except RuntimeError: return "--None--", "--None--" def relative(self, file): return os.path.abspath(os.path.join(os.path.split(self.path)[0], file)) def get_hashes(source, arch): mod = ModuleLoader(source) parent_ids = b" ".join(mod.gen_base_version(arch)) + b" " # Hash config def hash_methode(hashclass): def func(data): tmp = hashclass() tmp.update(parent_ids) tmp.update(data) return tmp.hexdigest() return func own = mod.hash(hash_methode(hashlib.sha3_512)).upper() # Get old hash old1, old2 = mod.get_old_hash(args.arch[0]) return own, old1, old2 def get_depends(source, arch): mod = ModuleLoader(source) return mod.get_depends(arch) if __name__ == '__main__': import argparse # Parse config parser = argparse.ArgumentParser(description="Generate hash of a module.") parser.add_argument("file", metavar="file", type=str, nargs=1, help="File configuration to generate hash.") parser.add_argument("arch", metavar="arch", type=str, nargs=1, help="The arch to build.") parser.add_argument("--depends", dest="dependes", action="store_const", const=True, default=False, help="List source runtime.") args = parser.parse_args() if args.dependes: print("\n".join(get_depends(args.file[0], args.arch[0]))) else: print("\n".join(get_hashes(args.file[0], args.arch[0])))