[svn] r4742 - trunk/tools/yam/patches

packagers at lists.rpmforge.net packagers at lists.rpmforge.net
Tue Sep 19 08:47:29 CEST 2006


Author: dag
Date: 2006-09-19 08:47:27 +0200 (Tue, 19 Sep 2006)
New Revision: 4742

Added:
   trunk/tools/yam/patches/yam-0.8.0-add_delete_to_rhn_download.patch
   trunk/tools/yam/patches/yam-0.8.0-symlinksync.patch
Log:
Added 2 important patches pending a merge

Added: trunk/tools/yam/patches/yam-0.8.0-add_delete_to_rhn_download.patch
===================================================================
--- trunk/tools/yam/patches/yam-0.8.0-add_delete_to_rhn_download.patch	                        (rev 0)
+++ trunk/tools/yam/patches/yam-0.8.0-add_delete_to_rhn_download.patch	2006-09-19 06:47:27 UTC (rev 4742)
@@ -0,0 +1,107 @@
+From: Tim Verhoeven
+Date: Sat, 10 Jun 2006 15:21:01 +0200
+Subject: Yam : patch om deletes te doen bij downloads van rhn
+--- /usr/bin/yam	2006-03-10 12:17:38.000000000 +0100
++++ ./yam.new	2006-06-10 15:13:07.000000000 +0200
+@@ -16,6 +16,7 @@
+ 
+ import os, sys, glob, re, shutil, getopt, popen2
+ import ConfigParser, urlparse, sha, types
++import rpm, fnmatch
+ 
+ VERSION = "0.8.0"
+ 
+@@ -822,6 +823,14 @@
+ 			}
+ 	return None
+ 
++def rpmOutToStr(arg):
++	# Convert output from rpm headers to a string if needed
++    if type(arg) != types.StringType:
++    	# and arg is not None:
++        arg = str(arg)
++
++    return arg
++
+ def mirrorrhn(url, path, dist):
+ 	'Mirror a channel from RHN'
+ 	global cfg, loginInfo, rd, repoDirector, rpcServer
+@@ -875,9 +884,52 @@
+ 		error(0, 'Error listing packages from channel %s. Skipping.\n%s' % (label, e))
+ 		return
+ 
++	### Prepare directory listing, used to see if we need to delete anything
++
++	# Get listing of already present RPM packages
++	listing = os.listdir(path)
++	listing = fnmatch.filter(listing, '*rpm')
++	current_packages = []
++
++	# Initialize RPM transaction set to process the RPM packages
++	ts = rpm.ts()
++	ts.setVSFlags(-1)
++
++	# Pares each file and get filename, package name, epoch, version and release
++	for fname in listing:
++		try:
++			fd = os.open(os.path.join(path, fname), os.O_RDONLY)
++		except:
++			# ignore non-files
++			continue
++		# Read RPM header from the opened file
++		h = ts.hdrFromFdno(fd)
++		os.close(fd)
++
++		# strip the strings from header.
++		# XXX rpm.RPMTAG_FOO is slightly faster than 'foo', less readable
++		# XXX no matter what there's a bsearch on access
++		pname = rpmOutToStr(h['name'])
++		EVR = (rpmOutToStr(h['epoch']),rpmOutToStr(h['version']),rpmOutToStr(h['release']))
++		arch = h['arch']
++		del h		# XXX dump the header soonest, avoid bloat
++
++		# Add header info to the current_packages dict
++		#print 'Filename %s, packagename %s, arch %s, version %s' % (fname, pname, arch, EVR)
++		current_packages.append(dict([('fname', fname), ('pname', pname), ('arch', arch), ('EVR', EVR)]))
++
++	# Some cleanup
++	del listing
++
+ 	### Download packages from the packagelist
+ 	signal.signal(signal.SIGINT, signal.SIG_DFL)
+ 	for pkg in package_list:
++		# amount of packages to keep including the one that will be downloaded
++		keep = 2
++		# check if th keep variable is large enough
++		if keep < 1:
++			error(0, 'The keep variable is to small, current value is %d, minimum is 1' % (keep))
++			sys.exit(1)
+ 		### FIXME: Check if not already on ISO-file or repository as well
+ 		filename = '%s-%s-%s.%s.rpm' % (pkg[0], pkg[1], pkg[2], pkg[4])
+ 		if os.path.isfile(os.path.join(path, filename)):
+@@ -888,6 +940,25 @@
+ 			else:
+ 				info(4, 'File %s has wrong size (found: %s, expected: %s), refetching.' % (filename, stat.st_size, pkg[5]))
+ 				remove(os.path.join(path, filename))
++		# Get list of local packages on the filesystem for the current package
++		local_packages = [d for d in current_packages if d.get('pname', None)==pkg[0]]
++		# Sort list of local packages according to version (EVR) key
++		decorated = [(dict_['EVR'], dict_) for dict_ in local_packages]
++		decorated.sort(lambda x,y: rpm.labelCompare(x[0],y[0]))
++		local_packages = [dict_ for (key, dict_) in decorated]
++		# If we have more local packages we want to keep we are going to delete some
++		if (len(local_packages) + 1) > keep:
++			# Remove from the local_packages list the packages we don't want to delete
++			for i in range(keep - 1 ):
++				local_packages.pop()
++			# The actual delete
++			for pkg in local_packages:
++				file = pkg['fname']
++				if op.dryrun:
++					info(3, 'Not removing file %s' % (os.path.join(path,file)))
++				else:
++					info(3, 'Removing file %s' % (os.path.join(path,file)))
++					os.remove(os.path.join(path, file))
+ 		if op.dryrun:
+ 			info(3, 'Not downloading package %s' % filename)
+ 			continue

