dbrtools/dbr/dbrpatch.py
changeset 178 eab8a264a833
equal deleted inserted replaced
176:6d3c3db11e72 178:eab8a264a833
       
     1 # Copyright (c) 2009 Symbian Foundation Ltd
       
     2 # This component and the accompanying materials are made available
       
     3 # under the terms of the License "Eclipse Public License v1.0"
       
     4 # which accompanies this distribution, and is available
       
     5 # at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     6 #
       
     7 # Initial Contributors:
       
     8 # Symbian Foundation Ltd - initial contribution.
       
     9 #
       
    10 # Contributors:
       
    11 # mattd <mattd@symbian.org>
       
    12 #
       
    13 # Description:
       
    14 # DBRpatch - module for handling patched baselines
       
    15 
       
    16 import re
       
    17 import os.path #used for 'listpatches' 
       
    18 import string
       
    19 import glob
       
    20 import dbrutils
       
    21 import dbrbaseline
       
    22 
       
    23 def newcompare(db1, db2): 
       
    24     db1files = set(db1.keys())
       
    25     db2files = set(db2.keys())
       
    26 
       
    27     removed = db1files - db2files
       
    28     added = db2files - db1files
       
    29     common = db1files & db2files
       
    30 
       
    31     touched = set()
       
    32     for file in common:
       
    33         if(db1[file]['time'] != db2[file]['time']):
       
    34             touched.add(file)
       
    35 
       
    36     sizechanged = set()
       
    37     for file in common:
       
    38         if(db1[file]['size'] != db2[file]['size']):
       
    39             sizechanged.add(file)
       
    40 
       
    41     changed = set()
       
    42 
       
    43     genmd5 = 1 #I probably want to try to generate... add this as a third arg???
       
    44 
       
    45     if(len(touched)):
       
    46       if(genmd5):
       
    47         md5testset = set()
       
    48         for file in touched:
       
    49           if((db1[file]['md5'] != 'xxx' ) and (db2[file]['md5'] == 'xxx')): #no point geenrating an MD5 if we've nothing to compare it to...
       
    50 #            print 'testing %s' % file
       
    51             md5testset.add(file)
       
    52         md5s = dbrutils.generateMD5s(md5testset)
       
    53         for file in md5testset:
       
    54           db2[file]['md5'] = md5s[file]['md5']
       
    55       for file in touched:
       
    56         if(db1[file]['md5'] != db2[file]['md5']):                    
       
    57           changed.add(file)
       
    58     touched = touched - changed
       
    59 
       
    60     untestable1 = set()
       
    61     untestable2 = set()
       
    62     for file in common:
       
    63         if(db1[file]['md5'] == "xxx"):
       
    64           untestable1.add(file)  
       
    65         if(db2[file]['md5'] == 'xxx'):
       
    66           untestable2.add(file)
       
    67           
       
    68     untestable = untestable1 & untestable2         
       
    69     changed = changed - untestable
       
    70 
       
    71     #remove the ones we know are changed
       
    72     touched = touched - changed
       
    73     touched = touched - untestable
       
    74  
       
    75     results = dict()
       
    76     results['added'] = dict()
       
    77     results['removed'] = dict()
       
    78     results['touched'] = dict()
       
    79     results['changed'] = dict()
       
    80     results['untestable'] = dict()
       
    81       
       
    82     for file in added:
       
    83       results['added'][file] = db2[file]  
       
    84     for file in removed:
       
    85       results['removed'][file] = 0
       
    86     for file in touched:
       
    87       results['touched'][file] = db2[file]  
       
    88     for file in changed:
       
    89       results['changed'][file] = db2[file]  
       
    90     for file in untestable:
       
    91       results['untestable'][file] = 0  
       
    92     return results
       
    93 
       
    94 def printresults(results):
       
    95     for file in sorted (results['added']):
       
    96       print 'added:', file
       
    97     for file in sorted (results['removed']):
       
    98       print 'removed:', file              
       
    99     for file in sorted (results['touched']):   
       
   100       print 'touched:', file              
       
   101     for file in sorted (results['changed']):
       
   102       print 'changed:', file          
       
   103     for file in sorted (results['untestable']):
       
   104       print 'untestable:', file          
       
   105     if(len(results['added']) + len(results['removed']) + len(results['changed']) + len(results['untestable']) == 0):
       
   106       print '\nStatus:\tclean'
       
   107     else:
       
   108       print '\nStatus:\tdirty'
       
   109       
       
   110 def newupdatedb(baseline,env):
       
   111     results = newcompare(baseline, env)
       
   112     printresults(results)
       
   113     for file in results['touched']:
       
   114       baseline[file]['time'] = env[file]['time']
       
   115     return results    
       
   116       
       
   117 def newcreatepatch(name, db1, db2):
       
   118     results = newcompare(db1, db2)
       
   119     printresults(results)
       
   120     for file in results['touched']:
       
   121       db1[file]['time'] = db2[file]['time']
       
   122     
       
   123     patch = dict();
       
   124     patch['name'] = name
       
   125     patch['time'] = 'now!!!'   
       
   126     patch['removed'] = results['removed']
       
   127     added = results['added'].keys()
       
   128     md5sAdded = dbrutils.generateMD5s(added)
       
   129     for file in added:
       
   130       results['added'][file]['md5'] = md5sAdded[file]['md5']
       
   131     patch['added'] = results['added']
       
   132     print "Need to add in the untestable stuff here also!!!"
       
   133     patch['changed'] = results['changed']
       
   134     patchname = "%spatch_%s" %(dbrutils.patchpath(), name)
       
   135   
       
   136     createpatchzip(patch, patchname)
       
   137 
       
   138     #update the ownership 
       
   139     for file in patch['changed']:
       
   140         db1[file]['name'] = name
       
   141 
       
   142     return db1
       
   143 
       
   144 def newcomparepatcheddbs(drive1, drive2):
       
   145     envdbroot = dbrutils.defaultdb()
       
   146     print "MattD: should move this function to a better location..."
       
   147     print 'Comparing %s with %s' % (drive2,drive1)
       
   148     print 'Loading %s' % drive1 
       
   149     baseline1 = dbrbaseline.readdb('%s%s' %(drive1,envdbroot))
       
   150     patches1 = loadpatches('%s/%s' %(drive1,dbrutils.patchpath()))
       
   151     db1 = createpatchedbaseline(baseline1,patches1)
       
   152 
       
   153     print 'Loading %s' % drive2 
       
   154     baseline2 = dbrbaseline.readdb('%s%s' %(drive2,envdbroot))
       
   155     patches2 = loadpatches('%s/%s' %(drive2,dbrutils.patchpath()))
       
   156     db2 = createpatchedbaseline(baseline2,patches2)
       
   157 
       
   158     results = newcompare(db1, db2)
       
   159     printresults(results)
       
   160  
       
   161 
       
   162 
       
   163 def createpatchzip(patch, patchname):
       
   164     patchtext = '%s.txt' % patchname
       
   165     patchtext = os.path.join(dbrutils.patchpath(),patchtext)
       
   166     
       
   167     writepatch(patch, patchtext)    
       
   168     files = set()
       
   169     files.update(patch['added'])
       
   170     files.update(patch['changed'])
       
   171     files.add(re.sub('\\\\','',patchtext)) #remove leading slash - Nasty - need to fix the whole EPOCROOT thing.
       
   172     
       
   173     zipname = '%s.zip' % patchname
       
   174     dbrutils.createzip(files, zipname)         
       
   175     
       
   176 
       
   177 def updatebaseline(baseline, db):
       
   178   for file in (db.keys()):
       
   179     origin = db[file]['name']
       
   180     if(origin == 'baseline'):
       
   181       if(baseline[file]['time'] != db[file]['time']):
       
   182          baseline[file]['time'] = db[file]['time']
       
   183          print 'Updating timestamp for %s in baseline' % file
       
   184   return baseline
       
   185 
       
   186 def updatepatches(patches, db):
       
   187   for file in (db.keys()):
       
   188       origin = db[file]['name']
       
   189       for patch in patches.keys():
       
   190         if(patches[patch]['name'] == origin):                                        
       
   191             mod=0                    
       
   192             if(file in patches[patch]['added']):
       
   193                mod = 'added'
       
   194             if(file in patches[patch]['changed']):
       
   195                 mod = 'changed'
       
   196             if(mod):
       
   197                 if (patches[patch][mod][file]['time'] != db[file]['time']):
       
   198                   patches[patch][mod][file]['time'] = db[file]['time']
       
   199                   print 'Updating timestamp in %s for %s' %(patches[patch]['name'],file)
       
   200   return patches            
       
   201     
       
   202 
       
   203 def createpatchedbaseline(baseline,patches):
       
   204     files = dict()
       
   205     files = addtodb(files,baseline,'baseline')
       
   206     for patch in sorted(patches.keys()):
       
   207 #        print 'adding patch: %s' % patch
       
   208         files = addtodb(files,patches[patch]['added'],patches[patch]['name'])
       
   209         files = addtodb(files,patches[patch]['changed'],patches[patch]['name'])
       
   210         files = removefromdb(files,patches[patch]['removed'],patches[patch]['name'])
       
   211     return files    
       
   212 
       
   213 def removefromdb(db,removed,name):
       
   214     for file in removed:
       
   215         if(file in db):
       
   216 #            print '%s removing %s' %(name,file)
       
   217             del db[file]
       
   218     return db
       
   219 
       
   220 def addtodb(db,new,name):
       
   221     for file in new:
       
   222         if(file not in db):
       
   223             db[file] = dict()
       
   224 #        else:
       
   225 #            print '%s overriding %s' % (name,file)
       
   226         db[file]['time'] = new[file]['time']
       
   227         db[file]['md5'] = new[file]['md5']
       
   228         db[file]['size'] = new[file]['size']
       
   229         db[file]['name'] = name
       
   230     return db
       
   231 
       
   232 def listpatches():
       
   233     path = dbrutils.patchpath()
       
   234     patchfiles = glob.glob('%spatch*.txt' % path)
       
   235     print 'Installed patches'
       
   236     for file in patchfiles:
       
   237       print '\t%s' % re.sub('.txt','',os.path.basename(file))
       
   238 
       
   239 def removepatch(patch):
       
   240     path = dbrutils.patchpath()
       
   241     file = '%s%s%s' %(path,patch,'.txt')
       
   242     files = set()
       
   243     files.add(file)
       
   244     dbrutils.deletefiles(files)
       
   245         
       
   246 
       
   247 def loadpatches(path):
       
   248     patches = dict()
       
   249     patchfiles = glob.glob('%spatch*.txt' % path)
       
   250 
       
   251     for file in patchfiles:
       
   252         print 'Loading patch: %s' % re.sub('.txt','',os.path.basename(file))
       
   253 #        print 'Reading: %s\n' % file
       
   254 #        patchname = re.match('\S+patch(\S+)\.txt',file)
       
   255 #        print 'patchname %s' % patchname.group(1);
       
   256         patch = readpatch(file)
       
   257 #        patches[patchname.group(1)] = patch
       
   258 #        print 'Read %s from %s' % (patch['name'],file)
       
   259         patches[file] = patch
       
   260     return patches
       
   261 
       
   262 
       
   263 def savepatches(patches):
       
   264     for patch in sorted(patches.keys()):
       
   265  #       print 'writing %s to %s' % (patches[patch]['name'],patch)
       
   266         writepatch(patches[patch], patch)
       
   267 
       
   268 
       
   269 def writepatch(patch, filename):
       
   270     file = open(filename,'w')
       
   271 #    print 'saving patch to %s' %filename
       
   272     file.write("name=%s\n" % patch['name']);
       
   273     file.write("time=%s\n" % patch['time']);
       
   274     
       
   275     removed = patch['removed']
       
   276     for filename in sorted(removed):
       
   277         str = "removed=%s\n" % filename
       
   278         file.write(str)
       
   279 
       
   280     added = patch['added']    
       
   281     for filename in sorted(added):
       
   282         if (len(added[filename]) < 3):
       
   283             added[filename].append('')
       
   284         str = "added=%s:%s:%s:%s\n" %( added[filename]['time'],added[filename]['size'],added[filename]['md5'], filename)
       
   285         file.write(str)
       
   286 
       
   287     changed = patch['changed']    
       
   288     for filename in sorted(changed):
       
   289         if (len(changed[filename]) < 3):
       
   290             changed[filename].append('')
       
   291         str = "changed=%s:%s:%s:%s\n" %( changed[filename]['time'],changed[filename]['size'],changed[filename]['md5'], filename)
       
   292         file.write(str)
       
   293     file.close()
       
   294         
       
   295 
       
   296 def readpatch(filename):
       
   297     file = open(filename,'r')
       
   298     #name=blah
       
   299     #time=blah
       
   300     #removed=file
       
   301     #added=time:size:md5:file
       
   302     #changed=time:size:md5:file
       
   303     patch = dict()
       
   304     removed = set()
       
   305     added = dict()
       
   306     changed = dict()
       
   307     for line in file:    
       
   308         results = re.split('=|\n',line)
       
   309         type = results[0]
       
   310         if( type == 'name'):
       
   311             patch['name'] = results[1]
       
   312         elif( type == 'time'):
       
   313             patch['time'] = results[1]
       
   314         elif( type == 'removed'):            
       
   315             removed.add(results[1]) 
       
   316         elif(( type == 'added') or (type == 'changed')):
       
   317             results2 = re.split(':|\n',results[1])
       
   318             entry = dict()
       
   319             entry['time'] = results2[0]
       
   320             entry['size'] = results2[1]
       
   321             entry['md5'] = results2[2]
       
   322             if(type == 'added'):
       
   323                 added[results2[3]] = entry
       
   324             else:
       
   325                 changed[results2[3]] = entry
       
   326     file.close()
       
   327     patch['removed'] = removed
       
   328     patch['added'] = added
       
   329     patch['changed'] = changed
       
   330     return patch
       
   331