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