Added epel-repoclosure
This commit is contained in:
parent
9e9ee86ec2
commit
bdea4df88d
7 changed files with 1192 additions and 0 deletions
277
scripts/epel-repoclosure/PackageOwners.py
Normal file
277
scripts/epel-repoclosure/PackageOwners.py
Normal file
|
@ -0,0 +1,277 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
# -*- 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 Library 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 commands
|
||||||
|
import errno
|
||||||
|
import os, sys, time
|
||||||
|
import shutil
|
||||||
|
import tempfile
|
||||||
|
from urllib import FancyURLopener
|
||||||
|
|
||||||
|
|
||||||
|
class AccountsURLopener(FancyURLopener):
|
||||||
|
"""Subclass of urllib.FancyURLopener to allow passing http basic auth info"""
|
||||||
|
def __init__(self, username, password):
|
||||||
|
FancyURLopener.__init__(self)
|
||||||
|
self.username = username
|
||||||
|
self.password = password
|
||||||
|
|
||||||
|
def prompt_user_passwd(self, host, realm):
|
||||||
|
return (self.username, self.password)
|
||||||
|
|
||||||
|
|
||||||
|
class PackageOwners:
|
||||||
|
"""interface to Fedora package owners list (and Fedora Extras owners/owners.list file)"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.dict = {}
|
||||||
|
self.how = 'unknown'
|
||||||
|
|
||||||
|
|
||||||
|
def FromURL(self, retries=3, retrysecs=300, url='https://admin.fedoraproject.org/pkgdb/acls/bugzilla?tg_format=plain',
|
||||||
|
pkgdb=True, repoid='Fedora', username=None, password=None):
|
||||||
|
# old url='http://cvs.fedora.redhat.com/viewcvs/*checkout*/owners/owners.list?root=extras'
|
||||||
|
if pkgdb:
|
||||||
|
self.how = 'pkgdb'
|
||||||
|
else:
|
||||||
|
self.how = 'url'
|
||||||
|
self.url = url
|
||||||
|
self.repoid = repoid
|
||||||
|
self.retries = retries
|
||||||
|
self.retrysecs = retrysecs
|
||||||
|
self.username = username
|
||||||
|
self.password = password
|
||||||
|
return self._refresh()
|
||||||
|
|
||||||
|
|
||||||
|
def FromCVS(self, retries=3, retrysecs=300, command='LC_ALL=C CVS_RSH=ssh cvs -f -d :pserver:anonymous@cvs.fedora.redhat.com:/cvs/extras co owners', workdir='',repoid='Fedora'):
|
||||||
|
self.how = 'cvs'
|
||||||
|
self.command = command
|
||||||
|
self.repoid = repoid
|
||||||
|
self.retries = retries
|
||||||
|
self.retrysecs = retrysecs
|
||||||
|
self.workdir = workdir
|
||||||
|
self.ownersfile = os.path.join('owners', 'owners.list')
|
||||||
|
self.cwdstack = []
|
||||||
|
return self._refresh()
|
||||||
|
|
||||||
|
|
||||||
|
def __getitem__(self,rpmname):
|
||||||
|
"""return e-mail address from initialowner field"""
|
||||||
|
return self.GetOwner(rpmname)
|
||||||
|
|
||||||
|
|
||||||
|
def GetOwner(self,rpmname):
|
||||||
|
"""return e-mail address from initialowner field"""
|
||||||
|
try:
|
||||||
|
r = self.dict[rpmname]['mailto']
|
||||||
|
except KeyError:
|
||||||
|
r = ''
|
||||||
|
return r
|
||||||
|
|
||||||
|
|
||||||
|
def GetOwners(self,rpmname):
|
||||||
|
"""return list of e-mail addresses from initialowner+initialcclist fields"""
|
||||||
|
r = self.GetCoOwnerList(rpmname)
|
||||||
|
r2 = self.GetOwner(rpmname)
|
||||||
|
if len(r2):
|
||||||
|
r.append(r2)
|
||||||
|
return r
|
||||||
|
|
||||||
|
|
||||||
|
def GetCoOwnerList(self,rpmname):
|
||||||
|
"""return list of e-mail addresses from initialcclist field"""
|
||||||
|
try:
|
||||||
|
r = self.dict[rpmname]['cc']
|
||||||
|
except KeyError:
|
||||||
|
r = []
|
||||||
|
return r
|
||||||
|
|
||||||
|
|
||||||
|
def _enterworkdir(self):
|
||||||
|
self.cwdstack.append( os.getcwd() )
|
||||||
|
if self.workdir != '':
|
||||||
|
os.chdir(self.workdir)
|
||||||
|
|
||||||
|
|
||||||
|
def _leaveworkdir(self):
|
||||||
|
if len(self.cwdstack):
|
||||||
|
os.chdir( self.cwdstack.pop() )
|
||||||
|
|
||||||
|
|
||||||
|
def _refresh(self):
|
||||||
|
self.dict = {} # map package name to email address, dict[name]
|
||||||
|
return self._download()
|
||||||
|
|
||||||
|
|
||||||
|
def _parse(self,ownerslist):
|
||||||
|
for line in ownerslist:
|
||||||
|
if line.startswith('#') or line.isspace():
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
(repo,pkgname,summary,emails,qacontact,cc) = line.rstrip().split('|')
|
||||||
|
# This is commented, because we don't need the summary.
|
||||||
|
#summary.replace(r'\u007c','|').replace('\u005c','\\')
|
||||||
|
|
||||||
|
# The PkgDb includes repo's other than Fedora (Fedora EPEL,
|
||||||
|
# Fedora OLPC, and Red Hat Linux, for example). Skip them.
|
||||||
|
if repo != self.repoid:
|
||||||
|
continue
|
||||||
|
def fixaddr(a):
|
||||||
|
# Old Fedora CVS owners.list contains e-mail addresses.
|
||||||
|
# PkgDb plain output contains usernames only.
|
||||||
|
if not self.how == 'pkgdb':
|
||||||
|
return a
|
||||||
|
if not self.usermap.has_key(a):
|
||||||
|
return a
|
||||||
|
return self.usermap[a]
|
||||||
|
|
||||||
|
addrs = []
|
||||||
|
mailto = '' # primary pkg owner
|
||||||
|
if len(emails):
|
||||||
|
if emails.find(',')>=0:
|
||||||
|
(addrs) = emails.split(',')
|
||||||
|
mailto = addrs[0]
|
||||||
|
addrs = addrs[1:]
|
||||||
|
else:
|
||||||
|
mailto = emails
|
||||||
|
mailto = fixaddr(mailto)
|
||||||
|
|
||||||
|
ccaddrs = []
|
||||||
|
if len(cc):
|
||||||
|
(ccaddrs) = cc.split(',')
|
||||||
|
addrs += ccaddrs
|
||||||
|
addrs = map(lambda a: fixaddr(a), addrs)
|
||||||
|
|
||||||
|
self.dict[pkgname] = {
|
||||||
|
'mailto' : mailto,
|
||||||
|
'cc' : addrs
|
||||||
|
}
|
||||||
|
except:
|
||||||
|
print 'ERROR: owners.list is broken'
|
||||||
|
print line
|
||||||
|
|
||||||
|
|
||||||
|
def _downloadfromcvs(self):
|
||||||
|
self._enterworkdir()
|
||||||
|
# Dumb caching. Check that file exists and is "quite recent".
|
||||||
|
cached = False
|
||||||
|
try:
|
||||||
|
fstats = os.stat(self.ownersfile)
|
||||||
|
if ( fstats.st_size and
|
||||||
|
((time.time() - fstats.st_ctime) < 3600*2) ):
|
||||||
|
cached = True
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if not cached:
|
||||||
|
# Remove 'owners' directory contents, if it exists.
|
||||||
|
for root, dirs, files in os.walk( 'owners', topdown=False ):
|
||||||
|
for fname in files:
|
||||||
|
os.remove(os.path.join( root, fname ))
|
||||||
|
for dname in dirs:
|
||||||
|
os.rmdir(os.path.join( root, dname ))
|
||||||
|
# Retry CVS checkout a few times.
|
||||||
|
for count in range(self.retries):
|
||||||
|
(rc, rv) = commands.getstatusoutput(self.command)
|
||||||
|
if not rc:
|
||||||
|
break
|
||||||
|
print rv
|
||||||
|
time.sleep(self.retrysecs)
|
||||||
|
if rc:
|
||||||
|
# TODO: customise behaviour on error conditions
|
||||||
|
self._leaveworkdir()
|
||||||
|
return False
|
||||||
|
|
||||||
|
try:
|
||||||
|
f = file( self.ownersfile )
|
||||||
|
except IOError, (err, strerr):
|
||||||
|
print 'ERROR: %s' % strerr
|
||||||
|
# TODO: customise behaviour on error conditions
|
||||||
|
self._leaveworkdir()
|
||||||
|
return err
|
||||||
|
ownerslist = f.readlines()
|
||||||
|
f.close()
|
||||||
|
self._parse(ownerslist)
|
||||||
|
self._leaveworkdir()
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def _getlinesfromurl(self,url):
|
||||||
|
err = 0
|
||||||
|
strerr = ''
|
||||||
|
# Retry URL download a few times.
|
||||||
|
for count in range(self.retries):
|
||||||
|
if count != 0:
|
||||||
|
time.sleep(self.retrysecs)
|
||||||
|
try:
|
||||||
|
opener = AccountsURLopener(self.username, self.password)
|
||||||
|
f = opener.open(url)
|
||||||
|
rc = 0
|
||||||
|
if 'www-authenticate' in f.headers:
|
||||||
|
rc = 1
|
||||||
|
strerr = 'Authentication is required to access %s' % url
|
||||||
|
break
|
||||||
|
except IOError, (_err, _strerr):
|
||||||
|
rc = 1
|
||||||
|
print url
|
||||||
|
print _strerr
|
||||||
|
(err,strerr) = (_err,_strerr)
|
||||||
|
if rc:
|
||||||
|
raise IOError, (err, strerr)
|
||||||
|
else:
|
||||||
|
l = f.readlines()
|
||||||
|
f.close()
|
||||||
|
return l
|
||||||
|
|
||||||
|
|
||||||
|
def _downloadfromurl(self):
|
||||||
|
self._parse(self._getlinesfromurl(self.url))
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def _downloadfrompkgdb(self):
|
||||||
|
fasdump = self._getlinesfromurl('https://admin.fedoraproject.org/accounts/dump-group.cgi')
|
||||||
|
self.usermap = {}
|
||||||
|
for line in fasdump:
|
||||||
|
fields = line.split(',')
|
||||||
|
try:
|
||||||
|
user = fields[0]
|
||||||
|
addr = fields[1]
|
||||||
|
except IndexError:
|
||||||
|
print line
|
||||||
|
raise
|
||||||
|
if (addr.find('@') < 0): # unexpected, no addr
|
||||||
|
print 'No email in:', line
|
||||||
|
raise Exception
|
||||||
|
self.usermap[user] = addr
|
||||||
|
self._parse(self._getlinesfromurl(self.url))
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def _download(self):
|
||||||
|
if self.how == 'url':
|
||||||
|
return self._downloadfromurl()
|
||||||
|
elif self.how == 'pkgdb':
|
||||||
|
return self._downloadfrompkgdb()
|
||||||
|
elif self.how == 'cvs':
|
||||||
|
return self._downloadfromcvs()
|
||||||
|
else:
|
||||||
|
self.__init__()
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
10
scripts/epel-repoclosure/demo.sh
Executable file
10
scripts/epel-repoclosure/demo.sh
Executable file
|
@ -0,0 +1,10 @@
|
||||||
|
# Run Extras repoclosure against EPEL 5.
|
||||||
|
|
||||||
|
# i386
|
||||||
|
#./rc-modified -q -d mdcache -n -c yum.epel.conf -a i686 -r centos-5-i386 -r centos-updates-5-i386 -r fedora-epel-5-i386 -r fedora-epel-testing-5-i386 > rc-epel5-20080113.txt
|
||||||
|
|
||||||
|
# x86_64 : APPEND!
|
||||||
|
#./rc-modified -q -d mdcache -n -c yum.epel.conf -a x86_64 -r centos-5-x86_64 -r centos-updates-5-x86_64 -r fedora-epel-5-x86_64 -r fedora-epel-testing-5-x86_64 >> rc-epel5-20080113.txt
|
||||||
|
|
||||||
|
# Show summary which can be sent to mailing-list.
|
||||||
|
./rc-report.py rc-epel5-20080113.txt -k epel -c rc-report-epel.cfg -w testing
|
166
scripts/epel-repoclosure/rc-epel5-20080113.txt
Normal file
166
scripts/epel-repoclosure/rc-epel5-20080113.txt
Normal file
|
@ -0,0 +1,166 @@
|
||||||
|
source rpm: R-2.6.1-1.el5.src.rpm
|
||||||
|
package: R - 2.6.1-1.el5.i386 from fedora-epel-needsign-5-i386
|
||||||
|
unresolved deps:
|
||||||
|
perl(File::Copy::Recursive)
|
||||||
|
|
||||||
|
source rpm: bodhi-0.4.4-1.el5.src.rpm
|
||||||
|
package: bodhi-server - 0.4.4-1.el5.noarch from fedora-epel-testing-5-i386
|
||||||
|
unresolved deps:
|
||||||
|
yum-utils >= 0:1.1.7
|
||||||
|
mash
|
||||||
|
|
||||||
|
source rpm: fedora-packager-0.1.1-1.el5.src.rpm
|
||||||
|
package: fedora-packager - 0.1.1-1.el5.noarch from fedora-epel-testing-5-i386
|
||||||
|
unresolved deps:
|
||||||
|
plague-client
|
||||||
|
|
||||||
|
source rpm: hspell-1.0-7.el5.src.rpm
|
||||||
|
package: hunspell-he - 1.0-7.el5.i386 from fedora-epel-testing-5-i386
|
||||||
|
unresolved deps:
|
||||||
|
hunspell
|
||||||
|
|
||||||
|
source rpm: koji-1.2.3-1.el5.src.rpm
|
||||||
|
package: koji-builder - 1.2.3-1.el5.noarch from fedora-epel-testing-5-i386
|
||||||
|
unresolved deps:
|
||||||
|
createrepo >= 0:0.4.11
|
||||||
|
|
||||||
|
source rpm: moodle-1.8.2-1.el5.src.rpm
|
||||||
|
package: moodle - 1.8.2-1.el5.noarch from fedora-epel-testing-5-i386
|
||||||
|
unresolved deps:
|
||||||
|
mimetex
|
||||||
|
|
||||||
|
source rpm: bzr-gtk-0.93.0-2.el5.src.rpm
|
||||||
|
package: nautilus-bzr - 0.93.0-2.el5.i386 from fedora-epel-testing-5-i386
|
||||||
|
unresolved deps:
|
||||||
|
nautilus-python >= 0:0.4.3-4
|
||||||
|
|
||||||
|
source rpm: nautilus-sendto-0.7-5.fc6.src.rpm
|
||||||
|
package: nautilus-sendto - 0.7-5.fc6.i386 from centos-5-i386
|
||||||
|
unresolved deps:
|
||||||
|
libgaim.so.0
|
||||||
|
|
||||||
|
source rpm: perl-Test-Base-0.53-1.el5.src.rpm
|
||||||
|
package: perl-Test-Base - 0.53-1.el5.noarch from fedora-epel-testing-5-i386
|
||||||
|
unresolved deps:
|
||||||
|
perl(Module::Install::Base)
|
||||||
|
|
||||||
|
source rpm: perl-libwhisker2-2.4-3.el5.src.rpm
|
||||||
|
package: perl-libwhisker2 - 2.4-3.el5.noarch from fedora-epel-testing-5-i386
|
||||||
|
unresolved deps:
|
||||||
|
perl(MD5)
|
||||||
|
|
||||||
|
source rpm: python-Coherence-0.2.1-3.el5.src.rpm
|
||||||
|
package: python-Coherence - 0.2.1-3.el5.noarch from fedora-epel-testing-5-i386
|
||||||
|
unresolved deps:
|
||||||
|
python-twisted-core
|
||||||
|
python-nevow
|
||||||
|
python-twisted-web
|
||||||
|
|
||||||
|
source rpm: revisor-2.0.5-15.el5.src.rpm
|
||||||
|
package: revisor-jigdo - 2.0.5-15.el5.noarch from fedora-epel-testing-5-i386
|
||||||
|
unresolved deps:
|
||||||
|
jigdo
|
||||||
|
|
||||||
|
source rpm: snake-0.9-0.5git.el5.src.rpm
|
||||||
|
package: snake-server - 0.9-0.5git.el5.noarch from fedora-epel-testing-5-i386
|
||||||
|
unresolved deps:
|
||||||
|
pykickstart >= 0:1.1
|
||||||
|
|
||||||
|
source rpm: translate-toolkit-0.10.1-1.el5.src.rpm
|
||||||
|
package: translate-toolkit - 0.10.1-1.el5.noarch from fedora-epel-testing-5-i386
|
||||||
|
unresolved deps:
|
||||||
|
python-enchant
|
||||||
|
|
||||||
|
source rpm: R-2.6.1-1.el5.src.rpm
|
||||||
|
package: R - 2.6.1-1.el5.i386 from fedora-epel-needsign-5-x86_64
|
||||||
|
unresolved deps:
|
||||||
|
perl(File::Copy::Recursive)
|
||||||
|
|
||||||
|
source rpm: R-2.6.1-1.el5.src.rpm
|
||||||
|
package: R - 2.6.1-1.el5.x86_64 from fedora-epel-needsign-5-x86_64
|
||||||
|
unresolved deps:
|
||||||
|
perl(File::Copy::Recursive)
|
||||||
|
|
||||||
|
source rpm: bodhi-0.4.4-1.el5.src.rpm
|
||||||
|
package: bodhi-server - 0.4.4-1.el5.noarch from fedora-epel-testing-5-x86_64
|
||||||
|
unresolved deps:
|
||||||
|
yum-utils >= 0:1.1.7
|
||||||
|
mash
|
||||||
|
|
||||||
|
source rpm: fedora-packager-0.1.1-1.el5.src.rpm
|
||||||
|
package: fedora-packager - 0.1.1-1.el5.noarch from fedora-epel-testing-5-x86_64
|
||||||
|
unresolved deps:
|
||||||
|
plague-client
|
||||||
|
|
||||||
|
source rpm: hspell-1.0-7.el5.src.rpm
|
||||||
|
package: hunspell-he - 1.0-7.el5.x86_64 from fedora-epel-testing-5-x86_64
|
||||||
|
unresolved deps:
|
||||||
|
hunspell
|
||||||
|
|
||||||
|
source rpm: koji-1.2.3-1.el5.src.rpm
|
||||||
|
package: koji-builder - 1.2.3-1.el5.noarch from fedora-epel-testing-5-x86_64
|
||||||
|
unresolved deps:
|
||||||
|
createrepo >= 0:0.4.11
|
||||||
|
|
||||||
|
source rpm: openib-1.2-6.el5.src.rpm
|
||||||
|
package: libcxgb3-devel - 1.0-6.el5.i386 from centos-5-x86_64
|
||||||
|
unresolved deps:
|
||||||
|
libcxgb3 = 0:1.0-6.el5
|
||||||
|
|
||||||
|
source rpm: moodle-1.8.2-1.el5.src.rpm
|
||||||
|
package: moodle - 1.8.2-1.el5.noarch from fedora-epel-testing-5-x86_64
|
||||||
|
unresolved deps:
|
||||||
|
mimetex
|
||||||
|
|
||||||
|
source rpm: mozldap-6.0.4-1.el5.src.rpm
|
||||||
|
package: mozldap-devel - 6.0.4-1.el5.i386 from centos-5-x86_64
|
||||||
|
unresolved deps:
|
||||||
|
mozldap = 0:6.0.4-1.el5
|
||||||
|
|
||||||
|
source rpm: nagios-2.9-1.el5.src.rpm
|
||||||
|
package: nagios-devel - 2.9-1.el5.i386 from fedora-epel-5-x86_64
|
||||||
|
unresolved deps:
|
||||||
|
nagios = 0:2.9-1.el5
|
||||||
|
|
||||||
|
source rpm: bzr-gtk-0.93.0-2.el5.src.rpm
|
||||||
|
package: nautilus-bzr - 0.93.0-2.el5.x86_64 from fedora-epel-testing-5-x86_64
|
||||||
|
unresolved deps:
|
||||||
|
nautilus-python >= 0:0.4.3-4
|
||||||
|
|
||||||
|
source rpm: nautilus-sendto-0.7-5.fc6.src.rpm
|
||||||
|
package: nautilus-sendto - 0.7-5.fc6.x86_64 from centos-5-x86_64
|
||||||
|
unresolved deps:
|
||||||
|
libgaim.so.0()(64bit)
|
||||||
|
|
||||||
|
source rpm: perl-Test-Base-0.53-1.el5.src.rpm
|
||||||
|
package: perl-Test-Base - 0.53-1.el5.noarch from fedora-epel-testing-5-x86_64
|
||||||
|
unresolved deps:
|
||||||
|
perl(Module::Install::Base)
|
||||||
|
|
||||||
|
source rpm: perl-libwhisker2-2.4-3.el5.src.rpm
|
||||||
|
package: perl-libwhisker2 - 2.4-3.el5.noarch from fedora-epel-testing-5-x86_64
|
||||||
|
unresolved deps:
|
||||||
|
perl(MD5)
|
||||||
|
|
||||||
|
source rpm: python-Coherence-0.2.1-3.el5.src.rpm
|
||||||
|
package: python-Coherence - 0.2.1-3.el5.noarch from fedora-epel-testing-5-x86_64
|
||||||
|
unresolved deps:
|
||||||
|
python-twisted-core
|
||||||
|
python-nevow
|
||||||
|
python-twisted-web
|
||||||
|
|
||||||
|
source rpm: revisor-2.0.5-15.el5.src.rpm
|
||||||
|
package: revisor-jigdo - 2.0.5-15.el5.noarch from fedora-epel-testing-5-x86_64
|
||||||
|
unresolved deps:
|
||||||
|
jigdo
|
||||||
|
|
||||||
|
source rpm: snake-0.9-0.5git.el5.src.rpm
|
||||||
|
package: snake-server - 0.9-0.5git.el5.noarch from fedora-epel-testing-5-x86_64
|
||||||
|
unresolved deps:
|
||||||
|
pykickstart >= 0:1.1
|
||||||
|
|
||||||
|
source rpm: translate-toolkit-0.10.1-1.el5.src.rpm
|
||||||
|
package: translate-toolkit - 0.10.1-1.el5.noarch from fedora-epel-testing-5-x86_64
|
||||||
|
unresolved deps:
|
||||||
|
python-enchant
|
||||||
|
|
282
scripts/epel-repoclosure/rc-modified
Executable file
282
scripts/epel-repoclosure/rc-modified
Executable file
|
@ -0,0 +1,282 @@
|
||||||
|
#!/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 Library 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.
|
||||||
|
# seth vidal 2005 (c) etc etc
|
||||||
|
# mschwendt: modified for Fedora Extras buildsys
|
||||||
|
|
||||||
|
#Read in the metadata of a series of repositories and check all the
|
||||||
|
# dependencies in all packages for resolution. Print out the list of
|
||||||
|
# packages with unresolved dependencies
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
# For patched "yum" and "rpmUtils" (post 2.6.1 checkForObsolete support).
|
||||||
|
# Comment this to use system yum.
|
||||||
|
#sys.path.insert(0,'/srv/extras-push/work/buildsys-utils/pushscript')
|
||||||
|
|
||||||
|
import yum
|
||||||
|
import yum.Errors
|
||||||
|
from yum.misc import getCacheDir
|
||||||
|
from optparse import OptionParser
|
||||||
|
import rpmUtils.arch
|
||||||
|
from yum.constants import *
|
||||||
|
if yum.__version__ < '3.0': # TODO: check
|
||||||
|
from repomd.packageSack import ListPackageSack
|
||||||
|
else:
|
||||||
|
from yum.packageSack import ListPackageSack
|
||||||
|
|
||||||
|
|
||||||
|
def parseArgs():
|
||||||
|
usage = "usage: %s [-c <config file>] [-a <arch>] [-r <repoid>] [-r <repoid2>]" % sys.argv[0]
|
||||||
|
parser = OptionParser(usage=usage)
|
||||||
|
parser.add_option("-c", "--config", default='/etc/yum.conf',
|
||||||
|
help='config file to use (defaults to /etc/yum.conf)')
|
||||||
|
parser.add_option("-a", "--arch", default=None,
|
||||||
|
help='check as if running the specified arch (default: current arch)')
|
||||||
|
parser.add_option("-r", "--repoid", default=[], action='append',
|
||||||
|
help="specify repo ids to query, can be specified multiple times (default is all enabled)")
|
||||||
|
parser.add_option("-t", "--tempcache", default=False, action="store_true",
|
||||||
|
help="Use a temp dir for storing/accessing yum-cache")
|
||||||
|
parser.add_option("-d", "--cachedir", default='',
|
||||||
|
help="specify a custom directory for storing/accessing yum-cache")
|
||||||
|
parser.add_option("-q", "--quiet", default=0, action="store_true",
|
||||||
|
help="quiet (no output to stderr)")
|
||||||
|
parser.add_option("-n", "--newest", default=0, action="store_true",
|
||||||
|
help="check only the newest packages in the repos")
|
||||||
|
(opts, args) = parser.parse_args()
|
||||||
|
return (opts, args)
|
||||||
|
|
||||||
|
class RepoClosure(yum.YumBase):
|
||||||
|
def __init__(self, arch = None, config = "/etc/yum.conf"):
|
||||||
|
yum.YumBase.__init__(self)
|
||||||
|
|
||||||
|
self.arch = arch
|
||||||
|
if yum.__version__ < '3.0': # TODO: check
|
||||||
|
self.doConfigSetup(fn = config)
|
||||||
|
else:
|
||||||
|
self.doConfigSetup(fn = config, init_plugins = False)
|
||||||
|
if hasattr(self.repos, 'sqlite'):
|
||||||
|
self.repos.sqlite = False
|
||||||
|
self.repos._selectSackType()
|
||||||
|
|
||||||
|
def evrTupletoVer(self,tuple):
|
||||||
|
"""convert and evr tuple to a version string, return None if nothing
|
||||||
|
to convert"""
|
||||||
|
|
||||||
|
e, v,r = tuple
|
||||||
|
|
||||||
|
if v is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
val = ''
|
||||||
|
if e is not None:
|
||||||
|
val = '%s:%s' % (e, v)
|
||||||
|
|
||||||
|
if r is not None:
|
||||||
|
val = '%s-%s' % (val, r)
|
||||||
|
|
||||||
|
return val
|
||||||
|
|
||||||
|
def readMetadata(self):
|
||||||
|
self.doRepoSetup()
|
||||||
|
self.doSackSetup(rpmUtils.arch.getArchList(self.arch))
|
||||||
|
for repo in self.repos.listEnabled():
|
||||||
|
try: # TODO: when exactly did this change to "mdtype"?
|
||||||
|
self.repos.populateSack(which=[repo.id], mdtype='filelists')
|
||||||
|
except TypeError:
|
||||||
|
self.repos.populateSack(which=[repo.id], with='filelists')
|
||||||
|
|
||||||
|
def getBrokenDeps(self, newest=False):
|
||||||
|
unresolved = {}
|
||||||
|
resolved = {}
|
||||||
|
newpkgtuplist = []
|
||||||
|
if newest:
|
||||||
|
if yum.__version__ >= '2.9': # TODO: check
|
||||||
|
pkgs = self.pkgSack.returnNewestByName()
|
||||||
|
else:
|
||||||
|
pkgs = []
|
||||||
|
for l in self.pkgSack.returnNewestByName():
|
||||||
|
pkgs.extend(l)
|
||||||
|
newestpkgtuplist = ListPackageSack(pkgs).simplePkgList()
|
||||||
|
|
||||||
|
pkgs = self.pkgSack.returnNewestByNameArch()
|
||||||
|
else:
|
||||||
|
pkgs = self.pkgSack
|
||||||
|
self.numpkgs = len(pkgs)
|
||||||
|
|
||||||
|
mypkgSack = ListPackageSack(pkgs)
|
||||||
|
pkgtuplist = mypkgSack.simplePkgList()
|
||||||
|
|
||||||
|
# Support new checkForObsolete code in Yum (#190116)
|
||||||
|
# _if available_
|
||||||
|
# so we don't examine old _obsolete_ sub-packages.
|
||||||
|
import rpmUtils.updates
|
||||||
|
self.up = rpmUtils.updates.Updates([],pkgtuplist)
|
||||||
|
self.up.rawobsoletes = mypkgSack.returnObsoletes()
|
||||||
|
|
||||||
|
haveCheckForObsolete = hasattr(rpmUtils.updates.Updates,'checkForObsolete')
|
||||||
|
if not haveCheckForObsolete:
|
||||||
|
print 'WARNING: rpmUtils.updates.checkForObsolete missing!'
|
||||||
|
|
||||||
|
for pkg in pkgs:
|
||||||
|
thispkgobsdict = {}
|
||||||
|
if haveCheckForObsolete:
|
||||||
|
try:
|
||||||
|
thispkgobsdict = self.up.checkForObsolete([pkg.pkgtup])
|
||||||
|
if thispkgobsdict.has_key(pkg.pkgtup):
|
||||||
|
continue
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def isnotnewest(pkg):
|
||||||
|
# Handle noarch<->arch switches in package updates, so any
|
||||||
|
# old nevra returned by returnNewestByNameArch() are skipped.
|
||||||
|
# TODO: There must be a more elegant/convenient way.
|
||||||
|
if (pkg.pkgtup[1] == 'noarch'):
|
||||||
|
if (pkg.pkgtup not in newestpkgtuplist):
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
for p in self.pkgSack.returnNewestByName(pkg.pkgtup[0]):
|
||||||
|
if (p.pkgtup[1] == 'noarch') and (p.pkgtup in newestpkgtuplist):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
for (req, flags, (reqe, reqv, reqr)) in pkg.returnPrco('requires'):
|
||||||
|
if req.startswith('rpmlib'): continue # ignore rpmlib deps
|
||||||
|
|
||||||
|
ver = self.evrTupletoVer((reqe, reqv, reqr))
|
||||||
|
if resolved.has_key((req,flags,ver)):
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
resolve_sack = self.whatProvides(req, flags, ver)
|
||||||
|
except yum.Errors.RepoError, e:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if len(resolve_sack) < 1:
|
||||||
|
if newest and isnotnewest(pkg):
|
||||||
|
break
|
||||||
|
if not unresolved.has_key(pkg):
|
||||||
|
unresolved[pkg] = []
|
||||||
|
unresolved[pkg].append((req, flags, ver))
|
||||||
|
continue
|
||||||
|
|
||||||
|
kernelprovides = True # make a false assumption
|
||||||
|
# If all providers are "kernel*" packages, we allow old ones.
|
||||||
|
for (pn,pa,pe,pv,pr) in resolve_sack.simplePkgList():
|
||||||
|
kernelprovides &= pn.startswith('kernel')
|
||||||
|
|
||||||
|
if newest and not kernelprovides and not req.startswith('kernel'): # we allow old kernels
|
||||||
|
resolved_by_newest = False
|
||||||
|
for po in resolve_sack:# look through and make sure all our answers are newest-only
|
||||||
|
|
||||||
|
# 2nd stage handling of obsoletes. Only keep providers,
|
||||||
|
# which are not obsolete. If no provider is left, the
|
||||||
|
# dep is unresolved.
|
||||||
|
thispkgobsdict = {}
|
||||||
|
if haveCheckForObsolete:
|
||||||
|
try:
|
||||||
|
thispkgobsdict = self.up.checkForObsolete([po.pkgtup])
|
||||||
|
if thispkgobsdict.has_key(po.pkgtup):
|
||||||
|
continue
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if po.pkgtup in pkgtuplist:
|
||||||
|
resolved_by_newest = True
|
||||||
|
break
|
||||||
|
|
||||||
|
if resolved_by_newest:
|
||||||
|
resolved[(req,flags,ver)] = 1
|
||||||
|
else:
|
||||||
|
if newest and isnotnewest(pkg):
|
||||||
|
break
|
||||||
|
if not unresolved.has_key(pkg):
|
||||||
|
unresolved[pkg] = []
|
||||||
|
unresolved[pkg].append((req, flags, ver))
|
||||||
|
|
||||||
|
return unresolved
|
||||||
|
|
||||||
|
|
||||||
|
def log(self, value, msg):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def main():
|
||||||
|
(opts, cruft) = parseArgs()
|
||||||
|
my = RepoClosure(arch = opts.arch, config = opts.config)
|
||||||
|
|
||||||
|
if opts.repoid:
|
||||||
|
for repo in my.repos.repos.values():
|
||||||
|
if repo.id not in opts.repoid:
|
||||||
|
repo.disable()
|
||||||
|
else:
|
||||||
|
repo.enable()
|
||||||
|
|
||||||
|
if os.geteuid() != 0 or opts.tempcache or opts.cachedir != '':
|
||||||
|
if opts.cachedir != '':
|
||||||
|
cachedir = opts.cachedir
|
||||||
|
else:
|
||||||
|
cachedir = getCacheDir()
|
||||||
|
if cachedir is None:
|
||||||
|
print "Error: Could not make cachedir, exiting"
|
||||||
|
sys.exit(50)
|
||||||
|
|
||||||
|
my.repos.setCacheDir(cachedir)
|
||||||
|
|
||||||
|
if not opts.quiet:
|
||||||
|
print 'Reading in repository metadata - please wait....'
|
||||||
|
|
||||||
|
try:
|
||||||
|
my.readMetadata()
|
||||||
|
except yum.Errors.RepoError, e:
|
||||||
|
print e
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if not opts.quiet:
|
||||||
|
print 'Checking Dependencies'
|
||||||
|
|
||||||
|
baddeps = my.getBrokenDeps(opts.newest)
|
||||||
|
num = my.numpkgs
|
||||||
|
|
||||||
|
repos = my.repos.listEnabled()
|
||||||
|
|
||||||
|
if not opts.quiet:
|
||||||
|
print 'Repos looked at: %s' % len(repos)
|
||||||
|
for repo in repos:
|
||||||
|
print ' %s' % repo
|
||||||
|
print 'Num Packages in Repos: %s' % num
|
||||||
|
|
||||||
|
pkgs = baddeps.keys()
|
||||||
|
def sortbyname(a,b):
|
||||||
|
return cmp(a.__str__(),b.__str__())
|
||||||
|
pkgs.sort(sortbyname)
|
||||||
|
for pkg in pkgs:
|
||||||
|
srcrpm = pkg.returnSimple('sourcerpm')
|
||||||
|
print 'source rpm: %s\npackage: %s from %s\n unresolved deps: ' % (srcrpm, pkg, pkg.repoid)
|
||||||
|
for (n, f, v) in baddeps[pkg]:
|
||||||
|
req = '%s' % n
|
||||||
|
if f:
|
||||||
|
flag = LETTERFLAGS[f]
|
||||||
|
req = '%s %s'% (req, flag)
|
||||||
|
if v:
|
||||||
|
req = '%s %s' % (req, v)
|
||||||
|
|
||||||
|
print ' %s' % req
|
||||||
|
print
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
9
scripts/epel-repoclosure/rc-report-epel.cfg
Normal file
9
scripts/epel-repoclosure/rc-report-epel.cfg
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
[FAS]
|
||||||
|
project = Fedora EPEL
|
||||||
|
#user = foo
|
||||||
|
#passwd = secret
|
||||||
|
|
||||||
|
[Mail]
|
||||||
|
from = Fedora Extras repoclosure <buildsys@fedoraproject.org>
|
||||||
|
replyto = epel-devel-list@redhat.com
|
||||||
|
subject = Broken dependencies in EPEL
|
351
scripts/epel-repoclosure/rc-report.py
Executable file
351
scripts/epel-repoclosure/rc-report.py
Executable file
|
@ -0,0 +1,351 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
# -*- mode: Python; indent-tabs-mode: nil; -*-
|
||||||
|
|
||||||
|
import errno, os, sys, stat
|
||||||
|
import re
|
||||||
|
import smtplib
|
||||||
|
import datetime, time
|
||||||
|
from optparse import OptionParser
|
||||||
|
import ConfigParser
|
||||||
|
|
||||||
|
from PackageOwners import PackageOwners
|
||||||
|
#from FakeOwners import FakeOwners as PackageOwners
|
||||||
|
|
||||||
|
FAS = {
|
||||||
|
'project' : "Fedora EPEL",
|
||||||
|
'user' : "",
|
||||||
|
'passwd' : "",
|
||||||
|
}
|
||||||
|
|
||||||
|
Mail = {
|
||||||
|
'server' : "localhost",
|
||||||
|
'user' : "",
|
||||||
|
'passwd' : "",
|
||||||
|
'maxsize' : 39*1024,
|
||||||
|
'from' : "root@localhost",
|
||||||
|
'replyto' : "root@localhost",
|
||||||
|
'subject' : "Broken dependencies in EPEL",
|
||||||
|
}
|
||||||
|
|
||||||
|
class BrokenDep:
|
||||||
|
def __init__(self):
|
||||||
|
self.pkgid = None # 'name - EVR.arch'
|
||||||
|
self.repoid = None # e.g. 'fedora-core-6-i386'
|
||||||
|
self.srp_mname = None
|
||||||
|
self.age = '' # e.g. '(14 days)'
|
||||||
|
self.owner = ''
|
||||||
|
self.coowners = []
|
||||||
|
# disabled/stripped feature
|
||||||
|
self.mail = True # whether to notify owner by mail
|
||||||
|
# disabled/stripped feature
|
||||||
|
self.new = False
|
||||||
|
self.report = []
|
||||||
|
|
||||||
|
def GetRequires(self):
|
||||||
|
pkgid2 = self.pkgid.replace(' ','')
|
||||||
|
r = []
|
||||||
|
for line in self.report:
|
||||||
|
if len(line) and not line.isspace() and not line.startswith('package: ') and line.find('unresolved deps:') < 0:
|
||||||
|
r.append( ' '+pkgid2+' requires '+line.lstrip() )
|
||||||
|
return '\n'.join(r)
|
||||||
|
|
||||||
|
|
||||||
|
def whiteListed(b): # Just a hook, not a generic white-list feature.
|
||||||
|
# These two in Fedora 7 Everything most likely won't be fixed.
|
||||||
|
if b.pkgid.startswith('kmod-em8300') and b.repoid.startswith('fedora-7'):
|
||||||
|
return True
|
||||||
|
elif b.pkgid.startswith('kmod-sysprof') and b.repoid.startswith('fedora-7'):
|
||||||
|
return True
|
||||||
|
elif b.pkgid.startswith('kmod'): # gah ;) temporarily catch them all
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def makeOwners(brokendeps):
|
||||||
|
owners = PackageOwners()
|
||||||
|
try:
|
||||||
|
#if not owners.FromURL():
|
||||||
|
if not owners.FromURL(repoid=FAS['project'],username=FAS['user'],password=FAS['passwd']):
|
||||||
|
raise IOError('ERROR: Could not retrieve package owner data.')
|
||||||
|
except IOError, e:
|
||||||
|
print e
|
||||||
|
sys.exit(1)
|
||||||
|
for b in brokendeps:
|
||||||
|
toaddr = owners.GetOwner(b.srpm_name)
|
||||||
|
if toaddr == '':
|
||||||
|
toaddr = 'UNKNOWN OWNER'
|
||||||
|
e = 'ERROR: "%s" not in owners.list!\n\n' % b.srpm_name
|
||||||
|
if e not in errcache:
|
||||||
|
errcache.append(e)
|
||||||
|
b.owner = toaddr
|
||||||
|
b.coowners = owners.GetCoOwnerList(b.srpm_name)
|
||||||
|
|
||||||
|
|
||||||
|
def mail(smtp, fromaddr, toaddrs, replytoaddr, subject, body):
|
||||||
|
from email.Header import Header
|
||||||
|
from email.MIMEText import MIMEText
|
||||||
|
msg = MIMEText( body, 'plain' )
|
||||||
|
from email.Utils import make_msgid
|
||||||
|
msg['Message-Id'] = make_msgid()
|
||||||
|
msg['Subject'] = Header(subject)
|
||||||
|
msg['From'] = Header(fromaddr)
|
||||||
|
from email.Utils import formatdate
|
||||||
|
msg['Date'] = formatdate()
|
||||||
|
if len(replytoaddr):
|
||||||
|
msg['ReplyTo'] = Header(replytoaddr)
|
||||||
|
|
||||||
|
if isinstance(toaddrs, basestring):
|
||||||
|
toaddrs = [toaddrs]
|
||||||
|
to = ''
|
||||||
|
for t in toaddrs:
|
||||||
|
if len(to):
|
||||||
|
to += ', '
|
||||||
|
to += t
|
||||||
|
msg['To'] = Header(to)
|
||||||
|
|
||||||
|
try:
|
||||||
|
r = smtp.sendmail( fromaddr, toaddrs, msg.as_string(False) )
|
||||||
|
for (name, errormsg) in r.iteritems():
|
||||||
|
print name, ':', errormsg
|
||||||
|
except smtplib.SMTPRecipientsRefused, obj:
|
||||||
|
print 'ERROR: SMTPRecipientsRefused'
|
||||||
|
for (addr, errormsg) in obj.recipients.iteritems():
|
||||||
|
print addr, ':', errormsg
|
||||||
|
except smtplib.SMTPException:
|
||||||
|
print 'ERROR: SMTPException'
|
||||||
|
|
||||||
|
|
||||||
|
def mailsplit(smtp, fromaddr, toaddrs, replytoaddr, subject, body):
|
||||||
|
# Split mail body at line positions to keep it below maxmailsize.
|
||||||
|
parts = 0
|
||||||
|
start = 0
|
||||||
|
end = len(body)
|
||||||
|
slices = []
|
||||||
|
while ( start < end ):
|
||||||
|
if ( (end-start) > Mail['maxsize'] ):
|
||||||
|
nextstart = body.rfind( '\n', start, start+Mail['maxsize'] )
|
||||||
|
if ( nextstart<0 or nextstart==start ):
|
||||||
|
print 'ERROR: cannot split mail body cleanly'
|
||||||
|
nextstart = end
|
||||||
|
else:
|
||||||
|
nextstart = end
|
||||||
|
slices.append( (start, nextstart) )
|
||||||
|
start = nextstart
|
||||||
|
parts += 1
|
||||||
|
|
||||||
|
curpart = 1
|
||||||
|
for (start,end) in slices:
|
||||||
|
if (parts>1):
|
||||||
|
subjectmodified = ( '(%d/%d) %s' % (curpart, parts, subject) )
|
||||||
|
time.sleep(1)
|
||||||
|
else:
|
||||||
|
subjectmodified = subject
|
||||||
|
slicedbody = body[start:end]
|
||||||
|
mail(smtp,fromaddr,toaddrs,replytoaddr,subjectmodified,slicedbody)
|
||||||
|
curpart += 1
|
||||||
|
|
||||||
|
|
||||||
|
def loadConfigFile(filename):
|
||||||
|
if not filename:
|
||||||
|
return
|
||||||
|
|
||||||
|
config = ConfigParser.ConfigParser()
|
||||||
|
try:
|
||||||
|
config.readfp(open(filename))
|
||||||
|
except IOError, (e, errstr):
|
||||||
|
print filename, ':', errstr
|
||||||
|
sys.exit(e)
|
||||||
|
|
||||||
|
try:
|
||||||
|
if config.has_section('FAS'):
|
||||||
|
for v in ['project','user','passwd']:
|
||||||
|
if config.has_option('FAS',v):
|
||||||
|
FAS[v] = config.get('FAS',v)
|
||||||
|
if config.has_section('Mail'):
|
||||||
|
for v in ['server','user','passwd','from','replyto','subject']:
|
||||||
|
if config.has_option('Mail',v):
|
||||||
|
Mail[v] = config.get('Mail',v)
|
||||||
|
if config.has_option('Mail','maxsize'):
|
||||||
|
Mail['maxsize'] = config.getint('Mail','maxsize')
|
||||||
|
|
||||||
|
except (ConfigParser.NoSectionError, ConfigParser.NoOptionError), e:
|
||||||
|
print 'Configuration file error:', e
|
||||||
|
|
||||||
|
|
||||||
|
### main
|
||||||
|
|
||||||
|
usage = "Usage: %s <options> <Extras repoclosure report file(s)>" % sys.argv[0]
|
||||||
|
parser = OptionParser(usage=usage)
|
||||||
|
parser.add_option("-c", "--config", default=None,
|
||||||
|
help="config file to use")
|
||||||
|
parser.add_option("-k", "--keyword", default=[], action='append',
|
||||||
|
help="a keyword to look for in repoids")
|
||||||
|
parser.add_option("-m", "--mail", default=[], action='append',
|
||||||
|
help="what mail to send (owner, summary)")
|
||||||
|
parser.add_option("-w", "--warn", default=[], action='append',
|
||||||
|
help="repository warnings to include (needsign, testing)")
|
||||||
|
parser.add_option("", "--noowners", default=False, action="store_true",
|
||||||
|
help="don't fetch package owner data from FAS")
|
||||||
|
(opts, args) = parser.parse_args()
|
||||||
|
|
||||||
|
loadConfigFile(opts.config)
|
||||||
|
|
||||||
|
domail = len(opts.mail)>0
|
||||||
|
brokendeps = [] # list of BrokenDeps
|
||||||
|
errcache = [] # error messages to be included in the summary mail
|
||||||
|
|
||||||
|
if not len(args):
|
||||||
|
print usage
|
||||||
|
sys.exit(errno.EINVAL)
|
||||||
|
# Parse extras-repoclosure output files and fill brokendeps array.
|
||||||
|
while len(args):
|
||||||
|
logfilename = args[0]
|
||||||
|
del args[0]
|
||||||
|
|
||||||
|
f = file( logfilename )
|
||||||
|
pkgre = re.compile('(?P<name>.*)-[^-]+-[^-]+$')
|
||||||
|
inbody = False
|
||||||
|
srcrpm = ''
|
||||||
|
for line in f:
|
||||||
|
if line.startswith('source rpm: '):
|
||||||
|
w = line.rstrip().split(' ')
|
||||||
|
srcrpm = w[2]
|
||||||
|
res = pkgre.search( srcrpm ) # try to get src.rpm "name"
|
||||||
|
if not res: # only true for invalid input
|
||||||
|
inbody = False
|
||||||
|
else:
|
||||||
|
srpm_name = res.group('name')
|
||||||
|
inbody = True
|
||||||
|
continue
|
||||||
|
|
||||||
|
elif inbody and line.startswith('package: '):
|
||||||
|
w = line.rstrip().split(' ')
|
||||||
|
repoid = w[5]
|
||||||
|
b = BrokenDep()
|
||||||
|
b.pkgid = w[1]+' - '+w[3] # name - EVR.arch
|
||||||
|
b.repoid = repoid
|
||||||
|
b.srpm_name = srpm_name
|
||||||
|
brokendeps.append(b)
|
||||||
|
|
||||||
|
if inbody:
|
||||||
|
# Copy report per broken package.
|
||||||
|
b.report.append( line.rstrip() )
|
||||||
|
|
||||||
|
|
||||||
|
def bdSortByOwnerAndName(a,b):
|
||||||
|
return cmp(a.owner+a.pkgid,b.owner+b.pkgid)
|
||||||
|
|
||||||
|
def bdSortByRepoAndName(a,b):
|
||||||
|
return cmp(a.repoid+a.pkgid,b.repoid+b.pkgid)
|
||||||
|
|
||||||
|
|
||||||
|
# Filter out unwanted repoids.
|
||||||
|
for b in list(brokendeps):
|
||||||
|
for needle in opts.keyword:
|
||||||
|
if b.repoid.find( needle ) >= 0: # wanted?
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
brokendeps.remove(b)
|
||||||
|
|
||||||
|
# Filter out entries from whitelist.
|
||||||
|
for b in list(brokendeps):
|
||||||
|
if whiteListed(b):
|
||||||
|
brokendeps.remove(b)
|
||||||
|
|
||||||
|
# Fill in package owners.
|
||||||
|
if not opts.noowners:
|
||||||
|
makeOwners(brokendeps)
|
||||||
|
|
||||||
|
# Build full mail report per owner. Use a flag for new breakage.
|
||||||
|
reports = {} # map of lists [new,body] - a flag and the full report for a package owner
|
||||||
|
if not opts.noowners:
|
||||||
|
brokendeps.sort(bdSortByOwnerAndName)
|
||||||
|
for b in brokendeps:
|
||||||
|
if b.new:
|
||||||
|
print 'NEW breakage: %s in %s' % (b.pkgid, b.repoid)
|
||||||
|
if b.mail:
|
||||||
|
r = '\n'.join(b.report)+'\n'
|
||||||
|
reports.setdefault(b.owner,[b.new,''])
|
||||||
|
reports[b.owner][1] += r
|
||||||
|
# Also build mails for co-owners.
|
||||||
|
for toaddr in b.coowners:
|
||||||
|
reports.setdefault(toaddr,[None,''])
|
||||||
|
reports[toaddr][1] += r
|
||||||
|
|
||||||
|
|
||||||
|
sep = '='*70+'\n'
|
||||||
|
summail = '' # main summary mail text
|
||||||
|
reportssummary = '' # any NEW stuff for the summary
|
||||||
|
|
||||||
|
def giveNeedsignMsg():
|
||||||
|
if 'needsign' in opts.warn:
|
||||||
|
return sep+"The results in this summary consider unreleased updates in the\nbuild-system's needsign-queue!\n"+sep+'\n'
|
||||||
|
else:
|
||||||
|
return ''
|
||||||
|
|
||||||
|
def giveTestingMsg():
|
||||||
|
if 'testing' in opts.warn:
|
||||||
|
return sep+"The results in this summary consider Test Updates!\n"+sep+'\n'
|
||||||
|
else:
|
||||||
|
return ''
|
||||||
|
|
||||||
|
# Create summary mail text.
|
||||||
|
reportssummary += giveNeedsignMsg()
|
||||||
|
reportssummary += giveTestingMsg()
|
||||||
|
summail += reportssummary
|
||||||
|
|
||||||
|
if not opts.noowners and len(brokendeps):
|
||||||
|
summail += ('Summary of broken packages (by owner):\n')
|
||||||
|
brokendeps.sort(bdSortByOwnerAndName)
|
||||||
|
o = None
|
||||||
|
for b in brokendeps:
|
||||||
|
if o != b.owner:
|
||||||
|
o = b.owner
|
||||||
|
seenbefore = []
|
||||||
|
summail += '\n '+b.owner.replace('@',' AT ')+'\n'
|
||||||
|
if b.pkgid not in seenbefore:
|
||||||
|
summail += ' '+b.pkgid+' '+b.age+'\n'
|
||||||
|
seenbefore.append(b.pkgid)
|
||||||
|
|
||||||
|
# Broken deps sorted by repository id.
|
||||||
|
brokendeps.sort(bdSortByRepoAndName)
|
||||||
|
r = None
|
||||||
|
for b in brokendeps:
|
||||||
|
if r != b.repoid:
|
||||||
|
r = b.repoid
|
||||||
|
summail += '\n\n'+sep+('Broken packages in %s:\n\n' % b.repoid)
|
||||||
|
summail += b.GetRequires()+'\n'
|
||||||
|
|
||||||
|
# Mail init.
|
||||||
|
if domail:
|
||||||
|
srv = smtplib.SMTP( Mail['server'] )
|
||||||
|
if ( len(Mail['user']) and len(Mail['passwd']) ):
|
||||||
|
try:
|
||||||
|
srv.login( Mail['user'], Mail['passwd'] )
|
||||||
|
except smtplib.SMTPException:
|
||||||
|
print 'ERROR: mailserver login failed'
|
||||||
|
sys.exit(-1)
|
||||||
|
|
||||||
|
# Mail reports to owners.
|
||||||
|
for toaddr,(new,body) in reports.iteritems():
|
||||||
|
# Send mail to every package owner with broken package dependencies.
|
||||||
|
mailtext = 'Your following packages in the repository suffer from broken dependencies:\n\n'
|
||||||
|
mailtext += giveNeedsignMsg()
|
||||||
|
mailtext += giveTestingMsg()
|
||||||
|
mailtext += body
|
||||||
|
if domail and ('owners' in opts.mail) and toaddr!='UNKNOWN OWNER':
|
||||||
|
subject = Mail['subject'] + ' - %s' % datetime.date.today()
|
||||||
|
mail( srv, Mail['from'], toaddr, Mail['replyto'], subject, mailtext )
|
||||||
|
|
||||||
|
# Mail summary to mailing-list.
|
||||||
|
if domail and ('summary' in opts.mail):
|
||||||
|
subject = Mail['subject'] + ' - %s' % datetime.date.today()
|
||||||
|
toaddr = Mail['replyto']
|
||||||
|
mailsplit( srv, Mail['from'], toaddr, '', subject, summail )
|
||||||
|
|
||||||
|
if domail:
|
||||||
|
srv.quit()
|
||||||
|
|
||||||
|
if len(summail):
|
||||||
|
print summail
|
97
scripts/epel-repoclosure/yum.epel.conf
Normal file
97
scripts/epel-repoclosure/yum.epel.conf
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
[main]
|
||||||
|
cachedir=/tmp/mdcache
|
||||||
|
debuglevel=2
|
||||||
|
logfile=/var/log/yum.log
|
||||||
|
pkgpolicy=newest
|
||||||
|
distroverpkg=fedora-release
|
||||||
|
reposdir=/dev/null
|
||||||
|
exactarch=1
|
||||||
|
obsoletes=1
|
||||||
|
retries=20
|
||||||
|
|
||||||
|
### EL5 ###
|
||||||
|
|
||||||
|
[centos-5-i386]
|
||||||
|
name=CentOS 5 - i386
|
||||||
|
baseurl=http://wftp.tu-chemnitz.de/pub/linux/centos/5/os/i386/
|
||||||
|
enabled=0
|
||||||
|
|
||||||
|
[centos-updates-5-i386]
|
||||||
|
name=CentOS Updates 5 - i386
|
||||||
|
baseurl=http://wftp.tu-chemnitz.de/pub/linux/centos/5/updates/i386/
|
||||||
|
enabled=0
|
||||||
|
|
||||||
|
[centos-5-x86_64]
|
||||||
|
name=CentOS 5 - x86_64
|
||||||
|
baseurl=http://wftp.tu-chemnitz.de/pub/linux/centos/5/os/x86_64/
|
||||||
|
enabled=0
|
||||||
|
|
||||||
|
[centos-updates-5-x86_64]
|
||||||
|
name=CentOS Updates 5 - x86_64
|
||||||
|
baseurl=http://wftp.tu-chemnitz.de/pub/linux/centos/5/updates/x86_64/
|
||||||
|
enabled=0
|
||||||
|
|
||||||
|
|
||||||
|
[fedora-epel-5-i386]
|
||||||
|
name=Fedora EPEL 5 - i386
|
||||||
|
baseurl=http://wftp.tu-chemnitz.de/pub/linux/fedora-epel/5/i386/
|
||||||
|
enabled=0
|
||||||
|
|
||||||
|
[fedora-epel-testing-5-i386]
|
||||||
|
name=Fedora EPEL Test Updates 5 - i386
|
||||||
|
baseurl=http://wftp.tu-chemnitz.de/pub/linux/fedora-epel/testing/5/i386/
|
||||||
|
enabled=0
|
||||||
|
|
||||||
|
[fedora-epel-5-x86_64]
|
||||||
|
name=Fedora EPEL 5 - x86_64
|
||||||
|
baseurl=http://wftp.tu-chemnitz.de/pub/linux/fedora-epel/5/x86_64/
|
||||||
|
enabled=0
|
||||||
|
|
||||||
|
[fedora-epel-testing-5-x86_64]
|
||||||
|
name=Fedora EPEL Test Updates 5 - x86_64
|
||||||
|
baseurl=http://wftp.tu-chemnitz.de/pub/linux/fedora-epel/testing/5/x86_64/
|
||||||
|
enabled=0
|
||||||
|
|
||||||
|
### EL4 ###
|
||||||
|
|
||||||
|
[centos-4-i386]
|
||||||
|
name=CentOS 4 - i386
|
||||||
|
baseurl=http://wftp.tu-chemnitz.de/pub/linux/centos/4/os/i386/
|
||||||
|
enabled=0
|
||||||
|
|
||||||
|
[centos-updates-4-i386]
|
||||||
|
name=CentOS Updates 4 - i386
|
||||||
|
baseurl=http://wftp.tu-chemnitz.de/pub/linux/centos/4/updates/i386/
|
||||||
|
enabled=0
|
||||||
|
|
||||||
|
[centos-4-x86_64]
|
||||||
|
name=CentOS 4 - x86_64
|
||||||
|
baseurl=http://wftp.tu-chemnitz.de/pub/linux/centos/4/os/x86_64/
|
||||||
|
enabled=0
|
||||||
|
|
||||||
|
[centos-updates-4-x86_64]
|
||||||
|
name=CentOS Updates 4 - x86_64
|
||||||
|
baseurl=http://wftp.tu-chemnitz.de/pub/linux/centos/4/updates/x86_64/
|
||||||
|
enabled=0
|
||||||
|
|
||||||
|
|
||||||
|
[fedora-epel-4-i386]
|
||||||
|
name=Fedora EPEL 4 - i386
|
||||||
|
baseurl=http://wftp.tu-chemnitz.de/pub/linux/fedora-epel/4/i386/
|
||||||
|
enabled=0
|
||||||
|
|
||||||
|
[fedora-epel-testing-4-i386]
|
||||||
|
name=Fedora EPEL Test Updates 4 - i386
|
||||||
|
baseurl=http://wftp.tu-chemnitz.de/pub/linux/fedora-epel/testing/4/i386/
|
||||||
|
enabled=0
|
||||||
|
|
||||||
|
[fedora-epel-4-x86_64]
|
||||||
|
name=Fedora EPEL 4 - x86_64
|
||||||
|
baseurl=http://wftp.tu-chemnitz.de/pub/linux/fedora-epel/4/x86_64/
|
||||||
|
enabled=0
|
||||||
|
|
||||||
|
[fedora-epel-testing-4-x86_64]
|
||||||
|
name=Fedora EPEL Test Updates 4 - x86_64
|
||||||
|
baseurl=http://wftp.tu-chemnitz.de/pub/linux/fedora-epel/testing/4/x86_64/
|
||||||
|
enabled=0
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue