linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] checkkconfigsymbols.py:  make it Git aware
@ 2015-03-11 11:16 Valentin Rothberg
  2015-03-11 12:04 ` Paul Bolle
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Valentin Rothberg @ 2015-03-11 11:16 UTC (permalink / raw)
  To: gregkh; +Cc: stefan.hengelein, linux-kernel, pebolle, rupran, Valentin Rothberg

The script now supports to check a specified commit or a specified range
of commits (i.e., commit1..commit2).  Developers and maintainers are
encouraged to use this functionality before sending or merging patches
to avoid potential bugs.

This patch adds the following options to the script:

 -c COMMIT, --commit=COMMIT
                  Check if the specified commit (hash) introduces
                  undefined Kconfig symbols.

 -d DIFF, --diff=DIFF
                  Diff undefined symbols between two commits.  The input
                  format bases on Git log's 'commmit1..commit2'.

Note that both options require to 'git reset --hard' the user's Git
tree, which can lead to the loss of uncommitted data.

Signed-off-by: Valentin Rothberg <valentinrothberg@gmail.com>
---
There are still some performance improvements possible (e.g., only parse Kconfig
files for a 2nd time when needed).

Currently, the two options work on a file base, such that files that already
reference the same added undefined feature will not be reported.  A solution can
be to work on a line base.

I like the simplicity of the code at the current state, but I will think about
both issues and send another patch in the near future.
---
 scripts/checkkconfigsymbols.py | 101 +++++++++++++++++++++++++++++++++++++++--
 1 file changed, 98 insertions(+), 3 deletions(-)

diff --git a/scripts/checkkconfigsymbols.py b/scripts/checkkconfigsymbols.py
index e9cc689033fe..7f1b5ccf75cb 100644
--- a/scripts/checkkconfigsymbols.py
+++ b/scripts/checkkconfigsymbols.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 
-"""Find Kconfig identifiers that are referenced but not defined."""
+"""Find Kconfig symbols that are referenced but not defined."""
 
 # (c) 2014 Valentin Rothberg <valentinrothberg@gmail.com>
 # (c) 2014 Stefan Hengelein <stefan.hengelein@fau.de>
@@ -10,7 +10,9 @@
 
 import os
 import re
+import sys
 from subprocess import Popen, PIPE, STDOUT
+from optparse import OptionParser
 
 
 # regex expressions
@@ -32,8 +34,100 @@ REGEX_KCONFIG_HELP = re.compile(r"^\s+(help|---help---)\s*$")
 REGEX_FILTER_FEATURES = re.compile(r"[A-Za-z0-9]$")
 
 
+def parse_options():
+    """The user interface of this module."""
+    usage = "%prog [options]\n\n"                                              \
+            "Run this tool to detect Kconfig symbols that are referenced but " \
+            "not defined in\nKconfig.  The output of this tool has the "       \
+            "format \'Undefined symbol\\tFile list\'\n\n"                      \
+            "If no option is specified, %prog will default to check your\n"    \
+            "current tree.  Please note that specifying commits will "         \
+            "\'git reset --hard\'\nyour current tree!  You may save "          \
+            "uncommited changes to avoid losing data."
+
+    parser = OptionParser(usage=usage)
+
+    parser.add_option('-c', '--commit', dest='commit', action='store',
+                      default="",
+                      help="Check if the specified commit (hash) introduces "
+                           "undefined Kconfig symbols.")
+
+    parser.add_option('-d', '--diff', dest='diff', action='store',
+                      default="",
+                      help="Diff undefined symbols between two commits.  The "
+                           "input format bases on Git log's "
+                           "\'commmit1..commit2\'.")
+
+    (opts, _) = parser.parse_args()
+
+    if opts.commit and opts.diff:
+        sys.exit("Please specify only one option at once.")
+
+    if opts.diff and not re.match(r"^[\w\-\.]+\.\.[\w\-\.]+$", opts.diff):
+        sys.exit("Please specify valid input in the following format: "
+                 "\'commmit1..commit2\'")
+
+    return opts
+
+
 def main():
     """Main function of this module."""
+    opts = parse_options()
+
+    if opts.commit or opts.diff:
+        # get commit range
+        commit_a = None
+        commit_b = None
+        if opts.commit:
+            commit_a = opts.commit + "~"
+            commit_b = opts.commit
+        elif opts.diff:
+            split = opts.diff.split("..")
+            commit_a = split[0]
+            commit_b = split[1]
+            undefined_a = {}
+            undefined_b = {}
+
+        # get undefined items before the commit
+        reset_commit(commit_a)
+        undefined_a = check_symbols()
+
+        # get undefined items for the commit
+        reset_commit(commit_b)
+        undefined_b = check_symbols()
+
+        # report cases that are present for the commit but not before
+        for feature in undefined_b:
+            # feature has not been undefined before
+            if not feature in undefined_a:
+                files = undefined_b.get(feature)
+                print "%s\t%s" % (feature, ", ".join(files))
+            # check there are new files that reference the undefined feature
+            else:
+                files = undefined_b.get(feature) - undefined_a.get(feature)
+                if files:
+                    print "%s\t%s" % (feature, ", ".join(files))
+
+    # default to check the entire tree
+    else:
+        undefined = check_symbols()
+        for feature in undefined:
+            files = undefined.get(feature)
+            print "%s\t%s" % (feature, ", ".join(files))
+
+
+def reset_commit(commit):
+    """Hard reset the current git tree to %commit."""
+    cmd = "git reset --hard %s" % commit
+    pop = Popen(cmd, stdout=PIPE, stderr=STDOUT, shell=True)
+    (stdout, _) = pop.communicate()  # wait until finished
+    if pop.returncode != 0:
+        sys.exit(stdout)
+
+
+def check_symbols():
+    """Find undefined Kconfig symbols and return a dict with the symbol as key
+    and a list of referencing files as value."""
     source_files = []
     kconfig_files = []
     defined_features = set()
@@ -61,7 +155,7 @@ def main():
     for kfile in kconfig_files:
         parse_kconfig_file(kfile, defined_features, referenced_features)
 
-    print "Undefined symbol used\tFile list"
+    undefined = {}  # {feature: [files]}
     for feature in sorted(referenced_features):
         # filter some false positives
         if feature == "FOO" or feature == "BAR" or \
@@ -73,7 +167,8 @@ def main():
                 if feature[:-len("_MODULE")] in defined_features:
                     continue
             files = referenced_features.get(feature)
-            print "%s\t%s" % (feature, ", ".join(files))
+            undefined[feature] = files
+    return undefined
 
 
 def parse_source_file(sfile, referenced_features):
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2015-03-16 11:16 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-03-11 11:16 [PATCH] checkkconfigsymbols.py: make it Git aware Valentin Rothberg
2015-03-11 12:04 ` Paul Bolle
2015-03-11 14:19   ` Valentin Rothberg
2015-03-11 14:33     ` Valentin Rothberg
2015-03-11 15:04       ` Valentin Rothberg
2015-03-13 20:20         ` Paul Bolle
2015-03-14 16:28           ` Valentin Rothberg
2015-03-16 10:38 ` [PATCH v2] " Valentin Rothberg
2015-03-16 11:16 ` [PATCH v3] " Valentin Rothberg

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).