#!/usr/bin/python -t # -*- mode: Python; indent-tabs-mode: nil; -*- # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA import errno, os, sys import fnmatch, re import rpmUtils.transaction, rpmUtils.miscutils import Utils dryrun = False def pruneRepo(keep,whitelist,srcdir,bindirlist): ts = rpmUtils.transaction.initReadOnlyTransaction() changed = False # Create list of src.rpm files. # We don't use "glob", so sub-directories are supported. print 'Expiring (keep=%d):' % keep, srcdir if (keep<1): print " Are you kidding?" return changed srcfiles = [] for root, dirs, files in os.walk(srcdir): for f in fnmatch.filter(files,'*.src.rpm'): srcfiles.append(os.path.join(root,f)) for f in fnmatch.filter(files,'*.nosrc.rpm'): srcfiles.append(os.path.join(root,f)) if not len(srcfiles): print ' Nothing found.' return changed assert srcfiles[0].startswith(srcdir) # Create map: rpm %name -> list of tuples (filename,name,e,v,r) newestsrcrpms = {} for f in srcfiles: hdr = rpmUtils.miscutils.hdrFromPackage(ts,f) n = hdr['name'] v = hdr['version'] r = hdr['release'] e = hdr['epoch'] if e is None: e = 0 newestsrcrpms.setdefault(n,[]) newestsrcrpms[n].append((f,n,e,v,r)) # Now purge old src.rpm unless their %name matches a white-list pattern. for l in newestsrcrpms.values(): x = len(l) if x > 1: # White-listing. (f,n,e,v,r) = l[0] keepthis = False for r in whitelist: if re.compile(r).search(n): keepthis = True break if keepthis: print ' Skipping',n continue def sortByEVR(fnevr1, fnevr2): (f1,n1,e1,v1,r1) = fnevr1 (f2,n2,e2,v2,r2) = fnevr2 rc = rpmUtils.miscutils.compareEVR((e1,v1,r1),(e2,v2,r2)) if rc == 0: return 0 if rc > 0: return -1 if rc < 0: return 1 l.sort(sortByEVR) # highest first in list oldies = [] if len(l) > abs(keep): oldies = l[keep:] for (f,n,e,v,r) in oldies: print ' Removing', os.path.basename(f) srcfiles.remove(f) if not dryrun: os.remove(f) changed = True if not len(srcfiles): print 'WARNING: No src.rpms left. Stopping here.' return changed # Examine binary repository directories and remove everything which # is missing its corresponding src.rpm. for bindir in bindirlist: print 'Pruning:', bindir for root, dirs, files in os.walk(bindir): for f in fnmatch.filter(files,'*.rpm'): fullname = os.path.join(root,f) hdr = rpmUtils.miscutils.hdrFromPackage(ts,fullname) sourcerpm = hdr['sourcerpm'] if not sourcerpm: # At least source rpms in binary package dirs cause this. # TODO: maybe just remove them too? print 'WARNING: SRPM name N/A for %s, skipping' % f continue if not sourcerpm.endswith('.rpm'): print 'WARNING: unusual SRPM name for %s (%s), skipping' % (f, sourcerpm) continue if not os.path.join(srcdir,sourcerpm) in srcfiles: print ' Removing', f if not dryrun: os.remove(fullname) changed = True return changed def main(cfg,dist): assert rpmUtils.miscutils.compareEVR((1,2,3),(1,2,0)) > 0 assert rpmUtils.miscutils.compareEVR((0,1,2),(0,1,2)) == 0 assert rpmUtils.miscutils.compareEVR((1,2,3),(4,0,99)) < 0 if not hasattr(cfg,'repoprune_keepdict') or not cfg.repoprune_keepdict.has_key(dist): print 'WARNING: repoprune_keepdict undefined for %s' % dist return False keepdict = cfg.repoprune_keepdict[dist] if isinstance(keepdict,dict): keep = keepdict['keep'] whitelist = keepdict['whitelist'] else: # old style cfg where we cannot customise the 'keep' value keep = (dist == 'development') and 1 or 2 whitelist = keepdict srcdir = Utils.srpm_repodir(cfg,dist) bindirs = [] for arch in cfg.archdict[dist]: # list of repo archs bindirs.append( Utils.rpm_repodir(cfg,dist,arch) ) if dist == 'development': # hack for rawhide/releases repo path scheme bindirs.append( Utils.debug_repodir(cfg,dist,arch) ) return pruneRepo(keep,whitelist,srcdir,bindirs) if __name__ == '__main__': dryrun = ('--dry-run' in sys.argv) if dryrun: sys.argv.remove('--dry-run') if len(sys.argv) < 3: print 'Usage: %s [--dry-run] [release]...\n' % os.path.basename(sys.argv[0]) sys.exit(errno.EINVAL) cfg = Utils.load_config_module(sys.argv[1]) me = os.getcwd() Utils.signer_gid_check(cfg.signersgid) os.umask(cfg.signersumask) for dist in sys.argv[2:]: if not cfg.archdict.has_key(dist): print "No distribution release named '%s' found" % dist continue main(cfg,dist) os.chdir(me)