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