|
| 1 | +# Performs a 'diff' on two RTK (Everywhere) Firmware settings CSV files |
| 2 | +# |
| 3 | +# E.g. the settings CSVs passed between the firmware and the web config javascript |
| 4 | +# The order of the settings going in one direction is very different to the other direction, |
| 5 | +# making it tricky to compare them directly |
| 6 | +# This code performs an exhaustive diff: looking for differences between the two; |
| 7 | +# any duplicates; and finding any settings present in one but not the other |
| 8 | + |
| 9 | +import sys |
| 10 | +import os |
| 11 | + |
| 12 | +class RTK_Settings_Diff(): |
| 13 | + |
| 14 | + def __init__(self, File1:str = None, File2:str = None): |
| 15 | + self.filename1 = File1 |
| 16 | + self.filename2 = File2 |
| 17 | + |
| 18 | + def setFilename1(self, File:str): |
| 19 | + self.filename1 = File |
| 20 | + |
| 21 | + def setFilename2(self, File:str): |
| 22 | + self.filename2 = File |
| 23 | + |
| 24 | + def readByte(self, fi): |
| 25 | + fileBytes = fi.read(1) |
| 26 | + if (len(fileBytes) == 0): |
| 27 | + return None |
| 28 | + #print(chr(fileBytes[0])) |
| 29 | + return chr(fileBytes[0]) |
| 30 | + |
| 31 | + def readFile(self, filename): |
| 32 | + print('Processing',filename) |
| 33 | + print() |
| 34 | + filesize = os.path.getsize(filename) # Record the file size |
| 35 | + |
| 36 | + # Try to open file for reading |
| 37 | + try: |
| 38 | + fi = open(filename,"rb") |
| 39 | + except: |
| 40 | + raise Exception('Invalid file!') |
| 41 | + |
| 42 | + # Read the file |
| 43 | + firstThing = '' |
| 44 | + secondThing = '' |
| 45 | + isFirstThing = True |
| 46 | + things = {} |
| 47 | + |
| 48 | + while filesize > 0: |
| 49 | + c = self.readByte(fi) |
| 50 | + if c == None: |
| 51 | + fi.close() |
| 52 | + return things |
| 53 | + elif c == ',': |
| 54 | + isFirstThing = not isFirstThing |
| 55 | + if isFirstThing: |
| 56 | + if firstThing in things.keys(): # Seen it before? |
| 57 | + print('Duplicate setting: {},{} : {}'.format(firstThing, secondThing, things[firstThing])) |
| 58 | + else: |
| 59 | + things[firstThing] = secondThing |
| 60 | + firstThing = '' |
| 61 | + secondThing = '' |
| 62 | + #print(firstThing, secondThing) |
| 63 | + elif c == '\r': |
| 64 | + pass |
| 65 | + elif c == '\n': |
| 66 | + pass |
| 67 | + else: |
| 68 | + if isFirstThing: |
| 69 | + firstThing = firstThing + str(c) |
| 70 | + else: |
| 71 | + secondThing = secondThing + str(c) |
| 72 | + filesize = filesize - 1 |
| 73 | + |
| 74 | + fi.close() |
| 75 | + return things |
| 76 | + |
| 77 | + def diff(self): |
| 78 | + |
| 79 | + print() |
| 80 | + |
| 81 | + things1 = self.readFile(self.filename1) |
| 82 | + #print(things1) |
| 83 | + |
| 84 | + print() |
| 85 | + |
| 86 | + things2 = self.readFile(self.filename2) |
| 87 | + #print(things2) |
| 88 | + |
| 89 | + print() |
| 90 | + |
| 91 | + for thing1 in things1.keys(): |
| 92 | + if thing1 not in things2.keys(): |
| 93 | + print('{},{} : only found in file 1'.format(thing1,things1[thing1])) |
| 94 | + |
| 95 | + print() |
| 96 | + |
| 97 | + for thing2 in things2.keys(): |
| 98 | + if thing2 not in things1.keys(): |
| 99 | + print('{},{} : only found in file 2'.format(thing2,things2[thing2])) |
| 100 | + |
| 101 | + print() |
| 102 | + |
| 103 | + for thing1 in things1.keys(): |
| 104 | + if thing1 in things2.keys(): |
| 105 | + if things1[thing1] != things2[thing1]: |
| 106 | + print('Diff: {},{} : {}'.format(thing1,things1[thing1],things2[thing1])) |
| 107 | + |
| 108 | +if __name__ == '__main__': |
| 109 | + |
| 110 | + import argparse |
| 111 | + |
| 112 | + parser = argparse.ArgumentParser(description='SparkFun RTK Firmware Settings Diff') |
| 113 | + parser.add_argument('File1', metavar='File1', type=str, help='The path to the first settings CSV file') |
| 114 | + parser.add_argument('File2', metavar='File2', type=str, help='The path to the second settings CSV file') |
| 115 | + args = parser.parse_args() |
| 116 | + |
| 117 | + diff = RTK_Settings_Diff(args.File1, args.File2) |
| 118 | + |
| 119 | + diff.diff() |
0 commit comments