#!/usr/bin/env python3 import argparse import csv import logging import json from pathlib import Path import pickle import git import sarge class GitHashCache: def __init__(self, cache_file): self.cache = cache_file self._data = dict() def __getitem__(self, key): if key not in self._data: return "" return self._data[key] def __setitem__(self, key, value): self._data[key] = value def get(self, key, *args, **kwargs): return self._data.get(key, *args, **kwargs) def save(self): logging.debug("Saving pickled data") with open(self.cache, "wb") as handle: pickle.dump(self._data, handle, pickle.HIGHEST_PROTOCOL) def load(self): if not Path(self.cache).exists(): logging.debug("File cache not found, not loading") return logging.debug("Saving pickled data") with open(self.cache, "rb") as handle: self._data = pickle.load(handle) def to_json(self): with Path(self.cache).with_suffix(".json").open("w") as handle: json.dump(self._data, handle, indent=4) def lsremote(url): remote_refs = {} g = git.cmd.Git() for ref in g.ls_remote(url).split('\n'): hash_ref_list = ref.split('\t') remote_refs[hash_ref_list[1]] = hash_ref_list[0] return remote_refs def get_remote_hash(url, branch="master"): refs = "refs/heads/{}".format(branch) return lsremote(url)[refs] def run_osc(repository, package_name): cmd = "osc service remoterun {0} {1}" cmd = cmd.format(repository, package_name) logging.debug("Running {}".format(cmd)) logging.info("Updating package {0}".format(package_name)) pid = sarge.run(cmd) if pid.returncode != 0: logging.error("Error during service run, package {}".format( package_name)) logging.debug("Package {} complete".format(package_name)) def update_package(hash_data, package_name, remote_name, obs_repository, branch): repo_name = "kde:{}".format(remote_name) remote_hash = get_remote_hash(repo_name, branch) repo_hashes = hash_data.get(obs_repository) if hash_data.get(obs_repository) is None: logging.debug("No prior data - initializing empty") hash_data[obs_repository] = dict() current_hash = hash_data[obs_repository].get(remote_name, "") logging.debug("Package {}, theirs {}, ours {}".format(remote_name, remote_hash, current_hash)) if remote_hash != current_hash: logging.debug("Hash doesn't match, updating") run_osc(obs_repository, package_name) hash_data[obs_repository][remote_name] = remote_hash hash_data.save() hash_data.to_json() def update_packages(cache_file, repo_mapping_file): hash_data = GitHashCache(cache_file) hash_data.load() with open(repo_mapping_file, "r") as mapping: repo_data = json.load(mapping) for obs_repository, branch_data in repo_data.items(): logging.info("Updating packages for {}".format(obs_repository)) for package in branch_data: kde_name = package["kde"] obs_name = package["obs"] branch = package["branch"] logging.debug("Updating package {} ({})".format(kde_name, obs_name)) logging.debug("Using branch {}".format(branch)) update_package(hash_data, obs_name, kde_name, obs_repository, branch) logging.debug("Saving data") hash_data.save() hash_data.to_json() def main(): parser = argparse.ArgumentParser() parser.add_argument("mapping_file", help="KDE:OBS repository mapping file") parser.add_argument("--debug", help="Show debugging output", action="store_true") options = parser.parse_args() level = logging.INFO if not options.debug else logging.DEBUG logging.basicConfig(format='%(levelname)s - %(message)s', level=level) cache_file = Path.home() / ".local/share/obs_repo_cache.cache" cache_file = str(cache_file) update_packages(cache_file, options.mapping_file) logging.info("Complete") if __name__ == "__main__": main()