1#!/usr/bin/env python3 2# 3# diffconfig - a tool to compare .config files. 4# 5# originally written in 2006 by Matt Mackall 6# (at least, this was in his bloatwatch source code) 7# last worked on 2008 by Tim Bird for the Linux kernel 8# Adapted to Buildroot 2017 by Marcus Folkesson 9# 10 11import sys, os 12 13def usage(): 14 print("""Usage: diffconfig [-h] [-m] [<config1> <config2>] 15 16Diffconfig is a simple utility for comparing two .config files. 17Using standard diff to compare .config files often includes extraneous and 18distracting information. This utility produces sorted output with only the 19changes in configuration values between the two files. 20 21Added and removed items are shown with a leading plus or minus, respectively. 22Changed items show the old and new values on a single line. 23 24If -m is specified, then output will be in "merge" style, which has the 25changed and new values in kernel config option format. 26 27If no config files are specified, .config and .config.old are used. 28 29Example usage: 30 $ diffconfig .config config-with-some-changes 31-BR2_LINUX_KERNEL_INTREE_DTS_NAME "vexpress-v2p-ca9" 32 BR2_LINUX_KERNEL_DTS_SUPPORT y -> n 33 BR2_LINUX_KERNEL_USE_INTREE_DTS y -> n 34 BR2_PACKAGE_DFU_UTIL n -> y 35 BR2_PACKAGE_LIBUSB n -> y 36 BR2_TARGET_GENERIC_HOSTNAME "buildroot" -> "Tuxie" 37 BR2_TARGET_GENERIC_ISSUE "Welcome to Buildroot" -> "Welcome to CustomBoard" 38+BR2_PACKAGE_LIBUSB_COMPAT n 39 40""") 41 sys.exit(0) 42 43# returns a dictionary of name/value pairs for config items in the file 44def readconfig(config_file): 45 d = {} 46 for line in config_file: 47 line = line.strip() 48 if len(line) == 0: 49 continue 50 if line[-11:] == " is not set": 51 d[line[2:-11]] = "n" 52 elif line[0] != "#": 53 name, val = line.split("=", 1) 54 d[name] = val 55 return d 56 57def print_config(op, config, value, new_value): 58 global merge_style 59 60 if merge_style: 61 if new_value: 62 if new_value=="n": 63 print("# %s is not set" % config) 64 else: 65 print("%s=%s" % (config, new_value)) 66 else: 67 if op=="-": 68 print("-%s %s" % (config, value)) 69 elif op=="+": 70 print("+%s %s" % (config, new_value)) 71 else: 72 print(" %s %s -> %s" % (config, value, new_value)) 73 74def main(): 75 global merge_style 76 77 # parse command line args 78 if ("-h" in sys.argv or "--help" in sys.argv): 79 usage() 80 81 merge_style = 0 82 if "-m" in sys.argv: 83 merge_style = 1 84 sys.argv.remove("-m") 85 86 argc = len(sys.argv) 87 if not (argc==1 or argc == 3): 88 print("Error: incorrect number of arguments or unrecognized option") 89 usage() 90 91 if argc == 1: 92 # if no filenames given, assume .config and .config.old 93 build_dir="" 94 if "KBUILD_OUTPUT" in os.environ: 95 build_dir = os.environ["KBUILD_OUTPUT"]+"/" 96 configa_filename = build_dir + ".config.old" 97 configb_filename = build_dir + ".config" 98 else: 99 configa_filename = sys.argv[1] 100 configb_filename = sys.argv[2] 101 102 try: 103 a = readconfig(open(configa_filename)) 104 b = readconfig(open(configb_filename)) 105 except (IOError): 106 e = sys.exc_info()[1] 107 print("I/O error[%s]: %s\n" % (e.args[0],e.args[1])) 108 usage() 109 110 # print items in a but not b (accumulate, sort and print) 111 old = [] 112 for config in a: 113 if config not in b: 114 old.append(config) 115 old.sort() 116 for config in old: 117 print_config("-", config, a[config], None) 118 del a[config] 119 120 # print items that changed (accumulate, sort, and print) 121 changed = [] 122 for config in a: 123 if a[config] != b[config]: 124 changed.append(config) 125 else: 126 del b[config] 127 changed.sort() 128 for config in changed: 129 print_config("->", config, a[config], b[config]) 130 del b[config] 131 132 # now print items in b but not in a 133 # (items from b that were in a were removed above) 134 new = sorted(b.keys()) 135 for config in new: 136 print_config("+", config, None, b[config]) 137 138main() 139