diff -r 6d3c3db11e72 -r eab8a264a833 dbrtools/dbr/dbrpatch.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dbrtools/dbr/dbrpatch.py Wed Mar 03 17:22:06 2010 +0000 @@ -0,0 +1,331 @@ +# Copyright (c) 2009 Symbian Foundation Ltd +# This component and the accompanying materials are made available +# under the terms of the License "Eclipse Public License v1.0" +# which accompanies this distribution, and is available +# at the URL "http://www.eclipse.org/legal/epl-v10.html". +# +# Initial Contributors: +# Symbian Foundation Ltd - initial contribution. +# +# Contributors: +# mattd +# +# Description: +# DBRpatch - module for handling patched baselines + +import re +import os.path #used for 'listpatches' +import string +import glob +import dbrutils +import dbrbaseline + +def newcompare(db1, db2): + db1files = set(db1.keys()) + db2files = set(db2.keys()) + + removed = db1files - db2files + added = db2files - db1files + common = db1files & db2files + + touched = set() + for file in common: + if(db1[file]['time'] != db2[file]['time']): + touched.add(file) + + sizechanged = set() + for file in common: + if(db1[file]['size'] != db2[file]['size']): + sizechanged.add(file) + + changed = set() + + genmd5 = 1 #I probably want to try to generate... add this as a third arg??? + + if(len(touched)): + if(genmd5): + md5testset = set() + for file in touched: + if((db1[file]['md5'] != 'xxx' ) and (db2[file]['md5'] == 'xxx')): #no point geenrating an MD5 if we've nothing to compare it to... +# print 'testing %s' % file + md5testset.add(file) + md5s = dbrutils.generateMD5s(md5testset) + for file in md5testset: + db2[file]['md5'] = md5s[file]['md5'] + for file in touched: + if(db1[file]['md5'] != db2[file]['md5']): + changed.add(file) + touched = touched - changed + + untestable1 = set() + untestable2 = set() + for file in common: + if(db1[file]['md5'] == "xxx"): + untestable1.add(file) + if(db2[file]['md5'] == 'xxx'): + untestable2.add(file) + + untestable = untestable1 & untestable2 + changed = changed - untestable + + #remove the ones we know are changed + touched = touched - changed + touched = touched - untestable + + results = dict() + results['added'] = dict() + results['removed'] = dict() + results['touched'] = dict() + results['changed'] = dict() + results['untestable'] = dict() + + for file in added: + results['added'][file] = db2[file] + for file in removed: + results['removed'][file] = 0 + for file in touched: + results['touched'][file] = db2[file] + for file in changed: + results['changed'][file] = db2[file] + for file in untestable: + results['untestable'][file] = 0 + return results + +def printresults(results): + for file in sorted (results['added']): + print 'added:', file + for file in sorted (results['removed']): + print 'removed:', file + for file in sorted (results['touched']): + print 'touched:', file + for file in sorted (results['changed']): + print 'changed:', file + for file in sorted (results['untestable']): + print 'untestable:', file + if(len(results['added']) + len(results['removed']) + len(results['changed']) + len(results['untestable']) == 0): + print '\nStatus:\tclean' + else: + print '\nStatus:\tdirty' + +def newupdatedb(baseline,env): + results = newcompare(baseline, env) + printresults(results) + for file in results['touched']: + baseline[file]['time'] = env[file]['time'] + return results + +def newcreatepatch(name, db1, db2): + results = newcompare(db1, db2) + printresults(results) + for file in results['touched']: + db1[file]['time'] = db2[file]['time'] + + patch = dict(); + patch['name'] = name + patch['time'] = 'now!!!' + patch['removed'] = results['removed'] + added = results['added'].keys() + md5sAdded = dbrutils.generateMD5s(added) + for file in added: + results['added'][file]['md5'] = md5sAdded[file]['md5'] + patch['added'] = results['added'] + print "Need to add in the untestable stuff here also!!!" + patch['changed'] = results['changed'] + patchname = "%spatch_%s" %(dbrutils.patchpath(), name) + + createpatchzip(patch, patchname) + + #update the ownership + for file in patch['changed']: + db1[file]['name'] = name + + return db1 + +def newcomparepatcheddbs(drive1, drive2): + envdbroot = dbrutils.defaultdb() + print "MattD: should move this function to a better location..." + print 'Comparing %s with %s' % (drive2,drive1) + print 'Loading %s' % drive1 + baseline1 = dbrbaseline.readdb('%s%s' %(drive1,envdbroot)) + patches1 = loadpatches('%s/%s' %(drive1,dbrutils.patchpath())) + db1 = createpatchedbaseline(baseline1,patches1) + + print 'Loading %s' % drive2 + baseline2 = dbrbaseline.readdb('%s%s' %(drive2,envdbroot)) + patches2 = loadpatches('%s/%s' %(drive2,dbrutils.patchpath())) + db2 = createpatchedbaseline(baseline2,patches2) + + results = newcompare(db1, db2) + printresults(results) + + + +def createpatchzip(patch, patchname): + patchtext = '%s.txt' % patchname + patchtext = os.path.join(dbrutils.patchpath(),patchtext) + + writepatch(patch, patchtext) + files = set() + files.update(patch['added']) + files.update(patch['changed']) + files.add(re.sub('\\\\','',patchtext)) #remove leading slash - Nasty - need to fix the whole EPOCROOT thing. + + zipname = '%s.zip' % patchname + dbrutils.createzip(files, zipname) + + +def updatebaseline(baseline, db): + for file in (db.keys()): + origin = db[file]['name'] + if(origin == 'baseline'): + if(baseline[file]['time'] != db[file]['time']): + baseline[file]['time'] = db[file]['time'] + print 'Updating timestamp for %s in baseline' % file + return baseline + +def updatepatches(patches, db): + for file in (db.keys()): + origin = db[file]['name'] + for patch in patches.keys(): + if(patches[patch]['name'] == origin): + mod=0 + if(file in patches[patch]['added']): + mod = 'added' + if(file in patches[patch]['changed']): + mod = 'changed' + if(mod): + if (patches[patch][mod][file]['time'] != db[file]['time']): + patches[patch][mod][file]['time'] = db[file]['time'] + print 'Updating timestamp in %s for %s' %(patches[patch]['name'],file) + return patches + + +def createpatchedbaseline(baseline,patches): + files = dict() + files = addtodb(files,baseline,'baseline') + for patch in sorted(patches.keys()): +# print 'adding patch: %s' % patch + files = addtodb(files,patches[patch]['added'],patches[patch]['name']) + files = addtodb(files,patches[patch]['changed'],patches[patch]['name']) + files = removefromdb(files,patches[patch]['removed'],patches[patch]['name']) + return files + +def removefromdb(db,removed,name): + for file in removed: + if(file in db): +# print '%s removing %s' %(name,file) + del db[file] + return db + +def addtodb(db,new,name): + for file in new: + if(file not in db): + db[file] = dict() +# else: +# print '%s overriding %s' % (name,file) + db[file]['time'] = new[file]['time'] + db[file]['md5'] = new[file]['md5'] + db[file]['size'] = new[file]['size'] + db[file]['name'] = name + return db + +def listpatches(): + path = dbrutils.patchpath() + patchfiles = glob.glob('%spatch*.txt' % path) + print 'Installed patches' + for file in patchfiles: + print '\t%s' % re.sub('.txt','',os.path.basename(file)) + +def removepatch(patch): + path = dbrutils.patchpath() + file = '%s%s%s' %(path,patch,'.txt') + files = set() + files.add(file) + dbrutils.deletefiles(files) + + +def loadpatches(path): + patches = dict() + patchfiles = glob.glob('%spatch*.txt' % path) + + for file in patchfiles: + print 'Loading patch: %s' % re.sub('.txt','',os.path.basename(file)) +# print 'Reading: %s\n' % file +# patchname = re.match('\S+patch(\S+)\.txt',file) +# print 'patchname %s' % patchname.group(1); + patch = readpatch(file) +# patches[patchname.group(1)] = patch +# print 'Read %s from %s' % (patch['name'],file) + patches[file] = patch + return patches + + +def savepatches(patches): + for patch in sorted(patches.keys()): + # print 'writing %s to %s' % (patches[patch]['name'],patch) + writepatch(patches[patch], patch) + + +def writepatch(patch, filename): + file = open(filename,'w') +# print 'saving patch to %s' %filename + file.write("name=%s\n" % patch['name']); + file.write("time=%s\n" % patch['time']); + + removed = patch['removed'] + for filename in sorted(removed): + str = "removed=%s\n" % filename + file.write(str) + + added = patch['added'] + for filename in sorted(added): + if (len(added[filename]) < 3): + added[filename].append('') + str = "added=%s:%s:%s:%s\n" %( added[filename]['time'],added[filename]['size'],added[filename]['md5'], filename) + file.write(str) + + changed = patch['changed'] + for filename in sorted(changed): + if (len(changed[filename]) < 3): + changed[filename].append('') + str = "changed=%s:%s:%s:%s\n" %( changed[filename]['time'],changed[filename]['size'],changed[filename]['md5'], filename) + file.write(str) + file.close() + + +def readpatch(filename): + file = open(filename,'r') + #name=blah + #time=blah + #removed=file + #added=time:size:md5:file + #changed=time:size:md5:file + patch = dict() + removed = set() + added = dict() + changed = dict() + for line in file: + results = re.split('=|\n',line) + type = results[0] + if( type == 'name'): + patch['name'] = results[1] + elif( type == 'time'): + patch['time'] = results[1] + elif( type == 'removed'): + removed.add(results[1]) + elif(( type == 'added') or (type == 'changed')): + results2 = re.split(':|\n',results[1]) + entry = dict() + entry['time'] = results2[0] + entry['size'] = results2[1] + entry['md5'] = results2[2] + if(type == 'added'): + added[results2[3]] = entry + else: + changed[results2[3]] = entry + file.close() + patch['removed'] = removed + patch['added'] = added + patch['changed'] = changed + return patch +