Pulled the DBRTools from their own repo and popped them into this one. Still very much a 'work in progress'.
authorMattD <mattd@symbian.org>
Wed, 03 Mar 2010 17:22:06 +0000
changeset 179 eab8a264a833
parent 177 6d3c3db11e72
child 180 c201f7c7df80
Pulled the DBRTools from their own repo and popped them into this one. Still very much a 'work in progress'.
dbrtools/dbr.py
dbrtools/dbr/checkenv.py
dbrtools/dbr/cleanenv.py
dbrtools/dbr/createpatch.py
dbrtools/dbr/dbrarchive.py
dbrtools/dbr/dbrbaseline.py
dbrtools/dbr/dbrpatch.py
dbrtools/dbr/dbrutils.py
dbrtools/dbr/diffenv.py
dbrtools/dbr/help.py
dbrtools/dbr/installpatch.py
dbrtools/dbr/intro.py
dbrtools/dbr/listpatches.py
dbrtools/dbr/removepatch.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dbrtools/dbr.py	Wed Mar 03 17:22:06 2010 +0000
@@ -0,0 +1,46 @@
+# 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 <mattd@symbian.org>
+#
+# Description:
+# DBR - the root DBR script that farms out the jobs to the other scripts
+
+import sys
+import os.path
+
+def main():
+    print 'MattD: Need to fix the import path properly!'
+    dbrpath = os.path.join(os.path.dirname(sys.argv[0]),'dbr')
+    sys.path.append(dbrpath)
+    args = sys.argv
+    if(len(sys.argv)>1):
+      cmd = sys.argv[1]
+      args.pop(0)
+      args.pop(0)
+  
+      if(cmd):
+        try:
+            command = __import__ (cmd)
+            command.run(args)        
+        except ImportError:
+          help(args)
+    else:
+      help(args)
+      
+def help(args):
+  try:
+    command = __import__ ('help')
+    command.run(args)        
+  except ImportError:
+    print "error: Cannot find DBR tools help in %s" % dbrpath
+                    
+main()
+  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dbrtools/dbr/checkenv.py	Wed Mar 03 17:22:06 2010 +0000
@@ -0,0 +1,54 @@
+# 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 <mattd@symbian.org>
+#
+# Description:
+# DBR checkenv - Checks your environment against what was installed
+
+import dbrbaseline
+import dbrpatch
+import dbrutils
+import glob
+
+import os.path
+
+def main():
+    dbfilename = dbrutils.defaultdb()
+
+    baseline = dbrbaseline.readdb(dbfilename)
+    if(len(baseline ) > 0):
+        patches = dbrpatch.loadpatches(dbrpatch.dbrutils.patchpath())
+        db = dbrpatch.createpatchedbaseline(baseline,patches)
+        env = dbrutils.scanenv()
+        dbrpatch.newupdatedb(db,env)
+        baseline = dbrpatch.updatebaseline(baseline, db)
+        patches = dbrpatch.updatepatches(patches, db)
+
+        dbrpatch.savepatches(patches)        
+    else:
+        baseline = createdb()
+    dbrbaseline.writedb(baseline,dbfilename)
+
+def createdb():
+    print 'creating db...Move CreateDB into dbrutils!!!'
+    env = dbrutils.scanenv()
+    hashes = glob.glob(os.path.join(dbrutils.patchpath(),'*.md5'))
+    for file in hashes:
+        print 'Reading: %s\n' % file
+        dbrutils.gethashes(env, file)
+    return env
+
+def run(args):  
+  main()
+
+def help():
+  print "Shows the current state of the environment"
+  print "Usage\n\tdbr checkenv"
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dbrtools/dbr/cleanenv.py	Wed Mar 03 17:22:06 2010 +0000
@@ -0,0 +1,59 @@
+# 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 <mattd@symbian.org>
+#
+# Description:
+# DBR cleanenv - cleans your environment
+
+import dbrbaseline
+import dbrpatch
+import dbrutils
+
+import re #temporary for dealing with patches
+
+def main(args):
+    zippath = '/'
+    if(len(args)):
+      zippath = args[0] 
+    
+    dbfilename = dbrutils.defaultdb()
+    baseline = dbrbaseline.readdb(dbfilename)
+    if(len(baseline ) > 0):
+        env = dbrutils.scanenv()
+        patches = dbrpatch.loadpatches(dbrpatch.dbrutils.patchpath())
+        db = dbrpatch.createpatchedbaseline(baseline,patches)
+        results = dbrpatch.newupdatedb(db,env)
+        dbrutils.deletefiles(sorted(results['added']))
+        required = set()
+        required.update(results['removed'])
+        required.update(results['changed'])
+        required.update(results['untestable']) #untestable is going to be a problem...
+        dbrutils.extractfiles(required, zippath)
+        for name in sorted(patches):
+          dbrutils.extractfromzip(required, re.sub('.txt','.zip',name))        
+
+        env = dbrutils.scanenv()
+        results2 = dbrpatch.newupdatedb(db,env)          
+         
+        baseline = dbrpatch.updatebaseline(baseline, db)
+        patches = dbrpatch.updatepatches(patches, db)
+
+        dbrpatch.savepatches(patches)        
+
+
+def run(args):  
+  main(args)
+
+def help():
+  print "Cleans the current environment"
+  print "Usage\n\tdbr cleanenv (<baseline_zip_path>)"
+  print "\nDefault behaviour presumes baselie zips exist at the root"
+  
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dbrtools/dbr/createpatch.py	Wed Mar 03 17:22:06 2010 +0000
@@ -0,0 +1,45 @@
+# 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 <mattd@symbian.org>
+#
+# Description:
+# DBR createpatch - Creates a patch of the changes made to a patched baseline
+
+import sys
+import dbrbaseline
+import dbrpatch
+import dbrutils
+
+def run(args):
+    if(len(args)):
+      dbfilename = dbrutils.defaultdb()
+      patchname = args[0]
+      if(patchname):
+          print 'Creating Patch:%s\n' % patchname
+          baseline = dbrbaseline.readdb(dbfilename)
+          if(len(baseline) > 0):
+              patches = dbrpatch.loadpatches(dbrpatch.dbrutils.patchpath())
+              db = dbrpatch.createpatchedbaseline(baseline,patches)
+              env = dbrutils.scanenv()
+              db = dbrpatch.newcreatepatch(patchname,db,env)
+              baseline = dbrpatch.updatebaseline(baseline, db)
+              patches = dbrpatch.updatepatches(patches, db)
+              dbrpatch.savepatches(patches)
+              dbrbaseline.writedb(baseline,dbfilename)
+      else:
+          help()
+    else:
+      help()
+      
+def help():
+  print 'usage: Createpatch <patchname>'
+        
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dbrtools/dbr/dbrarchive.py	Wed Mar 03 17:22:06 2010 +0000
@@ -0,0 +1,55 @@
+# 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 <mattd@symbian.org>
+#
+# Description:
+# DBR archive - handles archives - not used at present
+
+import dbrutils
+import re
+
+def readarchives(dbfile):
+    db = dict()
+    if(isfile(dbfile)):
+        file = open(dbfile,'r')
+        for line in file:
+            #file structure 'name:zip
+            results = re.split(',|\n',line)
+            db[results[0]] = results[1]
+        file.close()
+    return db
+    
+def writearchives(db, dbfile):
+    file = open(dbfile,'w')
+    for archive in sorted(db):
+        str = "%s,%s\n" % (archive, db[archive])
+        file.write(str)
+    file.close()
+
+def archivefile():
+    return '/epoc32/relinfo/archive.txt'
+
+def extract(archive,files):
+    
+    db = readarchives(archivefile())
+    if(archive is in db):
+        dbrutils.unzipfiles(db[archive],files)
+    elsif(re.search('baseline' archive)): #Nasty
+        for zip in sorted(db):
+            if(re.search('baseline' zip):
+                dbrutils.unzipfiles(db[zip],files)
+    
+def install(zip): #nasty at the moment...
+#    archives = readarchives(archivefile())
+    unzip(zip)
+    
+    
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dbrtools/dbr/dbrbaseline.py	Wed Mar 03 17:22:06 2010 +0000
@@ -0,0 +1,122 @@
+# 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 <mattd@symbian.org>
+#
+# Description:
+# DBRbaseline - module for handling vanilla baselines
+#
+
+
+import re
+import os
+import string
+from os.path import join, isfile, stat
+from stat import *
+import dbrutils
+                
+
+
+def readdb(dbfile):
+    db = dict()
+    if(isfile(dbfile)):
+        file = open(dbfile,'r')
+#        regex = re.compile('(\S+)\s+(\S+)\s+(\S+)\s+(.+)\n')
+        for line in file:
+            #file structure 'timestamp size hash filename' avoids the problems of spaces in names, etc...
+            results = re.split(':|\n',line)
+            if(len(results) > 3):
+              entry = dict()
+              entry['time'] = results[0]
+              entry['size'] = results[1]
+              entry['md5'] = results[2]
+              if(results[4]):
+                entry['archive'] = results[4] 
+                print entry['archive'] 
+              db[results[3]] = entry
+#            db[results[3]] = [results[0],results[1],results[2]]
+#            bits = regex.match(line)
+#            if(bits):
+#                db[bits.group(3)] = [bits.group(0), bits.group(1), bits.group(2)]
+        file.close()
+    return db
+
+def writedb(db, dbfile):
+#    print 'Writing db to', dbfile
+    file = open(dbfile,'w')
+    for filename in sorted(db):
+        if (len(db[filename]) < 3):
+            db[filename].append('')
+        str = "%s:%s:%s:%s" %( db[filename]['time'],db[filename]['size'],db[filename]['md5'], filename)
+        if('archive' in db[filename]):
+          str = "%s:%s" %(str,db[filename]['archive'])          
+#        if(db[filename]['md5'] == 'xxx'):
+#            print 'Warning: no MD5 for %s' % filename
+#        str = "%s:%s:%s:%s\n" %( db[filename][0],db[filename][1],db[filename][2], filename)
+        file.write('%s\n' % str)
+    file.close()
+
+def md5test(db, md5testset):
+    changed = set()
+    md5s = dbrutils.generateMD5s(md5testset)
+    for file in md5testset:
+        if(db[file]['md5'] != md5s[file]['md5']):
+            changed.add(file)
+    return changed
+
+
+def updatedb(db1, db2):
+  compareupdatedb(db1, db2, 1)
+  
+def comparedb(db1, db2):
+  compareupdatedb(db1, db2, 0)
+
+def compareupdatedb(db1, db2, update):
+    print "compareupdatedb() is deprecated"
+    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)
+
+    #pobably won't bother with size changed... we know they're different...
+#    md5testset = touched - sizechanged
+    md5testset = touched
+                
+    changed = md5test(db1,md5testset)
+
+    #remove the ones we know are changed
+    touched = touched - changed
+    
+    print 'Comparing dbs/n'
+    for file in sorted(added):
+        print 'added:', file
+    for file in sorted(removed):
+        print 'removed:', file
+    for file in sorted(touched):
+        print 'touched:', file
+    for file in sorted(changed):
+        print 'changed:', file
+
+    #update the touched...
+    if(update):
+      for file in sorted(touched):
+          print 'Updating timestamp for: ',file
+          db1[file]['time'] = db2[file]['time']
--- /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 <mattd@symbian.org>
+#
+# 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
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dbrtools/dbr/dbrutils.py	Wed Mar 03 17:22:06 2010 +0000
@@ -0,0 +1,194 @@
+# 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 <mattd@symbian.org>
+#
+# Description:
+# DBRutils - Module for handling little bits of stuff to do with generating hashes and scaning directories
+
+import re
+import os
+import sys
+import string
+from os.path import join, isfile, stat
+from stat import *
+
+import glob # temporary (I hope) used for grabbing stuf from zip files...
+
+
+
+def defaultdb():
+  return os.path.join(patchpath(),'baseline.db')
+
+def patchpath():
+  return os.path.join(epocroot(),'%s/' % patch_path_internal())
+
+def patch_path_internal():
+  return 'epoc32/relinfo'
+
+def exclude_dirs():
+    fixpath = re.compile('\\\\')
+    leadingslash = re.compile('^%s' % fixpath.sub('/',epocroot()))
+    return [string.lower(leadingslash.sub('',fixpath.sub('/',os.path.join(epocroot(),'epoc32/build')))),string.lower(leadingslash.sub('',fixpath.sub('/',patch_path_internal())))]
+
+def exclude_files():
+#    return ['\.sym$','\.dll$'] # just testing...
+    return ['\.sym$']
+    
+def epocroot():
+    return os.environ.get('EPOCROOT')
+
+def scanenv():
+    print 'Scanning local environment'
+    directory = os.path.join(epocroot(),'epoc32')
+    env = scandir(directory, exclude_dirs(), exclude_files())
+    return env
+
+def createzip(files, name):
+    tmpfilename = os.tmpnam( )
+    print tmpfilename    
+    f = open(tmpfilename,'w')
+    for file in sorted(files):
+        str = '%s%s' % (file,'\n')
+        f.write(str)    
+    f.close()
+    os.chdir(epocroot())
+    exestr = '7z a -Tzip -i@%s %s' %(tmpfilename,name)
+    print 'executing: >%s<\n' %exestr
+    os.system(exestr)
+    os.unlink(tmpfilename)
+
+def extractfiles(files, path):
+    zips = glob.glob(os.path.join(path, '*.zip'))
+    for name in zips:
+      extractfromzip(files, name)    
+        
+    
+def extractfromzip(files, name):
+    tmpfilename = os.tmpnam( )
+    print tmpfilename
+    os.chdir(epocroot())
+    f = open(tmpfilename,'w')
+    for file in sorted(files):
+        str = '%s%s' % (file,'\n')
+        f.write(str)    
+    f.close()
+    exestr = '7z x -y -i@%s %s' %(tmpfilename,name)
+    print 'executing: >%s<\n' %exestr
+    os.system(exestr)
+    os.unlink(tmpfilename)
+
+def deletefiles(files):
+    os.chdir(epocroot())
+    for file in files:
+      print 'deleting %s' %file
+      os.unlink(file)
+          
+
+def generateMD5s(testset):
+    db = dict()
+    if(len(testset)):
+#      print testset
+      os.chdir(epocroot())
+      tmpfilename = os.tmpnam( )
+      print tmpfilename, '\n'
+      f = open(tmpfilename,'w')
+      for file in testset:
+          entry = dict()
+          entry['md5'] = 'xxx'
+          db[file] = entry
+          str = '%s%s' % (file,'\n')
+          f.write(str)
+      f.close()
+      outputfile = os.tmpnam() 
+      exestr = 'evalid -f %s %s %s' % (tmpfilename, epocroot(), outputfile)
+#      print exestr
+      exeresult = os.system(exestr) 
+      if(exeresult):
+        sys.exit('Fatal error executing: %s\nReported error: %s' % (exestr,os.strerror(exeresult)))
+      else:  
+        db = gethashes(db,outputfile)
+        os.unlink(outputfile)
+        os.unlink(tmpfilename)
+    return db
+
+# Brittle and nasty!!!
+def gethashes(db,md5filename):
+    os.chdir(epocroot())
+#    print 'trying to open %s' % md5filename
+    file = open(md5filename,'r')
+    root = ''
+    fixpath = re.compile('\\\\')
+    leadingslash = re.compile('^%s' % fixpath.sub('/',epocroot()))
+
+    evalidparse = re.compile('(.+)\sTYPE=(.+)\sMD5=(.+)')
+    dirparse = re.compile('Directory:(\S+)')
+    for line in file:
+        res = evalidparse.match(line)
+        if(res):
+            filename = "%s%s" % (root,res.group(1))
+            filename = string.lower(fixpath.sub('/',leadingslash.sub('',filename)))            
+#            print "found %s" % filename   
+            if(filename in db):
+                db[filename]['md5'] = res.group(3)
+
+        else:
+            res = dirparse.match(line)
+            if(res):
+                if(res.group(1) == '.'):
+                    root = ''
+                else:
+                    root = '%s/' % res.group(1)
+            
+    file.close()
+    return db
+
+
+def scandir(top, exclude_dirs, exclude_files):
+# exclude_dirs must be in lower case...
+#    print "Remember to expand the logged dir from", top, "!!!"
+    countdown = 0
+    env = dict()
+    fixpath = re.compile('\\\\')
+    leadingslash = re.compile('^%s' % fixpath.sub('/',epocroot()))
+    
+    ignorestr=''
+    for exclude in exclude_files:
+      if(len(ignorestr)):
+        ignorestr = '%s|%s' % (ignorestr, exclude)
+      else:
+        ignorestr = exclude    
+    ignore = re.compile(ignorestr) 
+
+    for root, dirs, files in os.walk(top, topdown=True):
+        for dirname in dirs:
+#            print string.lower(leadingslash.sub('',fixpath.sub('/',os.path.join(root,dirname))))
+            if(string.lower(leadingslash.sub('',fixpath.sub('/',os.path.join(root,dirname)))) in exclude_dirs):
+#              print 'removing: %s' % os.path.join(root,dirname)
+              dirs.remove(dirname)
+        for name in files:
+            filename = os.path.join(root, name)
+            statinfo = os.stat(filename)
+            fn = string.lower(leadingslash.sub('',fixpath.sub('/',filename)))
+#            print '%s\t%s' % (filename, fn);
+            if(countdown == 0):
+                print '.',
+                countdown = 1000
+            countdown = countdown-1
+            if not ignore.search(fn,1):
+              entry = dict()
+              entry['time'] = '%d' % statinfo[ST_MTIME]
+              entry['size'] = '%d' % statinfo[ST_SIZE]
+              entry['md5'] = 'xxx'
+              env[fn] = entry
+  #            data = [statinfo[ST_MTIME],statinfo[ST_SIZE],'xxx']
+  #            env[fn] = data
+    print '\n'
+    return env
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dbrtools/dbr/diffenv.py	Wed Mar 03 17:22:06 2010 +0000
@@ -0,0 +1,33 @@
+# 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 <mattd@symbian.org>
+#
+# Description:
+# DBR diffenv - compares two environments
+
+import sys
+import dbrpatch
+
+def run(args):
+    if(len(args) == 2):
+      first = args[0]
+      second = args[1]      
+      dbrpatch.newcomparepatcheddbs(first, second)
+    else:
+      help()
+      
+def help():
+  print "Compares two environments"
+  print "Usage:"
+  print "\tdbr diffenv <drive1> <drive2>"
+    
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dbrtools/dbr/help.py	Wed Mar 03 17:22:06 2010 +0000
@@ -0,0 +1,51 @@
+# 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 <mattd@symbian.org>
+#
+# Description:
+# DBR help - displays the DBR help
+
+import sys
+
+def main():
+  args = sys.argv
+  run(args)
+
+def run(args):
+    if(len(args)):
+      try:
+        tool = __import__(args[0])
+        tool.help()
+      except ImportError:
+        print "No help on %s\n" % args[0]
+        usage()
+    else:
+      usage()
+    
+def usage():    
+    print "Usage:"
+    print "\tdbr intro\t- basic introduction\n"
+
+    print "\tdbr getenv\t- installs a baseline NOT IMPLEMENTED"
+    print "\tdbr checkenv\t- Checks current environment"
+#    print "\tdbr diffbaseline\t- Compares baselines"
+    print "\tdbr diffenv\t- Compares environments"
+    print "\tdbr cleanenv\t- cleans the environment"
+    print ""
+    print "\tdbr installpatch\t- installs a patch"
+    print "\tdbr createpatch\t- creates a patch"
+    print "\tdbr removepatch\t- removes a patch"
+    print "\tdbr listpatches\t- lists patches"
+    print ""
+    print "\tdbr help - help"
+    
+def help():
+  print "No help available!"    
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dbrtools/dbr/installpatch.py	Wed Mar 03 17:22:06 2010 +0000
@@ -0,0 +1,44 @@
+# 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 <mattd@symbian.org>
+#
+# Description:
+# DBR installpatch - installs a patch in the current environment
+
+import sys
+import os.path
+#import shutils
+import dbrutils
+
+
+
+def run(args):
+  if(len(args)):
+    patch = args[0]
+    if(patch):
+      if(os.path.exists(patch)):
+        patchname = os.path.basename(patch)
+        if(not os.path.exists(os.path.join(dbrutils.patchpath(),patchname))):
+          shutils.copyfile(patch, os.path.join(dbrutils.patchpath(),patchname))
+        files = set();
+        files.add('*')
+        dbrutils.extractfromzip(files,os.path.join(dbrutils.patchpath(),patchname))
+        print 'Should probably run checkenv now...'
+      else:
+        print 'Cannot find patch zip: %s\n' %patch
+        help()
+    else:
+        help()
+  else:
+   help()
+      
+def help():
+  print 'usage: Createpatch <patchname>'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dbrtools/dbr/intro.py	Wed Mar 03 17:22:06 2010 +0000
@@ -0,0 +1,46 @@
+# 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 <mattd@symbian.org>
+#
+# Description:
+# DBR intro - displays some introductory information
+
+def run(args):
+  help()
+
+def help():  
+  l1 ='\nDBR tools are simply a way of checking what has been changed in the build you are using.' 
+  l2 ='\n\nUnlike CBRs, they intentionally make no attempt at understanding components,'
+  l3 ='and subsequently they do not have the restrictions that CBRs require.'
+  l4 ='\n\nGenerally speaking all developers work from builds of the whole platform,'
+  l5 ='and developers want to change the build, and know what they have changed,'
+  l6 ='what has changed between builds, or what they have different to other developers'
+  l7 ='with as little hastle as possible.'
+  
+  l8 ='\nThere is a patching mechanism for developer providing patches to eachother for the short-term,'
+  l9 ='but the idea is that patches are short-lived, unlike CBRs where they can live forever.'
+  l10 ='\n\nIn short, you get most of the benefits of CBRs without the hastle.'  
+  print l1,l2,l3,l4,l5,l6,l7,l8,l9,l10  
+
+  s1='\nHow To use\n\n'
+  s2='Starting Method 1:\n'
+  s3='\t1. Unpack all your zips on to a clean drive\n'
+  s4='\t2. Ensure you\'ve extracted the MD5s into epoc32/relinfo\n'
+  s5='\t3. Run \'dbr checkenv\' to generate a database\n\n'
+  s6='Starting Method 2:\n'
+  s7='\t1. Run \'dbr getenv <build_location>\' to install a full build and configure the database\n\n'
+  s8='If you want to know what you\'ve changed, run \'dbr checkenv\'\n'
+  s9='If you want to clean the environment run \'dbr cleanenv\'\n'
+  s10='If you want to compare two baselines run \'dbr diffenv <env1> <env2>\'\n'
+  
+  
+  print s1,s2,s3,s4,s5,s6,s7,s8,s9, s10
+  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dbrtools/dbr/listpatches.py	Wed Mar 03 17:22:06 2010 +0000
@@ -0,0 +1,24 @@
+# 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 <mattd@symbian.org>
+#
+# Description:
+# DBR help - displays the DBR help
+
+import dbrpatch
+
+
+def run(args):
+    dbrpatch.listpatches()
+    
+    
+def help():
+  print "lists the patches"    
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dbrtools/dbr/removepatch.py	Wed Mar 03 17:22:06 2010 +0000
@@ -0,0 +1,25 @@
+# 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 <mattd@symbian.org>
+#
+# Description:
+# DBR help - displays the DBR help
+
+import dbrpatch
+
+
+def run(args):
+  if(len(args) == 1):
+    dbrpatch.removepatch(args[0]);
+    print 'do cleanenv!!!'
+    
+def help():
+  print "removes a patch"    
\ No newline at end of file