#!/usr/bin/env python3 # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 import sys import dnf import hawkey import signal import os import json base = None def get_sack(): global base if base is None: base = dnf.Base() base.read_all_repos() base.fill_sack() return base.sack # FIXME: leaks memory and does not work def flushcache(): try: os.remove('/var/cache/dnf/@System.solv') except OSError: pass get_sack().load_system_repo(build_cache=True) def versioncompare(versions): sack = get_sack() if (versions[0] is None) or (versions[1] is None): sys.stdout.write('0\n') else: evr_comparison = sack.evr_cmp(versions[0], versions[1]) sys.stdout.write('{}\n'.format(evr_comparison)) def query(command): sack = get_sack() subj = dnf.subject.Subject(command['provides']) q = subj.get_best_query(sack, with_provides=True) if command['action'] == "whatinstalled": q = q.installed() if command['action'] == "whatavailable": q = q.available() if 'epoch' in command: q = q.filterm(epoch=int(command['epoch'])) if 'version' in command: q = q.filterm(version__glob=command['version']) if 'release' in command: q = q.filterm(release__glob=command['release']) if 'arch' in command: q = q.filterm(arch__glob=command['arch']) # only apply the default arch query filter if it returns something archq = q.filter(arch=[ 'noarch', hawkey.detect_arch() ]) if len(archq.run()) > 0: q = archq pkgs = q.latest(1).run() if not pkgs: sys.stdout.write('{} nil nil\n'.format(command['provides'].split().pop(0))) else: # make sure we picked the package with the highest version pkgs.sort pkg = pkgs.pop() sys.stdout.write('{} {}:{}-{} {}\n'.format(pkg.name, pkg.epoch, pkg.version, pkg.release, pkg.arch)) # the design of this helper is that it should try to be 'brittle' and fail hard and exit in order # to keep process tables clean. additional error handling should probably be added to the retry loop # on the ruby side. def exit_handler(signal, frame): sys.exit(0) signal.signal(signal.SIGINT, exit_handler) signal.signal(signal.SIGHUP, exit_handler) signal.signal(signal.SIGPIPE, exit_handler) while 1: # kill self if we get orphaned (tragic) ppid = os.getppid() if ppid == 1: sys.exit(0) line = sys.stdin.readline() command = json.loads(line) if command['action'] == "whatinstalled": query(command) elif command['action'] == "whatavailable": query(command) elif command['action'] == "flushcache": flushcache() elif command['action'] == "versioncompare": versioncompare(command['versions']) else: raise RuntimeError("bad command")