diff options
Diffstat (limited to 'rpmci/dynrepo.py')
-rw-r--r-- | rpmci/dynrepo.py | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/rpmci/dynrepo.py b/rpmci/dynrepo.py new file mode 100644 index 0000000..e6cdc90 --- /dev/null +++ b/rpmci/dynrepo.py @@ -0,0 +1,104 @@ +#!/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 <walters@verbum.org> + +import os +import sys +import logging + +import glib +import rpm +import rpmUtils +import rpmUtils.miscutils + +from . import async_subprocess + +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) + + 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): + proc = popen_verbose(['repomanage', '-o', '.'], stdout=subprocess.PIPE, + stderr=sys.stderr, + cwd=dirpath) + output = proc.communicate()[0] + 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(dirpath) + subprocess.check_call(['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._dirpath) + 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 |