extras-buildsys/utils/pushscript Config_Extras.py, NONE, 1.1 MultiLib.py, NONE, 1.1 Push.py, NONE, 1.1 RepoBuild.py, NONE, 1.1 RepoManage.py, NONE, 1.1 RepoView.py, NONE, 1.1 Utils.py, NONE, 1.1 extras-push, NONE, 1.1 extras-repobuild, NONE, 1.1 extras-repomanage, NONE, 1.1 extras-repoview, NONE, 1.1
Michael Schwendt (mschwendt)
fedora-extras-commits at redhat.com
Fri Sep 29 16:14:17 UTC 2006
Author: mschwendt
Update of /cvs/fedora/extras-buildsys/utils/pushscript
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv24507/pushscript
Added Files:
Config_Extras.py MultiLib.py Push.py RepoBuild.py
RepoManage.py RepoView.py Utils.py extras-push
extras-repobuild extras-repomanage extras-repoview
Log Message:
Time to break some stuff:
* Move all relevant config values into a separate module, which is
loaded dynamically based on a "project" name/id passed to the tools:
E.g. extras-push -> project "Extras" -> Config_Extras.py
foo-push -> project "Foo" -> Config_Foo.py
* Push packages "by build job" instead of "by rpm file" -- we now can
ignore (or blacklist) individual build job results.
* Call repobuild/view/manage as module functions (to allow for future
logging and more exception handling).
--- NEW FILE Config_Extras.py ---
#!/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 os
signersgid = 100581 # signers group
signersumask = 0002
signkeyname = 'extras at fedoraproject.org'
distro = 'fedora'
project = 'extras'
class opts:
mail = True
repomanage = True
repoview = True
signkeycheck = True
doublesync = False
top_workdir = '/srv/rpmbuild'
treedir = top_workdir+'/%s/tree/%s' % (project, project)
stagesdir = top_workdir+'/repodir'
# Where we store mails to be sent, our main lockfile, ...
rundir = top_workdir+'/extras-push-rundir'
cachedir = rundir+'/mdcache'
alldists = [ 'development', '5', '4', '3' ] # also the order in build reports
archdict = {'3':['x86_64', 'i386'],
'4':['ppc','x86_64', 'i386'],
'5':['ppc','x86_64', 'i386'],
'development':['ppc','x86_64','i386'],
}
multilibdists = [ 'development', '5', '4', '3' ]
# map: dist -> target arch -> list of pkg name regexp patterns
# We don't check virtual package names, unless it's a virtual -devel pkg.
# black-list takes precedence over white-list
blacklists = { 'development' : { 'x86_64' : [] },
}
whitelists = { 'development' : { 'x86_64' : [ 'wine', 'wine-arts', 'wine-devel' ] },
# 'development' : { 'x86_64' : [ '.*-devel', 'wine', 'wine-arts', 'wine-devel' ] },
#'6' : { 'x86_64' : [ 'wine', 'wine-arts', 'wine-devel' ] },
'5' : { 'x86_64' : [ 'wine', 'wine-arts', 'wine-devel' ] },
'4' : { 'x86_64' : [ 'wine', 'wine-arts', 'wine-devel' ] },
'3' : { 'x86_64' : [ 'wine', 'wine-arts', 'wine-devel' ] },
}
# packages to exclude from being repomanaged: dist => shell quoted path regexp
repomanage_keepdict = {'3': "'/\([^/]\+-\)\?kmod-'",
'4': "'/\([^/]\+-\)\?kmod-'",
'5': "'/\([^/]\+-\)\?kmod-'",
'development': "'/\([^/]\+-\)\?kmod-'",
}
sync_cmd = 'extras-sync'
createrepo = '/usr/bin/createrepo'
cr_cachedir = '/tmp/repomd-cache' # createrepo cachedir
repoview = '/usr/bin/repoview'
#repoview = '/srv/extras-push/work/repoview'
repomanage = '/usr/bin/repomanage'
#post_cmds = []
post_cmds = ['upgradecheck.py -c %s' % os.path.expanduser('~/work/upgradecheck/upgradecheck-core+extras.conf'),
'nohup rc-run-all.py &'
]
# Build report.
smtp_server = ''
project_hr = 'Fedora Extras'
mail_from = 'buildsys at fedoraproject.org'
mail_to = 'fedora-extras-list at redhat.com'
mail_footer = """
For more information about the built packages please see the repository
or the Fedora Info Feed: http://fedoraproject.org/infofeed/
"""
--- NEW FILE MultiLib.py ---
#!/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 glob, pickle, re
import rpm, rpmUtils.arch, rpmUtils.transaction, rpmUtils.miscutils
import Utils
# TODO
sys.path.insert(0,'/srv/extras-push/work/extras-repoclosure')
import yum, yum.Errors
from yum.packages import YumLocalPackage
try:
from yum.packageSack import ListPackageSack
except: # yum < 2.9
from repomd.packageSack import ListPackageSack
from RepoSupport import RepoSupport
DEBUG = False
Utils.setdebug(DEBUG)
# The following dict can be generated with rpmUtils.arch functions.
# target arch -> compatible archs
compatarchdict = { 'x86_64' : ['x86_64', 'athlon', 'i686', 'i586', 'i486', 'i386', 'noarch']
}
# map: target arch -> 'debug','rpms' -> list of new multicompat pkgs
# to be installed/linked/copied and resolved later in a second pass
missingdict = {}
def isWantedName(cfg,dist,targetarch,namelist):
"""Check a single package name against black-list and white-list. Since
a package can have virtual names, this takes a list of names as input.
Returns: True or False"""
for n in namelist:
if cfg.blacklists.has_key(dist) and cfg.blacklists[dist].has_key(targetarch):
for r in cfg.blacklists[dist][targetarch]:
if re.compile('^'+r+'$').search(n):
return False
if cfg.whitelists.has_key(dist) and cfg.whitelists[dist].has_key(targetarch):
for r in cfg.whitelists[dist][targetarch]:
if re.compile('^'+r+'$').search(n):
return True
return False # reject by default
def evalPackage(cfg,ts,fname,dist, srpmlocdict):
# Examine the package, see whether we want it for any of the
# enabled multilib repositories. Then store the package names
# in a map, which is used in pass 2 (install+resolve deps).
if dist not in cfg.multilibdists:
return
for targetarch in cfg.archdict[dist]: # list of repo archs
if not compatarchdict.has_key(targetarch):
continue
pkg = YumLocalPackage(ts=ts,filename=fname)
srcrpm = pkg.tagByName('sourcerpm')
(n,a,e,v,r) = pkg.returnPackageTuple()
(sn,sv,sr,se,sa) = rpmUtils.miscutils.splitFilename(srcrpm)
debugrpm = '%s-debuginfo-%s-%s.%s.rpm' % (sn,sv,sr,a)
if a == targetarch or a == 'noarch': # installed by main push script
continue
if a not in compatarchdict[targetarch]: # incompatible pkg arch
continue
names = [n]
if not n.endswith('-devel'):
# packageObject in yum-2.6.0-1 is broken: no such attr 'prco'
#for (prov, flag, (prove, provv, provr)) in pkg.returnPrco('provides'):
hdr = rpmUtils.miscutils.hdrFromPackage(ts,fname)
for prov in hdr['provides']:
if prov.endswith('-devel'):
names.append(prov)
if not isWantedName(cfg,dist,targetarch,names):
continue
srpmloc = os.path.join(cfg.treedir,dist,'SRPMS',srcrpm)
if DEBUG and not os.path.isfile(srpmloc):
srpmloc = srpmlocdict[srcrpm]
try:
hdr = rpmUtils.miscutils.hdrFromPackage(ts,srpmloc)
excludearch = hdr['excludearch']
except rpmUtils.RpmUtilsError, e: # source rpm not there or bad
print 'ERROR: %s' % e
print srpmloc
print 'referenced by: %s' % fname
# TODO: We don't want such builds! Do something about it.
# Is this case possible at all? Or only during dep resolving
# and when running into old pkgs?
srcrpm = None
excludearch = []
if not srcrpm:
continue
if targetarch in excludearch:
print 'Multi-compat, but ExcludeArch %s' % excludearch
continue
# Save base file-names here.
pkgbasefn = os.path.basename(fname)
missingdict.setdefault(targetarch,{})
pkglist = missingdict[targetarch].setdefault('rpms',[])
if pkgbasefn not in pkglist:
pkglist.append(pkgbasefn)
missingdict[targetarch]['rpms'] = pkglist
print ' +', pkgbasefn
pkglist = missingdict[targetarch].setdefault('debug',[])
if debugrpm not in pkglist:
pkglist.append(debugrpm)
missingdict[targetarch]['debug'] = pkglist
print ' +', debugrpm
return
def evalFromTree(cfg,dist):
ts = rpmUtils.transaction.initReadOnlyTransaction()
global missingdict
missingdict = {}
for srcarch in cfg.archdict[dist]: # list of repo archs
srcdir = os.path.join(cfg.treedir,dist,srcarch)
print 'Scanning for multi-compat packages:', srcdir
files = glob.glob('%s/*.rpm' % srcdir)
for f in files:
evalPackage(cfg,ts,f,dist,{})
return
# --------------------------------------------------------------------
class Resolver(yum.YumBase):
def __init__(self, arch = None, config = "/etc/yum.conf"):
yum.YumBase.__init__(self)
self.arch = arch
self.doConfigSetup(fn = config)
if hasattr(self.repos, 'sqlite'):
self.repos.sqlite = False
self.repos._selectSackType()
self.resolved = {}
self.seenbefore = []
self.needed = {}
self.needed['rpms'] = []
self.needed['debug'] = []
def readMetadata(self):
self.doRepoSetup()
self.doSackSetup(rpmUtils.arch.getArchList(self.arch))
for repo in self.repos.listEnabled():
self.repos.populateSack(which=[repo.id], with='filelists')
def addNeededPkg(self,pkg):
(n,a,e,v,r) = pkg.returnPackageTuple()
file = '%s-%s-%s.%s.rpm' % (n,v,r,a)
if file not in self.needed['rpms']:
self.needed['rpms'].append(file)
print ' +', file
binarch = a
srcrpm = pkg.returnSimple('sourcerpm')
(n,v,r,e,a) = rpmUtils.miscutils.splitFilename(srcrpm)
debugrpm = '%s-debuginfo-%s-%s.%s.rpm' % (n,v,r,binarch)
if debugrpm not in self.needed['debug']:
self.needed['debug'].append(debugrpm)
print ' +', debugrpm
def resolveRequires(self,pkg):
if pkg.returnNevraPrintable() in self.seenbefore:
#print " ! SEEN BEFORE"
return
self.seenbefore.append( pkg.returnNevraPrintable() )
# yum-2.6.0-1
# for (req,flags,(reqe,reqv,reqr)) in pkg.returnPrco('requires'):
# File "packageObject.py", line 224, in returnPrco
#AttributeError: YumLocalPackage instance has no attribute 'prco'
#for (req,flags,evr) in getRequires( ... ):
for dep in pkg.requiresList():
if dep.startswith('rpmlib'):
continue # ignore rpmlib deps
if self.resolved.has_key(dep):
continue # resolved before
results = []
try:
results = self.returnPackagesByDep(dep)
except:
pass
if len(results) < 1: # unresolved, most likely in Core
#print 'UNRESOLVED:', dep
continue
self.resolved[dep] = True
for p in results:
self.addNeededPkg(p)
self.resolveRequires(p)
def log(self, value, msg):
pass
def resolveMissing(cfg,dist,targetarch):
if not missingdict.has_key(targetarch):
return False
missingdict[targetarch].setdefault('rpms',[])
missingdict[targetarch].setdefault('debug',[])
rs = RepoSupport() # TODO
conf = rs.GenerateConfig([dist])
repoids = []
srcarch = rpmUtils.arch.getBaseArch( rpmUtils.arch.multilibArches[targetarch][0] )
# Only look at basearch repo.
a = srcarch
for r in rs.ReleaseRepoDict()[dist]:
if r.find('extras') < 0:
continue
repoid = '%s-%s-%s' % (r,dist,a)
repoids.append(repoid)
print repoids
# Only look at multicompat packages.
my = Resolver(arch = srcarch, config = conf)
for repo in my.repos.repos.values():
if repo.id not in repoids:
repo.disable()
else:
repo.enable()
my.repos.setCacheDir(cfg.cachedir)
Utils.fix_mdcache_access(cfg.rundir,cfg.cachedir)
try:
print 'Reading metadata...'
my.readMetadata()
except yum.Errors.RepoError, e:
print 'Yum error: %s' % e
# TODO: This is only bad if it's something a re-run doesn't fix automatically.
except:
Utils.fix_mdcache_access(cfg.rundir,cfg.cachedir)
raise
print 'done.'
Utils.fix_mdcache_access(cfg.rundir,cfg.cachedir)
ts = rpmUtils.transaction.initReadOnlyTransaction()
compatrepodir = os.path.join(cfg.treedir,dist,srcarch)
for f in missingdict[targetarch]['rpms']:
print f
fpath = os.path.join(compatrepodir,f)
pkg = YumLocalPackage(ts=ts,filename=fpath)
my.resolveRequires(pkg)
changed = False
print 'Installing needed packages for %s:' % targetarch
for f in my.needed['rpms']+missingdict[targetarch]['rpms']:
srcfile = os.path.join(cfg.treedir,dist,srcarch,f)
destfile = os.path.join(cfg.treedir,dist,targetarch,f)
if not os.path.exists(destfile): # silent extra-check
Utils.install_link_or_copy(srcfile,destfile)
changed = True
for f in my.needed['debug']:
srcfile = os.path.join(cfg.treedir,dist,srcarch,'debug',f)
destfile = os.path.join(cfg.treedir,dist,targetarch,'debug',f)
if not os.path.exists(destfile): # silent extra-check
Utils.install_link_or_copy(srcfile,destfile)
changed = True
return changed
# --------------------------------------------------------------------
def main(dists):
for dist in dists:
evalFromTree(cfg,dist)
for arch in cfg.archdict[dist]: # list of repo archs
changedagain = resolveMissing(cfg,dist,arch)
if changedagain:
Utils.create_arch_repo(cfg,dist,arch)
if __name__ == '__main__':
if len(sys.argv) < 3:
print 'Usage: %s <project> <release> [release]...\n' % os.path.basename(sys.argv[0])
sys.exit(errno.EINVAL)
cfg = Utils.load_config_module(sys.argv[1])
Utils.signer_gid_check(cfg.signersgid)
os.umask(cfg.signersumask)
main(sys.argv[2:])
sys.exit(0)
--- NEW FILE Push.py ---
#!/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
import fcntl, fnmatch
import os, sys
import rpmUtils
import shutil
import string
import tempfile
import time
import Utils, MultiLib
import RepoBuild, RepoManage, RepoView
DEBUG = True
Utils.setdebug(DEBUG)
# Lockfile name supported by plague for mutual exclusion during
# access to needsign repository (i.e. 'stagesdir').
REPO_LOCKFILE_NAME = '.repo-update.lock'
class opts:
force = False
ts = rpmUtils.transaction.initReadOnlyTransaction()
# Further globals: cfg, srpmlocdict
class LockFile:
def __init__(self, name, blocking=False):
self.name = name
self.mode = fcntl.LOCK_EX
if not blocking:
self.mode |= fcntl.LOCK_NB
def lock(self):
if DEBUG:
return
try:
self.file = open(self.name,'w')
except IOError, (err, strerr):
print "ERROR: opening lockfile %s failed: %s (error %d)" % (self.name, strerr, err)
sys.exit(err)
self.rc = fcntl.flock(self.file, self.mode)
def unlock(self):
if DEBUG:
return
fcntl.flock(self.file, fcntl.LOCK_UN)
self.file.close()
def getrunfilename(dist):
runfilename = os.path.join(cfg.rundir, dist)
if DEBUG:
runfilename += '.DEBUG'
return runfilename
def getlinesfromrunfile(dist):
runfilename = getrunfilename(dist)
pkglist = []
try:
pkglist = file(runfilename).read().splitlines()
except IOError, (err, strerr):
if err != 2: # everything but file_not_found is unexpected
print 'ERROR: %s: %s' % (strerr,runfilename)
sys.exit(err)
return pkglist
def emptyrunfile(dist):
runfilename = getrunfilename(dist)
if not os.path.exists(runfilename):
return
try:
os.remove(runfilename)
except:
print 'ERROR: Could not remove %s' % runfilename
pass
# ====================================================================
def get_build_results(path,droppushed=False):
"""returns list of (name,[jobroots]) tuples for available build-results, where every "jobroot" is the path to a build-job results directory"""
# The needsign repository root contains a directory "name" for
# every built src.rpm package %{name}.
d = os.listdir(path)
try:
d.remove('repodata')
except ValueError:
pass
rv = [] # return value: list of (name,[jobroots]) tuples
for name in d:
pkgroot = os.path.join(path,name)
if not os.path.isdir(pkgroot):
continue
jobroots = []
# Every built version-release is stored in an own sub-dir of "name".
# e.g. ./foo/1.0-1 ./foo/1.0-2
for pkgrelroot in map(lambda f: os.path.join(pkgroot,f), os.listdir(pkgroot)):
if os.path.isdir(pkgrelroot):
if droppushed and os.path.isfile(os.path.join(pkgrelroot,'PUSHED')):
continue
jobroots.append(pkgrelroot)
rv.append( (name,jobroots) )
return rv
def find_files(rootpath,pattern='*'):
"""returns list of paths in given tree which point to a file matching the fnmatch pattern"""
rv = []
if not os.path.isdir(rootpath):
return rv
for root, dirs, files in os.walk(rootpath):
for f in fnmatch.filter(files,pattern):
rv.append(os.path.join(root,f))
return rv
def mark_pkg_pushed(pkgrelroot):
"""create a file named PUSHED in a package build-results root directory"""
fname = os.path.join(pkgrelroot,'PUSHED')
if os.path.isfile(fname):
return
if DEBUG:
print 'Creating %s' % fname
return
try:
f = open(fname,'w')
f.close()
except IOError, (err, strerr):
print 'ERROR: %s: %s' % (strerr,fname)
raise IOError, (err, strerr)
def prune_needsign_tree(needsignroot):
for (name,pkgrelroots) in get_build_results(needsignroot):
validbuilds = pkgrelroots
# Delete those builds which are marked as PUSHED and old enough.
for pkgrelroot in pkgrelroots:
flagname = os.path.join(pkgrelroot,'PUSHED')
if not os.path.isfile(flagname):
continue
mtime = os.path.getmtime(flagname)
# Check if there are *.rpm newer than the flag
# (When exactly is that possible? old-style kernel mods?)
changed = False
for root, dirs, files in os.walk(pkgrelroot):
if changed:
break
for f in fnmatch.filter(files, '*.rpm'):
if os.path.getmtime(os.path.join(root, f)) > mtime:
changed = True
break
if changed:
print 'New packages in PUSHED %s, clearing flag' % pkgrelroot
if not DEBUG:
os.remove(flagname)
continue
if ( time.time()-mtime > 3600*48 ):
print 'Removing old %s' % pkgrelroot
if not DEBUG:
shutil.rmtree(pkgrelroot)
validbuilds.remove(pkgrelroot)
# Now re-examine the remaining builds and mark unneeded ones as PUSHED.
# TODO: white-list some packages, such as "kmod-*"?
pkgrelroots = validbuilds
pkgroot = os.path.join(needsignroot,name)
if len(pkgrelroots) < 2: # only one release or empty dir
# Clean up empty package name directories.
if not len(pkgrelroots):
try:
Utils.debugprint('Removing empty directory %s' % pkgroot)
if not DEBUG:
os.rmdir(pkgroot)
except OSError, e:
print e
pass
continue # with next name
Utils.debugprint( '%s release(s) for %s: %s' % (len(pkgrelroots),name,' '.join(map(lambda f: os.path.basename(f),pkgrelroots))) )
# We assume this release to be the newest.
relroot = pkgrelroots[0]
# There can be only one src.rpm in this dir, since relroot
# and src.rpm filename are unique (due to NVR).
srcrpms = find_files(relroot,'*.src.rpm')
# Currently, directories can be empty though, unless we clean up
# the repodir regularly.
if not len(srcrpms):
continue
srcrpm = srcrpms[0]
(n,a,e,v,r) = naevr(srcrpm)
# Now compare with the other releases.
for nextrelroot in pkgrelroots[1:]:
nextsrcrpms = find_files(nextrelroot,'*.src.rpm')
if not len(nextsrcrpms):
continue
nextsrcrpm = nextsrcrpms[0]
(nextn,nexta,nexte,nextv,nextr) = naevr(nextsrcrpm)
# 1 means: e,v,r is higher than nexte,nextv,nextr
if rpmUtils.miscutils.compareEVR((e,v,r),(nexte,nextv,nextr)) == 1:
Utils.debugprint('Ignoring: %s' % nextrelroot)
mark_pkg_pushed(nextrelroot)
else:
Utils.debugprint('Ignoring: %s' % relroot)
mark_pkg_pushed(relroot)
# Make this the next newest package for ongoing comparison.
relroot = nextrelroot
(n,a,e,v,r) = (nextn,nexta,nexte,nextv,nextr)
def naevr(pkg):
"""return nevra from the package srpm"""
hdr = rpmUtils.miscutils.hdrFromPackage(ts, pkg)
name = hdr['name']
ver = hdr['version']
rel = hdr['release']
arch = hdr['arch']
epoch = hdr['epoch']
if epoch is None:
epoch = 0
return (name, arch, epoch, ver, rel)
def getexcludearch(pkgpath,reporoot):
"""Returns list of excluded archs for a binary rpm.
Needs access to the repository root directory where it
examines the source rpm."""
global ts, srpmlocdict
hdr = rpmUtils.miscutils.hdrFromPackage(ts,pkgpath)
source_rpm = hdr['sourcerpm']
if not DEBUG:
srpmloc = os.path.join(reporoot, 'SRPMS', source_rpm)
else: # in debug mode we cannot access signed/installed rpms
srpmloc = srpmlocdict[source_rpm]
hdr = rpmUtils.miscutils.hdrFromPackage(ts,srpmloc)
return hdr['excludearch']
def sign_pkgs(filelist):
"""gpg sign all the rpms"""
numfiles = len(filelist)
if numfiles < 1:
print "No packages to sign"
return 0
if DEBUG:
return 0
while numfiles > 0:
if numfiles > 256:
files = filelist[:256]
del filelist[:256]
else:
files = filelist
filelist = []
foo = string.join(files)
result = os.system('echo %s | xargs rpm --resign' % foo)
if result != 0:
return result
numfiles = len(filelist)
return 0
class PushWarning(Exception):
pass
def push(dist,needsignroot,destroot,name,pkgrelroot):
"""push the files found within a single package build-results directory"""
rollback = []
try:
push_with_rollback(rollback,dist,needsignroot,destroot,name,pkgrelroot)
except:
print 'ERROR: Rollback:', rollback
for f in rollback:
if DEBUG:
break
try:
os.remove(f)
except:
pass
raise
def push_with_rollback(rollback,dist,needsignroot,destroot,name,pkgrelroot):
print ' %s-%s' % (name,os.path.basename(pkgrelroot))
filedict = {}
filedict['srpm'] = []
filedict['rpm'] = []
filedict['debuginfo'] = []
filedict['other'] = []
# Match the build-results files to what list they should be in.
for file in find_files(pkgrelroot):
if file.endswith('.rpm'):
if file.find('debuginfo') != -1:
which = 'debuginfo'
elif file.endswith('.src.rpm'):
which = 'srpm'
else:
which = 'rpm'
else:
which = 'other'
filedict[which].append(file)
buildreportinfo = None
# In the run-file we store the package NVR ids for the build report.
# Content in that file also serves as an indication whether there is
# a "push" to finish, i.e. whether we need to sync the repository
# to the public master site.
runfilename = getrunfilename(dist)
rundirfile = open(runfilename,'a')
# go through each package and move it to the right arch location
# if it is a src.rpm package, move it into the SRPMS location
# if it is a noarch package, copy2 it to all arch locations
# if it is a debuginfo package, move it into the 'debug' dir for that arch
package = filedict['srpm'][0]
(n,a,e,v,r) = naevr(package)
pkg_fn = os.path.basename(package)
global srpmlocdict # debug only
srpmlocdict[pkg_fn] = package # debug only
destloc = os.path.join(destroot, 'SRPMS', pkg_fn)
if not os.path.exists(destloc):
rollback.append(destloc)
Utils.install_move(package,destloc)
buildreportinfo = '%s-%s-%s\n' % (n,v,r)
else: # src.rpm published before, exclude entire build job
mark_pkg_pushed( os.path.join(needsignroot,name,os.path.basename(pkgrelroot)) )
raise PushWarning, 'WARNING: %s published before' % pkg_fn
for package in filedict['rpm'] + filedict['debuginfo']:
pkg_fn = pkg_destfn = os.path.basename(package)
if package in filedict['debuginfo']:
pkg_destfn = 'debug/' + pkg_fn
(n,a,e,v,r) = naevr(package)
if a == 'noarch':
excludearch = getexcludearch(package,destroot)
linkloc = None
for basearch in cfg.archdict[dist]:
if basearch in excludearch:
print 'EXCLUDEARCH: Not releasing %s for %s.' % (pkg_fn,basearch)
continue # with next basearch
destloc = os.path.join(destroot, basearch, pkg_destfn)
rollback.append(destloc)
if linkloc:
Utils.install_link_or_copy(linkloc,destloc)
else:
Utils.install_copy(package,destloc)
linkloc = destloc
continue # with next package
# rpmUtils.arch.getBaseArch(a)
elif a in ['i386', 'i486', 'i586', 'i686', 'athlon']:
basearch = 'i386'
elif a in ['x86_64', 'ia32e', 'amd64']:
basearch = 'x86_64'
elif a in ['ppc', 'ppc64', 'ppc32']:
basearch = 'ppc'
else:
print 'Unknown arch %s' % a
continue # with next package
destloc = os.path.join(destroot, basearch, pkg_destfn)
rollback.append(destloc)
Utils.install_move(package,destloc)
# Mark successfully signed packages as PUSHED.
mark_pkg_pushed( os.path.join(needsignroot,name,os.path.basename(pkgrelroot)) )
rollback = []
rundirfile.write(buildreportinfo)
rundirfile.close()
def copy_sign_move(dist):
"""Copies, signs and moves packages for the given dist.
Returns (errcode, changed) where errcode is an error code and changed
is a boolean indicating whether the target repo was changed."""
distdir = '%s-%s-%s' % (cfg.distro, dist, cfg.project)
needsignroot = os.path.join(cfg.stagesdir, distdir)
destroot = os.path.join(cfg.treedir, dist)
changed = False
repodirs = [os.path.join(destroot, 'SRPMS')]
for arch in cfg.archdict[dist]:
repodirs.append(os.path.join(destroot, arch))
repodirs.append(os.path.join(destroot, arch, 'debug'))
for repodir in repodirs:
# We check for changes already here in case the repo has changed
# due to external activities such as removing files etc, and will
# recheck it again later if needed when we're done with this sign
# batch.
if not changed:
changed = Utils.is_repo_changed(repodir)
if changed:
print "Dist %s (%s) was externally changed" % (dist, repodir)
if not DEBUG and not os.path.exists(repodir):
os.makedirs(repodir)
repolockname = os.path.join(needsignroot,REPO_LOCKFILE_NAME)
repolock = LockFile(name=repolockname,blocking=True)
try:
print 'Waiting for repository lock on %s:' % distdir,
sys.stdout.flush()
repolock.lock()
print 'OK'
except IOError, (err, strerr):
print "ERROR: lockfile %s failure: %s (error %d)" % (repolockname, strerr, err)
sys.exit(err)
prune_needsign_tree(needsignroot)
results = get_build_results(needsignroot,droppushed=True)
# TODO: room for black-list checks.
print 'Package directories found: %d' % len(results)
if len(results) == 0:
return 0, changed
print 'Copying build results to temporary working directory:'
signtmpdir = tempfile.mkdtemp('','.push',cfg.treedir)
if signtmpdir == cfg.treedir: # paranoid, should never happen
sys.exit(errno.EPERM)
try:
for (name,pkgrelroots) in results:
destpkgroot = os.path.join(signtmpdir,name)
if not os.path.exists(destpkgroot):
os.makedirs(destpkgroot)
for pkgrelroot in pkgrelroots:
vr = os.path.basename(pkgrelroot)
print ' %s-%s' % (name,vr)
shutil.copytree(pkgrelroot,os.path.join(destpkgroot,vr))
except: # everything is fatal
print 'ERROR: Creating temporary working copy failed.'
shutil.rmtree(signtmpdir)
raise
# Now we have a temporary copy of everything from the needsign repository
# we want. Build results as ./foo/1.0-1/ directories in signtmpdir.
repolock.unlock()
try:
print "Signing Packages:"
rv = sign_pkgs( find_files(signtmpdir,'*.rpm') )
if rv:
print "Error signing packages! Please be patient - cleaning up."
raise Exception
print "Copying packages into repositories:"
global srpmlocdict
srpmlocdict = {} # debug only
results = get_build_results(signtmpdir)
for (name,pkgrelroots) in results:
for pkgrelroot in pkgrelroots:
try:
push(dist,needsignroot,destroot,name,pkgrelroot)
except PushWarning, e:
print e
except:
shutil.rmtree(signtmpdir)
raise
print('Removing tmp tree: %s' % signtmpdir)
shutil.rmtree(signtmpdir)
# All done, now check if something changed unless we already know it did:
if not changed:
for repodir in repodirs:
changed = Utils.is_repo_changed(repodir)
if changed:
Utils.debugprint("Dist %s (%s) was changed" % (dist, repodir))
break
return 0, changed
# ====================================================================
import datetime
import smtplib
from email.MIMEText import MIMEText
def email_list(distlist):
"""email mailing list with the new package listing"""
body = ''
for dist in cfg.alldists: # we do this for sorting the dists
if not dist in distlist:
continue
uniqued = rpmUtils.miscutils.unique( getlinesfromrunfile(dist) )
uniqued.sort()
if not uniqued:
continue
body += "\nPackages built and released for %s %s: %s \n\n" % (cfg.project_hr, dist, len(uniqued))
for pkg in uniqued:
add = ' %s\n' % (pkg)
body += add
body += '\n'
if not body:
return
body += cfg.mail_footer
msg = MIMEText(body)
subject = '%s Package Build Report %s' % (cfg.project_hr,datetime.date.today())
msg['Subject'] = subject
msg['From'] = cfg.mail_from
msg['To'] = cfg.mail_to
Utils.debugprint( msg.as_string() )
if not DEBUG:
s = smtplib.SMTP()
if cfg.smtp_server:
s.connect(cfg.smtp_server)
else:
s.connect()
s.sendmail(cfg.mail_from, [cfg.mail_to], msg.as_string())
s.close()
# Build report has been mailed, we can delete the run-files.
for dist in distlist:
emptyrunfile(dist)
# ====================================================================
if __name__ == '__main__':
if len(sys.argv) < 3:
print 'Usage: %s <project> <release|all> [release]...\n' % os.path.basename(sys.argv[0])
sys.exit(errno.EINVAL)
cfg = Utils.load_config_module(sys.argv[1])
os.umask(cfg.signersumask)
Utils.signer_gid_check(cfg.signersgid)
if cfg.opts.signkeycheck:
if cfg.signkeyname != os.popen('rpm --eval %_gpg_name','r').read().rstrip():
print 'ERROR: Configure ~/.rpmmacros for proper GPG signing before running this!'
sys.exit(errno.EPERM)
if '-f' in sys.argv[2:]:
sys.argv.remove('-f')
opts.force = True
diststopush = []
for d in sys.argv[2:]:
if d == 'all':
diststopush = cfg.alldists
continue
if d not in cfg.alldists:
print "ERROR: No Distribution named '%s' found" % d
sys.exit(errno.EINVAL)
if d not in diststopush:
diststopush.append(d)
Utils.debugprint(diststopush)
if not os.path.exists(cfg.rundir):
os.makedirs(cfg.rundir)
lockfile = os.path.join(cfg.rundir,'pushscript.lock')
lock = LockFile(lockfile)
try:
lock.lock()
except IOError:
print 'ERROR: script locked via lockfile %s - it seems to be running already' % lockfile
sys.exit(errno.EPERM)
changed = [] # dists with changes in them
mustfinish = [] # dists with pending build report
totalchanges = 0
for dist in diststopush:
result, repochanged = copy_sign_move(dist)
if result:
sys.exit(result)
if repochanged:
changed.append(dist)
# len(getlinesfromrunfile(dist)) is the number of build jobs
# per dist which have been pushed.
buildjobs = len( getlinesfromrunfile(dist) )
totalchanges += buildjobs
if buildjobs:
mustfinish.append(dist)
print 'Total number of pushed build jobs to report: %d' % totalchanges
# Option -f re-runs repobuild/repoview for all dists to push,
# even if no new packages have been pushed for a dist.
if opts.force:
changed = diststopush
for dist in changed:
if cfg.opts.repomanage:
RepoManage.main(cfg,dist)
RepoBuild.main(cfg,dist)
# TODO: multilib resolver hook
MultiLib.main(changed)
if changed:
if cfg.opts.doublesync:
Utils.run_and_check(cfg.sync_cmd)
for dist in changed:
if cfg.opts.repoview:
RepoView.main(cfg,dist)
if changed or mustfinish:
Utils.run_and_check(cfg.sync_cmd)
if cfg.opts.mail:
email_list(diststopush)
for cmd in cfg.post_cmds:
Utils.run_and_check(cmd)
lock.unlock()
sys.exit(0)
--- NEW FILE RepoBuild.py ---
#!/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 Utils
def main(cfg,dist):
if not cfg.archdict.has_key(dist):
print "No distribution release named '%s' found" % dist
sys.exit(errno.EINVAL)
Utils.create_src_repo(cfg,dist) # source rpms
for arch in cfg.archdict[dist]:
Utils.create_arch_repo(cfg,dist,arch) # binary+debuginfo rpms
if __name__ == '__main__':
if len(sys.argv) < 3:
print 'Usage: %s <project> <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)
main(cfg,sys.argv[2])
os.chdir(me)
--- NEW FILE RepoManage.py ---
#!/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 Utils
def do_repo_stuff(cfg, repodir, keep=2, nomanage=None):
print 'Processing: %s' % repodir
print 'cleaning up older packages (keeping %d latest)' % (keep)
repomanage = '%s -c -k%d -o %s' % (cfg.repomanage, keep, repodir)
if nomanage:
cmd = '%s | grep -v %s | xargs rm -f' % (repomanage, nomanage)
else:
cmd = '%s | xargs rm -f' % repomanage
Utils.run_and_check(cmd)
def main(cfg,dist):
if not cfg.archdict.has_key(dist):
print "No distribution release named '%s' found" % dist
sys.exit(errno.EINVAL)
destdir = os.path.join(cfg.treedir, dist)
keep = (dist == 'development') and 1 or 2
do_repo_stuff(cfg,os.path.join(destdir, 'SRPMS'), keep, cfg.repomanage_keepdict.get(dist))
# arch repo creation
for arch in cfg.archdict[dist]:
repodir = os.path.join(destdir, arch)
do_repo_stuff(cfg, repodir, keep, cfg.repomanage_keepdict.get(dist))
if __name__ == '__main__':
if len(sys.argv) < 3:
print 'Usage: %s <project> <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)
main(cfg,sys.argv[2])
os.chdir(me)
--- NEW FILE RepoView.py ---
#!/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 Utils
def do_repoview(cfg,repodir):
print 'Generating repoview in %s' % repodir
cmd = '%s -q %s' % (cfg.repoview,repodir)
Utils.run_and_check(cmd)
# if there's a debug subdir, make that a repo, too.
dbg_repodir = os.path.join(repodir, 'debug')
if os.path.exists(dbg_repodir):
print 'Generating repoview in %s' % dbg_repodir
cmd = '%s -q %s' % (cfg.repoview,dbg_repodir)
Utils.run_and_check(cmd)
def main(cfg,dist):
if not cfg.archdict.has_key(dist):
print "No distribution release named '%s' found" % dist
sys.exit(errno.EINVAL)
destdir = os.path.join(cfg.treedir, dist)
do_repoview(cfg,os.path.join(destdir, 'SRPMS'))
# arch repo creation
for arch in cfg.archdict[dist]:
repodir = os.path.join(destdir, arch)
do_repoview(cfg,repodir)
if __name__ == '__main__':
if len(sys.argv) < 3:
print 'Usage: %s <project> <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)
main(cfg,sys.argv[2])
os.chdir(me)
--- NEW FILE Utils.py ---
#!/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.
import errno
import fnmatch
import os, sys
import shutil
import stat, tempfile
compsname = 'comps.xml'
DEBUG = False
def setdebug(onoff):
global DEBUG
DEBUG = onoff
def debugprint(msg):
if DEBUG:
print msg
def run_and_check(cmd):
debugprint(cmd)
if not DEBUG:
result = os.system(cmd)
if result != 0:
print >> sys.stderr, 'Error running command: %s ' % cmd
if result > 127:
sys.exit(1)
sys.exit(result)
def load_config_module(project):
import imp
name = 'Config_'+project
try:
(fileobj, pathname, description) = imp.find_module(name)
cfg = imp.load_module(name,fileobj,pathname,description)
fileobj.close()
return cfg
except ImportError, e:
print e
sys.exit(errno.EIO)
def signer_gid_check(gid):
if os.getgid() != gid:
grpname = '(unknown)'
try:
import grp
grpname = grp.getgrgid(gid)[0]
except:
print 'WARNING: Could not get group name for gid %d' % gid
print 'ERROR: Change into the %s group before running this! Use "newgrp %s".' % (grpname, grpname)
sys.exit(errno.EPERM)
def install_copy(src,dest,overwrite=False):
"""shutil.copy2 a file, but by default don't overwrite destination"""
if not overwrite and os.path.exists(dest):
print('WARNING: %s already exists, ignoring new one' % dest)
return
debugprint('Copying %s to %s' % (src,dest))
if not DEBUG:
shutil.copy2(src,dest)
def install_move(src,dest,overwrite=False):
"""shutil.move a file, but by default don't overwrite destination"""
if not overwrite and os.path.exists(dest):
print('WARNING: %s already exists, ignoring new one' % dest)
return
debugprint('Moving %s to %s' % (src,dest))
if not DEBUG:
shutil.move(src,dest)
def install_link(src,dest):
"""os.link a file, but don't overwrite destination"""
if os.path.exists(dest):
print('WARNING: %s already exists, ignoring new one' % dest)
return
debugprint('Linking %s <- %s' % (src,dest))
if not DEBUG:
os.link(src,dest)
def install_link_or_copy(src,dest):
"""try install_link, if it fails, use install_copy"""
linked = False
try:
install_link(src,dest)
linked = True
except OSError, e:
print 'WARNING: Linking failed (%s), trying to copy...' % e
if not linked:
install_copy(src,dest)
def create_repository(cfg,repodir):
"""create/update repository metadata for a given directory"""
print 'Creating repository %s' % repodir
if not os.path.exists(repodir):
os.makedirs(repodir)
# TODO: Why remove the repodata dir? Isn't that entirely createrepo's
# work? (also further below for "debug")
# ? -> https://devel.linux.duke.edu/bugzilla/show_bug.cgi?id=595
rpdata = os.path.join(repodir, 'repodata')
debugprint('removing tree %s' % rpdata)
if os.path.exists(rpdata) and not DEBUG:
shutil.rmtree(rpdata)
compsarg = ''
if os.path.exists( os.path.join(repodir,compsname) ):
compsarg = '-g %s ' % compsname
excludearg = ''
if os.path.exists( os.path.join(repodir,'debug') ):
excludearg = "-x \'*debuginfo*\'"
cmd = '%s -c %s -q %s %s %s' % (cfg.createrepo, cfg.cr_cachedir, compsarg, excludearg, repodir)
run_and_check(cmd)
def create_arch_repo(cfg,dist,arch):
"""create/update repository metadata for a given dist+arch pair and
its 'debug' sub-directory, if available"""
repodir = os.path.join(cfg.treedir, dist, arch)
create_repository(cfg,repodir)
# If there's a debug subdir, make that a repo, too.
dbg_repodir = os.path.join(repodir, 'debug')
if os.path.exists(dbg_repodir):
create_repository(cfg,dbg_repodir)
def create_src_repo(cfg,dist):
"""create/update repository metadata for a given dist"""
create_repository( cfg, os.path.join(cfg.treedir,dist,'SRPMS') )
def is_repo_changed(repodir):
"""Checks if the repository has changed and needs to be reindexed"""
ref_file = os.path.join(repodir, 'repodata', 'repomd.xml')
if not os.path.exists(ref_file):
return True
ref_mtime = os.path.getmtime(ref_file)
if os.path.getmtime(repodir) > ref_mtime:
return True
ignored_dirs = (
os.path.join(repodir, 'repodata'),
os.path.join(repodir, 'debug'),
)
for root, dirs, files in os.walk(repodir):
next = False
for ignored in ignored_dirs:
if (root + "/").find(ignored + "/") == 0:
next = True
if next:
continue
for d in map(lambda x: os.path.join(root, x), dirs):
if d in ignored_dirs:
continue
elif os.path.getmtime(d) > ref_mtime:
return True
for f in fnmatch.filter(files, '*.rpm'):
if os.path.getmtime(os.path.join(root, f)) > ref_mtime:
return True
return False
def fix_mdcache_access(workdir,cachedir):
# Work around explicit directory mode 0755 in yum/repos.py (that
# is too restrictive for our extras_signers group) and an utime
# access denied problem in urlgrabber (file ownership is needed,
# group ownership is insufficient).
#
# We copy the mdcache tree to a temporary directory in order to
# become the owner of all files, then remove the copied tree and fix
# up directory modes. For this to work flawlessly, all files must be
# readable by our group.
try:
tmpdir = tempfile.mkdtemp('','.mdcache.tmp',workdir)
if tmpdir == workdir: # paranoid, should never happen
raise Exception
except:
sys.exit(errno.EIO)
if os.path.isdir(cachedir):
tmpcachedir = os.path.join(tmpdir,'mdcache')
try:
shutil.copytree(src=cachedir,dst=tmpcachedir,symlinks=True)
except:
print 'FATAL ERROR: mdcache copytree failed'
print '%s must be writable\n%s must be readable' % (workdir, cachedir)
shutil.rmtree(tmpdir)
sys.exit(1)
for root, dirs, files in os.walk(tmpcachedir):
for file in files:
fullpath = os.path.join(root,file)
filemode = stat.S_IMODE( os.stat(fullpath).st_mode )
filemode |= stat.S_IWGRP
os.chmod(fullpath,filemode)
shutil.rmtree(cachedir)
shutil.move(src=tmpcachedir,dst=cachedir)
shutil.rmtree(tmpdir)
--- NEW FILE extras-push ---
#!/usr/bin/python -t
# 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
cfg = 'Extras'
if __name__ == '__main__':
import os, sys, errno
if len(sys.argv) < 2:
print 'Usage: %s <release|all> [release]...\n' % os.path.basename(sys.argv[0])
sys.exit(errno.EINVAL)
cmd = os.path.join(sys.path[0],'Push.py')
args = [cmd]+[cfg]+sys.argv[1:]
os.execvp(cmd,args)
--- NEW FILE extras-repobuild ---
#!/usr/bin/python -t
# 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
cfg = 'Extras'
if __name__ == '__main__':
import os, sys, errno
if len(sys.argv) < 2:
print 'Usage: %s <release>\n' % os.path.basename(sys.argv[0])
sys.exit(errno.EINVAL)
cmd = os.path.join(sys.path[0],'RepoBuild.py')
args = [cmd]+[cfg]+sys.argv[1:]
os.execv(cmd,args)
--- NEW FILE extras-repomanage ---
#!/usr/bin/python -t
# 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
cfg = 'Extras'
if __name__ == '__main__':
import os, sys, errno
if len(sys.argv) < 2:
print 'Usage: %s <release>\n' % os.path.basename(sys.argv[0])
sys.exit(errno.EINVAL)
cmd = os.path.join(sys.path[0],'RepoManage.py')
args = [cmd]+[cfg]+sys.argv[1:]
os.execvp(cmd,args)
--- NEW FILE extras-repoview ---
#!/usr/bin/python -t
# 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
cfg = 'Extras'
if __name__ == '__main__':
import os, sys, errno
if len(sys.argv) < 2:
print 'Usage: %s <release>\n' % os.path.basename(sys.argv[0])
sys.exit(errno.EINVAL)
cmd = os.path.join(sys.path[0],'RepoView.py')
args = [cmd]+[cfg]+sys.argv[1:]
os.execvp(cmd,args)
More information about the fedora-extras-commits
mailing list