# ko build builds /tmp/nled-2.52-7.fc15.src.rpm 282 build (builds, nled-2.52-7.fc15.src.rpm) completed successfully # ko build builds /tmp/nled-2.52-7.fc15.src.rpm 290 build (builds, nled-2.52-7.fc15.src.rpm) completed successfully # ko build builds /tmp/nled-2.52-7.fc15.src.rpm 298 build (builds, nled-2.52-7.fc15.src.rpm) completed successfully # ko list-tagged builds nled Build Tag Built by ---------------------------------------- -------------------- ---------------- nled-2.52-7.267919.111107.fc15 builds admin nled-2.52-7.496d81.111107.fc15 builds admin nled-2.52-7.fc15 builds admin # ls -l /mnt/koji/packages/nled/2.52 total 12 drwxr-xr-x 6 apache apache 4096 Nov 7 19:43 7.267919.111107.fc15 drwxr-xr-x 6 apache apache 4096 Nov 7 19:52 7.496d81.111107.fc15 drwxr-xr-x 6 apache apache 4096 Nov 7 20:01 7.fc15 ... # ko list-tagged builds --latest nled Build Tag Built by ---------------------------------------- -------------------- ---------------- nled-2.52-7.fc15 builds admin # yum clean all ; yum --disablerepo=* --enablerepo=custom-test list nled nled.x86_64 2.52-7.fc15 custom-test
Code change: ( Don’t forget: import hashlib )
> ./hub/kojihub.py
def new_build(data): """insert a new build entry""" tdic = data.copy() data = data.copy() if not data.has_key('pkg_id'): #see if there's a package name name = data.get('name') if not name: raise koji.GenericError, "No name or package id provided for build" data['pkg_id'] = new_package(name,strict=False) for f in ('version','release','epoch'): if not data.has_key(f): raise koji.GenericError, "No %s value for build" % f #provide a few default values data.setdefault('state',koji.BUILD_STATES['COMPLETE']) data.setdefault('completion_time', 'NOW') data.setdefault('owner',context.session.user_id) data.setdefault('task_id',None) #check for existing build # TODO - table lock? q="""SELECT id,state,task_id FROM build WHERE pkg_id=%(pkg_id)d AND version=%(version)s AND release=%(release)s FOR UPDATE""" row = _fetchSingle(q, data) if row: id, state, task_id = row data['id'] = id st_desc = koji.BUILD_STATES[state] if st_desc == 'BUILDING': koji.plugin.run_callbacks('preBuildStateChange', attribute='state', old=state, new=data['state'], info=data) # check to see if this is the controlling task if data['state'] == state and data.get('task_id','') == task_id: #the controlling task must have restarted (and called initBuild again) return id raise koji.GenericError, "Build already in progress (task %d)" % task_id # TODO? - reclaim 'stale' builds (state=BUILDING and task_id inactive) elif st_desc in ('FAILED','CANCELED'): koji.plugin.run_callbacks('preBuildStateChange', attribute='state', old=state, new=data['state'], info=data) #should be ok to replace update = """UPDATE build SET state=%(state)i,task_id=%(task_id)s, owner=%(owner)s,completion_time=%(completion_time)s,create_event=get_event() WHERE id = %(id)i""" _dml(update, data) koji.plugin.run_callbacks('postBuildStateChange', attribute='state', old=state, new=data['state'], info=data) return id else: # BEG METHOD HIJACK # open the current file frot = "/mnt/koji/packages" fpth = ("%s/%s/%s" % (str(data["name"]), str(data["version"]), str(data["release"]))) fnme = ("%s-%s-%s" % (str(data["name"]), str(data["version"]), str(data["release"]))) fsrc = ("%s/%s/src/%s.src.rpm" % (frot, fpth, fnme)) try: fobj = open(fsrc, "r") except: raise koji.GenericError, "Could not open file [%s]" % (fsrc) # hash the current file hobj = hashlib.md5() while (1): fdta = fobj.read(2**10) if (not fdta): break hobj.update(fdta) fobj.close() hash = hobj.hexdigest() tida = time.strftime("%y%m%d") # set the new release name while (1): rell = str(data["release"]).rsplit(".", 1) rell.insert(1, hash[0:6] + "." + tida) reln = ".".join(rell) foln = ("%s/%s/%s/%s" % (frot, str(data["name"]), str(data["version"]), reln)) if (not os.path.exists(foln)): break hobj = hashlib.md5() hobj.update(hash) hash = hobj.hexdigest() data["reln"] = reln # get a list of old files/folders fill = [] dirl = ["%s/%s" % (frot, fpth)] while (len(dirl) > 0): try: tmpl = os.listdir(dirl[0]) except: tmpl = [] parn = dirl[0] dirl.pop(0) for tmpi in tmpl: tpth = ("%s/%s" % (parn, tmpi)) if (os.path.isdir(tpth)): dirl.append(tpth) else: name = re.sub("[^0-9A-Za-z]", ".", str(data["name"])) vers = re.sub("[^0-9A-Za-z]", ".", str(data["version"])) rels = re.sub("[^0-9A-Za-z]", ".", str(data["release"])) robj = re.match("^(.*)%s(.*)%s(.*)%s(.*)$" % (name, vers, rels), tmpi) if (robj): newn = (parn + "/" + robj.group(1) + name + robj.group(2) + vers + robj.group(3) + reln + robj.group(4)) fill.append([tpth, newn]) fill.append([frot + "/" + fpth, foln]) # update the sql database c = context.cnx.cursor() buil = "UPDATE build SET release=%(reln)s WHERE id = %(id)i" #_dml(buil, data) c.execute(buil, data) rpmi = "UPDATE rpminfo SET release=%(reln)s WHERE build_id = %(id)i" #_dml(rpmi, data) c.execute(rpmi, data) context.cnx.commit() c.close() # rename the files/folders now for item in fill: os.rename(item[0], item[1]) # carry on the same now return new_build(tdic) # END METHOD HIJACK else: koji.plugin.run_callbacks('preBuildStateChange', attribute='state', old=None, new=data['state'], info=data) #insert the new data data['id'] = _singleValue("SELECT nextval('build_id_seq')") q=""" INSERT INTO build (id,pkg_id,version,release,epoch,state, task_id,owner,completion_time) VALUES (%(id)i,%(pkg_id)i,%(version)s,%(release)s,%(epoch)s, %(state)s,%(task_id)s,%(owner)s,%(completion_time)s) """ _dml(q, data) koji.plugin.run_callbacks('postBuildStateChange', attribute='state', old=None, new=data['state'], info=data) #return build_id return data['id']
[…] Edit: I also did a little Koji mod which could bypass the “one-build” restriction here […]