#!/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, gzip import fnmatch, re import rpmUtils.transaction, rpmUtils.miscutils import commands, libxml2 import string from dumpMetadata import byteranges from packagelist import RpmItem, DrpmItem, PackageList import gzip from zlib import error as zlibError from gzip import write32u, FNAME DRPMWORTHKEEPINGTHRESH=0.7 DEBUG=0 def getDeltaNevr(filename): """Get nevr for src rpm of a deltarpm. Return a tuple of (n, e, v, r)""" def _getLength(in_data): length = 0 for val in in_data: length = length * 256 length += ord(val) return length def _stringToVersion(strng): i = strng.find(':') if i != -1: epoch = strng[:i] else: epoch = '0' j = strng.find('-') if j != -1: if strng[i + 1:j] == '': version = None else: version = strng[i + 1:j] release = strng[j + 1:] else: if strng[i + 1:] == '': version = None else: version = strng[i + 1:] release = None return (epoch, version, release) def _stringToNEVR(string): i = string.rfind("-", 0, string.rfind("-")-1) name = string[:i] (epoch, ver, rel) = _stringToVersion(string[i+1:]) return (name, epoch, ver, rel) (range_start, range_end) = byteranges(filename) fd = open(filename, "r") fd.seek(range_end) try: compobj = gzip.GzipFile("", "rb", 9, fd) except: raise zlibError("Data not stored in gzip format") if compobj.read(4)[:3] != "DLT": raise Exception("Not a deltarpm") nevr_length = _getLength(compobj.read(4)) nevr = compobj.read(nevr_length).strip("\x00") oldnevr = _stringToNEVR(nevr) compobj.close() return oldnevr def getFileList(path, ext, filelist): """Return all files in path matching ext, store them in filelist, recurse dirs. Returns a list object""" extlen = len(ext) totalpath = os.path.normpath(path) try: dir_list = os.listdir(totalpath) except OSError, e: errorprint(_('Error accessing directory %s, %s') % (totalpath, e)) sys.exit(1) for d in dir_list: if os.path.isdir(totalpath + '/' + d): filelist = getFileList(os.path.join(totalpath, d), ext, filelist) elif string.lower(d[-extlen:]) == '%s' % (ext): filelist.append(os.path.join(totalpath, d)) return filelist def createPrestoRepo(base_dir, drpm_dir): ts = rpmUtils.transaction.initReadOnlyTransaction() changed = False # Create list of .rpm files. # We don't use "glob", so sub-directories are supported. print 'Using base dir: %s' % base_dir print 'Using destination dir: %s' % drpm_dir rpm_files = getFileList(base_dir, ".rpm", []) drpm_files = getFileList(base_dir, ".drpm", []) if not len(rpm_files): print ' Nothing found.' return changed # Check whether rel_dir exists, and if it doesn't, create it if not os.access(drpm_dir, os.F_OK): os.makedirs(drpm_dir, 0755) elif not os.access(drpm_dir, os.W_OK): print 'ERROR: Unable to write to %s' % drpm_dir sys.exit(1) # Add all rpms to PackageList rpm_list = PackageList(base_dir, drpm_dir, DRPMWORTHKEEPINGTHRESH, DEBUG) for f in rpm_files: try: hdr = rpmUtils.miscutils.hdrFromPackage(ts, f) except: print "Unable to open %s" % f else: nm = hdr['name'] + "." + hdr['arch'] e = hdr['epoch'] if e is None: e = "0" nevra = (hdr['name'], e, hdr['version'], hdr['release'], hdr['arch']) rpm = RpmItem(nevra, f) rpm_list.addRpm(rpm) # Add all deltarpms to PackageList for f in drpm_files: try: hdr = rpmUtils.miscutils.hdrFromPackage(ts, f) except: print "Unable to open %s" % f else: (sn, se, sv, sr) = getDeltaNevr(f) nm = hdr['name'] + "." + hdr['arch'] e = hdr['epoch'] if e is None: e = "0" dst_nevra = (hdr['name'], e, hdr['version'], hdr['release'], hdr['arch']) src_nevra = (sn, se, sv, sr, hdr['arch']) drpm = DrpmItem(src_nevra, dst_nevra, f) rpm_list.addDrpm(drpm) if DEBUG: rpm_list.dump() # Build deltarpms rpm_list.makeDeltaRpms() def main(bin_rpm_path, delta_rpm_path): 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 return createPrestoRepo(bin_rpm_path, delta_rpm_path) if __name__ == '__main__': if len(sys.argv) < 2: print 'Usage: %s \n' % os.path.basename(sys.argv[0]) sys.exit(errno.EINVAL) bin_rpm_path = sys.argv[1] delta_rpm_path = sys.argv[2] main(bin_rpm_path, delta_rpm_path) sys.exit(0)