Added: trunk/tools/yam/patches/yam-0.8.0-symlinksync.patch
===================================================================
--- trunk/tools/yam/patches/yam-0.8.0-symlinksync.patch	                        (rev 0)
+++ trunk/tools/yam/patches/yam-0.8.0-symlinksync.patch	2006-09-19 06:47:27 UTC (rev 4742)
@@ -0,0 +1,222 @@
+From: Alexander Bergolth
+Date: Sun, 14 May 2006 01:37:32 +0200
+Subject: [tools] yam patch: synchronize symlinks rather than deleting and recreating them
+
+From: Alexander 'Leo' Bergolth
+Date: Mon, 19 Jun 2006 23:06:58 +0200
+Subject: Re: [tools] yam patch: synchronize symlinks rather than deleting and recreating them
+--- yam.orig	2006-05-13 23:05:41.024640140 +0200
++++ yam	2006-05-14 01:16:06.984394796 +0200
+@@ -14,6 +14,7 @@
+ ### Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ ### Copyright 2004-2006 Dag Wieers <dag at wieers.com>
+ 
++from __future__ import generators # for Python 2.2
+ import os, sys, glob, re, shutil, getopt, popen2, socket
+ import ConfigParser, urlparse, sha, types, traceback
+ 
+@@ -512,16 +513,80 @@
+ 		symlink(os.path.join(cf.htmldir, 'HEADER.repo.shtml'), os.path.join(self.dir, 'HEADER.shtml'))
+ 		symlink(os.path.join(cf.htmldir, 'README.repo.shtml'), os.path.join(self.dir, 'README.shtml'))
+ 
+-	def link(self, srcdir, repo):
+-		"Symlink all RPM packages that match a given arch"
+-		info(5, '%s: Symlink %s packages from %s' % (self.nick, repo, srcdir))
+-		mkdir(os.path.join(self.dir, 'RPMS.' + repo))
+-		mkdir(os.path.join(self.dir, 'RPMS.all'))
+-		os.path.walk(srcdir, rpmlink, (self, repo))
+-
+-	def clean(self, repo):
+-		info(5, '%s: Removing %s' % (self.nick, repo))
+-		remove(glob.glob(os.path.join(self.dir, 'RPMS.' + repo, '*.rpm')))
++        def linksync(self, srcdir):
++            # dist.linksync(os.path.join(cf.srcdir, dist.nick))
++            repos = self.repos.keys()
++            repos.sort()
++            allsrcdirs = []
++            for repo in repos:
++                reposrcdir = os.path.join(srcdir, self.nick, repo)
++                if not (repo in ['os', 'core'] and self.isos()):
++                    self.linksyncrepo(repo, reposrcdir)
++                    allsrcdirs.append(reposrcdir)
++
++            if self.isos():
++                srcdirs = [ os.path.join(self.dir, disc) for disc in self.discs ]
++                self.linksyncrepo('os', *srcdirs)
++                self.repos['os'] = None
++                allsrcdirs.extend(srcdirs)
++
++            ### Link custom local packages
++            reposrcdir = os.path.join(srcdir, self.nick, 'local')
++            if os.path.exists(reposrcdir):
++                self.linksyncrepo('local', reposrcdir)
++                allsrcdirs.append(reposrcdir)
++
++            reposrcdir = os.path.join(srcdir, 'all', 'local')
++            if os.path.exists(reposrcdir):
++                self.linksyncrepo('local', reposrcdir)
++                allsrcdirs.append(reposrcdir)
++
++            self.linksyncrepo('all', *allsrcdirs)
++
++        def linksyncrepo(self, repo, *srcdirs):
++            srcfiles = listrpms(*srcdirs)
++            srcfiles.sort()
++
++            destdir = os.path.join(self.dir, 'RPMS.' + repo)
++            info(4, 'creating links in %s to directories %s' % ( destdir, srcdirs ))
++            mkdir(os.path.join(self.dir, 'RPMS.' + repo))
++            
++            destfiles = listrpms(destdir)
++            # destfiles are tuples of (link, link target)
++            readlink = os.readlink
++            def linkdest(file):
++                try:
++                    return (file, readlink(file))
++                except OSError:
++                    return (file, False)
++            destfiles = map(linkdest, destfiles)
++            destfiles.sort(lambda x, y: cmp(x[1], y[1]))
++
++            for srcfile, destfile, tid in synciter(srcfiles, destfiles,
++                                                   keyb = lambda f: f[1]): # link target
++                if srcfile is None:
++                    # delete the link
++                    linkfile, target = destfile
++                    # info(5, 'Remove link: %s' % ( linkfile, ))
++                    if not op.dryrun:
++                        os.unlink(linkfile)
++                if destfile is None:
++                    # create a new link
++                    linkname = os.path.join(destdir, os.path.basename(srcfile))
++                    # for RPMS.all
++                    if os.path.exists(linkname):
++                        # file or non-broken symlink
++                        info(3, "File %s in more than one repo!" %\
++                             ( os.path.basename(linkname), ))
++                    else:
++                        if os.path.islink(linkname):
++                            # broken symlink
++                            if not op.dryrun:
++                                os.unlink(linkname)
++                        #info(5, 'Link: %s, %s' % ( srcfile, linkname ))
++                        if not op.dryrun:
++                            os.symlink(srcfile, linkname)
++
+ 
+ def sha1dir(dir):
+ 	"Return sha1sum of a directory"
+@@ -1000,6 +1065,71 @@
+ 	symlink(cf.htmldir + '/HEADER.index.shtml', cf.wwwdir + '/HEADER.shtml')
+ 	symlink(cf.htmldir + '/README.index.shtml', cf.wwwdir + '/README.shtml')
+ 
++
++class NoneIterator(object):
++    "Iterator with an additional nextNone method"
++    def __init__(self, o):
++        self.iterator = iter(o)
++    def __iter__(self):
++        return self
++    def next(self):
++        return self.iterator.next()
++    def nextNone(self):
++        "returns None instead of raising StopIteration at the end"
++        try:
++            return self.iterator.next()
++        except StopIteration:
++            return None
++
++def synciter(a, b, key = None, keya = None, keyb = None):
++    if key is None:
++        key = lambda x: x
++    if keya is None:
++        keya = key
++    if keyb is None:
++        keyb = key
++    ai = NoneIterator(a)
++    anext = ai.nextNone
++    bi = NoneIterator(b)
++    bnext = bi.nextNone
++    aelem = anext()
++    belem = bnext()
++    while not ((aelem is None) or (belem is None)):
++        akey = keya(aelem)
++        bkey = keyb(belem)
++        if akey == bkey:
++            yield aelem, belem, akey
++            aelem = anext()
++            belem = bnext()
++        elif akey > bkey:
++            # belem missing in a
++            yield None, belem, bkey
++            belem = bnext()
++        elif bkey > akey:
++            # aelem missing in b
++            yield aelem, None, akey
++            aelem = anext()
++    # rest
++    while aelem is not None:
++        akey = key(aelem)
++        yield aelem, None, akey
++        aelem = anext()
++    while belem is not None:
++        bkey = key(belem)
++        yield None, belem, bkey
++        belem = bnext()
++
++def listrpms(*dirs):
++    rpms = []
++    listdir = os.listdir
++    pathjoin = os.path.join
++    for dir in dirs:
++        files = filter(lambda f: f.endswith('.rpm'), listdir(dir))
++        files = [ pathjoin(dir, f) for f in files ]
++        rpms.extend(files)
++    return rpms
++
++
+ def main():
+ 	### Check availability of commands
+ 	for cmd in cf.cmd.keys():
+@@ -1057,40 +1187,8 @@
+ 			info(1, '%s: Generating %s meta-data' % (dist.nick, dist.name))
+ 			dist.html()
+ 
+-			info(2, '%s: Cleaning repositories' % dist.nick)
+-			dist.clean('all')
+-			if dist.isos():
+-				dist.clean('os')
+-			for repo in dist.repos.keys():
+-				dist.clean(repo)
+-			dist.clean('local')
+-
+ 			info(2, '%s: Symlinking packages' % dist.nick)
+-			for repo in dist.repos.keys():
+-				srcdir = os.path.join(cf.srcdir, dist.nick, repo)
+-				if repo in ['os', 'core']:
+-					if not dist.isos():
+-						dist.link(srcdir, repo)
+-				else:
+-					dist.link(srcdir, repo)
+-
+-			if dist.isos():
+-				for disc in dist.discs:
+-					dist.link(os.path.join(dist.dir, disc), 'os')
+-					dist.repos['os'] = None
+-
+-			### FIXME: should remove identical files from cf.srcdir + '/updates/' + dist + '/*.rpm'
+-			### Maybe add a hardlink utility for cleaning up afterwards
+-	#		os.remove(cf.srcdir + '/updates/' + dist + '/' + os.path.basename(file))
+-
+-			### Link custom local packages
+-			srcdir = os.path.join(cf.srcdir, dist.nick, 'local')
+-			if os.path.exists(srcdir):
+-				dist.link(srcdir, 'local')
+-
+-			srcdir = os.path.join(cf.srcdir, 'all', 'local')
+-			if os.path.exists(srcdir):
+-				dist.link(srcdir, 'local')
++                        dist.linksync(cf.srcdir)
+ 
+ 			info(2, '%s: Creating metadata' % dist.nick)
+ 			### Check for updated repositories



More information about the svn-commits mailing list