mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2025-02-24 14:51:11 +01:00
Update the check-includes script to enforce some naming and no-circularity rules
This commit is contained in:
parent
4ecd5da306
commit
c3c8c926bf
1 changed files with 64 additions and 0 deletions
|
@ -33,6 +33,9 @@ else:
|
||||||
def open_file(fname):
|
def open_file(fname):
|
||||||
return open(fname, 'r', encoding='utf-8')
|
return open(fname, 'r', encoding='utf-8')
|
||||||
|
|
||||||
|
def warn(msg):
|
||||||
|
print(msg, file=sys.stderr)
|
||||||
|
|
||||||
def err(msg):
|
def err(msg):
|
||||||
""" Declare that an error has happened, and remember that there has
|
""" Declare that an error has happened, and remember that there has
|
||||||
been an error. """
|
been an error. """
|
||||||
|
@ -48,14 +51,34 @@ def fname_is_c(fname):
|
||||||
INCLUDE_PATTERN = re.compile(r'\s*#\s*include\s+"([^"]*)"')
|
INCLUDE_PATTERN = re.compile(r'\s*#\s*include\s+"([^"]*)"')
|
||||||
RULES_FNAME = ".may_include"
|
RULES_FNAME = ".may_include"
|
||||||
|
|
||||||
|
ALLOWED_PATTERNS = [
|
||||||
|
re.compile(r'^.*\*\.(h|inc)$'),
|
||||||
|
re.compile(r'^.*/.*\.h$'),
|
||||||
|
re.compile(r'^ext/.*\.c$'),
|
||||||
|
re.compile(r'^orconfig.h$'),
|
||||||
|
re.compile(r'^micro-revision.i$'),
|
||||||
|
]
|
||||||
|
|
||||||
|
def pattern_is_normal(s):
|
||||||
|
for p in ALLOWED_PATTERNS:
|
||||||
|
if p.match(s):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
class Rules(object):
|
class Rules(object):
|
||||||
""" A 'Rules' object is the parsed version of a .may_include file. """
|
""" A 'Rules' object is the parsed version of a .may_include file. """
|
||||||
def __init__(self, dirpath):
|
def __init__(self, dirpath):
|
||||||
self.dirpath = dirpath
|
self.dirpath = dirpath
|
||||||
|
if dirpath.startswith("src/"):
|
||||||
|
self.incpath = dirpath[4:]
|
||||||
|
else:
|
||||||
|
self.incpath = dirpath
|
||||||
self.patterns = []
|
self.patterns = []
|
||||||
self.usedPatterns = set()
|
self.usedPatterns = set()
|
||||||
|
|
||||||
def addPattern(self, pattern):
|
def addPattern(self, pattern):
|
||||||
|
if not pattern_is_normal(pattern):
|
||||||
|
warn("Unusual pattern {} in {}".format(pattern, self.dirpath))
|
||||||
self.patterns.append(pattern)
|
self.patterns.append(pattern)
|
||||||
|
|
||||||
def includeOk(self, path):
|
def includeOk(self, path):
|
||||||
|
@ -86,6 +109,20 @@ class Rules(object):
|
||||||
if p not in self.usedPatterns:
|
if p not in self.usedPatterns:
|
||||||
print("Pattern {} in {} was never used.".format(p, self.dirpath))
|
print("Pattern {} in {} was never used.".format(p, self.dirpath))
|
||||||
|
|
||||||
|
def getAllowedDirectories(self):
|
||||||
|
allowed = []
|
||||||
|
for p in self.patterns:
|
||||||
|
m = re.match(r'^(.*)/\*\.(h|inc)$', p)
|
||||||
|
if m:
|
||||||
|
allowed.append(m.group(1))
|
||||||
|
continue
|
||||||
|
m = re.match(r'^(.*)/[^/]*$', p)
|
||||||
|
if m:
|
||||||
|
allowed.append(m.group(1))
|
||||||
|
continue
|
||||||
|
|
||||||
|
return allowed
|
||||||
|
|
||||||
def load_include_rules(fname):
|
def load_include_rules(fname):
|
||||||
""" Read a rules file from 'fname', and return it as a Rules object. """
|
""" Read a rules file from 'fname', and return it as a Rules object. """
|
||||||
result = Rules(os.path.split(fname)[0])
|
result = Rules(os.path.split(fname)[0])
|
||||||
|
@ -99,6 +136,8 @@ def load_include_rules(fname):
|
||||||
|
|
||||||
list_unused = False
|
list_unused = False
|
||||||
|
|
||||||
|
uses_dirs = { }
|
||||||
|
|
||||||
for dirpath, dirnames, fnames in os.walk("src"):
|
for dirpath, dirnames, fnames in os.walk("src"):
|
||||||
if ".may_include" in fnames:
|
if ".may_include" in fnames:
|
||||||
rules = load_include_rules(os.path.join(dirpath, RULES_FNAME))
|
rules = load_include_rules(os.path.join(dirpath, RULES_FNAME))
|
||||||
|
@ -108,8 +147,33 @@ for dirpath, dirnames, fnames in os.walk("src"):
|
||||||
if list_unused:
|
if list_unused:
|
||||||
rules.noteUnusedRules()
|
rules.noteUnusedRules()
|
||||||
|
|
||||||
|
uses_dirs[rules.incpath] = rules.getAllowedDirectories()
|
||||||
|
|
||||||
if trouble:
|
if trouble:
|
||||||
err(
|
err(
|
||||||
"""To change which includes are allowed in a C file, edit the {}
|
"""To change which includes are allowed in a C file, edit the {}
|
||||||
files in its enclosing directory.""".format(RULES_FNAME))
|
files in its enclosing directory.""".format(RULES_FNAME))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
all_levels = []
|
||||||
|
|
||||||
|
n = 0
|
||||||
|
while uses_dirs:
|
||||||
|
n += 0
|
||||||
|
cur_level = []
|
||||||
|
for k in list(uses_dirs):
|
||||||
|
uses_dirs[k] = [ d for d in uses_dirs[k]
|
||||||
|
if (d in uses_dirs and d != k)]
|
||||||
|
if uses_dirs[k] == []:
|
||||||
|
cur_level.append(k)
|
||||||
|
for k in cur_level:
|
||||||
|
del uses_dirs[k]
|
||||||
|
n += 1
|
||||||
|
if cur_level:
|
||||||
|
print(n, cur_level)
|
||||||
|
if n > 100:
|
||||||
|
break
|
||||||
|
|
||||||
|
if uses_dirs:
|
||||||
|
print("Circular dependencies in here somewhere:", uses_dirs)
|
||||||
|
sys.exit(1)
|
||||||
|
|
Loading…
Add table
Reference in a new issue