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