diff options
author | Nick Mathewson <nickm@torproject.org> | 2018-06-21 14:02:11 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2018-06-21 14:05:33 -0400 |
commit | 999f7984e189250216fcd0bbbe1c4c8d1b0c380b (patch) | |
tree | cb4fe061d96917b9c42680955a207a9ac5b4acbe /scripts | |
parent | 8918bd90e9ddc135c0519177a07cd7a8c18859ed (diff) | |
download | tor-999f7984e189250216fcd0bbbe1c4c8d1b0c380b.tar.gz tor-999f7984e189250216fcd0bbbe1c4c8d1b0c380b.zip |
New script to check includes for modularity violations
Includes configuration files to enforce these rules on lib and
common. Of course, "common" *is* a modularity violation right now,
so these rules aren't as strict as I would like them to be.
Diffstat (limited to 'scripts')
-rwxr-xr-x | scripts/maint/checkIncludes.py | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/scripts/maint/checkIncludes.py b/scripts/maint/checkIncludes.py new file mode 100755 index 0000000000..b96b7f4b34 --- /dev/null +++ b/scripts/maint/checkIncludes.py @@ -0,0 +1,70 @@ +#!/usr/bin/python3 + +import fnmatch +import os +import re +import sys + +trouble = False + +def err(msg): + global trouble + trouble = True + print(msg, file=sys.stderr) + +def fname_is_c(fname): + return fname.endswith(".h") or fname.endswith(".c") + +INCLUDE_PATTERN = re.compile(r'\s*#\s*include\s+"([^"]*)"') +RULES_FNAME = ".may_include" + +class Rules(object): + def __init__(self): + self.patterns = [] + + def addPattern(self, pattern): + self.patterns.append(pattern) + + def includeOk(self, path): + for pattern in self.patterns: + if fnmatch.fnmatchcase(path, pattern): + return True + return False + + def applyToLines(self, lines, context=""): + lineno = 0 + for line in lines: + lineno += 1 + m = INCLUDE_PATTERN.match(line) + if m: + include = m.group(1) + if not self.includeOk(include): + err("Forbidden include of {} on line {}{}".format( + include, lineno, context)) + + def applyToFile(self, fname): + with open(fname, 'r') as f: + #print(fname) + self.applyToLines(iter(f), " of {}".format(fname)) + +def load_include_rules(fname): + result = Rules() + with open(fname, 'r') as f: + for line in f: + line = line.strip() + if line.startswith("#") or not line: + continue + result.addPattern(line) + return result + +for dirpath, dirnames, fnames in os.walk("src"): + if ".may_include" in fnames: + rules = load_include_rules(os.path.join(dirpath, RULES_FNAME)) + for fname in fnames: + if fname_is_c(fname): + rules.applyToFile(os.path.join(dirpath,fname)) + +if trouble: + err( +"""To change which includes are allowed in a C file, edit the {} files in its +enclosing directory.""".format(RULES_FNAME)) |