#!/usr/bin/python # dynrepo.py: # Monitor set of RPMs in a directory. # # Licensed under the new-BSD license (http://www.opensource.org/licenses/bsd-license.php) # Copyright (C) 2010 Red Hat, Inc. # Written by Colin Walters import os import sys import logging import glib import gio import rpm import rpmUtils import rpmUtils.miscutils from . import subtask class Repo(object): def __init__(self, dirpath): self._dir = dirpath self._dir_gfile = gio.File(path=dirpath) self._monitor = self._dir_gfile.monitor(gio.FILE_MONITOR_NONE) self._monitor.connect('changed', self._on_dir_changed) self._rpms = {} def get_rpms(self): return self._rpms def get_rpms_for_name(self, name, arch): result = [] for filename,(n,a,e,v,r) in self._rpms.iteritems(): if n == name and (arch is None or a == arch): result.append((filename, n, a, e, v, r)) return result def get_latest_srpm_for_name(self, name): rpms = self.get_rpms_for_name(name, 'src') cmpevr=rpmUtils.miscutils.compareEVR if rpms: rpms.sort(lambda a,b: cmpevr(a[3:6], b[3:6])) return rpms[-1] return None def add_srpm(self, srpm_path): basename = os.path.basename(srpm_path) os.link(srpm_path, os.path.join(self._dir, basename)) def _delete_old_rpms_in_dir(self, dirpath): output = subtask.spawn_sync_get_output('srpm-repomanage', ['repomanage', '-o', '.'], cwd=dirpath) for line in output.split('\n'): if line.endswith('.rpm') and os.path.exists(line): os.unlink(line) def update_repo_sync(self): self._delete_old_rpms_in_dir(self._dir) subtask.spawn_sync('srpm-createrepo', ['createrepo', '.'], cwd=self._dir) def _headers_from_packages(self, rpmlist): result = {} ts = rpm.TransactionSet() ts.setVSFlags(~(rpm._RPMVSF_NOPAYLOAD)) for pkg in rpmlist: pkg_path = os.path.join(self._dir, pkg) try: header = rpmUtils.miscutils.hdrFromPackage(ts, pkg_path) except rpmUtils.RpmUtilsError, e: logging.exception(e) continue (n,a,e,v,r) = rpmUtils.miscutils.pkgTupleFromHeader(header) del header result[pkg] = (n,a,e,v,r) return result def _on_dir_changed(self, mon, gfile, other, event): self._reload() def _reload(self): dir_contents = os.listdir(self._dir) messages = set() rpmlist = set() for filename in dir_contents: if filename.endswith('.tmp'): continue if not filename.endswith('.rpm'): continue rpmlist.add(filename) deleted = [] for rpm in self._rpms: if rpm not in rpmlist: deleted.add(rpm) for rpm in deleted: del self._rpms[rpm] new = [] for rpm in self._rpms: if rpm not in rpmlist: new.append(rpm) for rpm,data in self._headers_from_packages(new).iteritems(): self._rpms[rpm] = data