koji-shadow: Initial setup of code to prefer a newer build
This commit is contained in:
parent
b55c3dc28c
commit
828ecc7484
1 changed files with 54 additions and 4 deletions
|
|
@ -41,6 +41,7 @@ import time
|
|||
import urllib2
|
||||
import urlgrabber.grabber as grabber
|
||||
import xmlrpclib # for ProtocolError and Fault
|
||||
import rpm
|
||||
|
||||
# koji.fp.o keeps stalling, probably network errors...
|
||||
# better to time out than to stall
|
||||
|
|
@ -104,6 +105,8 @@ def get_options():
|
|||
help=_("url of local XMLRPC server"))
|
||||
parser.add_option("-r", "--remote",
|
||||
help=_("url of remote XMLRPC server"))
|
||||
parser.add_option("--prefer-new", action="store_true", default=False,
|
||||
help=_("if there is a newer build locally prefer it for deps"))
|
||||
parser.add_option("--import-noarch", action="store_true",
|
||||
help=_("import missing noarch builds rather than rebuilding"))
|
||||
parser.add_option("--link-imports", action="store_true",
|
||||
|
|
@ -118,6 +121,12 @@ def get_options():
|
|||
help=_("CA certificate for authentication"))
|
||||
parser.add_option("--serverca",
|
||||
help=_("Server CA certificate"))
|
||||
parser.add_option("--rules",
|
||||
help=_("rules"))
|
||||
parser.add_option("--rules-greylist",
|
||||
help=_("greylist rules"))
|
||||
parser.add_option("--rules-blacklist",
|
||||
help=_("blacklist rules"))
|
||||
#parse once to get the config file
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
|
|
@ -319,6 +328,10 @@ class TrackedBuild(object):
|
|||
self.tracker = tracker
|
||||
self.info = remote.getBuild(build_id)
|
||||
self.nvr = "%(name)s-%(version)s-%(release)s" % self.info
|
||||
self.name = "%(name)s" % self.info
|
||||
self.epoch = "%(epoch)s" % self.info
|
||||
self.version = "%(version)s" % self.info
|
||||
self.release = "%(release)s" % self.info
|
||||
self.srpm = None
|
||||
self.rpms = None
|
||||
self.children = {}
|
||||
|
|
@ -573,6 +586,36 @@ class BuildTracker(object):
|
|||
return grey
|
||||
return default
|
||||
|
||||
def rpmvercmp (self, (e1, v1, r1), (e2, v2, r2)):
|
||||
"""find out which build is newer"""
|
||||
rc = rpm.labelCompare((e1, v1, r1), (e2, v2, r2))
|
||||
if rc == 1:
|
||||
#first evr wins
|
||||
return 1
|
||||
elif rc == 0:
|
||||
#same evr
|
||||
return 0
|
||||
else:
|
||||
#second evr wins
|
||||
return -1
|
||||
|
||||
def newerBuild(self, build, tag):
|
||||
#XXX: secondary arches need a policy to say if we have newer builld localy it will be the substitute
|
||||
if build.epoch is None:
|
||||
build.epoch = 0
|
||||
localLatestBuild = session.getLatestBuilds(tag, package=str(build.name))
|
||||
if localLatestBuild:
|
||||
parentevr = (str(build.epoch), build.version, build.release)
|
||||
latestevr = (str(localLatestBuild[0]['epoch']), localLatestBuild[0]['version'], localLatestBuild[0]['release'])
|
||||
newestRPM = self.rpmvercmp( parentevr, latestevr)
|
||||
if newestRPM == -1:
|
||||
#the local is newer
|
||||
print "Newer Build: %s-%s-%s" % (str(localLatestBuild[0]['name']), localLatestBuild[0]['version'], localLatestBuild[0]['release'] )
|
||||
info = session.getBuild("%s-%s-%s" % (str(localLatestBuild[0]['name']), localLatestBuild[0]['version'], localLatestBuild[0]['release'] ))
|
||||
if info:
|
||||
build = LocalBuild(info)
|
||||
return build
|
||||
|
||||
def getSubstitute(self, nvr):
|
||||
build = self.substitute_idx.get(nvr)
|
||||
if not build:
|
||||
|
|
@ -594,7 +637,7 @@ class BuildTracker(object):
|
|||
self.substitute_idx[nvr] = build
|
||||
return build
|
||||
|
||||
def scanBuild(self, build_id, from_build=None, depth=0):
|
||||
def scanBuild(self, build_id, from_build=None, depth=0, tag=None):
|
||||
"""Recursively scan a build and its dependencies"""
|
||||
#print build_id
|
||||
build = self.builds.get(build_id)
|
||||
|
|
@ -639,6 +682,13 @@ class BuildTracker(object):
|
|||
if depth > 0:
|
||||
print "%sDep replaced: %s->%s" % (head, build.nvr, replace)
|
||||
return build
|
||||
if options.prefer_new:
|
||||
if build.state != "common":
|
||||
latestBuild = self.newerBuild(build, tag)
|
||||
if latestBuild != None:
|
||||
build.substitute = latestBuild.nvr
|
||||
print "%sNewer build replaced: %s->%s" % (head, build.nvr, latestBuild.nvr)
|
||||
return build
|
||||
if build.state == "common":
|
||||
#we're good
|
||||
if build.rebuilt:
|
||||
|
|
@ -670,11 +720,11 @@ class BuildTracker(object):
|
|||
newdeps = []
|
||||
#don't actually set build.revised_deps until we finish the dep scan
|
||||
for dep_id in build.deps:
|
||||
dep = self.scanBuild(dep_id, from_build=build, depth=depth+1)
|
||||
dep = self.scanBuild(dep_id, from_build=build, depth=depth+1, tag=tag)
|
||||
if dep.substitute:
|
||||
dep2 = self.getSubstitute(dep.substitute)
|
||||
if isinstance(dep2, TrackedBuild):
|
||||
self.scanBuild(dep2.id, from_build=build, depth=depth+1)
|
||||
self.scanBuild(dep2.id, from_build=build, depth=depth+1, tag=tag)
|
||||
elif dep2 is None:
|
||||
#dep is missing on both local and remote
|
||||
print "%sSubstitute dep unavailable: %s" % (head, dep2.nvr)
|
||||
|
|
@ -709,7 +759,7 @@ class BuildTracker(object):
|
|||
for build in builds:
|
||||
for retry in xrange(10):
|
||||
try:
|
||||
self.scanBuild(build['id'])
|
||||
self.scanBuild(build['id'], tag=tag)
|
||||
if options.first_one:
|
||||
return
|
||||
except (socket.timeout, socket.error):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue